BlockList PropertyEditor
This commit is contained in:
@@ -195,6 +195,10 @@
|
||||
@import "components/contextdialogs/umb-dialog-datatype-delete.less";
|
||||
|
||||
|
||||
// Property Editors
|
||||
@import "../views/propertyeditors/blocklist/blocklist.component.less";
|
||||
|
||||
|
||||
// Utilities
|
||||
@import "utilities/layout/_display.less";
|
||||
@import "utilities/theme/_opacity.less";
|
||||
@@ -218,6 +222,11 @@
|
||||
// Used for prevalue editors
|
||||
@import "components/prevalues/multivalues.less";
|
||||
|
||||
// Block Elements
|
||||
@import "../views/blockelements/labelblock/labelblock.editor.less";
|
||||
@import "../views/blockelements/textareablock/textareablock.editor.less";
|
||||
@import "../views/blockelements/imageblock/imageblock.editor.less";
|
||||
|
||||
// Dashboards
|
||||
@import "dashboards/getstarted.less";
|
||||
@import "dashboards/umbraco-forms.less";
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<button type="button" class="btn-reset umb-outline blockelement-imageblock-editor" focus-when="{{moveFocusToBlock === block}}" ng-click="vm.editBlock(block)">
|
||||
<img src="{{block.content.temp_image}}">
|
||||
</button>
|
||||
@@ -0,0 +1,12 @@
|
||||
.blockelement-imageblock-editor {
|
||||
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
border: none;
|
||||
resize: none;
|
||||
border-radius: @baseBorderRadius;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +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.elementType.icon}}"></i>
|
||||
<span>{{vm.getBlockLabel(block)}}</span>
|
||||
</button>
|
||||
@@ -0,0 +1,34 @@
|
||||
.blockelement-labelblock-editor {
|
||||
|
||||
width: 100%;
|
||||
min-height: 48px;
|
||||
border: 1px solid @gray-9;
|
||||
border-radius: @baseBorderRadius;
|
||||
|
||||
color: @ui-action-discreet-type;
|
||||
|
||||
text-align: left;
|
||||
padding-left: 20px;
|
||||
padding-bottom: 2px;
|
||||
margin-bottom: 2px;
|
||||
margin-top: 2px;
|
||||
|
||||
user-select: none;
|
||||
|
||||
transition: border-color 120ms;
|
||||
|
||||
i {
|
||||
font-size: 22px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
span {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: @ui-action-discreet-type-hover;
|
||||
border-color: @gray-8;
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
//used for the media picker dialog
|
||||
angular.module("umbraco")
|
||||
.controller("Umbraco.Editors.TextAreaBlockElementEditorController",
|
||||
function ($scope) {
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.firstProperty = $scope.block.content.tabs[0].properties[0];
|
||||
/*
|
||||
vm.submitOnEnter = function($event) {
|
||||
if($event && $event.keyCode === 13 && !$event.shiftKey && !$event.ctrlKey) {
|
||||
var target = $event.target;
|
||||
if(target.selectionStart === target.selectionEnd && target.selectionEnd === target.textLength) {
|
||||
//&& (target.textLength === 0 || /\r|\n/.test(target.value.charAt(target.textLength - 1)))
|
||||
$scope.$emit("showFocusOutline");
|
||||
$scope.blockApi.showCreateOptionsFor($scope.block, $event);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
vm.onBlur = function() {
|
||||
if (vm.firstProperty.value === null || vm.firstProperty.value === "") {
|
||||
$scope.blockApi.deleteBlock($scope.block);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
);
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
|
||||
<div class="blockelement-textareablock-editor" ng-controller="Umbraco.Editors.TextAreaBlockElementEditorController as vm">
|
||||
|
||||
<!-- TODO: Each block should be wrapper in a Block Element Editor directive, handling validation messages etc. -->
|
||||
|
||||
<textarea
|
||||
umb-auto-resize
|
||||
ng-model="vm.firstProperty.value"
|
||||
ng-keypress="vm.submitOnEnter($event)"
|
||||
ng-blur="vm.onBlur()"
|
||||
focus-when="{{moveFocusToBlock === block}}"
|
||||
>
|
||||
</textarea>
|
||||
|
||||
</div>
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
.blockelement-textareablock-editor {
|
||||
|
||||
width: 100%;
|
||||
padding-bottom: 24px;
|
||||
padding-top: 24px;
|
||||
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
|
||||
min-height: 64px;
|
||||
box-sizing: border-box;
|
||||
|
||||
textarea {
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: 640px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border: none;
|
||||
resize: none;
|
||||
overflow: auto;
|
||||
|
||||
font-size: 18px;
|
||||
font-family: Georgia,Cambria,"Times New Roman",Times,serif;
|
||||
line-height: 1.25;
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
//used for the media picker dialog
|
||||
angular.module("umbraco")
|
||||
.controller("Umbraco.Editors.ElementEditorController",
|
||||
function ($scope) {
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.content = $scope.model.block.content;
|
||||
|
||||
vm.saveAndClose = function() {
|
||||
if ($scope.model && $scope.model.submit) {
|
||||
$scope.model.submit($scope.model);
|
||||
}
|
||||
}
|
||||
|
||||
vm.close = function() {
|
||||
if ($scope.model && $scope.model.close) {
|
||||
$scope.model.close($scope.model);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
);
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
<div class="umb-element-editor" ng-controller="Umbraco.Editors.ElementEditorController as vm">
|
||||
|
||||
<ng-form name="elementTypeForm" val-form-manager>
|
||||
<umb-editor-view ng-if="!page.loading">
|
||||
|
||||
<!-- editor header missing -->
|
||||
|
||||
<div class="umb-editor-container umb-panel-body umb-scrollable row-fluid">
|
||||
|
||||
<!-- Missing Deleted Message Bar (Displayed when viewing node in recycle bin) -->
|
||||
|
||||
<div class="umb-pane">
|
||||
|
||||
<div class="umb-editor-sub-views" val-sub-view>
|
||||
<div class="form-horizontal">
|
||||
<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">
|
||||
|
||||
<div class="umb-group-panel__header">
|
||||
<div id="group-{{group.id}}">{{ group.label }}</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-group-panel__content">
|
||||
<umb-property
|
||||
data-element="property-{{property.alias}}"
|
||||
ng-repeat="property in group.properties track by property.alias"
|
||||
property="property"
|
||||
show-inherit="content.variants.length > 1 && !property.culture && !activeVariant.language.isDefault"
|
||||
inherits-from="defaultVariant.language.name">
|
||||
|
||||
<div ng-class="{'o-40 cursor-not-allowed': content.variants.length > 1 && !activeVariant.language.isDefault && !property.culture && !property.unlockInvariantValue}">
|
||||
<umb-property-editor
|
||||
model="property"
|
||||
preview="content.variants.length > 1 && !activeVariant.language.isDefault && !property.culture && !property.unlockInvariantValue">
|
||||
</umb-property-editor>
|
||||
</div>
|
||||
|
||||
</umb-property>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<umb-empty-state
|
||||
ng-if="content.tabs.length === 0"
|
||||
position="center">
|
||||
<localize key="content_noProperties"></localize>
|
||||
</umb-empty-state>
|
||||
|
||||
</ng-form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<umb-editor-footer>
|
||||
|
||||
<!-- Missing breadcrumbs -->
|
||||
|
||||
<umb-editor-footer-content-right>
|
||||
|
||||
<umb-button
|
||||
action="vm.close()"
|
||||
button-style="link"
|
||||
label-key="general_close"
|
||||
type="button">
|
||||
</umb-button>
|
||||
|
||||
<umb-button
|
||||
action="vm.saveAndClose()"
|
||||
button-style="primary"
|
||||
state="saveAndCloseButtonState"
|
||||
label-key="buttons_saveAndClose"
|
||||
type="button">
|
||||
</umb-button>
|
||||
|
||||
</umb-editor-footer-content-right>
|
||||
|
||||
</umb-editor-footer>
|
||||
</umb-editor-view>
|
||||
</ng-form>
|
||||
</div>
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
<div class="umb-block-list">
|
||||
|
||||
|
||||
<div class="umb-block-list__wrapper">
|
||||
|
||||
<div ui-sortable="vm.sortableOptions" ng-model="vm.blocks">
|
||||
|
||||
<div ng-repeat="block 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 --delete" localize="title" title="general_delete" ng-click="vm.requestDeleteBlock(block); $event.stopPropagation();">
|
||||
<i class="icon icon-trash" aria-hidden="true"></i>
|
||||
<span class="sr-only">
|
||||
<localize key="general_delete">Delete</localize>
|
||||
</span>
|
||||
</button>
|
||||
<button type="button" class="btn-reset action --copy" localize="title" title="general_copy" ng-click="vm.requestCopyBlock(block, $event);" 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>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</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"
|
||||
ng-class="{ '--disabled': vm.availableBlockTypes.length === 0 }"
|
||||
ng-click="vm.showCreateDialog(vm.blocks.length, $event)"
|
||||
>
|
||||
<localize key="grid_addElement"></localize>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
<umb-overlay
|
||||
ng-if="vm.blockTypePicker.show"
|
||||
position="target"
|
||||
size="vm.blockTypePicker.size"
|
||||
view="vm.blockTypePicker.view"
|
||||
model="vm.blockTypePicker">
|
||||
</umb-overlay>
|
||||
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,553 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('umbraco')
|
||||
.component('blockListPropertyEditor', {
|
||||
templateUrl: 'views/propertyeditors/blocklist/blocklist.component.html',
|
||||
controller: BlockListController,
|
||||
controllerAs: 'vm',
|
||||
bindings: {
|
||||
|
||||
},
|
||||
require: {
|
||||
umbProperty: '?^umbProperty',
|
||||
propertyForm: '?^propertyForm'
|
||||
}
|
||||
});
|
||||
|
||||
function BlockListController($scope, $interpolate, editorService, clipboardService, localizationService, overlayService) {
|
||||
|
||||
var vm = this;
|
||||
var model = $scope.$parent.$parent.model;
|
||||
|
||||
$scope.moveFocusToBlock = null;
|
||||
|
||||
vm.quickMenuVisible = false;
|
||||
vm.quickMenuIndex = 0;
|
||||
|
||||
vm.quickMenuAddNewBlock = function(type) {
|
||||
addNewBlock(vm.quickMenuIndex, type);
|
||||
vm.quickMenuVisible = false;
|
||||
}
|
||||
|
||||
vm.availableBlockTypes = [
|
||||
{
|
||||
alias: "pageModule",
|
||||
name: "Module",
|
||||
icon: "icon-document",
|
||||
prototype_paste_data: {
|
||||
|
||||
elementType: {
|
||||
alias: 'contentTypeAlias',
|
||||
icon: "icon-document",
|
||||
label: "Text"
|
||||
},
|
||||
label: "{{pageTitle | truncate:true:36}}",
|
||||
labelInterpolate: $interpolate("{{pageTitle | truncate:true:36}}"),
|
||||
editor: "views/blockelements/labelblock/labelblock.editor.html",
|
||||
content: {
|
||||
variants: [
|
||||
{
|
||||
language: {
|
||||
isDefault: true
|
||||
}
|
||||
}
|
||||
],
|
||||
tabs: [
|
||||
{
|
||||
id: 1234,
|
||||
label: "Group 1",
|
||||
properties: [
|
||||
{
|
||||
label: "Page Title",
|
||||
description: "The title of the page",
|
||||
view: "textbox",
|
||||
config: {maxChars: 500},
|
||||
hideLabel: false,
|
||||
validation: {mandatory: true, mandatoryMessage: "", pattern: null, patternMessage: ""},
|
||||
readonly: false,
|
||||
id: 441,
|
||||
dataTypeKey: "0cc0eba1-9960-42c9-bf9b-60e150b429ae",
|
||||
value: "Consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
|
||||
alias: "pageTitle",
|
||||
editor: "Umbraco.TextBox",
|
||||
isSensitive: false,
|
||||
culture: null,
|
||||
segment: null
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
alias: "contentTypeAlias",
|
||||
name: "contentTypeName",
|
||||
icon: "icon-text",
|
||||
prototype_paste_data: {
|
||||
elementType: {
|
||||
alias: 'contentTypeAlias',
|
||||
icon: "icon-document",
|
||||
label: "Text"
|
||||
},
|
||||
label: "Label",
|
||||
editor: "views/blockelements/textareablock/textareablock.editor.html",
|
||||
content: {
|
||||
variants: [
|
||||
{
|
||||
language: {
|
||||
isDefault: true
|
||||
}
|
||||
}
|
||||
],
|
||||
tabs: [
|
||||
{
|
||||
id: 1234,
|
||||
label: "Group 1",
|
||||
properties: [
|
||||
{
|
||||
label: "Page Title",
|
||||
description: "The title of the page",
|
||||
view: "textbox",
|
||||
config: {maxChars: 500},
|
||||
hideLabel: false,
|
||||
validation: {mandatory: true, mandatoryMessage: "", pattern: null, patternMessage: ""},
|
||||
readonly: false,
|
||||
id: 441,
|
||||
dataTypeKey: "0cc0eba1-9960-42c9-bf9b-60e150b429ae",
|
||||
value: "",
|
||||
alias: "pageTitle",
|
||||
editor: "Umbraco.TextBox",
|
||||
isSensitive: false,
|
||||
culture: null,
|
||||
segment: null
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
alias: "contentTypeAlias",
|
||||
name: "contentTypeName",
|
||||
icon: "icon-picture",
|
||||
prototype_paste_data: {
|
||||
elementType: {
|
||||
alias: 'contentTypeAlias',
|
||||
icon: "icon-document",
|
||||
label: "Text"
|
||||
},
|
||||
label: "Label",
|
||||
editor: "views/blockelements/imageblock/imageblock.editor.html",
|
||||
content: {
|
||||
variants: [
|
||||
{
|
||||
language: {
|
||||
isDefault: true
|
||||
}
|
||||
}
|
||||
],
|
||||
tabs: [
|
||||
{
|
||||
id: 1234,
|
||||
label: "Group 1",
|
||||
properties: [
|
||||
{
|
||||
label: "Page Title",
|
||||
description: "The title of the page",
|
||||
view: "textbox",
|
||||
config: {maxChars: 500},
|
||||
hideLabel: false,
|
||||
validation: {mandatory: true, mandatoryMessage: "", pattern: null, patternMessage: ""},
|
||||
readonly: false,
|
||||
id: 441,
|
||||
dataTypeKey: "0cc0eba1-9960-42c9-bf9b-60e150b429ae",
|
||||
value: "Let's have a chat",
|
||||
alias: "pageTitle",
|
||||
editor: "Umbraco.TextBox",
|
||||
isSensitive: false,
|
||||
culture: null,
|
||||
segment: null
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
temp_image: "/umbraco/assets/img/login.jpg"
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
// var defaultBlockType...
|
||||
|
||||
// TODO: get icon, properties etc. from available types?
|
||||
vm.blocks = [
|
||||
{
|
||||
elementType: {
|
||||
alias: 'contentTypeAlias',
|
||||
icon: "icon-document",
|
||||
label: "Text"
|
||||
},
|
||||
label: "{{pageTitle | truncate:true:36}}",
|
||||
labelInterpolate: $interpolate("{{pageTitle | truncate:true:36}}"),
|
||||
key: 1,
|
||||
editor: "views/blockelements/labelblock/labelblock.editor.html",
|
||||
content: {
|
||||
variants: [
|
||||
{
|
||||
language: {
|
||||
isDefault: true
|
||||
}
|
||||
}
|
||||
],
|
||||
tabs: [
|
||||
{
|
||||
id: 1234,
|
||||
label: "Group 1",
|
||||
properties: [
|
||||
{
|
||||
label: "Page Title",
|
||||
description: "The title of the page",
|
||||
view: "textbox",
|
||||
config: {maxChars: 500},
|
||||
hideLabel: false,
|
||||
validation: {mandatory: true, mandatoryMessage: "", pattern: null, patternMessage: ""},
|
||||
readonly: false,
|
||||
id: 441,
|
||||
dataTypeKey: "0cc0eba1-9960-42c9-bf9b-60e150b429ae",
|
||||
value: "The purpose of lorem ipsum is to create a natural looking block of text (sentence, paragraph, page, etc.) that doesn't distract from the layout. A practice not without controversy, laying out pages with meaningless filler text can be very useful when the focus is meant to be on design, not content.",
|
||||
alias: "pageTitle",
|
||||
editor: "Umbraco.TextBox",
|
||||
isSensitive: false,
|
||||
culture: null,
|
||||
segment: null
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
elementType: {
|
||||
alias: 'contentTypeAlias',
|
||||
icon: "icon-document",
|
||||
label: "Text"
|
||||
},
|
||||
label: "{{pageTitle | truncate:true:36}}",
|
||||
labelInterpolate: $interpolate("{{pageTitle | truncate:true:36}}"),
|
||||
key: 2,
|
||||
editor: "views/blockelements/labelblock/labelblock.editor.html",
|
||||
content: {
|
||||
variants: [
|
||||
{
|
||||
language: {
|
||||
isDefault: true
|
||||
}
|
||||
}
|
||||
],
|
||||
tabs: [
|
||||
{
|
||||
id: 1234,
|
||||
label: "Group 1",
|
||||
properties: [
|
||||
{
|
||||
label: "Page Title",
|
||||
description: "The title of the page",
|
||||
view: "textbox",
|
||||
config: {maxChars: 500},
|
||||
hideLabel: false,
|
||||
validation: {mandatory: true, mandatoryMessage: "", pattern: null, patternMessage: ""},
|
||||
readonly: false,
|
||||
id: 441,
|
||||
dataTypeKey: "0cc0eba1-9960-42c9-bf9b-60e150b429ae",
|
||||
value: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
|
||||
alias: "pageTitle",
|
||||
editor: "Umbraco.TextBox",
|
||||
isSensitive: false,
|
||||
culture: null,
|
||||
segment: null
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
elementType: {
|
||||
alias: 'contentTypeAlias',
|
||||
icon: "icon-document",
|
||||
label: "Text"
|
||||
},
|
||||
label: "{{pageTitle | truncate:true:36}}",
|
||||
labelInterpolate: $interpolate("{{pageTitle | truncate:true:36}}"),
|
||||
key: 3,
|
||||
editor: "views/blockelements/labelblock/labelblock.editor.html",
|
||||
content: {
|
||||
variants: [
|
||||
{
|
||||
language: {
|
||||
isDefault: true
|
||||
}
|
||||
}
|
||||
],
|
||||
tabs: [
|
||||
{
|
||||
id: 1234,
|
||||
label: "Group 1",
|
||||
properties: [
|
||||
{
|
||||
label: "Page Title",
|
||||
description: "The title of the page",
|
||||
view: "textbox",
|
||||
config: {maxChars: 500},
|
||||
hideLabel: false,
|
||||
validation: {mandatory: true, mandatoryMessage: "", pattern: null, patternMessage: ""},
|
||||
readonly: false,
|
||||
id: 441,
|
||||
dataTypeKey: "0cc0eba1-9960-42c9-bf9b-60e150b429ae",
|
||||
value: "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
|
||||
alias: "pageTitle",
|
||||
editor: "Umbraco.TextBox",
|
||||
isSensitive: false,
|
||||
culture: null,
|
||||
segment: null
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
function setDirty() {
|
||||
if (vm.propertyForm) {
|
||||
vm.propertyForm.$setDirty();
|
||||
}
|
||||
};
|
||||
|
||||
function addNewBlock(index, type) {
|
||||
|
||||
var block = angular.copy(type.prototype_paste_data);
|
||||
|
||||
vm.blocks.splice(index, 0, block);
|
||||
$scope.moveFocusToBlock = block;
|
||||
|
||||
}
|
||||
/*
|
||||
function moveFocusToNextBlock(blockModel, $event) {
|
||||
var index = vm.blocks.indexOf(blockModel);
|
||||
if(index < vm.blocks.length) {
|
||||
var nextBlock = vm.blocks[index+1];
|
||||
$scope.moveFocusToBlock = nextBlock;
|
||||
} else {
|
||||
showCreateOptions(blockModel, $event);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
vm.showCreateOptionsFor = function(blockModel, $event) {
|
||||
var index = vm.blocks.indexOf(blockModel);
|
||||
$event.preventDefault();
|
||||
showCreateOptionsAt(index);
|
||||
}
|
||||
function showCreateOptionsAt(index) {
|
||||
vm.quickMenuIndex = index;
|
||||
vm.quickMenuVisible = true;
|
||||
window.addEventListener("keydown", handleTypingInCreateOptions);
|
||||
}
|
||||
|
||||
function handleTypingInCreateOptions(event) {
|
||||
if (event.ctrlKey || event.metaKey || event.altKey)
|
||||
return;
|
||||
|
||||
if (
|
||||
(event.keyCode === 13) // enter
|
||||
||
|
||||
(event.keyCode >= 48 && event.keyCode <= 90)// 0 to z
|
||||
||
|
||||
(event.keyCode >= 96 && event.keyCode <= 111)// numpads
|
||||
||
|
||||
(event.keyCode >= 186 && event.keyCode <= 222)// semi-colon and a lot of other special characters
|
||||
) {
|
||||
// Continue writting... needs to know default text-element. if we have one.
|
||||
}
|
||||
}
|
||||
|
||||
function hideCreateOptions() {
|
||||
vm.quickMenuVisible = false;
|
||||
window.removeEventListener("keydown", handleTypingInCreateOptions);
|
||||
}
|
||||
|
||||
vm.onCreateOptionsBlur = function($event) {
|
||||
|
||||
if(!$($event.relatedTarget).is(".umb-block-list__block--create-bar > button")) {
|
||||
hideCreateOptions();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
vm.getBlockLabel = function(block) {
|
||||
|
||||
var name = "";
|
||||
|
||||
var props = new Object();
|
||||
|
||||
var tab = block.content.tabs[0];
|
||||
// TODO: need to look up all tabs...
|
||||
for(const property of tab.properties) {
|
||||
props[property.alias] = property.value;
|
||||
}
|
||||
|
||||
if(block.labelInterpolate) {
|
||||
return block.labelInterpolate(props);
|
||||
}
|
||||
|
||||
return "block.label";
|
||||
}
|
||||
|
||||
vm.deleteBlock = function(block) {
|
||||
var index = vm.blocks.indexOf(block);
|
||||
if(index !== -1) {
|
||||
vm.blocks.splice(index, 1);
|
||||
}
|
||||
if(vm.quickMenuIndex > index) {
|
||||
vm.quickMenuIndex--;
|
||||
}
|
||||
}
|
||||
|
||||
vm.editBlock = function(blockModel) {
|
||||
|
||||
var elementEditor = {
|
||||
block: blockModel,
|
||||
view: "views/common/infiniteeditors/elementeditor/elementeditor.html",
|
||||
size: "large",
|
||||
submit: function(model) {
|
||||
blockModel.content = model.block.content;
|
||||
editorService.close();
|
||||
},
|
||||
close: function() {
|
||||
editorService.close();
|
||||
}
|
||||
};
|
||||
|
||||
// open property settings editor
|
||||
editorService.open(elementEditor);
|
||||
}
|
||||
|
||||
vm.showCreateDialog = function (createIndex, $event) {
|
||||
|
||||
if (vm.blockTypePicker) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (vm.availableBlockTypes.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
vm.blockTypePicker = {
|
||||
show: true,
|
||||
size: vm.availableBlockTypes.length > 6 ? "medium" : "small",
|
||||
filter: vm.availableBlockTypes.length > 12 ? true : false,
|
||||
orderBy: "$index",
|
||||
view: "itempicker",
|
||||
event: $event,
|
||||
availableItems: vm.availableBlockTypes,
|
||||
submit: function (model) {
|
||||
if (model && model.selectedItem) {
|
||||
addNewBlock(createIndex, model.selectedItem);
|
||||
}
|
||||
vm.blockTypePicker.close();
|
||||
},
|
||||
close: function () {
|
||||
vm.blockTypePicker.show = false;
|
||||
vm.blockTypePicker = null;
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
vm.requestCopyBlock = function(block) {
|
||||
console.log("copy")
|
||||
}
|
||||
vm.requestDeleteBlock = function(block) {
|
||||
localizationService.localizeMany(["content_nestedContentDeleteItem", "general_delete", "general_cancel", "contentTypeEditor_yesDelete"]).then(function (data) {
|
||||
const overlay = {
|
||||
title: data[1],
|
||||
content: data[0],
|
||||
closeButtonLabel: data[2],
|
||||
submitButtonLabel: data[3],
|
||||
submitButtonStyle: "danger",
|
||||
close: function () {
|
||||
overlayService.close();
|
||||
},
|
||||
submit: function () {
|
||||
vm.deleteBlock(block);
|
||||
overlayService.close();
|
||||
}
|
||||
};
|
||||
|
||||
overlayService.open(overlay);
|
||||
});
|
||||
}
|
||||
|
||||
vm.showCopy = clipboardService.isSupported();
|
||||
|
||||
|
||||
|
||||
vm.sorting = false;
|
||||
vm.sortableOptions = {
|
||||
axis: "y",
|
||||
cursor: "grabbing",
|
||||
handle: '.umb-block-list__block',
|
||||
cancel: 'input,textarea,select,option',
|
||||
classes: '.blockelement--dragging',
|
||||
distance: 5,
|
||||
tolerance: "pointer",
|
||||
scroll: true,
|
||||
start: function (ev, ui) {
|
||||
$scope.$apply(function () {
|
||||
vm.sorting = true;
|
||||
});
|
||||
},
|
||||
update: function (ev, ui) {
|
||||
setDirty();
|
||||
},
|
||||
stop: function (ev, ui) {
|
||||
$scope.$apply(function () {
|
||||
vm.sorting = false;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.blockApi = {
|
||||
showCreateOptionsFor: vm.showCreateOptionsFor,
|
||||
removeBlock: vm.removeBlock
|
||||
}
|
||||
|
||||
|
||||
var copyAllEntriesAction = {
|
||||
labelKey: 'clipboard_labelForCopyAllEntries',
|
||||
labelTokens: [model.label],
|
||||
icon: 'documents',
|
||||
method: function () {},
|
||||
isDisabled: true
|
||||
}
|
||||
|
||||
var propertyActions = [
|
||||
copyAllEntriesAction
|
||||
];
|
||||
|
||||
this.$onInit = function () {
|
||||
if (this.umbProperty) {
|
||||
this.umbProperty.setPropertyActions(propertyActions);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
})();
|
||||
+217
@@ -0,0 +1,217 @@
|
||||
@umb-block-list__item_minimum_height: 48px;
|
||||
|
||||
.umb-block-list {
|
||||
padding-bottom:10px;
|
||||
}
|
||||
|
||||
.umb-block-list__wrapper {
|
||||
position: relative;
|
||||
max-width: 1024px;
|
||||
> .ui-sortable > .ui-sortable-helper > .umb-block-list__block > .umb-block-list__block--content > * {
|
||||
box-shadow: 0px 5px 10px 0 rgba(0,0,0,.2);
|
||||
}
|
||||
}
|
||||
|
||||
.umb-block-list__block {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
cursor: grab;
|
||||
|
||||
.umb-block-list__block--head {
|
||||
opacity: 0;
|
||||
transition: opacity 120ms;
|
||||
}
|
||||
.umb-block-list__block--actions {
|
||||
opacity: 0;
|
||||
transition: opacity 120ms;
|
||||
}
|
||||
|
||||
&:hover, &:focus, &:focus-within {
|
||||
.umb-block-list__block--head {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.umb-block-list__block--actions {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&:focus, &:focus-within {
|
||||
.umb-block-list__block--head {
|
||||
&::before {
|
||||
background-color: @blueMid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.umb-block-list__block--head {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -180px;// 160px from control-header + 20px from spacing.
|
||||
bottom: 0;
|
||||
width: 180px;// 160px from control-header + 20px from spacing.
|
||||
user-select: none;
|
||||
padding-top: 6px;
|
||||
padding-right: 14px;
|
||||
box-sizing: border-box;
|
||||
color: @gray-5;
|
||||
background-color: rgba(255, 255, 255, .96);
|
||||
box-shadow: 0 0 6px 6px rgba(255, 255, 255, .96);
|
||||
text-align: right;
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
bottom: 6px;
|
||||
right: 4px;
|
||||
width: 1px;
|
||||
background-color: @gray-10;
|
||||
}
|
||||
|
||||
small {
|
||||
text-align: left;
|
||||
margin-left: 4px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
}
|
||||
label.umb-block-list__block--head {
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.umb-block-list__block--actions {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
font-size: 0;
|
||||
background-color: rgba(255, 255, 255, .96);
|
||||
border-radius: 14px;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
.action {
|
||||
display: inline-block;
|
||||
color: @ui-action-discreet-type;
|
||||
font-size: 18px;
|
||||
padding: 5px;
|
||||
&:hover {
|
||||
color: @ui-action-discreet-type-hover;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.umb-block-list__block--content {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
min-height: @umb-block-list__item_minimum_height;
|
||||
background-color: @white;
|
||||
border-radius: @baseBorderRadius;
|
||||
}
|
||||
|
||||
|
||||
.umb-block-list__block--create-button {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
z-index:1;
|
||||
opacity: 0;
|
||||
outline: none;
|
||||
height: 20px;
|
||||
margin-top: -10px;
|
||||
padding-top: 10px;
|
||||
margin-bottom: -10px;
|
||||
transition: opacity 240ms;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
background-color: @ui-outline;
|
||||
border-radius: 2px;
|
||||
top:9px;
|
||||
right: 0;
|
||||
left: 0;
|
||||
height: 2px;
|
||||
animation: umb-block-list__block--create-button 800ms ease-in-out infinite;
|
||||
@keyframes umb-block-list__block--create-button {
|
||||
0% { opacity: 0.5; }
|
||||
50% { opacity: 1; }
|
||||
100% { opacity: 0.5; }
|
||||
}
|
||||
}
|
||||
&::after {
|
||||
content: "+";
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-top: -16px;
|
||||
width: 28px;
|
||||
height: 25px;
|
||||
padding-bottom: 3px;
|
||||
border-radius: 3em;
|
||||
border: 2px solid @ui-outline;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: @ui-outline;
|
||||
font-size: 20px;
|
||||
font-weight: 800;
|
||||
background-color: rgba(255, 255, 255, .96);
|
||||
box-shadow: 0 0 0 2px rgba(255, 255, 255, .96);
|
||||
transform: scale(0);
|
||||
transition: transform 240ms ease-in;
|
||||
}
|
||||
&:focus {
|
||||
&::after {
|
||||
border: 2px solid @ui-outline;
|
||||
}
|
||||
}
|
||||
&:hover, &:focus {
|
||||
opacity: 1;
|
||||
transition-duration: 120ms;
|
||||
&::after {
|
||||
transform: scale(1);
|
||||
transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
.umb-block-list__block--create-bar {
|
||||
button {
|
||||
display: inline-block;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
border-radius: @baseBorderRadius;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
i {
|
||||
font-size: 30px;
|
||||
line-height: 20px;
|
||||
margin-bottom: 10px;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
.umb-block-list__create-button {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px dashed @ui-action-discreet-border;
|
||||
color: @ui-action-discreet-type;
|
||||
font-weight: bold;
|
||||
margin: 2px 0;
|
||||
padding: 5px 15px;
|
||||
box-sizing: border-box;
|
||||
border-radius: @baseBorderRadius;
|
||||
}
|
||||
|
||||
.umb-block-list__create-button:hover {
|
||||
color: @ui-action-discreet-type-hover;
|
||||
border-color: @ui-action-discreet-border-hover;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.umb-block-list__create-button.--disabled,
|
||||
.umb-block-list__create-button.--disabled:hover {
|
||||
color: @gray-7;
|
||||
border-color: @gray-7;
|
||||
cursor: default;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<block-list-property-editor></block-list-property-editor>
|
||||
Reference in New Issue
Block a user