From 818e9f8b4cb8b2374b6efcb4e66cdc76c98cc2ec Mon Sep 17 00:00:00 2001 From: Dave Woestenborghs Date: Thu, 15 Nov 2018 15:28:35 +0100 Subject: [PATCH 01/18] 3417 - don't use legacy action for create method --- src/Umbraco.Web/Trees/MacrosTreeController.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web/Trees/MacrosTreeController.cs b/src/Umbraco.Web/Trees/MacrosTreeController.cs index 3f925eef8d..0649378aaa 100644 --- a/src/Umbraco.Web/Trees/MacrosTreeController.cs +++ b/src/Umbraco.Web/Trees/MacrosTreeController.cs @@ -59,11 +59,8 @@ namespace Umbraco.Web.Trees if (id == Constants.System.Root.ToInvariantString()) { //Create the normal create action - menu.Items.Add(Services.TextService, opensDialog: true) - //Since we haven't implemented anything for macros in angular, this needs to be converted to - //use the legacy format - .ConvertLegacyMenuItem(null, "initmacros", queryStrings.GetValue("application")); - + menu.Items.Add(Services.TextService); + //refresh action menu.Items.Add(new RefreshNode(Services.TextService, true)); From 8304ada5287f416b9495aa638dbe45523c31351d Mon Sep 17 00:00:00 2001 From: Dave Woestenborghs Date: Fri, 4 Jan 2019 11:39:33 +0100 Subject: [PATCH 02/18] #3417 added create view --- src/Umbraco.Web.UI.Client/src/views/macros/create.html | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/views/macros/create.html diff --git a/src/Umbraco.Web.UI.Client/src/views/macros/create.html b/src/Umbraco.Web.UI.Client/src/views/macros/create.html new file mode 100644 index 0000000000..337ebfdaa5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/macros/create.html @@ -0,0 +1,3 @@ +
+

Create view

+
From bb6848dd0372110be227bc9918c3ff45afc7b3ba Mon Sep 17 00:00:00 2001 From: Dave Woestenborghs Date: Fri, 4 Jan 2019 11:44:23 +0100 Subject: [PATCH 03/18] #3417 renamed existing macrocontroller to macro rendering controller --- src/Umbraco.Web/Editors/BackOfficeServerVariables.cs | 2 +- .../{MacroController.cs => MacroRenderingController.cs} | 4 ++-- src/Umbraco.Web/Umbraco.Web.csproj | 2 +- src/Umbraco.Web/umbraco.presentation/page.cs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename src/Umbraco.Web/Editors/{MacroController.cs => MacroRenderingController.cs} (97%) diff --git a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs index 5bc01fa534..aab5f13479 100644 --- a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs +++ b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs @@ -169,7 +169,7 @@ namespace Umbraco.Web.Editors controller => controller.GetAllowedChildren(0)) }, { - "macroApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( + "macroApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( controller => controller.GetMacroParameters(0)) }, { diff --git a/src/Umbraco.Web/Editors/MacroController.cs b/src/Umbraco.Web/Editors/MacroRenderingController.cs similarity index 97% rename from src/Umbraco.Web/Editors/MacroController.cs rename to src/Umbraco.Web/Editors/MacroRenderingController.cs index 3c576befb9..e585f28c09 100644 --- a/src/Umbraco.Web/Editors/MacroController.cs +++ b/src/Umbraco.Web/Editors/MacroRenderingController.cs @@ -27,11 +27,11 @@ namespace Umbraco.Web.Editors /// Session, we don't want it to throw null reference exceptions. /// [PluginController("UmbracoApi")] - public class MacroController : UmbracoAuthorizedJsonController, IRequiresSessionState + public class MacroRenderingController : UmbracoAuthorizedJsonController, IRequiresSessionState { private readonly IVariationContextAccessor _variationContextAccessor; - public MacroController(IVariationContextAccessor variationContextAccessor) + public MacroRenderingController(IVariationContextAccessor variationContextAccessor) { _variationContextAccessor = variationContextAccessor; } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 17c2a54d81..16fbd6aa29 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -751,7 +751,7 @@ - + diff --git a/src/Umbraco.Web/umbraco.presentation/page.cs b/src/Umbraco.Web/umbraco.presentation/page.cs index 219e2101be..a2ccc1e094 100644 --- a/src/Umbraco.Web/umbraco.presentation/page.cs +++ b/src/Umbraco.Web/umbraco.presentation/page.cs @@ -102,7 +102,7 @@ namespace umbraco /// Initializes a new instance of the page for a content. /// /// The content. - /// This is for usage only. + /// This is for usage only. internal page(IContent content, IVariationContextAccessor variationContextAccessor) : this(new PagePublishedContent(content, variationContextAccessor)) { } From e1906113b969d728f6671aac15ee0e0749c545ac Mon Sep 17 00:00:00 2001 From: Dave Woestenborghs Date: Fri, 4 Jan 2019 12:31:58 +0100 Subject: [PATCH 04/18] #3417 added macro api controller and create method --- src/Umbraco.Web/Editors/MacrosController.cs | 64 +++++++++++++++++++++ src/Umbraco.Web/Umbraco.Web.csproj | 1 + 2 files changed, 65 insertions(+) create mode 100644 src/Umbraco.Web/Editors/MacrosController.cs diff --git a/src/Umbraco.Web/Editors/MacrosController.cs b/src/Umbraco.Web/Editors/MacrosController.cs new file mode 100644 index 0000000000..0adada0a2b --- /dev/null +++ b/src/Umbraco.Web/Editors/MacrosController.cs @@ -0,0 +1,64 @@ +using System; +using System.Net; +using System.Net.Http; +using System.Web.Http; + +using Umbraco.Core; +using Umbraco.Core.Logging; +using Umbraco.Core.Models; +using Umbraco.Web.Mvc; +using Umbraco.Web.WebApi; +using Umbraco.Web.WebApi.Filters; + +using Constants = Umbraco.Core.Constants; + +namespace Umbraco.Web.Editors +{ + /// + /// The API controller used for editing dictionary items + /// + [PluginController("UmbracoApi")] + [UmbracoTreeAuthorize(Constants.Trees.Macros)] + public class MacrosController : BackOfficeNotificationsController + { + /// + /// Creates a new macro + /// + /// + /// The name. + /// + /// + /// The . + /// + [HttpPost] + public HttpResponseMessage Create(string name) + { + if (string.IsNullOrWhiteSpace(name)) + return Request + .CreateNotificationValidationErrorResponse("Name can not be empty;"); + + var alias = name.ToSafeAlias(); + + var existingMacro = this.Services.MacroService.GetByAlias(alias); + + if (existingMacro != null) + { + return Request.CreateNotificationValidationErrorResponse("Macro with this name already exists"); + } + + try + { + var macro = new Macro { Alias = alias, Name = name }; + + this.Services.MacroService.Save(macro, this.Security.CurrentUser.Id); + + return Request.CreateResponse(HttpStatusCode.OK, macro.Id); + } + catch (Exception exception) + { + this.Logger.Error(exception, "Error creating macro"); + return Request.CreateNotificationValidationErrorResponse("Error creating dictionary item"); + } + } + } +} diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 16fbd6aa29..7186835ba8 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -117,6 +117,7 @@ + From c61b5f947dae03e456e1ef0ba976153768f7476b Mon Sep 17 00:00:00 2001 From: Dave Woestenborghs Date: Fri, 4 Jan 2019 13:49:03 +0100 Subject: [PATCH 05/18] #3417 renamed server variable --- .../src/common/resources/macro.resource.js | 6 +++--- src/Umbraco.Web/Editors/BackOfficeServerVariables.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js index dde887776e..07ad58bb78 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js @@ -24,7 +24,7 @@ function macroResource($q, $http, umbRequestHelper) { return umbRequestHelper.resourcePromise( $http.get( umbRequestHelper.getApiUrl( - "macroApiBaseUrl", + "macroRenderingApiBaseUrl", "GetMacroParameters", [{ macroId: macroId }])), 'Failed to retrieve macro parameters for macro with id ' + macroId); @@ -48,7 +48,7 @@ function macroResource($q, $http, umbRequestHelper) { return umbRequestHelper.resourcePromise( $http.post( umbRequestHelper.getApiUrl( - "macroApiBaseUrl", + "macroRenderingApiBaseUrl", "GetMacroResultAsHtmlForEditor"), { macroAlias: macroAlias, pageId: pageId, @@ -67,7 +67,7 @@ function macroResource($q, $http, umbRequestHelper) { return umbRequestHelper.resourcePromise( $http.post( umbRequestHelper.getApiUrl( - "macroApiBaseUrl", + "macroRenderingApiBaseUrl", "CreatePartialViewMacroWithFile"), { virtualPath: virtualPath, filename: filename diff --git a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs index aab5f13479..1550161ff0 100644 --- a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs +++ b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs @@ -169,7 +169,7 @@ namespace Umbraco.Web.Editors controller => controller.GetAllowedChildren(0)) }, { - "macroApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( + "macroRenderingApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( controller => controller.GetMacroParameters(0)) }, { From 03ce92212420d89f5a54f93631e8b35d796bee5c Mon Sep 17 00:00:00 2001 From: Dave Woestenborghs Date: Fri, 4 Jan 2019 17:10:53 +0100 Subject: [PATCH 06/18] #3417 register new api url in server variables --- src/Umbraco.Web/Editors/BackOfficeServerVariables.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs index 1550161ff0..52cfc1bdec 100644 --- a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs +++ b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs @@ -172,6 +172,10 @@ namespace Umbraco.Web.Editors "macroRenderingApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( controller => controller.GetMacroParameters(0)) }, + { + "macroApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( + controller => controller.Create(null)) + }, { "authenticationApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( controller => controller.PostLogin(null)) From d7af9d9fca9ec0760dfa88fb7a710fe5359a4e36 Mon Sep 17 00:00:00 2001 From: Dave Woestenborghs Date: Fri, 4 Jan 2019 17:36:42 +0100 Subject: [PATCH 07/18] #3417 added method to macro resource to create a macro --- .../src/common/resources/macro.resource.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js index 07ad58bb78..d0c6af2497 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js @@ -76,6 +76,19 @@ function macroResource($q, $http, umbRequestHelper) { 'Failed to create macro "' + filename + '"' ); + }, + + createMacro: function(name) { + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "macroApiBaseUrl", + "Create"), { + name : name, + } + ), + 'Failed to create macro "' + name + '"' + ); } }; } From 2ca7bb0cf3751077a35af9a61995df171e7274e9 Mon Sep 17 00:00:00 2001 From: Dave Woestenborghs Date: Mon, 7 Jan 2019 08:28:50 +0100 Subject: [PATCH 08/18] #3417 implemented create dialog for macros --- .../src/common/resources/macro.resource.js | 4 +- .../src/views/macros/create.html | 20 ++++++++- .../views/macros/macros.create.controller.js | 44 +++++++++++++++++++ src/Umbraco.Web/Editors/MacrosController.cs | 2 +- 4 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/views/macros/macros.create.controller.js diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js index d0c6af2497..9f22465757 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js @@ -83,9 +83,7 @@ function macroResource($q, $http, umbRequestHelper) { $http.post( umbRequestHelper.getApiUrl( "macroApiBaseUrl", - "Create"), { - name : name, - } + "Create?name=" + name) ), 'Failed to create macro "' + name + '"' ); diff --git a/src/Umbraco.Web.UI.Client/src/views/macros/create.html b/src/Umbraco.Web.UI.Client/src/views/macros/create.html index 337ebfdaa5..a72cd373b2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/macros/create.html +++ b/src/Umbraco.Web.UI.Client/src/views/macros/create.html @@ -1,3 +1,19 @@ -
-

