Merge remote-tracking branch 'origin/dev-v7' into dev-v7.10

This commit is contained in:
Shannon
2018-03-21 10:20:20 +11:00
17 changed files with 287 additions and 24 deletions

View File

@@ -30,7 +30,7 @@ As an Open Source platform, Umbraco is more than just a CMS. We are transparent
[Umbraco Cloud](https://umbraco.com) is the easiest and fastest way to use Umbraco yet with full support for all your custom .NET code and intergrations. You're up and running in less than a minute and your life will be made easier with automated upgrades and a built-in deployment engine. We offer a free 14 day trial, no credit card needed.
If you want to DIY you can [download Umbraco](https://our.umbraco.org/download) either as a ZIP file or via NuGet. It's the same version of Umbraco CMS that powers Umbraco Xloud, but you'll need to find a place to host yourself and handling deployments and upgrades is all down to you.
If you want to DIY you can [download Umbraco](https://our.umbraco.org/download) either as a ZIP file or via NuGet. It's the same version of Umbraco CMS that powers Umbraco Cloud, but you'll need to find a place to host yourself and handling deployments and upgrades is all down to you.
## Community

View File

@@ -122,6 +122,11 @@ namespace Umbraco.Core
/// Alias for the Dropdown list, publishing keys datatype.
/// </summary>
public const string DropdownlistPublishingKeysAlias = "Umbraco.DropdownlistPublishingKeys";
/// <summary>
/// Alias for the "new" Dropdown list, that replaces the old four deprecated ones and works as other list based property editors
/// </summary>
public const string DropDownListFlexibleAlias = "Umbraco.DropDown.Flexible";
/// <summary>
/// Guid for the Folder browser datatype.
@@ -452,4 +457,4 @@ namespace Umbraco.Core
}
}
}
}
}

View File

