diff --git a/UmbracoPackages/App_Plugins/brothers.uNesting/_nc.js b/UmbracoPackages/App_Plugins/brothers.uNesting/_nc.js index cb2db49..99c60c5 100644 --- a/UmbracoPackages/App_Plugins/brothers.uNesting/_nc.js +++ b/UmbracoPackages/App_Plugins/brothers.uNesting/_nc.js @@ -1,4 +1,121 @@ -angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.PropertyEditorController", [ +angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.DocTypePickerController", [ + + "$scope", + "Umbraco.PropertyEditors.NestedContent.Resources", + + function ($scope, ncResources) + { + + $scope.add = function () + { + $scope.model.value.push({ + // As per PR #4, all stored content type aliases must be prefixed "nc" for easier recognition. + // For good measure we'll also prefix the tab alias "nc" + ncAlias: "", + ncTabAlias: "", + nameTemplate: "" + }); + } + + $scope.canAdd = function () + { + return !$scope.model.docTypes || !$scope.model.value || $scope.model.value.length < $scope.model.docTypes.length; + } + + $scope.remove = function (index) + { + $scope.model.value.splice(index, 1); + } + + $scope.sortableOptions = { + axis: "y", + cursor: "move", + handle: ".handle", + placeholder: 'sortable-placeholder', + forcePlaceholderSize: true, + helper: function (e, ui) + { + // When sorting table rows, the cells collapse. This helper fixes that: https://www.foliotek.com/devblog/make-table-rows-sortable-using-jquery-ui-sortable/ + ui.children().each(function () + { + $(this).width($(this).width()); + }); + return ui; + }, + start: function (e, ui) + { + + var cellHeight = ui.item.height(); + + // Build a placeholder cell that spans all the cells in the row: https://stackoverflow.com/questions/25845310/jquery-ui-sortable-and-table-cell-size + var cellCount = 0; + $('td, th', ui.helper).each(function () + { + // For each td or th try and get it's colspan attribute, and add that or 1 to the total + var colspan = 1; + var colspanAttr = $(this).attr('colspan'); + if (colspanAttr > 1) + { + colspan = colspanAttr; + } + cellCount += colspan; + }); + + // Add the placeholder UI - note that this is the item's content, so td rather than tr - and set height of tr + ui.placeholder.html('').height(cellHeight); + } + }; + + $scope.docTypeTabs = {}; + + ncResources.getContentTypes().then(function (docTypes) + { + $scope.model.docTypes = docTypes; + + // Count doctype name occurrences + var docTypeNameOccurrences = _.countBy(docTypes, 'name'); + + // Populate document type tab dictionary + // And append alias to name if multiple doctypes have the same name + docTypes.forEach(function (value) + { + $scope.docTypeTabs[value.alias] = value.tabs; + + value.displayName = value.name; + + if (docTypeNameOccurrences[value.name] > 1) + { + value.displayName += " (" + value.alias + ")"; + } + }); + }); + + $scope.selectableDocTypesFor = function (config) + { + // return all doctypes that are: + // 1. either already selected for this config, or + // 2. not selected in any other config + return _.filter($scope.model.docTypes, function (docType) + { + return docType.alias === config.ncAlias || !_.find($scope.model.value, function (c) + { + return docType.alias === c.ncAlias; + }); + }); + } + + if (!$scope.model.value) + { + $scope.model.value = []; + $scope.add(); + } + } +]); + + + + +angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.PropertyEditorController", [ "$scope", "$interpolate", diff --git a/UmbracoPackages/App_Plugins/brothers.uNesting/elements.json b/UmbracoPackages/App_Plugins/brothers.uNesting/elements.json deleted file mode 100644 index 10b4376..0000000 --- a/UmbracoPackages/App_Plugins/brothers.uNesting/elements.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "text": { - "html": "text" - }, - "button": { - "text": "text", - "link": "url" - }, - "images": { - "items": "media" - }, - "xblocks": { - "items": "list" - } -} \ No newline at end of file diff --git a/UmbracoPackages/App_Plugins/brothers.uNesting/interceptor.js b/UmbracoPackages/App_Plugins/brothers.uNesting/interceptor.js deleted file mode 100644 index d31b0d4..0000000 --- a/UmbracoPackages/App_Plugins/brothers.uNesting/interceptor.js +++ /dev/null @@ -1,17 +0,0 @@ -angular.module('umbraco.services').config(['$httpProvider', function ($httpProvider) -{ - $httpProvider.interceptors.push(['$q', '$injector', 'notificationsService', function ($q, $injector, notificationsService) - { - return { - 'request': function (request) - { - if (request.url.indexOf("views/propertyeditors/nestedcontent/nestedcontent.html") === 0) - { - request.url = '/App_Plugins/brothers.uNesting/uNesting.html'; - } - - return request || $q.when(request); - } - }; - }]); -}]); \ No newline at end of file diff --git a/UmbracoPackages/App_Plugins/brothers.uNesting/package.manifest b/UmbracoPackages/App_Plugins/brothers.uNesting/package.manifest index 1cb8b8a..7c748b6 100644 --- a/UmbracoPackages/App_Plugins/brothers.uNesting/package.manifest +++ b/UmbracoPackages/App_Plugins/brothers.uNesting/package.manifest @@ -1,7 +1,6 @@ { "javascript": [ - "~/App_Plugins/brothers.uNesting/interceptor.js", - "~/App_Plugins/brothers.uNesting/uNesting.controller.js" + "~/App_Plugins/brothers.uNesting/uNesting.js" ], "css": [ "~/App_Plugins/brothers.uNesting/uNesting.css" diff --git a/UmbracoPackages/App_Plugins/brothers.uNesting/uNesting.controller.js b/UmbracoPackages/App_Plugins/brothers.uNesting/uNesting.controller.js deleted file mode 100644 index 4ba2a6b..0000000 --- a/UmbracoPackages/App_Plugins/brothers.uNesting/uNesting.controller.js +++ /dev/null @@ -1,101 +0,0 @@ - -angular.module("umbraco").controller("brothers.uNesting.PropertyEditorController", function ($scope, $controller, $http) -{ - angular.extend(this, $controller('Umbraco.PropertyEditors.NestedContent.PropertyEditorController', { $scope: $scope })); - - var elementsConfig = {}; - - var init = function () - { - $http.get("/App_Plugins/brothers.uNesting/elements.json").then(function (res) - { - elementsConfig = res.data; - - _.each($scope.nodes, function (node, idx) - { - node.uNestingContent = getContent(node, $scope.model.value[idx], elementsConfig[node.contentTypeAlias]); - }); - }); - }; - - $scope.$watch("inited", function (newVal) - { - if (newVal) - { - init(); - } - }); - - var getContent = function (node, item, config) - { - if (!item) - { - return ''; - } - if (!config) - { - return node.documentType.description; - } - - var lines = []; - - _.each(config, function (type, alias) - { - var value = item[alias]; - if (value) - { - if (type === 'text') - { - lines.push(stripHtml(value)); - } - if (type === 'url') - { - lines.push(value[0].url); - } - } - }); - - if (lines.length < 1) - { - return node.documentType.description; - } - else - { - return lines.join('
'); - } - }; - - - var stripHtml = function (html) - { - if (!html) - { - return ''; - } - - var stripped = html.replace('
', ' ').replace('
', ' ').replace('
', ' ').replace(/<[^>]+>/gm, ''); - - return stripped.length > 120 ? (stripped.substring(0, 120) + '...') : stripped; - }; - - //$scope.getView = function (node, idx) - //{ - // if ($scope.model.value[idx]) - // { - // var contentType = $scope.getContentTypeConfig($scope.model.value[idx].ncContentTypeAlias); - - // if (contentType !== null && contentType.nameExp) - // { - // // Run the expression against the stored dictionary value, NOT the node object - // var item = $scope.model.value[idx]; - // var newName = contentType.nameExp(item); - - // if (newName && (newName = $.trim(newName))) - // { - // return newName; - // } - // } - // } - // return node.documentType.description || 'Enter data ...'; - //}; -}); \ No newline at end of file diff --git a/UmbracoPackages/App_Plugins/brothers.uNesting/uNesting.css b/UmbracoPackages/App_Plugins/brothers.uNesting/uNesting.css index 08bb538..1523e55 100644 --- a/UmbracoPackages/App_Plugins/brothers.uNesting/uNesting.css +++ b/UmbracoPackages/App_Plugins/brothers.uNesting/uNesting.css @@ -18,14 +18,48 @@ margin-top: -1px; } +.unesting-items +{ + margin-top: -15px; +} +/*.unesting-item .unesting-items +{ + background-color: #f9f7f7; + box-shadow: 0 1px 1px 0 rgba(0,0,0,.16); +}*/ /* header */ - .unesting-item-header { - border-bottom: 1px solid #e9e9eb; + border-bottom: 1px solid #f6f6f7; cursor: pointer; background-color: #fff; user-select: none; + position: relative; +} + +.unesting-item.is-active > .unesting-item-header:after, +.unesting-item.is-active > .unesting-item-header:before +{ + position: absolute; + content: ' '; + display: inline-block; + left: 5px; + bottom: -19px; + border: 10px solid transparent; + border-top-color: white; + width: 0; + height: 0; +} + +.unesting-item.is-active > .unesting-item-header:before +{ + bottom: -21px; + border-top-color: #e9e9eb; +} + +.unesting-item:last-child .unesting-item-header +{ + border-bottom: none; } .unesting-item-header-inner @@ -36,19 +70,42 @@ padding: 15px 5px; color: #1b264f; border-radius: 3px 3px 0 0; + border-bottom: none; + background: none; } -.unesting-item-header-inner i +/*.unesting-item:nth-child(2n+1) .unesting-item-header-inner +{ + background: #faf9f9; +}*/ + +.unesting-item-header-inner > i { position: absolute; top: 50%; - margin-top: -11px; - font-size: 1.2rem; + margin-top: -13px; + left: 3px; + font-size: 1.4rem; + z-index: 1; } .unesting-item-header-content.--has-icon { - padding-left: 40px; + margin-left: 40px; + padding-left: 20px; + border-left: 1px solid #f6f6f7; +} + +.unesting-item-header-content-iconbg +{ + display: none; + position: absolute; + left: -46px; + width: 46px; + top: -16px; + background: #faf9f9; + z-index: 0; + bottom: -15px; } .unesting-item-header:hover .unesting-item-header-inner .unesting-item-header-content @@ -61,11 +118,14 @@ line-height: 20px; color: #1b264f; white-space: nowrap; + position: relative; } .unesting-item-header-content-name { max-height: 20px; + font-weight: 600; + font-size: 14px; } .unesting-item-header-content-text @@ -73,6 +133,9 @@ color: #817f85; font-size: 13px; overflow: hidden; + margin-top: 4px; + display: block; + line-height: 18px; } /* icons */ @@ -83,9 +146,9 @@ transition: opacity .12s ease-in-out; position: absolute; right: 0; - top: 3px; + top: 50%; padding: 5px; - margin-top: 8px; + margin-top: -22px; display: flex; grid-gap: 8px; } @@ -128,6 +191,7 @@ display: inline-block; margin: 0 1px; opacity: .6; + position: static; } .unesting-icon .icon @@ -160,11 +224,91 @@ background: none; } +.unesting-content > .umb-pane +{ + margin: 30px 20px; +} + +.unesting-item.is-active > .unesting-content +{ + background: #faf9f9; + margin: 0 -20px; + border-left: none; + border-right: none; + border-radius: 0; + border-top: 1px solid #e9e9eb; +} + +.unesting-content .unesting-item.is-active > .unesting-content +{ + background: white; + margin: 0 -20px; + border-left: 1px solid #e9e9eb; +} + +.unesting-item.is-active > .unesting-item-header +{ + border-bottom: none; +} + + +/* media */ +.unesting-media +{ + display: flex; + flex-direction: row; + margin-top: 4px; +} + +.unesting-media-item +{ + border-radius: 3px; + margin-right: 6px; + display: flex; + align-items: center; +} + +.unesting-media-item.has-title +{ + margin-right: 12px; +} + +.unesting-media-item-image +{ + background: #f6f4f4; + border-radius: 3px; + border: 1px solid #f6f6f7; +} + +.unesting-media-item-text +{ + padding: 0 10px; + max-width: 100px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + display: inline-block; +} + +.unesting-media-more +{ + max-width: 100%; + height: auto; + vertical-align: middle; + width: 50px; + height: 50px; + background: #f6f4f4; + display: inline-flex; + justify-content: center; + align-items: center; + font-size: 12px; + border-radius: 3px; +} + /* footer */ - .unesting-footer -{ +{ text-align: left; } @@ -174,11 +318,22 @@ } -/* data type overrides */ +/* doctypepicker */ +.unesting-doctype-textarea +{ + width: 100%; + height: 32px; + max-height: 200px; + min-height: 32px; + padding-top: 6px; + resize: vertical; +} + +/* data type overrides */ .unesting-item .umb-sortable-thumbnails li { - background: none; + /*background: none;*/ } diff --git a/UmbracoPackages/App_Plugins/brothers.uNesting/uNesting.docTypePicker.html b/UmbracoPackages/App_Plugins/brothers.uNesting/uNesting.docTypePicker.html new file mode 100644 index 0000000..82e6275 --- /dev/null +++ b/UmbracoPackages/App_Plugins/brothers.uNesting/uNesting.docTypePicker.html @@ -0,0 +1,63 @@ +
+
+ + + + + + + + + + + + + + + + + +
+ + Element Type + + Group + + Template + +
+ + + + + + + + + +
+
+ + +
+
+
+
+

+ Group:
+ Select the group whose properties should be displayed. If left blank, the first group on the element type will be used. +

+

+ Template:
+ Enter an angular expression to evaluate against each item for its name. Use {{$index}} to display the item index +

+
+
diff --git a/UmbracoPackages/App_Plugins/brothers.uNesting/uNesting.html b/UmbracoPackages/App_Plugins/brothers.uNesting/uNesting.html index 799c8d1..ef08fef 100644 --- a/UmbracoPackages/App_Plugins/brothers.uNesting/uNesting.html +++ b/UmbracoPackages/App_Plugins/brothers.uNesting/uNesting.html @@ -14,50 +14,53 @@
-
+
-
+
+
-
+ +
-
-