Merge branch 'v8/dev' into v8-fix-media-picker-create-folder

This commit is contained in:
elitsa
2019-04-24 09:41:48 +02:00
704 changed files with 14897 additions and 11551 deletions

View File

@@ -1,22 +0,0 @@
@ECHO OFF
ECHO.
ECHO.
ECHO This will only work when you have NPM available on the command line
ECHO Works great with NodeJS Portable - https://gareth.flowers/nodejs-portable/
ECHO.
ECHO.
set /P c=Are you sure you want to continue [Y/N]?
if /I "%c%" EQU "Y" goto :setupgulp
if /I "%c%" EQU "N" goto :eof
:setupgulp
call npm install
call npm -g install gulp
call npm -g install gulp-cli
ECHO.
ECHO.
ECHO You should now be able to run: gulp build or gulp dev
ECHO.
ECHO.

View File

@@ -0,0 +1,105 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbToggleGroup
@restrict E
@scope
@description
Use this directive to render a group of toggle buttons.
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<umb-toggle-group
items="vm.items"
on-click="vm.toggle(item)">
</umb-toggle-group>
</div>
</pre>
<h3>Controller example</h3>
<pre>
(function () {
"use strict";
function Controller() {
var vm = this;
vm.toggle = toggle;
function toggle(item) {
if(item.checked) {
// do something if item is checked
}
else {
// do something else if item is unchecked
}
}
function init() {
vm.items = [{
name: "Item 1",
description: "Item 1 description",
checked: false,
disabled: false
}, {
name: "Item 2",
description: "Item 2 description",
checked: true,
disabled: true
}];
}
init();
}
angular.module("umbraco").controller("My.Controller", Controller);
})();
</pre>
@param {Array} items The items to list in the toggle group
@param {callback} onClick The function which should be called when the toggle is clicked for one of the items.
**/
(function () {
'use strict';
function ToggleGroupDirective() {
function link(scope, el, attr, ctrl) {
scope.change = function(item) {
if (item.disabled) {
return;
}
item.checked = !item.checked;
if(scope.onClick) {
scope.onClick({'item': item});
}
};
}
var directive = {
restrict: 'E',
replace: true,
templateUrl: 'views/components/buttons/umb-toggle-group.html',
scope: {
items: "=",
onClick: "&"
},
link: link
};
return directive;
}
angular.module('umbraco.directives').directive('umbToggleGroup', ToggleGroupDirective);
})();

View File

@@ -116,6 +116,13 @@
function isContentCultureVariant() {
return $scope.content.variants.length > 1;
}
function reload() {
$scope.page.loading = true;
loadContent().then(function() {
$scope.page.loading = false;
});
}
function bindEvents() {
//bindEvents can be called more than once and we don't want to have multiple bound events
@@ -123,13 +130,10 @@
eventsService.unsubscribe(evts[e]);
}
evts.push(eventsService.on("editors.content.reload", function (name, args) {
evts.push(eventsService.on("editors.documentType.saved", function (name, args) {
// if this content item uses the updated doc type we need to reload the content item
if(args && args.node && args.node.key === $scope.content.key) {
$scope.page.loading = true;
loadContent().then(function() {
$scope.page.loading = false;
});
if(args && args.documentType && $scope.content.documentType.id === args.documentType.id) {
reload();
}
}));
@@ -331,8 +335,7 @@
// This is a helper method to reduce the amount of code repitition for actions: Save, Publish, SendToPublish
function performSave(args) {
//Used to check validility of nested form - coming from Content Apps mostly
//Set them all to be invalid
var fieldsToRollback = checkValidility();

View File

@@ -147,7 +147,7 @@
id: documentType.id,
submit: function (model) {
const args = { node: scope.node };
eventsService.emit('editors.content.reload', args);
eventsService.emit("editors.content.reload", args);
editorService.close();
},
close: function () {
@@ -344,8 +344,8 @@
loadAuditTrail(true);
loadRedirectUrls();
setNodePublishStatus();
updateCurrentUrls();
}
updateCurrentUrls();
});
//ensure to unregister from all events!

View File

@@ -0,0 +1,22 @@
(function () {
'use strict';
function umbNotificationList() {
var vm = this;
}
var umbNotificationListComponent = {
templateUrl: 'views/components/content/umb-variant-notification-list.html',
bindings: {
notifications: "<"
},
controllerAs: 'vm',
controller: umbNotificationList
};
angular.module("umbraco.directives")
.component('umbVariantNotificationList', umbNotificationListComponent);
})();

View File

@@ -47,6 +47,9 @@ The sub header is sticky and will follow along down the page when scrolling.
transclude: true,
restrict: 'E',
replace: true,
scope: {
"appearance": "@?"
},
templateUrl: 'views/components/editor/subheader/umb-editor-sub-header.html'
};

View File

@@ -42,7 +42,7 @@
item: '=',
onOpen: '&',
onOpenAnchor: '&',
index: '@'
hotkey: '<'
}
});

View File

@@ -0,0 +1,72 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbCheckbox
@restrict E
@scope
@description
<b>Added in Umbraco version 7.14.0</b> Use this directive to render an umbraco checkbox.
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<umb-checkbox
name="checkboxlist"
value="{{key}}"
model="true"
text="{{text}}">
</umb-checkbox>
</div>
</pre>
@param {boolean} model Set to <code>true</code> or <code>false</code> to set the checkbox to checked or unchecked.
@param {string} input-id Set the <code>id</code> of the checkbox.
@param {string} value Set the value of the checkbox.
@param {string} name Set the name of the checkbox.
@param {string} text Set the text for the checkbox label.
@param {string} server-validation-field Set the <code>val-server-field</code> of the checkbox.
@param {boolean} disabled Set the checkbox to be disabled.
@param {boolean} required Set the checkbox to be required.
@param {string} on-change Callback when the value of the checkbox changed by interaction.
**/
(function () {
'use strict';
function UmbCheckboxController($timeout) {
var vm = this;
vm.callOnChange = function() {
$timeout(function() {
vm.onChange({model:vm.model, value:vm.value});
}, 0);
}
}
var component = {
templateUrl: 'views/components/forms/umb-checkbox.html',
controller: UmbCheckboxController,
controllerAs: 'vm',
bindings: {
model: "=",
inputId: "@",
value: "@",
name: "@",
text: "@",
serverValidationField: "@",
disabled: "<",
required: "<",
onChange: "&"
}
};
angular.module('umbraco.directives').component('umbCheckbox', component);
})();

View File

@@ -0,0 +1,57 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbRadiobutton
@restrict E
@scope
@description
<b>Added in Umbraco version 7.14.0</b> Use this directive to render an umbraco radio button.
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<umb-radiobutton
name="radiobuttonlist"
value="{{key}}"
model="true"
text="{{text}}">
</umb-radiobutton>
</div>
</pre>
@param {boolean} model Set to <code>true</code> or <code>false</code> to set the radiobutton to checked or unchecked.
@param {string} value Set the value of the radiobutton.
@param {string} name Set the name of the radiobutton.
@param {string} text Set the text for the radiobutton label.
@param {boolean} disabled Set the radiobutton to be disabled.
@param {boolean} required Set the radiobutton to be required.
**/
(function () {
'use strict';
function RadiobuttonDirective() {
var directive = {
restrict: 'E',
replace: true,
templateUrl: 'views/components/forms/umb-radiobutton.html',
scope: {
model: "=",
value: "@",
name: "@",
text: "@",
disabled: "=",
required: "="
}
};
return directive;
}
angular.module('umbraco.directives').directive('umbRadiobutton', RadiobuttonDirective);
})();

View File