@@ -59,7 +59,6 @@
</pre>
<h1>General Options</h1>
Lorem ipsum dolor sit amet..
<table>
<thead>
<tr>
@@ -74,7 +73,7 @@ Lorem ipsum dolor sit amet..
<td>Set the title of the overlay.</td>
</tr>
<tr>
<td>model.subTitle</td>
<td>model.subtitle</td>
<td>String</td>
<td>Set the subtitle of the overlay.</td>
</tr>
@@ -496,6 +495,7 @@ Opens an overlay to show a custom YSOD. </br>
var activeElementType = document.activeElement.tagName;
var clickableElements = ["A", "BUTTON"];
var submitOnEnter = document.activeElement.hasAttribute("overlay-submit-on-enter");
var submitOnEnterValue = submitOnEnter ? document.activeElement.getAttribute("overlay-submit-on-enter") : "";
if(clickableElements.indexOf(activeElementType) === 0) {
document.activeElement.click();
@@ -503,7 +503,9 @@ Opens an overlay to show a custom YSOD. </br>
} else if(activeElementType === "TEXTAREA" && !submitOnEnter) {
} else {
} else if (submitOnEnter && submitOnEnterValue === "false") {
// don't do anything
}else {
scope.$apply(function () {
scope.submitForm(scope.model);
});

View File

@@ -168,6 +168,9 @@
//used for property editors
@import "property-editors.less";
//used for prevalue editors
@import "components/prevalues/multivalues.less";
@import "typeahead.less";
@import "hacks.less";
@@ -175,4 +178,4 @@
@import "healthcheck.less";
// cleanup properties.less when it is done
@import "properties.less";
@import "properties.less";

View File

@@ -0,0 +1,53 @@
.umb-prevalues-multivalues {
width: 400px;
}
.umb-prevalues-multivalues__left {
display: flex;
flex: 1 1 auto;
}
.umb-prevalues-multivalues__right {
display: flex;
flex: 0 0 auto;
align-items: center;
}
.umb-prevalues-multivalues__add {
display: flex;
}
.umb-prevalues-multivalues__add input {
width: 320px;
}
.umb-prevalues-multivalues__add input {
display: flex;
}
.umb-prevalues-multivalues__add button {
margin: 0 6px 0 0;
float: right
}
.umb-prevalues-multivalues__listitem {
display: flex;
padding: 6px;
margin: 10px 0px !important;
background: #F3F3F5;
cursor: move;
}
.umb-prevalues-multivalues__listitem i {
display: flex;
align-items: center;
margin-right: 5px
}
.umb-prevalues-multivalues__listitem a {
cursor: pointer;
}
.umb-prevalues-multivalues__listitem input {
width: 295px;
}

View File

@@ -1 +1 @@
<input name="boolean" type="checkbox" ng-model="model.value" ng-true-value="1" ng-false-value="0" />
<input name="boolean" type="checkbox" ng-model="model.value" ng-true-value="1" ng-false-value="0" id="boolean" /> <label for="boolean">True</label>

View File

@@ -5,6 +5,7 @@ angular.module("umbraco").controller("Umbraco.PrevalueEditors.MultiValuesControl
$scope.newItem = "";
$scope.hasError = false;
$scope.focusOnNew = false;
if (!angular.isArray($scope.model.value)) {
@@ -43,6 +44,7 @@ angular.module("umbraco").controller("Umbraco.PrevalueEditors.MultiValuesControl
$scope.model.value.push({ value: $scope.newItem });
$scope.newItem = "";
$scope.hasError = false;
$scope.focusOnNew = true;
return;
}
}
@@ -73,6 +75,12 @@ angular.module("umbraco").controller("Umbraco.PrevalueEditors.MultiValuesControl
}
};
$scope.createNew = function (event) {
if (event.keyCode == 13) {
$scope.add(event);
}
}
function getElementIndexByPrevalueText(value) {
for (var i = 0; i < $scope.model.value.length; i++) {
if ($scope.model.value[i].value === value) {

View File

@@ -1,13 +1,21 @@
<div class="umb-editor" ng-controller="Umbraco.PrevalueEditors.MultiValuesController">
<div class="control-group">
<input name="newItem" type="text" ng-model="newItem" val-highlight="{{hasError}}" />
<button class="btn" ng-click="add($event)">Add</button>
<div class="umb-editor umb-prevalues-multivalues" ng-controller="Umbraco.PrevalueEditors.MultiValuesController">
<div class="control-group umb-prevalues-multivalues__add">
<div class="umb-prevalues-multivalues__left">
<input overlay-submit-on-enter="false" name="newItem" focus-when="{{focusOnNew}}" ng-keydown="createNew($event)" type="text" ng-model="newItem" val-highlight="{{hasError}}" />
</div>
<div class="umb-prevalues-multivalues__right">
<button class="btn btn-info" ng-click="add($event)">Add</button>
</div>
</div>
<div ui-sortable="sortableOptions">
<div class="control-group" ng-repeat="item in model.value">
<div class="control-group umb-prevalues-multivalues__listitem" ng-repeat="item in model.value">
<i class="icon icon-navigation handle"></i>
<input type="text" ng-model="item.value" val-server="item_{{$index}}" required />
<button class="btn btn-danger" ng-click="remove(item, $event)">Remove</button>
<div class="umb-prevalues-multivalues__left">
<input type="text" ng-model="item.value" val-server="item_{{$index}}" required />
</div>
<div class="umb-prevalues-multivalues__right">
<a class="umb-node-preview__action" ng-click="remove(item, $event)">Remove</a>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,81 @@
angular.module("umbraco").controller("Umbraco.PropertyEditors.DropdownFlexibleController",
function($scope) {
//setup the default config
var config = {
items: [],
multiple: false
};
//map the user config
angular.extend(config, $scope.model.config);
//map back to the model
$scope.model.config = config;
function convertArrayToDictionaryArray(model){
//now we need to format the items in the dictionary because we always want to have an array
var newItems = [];
for (var i = 0; i < model.length; i++) {
newItems.push({ id: model[i], sortOrder: 0, value: model[i] });
}
return newItems;
}
function convertObjectToDictionaryArray(model){
//now we need to format the items in the dictionary because we always want to have an array
var newItems = [];
var vals = _.values($scope.model.config.items);
var keys = _.keys($scope.model.config.items);
for (var i = 0; i < vals.length; i++) {
var label = vals[i].value ? vals[i].value : vals[i];
newItems.push({ id: keys[i], sortOrder: vals[i].sortOrder, value: label });
}
return newItems;
}
$scope.updateSingleDropdownValue = function() {
$scope.model.value = [$scope.model.singleDropdownValue];
}
if (angular.isArray($scope.model.config.items)) {
//PP: I dont think this will happen, but we have tests that expect it to happen..
//if array is simple values, convert to array of objects
if(!angular.isObject($scope.model.config.items[0])){
$scope.model.config.items = convertArrayToDictionaryArray($scope.model.config.items);
}
}
else if (angular.isObject($scope.model.config.items)) {
$scope.model.config.items = convertObjectToDictionaryArray($scope.model.config.items);
}
else {
throw "The items property must be either an array or a dictionary";
}
//sort the values
$scope.model.config.items.sort(function (a, b) { return (a.sortOrder > b.sortOrder) ? 1 : ((b.sortOrder > a.sortOrder) ? -1 : 0); });
//now we need to check if the value is null/undefined, if it is we need to set it to "" so that any value that is set
// to "" gets selected by default
if ($scope.model.value === null || $scope.model.value === undefined) {
if ($scope.model.config.multiple) {
$scope.model.value = [];
}
else {
$scope.model.value = "";
}
}
// if we run in single mode we'll store the value in a local variable
// so we can pass an array as the model as our PropertyValueEditor expects that
$scope.model.singleDropdownValue = "";
if ($scope.model.config.multiple === "0") {
$scope.model.singleDropdownValue = Array.isArray($scope.model.value) ? $scope.model.value[0] : $scope.model.value;
}
});

View File

@@ -0,0 +1,19 @@
<div ng-controller="Umbraco.PropertyEditors.DropdownFlexibleController" ng-switch="model.config.multiple">
<select name="dropDownList"
class="umb-editor umb-dropdown"
ng-switch-default
ng-change="updateSingleDropdownValue()"
ng-model="model.singleDropdownValue"
ng-options="item.id as item.value for item in model.config.items">
<option></option>
</select>
<!--NOTE: This ng-switch is required because ng-multiple doesn't actually support dynamic bindings with multi-select lists -->
<select name="dropDownList"
class="umb-editor umb-dropdown"
ng-switch-when="1"
multiple
ng-model="model.value"
ng-options="item.id as item.value for item in model.config.items"></select>
</div>

View File

@@ -92,7 +92,6 @@
$scope.model.config.ticksPositions = _.map($scope.model.config.ticksPositions.split(','), function (item) {
return parseInt(item.trim());
});
console.log($scope.model.config.ticksPositions);
}
if (!$scope.model.config.ticksLabels) {
@@ -215,4 +214,4 @@
assetsService.loadCss("lib/slider/bootstrap-slider.css");
assetsService.loadCss("lib/slider/bootstrap-slider-custom.css");
}
angular.module("umbraco").controller("Umbraco.PropertyEditors.SliderController", sliderController);
angular.module("umbraco").controller("Umbraco.PropertyEditors.SliderController", sliderController);

View File

@@ -15,7 +15,7 @@ namespace Umbraco.Web.PropertyEditors
[ParameterEditor("propertyTypePickerMultiple", "Name", "textbox")]
[ParameterEditor("contentTypeMultiple", "Name", "textbox")]
[ParameterEditor("tabPickerMultiple", "Name", "textbox")]
[PropertyEditor(Constants.PropertyEditors.DropDownListMultipleAlias, "Dropdown list multiple", "dropdown", Group = "lists", Icon="icon-bulleted-list")]
[PropertyEditor(Constants.PropertyEditors.DropDownListMultipleAlias, "Dropdown list multiple", "dropdown", Group = "lists", Icon="icon-bulleted-list", IsDeprecated = true)]
public class DropDownMultiplePropertyEditor : DropDownMultipleWithKeysPropertyEditor
{
protected override PropertyValueEditor CreateValueEditor()
@@ -28,4 +28,4 @@ namespace Umbraco.Web.PropertyEditors
}
}

View File

@@ -12,7 +12,7 @@ namespace Umbraco.Web.PropertyEditors
/// Due to maintaining backwards compatibility this data type stores the value as a string which is a comma separated value of the
/// ids of the individual items so we have logic in here to deal with that.
/// </remarks>
[PropertyEditor(Constants.PropertyEditors.DropdownlistMultiplePublishKeysAlias, "Dropdown list multiple, publish keys", "dropdown", Group = "lists", Icon = "icon-bulleted-list")]
[PropertyEditor(Constants.PropertyEditors.DropdownlistMultiplePublishKeysAlias, "Dropdown list multiple, publish keys", "dropdown", Group = "lists", Icon = "icon-bulleted-list", IsDeprecated = true)]
public class DropDownMultipleWithKeysPropertyEditor : DropDownPropertyEditor
{
protected override PropertyValueEditor CreateValueEditor()
@@ -62,4 +62,4 @@ namespace Umbraco.Web.PropertyEditors
}
}
}
}

