Merge remote-tracking branch 'origin/v8/feature/block-editor-list' into v8/feature/block-editor-list-validation

# Conflicts:
#	src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockeditor/blockeditor.controller.js
#	src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/elementeditor/elementeditor.content.html
#	src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-block.component.js
#	src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-property-editor.html
This commit is contained in:
Shannon
2020-06-29 15:02:26 +10:00
28 changed files with 113 additions and 82 deletions
@@ -50,8 +50,6 @@
}
});
// Some property editors need to performe an action after all property editors have reacted to the formSubmitting.
$scope.$broadcast("postFormSubmitting", { scope: $scope });
}
});
@@ -11,7 +11,7 @@
/**
* @ngdoc method
* @name umbraco.services.udiService#parse
* @name umbraco.services.udiService#create
* @methodOf umbraco.services.udiService
* @function
*
@@ -200,9 +200,9 @@
// 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/components/blockcard/umb-block-card-grid.less";
@import "../views/components/blockcard/umb-block-card.less";
@import "../views/propertyeditors/blocklist/umb-block-list-property-editor.less";
@import "../views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.less";
@import "../views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.less";
@import "../views/propertyeditors/notsupported/notsupported.less";
@@ -0,0 +1 @@
<umb-element-editor-content model="model.content"></umb-element-editor-content>
@@ -1,12 +1,9 @@
//used for the media picker dialog
angular.module("umbraco")
.controller("Umbraco.Editors.BlockEditorController",
function ($scope, localizationService, formHelper) {
var vm = this;
// TODO: Why are we assigning content/setting separately when we already have vm.model?
vm.content = $scope.model.content;
vm.settings = $scope.model.settings;
vm.model = $scope.model;
vm.model = $scope.model;
vm.tabs = [];
localizationService.localizeMany([
@@ -17,17 +14,16 @@ angular.module("umbraco")
vm.submitLabel = data[1];
});
if (vm.content && vm.content.variants) {
if ($scope.model.content && $scope.model.content.variants) {
var apps = vm.content.apps;
var apps = $scope.model.content.apps;
vm.tabs = apps;
// replace view of content app.
var contentApp = apps.find(entry => entry.alias === "umbContent");
if (contentApp) {
// TODO: This is strange, why does this render a view from somewhere else and this is the only place where that view is used?
contentApp.view = "views/common/infiniteeditors/elementeditor/elementeditor.content.html";
contentApp.view = "views/common/infiniteeditors/blockeditor/blockeditor.content.html";
if(vm.model.hideContent) {
apps.splice(apps.indexOf(contentApp), 1);
} else if (vm.model.openSettings !== true) {
@@ -41,15 +37,14 @@ angular.module("umbraco")
}
if (vm.settings && vm.settings.variants) {
if (vm.model.settings && vm.model.settings.variants) {
localizationService.localize("blockEditor_tabBlockSettings").then(
function (settingsName) {
var settingsTab = {
"name": settingsName,
"alias": "settings",
"icon": "icon-settings",
// TODO: This is strange, why does this render a view from somewhere else and this is the only place where that view is used?
"view": "views/common/infiniteeditors/elementeditor/elementeditor.settings.html"
"view": "views/common/infiniteeditors/blockeditor/blockeditor.settings.html"
};
vm.tabs.push(settingsTab);
if (vm.model.openSettings) {
@@ -69,7 +64,7 @@ angular.module("umbraco")
vm.close = function() {
if (vm.model && vm.model.close) {
// TODO: If content has changed, we should notify user.
// TODO: check if content/settings has changed and ask user if they are sure.
vm.model.close(vm.model);
}
}
@@ -1,4 +1,3 @@
//used for the media picker dialog
angular.module("umbraco")
.controller("Umbraco.Editors.BlockPickerController",
function ($scope, localizationService) {
@@ -1,3 +0,0 @@
<div>
<umb-element-editor-content model="model.content" item-index="model.index"></umb-element-editor-content>
</div>
@@ -1,5 +1,5 @@
<div class="__showcase" ng-style="{'background-color':vm.blockConfigModel.backgroundColor, 'background-image': vm.blockConfigModel.thumbnail ? 'url('+vm.blockConfigModel.thumbnail+')' : 'transparent'}">
<div class="__showcase" ng-style="{'background-color':vm.blockConfigModel.backgroundColor, 'background-image': vm.blockConfigModel.thumbnail ? 'url('+vm.blockConfigModel.thumbnail+'?upscale=false&width=400)' : 'transparent'}">
<i ng-if="vm.blockConfigModel.thumbnail == null && vm.elementTypeModel.icon" class="__icon {{ vm.elementTypeModel.icon }}" ng-style="{'color':vm.blockConfigModel.iconColor}" aria-hidden="true"></i>
</div>
<div class="__info">
@@ -59,6 +59,8 @@ umb-block-card {
background-size: cover;
background-position: 50% 50%;
background-repeat: no-repeat;
.__icon {
position: absolute;
width: 100%;
@@ -6,7 +6,7 @@
angular
.module("umbraco")
.component("umbBlockCard", {
templateUrl: "views/propertyeditors/blockeditor/blockcard/blockcard.component.html",
templateUrl: "views/components/blockcard/umb-block-card.html",
controller: BlockCardController,
controllerAs: "vm",
transclude: true,
@@ -6,7 +6,7 @@
angular
.module('umbraco.directives')
.component('umbElementEditorContent', {
templateUrl: 'views/common/infiniteeditors/elementeditor/elementEditor.content.component.html',
templateUrl: 'views/components/elementeditor/umb-element-editor-content.component.html',
controller: ElementEditorContentComponentController,
controllerAs: 'vm',
bindings: {
@@ -1,9 +0,0 @@
(function () {
function NumberRangeController($scope) {
}
angular.module("umbraco").controller("Umbraco.PrevalueEditors.NumberRangeController", NumberRangeController);
})();
@@ -1,4 +1,4 @@
<div class="umb-property-editor umb-prevalues-numberrange" ng-controller="Umbraco.PrevalueEditors.NumberRangeController">
<div class="umb-property-editor umb-prevalues-numberrange">
<ng-form name="prevalueNumberRangeForm">
<input name="numberFieldMin" class="__min-input"
type="number"
@@ -1 +1 @@
<block-list-property-editor property-form="propertyForm" model="model"/>
<umb-block-list-property-editor property-form="propertyForm" model="model"/>
@@ -16,10 +16,11 @@
}
}
function BlockConfigurationController($scope, elementTypeResource, overlayService, localizationService, editorService) {
function BlockConfigurationController($scope, elementTypeResource, overlayService, localizationService, editorService, eventsService) {
var unsubscribe = [];
var vm = this;
vm.openBlock = null;
function onInit() {
@@ -38,6 +39,16 @@
});
}
function updateUsedElementTypes(event, args) {
var key = args.documentType.key;
for (var i = 0; i<vm.elementTypes.length; i++) {
if (vm.elementTypes[i].key === key) {
vm.elementTypes[i] = args.documentType;
}
}
}
unsubscribe.push(eventsService.on("editors.documentType.saved", updateUsedElementTypes));
vm.requestRemoveBlockByIndex = function (index) {
localizationService.localizeMany(["general_delete", "blockEditor_confirmDeleteBlockMessage", "blockEditor_confirmDeleteBlockNotice"]).then(function (data) {
var contentElementType = vm.getElementTypeByKey($scope.model.value[index].contentTypeKey);
@@ -77,9 +88,11 @@
};
vm.getElementTypeByKey = function(key) {
return _.find(vm.elementTypes, function (type) {
return type.key === key;
});
if (vm.elementTypes) {
return vm.elementTypes.find(function (type) {
return type.key === key;
});
}
};
vm.openAddDialog = function ($event, entry) {
@@ -193,7 +206,9 @@
};
$scope.$on('$destroy', function () {
unsubscribe.forEach(u => { u(); });
});
onInit();
@@ -10,7 +10,9 @@
(function () {
"use strict";
function BlockConfigurationOverlayController($scope, overlayService, localizationService, editorService, elementTypeResource) {
function BlockConfigurationOverlayController($scope, overlayService, localizationService, editorService, elementTypeResource, eventsService) {
var unsubscribe = [];
var vm = this;
vm.block = $scope.model.block;
@@ -20,11 +22,14 @@
function loadElementTypes() {
return elementTypeResource.getAll().then(function (elementTypes) {
vm.elementTypes = elementTypes;
vm.contentPreview = vm.getElementTypeByKey(vm.block.contentTypeKey);
vm.settingsPreview = vm.getElementTypeByKey(vm.block.settingsElementTypeKey);
});
}
vm.getElementTypeByKey = function(key) {
return _.find(vm.elementTypes, function (type) {
return vm.elementTypes.find(function (type) {
return type.key === key;
});
};
@@ -34,7 +39,6 @@
const editor = {
id: elementTypeId,
submit: function (model) {
loadElementTypes();
editorService.close();
},
close: function () {
@@ -50,9 +54,7 @@
infiniteMode: true,
isElement: true,
submit: function (model) {
loadElementTypes().then( function () {
callback(model.documentTypeKey);
});
callback(model.documentTypeKey);
editorService.close();
},
close: function () {
@@ -123,6 +125,26 @@
};
function updateUsedElementTypes(event, args) {
var key = args.documentType.key;
for (var i = 0; i<vm.elementTypes.length; i++) {
if (vm.elementTypes[i].key === key) {
vm.elementTypes[i] = args.documentType;
}
}
if (vm.contentPreview.key === key) {
vm.contentPreview = args.documentType;
$scope.$evalAsync();
}
if (vm.settingsPreview.key === key) {
vm.settingsPreview = args.documentType;
$scope.$evalAsync();
}
}
unsubscribe.push(eventsService.on("editors.documentType.saved", updateUsedElementTypes));
vm.addViewForBlock = function(block) {
localizationService.localize("blockEditor_headlineSelectView").then(function(localizedTitle) {
@@ -132,8 +154,10 @@
treeAlias: "files",
entityType: "file",
isDialog: true,
filter: function (i) {
return !(i.name.indexOf(".html") !== -1);
},
select: function (node) {
console.log(node)
const filepath = decodeURIComponent(node.id.replace(/\+/g, " "));
block.view = filepath;
editorService.close();
@@ -176,6 +200,9 @@
treeAlias: "files",
entityType: "file",
isDialog: true,
filter: function (i) {
return !(i.name.indexOf(".css") !== -1);
},
select: function (node) {
const filepath = decodeURIComponent(node.id.replace(/\+/g, " "));
block.stylesheet = filepath;
@@ -250,11 +277,14 @@
vm.close = function() {
if ($scope.model && $scope.model.close) {
// TODO: If content has changed, we should notify user.
$scope.model.close($scope.model);
}
}
$scope.$on('$destroy', function () {
unsubscribe.forEach(u => { u(); });
});
}
angular.module("umbraco").controller("Umbraco.PropertyEditors.BlockList.BlockConfigurationOverlayController", BlockConfigurationOverlayController);
@@ -107,8 +107,7 @@
<label class="control-label"><localize key="blockEditor_labelContentElementType">Content ElementType</localize></label>
<div class="controls">
<div class="__settings-input --hasValue" ng-if="vm.block.contentTypeKey !== null" >
{{ contentPreview = vm.getElementTypeByKey(vm.block.contentTypeKey); "" }}
<umb-node-preview icon="contentPreview.icon" name="contentPreview.name"></umb-node-preview>
<umb-node-preview icon="vm.contentPreview.icon" name="vm.contentPreview.name" alias="vm.contentPreview.alias"></umb-node-preview>
<div class="__control-actions">
<button type="button" class="btn-reset __control-actions-btn --open umb-outline" ng-click="vm.openElementType(vm.block.contentTypeKey)">
<i class="icon icon-edit"></i>
@@ -125,8 +124,7 @@
<label class="control-label"><localize key="blockEditor_labelSettingsElementType">Settings Element Type</localize></label>
<div class="controls">
<div class="__settings-input --hasValue" ng-if="vm.block.settingsElementTypeKey !== null">
{{ settingsPreview = vm.getElementTypeByKey(vm.block.settingsElementTypeKey); "" }}
<umb-node-preview icon="settingsPreview.icon" name="settingsPreview.name"></umb-node-preview>
<umb-node-preview icon="vm.settingsPreview.icon" name="vm.settingsPreview.name" alias="vm.settingsPreview.alias"></umb-node-preview>
<div class="__control-actions">
<button type="button" class="btn-reset __control-actions-btn --open umb-outline" ng-click="vm.openElementType(vm.block.settingsElementTypeKey)">
<i class="icon icon-edit"></i>
@@ -17,7 +17,7 @@
bindings: {
view: "@",
block: "=",
api: "=", // Should this be a one way bind?
api: "<",
index: "<"
}
}
@@ -1,6 +1,6 @@
<div class="umb-block-list">
<umb-load-indicator style="margin-bottom:20px;" ng-if="vm.loading"></umb-load-indicator>
<umb-load-indicator ng-if="vm.loading"></umb-load-indicator>
<div class="umb-block-list__wrapper" ng-style="vm.listWrapperStyles">
@@ -18,20 +18,22 @@
<div class="umb-block-list__block" ng-class="{'--active':layout.$block.active}">
<umb-block-list-scoped-block ng-if="layout.$block.config.stylesheet"
class="umb-block-list__block--content blockelement__draggable-element"
view="{{layout.$block.view}}"
stylesheet="/{{::layout.$block.config.stylesheet}}"
api="vm.blockEditorApi"
block="layout.$block"
index="$index">
<umb-block-list-scoped-block
ng-if="layout.$block.config.stylesheet"
class="umb-block-list__block--content blockelement__draggable-element"
view="{{layout.$block.view}}"
stylesheet="/{{::layout.$block.config.stylesheet}}"
api="vm.blockEditorApi"
block="layout.$block"
index="$index">
</umb-block-list-scoped-block>
<umb-block-list-block ng-if="!layout.$block.config.stylesheet"
class="umb-block-list__block--content"
view="{{layout.$block.view}}"
api="vm.blockEditorApi"
block="layout.$block"
index="$index">
<umb-block-list-block
ng-if="!layout.$block.config.stylesheet"
class="umb-block-list__block--content"
view="{{layout.$block.view}}"
api="vm.blockEditorApi"
block="layout.$block"
index="$index">
</umb-block-list-block>
<div class="umb-block-list__block--actions">
@@ -43,7 +45,7 @@
<localize key="general_settings">Settings</localize>
</span>
</button>
<button type="button" class="btn-reset umb-outline action --copy" localize="title" title="actions_copy" ng-click="vm.blockEditorApi.requestCopyBlock(layout.$block);" ng-if="layout.$block.showCopy === true">
<button type="button" class="btn-reset umb-outline action --copy" localize="title" title="actions_copy" ng-click="vm.blockEditorApi.copyBlock(layout.$block);" ng-if="layout.$block.showCopy === true">
<i class="icon icon-documents" aria-hidden="true"></i>
<span class="sr-only">
<localize key="general_copy">Copy</localize>
@@ -4,6 +4,10 @@
padding-bottom:10px;
}
.umb-block-list .umb-load-indicator {
margin-bottom:20px;
}
.umb-block-list__wrapper {
position: relative;
max-width: 1024px;
@@ -6,6 +6,8 @@
* @name umbraco.directives.directive:umbBlockListScopedBlock
* @description
* The component for a style-scoped block of the block list property editor.
* Uses a ShadowDom to make a scoped element.
* This way the backoffice styling does not collide with the block style.
*/
angular
@@ -4,7 +4,7 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:blockListPropertyEditor
* @name umbraco.directives.directive:umbBlockListPropertyEditor
* @function
*
* @description
@@ -12,8 +12,8 @@
*/
angular
.module("umbraco")
.component("blockListPropertyEditor", {
templateUrl: "views/propertyeditors/blocklist/blocklist.component.html",
.component("umbBlockListPropertyEditor", {
templateUrl: "views/propertyeditors/blocklist/umb-block-list-property-editor.html",
controller: BlockListController,
controllerAs: "vm",
bindings: {
@@ -391,10 +391,6 @@
};
function requestCopyBlock(block) {
clipboardService.copy("elementTypeArray", block.content.contentTypeAlias, block.content, block.label);
}
var requestCopyAllBlocks = function() {
var elementTypesToCopy = vm.layout.filter(entry => entry.$block.config.unsupported !== true).map(entry => entry.$block.content);
@@ -416,7 +412,7 @@
clipboardService.copyArray("elementTypeArray", aliases, elementTypesToCopy, localizedLabel, "icon-thumbnail-list", vm.model.id);
});
}
function requestCopyBlock(block) {
function copyBlock(block) {
clipboardService.copy("elementType", block.content.contentTypeAlias, block.content, block.label);
}
function requestPasteFromClipboard(index, pasteEntry) {
@@ -487,7 +483,7 @@
vm.blockEditorApi = {
editBlock: editBlock,
requestCopyBlock: requestCopyBlock,
copyBlock: copyBlock,
requestDeleteBlock: requestDeleteBlock,
deleteBlock: deleteBlock,
openSettingsForBlock: openSettingsForBlock
@@ -4,7 +4,7 @@
angular
.module("umbraco")
.controller("Umbraco.PropertyEditors.BlockListPropertyEditor.CreateButtonController",
function BlockListController($scope) {
function Controller($scope) {
var vm = this;
vm.plusPosX = 0;
@@ -480,7 +480,8 @@
var notSupported = [
"Umbraco.Tags",
"Umbraco.UploadField",
"Umbraco.ImageCropper"
"Umbraco.ImageCropper",
"Umbraco.BlockList"
];
// Initialize
@@ -45,7 +45,7 @@
]
};
describe('init blockEditoModelObject', function () {
describe('init blockEditorModelObject', function () {
it('fail if no model value', function () {
function createWithNoModelValue() {