From a33ccd15c6c92bf71360650904d52c13112b2ee3 Mon Sep 17 00:00:00 2001 From: Matthew-Wise Date: Sun, 30 Sep 2018 15:02:09 +0100 Subject: [PATCH] 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 @@ +