diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/tabs/umbtabsnav.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/tabs/umbtabsnav.directive.js index 890acf3d6f..50c4775ef9 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/tabs/umbtabsnav.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/tabs/umbtabsnav.directive.js @@ -43,7 +43,8 @@ templateUrl: "views/components/tabs/umb-tabs-nav.html", scope: { model: "=", - tabdrop: "=" + tabdrop: "=", + idSuffix: "@" }, link: link }; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umblaunchminieditor.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umblaunchminieditor.directive.js index 91212a82f8..11b934ce96 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umblaunchminieditor.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umblaunchminieditor.directive.js @@ -7,7 +7,7 @@ * Used on a button to launch a mini content editor editor dialog **/ angular.module("umbraco.directives") - .directive('umbLaunchMiniEditor', function (dialogService, editorState, fileManager, contentEditingHelper) { + .directive('umbLaunchMiniEditor', function (miniEditorHelper) { return { restrict: 'A', replace: false, @@ -16,69 +16,8 @@ angular.module("umbraco.directives") }, link: function(scope, element, attrs) { - var launched = false; - element.click(function() { - - if (launched === true) { - return; - } - - launched = true; - - //We need to store the current files selected in the file manager locally because the fileManager - // is a singleton and is shared globally. The mini dialog will also be referencing the fileManager - // and we don't want it to be sharing the same files as the main editor. So we'll store the current files locally here, - // clear them out and then launch the dialog. When the dialog closes, we'll reset the fileManager to it's previous state. - var currFiles = _.groupBy(fileManager.getFiles(), "alias"); - fileManager.clearFiles(); - - //We need to store the original editorState entity because it will need to change when the mini editor is loaded so that - // any property editors that are working with editorState get given the correct entity, otherwise strange things will - // start happening. - var currEditorState = editorState.getCurrent(); - - dialogService.open({ - template: "views/common/dialogs/content/edit.html", - id: scope.node.id, - closeOnSave: true, - tabFilter: ["Generic properties"], - callback: function (data) { - - //set the node name back - scope.node.name = data.name; - - //reset the fileManager to what it was - fileManager.clearFiles(); - _.each(currFiles, function (val, key) { - fileManager.setFiles(key, _.map(currFiles['upload'], function (i) { return i.file; })); - }); - - //reset the editor state - editorState.set(currEditorState); - - //Now we need to check if the content item that was edited was actually the same content item - // as the main content editor and if so, update all property data - if (data.id === currEditorState.id) { - var changed = contentEditingHelper.reBindChangedProperties(currEditorState, data); - } - - launched = false; - }, - closeCallback: function () { - //reset the fileManager to what it was - fileManager.clearFiles(); - _.each(currFiles, function (val, key) { - fileManager.setFiles(key, _.map(currFiles['upload'], function (i) { return i.file; })); - }); - - //reset the editor state - editorState.set(currEditorState); - - launched = false; - } - }); - + miniEditorHelper.launchMiniEditor(scope.node); }); } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbnodepreview.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbnodepreview.directive.js new file mode 100644 index 0000000000..77f6f06a30 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbnodepreview.directive.js @@ -0,0 +1,122 @@ +/** +@ngdoc directive +@name umbraco.directives.directive:umbNodePreview +@restrict E +@scope + +@description +Added in Umbraco v. 7.6: Use this directive to render a node preview. + +

Markup example

+
+    
+ +
+ + +
+ +
+
+ +

Controller example

+
+    (function () {
+        "use strict";
+    
+        function Controller() {
+    
+            var vm = this;
+    
+            vm.allowRemove = true;
+            vm.allowOpen = true;
+            vm.sortable = true;
+    
+            vm.nodes = [
+                {
+                    "icon": "icon-document",
+                    "name": "My node 1",
+                    "published": true,
+                    "description": "A short description of my node"
+                },
+                {
+                    "icon": "icon-document",
+                    "name": "My node 2",
+                    "published": true,
+                    "description": "A short description of my node"
+                }
+            ];
+    
+            vm.remove = remove;
+            vm.open = open;
+    
+            function remove(index, nodes) {
+                alert("remove node");
+            }
+    
+            function open(node) {
+                alert("open node");
+            }
+    
+        }
+    
+        angular.module("umbraco").controller("My.NodePreviewController", Controller);
+    
+    })();
+
+ +@param {string} icon (binding): The node icon. +@param {string} name (binding): The node name. +@param {boolean} published (binding): The node pusblished state. +@param {string} description (binding): A short description. +@param {boolean} sortable (binding): Will add a move cursor on the node preview. Can used in combination with ui-sortable. +@param {boolean} allowRemove (binding): Show/Hide the remove button. +@param {boolean} allowOpen (binding): Show/Hide the open button. +@param {function} onRemove (expression): Callback function when the remove button is clicked. +@param {function} onOpen (expression): Callback function when the open button is clicked. +**/ + +(function () { + 'use strict'; + + function NodePreviewDirective() { + + function link(scope, el, attr, ctrl) { + + } + + var directive = { + restrict: 'E', + replace: true, + templateUrl: 'views/components/umb-node-preview.html', + scope: { + icon: "=?", + name: "=", + description: "=?", + published: "=?", + sortable: "=?", + allowOpen: "=?", + allowRemove: "=?", + onOpen: "&?", + onRemove: "&?" + }, + link: link + }; + + return directive; + + } + + angular.module('umbraco.directives').directive('umbNodePreview', NodePreviewDirective); + +})(); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/mocks/resources/entity.mocks.js b/src/Umbraco.Web.UI.Client/src/common/mocks/resources/entity.mocks.js index fc60781375..8c03679183 100644 --- a/src/Umbraco.Web.UI.Client/src/common/mocks/resources/entity.mocks.js +++ b/src/Umbraco.Web.UI.Client/src/common/mocks/resources/entity.mocks.js @@ -33,6 +33,15 @@ angular.module('umbraco.mocks'). return [200, nodes, null]; } + function returnEntityUrl() { + + if (!mocksUtils.checkAuth()) { + return [401, null, null]; + } + + return [200, "url", null]; + + } return { register: function () { @@ -48,6 +57,10 @@ angular.module('umbraco.mocks'). $httpBackend .whenGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/Entity/GetById?')) .respond(returnEntitybyId); + + $httpBackend + .whenGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/Entity/GetUrl?')) + .respond(returnEntityUrl); } }; }]); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js index 914b601249..5e0f5deada 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js @@ -56,7 +56,7 @@ function entityResource($q, $http, umbRequestHelper) { * * ##usage *
-         * entityResource.getPath(id)
+         * entityResource.getPath(id, type)
          *    .then(function(pathArray) {
          *        alert('its here!');
          *    });
@@ -77,6 +77,37 @@ function entityResource($q, $http, umbRequestHelper) {
                'Failed to retrieve path for id:' + id);
         },
 
+        /**
+         * @ngdoc method
+         * @name umbraco.resources.entityResource#getUrl
+         * @methodOf umbraco.resources.entityResource
+         *
+         * @description
+         * Returns a url, given a node ID and type
+         *
+         * ##usage
+         * 
+         * entityResource.getUrl(id, type)
+         *    .then(function(url) {
+         *        alert('its here!');
+         *    });
+         * 
+ * + * @param {Int} id Id of node to return the public url to + * @param {string} type Object type name + * @returns {Promise} resourcePromise object containing the url. + * + */ + getUrl: function(id, type) { + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "entityApiBaseUrl", + "GetUrl", + [{ id: id }, {type: type }])), + 'Failed to retrieve url for id:' + id); + }, + /** * @ngdoc method * @name umbraco.resources.entityResource#getById @@ -140,7 +171,7 @@ function entityResource($q, $http, umbRequestHelper) { query += "ids=" + item + "&"; }); - // if ids array is empty we need a empty variable in the querystring otherwise the service returns a error + // if ids array is empty we need a empty variable in the querystring otherwise the service returns a error if (ids.length === 0) { query += "ids=&"; } diff --git a/src/Umbraco.Web.UI.Client/src/common/services/minieditorhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/minieditorhelper.service.js new file mode 100644 index 0000000000..693457c7e8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/services/minieditorhelper.service.js @@ -0,0 +1,89 @@ +(function () { + 'use strict'; + + function miniEditorHelper(dialogService, editorState, fileManager, contentEditingHelper, $q) { + + var launched = false; + + function launchMiniEditor(node) { + + var deferred = $q.defer(); + + launched = true; + + //We need to store the current files selected in the file manager locally because the fileManager + // is a singleton and is shared globally. The mini dialog will also be referencing the fileManager + // and we don't want it to be sharing the same files as the main editor. So we'll store the current files locally here, + // clear them out and then launch the dialog. When the dialog closes, we'll reset the fileManager to it's previous state. + var currFiles = _.groupBy(fileManager.getFiles(), "alias"); + fileManager.clearFiles(); + + //We need to store the original editorState entity because it will need to change when the mini editor is loaded so that + // any property editors that are working with editorState get given the correct entity, otherwise strange things will + // start happening. + var currEditorState = editorState.getCurrent(); + + dialogService.open({ + template: "views/common/dialogs/content/edit.html", + id: node.id, + closeOnSave: true, + tabFilter: ["Generic properties"], + callback: function (data) { + + //set the node name back + node.name = data.name; + + //reset the fileManager to what it was + fileManager.clearFiles(); + _.each(currFiles, function (val, key) { + fileManager.setFiles(key, _.map(currFiles['upload'], function (i) { return i.file; })); + }); + + //reset the editor state + editorState.set(currEditorState); + + //Now we need to check if the content item that was edited was actually the same content item + // as the main content editor and if so, update all property data + if (data.id === currEditorState.id) { + var changed = contentEditingHelper.reBindChangedProperties(currEditorState, data); + } + + launched = false; + + deferred.resolve(data); + + }, + closeCallback: function () { + //reset the fileManager to what it was + fileManager.clearFiles(); + _.each(currFiles, function (val, key) { + fileManager.setFiles(key, _.map(currFiles['upload'], function (i) { return i.file; })); + }); + + //reset the editor state + editorState.set(currEditorState); + + launched = false; + + deferred.reject(); + + } + }); + + return deferred.promise; + + } + + var service = { + launchMiniEditor: launchMiniEditor + }; + + return service; + + } + + + angular.module('umbraco.services').factory('miniEditorHelper', miniEditorHelper); + + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/less/belle.less b/src/Umbraco.Web.UI.Client/src/less/belle.less index c988f9edbb..6fbf12e815 100644 --- a/src/Umbraco.Web.UI.Client/src/less/belle.less +++ b/src/Umbraco.Web.UI.Client/src/less/belle.less @@ -125,6 +125,8 @@ @import "components/notifications/umb-notifications.less"; @import "components/umb-file-dropzone.less"; +@import "components/umb-node-preview.less"; +@import "components/umb-mini-editor.less"; // Utilities @import "utilities/_flexbox.less"; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-mini-editor.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-mini-editor.less new file mode 100644 index 0000000000..53e0dcd6b3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-mini-editor.less @@ -0,0 +1,33 @@ +.umb-modal .umb-mini-editor { + + .umb-panel-header { + padding: 20px; + background: @grayLighter; + border-bottom: 1px solid @grayLight; + height: 59px; + + .umb-headline { + margin-left: 0; + margin-right: 0; + margin-bottom: 0; + margin-top: 3px; + } + } + + .umb-panel-body { + padding-left: 0; + padding-right: 0; + } + + .umb-panel-body.with-footer { + bottom: 52px; + } + + .umb-panel-footer { + background: @grayLighter; + border-top: 1px solid @grayLight; + height: 51px; + padding: 0 20px; + } + +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-node-preview.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-node-preview.less new file mode 100644 index 0000000000..5b96492b48 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-node-preview.less @@ -0,0 +1,98 @@ +.umb-node-preview { + padding: 5px 15px; + margin-bottom: 5px; + background: @grayLighter; + border-radius: 3px; + display: flex; + align-items: center; + max-width: 66.6%; + box-sizing: border-box; +} + +.umb-node-preview--sortable { + cursor: move; +} + +.umb-node-preview--sortable:hover { + border-color: #d9d9d9; +} + +.umb-node-preview--unpublished { + .umb-node-preview__icon, + .umb-node-preview__name, + .umb-node-preview__description { + opacity: 0.6; + } +} + +.umb-node-preview__icon { + display: flex; + width: 25px; + height: 25px; + justify-content: center; + align-items: center; + font-size: 20px; + margin-right: 10px; + flex: 0 0 auto; +} + +.umb-node-preview__content { + flex: 1 1 auto; +} + +.umb-node-preview__name { + font-size: 13px; + font-weight: bold; + color: @black; +} + +.umb-node-preview__description { + font-size: 11px; + line-height: 1.5em; +} + +.umb-node-preview__actions { + flex: 0 0 auto; + display: flex; + align-items: center; +} + +.umb-node-preview__action { + margin-left: 5px; + margin-right: 5px; + font-size: 13px; + font-weight: bold; + opacity: 0.5; +} + +.umb-node-preview__action:hover { + color: @blue; + text-decoration: none; + opacity: 1; +} + +.umb-node-preview-add { + display: flex; + align-items: center; + justify-content: center; + border: 1px dashed #d9d9d9; + color: @blue; + font-weight: bold; + padding: 5px 15px; + max-width: 66.6%; + box-sizing: border-box; +} + +.umb-node-preview-add:hover { + color: @blue; +} + +.umb-overlay, +.umb-modal { + .umb-node-preview { + max-width: none; + } + .umb-node-preview-add { + max-width: none; + } +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/less/forms.less b/src/Umbraco.Web.UI.Client/src/less/forms.less index d046ac7104..5b6e97ad71 100644 --- a/src/Umbraco.Web.UI.Client/src/less/forms.less +++ b/src/Umbraco.Web.UI.Client/src/less/forms.less @@ -190,7 +190,7 @@ input[type="tel"], input[type="color"], .uneditable-input { display: inline-block; - height: @baseLineHeight; + height: 30px; padding: 4px 6px; margin-bottom: @baseLineHeight / 2; font-size: @baseFontSize; @@ -198,6 +198,7 @@ input[type="color"], color: @gray; .border-radius(@inputBorderRadius); vertical-align: middle; + box-sizing: border-box; } input.-full-width-input { diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/content/edit.html b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/content/edit.html index 55e0cad2e7..eef28aefa1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/content/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/content/edit.html @@ -2,7 +2,8 @@ ng-controller="Umbraco.Dialogs.Content.EditController" ng-show="loaded" ng-submit="save()" - val-form-manager> + val-form-manager + class="umb-mini-editor">
@@ -12,15 +13,33 @@
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/tabs/umb-tabs-nav.html b/src/Umbraco.Web.UI.Client/src/views/components/tabs/umb-tabs-nav.html index 8522bc3b6a..808822e138 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/tabs/umb-tabs-nav.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/tabs/umb-tabs-nav.html @@ -1,5 +1,5 @@ diff --git a/src/Umbraco.Web.UI.Client/src/views/components/umb-node-preview.html b/src/Umbraco.Web.UI.Client/src/views/components/umb-node-preview.html new file mode 100644 index 0000000000..f31f595a88 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/components/umb-node-preview.html @@ -0,0 +1,12 @@ +
+ +
+
{{ name }}
+
{{ description }}
+
+
+ Open + Remove +
+ +
\ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js index 667dfd0f22..ba29b92477 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js @@ -1,7 +1,7 @@ //this controller simply tells the dialogs service to open a mediaPicker window //with a specified callback, this callback will receive an object with a selection on it -function contentPickerController($scope, dialogService, entityResource, editorState, $log, iconHelper, $routeParams, fileManager, contentEditingHelper, angularHelper, navigationService, $location) { +function contentPickerController($scope, entityResource, editorState, iconHelper, $routeParams, angularHelper, navigationService, $location, miniEditorHelper) { function trim(str, chr) { var rgxtrim = (!chr) ? new RegExp('^\\s+|\\s+$', 'g') : new RegExp('^' + chr + '+|' + chr + '+$', 'g'); @@ -39,6 +39,9 @@ function contentPickerController($scope, dialogService, entityResource, editorSt else { $scope.contentPickerForm.maxCount.$setValidity("maxCount", true); } + + setSortingState($scope.renderModel); + }); } @@ -59,6 +62,14 @@ function contentPickerController($scope, dialogService, entityResource, editorSt } }; + // sortable options + $scope.sortableOptions = { + distance: 10, + tolerance: "pointer", + scroll: true, + zIndex: 6000 + }; + if ($scope.model.config) { //merge the server config on top of the default config, then set the server config to use the result $scope.model.config = angular.extend(defaultConfig, $scope.model.config); @@ -75,8 +86,9 @@ function contentPickerController($scope, dialogService, entityResource, editorSt : $scope.model.config.startNode.type === "media" ? "Media" : "Document"; - $scope.allowOpenButton = entityType === "Document" || entityType === "Media"; + $scope.allowOpenButton = entityType === "Document"; $scope.allowEditButton = entityType === "Document"; + $scope.allowRemoveButton = true; //the dialog options for the picker var dialogOptions = { @@ -192,14 +204,26 @@ function contentPickerController($scope, dialogService, entityResource, editorSt }); if (currIds.indexOf(item.id) < 0) { - item.icon = iconHelper.convertFromLegacyIcon(item.icon); - $scope.renderModel.push({ name: item.name, id: item.id, icon: item.icon, path: item.path }); + setEntityUrl(item); } }; $scope.clear = function () { $scope.renderModel = []; }; + + $scope.openMiniEditor = function(node) { + miniEditorHelper.launchMiniEditor(node).then(function(updatedNode){ + // update the node + node.name = updatedNode.name; + node.published = updatedNode.hasPublishedVersion; + if(entityType !== "Member") { + entityResource.getUrl(updatedNode.id, entityType).then(function(data){ + node.url = data; + }); + } + }); + }; var unsubscribe = $scope.$on("formSubmitting", function (ev, args) { var currIds = _.map($scope.renderModel, function (i) { @@ -215,26 +239,83 @@ function contentPickerController($scope, dialogService, entityResource, editorSt //load current data var modelIds = $scope.model.value ? $scope.model.value.split(',') : []; + entityResource.getByIds(modelIds, entityType).then(function (data) { - //Ensure we populate the render model in the same order that the ids were stored! _.each(modelIds, function (id, i) { var entity = _.find(data, function (d) { return d.id == id; }); - + if (entity) { - entity.icon = iconHelper.convertFromLegacyIcon(entity.icon); - $scope.renderModel.push({ name: entity.name, id: entity.id, icon: entity.icon, path: entity.path }); + setEntityUrl(entity); } - - }); + }); //everything is loaded, start the watch on the model startWatch(); }); + + function setEntityUrl(entity) { + // get url for content and media items + if(entityType !== "Member") { + entityResource.getUrl(entity.id, entityType).then(function(data){ + // update url + entity.url = data; + + // push item to render model + addSelectedItem(entity); + }); + } else { + addSelectedItem(entity); + } + } + + function addSelectedItem(item) { + + // set icon + if(item.icon) { + item.icon = iconHelper.convertFromLegacyIcon(item.icon); + } + + // set default icon + if (!item.icon) { + switch (entityType) { + case "Document": + item.icon = "icon-document"; + break; + case "Media": + item.icon = "icon-picture"; + break; + case "Member": + item.icon = "icon-user"; + break; + } + } + + $scope.renderModel.push({ + "name": item.name, + "id": item.id, + "icon": item.icon, + "path": item.path, + "url": item.url, + "published": (item.metaData && item.metaData.IsPublished === false && entityType === "Document") ? false : true + // only content supports published/unpublished content so we set everything else to published so the UI looks correct + }); + + } + + function setSortingState(items) { + // disable sorting if the list only consist of one item + if(items.length > 1) { + $scope.sortableOptions.disabled = false; + } else { + $scope.sortableOptions.disabled = true; + } + } + } angular.module('umbraco').controller("Umbraco.PropertyEditors.ContentPickerController", contentPickerController); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html index 9f5f3fb60f..900cf6b416 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html @@ -2,32 +2,28 @@ - - - +
+ + +
+ + + Add + diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergrouppicker/membergrouppicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergrouppicker/membergrouppicker.controller.js index 5ebbd37217..aa20a9c43b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergrouppicker/membergrouppicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergrouppicker/membergrouppicker.controller.js @@ -8,6 +8,7 @@ function memberGroupPicker($scope, dialogService){ } $scope.renderModel = []; + $scope.allowRemove = true; if ($scope.model.value) { var modelIds = $scope.model.value.split(','); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergrouppicker/membergrouppicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergrouppicker/membergrouppicker.html index 5258968c00..60ae9cb202 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergrouppicker/membergrouppicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergrouppicker/membergrouppicker.html @@ -1,27 +1,22 @@
+
+ + +
- - - + + Add + - - - + + Add + + /// Gets the url of an entity + /// + /// Int id of the entity to fetch URL for + /// The tpye of entity such as Document, Media, Member + /// The URL or path to the item + public HttpResponseMessage GetUrl(int id, UmbracoEntityTypes type) + { + var returnUrl = string.Empty; + + if (type == UmbracoEntityTypes.Document) + { + var foundUrl = Umbraco.Url(id); + if (string.IsNullOrEmpty(foundUrl) == false && foundUrl != "#") + { + returnUrl = foundUrl; + + return new HttpResponseMessage(HttpStatusCode.OK) + { + Content = new StringContent(returnUrl) + }; + } + } + + var ancestors = GetAncestors(id, type); + + //if content, skip the first node for replicating NiceUrl defaults + if(type == UmbracoEntityTypes.Document) { + ancestors = ancestors.Skip(1); + } + + returnUrl = "/" + string.Join("/", ancestors.Select(x => x.Name)); + + return new HttpResponseMessage(HttpStatusCode.OK) + { + Content = new StringContent(returnUrl) + }; + } + /// /// Gets an entity by it's unique id if the entity supports that /// diff --git a/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs index 4d58060164..be10cd83e2 100644 --- a/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs @@ -33,17 +33,12 @@ namespace Umbraco.Web.PropertyEditors internal class ContentPickerPreValueEditor : PreValueEditor { - [PreValueField("showOpenButton", "Show open button", "boolean")] + [PreValueField("showOpenButton", "Show open button (this feature is in preview!)", "boolean", Description = " Opens the node in a dialog")] public string ShowOpenButton { get; set; } - - [PreValueField("showEditButton", "Show edit button (this feature is in preview!)", "boolean")] - public string ShowEditButton { get; set; } [PreValueField("startNodeId", "Start node", "treepicker")] public int StartNodeId { get; set; } - [PreValueField("showPathOnHover", "Show path when hovering items", "boolean")] - public bool ShowPathOnHover { get; set; } } } } \ No newline at end of file diff --git a/src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs index b3d3f02448..82daf80e34 100644 --- a/src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs @@ -45,16 +45,9 @@ namespace Umbraco.Web.PropertyEditors [PreValueField("maxNumber", "Maximum number of items", "number")] public string MaxNumber { get; set; } - - [PreValueField("showOpenButton", "Show open button", "boolean")] + [PreValueField("showOpenButton", "Show open button (this feature is in preview!)", "boolean", Description = " Opens the node in a dialog")] public string ShowOpenButton { get; set; } - [PreValueField("showEditButton", "Show edit button (this feature is in preview!)", "boolean")] - public string ShowEditButton { get; set; } - - [PreValueField("showPathOnHover", "Show path when hovering items", "boolean")] - public bool ShowPathOnHover { get; set; } - /// /// This ensures the multiPicker pre-val is set based on the maxNumber of nodes set ///