From 16cd283462cfcc3f88c59192838eb23b660f030b Mon Sep 17 00:00:00 2001 From: leekelleher Date: Sat, 28 Apr 2012 13:52:25 -0100 Subject: [PATCH] uComponents: Added XPathDropDownList to the core --- .../XPathDropDownListDataEditor.cs | 149 ++++++++++++++++ .../XPathDropDownListDataType.cs | 101 +++++++++++ .../XPathDropDownListOptions.cs | 25 +++ .../XPathDropDownListPreValueEditor.cs | 162 ++++++++++++++++++ 4 files changed, 437 insertions(+) create mode 100644 components/editorControls/XPathDropDownList/XPathDropDownListDataEditor.cs create mode 100644 components/editorControls/XPathDropDownList/XPathDropDownListDataType.cs create mode 100644 components/editorControls/XPathDropDownList/XPathDropDownListOptions.cs create mode 100644 components/editorControls/XPathDropDownList/XPathDropDownListPreValueEditor.cs diff --git a/components/editorControls/XPathDropDownList/XPathDropDownListDataEditor.cs b/components/editorControls/XPathDropDownList/XPathDropDownListDataEditor.cs new file mode 100644 index 0000000000..fe7078c8ed --- /dev/null +++ b/components/editorControls/XPathDropDownList/XPathDropDownListDataEditor.cs @@ -0,0 +1,149 @@ +using System; +using System.Linq; +using System.Web.UI; +using System.Web.UI.WebControls; +using umbraco; +using umbraco.BusinessLogic; +using umbraco.cms.businesslogic; +using umbraco.cms.businesslogic.datatype; +using umbraco.cms.businesslogic.property; +using umbraco.cms.businesslogic.web; +using umbraco.interfaces; + +namespace umbraco.editorControls.XPathDropDownList +{ + /// + /// XPath configurabale DropDownList Data Type + /// + public class XPathDropDownListDataEditor : CompositeControl, IDataEditor + { + /// + /// Field for the data. + /// + private IData m_Data; + + /// + /// Field for the options. + /// + private XPathDropDownListOptions m_Options; + + /// + /// Field for the CustomValidator. + /// + private CustomValidator m_CustomValidator = new CustomValidator(); + + /// + /// Field for the DropDownList. + /// + private DropDownList m_DropDownList = new DropDownList(); + + /// + /// Gets a value indicating whether [treat as rich text editor]. + /// + /// + /// true if [treat as rich text editor]; otherwise, false. + /// + public virtual bool TreatAsRichTextEditor + { + get + { + return false; + } + } + + /// + /// Gets a value indicating whether [show label]. + /// + /// true if [show label]; otherwise, false. + public virtual bool ShowLabel + { + get + { + return true; + } + } + + /// + /// Gets the editor. + /// + /// The editor. + public Control Editor + { + get + { + return this; + } + } + + /// + /// Initializes a new instance of XPathCheckBoxListDataEditor + /// + /// + /// + internal XPathDropDownListDataEditor(IData data, XPathDropDownListOptions options) + { + this.m_Data = data; + this.m_Options = options; + } + + /// + /// Called by the ASP.NET page framework to notify server controls that use composition-based implementation to create any child controls they contain in preparation for posting back or rendering. + /// + protected override void CreateChildControls() + { + this.m_DropDownList.DataSource = uQuery.GetNodesByXPath(this.m_Options.XPath).ToNameIds(); + this.m_DropDownList.DataTextField = "Value"; + this.m_DropDownList.DataValueField = this.m_Options.UseId ? "Key" : "Value"; + this.m_DropDownList.DataBind(); + + // Add a default please select value + this.m_DropDownList.Items.Insert(0, new ListItem(string.Empty, "-1")); + + this.Controls.Add(this.m_CustomValidator); + this.Controls.Add(this.m_DropDownList); + } + + /// + /// Raises the event. + /// + /// The object that contains the event data. + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + this.EnsureChildControls(); + + if (!this.Page.IsPostBack) + { + // Get selected items from Node Name or Node Id + var dropDownListItem = this.m_DropDownList.Items.FindByValue(this.m_Data.Value.ToString()); + if (dropDownListItem != null) + { + dropDownListItem.Selected = true; + } + } + } + + /// + /// Called by Umbraco when saving the node + /// + public void Save() + { + Property property = new Property(((DefaultData)this.m_Data).PropertyId); + if (property.PropertyType.Mandatory && this.m_DropDownList.SelectedValue == "-1") + { + // Property is mandatory, but no value selected in the DropDownList + this.m_CustomValidator.IsValid = false; + + DocumentType documentType = new DocumentType(property.PropertyType.ContentTypeId); + ContentType.TabI tab = documentType.getVirtualTabs.Where(x => x.Id == property.PropertyType.TabId).FirstOrDefault(); + + if (tab != null) + { + this.m_CustomValidator.ErrorMessage = ui.Text("errorHandling", "errorMandatory", new string[] { property.PropertyType.Alias, tab.Caption }, User.GetCurrent()); + } + } + + this.m_Data.Value = this.m_DropDownList.SelectedValue; + } + } +} diff --git a/components/editorControls/XPathDropDownList/XPathDropDownListDataType.cs b/components/editorControls/XPathDropDownList/XPathDropDownListDataType.cs new file mode 100644 index 0000000000..6426b171d3 --- /dev/null +++ b/components/editorControls/XPathDropDownList/XPathDropDownListDataType.cs @@ -0,0 +1,101 @@ +using System; +using umbraco.cms.businesslogic.datatype; +using umbraco.interfaces; + +namespace umbraco.editorControls.XPathDropDownList +{ + /// + /// + /// + public class XPathDropDownListDataType : umbraco.cms.businesslogic.datatype.BaseDataType, IDataType + { + /// + /// + /// + private XPathDropDownListPreValueEditor preValueEditor; + + /// + /// + /// + private IDataEditor dataEditor; + + /// + /// + /// + private IData data; + + /// + /// Gets the name of the data type. + /// + /// The name of the data type. + public override string DataTypeName + { + get + { + return "XPath DropDownList"; + } + } + + /// + /// Gets the id. + /// + /// The id. + public override Guid Id + { + get + { + return new Guid(DataTypeGuids.XPathDropDownListId); + } + } + + /// + /// Lazy load the associated PreValueEditor instance, + /// this is constructed supplying 'this' + /// + public override IDataPrevalue PrevalueEditor + { + get + { + if (this.preValueEditor == null) + { + this.preValueEditor = new XPathDropDownListPreValueEditor(this); + } + + return this.preValueEditor; + } + } + + /// + /// Lazy load the assocated DataEditor, + /// this is constructed supplying the data value stored by the PreValueEditor, and also the configuration settings of the PreValueEditor + /// + public override IDataEditor DataEditor + { + get + { + if (this.dataEditor == null) + { + this.dataEditor = new XPathDropDownListDataEditor(this.Data, ((XPathDropDownListPreValueEditor)this.PrevalueEditor).Options); + } + + return this.dataEditor; + } + } + + /// + /// Lazy load an empty DefaultData object, this is used to pass data between the PreValueEditor and the DataEditor + /// + public override IData Data + { + get + { + if (this.data == null) + { + this.data = new umbraco.cms.businesslogic.datatype.DefaultData(this); + } + + return this.data; + } + } + } +} \ No newline at end of file diff --git a/components/editorControls/XPathDropDownList/XPathDropDownListOptions.cs b/components/editorControls/XPathDropDownList/XPathDropDownListOptions.cs new file mode 100644 index 0000000000..514fbfca90 --- /dev/null +++ b/components/editorControls/XPathDropDownList/XPathDropDownListOptions.cs @@ -0,0 +1,25 @@ + +namespace umbraco.editorControls.XPathDropDownList +{ + internal class XPathDropDownListOptions + { + /// + /// XPath string used to get Nodes to be used as CheckBox options in a CheckBoxList + /// + public string XPath { get; set; } + + /// + /// Defaults to true, where property value is a csv of NodeIds, else if false, then csv of Node names is stored + /// + public bool UseId { get; set; } + + /// + /// Initializes an instance of XPathDropDownListOptions + /// + public XPathDropDownListOptions() + { + this.XPath = string.Empty; + this.UseId = true; // Default to storing Node Id + } + } +} diff --git a/components/editorControls/XPathDropDownList/XPathDropDownListPreValueEditor.cs b/components/editorControls/XPathDropDownList/XPathDropDownListPreValueEditor.cs new file mode 100644 index 0000000000..ea64d8f4a4 --- /dev/null +++ b/components/editorControls/XPathDropDownList/XPathDropDownListPreValueEditor.cs @@ -0,0 +1,162 @@ +using System; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.Xml.XPath; +// using uComponents.DataTypes.Shared.Extensions; +// using uComponents.DataTypes.Shared.PrevalueEditors; +using umbraco.cms.businesslogic.datatype; + +namespace umbraco.editorControls.XPathDropDownList +{ + class XPathDropDownListPreValueEditor : AbstractJsonPrevalueEditor + { + /// + /// TextBox control to get the XPath expression + /// + private TextBox xPathTextBox = new TextBox(); + + /// + /// RequiredFieldValidator to ensure an XPath expression has been entered + /// + private RequiredFieldValidator xPathRequiredFieldValidator = new RequiredFieldValidator(); + + /// + /// Server side validation of XPath expression, to ensure some nodes are returned + /// + private CustomValidator xPathCustomValidator = new CustomValidator(); + + /// + /// Drop Down List to pick either Node Name or Node Id + /// + private DropDownList valueTypeDropDownList = new DropDownList(); + + /// + /// Data object used to define the configuration status of this PreValueEditor + /// + private XPathDropDownListOptions options = null; + + /// + /// Gets the options data object that represents the current state of this datatypes configuration + /// + internal XPathDropDownListOptions Options + { + get + { + if (this.options == null) + { + // Deserialize any stored settings for this PreValueEditor instance + this.options = this.GetPreValueOptions(); + + // If still null, ie, object couldn't be de-serialized from PreValue[0] string value + if (this.options == null) + { + // Create a new Options data object with the default values + this.options = new XPathDropDownListOptions(); + } + } + return this.options; + } + } + + /// + /// Initialize a new instance of XPathCheckBoxlistPreValueEditor + /// + /// XPathCheckBoxListDataType + public XPathDropDownListPreValueEditor(umbraco.cms.businesslogic.datatype.BaseDataType dataType) + : base(dataType, umbraco.cms.businesslogic.datatype.DBTypes.Nvarchar) + { + } + + /// + /// Creates all of the controls and assigns all of their properties + /// + protected override void CreateChildControls() + { + this.xPathTextBox.ID = "xPathTextBox"; + this.xPathTextBox.CssClass = "umbEditorTextField"; + + this.xPathRequiredFieldValidator.ControlToValidate = this.xPathTextBox.ID; + this.xPathRequiredFieldValidator.Display = ValidatorDisplay.Dynamic; + this.xPathRequiredFieldValidator.ErrorMessage = " XPath expression required"; + + this.xPathCustomValidator.ControlToValidate = this.xPathTextBox.ID; + this.xPathCustomValidator.Display = ValidatorDisplay.Dynamic; + this.xPathCustomValidator.ServerValidate += new ServerValidateEventHandler(XPathCustomValidator_ServerValidate); + + this.valueTypeDropDownList.ID = "valueTypeDropDownList"; + this.valueTypeDropDownList.Items.Add(new ListItem("Node Id", bool.TrueString)); + this.valueTypeDropDownList.Items.Add(new ListItem("Node Name", bool.FalseString)); + + this.Controls.Add(this.xPathTextBox); + this.Controls.Add(this.xPathRequiredFieldValidator); + this.Controls.Add(this.xPathCustomValidator); + this.Controls.Add(this.valueTypeDropDownList); + } + + /// + /// + /// + /// + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + //if (!this.Page.IsPostBack) + //{ + // Read in stored configuration values + this.xPathTextBox.Text = this.Options.XPath; + this.valueTypeDropDownList.SelectedValue = this.Options.UseId.ToString(); + //} + } + + /// + /// Will run the entered XPath expression to ensure it returns at least 1 node + /// + /// xPathCustomValidator + /// + private void XPathCustomValidator_ServerValidate(object source, ServerValidateEventArgs args) + { + string xPath = args.Value; + bool isValid = false; + + try + { + if (uQuery.GetNodesByXPath(xPath).Count >= 0) + { + isValid = true; + } + } + catch (XPathException) + { + this.xPathCustomValidator.ErrorMessage = " Syntax error in XPath expression"; + } + + args.IsValid = isValid; + } + + /// + /// Saves the pre value data to Umbraco + /// + public override void Save() + { + if (this.Page.IsValid) + { + this.Options.XPath = this.xPathTextBox.Text; + this.Options.UseId = bool.Parse(this.valueTypeDropDownList.SelectedValue); + + this.SaveAsJson(this.Options); // Serialize to Umbraco database field + } + } + + /// + /// Replaces the base class writer and instead uses the shared uComponents extension method, to inject consistant markup + /// + /// + protected override void RenderContents(HtmlTextWriter writer) + { + writer.AddPrevalueRow("XPath Expression", this.xPathTextBox, this.xPathRequiredFieldValidator, this.xPathCustomValidator); + writer.AddPrevalueRow("Value", this.valueTypeDropDownList); + } + + } +} \ No newline at end of file