diff --git a/.build/ReleaseCleanup.ps1 b/.build/ReleaseCleanup.ps1
new file mode 100644
index 0000000000..81ffb55d0a
--- /dev/null
+++ b/.build/ReleaseCleanup.ps1
@@ -0,0 +1,56 @@
+param (
+ [string]$cleanupTargetName,
+ [string]$cleanupDirectory
+)
+
+Write-Host "ReleaseCleanup script started..."
+# This script deletes/rename files according to rules in ReleaseCleanupConfiguration.xml - it is used by automated builds
+
+if(-not($cleanupTargetName)) { Throw "You must supply a value for -cleanupTargetName - matching a target name in ReleaseCleanupConfiguration.xml" }
+if(-not($cleanupDirectory)) { Throw "You must supply a value for -cleanupDirectory - this is the path where cleaning will be taking place" }
+
+$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
+[xml]$xml = Get-Content (Join-Path $scriptPath "ReleaseCleanupConfiguration.xml")
+
+$targetItems = $xml.SelectNodes("/Configuration/Target[@name='" + $cleanupTargetName + "']/*/*[@path]")
+
+Foreach ($fileNode in $targetItems) {
+ $relPath = $fileNode.Attributes["path"].Value
+ $fullPath = Join-Path $cleanupDirectory $relPath
+
+ if (($fileNode.Attributes["rename-find"]) -and ($fileNode.Attributes["rename-replace"]) ) {
+ # if rename
+ Write-Host "Handling $fullPath for renaming"
+
+ $findString = $fileNode.Attributes["rename-find"].Value.Replace("\","/")
+ $replaceString = $fileNode.Attributes["rename-replace"].Value
+
+ $matches = Get-ChildItem -Path $fullPath -Recurse
+
+ if ($matches.length -eq 0) { Write-Warning "Pattern matched 0 files - probably you should remove it from ReleaseCleanupConfiguration.xml in repo" }
+
+ Foreach ($match in $matches) {
+ $name = $match.FullName.Replace("\","/")
+ $newName = $name.Replace($findString.Replace("\","/"), $replaceString)
+
+ #ensure dir
+ $newDirPath = Split-Path -Path $newName
+ if (-not (Test-Path($newDirPath))) { New-Item -ItemType Directory -Force -Path $newDirPath }
+ Move-Item $match -Destination $newName -Force
+ }
+ }
+ else {
+ # assume delete otherwise
+ Write-Host "Handling $fullPath for deletion"
+
+ if (($fileNode.Name -eq "Directory") -and (Test-Path $fullPath)) {
+ Remove-Item -LiteralPath $fullPath -Force -Recurse
+ } else {
+ $matches = Get-ChildItem -Path $fullPath -Recurse
+
+ if ($matches.length -eq 0) { Write-Warning "Pattern matched 0 files - probably you should remove it from ReleaseCleanupConfiguration.xml in repo" }
+
+ $matches | Where-Object { Test-Path($_) } | Remove-Item -Force -Recurse
+ }
+ }
+}
diff --git a/.build/ReleaseCleanupConfiguration.xml b/.build/ReleaseCleanupConfiguration.xml
new file mode 100644
index 0000000000..7857487446
--- /dev/null
+++ b/.build/ReleaseCleanupConfiguration.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Composite/C1Console/Forms/CoreUiControls/TreeSelectorUiControl.cs b/Composite/C1Console/Forms/CoreUiControls/TreeSelectorUiControl.cs
new file mode 100644
index 0000000000..3741db400e
--- /dev/null
+++ b/Composite/C1Console/Forms/CoreUiControls/TreeSelectorUiControl.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using Composite.C1Console.Forms.Foundation;
+
+namespace Composite.C1Console.Forms.CoreUiControls
+{
+ [ControlValueProperty("SelectedKeys")]
+ internal abstract class TreeSelectorUiControl : UiControl
+ {
+ [BindableProperty]
+ [FormsProperty]
+ public string SelectedKey { get; set; }
+
+ [FormsProperty]
+ public string ElementProvider { get; set; }
+
+ [FormsProperty]
+ public string SelectableElementPropertyName { get; set; }
+
+ [FormsProperty]
+ public string SelectableElementPropertyValue { get; set; }
+
+ [FormsProperty]
+ public string SelectableElementReturnValue { get; set; }
+
+ [FormsProperty]
+ public string SerializedSearchToken { get; set; }
+
+ [FormsProperty]
+ public bool Required { get; set; }
+ }
+}
diff --git a/Composite/Composite.csproj b/Composite/Composite.csproj
index 58956dd4f5..936fe0a436 100644
--- a/Composite/Composite.csproj
+++ b/Composite/Composite.csproj
@@ -233,6 +233,7 @@
+
@@ -260,6 +261,10 @@
+
+ ASPXCodeBehind
+
+
diff --git a/Composite/Core/Localization/LocalizationFacade.cs b/Composite/Core/Localization/LocalizationFacade.cs
index f06c60ee2b..97225512fd 100644
--- a/Composite/Core/Localization/LocalizationFacade.cs
+++ b/Composite/Core/Localization/LocalizationFacade.cs
@@ -178,6 +178,19 @@ internal static void AddLocale(CultureInfo cultureInfo, string urlMappingName, b
UserSettings.SetForeignLocaleCultureInfo(username, cultureInfo);
}
}
+
+ List usergroupids =
+ (from u in DataFacade.GetData()
+ select u.Id).ToList();
+
+ foreach (Guid usergroupid in usergroupids)
+ {
+ var groupLang = DataFacade.BuildNew();
+ groupLang.Id = Guid.NewGuid();
+ groupLang.CultureName = cultureInfo.ToString();
+ groupLang.UserGroupId = usergroupid;
+ DataFacade.AddNew(groupLang);
+ }
}
if (DataLocalizationFacade.DefaultLocalizationCulture == null)
diff --git a/Composite/Core/PackageSystem/PackageFragmentInstallers/DataPackageFragmentInstaller.cs b/Composite/Core/PackageSystem/PackageFragmentInstallers/DataPackageFragmentInstaller.cs
index afa2739080..211a723ff3 100644
--- a/Composite/Core/PackageSystem/PackageFragmentInstallers/DataPackageFragmentInstaller.cs
+++ b/Composite/Core/PackageSystem/PackageFragmentInstallers/DataPackageFragmentInstaller.cs
@@ -191,15 +191,18 @@ private XElement AddData(DataType dataType, CultureInfo cultureInfo)
}
- var dataKey = CopyFieldValues(dataType, data, addElement);
+ var dataKey = PopulateAndReturnKeyPropertyValues(dataType, data, addElement);
if (dataType.AllowOverwrite || dataType.OnlyUpdate)
{
- IData existingData = DataFacade.TryGetDataByUniqueKey(interfaceType, dataKey);
+ List existingDataList = DataFacade.TryGetDataByLookupKeys(interfaceType, dataKey).ToList();
+ if (existingDataList.Count > 1) throw new InvalidOperationException("Got more than 1 existing data element when querying on key properties for " + addElement.ToString());
+
+ IData existingData = existingDataList.FirstOrDefault();
if (existingData != null)
{
- CopyFieldValues(dataType, existingData, addElement);
+ PopulateAndReturnKeyPropertyValues(dataType, existingData, addElement);
DataFacade.Update(existingData, false, true, false);
continue;
@@ -280,13 +283,16 @@ private void UpdateVersionId(IVersioned data)
}
}
-
- private static DataKeyPropertyCollection CopyFieldValues(DataType dataType, IData data, XElement addElement)
+
+ private static DataPropertyValueCollection PopulateAndReturnKeyPropertyValues(DataType dataType, IData dataToPopulate, XElement addElement)
{
- var dataKeyPropertyCollection = new DataKeyPropertyCollection();
+ var dataKeyPropertyCollection = new DataPropertyValueCollection();
var properties = GetDataTypeProperties(dataType.InterfaceType);
+ var keyPropertyNames = dataType.InterfaceType.GetKeyPropertyNames();
+ var versionKeyPropertyNames = dataType.InterfaceType.GetVersionKeyPropertyNames();
+
foreach (XAttribute attribute in addElement.Attributes())
{
string fieldName = attribute.Name.LocalName;
@@ -298,11 +304,11 @@ private static DataKeyPropertyCollection CopyFieldValues(DataType dataType, IDat
PropertyInfo propertyInfo = properties[fieldName];
object fieldValue = ValueTypeConverter.Convert(attribute.Value, propertyInfo.PropertyType);
- propertyInfo.SetValue(data, fieldValue, null);
+ propertyInfo.SetValue(dataToPopulate, fieldValue, null);
- if (dataType.InterfaceType.GetKeyPropertyNames().Contains(fieldName))
+ if (keyPropertyNames.Contains(fieldName) || versionKeyPropertyNames.Contains(fieldName))
{
- dataKeyPropertyCollection.AddKeyProperty(fieldName, fieldValue);
+ dataKeyPropertyCollection.AddKeyProperty(propertyInfo, fieldValue);
}
}
diff --git a/Composite/Data/DataFacade.cs b/Composite/Data/DataFacade.cs
index 9b42e89ab7..c44e9b5a8a 100644
--- a/Composite/Data/DataFacade.cs
+++ b/Composite/Data/DataFacade.cs
@@ -371,7 +371,7 @@ public static IQueryable GetDataFromOtherScope(T data, DataScopeIdentifier
using (new DataScope(dataScopeIdentifier))
{
- return DataExpressionBuilder.GetQueryableByData(data, true);
+ return DataExpressionBuilder.GetQueryableByData(data);
}
}
@@ -384,7 +384,7 @@ public static IQueryable GetDataFromOtherLocale(T data, CultureInfo cultur
using (new DataScope(cultureInfo))
{
- return DataExpressionBuilder.GetQueryableByData(data, true);
+ return DataExpressionBuilder.GetQueryableByData(data);
}
}
@@ -397,13 +397,6 @@ public static IEnumerable GetDataFromOtherScope(IData data, DataScopeIden
///
public static IEnumerable GetDataFromOtherScope(
IData data, DataScopeIdentifier dataScopeIdentifier, bool useCaching)
- {
- return GetDataFromOtherScope(data, dataScopeIdentifier, useCaching, true);
- }
-
- ///
- public static IEnumerable GetDataFromOtherScope(
- IData data, DataScopeIdentifier dataScopeIdentifier, bool useCaching, bool ignoreVersioning)
{
Verify.ArgumentNotNull(data, "data");
Verify.ArgumentNotNull(dataScopeIdentifier, nameof(dataScopeIdentifier));
@@ -432,7 +425,7 @@ public static IEnumerable GetDataFromOtherScope(
{
IQueryable table = GetData(data.DataSourceId.InterfaceType, false);
- IQueryable queryable = DataExpressionBuilder.GetQueryableByData(data, table, ignoreVersioning);
+ IQueryable queryable = DataExpressionBuilder.GetQueryableByData(data, table);
foreach (object obj in queryable)
{
@@ -509,7 +502,7 @@ public static LambdaExpression GetPredicateExpressionByUniqueKey(Type interfaceT
// Private helper
private static Expression GetPredicateExpressionByUniqueKeyFilterExpression(IReadOnlyList keyProperties, DataKeyPropertyCollection dataKeyPropertyCollection, ParameterExpression parameterExpression)
{
- if (keyProperties.Count != dataKeyPropertyCollection.Count) throw new ArgumentException("Missing og to many key properties");
+ if (keyProperties.Count != dataKeyPropertyCollection.Count) throw new ArgumentException("Missing or too many key properties");
var propertiesWithValues = new List>();
foreach (var kvp in dataKeyPropertyCollection.KeyProperties)
@@ -606,6 +599,28 @@ public static IData TryGetDataByUniqueKey(Type interfaceType, DataKeyPropertyCol
return data;
}
+ ///
+ /// Returns all data items of the given type, which matches the provided dataPropertyCollection (property/value pairs)
+ ///
+ /// The data type to query - type is expected to implement a subinterface of IData
+ /// The properties and values to use for filtering
+ /// Data matching the provided property values
+ public static IEnumerable TryGetDataByLookupKeys(Type interfaceType, DataPropertyValueCollection dataPropertyCollection)
+ {
+ Verify.ArgumentNotNull(interfaceType, nameof(interfaceType));
+ Verify.ArgumentNotNull(dataPropertyCollection, nameof(dataPropertyCollection));
+
+ LambdaExpression lambdaExpression = GetPredicateExpression(interfaceType, dataPropertyCollection);
+
+ MethodInfo methodInfo = GetGetDataWithPredicatMethodInfo(interfaceType);
+
+ var queryable = (IQueryable)methodInfo.Invoke(null, new object[] { lambdaExpression });
+
+ return ((IEnumerable)queryable).Cast();
+ }
+
+
+
///
public static IEnumerable TryGetDataVersionsByUniqueKey(Type interfaceType, DataKeyPropertyCollection dataKeyPropertyCollection)
diff --git a/Composite/Data/Foundation/DataExpressionBuilder.cs b/Composite/Data/Foundation/DataExpressionBuilder.cs
index 0a861aa5c2..c712392d2b 100644
--- a/Composite/Data/Foundation/DataExpressionBuilder.cs
+++ b/Composite/Data/Foundation/DataExpressionBuilder.cs
@@ -29,21 +29,14 @@ static DataExpressionBuilder()
///
public static IQueryable GetQueryableByData(IData data)
{
- return GetQueryableByData(data, true);
+ return GetQueryableByData(data, null);
}
- public static IQueryable GetQueryableByData(IData data, bool ignoreVersioning)
+ public static IQueryable GetQueryableByData(IData data, IQueryable sourceQueryable)
{
- return GetQueryableByData(data, null, ignoreVersioning);
- }
-
-
-
- public static IQueryable GetQueryableByData(IData data, IQueryable sourceQueryable, bool ignoreVersioning)
- {
- LambdaExpression whereLambdaExpression = GetWhereLambdaExpression(data, ignoreVersioning);
+ LambdaExpression whereLambdaExpression = GetWhereLambdaExpression(data);
if (sourceQueryable == null)
{
@@ -59,10 +52,10 @@ public static IQueryable GetQueryableByData(IData data, IQueryable sourceQueryab
- public static IQueryable GetQueryableByData(T data, bool ignoreVersioning)
+ public static IQueryable GetQueryableByData(T data)
where T : class, IData
{
- LambdaExpression whereLambdaExpression = GetWhereLambdaExpression(data, ignoreVersioning);
+ LambdaExpression whereLambdaExpression = GetWhereLambdaExpression(data);
IQueryable queryable = DataFacade.GetData(data.DataSourceId.InterfaceType);
@@ -75,9 +68,9 @@ public static IQueryable GetQueryableByData(T data, bool ignoreVersioning)
- public static Delegate GetWherePredicateDelegate(IData data, bool ignoreVersioning)
+ public static Delegate GetWherePredicateDelegate(IData data)
{
- LambdaExpression whereLambdaExpression = GetWhereLambdaExpression(data, ignoreVersioning);
+ LambdaExpression whereLambdaExpression = GetWhereLambdaExpression(data);
Delegate resultDelegate = whereLambdaExpression.Compile();
@@ -86,7 +79,7 @@ public static Delegate GetWherePredicateDelegate(IData data, bool ignoreVersioni
- private static LambdaExpression GetWhereLambdaExpression(IData data, bool ignoreVersioning)
+ private static LambdaExpression GetWhereLambdaExpression(IData data)
{
var propertyInfoes = data.DataSourceId.InterfaceType.GetPhysicalKeyProperties();
diff --git a/Composite/Data/ProcessControlled/ProcessControllers/GenericPublishProcessController/GenericPublishProcessController.cs b/Composite/Data/ProcessControlled/ProcessControllers/GenericPublishProcessController/GenericPublishProcessController.cs
index ff2d64def2..329cda425f 100644
--- a/Composite/Data/ProcessControlled/ProcessControllers/GenericPublishProcessController/GenericPublishProcessController.cs
+++ b/Composite/Data/ProcessControlled/ProcessControllers/GenericPublishProcessController/GenericPublishProcessController.cs
@@ -370,7 +370,7 @@ public List GetActions(IData data, Type elementProviderType)
var clientActions = visualTrans.Select(newState => _visualTransitionsActions[newState]()).ToList();
- IData publicData = DataFacade.GetDataFromOtherScope(data, DataScopeIdentifier.Public, true, false).FirstOrDefault();
+ IData publicData = DataFacade.GetDataFromOtherScope(data, DataScopeIdentifier.Public, true).FirstOrDefault();
if (publicData != null)
{
var unpublishAction = new ElementAction(new ActionHandle(new ProxyDataActionToken(ActionIdentifier.Unpublish) { DoIgnoreEntityTokenLocking = true }))
diff --git a/Composite/Plugins/Forms/WebChannel/UiControlFactories/TemplatedTreelSelectorUiControlFactory.cs b/Composite/Plugins/Forms/WebChannel/UiControlFactories/TemplatedTreelSelectorUiControlFactory.cs
new file mode 100644
index 0000000000..4fb965d3a7
--- /dev/null
+++ b/Composite/Plugins/Forms/WebChannel/UiControlFactories/TemplatedTreelSelectorUiControlFactory.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Configuration;
+using System.Web.UI;
+using Composite.C1Console.Forms;
+using Composite.C1Console.Forms.CoreUiControls;
+using Composite.C1Console.Forms.Plugins.UiControlFactory;
+using Composite.C1Console.Forms.WebChannel;
+using Composite.Plugins.Forms.WebChannel.Foundation;
+using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
+using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder;
+using Microsoft.Practices.ObjectBuilder;
+
+
+namespace Composite.Plugins.Forms.WebChannel.UiControlFactories
+{
+ ///
+ ///
+ ///
+ [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
+ public abstract class TreeSelectorTemplateUserControlBase : UserControl, IPostBackDataHandler
+ {
+ ///
+ protected abstract void BindStateToProperties();
+
+ ///
+ protected abstract void InitializeViewState();
+
+ ///
+ public abstract string GetDataFieldClientName();
+
+ internal void BindStateToControlProperties()
+ {
+ this.BindStateToProperties();
+ }
+
+ internal void InitializeWebViewState()
+ {
+ this.InitializeViewState();
+ }
+
+ ///
+ public string SelectedKey { get; set; }
+
+ ///
+ public string ElementProvider { get; set; }
+
+ ///
+ public string SelectableElementPropertyName { get; set; }
+
+ ///
+ public string SelectableElementPropertyValue { get; set; }
+
+ ///
+ public string SelectableElementReturnValue { get; set; }
+
+ ///
+ public string SerializedSearchToken { get; set; }
+
+ ///
+ public bool Required { get; set; }
+
+ ///
+ /// When implemented by a class, processes postback data for an ASP.NET server control.
+ ///
+ ///
+ ///
+ ///
+ public virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection)
+ {
+ return false;
+ }
+
+ ///
+ /// When implemented by a class, signals the server control to notify the ASP.NET application that the state of the control has changed.
+ ///
+ public virtual void RaisePostDataChangedEvent()
+ {
+ }
+ }
+
+
+
+ internal sealed class TemplatedTreeSelectorUiControl : TreeSelectorUiControl, IWebUiControl
+ {
+ private readonly Type _userControlType;
+ private TreeSelectorTemplateUserControlBase _userControl;
+
+ internal TemplatedTreeSelectorUiControl(Type userControlType)
+ {
+ _userControlType = userControlType;
+ }
+
+ public override void BindStateToControlProperties()
+ {
+ _userControl.BindStateToControlProperties();
+
+ this.SelectedKey = _userControl.SelectedKey;
+ }
+
+ public void InitializeViewState()
+ {
+ _userControl.InitializeWebViewState();
+ }
+
+
+ public Control BuildWebControl()
+ {
+ _userControl = _userControlType.ActivateAsUserControl(this.UiControlID);
+
+ _userControl.SelectedKey = this.SelectedKey;
+ _userControl.ElementProvider = this.ElementProvider;
+ _userControl.SelectableElementPropertyName = this.SelectableElementPropertyName;
+ _userControl.SelectableElementPropertyValue = this.SelectableElementPropertyValue;
+ _userControl.SelectableElementReturnValue = this.SelectableElementReturnValue;
+ _userControl.SerializedSearchToken = this.SerializedSearchToken;
+ _userControl.Required = this.Required;
+
+ return _userControl;
+ }
+
+ public bool IsFullWidthControl => false;
+
+ public string ClientName => _userControl.GetDataFieldClientName();
+ }
+
+
+
+ [ConfigurationElementType(typeof(TemplatedTreeSelectorUiControlFactoryData))]
+ internal sealed class TemplatedTreeSelectorUiControlFactory : Base.BaseTemplatedUiControlFactory
+ {
+ public TemplatedTreeSelectorUiControlFactory(TemplatedTreeSelectorUiControlFactoryData data)
+ : base(data)
+ { }
+
+ public override IUiControl CreateControl()
+ {
+ var control = new TemplatedTreeSelectorUiControl(this.UserControlType);
+
+ return control;
+ }
+ }
+
+
+
+ [Assembler(typeof(TemplatedTreeSelectorUiControlFactoryAssembler))]
+ internal sealed class TemplatedTreeSelectorUiControlFactoryData : UiControlFactoryData, Base.ITemplatedUiControlFactoryData
+ {
+ private const string _userControlVirtualPathPropertyName = "userControlVirtualPath";
+ private const string _cacheCompiledUserControlTypePropertyName = "cacheCompiledUserControlType";
+
+ [ConfigurationProperty(_userControlVirtualPathPropertyName, IsRequired = true)]
+ public string UserControlVirtualPath
+ {
+ get { return (string)base[_userControlVirtualPathPropertyName]; }
+ set { base[_userControlVirtualPathPropertyName] = value; }
+ }
+
+ [ConfigurationProperty(_cacheCompiledUserControlTypePropertyName, IsRequired = false, DefaultValue = true)]
+ public bool CacheCompiledUserControlType
+ {
+ get { return (bool)base[_cacheCompiledUserControlTypePropertyName]; }
+ set { base[_cacheCompiledUserControlTypePropertyName] = value; }
+ }
+ }
+
+
+
+ internal sealed class TemplatedTreeSelectorUiControlFactoryAssembler : IAssembler
+ {
+ public IUiControlFactory Assemble(IBuilderContext context, UiControlFactoryData objectConfiguration, IConfigurationSource configurationSource, ConfigurationReflectionCache reflectionCache)
+ {
+ return new TemplatedTreeSelectorUiControlFactory(
+ objectConfiguration as TemplatedTreeSelectorUiControlFactoryData);
+ }
+ }
+}
diff --git a/Composite/Plugins/Functions/WidgetFunctionProviders/StandardWidgetFunctionProvider/StandardWidgetFunctionProvider.cs b/Composite/Plugins/Functions/WidgetFunctionProviders/StandardWidgetFunctionProvider/StandardWidgetFunctionProvider.cs
index dbb52c6ffc..7e8848ef22 100644
--- a/Composite/Plugins/Functions/WidgetFunctionProviders/StandardWidgetFunctionProvider/StandardWidgetFunctionProvider.cs
+++ b/Composite/Plugins/Functions/WidgetFunctionProviders/StandardWidgetFunctionProvider/StandardWidgetFunctionProvider.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using Composite.Data;
@@ -90,6 +90,7 @@ private void InitializeStaticTypeFunctions()
_widgetStaticTypeFunctions.Add(new TextAreaWidgetFuntion(_entityTokenFactory));
_widgetStaticTypeFunctions.Add(new String.SelectorWidgetFunction(_entityTokenFactory));
_widgetStaticTypeFunctions.Add(new String.HierarchicalSelectorWidgetFunction(_entityTokenFactory));
+ _widgetStaticTypeFunctions.Add(new TreeSelectorWidgetFunction(_entityTokenFactory));
_widgetStaticTypeFunctions.Add(new DataIdMultiSelectorWidgetFunction(_entityTokenFactory));
_widgetStaticTypeFunctions.Add(new String.VisualXhtmlEditorFuntion(_entityTokenFactory));
_widgetStaticTypeFunctions.Add(new String.UrlComboBoxWidgetFunction(_entityTokenFactory));
diff --git a/Composite/Plugins/Functions/WidgetFunctionProviders/StandardWidgetFunctionProvider/String/TreeSelectorWidgetFunction.cs b/Composite/Plugins/Functions/WidgetFunctionProviders/StandardWidgetFunctionProvider/String/TreeSelectorWidgetFunction.cs
new file mode 100644
index 0000000000..217dbe51a5
--- /dev/null
+++ b/Composite/Plugins/Functions/WidgetFunctionProviders/StandardWidgetFunctionProvider/String/TreeSelectorWidgetFunction.cs
@@ -0,0 +1,97 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Xml.Linq;
+
+using Composite.Functions;
+using Composite.Plugins.Functions.WidgetFunctionProviders.StandardWidgetFunctionProvider.Foundation;
+using Composite.C1Console.Forms.CoreUiControls;
+using Composite.Core.Xml;
+
+namespace Composite.Plugins.Functions.WidgetFunctionProviders.StandardWidgetFunctionProvider.String
+{
+ internal sealed class TreeSelectorWidgetFunction : CompositeWidgetFunctionBase
+ {
+ private const string _functionName = "TreeSelector";
+ public const string CompositeName = CompositeWidgetFunctionBase.CommonNamespace + ".String." + _functionName;
+
+ public TreeSelectorWidgetFunction(EntityTokenFactory entityTokenFactory)
+ : base(CompositeName, typeof(string), entityTokenFactory)
+ {
+ SetParameterProfiles();
+ }
+
+
+ private void SetParameterProfiles()
+ {
+ base.AddParameterProfile(
+ new ParameterProfile("ElementProvider",
+ typeof(string),
+ true,
+ new ConstantValueProvider(string.Empty),
+ StandardWidgetFunctions.TextBoxWidget,
+ null,
+ "Element Provider", new HelpDefinition("The name of a tree element provider (as defined in Composite.config)")));
+
+ base.AddParameterProfile(
+ new ParameterProfile("SelectableElementPropertyName",
+ typeof(string),
+ true,
+ new ConstantValueProvider(string.Empty),
+ StandardWidgetFunctions.TextBoxWidget,
+ null,
+ "Selectable Element Property Name", new HelpDefinition("The name of a property used to identify a selectable tree element by")));
+
+ base.AddParameterProfile(
+ new ParameterProfile("SelectableElementPropertyValue",
+ typeof(string),
+ false,
+ new ConstantValueProvider(string.Empty),
+ StandardWidgetFunctions.TextBoxWidget,
+ null,
+ "Selectable Element Property Value", new HelpDefinition("The value of the property optionally used (if provided) to further identify a selectable tree element by")));
+
+ base.AddParameterProfile(
+ new ParameterProfile("SelectableElementReturnValue",
+ typeof(string),
+ false,
+ new ConstantValueProvider(string.Empty),
+ StandardWidgetFunctions.TextBoxWidget,
+ null,
+ "Selectable Element Return Value", new HelpDefinition("The value to return for the selected tree element")));
+ base.AddParameterProfile(
+ new ParameterProfile("SerializedSearchToken",
+ typeof(string),
+ false,
+ new ConstantValueProvider(string.Empty),
+ StandardWidgetFunctions.TextBoxWidget,
+ null,
+ "Selectable Element Return Value", new HelpDefinition("A search token to filter tree elements by")));
+ base.AddParameterProfile(
+ new ParameterProfile("Required",
+ typeof(bool),
+ false,
+ new ConstantValueProvider(true),
+ StandardWidgetFunctions.GetBoolSelectorWidget("Yes, selection is required", "No, a 'none' selection is allowed."),
+ null,
+ "Required", new HelpDefinition("An option that indicates whether the user is required to make a selection")));
+
+ }
+
+
+ public override XElement GetWidgetMarkup(ParameterList parameters, string label, HelpDefinition helpDefinition, string bindingSourceName)
+ {
+ XElement formElement = base.BuildBasicWidgetMarkup("TreeSelector", "SelectedKey", label, helpDefinition, bindingSourceName);
+ foreach (var propertyName in new []
+ {
+ "ElementProvider", "SelectableElementPropertyName", "SelectableElementPropertyValue", "SelectableElementReturnValue", "SerializedSearchToken", "Required"
+ })
+ {
+ string propertyValue = parameters.GetParameter(propertyName);
+ formElement.Add(new XAttribute(propertyName, propertyValue));
+ }
+ return formElement;
+ }
+ }
+}
diff --git a/Composite/Properties/SharedAssemblyInfo.cs b/Composite/Properties/SharedAssemblyInfo.cs
index c83dfe9766..dc4329dde4 100644
--- a/Composite/Properties/SharedAssemblyInfo.cs
+++ b/Composite/Properties/SharedAssemblyInfo.cs
@@ -2,9 +2,9 @@
// General Information about the assemblies Composite and Composite.Workflows
#if !InternalBuild
-[assembly: AssemblyTitle("C1 CMS 6.7")]
+[assembly: AssemblyTitle("C1 CMS 6.8")]
#else
-[assembly: AssemblyTitle("C1 CMS 6.7 (Internal Build)")]
+[assembly: AssemblyTitle("C1 CMS 6.8 (Internal Build)")]
#endif
[assembly: AssemblyCompany("Orckestra Inc")]
@@ -13,4 +13,4 @@
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-[assembly: AssemblyVersion("6.7.*")]
+[assembly: AssemblyVersion("6.8.*")]
diff --git a/Package.nuspec b/Package.nuspec
index 6054b350dd..5925153686 100644
--- a/Package.nuspec
+++ b/Package.nuspec
@@ -28,9 +28,8 @@
-
-
-
-
+
+
+
diff --git a/Website/App_Data/Composite/DebugBuild.Composite.config b/Website/App_Data/Composite/DebugBuild.Composite.config
index b444bb16eb..c1c5c02345 100644
--- a/Website/App_Data/Composite/DebugBuild.Composite.config
+++ b/Website/App_Data/Composite/DebugBuild.Composite.config
@@ -194,7 +194,8 @@
-
+
+
diff --git a/Website/App_Data/Composite/ReleaseBuild.Composite.config b/Website/App_Data/Composite/ReleaseBuild.Composite.config
index 112f99a63d..b257af27c6 100644
--- a/Website/App_Data/Composite/ReleaseBuild.Composite.config
+++ b/Website/App_Data/Composite/ReleaseBuild.Composite.config
@@ -189,7 +189,8 @@
-
+
+
diff --git a/Website/App_Data/Composite/ReleaseBuild.Composite.config.changeHistory.txt b/Website/App_Data/Composite/ReleaseBuild.Composite.config.changeHistory.txt
index 9b5c5997ea..6e456a7377 100644
--- a/Website/App_Data/Composite/ReleaseBuild.Composite.config.changeHistory.txt
+++ b/Website/App_Data/Composite/ReleaseBuild.Composite.config.changeHistory.txt
@@ -173,4 +173,4 @@ Changes in 6.0 or later
-Added to loggingConfiguration/specialSources/allEvents/listeners
Changes in 6.7 or later:
- - n/a
\ No newline at end of file
+ -Added to configuration/Composite.C1Console.Forms.Plugins.UiControlFactoryConfiguration/Channels/Channel/Namespaces/Namespace/Factories
\ No newline at end of file
diff --git a/Website/Composite/CompileScripts.xml b/Website/Composite/CompileScripts.xml
index 6cca8a60ce..6973950b2d 100644
--- a/Website/Composite/CompileScripts.xml
+++ b/Website/Composite/CompileScripts.xml
@@ -1,4 +1,4 @@
-
+
@@ -196,6 +196,7 @@
+
diff --git a/Website/Composite/controls/FormsControls/FormUiControlTemplates/Selectors/TreeSelector.ascx b/Website/Composite/controls/FormsControls/FormUiControlTemplates/Selectors/TreeSelector.ascx
new file mode 100644
index 0000000000..fb1f6e07a6
--- /dev/null
+++ b/Website/Composite/controls/FormsControls/FormUiControlTemplates/Selectors/TreeSelector.ascx
@@ -0,0 +1,55 @@
+<%@ Control Language="C#" Inherits="Composite.Plugins.Forms.WebChannel.UiControlFactories.TreeSelectorTemplateUserControlBase" %>
+
+
+ />
diff --git a/Website/Composite/scripts/source/top/core/ViewDefinitions.js b/Website/Composite/scripts/source/top/core/ViewDefinitions.js
index 1cf01c2c8b..a24999d56a 100644
--- a/Website/Composite/scripts/source/top/core/ViewDefinitions.js
+++ b/Website/Composite/scripts/source/top/core/ViewDefinitions.js
@@ -436,6 +436,26 @@ var ViewDefinitions = {
}
}),
+ /*
+ * Stub for tree selector.
+ */
+ "Composite.Management.TreeSelectorDialog": new DialogViewDefinition({
+ handle: "Composite.Management.TreeSelectorDialog",
+ isMutable : true,
+ position: Dialog.MODAL,
+ url: Dialog.URL_TREESELECTOR,
+ argument: {
+ label: "",
+ image: "${icon:link}",
+ selectionProperty: "ElementType",
+ selectionValue: null,
+ selectionResult: null,
+ nodes: [
+ { key: null }
+ ]
+ }
+ }),
+
/*
* Function selector (ALL TYPES).
*/
diff --git a/Website/Composite/scripts/source/top/ui/bindings/data/dialogs/DataInputDialogBinding.js b/Website/Composite/scripts/source/top/ui/bindings/data/dialogs/DataInputDialogBinding.js
index d3eae4d87f..3ebf05284a 100644
--- a/Website/Composite/scripts/source/top/ui/bindings/data/dialogs/DataInputDialogBinding.js
+++ b/Website/Composite/scripts/source/top/ui/bindings/data/dialogs/DataInputDialogBinding.js
@@ -68,12 +68,8 @@ DataInputDialogBinding.prototype.buildButton = function () {
self._isButtonClicked = false;
}, 1000);
- var handle = self.getProperty("handle");
- var definition = ViewDefinition.clone(
- handle,
- "Generated.ViewDefinition.Handle." + KeyMaster.getUniqueKey()
- );
+ var definition = self.getDefinition();
if (definition instanceof DialogViewDefinition) {
@@ -108,6 +104,22 @@ DataInputDialogBinding.prototype.buildButton = function () {
this._dialogButtonBinding = button;
};
+/**
+ * Get definition to invoke.
+ */
+DataInputDialogBinding.prototype.getDefinition = function () {
+
+ var handle = this.getProperty("handle");
+
+ var definition = ViewDefinition.clone(
+ handle,
+ "Generated.ViewDefinition.Handle." + KeyMaster.getUniqueKey()
+ );
+
+ return definition;
+};
+
+
/**
* Invoke dialog programatically.
*/
diff --git a/Website/Composite/scripts/source/top/ui/bindings/data/dialogs/TreeSelectorDialogBinding.js b/Website/Composite/scripts/source/top/ui/bindings/data/dialogs/TreeSelectorDialogBinding.js
new file mode 100644
index 0000000000..5ae041dcfa
--- /dev/null
+++ b/Website/Composite/scripts/source/top/ui/bindings/data/dialogs/TreeSelectorDialogBinding.js
@@ -0,0 +1,53 @@
+TreeSelectorDialogBinding.prototype = new DataInputDialogBinding;
+TreeSelectorDialogBinding.prototype.constructor = TreeSelectorDialogBinding;
+TreeSelectorDialogBinding.superclass = DataInputDialogBinding.prototype;
+
+/**
+* @class
+* @implements {IData}
+*/
+function TreeSelectorDialogBinding() {
+
+ /**
+ * @type {SystemLogger}
+ */
+ this.logger = SystemLogger.getLogger("TreeSelectorDialogBinding");
+
+ /**
+ * @type {LabelBinding}
+ */
+ this.labelBinding = null;
+
+
+}
+
+/**
+* Identifies binding.
+*/
+TreeSelectorDialogBinding.prototype.toString = function () {
+
+ return "[TreeSelectorDialogBinding]";
+}
+
+/**
+ * Get definition to invoke.
+ * @overloads {DataInputDialogBinding#getDefinition}
+ */
+TreeSelectorDialogBinding.prototype.getDefinition = function () {
+
+ var definition = ViewDefinition.clone(
+ "Composite.Management.TreeSelectorDialog",
+ "Generated.ViewDefinition.Handle." + KeyMaster.getUniqueKey()
+ );
+ definition.argument.selectionProperty = this.getProperty("selection-property");
+ definition.argument.selectionValue = this.getProperty("selection-value");
+ definition.argument.selectionResult = this.getProperty("selection-result");
+ definition.argument.nodes = [
+ {
+ key: this.getProperty("element-provider"),
+ search: this.getProperty('serialized-search-token')
+ }
+ ];
+
+ return definition;
+};
\ No newline at end of file
diff --git a/Website/Frontend/Config/VisualEditor/Default.common.xml b/Website/Frontend/Config/VisualEditor/ReleaseBuild.common.xml
similarity index 99%
rename from Website/Frontend/Config/VisualEditor/Default.common.xml
rename to Website/Frontend/Config/VisualEditor/ReleaseBuild.common.xml
index f30438f247..9cfefcfa90 100644
--- a/Website/Frontend/Config/VisualEditor/Default.common.xml
+++ b/Website/Frontend/Config/VisualEditor/ReleaseBuild.common.xml
@@ -130,4 +130,4 @@
-
\ No newline at end of file
+
diff --git a/Website/ReleaseCleanupConfiguration.xml b/Website/ReleaseCleanupConfiguration.xml
index 20ff15d3fc..92ece5a5fc 100644
--- a/Website/ReleaseCleanupConfiguration.xml
+++ b/Website/ReleaseCleanupConfiguration.xml
@@ -1,4 +1,4 @@
-
+
diff --git a/Website/WebSite.csproj b/Website/WebSite.csproj
index 820e32b677..c0eb6cac51 100644
--- a/Website/WebSite.csproj
+++ b/Website/WebSite.csproj
@@ -324,6 +324,7 @@
+
@@ -664,6 +665,7 @@
+
@@ -2799,19 +2801,18 @@
)
if not exist "$(ProjectDir)Frontend\Config\VisualEditor\common.xml" (
- copy "$(ProjectDir)Frontend\Config\VisualEditor\Default.common.xml" "$(ProjectDir)Frontend\Config\VisualEditor\common.xml"
+ copy "$(ProjectDir)Frontend\Config\VisualEditor\ReleaseBuild.common.xml" "$(ProjectDir)Frontend\Config\VisualEditor\common.xml"
)
if not exist "$(TargetDir)\System.Threading.Tasks.Dataflow.dll" (
copy "$(ProjectDir)\..\Packages\System.Threading.Tasks.Dataflow.4.6.0\lib\netstandard1.1\System.Threading.Tasks.Dataflow.dll" "$(TargetDir)\System.Threading.Tasks.Dataflow.dll"
)
-
cd "$(ProjectDir)"
- .\node_modules\.bin\jspm install --quick
+ robocopy "..\Packages\PhantomJS.2.1.1\tools\phantomjs" "App_Data\Composite\PhantomJs" "phantomjs.exe"
+ .\node_modules\.bin\jspm install --quick
- robocopy "$(ProjectDir)\..\Packages\PhantomJS.2.1.1\tools\phantomjs" "$(ProjectDir)\App_Data\Composite\PhantomJs" "phantomjs.exe"
set rce=%25errorlevel%25
if not %25rce%25==1 exit %25rce%25 else exit 0
@@ -2819,4 +2820,4 @@
-
\ No newline at end of file
+
diff --git a/Website/package.json b/Website/package.json
index 95bb8dc981..53d939be87 100644
--- a/Website/package.json
+++ b/Website/package.json
@@ -14,10 +14,10 @@
"devDependencies": {
"JSONPath": "^0.10.0",
"autoprefixer-core": "^5.2.1",
- "chromedriver": "^2.34.0",
"chokidar-socket-emitter": "0.5.4",
+ "chromedriver": "^2.34.0",
"csswring": "^3.0.5",
- "eslint": "3.1.1",
+ "eslint": "^4.18.2",
"eslint-plugin-mocha": "4.0.0",
"eslint-plugin-react": "5.2.2",
"grunt": "~0.4.5",