From be4ea93d1277b53146cd9c7ae4b8c68ab0754806 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 1 May 2018 18:17:07 +1000 Subject: [PATCH] U4-11289 Tracking the currently selected language in the main tree --- .../Implement/EntityRepository.cs | 13 +++-- .../application/umbsections.directive.js | 9 ++-- .../components/content/edit.controller.js | 12 ++--- .../editor/umbeditorheader.directive.js | 2 +- .../src/common/resources/content.resource.js | 6 +-- .../services/contenteditinghelper.service.js | 8 +-- .../src/common/services/navigation.service.js | 19 +++++++ .../services/umbdataformatter.service.js | 4 +- .../src/controllers/navigation.controller.js | 52 +++++++++++++------ src/Umbraco.Web.UI.Client/src/routes.js | 1 - .../confirmroutechange.controller.js | 4 +- .../common/overlays/user/user.controller.js | 2 +- .../views/content/content.edit.controller.js | 2 +- .../src/views/content/edit.html | 2 +- src/Umbraco.Web/Editors/ContentController.cs | 52 ++++++++----------- .../Models/ContentEditing/ContentItemSave.cs | 4 +- .../ContentEditing/ContentVariationPublish.cs | 4 +- .../Trees/ContentTreeController.cs | 2 +- .../Trees/ContentTreeControllerBase.cs | 18 +++---- .../WebApi/Binders/ContentItemBinder.cs | 6 +-- 20 files changed, 130 insertions(+), 92 deletions(-) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/EntityRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/EntityRepository.cs index 09711cf9e1..0dd7a25798 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/EntityRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/EntityRepository.cs @@ -24,9 +24,12 @@ namespace Umbraco.Core.Persistence.Repositories.Implement internal class EntityRepository : IEntityRepository { private readonly IScopeAccessor _scopeAccessor; - public EntityRepository(IScopeAccessor scopeAccessor) + private readonly ILanguageRepository _langRepository; + + public EntityRepository(IScopeAccessor scopeAccessor, ILanguageRepository langRepository) { _scopeAccessor = scopeAccessor; + _langRepository = langRepository; } protected IUmbracoDatabase Database => _scopeAccessor.AmbientScope.Database; @@ -889,17 +892,19 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// /// /// - private static EntitySlim BuildDocumentEntity(ContentEntityDto dto) + private EntitySlim BuildDocumentEntity(ContentEntityDto dto) { // EntitySlim does not track changes var entity = new DocumentEntitySlim(); BuildDocumentEntity(entity, dto); - var variantInfo = new Dictionary(); + var variantInfo = new Dictionary(StringComparer.InvariantCultureIgnoreCase); if (dto.VariationInfo != null) { foreach (var info in dto.VariationInfo) { - variantInfo[info.LanguageId] = info.Name; + var isoCode = _langRepository.GetIsoCodeById(info.LanguageId); + if (isoCode != null) + variantInfo[isoCode] = info.Name; } entity.AdditionalData["CultureNames"] = variantInfo; } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbsections.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbsections.directive.js index 0896f986e6..23664ed842 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbsections.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbsections.directive.js @@ -38,7 +38,7 @@ function sectionsDirective($timeout, $window, navigationService, treeService, se calculateWidth(); }); } - + function calculateWidth(){ $timeout(function(){ //total width minus room for avatar, search, and help icon @@ -119,9 +119,10 @@ function sectionsDirective($timeout, $window, navigationService, treeService, se } else { var lastAccessed = historyService.getLastAccessedItemForSection(section.alias); - var path = lastAccessed != null ? lastAccessed.link : section.alias; - $location.path(path).search(''); - } + var path = lastAccessed != null ? lastAccessed.link : section.alias; + $location.path(path); + } + navigationService.clearSearch(); }; 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 ffac0bf965..63bdb9c92e 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 @@ -20,7 +20,7 @@ $scope.page.listViewPath = null; $scope.page.isNew = $scope.isNew ? true : false; $scope.page.buttonGroupState = "init"; - $scope.page.languageId = $scope.languageId; + $scope.page.culture = $scope.culture; $scope.allowOpen = true; // add all editors to an editors array to support split view @@ -122,14 +122,14 @@ /** * This does the content loading and initializes everything, called on load and changing variants - * @param {any} languageId + * @param {any} culture */ - function getNode(languageId) { + function getNode(culture) { $scope.page.loading = true; //we are editing so get the content item from the server - $scope.getMethod()($scope.contentId, languageId) + $scope.getMethod()($scope.contentId, culture) .then(function (data) { $scope.content = data; @@ -258,7 +258,7 @@ else { //Browse content nodes based on the selected tree language variant - $scope.page.languageId ? getNode($scope.page.languageId) : getNode(); + $scope.page.culture ? getNode($scope.page.culture) : getNode(); } @@ -527,7 +527,7 @@ saveMethod: "&", getMethod: "&", getScaffoldMethod: "&?", - languageId: "=?" + culture: "=?" } }; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js index 6a15b0baba..9b0e0d810b 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js @@ -253,7 +253,7 @@ Use this directive to construct a header inside the main editor window. scope.selectVariant = function (event, variant) { scope.vm.dropdownOpen = false; - $location.search({ languageId: variant.language.id }); + $location.search("cculture", variant.language.culture); }; scope.openIconPicker = function() { 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 7d560d7b43..1f2a611fe5 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 @@ -314,17 +314,17 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { * * * @param {Int} id id of content item to return - * @param {Int} languageId optional ID of the language to retrieve the item in + * @param {Int} culture optional culture to retrieve the item in * @returns {Promise} resourcePromise object containing the content item. * */ - getById: function (id, languageId) { + getById: function (id, culture) { return umbRequestHelper.resourcePromise( $http.get( umbRequestHelper.getApiUrl( "contentApiBaseUrl", "GetById", - { id: id, languageId: languageId })), + { id: id, culture: culture })), 'Failed to retrieve data for content id ' + id); }, diff --git a/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js index 36a184cd95..e8e10c5d63 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js @@ -5,7 +5,7 @@ * @description A helper service for most editors, some methods are specific to content/media/member model types but most are used by * all editors to share logic and reduce the amount of replicated code among editors. **/ -function contentEditingHelper(fileManager, $q, $location, $routeParams, notificationsService, localizationService, serverValidationManager, dialogService, formHelper, appState) { +function contentEditingHelper(fileManager, $q, $location, $routeParams, notificationsService, navigationService, localizationService, serverValidationManager, dialogService, formHelper, appState) { function isValidIdentifier(id){ //empty id <= 0 @@ -596,7 +596,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica // /belle/#/content/edit/9876 (where 9876 is the new id) //clear the query strings - $location.search(""); + navigationService.clearSearch(); //change to new path $location.path("/" + $routeParams.section + "/" + $routeParams.tree + "/" + $routeParams.method + "/" + id); @@ -617,9 +617,9 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica * For some editors like scripts or entites that have names as ids, these names can change and we need to redirect * to their new paths, this is helper method to do that. */ - redirectToRenamedContent: function (id) { + redirectToRenamedContent: function (id) { //clear the query strings - $location.search(""); + navigationService.clearSearch(); //change to new path $location.path("/" + $routeParams.section + "/" + $routeParams.tree + "/" + $routeParams.method + "/" + id); //don't add a browser history for this diff --git a/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js b/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js index 257d36af31..9a19304288 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js @@ -102,6 +102,25 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo }, + /** + * @ngdoc method + * @name umbraco.services.navigationService#clearSearch + * @methodOf umbraco.services.navigationService + * + * @description + * utility to clear the querystring/search params while maintaining a known list of parameters that should be maintained throughout the app + */ + clearSearch: function () { + var retainKeys = ["mculture"]; + var currentSearch = $location.search(); + $location.search(''); + _.each(retainKeys, function (k) { + if (currentSearch[k]) { + $location.search(k, currentSearch[k]); + } + }); + }, + /** * @ngdoc method * @name umbraco.services.navigationService#load diff --git a/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js b/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js index 5ef6eae293..1888ff623d 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js @@ -333,11 +333,11 @@ function (d) { //set the selected variant if this is current if (d.current === true) { - saveModel.languageId = d.language.id; + saveModel.culture = d.language.culture; } if (d.publish === true) { saveModel.publishVariations.push({ - languageId: d.language.id, + culture: d.language.culture, segment: d.segment }); } diff --git a/src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js b/src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js index b1810ca683..00458aa6b4 100644 --- a/src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js +++ b/src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js @@ -96,10 +96,12 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar appState.setMenuState("currentNode", args.node); //not legacy, lets just set the route value and clear the query string if there is one. - $location.path(n.routePath).search(""); + $location.path(n.routePath); + navigationService.clearSearch(); } else if (n.section) { - $location.path(n.section).search(""); + $location.path(n.section); + navigationService.clearSearch(); } navigationService.hideNavigation(); @@ -236,24 +238,37 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar languageResource.getAll().then(function(languages) { $scope.languages = languages; - // make the default language selected - $scope.languages.forEach(function (language) { - if (language.isDefault) { - $scope.selectedLanguage = language; + if ($scope.languages.length > 1) { + var defaultLang = _.find($scope.languages, function (l) { + return l.isDefault; + }); + if (defaultLang) { + //set the route param + $location.search("mculture", defaultLang.culture); } - }); - }); + } + init(); + }); })); - /** - * Updates the tree's query parameters - */ - function initTree() { + function init() { + //select the current language if set in the query string + var mainCulture = $location.search().mculture; + if (mainCulture && $scope.languages && $scope.languages.length > 1) { + var found = _.find($scope.languages, function (l) { + return l.culture === mainCulture; + }); + if (found) { + //set the route param + $scope.selectedLanguage = found; + } + } + //create the custom query string param for this tree var queryParams = {}; - if ($scope.selectedLanguage && $scope.selectedLanguage.id) { - queryParams["languageId"] = $scope.selectedLanguage.id; + if ($scope.selectedLanguage && $scope.selectedLanguage.culture) { + queryParams["culture"] = $scope.selectedLanguage.culture; } var queryString = $.param(queryParams); //create the query string from the params object @@ -266,6 +281,7 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar } } + function nodeExpandedHandler(args) { //store the reference to the expanded node path if (args.node) { @@ -274,11 +290,15 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar } $scope.selectLanguage = function(language) { - $scope.selectedLanguage = language; + + $location.search("mculture", language.culture); + + //$scope.selectedLanguage = language; + // close the language selector $scope.page.languageSelectorIsOpen = false; - initTree(); //this will reset the tree params and the tree directive will pick up the changes in a $watch + init(); //re-bind language to the query string and update the tree params //execute after next digest because the internal watch on the customtreeparams needs to be bound now that we've changed it $timeout(function () { diff --git a/src/Umbraco.Web.UI.Client/src/routes.js b/src/Umbraco.Web.UI.Client/src/routes.js index 5f660cf212..e4f9852a11 100644 --- a/src/Umbraco.Web.UI.Client/src/routes.js +++ b/src/Umbraco.Web.UI.Client/src/routes.js @@ -104,7 +104,6 @@ app.config(function ($routeProvider) { resolve: doLogout() }) .when('/:section', { - //This allows us to dynamically change the template for this route since you cannot inject services into the templateUrl method. template: "
", //This controller will execute for this route, then we can execute some code in order to set the template Url diff --git a/src/Umbraco.Web.UI.Client/src/views/common/notifications/confirmroutechange.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/notifications/confirmroutechange.controller.js index c9f3cc347c..5851d30610 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/notifications/confirmroutechange.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/notifications/confirmroutechange.controller.js @@ -13,7 +13,7 @@ angular.module("umbraco").controller("Umbraco.Notifications.ConfirmRouteChangeCo // when no callback is added run the normal functionality of the discard button not.args.listener(); - $location.search(""); + navigationService.clearSearch(); //we need to break the path up into path and query var parts = not.args.path.split("?"); @@ -33,4 +33,4 @@ angular.module("umbraco").controller("Umbraco.Notifications.ConfirmRouteChangeCo notificationsService.remove(not); }; - }); \ No newline at end of file + }); diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/user/user.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/user/user.controller.js index 700b18b518..e8b1bb0f68 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/user/user.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/user/user.controller.js @@ -36,7 +36,7 @@ angular.module("umbraco") //perform the path change, if it is successful then the promise will resolve otherwise it will fail $scope.model.close(); - $location.path("/logout"); + $location.path("/logout").search(''); }; $scope.gotoHistory = function (link) { diff --git a/src/Umbraco.Web.UI.Client/src/views/content/content.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/content.edit.controller.js index e8a384c2a9..1bd924e9f0 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/content.edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/content.edit.controller.js @@ -21,7 +21,7 @@ function ContentEditController($scope, $routeParams, contentResource) { $scope.getScaffoldMethod = $routeParams.blueprintId ? scaffoldBlueprint : scaffoldEmpty; $scope.page = $routeParams.page; $scope.isNew = $routeParams.create; - $scope.languageId = $routeParams.languageId; + $scope.culture = $routeParams.cculture; } angular.module("umbraco").controller("Umbraco.Editors.Content.EditController", ContentEditController); diff --git a/src/Umbraco.Web.UI.Client/src/views/content/edit.html b/src/Umbraco.Web.UI.Client/src/views/content/edit.html index 96d80fb151..84537672d4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/edit.html @@ -7,6 +7,6 @@ get-scaffold-method="getScaffoldMethod" tree-alias="content" is-new="isNew" - language-id="languageId"> + culture="culture"> diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index b4483fc09a..efdc6c23ab 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -253,11 +253,11 @@ namespace Umbraco.Web.Editors /// Gets the content json for the content id /// /// - /// + /// /// [OutgoingEditorModelEvent] [EnsureUserPermissionForContent("id")] - public ContentItemDisplay GetById(int id, int? languageId = null) + public ContentItemDisplay GetById(int id, string culture = null) { var foundContent = GetObjectFromRequest(() => Services.ContentService.GetById(id)); if (foundContent == null) @@ -266,7 +266,7 @@ namespace Umbraco.Web.Editors return null;//irrelevant since the above throws } - var content = MapToDisplay(foundContent, GetLanguageCulture(languageId)); + var content = MapToDisplay(foundContent, culture); return content; } @@ -573,12 +573,12 @@ namespace Umbraco.Web.Editors public ContentItemDisplay PostSave([ModelBinder(typeof(ContentItemBinder))] ContentItemSave contentItem) { var contentItemDisplay = PostSaveInternal(contentItem, content => Services.ContentService.Save(contentItem.PersistedContent, Security.CurrentUser.Id)); - //ensure the active language is still selected - if (contentItem.LanguageId.HasValue) + //ensure the active culture is still selected + if (!contentItem.Culture.IsNullOrWhiteSpace()) { foreach (var contentVariation in contentItemDisplay.Variants) { - contentVariation.IsCurrent = contentVariation.Language.Id == contentItem.LanguageId; + contentVariation.IsCurrent = contentVariation.Language.IsoCode.InvariantEquals(contentItem.Culture); } } return contentItemDisplay; @@ -606,7 +606,7 @@ namespace Umbraco.Web.Editors { //ok, so the absolute mandatory data is invalid and it's new, we cannot actually continue! // add the modelstate to the outgoing object and throw a validation message - var forDisplay = MapToDisplay(contentItem.PersistedContent, GetLanguageCulture(contentItem.LanguageId)); + var forDisplay = MapToDisplay(contentItem.PersistedContent, contentItem.Culture); forDisplay.Errors = ModelState.ToErrorDictionary(); throw new HttpResponseException(Request.CreateValidationErrorResponse(forDisplay)); @@ -643,30 +643,30 @@ namespace Umbraco.Web.Editors else { //publish the item and check if it worked, if not we will show a diff msg below - contentItem.PersistedContent.TryPublishValues(GetLanguageCulture(contentItem.LanguageId)); //we are not checking for a return value here because we've already pre-validated the property values + contentItem.PersistedContent.TryPublishValues(contentItem.Culture); //we are not checking for a return value here because we've already pre-validated the property values //check if we are publishing other variants and validate them - var allLangs = Services.LocalizationService.GetAllLanguages().ToDictionary(x => x.Id, x => x); - var variantsToValidate = contentItem.PublishVariations.Where(x => x.LanguageId != contentItem.LanguageId).ToList(); + var allLangs = Services.LocalizationService.GetAllLanguages().ToDictionary(x => x.IsoCode, x => x, StringComparer.InvariantCultureIgnoreCase); + var variantsToValidate = contentItem.PublishVariations.Where(x => !x.Culture.InvariantEquals(contentItem.Culture)).ToList(); foreach (var publishVariation in variantsToValidate) { - if (!contentItem.PersistedContent.TryPublishValues(GetLanguageCulture(publishVariation.LanguageId))) + if (!contentItem.PersistedContent.TryPublishValues(publishVariation.Culture)) { - var errMsg = Services.TextService.Localize("speechBubbles/contentLangValidationError", new[] {allLangs[publishVariation.LanguageId].CultureName}); - ModelState.AddModelError("publish_variant_" + publishVariation.LanguageId + "_", errMsg); + var errMsg = Services.TextService.Localize("speechBubbles/contentLangValidationError", new[] {allLangs[publishVariation.Culture].CultureName}); + ModelState.AddModelError("publish_variant_" + publishVariation.Culture + "_", errMsg); } } //validate any mandatory variants that are not in the list var mandatoryLangs = Mapper.Map, IEnumerable>(allLangs.Values) - .Where(x => variantsToValidate.All(v => v.LanguageId != x.Id)) //don't include variants above - .Where(x => x.Id != contentItem.LanguageId) //don't include the current variant + .Where(x => variantsToValidate.All(v => !v.Culture.InvariantEquals(x.IsoCode))) //don't include variants above + .Where(x => !x.IsoCode.InvariantEquals(contentItem.Culture)) //don't include the current variant .Where(x => x.Mandatory); foreach (var lang in mandatoryLangs) { - if (contentItem.PersistedContent.Validate(GetLanguageCulture(lang.Id)).Length > 0) + if (contentItem.PersistedContent.Validate(lang.IsoCode).Length > 0) { - var errMsg = Services.TextService.Localize("speechBubbles/contentReqLangValidationError", new[]{allLangs[lang.Id].CultureName}); + var errMsg = Services.TextService.Localize("speechBubbles/contentReqLangValidationError", new[]{allLangs[lang.IsoCode].CultureName}); ModelState.AddModelError("publish_variant_" + lang.Id + "_", errMsg); } } @@ -676,7 +676,7 @@ namespace Umbraco.Web.Editors } //get the updated model - var display = MapToDisplay(contentItem.PersistedContent, GetLanguageCulture(contentItem.LanguageId)); + var display = MapToDisplay(contentItem.PersistedContent, contentItem.Culture); //lasty, if it is not valid, add the modelstate to the outgoing object and throw a 403 HandleInvalidModelState(display); @@ -954,10 +954,9 @@ namespace Umbraco.Web.Editors if (contentItem.Name.IsNullOrWhiteSpace() == false) { //set the name according to the culture settings - if (contentItem.LanguageId.HasValue && contentItem.PersistedContent.ContentType.Variations.HasFlag(ContentVariation.CultureNeutral)) + if (!contentItem.Culture.IsNullOrWhiteSpace() && contentItem.PersistedContent.ContentType.Variations.HasFlag(ContentVariation.CultureNeutral)) { - var culture = Services.LocalizationService.GetLanguageById(contentItem.LanguageId.Value).IsoCode; - contentItem.PersistedContent.SetName(culture, contentItem.Name); + contentItem.PersistedContent.SetName(contentItem.Culture, contentItem.Name); } else { @@ -990,8 +989,8 @@ namespace Umbraco.Web.Editors base.MapPropertyValues( contentItem, - (save, property) => property.GetValue(GetLanguageCulture(save.LanguageId)), //get prop val - (save, property, v) => property.SetValue(v, GetLanguageCulture(save.LanguageId))); //set prop val + (save, property) => property.GetValue(save.Culture), //get prop val + (save, property, v) => property.SetValue(v, save.Culture)); //set prop val } /// @@ -1199,11 +1198,6 @@ namespace Umbraco.Web.Editors return display; } - - private string GetLanguageCulture(int? languageId) - { - if (languageId == null) return null; - return Core.Composing.Current.Services.LocalizationService.GetLanguageById(languageId.Value).IsoCode; // fixme optimize! - } + } } diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentItemSave.cs b/src/Umbraco.Web/Models/ContentEditing/ContentItemSave.cs index ca410100ec..01d1a50460 100644 --- a/src/Umbraco.Web/Models/ContentEditing/ContentItemSave.cs +++ b/src/Umbraco.Web/Models/ContentEditing/ContentItemSave.cs @@ -15,8 +15,8 @@ namespace Umbraco.Web.Models.ContentEditing /// /// The language Id for the content variation being saved /// - [DataMember(Name = "languageId")] - public int? LanguageId { get; set; } //TODO: Change this to ContentVariationPublish, but this will all change anyways when we can edit all variants at once + [DataMember(Name = "culture")] + public string Culture { get; set; } //TODO: Change this to ContentVariationPublish, but this will all change anyways when we can edit all variants at once /// /// The template alias to save diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentVariationPublish.cs b/src/Umbraco.Web/Models/ContentEditing/ContentVariationPublish.cs index aefc487e7c..71c4672ccb 100644 --- a/src/Umbraco.Web/Models/ContentEditing/ContentVariationPublish.cs +++ b/src/Umbraco.Web/Models/ContentEditing/ContentVariationPublish.cs @@ -8,9 +8,9 @@ namespace Umbraco.Web.Models.ContentEditing /// public class ContentVariationPublish { - [DataMember(Name = "languageId", IsRequired = true)] + [DataMember(Name = "culture", IsRequired = true)] [Required] - public int LanguageId { get; set; } + public string Culture { get; set; } [DataMember(Name = "segment")] public string Segment { get; set; } diff --git a/src/Umbraco.Web/Trees/ContentTreeController.cs b/src/Umbraco.Web/Trees/ContentTreeController.cs index 53528484d1..ad190fe8ed 100644 --- a/src/Umbraco.Web/Trees/ContentTreeController.cs +++ b/src/Umbraco.Web/Trees/ContentTreeController.cs @@ -47,7 +47,7 @@ namespace Umbraco.Web.Trees /// protected override TreeNode GetSingleTreeNode(IEntitySlim entity, string parentId, FormDataCollection queryStrings) { - var langId = queryStrings["languageId"].TryConvertTo(); + var langId = queryStrings["culture"].TryConvertTo(); var allowedUserOptions = GetAllowedUserMenuItemsForNode(entity); if (CanUserAccessNode(entity, allowedUserOptions, langId.Success ? langId.Result : null)) diff --git a/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs b/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs index 4e7b78efe9..0c0308a471 100644 --- a/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs +++ b/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs @@ -149,8 +149,8 @@ namespace Umbraco.Web.Trees // get child entities - if id is root, but user's start nodes do not contain the // root node, this returns the start nodes instead of root's children - var langId = queryStrings["languageId"].TryConvertTo(); - var entities = GetChildEntities(id, langId.Success ? langId.Result : null).ToList(); + var culture = queryStrings["culture"].TryConvertTo(); + var entities = GetChildEntities(id, culture.Success ? culture.Result : null).ToList(); nodes.AddRange(entities.Select(x => GetSingleTreeNodeWithAccessCheck(x, id, queryStrings)).Where(x => x != null)); // if the user does not have access to the root node, what we have is the start nodes, @@ -182,7 +182,7 @@ namespace Umbraco.Web.Trees protected abstract UmbracoObjectTypes UmbracoObjectType { get; } - protected IEnumerable GetChildEntities(string id, int? langId) + protected IEnumerable GetChildEntities(string id, string culture) { // try to parse id as an integer else use GetEntityFromId // which will grok Guids, Udis, etc and let use obtain the id @@ -211,7 +211,7 @@ namespace Umbraco.Web.Trees } //This should really never be null, but we'll error check anyways - var currLangId = langId ?? Services.LocalizationService.GetDefaultLanguageId(); + culture = culture ?? Services.LocalizationService.GetDefaultLanguageIsoCode(); //Try to see if there is a variant name for the current language for the item and set the name accordingly. //If any of this fails, the tree node name will remain the default invariant culture name. @@ -219,14 +219,14 @@ namespace Umbraco.Web.Trees //fixme - what if there is no name found at all ? This could occur if the doc type is variant and the user fills in all language values, then creates a new lang and sets it as the default //fixme - what if the user changes this document type to not allow culture variants after it's already been created with culture variants, this means we'll be displaying the culture variant name when in fact we should be displaying the invariant name... but that would be null - if (currLangId.HasValue) + if (!culture.IsNullOrWhiteSpace()) { foreach (var e in result) { if (e.AdditionalData.TryGetValue("CultureNames", out var cultureNames) - && cultureNames is IDictionary cnd) + && cultureNames is IDictionary cnd) { - if (cnd.TryGetValue(currLangId.Value, out var name)) + if (cnd.TryGetValue(culture, out var name)) { e.Name = name; } @@ -393,9 +393,9 @@ namespace Umbraco.Web.Trees /// A list of MenuItems that the user has permissions to execute on the current document /// By default the user must have Browse permissions to see the node in the Content tree /// - internal bool CanUserAccessNode(IUmbracoEntity doc, IEnumerable allowedUserOptions, int? langId) + internal bool CanUserAccessNode(IUmbracoEntity doc, IEnumerable allowedUserOptions, string culture) { - //TODO: At some stage when we implement permissions on languages we'll need to take care of langId + //TODO: At some stage when we implement permissions on languages we'll need to take care of culture return allowedUserOptions.Select(x => x.Action).OfType().Any(); } diff --git a/src/Umbraco.Web/WebApi/Binders/ContentItemBinder.cs b/src/Umbraco.Web/WebApi/Binders/ContentItemBinder.cs index 525b1fcf2c..8c3b705bb6 100644 --- a/src/Umbraco.Web/WebApi/Binders/ContentItemBinder.cs +++ b/src/Umbraco.Web/WebApi/Binders/ContentItemBinder.cs @@ -27,14 +27,14 @@ namespace Umbraco.Web.WebApi.Binders protected override ContentItemDto MapFromPersisted(ContentItemSave model) { - return MapFromPersisted(model.PersistedContent, model.LanguageId); + return MapFromPersisted(model.PersistedContent, model.Culture); } - internal static ContentItemDto MapFromPersisted(IContent content, int? languageId) + internal static ContentItemDto MapFromPersisted(IContent content, string culture) { return ContextMapper.Map>(content, new Dictionary { - [ContextMapper.CultureKey] = languageId + [ContextMapper.CultureKey] = culture }); } }