From 809671b9caa4355d086afb8abeaec041287640f4 Mon Sep 17 00:00:00 2001 From: patrickdemooij9 Date: Thu, 21 Oct 2021 02:09:08 +0200 Subject: [PATCH] Align template picking more towards the other pickers (#11363) * Align template picking more towards the other pickers * style/cleanup - remove unused args, updated openItemPicker function name to openTemplatePicker since that's what we're opening Co-authored-by: Nathan Woulfe --- .../components/umbgridselector.directive.js | 49 ++++++++++--------- .../src/common/services/editor.service.js | 25 +++++++++- .../treepicker/treepicker.controller.js | 3 ++ .../views/templates/templates.controller.js | 26 +++++++++- .../views/templates/templates.html | 3 +- .../src/views/templates/edit.controller.js | 26 +++++----- src/Umbraco.Web/Editors/EntityController.cs | 18 +++++++ 7 files changed, 110 insertions(+), 40 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgridselector.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgridselector.directive.js index bf03749faa..4c628391cb 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgridselector.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgridselector.directive.js @@ -1,9 +1,9 @@ (function () { 'use strict'; - function GridSelector($location, overlayService, editorService) { + function GridSelector(overlayService, editorService) { - function link(scope, el, attr, ctrl) { + function link(scope) { var eventBindings = []; scope.dialogModel = {}; @@ -33,26 +33,30 @@ }; scope.openItemPicker = function ($event) { - var dialogModel = { - view: "itempicker", - title: "Choose " + scope.itemLabel, - availableItems: scope.availableItems, - selectedItems: scope.selectedItems, - position: "target", - event: $event, - submit: function (model) { - scope.selectedItems.push(model.selectedItem); - // if no default item - set item as default - if (scope.defaultItem === null) { - scope.setAsDefaultItem(model.selectedItem); + if (scope.itemPicker) { + scope.itemPicker(); + } else { + var dialogModel = { + view: "itempicker", + title: "Choose " + scope.itemLabel, + availableItems: scope.availableItems, + selectedItems: scope.selectedItems, + position: "target", + event: $event, + submit: function (model) { + scope.selectedItems.push(model.selectedItem); + // if no default item - set item as default + if (scope.defaultItem === null) { + scope.setAsDefaultItem(model.selectedItem); + } + overlayService.close(); + }, + close: function () { + overlayService.close(); } - overlayService.close(); - }, - close: function() { - overlayService.close(); - } - }; - overlayService.open(dialogModel); + }; + overlayService.open(dialogModel); + } }; scope.openTemplate = function (selectedItem) { @@ -156,7 +160,8 @@ availableItems: "=", defaultItem: "=", itemName: "@", - updatePlaceholder: "=" + updatePlaceholder: "=", + itemPicker: "=" }, link: link }; diff --git a/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js b/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js index b917d6fa4f..a68f68fbb3 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js @@ -179,7 +179,7 @@ When building a custom infinite editor view you can use the same components as a } else { focus(); } - }); + }); /** * @ngdoc method @@ -928,6 +928,28 @@ When building a custom infinite editor view you can use the same components as a open(editor); } + /** + * @ngdoc method + * @name umbraco.services.editorService#templatePicker + * @methodOf umbraco.services.editorService + * + * @description + * Opens a template picker in infinite editing, the submit callback returns an array of selected items. + * + * @param {object} editor rendering options. + * @param {boolean} editor.multiPicker Pick one or multiple items. + * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object. + * @param {function} editor.close Callback function when the close button is clicked. + * @returns {object} editor object. + */ + function templatePicker(editor) { + editor.view = "views/common/infiniteeditors/treepicker/treepicker.html"; + if (!editor.size) editor.size = "small"; + editor.section = "settings"; + editor.treeAlias = "templates"; + open(editor); + } + /** * @ngdoc method * @name umbraco.services.editorService#macroPicker @@ -1088,6 +1110,7 @@ When building a custom infinite editor view you can use the same components as a templateSections: templateSections, userPicker: userPicker, itemPicker: itemPicker, + templatePicker: templatePicker, macroPicker: macroPicker, memberGroupPicker: memberGroupPicker, memberPicker: memberPicker, diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/treepicker/treepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/treepicker/treepicker.controller.js index ed5c4096bc..72eb504c60 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/treepicker/treepicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/treepicker/treepicker.controller.js @@ -141,6 +141,9 @@ angular.module("umbraco").controller("Umbraco.Editors.TreePickerController", }); } } + else if (vm.treeAlias === "templates") { + vm.entityType = "Template"; + } // TODO: Seems odd this logic is here, i don't think it needs to be and should just exist on the property editor using this if ($scope.model.minNumber) { diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/templates/templates.controller.js b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/templates/templates.controller.js index e2a964c293..46e856410d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/templates/templates.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/templates/templates.controller.js @@ -9,7 +9,7 @@ (function () { 'use strict'; - function TemplatesController($scope, entityResource, contentTypeHelper, templateResource, contentTypeResource, $routeParams) { + function TemplatesController($scope, entityResource, contentTypeHelper, contentTypeResource, editorService, $routeParams) { /* ----------- SCOPE VARIABLES ----------- */ @@ -22,6 +22,7 @@ vm.isElement = $scope.model.isElement; vm.createTemplate = createTemplate; + vm.openTemplatePicker = openTemplatePicker; /* ---------- INIT ---------- */ @@ -81,6 +82,29 @@ vm.canCreateTemplate = existingTemplate ? false : true; } + function openTemplatePicker() { + const editor = { + title: "Choose template", + filterCssClass: 'not-allowed', + multiPicker: true, + filter: item => { + return !vm.availableTemplates.some(template => template.id == item.id) || + $scope.model.allowedTemplates.some(template => template.id == item.id); + }, + submit: model => { + model.selection.forEach(item => { + $scope.model.allowedTemplates.push(item); + }); + editorService.close(); + }, + close: function() { + editorService.close(); + } + } + + editorService.templatePicker(editor); + } + var unbindWatcher = $scope.$watch("model.isElement", function(newValue, oldValue) { vm.isElement = newValue; diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/templates/templates.html b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/templates/templates.html index 279ffb73c0..04fd61be3c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/templates/templates.html +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/templates/templates.html @@ -17,7 +17,8 @@ item-name="template" name="model.name" alias="model.alias" - update-placeholder="vm.updateTemplatePlaceholder"> + update-placeholder="vm.updateTemplatePlaceholder" + item-picker="vm.openTemplatePicker"> { + const editor = { + title, + filterCssClass: 'not-allowed', + filter: item => !availableMasterTemplates.some(template => template.id == item.id), + submit: model => { + var template = model.selection[0]; if (template && template.alias) { vm.template.masterTemplateAlias = template.alias; setLayout(template.alias + ".cshtml"); @@ -575,14 +575,10 @@ } editorService.close(); }, - close: function (oldModel) { - // close dialog - editorService.close(); - // focus editor - vm.editor.focus(); - } - }; - editorService.itemPicker(masterTemplate); + close: () => editorService.close(), + } + + editorService.templatePicker(editor); }); } diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index 0b6273e79d..573246e1f0 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -997,6 +997,15 @@ namespace Umbraco.Web.Editors case UmbracoEntityTypes.Macro: + case UmbracoEntityTypes.Template: + var template = Services.FileService.GetTemplate(key); + if (template is null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + return Mapper.Map(template); + default: throw new NotSupportedException("The " + typeof(EntityController) + " does not currently support data for the type " + entityType); } @@ -1029,6 +1038,15 @@ namespace Umbraco.Web.Editors case UmbracoEntityTypes.Macro: + case UmbracoEntityTypes.Template: + var template = Services.FileService.GetTemplate(id); + if (template is null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + return Mapper.Map(template); + default: throw new NotSupportedException("The " + typeof(EntityController) + " does not currently support data for the type " + entityType); }