View File

@@ -16,7 +16,7 @@ namespace Umbraco.Web.PropertyEditors
/// as INT and we have logic in here to ensure it is formatted correctly including ensuring that the string value is published
/// in cache and not the int ID.
/// </remarks>
[PropertyEditor(Constants.PropertyEditors.DropDownListAlias, "Dropdown list", "dropdown", ValueType = PropertyEditorValueTypes.String, Group = "lists", Icon = "icon-indent")]
[PropertyEditor(Constants.PropertyEditors.DropDownListAlias, "Dropdown list", "dropdown", ValueType = PropertyEditorValueTypes.String, Group = "lists", Icon = "icon-indent", IsDeprecated = true)]
public class DropDownPropertyEditor : DropDownWithKeysPropertyEditor
{
/// <summary>
@@ -29,4 +29,4 @@ namespace Umbraco.Web.PropertyEditors
}
}
}
}

View File

@@ -11,7 +11,7 @@ namespace Umbraco.Web.PropertyEditors
/// as INT and we have logic in here to ensure it is formatted correctly including ensuring that the INT ID value is published
/// in cache and not the string value.
/// </remarks>
[PropertyEditor(Constants.PropertyEditors.DropdownlistPublishingKeysAlias, "Dropdown list, publishing keys", "dropdown", ValueType = PropertyEditorValueTypes.Integer, Group = "lists", Icon = "icon-indent")]
[PropertyEditor(Constants.PropertyEditors.DropdownlistPublishingKeysAlias, "Dropdown list, publishing keys", "dropdown", ValueType = PropertyEditorValueTypes.Integer, Group = "lists", Icon = "icon-indent", IsDeprecated = true)]
public class DropDownWithKeysPropertyEditor : PropertyEditor
{
@@ -24,4 +24,4 @@ namespace Umbraco.Web.PropertyEditors
return new ValueListPreValueEditor();
}
}
}
}