Create view

+
+ +
+
Create an item under {{currentNode.name}}
+
+ +
+
+ + + + + + +
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/macros/macros.create.controller.js b/src/Umbraco.Web.UI.Client/src/views/macros/macros.create.controller.js new file mode 100644 index 0000000000..1745b7b7f6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/macros/macros.create.controller.js @@ -0,0 +1,44 @@ +/** + * @ngdoc controller + * @name Umbraco.Editors.Macros.CreateController + * @function + * + * @description + * The controller for creating macro items + */ +function MacrosCreateController($scope, $location, macroResource, navigationService, notificationsService, formHelper, appState) { + var vm = this; + + vm.itemKey = ""; + + function createItem() { + + var node = $scope.currentNode; + + macroResource.createMacro(vm.itemKey).then(function (data) { + navigationService.hideMenu(); + + // set new item as active in tree + var currPath = node.path ? node.path : "-1"; + navigationService.syncTree({ tree: "macros", path: currPath + "," + data, forceReload: true, activate: true }); + + // reset form state + formHelper.resetForm({ scope: $scope }); + + // navigate to edit view + var currentSection = appState.getSectionState("currentSection"); + $location.path("/" + currentSection + "/macros/edit/" + data); + + + }, function (err) { + if (err.data && err.data.message) { + notificationsService.error(err.data.message); + navigationService.hideMenu(); + } + }); + } + + vm.createItem = createItem; +} + +angular.module("umbraco").controller("Umbraco.Editors.Macros.CreateController", MacrosCreateController); diff --git a/src/Umbraco.Web/Editors/MacrosController.cs b/src/Umbraco.Web/Editors/MacrosController.cs index 0adada0a2b..f1d949231e 100644 --- a/src/Umbraco.Web/Editors/MacrosController.cs +++ b/src/Umbraco.Web/Editors/MacrosController.cs @@ -48,7 +48,7 @@ namespace Umbraco.Web.Editors try { - var macro = new Macro { Alias = alias, Name = name }; + var macro = new Macro { Alias = alias, Name = name, MacroSource = string.Empty}; this.Services.MacroService.Save(macro, this.Security.CurrentUser.Id); From edd2adc8a00db041b2ee7f073969ea0b5c58bdb9 Mon Sep 17 00:00:00 2001 From: Dave Woestenborghs Date: Mon, 7 Jan 2019 08:31:06 +0100 Subject: [PATCH 09/18] #3417 changed path of macro tree item to use angular view instead of webform --- src/Umbraco.Web/Trees/MacrosTreeController.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Umbraco.Web/Trees/MacrosTreeController.cs b/src/Umbraco.Web/Trees/MacrosTreeController.cs index 0649378aaa..f16cfe09d4 100644 --- a/src/Umbraco.Web/Trees/MacrosTreeController.cs +++ b/src/Umbraco.Web/Trees/MacrosTreeController.cs @@ -42,10 +42,7 @@ namespace Umbraco.Web.Trees queryStrings, macro.Name, "icon-settings-alt", - false, - //TODO: Rebuild the macro editor in angular, then we dont need to have this at all (which is just a path to the legacy editor) - "/" + queryStrings.GetValue("application") + "/framed/" + - Uri.EscapeDataString("/umbraco/developer/macros/editMacro.aspx?macroID=" + macro.Id))); + false)); } } From b9d779e921a116dd86a04df25ff7ce3252a3269b Mon Sep 17 00:00:00 2001 From: Dave Woestenborghs Date: Tue, 8 Jan 2019 08:34:46 +0100 Subject: [PATCH 10/18] #3417 prototyped the UI for settings of the macro --- .../src/views/macros/edit.html | 31 +++++++ .../views/macros/macros.edit.controller.js | 87 +++++++++++++++++++ .../src/views/macros/views/parameters.html | 3 + .../src/views/macros/views/settings.html | 33 +++++++ 4 files changed, 154 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/views/macros/edit.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/macros/views/parameters.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/macros/views/settings.html diff --git a/src/Umbraco.Web.UI.Client/src/views/macros/edit.html b/src/Umbraco.Web.UI.Client/src/views/macros/edit.html new file mode 100644 index 0000000000..911dcf0c9e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/macros/edit.html @@ -0,0 +1,31 @@ +
+ + +
+ + + + + + + + + + + + + + + + +
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js new file mode 100644 index 0000000000..ef65c77e1d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js @@ -0,0 +1,87 @@ +/** + * @ngdoc controller + * @name Umbraco.Editors.Macros.EditController + * @function + * + * @description + * The controller for editing macros. + */ +function MacrosEditController($scope, $routeParams, macroResource, editorState, navigationService, dateHelper, userService, entityResource, formHelper, contentEditingHelper, localizationService) { + + var vm = this; + + vm.page = {}; + vm.page.loading = false; + vm.page.saveButtonState = "init"; + vm.page.menu = {} + + vm.save = saveMacro; + vm.toggle = toggleValue; + + init(); + + function init() { + vm.page.loading = true; + + + vm.page.navigation = [ + { + "name": "Settings", + "alias": "settings", + "icon": "icon-settings", + "view": "views/macros/views/settings.html", + "active": true + }, + { + "name": "Parameters", + "alias": "parameters", + "icon": "icon-list", + "view": "views/macros/views/parameters.html" + } + ]; + + vm.macro = { + "name": "Test macro", + "alias": "testMacro", + "id": 1, + "key": "unique key goes here", + "useInEditor": true, + "renderInEditor": false, + "cachePeriod": 2400, + "cacheByPage": true, + "cacheByUser": false, + "view" : "Second" + } + + vm.views = ['First', 'Second', 'Third']; + + vm.page.loading = false; + } + + function toggleValue(key) { + vm.macro[key] = !vm.macro[key]; + } + + function saveMacro() { + vm.page.saveButtonState = "busy"; + + if (formHelper.submitForm({ scope: $scope, statusMessage: "Saving..." })) { + console.log(vm.macro); + //relationTypeResource.save(vm.relationType).then(function (data) { + // formHelper.resetForm({ scope: $scope, notifications: data.notifications }); + // bindRelationType(data); + // vm.page.saveButtonState = "success"; + //}, function (error) { + // contentEditingHelper.handleSaveError({ + // redirectOnFailure: false, + // err: error + // }); + + // notificationsService.error(error.data.message); + // vm.page.saveButtonState = "error"; + //}); + } + } +} + +angular.module("umbraco").controller("Umbraco.Editors.Macros.EditController", MacrosEditController); diff --git a/src/Umbraco.Web.UI.Client/src/views/macros/views/parameters.html b/src/Umbraco.Web.UI.Client/src/views/macros/views/parameters.html new file mode 100644 index 0000000000..6a10d4f80b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/macros/views/parameters.html @@ -0,0 +1,3 @@ + + + diff --git a/src/Umbraco.Web.UI.Client/src/views/macros/views/settings.html b/src/Umbraco.Web.UI.Client/src/views/macros/views/settings.html new file mode 100644 index 0000000000..51e83a9134 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/macros/views/settings.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 5ebf51e6df64419c6676051624237a6a7ca8bcc7 Mon Sep 17 00:00:00 2001 From: Dave Woestenborghs Date: Wed, 16 Jan 2019 08:40:00 +0100 Subject: [PATCH 11/18] #3417 added mockup of parameter editing --- .../src/views/macros/edit.html | 5 +- .../infiniteeditors/parameter.controller.js | 27 +++++++ .../macros/infiniteeditors/parameter.html | 58 ++++++++++++++ .../views/macros/macros.edit.controller.js | 30 ++++++- .../views/macro.parameters.controller.js | 78 +++++++++++++++++++ .../src/views/macros/views/parameters.html | 31 +++++++- 6 files changed, 223 insertions(+), 6 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/views/macros/infiniteeditors/parameter.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/macros/infiniteeditors/parameter.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/macros/views/macro.parameters.controller.js diff --git a/src/Umbraco.Web.UI.Client/src/views/macros/edit.html b/src/Umbraco.Web.UI.Client/src/views/macros/edit.html index 911dcf0c9e..ddb5f98781 100644 --- a/src/Umbraco.Web.UI.Client/src/views/macros/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/macros/edit.html @@ -1,7 +1,6 @@ -
- - +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ' + + + + +
diff --git a/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js index ef65c77e1d..81c699a05f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js @@ -6,7 +6,7 @@ * @description * The controller for editing macros. */ -function MacrosEditController($scope, $routeParams, macroResource, editorState, navigationService, dateHelper, userService, entityResource, formHelper, contentEditingHelper, localizationService) { +function MacrosEditController($scope, $routeParams, macroResource, editorState, navigationService, dateHelper, userService, entityResource, formHelper, contentEditingHelper, localizationService, angularHelper) { var vm = this; @@ -17,6 +17,7 @@ function MacrosEditController($scope, $routeParams, macroResource, editorState, vm.save = saveMacro; vm.toggle = toggleValue; + init(); @@ -50,11 +51,25 @@ function MacrosEditController($scope, $routeParams, macroResource, editorState, "cachePeriod": 2400, "cacheByPage": true, "cacheByUser": false, - "view" : "Second" + "view": "Second", + "parameters": [ + { + "key": "title", + "label": "Label", + "editor": "editor" + }, + { + "key": "link", + "label": "Link", + "editor": "Link picker" + } + ] } vm.views = ['First', 'Second', 'Third']; + vm.parameterEditors = ['editor', 'Link picker', 'Image picker']; + vm.page.loading = false; } @@ -82,6 +97,17 @@ function MacrosEditController($scope, $routeParams, macroResource, editorState, //}); } } + + function setFormDirty() { + var currentForm = angularHelper.getCurrentForm($scope); + + if (currentForm) { + + currentForm.$setDirty(); + } + } + + vm.setDirty = setFormDirty; } angular.module("umbraco").controller("Umbraco.Editors.Macros.EditController", MacrosEditController); diff --git a/src/Umbraco.Web.UI.Client/src/views/macros/views/macro.parameters.controller.js b/src/Umbraco.Web.UI.Client/src/views/macros/views/macro.parameters.controller.js new file mode 100644 index 0000000000..851b537c3b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/macros/views/macro.parameters.controller.js @@ -0,0 +1,78 @@ +/** + * @ngdoc controller + * @name Umbraco.Editors.Macros.ParametersController + * @function + * + * @description + * The controller for editing macros parameters + */ +function MacrosParametersController($scope, editorService) { + + $scope.sortableOptions = { + axis: 'y', + containment: 'parent', + cursor: 'move', + items: 'div.umb-stylesheet-rules__listitem', + handle: '.handle', + tolerance: 'pointer', + update: function (e, ui) { + $scope.model.setDirty(); + } + }; + + + $scope.remove = function (parameter, evt) { + evt.preventDefault(); + + $scope.model.macro.parameters = _.without($scope.model.macro.parameters, parameter); + $scope.model.setDirty(); + } + + $scope.add = function (evt) { + evt.preventDefault(); + + openOverlay({}, 'Add parameter', (newParameter) => { + if (!$scope.model.macro.parameters) { + $scope.model.macro.parameters = []; + } + $scope.model.macro.parameters.push(newParameter); + $scope.model.setDirty(); + }); + } + + $scope.edit = function (parameter, evt) { + evt.preventDefault(); + + openOverlay(parameter,'Edit parameter', (newParameter) => { + parameter.key = newParameter.key; + parameter.label = newParameter.label; + parameter.editor = newParameter.editor; + parameter.editor = newParameter.editor; + $scope.model.setDirty(); + }); + } + + function openOverlay(parameter, title, onSubmit) { + + const ruleDialog = { + title: title, + parameter: _.clone(parameter), + editors : $scope.model.parameterEditors, + view: "views/macros/infiniteeditors/parameter.html", + size: "small", + submit: function (model) { + onSubmit(model.parameter); + editorService.close(); + }, + close: function () { + editorService.close(); + } + }; + + editorService.open(ruleDialog); + + } + +} + +angular.module("umbraco").controller("Umbraco.Editors.Macros.ParametersController", MacrosParametersController); diff --git a/src/Umbraco.Web.UI.Client/src/views/macros/views/parameters.html b/src/Umbraco.Web.UI.Client/src/views/macros/views/parameters.html index 6a10d4f80b..91231a49b7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/macros/views/parameters.html +++ b/src/Umbraco.Web.UI.Client/src/views/macros/views/parameters.html @@ -1,3 +1,32 @@  - + +
+
+
Parameters
+ Define the parameters hat should be available when using his macro +
+
+
+
+
+ +
+ {{parameter.label}} +
+
+ Remove +
+
+
+ + +
+
+
+ +
From b6a8ad1b6e9827c0a211b51af28e67c98cc36c94 Mon Sep 17 00:00:00 2001 From: Dave Woestenborghs Date: Wed, 16 Jan 2019 16:21:19 +0100 Subject: [PATCH 12/18] #3417 load available partial views from api --- .../src/common/resources/macro.resource.js | 7 + .../views/macros/macros.edit.controller.js | 144 +++++++++++------- src/Umbraco.Web/Editors/MacrosController.cs | 124 ++++++++++++++- 3 files changed, 215 insertions(+), 60 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js index 9f22465757..237a361f7e 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js @@ -87,6 +87,13 @@ function macroResource($q, $http, umbRequestHelper) { ), 'Failed to create macro "' + name + '"' ); + }, + + getPartialViews: function() { + return umbRequestHelper.resourcePromise( + $http.get(umbRequestHelper.getApiUrl("macroApiBaseUrl", "GetPartialViews"), + "Failed to get partial views") + ); } }; } diff --git a/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js index 81c699a05f..fa3a4e45a5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js @@ -6,77 +6,25 @@ * @description * The controller for editing macros. */ -function MacrosEditController($scope, $routeParams, macroResource, editorState, navigationService, dateHelper, userService, entityResource, formHelper, contentEditingHelper, localizationService, angularHelper) { +function MacrosEditController($scope, $q, $routeParams, macroResource, editorState, navigationService, dateHelper, userService, entityResource, formHelper, contentEditingHelper, localizationService, angularHelper) { var vm = this; + vm.promises = {}; + vm.page = {}; vm.page.loading = false; vm.page.saveButtonState = "init"; vm.page.menu = {} - vm.save = saveMacro; - vm.toggle = toggleValue; - - - init(); - - function init() { - vm.page.loading = true; - - - vm.page.navigation = [ - { - "name": "Settings", - "alias": "settings", - "icon": "icon-settings", - "view": "views/macros/views/settings.html", - "active": true - }, - { - "name": "Parameters", - "alias": "parameters", - "icon": "icon-list", - "view": "views/macros/views/parameters.html" - } - ]; - - vm.macro = { - "name": "Test macro", - "alias": "testMacro", - "id": 1, - "key": "unique key goes here", - "useInEditor": true, - "renderInEditor": false, - "cachePeriod": 2400, - "cacheByPage": true, - "cacheByUser": false, - "view": "Second", - "parameters": [ - { - "key": "title", - "label": "Label", - "editor": "editor" - }, - { - "key": "link", - "label": "Link", - "editor": "Link picker" - } - ] - } - - vm.views = ['First', 'Second', 'Third']; - - vm.parameterEditors = ['editor', 'Link picker', 'Image picker']; - - vm.page.loading = false; - } + function toggleValue(key) { vm.macro[key] = !vm.macro[key]; } + vm.toggle = toggleValue; + function saveMacro() { vm.page.saveButtonState = "busy"; @@ -98,6 +46,8 @@ function MacrosEditController($scope, $routeParams, macroResource, editorState, } } + vm.save = saveMacro; + function setFormDirty() { var currentForm = angularHelper.getCurrentForm($scope); @@ -108,6 +58,84 @@ function MacrosEditController($scope, $routeParams, macroResource, editorState, } vm.setDirty = setFormDirty; + + function getPartialViews() { + var deferred = $q.defer(); + + macroResource.getPartialViews().then(function (data) { + deferred.resolve(data); + }, function () { + deferred.reject(); + }); + + return deferred.promise; + } + + function init() { + vm.page.loading = true; + + vm.promises['partialViews'] = getPartialViews(); + + $q.all(vm.promises).then(function (values) { + var keys = Object.keys(values); + + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + + if (keys[i] === 'partialViews') { + vm.views = values[key]; + } + } + + vm.page.loading = false; + }); + + + vm.page.navigation = [ + { + "name": "Settings", + "alias": "settings", + "icon": "icon-settings", + "view": "views/macros/views/settings.html", + "active": true + }, + { + "name": "Parameters", + "alias": "parameters", + "icon": "icon-list", + "view": "views/macros/views/parameters.html" + } + ]; + + vm.macro = { + "name": "Test macro", + "alias": "testMacro", + "id": 1, + "key": "unique key goes here", + "useInEditor": true, + "renderInEditor": false, + "cachePeriod": 2400, + "cacheByPage": true, + "cacheByUser": false, + "view": "Second", + "parameters": [ + { + "key": "title", + "label": "Label", + "editor": "editor" + }, + { + "key": "link", + "label": "Link", + "editor": "Link picker" + } + ] + } + + vm.parameterEditors = ['editor', 'Link picker', 'Image picker']; + } + + init(); } angular.module("umbraco").controller("Umbraco.Editors.Macros.EditController", MacrosEditController); diff --git a/src/Umbraco.Web/Editors/MacrosController.cs b/src/Umbraco.Web/Editors/MacrosController.cs index f1d949231e..553924c3e6 100644 --- a/src/Umbraco.Web/Editors/MacrosController.cs +++ b/src/Umbraco.Web/Editors/MacrosController.cs @@ -14,6 +14,12 @@ using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Editors { + using System.Collections.Generic; + using System.IO; + using System.Linq; + + using Umbraco.Core.IO; + /// /// The API controller used for editing dictionary items /// @@ -48,7 +54,7 @@ namespace Umbraco.Web.Editors try { - var macro = new Macro { Alias = alias, Name = name, MacroSource = string.Empty}; + var macro = new Macro { Alias = alias, Name = name, MacroSource = string.Empty }; this.Services.MacroService.Save(macro, this.Security.CurrentUser.Id); @@ -58,7 +64,121 @@ namespace Umbraco.Web.Editors { this.Logger.Error(exception, "Error creating macro"); return Request.CreateNotificationValidationErrorResponse("Error creating dictionary item"); - } + } + } + + /// + /// Gets a list of available macro partials + /// + /// + /// The . + /// + public HttpResponseMessage GetPartialViews() + { + var views = new List(); + + views.AddRange(this.FindPartialViewsFiles()); + + return this.Request.CreateResponse(HttpStatusCode.OK, views); + } + + /// + /// Finds all the macro partials + /// + /// + /// The . + /// + private IEnumerable FindPartialViewsFiles() + { + var files = new List(); + + files.AddRange(this.FindPartialViewFilesInViewsFolder()); + files.AddRange(this.FindPartialViewFilesInPluginFolders()); + + return files; + } + + /// + /// Finds all macro partials in the views folder + /// + /// + /// The . + /// + private IEnumerable FindPartialViewFilesInViewsFolder() + { + var partialsDir = IOHelper.MapPath(SystemDirectories.MacroPartials); + + return this.FindPartialViewFilesInFolder( + partialsDir, + partialsDir, + SystemDirectories.MacroPartials); + } + + /// + /// Finds partial view files in app plugin folders. + /// + /// + /// The . + /// + private IEnumerable FindPartialViewFilesInPluginFolders() + { + var files = new List(); + + var appPluginsFolder = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.AppPlugins)); + + if (!appPluginsFolder.Exists) + { + return files; + } + + foreach (var directory in appPluginsFolder.GetDirectories()) + { + var viewsFolder = directory.GetDirectories("Views"); + if (viewsFolder.Any()) + { + var macroPartials = viewsFolder.First().GetDirectories("MacroPartials"); + if (macroPartials.Any()) + { + files.AddRange(this.FindPartialViewFilesInFolder(macroPartials.First().FullName, macroPartials.First().FullName, SystemDirectories.AppPlugins + "/" + directory.Name + "/Views/MacroPartials")); + } + } + } + + return files; + } + + /// + /// Finds all partial views in a folder and subfolders + /// + /// + /// The org path. + /// + /// + /// The path. + /// + /// + /// The prefix virtual path. + /// + /// + /// The . + /// + private IEnumerable FindPartialViewFilesInFolder(string orgPath, string path, string prefixVirtualPath) + { + var files = new List(); + var dirInfo = new DirectoryInfo(path); + + foreach (var dir in dirInfo.GetDirectories()) + { + files.AddRange(this.FindPartialViewFilesInFolder(orgPath, path + "/" + dir.Name, prefixVirtualPath)); + } + + var fileInfo = dirInfo.GetFiles("*.*"); + + files.AddRange( + fileInfo.Select(file => + prefixVirtualPath.TrimEnd('/') + "/" + (path.Replace(orgPath, string.Empty).Trim('/') + "/" + file.Name).Trim('/'))); + + return files; } } } From c0e62c4c5fa39ae3858eb5d74f0b3f417aeed10e Mon Sep 17 00:00:00 2001 From: Dave Woestenborghs Date: Wed, 16 Jan 2019 16:37:33 +0100 Subject: [PATCH 13/18] #3417 retreive a list with parameter editors from API --- .../src/common/resources/macro.resource.js | 7 +++++++ .../macros/infiniteeditors/parameter.html | 2 +- .../views/macros/macros.edit.controller.js | 21 ++++++++++++++++--- src/Umbraco.Web/Editors/MacrosController.cs | 12 +++++++++++ 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js index 237a361f7e..5313eadcaa 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js @@ -94,6 +94,13 @@ function macroResource($q, $http, umbRequestHelper) { $http.get(umbRequestHelper.getApiUrl("macroApiBaseUrl", "GetPartialViews"), "Failed to get partial views") ); + }, + + getParameterEditors: function () { + return umbRequestHelper.resourcePromise( + $http.get(umbRequestHelper.getApiUrl("macroApiBaseUrl", "GetParameterEditors"), + "Failed to get parameter editors") + ); } }; } diff --git a/src/Umbraco.Web.UI.Client/src/views/macros/infiniteeditors/parameter.html b/src/Umbraco.Web.UI.Client/src/views/macros/infiniteeditors/parameter.html index ac01fa588e..bf9dbf86a3 100644 --- a/src/Umbraco.Web.UI.Client/src/views/macros/infiniteeditors/parameter.html +++ b/src/Umbraco.Web.UI.Client/src/views/macros/infiniteeditors/parameter.html @@ -26,7 +26,7 @@ - + diff --git a/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js index fa3a4e45a5..f8cde110e6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js @@ -71,10 +71,23 @@ function MacrosEditController($scope, $q, $routeParams, macroResource, editorSta return deferred.promise; } + function getParameterEditors() { + var deferred = $q.defer(); + + macroResource.getParameterEditors().then(function (data) { + deferred.resolve(data); + }, function () { + deferred.reject(); + }); + + return deferred.promise; + } + function init() { vm.page.loading = true; vm.promises['partialViews'] = getPartialViews(); + vm.promises['parameterEditors'] = getParameterEditors(); $q.all(vm.promises).then(function (values) { var keys = Object.keys(values); @@ -85,6 +98,10 @@ function MacrosEditController($scope, $q, $routeParams, macroResource, editorSta if (keys[i] === 'partialViews') { vm.views = values[key]; } + + if (keys[i] === 'parameterEditors') { + vm.parameterEditors = values[key]; + } } vm.page.loading = false; @@ -130,9 +147,7 @@ function MacrosEditController($scope, $q, $routeParams, macroResource, editorSta "editor": "Link picker" } ] - } - - vm.parameterEditors = ['editor', 'Link picker', 'Image picker']; + } } init(); diff --git a/src/Umbraco.Web/Editors/MacrosController.cs b/src/Umbraco.Web/Editors/MacrosController.cs index 553924c3e6..6e2d032ad4 100644 --- a/src/Umbraco.Web/Editors/MacrosController.cs +++ b/src/Umbraco.Web/Editors/MacrosController.cs @@ -19,6 +19,7 @@ namespace Umbraco.Web.Editors using System.Linq; using Umbraco.Core.IO; + using Umbraco.Web.Composing; /// /// The API controller used for editing dictionary items @@ -82,6 +83,17 @@ namespace Umbraco.Web.Editors return this.Request.CreateResponse(HttpStatusCode.OK, views); } + /// + /// Gets the available parameter editors + /// + /// + /// The . + /// + public HttpResponseMessage GetParameterEditors() + { + return this.Request.CreateResponse(HttpStatusCode.OK, Current.ParameterEditors); + } + /// /// Finds all the macro partials /// From a83ac4a24dd6ced3c6f993cd6c4e9c048191df67 Mon Sep 17 00:00:00 2001 From: Dave Woestenborghs Date: Fri, 18 Jan 2019 09:31:38 +0100 Subject: [PATCH 14/18] #3417 retreive data for edit screen --- .../src/common/resources/macro.resource.js | 6 + .../macros/infiniteeditors/parameter.html | 2 +- .../views/macros/macros.edit.controller.js | 48 ++++---- .../src/views/macros/views/settings.html | 3 +- src/Umbraco.Web/Editors/MacrosController.cs | 116 ++++++++++++++---- .../Models/ContentEditing/MacroDisplay.cs | 67 ++++++++++ .../ContentEditing/MacroParameterDisplay.cs | 29 +++++ src/Umbraco.Web/Umbraco.Web.csproj | 2 + 8 files changed, 220 insertions(+), 53 deletions(-) create mode 100644 src/Umbraco.Web/Models/ContentEditing/MacroDisplay.cs create mode 100644 src/Umbraco.Web/Models/ContentEditing/MacroParameterDisplay.cs diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js index 5313eadcaa..1471abd8d3 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js @@ -101,6 +101,12 @@ function macroResource($q, $http, umbRequestHelper) { $http.get(umbRequestHelper.getApiUrl("macroApiBaseUrl", "GetParameterEditors"), "Failed to get parameter editors") ); + }, + + getById: function(id) { + return umbRequestHelper.resourcePromise( + $http.get(umbRequestHelper.getApiUrl("macroApiBaseUrl", "GetById", { "id" : id}), "Failed to get macro") + ); } }; } diff --git a/src/Umbraco.Web.UI.Client/src/views/macros/infiniteeditors/parameter.html b/src/Umbraco.Web.UI.Client/src/views/macros/infiniteeditors/parameter.html index bf9dbf86a3..402c3c4984 100644 --- a/src/Umbraco.Web.UI.Client/src/views/macros/infiniteeditors/parameter.html +++ b/src/Umbraco.Web.UI.Client/src/views/macros/infiniteeditors/parameter.html @@ -26,7 +26,7 @@ - + diff --git a/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js index f8cde110e6..91af9b0f09 100644 --- a/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js @@ -83,11 +83,24 @@ function MacrosEditController($scope, $q, $routeParams, macroResource, editorSta return deferred.promise; } + function getMacro() { + var deferred = $q.defer(); + + macroResource.getById($routeParams.id).then(function (data) { + deferred.resolve(data); + }, function () { + deferred.reject(); + }); + + return deferred.promise; + } + function init() { vm.page.loading = true; vm.promises['partialViews'] = getPartialViews(); vm.promises['parameterEditors'] = getParameterEditors(); + vm.promises['macro'] = getMacro(); $q.all(vm.promises).then(function (values) { var keys = Object.keys(values); @@ -102,12 +115,20 @@ function MacrosEditController($scope, $q, $routeParams, macroResource, editorSta if (keys[i] === 'parameterEditors') { vm.parameterEditors = values[key]; } + + if (keys[i] === 'macro') { + vm.macro = values[key]; + editorState.set(vm.macro); + + navigationService.syncTree({ tree: "macros", path: vm.macro.path, forceReload: true }).then(function (syncArgs) { + vm.page.menu.currentNode = syncArgs.node; + }); + } } vm.page.loading = false; }); - vm.page.navigation = [ { "name": "Settings", @@ -123,31 +144,6 @@ function MacrosEditController($scope, $q, $routeParams, macroResource, editorSta "view": "views/macros/views/parameters.html" } ]; - - vm.macro = { - "name": "Test macro", - "alias": "testMacro", - "id": 1, - "key": "unique key goes here", - "useInEditor": true, - "renderInEditor": false, - "cachePeriod": 2400, - "cacheByPage": true, - "cacheByUser": false, - "view": "Second", - "parameters": [ - { - "key": "title", - "label": "Label", - "editor": "editor" - }, - { - "key": "link", - "label": "Link", - "editor": "Link picker" - } - ] - } } init(); diff --git a/src/Umbraco.Web.UI.Client/src/views/macros/views/settings.html b/src/Umbraco.Web.UI.Client/src/views/macros/views/settings.html index 51e83a9134..ba5b324837 100644 --- a/src/Umbraco.Web.UI.Client/src/views/macros/views/settings.html +++ b/src/Umbraco.Web.UI.Client/src/views/macros/views/settings.html @@ -2,7 +2,8 @@ - + diff --git a/src/Umbraco.Web/Editors/MacrosController.cs b/src/Umbraco.Web/Editors/MacrosController.cs index 6e2d032ad4..d604137e19 100644 --- a/src/Umbraco.Web/Editors/MacrosController.cs +++ b/src/Umbraco.Web/Editors/MacrosController.cs @@ -1,25 +1,24 @@ -using System; -using System.Net; -using System.Net.Http; -using System.Web.Http; - -using Umbraco.Core; -using Umbraco.Core.Logging; -using Umbraco.Core.Models; -using Umbraco.Web.Mvc; -using Umbraco.Web.WebApi; -using Umbraco.Web.WebApi.Filters; - -using Constants = Umbraco.Core.Constants; - -namespace Umbraco.Web.Editors +namespace Umbraco.Web.Editors { + using System; using System.Collections.Generic; using System.IO; using System.Linq; + using System.Net; + using System.Net.Http; + using System.Web.Http; + using Umbraco.Core; using Umbraco.Core.IO; + using Umbraco.Core.Logging; + using Umbraco.Core.Models; using Umbraco.Web.Composing; + using Umbraco.Web.Models.ContentEditing; + using Umbraco.Web.Mvc; + using Umbraco.Web.WebApi; + using Umbraco.Web.WebApi.Filters; + + using Constants = Umbraco.Core.Constants; /// /// The API controller used for editing dictionary items @@ -41,33 +40,75 @@ namespace Umbraco.Web.Editors public HttpResponseMessage Create(string name) { if (string.IsNullOrWhiteSpace(name)) - return Request - .CreateNotificationValidationErrorResponse("Name can not be empty;"); + { + return this.ReturnErrorResponse("Name can not be empty"); + } var alias = name.ToSafeAlias(); - var existingMacro = this.Services.MacroService.GetByAlias(alias); - - if (existingMacro != null) + if (this.Services.MacroService.GetByAlias(alias) != null) { - return Request.CreateNotificationValidationErrorResponse("Macro with this name already exists"); + return this.ReturnErrorResponse("Macro with this name already exists"); } try { - var macro = new Macro { Alias = alias, Name = name, MacroSource = string.Empty }; + var macro = new Macro + { + Alias = alias, + Name = name, + MacroSource = string.Empty, + MacroType = MacroTypes.PartialView + }; this.Services.MacroService.Save(macro, this.Security.CurrentUser.Id); - return Request.CreateResponse(HttpStatusCode.OK, macro.Id); + return this.Request.CreateResponse(HttpStatusCode.OK, macro.Id); } catch (Exception exception) { - this.Logger.Error(exception, "Error creating macro"); - return Request.CreateNotificationValidationErrorResponse("Error creating dictionary item"); + return this.ReturnErrorResponse("Error creating macro", true, exception); } } + [HttpGet] + public HttpResponseMessage GetById(int id) + { + var macro = this.Services.MacroService.GetById(id); + + if (macro == null) + { + return this.ReturnErrorResponse($"Macro with id {id} does not exist"); + } + + var macroDisplay = new MacroDisplay + { + Alias = macro.Alias, Id = macro.Id, Key = macro.Key, Name = macro.Name, + CacheByPage = macro.CacheByPage, CacheByUser = macro.CacheByMember, + CachePeriod = macro.CacheDuration, + View = macro.MacroSource, + RenderInEditor = !macro.DontRender, + UseInEditor = macro.UseInEditor, + Path = $"-1,{macro.Id}" + }; + + var parameters = new List(); + + foreach (var param in macro.Properties.Values.OrderBy(x => x.SortOrder)) + { + parameters.Add(new MacroParameterDisplay + { + Editor = param.EditorAlias, + Key = param.Alias, + Label = param.Name + }); + } + + macroDisplay.Parameters = parameters; + + return this.Request.CreateResponse(HttpStatusCode.OK, macroDisplay); + } + /// /// Gets a list of available macro partials /// @@ -94,6 +135,31 @@ namespace Umbraco.Web.Editors return this.Request.CreateResponse(HttpStatusCode.OK, Current.ParameterEditors); } + /// + /// Returns a error response and optionally logs it + /// + /// + /// The error message. + /// + /// + /// Value to indicate if the error needs to be logged + /// + /// + /// The exception to log + /// + /// + /// The . + /// + private HttpResponseMessage ReturnErrorResponse(string message, bool logError = false, Exception exception = null) + { + if (logError && exception != null) + { + this.Logger.Error(exception, message); + } + + return this.Request.CreateNotificationValidationErrorResponse(message); + } + /// /// Finds all the macro partials /// diff --git a/src/Umbraco.Web/Models/ContentEditing/MacroDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/MacroDisplay.cs new file mode 100644 index 0000000000..e84887b88b --- /dev/null +++ b/src/Umbraco.Web/Models/ContentEditing/MacroDisplay.cs @@ -0,0 +1,67 @@ +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace Umbraco.Web.Models.ContentEditing +{ + /// + /// The macro display model + /// + [DataContract(Name = "dictionary", Namespace = "")] + public class MacroDisplay : EntityBasic, INotificationModel + { + /// + /// Initializes a new instance of the class. + /// + public MacroDisplay() + { + this.Notifications = new List(); + this.Parameters = new List(); + } + + /// + [DataMember(Name = "notifications")] + public List Notifications { get; } + + /// + /// Gets or sets a value indicating whether the macro can be used in a rich text editor. + /// + [DataMember(Name = "useInEditor")] + public bool UseInEditor { get; set; } + + /// + /// Gets or sets a value indicating whether the macro should be rendered a rich text editor. + /// + [DataMember(Name = "renderInEditor")] + public bool RenderInEditor { get; set; } + + /// + /// Gets or sets the cache period. + /// + [DataMember(Name = "cachePeriod")] + public int CachePeriod { get; set; } + + /// + /// Gets or sets a value indicating whether the macro should be cached by page + /// + [DataMember(Name = "cacheByPage")] + public bool CacheByPage { get; set; } + + /// + /// Gets or sets a value indicating whether the macro should be cached by user + /// + [DataMember(Name = "cacheByUser")] + public bool CacheByUser { get; set; } + + /// + /// Gets or sets the view. + /// + [DataMember(Name = "view")] + public string View { get; set; } + + /// + /// Gets or sets the parameters. + /// + [DataMember(Name = "parameters")] + public IEnumerable Parameters { get; set; } + } +} diff --git a/src/Umbraco.Web/Models/ContentEditing/MacroParameterDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/MacroParameterDisplay.cs new file mode 100644 index 0000000000..56d3d1b76e --- /dev/null +++ b/src/Umbraco.Web/Models/ContentEditing/MacroParameterDisplay.cs @@ -0,0 +1,29 @@ +namespace Umbraco.Web.Models.ContentEditing +{ + using System.Runtime.Serialization; + + /// + /// The macro parameter display. + /// + [DataContract(Name = "parameter", Namespace = "")] + public class MacroParameterDisplay + { + /// + /// Gets or sets the key. + /// + [DataMember(Name = "key")] + public string Key { get; set; } + + /// + /// Gets or sets the label. + /// + [DataMember(Name = "label")] + public string Label { get; set; } + + /// + /// Gets or sets the editor. + /// + [DataMember(Name = "editor")] + public string Editor { get; set; } + } +} diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 7186835ba8..dbf422531d 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -158,6 +158,8 @@ + + From 7fd7d7a582593eb38691368be2f0b458a502bd36 Mon Sep 17 00:00:00 2001 From: Dave Woestenborghs Date: Fri, 18 Jan 2019 12:37:04 +0100 Subject: [PATCH 15/18] #3417 also send id of parameter with api response --- src/Umbraco.Web/Editors/MacrosController.cs | 3 ++- .../Models/ContentEditing/MacroParameterDisplay.cs | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web/Editors/MacrosController.cs b/src/Umbraco.Web/Editors/MacrosController.cs index d604137e19..f8214b77a8 100644 --- a/src/Umbraco.Web/Editors/MacrosController.cs +++ b/src/Umbraco.Web/Editors/MacrosController.cs @@ -100,7 +100,8 @@ { Editor = param.EditorAlias, Key = param.Alias, - Label = param.Name + Label = param.Name, + Id = param.Id }); } diff --git a/src/Umbraco.Web/Models/ContentEditing/MacroParameterDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/MacroParameterDisplay.cs index 56d3d1b76e..2a07dd84ef 100644 --- a/src/Umbraco.Web/Models/ContentEditing/MacroParameterDisplay.cs +++ b/src/Umbraco.Web/Models/ContentEditing/MacroParameterDisplay.cs @@ -25,5 +25,11 @@ /// [DataMember(Name = "editor")] public string Editor { get; set; } + + /// + /// Gets or sets the id. + /// + [DataMember(Name = "id")] + public int Id { get; set; } } } From 2dc9eb3a90c52346643a9c24a516a32c39136825 Mon Sep 17 00:00:00 2001 From: Dave Woestenborghs Date: Fri, 18 Jan 2019 15:02:18 +0100 Subject: [PATCH 16/18] #3417 handle saving of general macro data --- .../src/common/resources/macro.resource.js | 42 ++++--- .../views/macros/macros.edit.controller.js | 49 +++++---- src/Umbraco.Web/Editors/MacrosController.cs | 104 ++++++++++++++---- 3 files changed, 131 insertions(+), 64 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js index 1471abd8d3..a5d960a9ec 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/macro.resource.js @@ -20,14 +20,14 @@ function macroResource($q, $http, umbRequestHelper) { * @param {int} macroId The macro id to get parameters for * */ - getMacroParameters: function (macroId) { + getMacroParameters: function(macroId) { return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "macroRenderingApiBaseUrl", - "GetMacroParameters", - [{ macroId: macroId }])), - 'Failed to retrieve macro parameters for macro with id ' + macroId); + $http.get( + umbRequestHelper.getApiUrl( + "macroRenderingApiBaseUrl", + "GetMacroParameters", + [{ macroId: macroId }])), + 'Failed to retrieve macro parameters for macro with id ' + macroId); }, /** @@ -43,13 +43,14 @@ function macroResource($q, $http, umbRequestHelper) { * @param {Array} macroParamDictionary A dictionary of macro parameters * */ - getMacroResultAsHtmlForEditor: function (macroAlias, pageId, macroParamDictionary) { + getMacroResultAsHtmlForEditor: function(macroAlias, pageId, macroParamDictionary) { return umbRequestHelper.resourcePromise( $http.post( umbRequestHelper.getApiUrl( "macroRenderingApiBaseUrl", - "GetMacroResultAsHtmlForEditor"), { + "GetMacroResultAsHtmlForEditor"), + { macroAlias: macroAlias, pageId: pageId, macroParams: macroParamDictionary @@ -68,10 +69,11 @@ function macroResource($q, $http, umbRequestHelper) { $http.post( umbRequestHelper.getApiUrl( "macroRenderingApiBaseUrl", - "CreatePartialViewMacroWithFile"), { - virtualPath: virtualPath, - filename: filename - } + "CreatePartialViewMacroWithFile"), + { + virtualPath: virtualPath, + filename: filename + } ), 'Failed to create macro "' + filename + '"' ); @@ -96,7 +98,7 @@ function macroResource($q, $http, umbRequestHelper) { ); }, - getParameterEditors: function () { + getParameterEditors: function() { return umbRequestHelper.resourcePromise( $http.get(umbRequestHelper.getApiUrl("macroApiBaseUrl", "GetParameterEditors"), "Failed to get parameter editors") @@ -105,10 +107,16 @@ function macroResource($q, $http, umbRequestHelper) { getById: function(id) { return umbRequestHelper.resourcePromise( - $http.get(umbRequestHelper.getApiUrl("macroApiBaseUrl", "GetById", { "id" : id}), "Failed to get macro") - ); + $http.get(umbRequestHelper.getApiUrl("macroApiBaseUrl", "GetById", { "id": id }), "Failed to get macro") + ); + }, + + saveMacro: function(macro) { + return umbRequestHelper.resourcePromise( + $http.post(umbRequestHelper.getApiUrl("macroApiBaseUrl", "Save"), macro) + ); } - }; +}; } angular.module('umbraco.resources').factory('macroResource', macroResource); diff --git a/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js index 91af9b0f09..978025ceb4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js @@ -6,7 +6,7 @@ * @description * The controller for editing macros. */ -function MacrosEditController($scope, $q, $routeParams, macroResource, editorState, navigationService, dateHelper, userService, entityResource, formHelper, contentEditingHelper, localizationService, angularHelper) { +function MacrosEditController($scope, $q, $routeParams, macroResource, editorState, navigationService, formHelper, contentEditingHelper, localizationService, angularHelper) { var vm = this; @@ -25,24 +25,23 @@ function MacrosEditController($scope, $q, $routeParams, macroResource, editorSta vm.toggle = toggleValue; - function saveMacro() { - vm.page.saveButtonState = "busy"; + function saveMacro() { if (formHelper.submitForm({ scope: $scope, statusMessage: "Saving..." })) { - console.log(vm.macro); - //relationTypeResource.save(vm.relationType).then(function (data) { - // formHelper.resetForm({ scope: $scope, notifications: data.notifications }); - // bindRelationType(data); - // vm.page.saveButtonState = "success"; - //}, function (error) { - // contentEditingHelper.handleSaveError({ - // redirectOnFailure: false, - // err: error - // }); + vm.page.saveButtonState = "busy"; + + macroResource.saveMacro(vm.macro).then(function (data) { + formHelper.resetForm({ scope: $scope, notifications: data.notifications }); + bindMacro(data); + vm.page.saveButtonState = "success"; + }, function (error) { + contentEditingHelper.handleSaveError({ + redirectOnFailure: false, + err: error + }); - // notificationsService.error(error.data.message); - // vm.page.saveButtonState = "error"; - //}); + vm.page.saveButtonState = "error"; + }); } } @@ -95,6 +94,15 @@ function MacrosEditController($scope, $q, $routeParams, macroResource, editorSta return deferred.promise; } + function bindMacro(data) { + vm.macro = data; + editorState.set(vm.macro); + + navigationService.syncTree({ tree: "macros", path: vm.macro.path, forceReload: true }).then(function (syncArgs) { + vm.page.menu.currentNode = syncArgs.node; + }); + } + function init() { vm.page.loading = true; @@ -116,13 +124,8 @@ function MacrosEditController($scope, $q, $routeParams, macroResource, editorSta vm.parameterEditors = values[key]; } - if (keys[i] === 'macro') { - vm.macro = values[key]; - editorState.set(vm.macro); - - navigationService.syncTree({ tree: "macros", path: vm.macro.path, forceReload: true }).then(function (syncArgs) { - vm.page.menu.currentNode = syncArgs.node; - }); + if (keys[i] === 'macro') { + bindMacro(values[key]); } } diff --git a/src/Umbraco.Web/Editors/MacrosController.cs b/src/Umbraco.Web/Editors/MacrosController.cs index f8214b77a8..933de89635 100644 --- a/src/Umbraco.Web/Editors/MacrosController.cs +++ b/src/Umbraco.Web/Editors/MacrosController.cs @@ -15,6 +15,7 @@ using Umbraco.Web.Composing; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; + using Umbraco.Web.UI; using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; @@ -48,18 +49,18 @@ if (this.Services.MacroService.GetByAlias(alias) != null) { - return this.ReturnErrorResponse("Macro with this name already exists"); + return this.ReturnErrorResponse("Macro with this alias already exists"); } try { var macro = new Macro - { - Alias = alias, - Name = name, - MacroSource = string.Empty, - MacroType = MacroTypes.PartialView - }; + { + Alias = alias, + Name = name, + MacroSource = string.Empty, + MacroType = MacroTypes.PartialView + }; this.Services.MacroService.Save(macro, this.Security.CurrentUser.Id); @@ -72,7 +73,7 @@ } [HttpGet] - public HttpResponseMessage GetById(int id) + public HttpResponseMessage GetById(int id) { var macro = this.Services.MacroService.GetById(id); @@ -82,27 +83,31 @@ } var macroDisplay = new MacroDisplay - { - Alias = macro.Alias, Id = macro.Id, Key = macro.Key, Name = macro.Name, - CacheByPage = macro.CacheByPage, CacheByUser = macro.CacheByMember, - CachePeriod = macro.CacheDuration, - View = macro.MacroSource, - RenderInEditor = !macro.DontRender, - UseInEditor = macro.UseInEditor, - Path = $"-1,{macro.Id}" - }; + { + Alias = macro.Alias, + Id = macro.Id, + Key = macro.Key, + Name = macro.Name, + CacheByPage = macro.CacheByPage, + CacheByUser = macro.CacheByMember, + CachePeriod = macro.CacheDuration, + View = macro.MacroSource, + RenderInEditor = !macro.DontRender, + UseInEditor = macro.UseInEditor, + Path = $"-1,{macro.Id}" + }; var parameters = new List(); foreach (var param in macro.Properties.Values.OrderBy(x => x.SortOrder)) { parameters.Add(new MacroParameterDisplay - { - Editor = param.EditorAlias, - Key = param.Alias, - Label = param.Name, - Id = param.Id - }); + { + Editor = param.EditorAlias, + Key = param.Alias, + Label = param.Name, + Id = param.Id + }); } macroDisplay.Parameters = parameters; @@ -110,6 +115,57 @@ return this.Request.CreateResponse(HttpStatusCode.OK, macroDisplay); } + [HttpPost] + public HttpResponseMessage Save(MacroDisplay macroDisplay) + { + if (macroDisplay == null) + { + return this.ReturnErrorResponse($"No macro data found in request"); + } + + var macro = this.Services.MacroService.GetById(int.Parse(macroDisplay.Id.ToString())); + + if (macro == null) + { + return this.ReturnErrorResponse($"Macro with id {macroDisplay.Id} does not exist"); + } + + if (macroDisplay.Alias != macro.Alias) + { + var macroByAlias = this.Services.MacroService.GetByAlias(macroDisplay.Alias); + + if (macroByAlias != null) + { + return this.ReturnErrorResponse("Macro with this alias already exists"); + } + } + + macro.Alias = macroDisplay.Alias; + macro.Name = macroDisplay.Name; + macro.CacheByMember = macroDisplay.CacheByUser; + macro.CacheByPage = macroDisplay.CacheByPage; + macro.CacheDuration = macroDisplay.CachePeriod; + macro.DontRender = !macroDisplay.RenderInEditor; + macro.UseInEditor = macroDisplay.UseInEditor; + macro.MacroSource = macroDisplay.View; + macro.MacroType = MacroTypes.PartialView; + + try + { + this.Services.MacroService.Save(macro, this.Security.CurrentUser.Id); + + macroDisplay.Notifications.Clear(); + + macroDisplay.Notifications.Add(new Models.ContentEditing.Notification("Success", "Macro saved", SpeechBubbleIcon.Success)); + + return this.Request.CreateResponse(HttpStatusCode.OK, macroDisplay); + } + catch (Exception exception) + { + return this.ReturnErrorResponse("Error creating macro", true, exception); + } + } + /// /// Gets a list of available macro partials /// @@ -245,7 +301,7 @@ { var files = new List(); var dirInfo = new DirectoryInfo(path); - + foreach (var dir in dirInfo.GetDirectories()) { files.AddRange(this.FindPartialViewFilesInFolder(orgPath, path + "/" + dir.Name, prefixVirtualPath)); From d5c6e0c6e7fa9a85af51f1e99b99c9ccd114a2d5 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Mon, 21 Jan 2019 09:10:08 +0100 Subject: [PATCH 17/18] - Saving paramters --- src/Umbraco.Core/Collections/ObservableDictionary.cs | 12 ++++++++++++ src/Umbraco.Web/Editors/MacrosController.cs | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Collections/ObservableDictionary.cs b/src/Umbraco.Core/Collections/ObservableDictionary.cs index 6518533476..40269aa4eb 100644 --- a/src/Umbraco.Core/Collections/ObservableDictionary.cs +++ b/src/Umbraco.Core/Collections/ObservableDictionary.cs @@ -125,6 +125,18 @@ namespace Umbraco.Core.Collections } + public void ReplaceAll(IEnumerable values) + { + if (values == null) throw new ArgumentNullException(nameof(values)); + + Clear(); + + foreach (var value in values) + { + Add(value); + } + } + public bool Remove(TKey key) { if (!Indecies.ContainsKey(key)) return false; diff --git a/src/Umbraco.Web/Editors/MacrosController.cs b/src/Umbraco.Web/Editors/MacrosController.cs index 933de89635..5ff2f7bf34 100644 --- a/src/Umbraco.Web/Editors/MacrosController.cs +++ b/src/Umbraco.Web/Editors/MacrosController.cs @@ -149,6 +149,7 @@ macro.UseInEditor = macroDisplay.UseInEditor; macro.MacroSource = macroDisplay.View; macro.MacroType = MacroTypes.PartialView; + macro.Properties.ReplaceAll(macroDisplay.Parameters.Select((x,i) => new MacroProperty(x.Key, x.Label, i, x.Editor))); try { @@ -218,7 +219,7 @@ } /// - /// Finds all the macro partials + /// Finds all the macro partials /// /// /// The . From 3fd8c6354275115405528f9a1261be7376b92c88 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Mon, 21 Jan 2019 09:10:39 +0100 Subject: [PATCH 18/18] - Show Ids - Hide "Render in rich text editor and the grid" if "Use in rich text editor and the grid" is false --- .../src/views/macros/views/settings.html | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/macros/views/settings.html b/src/Umbraco.Web.UI.Client/src/views/macros/views/settings.html index ba5b324837..59ccf2bc7e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/macros/views/settings.html +++ b/src/Umbraco.Web.UI.Client/src/views/macros/views/settings.html @@ -1,8 +1,17 @@  + + + + {{model.macro.id}}
+ {{model.macro.key}} +
+
+
+ - @@ -13,9 +22,9 @@ - - - + + +