init doc type with tabs prototype

This commit is contained in:
Mads Rasmussen
2021-02-24 14:25:03 +01:00
parent 3e7f912fcd
commit 2470ee96ec
14 changed files with 670 additions and 11 deletions

View File

@@ -8,7 +8,7 @@
},
"parserOptions": {
"ecmaVersion": 6
"ecmaVersion": 2018
},
"globals": {

View File

@@ -0,0 +1,36 @@
(function () {
'use strict';
/**
* A component to render the content type group
*/
function umbContentTypeGroupController() {
const vm = this;
vm.updateName = updateName;
function updateName (group) {
if (vm.onUpdateName) {
vm.onUpdateName({ group });
}
}
}
const umbContentTypeGroupComponent = {
templateUrl: 'views/components/contenttype/umb-content-type-group.html',
controllerAs: 'vm',
transclude: true,
bindings: {
group: "<",
allowName: "<",
onUpdateName: "&"
},
controller: umbContentTypeGroupController
};
angular.module('umbraco.directives').component('umbContentTypeGroup', umbContentTypeGroupComponent);
})();

View File

@@ -0,0 +1,33 @@
(function () {
'use strict';
/**
* A component to render the content type group placeholder
*/
function umbContentTypeGroupPlaceholderController() {
const vm = this;
vm.click = click;
function click () {
if (vm.onClick) {
vm.onClick();
}
}
}
const umbContentTypeGroupPlaceholderComponent = {
templateUrl: 'views/components/contenttype/umb-content-type-group-placeholder.html',
controllerAs: 'vm',
bindings: {
onClick: '&'
},
controller: umbContentTypeGroupPlaceholderController
};
angular.module('umbraco.directives').component('umbContentTypeGroupPlaceholder', umbContentTypeGroupPlaceholderComponent);
})();

View File

@@ -0,0 +1,23 @@
(function () {
'use strict';
/**
* A component to render the content type groups
*/
function umbContentTypeGroupsController() {
const vm = this;
}
const umbContentTypeGroupsComponent = {
templateUrl: 'views/components/contenttype/umb-content-type-groups.html',
controllerAs: 'vm',
transclude: true,
controller: umbContentTypeGroupsController
};
angular.module('umbraco.directives').component('umbContentTypeGroups', umbContentTypeGroupsComponent);
})();

View File

@@ -0,0 +1,28 @@
(function () {
'use strict';
/**
* A component to render the content type property
*/
function umbContentTypePropertyController() {
const vm = this;
}
const umbContentTypePropertyComponent = {
templateUrl: 'views/components/contenttype/umb-content-type-property.html',
bindings: {
property: "<",
compact: "<"
},
controllerAs: 'vm',
controller: umbContentTypePropertyController
};
angular.module('umbraco.directives').component('umbContentTypeProperty', umbContentTypePropertyComponent);
})();

View File

@@ -0,0 +1,33 @@
(function () {
'use strict';
/**
* A component to render the content type property
*/
function umbContentTypePropertyPlaceholderController() {
const vm = this;
vm.click = click;
function click ($event) {
if (vm.onClick) {
vm.onClick({$event})
}
}
}
const umbContentTypePropertyPlaceholderComponent = {
templateUrl: 'views/components/contenttype/umb-content-type-property-placeholder.html',
bindings: {
onClick: "&"
},
controllerAs: 'vm',
controller: umbContentTypePropertyPlaceholderController
};
angular.module('umbraco.directives').component('umbContentTypePropertyPlaceholder', umbContentTypePropertyPlaceholderComponent);
})();

View File

@@ -387,6 +387,81 @@
};
/* ---------- TABS ---------- */
scope.model.hasTabs = true;
scope.openTabIndex = 0;
scope.changeTab = function (index) {
scope.openTabIndex = index;
};
scope.addTab = function (tab) {
scope.addGroup(tab);
scope.openTabIndex = scope.model.groups.length - 2;
};
scope.addFieldset = function () {
const activeTab = scope.model.groups[scope.openTabIndex];
if (!activeTab) {
return
}
if (!scope.model.fieldsets) {
scope.model.fieldsets = [];
}
const fieldset = {
groupId: activeTab.id,
id: scope.model.fieldsets.length + 1, // temp id
name: ""
};
scope.model.fieldsets = [...scope.model.fieldsets, fieldset];
};
scope.addNewProperty = function (group, fieldset) {
let newProperty = {
label: null,
alias: null,
propertyState: "init",
validation: {
mandatory: false,
mandatoryMessage: null,
pattern: null,
patternMessage: null
},
labelOnTop: false
};
const propertySettings = {
title: "Property settings",
property: newProperty,
contentType: scope.contentType,
contentTypeName: scope.model.name,
contentTypeAllowCultureVariant: scope.model.allowCultureVariant,
contentTypeAllowSegmentVariant: scope.model.allowSegmentVariant,
view: "views/common/infiniteeditors/propertysettings/propertysettings.html",
size: "small",
submit: function (model) {
newProperty = {...model.property};
newProperty.fieldsetId = fieldset ? fieldset.id : null;
newProperty.propertyState = "active";
group.properties.push(newProperty);
editorService.close();
},
close: function () {
editorService.close();
}
};
editorService.open(propertySettings);
};
/* ---------- GROUPS ---------- */
scope.addGroup = function (group) {

View File

@@ -1,3 +1,98 @@
/* ---------- TABS ---------- */
.umb-group-builder__tabs {
list-style: none;
margin: 0;
padding: 0;
display: flex;
align-items: center;
background-color: @white;
height: 70px;
border-bottom: 1px solid @gray-9;
margin-bottom: 20px;
li {
height: 100%;
}
}
.umb-group-builder__tab {
position: relative;
padding: 0 50px 0 20px;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
border-right: 1px solid @gray-9;
&:hover {
cursor: pointer;
.umb-group-builder__tab-remove {
display: block;
}
}
&::before {
content: "";
position: absolute;
height: 0px;
left: 10px;
right: 10px;
background-color: @ui-light-active-border;
bottom: 0;
border-radius: @baseBorderRadius @baseBorderRadius 0 0;
opacity: 0;
transition: all .2s linear;
}
&.is-active {
color: @ui-light-active-type !important;
.umb-group-builder__tab-remove {
display: block;
}
&::before {
opacity: 1;
height: 4px;
}
}
&.is-inherited {
.umb-group-builder__group-title-input {
padding: 0;
}
}
}
.umb-group-builder__tab-remove {
position: absolute;
right: 20px;
display: none;
}
.umb-group-builder__tab-name {
font-weight: bold;
}
.umb-group-builder__tab--placeholder {
border: 1px dashed @gray-7;
border-bottom: none;
border-top: none;
padding-right: 20px;
}
.umb-group-builder__tab-inherited-label {
font-size: 12px;
color: @gray-6;
button {
font-size: 12px;
color: @gray-6;
}
}
/* ---------- GROUPS ---------- */
.umb-group-builder__groups {
@@ -14,6 +109,7 @@
background-color: @white;
position: relative;
box-shadow: 0 1px 1px 0 rgba(0,0,0,0.16);
margin-bottom: 20px;
}
.umb-group-builder__group.-inherited {
@@ -137,12 +233,9 @@ input.umb-group-builder__group-title-input:disabled:hover {
}
.umb-group-builder__group-add-property {
width: calc(100% - 315px);
margin-left: 270px;
width: 100%;
min-height: 46px;
border-radius: 3px;
border-radius: @baseBorderRadius;
display: flex;
justify-content: center;
align-items: center;

View File

@@ -0,0 +1,3 @@
<button type="button" class="umb-group-builder__group -placeholder" hotkey="alt+shift+g" ng-click="vm.click()" data-element="group-add">
<localize key="contentTypeEditor_addGroup"></localize>
</button>

View File

@@ -0,0 +1,67 @@
<div class="umb-group-builder__group" ng-class="{'-active':tab.tabState=='active', '-inherited': group.inherited, 'umb-group-builder__group-handle -sortable': sortingMode && !vm.group.inherited}" ng-focus="activateGroup(tab)">
<div class="umb-group-builder__group-title-wrapper" ng-if="vm.allowName">
<ng-form name="groupNameForm" data-element="group-name">
<div class="umb-group-builder__group-title control-group -no-margin" ng-class="{'-active':tab.tabState=='active', '-inherited': tab.inherited}">
<i class="umb-group-builder__group-title-icon icon-navigation" ng-if="sortingMode && !tab.inherited"></i>
<input data-element="group-name-field"
class="umb-group-builder__group-title-input"
type="text"
localize="placeholder"
placeholder="@placeholders_entername"
name="groupName"
ng-model="vm.group.name"
ng-class="{'-placeholder': vm.group.name == ''}"
ng-change="vm.updateName(vm.group)"
ng-disabled="vm.group.inherited"
umb-auto-focus
umb-auto-resize
ng-focus="activateGroup(tab)"
required
val-server-field="{{'Groups[' + $index + '].Name'}}"
data-lpignore="true" />
<div ng-messages="groupNameForm.groupName.$error" show-validation-on-submit>
<div class="umb-validation-label -arrow-left" ng-message="valServerField">{{groupNameForm.groupName.errorMsg}}</div>
<div class="umb-validation-label -arrow-left" ng-message="required"><localize key="required"></localize></div>
</div>
</div>
</ng-form>
<div class="umb-group-builder__group-inherited-label" ng-if="vm.group.inherited">
<i class="icon icon-merge"></i>
<localize key="contentTypeEditor_inheritedFrom"></localize>: {{ vm.group.inheritedFromName }}
<span ng-repeat="contentTypeName in vm.group.parentTabContentTypeNames">
<button type="button" class="btn-link btn-small p0" ng-click="openDocumentType(vm.group.parentTabContentTypes[$index])">{{ contentTypeName }}</button>
<span ng-if="!$last">, </span>
</span>
</div>
<ng-form name="groupSortOrderForm" class="umb-group-builder__group-sort-order">
<div ng-if="sortingMode">
<input name="groupSortOrder" type="number" class="umb-property-editor-tiny" style="margin-bottom: 0;" ng-model="vm.group.sortOrder" ng-disabled="vm.group.inherited" ng-blur="changeSortOrderValue(tab)" required />
<!-- This is a manual validation message not bound to a validator -->
<div class="umb-validation-label -arrow-left" ng-if="groupSortOrderForm.groupSortOrder.$error.required && tab.showSortOrderMissing"><localize key="required"></localize></div>
<div ng-messages="groupSortOrderForm.groupSortOrder.$error" show-validation-on-submit>
<div class="umb-validation-label -arrow-left" ng-message="required"><localize key="required"></localize></div>
</div>
</div>
</ng-form>
<div class="umb-group-builder__group-remove" ng-if="!sortingMode && canRemoveGroup(tab)">
<i class="icon-trash" ng-click="togglePrompt(tab)"></i>
<umb-confirm-action
ng-if="vm.group.deletePrompt"
direction="left"
on-confirm="removeGroup($index)"
on-cancel="hidePrompt(tab)">
</umb-confirm-action>
</div>
</div>
<ng-transclude></ng-transclude>
</div>

View File

@@ -0,0 +1 @@
<div class="umb-group-builder__groups" ng-transclude></div>

View File

@@ -0,0 +1,11 @@
<div>
<button
type="button"
data-element="property-add"
class="umb-group-builder__group-add-property"
ng-click="vm.click($event)"
ng-focus="activateGroup(tab)"
focus-when="{{property.focus}}">
<localize key="contentTypeEditor_addProperty"></localize>
</button>
</div>

View File

@@ -0,0 +1,155 @@
<div class="umb-group-builder__property" ng-class="{'-active': vm.dialogIsOpen, '-active': vm.property.propertyState=='active', '-inherited': vm.property.inherited, '-locked': vm.property.locked, 'umb-group-builder__property-handle -sortable': vm.compact && !vm.property.inherited, '-sortable-locked': vm.compact && vm.property.inherited}">
<!-- property meta text -->
<div class="umb-group-builder__property-meta" ng-class="{'-full-width': vm.compact}">
<ng-form name="propertyTypeForm">
<div class="control-group -no-margin" ng-if="!vm.compact">
<div class="umb-group-builder__property-meta-alias umb-locked-field__text cursor-not-allowed" style="padding-left: 1px" ng-if="vm.property.inherited || vm.property.locked">{{ vm.property.alias }}</div>
<umb-locked-field
ng-if="!vm.property.inherited && !vm.property.locked"
locked="locked"
ng-model="vm.property.alias"
placeholder-text="'Alias...'"
server-validation-field="{{'Groups[' + $parent.$parent.$parent.$parent.$index + '].Properties[' + $index + '].Alias'}}">
</umb-locked-field>
<div class="umb-group-builder__property-meta-label">
<textarea localize="placeholder"
placeholder="@placeholders_label"
ng-model="vm.property.label"
ng-disabled="vm.property.inherited || vm.property.locked"
name="groupName"
umb-auto-resize
required
val-server-field="{{'Groups[' + $parent.$parent.$parent.$parent.$index + '].Properties[' + $index + '].Label'}}">
</textarea>
<div ng-messages="propertyTypeForm.groupName.$error" show-validation-on-submit>
<div class="umb-validation-label" ng-message="valServerField">{{propertyTypeForm.groupName.errorMsg}}</div>
<div class="umb-validation-label" ng-message="required"><localize key="contentTypeEditor_requiredLabel"></localize></div>
</div>
</div>
<div class="umb-group-builder__property-meta-description">
<textarea
localize="placeholder"
placeholder="@placeholders_enterDescription"
ng-model="vm.property.description"
ng-disabled="vm.property.inherited || vm.property.locked"
umb-auto-resize>
</textarea>
</div>
</div>
</ng-form>
<div ng-if="vm.compact" class="flex items-center">
<i class="icon icon-navigation" ng-if="!vm.property.inherited" style="margin-right: 10px;"></i>
<span class="umb-group-builder__property-meta-label">{{ vm.property.label }}</span>
<span class="umb-group-builder__property-meta-alias" style="margin-bottom: 0; margin-left: 5px; margin-top: 1px;">({{ vm.property.alias }})</span>
<input name="propertySortOrder" type="number" class="umb-group-builder__group-sort-value umb-property-editor-tiny" ng-model="vm.property.sortOrder" ng-disabled="vm.property.inherited" />
</div>
</div>
<div tabindex="-1" class="umb-group-builder__property-preview" ng-if="!vm.compact" ng-class="{'-not-clickable': !vm.compact && (vm.property.inherited || vm.property.locked)}">
<div class="umb-group-builder__property-tags">
<span class="umb-group-builder__property-tag -white">
<span ng-if="vm.property.dataTypeName !== undefined">{{vm.property.dataTypeName}}</span>
<span ng-if="vm.property.dataTypeName == undefined"><localize key="general_preview"></localize></span>
</span>
<div class="umb-group-builder__property-tag -white" ng-if="vm.property.validation.mandatory">
<i class="umb-group-builder__property-tag-icon">*</i>
<localize key="general_mandatory"></localize>
</div>
<div class="umb-group-builder__property-tag -white" ng-if="vm.property.showOnMemberProfile">
<i class="icon-eye umb-group-builder__property-tag-icon"></i>
<localize key="contentTypeEditor_showOnMemberProfile"></localize>
</div>
<div class="umb-group-builder__property-tag -white" ng-if="vm.property.memberCanEdit">
<i class="icon-edit umb-group-builder__property-tag-icon"></i>
<localize key="contentTypeEditor_memberCanEdit"></localize>
</div>
<div class="umb-group-builder__property-tag -white" ng-if="vm.property.isSensitiveData">
<i class="icon-lock umb-group-builder__property-tag-icon"></i>
<localize key="contentTypeEditor_isSensitiveData"></localize>
</div>
<div class="umb-group-builder__property-tag -white" ng-if="vm.property.allowCultureVariant">
<i class="icon-shuffle umb-group-builder__property-tag-icon"></i>
<localize key="contentTypeEditor_cultureVariantLabel"></localize>
</div>
<div class="umb-group-builder__property-tag -white" ng-if="vm.property.allowSegmentVariant">
<i class="icon-shuffle umb-group-builder__property-tag-icon"></i>
<localize key="contentTypeEditor_segmentVariantLabel"></localize>
</div>
</div>
<div class="umb-group-builder__property-tags -right">
<div class="umb-group-builder__property-tag" ng-if="vm.property.inherited">
<umb-icon icon="icon-merge" class="icon-merge"></umb-icon>
<span style="margin-right: 3px"><localize key="contentTypeEditor_inheritedFrom"></localize></span>
{{vm.property.contentTypeName}}
</div>
<div class="umb-group-builder__property-tag" ng-if="vm.property.locked">
<umb-icon icon="icon-lock" class="icon-lock"></umb-icon>
<localize key="general_locked"></localize>
</div>
</div>
<ng-form inert class="umb-group-builder__property-preview-form" name="propertyEditorPreviewForm" umb-disable-form-validation ng-click="editPropertyTypeSettings(property, tab)" tabindex="-1">
<umb-property-editor
ng-if="vm.property.view !== undefined"
model="vm.property"
preview="true">
</umb-property-editor>
</ng-form>
<button aria-label="Open settings" class="umb-group-builder__open-settings" ng-if="!vm.property.inherited && !vm.property.locked" ng-click="editPropertyTypeSettings(property, tab)"></button>
</div>
<!-- row tools -->
<div class="umb-group-builder__property-actions" ng-if="!vm.compact">
<div ng-if="!vm.property.inherited">
<!-- settings for property -->
<div class="umb-group-builder__property-action">
<button aria-label="Open settings" class="btn-icon" ng-click="editPropertyTypeSettings(property, tab)" localize="title" title="@general_edit">
<umb-icon icon="icon-settings" class="icon-settings"></umb-icon>
</button>
</div>
<!-- delete property -->
<div ng-if="!vm.property.locked" class="umb-group-builder__property-action">
<button aria-label="Delete property" class="btn-icon" ng-click="togglePrompt(property)">
<umb-icon icon="icon-trash" class="icon-trash"></umb-icon>
</button>
<umb-confirm-action
ng-if="vm.property.deletePrompt"
direction="left"
on-confirm="deleteProperty(tab, $index)"
on-cancel="hidePrompt(property)">
</umb-confirm-action>
</div>
</div>
</div>
</div>

View File

@@ -4,6 +4,11 @@
<umb-editor-sub-header-content-right>
<div class="flex items-center">
<div>Use Tabs</div>
<input type="checkbox" ng-model="model.hasTabs" />
</div>
<umb-button
style="margin-right: 5px;"
alias="compositions"
@@ -39,16 +44,114 @@
<a ng-if="!sortingMode" hotkey="alt+shift+p" ng-click="addPropertyToActiveGroup()"></a>
<ul class="umb-group-builder__groups" ui-sortable="sortableOptionsGroup" ng-model="model.groups">
<!-- WITH TABS --->
<div ng-if="model.hasTabs">
<ul class="umb-group-builder__tabs">
<li ng-repeat="tab in model.groups">
<div ng-if="tab.tabState !== 'init'" ng-click="changeTab($index)" class="umb-group-builder__tab" ng-class="{'is-active': $index === openTabIndex, 'is-inherited': tab.inherited}">
<div>
<div class="umb-group-builder__tab-inherited-label" ng-if="tab.inherited">
<localize key="contentTypeEditor_inheritedFrom"></localize>: {{ tab.inheritedFromName }}
<span ng-repeat="contentTypeName in tab.parentTabContentTypeNames">
<button type="button" class="btn-link btn-small p0" ng-click="openDocumentType(tab.parentTabContentTypes[$index])">{{ contentTypeName }}</button>
<span ng-if="!$last">, </span>
</span>
</div>
<div class="umb-group-builder__tab-name" ng-if="tab.inherited">{{ tab.name }}</div>
<input
ng-if="!tab.inherited"
class="umb-group-builder__group-title-input"
data-element="group-name-field"
type="text"
localize="placeholder"
placeholder="@placeholders_entername"
name="groupName"
ng-model="tab.name"
ng-class="{'-placeholder': tab.name == ''}"
ng-change="updateGroupTitle(tab)"
ng-disabled="tab.inherited"
umb-auto-focus
umb-auto-resize
ng-focus="activateGroup(tab)"
required
val-server-field="{{'Groups[' + $index + '].Name'}}"
data-lpignore="true" />
</div>
<div class="umb-group-builder__tab-remove" ng-if="!sortingMode && canRemoveGroup(tab)">
<button type="button" class="btn-reset" ng-click="togglePrompt(tab)">
<i class="icon-trash"></i>
</button>
<umb-confirm-action
ng-if="tab.deletePrompt"
direction="left"
on-confirm="removeGroup($index)"
on-cancel="hidePrompt(tab)">
</umb-confirm-action>
</div>
</div>
<button ng-if="tab.tabState ==='init' && !sortingMode" type="button" hotkey="alt+shift+g" ng-click="addTab(tab)" data-element="group-add" class="btn-reset umb-group-builder__tab umb-group-builder__tab--placeholder">
Add tab
</button>
</li>
</ul>
<umb-content-type-group ng-if="model.groups.length > 1">
<ul class="umb-group-builder__properties" ui-sortable="sortableOptionsProperty" ng-model="model.groups[openTabIndex].properties">
<li ng-repeat="property in model.groups[openTabIndex].properties | filter: {fieldsetId: '!'}" data-element="property-{{property.alias}}" ng-class="{'umb-group-builder__property-sortable': sortingMode && !property.inherited}">
<umb-content-type-property
ng-if="property.propertyState !== 'init'"
property="property"
compact="sortingMode">
</umb-content-type-property>
<umb-content-type-property-placeholder
ng-if="property.propertyState === 'init' && !sortingMode"
on-click="addProperty(property, model.groups[openTabIndex])">
</umb-content-type-property-placeholder>
</li>
</ul>
</umb-content-type-group>
<umb-content-type-groups>
<umb-content-type-group
allow-name="true"
ng-repeat="fieldset in model.fieldsets | filter: { groupId: model.groups[openTabIndex].id }"
group="fieldset">
<ul class="umb-group-builder__properties">
<li ng-repeat="property in model.groups[openTabIndex].properties | filter:{ fieldsetId: fieldset.id }" data-element="property-{{property.alias}}" ng-class="{'umb-group-builder__property-sortable': sortingMode && !property.inherited}">
<umb-content-type-property
property="property"
compact="sortingMode">
</umb-content-type-property>
</li>
<li>
<umb-content-type-property-placeholder
ng-if="!sortingMode"
on-click="addNewProperty(model.groups[openTabIndex], fieldset)">
</umb-content-type-property-placeholder>
</li>
</ul>
</umb-content-type-group>
</umb-content-type-groups>
<umb-content-type-group-placeholder
ng-if="model.groups.length > 1 && !sortingMode"
on-click="addFieldset()">
</umb-content-type-group-placeholder>
</div>
<!-- WITHOUT TABS -->
<ul ng-if="!model.hasTabs" class="umb-group-builder__groups" ui-sortable="sortableOptionsGroup" ng-model="model.groups">
<li ng-repeat="tab in model.groups" ng-class="{'umb-group-builder__group-sortable': sortingMode}" data-element="group-{{tab.name}}">
<!-- TAB INIT STATE -->
<!-- GROUP INIT STATE -->
<button type="button" class="umb-group-builder__group -placeholder" hotkey="alt+shift+g" ng-click="addGroup(tab)" ng-if="tab.tabState=='init' && !sortingMode" data-element="group-add">
<localize key="contentTypeEditor_addGroup"></localize>
</button>
<!-- TAB ACTIVE OR INACTIVE STATE -->
<!-- GROUP ACTIVE OR INACTIVE STATE -->
<div class="umb-group-builder__group" ng-if="tab.tabState !== 'init'" ng-class="{'-active':tab.tabState=='active', '-inherited': tab.inherited, 'umb-group-builder__group-handle -sortable': sortingMode && !tab.inherited}" tabindex="0" ng-focus="activateGroup(tab)">
<div class="umb-group-builder__group-title-wrapper">
@@ -289,8 +392,6 @@
</div>
<br>
</li>
</ul>