Merge remote-tracking branch 'origin/dev-v8' into temp8-server-content-validation-fixes-4884
This commit is contained in:
@@ -133,7 +133,11 @@ namespace Umbraco.Core.Composing
|
||||
|
||||
Configs.RegisterWith(_register);
|
||||
|
||||
return _register.CreateFactory();
|
||||
IFactory factory = null;
|
||||
// ReSharper disable once AccessToModifiedClosure -- on purpose
|
||||
_register.Register(_ => factory, Lifetime.Singleton);
|
||||
factory = _register.CreateFactory();
|
||||
return factory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -2875,7 +2875,14 @@ namespace Umbraco.Core.Services.Implement
|
||||
{
|
||||
foreach (var property in blueprint.Properties)
|
||||
{
|
||||
content.SetValue(property.Alias, property.GetValue(culture), culture);
|
||||
if (property.PropertyType.VariesByCulture())
|
||||
{
|
||||
content.SetValue(property.Alias, property.GetValue(culture), culture);
|
||||
}
|
||||
else
|
||||
{
|
||||
content.SetValue(property.Alias, property.GetValue());
|
||||
}
|
||||
}
|
||||
|
||||
content.Name = blueprint.Name;
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Tests.Composing
|
||||
{
|
||||
[TestFixture]
|
||||
public class CompositionTests
|
||||
{
|
||||
[Test]
|
||||
public void FactoryIsResolvable()
|
||||
{
|
||||
Func<IFactory, IFactory> factoryFactory = null;
|
||||
|
||||
var mockedRegister = Mock.Of<IRegister>();
|
||||
var mockedFactory = Mock.Of<IFactory>();
|
||||
|
||||
// the mocked register creates the mocked factory
|
||||
Mock.Get(mockedRegister)
|
||||
.Setup(x => x.CreateFactory())
|
||||
.Returns(mockedFactory);
|
||||
|
||||
// the mocked register can register a factory factory
|
||||
Mock.Get(mockedRegister)
|
||||
.Setup(x => x.Register(It.IsAny<Func<IFactory, IFactory>>(), Lifetime.Singleton))
|
||||
.Callback<Func<IFactory, IFactory>, Lifetime>((ff, lt) => factoryFactory = ff);
|
||||
|
||||
// the mocked factory can invoke the factory factory
|
||||
Mock.Get(mockedFactory)
|
||||
.Setup(x => x.GetInstance(typeof(IFactory)))
|
||||
.Returns(() => factoryFactory?.Invoke(mockedFactory));
|
||||
|
||||
var logger = new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>());
|
||||
var typeLoader = new TypeLoader(Mock.Of<IAppPolicyCache>(), "", logger);
|
||||
var composition = new Composition(mockedRegister, typeLoader, logger, Mock.Of<IRuntimeState>());
|
||||
|
||||
// create the factory, ensure it is the mocked factory
|
||||
var factory = composition.CreateFactory();
|
||||
Assert.AreSame(mockedFactory, factory);
|
||||
|
||||
// ensure we can get an IFactory instance,
|
||||
// meaning that it has been properly registered
|
||||
|
||||
var resolved = factory.GetInstance<IFactory>();
|
||||
Assert.IsNotNull(resolved);
|
||||
Assert.AreSame(factory, resolved);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,6 +118,7 @@
|
||||
<Compile Include="Cache\SnapDictionaryTests.cs" />
|
||||
<Compile Include="Clr\ReflectionUtilitiesTests.cs" />
|
||||
<Compile Include="Collections\OrderedHashSetTests.cs" />
|
||||
<Compile Include="Composing\CompositionTests.cs" />
|
||||
<Compile Include="Composing\LightInjectValidation.cs" />
|
||||
<Compile Include="Composing\ContainerConformingTests.cs" />
|
||||
<Compile Include="CoreThings\CallContextTests.cs" />
|
||||
|
||||
+29
-2
@@ -331,8 +331,35 @@
|
||||
|
||||
// This is a helper method to reduce the amount of code repitition for actions: Save, Publish, SendToPublish
|
||||
function performSave(args) {
|
||||
|
||||
|
||||
|
||||
// Check that all variants for publishing have a name.
|
||||
if (args.action === "publish" || args.action === "sendToPublish") {
|
||||
|
||||
if ($scope.content.variants) {
|
||||
var iVariant;
|
||||
for (var i = 0; i < $scope.content.variants.length; i++) {
|
||||
iVariant = $scope.content.variants[i];
|
||||
|
||||
iVariant.notifications = [];// maybe not needed, need to investigate.
|
||||
|
||||
if(iVariant.publish === true) {
|
||||
if (iVariant.name == null) {
|
||||
|
||||
var tokens = [iVariant.language.name];
|
||||
|
||||
localizationService.localize("publish_contentPublishedFailedByMissingName", tokens).then(function (value) {
|
||||
iVariant.notifications.push({"message": value, "type": 1});
|
||||
});
|
||||
|
||||
return $q.reject();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//Used to check validility of nested form - coming from Content Apps mostly
|
||||
//Set them all to be invalid
|
||||
var fieldsToRollback = checkValidility();
|
||||
|
||||
+34
-21
@@ -22,38 +22,51 @@
|
||||
</pre>
|
||||
|
||||
@param {boolean} model Set to <code>true</code> or <code>false</code> to set the checkbox to checked or unchecked.
|
||||
@param {string} input-id Set the <code>id</code> of the checkbox.
|
||||
@param {string} value Set the value of the checkbox.
|
||||
@param {string} name Set the name of the checkbox.
|
||||
@param {string} text Set the text for the checkbox label.
|
||||
@param {string} server-validation-field Set the <code>val-server-field</code> of the checkbox.
|
||||
@param {boolean} disabled Set the checkbox to be disabled.
|
||||
@param {boolean} required Set the checkbox to be required.
|
||||
@param {string} onChange Callback when the value of the input element changes.
|
||||
@param {string} on-change Callback when the value of the checkbox changed by interaction.
|
||||
|
||||
**/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function CheckboxDirective() {
|
||||
var directive = {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
templateUrl: 'views/components/forms/umb-checkbox.html',
|
||||
scope: {
|
||||
model: "=",
|
||||
value: "@",
|
||||
name: "@",
|
||||
text: "@",
|
||||
disabled: "=",
|
||||
required: "=",
|
||||
onChange: "&"
|
||||
}
|
||||
};
|
||||
|
||||
return directive;
|
||||
|
||||
|
||||
|
||||
function UmbCheckboxController($timeout) {
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.callOnChange = function() {
|
||||
$timeout(function() {
|
||||
vm.onChange({model:vm.model, value:vm.value});
|
||||
}, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
var component = {
|
||||
templateUrl: 'views/components/forms/umb-checkbox.html',
|
||||
controller: UmbCheckboxController,
|
||||
controllerAs: 'vm',
|
||||
bindings: {
|
||||
model: "=",
|
||||
inputId: "@",
|
||||
value: "@",
|
||||
name: "@",
|
||||
text: "@",
|
||||
serverValidationField: "@",
|
||||
disabled: "<",
|
||||
required: "<",
|
||||
onChange: "&"
|
||||
}
|
||||
};
|
||||
|
||||
angular.module('umbraco.directives').directive('umbCheckbox', CheckboxDirective);
|
||||
angular.module('umbraco.directives').component('umbCheckbox', component);
|
||||
|
||||
})();
|
||||
|
||||
+22
-9
@@ -19,9 +19,15 @@ angular.module("umbraco.directives")
|
||||
promises.push(assetsService.loadJs("lib/tinymce/tinymce.min.js", scope));
|
||||
}
|
||||
|
||||
var toolbar = ["code", "styleselect", "bold", "italic", "alignleft", "aligncenter", "alignright", "bullist", "numlist", "link", "umbmediapicker", "umbembeddialog"];
|
||||
if (scope.configuration && scope.configuration.toolbar) {
|
||||
toolbar = scope.configuration.toolbar;
|
||||
var editorConfig = scope.configuration ? scope.configuration : null;
|
||||
if (!editorConfig || angular.isString(editorConfig)) {
|
||||
editorConfig = tinyMceService.defaultPrevalues();
|
||||
//for the grid by default, we don't want to include the macro toolbar
|
||||
editorConfig.toolbar = _.without(editorConfig, "umbmacro");
|
||||
}
|
||||
//make sure there's a max image size
|
||||
if (!scope.configuration.maxImageSize && scope.configuration.maxImageSize !== 0) {
|
||||
editorConfig.maxImageSize = tinyMceService.defaultPrevalues().maxImageSize;
|
||||
}
|
||||
|
||||
//stores a reference to the editor
|
||||
@@ -29,9 +35,9 @@ angular.module("umbraco.directives")
|
||||
|
||||
promises.push(tinyMceService.getTinyMceEditorConfig({
|
||||
htmlId: scope.uniqueId,
|
||||
stylesheets: scope.configuration ? scope.configuration.stylesheets : null,
|
||||
toolbar: toolbar,
|
||||
mode: scope.configuration.mode
|
||||
stylesheets: editorConfig.stylesheets,
|
||||
toolbar: editorConfig.toolbar,
|
||||
mode: editorConfig.mode
|
||||
}));
|
||||
|
||||
// pin toolbar to top of screen if we have focus and it scrolls off the screen
|
||||
@@ -46,9 +52,16 @@ angular.module("umbraco.directives")
|
||||
|
||||
$q.all(promises).then(function (result) {
|
||||
|
||||
var tinyMceEditorConfig = result[promises.length - 1];
|
||||
var standardConfig = result[promises.length - 1];
|
||||
|
||||
tinyMceEditorConfig.setup = function (editor) {
|
||||
//create a baseline Config to extend upon
|
||||
var baseLineConfigObj = {
|
||||
maxImageSize: editorConfig.maxImageSize
|
||||
};
|
||||
|
||||
angular.extend(baseLineConfigObj, standardConfig);
|
||||
|
||||
baseLineConfigObj.setup = function (editor) {
|
||||
|
||||
//set the reference
|
||||
tinyMceEditor = editor;
|
||||
@@ -111,7 +124,7 @@ angular.module("umbraco.directives")
|
||||
//the elements needed
|
||||
$timeout(function () {
|
||||
tinymce.DOM.events.domLoaded = true;
|
||||
tinymce.init(tinyMceEditorConfig);
|
||||
tinymce.init(baseLineConfigObj);
|
||||
}, 150, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,10 @@ a.umb-list-item:focus {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.umb-list-item--error {
|
||||
color: @red;
|
||||
}
|
||||
|
||||
.umb-list-item:hover .umb-list-checkbox,
|
||||
.umb-list-item--selected .umb-list-checkbox {
|
||||
opacity: 1;
|
||||
@@ -34,4 +38,4 @@ a.umb-list-item:focus {
|
||||
|
||||
.umb-list-checkbox--visible {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +113,12 @@ var app = angular.module("umbraco.preview", ['umbraco.resources', 'umbraco.servi
|
||||
$scope.exitPreview = function () {
|
||||
|
||||
var culture = $location.search().culture || getParameterByName("culture");
|
||||
var relativeUrl = "/" + $scope.pageId +'?culture='+ culture;
|
||||
var relativeUrl = "/" + $scope.pageId;
|
||||
|
||||
if(culture){
|
||||
relativeUrl +='?culture='+ culture;
|
||||
}
|
||||
|
||||
window.top.location.href = "../preview/end?redir=" + encodeURIComponent(relativeUrl);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
<label class="checkbox umb-form-check umb-form-check--checkbox" ng-class="{ 'umb-form-check--disabled': disabled }">
|
||||
<input type="checkbox" name="{{name}}"
|
||||
value="{{value}}"
|
||||
<input type="checkbox"
|
||||
id="{{vm.inputId}}"
|
||||
name="{{vm.name}}"
|
||||
value="{{vm.value}}"
|
||||
class="umb-form-check__input"
|
||||
ng-model="model.checked"
|
||||
ng-disabled="disabled"
|
||||
ng-required="required"
|
||||
ng-change="onChange(model)"/>
|
||||
val-server-field="{{vm.serverValidationField}}"
|
||||
ng-model="vm.model"
|
||||
ng-disabled="vm.disabled"
|
||||
ng-required="vm.required"
|
||||
ng-change="vm.callOnChange()"/>
|
||||
|
||||
<span class="umb-form-check__state" aria-hidden="true">
|
||||
<span class="umb-form-check__check">
|
||||
<i class="umb-form-check__icon icon-check"></i>
|
||||
</span>
|
||||
</span>
|
||||
<span class="umb-form-check__text">{{text}}</span>
|
||||
<span class="umb-form-check__text">{{vm.text}}</span>
|
||||
</label>
|
||||
|
||||
@@ -14,34 +14,51 @@
|
||||
|
||||
/** Returns true if publishing is possible based on if there are un-published mandatory languages */
|
||||
function canPublish() {
|
||||
var selected = [];
|
||||
|
||||
var possible = false;
|
||||
for (var i = 0; i < vm.variants.length; i++) {
|
||||
var variant = vm.variants[i];
|
||||
|
||||
//if this variant will show up in the publish-able list
|
||||
var publishable = dirtyVariantFilter(variant);
|
||||
var published = !(variant.state === "NotCreated" || variant.state === "Draft");
|
||||
|
||||
if ((variant.language.isMandatory && !published) && (!publishable || !variant.publish)) {
|
||||
//if a mandatory variant isn't published
|
||||
//and it's not publishable or not selected to be published
|
||||
//then we cannot continue
|
||||
|
||||
// TODO: Show a message when this occurs
|
||||
var state = canVariantPublish(variant);
|
||||
if (state === true) {
|
||||
possible = true;
|
||||
}
|
||||
if (state === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (variant.publish) {
|
||||
selected.push(variant.publish);
|
||||
}
|
||||
}
|
||||
return selected.length > 0;
|
||||
return possible;
|
||||
}
|
||||
|
||||
/** Returns true if publishing is possible based on if the variant is a un-published mandatory language */
|
||||
function canVariantPublish(variant) {
|
||||
|
||||
//if this variant will show up in the publish-able list
|
||||
var publishable = dirtyVariantFilter(variant);
|
||||
var published = !(variant.state === "NotCreated" || variant.state === "Draft");
|
||||
|
||||
// is this variant mandatory:
|
||||
if (variant.language.isMandatory && !published && !variant.publish) {
|
||||
//if a mandatory variant isn't published or set to be published
|
||||
//then we cannot continue
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// is this variant selected for publish:
|
||||
if (variant.publish === true) {
|
||||
return publishable;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function changeSelection(variant) {
|
||||
|
||||
$scope.model.disableSubmitButton = !canPublish();
|
||||
//need to set the Save state to true if publish is true
|
||||
variant.save = variant.publish;
|
||||
|
||||
variant.willPublish = canVariantPublish(variant);
|
||||
}
|
||||
|
||||
function dirtyVariantFilter(variant) {
|
||||
@@ -102,32 +119,49 @@
|
||||
|
||||
_.each(vm.variants,
|
||||
function (variant) {
|
||||
if(variant.state !== "NotCreated"){
|
||||
vm.isNew = false;
|
||||
if(variant.state === "NotCreated") {
|
||||
vm.isNew = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
_.each(vm.variants,
|
||||
function (variant) {
|
||||
variant.compositeId = contentEditingHelper.buildCompositeVariantId(variant);
|
||||
variant.htmlId = "_content_variant_" + variant.compositeId;
|
||||
|
||||
// reset to not be published
|
||||
variant.publish = false;
|
||||
variant.save = false;
|
||||
|
||||
//check for pristine variants
|
||||
if (!vm.hasPristineVariants) {
|
||||
vm.hasPristineVariants = pristineVariantFilter(variant);
|
||||
}
|
||||
|
||||
if(hasAnyData(variant)){
|
||||
|
||||
// If the variant havent been created jet.
|
||||
if(variant.state === "NotCreated") {
|
||||
// If the variant is mandatory, then set the variant to be published.
|
||||
if (variant.language.isMandatory === true) {
|
||||
variant.publish = true;
|
||||
variant.save = true;
|
||||
}
|
||||
}
|
||||
|
||||
variant.canPublish = dirtyVariantFilter(variant);
|
||||
|
||||
// if we have data on this variant.
|
||||
if(variant.canPublish && hasAnyData(variant)) {
|
||||
// and if some varaints havent been saved before, or they dont have a publishing date set, then we set it for publishing.
|
||||
if(vm.isNew || variant.publishDate == null){
|
||||
variant.publish = true;
|
||||
variant.save = true;
|
||||
}
|
||||
}else{
|
||||
variant.publish = false;
|
||||
variant.save = false;
|
||||
variant.canSave = false;
|
||||
}
|
||||
});
|
||||
|
||||
variant.willPublish = canVariantPublish(variant);
|
||||
}
|
||||
);
|
||||
|
||||
if (vm.variants.length !== 0) {
|
||||
//now sort it so that the current one is at the top
|
||||
@@ -156,7 +190,6 @@
|
||||
|
||||
localizationService.localize(labelKey).then(function (value) {
|
||||
vm.headline = value;
|
||||
|
||||
vm.loading = false;
|
||||
});
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
<div class="umb-list umb-list--condensed" ng-if="!vm.loading">
|
||||
|
||||
<div class="umb-list-item" ng-repeat="variant in vm.variants | filter:vm.dirtyVariantFilter track by variant.compositeId">
|
||||
<div class="umb-list-item" ng-repeat="variant in vm.variants | filter:vm.dirtyVariantFilter track by variant.compositeId" ng-class="{'umb-list-item--error': publishVariantSelectorForm.publishVariantSelector.$invalid || (variant.notifications | filter:{type:1}).length > 0}">
|
||||
<ng-form name="publishVariantSelectorForm">
|
||||
<div class="flex">
|
||||
<input id="{{variant.htmlId}}"
|
||||
@@ -18,16 +18,18 @@
|
||||
type="checkbox"
|
||||
ng-model="variant.publish"
|
||||
ng-change="vm.changeSelection(variant)"
|
||||
ng-disabled="(vm.isNew && variant.language.isMandatory) || (variant.canSave === false)"
|
||||
ng-disabled="(variant.canPublish === false)"
|
||||
style="margin-right: 8px;"
|
||||
val-server-field="{{variant.htmlId}}" />
|
||||
<div>
|
||||
<label for="{{variant.htmlId}}" style="margin-bottom: 2px;">
|
||||
<span>{{ variant.language.name }}</span>
|
||||
<strong ng-if="variant.language.isMandatory" class="umb-control-required">*</strong>
|
||||
|
||||
<span class="db umb-permission__description" ng-if="!publishVariantSelectorForm.publishVariantSelector.$invalid && !(variant.notifications && variant.notifications.length > 0)">
|
||||
<umb-variant-state variant="variant"></umb-variant-state>
|
||||
<span ng-if="variant.language.isMandatory"> - <localize key="languages_mandatoryLanguage"></localize></span>
|
||||
<span ng-if="variant.language.isMandatory"> - </span>
|
||||
<span ng-if="variant.language.isMandatory" ng-class="{'text-error': (variant.language.isMandatory && variant.willPublish === false) }"><localize key="languages_mandatoryLanguage"></localize></span>
|
||||
</span>
|
||||
|
||||
<span class="db" ng-messages="publishVariantSelectorForm.publishVariantSelector.$error" show-validation-on-submit>
|
||||
@@ -35,7 +37,7 @@
|
||||
</span>
|
||||
|
||||
<span class="db" ng-repeat="notification in variant.notifications">
|
||||
<span class="db umb-permission__description text-success">{{notification.message}}</span>
|
||||
<span class="db umb-permission__description" ng-class="{'text-success': notification.type === 3, 'text-error': notification.type !== 3}">{{notification.message}}</span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -22,11 +22,13 @@
|
||||
<p><localize key="content_publishDescendantsWithVariantsHelp"></localize></p>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom: 15px;">
|
||||
<label>
|
||||
<input type="checkbox"
|
||||
ng-model="model.includeUnpublished"
|
||||
style="margin-right: 8px;" />
|
||||
<div style="margin-bottom: 15px;" class="flex">
|
||||
|
||||
<umb-checkbox
|
||||
input-id="includeUnpublishedSelector"
|
||||
model="model.includeUnpublished" />
|
||||
|
||||
<label for="includeUnpublishedSelector">
|
||||
<localize key="content_includeUnpublished"></localize>
|
||||
</label>
|
||||
</div>
|
||||
@@ -40,13 +42,14 @@
|
||||
<div class="umb-list-item umb-list--condensed" ng-repeat="variant in vm.variants">
|
||||
<ng-form name="publishVariantSelectorForm">
|
||||
<div class="flex">
|
||||
<input id="{{variant.htmlId}}"
|
||||
name="publishVariantSelector"
|
||||
type="checkbox"
|
||||
ng-model="variant.publish"
|
||||
ng-change="vm.changeSelection(variant)"
|
||||
style="margin-right: 8px;"
|
||||
val-server-field="{{variant.htmlId}}" />
|
||||
|
||||
<umb-checkbox
|
||||
input-id="{{variant.htmlId}}"
|
||||
name="publishVariantSelector"
|
||||
model="variant.publish"
|
||||
on-change="vm.changeSelection(variant)"
|
||||
server-validation-field="{{variant.htmlId}}"/>
|
||||
|
||||
<div>
|
||||
<label for="{{variant.htmlId}}" style="margin-bottom: 0;">
|
||||
<span>{{ variant.language.name }}</span>
|
||||
|
||||
@@ -6,53 +6,12 @@
|
||||
<umb-load-indicator></umb-load-indicator>
|
||||
</div>
|
||||
|
||||
|
||||
<div ng-if="vm.isNew && !vm.loading">
|
||||
<div ng-if="!vm.loading">
|
||||
<div style="margin-bottom: 15px;">
|
||||
<p><localize key="content_languagesToSaveForFirstTime"></localize></p>
|
||||
</div>
|
||||
|
||||
<div class="umb-list umb-list--condensed">
|
||||
|
||||
<div class="umb-list-item" ng-repeat="variant in vm.variants">
|
||||
<ng-form name="saveVariantSelectorForm">
|
||||
<div class="flex">
|
||||
<input id="{{variant.htmlId}}"
|
||||
name="saveVariantSelector"
|
||||
type="checkbox"
|
||||
ng-model="variant.save"
|
||||
ng-disabled="vm.isNew"
|
||||
style="margin-right: 8px;"
|
||||
val-server-field="{{variant.htmlId}}" />
|
||||
<div>
|
||||
<label for="{{variant.htmlId}}" style="margin-bottom: 2px;">
|
||||
<span>{{ variant.language.name }}</span>
|
||||
<strong ng-if="variant.language.isMandatory" class="umb-control-required">*</strong>
|
||||
|
||||
<span class="db" ng-if="!saveVariantSelectorForm.$invalid && !(variant.notifications && variant.notifications.length > 0)">
|
||||
<umb-variant-state class="umb-permission__description" variant="variant"></umb-variant-state>
|
||||
</span>
|
||||
|
||||
<span class="db" ng-messages="saveVariantSelectorForm.saveVariantSelector.$error" show-validation-on-submit>
|
||||
<span class="db umb-permission__description text-error" ng-message="valServerField">{{saveVariantSelectorForm.saveVariantSelector.errorMsg}}</span>
|
||||
</span>
|
||||
|
||||
<span class="db" ng-repeat="notification in variant.notifications">
|
||||
<span class="db umb-permission__description text-success">{{notification.message}}</span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</ng-form>
|
||||
</div>
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="!vm.isNew && !vm.loading">
|
||||
<div style="margin-bottom: 15px;">
|
||||
<p><localize key="content_languagesToSave"></localize></p>
|
||||
<p>
|
||||
<localize ng-if="!vm.isNew" key="content_languagesToSave"></localize>
|
||||
<localize ng-if="vm.isNew" key="content_languagesToSaveForFirstTime"></localize>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="umb-list umb-list--condensed">
|
||||
@@ -60,13 +19,14 @@
|
||||
<div class="umb-list-item" ng-repeat="variant in vm.variants | filter:vm.dirtyVariantFilter track by variant.compositeId">
|
||||
<ng-form name="saveVariantSelectorForm">
|
||||
<div class="flex">
|
||||
<input id="{{variant.htmlId}}"
|
||||
name="saveVariantSelector"
|
||||
type="checkbox"
|
||||
ng-model="variant.save"
|
||||
ng-change="vm.changeSelection(variant)"
|
||||
style="margin-right: 8px;"
|
||||
val-server-field="{{variant.htmlId}}" />
|
||||
|
||||
<umb-checkbox
|
||||
input-id="{{variant.htmlId}}"
|
||||
name="saveVariantSelector"
|
||||
model="variant.save"
|
||||
on-change="vm.changeSelection(variant)"
|
||||
server-validation-field="{{variant.htmlId}}"/>
|
||||
|
||||
<div>
|
||||
<label for="{{variant.htmlId}}" style="margin-bottom: 2px;">
|
||||
<span>{{ variant.language.name }}</span>
|
||||
@@ -94,7 +54,10 @@
|
||||
|
||||
<div class="umb-list umb-list--condensed" ng-if="vm.hasPristineVariants">
|
||||
<div style="margin-bottom: 15px; font-weight: bold;">
|
||||
<p><localize key="content_unmodifiedLanguages"></localize></p>
|
||||
<p>
|
||||
<localize ng-if="!vm.isNew" key="content_unmodifiedLanguages"></localize>
|
||||
<localize ng-if="vm.isNew" key="content_untouchedLanguagesForFirstTime"></localize>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="umb-list-item" ng-repeat="variant in vm.variants | filter:vm.pristineVariantFilter">
|
||||
|
||||
@@ -87,12 +87,13 @@
|
||||
<div class="umb-list-item" ng-repeat="variant in vm.variants | filter:vm.dirtyVariantFilter">
|
||||
<ng-form name="scheduleSelectorForm">
|
||||
<div class="flex">
|
||||
<input id="{{'saveVariantSelector_' + variant.language.culture}}"
|
||||
name="saveVariantSelector"
|
||||
type="checkbox"
|
||||
ng-model="variant.save"
|
||||
ng-change="vm.changeSelection(variant)"
|
||||
style="margin-right: 8px;" />
|
||||
|
||||
<umb-checkbox
|
||||
input-id="{{'saveVariantSelector_' + variant.language.culture}}"
|
||||
name="saveVariantSelector"
|
||||
model="variant.save"
|
||||
on-change="vm.changeSelection(variant)"/>
|
||||
|
||||
<div>
|
||||
|
||||
<label for="{{'saveVariantSelector_' + variant.language.culture}}" style="margin-bottom: 2px;">
|
||||
|
||||
@@ -13,13 +13,14 @@
|
||||
<div class="umb-list-item" ng-repeat="variant in vm.variants | filter:vm.modifiedVariantFilter">
|
||||
<ng-form name="publishVariantSelectorForm">
|
||||
<div class="flex">
|
||||
<input id="{{variant.htmlId}}"
|
||||
name="publishVariantSelector"
|
||||
type="checkbox"
|
||||
ng-model="variant.save"
|
||||
ng-change="vm.changeSelection(variant)"
|
||||
style="margin-right: 8px;"
|
||||
val-server-field="{{variant.htmlId}}" />
|
||||
|
||||
<umb-checkbox
|
||||
input-id="{{variant.htmlId}}"
|
||||
name="publishVariantSelector"
|
||||
model="variant.save"
|
||||
on-change="vm.changeSelection(variant)"
|
||||
server-validation-field="{{variant.htmlId}}"/>
|
||||
|
||||
<div>
|
||||
<label for="{{variant.htmlId}}" style="margin-bottom: 2px;">
|
||||
<span>{{ variant.language.name }}</span>
|
||||
|
||||
@@ -16,14 +16,15 @@
|
||||
<div class="umb-list-item" ng-repeat="variant in vm.variants | filter:vm.publishedVariantFilter">
|
||||
<ng-form name="unpublishVariantSelectorForm">
|
||||
<div class="flex">
|
||||
<input id="{{variant.htmlId}}"
|
||||
name="unpublishVariantSelector"
|
||||
type="checkbox"
|
||||
ng-model="variant.save"
|
||||
ng-change="vm.changeSelection(variant)"
|
||||
ng-disabled="variant.disabled"
|
||||
style="margin-right: 8px;"
|
||||
val-server-field="{{variant.htmlId}}" />
|
||||
|
||||
<umb-checkbox
|
||||
input-id="{{variant.htmlId}}"
|
||||
name="unpublishVariantSelector"
|
||||
model="variant.save"
|
||||
on-change="vm.changeSelection(variant)"
|
||||
disabled="variant.disabled"
|
||||
server-validation-field="{{variant.htmlId}}"/>
|
||||
|
||||
<div>
|
||||
<label for="{{variant.htmlId}}" style="margin-bottom: 2px;">
|
||||
<span>{{ variant.language.name }}</span>
|
||||
|
||||
+7
-10
@@ -50,8 +50,9 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.CheckboxListContro
|
||||
//get all of the same values between the arrays
|
||||
var same = _.intersection($scope.model.value, selectedVals);
|
||||
//if the lengths are the same as the value, then we are in sync, just exit
|
||||
if (same.length == $scope.model.value.length === selectedVals.length) {
|
||||
return;
|
||||
|
||||
if (same.length === $scope.model.value.length === selectedVals.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.selectedItems = [];
|
||||
@@ -66,18 +67,14 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.CheckboxListContro
|
||||
}
|
||||
}
|
||||
|
||||
function changed(item) {
|
||||
function changed(model, value) {
|
||||
|
||||
var index = _.findIndex($scope.model.value,
|
||||
function (v) {
|
||||
return v === item.val;
|
||||
}
|
||||
);
|
||||
var index = $scope.model.value.indexOf(value);
|
||||
|
||||
if (item.checked) {
|
||||
if (model) {
|
||||
//if it doesn't exist in the model, then add it
|
||||
if (index < 0) {
|
||||
$scope.model.value.push(item.val);
|
||||
$scope.model.value.push(value);
|
||||
}
|
||||
} else {
|
||||
//if it exists in the model, then remove it
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<div class="umb-property-editor umb-checkboxlist" ng-controller="Umbraco.PropertyEditors.CheckboxListController">
|
||||
<ul class="unstyled">
|
||||
<li ng-repeat="item in selectedItems track by item.key">
|
||||
<umb-checkbox name="{{model.alias}}" value="{{item.val}}" model="item" text="{{item.val}}" on-change="changed(item)" required="model.validation.mandatory && !model.value.length"></umb-checkbox>
|
||||
<umb-checkbox name="{{model.alias}}" value="{{item.val}}" model="item.checked" text="{{item.val}}" on-change="changed(model, value)" required="model.validation.mandatory && !model.value.length"></umb-checkbox>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -17,12 +17,13 @@ angular.module("umbraco")
|
||||
if (!editorConfig || angular.isString(editorConfig)) {
|
||||
editorConfig = tinyMceService.defaultPrevalues();
|
||||
}
|
||||
|
||||
var promises = [];
|
||||
if (!editorConfig.maxImageSize && editorConfig.maxImageSize != 0) {
|
||||
//make sure there's a max image size
|
||||
if (!editorConfig.maxImageSize && editorConfig.maxImageSize !== 0) {
|
||||
editorConfig.maxImageSize = tinyMceService.defaultPrevalues().maxImageSize;
|
||||
}
|
||||
|
||||
var promises = [];
|
||||
|
||||
//queue file loading
|
||||
if (typeof tinymce === "undefined") { // Don't reload tinymce if already loaded
|
||||
promises.push(assetsService.loadJs("lib/tinymce/tinymce.min.js", $scope));
|
||||
@@ -43,7 +44,7 @@ angular.module("umbraco")
|
||||
|
||||
var standardConfig = result[promises.length - 1];
|
||||
|
||||
//create a baseline Config to exten upon
|
||||
//create a baseline Config to extend upon
|
||||
var baseLineConfigObj = {
|
||||
maxImageSize: editorConfig.maxImageSize
|
||||
};
|
||||
|
||||
@@ -271,13 +271,14 @@
|
||||
<key alias="languagesToPublishForFirstTime">Hvilke sprog vil du gerne udgive? Alle sprog med indhold gemmes!</key>
|
||||
<key alias="languagesToPublish">Hvilke sprog vil du gerne udgive?</key>
|
||||
<key alias="languagesToSave">Hvilke sprog vil du gerne gemme?</key>
|
||||
<key alias="languagesToSaveForFirstTime">Alle sprog med indhold gemmes ved oprettelsen!</key>
|
||||
<key alias="languagesToSaveForFirstTime">Hvilke sprog vil du gerne gemme?</key>
|
||||
<key alias="languagesToSendForApproval">Hvilke sprog vil du gerne sende til godkendelse?</key>
|
||||
<key alias="languagesToSchedule">Hvilke sprog vil du gerne planlægge?</key>
|
||||
<key alias="languagesToUnpublish">Vælg sproget du vil afpublicere. Afpublicering af et obligatorisk sprog vil afpublicere alle sprog.</key>
|
||||
<key alias="publishedLanguages">Udgivne sprog</key>
|
||||
<key alias="unpublishedLanguages">Ikke-udgivne sprog</key>
|
||||
<key alias="unmodifiedLanguages">Uændrede sprog</key>
|
||||
<key alias="unmodifiedLanguages">Uændrede sprog</key>
|
||||
<key alias="untouchedLanguagesForFirstTime">Disse sprog er ikke blevet oprettet</key>
|
||||
<key alias="readyToPublish">Klar til at udgive?</key>
|
||||
<key alias="readyToSave">Klar til at gemme?</key>
|
||||
<key alias="sendForApproval">Send til godkendelse</key>
|
||||
@@ -985,7 +986,8 @@ Mange hilsner fra Umbraco robotten
|
||||
<key alias="contentPublishedFailedInvalid"><![CDATA[
|
||||
%0% kunne ikke publiceres da følgende egenskaber : %1% ikke overholdte valderingsreglerne.
|
||||
]]></key>
|
||||
<key alias="contentPublishedFailedByEvent">%0% kunne ikke udgives, fordi et 3. parts modul annullerede handlingen</key>
|
||||
<key alias="contentPublishedFailedByEvent">%0% kunne ikke udgives, fordi et 3. parts modul annullerede handlingen</key>
|
||||
<key alias="contentPublishedFailedByMissingName"><![CDATA[%0% kan ikke udgives, fordi det mangler et navn.]]></key>
|
||||
<key alias="includeUnpublished">Medtag ikke-udgivede undersider</key>
|
||||
<key alias="inProgress">Publicerer - vent venligst...</key>
|
||||
<key alias="inProgressCounter">%0% ud af %1% sider er blevet udgivet...</key>
|
||||
|
||||
@@ -281,13 +281,14 @@
|
||||
<key alias="languagesToPublishForFirstTime">What languages would you like to publish? All languages with content are saved!</key>
|
||||
<key alias="languagesToPublish">What languages would you like to publish?</key>
|
||||
<key alias="languagesToSave">What languages would you like to save?</key>
|
||||
<key alias="languagesToSaveForFirstTime">All languages with content are saved on creation!</key>
|
||||
<key alias="languagesToSaveForFirstTime">What languages would you like to save?</key>
|
||||
<key alias="languagesToSendForApproval">What languages would you like to send for approval?</key>
|
||||
<key alias="languagesToSchedule">What languages would you like to schedule?</key>
|
||||
<key alias="languagesToUnpublish">Select the languages to unpublish. Unpublishing a mandatory language will unpublish all languages.</key>
|
||||
<key alias="publishedLanguages">Published Languages</key>
|
||||
<key alias="unpublishedLanguages">Unpublished Languages</key>
|
||||
<key alias="unmodifiedLanguages">Unmodified Languages</key>
|
||||
<key alias="unmodifiedLanguages">Unmodified Languages</key>
|
||||
<key alias="untouchedLanguagesForFirstTime">These languages haven't been created</key>
|
||||
<key alias="readyToPublish">Ready to Publish?</key>
|
||||
<key alias="readyToSave">Ready to Save?</key>
|
||||
<key alias="sendForApproval">Send for approval</key>
|
||||
@@ -1235,7 +1236,8 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
]]></key>
|
||||
<key alias="contentPublishedFailedByParent"><![CDATA[
|
||||
%0% can not be published, because a parent page is not published.
|
||||
]]></key>
|
||||
]]></key>
|
||||
<key alias="contentPublishedFailedByMissingName"><![CDATA[%0% can not be published, because its missing a name.]]></key>
|
||||
<key alias="includeUnpublished">Include unpublished subpages</key>
|
||||
<key alias="inProgress">Publishing in progress - please wait...</key>
|
||||
<key alias="inProgressCounter">%0% out of %1% pages have been published...</key>
|
||||
|
||||
@@ -283,13 +283,14 @@
|
||||
<key alias="languagesToPublishForFirstTime">What languages would you like to publish? All languages with content are saved!</key>
|
||||
<key alias="languagesToPublish">What languages would you like to publish?</key>
|
||||
<key alias="languagesToSave">What languages would you like to save?</key>
|
||||
<key alias="languagesToSaveForFirstTime">All languages with content are saved on creation!</key>
|
||||
<key alias="languagesToSaveForFirstTime">What languages would you like to save?</key>
|
||||
<key alias="languagesToSendForApproval">What languages would you like to send for approval?</key>
|
||||
<key alias="languagesToSchedule">What languages would you like to schedule?</key>
|
||||
<key alias="languagesToUnpublish">Select the languages to unpublish. Unpublishing a mandatory language will unpublish all languages.</key>
|
||||
<key alias="publishedLanguages">Published Languages</key>
|
||||
<key alias="unpublishedLanguages">Unpublished Languages</key>
|
||||
<key alias="unmodifiedLanguages">Unmodified Languages</key>
|
||||
<key alias="untouchedLanguagesForFirstTime">These languages haven't been created</key>
|
||||
<key alias="readyToPublish">Ready to Publish?</key>
|
||||
<key alias="readyToSave">Ready to Save?</key>
|
||||
<key alias="sendForApproval">Send for approval</key>
|
||||
@@ -1239,7 +1240,8 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
]]></key>
|
||||
<key alias="contentPublishedFailedByParent"><![CDATA[
|
||||
%0% can not be published, because a parent page is not published.
|
||||
]]></key>
|
||||
]]></key>
|
||||
<key alias="contentPublishedFailedByMissingName"><![CDATA[%0% can not be published, because its missing a name.]]></key>
|
||||
<key alias="inProgress">Publishing in progress - please wait...</key>
|
||||
<key alias="inProgressCounter">%0% out of %1% pages have been published...</key>
|
||||
<key alias="nodePublish">%0% has been published</key>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core;
|
||||
@@ -14,11 +15,18 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
[DefaultPropertyValueConverter]
|
||||
public class MediaPickerValueConverter : PropertyValueConverterBase
|
||||
{
|
||||
// hard-coding "image" here but that's how it works at UI level too
|
||||
private const string ImageTypeAlias = "image";
|
||||
|
||||
private readonly IPublishedModelFactory _publishedModelFactory;
|
||||
private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
|
||||
|
||||
public MediaPickerValueConverter(IPublishedSnapshotAccessor publishedSnapshotAccessor)
|
||||
public MediaPickerValueConverter(IPublishedSnapshotAccessor publishedSnapshotAccessor,
|
||||
IPublishedModelFactory publishedModelFactory)
|
||||
{
|
||||
_publishedSnapshotAccessor = publishedSnapshotAccessor ?? throw new ArgumentNullException(nameof(publishedSnapshotAccessor));
|
||||
_publishedSnapshotAccessor = publishedSnapshotAccessor ??
|
||||
throw new ArgumentNullException(nameof(publishedSnapshotAccessor));
|
||||
_publishedModelFactory = publishedModelFactory;
|
||||
}
|
||||
|
||||
public override bool IsConverter(PublishedPropertyType propertyType)
|
||||
@@ -31,11 +39,13 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
var isMultiple = IsMultipleDataType(propertyType.DataType);
|
||||
var isOnlyImages = IsOnlyImagesDataType(propertyType.DataType);
|
||||
|
||||
// hard-coding "image" here but that's how it works at UI level too
|
||||
|
||||
return isMultiple
|
||||
? (isOnlyImages ? typeof(IEnumerable<>).MakeGenericType(ModelType.For("image")) : typeof(IEnumerable<IPublishedContent>))
|
||||
: (isOnlyImages ? ModelType.For("image") : typeof(IPublishedContent));
|
||||
? isOnlyImages
|
||||
? typeof(IEnumerable<>).MakeGenericType(ModelType.For(ImageTypeAlias))
|
||||
: typeof(IEnumerable<IPublishedContent>)
|
||||
: isOnlyImages
|
||||
? ModelType.For(ImageTypeAlias)
|
||||
: typeof(IPublishedContent);
|
||||
}
|
||||
|
||||
public override PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType)
|
||||
@@ -53,7 +63,8 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
return config.OnlyImages;
|
||||
}
|
||||
|
||||
public override object ConvertSourceToIntermediate(IPublishedElement owner, PublishedPropertyType propertyType, object source, bool preview)
|
||||
public override object ConvertSourceToIntermediate(IPublishedElement owner, PublishedPropertyType propertyType,
|
||||
object source, bool preview)
|
||||
{
|
||||
if (source == null) return null;
|
||||
|
||||
@@ -64,15 +75,19 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
return nodeIds;
|
||||
}
|
||||
|
||||
public override object ConvertIntermediateToObject(IPublishedElement owner, PublishedPropertyType propertyType, PropertyCacheLevel cacheLevel, object source, bool preview)
|
||||
public override object ConvertIntermediateToObject(IPublishedElement owner, PublishedPropertyType propertyType,
|
||||
PropertyCacheLevel cacheLevel, object source, bool preview)
|
||||
{
|
||||
if (source == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var isMultiple = IsMultipleDataType(propertyType.DataType);
|
||||
var isOnlyImages = IsOnlyImagesDataType(propertyType.DataType);
|
||||
|
||||
var udis = (Udi[]) source;
|
||||
var mediaItems = isOnlyImages
|
||||
? _publishedModelFactory.CreateModelList(ImageTypeAlias)
|
||||
: new List<IPublishedContent>();
|
||||
|
||||
if (source == null) return isMultiple ? mediaItems : null;
|
||||
|
||||
var udis = (Udi[])source;
|
||||
var mediaItems = new List<IPublishedContent>();
|
||||
if (udis.Any())
|
||||
{
|
||||
foreach (var udi in udis)
|
||||
@@ -84,12 +99,15 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
mediaItems.Add(item);
|
||||
}
|
||||
|
||||
if (IsMultipleDataType(propertyType.DataType))
|
||||
return mediaItems;
|
||||
return mediaItems.FirstOrDefault();
|
||||
return isMultiple ? mediaItems : FirstOrDefault(mediaItems);
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
private object FirstOrDefault(IList mediaItems)
|
||||
{
|
||||
return mediaItems.Count == 0 ? null : mediaItems[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user