From ad8c309f3d18c6fe8bdf1a91b98135d973bd748c Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 26 Sep 2018 16:27:34 +0200 Subject: [PATCH 1/7] Variant-contextual breadcrumb --- .../components/content/edit.controller.js | 9 +++++- .../src/common/resources/entity.resource.js | 8 +++-- src/Umbraco.Web/Editors/EntityController.cs | 16 ++++++---- .../Models/Mapping/EntityMapperProfile.cs | 29 +++++++++++++++++++ 4 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js index dbebf840f1..1bdc05691b 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js @@ -41,10 +41,17 @@ //We fetch all ancestors of the node to generate the footer breadcrumb navigation if (!$scope.page.isNew) { if (content.parentId && content.parentId !== -1) { - entityResource.getAncestors(content.id, "document") + entityResource.getAncestors(content.id, "document", $scope.culture) .then(function (anc) { $scope.ancestors = anc; }); + $scope.$watch('culture', + function(value, oldValue) { + entityResource.getAncestors(content.id, "document", value) + .then(function (anc) { + $scope.ancestors = anc; + }); + }); } } diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js index 6647c6fb7f..f864696873 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js @@ -288,17 +288,19 @@ function entityResource($q, $http, umbRequestHelper) { * Gets ancestor entities for a given item * * - * @param {string} type Object type name + * @param {string} type Object type name + * @param {string} culture Culture * @returns {Promise} resourcePromise object containing the entity. * */ - getAncestors: function (id, type) { + getAncestors: function (id, type, culture) { + if (culture === undefined) culture = ""; return umbRequestHelper.resourcePromise( $http.get( umbRequestHelper.getApiUrl( "entityApiBaseUrl", "GetAncestors", - [{id: id}, {type: type}])), + [{ id: id }, { type: type }, { culture: culture }])), 'Failed to retrieve ancestor data for id ' + id); }, diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index 313693c08c..4f1daba62c 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -10,15 +10,18 @@ using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; using System.Linq; using System.Net.Http; +using System.Net.Http.Formatting; using Umbraco.Core.Models; using Constants = Umbraco.Core.Constants; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using System.Web.Http.Controllers; using Umbraco.Core.Models.Entities; using Umbraco.Core.Xml; +using Umbraco.Web.Models.Mapping; using Umbraco.Web.Search; using Umbraco.Web.Trees; using Umbraco.Web.WebApi; +using Umbraco.Web.WebApi.Filters; namespace Umbraco.Web.Editors { @@ -211,7 +214,7 @@ namespace Umbraco.Web.Editors } } - var ancestors = GetAncestors(id, type); + var ancestors = GetResultForAncestors(id, type); //if content, skip the first node for replicating NiceUrl defaults if(type == UmbracoEntityTypes.Document) { @@ -588,9 +591,10 @@ namespace Umbraco.Web.Editors } } - public IEnumerable GetAncestors(int id, UmbracoEntityTypes type) + [HttpQueryStringFilter("queryStrings")] + public IEnumerable GetAncestors(int id, UmbracoEntityTypes type, FormDataCollection queryStrings) { - return GetResultForAncestors(id, type); + return GetResultForAncestors(id, type, queryStrings); } /// @@ -632,7 +636,7 @@ namespace Umbraco.Web.Editors } } - private IEnumerable GetResultForAncestors(int id, UmbracoEntityTypes entityType) + private IEnumerable GetResultForAncestors(int id, UmbracoEntityTypes entityType, FormDataCollection queryStrings = null) { var objectType = ConvertToObjectType(entityType); if (objectType.HasValue) @@ -672,12 +676,14 @@ namespace Umbraco.Web.Editors ids = lids.ToArray(); } + var culture = queryStrings?.GetValue("culture"); + return ids.Length == 0 ? Enumerable.Empty() : Services.EntityService.GetAll(objectType.Value, ids) .WhereNotNull() .OrderBy(x => x.Level) - .Select(Mapper.Map); + .Select(x => Mapper.Map(x, opts => { opts.SetCulture(culture);})); } //now we need to convert the unknown ones switch (entityType) diff --git a/src/Umbraco.Web/Models/Mapping/EntityMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/EntityMapperProfile.cs index 917f61a429..bfabfd799a 100644 --- a/src/Umbraco.Web/Models/Mapping/EntityMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/EntityMapperProfile.cs @@ -25,6 +25,7 @@ namespace Umbraco.Web.Models.Mapping var contentTypeUdiResolver = new ContentTypeUdiResolver(); CreateMap() + .ForMember(dest => dest.Name, opt => opt.ResolveUsing()) .ForMember(dest => dest.Udi, opt => opt.MapFrom(src => Udi.Create(ObjectTypes.GetUdiType(src.NodeObjectType), src.Key))) .ForMember(dest => dest.Icon, opt => opt.MapFrom(src => GetContentTypeIcon(src))) .ForMember(dest => dest.Trashed, opt => opt.MapFrom(src => src.Trashed)) @@ -179,5 +180,33 @@ namespace Umbraco.Web.Models.Mapping CreateMap, IEnumerable>() .ConvertUsing(results => results.Select(Mapper.Map).ToList()); } + + /// + /// Resolves the name for a content item/content variant + /// + private class NameResolver : IValueResolver + { + public string Resolve(EntitySlim source, EntityBasic destination, string destMember, ResolutionContext context) + { + if (!(source is DocumentEntitySlim doc)) + return source.Name; + + // invariant = only 1 name + if (!doc.Variations.VariesByCulture()) return source.Name; + + // variant = depends on culture + var culture = context.Options.GetCulture(); + + // if there's no culture here, the issue is somewhere else (UI, whatever) - throw! + if (culture == null) + //throw new InvalidOperationException("Missing culture in mapping options."); + // fixme we should throw, but this is used in various places that won't set a culture yet + return source.Name; + + // if we don't have a name for a culture, it means the culture is not available, and + // hey we should probably not be mapping it, but it's too late, return a fallback name + return doc.CultureNames.TryGetValue(culture, out var name) && !name.IsNullOrWhiteSpace() ? name : $"(({source.Name}))"; + } + } } } From b1be86c9d666ab486cdcc010d6bc62795aaeaa53 Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 28 Sep 2018 16:51:44 +0200 Subject: [PATCH 2/7] fix nuspec, app_browsers is gone --- build/NuSpecs/UmbracoCms.nuspec | 1 - 1 file changed, 1 deletion(-) diff --git a/build/NuSpecs/UmbracoCms.nuspec b/build/NuSpecs/UmbracoCms.nuspec index 7a7f672ea6..3f649b5116 100644 --- a/build/NuSpecs/UmbracoCms.nuspec +++ b/build/NuSpecs/UmbracoCms.nuspec @@ -40,7 +40,6 @@ - From 3382a4efdb80d319cf13c87f5284b9c363844995 Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 27 Sep 2018 19:25:58 +0200 Subject: [PATCH 3/7] Fix nested content breaking issue --- .../propertyeditors/nestedcontent/nestedcontent.controller.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js index 0a44a9fcaa..c007d1b409 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js @@ -279,7 +279,8 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop _.each($scope.model.config.contentTypes, function (contentType) { contentResource.getScaffold(-20, contentType.ncAlias).then(function (scaffold) { // remove all tabs except the specified tab - var tab = _.find(scaffold.tabs, function (tab) { + var tabs = scaffold.variants[0].tabs; + var tab = _.find(tabs, function (tab) { return tab.id != 0 && (tab.alias.toLowerCase() == contentType.ncTabAlias.toLowerCase() || contentType.ncTabAlias == ""); }); scaffold.tabs = []; From 621ef28680c2e470ec86253f3aecbe0be0e7223d Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 27 Sep 2018 19:50:45 +0200 Subject: [PATCH 4/7] Fix PublishedElementModel, must be abstract --- .../Models/PublishedContent/PublishedElementModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedElementModel.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedElementModel.cs index e0514b38d7..882109f908 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedElementModel.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedElementModel.cs @@ -6,7 +6,7 @@ /// /// Every strongly-typed property set class should inherit from PublishedElementModel /// (or inherit from a class that inherits from... etc.) so they are picked by the factory. - public class PublishedElementModel : PublishedElementWrapped + public abstract class PublishedElementModel : PublishedElementWrapped { /// /// From b572407084616024adcbba722b76bcad1e82f4ed Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 28 Sep 2018 16:50:51 +0200 Subject: [PATCH 5/7] Fix nested content when empty or null --- .../NestedContentManyValueConverter.cs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentManyValueConverter.cs b/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentManyValueConverter.cs index 7cd631d663..fee6ee8f8a 100644 --- a/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentManyValueConverter.cs +++ b/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentManyValueConverter.cs @@ -55,19 +55,18 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters { using (_proflog.DebugDuration($"ConvertPropertyToNestedContent ({propertyType.DataType.Id})")) { - var value = (string)inter; - if (string.IsNullOrWhiteSpace(value)) return null; - - var objects = JsonConvert.DeserializeObject>(value); - if (objects.Count == 0) - return Enumerable.Empty(); - var configuration = propertyType.DataType.ConfigurationAs(); var contentTypes = configuration.ContentTypes; var elements = contentTypes.Length > 1 ? new List() : PublishedModelFactory.CreateModelList(contentTypes[0].Alias); + var value = (string)inter; + if (string.IsNullOrWhiteSpace(value)) return elements; + + var objects = JsonConvert.DeserializeObject>(value); + if (objects.Count == 0) return elements; + foreach (var sourceObject in objects) { var element = ConvertToElement(sourceObject, referenceCacheLevel, preview); From a33ccd15c6c92bf71360650904d52c13112b2ee3 Mon Sep 17 00:00:00 2001 From: Matthew-Wise Date: Sun, 30 Sep 2018 15:02:09 +0100 Subject: [PATCH 6/7] Convertion of assigndomain2.aspx to angular (#2897) --- .../validation/valmulti.directive.js | 27 ++++ .../src/common/resources/content.resource.js | 108 ++++++++++----- .../src/views/content/assigndomain.html | 84 +++++++++--- .../content.assigndomain.controller.js | 123 +++++++++++++++++- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 1 - .../Umbraco/dialogs/AssignDomain2.aspx | 79 ----------- src/Umbraco.Web/Editors/ContentController.cs | 14 ++ .../ContentDomainsAndCulture.cs | 11 ++ src/Umbraco.Web/Umbraco.Web.csproj | 1 + 9 files changed, 307 insertions(+), 141 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/validation/valmulti.directive.js delete mode 100644 src/Umbraco.Web.UI/Umbraco/dialogs/AssignDomain2.aspx create mode 100644 src/Umbraco.Web/Models/ContentEditing/ContentDomainsAndCulture.cs diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valmulti.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valmulti.directive.js new file mode 100644 index 0000000000..1aca4c2528 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valmulti.directive.js @@ -0,0 +1,27 @@ +(function () { + /** + * @ngdoc directive + * @name umbraco.directives.directive:multi + * @restrict A + * @description Used on input fields when you want to validate multiple fields at once. + **/ + function multi($parse, $rootScope) { + return { + restrict: 'A', + require: 'ngModel', + link: function (scope, elem, attrs, ngModelCtrl) { + var validate = $parse(attrs.multi)(scope); + ngModelCtrl.$viewChangeListeners.push(function () { + // ngModelCtrl.$setValidity('multi', validate()); + $rootScope.$broadcast('multi:valueChanged'); + }); + + var deregisterListener = scope.$on('multi:valueChanged', function (event) { + ngModelCtrl.$setValidity('multi', validate()); + }); + scope.$on('$destroy', deregisterListener); // optional, only required for $rootScope.$on + } + }; + } + angular.module('umbraco.directives.validation').directive('multi', ['$parse', '$rootScope', multi]); +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js index 089637521a..073682b59f 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js @@ -242,6 +242,44 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { { id: id, culture: culture })), 'Failed to publish content with id ' + id); }, + /** + * @ngdoc method + * @name umbraco.resources.contentResource#getCultureAndDomains + * @methodOf umbraco.resources.contentResource + * + * @description + * Gets the culture and hostnames for a content item with the given Id + * + * ##usage + *
+          * contentResource.getCultureAndDomains(1234)
+          *    .then(function(data) {
+          *        alert(data.Domains, data.Language);
+          *    });
+          * 
+ * @param {Int} id the ID of the node to get the culture and domains for. + * @returns {Promise} resourcePromise object. + * + */ + getCultureAndDomains: function (id) { + if (!id) { + throw "id cannot be null"; + } + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "GetCultureAndDomains", { id: id })), + 'Failed to retreive culture and hostnames for ' + id); + }, + saveLanguageAndDomains: function (model) { + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "PostSaveLanguageAndDomains"), + model)); + }, /** * @ngdoc method * @name umbraco.resources.contentResource#emptyRecycleBin @@ -334,26 +372,26 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { */ getById: function (id) { return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "contentApiBaseUrl", - "GetById", - { id: id })), - 'Failed to retrieve data for content id ' + id) - .then(function(result) { + $http.get( + umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "GetById", + { id: id })), + 'Failed to retrieve data for content id ' + id) + .then(function (result) { return $q.when(umbDataFormatter.formatContentGetData(result)); }); }, getBlueprintById: function (id) { return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "contentApiBaseUrl", - "GetBlueprintById", - [{ id: id }])), - 'Failed to retrieve data for content id ' + id) - .then(function(result) { + $http.get( + umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "GetBlueprintById", + [{ id: id }])), + 'Failed to retrieve data for content id ' + id) + .then(function (result) { return $q.when(umbDataFormatter.formatContentGetData(result)); }); }, @@ -410,15 +448,15 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { }); return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "contentApiBaseUrl", - "GetByIds", - idQuery)), - 'Failed to retrieve data for content with multiple ids') + $http.get( + umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "GetByIds", + idQuery)), + 'Failed to retrieve data for content with multiple ids') .then(function (result) { //each item needs to be re-formatted - _.each(result, function(r) { + _.each(result, function (r) { umbDataFormatter.formatContentGetData(r) }); return $q.when(result); @@ -461,13 +499,13 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { getScaffold: function (parentId, alias) { return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "contentApiBaseUrl", - "GetEmpty", - [{ contentTypeAlias: alias }, { parentId: parentId }])), - 'Failed to retrieve data for empty content item type ' + alias) - .then(function(result) { + $http.get( + umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "GetEmpty", + [{ contentTypeAlias: alias }, { parentId: parentId }])), + 'Failed to retrieve data for empty content item type ' + alias) + .then(function (result) { return $q.when(umbDataFormatter.formatContentGetData(result)); }); }, @@ -475,13 +513,13 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { getBlueprintScaffold: function (parentId, blueprintId) { return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "contentApiBaseUrl", - "GetEmpty", - [{ blueprintId: blueprintId }, { parentId: parentId }])), - 'Failed to retrieve blueprint for id ' + blueprintId) - .then(function(result) { + $http.get( + umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "GetEmpty", + [{ blueprintId: blueprintId }, { parentId: parentId }])), + 'Failed to retrieve blueprint for id ' + blueprintId) + .then(function (result) { return $q.when(umbDataFormatter.formatContentGetData(result)); }); }, diff --git a/src/Umbraco.Web.UI.Client/src/views/content/assigndomain.html b/src/Umbraco.Web.UI.Client/src/views/content/assigndomain.html index 0283459483..e12bac75a6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/assigndomain.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/assigndomain.html @@ -1,24 +1,70 @@ -
-
- -

UI magic to be done...

-
-
+
+
+ +
Culture
+ + +
+ +
Domains
+
+ + + +
+ + + + + + + + + + + + + + +
+
+ + + + + + + + + + +
+
+ + +
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/content/content.assigndomain.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/content.assigndomain.controller.js index 6f72543cfc..e7fe5c6833 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/content.assigndomain.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/content.assigndomain.controller.js @@ -1,17 +1,126 @@ (function () { "use strict"; - function AssignDomainController($scope) { - + function AssignDomainController($scope, localizationService, languageResource, contentResource) { var vm = this; vm.closeDialog = closeDialog; - - function closeDialog() { - $scope.nav.hideDialog(); + vm.addDomain = addDomain; + vm.removeDomain = removeDomain; + vm.save = save; + vm.validateDomain = validateDomain; + vm.languages = []; + vm.domains = []; + vm.language = null; + vm.domainPattern = /^(http[s]?:\/\/)?([-\w]+(\.[-\w]+)*)(:\d+)?(\/[-\w]*|-)?$/gi; //TODO: This regex is not working as it should. + function activate() { + languageResource.getAll().then(function (langs) { + vm.languages = langs; + var defLang = langs.filter(function (l) { + return l.isDefault; + }); + + if (defLang.length > 0) { + vm.defaultLanguage = defLang[0]; + } + else { + vm.defaultLanguage = langs[0]; + } + getCultureAndDomains(); + }); + + localizationService.localize("assignDomain_inherit").then(function (value) { + vm.inherit = value; + }); + } + function getCultureAndDomains () { + contentResource.getCultureAndDomains($scope.currentNode.id) + .then(function (data) { + if (data.Language !== "undefined") { + var lang = vm.languages.filter(function (l) { + return matchLanguageById(l, data.Language.Id); + + }); + if (lang.length > 0) { + vm.language = lang[0]; + } + } + vm.domains = data.Domains.map(function (d) { + var matchedLangs = vm.languages.filter(function (l) { + return matchLanguageById(l, d.Language); + + }); + return { + Name: d.Name, + Lang: matchedLangs.length > 0 ? matchedLangs[0] : vm.defaultLanguage + } + }); + }); + } + + function matchLanguageById(language, id) { + return language.Id === id; + } + + function closeDialog() { + $scope.nav.hideDialog(); + } + + function addDomain() { + vm.domains.push({ + Name: '', + Lang: vm.defaultLanguage + }); + } + + function removeDomain(index) { + vm.domains.splice(index, 1); + } + + function validateDomain() { + var valid = true, duplicateTest = {}; + if (vm.domains.length > 1) { + + vm.domains.map(function (d, index) { + if (d.Name in duplicateTest) { + valid = false; + } + else { + duplicateTest[d.Name] = index; + } + }); + } + return valid; + } + + function save() { + + if (vm.domainForm.$valid) { + var data = { + NodeId: $scope.currentNode.id, + Domains: vm.domains.map(function (d) { + return { + Name: d.Name, + Lang: d.Lang.id + }; + }), + Language: vm.language != null ? vm.language.id : 0 + }; + console.log(data); + contentResource.saveLanguageAndDomains(data).then(function () { + closeDialog(); + }, function (e) { + console.log(e); //TODO: not sure how best to handle this case + }); + } + else { + console.log('not valid'); + } + } + + activate(); } - angular.module("umbraco").controller("Umbraco.Editors.Content.AssignDomainController", AssignDomainController); +})(); -})(); \ No newline at end of file diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 69a3baf612..413305d4dc 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -333,7 +333,6 @@ - ASPXCodeBehind diff --git a/src/Umbraco.Web.UI/Umbraco/dialogs/AssignDomain2.aspx b/src/Umbraco.Web.UI/Umbraco/dialogs/AssignDomain2.aspx deleted file mode 100644 index 60601d1ac0..0000000000 --- a/src/Umbraco.Web.UI/Umbraco/dialogs/AssignDomain2.aspx +++ /dev/null @@ -1,79 +0,0 @@ -<%@ Page Language="c#" MasterPageFile="../masterpages/umbracoDialog.Master" Codebehind="AssignDomain2.aspx.cs" AutoEventWireup="True" Inherits="umbraco.dialogs.AssignDomain2" %> -<%@ Import Namespace="Umbraco.Web" %> -<%@ Register TagPrefix="umb" Namespace="ClientDependency.Core.Controls" Assembly="ClientDependency.Core" %> -<%@ Register TagPrefix="cc1" Namespace="Umbraco.Web._Legacy.Controls" Assembly="Umbraco.Web" %> - - - - - - - - - - - -
- - -
- - - - - - - - - - - <%=Services.TextService.Localize("assignDomain/domainHelp") %> - - - - - - - - - - - - - - - -
<%=Services.TextService.Localize("assignDomain/domain") %><%=Services.TextService.Localize("assignDomain/language") %> -
-
- - - - - - -
- -
- - - - - -
diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index fbff9bdaa1..8e46b86105 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -56,6 +56,8 @@ namespace Umbraco.Web.Editors private readonly PropertyEditorCollection _propertyEditors; private readonly Lazy> _allLangs; + public object Domains { get; private set; } + public ContentController(IPublishedSnapshotService publishedSnapshotService, PropertyEditorCollection propertyEditors) { if (publishedSnapshotService == null) throw new ArgumentNullException(nameof(publishedSnapshotService)); @@ -1146,6 +1148,18 @@ namespace Umbraco.Web.Editors } } + public ContentDomainsAndCulture GetCultureAndDomains(int id) + { + var nodeDomains = Services.DomainService.GetAssignedDomains(id, true).ToArray(); + var wildcard = nodeDomains.FirstOrDefault(d => d.IsWildcard); + var domains = nodeDomains.Where(d => !d.IsWildcard).Select(d => new DomainDisplay(d.DomainName, d.LanguageId.GetValueOrDefault(0))); + return new ContentDomainsAndCulture + { + Domains = domains, + Language = wildcard == null || !wildcard.LanguageId.HasValue ? "undefined" : wildcard.LanguageId.ToString() + }; + } + [HttpPost] public DomainSave PostSaveLanguageAndDomains(DomainSave model) { diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentDomainsAndCulture.cs b/src/Umbraco.Web/Models/ContentEditing/ContentDomainsAndCulture.cs new file mode 100644 index 0000000000..9f0750cb7c --- /dev/null +++ b/src/Umbraco.Web/Models/ContentEditing/ContentDomainsAndCulture.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; + +namespace Umbraco.Web.Models.ContentEditing +{ + public class ContentDomainsAndCulture + { + public IEnumerable Domains { get; set; } + + public string Language { get; internal set; } + } +} diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index ec4ccae121..c2a420b3d6 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -163,6 +163,7 @@ + From d56d39ee1a0377f7f97ab3b916bb990b2634bc98 Mon Sep 17 00:00:00 2001 From: Stephan Date: Sun, 30 Sep 2018 19:09:06 +0200 Subject: [PATCH 7/7] Fix nested content validation when null --- src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs index 4cb8fde97a..9739b7a30b 100644 --- a/src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs @@ -272,6 +272,9 @@ namespace Umbraco.Web.PropertyEditors public IEnumerable Validate(object rawValue, string valueType, object dataTypeConfiguration) { + if (rawValue == null) + yield break; + var value = JsonConvert.DeserializeObject>(rawValue.ToString()); if (value == null) yield break;