Merge remote-tracking branch 'origin/v8/8.7' into v8/feature/block-list-editor-remove-unused-block-index
# Conflicts: # src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js
This commit is contained in:
@@ -730,7 +730,7 @@
|
||||
return null;
|
||||
}
|
||||
|
||||
var dataModel = getDataByUdi(layoutEntry.udi, this.value.contentData);
|
||||
var dataModel = getDataByUdi(layoutEntry.contentUdi, this.value.contentData);
|
||||
if (dataModel === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
// -------------------------
|
||||
|
||||
.alert {
|
||||
position: relative;
|
||||
padding: 8px 35px 8px 14px;
|
||||
margin-bottom: @baseLineHeight;
|
||||
background-color: @warningBackground;
|
||||
@@ -98,3 +99,29 @@
|
||||
.alert-block p + p {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
|
||||
// Property error alerts
|
||||
// -------------------------
|
||||
.alert.property-error {
|
||||
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
padding: 6px 16px 6px 12px;
|
||||
margin-bottom: 6px;
|
||||
|
||||
&::after {
|
||||
content:'';
|
||||
position: absolute;
|
||||
bottom:-6px;
|
||||
left: 6px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 6px solid transparent;
|
||||
border-right: 6px solid transparent;
|
||||
border-top: 6px solid;
|
||||
}
|
||||
&.alert-error::after {
|
||||
border-top-color: @errorBackground;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,19 @@ button.umb-variant-switcher__toggle {
|
||||
font-weight: bold;
|
||||
background-color: @errorBackground;
|
||||
color: @errorText;
|
||||
|
||||
animation-duration: 1.4s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-name: umb-variant-switcher__toggle--badge-bounce;
|
||||
animation-timing-function: ease;
|
||||
@keyframes umb-variant-switcher__toggle--badge-bounce {
|
||||
0% { transform: translateY(0); }
|
||||
20% { transform: translateY(-6px); }
|
||||
40% { transform: translateY(0); }
|
||||
55% { transform: translateY(-3px); }
|
||||
70% { transform: translateY(0); }
|
||||
100% { transform: translateY(0); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -226,6 +239,19 @@ button.umb-variant-switcher__toggle {
|
||||
font-weight: bold;
|
||||
background-color: @errorBackground;
|
||||
color: @errorText;
|
||||
|
||||
animation-duration: 1.4s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-name: umb-variant-switcher__name--badge-bounce;
|
||||
animation-timing-function: ease;
|
||||
@keyframes umb-variant-switcher__name--badge-bounce {
|
||||
0% { transform: translateY(0); }
|
||||
20% { transform: translateY(-6px); }
|
||||
40% { transform: translateY(0); }
|
||||
55% { transform: translateY(-3px); }
|
||||
70% { transform: translateY(0); }
|
||||
100% { transform: translateY(0); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,39 @@
|
||||
height: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
// Validation
|
||||
.show-validation &.-has-error {
|
||||
color: @red;
|
||||
|
||||
&:hover {
|
||||
color: @red !important;
|
||||
}
|
||||
|
||||
&::before {
|
||||
background-color: @red;
|
||||
}
|
||||
|
||||
&:not(.is-active) {
|
||||
.badge {
|
||||
animation-duration: 1.4s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-name: umb-sub-views-nav-item--badge-bounce;
|
||||
animation-timing-function: ease;
|
||||
@keyframes umb-sub-views-nav-item--badge-bounce {
|
||||
0% { transform: translateY(0); }
|
||||
20% { transform: translateY(-6px); }
|
||||
40% { transform: translateY(0); }
|
||||
55% { transform: translateY(-3px); }
|
||||
70% { transform: translateY(0); }
|
||||
100% { transform: translateY(0); }
|
||||
}
|
||||
}
|
||||
.badge.--error-badge {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__action:active,
|
||||
@@ -101,6 +134,10 @@
|
||||
height: 12px;
|
||||
min-width: 12px;
|
||||
}
|
||||
&.--error-badge {
|
||||
display: none;
|
||||
font-weight: 900;
|
||||
}
|
||||
}
|
||||
|
||||
&-text {
|
||||
@@ -182,13 +219,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validation
|
||||
.show-validation .umb-sub-views-nav-item__action.-has-error,
|
||||
.show-validation .umb-sub-views-nav-item > a.-has-error {
|
||||
color: @red;
|
||||
|
||||
&::before {
|
||||
background-color: @red;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,6 +272,7 @@ label:not([for]) {
|
||||
/* CONTROL VALIDATION */
|
||||
.umb-control-required {
|
||||
color: @controlRequiredColor;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.controls-row {
|
||||
|
||||
@@ -138,7 +138,9 @@
|
||||
// additional targetting of the ng-invalid class.
|
||||
.formFieldState(@textColor: @gray-4, @borderColor: @gray-7, @backgroundColor: @gray-10) {
|
||||
// Set the text color
|
||||
.control-label,
|
||||
> .control-label,
|
||||
> .umb-el-wrap > .control-label,
|
||||
> .umb-el-wrap > .control-header > .control-label,
|
||||
.help-block,
|
||||
.help-inline {
|
||||
color: @textColor;
|
||||
|
||||
@@ -481,7 +481,7 @@
|
||||
|
||||
@formErrorText: @errorBackground;
|
||||
@formErrorBackground: lighten(@errorBackground, 55%);
|
||||
@formErrorBorder: darken(spin(@errorBackground, -10), 3%);
|
||||
@formErrorBorder: @red;
|
||||
|
||||
@formSuccessText: @successBackground;
|
||||
@formSuccessBackground: lighten(@successBackground, 48%);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
angular.module("umbraco")
|
||||
.controller("Umbraco.Editors.BlockEditorController",
|
||||
function ($scope, localizationService, formHelper) {
|
||||
function ($scope, localizationService, formHelper, overlayService) {
|
||||
var vm = this;
|
||||
|
||||
vm.model = $scope.model;
|
||||
@@ -42,6 +42,7 @@ angular.module("umbraco")
|
||||
|
||||
vm.submitAndClose = function () {
|
||||
if (vm.model && vm.model.submit) {
|
||||
|
||||
// always keep server validations since this will be a nested editor and server validations are global
|
||||
if (formHelper.submitForm({
|
||||
scope: $scope,
|
||||
@@ -49,13 +50,16 @@ angular.module("umbraco")
|
||||
keepServerValidation: true
|
||||
})) {
|
||||
vm.model.submit(vm.model);
|
||||
vm.saveButtonState = "success";
|
||||
} else {
|
||||
vm.saveButtonState = "error";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vm.close = function () {
|
||||
if (vm.model && vm.model.close) {
|
||||
// TODO: At this stage there could very well have been server errors that have been cleared
|
||||
// TODO: At this stage there could very well have been server errors that have been cleared
|
||||
// but if we 'close' we are basically cancelling the value changes which means we'd want to cancel
|
||||
// all of the server errors just cleared. It would be possible to do that but also quite annoying.
|
||||
// The rudimentary way would be to:
|
||||
@@ -67,6 +71,29 @@ angular.module("umbraco")
|
||||
// * It would have a 'commit' method to commit the removed errors - which we would call in the formHelper.submitForm when it's successful
|
||||
// * It would have a 'rollback' method to reset the removed errors - which we would call here
|
||||
|
||||
|
||||
if (vm.blockForm.$dirty === true) {
|
||||
localizationService.localizeMany(["prompt_discardChanges", "blockEditor_blockHasChanges"]).then(function (localizations) {
|
||||
const confirm = {
|
||||
title: localizations[0],
|
||||
view: "default",
|
||||
content: localizations[1],
|
||||
submitButtonLabelKey: "general_discard",
|
||||
submitButtonStyle: "danger",
|
||||
closeButtonLabelKey: "general_cancel",
|
||||
submit: function () {
|
||||
overlayService.close();
|
||||
vm.model.close(vm.model);
|
||||
},
|
||||
close: function () {
|
||||
overlayService.close();
|
||||
}
|
||||
};
|
||||
overlayService.open(confirm);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
// TODO: check if content/settings has changed and ask user if they are sure.
|
||||
vm.model.close(vm.model);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
<umb-button
|
||||
action="vm.submitAndClose()"
|
||||
button-style="primary"
|
||||
state="submitButtonState"
|
||||
state="vm.saveButtonState"
|
||||
label="{{vm.submitLabel}}"
|
||||
type="button">
|
||||
</umb-button>
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
<i class="icon {{ vm.item.icon }}" aria-hidden="true"></i>
|
||||
<span class="umb-sub-views-nav-item-text">{{ vm.item.name }}</span>
|
||||
<div ng-show="vm.item.badge" class="badge -type-{{vm.item.badge.type}}">{{vm.item.badge.count}}</div>
|
||||
<div ng-show="!vm.item.badge" class="badge -type-alert --error-badge">!</div>
|
||||
</button>
|
||||
|
||||
<ul class="dropdown-menu umb-sub-views-nav-item__anchor_dropdown" ng-if="vm.item.anchors && vm.item.anchors.length > 1">
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
ng-form.ng-invalid-val-server-match-settings > .umb-block-list__block > .umb-block-list__block--actions {
|
||||
opacity: 1;
|
||||
}
|
||||
.umb-block-list__block--actions {
|
||||
position: absolute;
|
||||
z-index:999999999;// We always want to be on top of custom view, but we need to make sure we still are behind relevant Umbraco CMS UI. ToDo: Needs further testing.
|
||||
@@ -58,6 +61,40 @@
|
||||
&:hover {
|
||||
color: @ui-action-discreet-type-hover;
|
||||
}
|
||||
> .__error-badge {
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
right: -2px;
|
||||
min-width: 8px;
|
||||
color: @white;
|
||||
background-color: @ui-active-type;
|
||||
border: 2px solid @white;
|
||||
border-radius: 50%;
|
||||
font-size: 8px;
|
||||
font-weight: bold;
|
||||
padding: 2px;
|
||||
line-height: 8px;
|
||||
background-color: @red;
|
||||
display: none;
|
||||
font-weight: 900;
|
||||
}
|
||||
&.--error > .__error-badge {
|
||||
display: block;
|
||||
|
||||
animation-duration: 1.4s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-name: umb-block-list__action--badge-bounce;
|
||||
animation-timing-function: ease;
|
||||
@keyframes umb-block-list__action--badge-bounce {
|
||||
0% { transform: translateY(0); }
|
||||
20% { transform: translateY(-4px); }
|
||||
40% { transform: translateY(0); }
|
||||
55% { transform: translateY(-2px); }
|
||||
70% { transform: translateY(0); }
|
||||
100% { transform: translateY(0); }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
<umb-block-list-block stylesheet="{{::vm.layout.$block.config.stylesheet}}"
|
||||
class="umb-block-list__block--content"
|
||||
ng-class="{'blockelement__draggable-element': vm.layout.$block.config.stylesheet}"
|
||||
view="{{vm.layout.$block.view}}"
|
||||
api="vm.blockEditorApi"
|
||||
block="vm.layout.$block"
|
||||
@@ -19,6 +20,7 @@
|
||||
<span class="sr-only">
|
||||
<localize key="general_settings">Settings</localize>
|
||||
</span>
|
||||
<div class="__error-badge">!</div>
|
||||
</button>
|
||||
<button type="button" class="btn-reset umb-outline action --copy" localize="title" title="actions_copy"
|
||||
ng-click="vm.blockEditorApi.copyBlock(vm.layout.$block);"
|
||||
|
||||
@@ -101,10 +101,6 @@
|
||||
scopeOfExistence = vm.umbElementEditorContent.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, scopeOfExistence, $scope);
|
||||
modelObject.load().then(onLoaded);
|
||||
|
||||
copyAllBlocksAction = {
|
||||
labelKey: "clipboard_labelForCopyAllEntries",
|
||||
labelTokens: [vm.model.label],
|
||||
@@ -128,6 +124,11 @@
|
||||
if (vm.umbProperty) {
|
||||
vm.umbProperty.setPropertyActions(propertyActions);
|
||||
}
|
||||
|
||||
// Create Model Object, to manage our data for this Block Editor.
|
||||
modelObject = blockEditorService.createModelObject(vm.model.value, vm.model.editor, vm.model.config.blocks, scopeOfExistence, $scope);
|
||||
modelObject.load().then(onLoaded);
|
||||
|
||||
};
|
||||
|
||||
// Called when we save the value, the server may return an updated data and our value is re-synced
|
||||
|
||||
Reference in New Issue
Block a user