diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditors.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditors.directive.js index 9ea4a3fb12..23271a70d5 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditors.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditors.directive.js @@ -12,6 +12,8 @@ function addEditor(editor) { + editor.animating = true; + showOverlayOnPrevEditor(); // start collapsing editors to make room for new ones @@ -58,7 +60,7 @@ return (index + 1) * 80; }, easing: 'easeInOutQuint', - duration: 600 + duration: 500 }); */ @@ -92,7 +94,12 @@ translateX: [100 + '%', 0], opacity: [0, 1], easing: 'easeInOutQuint', - duration: 600 + duration: 500, + complete: function() { + $timeout(function(){ + editor.animating = false; + }); + } }); }); @@ -101,6 +108,8 @@ function removeEditor(editor) { + editor.animating = true; + $timeout(function(){ var editorsElement = el[0]; @@ -111,7 +120,7 @@ translateX: [0, 100 + '%'], opacity: [1, 0], easing: 'easeInOutQuint', - duration: 600, + duration: 500, complete: function(a) { $timeout(function(){ scope.editors.splice(-1,1); @@ -162,7 +171,7 @@ } }, easing: 'easeInOutQuint', - duration: 600, + duration: 500, completed: function() { } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js index c0be05addf..e2c2caf85b 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js @@ -1,7 +1,7 @@ (function() { 'use strict'; - function GroupsBuilderDirective(contentTypeHelper, contentTypeResource, mediaTypeResource, dataTypeHelper, dataTypeResource, $filter, iconHelper, $q, $timeout, notificationsService, localizationService) { + function GroupsBuilderDirective(contentTypeHelper, contentTypeResource, mediaTypeResource, dataTypeHelper, dataTypeResource, $filter, iconHelper, $q, $timeout, notificationsService, localizationService, editorService) { function link(scope, el, attr, ctrl) { @@ -491,13 +491,73 @@ if (!property.inherited) { - scope.propertySettingsDialogModel = {}; - scope.propertySettingsDialogModel.title = "Property settings"; - scope.propertySettingsDialogModel.property = property; - scope.propertySettingsDialogModel.contentType = scope.contentType; - scope.propertySettingsDialogModel.contentTypeName = scope.model.name; - scope.propertySettingsDialogModel.view = "views/common/overlays/contenttypeeditor/propertysettings/propertysettings.html"; - scope.propertySettingsDialogModel.show = true; + var oldPropertyModel = angular.copy(property); + + var propertySettings = { + title: "Property settings", + property: property, + contentType: scope.contentType, + contentTypeName: scope.model.name, + view: "views/pickers/propertysettings/propertysettings.html", + size: "small", + submit: function(model) { + + property.inherited = false; + property.dialogIsOpen = false; + + // update existing data types + if(model.updateSameDataTypes) { + updateSameDataTypes(property); + } + + // close the editor + editorService.close(); + + // push new init property to group + addInitProperty(group); + + // set focus on init property + var numberOfProperties = group.properties.length; + group.properties[numberOfProperties - 1].focus = true; + + // push new init tab to the scope + addInitGroup(scope.model.groups); + + }, + close: function() { + + // reset all property changes + property.label = oldPropertyModel.label; + property.alias = oldPropertyModel.alias; + property.description = oldPropertyModel.description; + property.config = oldPropertyModel.config; + property.editor = oldPropertyModel.editor; + property.view = oldPropertyModel.view; + property.dataTypeId = oldPropertyModel.dataTypeId; + property.dataTypeIcon = oldPropertyModel.dataTypeIcon; + property.dataTypeName = oldPropertyModel.dataTypeName; + property.validation.mandatory = oldPropertyModel.validation.mandatory; + property.validation.pattern = oldPropertyModel.validation.pattern; + property.showOnMemberProfile = oldPropertyModel.showOnMemberProfile; + property.memberCanEdit = oldPropertyModel.memberCanEdit; + property.isSensitiveValue = oldPropertyModel.isSensitiveValue; + + // because we set state to active, to show a preview, we have to check if has been filled out + // label is required so if it is not filled we know it is a placeholder + if(oldPropertyModel.editor === undefined || oldPropertyModel.editor === null || oldPropertyModel.editor === "") { + property.propertyState = "init"; + } else { + property.propertyState = oldPropertyModel.propertyState; + } + + // remove the editor + editorService.close(); + + } + }; + + // open property settings editor + editorService.open(propertySettings); // set state to active to access the preview property.propertyState = "active"; @@ -505,64 +565,6 @@ // set property states property.dialogIsOpen = true; - scope.propertySettingsDialogModel.submit = function(model) { - - property.inherited = false; - property.dialogIsOpen = false; - - // update existing data types - if(model.updateSameDataTypes) { - updateSameDataTypes(property); - } - - // remove dialog - scope.propertySettingsDialogModel.show = false; - scope.propertySettingsDialogModel = null; - - // push new init property to group - addInitProperty(group); - - // set focus on init property - var numberOfProperties = group.properties.length; - group.properties[numberOfProperties - 1].focus = true; - - // push new init tab to the scope - addInitGroup(scope.model.groups); - - }; - - scope.propertySettingsDialogModel.close = function(oldModel) { - - // reset all property changes - property.label = oldModel.property.label; - property.alias = oldModel.property.alias; - property.description = oldModel.property.description; - property.config = oldModel.property.config; - property.editor = oldModel.property.editor; - property.view = oldModel.property.view; - property.dataTypeId = oldModel.property.dataTypeId; - property.dataTypeIcon = oldModel.property.dataTypeIcon; - property.dataTypeName = oldModel.property.dataTypeName; - property.validation.mandatory = oldModel.property.validation.mandatory; - property.validation.pattern = oldModel.property.validation.pattern; - property.showOnMemberProfile = oldModel.property.showOnMemberProfile; - property.memberCanEdit = oldModel.property.memberCanEdit; - property.isSensitiveValue = oldModel.property.isSensitiveValue; - - // because we set state to active, to show a preview, we have to check if has been filled out - // label is required so if it is not filled we know it is a placeholder - if(oldModel.property.editor === undefined || oldModel.property.editor === null || oldModel.property.editor === "") { - property.propertyState = "init"; - } else { - property.propertyState = oldModel.property.propertyState; - } - - // remove dialog - scope.propertySettingsDialogModel.show = false; - scope.propertySettingsDialogModel = null; - - }; - } }; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-editor.less b/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-editor.less index b4a0ffe895..25f8b7e255 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-editor.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-editor.less @@ -26,6 +26,10 @@ .umb-editor--small { width: 500px; left: auto; + + .umb-editor-container { + max-width: 500px; + } } .umb-editor__overlay { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less index eecbf51ec5..9afe5182c9 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less @@ -13,6 +13,7 @@ border-radius: 0 10px 10px 10px; padding: 10px 10px 5px 10px; box-sizing: border-box; + background-color: @white; } .umb-group-builder__group.-active { @@ -536,4 +537,4 @@ input.umb-group-builder__group-title-input { label.checkbox.no-indent { width: 100%; } -} +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor.html b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor.html index 31e19a5f61..af24d20ec0 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor.html @@ -1,5 +1,5 @@
-
-
+
+
\ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html b/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html index 628549cee9..5a0d98e8d8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html @@ -300,12 +300,4 @@ view="compositionsDialogModel.view"> - - - diff --git a/src/Umbraco.Web.UI.Client/src/views/pickers/datatypepicker/datatypepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/pickers/datatypepicker/datatypepicker.controller.js new file mode 100644 index 0000000000..53ad1053a0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/pickers/datatypepicker/datatypepicker.controller.js @@ -0,0 +1,214 @@ +/** + * @ngdoc controller + * @name Umbraco.Editors.DataTypePickerController + * @function + * + * @description + * The controller for the content type editor data type picker dialog + */ + +(function() { + "use strict"; + + function DataTypePicker($scope, dataTypeResource, dataTypeHelper, contentTypeResource, localizationService, editorService) { + + var vm = this; + + if (!$scope.model.title) { + $scope.model.title = localizationService.localize("defaultdialogs_selectEditor"); + } + + vm.searchTerm = ""; + vm.showTabs = false; + vm.tabsLoaded = 0; + vm.typesAndEditors = []; + vm.userConfigured = []; + vm.loading = false; + vm.tabs = [{ + active: true, + id: 1, + label: localizationService.localize("contentTypeEditor_availableEditors"), + alias: "Default", + typesAndEditors: [] + }, { + active: false, + id: 2, + label: localizationService.localize("contentTypeEditor_reuse"), + alias: "Reuse", + userConfigured: [] + }]; + + vm.filterItems = filterItems; + vm.showDetailsOverlay = showDetailsOverlay; + vm.hideDetailsOverlay = hideDetailsOverlay; + vm.pickEditor = pickEditor; + vm.pickDataType = pickDataType; + vm.close = close; + + function activate() { + + getGroupedDataTypes(); + getGroupedPropertyEditors(); + + } + + function getGroupedPropertyEditors() { + + vm.loading = true; + + dataTypeResource.getGroupedPropertyEditors().then(function(data) { + vm.tabs[0].typesAndEditors = data; + vm.typesAndEditors = data; + vm.tabsLoaded = vm.tabsLoaded + 1; + checkIfTabContentIsLoaded(); + }); + + } + + function getGroupedDataTypes() { + + vm.loading = true; + + dataTypeResource.getGroupedDataTypes().then(function(data) { + vm.tabs[1].userConfigured = data; + vm.userConfigured = data; + vm.tabsLoaded = vm.tabsLoaded + 1; + checkIfTabContentIsLoaded(); + }); + + } + + function checkIfTabContentIsLoaded() { + if (vm.tabsLoaded === 2) { + vm.loading = false; + vm.showTabs = true; + } + } + + function filterItems() { + // clear item details + $scope.model.itemDetails = null; + + if (vm.searchTerm) { + vm.showFilterResult = true; + vm.showTabs = false; + } else { + vm.showFilterResult = false; + vm.showTabs = true; + } + + } + + function showDetailsOverlay(property) { + + var propertyDetails = {}; + propertyDetails.icon = property.icon; + propertyDetails.title = property.name; + + $scope.model.itemDetails = propertyDetails; + + } + + function hideDetailsOverlay() { + $scope.model.itemDetails = null; + } + + function pickEditor(editor) { + + var parentId = -1; + + dataTypeResource.getScaffold(parentId).then(function(dataType) { + + // set alias + dataType.selectedEditor = editor.alias; + + // set name + var nameArray = []; + + if ($scope.model.contentTypeName) { + nameArray.push($scope.model.contentTypeName); + } + + if ($scope.model.property.label) { + nameArray.push($scope.model.property.label); + } + + if (editor.name) { + nameArray.push(editor.name); + } + + // make name + dataType.name = nameArray.join(" - "); + + // get pre values + dataTypeResource.getPreValues(dataType.selectedEditor).then(function(preValues) { + dataType.preValues = preValues; + openDataTypeEditor(dataType, true); + }); + + }); + + } + + function pickDataType(selectedDataType) { + + dataTypeResource.getById(selectedDataType.id).then(function(dataType) { + contentTypeResource.getPropertyTypeScaffold(dataType.id).then(function(propertyType) { + submit(dataType, propertyType, false); + }); + }); + + } + + function openDataTypeEditor(dataType, isNew) { + + var dataTypeSettings = { + title: localizationService.localize("contentTypeEditor_editorSettings"), + dataType: dataType, + create: isNew, + view: "views/pickers/datatypesettings/datatypesettings.html", + submit: function(model) { + var preValues = dataTypeHelper.createPreValueProps(model.dataType.preValues); + dataTypeResource.save(model.dataType, preValues, isNew).then(function(newDataType) { + contentTypeResource.getPropertyTypeScaffold(newDataType.id).then(function(propertyType) { + submit(newDataType, propertyType, true); + editorService.close(); + }); + }); + }, + close: function() { + editorService.close(); + } + }; + + editorService.open(dataTypeSettings); + + } + + function submit(dataType, propertyType, isNew) { + // update property + $scope.model.property.config = propertyType.config; + $scope.model.property.editor = propertyType.editor; + $scope.model.property.view = propertyType.view; + $scope.model.property.dataTypeId = dataType.id; + $scope.model.property.dataTypeIcon = dataType.icon; + $scope.model.property.dataTypeName = dataType.name; + + $scope.model.updateSameDataTypes = isNew; + + $scope.model.submit($scope.model); + } + + function close() { + if($scope.model.close) { + $scope.model.close(); + } + } + + activate(); + + } + + angular.module("umbraco").controller("Umbraco.Editors.DataTypePickerController", DataTypePicker); + +})(); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/pickers/datatypepicker/datatypepicker.html b/src/Umbraco.Web.UI.Client/src/views/pickers/datatypepicker/datatypepicker.html new file mode 100644 index 0000000000..1fe7caa816 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/pickers/datatypepicker/datatypepicker.html @@ -0,0 +1,138 @@ + + +
+ + + + + + + + + +
+ +
+ + +
+ + + +
+
+
{{key}}
+ +
+
+
+
+
{{key}}
+ +
+
+
+
+
+ +
+
+
+
+
{{key}}
+ +
+
+
+
+
+
{{key}}
+ +
+
+
+ + + + +
+
+
+ + + + + + + + +
+ +
\ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/pickers/datatypesettings/datatypesettings.controller.js b/src/Umbraco.Web.UI.Client/src/views/pickers/datatypesettings/datatypesettings.controller.js new file mode 100644 index 0000000000..6dea46ba49 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/pickers/datatypesettings/datatypesettings.controller.js @@ -0,0 +1,36 @@ +/** + * @ngdoc controller + * @name Umbraco.Editors.DataTypeSettingsController + * @function + * + * @description + * The controller for the content type editor data type settings dialog + */ + +(function () { + "use strict"; + + function DataTypeSettingsController($scope) { + + var vm = this; + + vm.close = close; + vm.submit = submit; + + function close() { + if ($scope.model && $scope.model.close) { + $scope.model.close(); + } + } + + function submit() { + if ($scope.model && $scope.model.submit) { + $scope.model.submit($scope.model); + } + } + + } + + angular.module("umbraco").controller("Umbraco.Editors.DataTypeSettingsController", DataTypeSettingsController); + +})(); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/pickers/datatypesettings/datatypesettings.html b/src/Umbraco.Web.UI.Client/src/views/pickers/datatypesettings/datatypesettings.html new file mode 100644 index 0000000000..90a8ea3573 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/pickers/datatypesettings/datatypesettings.html @@ -0,0 +1,62 @@ + + +
+ + + + + + + + +
+ + using this editor will get updated with the new settings. +
+ +
+
+ +
+ +
+
+
+ +
+ + + + + +
+
+
+ + + + + + + + + + +
+ +
\ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/pickers/propertysettings/propertysettings.controller.js b/src/Umbraco.Web.UI.Client/src/views/pickers/propertysettings/propertysettings.controller.js new file mode 100644 index 0000000000..927e757374 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/pickers/propertysettings/propertysettings.controller.js @@ -0,0 +1,215 @@ +/** + * @ngdoc controller + * @name Umbraco.Editors.PropertySettingsController + * @function + * + * @description + * The controller for the content type editor property settings dialog + */ + +(function () { + "use strict"; + + function PropertySettingsEditor($scope, contentTypeResource, dataTypeResource, dataTypeHelper, localizationService, userService, editorService) { + + var vm = this; + + vm.showValidationPattern = false; + vm.focusOnPatternField = false; + vm.focusOnMandatoryField = false; + vm.selectedValidationType = {}; + vm.validationTypes = [ + { + "name": localizationService.localize("validation_validateAsEmail"), + "key": "email", + "pattern": "[a-zA-Z0-9_\.\+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-\.]+", + "enableEditing": true + }, + { + "name": localizationService.localize("validation_validateAsNumber"), + "key": "number", + "pattern": "^[0-9]*$", + "enableEditing": true + }, + { + "name": localizationService.localize("validation_validateAsUrl"), + "key": "url", + "pattern": "https?\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,}", + "enableEditing": true + }, + { + "name": localizationService.localize("validation_enterCustomValidation"), + "key": "custom", + "pattern": "", + "enableEditing": true + } + ]; + + vm.changeValidationType = changeValidationType; + vm.changeValidationPattern = changeValidationPattern; + vm.openDataTypePicker = openDataTypePicker; + vm.openDataTypeSettings = openDataTypeSettings; + vm.submit = submit; + vm.close = close; + + userService.getCurrentUser().then(function(user) { + vm.showSensitiveData = user.userGroups.indexOf("sensitiveData") != -1; + }); + + function activate() { + matchValidationType(); + } + + function changeValidationPattern() { + matchValidationType(); + } + + function openDataTypePicker(property) { + + vm.focusOnMandatoryField = false; + + var dataTypePicker = { + property: $scope.model.property, + contentTypeName: $scope.model.contentTypeName, + view: "views/pickers/datatypepicker/datatypepicker.html", + size: "small", + submit: function(model) { + + $scope.model.updateSameDataTypes = model.updateSameDataTypes; + + vm.focusOnMandatoryField = true; + + // update property + property.config = model.property.config; + property.editor = model.property.editor; + property.view = model.property.view; + property.dataTypeId = model.property.dataTypeId; + property.dataTypeIcon = model.property.dataTypeIcon; + property.dataTypeName = model.property.dataTypeName; + + editorService.close(); + }, + close: function(model) { + editorService.close(); + } + }; + + editorService.open(dataTypePicker); + + } + + function openDataTypeSettings(property) { + + vm.focusOnMandatoryField = false; + + // get data type + dataTypeResource.getById(property.dataTypeId).then(function (dataType) { + + var dataTypeSettings = { + title: "Data type settings", + view: "views/pickers/datatypesettings/datatypesettings.html", + dataType: dataType, + submit: function(model) { + + var preValues = dataTypeHelper.createPreValueProps(model.dataType.preValues); + + dataTypeResource.save(model.dataType, preValues, false).then(function (newDataType) { + + contentTypeResource.getPropertyTypeScaffold(newDataType.id).then(function (propertyType) { + + // update editor + property.config = propertyType.config; + property.editor = propertyType.editor; + property.view = propertyType.view; + property.dataTypeId = newDataType.id; + property.dataTypeIcon = newDataType.icon; + property.dataTypeName = newDataType.name; + + // set flag to update same data types + $scope.model.updateSameDataTypes = true; + + vm.focusOnMandatoryField = true; + + editorService.close(); + + }); + + }); + + }, + close: function() { + editorService.close(); + } + }; + + editorService.open(dataTypeSettings); + + }); + + } + + function submit() { + if($scope.model.submit) { + $scope.model.submit($scope.model); + } + } + + function close() { + if($scope.model.close) { + $scope.model.close(); + } + } + + function matchValidationType() { + + if ($scope.model.property.validation.pattern !== null && $scope.model.property.validation.pattern !== "" && $scope.model.property.validation.pattern !== undefined) { + + var match = false; + + // find and show if a match from the list has been chosen + angular.forEach(vm.validationTypes, function (validationType, index) { + if ($scope.model.property.validation.pattern === validationType.pattern) { + vm.selectedValidationType = vm.validationTypes[index]; + vm.showValidationPattern = true; + match = true; + } + }); + + // if there is no match - choose the custom validation option. + if (!match) { + angular.forEach(vm.validationTypes, function (validationType) { + if (validationType.key === "custom") { + vm.selectedValidationType = validationType; + vm.showValidationPattern = true; + } + }); + } + } + + } + + function changeValidationType(selectedValidationType) { + + if (selectedValidationType) { + $scope.model.property.validation.pattern = selectedValidationType.pattern; + vm.showValidationPattern = true; + + // set focus on textarea + if (selectedValidationType.key === "custom") { + vm.focusOnPatternField = true; + } + + } else { + $scope.model.property.validation.pattern = ""; + vm.showValidationPattern = false; + } + + } + + activate(); + + } + + angular.module("umbraco").controller("Umbraco.Editors.PropertySettingsController", PropertySettingsEditor); + +})(); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/pickers/propertysettings/propertysettings.html b/src/Umbraco.Web.UI.Client/src/views/pickers/propertysettings/propertysettings.html new file mode 100644 index 0000000000..36203e3b05 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/pickers/propertysettings/propertysettings.html @@ -0,0 +1,166 @@ + + +
+ + + + + + + + +
+ +
+
+ +
Required label
+
+
+ +
+
+ +
+ +
+ + + + +
+ +
+ + + + + + + +
+ +
+ +
+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + + + + + + + + + + + + + + +
+ +
+ \ No newline at end of file