View File

@@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
namespace Umbraco.Web.PropertyEditors
{
[PropertyEditor(Constants.PropertyEditors.DropDownListFlexibleAlias, "Dropdown", "dropdownFlexible", Group = "lists", Icon = "icon-indent")]
public class DropdownFlexiblePropertyEditor : PropertyEditor
{
private static readonly string _multipleKey = "multiple";
/// <summary>
/// Return a custom pre-value editor
/// </summary>
/// <returns></returns>
/// <remarks>
/// We are just going to re-use the ValueListPreValueEditor
/// </remarks>
protected override PreValueEditor CreatePreValueEditor()
{
return new DropdownFlexiblePreValueEditor();
}
/// <summary>
/// We need to override the value editor so that we can ensure the string value is published in cache and not the integer ID value.
/// </summary>
/// <returns></returns>
protected override PropertyValueEditor CreateValueEditor()
{
return new PublishValuesMultipleValueEditor(false, base.CreateValueEditor());
}
internal class DropdownFlexiblePreValueEditor : ValueListPreValueEditor
{
public DropdownFlexiblePreValueEditor()
{
Fields.Insert(0, new PreValueField
{
Key = "multiple",
Name = "Enable multiple choice",
Description = "When checked, the dropdown will be a select multiple / combo box style dropdown",
View = "boolean"
});
}
public override IDictionary<string, PreValue> ConvertEditorToDb(IDictionary<string, object> editorValue, PreValueCollection currentValue)
{
var result = base.ConvertEditorToDb(editorValue, currentValue);
// get multiple config
var multipleValue = editorValue[_multipleKey] != null ? editorValue[_multipleKey].ToString() : "0";
result.Add(_multipleKey, new PreValue(-1, multipleValue));
return result;
}
public override IDictionary<string, object> ConvertDbToEditor(IDictionary<string, object> defaultPreVals, PreValueCollection persistedPreVals)
{
// weird way, but as the value stored is 0 or 1 need to do it this way
string multipleMode = "0";
if (persistedPreVals != null && persistedPreVals.PreValuesAsDictionary[_multipleKey] != null)
{
multipleMode = persistedPreVals.PreValuesAsDictionary[_multipleKey].Value;
// remove from the collection sent to the base multiple values collection
persistedPreVals.PreValuesAsDictionary.Remove(_multipleKey);
}
var returnVal = base.ConvertDbToEditor(defaultPreVals, persistedPreVals);
returnVal[_multipleKey] = multipleMode;
return returnVal;
}
}
}
}

View File

@@ -340,6 +340,7 @@
<Compile Include="Models\Mapping\ContentTreeNodeUrlResolver.cs" />
<Compile Include="Models\Mapping\MemberTreeNodeUrlResolver.cs" />
<Compile Include="Models\Trees\ExportMember.cs" />
<Compile Include="PropertyEditors\DropdownFlexiblePropertyEditor.cs" />
<Compile Include="TourFilterResolver.cs" />
<Compile Include="Editors\UserEditorAuthorizationHelper.cs" />
<Compile Include="Editors\UserGroupAuthorizationAttribute.cs" />