From 526b43c6232047a88a6ac6d1b8e32b95eb9b4742 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Thu, 5 Apr 2018 10:24:06 +0100 Subject: [PATCH 01/25] Bumped version number for v2 development --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 1a88947..7e3c389 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,7 +1,7 @@ image: Visual Studio 2017 # version format -version: 1.1.1.{build} +version: 2.0.0.{build} # UMBRACO_PACKAGE_PRERELEASE_SUFFIX if a rtm release build this should be blank, otherwise if empty will default to alpha # example UMBRACO_PACKAGE_PRERELEASE_SUFFIX=beta From 4c2bdaa1c9fd4b4ec60fd38296681f5d9c386932 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Sun, 1 Apr 2018 17:41:11 +0100 Subject: [PATCH 02/25] Upgrades Umbraco dependency to v7.7.0 This is done as a separate branch/PR, so to reduce the noise of following "v2" PRs. --- .../Our.Umbraco.InnerContent.csproj | 28 +++++----------- src/Our.Umbraco.InnerContent/app.config | 12 +++++-- src/Our.Umbraco.InnerContent/packages.config | 33 +++++++++++-------- 3 files changed, 37 insertions(+), 36 deletions(-) diff --git a/src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj b/src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj index f8be1d0..2ee37db 100644 --- a/src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj +++ b/src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj @@ -30,24 +30,12 @@ 4 - - ..\packages\ClientDependency.1.8.4\lib\net45\ClientDependency.Core.dll + + ..\packages\UmbracoCms.Core.7.7.0\lib\net45\interfaces.dll False - - ..\packages\UmbracoCms.Core.7.4.0\lib\interfaces.dll - False - - - ..\packages\UmbracoCms.Core.7.4.0\lib\log4net.dll - False - - - ..\packages\MiniProfiler.2.1.0\lib\net40\MiniProfiler.dll - False - - - ..\packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll + + ..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll False @@ -68,12 +56,12 @@ - - ..\packages\UmbracoCms.Core.7.4.0\lib\umbraco.dll + + ..\packages\UmbracoCms.Core.7.7.0\lib\net45\umbraco.dll False - - ..\packages\UmbracoCms.Core.7.4.0\lib\Umbraco.Core.dll + + ..\packages\UmbracoCms.Core.7.7.0\lib\net45\Umbraco.Core.dll False diff --git a/src/Our.Umbraco.InnerContent/app.config b/src/Our.Umbraco.InnerContent/app.config index 1b7e920..e317590 100644 --- a/src/Our.Umbraco.InnerContent/app.config +++ b/src/Our.Umbraco.InnerContent/app.config @@ -18,7 +18,7 @@ - + @@ -26,7 +26,7 @@ - + @@ -36,6 +36,14 @@ + + + + + + + + \ No newline at end of file diff --git a/src/Our.Umbraco.InnerContent/packages.config b/src/Our.Umbraco.InnerContent/packages.config index a56b824..f186dc0 100644 --- a/src/Our.Umbraco.InnerContent/packages.config +++ b/src/Our.Umbraco.InnerContent/packages.config @@ -1,37 +1,42 @@  - - + + - - - - + + + + + + - + + - - - - - + + + + + + - + - + + \ No newline at end of file From 7bc5d7c394d3381c78139017e43c940b714fd875 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Sun, 1 Apr 2018 17:57:16 +0100 Subject: [PATCH 03/25] Adds support for Content Templates (aka Blueprints) Reworks how the Content Type picker overlay works. Targets the overlay to the "right" panel and enables Content Type selection to follow the same pattern as creating regular content nodes. When a Content Type is selected, any Content Templates (Blueprints) will be displayed and can be selected. Underlying updates have been made to the InnerContent resource & service scripts - these may be breaking changes, though I have only tested using Stacked Content, which (at present) has no side effects. --- .../Our.Umbraco.InnerContent.csproj | 1 + .../Controllers/InnerContentApiController.cs | 38 ++++--- .../InnerContent/css/innercontent.css | 4 + .../js/innercontent.controllers.js | 103 ++++++++++++++---- .../InnerContent/js/innercontent.resources.js | 4 +- .../views/innercontent.create.html | 48 ++++++++ .../views/innercontent.overlay.html | 2 +- 7 files changed, 159 insertions(+), 41 deletions(-) create mode 100644 src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.create.html diff --git a/src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj b/src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj index 2ee37db..2438b53 100644 --- a/src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj +++ b/src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj @@ -92,6 +92,7 @@ + diff --git a/src/Our.Umbraco.InnerContent/Web/Controllers/InnerContentApiController.cs b/src/Our.Umbraco.InnerContent/Web/Controllers/InnerContentApiController.cs index 4d7db26..8c95011 100644 --- a/src/Our.Umbraco.InnerContent/Web/Controllers/InnerContentApiController.cs +++ b/src/Our.Umbraco.InnerContent/Web/Controllers/InnerContentApiController.cs @@ -32,18 +32,19 @@ public IEnumerable GetAllContentTypes() [HttpGet] public IEnumerable GetContentTypesByGuid([ModelBinder] Guid[] guids) { - return Services.ContentTypeService.GetAllContentTypes() - .Where(x => guids == null || guids.Contains(x.Key)) - .OrderBy(x => x.SortOrder) - .Select(x => new - { - id = x.Id, - guid = x.Key, - name = x.Name, - alias = x.Alias, - icon = string.IsNullOrWhiteSpace(x.Icon) || x.Icon == ".sprTreeFolder" ? "icon-folder" : x.Icon, - tabs = x.CompositionPropertyGroups.Select(y => y.Name).Distinct() - }); + var contentTypes = Services.ContentTypeService.GetAllContentTypes(guids).OrderBy(x => x.SortOrder).ToList(); + var blueprints = Services.ContentService.GetBlueprintsForContentTypes(contentTypes.Select(x => x.Id).ToArray()).ToArray(); + + // NOTE: Using an anonymous class, as the `ContentTypeBasic` type is heavier than what we need (for our requirements) + return contentTypes.Select(ct => new + { + name = ct.Name, // TODO: localize the name (in case of dictionary items), e.g. `localizedTextService.UmbracoDictionaryTranslate` + description = ct.Description, // TODO: localize the description (in case of dictionary items), e.g. `localizedTextService.UmbracoDictionaryTranslate` + key = ct.Key, + icon = string.IsNullOrWhiteSpace(ct.Icon) || ct.Icon == ".sprTreeFolder" ? "icon-document" : ct.Icon, + blueprints = blueprints.Where(bp => bp.ContentTypeId == ct.Id).ToDictionary(bp => bp.Id, bp => bp.Name) + // TODO: tabs = ct.CompositionPropertyGroups.Select(y => y.Name).Distinct() + }); } [HttpGet] @@ -75,10 +76,17 @@ public IDictionary GetContentTypeIconsByGuid([ModelBinder] Guid[ [HttpGet] [UseInternalActionFilter("Umbraco.Web.WebApi.Filters.OutgoingEditorModelEventAttribute", onActionExecuted: true)] - public ContentItemDisplay GetContentTypeScaffoldByGuid(Guid guid) + public ContentItemDisplay GetContentTypeScaffoldByGuid(Guid contentTypeGuid, int blueprintId = 0) { - var contentType = Services.ContentTypeService.GetContentType(guid); - return new ContentController().GetEmpty(contentType.Alias, -20); + var controller = new ContentController(); + + if (blueprintId > 0) + { + return controller.GetEmpty(blueprintId, -20); + } + + var contentType = Services.ContentTypeService.GetContentType(contentTypeGuid); + return controller.GetEmpty(contentType.Alias, -20); } } } \ No newline at end of file diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/css/innercontent.css b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/css/innercontent.css index 3c0fdf5..9c53cf3 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/css/innercontent.css +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/css/innercontent.css @@ -31,3 +31,7 @@ .inner-content-dialog > .nav-tabs { margin: -31px 0 0 20px; } + +.inner-content-pane { + margin: 30px 20px; +} diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js index cb31746..7ea16b7 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js @@ -16,7 +16,7 @@ angular.module("umbraco").controller("Our.Umbraco.InnerContent.Controllers.DocTy $scope.selectedDocTypeTabs = function (cfg) { var dt = _.find($scope.model.docTypes, function (itm) { - return itm.guid.toLowerCase() === cfg.icContentTypeGuid.toLowerCase(); + return itm.key.toLowerCase() === cfg.icContentTypeGuid.toLowerCase(); }); var tabs = dt ? dt.tabs : []; if (!_.contains(tabs, cfg.icTabAlias)) { @@ -82,6 +82,62 @@ angular.module("umbraco").controller("Our.Umbraco.InnerContent.Controllers.DocTy ]); // Property Editors +angular.module("umbraco").controller("Our.Umbraco.InnerContent.Controllers.InnerContentCreateController", + [ + "$scope", + "$rootScope", + "blueprintConfig", + + function ($scope, $rootScope, blueprintConfig) { + + function initialize() { + + $scope.allowedTypes = $scope.model.availableItems; + $scope.allowBlank = blueprintConfig.allowBlank; + + if ($scope.allowedTypes.length === 1) { + $scope.selectedDocType = $scope.allowedTypes[0]; + $scope.selectContentType = false; + $scope.selectBlueprint = true; + } else { + $scope.selectContentType = true; + $scope.selectBlueprint = false; + } + }; + + function createBlank(docTypeKey) { + $scope.model.selectedItem = { "key": docTypeKey, "blueprint": null }; + $scope.model.submit($scope.model); + }; + + function createOrSelectBlueprintIfAny(docType) { + var blueprintIds = _.keys(docType.blueprints || {}); + $scope.selectedDocType = docType; + if (blueprintIds.length) { + if (blueprintConfig.skipSelect) { + createFromBlueprint(docType.key, blueprintIds[0]); + } else { + $scope.selectContentType = false; + $scope.selectBlueprint = true; + } + } else { + createBlank(docType.key); + } + }; + + function createFromBlueprint(docTypeKey, blueprintId) { + $scope.model.selectedItem = { "key": docTypeKey, "blueprint": blueprintId }; + $scope.model.submit($scope.model); + }; + + $scope.createBlank = createBlank; + $scope.createOrSelectBlueprintIfAny = createOrSelectBlueprintIfAny; + $scope.createFromBlueprint = createFromBlueprint; + + initialize(); + } + ]); + angular.module("umbraco").controller("Our.Umbraco.InnerContent.Controllers.InnerContentDialogController", [ "$scope", @@ -111,16 +167,16 @@ angular.module('umbraco.directives').directive('innerContentOverlay', [ scope.config.editorModels = scope.config.editorModels || {}; scope.currentItem = null; - var getContentType = function (guid) { + var getContentType = function (key) { return _.find(scope.config.contentTypes, function (ct) { - return ct.icContentTypeGuid.toLowerCase() === guid.toLowerCase(); + return ct.icContentTypeGuid.toLowerCase() === key.toLowerCase(); }); } // Helper function to createEditorModel but at the same time // cache the scaffold so that if we create another item of the same // content type, we don't need to fetch the scaffold again - var createEditorModel = function (contentType, dbModel) { + var createEditorModel = function (contentType, blueprintId, dbModel) { var process = function (editorModel, dbModel2) { var n = angular.copy(editorModel); @@ -128,13 +184,14 @@ angular.module('umbraco.directives').directive('innerContentOverlay', [ return innerContentService.extendEditorModel(n, dbModel2); } - if (scope.config.editorModels.hasOwnProperty(contentType.icContentTypeGuid)) { - var res = process(scope.config.editorModels[contentType.icContentTypeGuid], dbModel); + var cacheKey = contentType.icContentTypeGuid + ":" + blueprintId; + if (scope.config.editorModels.hasOwnProperty(cacheKey)) { + var res = process(scope.config.editorModels[cacheKey], dbModel); return $q.when(res); } else { - return innerContentService.createEditorModel(contentType).then(function (em) { - scope.config.editorModels[contentType.icContentTypeGuid] = em; - var res = process(scope.config.editorModels[contentType.icContentTypeGuid], dbModel); + return innerContentService.createEditorModel(contentType, blueprintId).then(function (em) { + scope.config.editorModels[cacheKey] = em; + var res = process(scope.config.editorModels[cacheKey], dbModel); return res; }); } @@ -142,13 +199,14 @@ angular.module('umbraco.directives').directive('innerContentOverlay', [ } scope.contentTypePickerOverlay = { - view: "itempicker", - filter: false, + view: Umbraco.Sys.ServerVariables.umbracoSettings.appPluginsPath + "/innercontent/views/innercontent.create.html", title: "Insert Content", show: false, + hideSubmitButton: true, submit: function (model) { - var ct = getContentType(model.selectedItem.guid); - createEditorModel(ct).then(function (em) { + var ct = getContentType(model.selectedItem.key); + var bp = model.selectedItem.blueprint; + createEditorModel(ct, bp).then(function (em) { scope.currentItem = em; scope.closeContentTypePickerOverlay(); scope.openContentEditorOverlay(); @@ -184,9 +242,9 @@ angular.module('umbraco.directives').directive('innerContentOverlay', [ return; } - if (scope.contentTypePickerOverlay.availableItems.length === 1) { - var ct = getContentType(scope.contentTypePickerOverlay.availableItems[0].guid); - createEditorModel(ct).then(function (em) { + if (scope.contentTypePickerOverlay.availableItems.length === 1 && _.isEmpty(scope.contentTypePickerOverlay.availableItems[0].blueprints)) { + var ct = getContentType(scope.contentTypePickerOverlay.availableItems[0].key); + createEditorModel(ct, -1).then(function (em) { scope.currentItem = em; scope.openContentEditorOverlay(); }); @@ -227,7 +285,7 @@ angular.module('umbraco.directives').directive('innerContentOverlay', [ scope.openContentTypePickerOverlay(); } else { var ct = getContentType(scope.config.data.model.icContentTypeGuid); - createEditorModel(ct, scope.config.data.model).then(function (em) { + createEditorModel(ct, -1, scope.config.data.model).then(function (em) { scope.currentItem = em; scope.openContentEditorOverlay(); }); @@ -244,7 +302,6 @@ angular.module('umbraco.directives').directive('innerContentOverlay', [ var guids = scope.config.contentTypes.map(function (itm) { return itm.icContentTypeGuid; }); - innerContentService.getContentTypesByGuid(guids).then(function (docTypes) { // Cache items in the PE's config so we only request these once per PE instance @@ -350,8 +407,8 @@ angular.module("umbraco").factory('innerContentService', [ var self = {}; - var getScaffold = function (contentType) { - return icResources.getContentTypeScaffoldByGuid(contentType.icContentTypeGuid).then(function (scaffold) { + var getScaffold = function (contentType, blueprintId) { + return icResources.getContentTypeScaffoldByGuid(contentType.icContentTypeGuid, blueprintId).then(function (scaffold) { // remove all tabs except the specified tab if (contentType.hasOwnProperty("icTabAlias")) { @@ -416,9 +473,9 @@ angular.module("umbraco").factory('innerContentService', [ return icResources.getContentTypeIconsByGuid(guids); } - self.createEditorModel = function (contentType, dbModel) { + self.createEditorModel = function (contentType, blueprintId, dbModel) { - return getScaffold(contentType).then(function (scaffold) { + return getScaffold(contentType, blueprintId).then(function (scaffold) { scaffold.key = self.generateUid(); scaffold.icContentTypeGuid = contentType.icContentTypeGuid; @@ -478,7 +535,7 @@ angular.module("umbraco").factory('innerContentService', [ } self.createDefaultDbModel = function (contentType) { - return self.createEditorModel(contentType).then(function (editorModel) { + return self.createEditorModel(contentType, -1).then(function (editorModel) { return self.createDbModel(editorModel); }); } diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.resources.js b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.resources.js index 7053d61..657ac48 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.resources.js +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.resources.js @@ -40,12 +40,12 @@ 'Failed to retrieve content type icons' ); }, - getContentTypeScaffoldByGuid: function (guid) { + getContentTypeScaffoldByGuid: function (contentTypeGuid, blueprintId) { return umbRequestHelper.resourcePromise( $http({ url: "/umbraco/backoffice/InnerContent/InnerContentApi/GetContentTypeScaffoldByGuid", method: "GET", - params: { guid: guid } + params: { contentTypeGuid: contentTypeGuid, blueprintId: blueprintId } }), 'Failed to retrieve content type scaffold' ); diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.create.html b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.create.html new file mode 100644 index 0000000..ad7edec --- /dev/null +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.create.html @@ -0,0 +1,48 @@ +
+ +
Select a content type
+
Select a blueprint
+ +

