From b26db075a3777f917d9e16cf2c4e5a9f7d4dfc71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 8 Apr 2020 11:58:25 +0200 Subject: [PATCH] BlockList PreValue Editor opens configurations as overlay --- .../common/resources/elementtype.resource.js | 11 +- src/Umbraco.Web.UI.Client/src/less/belle.less | 5 +- .../src/less/variables.less | 2 + .../blockcard/blockcard.component.html | 11 + .../blockcard/blockcard.component.js | 28 ++ .../blockcard/blockcard.component.less | 120 +++++++ .../blockcard/umb-block-card-grid.less | 15 + .../blocklist/blocklist.component.less | 5 +- ...blocklist.blockconfiguration.controller.js | 208 ++++++++++++ .../blocklist.blockconfiguration.html | 30 ++ .../blocklist.blockconfiguration.less | 28 ++ ...t.blockconfiguration.overlay.controller.js | 190 +++++++++++ .../blocklist.blockconfiguration.overlay.html | 310 ++++++++++++++++++ ...blocklist.blockconfiguration.overlay.less} | 59 +--- .../blocklist.elementtypepicker.controller.js | 285 ---------------- .../prevalue/blocklist.elementtypepicker.html | 81 ----- src/Umbraco.Web.UI/Umbraco/config/lang/en.xml | 6 + .../Umbraco/config/lang/en_us.xml | 6 + .../Editors/ElementTypeController.cs | 29 ++ .../PropertyEditors/BlockListConfiguration.cs | 16 +- src/Umbraco.Web/Umbraco.Web.csproj | 1 + 21 files changed, 1022 insertions(+), 424 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockeditor/blockcard/blockcard.component.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockeditor/blockcard/blockcard.component.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockeditor/blockcard/blockcard.component.less create mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockeditor/blockcard/umb-block-card-grid.less create mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.less create mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.html rename src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/{blocklist.elementtypepicker.less => blocklist.blockconfiguration.overlay.less} (68%) delete mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.elementtypepicker.controller.js delete mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.elementtypepicker.html create mode 100644 src/Umbraco.Web/Editors/ElementTypeController.cs diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/elementtype.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/elementtype.resource.js index 680b75ac78..a235bcda3e 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/elementtype.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/elementtype.resource.js @@ -9,12 +9,11 @@ function elementTypeResource($q, $http, umbRequestHelper) { getAll: function () { - // TODO: Change this into a real api (ElementTypeApi). This is a temporary fix to get data. - var url = Umbraco.Sys.ServerVariables.umbracoSettings.umbracoPath + "/backoffice/UmbracoApi/NestedContent/GetContentTypes"; - return umbRequestHelper.resourcePromise( - $http.get(url), - 'Failed to retrieve content types' - ); + var url = Umbraco.Sys.ServerVariables.umbracoSettings.umbracoPath + "/backoffice/UmbracoApi/ElementType/GetAll"; + return umbRequestHelper.resourcePromise( + $http.get(url), + 'Failed to retrieve element types' + ); /* return umbRequestHelper.resourcePromise( diff --git a/src/Umbraco.Web.UI.Client/src/less/belle.less b/src/Umbraco.Web.UI.Client/src/less/belle.less index 14a62ae790..6c021203a5 100644 --- a/src/Umbraco.Web.UI.Client/src/less/belle.less +++ b/src/Umbraco.Web.UI.Client/src/less/belle.less @@ -198,8 +198,11 @@ // Property Editors +@import "../views/propertyeditors/blockeditor/blockcard/umb-block-card-grid.less"; +@import "../views/propertyeditors/blockeditor/blockcard/blockcard.component.less"; @import "../views/propertyeditors/blocklist/blocklist.component.less"; -@import "../views/propertyeditors/blocklist/prevalue/blocklist.elementtypepicker.less"; +@import "../views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.less"; +@import "../views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.less"; @import "../views/propertyeditors/notsupported/notsupported.less"; diff --git a/src/Umbraco.Web.UI.Client/src/less/variables.less b/src/Umbraco.Web.UI.Client/src/less/variables.less index b645e3113b..c320a31807 100644 --- a/src/Umbraco.Web.UI.Client/src/less/variables.less +++ b/src/Umbraco.Web.UI.Client/src/less/variables.less @@ -202,6 +202,7 @@ @ui-icon: @blueNight; @ui-icon-hover: @blueMid; +@ui-drop-area-color: @blueMidLight; // Scaffolding @@ -252,6 +253,7 @@ // Disabled this to keep consistency throughout the backoffice UI. Untill a better solution is thought up, this will do. @baseBorderRadius: 3px; // 2px; +@doubleBorderRadius: 6px; @borderRadiusLarge: 3px; // 6px; @borderRadiusSmall: 3px; // 3px; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockeditor/blockcard/blockcard.component.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockeditor/blockcard/blockcard.component.html new file mode 100644 index 0000000000..c66879e864 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockeditor/blockcard/blockcard.component.html @@ -0,0 +1,11 @@ + +
+ +
+
+
+
+
+ + + diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockeditor/blockcard/blockcard.component.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockeditor/blockcard/blockcard.component.js new file mode 100644 index 0000000000..98e7303219 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockeditor/blockcard/blockcard.component.js @@ -0,0 +1,28 @@ +(function () { + "use strict"; + + angular + .module("umbraco") + .component("umbBlockCard", { + templateUrl: "views/propertyeditors/blockeditor/blockcard/blockcard.component.html", + controller: BlockCardController, + controllerAs: "vm", + transclude: true, + bindings: { + blockConfigModel: "<", + elementTypeModel: "<" + } + }); + + function BlockCardController() { + + var vm = this; + + vm.$onInit = function() { + console.log(vm.blockConfigModel); + console.log(vm.elementTypeModel); + } + + } + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockeditor/blockcard/blockcard.component.less b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockeditor/blockcard/blockcard.component.less new file mode 100644 index 0000000000..5adbded9bb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockeditor/blockcard/blockcard.component.less @@ -0,0 +1,120 @@ +.umb-block-card, +umb-block-card { + position: relative; + display: inline-block; + width: 100%; + height: auto; + margin-right: 20px; + margin-bottom: 20px; + background-color: white; + border-radius: @doubleBorderRadius; + box-shadow: 0 1px 2px rgba(0,0,0,.2); + overflow: hidden; + + cursor: pointer; + + &.--isOpen { + &::after { + content: ""; + position: absolute; + border: 2px solid @ui-active-border; + border-radius: @doubleBorderRadius; + top:0; + bottom: 0; + left: 0; + right: 0; + } + } + + &.--sortable-placeholder { + &::after { + content: ""; + position: absolute; + background-color:rgba(@ui-drop-area-color, .05); + border: 2px solid rgba(@ui-drop-area-color, .1); + border-radius: @doubleBorderRadius; + box-shadow: 0 0 4px rgba(@ui-drop-area-color, 0.05); + top:0; + bottom: 0; + left: 0; + right: 0; + animation: umb-block-card--sortable-placeholder 400ms ease-in-out alternate infinite; + @keyframes umb-block-card--sortable-placeholder { + 0% { opacity: 1; } + 100% { opacity: 0.5; } + } + } + box-shadow: none; + } + + .__showcase { + position: relative; + width: 100%; + padding-bottom: 10/16*100%; + background-color: @gray-11; + .__icon { + position: absolute; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + font-size:42px; + } + } + + .__info { + width: 100%; + background-color: #fff; + padding-bottom: 6px; + + .__name { + font-weight: bold; + font-size: 14px; + color: @ui-action-type; + margin-left: 16px; + margin-top: 8px; + margin-bottom: -1px; + } + .__subname { + color: @gray-4; + font-size: 12px; + margin-left: 16px; + margin-bottom: -1px; + } + } + + &:hover { + .__info { + .__name { + color: @ui-action-type-hover; + } + } + } + + .__actions { + position: absolute; + top: 10px; + right: 0; + opacity: 0; + transition: opacity 120ms; + .__action { + display: inline-block; + border-radius: 50%; + width: 28px; + height: 28px; + margin-right: 10px; + background-color: white; + color:@ui-action-type; + &:hover { + color: @ui-action-type-hover; + } + } + } + &:hover, &:focus, &:focus-within { + .__actions { + opacity: 1; + } + } + +} diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockeditor/blockcard/umb-block-card-grid.less b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockeditor/blockcard/umb-block-card-grid.less new file mode 100644 index 0000000000..e4953999fd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockeditor/blockcard/umb-block-card-grid.less @@ -0,0 +1,15 @@ +.umb-block-card-grid { + /* FlexBox Fallback */ + display: flex; + flex-wrap: wrap; + > * { + flex: 1 1 240px; + } + + /* Grid Setup */ + display: grid; + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + grid-auto-rows: minmax(200px, auto); + grid-gap: 20px; + +} diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklist.component.less b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklist.component.less index d08c862f88..d118e6356c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklist.component.less +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklist.component.less @@ -87,10 +87,9 @@ right: 0; left: 0; height: 2px; - animation: umb-block-list__block--create-button_before 800ms ease-in-out infinite; + animation: umb-block-list__block--create-button_before 400ms ease-in-out alternate infinite; @keyframes umb-block-list__block--create-button_before { - 0% { opacity: 0.5; } - 50% { opacity: 1; } + 0% { opacity: 1; } 100% { opacity: 0.5; } } } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.controller.js new file mode 100644 index 0000000000..a058f465e0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.controller.js @@ -0,0 +1,208 @@ +/** + * @ngdoc controller + * @name Umbraco.Editors.BlockList.BlockConfigurationController + * @function + * + * @description + * The controller for the content type editor property settings dialog + */ + +(function () { + "use strict"; + + function TransferProperties(fromObject, toObject) { + for (var p in fromObject) { + toObject[p] = fromObject[p]; + } + } + + function BlockConfigurationController($scope, elementTypeResource, overlayService, localizationService, editorService) { + + var vm = this; + + vm.enableAddBlock = true; + vm.openBlock = null; + + function evaluateStatus() { + + if (!vm.elementTypes) return;// cancel if elementTypes isnt loaded jet. + + vm.enableAddBlock = vm.getAvailableElementTypes().length > 0; + + } + + function onInit() { + + if (!$scope.model.value) { + $scope.model.value = []; + } + + loadElementTypes(); + + } + + function loadElementTypes() { + return elementTypeResource.getAll().then(function (elementTypes) { + vm.elementTypes = elementTypes; + evaluateStatus(); + }); + } + + vm.requestRemoveBlockByIndex = function (index) { + localizationService.localizeMany(["general_delete", "blockEditor_confirmDeleteBlockMessage", "blockEditor_confirmDeleteBlockNotice"]).then(function (data) { + var contentElementType = vm.getElementTypeByAlias($scope.model.value[index].contentTypeAlias); + overlayService.confirmDelete({ + title: data[0], + content: localizationService.tokenReplace(data[1], [contentElementType.name]), + confirmMessage: data[2], + close: function () { + overlayService.close(); + }, + submit: function () { + vm.removeBlockByIndex(index); + overlayService.close(); + } + }); + }); + } + + vm.removeBlockByIndex = function (index) { + $scope.model.value.splice(index, 1); + }; + + vm.sortableOptions = { + "ui-floating": true, + items: "umb-block-card", + cursor: "grabbing", + placeholder: 'umb-block-card --sortable-placeholder' + }; + + + vm.getAvailableElementTypes = function () { + return vm.elementTypes.filter(function (type) { + return !$scope.model.value.find(function (entry) { + return type.alias === entry.contentTypeAlias; + }); + }); + }; + + vm.getElementTypeByAlias = function(alias) { + return _.find(vm.elementTypes, function (type) { + return type.alias === alias; + }); + }; + + vm.openAddDialog = function ($event, entry) { + + //we have to add the alias to the objects (they are stored as contentTypeAlias) + var selectedItems = _.each($scope.model.value, function (obj) { + obj.alias = obj.contentTypeAlias; + return obj; + }); + + var availableItems = vm.getAvailableElementTypes() + + var elemTypeSelectorOverlay = { + view: "itempicker", + title: "no title jet", + availableItems: availableItems, + selectedItems: selectedItems, + createNewItem: { + action: function() { + overlayService.close(); + vm.createElementTypeAndAdd(vm.addBlockFromElementTypeAlias); + }, + icon: "icon-add", + name: "Create new" + }, + position: "target", + event: $event, + size: availableItems.length < 7 ? "small" : "medium", + submit: function (overlay) { + vm.addBlockFromElementTypeAlias(overlay.selectedItem.alias); + overlayService.close(); + }, + close: function () { + overlayService.close(); + } + }; + + overlayService.open(elemTypeSelectorOverlay); + }; + + vm.createElementTypeAndAdd = function(callback) { + const editor = { + create: true, + infiniteMode: true, + isElement: true, + submit: function (model) { + loadElementTypes().then( function () { + callback(model.documentTypeAlias); + }); + editorService.close(); + }, + close: function () { + editorService.close(); + } + }; + editorService.documentTypeEditor(editor); + } + + vm.addBlockFromElementTypeAlias = function(alias) { + + var entry = { + "contentTypeAlias": alias, + "view": null, + "labelTemplate": "", + "settingsElementTypeAlias": null + }; + + $scope.model.value.push(entry); + }; + + + + + + vm.openBlockOverlay = function (block) { + + localizationService.localize("blockEditor_blockConfigurationOverlayTitle", [vm.getElementTypeByAlias(block.contentTypeAlias).name]).then(function (data) { + + var clonedBlockData = angular.copy(block); + vm.openBlock = block; + + var overlayModel = { + block: clonedBlockData, + title: data, + view: "views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.html", + size: "small", + submit: function(overlayModel) { + TransferProperties(overlayModel.block, block);// transfer properties back to block object. (Doing this cause we dont know if block object is added to model jet, therefor we cant use index or replace the object.) + overlayModel.close(); + }, + close: function() { + editorService.close(); + vm.openBlock = null; + } + }; + + // open property settings editor + editorService.open(overlayModel); + + }); + + }; + + + + onInit(); + + $scope.$watchCollection('model.value', function(newVal, oldVal) { + evaluateStatus(); + }); + + } + + angular.module("umbraco").controller("Umbraco.PropertyEditors.BlockList.BlockConfigurationController", BlockConfigurationController); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.html new file mode 100644 index 0000000000..06e9714b77 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.html @@ -0,0 +1,30 @@ +
+ +
+ + +
+ +
+
+ + +
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.less b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.less new file mode 100644 index 0000000000..f4d9caa73b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.less @@ -0,0 +1,28 @@ +.umb-block-list-block-configuration { + + .__add-button { + position: relative; + display: inline-flex; + width: 100%; + height: auto; + margin-right: 20px; + margin-bottom: 20px; + + color: @ui-action-discreet-type; + border: 1px dashed @ui-action-discreet-border; + border-radius: @doubleBorderRadius; + + align-items: center; + justify-content: center; + + padding: 5px 15px; + box-sizing: border-box; + font-weight: bold; + } + + .__add-button:hover { + color: @ui-action-discreet-type-hover; + border-color: @ui-action-discreet-border-hover; + } + +} diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.controller.js new file mode 100644 index 0000000000..015d25e9fb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.controller.js @@ -0,0 +1,190 @@ +/** + * @ngdoc controller + * @name Umbraco.Editors.BlockList.BlockConfigurationOverlayController + * @function + * + * @description + * The controller for the content type editor property settings dialog + */ + +(function () { + "use strict"; + + function BlockConfigurationOverlayController($scope, overlayService, localizationService, editorService, elementTypeResource) { + + var vm = this; + vm.block = $scope.model.block; + + loadElementTypes(); + + function loadElementTypes() { + return elementTypeResource.getAll().then(function (elementTypes) { + vm.elementTypes = elementTypes; + }); + } + + vm.getElementTypeByAlias = function(alias) { + return _.find(vm.elementTypes, function (type) { + return type.alias === alias; + }); + }; + + vm.openElementType = function(elementTypeAlias) { + var elementTypeId = vm.getElementTypeByAlias(elementTypeAlias).id; + const editor = { + id: elementTypeId, + submit: function (model) { + loadElementTypes(); + editorService.close(); + }, + close: function () { + editorService.close(); + } + }; + editorService.documentTypeEditor(editor); + } + + vm.addSettingsForBlock = function ($event, block) { + + var elemTypeSelectorOverlay = { + view: "itempicker", + title: "Pick settings (missing translation)", + availableItems: vm.elementTypes, + position: "target", + event: $event, + size: vm.elementTypes.length < 7 ? "small" : "medium", + createNewItem: { + action: function() { + overlayService.close(); + vm.createElementTypeAndAdd((alias) => { + vm.applySettingsToBlock(block, alias); + }); + }, + icon: "icon-add", + name: "Create new" + }, + submit: function (overlay) { + vm.applySettingsToBlock(block, overlay.selectedItem.alias); + overlayService.close(); + }, + close: function () { + overlayService.close(); + } + }; + + overlayService.open(elemTypeSelectorOverlay); + }; + vm.applySettingsToBlock = function(block, alias) { + block.settingsElementTypeAlias = alias; + }; + + vm.requestRemoveSettingsForBlock = function(block) { + localizationService.localizeMany(["general_remove", "defaultdialogs_confirmremoveusageof"]).then(function (data) { + + var settingsElementType = vm.getElementTypeByAlias(entry.settingsElementTypeAlias); + + overlayService.confirmRemove({ + title: data[0], + content: localizationService.tokenReplace(data[1], [settingsElementType.name]), + close: function () { + overlayService.close(); + }, + submit: function () { + vm.removeSettingsForEntry(entry); + overlayService.close(); + } + }); + }); + }; + vm.removeSettingsForEntry = function(entry) { + entry.settingsElementTypeAlias = null; + }; + + + vm.addViewForBlock = function(block) { + const filePicker = { + title: "Select view (TODO need translation)", + section: "settings", + treeAlias: "files", + entityType: "file", + isDialog: true, + filter: function (i) { + return i.name.indexOf(".html" !== -1); + }, + select: function (file) { + console.log(file); + block.view = file.name; + editorService.close(); + }, + close: function () { + editorService.close(); + } + }; + editorService.treePicker(filePicker); + } + vm.requestRemoveViewForBlock = function(block) { + localizationService.localizeMany(["general_remove", "defaultdialogs_confirmremoveusageof"]).then(function (data) { + overlayService.confirmRemove({ + title: data[0], + content: localizationService.tokenReplace(data[1], [block.view]), + close: function () { + overlayService.close(); + }, + submit: function () { + vm.removeViewForBlock(block); + overlayService.close(); + } + }); + }); + }; + vm.removeViewForBlock = function(block) { + block.view = null; + }; + + + + vm.addThumbnailForBlock = function(block) { + const thumbnailPicker = { + title: "Select thumbnail (TODO need translation)", + section: "settings", + treeAlias: "files", + entityType: "file", + isDialog: true, + filter: function (i) { + return (i.name.indexOf(".jpg") !== -1 || i.name.indexOf(".jpeg") !== -1 || i.name.indexOf(".png") !== -1 || i.name.indexOf(".svg") !== -1 || i.name.indexOf(".webp") !== -1 || i.name.indexOf(".gif") !== -1); + }, + select: function (file) { + block.thumbnail = file.name; + editorService.close(); + }, + close: function () { + editorService.close(); + } + }; + editorService.treePicker(thumbnailPicker); + } + vm.removeThumbnailForBlock = function(entry) { + entry.thumbnail = null; + }; + + + + + vm.submit = function () { + if ($scope.model && $scope.model.submit) { + $scope.model.submit($scope.model); + } + } + + vm.close = function() { + if ($scope.model && $scope.model.close) { + // TODO: If content has changed, we should notify user. + $scope.model.close($scope.model); + } + } + + } + + angular.module("umbraco").controller("Umbraco.PropertyEditors.BlockList.BlockConfigurationOverlayController", BlockConfigurationOverlayController); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.html new file mode 100644 index 0000000000..255d27cb8d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.html @@ -0,0 +1,310 @@ +
+ +
+ + + + + + + +
+ +
+ +
+
Block Editor
+
+ +
+ + +
+
+ +
+ +
+
+
+ + +
+
+ +
+
+ + +
+ +
+
+ +
+
+
+ + +
+
+ +
+ +
+
+
+ +
+ +
+ +
+ +
+
Data Settings
+
+ +
+ + +
+
+ +
+
+ {{ contentPreview = vm.getElementTypeByAlias(vm.block.contentTypeAlias); "" }} + +
+ +
+
+
+
+
+ + +
+
+ +
+
+ {{ settingsPreview = vm.getElementTypeByAlias(vm.block.settingsElementTypeAlias); "" }} + +
+ + +
+
+ +
+
+
+ + +
+
+ +
+ +
+
Showcase
+
+ +
+ + +
+
+ +
+ +
+
+
+ + +
+
+ +
+ +
+
+
+ + +
+
+ +
+
+ + +
+ +
+
+ +
+
+
+ +
+ +
+ +
+
+ + + + + + + + + + + + + + +
+
+
+ + + diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.elementtypepicker.less b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.less similarity index 68% rename from src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.elementtypepicker.less rename to src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.less index 216856dee9..c4b6349747 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.elementtypepicker.less +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.less @@ -1,46 +1,11 @@ -.umb-block-list-element-type-picker { +.umb-block-list-block-configuration-overlay { - .block-entry { - cursor: grab; - background-color: white; - border-radius: @baseBorderRadius; - } - - .umb-table { - border:1px solid @gray-11; - } - - .umb-table-head { - button { - margin-left: 5px; - color: @ui-action-discreet-type; - &:hover { - color: @ui-action-discreet-type-hover; - } - } - } - - .umb-table-cell { - padding-left: 10px; - padding-right: 0; - &.action-cell { - padding-right: 15px; - } - } - - .action-cell { - flex: 0 0 30px; - } - - .text-input { - width: 100%; - } .umb-node-preview { flex-grow: 1; } - .cell-actions { + .__control-actions { position: absolute; display: flex; align-items: center; @@ -51,14 +16,14 @@ opacity: 0; transition: opacity 120ms; } - .umb-table-cell:hover, - .umb-table-cell:focus, - .umb-table-cell:focus-within { - .cell-actions { + .control-group:hover, + .control-group:focus, + .control-group:focus-within { + .__control-actions { opacity: 1; } } - .cell-actions-btn { + .__control-actions-btn { position: relative; color: @ui-action-discreet-type; height: 30px; @@ -76,14 +41,15 @@ border-bottom: none; } - .settings-input { + .__settings-input { position: relative; padding: 5px 8px; + margin-bottom: 10px; color: @ui-action-discreet-type; border: 1px dashed @ui-action-discreet-border; width: 100%; font-weight: bold; - display: flex; + display: inline-flex; flex-flow: row nowrap; localize { @@ -93,6 +59,7 @@ .umb-node-preview { padding: 3px 0; margin-left: 5px; + overflow: hidden; } &.--noValue { @@ -112,7 +79,7 @@ } } - .add-button { + .__add-button { width:100%; color: @ui-action-discreet-type; border: 1px dashed @ui-action-discreet-border; @@ -126,7 +93,7 @@ font-weight: bold; } - .add-button:hover { + .__add-button:hover { color: @ui-action-discreet-type-hover; border-color: @ui-action-discreet-border-hover; } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.elementtypepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.elementtypepicker.controller.js deleted file mode 100644 index 77751579c9..0000000000 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.elementtypepicker.controller.js +++ /dev/null @@ -1,285 +0,0 @@ -/** - * @ngdoc controller - * @name Umbraco.Editors.PropertySettingsController - * @function - * - * @description - * The controller for the content type editor property settings dialog - */ - -(function () { - "use strict"; - - function ElementTypePickerController($scope, elementTypeResource, overlayService, localizationService, editorService) { - - var vm = this; - - vm.enableAddEntry = true; - - function evaluateStatus() { - - if (!vm.elementTypes) return;// cancel if elementTypes isnt loaded jet. - - vm.enableAddEntry = vm.getAvailableElementTypes().length > 0; - - } - - function onInit() { - - if (!$scope.model.value) { - $scope.model.value = []; - } - - localizationService.localize("content_nestedContentSelectElementTypeModalTitle").then(function (value) { - //selectElementTypeModalTitle = value; - }); - - loadElementTypes(); - - } - - function loadElementTypes() { - return elementTypeResource.getAll().then(function (elementTypes) { - vm.elementTypes = elementTypes; - evaluateStatus(); - }); - } - - vm.requestRemoveEntryByIndex = function (index) { - localizationService.localizeMany(["general_delete", "blockEditor_confirmDeleteBlockMessage", "blockEditor_confirmDeleteBlockNotice"]).then(function (data) { - var contentElementType = vm.getElementTypeByAlias($scope.model.value[index].contentTypeAlias); - overlayService.confirmDelete({ - title: data[0], - content: localizationService.tokenReplace(data[1], [contentElementType.name]), - confirmMessage: data[2], - close: function () { - overlayService.close(); - }, - submit: function () { - vm.removeEntryByIndex(index); - overlayService.close(); - } - }); - }); - } - - vm.removeEntryByIndex = function (index) { - $scope.model.value.splice(index, 1); - }; - - vm.sortableOptions = { - axis: "y", - cursor: "grabbing", - placeholder: 'sortable-placeholder', - forcePlaceholderSize: true - }; - - - vm.getAvailableElementTypes = function () { - return vm.elementTypes.filter(function (type) { - return !$scope.model.value.find(function (entry) { - return type.alias === entry.contentTypeAlias; - }); - }); - }; - - vm.getElementTypeByAlias = function(alias) { - return _.find(vm.elementTypes, function (type) { - return type.alias === alias; - }); - }; - - vm.openAddDialog = function ($event, entry) { - - //we have to add the alias to the objects (they are stored as contentTypeAlias) - var selectedItems = _.each($scope.model.value, function (obj) { - obj.alias = obj.contentTypeAlias; - return obj; - }); - - var availableItems = vm.getAvailableElementTypes() - - var elemTypeSelectorOverlay = { - view: "itempicker", - title: "no title jet", - availableItems: availableItems, - selectedItems: selectedItems, - createNewItem: { - action: function() { - overlayService.close(); - vm.createElementTypeAndAdd(vm.addEntryFromElementTypeAlias); - }, - icon: "icon-add", - name: "Create new" - }, - position: "target", - event: $event, - size: availableItems.length < 7 ? "small" : "medium", - submit: function (overlay) { - vm.addEntryFromElementTypeAlias(overlay.selectedItem.alias); - overlayService.close(); - }, - close: function () { - overlayService.close(); - } - }; - - overlayService.open(elemTypeSelectorOverlay); - }; - - vm.createElementTypeAndAdd = function(callback) { - const editor = { - create: true, - infiniteMode: true, - isElement: true, - submit: function (model) { - console.log(model) - loadElementTypes().then( function () { - callback(model.documentTypeAlias); - }); - editorService.close(); - }, - close: function () { - editorService.close(); - } - }; - editorService.documentTypeEditor(editor); - } - - vm.addEntryFromElementTypeAlias = function(alias) { - - var entry = { - "contentTypeAlias": alias, - "view": null, - "labelTemplate": "", - "settingsElementTypeAlias": null - }; - - $scope.model.value.push(entry); - }; - - vm.requestRemoveSettingsForEntry = function(entry) { - localizationService.localizeMany(["general_remove", "defaultdialogs_confirmremoveusageof"]).then(function (data) { - - var settingsElementType = vm.getElementTypeByAlias(entry.settingsElementTypeAlias); - - overlayService.confirmRemove({ - title: data[0], - content: localizationService.tokenReplace(data[1], [settingsElementType.name]), - close: function () { - overlayService.close(); - }, - submit: function () { - vm.removeSettingsForEntry(entry); - overlayService.close(); - } - }); - }); - }; - vm.removeSettingsForEntry = function(entry) { - entry.settingsElementTypeAlias = null; - }; - - vm.addSettingsForEntry = function ($event, entry) { - - var elemTypeSelectorOverlay = { - view: "itempicker", - title: "Pick settings (missing translation)", - availableItems: vm.elementTypes, - position: "target", - event: $event, - size: vm.elementTypes.length < 7 ? "small" : "medium", - createNewItem: { - action: function() { - overlayService.close(); - vm.createElementTypeAndAdd((alias) => { - vm.addSettingsAtEntry(entry, alias); - }); - }, - icon: "icon-add", - name: "Create new" - }, - submit: function (overlay) { - vm.addSettingsAtEntry(entry, overlay.selectedItem.alias); - overlayService.close(); - }, - close: function () { - overlayService.close(); - } - }; - - overlayService.open(elemTypeSelectorOverlay); - }; - vm.addSettingsAtEntry = function(entry, alias) { - entry.settingsElementTypeAlias = alias; - }; - - vm.openElementType = function(elementTypeAlias) { - var elementTypeId = vm.getElementTypeByAlias(elementTypeAlias).id; - const editor = { - id: elementTypeId, - submit: function (model) { - loadElementTypes(); - editorService.close(); - }, - close: function () { - editorService.close(); - } - }; - editorService.documentTypeEditor(editor); - } - - vm.requestRemoveViewForEntry = function(entry) { - localizationService.localizeMany(["general_remove", "defaultdialogs_confirmremoveusageof"]).then(function (data) { - overlayService.confirmRemove({ - title: data[0], - content: localizationService.tokenReplace(data[1], [entry.view]), - close: function () { - overlayService.close(); - }, - submit: function () { - vm.removeViewForEntry(entry); - overlayService.close(); - } - }); - }); - }; - vm.removeViewForEntry = function(entry) { - entry.view = null; - }; - vm.addViewForEntry = function(entry) { - const filePicker = { - title: "Select view (TODO need translation)", - section: "settings", - treeAlias: "files", - entityType: "file", - isDialog: true, - filter: function (i) { - if (i.name.indexOf(".html") !== -1) { - return true; - } - }, - select: function (file) { - console.log(file); - entry.view = file.name; - editorService.close(); - }, - close: function () { - editorService.close(); - } - }; - editorService.treePicker(filePicker); - } - - - onInit(); - - $scope.$watchCollection('model.value', function(newVal, oldVal) { - evaluateStatus(); - }); - - } - - angular.module("umbraco").controller("Umbraco.PropertyEditors.BlockList.ElementTypePickerController", ElementTypePickerController); - -})(); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.elementtypepicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.elementtypepicker.html deleted file mode 100644 index 8184761a1a..0000000000 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.elementtypepicker.html +++ /dev/null @@ -1,81 +0,0 @@ -
-
-
-
-
- Custom view -
-
- Label - -
-
- Custom view -
-
- Custom view -
-
-
-
-
-
-
-
- {{ contentPreview = vm.getElementTypeByAlias(entry.contentTypeAlias); "" }} - -
- -
-
-
- -
-
-
- - -
- -
-
- -
-
-
- {{ settingsPreview = vm.getElementTypeByAlias(entry.settingsElementTypeAlias); "" }} - -
- - -
-
- -
-
- -
-
-
-
- -
diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml index a09088efa1..409ba0cefe 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml @@ -2403,14 +2403,20 @@ To manage your website, simply open the Umbraco back office and start adding con Create forms using an intuitive drag and drop interface. From simple contact forms that sends e-mails to advanced questionaires that integrate with CRM systems. Your clients will love it! + Background color + Icon color Content model Label Custom view Settings model + Overlay editor size Add custom view Add settings Overwrite label template %0%.]]> Content using this block will be lost. + + Thumbnail + Add thumbnail diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index 89fbceaea8..404993a201 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -2414,14 +2414,20 @@ To manage your website, simply open the Umbraco back office and start adding con Create forms using an intuitive drag and drop interface. From simple contact forms that sends e-mails to advanced questionaires that integrate with CRM systems. Your clients will love it! + Background color + Icon color Content model Label Custom view Settings model + Overlay editor size Add custom view Add settings Overwrite label template %0%.]]> Content using this block will be lost. + + Thumbnail + Add thumbnail diff --git a/src/Umbraco.Web/Editors/ElementTypeController.cs b/src/Umbraco.Web/Editors/ElementTypeController.cs new file mode 100644 index 0000000000..64dfbbb4ab --- /dev/null +++ b/src/Umbraco.Web/Editors/ElementTypeController.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using System.Linq; +using Umbraco.Core.Services; +using Umbraco.Web.Editors; +using Umbraco.Web.Mvc; + +namespace Umbraco.Web.Editors +{ + [PluginController("UmbracoApi")] + public class ElementTypeController : UmbracoAuthorizedJsonController + { + [System.Web.Http.HttpGet] + public IEnumerable GetAll() + { + return Services.ContentTypeService + .GetAllElementTypes() + .OrderBy(x => x.SortOrder) + .Select(x => new + { + id = x.Id, + key = x.Key, + name = x.Name, + description = x.Description, + alias = x.Alias, + icon = x.Icon + }); + } + } +} diff --git a/src/Umbraco.Web/PropertyEditors/BlockListConfiguration.cs b/src/Umbraco.Web/PropertyEditors/BlockListConfiguration.cs index 20b6c00d68..584ed5f1f8 100644 --- a/src/Umbraco.Web/PropertyEditors/BlockListConfiguration.cs +++ b/src/Umbraco.Web/PropertyEditors/BlockListConfiguration.cs @@ -10,7 +10,7 @@ namespace Umbraco.Web.PropertyEditors public class BlockListConfiguration { - [ConfigurationField("blocks", "Available Blocks", "views/propertyeditors/blocklist/prevalue/blocklist.elementtypepicker.html", Description = "Define the available blocks.")] + [ConfigurationField("blocks", "Available Blocks", "views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.html", Description = "Define the available blocks.")] public BlockConfiguration[] Blocks { get; set; } @@ -28,7 +28,16 @@ namespace Umbraco.Web.PropertyEditors public class BlockConfiguration { - // TODO: rename this to contentElementTypeAlias, I would like this to be specific, since we have the settings. + + [JsonProperty("backgroundColor")] + public string BackgroundColor { get; set; } + + [JsonProperty("iconColor")] + public string IconColor { get; set; } + + [JsonProperty("thumbnail")] + public string Thumbnail { get; set; } + [JsonProperty("contentTypeAlias")] public string Alias { get; set; } @@ -40,6 +49,9 @@ namespace Umbraco.Web.PropertyEditors [JsonProperty("label")] public string Label { get; set; } + + [JsonProperty("editorSize")] + public string EditorSize { get; set; } } [ConfigurationField("useInlineEditingAsDefault", "Inline editing mode", "boolean", Description = "Use the inline editor as the default block view")] diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 975f242dee..c657a52dcc 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -149,6 +149,7 @@ +