use val-tab directive in doc type editor
This commit is contained in:
@@ -9,21 +9,12 @@
|
||||
|
||||
const vm = this;
|
||||
|
||||
vm.$onInit = onInit;
|
||||
|
||||
vm.updateName = updateName;
|
||||
vm.removeGroup = removeGroup;
|
||||
vm.whenNameFocus = whenNameFocus;
|
||||
vm.whenFocus = whenFocus;
|
||||
vm.changeSortOrderValue = changeSortOrderValue;
|
||||
|
||||
function onInit() {
|
||||
// we need a group name for the validation and angular doesn't allow dashes in form name.
|
||||
// this is a workaround to make it work
|
||||
const identifier = vm.group.key.replaceAll('-', '');
|
||||
vm.formName = `groupForm${identifier}`;
|
||||
}
|
||||
|
||||
function updateName (group) {
|
||||
if (vm.onUpdateName) {
|
||||
vm.onUpdateName({ group });
|
||||
@@ -66,10 +57,11 @@
|
||||
allowRemove: '<',
|
||||
onRemove: '&',
|
||||
sorting: '<',
|
||||
valServerFieldName: '@',
|
||||
onNameFocus: '&',
|
||||
onFocus: '&',
|
||||
onChangeSortOrderValue: '&'
|
||||
onChangeSortOrderValue: '&',
|
||||
valServerFieldName: '@',
|
||||
valTabAlias: "@"
|
||||
},
|
||||
controller: umbContentTypeGroupController
|
||||
};
|
||||
|
||||
@@ -40,9 +40,10 @@
|
||||
sortable: '<',
|
||||
onEdit: '&',
|
||||
onRemove: '&',
|
||||
onChangeSortOrderValue: '&',
|
||||
valServerFieldAlias: '@',
|
||||
valServerFieldLabel: '@',
|
||||
onChangeSortOrderValue: '&'
|
||||
valTabAlias: '@'
|
||||
},
|
||||
controllerAs: 'vm',
|
||||
controller: umbContentTypePropertyController
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
function GroupsBuilderDirective(contentTypeHelper, contentTypeResource, mediaTypeResource,
|
||||
dataTypeHelper, dataTypeResource, $filter, iconHelper, $q, $timeout, notificationsService,
|
||||
localizationService, editorService, eventsService, overlayService) {
|
||||
localizationService, editorService, eventsService, overlayService, contentEditingHelper) {
|
||||
|
||||
function link(scope, el, attr, ctrl) {
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
scope.genericTab = {
|
||||
key: null,
|
||||
name: "Generic",
|
||||
alias: contentEditingHelper.genericTabAlias,
|
||||
parentKey: null,
|
||||
type: TYPE_TAB,
|
||||
sortOrder: 0,
|
||||
@@ -41,6 +42,10 @@
|
||||
tab.indexInGroups = newValue.findIndex(group => group.key === tab.key);
|
||||
});
|
||||
|
||||
newValue.forEach(group => {
|
||||
group.validationAlias = contentEditingHelper.generateTabValidationAlias(group, newValue);
|
||||
});
|
||||
|
||||
checkGenericTabVisibility();
|
||||
|
||||
if (!scope.openTabKey && scope.hasGenericTab) {
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function valGroupsInTabDirective(angularHelper) {
|
||||
function link(scope, el, attrs, ctrl) {
|
||||
const valFormManager = ctrl[1];
|
||||
const formCtrl = ctrl[0];
|
||||
|
||||
if (!valFormManager) {
|
||||
return;
|
||||
}
|
||||
|
||||
// valformmanager onValidationStatusChanged only emit updates when the parent form status changes.
|
||||
// In this case we need to know the status for all sub forms so we can update each tab validation status correctly based on the child group form states.
|
||||
// the code finds the child group form for a given tab and if any of those group forms are invalid the tab will be flag with an error.
|
||||
scope.$watch(() => angularHelper.countAllFormErrors(formCtrl), () => {
|
||||
update();
|
||||
});
|
||||
|
||||
function update () {
|
||||
const { tab, groups } = scope.$eval(attrs.valGroupsInTab);
|
||||
|
||||
if (!tab && !groups) {
|
||||
tab.hasError = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const tabGroups = [];
|
||||
const tabGroupsIdentifiers = groups.filter(group => group.parentKey === tab.key).map(group => group.key.replaceAll('-', ''));
|
||||
|
||||
for (const [key, value] of Object.entries(formCtrl)) {
|
||||
if (key.startsWith('groupForm')) {
|
||||
const groupIdentifier = key.replace('groupForm', '');
|
||||
if (groupIdentifier && tabGroupsIdentifiers.indexOf(groupIdentifier) !== -1) {
|
||||
tabGroups.push(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tab.hasError = tabGroups.filter(group => group.$invalid).length > 0;
|
||||
}
|
||||
}
|
||||
|
||||
var directive = {
|
||||
require: ['?^^form', '?^^valFormManager'],
|
||||
restrict: "A",
|
||||
link: link
|
||||
};
|
||||
|
||||
return directive;
|
||||
}
|
||||
|
||||
angular.module('umbraco.directives').directive('valGroupsInTab', valGroupsInTabDirective);
|
||||
|
||||
})();
|
||||
@@ -12,14 +12,21 @@ function valTab($timeout) {
|
||||
restrict: "A",
|
||||
link: function (scope, element, attr, ctrs) {
|
||||
|
||||
var evts = [];
|
||||
var form = ctrs[0];
|
||||
var tabAlias = scope.tab.alias;
|
||||
var tab = scope.$eval(attr.valTab) || scope.tab;
|
||||
|
||||
if (!tab) {
|
||||
return;
|
||||
}
|
||||
|
||||
var tabAlias = tab.alias || tab.key;
|
||||
|
||||
let closestEditor = element.closest(".blockelement-inlineblock-editor");
|
||||
closestEditor = closestEditor.length === 0 ? element.closest(".umb-editor-sub-view") : closestEditor;
|
||||
closestEditor = closestEditor.length === 0 ? element.closest(".umb-editor") : closestEditor;
|
||||
|
||||
scope.tabHasError = false;
|
||||
setSuccess();
|
||||
|
||||
function setValidity (form) {
|
||||
if (!form.$valid) {
|
||||
@@ -27,23 +34,50 @@ function valTab($timeout) {
|
||||
|
||||
//check if the validation messages are contained inside of this tabs
|
||||
if (tabContent.find(".ng-invalid").length > 0) {
|
||||
scope.tabHasError = true;
|
||||
setError();
|
||||
} else {
|
||||
scope.tabHasError = false;
|
||||
setSuccess();
|
||||
}
|
||||
}
|
||||
else {
|
||||
scope.tabHasError = false;
|
||||
setSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
function setError () {
|
||||
scope.tabHasError = true;
|
||||
tab.hasError = true;
|
||||
}
|
||||
|
||||
function setSuccess () {
|
||||
scope.tabHasError = false;
|
||||
tab.hasError = false;
|
||||
}
|
||||
|
||||
function subscribe () {
|
||||
for (let control of form.$$controls) {
|
||||
var unbind = scope.$watch(() => control.$invalid, function () {
|
||||
setValidity(form);
|
||||
});
|
||||
|
||||
evts.push(unbind);
|
||||
}
|
||||
}
|
||||
|
||||
function unsubscribe () {
|
||||
evts.forEach(event => event());
|
||||
}
|
||||
|
||||
// we need to watch validation state on individual controls so we can update specific tabs accordingly
|
||||
$timeout(() => {
|
||||
for (let control of form.$$controls) {
|
||||
scope.$watch(() => control.$invalid, function () {
|
||||
setValidity(form);
|
||||
});
|
||||
}
|
||||
scope.$watchCollection(() => form.$$controls, function (newValue) {
|
||||
unsubscribe();
|
||||
subscribe();
|
||||
});
|
||||
});
|
||||
|
||||
scope.$on('$destroy', function () {
|
||||
unsubscribe();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -183,19 +183,20 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, editorSt
|
||||
genericTabAlias: "_umb_genericTab",
|
||||
|
||||
generateTabValidationAlias: function (group, groups) {
|
||||
const prefix = "tab-content-";
|
||||
let validationAlias = this.genericTabAlias;
|
||||
|
||||
if (group.parentKey) {
|
||||
const parentGroup = groups.find(tab => tab.key === group.parentKey);
|
||||
validationAlias = parentGroup.alias;
|
||||
validationAlias = parentGroup.alias || parentGroup.key;
|
||||
}
|
||||
|
||||
// tabs should use their own alias so direct properties will trigger the right tab
|
||||
if (group.type === 1) {
|
||||
validationAlias = group.alias;
|
||||
validationAlias = group.alias || group.key;
|
||||
}
|
||||
|
||||
return validationAlias;
|
||||
return prefix + validationAlias;
|
||||
},
|
||||
|
||||
registerGenericTab: function (groups) {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</umb-editor-tab-bar>
|
||||
|
||||
<umb-box ng-repeat="tab in tabs" ng-show="tab.key === activeTabKey && tab.properties.length > 0">
|
||||
<umb-box-content data-element="tab-content-{{tab.validationAlias}}">
|
||||
<umb-box-content data-element="{{tab.validationAlias}}">
|
||||
<umb-property
|
||||
data-element="property-{{property.alias}}"
|
||||
ng-repeat="property in tab.properties track by property.alias"
|
||||
@@ -29,7 +29,7 @@
|
||||
<div id="group-{{group.id}}">{{ group.label }}</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-group-panel__content" data-element="tab-content-{{group.validationAlias}}">
|
||||
<div class="umb-group-panel__content" data-element="{{group.validationAlias}}">
|
||||
<umb-property
|
||||
data-element="property-{{property.alias}}"
|
||||
ng-repeat="property in group.properties track by property.alias"
|
||||
|
||||
@@ -1,61 +1,59 @@
|
||||
<div data-element="group-{{vm.group.name}}" class="umb-group-builder__group" ng-class="{'-inherited': vm.group.inherited, 'umb-group-builder__group-handle -sortable': vm.sorting && !vm.group.inherited}" tabindex="0" ng-focus="vm.whenFocus()">
|
||||
<ng-form name="{{ vm.formName }}">
|
||||
<div class="umb-group-builder__group-title-wrapper" ng-if="vm.allowName">
|
||||
<div class="umb-group-builder__group-title-wrapper" ng-if="vm.allowName" data-element="{{vm.valTabAlias}}">
|
||||
|
||||
<ng-form name="groupNameForm" data-element="group-name">
|
||||
<div class="umb-group-builder__group-title control-group -no-margin" ng-class="{'-inherited': vm.group.inherited}">
|
||||
<i class="umb-group-builder__group-title-icon icon-navigation" ng-if="vm.sorting && !vm.group.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
|
||||
ng-focus="vm.whenNameFocus()"
|
||||
required
|
||||
val-server-field="{{vm.valServerFieldName}}"
|
||||
data-lpignore="true" />
|
||||
<ng-form name="groupNameForm" data-element="group-name">
|
||||
<div class="umb-group-builder__group-title control-group -no-margin" ng-class="{'-inherited': vm.group.inherited}">
|
||||
<i class="umb-group-builder__group-title-icon icon-navigation" ng-if="vm.sorting && !vm.group.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
|
||||
ng-focus="vm.whenNameFocus()"
|
||||
required
|
||||
val-server-field="{{vm.valServerFieldName}}"
|
||||
data-lpignore="true" />
|
||||
|
||||
<div class="umb-group-builder__group-title-val-message" 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 class="umb-group-builder__group-title-val-message" 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>
|
||||
</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>
|
||||
|
||||
<ng-form name="groupSortOrderForm" class="umb-group-builder__group-sort-order">
|
||||
<div ng-if="vm.sorting">
|
||||
<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="vm.changeSortOrderValue()" 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="vm.allowRemove">
|
||||
<i class="icon-trash" ng-click="vm.removeGroup()"></i>
|
||||
</div>
|
||||
<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>
|
||||
|
||||
<div class="umb-group-builder__group-content">
|
||||
<ng-transclude></ng-transclude>
|
||||
<ng-form name="groupSortOrderForm" class="umb-group-builder__group-sort-order">
|
||||
<div ng-if="vm.sorting">
|
||||
<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="vm.changeSortOrderValue()" 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="vm.allowRemove">
|
||||
<i class="icon-trash" ng-click="vm.removeGroup()"></i>
|
||||
</div>
|
||||
</ng-form>
|
||||
</div>
|
||||
|
||||
<div class="umb-group-builder__group-content">
|
||||
<ng-transclude></ng-transclude>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,7 +1,7 @@
|
||||
<div data-element="property-{{vm.property.alias}}" 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.sortable && !vm.property.inherited, '-sortable-locked': vm.sortable && vm.property.inherited}">
|
||||
|
||||
<!-- property meta text -->
|
||||
<div class="umb-group-builder__property-meta" ng-class="{'-full-width': vm.sortable}">
|
||||
<div class="umb-group-builder__property-meta" ng-class="{'-full-width': vm.sortable}" data-element="{{vm.valTabAlias}}">
|
||||
|
||||
<ng-form name="propertyTypeForm">
|
||||
<div class="control-group -no-margin" ng-if="!vm.sortable">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div ng-click="vm.click()" class="umb-group-builder__tab" ng-class="{'is-active': vm.isOpen, 'is-inherited': vm.tab.inherited, 'umb-group-builder__tab-handle -sortable': vm.sorting && !vm.tab.inherited, 'has-error': vm.tab.hasError}">
|
||||
<div ng-click="vm.click()" class="umb-group-builder__tab" ng-class="{'is-active': vm.isOpen, 'is-inherited': vm.tab.inherited, 'umb-group-builder__tab-handle -sortable': vm.sorting && !vm.tab.inherited, 'has-error': vm.tab.hasError}" val-tab="vm.tab">
|
||||
<div>
|
||||
<div class="umb-group-builder__tab-inherited-label" ng-if="vm.tab.inherited">
|
||||
<localize key="contentTypeEditor_inheritedFrom"></localize>: {{ vm.tab.inheritedFromName }}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</umb-editor-tab-bar>
|
||||
|
||||
<umb-box ng-repeat="tab in vm.tabs" ng-show="tab.key === vm.activeTabKey && tab.properties.length > 0">
|
||||
<umb-box-content data-element="tab-content-{{tab.validationAlias}}">
|
||||
<umb-box-content data-element="{{tab.validationAlias}}">
|
||||
<umb-property
|
||||
data-element="property-{{property.alias}}"
|
||||
ng-repeat="property in tab.properties track by property.alias"
|
||||
@@ -35,7 +35,7 @@
|
||||
<div id="group-{{group.id}}">{{ group.label }}</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-group-panel__content" data-element="tab-content-{{group.validationAlias}}">
|
||||
<div class="umb-group-panel__content" data-element="{{group.validationAlias}}">
|
||||
<umb-property
|
||||
data-element="property-{{property.alias}}"
|
||||
ng-repeat="property in group.properties track by property.alias"
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
allow-change-name="false">
|
||||
</umb-content-type-tab>
|
||||
</li>
|
||||
<li ng-repeat="(tabIndex, tab) in tabs track by tab.key" ng-class="{'umb-group-builder__tab-sortable': sortingMode}" umb-droppable="droppableOptionsTab" data-tab-key="{{tab.key}}" val-groups-in-tab="{ tab: tab, groups: model.groups }">
|
||||
<li ng-repeat="(tabIndex, tab) in tabs track by tab.key" ng-class="{'umb-group-builder__tab-sortable': sortingMode}" umb-droppable="droppableOptionsTab" data-tab-key="{{tab.key}}">
|
||||
<umb-content-type-tab
|
||||
tab="tab"
|
||||
is-open="tab.key === openTabKey"
|
||||
@@ -125,8 +125,9 @@
|
||||
allow-remove="canRemoveGroup(group) && !sortingMode"
|
||||
on-remove="removeGroup(group)"
|
||||
sorting="sortingMode"
|
||||
on-change-sort-order-value="onChangeGroupSortOrderValue(group)"
|
||||
val-server-field-name="{{'Groups[' + $index + '].Name'}}"
|
||||
on-change-sort-order-value="onChangeGroupSortOrderValue(group)">
|
||||
val-tab-alias="{{group.validationAlias}}">
|
||||
|
||||
<ul class="umb-group-builder__properties" ui-sortable="sortableOptionsProperty" ng-model="group.properties" ng-show="group.properties.length > 0 || sortingMode">
|
||||
<li ng-repeat="(propertyIndex, property) in group.properties track by property.alias" ng-class="{'umb-group-builder__property-sortable': sortingMode && !property.inherited}">
|
||||
@@ -136,9 +137,10 @@
|
||||
sortable="sortingMode"
|
||||
on-edit="editPropertyTypeSettings(property)"
|
||||
on-remove="deleteProperty(group.properties, property)"
|
||||
on-change-sort-order-value="onChangePropertySortOrderValue(group)"
|
||||
val-server-field-alias="{{'Groups[' + groupIndex + '].Properties[' + propertyIndex + '].Alias'}}"
|
||||
val-server-field-label="{{'Groups[' + groupIndex + '].Properties[' + propertyIndex + '].Label'}}"
|
||||
on-change-sort-order-value="onChangePropertySortOrderValue(group)">
|
||||
val-tab-alias="{{group.validationAlias}}">
|
||||
</umb-content-type-property>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
Reference in New Issue
Block a user