+ +

+ + + + + +
\ No newline at end of file diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.overlay.html b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.overlay.html index 4902b96..663d047 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.overlay.html +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.overlay.html @@ -3,7 +3,7 @@ + position="right"> Date: Tue, 10 Apr 2018 11:58:12 +0100 Subject: [PATCH 04/25] Separated out the `GetScaffoldBy` controller methods https://github.com/umco/umbraco-inner-content/pull/23#discussion_r180358704 --- .../Controllers/InnerContentApiController.cs | 18 +++++++++--------- .../js/innercontent.controllers.js | 11 +++++++++-- .../InnerContent/js/innercontent.resources.js | 16 +++++++++++++--- 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/src/Our.Umbraco.InnerContent/Web/Controllers/InnerContentApiController.cs b/src/Our.Umbraco.InnerContent/Web/Controllers/InnerContentApiController.cs index 8c95011..4222dcc 100644 --- a/src/Our.Umbraco.InnerContent/Web/Controllers/InnerContentApiController.cs +++ b/src/Our.Umbraco.InnerContent/Web/Controllers/InnerContentApiController.cs @@ -76,17 +76,17 @@ public IDictionary GetContentTypeIconsByGuid([ModelBinder] Guid[ [HttpGet] [UseInternalActionFilter("Umbraco.Web.WebApi.Filters.OutgoingEditorModelEventAttribute", onActionExecuted: true)] - public ContentItemDisplay GetContentTypeScaffoldByGuid(Guid contentTypeGuid, int blueprintId = 0) + public ContentItemDisplay GetContentTypeScaffoldByGuid(Guid guid) { - var controller = new ContentController(); - - if (blueprintId > 0) - { - return controller.GetEmpty(blueprintId, -20); - } + var contentType = Services.ContentTypeService.GetContentType(guid); + return new ContentController().GetEmpty(contentType.Alias, -20); + } - var contentType = Services.ContentTypeService.GetContentType(contentTypeGuid); - return controller.GetEmpty(contentType.Alias, -20); + [HttpGet] + [UseInternalActionFilter("Umbraco.Web.WebApi.Filters.OutgoingEditorModelEventAttribute", onActionExecuted: true)] + public ContentItemDisplay GetContentTypeScaffoldByBlueprintId(int blueprintId) + { + return new ContentController().GetEmpty(blueprintId, -20); } } } \ No newline at end of file diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js index 7ea16b7..04c26c0 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js @@ -408,7 +408,8 @@ angular.module("umbraco").factory('innerContentService', [ var self = {}; var getScaffold = function (contentType, blueprintId) { - return icResources.getContentTypeScaffoldByGuid(contentType.icContentTypeGuid, blueprintId).then(function (scaffold) { + + var processScaffold = function (scaffold) { // remove all tabs except the specified tab if (contentType.hasOwnProperty("icTabAlias")) { @@ -432,7 +433,13 @@ angular.module("umbraco").factory('innerContentService', [ return scaffold; - }); + }; + + if (blueprintId > 0) { + return icResources.getContentTypeScaffoldByBlueprintId(blueprintId).then(processScaffold); + } else { + return icResources.getContentTypeScaffoldByGuid(contentType.icContentTypeGuid).then(processScaffold); + } } self.populateName = function (itm, idx, contentTypes) { diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.resources.js b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.resources.js index 657ac48..817113a 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.resources.js +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.resources.js @@ -40,14 +40,24 @@ 'Failed to retrieve content type icons' ); }, - getContentTypeScaffoldByGuid: function (contentTypeGuid, blueprintId) { + getContentTypeScaffoldByGuid: function (guid) { return umbRequestHelper.resourcePromise( $http({ url: "/umbraco/backoffice/InnerContent/InnerContentApi/GetContentTypeScaffoldByGuid", method: "GET", - params: { contentTypeGuid: contentTypeGuid, blueprintId: blueprintId } + params: { guid: guid } }), - 'Failed to retrieve content type scaffold' + 'Failed to retrieve content type scaffold by Guid' + ); + }, + getContentTypeScaffoldByBlueprintId: function (blueprintId) { + return umbRequestHelper.resourcePromise( + $http({ + url: "/umbraco/backoffice/InnerContent/InnerContentApi/GetContentTypeScaffoldByBlueprintId", + method: "GET", + params: { blueprintId: blueprintId } + }), + 'Failed to retrieve content type scaffold by blueprint Id' ); } }; From 0c346edb00fb98fe123bd79799e01697aa1a5f1b Mon Sep 17 00:00:00 2001 From: leekelleher Date: Tue, 10 Apr 2018 11:59:16 +0100 Subject: [PATCH 05/25] Added `guid` field to the `GetContentTypesByGuid` return object For backwards-compatibility reasoning. https://github.com/umco/umbraco-inner-content/pull/23#discussion_r180367080 --- .../Web/Controllers/InnerContentApiController.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Our.Umbraco.InnerContent/Web/Controllers/InnerContentApiController.cs b/src/Our.Umbraco.InnerContent/Web/Controllers/InnerContentApiController.cs index 4222dcc..829fbbe 100644 --- a/src/Our.Umbraco.InnerContent/Web/Controllers/InnerContentApiController.cs +++ b/src/Our.Umbraco.InnerContent/Web/Controllers/InnerContentApiController.cs @@ -40,6 +40,7 @@ public IEnumerable GetContentTypesByGuid([ModelBinder] Guid[] guids) { name = ct.Name, // TODO: localize the name (in case of dictionary items), e.g. `localizedTextService.UmbracoDictionaryTranslate` description = ct.Description, // TODO: localize the description (in case of dictionary items), e.g. `localizedTextService.UmbracoDictionaryTranslate` + guid = ct.Key, key = ct.Key, icon = string.IsNullOrWhiteSpace(ct.Icon) || ct.Icon == ".sprTreeFolder" ? "icon-document" : ct.Icon, blueprints = blueprints.Where(bp => bp.ContentTypeId == ct.Id).ToDictionary(bp => bp.Id, bp => bp.Name) From fddf5a5f13b07226b082c3616fa4c6617645cb3c Mon Sep 17 00:00:00 2001 From: leekelleher Date: Tue, 10 Apr 2018 12:05:11 +0100 Subject: [PATCH 06/25] Local variable rename for consistency --- .../App_Plugins/InnerContent/js/innercontent.controllers.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js index 04c26c0..f203732 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js @@ -302,10 +302,10 @@ angular.module('umbraco.directives').directive('innerContentOverlay', [ var guids = scope.config.contentTypes.map(function (itm) { return itm.icContentTypeGuid; }); - innerContentService.getContentTypesByGuid(guids).then(function (docTypes) { + innerContentService.getContentTypesByGuid(guids).then(function (contentTypes) { // Cache items in the PE's config so we only request these once per PE instance - scope.config.contentTypePickerItems = docTypes; + scope.config.contentTypePickerItems = contentTypes; initOpen(); From 8bbfa324731c96cda7cea6a657f1a75dafca1b6b Mon Sep 17 00:00:00 2001 From: leekelleher Date: Tue, 10 Apr 2018 12:12:02 +0100 Subject: [PATCH 07/25] Reverted local variable name to `guid` It makes sense in the context of the `getContentType` function. https://github.com/umco/umbraco-inner-content/pull/23#discussion_r180355724 --- .../App_Plugins/InnerContent/js/innercontent.controllers.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js index f203732..e41e0a3 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js @@ -167,9 +167,9 @@ angular.module('umbraco.directives').directive('innerContentOverlay', [ scope.config.editorModels = scope.config.editorModels || {}; scope.currentItem = null; - var getContentType = function (key) { + var getContentType = function (guid) { return _.find(scope.config.contentTypes, function (ct) { - return ct.icContentTypeGuid.toLowerCase() === key.toLowerCase(); + return ct.icContentTypeGuid.toLowerCase() === guid.toLowerCase(); }); } From e71be65c841fdedc11a8e763e8c24794e68f3ccd Mon Sep 17 00:00:00 2001 From: leekelleher Date: Tue, 10 Apr 2018 16:40:04 +0100 Subject: [PATCH 08/25] Moved the "blueprintId" argument to the end of the method signature Removed the unnecessary empty/null values that are were being passed in, (apart from one place where we have to) https://github.com/umco/umbraco-inner-content/pull/23#discussion_r180432197 --- .../InnerContent/js/innercontent.controllers.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js index e41e0a3..98fddce 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js @@ -176,7 +176,7 @@ angular.module('umbraco.directives').directive('innerContentOverlay', [ // Helper function to createEditorModel but at the same time // cache the scaffold so that if we create another item of the same // content type, we don't need to fetch the scaffold again - var createEditorModel = function (contentType, blueprintId, dbModel) { + var createEditorModel = function (contentType, dbModel, blueprintId) { var process = function (editorModel, dbModel2) { var n = angular.copy(editorModel); @@ -189,7 +189,7 @@ angular.module('umbraco.directives').directive('innerContentOverlay', [ var res = process(scope.config.editorModels[cacheKey], dbModel); return $q.when(res); } else { - return innerContentService.createEditorModel(contentType, blueprintId).then(function (em) { + return innerContentService.createEditorModel(contentType, dbModel, blueprintId).then(function (em) { scope.config.editorModels[cacheKey] = em; var res = process(scope.config.editorModels[cacheKey], dbModel); return res; @@ -206,7 +206,7 @@ angular.module('umbraco.directives').directive('innerContentOverlay', [ submit: function (model) { var ct = getContentType(model.selectedItem.key); var bp = model.selectedItem.blueprint; - createEditorModel(ct, bp).then(function (em) { + createEditorModel(ct, null, bp).then(function (em) { scope.currentItem = em; scope.closeContentTypePickerOverlay(); scope.openContentEditorOverlay(); @@ -244,7 +244,7 @@ angular.module('umbraco.directives').directive('innerContentOverlay', [ if (scope.contentTypePickerOverlay.availableItems.length === 1 && _.isEmpty(scope.contentTypePickerOverlay.availableItems[0].blueprints)) { var ct = getContentType(scope.contentTypePickerOverlay.availableItems[0].key); - createEditorModel(ct, -1).then(function (em) { + createEditorModel(ct).then(function (em) { scope.currentItem = em; scope.openContentEditorOverlay(); }); @@ -285,7 +285,7 @@ angular.module('umbraco.directives').directive('innerContentOverlay', [ scope.openContentTypePickerOverlay(); } else { var ct = getContentType(scope.config.data.model.icContentTypeGuid); - createEditorModel(ct, -1, scope.config.data.model).then(function (em) { + createEditorModel(ct, scope.config.data.model).then(function (em) { scope.currentItem = em; scope.openContentEditorOverlay(); }); @@ -480,7 +480,7 @@ angular.module("umbraco").factory('innerContentService', [ return icResources.getContentTypeIconsByGuid(guids); } - self.createEditorModel = function (contentType, blueprintId, dbModel) { + self.createEditorModel = function (contentType, dbModel, blueprintId) { return getScaffold(contentType, blueprintId).then(function (scaffold) { @@ -542,7 +542,7 @@ angular.module("umbraco").factory('innerContentService', [ } self.createDefaultDbModel = function (contentType) { - return self.createEditorModel(contentType, -1).then(function (editorModel) { + return self.createEditorModel(contentType).then(function (editorModel) { return self.createDbModel(editorModel); }); } From f078219d15c47fe59b7fb68b570368a822c0d344 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Tue, 10 Apr 2018 16:41:06 +0100 Subject: [PATCH 09/25] Code tidyup - Clarified a TODO note - Removed the "tabs" field, as it isn't being used by IC (nor SC) - Renamed JS local variable --- .../Web/Controllers/InnerContentApiController.cs | 9 ++++++--- .../InnerContent/js/innercontent.controllers.js | 6 +++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Our.Umbraco.InnerContent/Web/Controllers/InnerContentApiController.cs b/src/Our.Umbraco.InnerContent/Web/Controllers/InnerContentApiController.cs index 829fbbe..e76d4f5 100644 --- a/src/Our.Umbraco.InnerContent/Web/Controllers/InnerContentApiController.cs +++ b/src/Our.Umbraco.InnerContent/Web/Controllers/InnerContentApiController.cs @@ -38,13 +38,16 @@ public IEnumerable GetContentTypesByGuid([ModelBinder] Guid[] guids) // NOTE: Using an anonymous class, as the `ContentTypeBasic` type is heavier than what we need (for our requirements) return contentTypes.Select(ct => new { - name = ct.Name, // TODO: localize the name (in case of dictionary items), e.g. `localizedTextService.UmbracoDictionaryTranslate` - description = ct.Description, // TODO: localize the description (in case of dictionary items), e.g. `localizedTextService.UmbracoDictionaryTranslate` + // TODO: localize the name and description (in case of dictionary items) + // Umbraco core uses `localizedTextService.UmbracoDictionaryTranslate`, but this is currently marked as internal. + // https://github.com/umbraco/Umbraco-CMS/blob/release-7.7.0/src/Umbraco.Core/Services/LocalizedTextServiceExtensions.cs#L76 + + name = ct.Name, + description = ct.Description, guid = ct.Key, key = ct.Key, icon = string.IsNullOrWhiteSpace(ct.Icon) || ct.Icon == ".sprTreeFolder" ? "icon-document" : ct.Icon, blueprints = blueprints.Where(bp => bp.ContentTypeId == ct.Id).ToDictionary(bp => bp.Id, bp => bp.Name) - // TODO: tabs = ct.CompositionPropertyGroups.Select(y => y.Name).Distinct() }); } diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js index 98fddce..97af8e9 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js @@ -409,7 +409,7 @@ angular.module("umbraco").factory('innerContentService', [ var getScaffold = function (contentType, blueprintId) { - var processScaffold = function (scaffold) { + var process = function (scaffold) { // remove all tabs except the specified tab if (contentType.hasOwnProperty("icTabAlias")) { @@ -436,9 +436,9 @@ angular.module("umbraco").factory('innerContentService', [ }; if (blueprintId > 0) { - return icResources.getContentTypeScaffoldByBlueprintId(blueprintId).then(processScaffold); + return icResources.getContentTypeScaffoldByBlueprintId(blueprintId).then(process); } else { - return icResources.getContentTypeScaffoldByGuid(contentType.icContentTypeGuid).then(processScaffold); + return icResources.getContentTypeScaffoldByGuid(contentType.icContentTypeGuid).then(process); } } From b37fd3f4dd93dcd15eb2895203e34d0618f803e1 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Thu, 19 Apr 2018 14:16:08 +0100 Subject: [PATCH 10/25] [WIP] Save item as blueprint Added C# code to convert the JSON data to an IContent and save as a Content Template (aka Blueprint) --- .../Helpers/InnerContentHelper.cs | 37 +++++++++++++++++++ .../Controllers/InnerContentApiController.cs | 16 ++++++++ 2 files changed, 53 insertions(+) diff --git a/src/Our.Umbraco.InnerContent/Helpers/InnerContentHelper.cs b/src/Our.Umbraco.InnerContent/Helpers/InnerContentHelper.cs index ef26ecd..fac4287 100644 --- a/src/Our.Umbraco.InnerContent/Helpers/InnerContentHelper.cs +++ b/src/Our.Umbraco.InnerContent/Helpers/InnerContentHelper.cs @@ -154,5 +154,42 @@ internal static PublishedContentType GetPublishedContentTypeFromItem(JObject ite return PublishedContentType.Get(PublishedItemType.Content, contentTypeAlias); } + + internal static IContent ConvertInnerContentToBlueprint(JObject item, int userId = 0) + { + var contentType = GetContentTypeFromItem(item); + + // creates a fast lookup of the property types + var propertyTypes = contentType.PropertyTypes.ToDictionary(x => x.Alias, x => x, StringComparer.InvariantCultureIgnoreCase); + + var propValues = item.ToObject>(); + var properties = new List(); + + foreach (var jProp in propValues) + { + if (propertyTypes.ContainsKey(jProp.Key) == false) + continue; + + var propType = propertyTypes[jProp.Key]; + if (propType != null) + { + // TODO: Check if we need to call `ConvertEditorToDb`? + properties.Add(new Property(propType, jProp.Value)); + } + } + + // Manually parse out the special properties + propValues.TryGetValue("name", out object name); + propValues.TryGetValue("key", out object key); + + return new Content(name?.ToString(), -1, contentType, new PropertyCollection(properties)) + { + Key = key == null ? Guid.Empty : Guid.Parse(key.ToString()), + ParentId = -1, + Path = "-1", + CreatorId = userId, + WriterId = userId + }; + } } } \ No newline at end of file diff --git a/src/Our.Umbraco.InnerContent/Web/Controllers/InnerContentApiController.cs b/src/Our.Umbraco.InnerContent/Web/Controllers/InnerContentApiController.cs index e76d4f5..af6ff1d 100644 --- a/src/Our.Umbraco.InnerContent/Web/Controllers/InnerContentApiController.cs +++ b/src/Our.Umbraco.InnerContent/Web/Controllers/InnerContentApiController.cs @@ -3,7 +3,10 @@ using System.Linq; using System.Web.Http; using System.Web.Http.ModelBinding; +using Newtonsoft.Json.Linq; +using Our.Umbraco.InnerContent.Helpers; using Our.Umbraco.InnerContent.Web.WebApi.Filters; +using Umbraco.Core.Services; using Umbraco.Web.Editors; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; @@ -92,5 +95,18 @@ public ContentItemDisplay GetContentTypeScaffoldByBlueprintId(int blueprintId) { return new ContentController().GetEmpty(blueprintId, -20); } + + [HttpPost] + public SimpleNotificationModel CreateBlueprintFromContent([FromBody] JObject item, int userId = 0) + { + var blueprint = InnerContentHelper.ConvertInnerContentToBlueprint(item, userId); + + Services.ContentService.SaveBlueprint(blueprint, userId); + + return new SimpleNotificationModel(new Notification( + Services.TextService.Localize("blueprints/createdBlueprintHeading"), + Services.TextService.Localize("blueprints/createdBlueprintMessage", new[] { blueprint.Name }), + global::Umbraco.Web.UI.SpeechBubbleIcon.Success)); + } } } \ No newline at end of file From 3b79668a84e24e1591ccc2022de9f9ab0f2b7053 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 23 Apr 2018 16:28:25 +0100 Subject: [PATCH 11/25] Consistency --- src/Our.Umbraco.InnerContent/Helpers/InnerContentHelper.cs | 3 ++- .../UI/App_Plugins/InnerContent/views/innercontent.create.html | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Our.Umbraco.InnerContent/Helpers/InnerContentHelper.cs b/src/Our.Umbraco.InnerContent/Helpers/InnerContentHelper.cs index ef26ecd..5c34c02 100644 --- a/src/Our.Umbraco.InnerContent/Helpers/InnerContentHelper.cs +++ b/src/Our.Umbraco.InnerContent/Helpers/InnerContentHelper.cs @@ -23,7 +23,8 @@ public static IEnumerable ConvertInnerContentToPublishedConte return items.Select((x, i) => ConvertInnerContentToPublishedContent((JObject)x, parentNode, i, level, preview)).ToList(); } - public static IPublishedContent ConvertInnerContentToPublishedContent(JObject item, + public static IPublishedContent ConvertInnerContentToPublishedContent( + JObject item, IPublishedContent parentNode = null, int sortOrder = 0, int level = 0, diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.create.html b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.create.html index ad7edec..b8d815e 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.create.html +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.create.html @@ -1,6 +1,6 @@ 
-
Select a content type
+
Select a Content Type
Select a blueprint

