Enable Block List Editor settings editing

This commit is contained in:
Benjamin Carleski
2020-03-27 15:41:48 -07:00
parent 5ed727df02
commit 09be6b8ee4
8 changed files with 200 additions and 73 deletions

View File

@@ -56,7 +56,21 @@
* @param {Object} toModel ElementTypeModel to recive property values from.
*/
function mapElementTypeValues(fromModel, toModel) {
if (!fromModel || !fromModel.variants) {
toModel.variants = null;
return;
}
if (!fromModel.variants.length) {
toModel.variants = [];
return;
}
var fromVariant = fromModel.variants[0];
if (!fromVariant) {
toModel.variants = [null];
return;
}
var toVariant = toModel.variants[0];
for (var t = 0; t < fromVariant.tabs.length; t++) {
@@ -81,6 +95,31 @@
}
/**
* Used to add watchers on all properties in a content or settings model
*/
function addWatchers(blockModel, isolatedScope, forSettings) {
var model = forSettings ? blockModel.settings : blockModel.content;
if (!model || !model.variants || !model.variants.length) { return; }
// Start watching each property value.
var variant = model.variants[0];
var field = forSettings ? "settings" : "content";
var watcherCreator = forSettings ? createSettingsModelPropWatcher : createContentModelPropWatcher;
for (var t = 0; t < variant.tabs.length; t++) {
var tab = variant.tabs[t];
for (var p = 0; p < tab.properties.length; p++) {
var prop = tab.properties[p];
// Watch value of property since this is the only value we want to keep synced.
// Do notice that it is not performing a deep watch, meaning that we are only watching primatives and changes directly to the object of property-value.
// But we like to sync non-primative values as well! Yes, and this does happen, just not through this code, but through the nature of JavaScript.
// Non-primative values act as references to the same data and are therefor synced.
blockModel.watchers.push(isolatedScope.$watch("blockModels._" + blockModel.key + "." + field + ".variants[0].tabs[" + t + "].properties[" + p + "].value", watcherCreator(blockModel, prop)));
}
}
}
/**
* Used to create a scoped watcher for a content property on a blockModel.
*/
@@ -225,13 +264,13 @@
blockModel.config = angular.copy(blockConfiguration);
blockModel.labelInterpolator = $interpolate(blockModel.config.label);
var scaffold = this.getScaffoldFor(blockConfiguration.contentTypeAlias);
if(scaffold === null) {
var contentScaffold = this.getScaffoldFor(blockConfiguration.contentTypeAlias);
if(contentScaffold === null) {
return null;
}
// make basics from scaffold
blockModel.content = angular.copy(scaffold);
blockModel.content = angular.copy(contentScaffold);
blockModel.content.udi = udi;
mapToElementTypeModel(blockModel.content, contentModel);
@@ -240,37 +279,32 @@
blockModel.layoutModel = layoutEntry;
blockModel.watchers = [];
// TODO: implement settings
// create ElementTypeModel of settings
// store ElementTypeModel in blockModel.settings
// setup watchers for mapping
if (blockConfiguration.settingsElementTypeAlias) {
var settingsScaffold = this.getScaffoldFor(blockConfiguration.settingsElementTypeAlias);
if (settingsScaffold === null) {
return null;
}
// make basics from scaffold
blockModel.settings = angular.copy(settingsScaffold);
layoutEntry.settings = layoutEntry.settings || { key: String.CreateGuid(), contentTypeAlias: blockConfiguration.settingsElementTypeAlias };
if (!layoutEntry.settings.key) { layoutEntry.settings.key = String.CreateGuid(); }
if (!layoutEntry.settings.contentTypeAlias) { layoutEntry.settings.contentTypeAlias = blockConfiguration.settingsElementTypeAlias; }
mapToElementTypeModel(blockModel.settings, layoutEntry.settings);
} else {
layoutEntry.settings = null;
}
// Add blockModel to our isolated scope to enable watching its values:
this.isolatedScope.blockModels["_"+blockModel.key] = blockModel;
// Start watching each property value.
var variant = blockModel.content.variants[0];
for (var t = 0; t < variant.tabs.length; t++) {
var tab = variant.tabs[t];
for (var p = 0; p < tab.properties.length; p++) {
var prop = tab.properties[p];
// Watch value of property since this is the only value we want to keep synced.
// Do notice that it is not performing a deep watch, meaning that we are only watching primatives and changes directly to the object of property-value.
// But we like to sync non-primative values as well! Yes, and this does happen, just not through this code, but through the nature of JavaScript.
// Non-primative values act as references to the same data and are therefor synced.
blockModel.watchers.push(this.isolatedScope.$watch("blockModels._"+blockModel.key+".content.variants[0].tabs["+t+"].properties["+p+"].value", createContentModelPropWatcher(blockModel, prop)));
}
}
addWatchers(blockModel, this.isolatedScope);
addWatchers(blockModel, this.isolatedScope, true);
return blockModel;
},
removeDataAndDestroyModel: function(blockModel) {
removeDataAndDestroyModel: function (blockModel) {
this.destroyBlockModel(blockModel);
this.removeDataByUdi(blockModel.content.udi);
},
@@ -331,7 +365,7 @@
}
if (blockConfiguration.settingsElementTypeAlias != null) {
entry.settings = {};
entry.settings = { key: String.CreateGuid(), contentTypeAlias: blockConfiguration.settingsElementTypeAlias };
}
return entry;

View File

@@ -2,17 +2,49 @@
angular.module("umbraco")
.controller("Umbraco.Editors.BlockEditorController",
function ($scope) {
var vm = this;
function showContent() {
if (vm.settingsTab) vm.settingsTab.active = false;
vm.contentTab.active = true;
}
function showSettings() {
if (vm.settingsTab) vm.settingsTab.active = true;
vm.contentTab.active = false;
}
vm.content = $scope.model.content;
vm.settings = $scope.model.settings;
vm.tabs = [];
var settingsOnly = vm.content && vm.content.variants ? false : true;
// TODO: implement settings — do notice that settings is optional.
//vm.settings = $scope.model.settings;
if (!settingsOnly) {
vm.contentTab = {
"name": "Content",
"alias": "content",
"icon": "icon-document",
"action": showContent,
"active": true
};
vm.title = $scope.model.title;
vm.tabs.push(vm.contentTab);
}
vm.saveAndClose = function() {
if (vm.settings && vm.settings.variants) {
vm.settingsTab = {
"name": "Settings",
"alias": "settings",
"icon": "icon-settings",
"action": showSettings,
"active": settingsOnly
};
vm.tabs.push(vm.settingsTab);
}
vm.title = (settingsOnly ? 'SETTINGS: ' : '') + $scope.model.title;
vm.saveAndClose = function () {
if ($scope.model && $scope.model.submit) {
$scope.model.submit($scope.model);
}

View File

@@ -1,15 +1,16 @@
<div class="umb-block-editor" ng-controller="Umbraco.Editors.BlockEditorController as vm">
<ng-form name="blockForm" val-form-manager>
<umb-editor-view ng-if="!page.loading">
<umb-editor-view umb-tabs ng-if="!page.loading">
<umb-editor-header
name="vm.title"
name-locked="true"
navigation="vm.content.apps"
navigation="vm.tabs"
hide-alias="true"
hide-icon="true"
hide-description="true">
hide-description="true"
on-select-navigation-item="vm.selectTab">
</umb-editor-header>
<div class="umb-editor-container umb-panel-body umb-scrollable row-fluid">
@@ -21,12 +22,19 @@
-->
<!-- Missing content apps? — but i'm not sure content apps will or can work for ElementTypes? -->
<div ng-show="vm.contentTab.active">
<div class="umb-pane">
<div class="umb-editor-sub-views" val-sub-view>
<umb-element-content-editor content="vm.content"></umb-element-content-editor>
</div>
</div>
</div>
<!-- TODO: implement settings -->
<div class="umb-pane">
<div class="umb-editor-sub-views" val-sub-view>
<umb-element-content-editor content="vm.content"></umb-element-content-editor>
<div ng-show="vm.settingsTab.active">
<div class="umb-pane" ng-if="vm.settings">
<div class="umb-editor-sub-views" val-sub-view>
<umb-element-content-editor content="vm.settings"></umb-element-content-editor>
</div>
</div>
</div>
</div>

View File

@@ -182,24 +182,29 @@
vm.blocks.forEach(deleteBlock);
}
function editBlock(blockModel) {
function editBlock(blockModel, hideContent) {
if (hideContent && !blockModel.config.settingsElementTypeAlias) {
return;
}
// make a clone to avoid editing model directly.
var blockContentModelClone = angular.copy(blockModel.content);
// TODO: implement settings
// Settings should be available as a tab in this overlay:
//var blockSettingsModelClone = angular.copy(blockModel.settings);
var blockContentModelClone = angular.copy(hideContent ? null : blockModel.content);
var blockSettingsModelClone = angular.copy(blockModel.settings);
var blockEditorModel = {
content: blockContentModelClone,
//settings: blockSettingsModelClone,
settings: blockSettingsModelClone,
title: blockModel.label,
view: "views/common/infiniteeditors/blockeditor/blockeditor.html",
size: blockModel.config.overlaySize || "medium",
submit: function(blockEditorModel) {
// To ensure syncronization gets tricked we transfer
blockEditorService.mapElementTypeValues(blockEditorModel.content, blockModel.content)
if (!hideContent) {
blockEditorService.mapElementTypeValues(blockEditorModel.content, blockModel.content)
}
if (blockModel.config.settingsElementTypeAlias) {
blockEditorService.mapElementTypeValues(blockEditorModel.settings, blockModel.settings)
}
editorService.close();
},
close: function() {
@@ -244,10 +249,14 @@
vm.blockTypePicker.close();
},
submit: function (model) {
var added = false;
if (model && model.selectedItem) {
addNewBlock(createIndex, model.selectedItem.alias);
added = addNewBlock(createIndex, model.selectedItem.alias);
}
vm.blockTypePicker.close();
if (added && vm.blocks.length > createIndex) {
editBlock(vm.blocks[createIndex]);
}
},
close: function () {
vm.blockTypePicker.show = false;
@@ -379,8 +388,8 @@
});
}
function openSettingsForBlock() {
alert("settings not implemented jet.");
function openSettingsForBlock(block) {
editBlock(block, true);
}