@@ -13,25 +13,36 @@ angular.module("umbraco.directives")
// TODO: A lot of the code below should be shared between the grid rte and the normal rte
var promises = [];
//To id the html textarea we need to use the datetime ticks because we can have multiple rte's per a single property alias
// because now we have to support having 2x (maybe more at some stage) content editors being displayed at once. This is because
// we have this mini content editor panel that can be launched with MNTP.
scope.textAreaHtmlId = scope.uniqueId + "_" + String.CreateGuid();
//queue file loading
if (typeof (tinymce) === "undefined") {
promises.push(assetsService.loadJs("lib/tinymce/tinymce.min.js", scope));
}
var toolbar = ["code", "styleselect", "bold", "italic", "alignleft", "aligncenter", "alignright", "bullist", "numlist", "link", "umbmediapicker", "umbembeddialog"];
if (scope.configuration && scope.configuration.toolbar) {
toolbar = scope.configuration.toolbar;
var editorConfig = scope.configuration ? scope.configuration : null;
if (!editorConfig || angular.isString(editorConfig)) {
editorConfig = tinyMceService.defaultPrevalues();
//for the grid by default, we don't want to include the macro toolbar
editorConfig.toolbar = _.without(editorConfig, "umbmacro");
}
//make sure there's a max image size
if (!scope.configuration.maxImageSize && scope.configuration.maxImageSize !== 0) {
editorConfig.maxImageSize = tinyMceService.defaultPrevalues().maxImageSize;
}
//stores a reference to the editor
var tinyMceEditor = null;
promises.push(tinyMceService.getTinyMceEditorConfig({
htmlId: scope.uniqueId,
stylesheets: scope.configuration ? scope.configuration.stylesheets : null,
toolbar: toolbar,
mode: scope.configuration.mode
htmlId: scope.textAreaHtmlId,
stylesheets: editorConfig.stylesheets,
toolbar: editorConfig.toolbar,
mode: editorConfig.mode
}));
// pin toolbar to top of screen if we have focus and it scrolls off the screen
@@ -46,9 +57,16 @@ angular.module("umbraco.directives")
$q.all(promises).then(function (result) {
var tinyMceEditorConfig = result[promises.length - 1];
var standardConfig = result[promises.length - 1];
tinyMceEditorConfig.setup = function (editor) {
//create a baseline Config to extend upon
var baseLineConfigObj = {
maxImageSize: editorConfig.maxImageSize
};
angular.extend(baseLineConfigObj, standardConfig);
baseLineConfigObj.setup = function (editor) {
//set the reference
tinyMceEditor = editor;
@@ -111,7 +129,7 @@ angular.module("umbraco.directives")
//the elements needed
$timeout(function () {
tinymce.DOM.events.domLoaded = true;
tinymce.init(tinyMceEditorConfig);
tinymce.init(baseLineConfigObj);
}, 150, false);
}
@@ -132,17 +150,11 @@ angular.module("umbraco.directives")
}
});
//listen for formSubmitting event (the result is callback used to remove the event subscription)
var formSubmittingListener = scope.$on("formSubmitting", function () {
scope.value = tinyMceEditor ? tinyMceEditor.getContent() : null;
});
//when the element is disposed we need to unsubscribe!
// NOTE: this is very important otherwise if this is part of a modal, the listener still exists because the dom
// element might still be there even after the modal has been hidden.
scope.$on('$destroy', function () {
formSubmittingListener();
eventsService.unsubscribe(tabShownListener);
//ensure we unbind this in case the blur doesn't fire above
$('.umb-panel-body').off('scroll', pinToolbar);

View File

@@ -32,16 +32,27 @@ angular.module("umbraco.directives")
restrict: 'E',
scope:{
key: '@',
tokens: '='
tokens: '=',
watchTokens: '@'
},
replace: true,
link: function (scope, element, attrs) {
var key = scope.key;
var tokens = scope.tokens ? scope.tokens : null;
localizationService.localize(key, tokens).then(function(value){
element.html(value);
scope.text = "";
// A render function to be able to update tokens as values update.
function render() {
element.html(localizationService.tokenReplace(scope.text, scope.tokens || null));
}
localizationService.localize(key).then(function(value){
scope.text = value;
render();
});
if (scope.watchTokens === 'true') {
scope.$watch("tokens", render, true);
}
}
};
})

View File

@@ -12,6 +12,7 @@ function treeSearchBox(localizationService, searchService, $q) {
searchFromName: "@",
showSearch: "@",
section: "@",
ignoreUserStartNodes: "@",
hideSearchCallback: "=",
searchCallback: "="
},
@@ -34,6 +35,7 @@ function treeSearchBox(localizationService, searchService, $q) {
scope.showSearch = "false";
}
//used to cancel any request in progress if another one needs to take it's place
var canceler = null;
@@ -60,6 +62,11 @@ function treeSearchBox(localizationService, searchService, $q) {
searchArgs["searchFrom"] = scope.searchFromId;
}
//append ignoreUserStartNodes value if there is one
if (scope.ignoreUserStartNodes) {
searchArgs["ignoreUserStartNodes"] = scope.ignoreUserStartNodes;
}
searcher(searchArgs).then(function (data) {
scope.searchCallback(data);
//set back to null so it can be re-created

View File

@@ -60,6 +60,7 @@ function confirmDirective() {
link: function (scope, element, attr, ctrl) {
scope.showCancel = false;
scope.showConfirm = false;
scope.confirmButtonState = "init";
if (scope.onConfirm) {
scope.showConfirm = true;
@@ -68,6 +69,15 @@ function confirmDirective() {
if (scope.onCancel) {
scope.showCancel = true;
}
scope.confirm = function () {
if (!scope.onConfirm) {
return;
}
scope.confirmButtonState = "busy";
scope.onConfirm();
}
}
};
}

View File

@@ -117,9 +117,11 @@ Use this directive to generate a list of content items presented as a flexbox gr
};
scope.clickItemName = function(item, $event, $index) {
if(scope.onClickName) {
if(scope.onClickName && !($event.metaKey || $event.ctrlKey)) {
scope.onClickName(item, $event, $index);
$event.preventDefault();
}
$event.stopPropagation();
};
}

View File

@@ -1,13 +1,17 @@
(function() {
'use strict';
function GroupsBuilderDirective(contentTypeHelper, contentTypeResource, mediaTypeResource, dataTypeHelper, dataTypeResource, $filter, iconHelper, $q, $timeout, notificationsService, localizationService, editorService) {
function GroupsBuilderDirective(contentTypeHelper, contentTypeResource, mediaTypeResource,
dataTypeHelper, dataTypeResource, $filter, iconHelper, $q, $timeout, notificationsService,
localizationService, editorService, eventsService) {
function link(scope, el, attr, ctrl) {
var eventBindings = [];
var validationTranslated = "";
var tabNoSortOrderTranslated = "";
scope.dataTypeHasChanged = false;
scope.sortingMode = false;
scope.toolbar = [];
scope.sortableOptionsGroup = {};
@@ -613,18 +617,44 @@
});
});
}
var unbindModelWatcher = scope.$watch('model', function(newValue, oldValue) {
if (newValue !== undefined && newValue.groups !== undefined) {
activate();
function hasPropertyOfDataTypeId(dataTypeId) {
// look at each property
var result = _.filter(scope.model.groups, function(group) {
return _.filter(group.properties, function(property) {
return (property.dataTypeId === dataTypeId);
});
});
return (result.length > 0);
}
});
// clean up
scope.$on('$destroy', function(){
unbindModelWatcher();
});
eventBindings.push(scope.$watch('model', function(newValue, oldValue) {
if (newValue !== undefined && newValue.groups !== undefined) {
activate();
}
}));
// clean up
eventBindings.push(eventsService.on("editors.dataTypeSettings.saved", function (name, args) {
if(hasPropertyOfDataTypeId(args.dataType.id)) {
scope.dataTypeHasChanged = true;
}
}));
// clean up
eventBindings.push(scope.$on('$destroy', function() {
for(var e in eventBindings) {
eventBindings[e]();
}
// if a dataType has changed, we want to notify which properties that are affected by this dataTypeSettings change
if(scope.dataTypeHasChanged === true) {
var args = {documentType: scope.model};
eventsService.emit("editors.documentType.saved", args);
}
}));
}

View File

@@ -91,6 +91,10 @@ Use this directive to generate a pagination.
function link(scope, el, attr, ctrl) {
function activate() {
// page number is sometimes a string - let's make sure it's an int before we do anything with it
if (scope.pageNumber) {
scope.pageNumber = parseInt(scope.pageNumber);
}
scope.pagination = [];

View File

@@ -56,7 +56,7 @@ Use this directive make an element sticky and follow the page when scrolling.
}
if (attr.scrollableContainer) {
scrollableContainer = $(attr.scrollableContainer);
scrollableContainer = bar.closest(attr.scrollableContainer);
} else {
scrollableContainer = $(window);
}
@@ -121,7 +121,7 @@ Use this directive make an element sticky and follow the page when scrolling.
function calculateSize() {
var width = bar.innerWidth();
clonedBar.css({
width: width
width: width + 10 // + 10 (5*2) because we need to add border to avoid seeing the shadow beneath. Look at the CSS.
});
}

View File

@@ -117,10 +117,11 @@
var vm = this;
vm.clickItem = function (item, $event) {
if (vm.onClick) {
if (vm.onClick && !($event.metaKey || $event.ctrlKey)) {
vm.onClick({ item: item});
$event.stopPropagation();
$event.preventDefault();
}
$event.stopPropagation();
};
vm.selectItem = function (item, $index, $event) {

View File

@@ -15,10 +15,12 @@ function umbFileUpload() {
el.on('change', function (event) {
var files = event.target.files;
//emit event upward
scope.$emit("filesSelected", { files: files });
scope.$emit("filesSelected", { files: files });
//clear the element value - this allows us to pick the same file again and again
el.val('');
});
}
};
}
angular.module('umbraco.directives').directive("umbFileUpload", umbFileUpload);
angular.module('umbraco.directives').directive("umbFileUpload", umbFileUpload);

View File

@@ -1,36 +0,0 @@
(function () {
'use strict';
function PermissionDirective() {
function link(scope, el, attr, ctrl) {
scope.change = function() {
scope.selected = !scope.selected;
if(scope.onChange) {
scope.onChange({'selected': scope.selected});
}
};
}
var directive = {
restrict: 'E',
replace: true,
templateUrl: 'views/components/users/umb-permission.html',
scope: {
name: "=",
description: "=?",
selected: "=",
onChange: "&"
},
link: link
};
return directive;
}
angular.module('umbraco.directives').directive('umbPermission', PermissionDirective);
})();

View File

@@ -27,7 +27,10 @@ function valPropertyMsg(serverValidationManager) {
var umbPropCtrl = ctrl[2];
scope.currentProperty = umbPropCtrl.property;
var currentCulture = scope.currentProperty.culture;
//if the property is invariant (no culture), then we will explicitly set it to the string 'invariant'
//since this matches the value that the server will return for an invariant property.
var currentCulture = scope.currentProperty.culture || "invariant";
var watcher = null;
@@ -62,8 +65,8 @@ function valPropertyMsg(serverValidationManager) {
if (!watcher) {
watcher = scope.$watch("currentProperty.value",
function (newValue, oldValue) {
if (!newValue || angular.equals(newValue, oldValue)) {
if (angular.equals(newValue, oldValue)) {
return;
}
@@ -78,10 +81,12 @@ function valPropertyMsg(serverValidationManager) {
// based on other errors. We'll also check if there's no other validation errors apart from valPropertyMsg, if valPropertyMsg
// is the only one, then we'll clear.
if ((errCount === 1 && angular.isArray(formCtrl.$error.valPropertyMsg)) || (formCtrl.$invalid && angular.isArray(formCtrl.$error.valServer))) {
if (errCount === 0 || (errCount === 1 && angular.isArray(formCtrl.$error.valPropertyMsg)) || (formCtrl.$invalid && angular.isArray(formCtrl.$error.valServer))) {
scope.errorMsg = "";
formCtrl.$setValidity('valPropertyMsg', true);
stopWatch();
} else if (showValidation && scope.errorMsg === "") {
formCtrl.$setValidity('valPropertyMsg', false);
scope.errorMsg = getErrorMsg();
}
}, true);
}
@@ -152,6 +157,7 @@ function valPropertyMsg(serverValidationManager) {
showValidation = true;
if (hasError && scope.errorMsg === "") {
scope.errorMsg = getErrorMsg();
startWatch();
}
else if (!hasError) {
scope.errorMsg = "";

View File

@@ -59,20 +59,27 @@
}
//A 401 means that the user is not logged in
if (rejection.status === 401 && !rejection.config.url.endsWith("umbraco/backoffice/UmbracoApi/Authentication/GetCurrentUser")) {
if (rejection.status === 401) {
//avoid an infinite loop
var umbRequestHelper = $injector.get('umbRequestHelper');
var getCurrentUserPath = umbRequestHelper.getApiUrl("authenticationApiBaseUrl", "GetCurrentUser");
if (!rejection.config.url.endsWith(getCurrentUserPath)) {
var userService = $injector.get('userService'); // see above
var userService = $injector.get('userService'); // see above
//Associate the user name with the retry to ensure we retry for the right user
return userService.getCurrentUser()
.then(function (user) {
var userName = user ? user.name : null;
//The request bounced because it was not authorized - add a new request to the retry queue
return requestRetryQueue.pushRetryFn('unauthorized-server', userName, function retryRequest() {
// We must use $injector to get the $http service to prevent circular dependency
return $injector.get('$http')(rejection.config);
//Associate the user name with the retry to ensure we retry for the right user
return userService.getCurrentUser()
.then(function(user) {
var userName = user ? user.name : null;
//The request bounced because it was not authorized - add a new request to the retry queue
return requestRetryQueue.pushRetryFn('unauthorized-server',
userName,
function retryRequest() {
// We must use $injector to get the $http service to prevent circular dependency
return $injector.get('$http')(rejection.config);
});
});
});
}
}
else if (rejection.status === 404) {

View File

@@ -215,14 +215,6 @@ angular.module('umbraco.mocks').
"placeholders_nameentity": "Name the %0%...",
"placeholders_search": "Type to search...",
"placeholders_filter": "Type to filter...",
"editcontenttype_allowedchildnodetypes": "Allowed child nodetypes",
"editcontenttype_create": "Create",
"editcontenttype_deletetab": "Delete tab",
"editcontenttype_description": "Description",
"editcontenttype_newtab": "New tab",
"editcontenttype_tab": "Tab",
"editcontenttype_thumbnail": "Thumbnail",
"editcontenttype_iscontainercontenttype": "Use as container content type",
"editdatatype_addPrevalue": "Add prevalue",
"editdatatype_dataBaseDatatype": "Database datatype",
"editdatatype_guid": "Property editor GUID",

View File

@@ -365,17 +365,28 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
* </pre>
*
* @param {Int} id id of content item to return
* @param {Int} culture optional culture to retrieve the item in
* @param {Bool} options.ignoreUserStartNodes set to true to allow a user to choose nodes that they normally don't have access to
* @returns {Promise} resourcePromise object containing the content item.
*
*/
getById: function (id) {
getById: function (id, options) {
var defaults = {
ignoreUserStartNodes: false
};
if (options === undefined) {
options = {};
}
//overwrite the defaults if there are any specified
angular.extend(defaults, options);
//now copy back to the options we will use
options = defaults;
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"GetById",
{ id: id })),
[{ id: id }, { ignoreUserStartNodes: options.ignoreUserStartNodes }])),
'Failed to retrieve data for content id ' + id)
.then(function (result) {
return $q.when(umbDataFormatter.formatContentGetData(result));

View File

@@ -344,6 +344,12 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter, loca
$http.post(umbRequestHelper.getApiUrl("contentTypeApiBaseUrl", "Import", { file: file })),
"Failed to import document type " + file
);
},
createDefaultTemplate: function (id) {
return umbRequestHelper.resourcePromise(
$http.post(umbRequestHelper.getApiUrl("contentTypeApiBaseUrl", "PostCreateDefaultTemplate", { id: id })),
'Failed to create default template for content type with id ' + id);
}
};
}

View File

@@ -284,15 +284,31 @@ function entityResource($q, $http, umbRequestHelper) {
* @returns {Promise} resourcePromise object containing the entity.
*
*/
getAncestors: function (id, type, culture) {
getAncestors: function (id, type, culture, options) {
var defaults = {
ignoreUserStartNodes: false
};
if (options === undefined) {
options = {};
}
//overwrite the defaults if there are any specified
angular.extend(defaults, options);
//now copy back to the options we will use
options = defaults;
if (culture === undefined) culture = "";
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"entityApiBaseUrl",
"GetAncestors",
[{ id: id }, { type: type }, { culture: culture }])),
'Failed to retrieve ancestor data for id ' + id);
[
{ id: id },
{ type: type },
{ culture: culture },
{ ignoreUserStartNodes: options.ignoreUserStartNodes }
])),
'Failed to retrieve ancestor data for id ' + id);
},
/**
@@ -424,7 +440,8 @@ function entityResource($q, $http, umbRequestHelper) {
pageNumber: 1,
filter: '',
orderDirection: "Ascending",
orderBy: "SortOrder"
orderBy: "SortOrder",
ignoreUserStartNodes: false
};
if (options === undefined) {
options = {};
@@ -453,7 +470,8 @@ function entityResource($q, $http, umbRequestHelper) {
pageSize: options.pageSize,
orderBy: options.orderBy,
orderDirection: options.orderDirection,
filter: encodeURIComponent(options.filter)
filter: encodeURIComponent(options.filter),
ignoreUserStartNodes: options.ignoreUserStartNodes
}
)),
'Failed to retrieve child data for id ' + parentId);
@@ -481,12 +499,19 @@ function entityResource($q, $http, umbRequestHelper) {
* @returns {Promise} resourcePromise object containing the entity array.
*
*/
search: function (query, type, searchFrom, canceler) {
search: function (query, type, options, canceler) {
var args = [{ query: query }, { type: type }];
if (searchFrom) {
args.push({ searchFrom: searchFrom });
if(options !== undefined) {
if (options.searchFrom) {
args.push({ searchFrom: options.searchFrom });
}
if (options.ignoreUserStartNodes) {
args.push({ ignoreUserStartNodes: options.ignoreUserStartNodes });
}
}
var httpConfig = {};
if (canceler) {

View File

@@ -53,7 +53,7 @@ function logResource($q, $http, umbRequestHelper) {
*
* @param {Object} options options object
* @param {Int} options.id the id of the entity
* @param {Int} options.pageSize if paging data, number of nodes per page, default = 10, set to 0 to disable paging
* @param {Int} options.pageSize if paging data, number of nodes per page, default = 10
* @param {Int} options.pageNumber if paging data, current page index, default = 1
* @param {String} options.orderDirection can be `Ascending` or `Descending` - Default: `Descending`
* @param {Date} options.sinceDate if provided this will only get log entries going back to this date
@@ -122,7 +122,7 @@ function logResource($q, $http, umbRequestHelper) {
* </pre>
*
* @param {Object} options options object
* @param {Int} options.pageSize if paging data, number of nodes per page, default = 10, set to 0 to disable paging
* @param {Int} options.pageSize if paging data, number of nodes per page, default = 10
* @param {Int} options.pageNumber if paging data, current page index, default = 1
* @param {String} options.orderDirection can be `Ascending` or `Descending` - Default: `Descending`
* @param {Date} options.sinceDate if provided this will only get log entries going back to this date

View File

@@ -329,7 +329,8 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
filter: '',
orderDirection: "Ascending",
orderBy: "SortOrder",
orderBySystemField: true
orderBySystemField: true,
ignoreUserStartNodes: false
};
if (options === undefined) {
options = {};
@@ -367,6 +368,7 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
"GetChildren",
[
{ id: parentId },
{ ignoreUserStartNodes: options.ignoreUserStartNodes },
{ pageNumber: options.pageNumber },
{ pageSize: options.pageSize },
{ orderBy: options.orderBy },

View File

@@ -291,84 +291,3 @@ function appState(eventsService) {
};
}
angular.module('umbraco.services').factory('appState', appState);
/**
* @ngdoc service
* @name umbraco.services.editorState
* @function
*
* @description
* Tracks the parent object for complex editors by exposing it as
* an object reference via editorState.current.entity
*
* it is possible to modify this object, so should be used with care
*/
angular.module('umbraco.services').factory("editorState", function() {
var current = null;
var state = {
/**
* @ngdoc function
* @name umbraco.services.angularHelper#set
* @methodOf umbraco.services.editorState
* @function
*
* @description
* Sets the current entity object for the currently active editor
* This is only used when implementing an editor with a complex model
* like the content editor, where the model is modified by several
* child controllers.
*/
set: function (entity) {
current = entity;
},
/**
* @ngdoc function
* @name umbraco.services.angularHelper#reset
* @methodOf umbraco.services.editorState
* @function
*
* @description
* Since the editorstate entity is read-only, you cannot set it to null
* only through the reset() method
*/
reset: function() {
current = null;
},
/**
* @ngdoc function
* @name umbraco.services.angularHelper#getCurrent
* @methodOf umbraco.services.editorState
* @function
*
* @description
* Returns an object reference to the current editor entity.
* the entity is the root object of the editor.
* EditorState is used by property/parameter editors that need
* access to the entire entity being edited, not just the property/parameter
*
* editorState.current can not be overwritten, you should only read values from it
* since modifying individual properties should be handled by the property editors
*/
getCurrent: function() {
return current;
}
};
// TODO: This shouldn't be removed! use getCurrent() method instead of a hacked readonly property which is confusing.
//create a get/set property but don't allow setting
Object.defineProperty(state, "current", {
get: function () {
return current;
},
set: function (value) {
throw "Use editorState.set to set the value of the current entity";
}
});
return state;
});

View File

@@ -301,6 +301,19 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
return allProps;
},
/**
* @ngdoc method
* @name umbraco.services.contentEditingHelper#buildCompositeVariantId
* @methodOf umbraco.services.contentEditingHelper
* @function
*
* @description
* Returns a id for the variant that is unique between all variants on the content
*/
buildCompositeVariantId: function (variant) {
return (variant.language ? variant.language.culture : "invariant") + "_" + (variant.segment ? variant.segment : "");
},
/**
* @ngdoc method

View File

@@ -0,0 +1,80 @@
/**
* @ngdoc service
* @name umbraco.services.editorState
* @function
*
* @description
* Tracks the parent object for complex editors by exposing it as
* an object reference via editorState.current.entity
*
* it is possible to modify this object, so should be used with care
*/
angular.module('umbraco.services').factory("editorState", function() {
var current = null;
var state = {
/**
* @ngdoc function
* @name umbraco.services.angularHelper#set
* @methodOf umbraco.services.editorState
* @function
*
* @description
* Sets the current entity object for the currently active editor
* This is only used when implementing an editor with a complex model
* like the content editor, where the model is modified by several
* child controllers.
*/
set: function (entity) {
current = entity;
},
/**
* @ngdoc function
* @name umbraco.services.angularHelper#reset
* @methodOf umbraco.services.editorState
* @function
*
* @description
* Since the editorstate entity is read-only, you cannot set it to null
* only through the reset() method
*/
reset: function() {
current = null;
},
/**
* @ngdoc function
* @name umbraco.services.angularHelper#getCurrent
* @methodOf umbraco.services.editorState
* @function
*
* @description
* Returns an object reference to the current editor entity.
* the entity is the root object of the editor.
* EditorState is used by property/parameter editors that need
* access to the entire entity being edited, not just the property/parameter
*
* editorState.current can not be overwritten, you should only read values from it
* since modifying individual properties should be handled by the property editors
*/
getCurrent: function() {
return current;
}
};
// TODO: This shouldn't be removed! use getCurrent() method instead of a hacked readonly property which is confusing.
//create a get/set property but don't allow setting
Object.defineProperty(state, "current", {
get: function () {
return current;
},
set: function (value) {
throw "Use editorState.set to set the value of the current entity";
}
});
return state;
});

View File

@@ -45,7 +45,7 @@
(function () {
'use strict';
function listViewHelper(localStorageService) {
function listViewHelper($location, localStorageService, urlHelper) {
var firstSelectedIndex = 0;
var localStorageKey = "umblistViewLayout";
@@ -59,11 +59,11 @@
* Method for internal use, based on the collection of layouts passed, the method selects either
* any previous layout from local storage, or picks the first allowed layout
*
* @param {Number} nodeId The id of the current node displayed in the content editor
* @param {Any} id The identifier of the current node or application displayed in the content editor
* @param {Array} availableLayouts Array of all allowed layouts, available from $scope.model.config.layouts
*/
function getLayout(nodeId, availableLayouts) {
function getLayout(id, availableLayouts) {
var storedLayouts = [];
@@ -74,8 +74,8 @@
if (storedLayouts && storedLayouts.length > 0) {
for (var i = 0; storedLayouts.length > i; i++) {
var layout = storedLayouts[i];
if (layout.nodeId === nodeId) {
return setLayout(nodeId, layout, availableLayouts);
if (isMatchingLayout(id, layout)) {
return setLayout(id, layout, availableLayouts);
}
}
@@ -93,12 +93,12 @@
* @description
* Changes the current layout used by the listview to the layout passed in. Stores selection in localstorage
*
* @param {Number} nodeID Id of the current node displayed in the content editor
* @param {Any} id The identifier of the current node or application displayed in the content editor
* @param {Object} selectedLayout Layout selected as the layout to set as the current layout
* @param {Array} availableLayouts Array of all allowed layouts, available from $scope.model.config.layouts
*/
function setLayout(nodeId, selectedLayout, availableLayouts) {
function setLayout(id, selectedLayout, availableLayouts) {
var activeLayout = {};
var layoutFound = false;
@@ -118,7 +118,7 @@
activeLayout = getFirstAllowedLayout(availableLayouts);
}
saveLayoutInLocalStorage(nodeId, activeLayout);
saveLayoutInLocalStorage(id, activeLayout);
return activeLayout;
@@ -132,11 +132,11 @@
* @description
* Stores a given layout as the current default selection in local storage
*
* @param {Number} nodeId Id of the current node displayed in the content editor
* @param {Any} id The identifier of the current node or application displayed in the content editor
* @param {Object} selectedLayout Layout selected as the layout to set as the current layout
*/
function saveLayoutInLocalStorage(nodeId, selectedLayout) {
function saveLayoutInLocalStorage(id, selectedLayout) {
var layoutFound = false;
var storedLayouts = [];
@@ -147,7 +147,7 @@
if (storedLayouts.length > 0) {
for (var i = 0; storedLayouts.length > i; i++) {
var layout = storedLayouts[i];
if (layout.nodeId === nodeId) {
if (isMatchingLayout(id, layout)) {
layout.path = selectedLayout.path;
layoutFound = true;
}
@@ -156,7 +156,7 @@
if (!layoutFound) {
var storageObject = {
"nodeId": nodeId,
"id": id,
"path": selectedLayout.path
};
storedLayouts.push(storageObject);
@@ -397,6 +397,54 @@
}
}
/**
* @ngdoc method
* @name umbraco.services.listViewHelper#selectAllItemsToggle
* @methodOf umbraco.services.listViewHelper
*
* @description
* Helper method for toggling the select state on all items.
*
* @param {Array} items Items to toggle selection on, should be $scope.items
* @param {Array} selection Listview selection, available as $scope.selection
*/
function selectAllItemsToggle(items, selection) {
if (!angular.isArray(items)) {
return;
}
if (isSelectedAll(items, selection)) {
// unselect all items
angular.forEach(items, function (item) {
item.selected = false;
});
// reset selection without loosing reference.
selection.length = 0;
} else {
// reset selection without loosing reference.
selection.length = 0;
// select all items
angular.forEach(items, function (item) {
var obj = {
id: item.id
};
if (item.key) {
obj.key = item.key;
}
item.selected = true;
selection.push(obj);
});
}
}
/**
* @ngdoc method
@@ -510,6 +558,38 @@
};
}
/**
* @ngdoc method
* @name umbraco.services.listViewHelper#editItem
* @methodOf umbraco.services.listViewHelper
*
* @description
* Method for opening an item in a list view for editing.
*
* @param {Object} item The item to edit
*/
function editItem(item) {
if (!item.editPath) {
return;
}
var parts = item.editPath.split("?");
var path = parts[0];
var params = parts[1]
? urlHelper.getQueryStringParams("?" + parts[1])
: {};
$location.path(path);
for (var p in params) {
$location.search(p, params[p]);
}
}
function isMatchingLayout(id, layout) {
// legacy format uses "nodeId", be sure to look for both
return layout.id === id || layout.nodeId === id;
}
var service = {
getLayout: getLayout,
@@ -521,10 +601,12 @@
deselectItem: deselectItem,
clearSelection: clearSelection,
selectAllItems: selectAllItems,
selectAllItemsToggle: selectAllItemsToggle,
isSelectedAll: isSelectedAll,
setSortingDirection: setSortingDirection,
setSorting: setSorting,
getButtonPermissions: getButtonPermissions
getButtonPermissions: getButtonPermissions,
editItem: editItem
};

View File

@@ -43,16 +43,11 @@ angular.module('umbraco.services')
var entry = dictionary[value];
if (entry) {
if (tokens) {
for (var i = 0; i < tokens.length; i++) {
entry = entry.replace("%" + i + "%", tokens[i]);
}
}
return entry;
return service.tokenReplace(entry, tokens);
}
return "[" + value + "]";
}
var service = {
// array to hold the localized resource string entries
dictionary: [],
@@ -127,7 +122,29 @@ angular.module('umbraco.services')
}
return value;
},
/**
* @ngdoc method
* @name umbraco.services.localizationService#tokenReplace
* @methodOf umbraco.services.localizationService
*
* @description
* Helper to replace tokens
* @param {String} value the text-string to manipulate
* @param {Array} tekens An array of tokens values
* @returns {String} Replaced test-string
*/
tokenReplace: function (text, tokens) {
if (tokens) {
for (var i = 0; i < tokens.length; i++) {
text = text.replace("%" + i + "%", tokens[i]);
}
}
return text;
},
/**
* @ngdoc method
* @name umbraco.services.localizationService#localize
@@ -146,8 +163,7 @@ angular.module('umbraco.services')
*/
localize: function (value, tokens) {
return service.initLocalizedResources().then(function (dic) {
var val = _lookup(value, tokens, dic);
return val;
return _lookup(value, tokens, dic);
});
},

View File

@@ -26,6 +26,8 @@ function navigationService($routeParams, $location, $q, $timeout, $injector, eve
navReadyPromise.resolve(mainTreeApi);
});
//A list of query strings defined that when changed will not cause a reload of the route
var nonRoutingQueryStrings = ["mculture", "cculture", "lq"];
var retainedQueryStrings = ["mculture"];

View File

@@ -85,17 +85,17 @@ angular.module('umbraco.services')
nArray.push(item);
if(!item.sticky) {
$timeout(function() {
var found = _.find(nArray, function(i) {
return i.id === item.id;
});
if (found) {
var index = nArray.indexOf(found);
nArray.splice(index, 1);
}
}, 7000);
$timeout(
function() {
var found = _.find(nArray, function(i) {
return i.id === item.id;
});
if (found) {
var index = nArray.indexOf(found);
nArray.splice(index, 1);
}
}
, 10000);
}
return item;

View File

@@ -42,7 +42,11 @@ angular.module('umbraco.services')
throw "args.term is required";
}
return entityResource.search(args.term, "Member", args.searchFrom).then(function (data) {
var options = {
searchFrom: args.searchFrom
}
return entityResource.search(args.term, "Member", options).then(function (data) {
_.each(data, function (item) {
searchResultFormatter.configureMemberResult(item);
});
@@ -67,7 +71,12 @@ angular.module('umbraco.services')
throw "args.term is required";
}
return entityResource.search(args.term, "Document", args.searchFrom, args.canceler).then(function (data) {
var options = {
searchFrom: args.searchFrom,
ignoreUserStartNodes: args.ignoreUserStartNodes
}
return entityResource.search(args.term, "Document", options, args.canceler).then(function (data) {
_.each(data, function (item) {
searchResultFormatter.configureContentResult(item);
});
@@ -92,7 +101,12 @@ angular.module('umbraco.services')
throw "args.term is required";
}
return entityResource.search(args.term, "Media", args.searchFrom).then(function (data) {
var options = {
searchFrom: args.searchFrom,
ignoreUserStartNodes: args.ignoreUserStartNodes
}
return entityResource.search(args.term, "Media", options).then(function (data) {
_.each(data, function (item) {
searchResultFormatter.configureMediaResult(item);
});

View File

@@ -48,7 +48,14 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
if (configuredStylesheets) {
angular.forEach(configuredStylesheets, function (val, key) {
stylesheets.push(Umbraco.Sys.ServerVariables.umbracoSettings.cssPath + "/" + val + ".css");
if (val.indexOf(Umbraco.Sys.ServerVariables.umbracoSettings.cssPath + "/") === 0) {
// current format (full path to stylesheet)
stylesheets.push(val);
}
else {
// legacy format (stylesheet name only) - must prefix with stylesheet folder and postfix with ".css"
stylesheets.push(Umbraco.Sys.ServerVariables.umbracoSettings.cssPath + "/" + val + ".css");
}
promises.push(stylesheetResource.getRulesByName(val).then(function (rules) {
angular.forEach(rules, function (rule) {
@@ -427,8 +434,8 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
data["rel"] = img.id;
data["data-id"] = img.id;
}
editor.insertContent(editor.dom.createHTML('img', data));
editor.selection.setContent(editor.dom.createHTML('img', data));
$timeout(function () {
var imgElm = editor.dom.get('__mcenew');
@@ -1143,11 +1150,25 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
let self = this;
function getIgnoreUserStartNodes(args) {
var ignoreUserStartNodes = false;
// Most property editors have a "config" property with ignoreUserStartNodes on then
if (args.model.config) {
ignoreUserStartNodes = Object.toBoolean(args.model.config.ignoreUserStartNodes);
}
// EXCEPT for the grid's TinyMCE editor, that one wants to be special and the config is called "configuration" instead
else if (args.model.configuration) {
ignoreUserStartNodes = Object.toBoolean(args.model.configuration.ignoreUserStartNodes);
}
return ignoreUserStartNodes;
}
//create link picker
self.createLinkPicker(args.editor, function (currentTarget, anchorElement) {
var linkPicker = {
currentTarget: currentTarget,
anchors: editorState.current ? self.getAnchorNames(JSON.stringify(editorState.current.properties)) : [],
ignoreUserStartNodes: getIgnoreUserStartNodes(args),
submit: function (model) {
self.insertLinkInEditor(args.editor, model.target, anchorElement);
editorService.close();
@@ -1161,13 +1182,25 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
//Create the insert media plugin
self.createMediaPicker(args.editor, function (currentTarget, userData) {
var startNodeId = userData.startMediaIds.length !== 1 ? -1 : userData.startMediaIds[0];
var startNodeIsVirtual = userData.startMediaIds.length !== 1;
var ignoreUserStartNodes = getIgnoreUserStartNodes(args);
if (ignoreUserStartNodes) {
ignoreUserStartNodes = true;
startNodeId = -1;
startNodeIsVirtual = true;
}
var mediaPicker = {
currentTarget: currentTarget,
onlyImages: true,
showDetails: true,
disableFolderSelect: true,
startNodeId: userData.startMediaIds.length !== 1 ? -1 : userData.startMediaIds[0],
startNodeIsVirtual: userData.startMediaIds.length !== 1,
startNodeId: startNodeId,
startNodeIsVirtual: startNodeIsVirtual,
ignoreUserStartNodes: ignoreUserStartNodes,
submit: function (model) {
self.insertMediaInEditor(args.editor, model.selection[0]);
editorService.close();

View File

@@ -29,6 +29,15 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
return cacheKey;
}
// Adapted from: https://stackoverflow.com/a/2140723
// Please note, we can NOT test this functionality correctly in Phantom because it implements
// the localeCompare method incorrectly: https://github.com/ariya/phantomjs/issues/11063
function invariantEquals(a, b) {
return typeof a === "string" && typeof b === "string"
? a.localeCompare(b, undefined, { sensitivity: "base" }) === 0
: a === b;
}
return {
/** Internal method to return the tree cache */
@@ -165,8 +174,8 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
Umbraco.Sys.ServerVariables.umbracoPlugins.trees &&
angular.isArray(Umbraco.Sys.ServerVariables.umbracoPlugins.trees)) {
var found = _.find(Umbraco.Sys.ServerVariables.umbracoPlugins.trees, function(item) {
return item.alias === treeAlias;
var found = _.find(Umbraco.Sys.ServerVariables.umbracoPlugins.trees, function (item) {
return invariantEquals(item.alias, treeAlias);
});
return found ? found.packageFolder : undefined;
@@ -350,6 +359,9 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
parent.children.splice(parent.children.indexOf(treeNode), 1);
parent.hasChildren = parent.children.length !== 0;
//Notify that the node has been removed
eventsService.emit("treeService.removeNode", { node: treeNode });
},
/**

View File

@@ -365,7 +365,7 @@
action: action,
variants: _.map(displayModel.variants, function(v) {
return {
name: v.name,
name: v.name || "", //if its null/empty,we must pass up an empty string else we get json converter errors
properties: getContentProperties(v.tabs),
culture: v.language ? v.language.culture : null,
publish: v.publish,

View File

@@ -9,7 +9,7 @@
*
* @param {navigationService} navigationService A reference to the navigationService
*/
function NavigationController($scope, $rootScope, $location, $log, $q, $routeParams, $timeout, $cookies, treeService, appState, navigationService, keyboardService, historyService, eventsService, angularHelper, languageResource, contentResource) {
function NavigationController($scope, $rootScope, $location, $log, $q, $routeParams, $timeout, $cookies, treeService, appState, navigationService, keyboardService, historyService, eventsService, angularHelper, languageResource, contentResource, editorState) {
//this is used to trigger the tree to start loading once everything is ready
var treeInitPromise = $q.defer();
@@ -249,6 +249,20 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar
$scope.infiniteMode = args && args.editors.length > 0 ? true : false;
}));
evts.push(eventsService.on("treeService.removeNode", function (e, args) {
//check to see if the current page has been removed
var currentEditorState = editorState.getCurrent()
if (currentEditorState && currentEditorState.id.toString() === args.node.id.toString()) {
//current page is loaded, so navigate to root
var section = appState.getSectionState("currentSection");
$location.path("/" + section);
}
}));
/**
* Based on the current state of the application, this configures the scope variables that control the main tree and language drop down
*/

View File

@@ -117,6 +117,7 @@
@import "components/umb-confirm-action.less";
@import "components/umb-keyboard-shortcuts-overview.less";
@import "components/umb-checkbox-list.less";
@import "components/umb-form-check.less";
@import "components/umb-locked-field.less";
@import "components/umb-tabs.less";
@import "components/umb-load-indicator.less";
@@ -136,10 +137,12 @@
@import "components/umb-iconpicker.less";
@import "components/umb-insert-code-box.less";
@import "components/umb-packages.less";
@import "components/umb-logviewer.less";
@import "components/umb-package-local-install.less";
@import "components/umb-panel-group.less";
@import "components/umb-lightbox.less";
@import "components/umb-avatar.less";
@import "components/umb-readonlyvalue.less";
@import "components/umb-progress-bar.less";
@import "components/umb-querybuilder.less";
@import "components/umb-pagination.less";
@@ -153,11 +156,15 @@
@import "components/umb-number-badge.less";
@import "components/umb-progress-circle.less";
@import "components/umb-stylesheet.less";
@import "components/umb-textstring.less";
@import "components/umb-textarea.less";
@import "components/umb-dropdown.less";
@import "components/umb-range-slider.less";
@import "components/buttons/umb-button.less";
@import "components/buttons/umb-button-group.less";
@import "components/buttons/umb-toggle.less";
@import "components/buttons/umb-toggle-group.less";
@import "components/notifications/umb-notifications.less";
@import "components/umb-file-dropzone.less";
@@ -166,12 +173,12 @@
@import "components/umb-property-file-upload.less";
@import "components/users/umb-user-cards.less";
@import "components/users/umb-user-table.less";
@import "components/users/umb-user-details.less";
@import "components/users/umb-user-group-picker-list.less";
@import "components/users/umb-user-group-preview.less";
@import "components/users/umb-user-preview.less";
@import "components/users/umb-user-picker-list.less";
@import "components/users/umb-permission.less";
// Utilities

View File

@@ -0,0 +1,35 @@
.umb-toggle-group {
.umb-toggle-group-item {
display: flex;
border-bottom: 1px solid @gray-9;
padding: 7px 0;
}
.umb-toggle-group-item:last-of-type {
border-bottom: none;
}
.umb-toggle-group-item__toggle {
padding-right: 20px;
cursor: pointer;
}
.umb-toggle-group-item__content {
display: flex;
flex-direction: column;
justify-content: center;
flex: 1 1 auto;
cursor: pointer;
}
.umb-toggle-group-item--disabled .umb-toggle-group-item__toggle,
.umb-toggle-group-item--disabled .umb-toggle-group-item__content {
cursor: not-allowed;
opacity: 0.8;
}
.umb-toggle-group-item__description {
font-size: 13px;
color: @gray-4;
}
}

View File

@@ -10,47 +10,111 @@
}
}
.umb-toggle:focus .umb-toggle__toggle{
box-shadow: 0 1px 3px fade(@black, 12%), 0 1px 2px fade(@black, 24%);
}
.umb-toggle__handler {
position: absolute;
top: 0;
left: 0;
display: block;
width: 24px;
height: 24px;
background-color: @white;
border-radius: 50px;
transform: rotate(-45deg);
}
.umb-toggle__toggle {
cursor: pointer;
align-items: center;
display: flex;
width: 48px;
height: 24px;
background: @gray-8;
border-radius: 90px;
width: 38px;
height: 18px;
border-radius: 10px;
border: 1px solid @inputBorder;
background-color: @inputBorder;
position: relative;
transition: box-shadow .3s;
transition: background-color 120ms;
.umb-toggle:hover &,
.umb-toggle:focus & {
border-color: @inputBorderFocus;
}
.umb-toggle.umb-toggle--checked & {
border-color: @ui-btn;
background-color: @ui-btn;
&:hover {
background-color: @ui-btn-hover;
}
}
.umb-toggle.umb-toggle--checked:focus & {
border-color: black;
}
}
.umb-toggle--checked .umb-toggle__toggle {
background-color: @green;
.umb-toggle__handler {
position: absolute;
top: 1px;
left: 1px;
display: block;
width: 16px;
height: 16px;
background-color: @white;
border-radius: 8px;
transition: transform 120ms ease-in-out, background-color 120ms;
.umb-toggle.umb-toggle--checked & {
transform: translateX(20px);
background-color: white;
}
}
.umb-toggle--disabled .umb-toggle__toggle {
cursor: not-allowed;
opacity: 0.8;
/* Icons */
.umb-toggle__icon {
position: absolute;
font-size: 12px;
line-height: 1em;
text-decoration: none;
transition: all 0.2s ease;
}
.umb-toggle--checked .umb-toggle__handler {
transform: translate3d(24px, 0, 0) rotate(0);
.umb-toggle__icon--left {
left: 5px;
color: white;
transition: opacity 120ms;
opacity: 0;
// .umb-toggle:hover & {
// color: @ui-btn-hover;
// }
.umb-toggle--checked & {
opacity: 1;
}
.umb-toggle.umb-toggle--checked:hover & {
color: white;
}
}
.umb-toggle__icon--right {
right: 5px;
color: @ui-btn;
transition: opacity 120ms;
.umb-toggle--checked & {
opacity: 0;
}
.umb-toggle:hover & {
color: @ui-btn-hover;
}
}
.umb-toggle.umb-toggle--disabled {
.umb-toggle__toggle {
cursor: not-allowed;
border-color: @gray-5;
}
.umb-toggle__handler {
background-color: @gray-5;
}
}
/* Labels */
.umb-toggle__label {
@@ -64,22 +128,3 @@
.umb-toggle__label--right {
margin-left: 8px;
}
/* Icons */
.umb-toggle__icon {
position: absolute;
line-height: 1em;
text-decoration: none;
transition: all 0.2s ease;
}
.umb-toggle__icon--left {
left: 7px;
color: @white;
}
.umb-toggle__icon--right {
right: 7px;
color: @gray-5;
}

View File

@@ -90,6 +90,9 @@
.umb-editor-header__name-and-description {
margin-right: 20px;
.umb-panel-header-description {
padding: 0 10px;
}
}
.-split-view-active .umb-editor-header__name-and-description {
@@ -166,24 +169,30 @@ a.umb-editor-header__close-split-view:hover {
height: 30px;
text-decoration: none !important;
font-size: 13px;
//color: @gray-4;
color: @ui-action-disgrete-type;
//background-color: @white;
color: @ui-action-discreet-type;
max-width: 50%;
white-space: nowrap;
span {
text-overflow: ellipsis;
overflow: hidden;
}
}
a.umb-variant-switcher__toggle {
transition: color 0.2s ease-in-out;
&:hover {
//background-color: @gray-10;
color: @ui-action-disgrete-type-hover;
color: @ui-action-discreet-type-hover;
.umb-variant-switcher__expand {
color: @ui-action-disgrete-type-hover;
color: @ui-action-discreet-type-hover;
}
}
}
.umb-variant-switcher__expand {
color: @ui-action-disgrete-type;
color: @ui-action-discreet-type;
margin-top: 3px;
margin-left: 5px;
margin-right: -5px;
@@ -195,6 +204,7 @@ a.umb-variant-switcher__toggle {
justify-content: space-between;
align-items: center;
border-bottom: 1px solid @gray-9;
position: relative;
&:hover .umb-variant-switcher__name-wrapper {
}
@@ -246,10 +256,15 @@ a.umb-variant-switcher__toggle {
}
.umb-variant-switcher__split-view {
font-size: 13px;
display: none;
padding: 16px 20px;
font-size: 13px;
display: none;
padding: 16px 20px;
position: absolute;
right: 0;
top: 0;
bottom: 0;
background-color: @white;
&:hover {
background-color: @ui-option-hover;
color: @ui-option-type-hover;

View File

@@ -1,7 +1,11 @@
.umb-editor-sub-header {
padding: 10px 0;
margin-bottom: 10px;
background: @gray-10;
background: @brownGrayLight;
border-left: 5px solid @brownGrayLight;
border-right: 5px solid @brownGrayLight;
margin-left: -5px;
margin-right: -5px;
display: flex;
justify-content: space-between;
margin-top: -10px;
@@ -12,23 +16,32 @@
&.nested {
margin-top: 0;
margin-bottom: 0;
background: @gray-10;
background: @brownGrayLight;
}
}
.umb-editor-sub-header--white {
background-color: white;
border-color: white;
}
.umb-editor-sub-header.--state-selection {
padding-left: 10px;
padding-right: 10px;
background-color: @pinkLight;
border-color: @pinkLight;
border-radius: 3px;
}
.umb-editor-sub-header.-umb-sticky-bar {
box-shadow: 0 6px 3px -3px rgba(0,0,0,.16);
transition: box-shadow 1s;
top: calc(@appHeaderHeight + @editorHeaderHeight);
transition: box-shadow 240ms;
margin-top: 0;
margin-bottom: 0;
top: calc(@appHeaderHeight + @editorHeaderHeight);
.umb-editor--infinityMode & {
top: calc(@editorHeaderHeight);
}
}
.umb-group-builder__property-preview .umb-editor-sub-header {

View File

@@ -1,7 +1,7 @@
.umb-expansion-panel {
background: @white;
border-radius: 3px;
margin-bottom: 16px;
margin-bottom: 20px;
box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.16);
}

View File

@@ -22,7 +22,14 @@
font-size: 14px;
border: none;
position: relative;
margin-bottom: 0;
border-radius: 10px;
margin: 10px;
.close {
top: 0;
right: -6px;
opacity: 0.4;
}
}
.umb-notifications__notification.-extra-padding {

View File

@@ -250,3 +250,11 @@
.form-horizontal .umb-overlay .controls {
margin-left: 0 !important;
}
.umb-overlay .text-error {
color: @formErrorText;
}
.umb-overlay .text-success {
color: @formSuccessText;
}

View File

@@ -11,4 +11,5 @@
animation: fadeIn;
margin-top: 15px;
pointer-events: none;
border-radius: 3px;
}

View File

@@ -166,7 +166,9 @@ body.touch .umb-tree {
}
.umb-tree .umb-tree-node-checked > .umb-tree-item__inner > i[class^="icon-"],
.umb-tree .umb-tree-node-checked > .umb-tree-item__inner > i[class*=" icon-"] {
.umb-tree .umb-tree-node-checked > .umb-tree-item__inner > i[class*=" icon-"],
.umb-tree .umb-tree-node-checked .umb-search-group-item-name > i[class^="icon-"],
.umb-tree .umb-tree-node-checked .umb-search-group-item-name > i[class*=" icon-"] {
font-family: 'icomoon' !important;
color: @green !important;
@@ -226,40 +228,64 @@ body.touch .umb-tree {
}
}
.umb-tree-item__annotation {
&::before {
font-family: 'icomoon';
position: absolute;
bottom: 0;
}
}
.has-unpublished-version, .is-container, .protected {
> .umb-tree-item__inner {
> .umb-tree-item__annotation {
background-color: @white;
border-radius: 50%;
width: 12px;
height: 12px;
position: absolute;
margin-left: 12px;
top: 17px;
.has-unpublished-version > .umb-tree-item__inner > .umb-tree-item__annotation::before {
content: "\e25a";
color: @green;
font-size: 20px;
margin-left: -25px;
&::before {
font-family: 'icomoon';
position: absolute;
top: -4px;
}
}
&:hover > .umb-tree-item__annotation {
background-color: @ui-option-hover;
}
}
&.current > .umb-tree-item__inner > .umb-tree-item__annotation {
background-color: @pinkLight;
}
}
.is-container > .umb-tree-item__inner > .umb-tree-item__annotation::before {
content: "\e04e";
color: @blue;
font-size: 9px;
margin-left: -20px;
margin-left: 2px;
left: 0px;
}
.has-unpublished-version > .umb-tree-item__inner > .umb-tree-item__annotation::before {
content: "\e25a";
color: @green;
font-size: 23px;
margin-left: 16px;
left: -21px;
}
.protected > .umb-tree-item__inner > .umb-tree-item__annotation::before {
content: "\e256";
color: @red;
font-size: 20px;
margin-left: -25px;
font-size: 23px;
margin-left: -3px;
left: -2px;
}
.locked > .umb-tree-item__inner > .umb-tree-item__annotation::before {
content: "\e0a7";
color: @red;
font-size: 9px;
margin-left: -20px;
margin-left: 2px;
left: 0px;
}
.no-access {

View File

@@ -1,7 +1,7 @@
.umb-box {
background: @white;
border-radius: 3px;
margin-bottom: 8px;
margin-bottom: 20px;
box-shadow: 0 1px 1px 0 rgba(0,0,0,.16);
}
@@ -28,4 +28,4 @@
.umb-box-content {
padding: 20px;
}
}

View File

@@ -1,3 +1,6 @@
@checkboxWidth: 15px;
@checkboxHeight: 15px;
.umb-checkbox-list {
list-style: none;
margin-left: 0;

View File

@@ -2,19 +2,21 @@
border: 2px solid @white;
width: 25px;
height: 25px;
background: @gray-7;
border-radius: 50%;
border: 1px solid @gray-7;
border-radius: 3px;
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
color: @white;
color: @gray-7;
cursor: pointer;
font-size: 15px;
}
.umb-checkmark--checked {
background: @green;
background: @ui-active;
border-color: @ui-active;
color: @white;
}
.umb-checkmark--xs {

View File

@@ -13,24 +13,37 @@
user-select: none;
box-shadow: 0 1px 1px 0 rgba(0,0,0,0.16);
border-radius: 3px;
}
.umb-content-grid__item.-selected {
&::before {
content: "";
position: absolute;
z-index:2;
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
border: 2px solid @ui-selected-border;
border-radius: 5px;
box-shadow: 0 0 4px 0 darken(@ui-selected-border, 20), inset 0 0 2px 0 darken(@ui-selected-border, 20);
pointer-events: none;
.umb-content-grid__item {
&.-selected, &:hover {
&::before {
content: "";
position: absolute;
z-index: 2;
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
border: 2px solid @ui-selected-border;
border-radius: 5px;
box-shadow: 0 0 4px 0 darken(@ui-selected-border, 20), inset 0 0 2px 0 darken(@ui-selected-border, 20);
pointer-events: none;
}
}
}
.umb-content-grid__item:hover {
&::before {
opacity: .33;
}
}
.umb-content-grid__item.-selected:hover {
&::before {
opacity: .75;
}
}
.umb-content-grid__icon-container {
@@ -59,7 +72,8 @@
display: inline-flex;
color: @ui-option-type;
&:hover {
&:hover, &:focus {
text-decoration: none;
color:@ui-option-type-hover;
}
}

View File

@@ -0,0 +1,3 @@
.umb-dropdown {
.umb-property-editor--limit-width();
}

View File

@@ -61,6 +61,9 @@
.show-validation .umb-sub-views-nav-item > a.-has-error {
color: @red;
&::after {
background-color: @red;
}
}
.umb-sub-views-nav-item .icon {

View File

@@ -41,13 +41,13 @@
// file select link
.file-select {
font-size: 15px;
color: @ui-action-disgrete-type;
color: @ui-action-discreet-type;
cursor: pointer;
margin-top: 10px;
&:hover {
color: @ui-action-disgrete-type-hover;
color: @ui-action-discreet-type-hover;
text-decoration: none;
}
}

View File

@@ -27,7 +27,12 @@
.umb-folder-grid__folder.-selected {
color:@ui-selected-type;
&:hover {
color:@ui-selected-type-hover;
}
}
.umb-folder-grid__folder.-selected, .umb-folder-grid__folder:hover {
&::before {
content: "";
position: absolute;
@@ -41,9 +46,15 @@
box-shadow: 0 0 4px 0 darken(@ui-selected-border, 20), inset 0 0 2px 0 darken(@ui-selected-border, 20);
pointer-events: none;
}
&:hover {
color:@ui-selected-type-hover;
}
.umb-folder-grid__folder:hover {
&::before {
opacity: .33;
}
}
.umb-folder-grid__folder.-selected:hover {
&::before {
opacity: .75;
}
}

View File

@@ -0,0 +1,136 @@
@checkboxWidth: 16px;
@checkboxHeight: 16px;
.umb-form-check {
display: flex;
flex-wrap: wrap;
align-items: center;
position: relative;
padding: 0;
margin: 0;
min-height: 22px;
line-height: 22px;
cursor: pointer !important;
&__text {
margin: 0 0 0 26px;
position: relative;
top: 0;
}
&__input {
position: absolute;
top: 0;
left: 0;
opacity: 0;
&:checked ~ .umb-form-check__state .umb-form-check__check {
border-color: @ui-option-type;
}
&:focus:checked ~ .umb-form-check .umb-form-check__check,
&:focus ~ .umb-form-check__state .umb-form-check__check {
border-color: @inputBorderFocus;
}
&:checked ~ .umb-form-check__state {
.umb-form-check__check {
// This only happens if the state has a radiobutton modifier
.umb-form-check--radiobutton & {
&:before {
opacity: 1;
transform: scale(1);
}
}
// This only happens if state has the checkbox modifier
.umb-form-check--checkbox & {
&:before {
width: @checkboxWidth;
height: @checkboxHeight;
}
}
}
// This only happens if state has the checkbox modifier
.umb-form-check--checkbox & {
.umb-form-check__icon {
opacity: 1;
}
}
}
}
&__state {
display: flex;
height: 18px;
margin-top: 2px;
position: absolute;
top: 0;
left: 0;
}
&__check {
display: flex;
position: relative;
background: @white;
border: 1px solid @inputBorder;
width: @checkboxWidth;
height: @checkboxHeight;
&:before {
content: "";
background: @ui-option-type;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
}
// This only happens if state has the radiobutton modifier
.umb-form-check--radiobutton & {
border-radius: 100%;
&:before {
width: 10px;
height: 10px;
border-radius: 100%;
opacity: 0;
transform: scale(0);
transition: .15s ease-out;
}
}
// This only happens if state has the checkbox modifier
.umb-form-check--checkbox & {
&:before {
width: 0;
height: 0;
transition: .05s ease-out;
}
}
}
&__icon {
color: @white;
text-align: center;
font-size: 12px;
opacity: 0;
transition: .2s ease-out;
&:before {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
margin: auto;
}
}
&.umb-form-check--disabled {
cursor: not-allowed !important;
opacity: 0.5;
}
}

View File

@@ -128,9 +128,10 @@
position: relative;
margin-bottom: 40px;
padding-top: 10px;
border: 1px solid @grayLighter;
&:hover {
background-color: @grayLighter;
border-color: @grayLight;
}
&[ng-click],
@@ -161,15 +162,16 @@
}
.umb-grid .umb-row .umb-cell-placeholder {
min-height: 130px;
background-color: @gray-10;
border-width: 2px;
min-height: 88px;
border-width: 1px;
border-style: dashed;
border-color: @gray-8;
border-color: @ui-action-discreet-border;
color: @ui-action-discreet-type;
transition: border-color 100ms linear;
&:hover {
border-color: @blueMid;
border-color: @ui-action-discreet-border-hover;
color: @ui-action-discreet-type-hover;
cursor: pointer;
}
}
@@ -207,9 +209,9 @@
}
.umb-grid .cell-tools-add {
color: @ui-action-type;
color: @ui-action-discreet-type;
&:focus, &:hover {
color: @ui-action-type-hover;
color: @ui-action-discreet-type-hover;
text-decoration: none;
}
}
@@ -219,16 +221,18 @@
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: @ui-action-type;
color: @ui-action-discreet-type;
}
.umb-grid .cell-tools-add.-bar {
display: block;
background: @gray-10;
text-align: center;
padding: 5px;
border: 1px dashed @gray-7;
border: 1px dashed @ui-action-discreet-border;
margin: 10px;
&:focus, &:hover {
border-color: @ui-action-discreet-border-hover;
}
}
@@ -249,7 +253,6 @@
.umb-grid .cell-tools-edit {
display: inline-block;
color: @white;
}
.umb-grid .drop-overlay {
@@ -412,36 +415,17 @@
// Row states
.umb-grid .umb-row.-active {
background-color: @ui-action-type;
border-color: @ui-action-type;
.umb-row-title-bar {
cursor: move;
}
.row-tool,
.umb-row-title {
color: @white;
}
.umb-grid-has-config {
color: fade(@white, 66);
}
.umb-cell {
.umb-grid-has-config {
color: fade(@black, 44);
}
}
.umb-cell .umb-cell-content {
border-color: transparent;
}
}
.umb-grid .umb-row.-active-child {
background-color: @gray-10;
.umb-row-title-bar {
cursor: inherit;
}
@@ -449,22 +433,7 @@
.umb-row-title {
color: @gray-3;
}
.row-tool {
color: fade(@black, 23);
}
.umb-grid-has-config {
color: fade(@black, 44);
}
.umb-cell-content.-placeholder {
border-color: @gray-8;
&:hover {
border-color: fade(@gray, 44);
}
}
}
@@ -573,14 +542,13 @@
display: inline-block;
cursor: pointer;
border-radius: 200px;
background: @gray-10;
border: 1px solid @gray-7;
border: 1px solid @ui-action-discreet-border;
margin: 2px;
&:hover, &:hover * {
background: @ui-action-type-hover !important;
background: @ui-action-discreet-type-hover !important;
color: @white !important;
border-color: @ui-action-type-hover !important;
border-color: @ui-action-discreet-border-hover !important;
text-decoration: none;
}
}

View File

@@ -75,7 +75,7 @@
display: flex;
align-items: center;
border-bottom: 1px solid @gray-9;
padding: 10px 15px;
padding: 10px 15px 10px 10px;
}
.umb-group-builder__group-title {
@@ -112,7 +112,7 @@ input.umb-group-builder__group-title-input {
}
input.umb-group-builder__group-title-input:disabled:hover {
border: none;
border-color: transparent;
}
.umb-group-builder__group-title-input:hover {
@@ -135,12 +135,35 @@ input.umb-group-builder__group-title-input:disabled:hover {
margin-left: auto;
}
.umb-group-builder__group-add-property {
min-height: 46px;
margin-right: 45px;
margin-left: 270px;
border-radius: 3px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
border: 1px dashed @gray-7;
background-color: transparent;
color: @ui-action-type;
font-weight: bold;
position: relative;
&:hover {
color:@ui-action-type-hover;
text-decoration: none;
border-color: @ui-active-type-hover;
}
}
/* ---------- PROPERTIES ---------- */
.umb-group-builder__properties {
list-style: none;
margin: 0;
padding: 15px;
padding-right: 5px;
min-height: 35px; // the height of a sortable property
}
@@ -228,6 +251,9 @@ input.umb-group-builder__group-title-input:disabled:hover {
overflow: hidden;
border-color: transparent;
background: transparent;
&:focus {
border-color: @inputBorderFocus;
}
}
.umb-group-builder__property-meta-label textarea.ng-invalid {
@@ -247,6 +273,9 @@ input.umb-group-builder__group-title-input:disabled:hover {
overflow: hidden;
border-color: transparent;
background: transparent;
&:focus {
border-color: @inputBorderFocus;
}
}
.umb-group-builder__property-preview {
@@ -265,21 +294,17 @@ input.umb-group-builder__group-title-input:disabled:hover {
bottom: 0;
left: 0;
right: 0;
background: rgba(0,0,0,0.1);
background: rgba(225,225,225,.5);
transition: opacity 120ms;
}
}
.umb-group-builder__property-preview:hover {
.umb-group-builder__property-preview:not(.-not-clickable):hover {
&::after {
opacity: .8;
opacity: .66;
}
}
.umb-group-builder__property-preview:focus {
outline: none;
}
.umb-group-builder__property-preview.-not-clickable {
cursor: auto;
}
@@ -301,23 +326,54 @@ input.umb-group-builder__group-title-input:disabled:hover {
opacity: 0.8
}
.umb-group-builder__open-settings {
position: absolute;
z-index:1;
top: 0;
bottom:0;
left: 0;
width: 100%;
background-color: transparent;
border: none;
&:focus {
outline:0;
border: 1px solid @inputBorderFocus;
}
}
.umb-group-builder__property-actions {
flex: 0 0 40px;
text-align: center;
margin: 15px 0 0 15px;
flex: 0 0 44px;
text-align: right;
margin-top: 7px;
}
.umb-group-builder__property-action {
margin: 0 0 10px 0;
display: block;
font-size: 18px;
position: relative;
cursor: pointer;
color: @ui-icon;
}
.umb-group-builder__property-action:hover {
color: @ui-icon-hover;
position: relative;
margin: 5px 0;
> button {
border: none;
font-size: 18px;
position: relative;
cursor: pointer;
color: @ui-icon;
margin: 0;
padding: 5px 10px;
width: auto;
overflow: visible;
background: transparent;
line-height: normal;
outline: 0;
-webkit-appearance: none;
&:hover, &:focus {
color: @ui-icon-hover;
}
}
}
.umb-group-builder__property-tags {
@@ -439,7 +495,7 @@ input.umb-group-builder__group-sort-value {
font-size: 14px;
color: @ui-action-type;
&:hover {
&:hover{
text-decoration: none;
color:@ui-action-type-hover;
border-color:@ui-action-border-hover;

View File

@@ -22,11 +22,20 @@ a.umb-list-item:focus {
opacity: 0.6;
}
.umb-list-item--error {
color: @red;
}
.umb-list-item:hover .umb-list-checkbox,
.umb-list-item--selected .umb-list-checkbox {
opacity: 1;
}
.umb-list-item__description {
font-size: 13px;
color: @gray-4;
}
.umb-list-checkbox {
position: absolute;
opacity: 0;
@@ -34,4 +43,4 @@ a.umb-list-item:focus {
.umb-list-checkbox--visible {
opacity: 1;
}
}

View File

@@ -0,0 +1,42 @@
/* PACKAGE DETAILS */
.umb-logviewer {
display: flex;
flex-flow: row wrap;
}
@sidebarwidth: 350px; // Width of sidebar. Ugly hack because of old version of Less
.umb-logviewer__main-content {
flex: 1 1 auto;
margin-right: 20px;
width: calc(~'100%' - ~'@{sidebarwidth}' - ~'20px'); // Make sure that the main content area doesn't gets affected by inline styling
min-width: 500px;
.btn-link {
text-align: left;
}
}
.umb-logviewer__sidebar {
flex: 0 0 @sidebarwidth;
}
@media (max-width: 768px) {
.umb-logviewer {
flex-direction: column;
}
.umb-logviewer__main-content {
flex: 1 1 auto;
width: 100%;
margin-bottom: 30px;
margin-right: 0;
}
.umb-logviewer__sidebar {
flex: 1 1 auto;
width: 100%;
}
}

View File

@@ -38,12 +38,12 @@
}
.umb-media-grid__item.-selected {
//background: @ui-selected;
color:@ui-selected-type;
//border-color: @ui-selected-border;
//box-shadow: 0 2px 8px 0 darken(@ui-selected-border, 20);
.umb-media-grid__item-overlay {
color: @ui-selected-type;
}
}
.umb-media-grid__item.-selected, .umb-media-grid__item:hover {
&::before {
content: "";
position: absolute;
@@ -57,12 +57,16 @@
box-shadow: 0 0 4px 0 darken(@ui-selected-border, 20), inset 0 0 2px 0 darken(@ui-selected-border, 20);
pointer-events: none;
}
.umb-media-grid__item-overlay {
color: @ui-selected-type;
//background: @ui-selected-border;
}
.umb-media-grid__item:hover {
&::before {
opacity: .33;
}
}
.umb-media-grid__item.-selected:hover {
&::before {
opacity: .75;
}
}
.umb-media-grid__item-file-icon > span {
@@ -158,6 +162,9 @@
.umb-media-grid__item:hover .umb-media-grid__item-overlay {
opacity: 1;
i {
text-decoration: none;
}
}
.umb-media-grid__item-name {
@@ -211,7 +218,7 @@
transition: opacity 150ms;
&:hover {
color: @ui-action-disgrete-type-hover;
color: @ui-action-discreet-type-hover;
}
}

View File

@@ -127,6 +127,9 @@
border-radius: 200px;
text-decoration: none !important;
}
.umb-nested-content__icon.umb-nested-content__icon--disabled:hover {
cursor: default;
}
.umb-nested-content__icon:hover,
.umb-nested-content__icon--active

View File

@@ -6,7 +6,7 @@
}
.umb-editor-wrapper .umb-node-preview {
max-width: 66.6%;
.umb-property-editor--limit-width();
}
.umb-node-preview:last-of-type {
@@ -89,21 +89,21 @@
display: flex;
align-items: center;
justify-content: center;
border: 1px dashed @ui-action-disgrete-border;
color: @ui-action-disgrete-type;
border: 1px dashed @ui-action-discreet-border;
color: @ui-action-discreet-type;
font-weight: bold;
padding: 5px 15px;
box-sizing: border-box;
}
.umb-node-preview-add:hover {
color: @ui-action-disgrete-type-hover;
border-color: @ui-action-disgrete-border-hover;
color: @ui-action-discreet-type-hover;
border-color: @ui-action-discreet-border-hover;
text-decoration: none;
}
.umb-editor-wrapper .umb-node-preview-add {
max-width: 66.6%;
.umb-property-editor--limit-width();
}
.umb-overlay,

View File

@@ -261,6 +261,7 @@
.umb-package-details {
display: flex;
flex-flow: row wrap;
}
a.umb-package-details__back-link {
@@ -280,6 +281,7 @@ a.umb-package-details__back-link {
flex: 1 1 auto;
margin-right: 20px;
width: calc(~'100%' - ~'@{sidebarwidth}' - ~'20px'); // Make sure that the main content area doesn't gets affected by inline styling
min-width: 500px;
}
.umb-package-details__sidebar {
@@ -406,7 +408,7 @@ a.umb-package-details__back-link {
.umb-gallery__thumbnail {
flex: 0 1 100px;
border: 1px solid @ui-action-disgrete-border;
border: 1px solid @ui-action-discreet-border;
border-radius: 3px;
margin: 5px;
padding: 10px;
@@ -416,7 +418,7 @@ a.umb-package-details__back-link {
.umb-gallery__thumbnail:hover {
cursor: pointer;
border-color: @ui-action-disgrete-border-hover;
border-color: @ui-action-discreet-border-hover;
}
/* PACKAGE LIST */

View File

@@ -0,0 +1,3 @@
.umb-readonlyvalue {
position:relative;
}

View File

@@ -91,12 +91,39 @@ input.umb-table__input {
.umb-table-body .umb-table-row {
color: @gray-5;
border-top: 1px solid @gray-9;
cursor: pointer;
font-size: 14px;
position: relative;
min-height: 52px;
}
.umb-table-body .umb-table-row.-selectable {
cursor: pointer;
}
.umb-table-row.-selected,
.umb-table-body .umb-table-row.-selectable:hover {
&::before {
content: "";
position: absolute;
z-index:1;
top: 1px;
left: 1px;
right: 1px;
bottom: 1px;
border: 2px solid @ui-selected-border;
pointer-events: none;
}
}
.umb-table-body .umb-table-row.-selectable {
&:hover {
background-color: @ui-option-hover;
&::before {
opacity:.33;
}
}
}
.umb-table-body .umb-table-row.-selected.-selectable {
&:hover {
&::before {
opacity:.66;
}
}
}
@@ -109,9 +136,14 @@ input.umb-table__input {
}
.umb-table-body__link {
color: @ui-option-type;
font-size: 14px;
font-weight: bold;
text-decoration: none;
&:hover {
&:hover, &:focus {
color: @ui-option-type-hover;
text-decoration: underline;
}
}
@@ -122,7 +154,7 @@ input.umb-table__input {
margin: 0 auto;
font-size: 20px;
line-height: 20px;
color: @gray-7;
color: @ui-option-type;
}
.umb-table-body__checkicon,
@@ -135,9 +167,30 @@ input.umb-table__input {
}
.umb-table-body .umb-table__name {
color: @black;
color: @ui-option-type;
font-size: 14px;
font-weight: bold;
a {
color: @ui-option-type;
&:hover, &:focus {
color: @ui-option-type-hover;
text-decoration: underline;
}
}
}
.umb-table-body .umb-table-row.-light {
.umb-table-body__icon {
color: @ui-option-disabled-type;
}
.umb-table__name {
color: @ui-option-disabled-type;
a {
color: @ui-option-disabled-type;
&:hover, &:focus {
color: @ui-option-disabled-type-hover;
}
}
}
}
// Styles of no items in the listview
@@ -150,27 +203,15 @@ input.umb-table__input {
}
// Show checkmark when checked, hide file icon
.umb-table-row--selected {
/*
.umb-table-row.-selected {
.umb-table-body__fileicon {
display: none;
}
.umb-table-body__checkicon {
display: inline-block;
}
*/
&::before {
content: "";
position: absolute;
z-index:1;
top: 1px;
left: 1px;
right: 1px;
bottom: 1px;
border: 2px solid @ui-selected-border;
box-shadow: 0 0 2px 0 fade(@ui-selected-border, 80%);
pointer-events: none;
}
}
// Table Row Styles
@@ -223,6 +264,15 @@ input.umb-table__input {
flex: 0 0 auto !important;
}
.umb-table-cell--small {
flex: .5 .5 1%;
max-width: 12.5%;
}
.umb-table-cell--large {
flex: 1 1 25%;
max-width: 25%;
}
.umb-table-cell--faded {
opacity: 0.4;
}

View File

@@ -0,0 +1,3 @@
.umb-textarea {
.umb-property-editor--limit-width();
}

View File

@@ -0,0 +1,3 @@
.umb-textstring {
.umb-property-editor--limit-width();
}

View File

@@ -1,33 +0,0 @@
.umb-permission {
display: flex;
border-bottom: 1px solid @gray-9;
padding: 7px 0;
}
.umb-permission:last-of-type {
border-bottom: none;
}
.umb-permission__toggle {
padding-right: 20px;
cursor: pointer;
}
.umb-permission__content {
display: flex;
flex-direction: column;
justify-content: center;
flex: 1 1 auto;
cursor: pointer;
}
.umb-permission--disabled .umb-permission__toggle,
.umb-permission--disabled .umb-permission__content {
cursor: not-allowed;
opacity: 0.8;
}
.umb-permission__description {
font-size: 13px;
color: @gray-4;
}

View File

@@ -17,7 +17,11 @@
outline: none;
text-decoration: none !important;
}
.umb-user-card.-selected {
.umb-user-card.-selectable {
cursor: pointer;
}
.umb-user-card.-selected, .umb-user-card.-selectable:hover {
&::before {
content: "";
position: absolute;
@@ -26,12 +30,21 @@
left: -2px;
right: -2px;
bottom: -2px;
border: 2px solid @ui-selected-border;
border-radius: 5px;
box-shadow: 0 0 4px 0 darken(@ui-selected-border, 20), inset 0 0 2px 0 darken(@ui-selected-border, 20);
pointer-events: none;
border: 2px solid @ui-selected-border;
box-shadow: 0 0 4px 0 darken(@ui-selected-border, 20), inset 0 0 2px 0 darken(@ui-selected-border, 20);
}
}
.umb-user-card.-selectable:hover {
&::before {
opacity: .33;
}
}
.umb-user-card.-selected:hover {
&::before {
opacity: .75;
}
}
.umb-user-card__content {
@@ -44,14 +57,18 @@
box-sizing: border-box;
display: flex;
flex-direction: column;
cursor: pointer;
max-width: 100%;
}
.umb-user-card__goToUser {
&:hover {
&:hover, &:focus {
text-decoration: none;
.umb-user-card__name {
text-decoration: underline;
text-decoration: underline;
color: @ui-option-type-hover;
}
.umb-avatar {
border: 1px solid @ui-option-type-hover;
}
}
}

View File

@@ -0,0 +1,71 @@
.umb-user-table {
.umb-user-table-col-avatar {
flex: 0 0 32px;
padding: 15px 0;
.umb-checkmark {
margin-left:5px;
}
}
.umb-table-cell a {
&:hover, &:focus {
.umb-avatar {
border: 1px solid @ui-option-type-hover;
}
}
}
.umb-table-body .umb-table-cell.umb-table__name {
a {
display: flex;
}
}
.umb-table-cell.umb-table__name a {
&:hover, &:focus {
text-decoration: underline;
}
}
.umb-user-table-row {
.umb-checkmark {
visibility: hidden;
}
}
&.-has-selection {
.umb-user-table-row.-selectable {
.umb-checkmark {
visibility: visible;
}
}
}
.umb-user-table-row.-selectable:hover {
.umb-checkmark {
visibility: visible;
}
}
.umb-user-table-row.-selected {
.umb-checkmark {
visibility: visible;
}
&::before {
content: "";
position: absolute;
z-index:1;
top: 1px;
left: 1px;
right: 1px;
bottom: 1px;
border: 2px solid @ui-selected-border;
box-shadow: 0 0 2px 0 fade(@ui-selected-border, 80%);
pointer-events: none;
}
}
}

View File

@@ -533,6 +533,10 @@ div.help {
}
table.domains .help-inline {
color:@red;
}
// INPUT GROUPS
// ------------

View File

@@ -1,8 +1,6 @@
// Listview
// -------------------------
.umb-listview{width: auto !important;}
.umb-listview table {
border: 1px solid @gray-8;
}
@@ -30,7 +28,7 @@
position: absolute;
padding: 5px 8px;
pointer-events: none;
top: 0;
top: 2px;
}
input[type="text"] {
@@ -239,8 +237,8 @@
.list-view-add-layout {
margin-top: 10px;
color: @ui-action-disgrete-type;
border: 1px dashed @ui-action-disgrete-border;
color: @ui-action-discreet-type;
border: 1px dashed @ui-action-discreet-border;
display: flex;
align-items: center;
justify-content: center;
@@ -250,6 +248,6 @@
.list-view-add-layout:hover {
text-decoration: none;
color: @ui-action-disgrete-type-hover;
border-color: @ui-action-disgrete-border-hover;
color: @ui-action-discreet-type-hover;
border-color: @ui-action-discreet-border-hover;
}

View File

@@ -231,13 +231,15 @@ label:not([for]) {
align-items: center;
}
.controls-row > .vertical-align-items > input.umb-property-editor-tiny {
margin-left: 5px;
margin-right: 5px;
.controls-row > .vertical-align-items > input.umb-property-editor-tiny,
.controls-row > .vertical-align-items > input.umb-property-editor-small {
margin-left: 5px;
margin-right: 5px;
}
.controls-row > .vertical-align-items > input.umb-property-editor-tiny:first-child {
margin-left: 0;
.controls-row > .vertical-align-items > input.umb-property-editor-tiny:first-child
.controls-row > .vertical-align-items > input.umb-property-editor-small:first-child {
margin-left: 0;
}
.thumbnails .selected {

View File

@@ -402,6 +402,11 @@
// COMPONENT MIXINS
// --------------------------------------------------
// Limit width of specific property editors
.umb-property-editor--limit-width {
max-width: 800px;
}
// Horizontal dividers
// -------------------------
// Dividers (basically an hr) within dropdowns and nav lists

View File

@@ -52,12 +52,22 @@
bottom: 0px;
left: 0px;
right: 0px;
position: absolute;;
position: absolute;
}
.--notInFront .umb-modalcolumn::after {
content: '';
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
background: rgba(0,0,0,.4);
}
/* re-align loader */
.umb-modal .umb-loader-wrapper, .umb-modalcolumn .umb-loader-wrapper, .umb-dialog .umb-loader-wrapper{
position:relative;
position:relative;
margin: 20px -20px;
}
@@ -96,7 +106,7 @@
.umb-dialog-footer{
position: absolute;
overflow:auto;
text-align: right;
text-align: right;
height: 32px;
left: 0px;
right: 0px;
@@ -116,7 +126,7 @@
.umbracoDialog form{height: 100%;}
/*ensures dialogs doesnt have side-by-side labels*/
.umbracoDialog .controls-row,
.umbracoDialog .controls-row,
.umb-modal .controls-row{margin-left: 0px !important;}
/* modal and umb-modal are used for right.hand dialogs */
@@ -164,7 +174,7 @@
padding: 20px;
background: @white;
border: none;
height: auto;
height: auto;
}
.umb-modal .umb-panel-body{
padding: 0px 20px 0px 20px;
@@ -176,7 +186,7 @@
}
.umb-modal i {
font-size: 20px;
}
}
.umb-modal .breadcrumb {
background: none;
padding: 0

View File

@@ -13,23 +13,25 @@
border: none;
border-radius: 0;
overflow-y: auto;
background-color: @purple-d2;
background-color: @blueNight;
}
.login-overlay__background-image {
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
background-image: url('../img/login.jpg');
width: 100%;
height: 100%;
position: absolute;
opacity: 0.05;
}
.login-overlay__logo {
position: absolute;
top: 22px;
left: 25px;
width: 30px;
height: 30px;
z-index: 1;
}

View File

@@ -346,7 +346,7 @@
justify-content: center;
align-items: center;
background: @white;
border: 1px solid @ui-action-disgrete-border;
border: 1px solid @ui-action-discreet-border;
animation: fadeIn 0.5s;
border-radius: 3px;
width: 50px;
@@ -354,7 +354,7 @@
.icon {
opacity: 0.8;
}
border-color: @ui-action-disgrete-border-hover;
border-color: @ui-action-discreet-border-hover;
}
}

View File

@@ -16,6 +16,75 @@
border-left: 1px solid @gray-10;
}
.date-wrapper__date .flatpickr-input > a {
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
padding: 4px 15px;
box-sizing: border-box;
min-width: 200px;
color: @ui-action-discreet-type;
border: 1px dashed @ui-action-discreet-border;
border-radius: 3px;
&:hover, &:focus {
text-decoration: none;
color: @ui-action-discreet-type-hover;
border-color: @ui-action-discreet-border-hover;
localize {
text-decoration: none;
}
}
}
//----- VARIANTS SCHEDULED PUBLISH ------
.date-wrapper-mini {
display: flex;
flex-direction: row;
}
.date-wrapper-mini__date {
display: flex;
margin-left: 5px;
margin-top: 5px;
margin-bottom: 10px;
&:first-of-type {
margin-left: 0;
}
}
.date-wrapper-mini__date .flatpickr-input > a {
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
padding: 1px 15px;
box-sizing: border-box;
min-width: 180px;
color: @ui-action-discreet-type;
border: 1px dashed @ui-action-discreet-border;
border-radius: 3px;
&:hover, &:focus {
text-decoration: none;
color: @ui-action-discreet-type-hover;
border-color: @ui-action-discreet-border-hover;
localize {
text-decoration: none;
}
}
}
//------------------- HISTORY ------------------
.history {
@@ -71,4 +140,4 @@
.history-line {
display: none;
}
}
}

View File

@@ -4,26 +4,12 @@
// Container styles
// --------------------------------------------------
.umb-property-editor {
@media (max-width: 800px) {
width: 100%;
}
@media (min-width: 800px) {
min-width:66.6%;
}
&-pull {
float:left;
width:66.6%;
}
&-push {
float:right;
}
width: 100%;
}
.umb-property-editor-tiny {
width: 60px;
width: 60px;
&.umb-editor-push {
width:30%;
min-width:0;
@@ -69,10 +55,19 @@
}
}
.umb-property .alert {
border-radius: 3px;
}
//
// Content picker
// --------------------------------------------------
.umb-contentpicker {
.umb-property-editor--limit-width();
}
.umb-contentpicker li a:hover .hover-hide, .umb-contentpicker li a .hover-show{
display: none;
}
@@ -213,7 +208,7 @@
margin: 24px 0 0;
display: flex;
}
&__input {
width: 100%;
&-wrap{
@@ -255,8 +250,8 @@
transition: all 150ms ease-in-out;
&:hover {
color: @ui-action-disgrete-type-hover;
border-color: @ui-action-disgrete-type-hover;
color: @ui-action-discreet-type-hover;
border-color: @ui-action-discreet-type-hover;
}
}
@@ -842,6 +837,8 @@
padding: 10px;
font-size: 13px;
text-shadow: none;
box-sizing: border-box;
.umb-property-editor--limit-width();
.tag {
cursor: default;
@@ -906,13 +903,6 @@
min-height:200px;
}
//
// Nested boolean (e.g. list view bulk action permissions)
// -------------------------------------------------------
.umb-nested-boolean label {margin-bottom: 8px; float: left; width: 320px;}
.umb-nested-boolean label span {float: left; width: 80%;}
.umb-nested-boolean label input[type='checkbox'] {margin-right: 10px; float: left;}
//
// Custom styles of property editors in property preview in document type editor
// -----------------------------------------------------------------------------

View File

@@ -3,6 +3,8 @@
.umb-rte {
position: relative;
.umb-property-editor--limit-width();
.-loading {
position: absolute;
@@ -64,6 +66,13 @@
/* pre-value editor */
.rte-editor-preval .control-group .controls > div > label .mce-ico {
line-height: 20px;
.rte-editor-preval .control-group .controls > div > label {
cursor: pointer !important;
.mce-cmd .checkbox {
padding-right: 0;
}
.mce-ico {
line-height: 20px;
}
}

View File

@@ -11,7 +11,6 @@ ul.sections>li {
display: flex;
justify-content: center;
align-items: center;
padding: 0 20px;
position: relative;
}
@@ -22,27 +21,33 @@ ul.sections>li>a {
align-items: center;
justify-content: center;
position: relative;
padding: 0 10px;
text-decoration: none;
outline: none;
cursor: pointer;
}
ul.sections>li>a .section__name {
border-radius: 3px;
margin-top:1px;
padding: 3px 10px 4px 10px;
opacity: 0.8;
transition: opacity .1s linear;
transition: opacity .1s linear, box-shadow .1s;
}
ul.sections>li>a::after {
content: "";
left: 10px;
right: 10px;
height: 4px;
width: 100%;
bottom: 0;
transform: translateY(4px);
background-color: @pinkLight;
position: absolute;
bottom: -4px;
position: absolute;
border-radius: 3px 3px 0 0;
opacity: 0;
padding: 0 2px;
transition: all .2s linear;
transition: transform 240ms ease-in-out;
}
ul.sections>li.current>a {
@@ -50,16 +55,23 @@ ul.sections>li.current>a {
}
ul.sections>li.current>a::after {
opacity: 1;
bottom: 0;
transform: translateY(0px);
}
ul.sections>li.current>a .section__name,
ul.sections>li>a:hover .section__name,
ul.sections>li>a:hover .section__name,
ul.sections>li>a:focus .section__name {
opacity: 1;
-webkit-font-smoothing: subpixel-antialiased;
}
ul.sections>li>a:focus .section__name {
box-shadow: 0 0 2px @pinkLight, inset 0 0 2px 1px @pinkLight;
}
ul.sections>li>a:hover .section__name,
ul.sections>li.current>a:focus .section__name {
box-shadow: none;
}
/* Sections tray */

View File

@@ -41,8 +41,8 @@
@purple-washed: #F6F3FD;
// UI Colors
@red-d1: #F02E28;// currently used for validation, and is hard coded inline in various html places :/
@red: #D42054;// updated 2019 - should be used as validation! and is already in some cases like the .umb-validation-label
@red-d1: #F02E28;
@red: #D42054;// updated 2019
@red-l1: #e22c60;// updated 2019
@red-l2: #FE8B88;
@red-l3: #FFB2B0;
@@ -112,7 +112,7 @@
@blueExtraDark: #1b264f;// added 2019
@blueLight: #ADD8E6;
@blueNight: #162335;// added 2019
@orange: #f79c37;// updated 2019
//@orange: #f79c37;// updated 2019
@pink: #D93F4C;// #C3325F;// update 2019
@pinkLight: #f5c1bc;// added 2019
@pinkRedLight: #ff8a89;// added 2019
@@ -130,8 +130,12 @@
// -------------------------
@ui-option-type: @blueExtraDark;
@ui-option-hover: @sand-7;
@ui-option-type-hover: @blueMid;
@ui-option-hover: @sand-7;
@ui-option-disabled-type: @gray-6;
@ui-option-disabled-type-hover: @gray-5;
@ui-option-disabled-hover: @sand-7;
//@ui-active: #346ab3;
@ui-active: @pinkLight;
@@ -162,12 +166,12 @@
@ui-action-border: @blueExtraDark;
@ui-action-border-hover: @blueMid;
@ui-action-disgrete: white;
@ui-action-disgrete-hover: @sand-7;
@ui-action-disgrete-type: @blueExtraDark;
@ui-action-disgrete-type-hover: @blueMid;
@ui-action-disgrete-border: @gray-7;
@ui-action-disgrete-border-hover: @blueMid;
@ui-action-discreet: white;
@ui-action-discreet-hover: @sand-7;
@ui-action-discreet-type: @blueExtraDark;
@ui-action-discreet-type-hover: @blueMid;
@ui-action-discreet-border: @gray-7;
@ui-action-discreet-border-hover: @blueMid;
@type-white: @white;
@type-black: @blueNight;
@@ -195,6 +199,16 @@
.turquoise{color: @turquoise;}
.turquoise-d1{color: @turquoise-d1;}
.text-warning {
color: @orange;
}
.text-error {
color: @red;
}
.text-success {
color: @green;
}
//icon colors for tree icons
.color-red, .color-red i{color: @red-d1 !important;}
@@ -508,7 +522,7 @@
@warningBorder: transparent;
@errorText: @white;
@errorBackground: @red-d1;
@errorBackground: @red;
@errorBorder: transparent;
@successText: @white;

View File

@@ -78,7 +78,7 @@
// method to select a search result
function selectResult(evt, result) {
result.selected = result.selected === true ? false : true;
nodeSelectHandler(evt, { event: evt, node: result });
nodeSelectHandler({ event: evt, node: result });
}
//callback when there are search results
@@ -96,7 +96,7 @@
// Mini list view
$scope.selectListViewNode = function (node) {
node.selected = node.selected === true ? false : true;
nodeSelectHandler({}, { node: node });
nodeSelectHandler({ node: node });
};
$scope.closeMiniListView = function () {

View File

@@ -10,7 +10,7 @@
(function() {
"use strict";
function DataTypePicker($scope, dataTypeResource, dataTypeHelper, contentTypeResource, localizationService, editorService) {
function DataTypePicker($scope, $filter, dataTypeResource, dataTypeHelper, contentTypeResource, localizationService, editorService) {
var vm = this;
@@ -119,13 +119,28 @@
$scope.model.itemDetails = null;
if (vm.searchTerm) {
vm.showFilterResult = true;
vm.showTabs = false;
var regex = new RegExp(vm.searchTerm, "i");
vm.filterResult = {
userConfigured: filterCollection(vm.userConfigured, regex),
typesAndEditors: filterCollection(vm.typesAndEditors, regex)
};
} else {
vm.showFilterResult = false;
vm.filterResult = null;
vm.showTabs = true;
}
}
function filterCollection(collection, regex) {
return _.map(_.keys(collection), function (key) {
return {
group: key,
dataTypes: $filter('filter')(collection[key], function (dataType) {
return regex.test(dataType.name) || regex.test(dataType.alias);
})
}
});
}
function showDetailsOverlay(property) {
@@ -201,4 +216,4 @@
angular.module("umbraco").controller("Umbraco.Editors.DataTypePickerController", DataTypePicker);
})();
})();

View File

@@ -79,13 +79,13 @@
</umb-tab-content>
</div>
<!-- FILTER RESULTS -->
<div ng-if="vm.showFilterResult">
<div ng-if="vm.filterResult">
<h5 class="-border-bottom -black"><localize key="contentTypeEditor_reuse"></localize></h5>
<div ng-repeat="(key,value) in vm.userConfigured">
<div ng-if="(value | filter:vm.searchTerm).length > 0">
<h5>{{key}}</h5>
<div ng-repeat="result in vm.filterResult.userConfigured">
<div ng-if="result.dataTypes.length > 0">
<h5>{{result.group}}</h5>
<ul class="umb-card-grid" ng-mouseleave="vm.hideDetailsOverlay()">
<li ng-repeat="dataType in value | orderBy:'name' | filter: vm.searchTerm"
<li ng-repeat="dataType in result.dataTypes | orderBy:'name'"
ng-mouseover="vm.showDetailsOverlay(dataType)"
ng-click="vm.pickDataType(dataType)"
class="-four-in-row">
@@ -101,11 +101,11 @@
</div>
</div>
<h5 class="-border-bottom -black"><localize key="contentTypeEditor_availableEditors"></localize></h5>
<div ng-repeat="(key,value) in vm.typesAndEditors">
<div ng-if="(value | filter:vm.searchTerm).length > 0">
<h5>{{key}}</h5>
<div ng-repeat="result in vm.filterResult.typesAndEditors">
<div ng-if="result.dataTypes.length > 0">
<h5>{{result.group}}</h5>
<ul class="umb-card-grid" ng-mouseleave="vm.hideDetailsOverlay()">
<li ng-repeat="systemDataType in value | orderBy:'name' | filter: vm.searchTerm"
<li ng-repeat="systemDataType in result.dataTypes | orderBy:'name'"
ng-mouseover="vm.showDetailsOverlay(systemDataType)"
ng-click="vm.pickEditor(systemDataType)"
class="-four-in-row">

View File

@@ -10,7 +10,8 @@
(function () {
"use strict";
function DataTypeSettingsController($scope, dataTypeResource, dataTypeHelper, localizationService, notificationsService, overlayService, formHelper) {
function DataTypeSettingsController($scope, dataTypeResource, dataTypeHelper,
localizationService, notificationsService, overlayService, formHelper, eventsService) {
var vm = this;
@@ -99,31 +100,41 @@
}
function submit() {
if (!formHelper.submitForm({ scope: $scope })) {
return;
}
vm.saveButtonState = "busy";
var preValues = dataTypeHelper.createPreValueProps(vm.dataType.preValues);
dataTypeResource.save(vm.dataType, preValues, $scope.model.create).then(function(newDataType) {
$scope.model.dataType = newDataType;
vm.saveButtonState = "success";
dataTypeResource.save(vm.dataType, preValues, $scope.model.create).then(
function(newDataType) {
$scope.model.dataType = newDataType;
var args = { dataType: newDataType };
eventsService.emit("editors.dataTypeSettings.saved", args);
vm.saveButtonState = "success";
if ($scope.model && $scope.model.submit) {
$scope.model.submit($scope.model);
}
}, function(err) {
vm.saveButtonState = "error";
if(err.status === 400) {
if (err.data && (err.data.ModelState)) {
formHelper.handleServerValidation(err.data.ModelState);
if ($scope.model && $scope.model.submit) {
$scope.model.submit($scope.model);
}
}, function(err) {
vm.saveButtonState = "error";
if(err.status === 400) {
if (err.data && (err.data.ModelState)) {
formHelper.handleServerValidation(err.data.ModelState);
for (var e in err.data.ModelState) {
notificationsService.error("Validation", err.data.ModelState[e][0]);
for (var e in err.data.ModelState) {
notificationsService.error("Validation", err.data.ModelState[e][0]);
}
}
}
}
});
);
}

View File

@@ -1,7 +1,8 @@
<div ng-controller="Umbraco.Editors.DataTypeSettingsController as vm">
<umb-editor-view data-element="editor-data-type-settings">
<form novalidate name="dataTypeSettingsForm" val-form-manager>
<form novalidate name="dataTypeSettingsForm" val-form-manager>
<umb-editor-view data-element="editor-data-type-settings">
<umb-editor-header
name="model.title"
@@ -11,7 +12,7 @@
hide-description="true">
</umb-editor-header>
<umb-editor-container>
<umb-editor-container class="form-horizontal">
<umb-load-indicator
ng-if="vm.loadingDataType">
@@ -66,7 +67,8 @@
</umb-editor-footer-content-right>
</umb-editor-footer>
</form>
</umb-editor-view>
</form>
</umb-editor-view>
</div>

View File

@@ -28,9 +28,11 @@ angular.module("umbraco").controller("Umbraco.Editors.LinkPickerController",
searchFromName: null,
showSearch: false,
results: [],
selectedSearchResults: []
selectedSearchResults: [],
ignoreUserStartNodes: dialogOptions.ignoreUserStartNodes
};
$scope.customTreeParams = dialogOptions.ignoreUserStartNodes ? "ignoreUserStartNodes=" + dialogOptions.ignoreUserStartNodes : "";
$scope.showTarget = $scope.model.hideTarget !== true;
// this ensures that we only sync the tree once and only when it's ready
@@ -73,7 +75,11 @@ angular.module("umbraco").controller("Umbraco.Editors.LinkPickerController",
});
// get the content properties to build the anchor name list
contentResource.getById(id).then(function (resp) {
var options = {};
options.ignoreUserStartNodes = dialogOptions.ignoreUserStartNodes;
contentResource.getById(id, options).then(function (resp) {
$scope.anchorValues = tinyMceService.getAnchorNames(JSON.stringify(resp.properties));
$scope.model.target.url = resp.urls[0].text;
});
@@ -119,7 +125,10 @@ angular.module("umbraco").controller("Umbraco.Editors.LinkPickerController",
if (args.node.id < 0) {
$scope.model.target.url = "/";
} else {
contentResource.getById(args.node.id).then(function (resp) {
var options = {};
options.ignoreUserStartNodes = dialogOptions.ignoreUserStartNodes;
contentResource.getById(args.node.id, options).then(function (resp) {
$scope.anchorValues = tinyMceService.getAnchorNames(JSON.stringify(resp.properties));
$scope.model.target.url = resp.urls[0].text;
});
@@ -139,9 +148,17 @@ angular.module("umbraco").controller("Umbraco.Editors.LinkPickerController",
$scope.switchToMediaPicker = function () {
userService.getCurrentUser().then(function (userData) {
var startNodeId = userData.startMediaIds.length !== 1 ? -1 : userData.startMediaIds[0];
var startNodeIsVirtual = userData.startMediaIds.length !== 1;
if (dialogOptions.ignoreUserStartNodes) {
startNodeId = -1;
startNodeIsVirtual = true;
}
var mediaPicker = {
startNodeId: userData.startMediaIds.length !== 1 ? -1 : userData.startMediaIds[0],
startNodeIsVirtual: userData.startMediaIds.length !== 1,
startNodeId: startNodeId,
startNodeIsVirtual: startNodeIsVirtual,
ignoreUserStartNodes: dialogOptions.ignoreUserStartNodes,
submit: function (model) {
var media = model.selection[0];

View File

@@ -68,6 +68,7 @@
search-from-id="{{searchInfo.searchFromId}}"
search-from-name="{{searchInfo.searchFromName}}"
show-search="{{searchInfo.showSearch}}"
ignore-user-start-nodes="{{searchInfo.ignoreUserStartNodes}}"
section="{{section}}">
</umb-tree-search-box>
@@ -84,6 +85,7 @@
section="content"
hideheader="true"
hideoptions="true"
customtreeparams="{{customTreeParams}}"
api="dialogTreeApi"
on-init="onTreeInit()"
enablelistviewexpand="true"

View File

@@ -20,11 +20,13 @@ angular.module("umbraco")
$scope.showDetails = dialogOptions.showDetails;
$scope.multiPicker = (dialogOptions.multiPicker && dialogOptions.multiPicker !== "0") ? true : false;
$scope.startNodeId = dialogOptions.startNodeId ? dialogOptions.startNodeId : -1;
$scope.ignoreUserStartNodes = Object.toBoolean(dialogOptions.ignoreUserStartNodes);
$scope.cropSize = dialogOptions.cropSize;
$scope.lastOpenedNode = localStorageService.get("umbLastOpenedMediaNodeId");
$scope.lockedFolder = true;
$scope.allowMediaEdit = dialogOptions.allowMediaEdit ? dialogOptions.allowMediaEdit : false;
var userStartNodes = [];
var umbracoSettings = Umbraco.Sys.ServerVariables.umbracoSettings;
var allowedUploadFiles = mediaHelper.formatFileTypes(umbracoSettings.allowedUploadFiles);
if ($scope.onlyImages) {
@@ -54,7 +56,8 @@ angular.module("umbraco")
pageSize: 100,
totalItems: 0,
totalPages: 0,
filter: ''
filter: "",
ignoreUserStartNodes: $scope.model.ignoreUserStartNodes
};
//preload selected item
@@ -66,7 +69,7 @@ angular.module("umbraco")
function onInit() {
if ($scope.startNodeId !== -1) {
entityResource.getById($scope.startNodeId, "media")
.then(function (ent) {
.then(function(ent) {
$scope.startNodeId = ent.id;
run();
});
@@ -143,7 +146,7 @@ angular.module("umbraco")
}
};
$scope.gotoFolder = function(folder) {
$scope.gotoFolder = function (folder) {
if (!$scope.multiPicker) {
deselectAllImages($scope.model.selection);
}
@@ -152,8 +155,10 @@ angular.module("umbraco")
folder = { id: -1, name: "Media", icon: "icon-folder" };
}
var options = {};
if (folder.id > 0) {
entityResource.getAncestors(folder.id, "media")
options.ignoreUserStartNodes = $scope.model.ignoreUserStartNodes;
entityResource.getAncestors(folder.id, "media", options)
.then(function(anc) {
$scope.path = _.filter(anc,
function(f) {
@@ -169,13 +174,26 @@ angular.module("umbraco")
$scope.path = [];
}
$scope.lockedFolder = folder.id === -1 && $scope.model.startNodeIsVirtual;
$scope.lockedFolder = (folder.id === -1 && $scope.model.startNodeIsVirtual) || hasFolderAccess(folder) === false;
$scope.currentFolder = folder;
localStorageService.set("umbLastOpenedMediaNodeId", folder.id);
return getChildren(folder.id);
options.ignoreUserStartNodes = $scope.ignoreUserStartNodes;
return getChildren(folder.id, options);
};
function hasFolderAccess(node) {
var nodePath = node.path ? node.path.split(',') : [node.id];
for (var i = 0; i < nodePath.length; i++) {
if (userStartNodes.indexOf(parseInt(nodePath[i])) !== -1)
return true;
}
return false;
}
$scope.clickHandler = function(image, event, index) {
if (image.isFolder) {
if ($scope.disableFolderSelect) {
@@ -299,7 +317,8 @@ angular.module("umbraco")
pageSize: 100,
totalItems: 0,
totalPages: 0,
filter: ''
filter: "",
ignoreUserStartNodes: $scope.model.ignoreUserStartNodes
};
getChildren($scope.currentFolder.id);
}
@@ -367,9 +386,9 @@ angular.module("umbraco")
}
}
function getChildren(id) {
function getChildren(id, options) {
$scope.loading = true;
return mediaResource.getChildren(id)
return mediaResource.getChildren(id, options)
.then(function(data) {
$scope.searchOptions.filter = "";
$scope.images = data.items ? data.items : [];

View File

@@ -79,7 +79,7 @@
// method to select a search result
function selectResult(evt, result) {
result.selected = result.selected === true ? false : true;
nodeSelectHandler(evt, { event: evt, node: result });
nodeSelectHandler({ event: evt, node: result });
}
//callback when there are search results
@@ -96,7 +96,7 @@
// Mini list view
$scope.selectListViewNode = function (node) {
node.selected = node.selected === true ? false : true;
nodeSelectHandler({}, { node: node });
nodeSelectHandler({ node: node });
};
$scope.closeMiniListView = function () {

View File

@@ -17,12 +17,7 @@
<umb-control-group
ng-repeat="(category, permissions) in model.node.permissions"
label="{{category}}">
<umb-permission
ng-repeat="permission in permissions"
name="permission.name"
description="permission.description"
selected="permission.checked">
</umb-permission>
<umb-toggle-group items="permissions"></umb-toggle-group>
</umb-control-group>
</umb-box-content>
</umb-box>

View File

@@ -36,6 +36,7 @@ angular.module("umbraco").controller("Umbraco.Editors.TreePickerController",
selectedSearchResults: []
}
vm.startNodeId = $scope.model.startNodeId;
vm.ignoreUserStartNodes = $scope.model.ignoreUserStartNodes;
//Used for toggling an empty-state message
//Some trees can have no items (dictionary & forms email templates)
vm.hasItems = true;
@@ -171,6 +172,9 @@ angular.module("umbraco").controller("Umbraco.Editors.TreePickerController",
if (vm.startNodeId) {
queryParams["startNodeId"] = $scope.model.startNodeId;
}
if (vm.ignoreUserStartNodes) {
queryParams["ignoreUserStartNodes"] = $scope.model.ignoreUserStartNodes;
}
if (vm.selectedLanguage && vm.selectedLanguage.id) {
queryParams["culture"] = vm.selectedLanguage.culture;
}

View File

@@ -27,7 +27,7 @@
<a ng-click="vm.selectLanguage(language)" ng-repeat="language in vm.languages" href="">{{language.name}}</a>
</div>
</div>
<div class="umb-control-group">
<umb-tree-search-box
ng-if="vm.enableSearh"
@@ -36,6 +36,7 @@
search-from-id="{{vm.searchInfo.searchFromId}}"
search-from-name="{{vm.searchInfo.searchFromName}}"
show-search="{{vm.searchInfo.showSearch}}"
ignore-user-start-nodes="{{vm.ignoreUserStartNodes}}"
section="{{vm.section}}">
</umb-tree-search-box>
</div>

View File

@@ -8,6 +8,10 @@ function ItemPickerOverlay($scope, localizationService) {
$scope.model.title = value;
});
}
if (!$scope.model.orderBy) {
$scope.model.orderBy = "name";
}
}
$scope.selectItem = function(item) {

View File

@@ -12,7 +12,7 @@
</div>
<ul class="umb-card-grid">
<li ng-repeat="availableItem in model.availableItems | compareArrays:model.selectedItems:'alias' | orderBy:'name' | filter:searchTerm"
<li ng-repeat="availableItem in model.availableItems | compareArrays:model.selectedItems:'alias' | orderBy:model.orderBy | filter:searchTerm"
ng-click="selectItem(availableItem)"
class="-three-in-row">
<a class="umb-card-grid-item" href="" title="{{ availableItem.name }}">

Some files were not shown because too many files have changed in this diff Show More