From fc74f559159e9a7994ead2f87e4457f1328c5592 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 23 Apr 2018 16:28:55 +0100 Subject: [PATCH 12/25] Changed overlay title to be "Edit" + the content-type name --- .../UI/App_Plugins/InnerContent/js/innercontent.controllers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js index 97af8e9..81f7d3a 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js @@ -260,7 +260,7 @@ angular.module('umbraco.directives').directive('innerContentOverlay', [ }; scope.openContentEditorOverlay = function () { - scope.contentEditorOverlay.title = "Edit item"; + scope.contentEditorOverlay.title = "Edit " + scope.currentItem.contentTypeName; scope.contentEditorOverlay.dialogData = { item: scope.currentItem }; scope.contentEditorOverlay.show = true; }; From f704cbda89ea0505cb932634ac5a4f32fb436b50 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Tue, 8 May 2018 18:05:55 +0100 Subject: [PATCH 13/25] Adds a unique suffix to the tab ID When using doctype compositions, the tab Id may conflict with any nested inner-content items. This patch attempts to make the tab ID to be unique. See https://github.com/umco/umbraco-stacked-content/issues/23 for further background on this issue. --- .../InnerContent/js/innercontent.controllers.js | 9 ++++++--- .../InnerContent/views/innercontent.dialog.html | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js index 81f7d3a..1907cee 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js @@ -141,16 +141,19 @@ angular.module("umbraco").controller("Our.Umbraco.InnerContent.Controllers.Inner angular.module("umbraco").controller("Our.Umbraco.InnerContent.Controllers.InnerContentDialogController", [ "$scope", - "$rootScope", - "$interpolate", + "overlayHelper", - function ($scope, $rootScope) { + function ($scope, overlayHelper) { $scope.item = $scope.model.dialogData.item; // Set a nodeContext property as nested property editors // can use this to know what doc type this node is etc // NC + DTGE do the same $scope.nodeContext = $scope.item; + + // When using doctype compositions, the tab Id may conflict with any nested inner-content items. + // This attempts to make the tab ID to be unique. + $scope.tabIdSuffix = "_" + $scope.item.contentTypeAlias + "_" + overlayHelper.getNumberOfOverlays(); } ]); diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.dialog.html b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.dialog.html index 439518f..3b9072e 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.dialog.html +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.dialog.html @@ -1,10 +1,10 @@ 

- +
- + From 3b91cdc7b1c24a60ecc9b81092faf45bc2f698bf Mon Sep 17 00:00:00 2001 From: leekelleher Date: Tue, 8 May 2018 22:34:14 +0100 Subject: [PATCH 14/25] Adds Copy/Paste API Uses the localStorage API for copy & paste mechanism. --- .../js/innercontent.controllers.js | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js index 81f7d3a..5f9bdff 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js @@ -400,10 +400,10 @@ angular.module("umbraco").factory('innerContentService', [ "$q", "$interpolate", "contentResource", - + "localStorageService", "Our.Umbraco.InnerContent.Resources.InnerContentResources", - function ($q, $interpolate, contentResource, icResources) { + function ($q, $interpolate, contentResource, localStorageService, icResources) { var self = {}; @@ -602,6 +602,34 @@ angular.module("umbraco").factory('innerContentService', [ } + self.canCopyContent = function () { + return localStorageService.isSupported; + }; + + self.canPasteContent = function () { + return localStorageService.isSupported; + }; + + self.setCopiedContent = function (itm) { + if (itm && itm.icContentTypeGuid) { + localStorageService.set("icContentTypeGuid", itm.icContentTypeGuid); + itm.key = undefined; + localStorageService.set("icContentJson", itm); + return true; + } + return false; + } + + self.getCopiedContent = function () { + var itm = localStorageService.get("icContentJson"); + itm.key = self.generateUid(); + return itm; + } + + self.getCopiedContentTypeGuid = function () { + return localStorageService.get("icContentTypeGuid"); + } + // Helpful methods var lut = []; for (var i = 0; i < 256; i++) { lut[i] = (i < 16 ? '0' : '') + (i).toString(16); } self.generateUid = function () { From 4487519dbc223ef2409f5f30141344cef6cb7f2e Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 2 Jul 2018 14:13:18 +0100 Subject: [PATCH 15/25] Breaking-change: Renamed the namespace for the `InnerContentValueConverter` This is to keep the namespaces consistent with other UMCO projects. --- src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj | 2 +- .../InnerContentValueConverter.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/Our.Umbraco.InnerContent/{Converters => ValueConverters}/InnerContentValueConverter.cs (95%) diff --git a/src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj b/src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj index 2438b53..4054aa7 100644 --- a/src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj +++ b/src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj @@ -67,7 +67,7 @@ - + diff --git a/src/Our.Umbraco.InnerContent/Converters/InnerContentValueConverter.cs b/src/Our.Umbraco.InnerContent/ValueConverters/InnerContentValueConverter.cs similarity index 95% rename from src/Our.Umbraco.InnerContent/Converters/InnerContentValueConverter.cs rename to src/Our.Umbraco.InnerContent/ValueConverters/InnerContentValueConverter.cs index 10a74d8..54afb1c 100644 --- a/src/Our.Umbraco.InnerContent/Converters/InnerContentValueConverter.cs +++ b/src/Our.Umbraco.InnerContent/ValueConverters/InnerContentValueConverter.cs @@ -4,7 +4,7 @@ using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; -namespace Our.Umbraco.InnerContent.Converters +namespace Our.Umbraco.InnerContent.ValueConverters { public abstract class InnerContentValueConverter : PropertyValueConverterBase { From 2525bbae177dc2dd4701d99758ad7c6c434157b9 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 2 Jul 2018 14:14:18 +0100 Subject: [PATCH 16/25] Breaking-change: Removed the "Wrapper" suffix from `InnerContentPropertyValueEditorWrapper` It doesn't need it, since there is only one ValueEditor class for InnerContent. --- src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj | 2 +- ...lueEditorWrapper.cs => InnerContentPropertyValueEditor.cs} | 4 ++-- .../PropertyEditors/SimpleInnerContentPropertyValueEditor.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) rename src/Our.Umbraco.InnerContent/PropertyEditors/{InnerContentPropertyValueEditorWrapper.cs => InnerContentPropertyValueEditor.cs} (98%) diff --git a/src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj b/src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj index 4054aa7..0ddfb73 100644 --- a/src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj +++ b/src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj @@ -76,7 +76,7 @@ - + diff --git a/src/Our.Umbraco.InnerContent/PropertyEditors/InnerContentPropertyValueEditorWrapper.cs b/src/Our.Umbraco.InnerContent/PropertyEditors/InnerContentPropertyValueEditor.cs similarity index 98% rename from src/Our.Umbraco.InnerContent/PropertyEditors/InnerContentPropertyValueEditorWrapper.cs rename to src/Our.Umbraco.InnerContent/PropertyEditors/InnerContentPropertyValueEditor.cs index 77caf30..b9043af 100644 --- a/src/Our.Umbraco.InnerContent/PropertyEditors/InnerContentPropertyValueEditorWrapper.cs +++ b/src/Our.Umbraco.InnerContent/PropertyEditors/InnerContentPropertyValueEditor.cs @@ -12,9 +12,9 @@ namespace Our.Umbraco.InnerContent.PropertyEditors { - public abstract class InnerContentPropertyValueEditorWrapper : PropertyValueEditorWrapper + public abstract class InnerContentPropertyValueEditor : PropertyValueEditorWrapper { - protected InnerContentPropertyValueEditorWrapper(PropertyValueEditor wrapped) + protected InnerContentPropertyValueEditor(PropertyValueEditor wrapped) : base(wrapped) { } diff --git a/src/Our.Umbraco.InnerContent/PropertyEditors/SimpleInnerContentPropertyValueEditor.cs b/src/Our.Umbraco.InnerContent/PropertyEditors/SimpleInnerContentPropertyValueEditor.cs index 20087da..b382126 100644 --- a/src/Our.Umbraco.InnerContent/PropertyEditors/SimpleInnerContentPropertyValueEditor.cs +++ b/src/Our.Umbraco.InnerContent/PropertyEditors/SimpleInnerContentPropertyValueEditor.cs @@ -8,7 +8,7 @@ namespace Our.Umbraco.InnerContent.PropertyEditors { - public class SimpleInnerContentPropertyValueEditor : InnerContentPropertyValueEditorWrapper + public class SimpleInnerContentPropertyValueEditor : InnerContentPropertyValueEditor { public SimpleInnerContentPropertyValueEditor(PropertyValueEditor wrapped) : base(wrapped) From 5baa08f9aafe435ea913ad544651165f6815b077 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 2 Jul 2018 14:15:14 +0100 Subject: [PATCH 17/25] JS quote consistency We had a mix of both single and double quotes, opted to use the latter. --- .../js/innercontent.controllers.js | 30 +++++++++---------- .../InnerContent/js/innercontent.resources.js | 14 ++++----- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js index 9df7c18..042f187 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js @@ -30,7 +30,7 @@ angular.module("umbraco").controller("Our.Umbraco.InnerContent.Controllers.DocTy } $scope.sortableOptions = { - axis: 'y', + axis: "y", cursor: "move", handle: ".icon-navigation" }; @@ -65,7 +65,7 @@ angular.module("umbraco").controller("Our.Umbraco.InnerContent.Controllers.DocTy } $scope.sortableOptions = { - axis: 'y', + axis: "y", cursor: "move", handle: ".icon-navigation" }; @@ -158,7 +158,7 @@ angular.module("umbraco").controller("Our.Umbraco.InnerContent.Controllers.Inner ]); // Directives -angular.module('umbraco.directives').directive('innerContentOverlay', [ +angular.module("umbraco.directives").directive("innerContentOverlay", [ "$q", "innerContentService", @@ -324,9 +324,9 @@ angular.module('umbraco.directives').directive('innerContentOverlay', [ } var directive = { - restrict: 'E', + restrict: "E", replace: true, - templateUrl: Umbraco.Sys.ServerVariables.umbracoSettings.appPluginsPath + '/innercontent/views/innercontent.overlay.html', + templateUrl: Umbraco.Sys.ServerVariables.umbracoSettings.appPluginsPath + "/innercontent/views/innercontent.overlay.html", scope: { config: "=" }, @@ -338,7 +338,7 @@ angular.module('umbraco.directives').directive('innerContentOverlay', [ } ]); -angular.module('umbraco.directives').directive('innerContentUnsavedChanges', [ +angular.module("umbraco.directives").directive("innerContentUnsavedChanges", [ "$rootScope", @@ -386,9 +386,9 @@ angular.module('umbraco.directives').directive('innerContentUnsavedChanges', [ } var directive = { - restrict: 'E', + restrict: "E", replace: true, - templateUrl: Umbraco.Sys.ServerVariables.umbracoSettings.appPluginsPath + '/innercontent/views/innercontent.unsavedchanges.html', + templateUrl: Umbraco.Sys.ServerVariables.umbracoSettings.appPluginsPath + "/innercontent/views/innercontent.unsavedchanges.html", link: link }; @@ -398,7 +398,7 @@ angular.module('umbraco.directives').directive('innerContentUnsavedChanges', [ ]); // Services -angular.module("umbraco").factory('innerContentService', [ +angular.module("umbraco").factory("innerContentService", [ "$q", "$interpolate", @@ -558,8 +558,8 @@ angular.module("umbraco").factory('innerContentService', [ var lexicographical = options && options.lexicographical, zeroExtend = options && options.zeroExtend, - v1parts = v1.split('.'), - v2parts = v2.split('.'); + v1parts = v1.split("."), + v2parts = v2.split("."); function isValidPart(x) { return (lexicographical ? /^\d+[A-Za-z]*$/ : /^\d+$/).test(x); @@ -634,15 +634,15 @@ angular.module("umbraco").factory('innerContentService', [ } // Helpful methods - var lut = []; for (var i = 0; i < 256; i++) { lut[i] = (i < 16 ? '0' : '') + (i).toString(16); } + var lut = []; for (var i = 0; i < 256; i++) { lut[i] = (i < 16 ? "0" : "") + (i).toString(16); } self.generateUid = function () { var d0 = Math.random() * 0xffffffff | 0; var d1 = Math.random() * 0xffffffff | 0; var d2 = Math.random() * 0xffffffff | 0; var d3 = Math.random() * 0xffffffff | 0; - return lut[d0 & 0xff] + lut[d0 >> 8 & 0xff] + lut[d0 >> 16 & 0xff] + lut[d0 >> 24 & 0xff] + '-' + - lut[d1 & 0xff] + lut[d1 >> 8 & 0xff] + '-' + lut[d1 >> 16 & 0x0f | 0x40] + lut[d1 >> 24 & 0xff] + '-' + - lut[d2 & 0x3f | 0x80] + lut[d2 >> 8 & 0xff] + '-' + lut[d2 >> 16 & 0xff] + lut[d2 >> 24 & 0xff] + + return lut[d0 & 0xff] + lut[d0 >> 8 & 0xff] + lut[d0 >> 16 & 0xff] + lut[d0 >> 24 & 0xff] + "-" + + lut[d1 & 0xff] + lut[d1 >> 8 & 0xff] + "-" + lut[d1 >> 16 & 0x0f | 0x40] + lut[d1 >> 24 & 0xff] + "-" + + lut[d2 & 0x3f | 0x80] + lut[d2 >> 8 & 0xff] + "-" + lut[d2 >> 16 & 0xff] + lut[d2 >> 24 & 0xff] + lut[d3 & 0xff] + lut[d3 >> 8 & 0xff] + lut[d3 >> 16 & 0xff] + lut[d3 >> 24 & 0xff]; } diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.resources.js b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.resources.js index 817113a..e6c1014 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.resources.js +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.resources.js @@ -1,4 +1,4 @@ -angular.module('umbraco.resources').factory('Our.Umbraco.InnerContent.Resources.InnerContentResources', +angular.module("umbraco.resources").factory("Our.Umbraco.InnerContent.Resources.InnerContentResources", function ($q, $http, umbRequestHelper) { return { getAllContentTypes: function () { @@ -7,7 +7,7 @@ url: "/umbraco/backoffice/InnerContent/InnerContentApi/GetAllContentTypes", method: "GET" }), - 'Failed to retrieve content types' + "Failed to retrieve content types" ); }, getContentTypesByGuid: function (guids) { @@ -17,7 +17,7 @@ method: "GET", params: { guids: guids } }), - 'Failed to retrieve content types' + "Failed to retrieve content types" ); }, getContentTypesByAlias: function (aliases) { @@ -27,7 +27,7 @@ method: "GET", params: { aliases: aliases } }), - 'Failed to retrieve content types' + "Failed to retrieve content types" ); }, getContentTypeIconsByGuid: function (guids) { @@ -37,7 +37,7 @@ method: "GET", params: { guids: guids } }), - 'Failed to retrieve content type icons' + "Failed to retrieve content type icons" ); }, getContentTypeScaffoldByGuid: function (guid) { @@ -47,7 +47,7 @@ method: "GET", params: { guid: guid } }), - 'Failed to retrieve content type scaffold by Guid' + "Failed to retrieve content type scaffold by Guid" ); }, getContentTypeScaffoldByBlueprintId: function (blueprintId) { @@ -57,7 +57,7 @@ method: "GET", params: { blueprintId: blueprintId } }), - 'Failed to retrieve content type scaffold by blueprint Id' + "Failed to retrieve content type scaffold by blueprint Id" ); } }; From 306d7ca4a5bfad4196ccd4f916d91c0eadad1187 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 2 Jul 2018 14:29:48 +0100 Subject: [PATCH 18/25] Combined the controllers and resources JS files This cuts down on the extra HTTP request in the backoffice. --- .../Our.Umbraco.InnerContent.csproj | 3 +- ...content.controllers.js => innercontent.js} | 68 ++++++++++++++++++- .../InnerContent/js/innercontent.resources.js | 64 ----------------- .../App_Plugins/InnerContent/package.manifest | 13 ++-- 4 files changed, 74 insertions(+), 74 deletions(-) rename src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/{innercontent.controllers.js => innercontent.js} (88%) delete mode 100644 src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.resources.js diff --git a/src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj b/src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj index 0ddfb73..9467cb0 100644 --- a/src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj +++ b/src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj @@ -90,8 +90,7 @@ - - + diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js similarity index 88% rename from src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js rename to src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js index 042f187..1777bf9 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.controllers.js +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js @@ -649,4 +649,70 @@ angular.module("umbraco").factory("innerContentService", [ return self; } -]); \ No newline at end of file +]); + +// Resources +angular.module("umbraco.resources").factory("Our.Umbraco.InnerContent.Resources.InnerContentResources", + function ($q, $http, umbRequestHelper) { + return { + getAllContentTypes: function () { + return umbRequestHelper.resourcePromise( + $http({ + url: "/umbraco/backoffice/InnerContent/InnerContentApi/GetAllContentTypes", + method: "GET" + }), + "Failed to retrieve content types" + ); + }, + getContentTypesByGuid: function (guids) { + return umbRequestHelper.resourcePromise( + $http({ + url: "/umbraco/backoffice/InnerContent/InnerContentApi/GetContentTypesByGuid", + method: "GET", + params: { guids: guids } + }), + "Failed to retrieve content types" + ); + }, + getContentTypesByAlias: function (aliases) { + return umbRequestHelper.resourcePromise( + $http({ + url: "/umbraco/backoffice/InnerContent/InnerContentApi/GetContentTypesByAlias", + method: "GET", + params: { aliases: aliases } + }), + "Failed to retrieve content types" + ); + }, + getContentTypeIconsByGuid: function (guids) { + return umbRequestHelper.resourcePromise( + $http({ + url: "/umbraco/backoffice/InnerContent/InnerContentApi/GetContentTypeIconsByGuid", + method: "GET", + params: { guids: guids } + }), + "Failed to retrieve content type icons" + ); + }, + getContentTypeScaffoldByGuid: function (guid) { + return umbRequestHelper.resourcePromise( + $http({ + url: "/umbraco/backoffice/InnerContent/InnerContentApi/GetContentTypeScaffoldByGuid", + method: "GET", + params: { guid: guid } + }), + "Failed to retrieve content type scaffold by Guid" + ); + }, + getContentTypeScaffoldByBlueprintId: function (blueprintId) { + return umbRequestHelper.resourcePromise( + $http({ + url: "/umbraco/backoffice/InnerContent/InnerContentApi/GetContentTypeScaffoldByBlueprintId", + method: "GET", + params: { blueprintId: blueprintId } + }), + "Failed to retrieve content type scaffold by blueprint Id" + ); + } + }; + }); diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.resources.js b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.resources.js deleted file mode 100644 index e6c1014..0000000 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.resources.js +++ /dev/null @@ -1,64 +0,0 @@ -angular.module("umbraco.resources").factory("Our.Umbraco.InnerContent.Resources.InnerContentResources", - function ($q, $http, umbRequestHelper) { - return { - getAllContentTypes: function () { - return umbRequestHelper.resourcePromise( - $http({ - url: "/umbraco/backoffice/InnerContent/InnerContentApi/GetAllContentTypes", - method: "GET" - }), - "Failed to retrieve content types" - ); - }, - getContentTypesByGuid: function (guids) { - return umbRequestHelper.resourcePromise( - $http({ - url: "/umbraco/backoffice/InnerContent/InnerContentApi/GetContentTypesByGuid", - method: "GET", - params: { guids: guids } - }), - "Failed to retrieve content types" - ); - }, - getContentTypesByAlias: function (aliases) { - return umbRequestHelper.resourcePromise( - $http({ - url: "/umbraco/backoffice/InnerContent/InnerContentApi/GetContentTypesByAlias", - method: "GET", - params: { aliases: aliases } - }), - "Failed to retrieve content types" - ); - }, - getContentTypeIconsByGuid: function (guids) { - return umbRequestHelper.resourcePromise( - $http({ - url: "/umbraco/backoffice/InnerContent/InnerContentApi/GetContentTypeIconsByGuid", - method: "GET", - params: { guids: guids } - }), - "Failed to retrieve content type icons" - ); - }, - getContentTypeScaffoldByGuid: function (guid) { - return umbRequestHelper.resourcePromise( - $http({ - url: "/umbraco/backoffice/InnerContent/InnerContentApi/GetContentTypeScaffoldByGuid", - method: "GET", - params: { guid: guid } - }), - "Failed to retrieve content type scaffold by Guid" - ); - }, - getContentTypeScaffoldByBlueprintId: function (blueprintId) { - return umbRequestHelper.resourcePromise( - $http({ - url: "/umbraco/backoffice/InnerContent/InnerContentApi/GetContentTypeScaffoldByBlueprintId", - method: "GET", - params: { blueprintId: blueprintId } - }), - "Failed to retrieve content type scaffold by blueprint Id" - ); - } - }; - }); \ No newline at end of file diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/package.manifest b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/package.manifest index 85d0c3f..f7e52f9 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/package.manifest +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/package.manifest @@ -1,9 +1,8 @@ { - "javascript" : [ - "~/App_Plugins/InnerContent/js/innercontent.resources.js", - "~/App_Plugins/InnerContent/js/innercontent.controllers.js" - ], - "css" : [ - "~/App_Plugins/InnerContent/css/innercontent.css" - ] + "javascript": [ + "~/App_Plugins/InnerContent/js/innercontent.js" + ], + "css": [ + "~/App_Plugins/InnerContent/css/innercontent.css" + ] } \ No newline at end of file From 1dde58c4c825798d58dc767c0f7b4c914e2a5f9b Mon Sep 17 00:00:00 2001 From: leekelleher Date: Wed, 11 Jul 2018 17:42:41 +0100 Subject: [PATCH 19/25] Applied ESLint rules to our JS file --- .../InnerContent/js/innercontent.js | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js index face8d7..d1ea5ff 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js @@ -12,7 +12,7 @@ angular.module("umbraco").controller("Our.Umbraco.InnerContent.Controllers.DocTy icTabAlias: "", nameTemplate: "" }); - } + }; $scope.selectedDocTypeTabs = function (cfg) { var dt = _.find($scope.model.docTypes, function (itm) { @@ -23,11 +23,11 @@ angular.module("umbraco").controller("Our.Umbraco.InnerContent.Controllers.DocTy cfg.icTabAlias = tabs[0]; } return tabs; - } + }; $scope.remove = function (index) { $scope.model.value.splice(index, 1); - } + }; $scope.sortableOptions = { axis: "y", @@ -58,11 +58,11 @@ angular.module("umbraco").controller("Our.Umbraco.InnerContent.Controllers.DocTy icContentTypeGuid: "", nameTemplate: "" }); - } + }; $scope.remove = function (index) { $scope.model.value.splice(index, 1); - } + }; $scope.sortableOptions = { axis: "y", @@ -174,7 +174,7 @@ angular.module("umbraco.directives").directive("innerContentOverlay", [ return _.find(scope.config.contentTypes, function (ct) { return ct.icContentTypeGuid.toLowerCase() === guid.toLowerCase(); }); - } + }; // Helper function to createEditorModel but at the same time // cache the scaffold so that if we create another item of the same @@ -185,7 +185,7 @@ angular.module("umbraco.directives").directive("innerContentOverlay", [ var n = angular.copy(editorModel); n.key = innerContentService.generateUid(); // Create new ID for item return innerContentService.extendEditorModel(n, dbModel2); - } + }; var cacheKey = contentType.icContentTypeGuid + ":" + blueprintId; if (scope.config.editorModels.hasOwnProperty(cacheKey)) { @@ -199,7 +199,7 @@ angular.module("umbraco.directives").directive("innerContentOverlay", [ }); } - } + }; scope.contentTypePickerOverlay = { view: Umbraco.Sys.ServerVariables.umbracoSettings.appPluginsPath + "/innercontent/views/innercontent.create.html", @@ -297,7 +297,7 @@ angular.module("umbraco.directives").directive("innerContentOverlay", [ }); } - } + }; // Initialize if (scope.config) { @@ -374,17 +374,17 @@ angular.module("umbraco.directives").directive("innerContentUnsavedChanges", [ } else { overlayScope.oldCloseOverLay.apply(overlayScope); } - } + }; } scope.confirmClose = function () { scope.showConfirmClose = false; overlayScope.oldCloseOverLay.apply(overlayScope); - } + }; scope.cancelClose = function () { scope.showConfirmClose = false; - } + }; } @@ -446,7 +446,7 @@ angular.module("umbraco").factory("innerContentService", [ } else { return icResources.getContentTypeScaffoldByGuid(contentType.icContentTypeGuid).then(process); } - } + }; self.populateName = function (itm, idx, contentTypes) { @@ -472,19 +472,19 @@ angular.module("umbraco").factory("innerContentService", [ delete itm.$index; } - } + }; self.getAllContentTypes = function () { return icResources.getAllContentTypes(); - } + }; self.getContentTypesByGuid = function (guids) { return icResources.getContentTypesByGuid(guids); - } + }; self.getContentTypeIconsByGuid = function (guids) { return icResources.getContentTypeIconsByGuid(guids); - } + }; self.createEditorModel = function (contentType, dbModel, blueprintId) { @@ -498,7 +498,7 @@ angular.module("umbraco").factory("innerContentService", [ }); - } + }; self.extendEditorModel = function (editorModel, dbModel) { @@ -523,7 +523,7 @@ angular.module("umbraco").factory("innerContentService", [ return editorModel; - } + }; self.createDbModel = function (model) { @@ -545,17 +545,17 @@ angular.module("umbraco").factory("innerContentService", [ } return dbModel; - } + }; self.createDefaultDbModel = function (contentType) { return self.createEditorModel(contentType).then(function (editorModel) { return self.createDbModel(editorModel); }); - } + }; self.compareCurrentUmbracoVersion = function compareCurrentUmbracoVersion(v, options) { return this.compareVersions(Umbraco.Sys.ServerVariables.application.version, v, options); - } + }; self.compareVersions = function compareVersions(v1, v2, options) { @@ -606,7 +606,7 @@ angular.module("umbraco").factory("innerContentService", [ return 0; - } + }; self.canCopyContent = function () { return localStorageService.isSupported; @@ -624,20 +624,20 @@ angular.module("umbraco").factory("innerContentService", [ return true; } return false; - } + }; self.getCopiedContent = function () { var itm = localStorageService.get("icContentJson"); itm.key = self.generateUid(); return itm; - } + }; self.getCopiedContentTypeGuid = function () { return localStorageService.get("icContentTypeGuid"); - } + }; // Helpful methods - var lut = []; for (var i = 0; i < 256; i++) { lut[i] = (i < 16 ? "0" : "") + (i).toString(16); } + var lut = []; for (var i = 0; i < 256; i++) { lut[i] = (i < 16 ? "0" : "") + i.toString(16); } self.generateUid = function () { var d0 = Math.random() * 0xffffffff | 0; var d1 = Math.random() * 0xffffffff | 0; @@ -647,7 +647,7 @@ angular.module("umbraco").factory("innerContentService", [ lut[d1 & 0xff] + lut[d1 >> 8 & 0xff] + "-" + lut[d1 >> 16 & 0x0f | 0x40] + lut[d1 >> 24 & 0xff] + "-" + lut[d2 & 0x3f | 0x80] + lut[d2 >> 8 & 0xff] + "-" + lut[d2 >> 16 & 0xff] + lut[d2 >> 24 & 0xff] + lut[d3 & 0xff] + lut[d3 >> 8 & 0xff] + lut[d3 >> 16 & 0xff] + lut[d3 >> 24 & 0xff]; - } + }; return self; } From 79b306c1544961cb2887380d481ee79da03178e4 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Wed, 11 Jul 2018 17:43:02 +0100 Subject: [PATCH 20/25] Added support for Umbraco in a virtual directory --- .../UI/App_Plugins/InnerContent/js/innercontent.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js index d1ea5ff..4c77ec2 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js @@ -661,7 +661,7 @@ angular.module("umbraco.resources").factory("Our.Umbraco.InnerContent.Resources. getAllContentTypes: function () { return umbRequestHelper.resourcePromise( $http({ - url: "/umbraco/backoffice/InnerContent/InnerContentApi/GetAllContentTypes", + url: umbRequestHelper.convertVirtualToAbsolutePath("~/umbraco/backoffice/InnerContent/InnerContentApi/GetAllContentTypes"), method: "GET" }), "Failed to retrieve content types" @@ -670,7 +670,7 @@ angular.module("umbraco.resources").factory("Our.Umbraco.InnerContent.Resources. getContentTypesByGuid: function (guids) { return umbRequestHelper.resourcePromise( $http({ - url: "/umbraco/backoffice/InnerContent/InnerContentApi/GetContentTypesByGuid", + url: umbRequestHelper.convertVirtualToAbsolutePath("~/umbraco/backoffice/InnerContent/InnerContentApi/GetContentTypesByGuid"), method: "GET", params: { guids: guids } }), @@ -680,7 +680,7 @@ angular.module("umbraco.resources").factory("Our.Umbraco.InnerContent.Resources. getContentTypesByAlias: function (aliases) { return umbRequestHelper.resourcePromise( $http({ - url: "/umbraco/backoffice/InnerContent/InnerContentApi/GetContentTypesByAlias", + url: umbRequestHelper.convertVirtualToAbsolutePath("~/umbraco/backoffice/InnerContent/InnerContentApi/GetContentTypesByAlias"), method: "GET", params: { aliases: aliases } }), @@ -690,7 +690,7 @@ angular.module("umbraco.resources").factory("Our.Umbraco.InnerContent.Resources. getContentTypeIconsByGuid: function (guids) { return umbRequestHelper.resourcePromise( $http({ - url: "/umbraco/backoffice/InnerContent/InnerContentApi/GetContentTypeIconsByGuid", + url: umbRequestHelper.convertVirtualToAbsolutePath("~/umbraco/backoffice/InnerContent/InnerContentApi/GetContentTypeIconsByGuid"), method: "GET", params: { guids: guids } }), @@ -700,7 +700,7 @@ angular.module("umbraco.resources").factory("Our.Umbraco.InnerContent.Resources. getContentTypeScaffoldByGuid: function (guid) { return umbRequestHelper.resourcePromise( $http({ - url: "/umbraco/backoffice/InnerContent/InnerContentApi/GetContentTypeScaffoldByGuid", + url: umbRequestHelper.convertVirtualToAbsolutePath("~/umbraco/backoffice/InnerContent/InnerContentApi/GetContentTypeScaffoldByGuid"), method: "GET", params: { guid: guid } }), @@ -710,7 +710,7 @@ angular.module("umbraco.resources").factory("Our.Umbraco.InnerContent.Resources. getContentTypeScaffoldByBlueprintId: function (blueprintId) { return umbRequestHelper.resourcePromise( $http({ - url: "/umbraco/backoffice/InnerContent/InnerContentApi/GetContentTypeScaffoldByBlueprintId", + url: umbRequestHelper.convertVirtualToAbsolutePath("~/umbraco/backoffice/InnerContent/InnerContentApi/GetContentTypeScaffoldByBlueprintId"), method: "GET", params: { blueprintId: blueprintId } }), From 14fa256f60e63b36ed00705fabdfe5a61eb52380 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Thu, 12 Jul 2018 12:16:26 +0100 Subject: [PATCH 21/25] Small refactor of the "hideLabel" code --- .../PropertyEditors/InnerContentPropertyValueEditor.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Our.Umbraco.InnerContent/PropertyEditors/InnerContentPropertyValueEditor.cs b/src/Our.Umbraco.InnerContent/PropertyEditors/InnerContentPropertyValueEditor.cs index afe5389..55178c8 100644 --- a/src/Our.Umbraco.InnerContent/PropertyEditors/InnerContentPropertyValueEditor.cs +++ b/src/Our.Umbraco.InnerContent/PropertyEditors/InnerContentPropertyValueEditor.cs @@ -3,7 +3,6 @@ using System.Linq; using Newtonsoft.Json.Linq; using Our.Umbraco.InnerContent.Helpers; -using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.Editors; using Umbraco.Core.PropertyEditors; @@ -22,14 +21,9 @@ public override void ConfigureForDisplay(PreValueCollection preValues) { base.ConfigureForDisplay(preValues); - var asDictionary = preValues.PreValuesAsDictionary; - if (asDictionary.ContainsKey("hideLabel")) + if (preValues.PreValuesAsDictionary.ContainsKey("hideLabel")) { - var boolAttempt = asDictionary["hideLabel"].Value.TryConvertTo(); - if (boolAttempt.Success) - { - HideLabel = boolAttempt.Result; - } + HideLabel = preValues.PreValuesAsDictionary["hideLabel"].Value == "1"; } } From 15a7d44d5603d91aa2053b1d773a4d7d0eca347b Mon Sep 17 00:00:00 2001 From: leekelleher Date: Thu, 12 Jul 2018 16:24:38 +0100 Subject: [PATCH 22/25] Removed the "DocType Tab Picker" prevalue editor This could be a case of YAGNI, (we haven't used it yet). We can re-introduce this, if it is needed in future. --- .../Our.Umbraco.InnerContent.csproj | 1 - .../InnerContent/js/innercontent.js | 47 ---------------- .../views/innercontent.doctypetabpicker.html | 54 ------------------- 3 files changed, 102 deletions(-) delete mode 100644 src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.doctypetabpicker.html diff --git a/src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj b/src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj index 9467cb0..87700b3 100644 --- a/src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj +++ b/src/Our.Umbraco.InnerContent/Our.Umbraco.InnerContent.csproj @@ -95,7 +95,6 @@ - diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js index 4c77ec2..5054821 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js @@ -1,51 +1,4 @@ // Prevalue Editors -angular.module("umbraco").controller("Our.Umbraco.InnerContent.Controllers.DocTypeTabPickerController", [ - - "$scope", - "innerContentService", - - function ($scope, innerContentService) { - - $scope.add = function () { - $scope.model.value.push({ - icContentTypeGuid: "", - icTabAlias: "", - nameTemplate: "" - }); - }; - - $scope.selectedDocTypeTabs = function (cfg) { - var dt = _.find($scope.model.docTypes, function (itm) { - return itm.key.toLowerCase() === cfg.icContentTypeGuid.toLowerCase(); - }); - var tabs = dt ? dt.tabs : []; - if (!_.contains(tabs, cfg.icTabAlias)) { - cfg.icTabAlias = tabs[0]; - } - return tabs; - }; - - $scope.remove = function (index) { - $scope.model.value.splice(index, 1); - }; - - $scope.sortableOptions = { - axis: "y", - cursor: "move", - handle: ".icon-navigation" - }; - - innerContentService.getAllContentTypes().then(function (docTypes) { - $scope.model.docTypes = docTypes; - }); - - if (!$scope.model.value) { - $scope.model.value = []; - $scope.add(); - } - } -]); - angular.module("umbraco").controller("Our.Umbraco.InnerContent.Controllers.DocTypePickerController", [ "$scope", diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.doctypetabpicker.html b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.doctypetabpicker.html deleted file mode 100644 index 7023b45..0000000 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.doctypetabpicker.html +++ /dev/null @@ -1,54 +0,0 @@ -
-
- - - - - - - - - - - - - - - - -
- - Document Type - - Tab - - Name Template - -
- - - - - - - Remove -
-
- Add - -
-
-
-
-

- Tab:
- Select the tab who's properties should be displayed. If left blank, the first tab on the doc type will be used. -

-

- Name template:
- Enter an angular expression to evaluate against each item for its name. -

-
-
\ No newline at end of file From 5c5d2030e5c7da2e27a78fe7b13f0be45a1d6c84 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Thu, 12 Jul 2018 17:35:11 +0100 Subject: [PATCH 23/25] Refactored the doctype picker view to use "as vm" syntax --- .../InnerContent/js/innercontent.js | 45 +++++++++++++------ .../views/innercontent.doctypepicker.html | 10 ++--- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js index 5054821..59b50cf 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js @@ -6,31 +6,50 @@ angular.module("umbraco").controller("Our.Umbraco.InnerContent.Controllers.DocTy function ($scope, innerContentService) { - $scope.add = function () { + var vm = this; + vm.add = add; + vm.remove = remove; + vm.sortableOptions = { + axis: "y", + containment: "parent", + cursor: "move", + handle: ".icon-navigation", + opacity: 0.7, + scroll: true, + tolerance: "pointer", + stop: function (e, ui) { + setDirty(); + } + }; + + innerContentService.getAllContentTypes().then(function (docTypes) { + vm.docTypes = docTypes; + }); + + if (!$scope.model.value) { + $scope.model.value = []; + add(); + } + + function add() { $scope.model.value.push({ icContentTypeGuid: "", nameTemplate: "" }); }; - $scope.remove = function (index) { + function remove(index) { $scope.model.value.splice(index, 1); }; - $scope.sortableOptions = { - axis: "y", - cursor: "move", - handle: ".icon-navigation" }; - innerContentService.getAllContentTypes().then(function (docTypes) { - $scope.model.docTypes = docTypes; - }); - if (!$scope.model.value) { - $scope.model.value = []; - $scope.add(); - } + function setDirty() { + if ($scope.propertyForm) { + $scope.propertyForm.$setDirty(); + } + }; } ]); diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.doctypepicker.html b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.doctypepicker.html index 434774b..bfd81c7 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.doctypepicker.html +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.doctypepicker.html @@ -1,4 +1,4 @@ -
+
@@ -13,24 +13,24 @@ - +
- - Remove + Remove
- Add + Add
From 8c04f9fa48e7cadee9bf5536fea3b67b0e1513fe Mon Sep 17 00:00:00 2001 From: leekelleher Date: Thu, 12 Jul 2018 17:36:09 +0100 Subject: [PATCH 24/25] Replaced the help text with Umbraco's `umb-tooltip` directive --- .../InnerContent/css/innercontent.css | 14 +++++------ .../InnerContent/js/innercontent.js | 24 +++++++++++++++++++ .../views/innercontent.doctypepicker.html | 15 ++++++------ 3 files changed, 38 insertions(+), 15 deletions(-) diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/css/innercontent.css b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/css/innercontent.css index 9c53cf3..b8c6dfc 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/css/innercontent.css +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/css/innercontent.css @@ -1,24 +1,24 @@ /* Inner Content - Doc Type Picker */ -.inner-content__doctypepicker table input, .inner-content__doctypepicker table select { + +.inner-content__doctypepicker table input, +.inner-content__doctypepicker table select { width: 100%; padding-right: 0; } -.inner-content__doctypepicker table td.icon-navigation, .inner-content__doctypepicker i.inner-content__help-icon { +.inner-content__doctypepicker table td.icon-navigation, +.inner-content__doctypepicker i.inner-content__help-icon { vertical-align: middle; color: #CCC; } -.inner-content__doctypepicker table td.icon-navigation:hover, .inner-content__doctypepicker i.inner-content__help-icon:hover { +.inner-content__doctypepicker table td.icon-navigation:hover, +.inner-content__doctypepicker i.inner-content__help-icon:hover { color: #343434; } -.inner-content__doctypepicker i.inner-content__help-icon { - margin-left: 10px; -} - .inner-content__doctypepicker table .td-min { width: 1px; } diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js index 59b50cf..4dd51bc 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js @@ -9,6 +9,9 @@ angular.module("umbraco").controller("Our.Umbraco.InnerContent.Controllers.DocTy var vm = this; vm.add = add; vm.remove = remove; + vm.tooltipMouseOver = tooltipMouseOver; + vm.tooltipMouseLeave = tooltipMouseLeave; + vm.sortableOptions = { axis: "y", containment: "parent", @@ -22,6 +25,12 @@ angular.module("umbraco").controller("Our.Umbraco.InnerContent.Controllers.DocTy } }; + vm.tooltip = { + show: false, + event: null, + content: null + }; + innerContentService.getAllContentTypes().then(function (docTypes) { vm.docTypes = docTypes; }); @@ -36,14 +45,29 @@ angular.module("umbraco").controller("Our.Umbraco.InnerContent.Controllers.DocTy icContentTypeGuid: "", nameTemplate: "" }); + setDirty(); }; function remove(index) { $scope.model.value.splice(index, 1); + setDirty(); }; + function tooltipMouseOver($event) { + vm.tooltip = { + show: true, + event: $event, + content: $event.currentTarget.dataset.tooltip + }; }; + function tooltipMouseLeave() { + vm.tooltip = { + show: false, + event: null, + content: null + }; + }; function setDirty() { if ($scope.propertyForm) { diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.doctypepicker.html b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.doctypepicker.html index bfd81c7..1ac3718 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.doctypepicker.html +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/views/innercontent.doctypepicker.html @@ -9,6 +9,10 @@ Name Template + @@ -31,14 +35,9 @@
Add -
-
-
-

- Name template:
- Enter an angular expression to evaluate against each item for its name. -

-
+ + {{vm.tooltip.content}} +
\ No newline at end of file From e73732937d9843be7195d931c204a4441597c3df Mon Sep 17 00:00:00 2001 From: leekelleher Date: Fri, 20 Jul 2018 11:38:24 +0100 Subject: [PATCH 25/25] Code amends & housekeeping --- .../InnerContentPropertyValueEditor.cs | 11 ++++--- .../InnerContent/css/innercontent.css | 7 ++-- .../InnerContent/js/innercontent.js | 32 +++++++++++++------ 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/Our.Umbraco.InnerContent/PropertyEditors/InnerContentPropertyValueEditor.cs b/src/Our.Umbraco.InnerContent/PropertyEditors/InnerContentPropertyValueEditor.cs index 55178c8..5e99441 100644 --- a/src/Our.Umbraco.InnerContent/PropertyEditors/InnerContentPropertyValueEditor.cs +++ b/src/Our.Umbraco.InnerContent/PropertyEditors/InnerContentPropertyValueEditor.cs @@ -3,6 +3,7 @@ using System.Linq; using Newtonsoft.Json.Linq; using Our.Umbraco.InnerContent.Helpers; +using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.Editors; using Umbraco.Core.PropertyEditors; @@ -70,7 +71,7 @@ protected void ConvertInnerContentDbToString(JObject item, IDataTypeService data var propEditor = PropertyEditorResolver.Current.GetByAlias(propType.PropertyEditorAlias); // Get the editor to do it's conversion, and store it back - item[propKey] = propEditor.ValueEditor.ConvertDbToString(prop, propType, dataTypeService); + item[propKey] = propEditor?.ValueEditor?.ConvertDbToString(prop, propType, dataTypeService); } catch (InvalidOperationException) { @@ -116,7 +117,7 @@ protected void ConvertInnerContentDbToEditor(JObject item, IDataTypeService data foreach (var propKey in propValueKeys) { - var propType = contentType.CompositionPropertyTypes.FirstOrDefault(x => x.Alias == propKey); + var propType = contentType.CompositionPropertyTypes.FirstOrDefault(x => x.Alias.InvariantEquals(propKey)); if (propType == null) { if (IsSystemPropertyKey(propKey) == false) @@ -136,7 +137,7 @@ protected void ConvertInnerContentDbToEditor(JObject item, IDataTypeService data var propEditor = PropertyEditorResolver.Current.GetByAlias(propType.PropertyEditorAlias); // Get the editor to do it's conversion - var newValue = propEditor.ValueEditor.ConvertDbToEditor(prop, propType, dataTypeService); + var newValue = propEditor?.ValueEditor?.ConvertDbToEditor(prop, propType, dataTypeService); // Store the value back item[propKey] = (newValue == null) ? null : JToken.FromObject(newValue); @@ -144,7 +145,7 @@ protected void ConvertInnerContentDbToEditor(JObject item, IDataTypeService data catch (InvalidOperationException) { // https://github.com/umco/umbraco-nested-content/issues/111 - // Catch any invalid cast operations as likely means courier failed due to missing + // Catch any invalid cast operations as likely means Courier failed due to missing // or trashed item so couldn't convert a guid back to an int item[propKey] = null; @@ -153,7 +154,7 @@ protected void ConvertInnerContentDbToEditor(JObject item, IDataTypeService data } // Process children - var childrenProp = item.Properties().FirstOrDefault(x => x.Name == "children"); + var childrenProp = item.Properties().FirstOrDefault(x => x.Name.InvariantEquals("children")); if (childrenProp != null) { ConvertInnerContentDbToEditor(childrenProp.Value.Value(), dataTypeService); diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/css/innercontent.css b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/css/innercontent.css index b8c6dfc..5fe1ff7 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/css/innercontent.css +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/css/innercontent.css @@ -1,6 +1,4 @@ -/* - Inner Content - Doc Type Picker -*/ +/* Inner Content - Doc Type Picker */ .inner-content__doctypepicker table input, .inner-content__doctypepicker table select { @@ -23,6 +21,9 @@ width: 1px; } + +/* Inner Content - Content Overlay Panel */ + .inner-content-overlay > .umb-overlay-right > .umb-overlay__form > .umb-overlay-container { padding: 0; position: static; diff --git a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js index 4dd51bc..ce0e38b 100644 --- a/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js +++ b/src/Our.Umbraco.InnerContent/Web/UI/App_Plugins/InnerContent/js/innercontent.js @@ -81,10 +81,9 @@ angular.module("umbraco").controller("Our.Umbraco.InnerContent.Controllers.DocTy angular.module("umbraco").controller("Our.Umbraco.InnerContent.Controllers.InnerContentCreateController", [ "$scope", - "$rootScope", "blueprintConfig", - function ($scope, $rootScope, blueprintConfig) { + function ($scope, blueprintConfig) { function initialize() { @@ -364,8 +363,7 @@ angular.module("umbraco.directives").directive("innerContentUnsavedChanges", [ if (scope.canConfirmClose) { overlayScope.oldCloseOverLay = overlayScope.closeOverLay; overlayScope.closeOverLay = function () { - // TODO: Find out why this throws an error with nested IC editors. (`$dirty` is undefined) [LK:2018-02-28] - if (overlayScope.overlayForm.$dirty) { + if (overlayScope.overlayForm && overlayScope.overlayForm.$dirty) { scope.showConfirmClose = true; } else { overlayScope.oldCloseOverLay.apply(overlayScope); @@ -399,13 +397,11 @@ angular.module("umbraco.directives").directive("innerContentUnsavedChanges", [ // Services angular.module("umbraco").factory("innerContentService", [ - "$q", "$interpolate", - "contentResource", "localStorageService", "Our.Umbraco.InnerContent.Resources.InnerContentResources", - function ($q, $interpolate, contentResource, localStorageService, icResources) { + function ($interpolate, localStorageService, icResources) { var self = {}; @@ -651,8 +647,12 @@ angular.module("umbraco").factory("innerContentService", [ ]); // Resources -angular.module("umbraco.resources").factory("Our.Umbraco.InnerContent.Resources.InnerContentResources", - function ($q, $http, umbRequestHelper) { +angular.module("umbraco.resources").factory("Our.Umbraco.InnerContent.Resources.InnerContentResources", [ + + "$http", + "umbRequestHelper", + + function ($http, umbRequestHelper) { return { getAllContentTypes: function () { return umbRequestHelper.resourcePromise( @@ -712,6 +712,18 @@ angular.module("umbraco.resources").factory("Our.Umbraco.InnerContent.Resources. }), "Failed to retrieve content type scaffold by blueprint Id" ); + }, + createBlueprintFromContent: function (data, userId) { + return umbRequestHelper.resourcePromise( + $http({ + url: umbRequestHelper.convertVirtualToAbsolutePath("~/umbraco/backoffice/InnerContent/InnerContentApi/CreateBlueprintFromContent"), + method: "POST", + params: { userId: userId }, + data: data + }), + "Failed to create blueprint from content" + ); } }; - }); + } +]);