Appending the block objects to layout, to share it across variants and in split-view.
This commit is contained in:
@@ -28,13 +28,20 @@
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* // We must get a scope that exists in all the lifetime of this data. Across variants and split-view.
|
||||
* var scopeOfExistence = $scope;
|
||||
* // Setup your component to require umbVariantContentEditors and use the method getScope to retrive a shared scope for multiple editors of this content.
|
||||
* if(vm.umbVariantContentEditors && vm.umbVariantContentEditors.getScope) {
|
||||
* scopeOfExistence = vm.umbVariantContentEditors.getScope();
|
||||
* }
|
||||
*
|
||||
* // Define variables for layout and modelObject as you will be using these through our your property-editor.
|
||||
* var layout;
|
||||
* var modelObject;
|
||||
*
|
||||
* // When we are ready we can instantiate the Model Object can load the dependencies of it.
|
||||
* vm.$onInit = function() {
|
||||
* modelObject = blockEditorService.createModelObject(vm.model.value, vm.model.editor, vm.model.config.blocks, $scope);
|
||||
* modelObject = blockEditorService.createModelObject(vm.model.value, vm.model.editor, vm.model.config.blocks, scopeOfExistence);
|
||||
* modelObject.load().then(onLoaded);
|
||||
* }
|
||||
*
|
||||
@@ -171,13 +178,14 @@
|
||||
|
||||
function blockEditorModelObjectFactory($interpolate, udiService, contentResource) {
|
||||
|
||||
|
||||
/**
|
||||
* Simple mapping from property model content entry to editing model,
|
||||
* needs to stay simple to avoid deep watching.
|
||||
*/
|
||||
function mapToElementModel(elementModel, dataModel) {
|
||||
|
||||
if (!elementModel || !elementModel.variants || !elementModel.variants.length) { return; }
|
||||
|
||||
var variant = elementModel.variants[0];
|
||||
|
||||
for (var t = 0; t < variant.tabs.length; t++) {
|
||||
@@ -190,6 +198,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -198,6 +207,8 @@
|
||||
*/
|
||||
function mapToPropertyModel(elementModel, dataModel) {
|
||||
|
||||
if (!elementModel || !elementModel.variants || !elementModel.variants.length) { return; }
|
||||
|
||||
var variant = elementModel.variants[0];
|
||||
|
||||
for (var t = 0; t < variant.tabs.length; t++) {
|
||||
@@ -210,6 +221,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -272,7 +284,7 @@
|
||||
// Start watching each property value.
|
||||
var variant = model.variants[0];
|
||||
var field = forSettings ? "settings" : "content";
|
||||
var watcherCreator = forSettings ? createSettingsModelPropWatcher : createDataModelPropWatcher;
|
||||
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++) {
|
||||
@@ -283,6 +295,13 @@
|
||||
// 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.
|
||||
blockObject.watchers.push(isolatedScope.$watch("blockObjects._" + blockObject.key + "." + field + ".variants[0].tabs[" + t + "].properties[" + p + "].value", watcherCreator(blockObject, prop)));
|
||||
|
||||
// We also like to watch our data model to be able to capture changes coming from other places.
|
||||
if (forSettings === true) {
|
||||
blockObject.watchers.push(isolatedScope.$watch("blockObjects._" + blockObject.key + "." + "layout.settings" + "." + prop.alias, createLayoutSettingsModelWatcher(blockObject, prop)));
|
||||
} else {
|
||||
blockObject.watchers.push(isolatedScope.$watch("blockObjects._" + blockObject.key + "." + "data" + "." + prop.alias, createDataModelWatcher(blockObject, prop)));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (blockObject.watchers.length === 0) {
|
||||
@@ -291,10 +310,31 @@
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to create a prop watcher for the data in the property editor data model.
|
||||
*/
|
||||
function createDataModelWatcher(blockObject, prop) {
|
||||
return function() {
|
||||
// sync data:
|
||||
prop.value = blockObject.data[prop.alias];
|
||||
|
||||
blockObject.updateLabel();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Used to create a prop watcher for the settings in the property editor data model.
|
||||
*/
|
||||
function createLayoutSettingsModelWatcher(blockObject, prop) {
|
||||
return function() {
|
||||
// sync data:
|
||||
prop.value = blockObject.layout.settings[prop.alias];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to create a scoped watcher for a content property on a blockObject.
|
||||
*/
|
||||
function createDataModelPropWatcher(blockObject, prop) {
|
||||
function createContentModelPropWatcher(blockObject, prop) {
|
||||
return function() {
|
||||
// sync data:
|
||||
blockObject.data[prop.alias] = prop.value;
|
||||
@@ -482,8 +522,9 @@
|
||||
* @ngdoc method
|
||||
* @name getBlockObject
|
||||
* @methodOf umbraco.services.blockEditorModelObject
|
||||
* @description Retrieve editor friendly model of a block.
|
||||
* BlockObject is a class instance which setups live syncronization of content and settings models back to the data of your property editor model.
|
||||
* @description Retrieve a Block Object for the given layout entry.
|
||||
* The Block Object offers the nesecary data to display and edit a block.
|
||||
* The Block Object setups live syncronization of content and settings models back to the data of your Property Editor model.
|
||||
* The returned object, named ´BlockObject´, contains several usefull models to make editing of this block happen.
|
||||
* The ´BlockObject´ contains the following properties:
|
||||
* - key {string}: runtime generated key, usefull for tracking of this object
|
||||
@@ -509,19 +550,32 @@
|
||||
}
|
||||
|
||||
var blockConfiguration = this.getBlockConfiguration(dataModel.contentTypeKey);
|
||||
var contentScaffold;
|
||||
|
||||
if (blockConfiguration === null) {
|
||||
console.error("The block entry of "+udi+" is not begin initialized cause its contentTypeKey is not allowed for this PropertyEditor")
|
||||
// This is not an allowed block type, therefor we return null;
|
||||
return null;
|
||||
console.error("The block entry of "+udi+" is not begin initialized cause its contentTypeKey is not allowed for this PropertyEditor");
|
||||
} else {
|
||||
var contentScaffold = this.getScaffoldFromKey(blockConfiguration.contentTypeKey);
|
||||
if(contentScaffold === null) {
|
||||
console.error("The block entry of "+udi+" is not begin initialized cause its Element Type was not loaded.");
|
||||
}
|
||||
}
|
||||
|
||||
var contentScaffold = this.getScaffoldFromKey(blockConfiguration.contentTypeKey);
|
||||
if(contentScaffold === null) {
|
||||
return null;
|
||||
if (blockConfiguration === null || contentScaffold === null) {
|
||||
|
||||
blockConfiguration = {
|
||||
label: "Unsupported Block ("+udi+")",
|
||||
unsupported: true
|
||||
};
|
||||
contentScaffold = {};
|
||||
|
||||
}
|
||||
|
||||
var blockObject = {};
|
||||
// Set an angularJS cloneNode method, to avoid this object begin cloned.
|
||||
blockObject.cloneNode = function() {
|
||||
return null;// angularJS accept this as a cloned value as long as the
|
||||
}
|
||||
blockObject.key = String.CreateGuid().replace(/-/g, "");
|
||||
blockObject.config = Utilities.copy(blockConfiguration);
|
||||
if (blockObject.config.label && blockObject.config.label !== "") {
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
<div class="umb-block-list__wrapper" ng-style="vm.listWrapperStyles">
|
||||
|
||||
<div ui-sortable="vm.sortableOptions" ng-model="vm.blocks" ng-if="vm.loading !== true">
|
||||
<div ui-sortable="vm.sortableOptions" ng-model="vm.layout" ng-if="vm.loading !== true">
|
||||
|
||||
<div ng-repeat="block in vm.blocks track by block.key">
|
||||
<div ng-repeat="layout in vm.layout track by layout.$block.key">
|
||||
|
||||
<button
|
||||
type="button"
|
||||
@@ -18,27 +18,27 @@
|
||||
<div class="__plus" ng-style="{'left':inlineCreateButtonCtrl.plusPosX}">+</div>
|
||||
</button>
|
||||
|
||||
<div class="umb-block-list__block" ng-class="{'--open':block.isOpen}">
|
||||
<div class="umb-block-list__block" ng-class="{'--open':layout.$block.isOpen}">
|
||||
|
||||
<umb-block-list-scoped-block-content ng-if="block.config.stylesheet" class="umb-block-list__block--content blockelement__draggable-element" view="{{block.view}}" stylesheet="/{{::block.config.stylesheet}}" api="vm.blockEditorApi" block="block" index="$index">
|
||||
<umb-block-list-scoped-block-content 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-content>
|
||||
<umb-block-list-block-content ng-if="!block.config.stylesheet" class="umb-block-list__block--content" view="{{block.view}}" api="vm.blockEditorApi" block="block" index="$index">
|
||||
<umb-block-list-block-content 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-content>
|
||||
|
||||
<div class="umb-block-list__block--actions">
|
||||
<button type="button" class="btn-reset umb-outline action --settings" localize="title" title="actions_editSettings" ng-click="vm.blockEditorApi.openSettingsForBlock(block);" ng-if="block.showSettings === true">
|
||||
<button type="button" class="btn-reset umb-outline action --settings" localize="title" title="actions_editSettings" ng-click="vm.blockEditorApi.openSettingsForBlock(layout.$block);" ng-if="layout.$block.showSettings === true">
|
||||
<i class="icon icon-settings" aria-hidden="true"></i>
|
||||
<span class="sr-only">
|
||||
<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(block);" ng-if="vm.showCopy">
|
||||
<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">
|
||||
<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 umb-outline action --delete" localize="title" title="actions_delete" ng-click="vm.blockEditorApi.requestDeleteBlock(block);">
|
||||
<button type="button" class="btn-reset umb-outline action --delete" localize="title" title="actions_delete" ng-click="vm.blockEditorApi.requestDeleteBlock(layout.$block);">
|
||||
<i class="icon icon-trash" aria-hidden="true"></i>
|
||||
<span class="sr-only">
|
||||
<localize key="general_delete">Delete</localize>
|
||||
@@ -56,21 +56,21 @@
|
||||
type="button"
|
||||
class="btn-reset umb-block-list__create-button umb-outline"
|
||||
ng-class="{ '--disabled': vm.availableBlockTypes.length === 0 }"
|
||||
ng-click="vm.showCreateDialog(vm.blocks.length, $event)"
|
||||
ng-click="vm.showCreateDialog(vm.layout.length, $event)"
|
||||
>
|
||||
<localize key="grid_addElement"></localize>
|
||||
</button>
|
||||
|
||||
<input type="hidden" name="minCount" ng-model="vm.blocks" />
|
||||
<input type="hidden" name="maxCount" ng-model="vm.blocks" />
|
||||
<input type="hidden" name="minCount" ng-model="vm.layout" />
|
||||
<input type="hidden" name="maxCount" ng-model="vm.layout" />
|
||||
<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>
|
||||
<localize key="validation_entriesShort" tokens="[vm.validationLimit.min, vm.validationLimit.min - vm.layout.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.layout.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>
|
||||
<localize key="validation_entriesExceed" tokens="[vm.validationLimit.max, vm.layout.length - vm.validationLimit.max]" watch-tokens="true">Maximum %0% entries, <strong>%1%</strong> too many.</localize>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
},
|
||||
require: {
|
||||
umbProperty: "?^umbProperty",
|
||||
umbVariantContent: '?^^umbVariantContent'
|
||||
umbVariantContent: '?^^umbVariantContent',
|
||||
umbVariantContentEditors: '?^^umbVariantContentEditors'
|
||||
}
|
||||
});
|
||||
|
||||
@@ -49,10 +50,9 @@
|
||||
vm.currentBlockInFocus = block;
|
||||
block.focus = true;
|
||||
}
|
||||
vm.showCopy = clipboardService.isSupported();
|
||||
vm.supportCopy = clipboardService.isSupported();
|
||||
|
||||
var layout = [];// The layout object specific to this Block Editor, will be a direct reference from Property Model.
|
||||
vm.blocks = [];// Runtime list of block models, needs to be synced to property model on form submit.
|
||||
vm.layout = [];// The layout object specific to this Block Editor, will be a direct reference from Property Model.
|
||||
vm.availableBlockTypes = [];// Available block entries of this property editor.
|
||||
|
||||
var labels = {};
|
||||
@@ -82,9 +82,14 @@
|
||||
if(typeof vm.model.value !== 'object' || vm.model.value === null) {// testing if we have null or undefined value or if the value is set to another type than Object.
|
||||
vm.model.value = {};
|
||||
}
|
||||
|
||||
var scopeOfExistence = $scope;
|
||||
if(vm.umbVariantContentEditors && vm.umbVariantContentEditors.getScope) {
|
||||
scopeOfExistence = vm.umbVariantContentEditors.getScope();
|
||||
}
|
||||
|
||||
// Create Model Object, to manage our data for this Block Editor.
|
||||
modelObject = blockEditorService.createModelObject(vm.model.value, vm.model.editor, vm.model.config.blocks, $scope);
|
||||
modelObject = blockEditorService.createModelObject(vm.model.value, vm.model.editor, vm.model.config.blocks, scopeOfExistence);
|
||||
modelObject.load().then(onLoaded);
|
||||
|
||||
copyAllBlocksAction = {
|
||||
@@ -124,15 +129,20 @@
|
||||
function onLoaded() {
|
||||
|
||||
// Store a reference to the layout model, because we need to maintain this model.
|
||||
layout = modelObject.getLayout([]);
|
||||
vm.layout = modelObject.getLayout([]);
|
||||
|
||||
// maps layout entries to editor friendly models aka. blockObjects.
|
||||
layout.forEach(entry => {
|
||||
var block = getBlockObject(entry);
|
||||
|
||||
// If this entry was not supported by our property-editor it would return 'null'.
|
||||
if(block !== null) {
|
||||
vm.blocks.push(block);
|
||||
// Append the blockObjects to our layout.
|
||||
vm.layout.forEach(entry => {
|
||||
if (entry.$block === undefined || entry.$block === null) {
|
||||
console.log("We are creating a BlockObject for", entry.udi);
|
||||
var block = getBlockObject(entry);
|
||||
|
||||
// If this entry was not supported by our property-editor it would return 'null'.
|
||||
if(block !== null) {
|
||||
entry.$block = block;
|
||||
} else {
|
||||
entry.$block = blockEditorService.UNSUPPORTED_BLOCKOBJECT;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -145,16 +155,25 @@
|
||||
|
||||
}
|
||||
|
||||
function getDefaultViewForBlock(block) {
|
||||
|
||||
if (block.config.unsupported === true)
|
||||
return "views/propertyeditors/blocklist/blocklistentryeditors/unsupportedblock/unsupportedblock.editor.html";
|
||||
|
||||
if (inlineEditing === true)
|
||||
return "views/propertyeditors/blocklist/blocklistentryeditors/inlineblock/inlineblock.editor.html";
|
||||
return "views/propertyeditors/blocklist/blocklistentryeditors/labelblock/labelblock.editor.html";
|
||||
}
|
||||
|
||||
function getBlockObject(entry) {
|
||||
var block = modelObject.getBlockObject(entry);
|
||||
|
||||
if (block === null) return null;
|
||||
|
||||
// Lets apply fallback views, and make the view available directly on the blockObject.
|
||||
block.view = (block.config.view ? "/" + block.config.view : (inlineEditing ? "views/propertyeditors/blocklist/blocklistentryeditors/inlineblock/inlineblock.editor.html" : "views/propertyeditors/blocklist/blocklistentryeditors/labelblock/labelblock.editor.html"));
|
||||
block.view = (block.config.view ? "/" + block.config.view : getDefaultViewForBlock(block));
|
||||
|
||||
block.showSettings = block.config.settingsElementTypeKey != null;
|
||||
block.showCopy = vm.supportCopy && block.config.contentTypeKey != null;// if we have content, otherwise it dosnt make sense to copy.
|
||||
|
||||
return block;
|
||||
}
|
||||
@@ -176,11 +195,11 @@
|
||||
|
||||
// If we reach this line, we are good to add the layoutEntry and blockObject to our models.
|
||||
|
||||
// add layout entry at the decired location in layout.
|
||||
layout.splice(index, 0, layoutEntry);
|
||||
// Add the Block Object to our layout entry.
|
||||
layoutEntry.$block = blockObject;
|
||||
|
||||
// apply block model at decired location in blocks.
|
||||
vm.blocks.splice(index, 0, blockObject);
|
||||
// add layout entry at the decired location in layout.
|
||||
vm.layout.splice(index, 0, layoutEntry);
|
||||
|
||||
// lets move focus to this new block.
|
||||
vm.setBlockFocus(blockObject);
|
||||
@@ -193,24 +212,19 @@
|
||||
|
||||
function deleteBlock(block) {
|
||||
|
||||
var index = vm.blocks.indexOf(block);
|
||||
if(index !== -1) {
|
||||
|
||||
var layoutIndex = layout.findIndex(entry => entry.udi === block.content.udi);
|
||||
if(layoutIndex !== -1) {
|
||||
layout.splice(index, 1);
|
||||
} else {
|
||||
throw new Error("Could not find layout entry of block with udi: "+block.content.udi)
|
||||
}
|
||||
|
||||
vm.blocks.splice(index, 1);
|
||||
|
||||
modelObject.removeDataAndDestroyModel(block);
|
||||
var layoutIndex = vm.layout.findIndex(entry => entry.udi === block.content.udi);
|
||||
if(layoutIndex === -1) {
|
||||
throw new Error("Could not find layout entry of block with udi: "+block.content.udi)
|
||||
}
|
||||
vm.layout.splice(layoutIndex, 1);
|
||||
modelObject.removeDataAndDestroyModel(block);
|
||||
|
||||
}
|
||||
|
||||
function deleteAllBlocks() {
|
||||
vm.blocks.forEach(deleteBlock);
|
||||
vm.layout.forEach(entry => {
|
||||
deleteBlock(entry.$block);
|
||||
});
|
||||
}
|
||||
|
||||
function editBlock(blockObject, openSettings) {
|
||||
@@ -293,15 +307,15 @@
|
||||
|
||||
if(!(mouseEvent.ctrlKey || mouseEvent.metaKey)) {
|
||||
editorService.close();
|
||||
if (added && vm.model.config.useInlineEditingAsDefault !== true && vm.blocks.length > createIndex) {
|
||||
editBlock(vm.blocks[createIndex]);
|
||||
if (added && vm.model.config.useInlineEditingAsDefault !== true && vm.layout.length > createIndex) {
|
||||
editBlock(vm.layout[createIndex].$block);
|
||||
}
|
||||
}
|
||||
},
|
||||
close: function() {
|
||||
// if opned by a inline creator button(index less than length), we want to move the focus away, to hide line-creator.
|
||||
if (createIndex < vm.blocks.length) {
|
||||
vm.setBlockFocus(vm.blocks[Math.max(createIndex-1, 0)]);
|
||||
if (createIndex < vm.layout.length) {
|
||||
vm.setBlockFocus(vm.layout[Math.max(createIndex-1, 0)].$block);
|
||||
}
|
||||
|
||||
editorService.close();
|
||||
@@ -357,7 +371,7 @@
|
||||
var requestCopyAllBlocks = function() {
|
||||
|
||||
// list aliases
|
||||
var aliases = vm.blocks.map(block => block.content.contentTypeAlias);
|
||||
var aliases = vm.layout.map(entry => entry.$block.content.contentTypeAlias);
|
||||
|
||||
// remove dublicates
|
||||
aliases = aliases.filter((item, index) => aliases.indexOf(item) === index);
|
||||
@@ -366,8 +380,9 @@
|
||||
if(vm.umbVariantContent) {
|
||||
contentNodeName = vm.umbVariantContent.editor.content.name;
|
||||
}
|
||||
// TODO: check if we are in an overlay and then lets get the Label of this block.
|
||||
|
||||
var elementTypesToCopy = vm.blocks.map(block => block.content);
|
||||
var elementTypesToCopy = vm.layout.map(entry => entry.$block.content);
|
||||
|
||||
localizationService.localize("clipboard_labelForArrayOfItemsFrom", [vm.model.label, contentNodeName]).then(function(localizedLabel) {
|
||||
clipboardService.copyArray("elementTypeArray", aliases, elementTypesToCopy, localizedLabel, "icon-thumbnail-list", vm.model.id);
|
||||
@@ -392,13 +407,13 @@
|
||||
if (blockObject === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// set the BlockObject on our layout entry.
|
||||
layoutEntry.$block = blockObject;
|
||||
|
||||
// insert layout entry at the decired location in layout.
|
||||
layout.splice(index, 0, layoutEntry);
|
||||
vm.layout.splice(index, 0, layoutEntry);
|
||||
|
||||
// insert block model at the decired location in blocks.
|
||||
vm.blocks.splice(index, 0, blockObject);
|
||||
|
||||
vm.currentBlockInFocus = blockObject;
|
||||
|
||||
return true;
|
||||
@@ -452,11 +467,6 @@
|
||||
openSettingsForBlock: openSettingsForBlock
|
||||
}
|
||||
|
||||
|
||||
|
||||
var runtimeSortVars = {};
|
||||
|
||||
vm.sorting = false;
|
||||
vm.sortableOptions = {
|
||||
axis: "y",
|
||||
cursor: "grabbing",
|
||||
@@ -466,47 +476,25 @@
|
||||
distance: 5,
|
||||
tolerance: "pointer",
|
||||
scroll: true,
|
||||
start: function (ev, ui) {
|
||||
runtimeSortVars.moveFromIndex = ui.item.index();
|
||||
$scope.$evalAsync(function () {
|
||||
vm.sorting = true;
|
||||
});
|
||||
},
|
||||
update: function (ev, ui) {
|
||||
setDirty();
|
||||
},
|
||||
stop: function (ev, ui) {
|
||||
|
||||
// Lets update the layout part of the property model to match the update.
|
||||
var moveFromIndex = runtimeSortVars.moveFromIndex;
|
||||
var moveToIndex = ui.item.index();
|
||||
|
||||
if (moveToIndex !== -1 && moveFromIndex !== moveToIndex) {
|
||||
var movedEntry = layout[moveFromIndex];
|
||||
layout.splice(moveFromIndex, 1);
|
||||
layout.splice(moveToIndex, 0, movedEntry);
|
||||
}
|
||||
|
||||
$scope.$evalAsync(function () {
|
||||
vm.sorting = false;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function onAmountOfBlocksChanged() {
|
||||
|
||||
// enable/disable property actions
|
||||
copyAllBlocksAction.isDisabled = vm.blocks.length === 0;
|
||||
deleteAllBlocksAction.isDisabled = vm.blocks.length === 0;
|
||||
copyAllBlocksAction.isDisabled = vm.layout.length === 0;
|
||||
deleteAllBlocksAction.isDisabled = vm.layout.length === 0;
|
||||
|
||||
// validate limits:
|
||||
if (vm.propertyForm) {
|
||||
|
||||
var isMinRequirementGood = vm.validationLimit.min === null || vm.blocks.length >= vm.validationLimit.min;
|
||||
var isMinRequirementGood = vm.validationLimit.min === null || vm.layout.length >= vm.validationLimit.min;
|
||||
vm.propertyForm.minCount.$setValidity("minCount", isMinRequirementGood);
|
||||
|
||||
var isMaxRequirementGood = vm.validationLimit.max === null || vm.blocks.length <= vm.validationLimit.max;
|
||||
var isMaxRequirementGood = vm.validationLimit.max === null || vm.layout.length <= vm.validationLimit.max;
|
||||
vm.propertyForm.maxCount.$setValidity("maxCount", isMaxRequirementGood);
|
||||
|
||||
}
|
||||
@@ -515,7 +503,7 @@
|
||||
|
||||
|
||||
|
||||
unsubscribe.push($scope.$watch(() => vm.blocks.length, onAmountOfBlocksChanged));
|
||||
unsubscribe.push($scope.$watch(() => vm.layout.length, onAmountOfBlocksChanged));
|
||||
|
||||
$scope.$on("$destroy", function () {
|
||||
for (const subscription of unsubscribe) {
|
||||
|
||||
Reference in New Issue
Block a user