block editor implementation
This commit is contained in:
@@ -5,24 +5,43 @@
|
||||
function blockEditorService($interpolate, udiService) {
|
||||
|
||||
|
||||
function applyModelToScaffold(scaffold, contentModel) {
|
||||
|
||||
scaffold.key = contentModel.key;
|
||||
function mapToEditingModel(editingModel, contentModel) {
|
||||
|
||||
var variant = scaffold.variants[0];
|
||||
var variant = editingModel.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];
|
||||
if (contentModel[prop.alias]) {
|
||||
console.log("mapping:", prop.alias, contentModel[prop.alias])
|
||||
prop.value = contentModel[prop.alias];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function mapToPropertyModel(editingModel, contentModel) {
|
||||
|
||||
var variant = editingModel.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];
|
||||
if (contentModel[prop.propertyAlias]) {
|
||||
prop.value = contentModel[prop.propertyAlias];
|
||||
if (prop.value) {
|
||||
contentModel[prop.propertyAlias] = prop.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function mapValueToPropertyModel(value, alias, contentModel) {
|
||||
contentModel[alias] = value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc factory
|
||||
@@ -107,7 +126,9 @@
|
||||
*/
|
||||
getEditingModel: function(layoutEntry) {
|
||||
|
||||
var contentModel = this.getContentByUdi(layoutEntry.udi);
|
||||
var udi = layoutEntry.udi;
|
||||
|
||||
var contentModel = this.getContentByUdi(udi);
|
||||
|
||||
var blockConfiguration = this.getBlockConfiguration(contentModel.contentTypeAlias);
|
||||
|
||||
@@ -116,21 +137,44 @@
|
||||
return null;
|
||||
}
|
||||
|
||||
var model = angular.copy(blockConfiguration);
|
||||
model.labelInterpolate = $interpolate(model.label);
|
||||
model.overlaySize = model.overlaySize || "medium";
|
||||
|
||||
var editingModel = {};
|
||||
editingModel.config = angular.copy(blockConfiguration);
|
||||
editingModel.labelInterpolator = $interpolate(editingModel.config.label);
|
||||
|
||||
var scaffold = this.getScaffoldFor(blockConfiguration.contentTypeAlias);
|
||||
if(scaffold === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
model.content = angular.copy(scaffold);
|
||||
applyModelToScaffold(model.content, contentModel);
|
||||
// make basics from scaffold
|
||||
editingModel.content = angular.copy(scaffold);
|
||||
editingModel.content.udi = udi;
|
||||
|
||||
mapToEditingModel(editingModel.content, contentModel);
|
||||
|
||||
editingModel.contentModel = contentModel;
|
||||
editingModel.layoutModel = layoutEntry;
|
||||
|
||||
// TODO: settings
|
||||
|
||||
return model;
|
||||
return editingModel;
|
||||
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve editing model of a layout entry
|
||||
* @return {Object} Scaffolded Block Content object.
|
||||
*/
|
||||
setDataFromEditingModel: function(editingModel) {
|
||||
|
||||
var udi = editingModel.content.key;
|
||||
|
||||
var contentModel = this.getContentByUdi(udi);
|
||||
|
||||
mapToPropertyModel(editingModel.content, contentModel);
|
||||
|
||||
// TODO: sync settings to layout entry.
|
||||
|
||||
},
|
||||
|
||||
@@ -165,7 +209,6 @@
|
||||
return entry;
|
||||
},
|
||||
|
||||
// private
|
||||
getContentByUdi: function(udi) {
|
||||
return this.value.data.find(entry => entry.udi === udi);
|
||||
},
|
||||
@@ -198,12 +241,11 @@
|
||||
createModelObject: function(propertyModelValue, propertyEditorAlias, blockConfigurations) {
|
||||
return new BlockEditorModelObject(propertyModelValue, propertyEditorAlias, blockConfigurations);
|
||||
},
|
||||
getBlockLabel: function(blockModelObject, labelIndex) {
|
||||
getBlockLabel: function(blockModelObject) {
|
||||
|
||||
// TODO: we should do something about this for performance.
|
||||
|
||||
var vars = new Object();
|
||||
vars["$index"] = labelIndex;
|
||||
|
||||
var variant = blockModelObject.content.variants[0];
|
||||
var tab = variant.tabs[0];
|
||||
@@ -212,8 +254,8 @@
|
||||
vars[property.alias] = property.value;
|
||||
}
|
||||
|
||||
if(blockModelObject.labelInterpolate) {
|
||||
return blockModelObject.labelInterpolate(vars);
|
||||
if(blockModelObject.labelInterpolator) {
|
||||
return blockModelObject.labelInterpolator(vars);
|
||||
}
|
||||
|
||||
return blockModelObject.contentTypeName;
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
* @returns {string} The generated UDI
|
||||
*/
|
||||
create: function(entityType) {
|
||||
return "umb://" + entityType + "/" + String.CreateGuid();
|
||||
return "umb://" + entityType + "/" + (String.CreateGuid().replace(/-/g, ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<button type="button" class="btn-reset umb-outline blockelement-imageblock-editor blockelement__draggable-element" focus-when="{{moveFocusToBlock === block}}" ng-click="vm.editBlock(block)">
|
||||
<img src="{{block.content.temp_image}}">
|
||||
<button type="button" class="btn-reset umb-outline blockelement-imageblock-editor blockelement__draggable-element" focus-when="{{vm.focusThis}}" ng-click="vm.blockEditorApi.editBlock(vm.block)">
|
||||
<img src="{{vm.block.content.temp_image}}">
|
||||
</button>
|
||||
|
||||
+4
-4
@@ -1,10 +1,10 @@
|
||||
<div class="blockelement-inlineblock-editor" ng-class="{'--open': bc.isOpen}" ng-controller="Umbraco.PropertyEditors.BlockEditor.InlineBlockEditor as bc">
|
||||
<button type="button" class="btn-reset umb-outline blockelement__draggable-element" ng-click="bc.openBlock(block)" focus-when="{{moveFocusToBlock === block}}">
|
||||
<button type="button" class="btn-reset umb-outline blockelement__draggable-element" ng-click="bc.openBlock(block)" focus-when="{{vm.focusThis}}">
|
||||
<span class="caret"></span>
|
||||
<i class="icon {{block.content.icon}}"></i>
|
||||
<span>{{block.label}}</span>
|
||||
<i class="icon {{vm.block.content.icon}}"></i>
|
||||
<span>{{vm.block.label}}</span>
|
||||
</button>
|
||||
<div class="blockelement-inlineblock-editor__inner" ng-if="bc.isOpen === true">
|
||||
<umb-element-content-editor content="block.content"></umb-element-content-editor>
|
||||
<umb-element-content-editor content="vm.block.content"></umb-element-content-editor>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
}
|
||||
.blockelement-inlineblock-editor__inner {
|
||||
border-top: 1px solid @gray-8;
|
||||
background-color: @gray-11;
|
||||
|
||||
.umb-group-panel {
|
||||
background-color: transparent;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<button type="button" class="btn-reset umb-outline blockelement-labelblock-editor blockelement__draggable-element" ng-click="vm.editBlock(block)" focus-when="{{moveFocusToBlock === block}}">
|
||||
<i class="icon {{block.content.icon}}"></i>
|
||||
<span>{{block.label}}</span>
|
||||
<button type="button" class="btn-reset umb-outline blockelement-labelblock-editor blockelement__draggable-element" ng-click="vm.blockEditorApi.editBlock(vm.block)" focus-when="{{vm.focusThis}}">
|
||||
<i class="icon {{vm.block.content.icon}}"></i>
|
||||
<span>{{vm.block.label}}</span>
|
||||
</button>
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
<ng-form name="elementTypeContentForm">
|
||||
<div class="umb-group-panel"
|
||||
data-element="group-{{group.alias}}"
|
||||
ng-repeat="group in vm.content.tabs track by group.label">
|
||||
ng-repeat="group in vm.content.variants[0].tabs track by group.label">
|
||||
|
||||
<div class="umb-group-panel__header">
|
||||
<div id="group-{{group.id}}">{{ group.label }}</div>
|
||||
|
||||
-2
@@ -14,8 +14,6 @@
|
||||
|
||||
function ElementEditorComponentController() {
|
||||
|
||||
const vm = this;
|
||||
|
||||
// TODO: we might not need this..
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -5,9 +5,9 @@ angular.module("umbraco")
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.content = $scope.model.block.content;
|
||||
vm.content = $scope.model.content;
|
||||
|
||||
vm.title = $scope.model.block.label;
|
||||
vm.title = $scope.model.title;
|
||||
|
||||
vm.saveAndClose = function() {
|
||||
if ($scope.model && $scope.model.submit) {
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
<div class="umb-block-list__block">
|
||||
<div class="umb-block-list__block--content" ng-if="vm.block.view" ng-include="vm.block.view">
|
||||
</div>
|
||||
|
||||
<div class="umb-block-list__block--actions">
|
||||
<button type="button" class="btn-reset action --copy" localize="title" title="general_copy" ng-click="vm.blockEditorApi.requestCopyBlock(vm.block);" ng-if="vm.showCopy">
|
||||
<i class="icon icon-documents" aria-hidden="true"></i>
|
||||
<span class="sr-only">
|
||||
<localize key="general_copy">Copy</localize>
|
||||
</span>
|
||||
</button>
|
||||
<button type="button" class="btn-reset action --delete" localize="title" title="general_delete" ng-click="vm.blockEditorApi.requestDeleteBlock(vm.block);">
|
||||
<i class="icon icon-trash" aria-hidden="true"></i>
|
||||
<span class="sr-only">
|
||||
<localize key="general_delete">Delete</localize>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
angular
|
||||
.module("umbraco")
|
||||
.component("blockListPropertyEditorBlock", {
|
||||
templateUrl: "views/propertyeditors/blocklist/blocklist.block.component.html",
|
||||
controller: BlockListBlockController,
|
||||
controllerAs: "vm",
|
||||
bindings: {
|
||||
block: "=",
|
||||
blockEditorApi: "=",
|
||||
focusThisBlock: "<?"
|
||||
}
|
||||
});
|
||||
|
||||
function BlockListBlockController($scope, blockEditorService) {
|
||||
|
||||
var unsubscribe = [];
|
||||
var vm = this;
|
||||
|
||||
console.log("BlockListBlockController", vm);
|
||||
|
||||
vm.$onInit = function() {
|
||||
|
||||
// Start watching each property value.
|
||||
var variant = vm.block.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];
|
||||
unsubscribe.push($scope.$watch("vm.block.content.variants[0].tabs["+t+"].properties["+p+"].value", createPropWatcher(prop)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createPropWatcher(prop) {
|
||||
|
||||
return function() {
|
||||
|
||||
// sync data:
|
||||
console.log(prop.alias, prop.value);
|
||||
vm.block.contentModel[prop.alias] = prop.value;
|
||||
|
||||
// update label:
|
||||
updateLabel();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function updateLabel() {
|
||||
vm.block.label = blockEditorService.getBlockLabel(vm.block);
|
||||
}
|
||||
|
||||
$scope.$on("$destroy", function () {
|
||||
for (const subscription of unsubscribe) {
|
||||
subscription();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
})();
|
||||
+4
-67
@@ -5,82 +5,21 @@
|
||||
|
||||
<div ui-sortable="vm.sortableOptions" ng-model="vm.blocks">
|
||||
|
||||
<div ng-repeat="block in vm.blocks">
|
||||
<div ng-repeat="blockItem in vm.blocks">
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn-reset umb-block-list__block--create-button"
|
||||
ng-click="vm.showCreateDialog($index, $event)"
|
||||
outcommented-ng-if="vm.quickMenuVisible === false || $index !== vm.quickMenuIndex"
|
||||
>
|
||||
</button>
|
||||
<!--
|
||||
<div class="umb-block-list__block--create-bar" ng-if="vm.quickMenuVisible === true && $index === vm.quickMenuIndex">
|
||||
<button type="button"
|
||||
class="btn-reset"
|
||||
ng-repeat="type in vm.availableBlockTypes | limitTo:4"
|
||||
focus-when="{{$index === 0}}"
|
||||
ng-blur="vm.onCreateOptionsBlur($event)"
|
||||
ng-click="vm.quickMenuAddNewBlock(type)"
|
||||
>
|
||||
<i class="icon {{type.icon}}"></i>
|
||||
<span>{{type.name}}</span>
|
||||
</button>
|
||||
<button type="button"
|
||||
ng-if="vm.availableBlockTypes.length > 4"
|
||||
class="btn-reset"
|
||||
ng-click="vm.showCreateDialog($index, $event)"
|
||||
>
|
||||
<i class="icon icon-three-dots"></i>
|
||||
<span>more</span>
|
||||
</button>
|
||||
</div>
|
||||
-->
|
||||
|
||||
<div class="umb-block-list__block">
|
||||
<!--
|
||||
<div class="umb-block-list__block--head">
|
||||
<i class="icon" ng-class="block.icon"></i>
|
||||
<small>{{block.elementType.label}}</small>
|
||||
</div>
|
||||
-->
|
||||
<div class="umb-block-list__block--content" ng-if="block.editor" ng-include="block.editor">
|
||||
</div>
|
||||
<div class="umb-block-list__block--content" ng-if="!block.editor">
|
||||
<!-- TODO: Move LabelBlock into this, no reason to have that as seperate code, that would make it the default fallback. -->
|
||||
<h1>No editor</h1>
|
||||
</div>
|
||||
|
||||
<div class="umb-block-list__block--actions">
|
||||
<button type="button" class="btn-reset action --copy" localize="title" title="general_copy" ng-click="vm.requestCopyBlock(block);" ng-if="vm.showCopy">
|
||||
<i class="icon icon-documents" aria-hidden="true"></i>
|
||||
<span class="sr-only">
|
||||
<localize key="general_copy">Copy</localize>
|
||||
</span>
|
||||
</button>
|
||||
<button type="button" class="btn-reset action --delete" localize="title" title="general_delete" ng-click="vm.requestDeleteBlock(block);">
|
||||
<i class="icon icon-trash" aria-hidden="true"></i>
|
||||
<span class="sr-only">
|
||||
<localize key="general_delete">Delete</localize>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<block-list-property-editor-block block="blockItem" block-editor-api="vm.blockEditorApi" focus-this-block="false">
|
||||
</block-list-property-editor-block>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<button
|
||||
type="button"
|
||||
class="btn-reset umb-block-list__block--create-button"
|
||||
ng-click="vm.showCreateDialog(vm.blocks.length, $event)"
|
||||
ng-if="vm.blocks.length !== 0"
|
||||
>
|
||||
</button>
|
||||
-->
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn-reset umb-block-list__create-button"
|
||||
@@ -90,16 +29,14 @@
|
||||
<localize key="grid_addElement"></localize>
|
||||
</button>
|
||||
|
||||
|
||||
<input type="hidden" name="minCount" ng-model="vm.blocks" />
|
||||
<input type="hidden" name="maxCount" ng-model="vm.blocks" />
|
||||
|
||||
<div ng-messages="vm.propertyForm.minCount.$error" show-validation-on-submit>
|
||||
<div class="help text-error" ng-message="minCount">
|
||||
<localize key="validation_entriesShort" tokens="[vm.validationLimit.min, vm.validationLimit.min - vm.blocks.length]" watch-tokens="true">Minimum %0% entries, needs <strong>%1%</strong> more.</localize>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-if="vm.propertyForm.maxCount.$error === true || vm.blocks.length > vm.validationLimit.max">
|
||||
<div ng-if="vm.propertyForm.maxCount.$error === true && vm.blocks.length > vm.validationLimit.max">
|
||||
<div class="help text-error">
|
||||
<localize key="validation_entriesExceed" tokens="[vm.validationLimit.max, vm.blocks.length - vm.validationLimit.max]" watch-tokens="true">Maximum %0% entries, <strong>%1%</strong> too many.</localize>
|
||||
</div>
|
||||
|
||||
+155
-908
File diff suppressed because it is too large
Load Diff
@@ -1 +1 @@
|
||||
<block-list-property-editor></block-list-property-editor>
|
||||
<block-list-property-editor property-form="propertyForm" model="model"/>
|
||||
|
||||
@@ -42,8 +42,8 @@ namespace Umbraco.Web.PropertyEditors
|
||||
public string Label { get; set; }
|
||||
}
|
||||
|
||||
[ConfigurationField("useAccordionsAsDefault", "Inline editing mode", "boolean", Description = "Use the inline editor as the default block view")]
|
||||
public bool useInlineEditingAsDefault { get; set; }
|
||||
[ConfigurationField("useInlineEditingAsDefault", "Inline editing mode", "boolean", Description = "Use the inline editor as the default block view")]
|
||||
public bool UseInlineEditingAsDefault { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user