+
+@param {string=} position The loader position ("top", "bottom").
+
+**/
+
+(function() {
+ 'use strict';
+
+ function UmbLoaderDirective() {
+
+ function link(scope, el, attr, ctrl) {
+
+ }
+
+ var directive = {
+ restrict: 'E',
+ replace: true,
+ templateUrl: 'views/components/umb-loader.html',
+ scope: {
+ position: "@?"
+ },
+ link: link
+ };
+
+ return directive;
+ }
+
+ angular.module('umbraco.directives').directive('umbLoader', UmbLoaderDirective);
+
+})();
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbloadindicator.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbloadindicator.directive.js
index 0671770796..c45b8f3f47 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbloadindicator.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbloadindicator.directive.js
@@ -39,7 +39,7 @@ Use this directive to generate a loading indicator.
});
}
-½
+
angular.module("umbraco").controller("My.Controller", Controller);
})();
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbstickybar.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbstickybar.directive.js
index 07e45ff0f7..de6555a05a 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbstickybar.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbstickybar.directive.js
@@ -25,92 +25,64 @@ Use this directive make an element sticky and follow the page when scrolling. `u
function StickyBarDirective() {
- /**
- On initial load, the intersector fires if the grid editor is in the viewport
- This flag is used to suppress the setClass behaviour on the initial load
- **/
- var initial = true;
+ let headerObserver;
/**
Toggle `umb-sticky-bar--active` class on the sticky-bar element
**/
- function setClass(addClass, current) {
- if (!initial) {
- current.classList.toggle('umb-sticky-bar--active', addClass);
- } else {
- initial = false;
- }
- }
+ const setClass = (addClass, current) => current.classList.toggle('umb-sticky-bar--active', addClass);
/**
Inserts two elements in the umbStickyBar parent element
These are used by the IntersectionObserve to calculate scroll position
**/
- function addSentinels(current) {
- ['-top', '-bottom'].forEach(s => {
- const sentinel = document.createElement('div');
- sentinel.classList.add('umb-sticky-sentinel', s);
- current.parentElement.appendChild(sentinel);
- });
- }
-
- /**
- Calls into setClass when the footer sentinel enters/exits the bottom of the container
- Container is the parent element of the umbStickyBar element
- **/
- function observeFooter(current, container) {
- const observer = new IntersectionObserver((records, observer) => {
- let [target, rootBounds, intersected] = [records[0].boundingClientRect, records[0].rootBounds, records[0].intersectionRatio === 1];
-
- if (target.bottom > rootBounds.top && intersected) {
- setClass(true, current);
- }
- if (target.top < rootBounds.top && target.bottom < rootBounds.bottom) {
- setClass(false, current);
- }
- }, {
- threshold: [1],
- root: container
- });
-
- observer.observe(current.parentElement.querySelector('.umb-sticky-sentinel.-bottom'));
- }
+ const addSentinel = current => {
+ const sentinel = document.createElement('div');
+ sentinel.classList.add('umb-sticky-sentinel', '-top');
+ current.parentElement.prepend(sentinel);
+ };
/**
Calls into setClass when the header sentinel enters/exits the top of the container
Container is the parent element of the umbStickyBar element
**/
- function observeHeader(current, container) {
- const observer = new IntersectionObserver((records, observer) => {
+ const observeHeader = (current, container) => {
+ headerObserver = new IntersectionObserver((records, observer) => {
let [target, rootBounds] = [records[0].boundingClientRect, records[0].rootBounds];
- if (target.bottom < rootBounds.top) {
- setClass(true, current);
- }
+ if (rootBounds && target) {
+ if (target.bottom < rootBounds.top) {
+ setClass(true, current);
+ }
- if (target.bottom >= rootBounds.top && target.bottom < rootBounds.bottom) {
- setClass(false, current);
+ if (target.bottom >= rootBounds.top && target.bottom < rootBounds.bottom) {
+ setClass(false, current);
+ }
}
}, {
threshold: [0],
root: container
});
- observer.observe(current.parentElement.querySelector('.umb-sticky-sentinel.-top'));
- }
+ headerObserver.observe(current.parentElement.querySelector('.umb-sticky-sentinel.-top'));
+ };
function link(scope, el, attr, ctrl) {
let current = el[0];
- let container = current.closest('[data-element="editor-container"]');
+ let container = current.closest('.umb-editor-container') || current.closest('.umb-dashboard');
- addSentinels(current);
+ if (container) {
+ addSentinel(current);
+ observeHeader(current, container);
+ }
- observeHeader(current, container);
- observeFooter(current, container);
+ scope.$on('$destroy', () => {
+ headerObserver.disconnect();
+ });
}
- var directive = {
+ const directive = {
restrict: 'A',
link: link
};
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbpropertyfileupload.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbpropertyfileupload.directive.js
index e5bdd3ca78..6360b429b9 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbpropertyfileupload.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbpropertyfileupload.directive.js
@@ -176,6 +176,11 @@
}
function getThumbnail(file) {
+
+ if (file.extension === 'svg') {
+ return file.fileName;
+ }
+
if (!file.isImage) {
return null;
}
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/users/changepassword.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/users/changepassword.directive.js
index f8dbefa5d7..97eb2bf708 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/components/users/changepassword.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/users/changepassword.directive.js
@@ -1,167 +1,172 @@
(function () {
- 'use strict';
+ 'use strict';
- function ChangePasswordController($scope) {
+ function ChangePasswordController($scope) {
- function resetModel(isNew) {
- //the model config will contain an object, if it does not we'll create defaults
- //NOTE: We will not support doing the password regex on the client side because the regex on the server side
- //based on the membership provider cannot always be ported to js from .net directly.
- /*
- {
- hasPassword: true/false,
- requiresQuestionAnswer: true/false,
- enableReset: true/false,
- enablePasswordRetrieval: true/false,
- minPasswordLength: 10
- }
- */
+ var vm = this;
- $scope.showReset = false;
+ vm.$onInit = onInit;
+ vm.$onDestroy = onDestroy;
+ vm.doChange = doChange;
+ vm.cancelChange = cancelChange;
+ vm.showOldPass = showOldPass;
+ vm.showCancelBtn = showCancelBtn;
- //set defaults if they are not available
- if ($scope.config.disableToggle === undefined) {
- $scope.config.disableToggle = false;
- }
- if ($scope.config.hasPassword === undefined) {
- $scope.config.hasPassword = false;
- }
- if ($scope.config.enablePasswordRetrieval === undefined) {
- $scope.config.enablePasswordRetrieval = true;
- }
- if ($scope.config.requiresQuestionAnswer === undefined) {
- $scope.config.requiresQuestionAnswer = false;
- }
- //don't enable reset if it is new - that doesn't make sense
- if (isNew === "true") {
- $scope.config.enableReset = false;
- }
- else if ($scope.config.enableReset === undefined) {
- $scope.config.enableReset = true;
- }
-
- if ($scope.config.minPasswordLength === undefined) {
- $scope.config.minPasswordLength = 0;
- }
-
- //set the model defaults
- if (!angular.isObject($scope.passwordValues)) {
- //if it's not an object then just create a new one
- $scope.passwordValues = {
- newPassword: null,
- oldPassword: null,
- reset: null,
- answer: null
- };
- }
- else {
- //just reset the values
+ var unsubscribe = [];
+
+ function resetModel(isNew) {
+ //the model config will contain an object, if it does not we'll create defaults
+ //NOTE: We will not support doing the password regex on the client side because the regex on the server side
+ //based on the membership provider cannot always be ported to js from .net directly.
+ /*
+ {
+ hasPassword: true/false,
+ requiresQuestionAnswer: true/false,
+ enableReset: true/false,
+ enablePasswordRetrieval: true/false,
+ minPasswordLength: 10
+ }
+ */
+
+ vm.showReset = false;
+
+ //set defaults if they are not available
+ if (vm.config.disableToggle === undefined) {
+ vm.config.disableToggle = false;
+ }
+ if (vm.config.hasPassword === undefined) {
+ vm.config.hasPassword = false;
+ }
+ if (vm.config.enablePasswordRetrieval === undefined) {
+ vm.config.enablePasswordRetrieval = true;
+ }
+ if (vm.config.requiresQuestionAnswer === undefined) {
+ vm.config.requiresQuestionAnswer = false;
+ }
+ //don't enable reset if it is new - that doesn't make sense
+ if (isNew === "true") {
+ vm.config.enableReset = false;
+ }
+ else if (vm.config.enableReset === undefined) {
+ vm.config.enableReset = true;
+ }
+
+ if (vm.config.minPasswordLength === undefined) {
+ vm.config.minPasswordLength = 0;
+ }
+
+ //set the model defaults
+ if (!angular.isObject(vm.passwordValues)) {
+ //if it's not an object then just create a new one
+ vm.passwordValues = {
+ newPassword: null,
+ oldPassword: null,
+ reset: null,
+ answer: null
+ };
+ }
+ else {
+ //just reset the values
+
+ if (!isNew) {
+ //if it is new, then leave the generated pass displayed
+ vm.passwordValues.newPassword = null;
+ vm.passwordValues.oldPassword = null;
+ }
+ vm.passwordValues.reset = null;
+ vm.passwordValues.answer = null;
+ }
+
+ //the value to compare to match passwords
+ if (!isNew) {
+ vm.passwordValues.confirm = "";
+ }
+ else if (vm.passwordValues.newPassword && vm.passwordValues.newPassword.length > 0) {
+ //if it is new and a new password has been set, then set the confirm password too
+ vm.passwordValues.confirm = vm.passwordValues.newPassword;
+ }
- if (!isNew) {
- //if it is new, then leave the generated pass displayed
- $scope.passwordValues.newPassword = null;
- $scope.passwordValues.oldPassword = null;
}
- $scope.passwordValues.reset = null;
- $scope.passwordValues.answer = null;
- }
- //the value to compare to match passwords
- if (!isNew) {
- $scope.passwordValues.confirm = "";
- }
- else if ($scope.passwordValues.newPassword && $scope.passwordValues.newPassword.length > 0) {
- //if it is new and a new password has been set, then set the confirm password too
- $scope.passwordValues.confirm = $scope.passwordValues.newPassword;
- }
+ //when the scope is destroyed we need to unsubscribe
+ function onDestroy() {
+ for (var u in unsubscribe) {
+ unsubscribe[u]();
+ }
+ }
+
+ function onInit() {
+ //listen for the saved event, when that occurs we'll
+ //change to changing = false;
+ unsubscribe.push($scope.$on("formSubmitted", function () {
+ if (vm.config.disableToggle === false) {
+ vm.changing = false;
+ }
+ }));
+
+ unsubscribe.push($scope.$on("formSubmitting", function () {
+ //if there was a previously generated password displaying, clear it
+ if (vm.changing && vm.passwordValues) {
+ vm.passwordValues.generatedPassword = null;
+ }
+ else if (!vm.changing) {
+ //we are not changing, so the model needs to be null
+ vm.passwordValues = null;
+ }
+ }));
+
+ resetModel(vm.isNew);
+
+ //if there is no password saved for this entity , it must be new so we do not allow toggling of the change password, it is always there
+ //with validators turned on.
+ vm.changing = vm.config.disableToggle === true || !vm.config.hasPassword;
+
+ //we're not currently changing so set the model to null
+ if (!vm.changing) {
+ vm.passwordValues = null;
+ }
+ }
+
+ function doChange() {
+ resetModel();
+ vm.changing = true;
+ //if there was a previously generated password displaying, clear it
+ vm.passwordValues.generatedPassword = null;
+ vm.passwordValues.confirm = null;
+ };
+
+ function cancelChange() {
+ vm.changing = false;
+ //set model to null
+ vm.passwordValues = null;
+ };
+
+ function showOldPass() {
+ return vm.config.hasPassword &&
+ !vm.config.allowManuallyChangingPassword &&
+ !vm.config.enablePasswordRetrieval && !vm.showReset;
+ };
+
+ // TODO: I don't think we need this or the cancel button, this can be up to the editor rendering this component
+ function showCancelBtn() {
+ return vm.config.disableToggle !== true && vm.config.hasPassword;
+ };
}
- resetModel($scope.isNew);
-
- //if there is no password saved for this entity , it must be new so we do not allow toggling of the change password, it is always there
- //with validators turned on.
- $scope.changing = $scope.config.disableToggle === true || !$scope.config.hasPassword;
-
- //we're not currently changing so set the model to null
- if (!$scope.changing) {
- $scope.passwordValues = null;
- }
-
- $scope.doChange = function () {
- resetModel();
- $scope.changing = true;
- //if there was a previously generated password displaying, clear it
- $scope.passwordValues.generatedPassword = null;
- $scope.passwordValues.confirm = null;
+ var component = {
+ templateUrl: 'views/components/users/change-password.html',
+ controller: ChangePasswordController,
+ controllerAs: 'vm',
+ bindings: {
+ isNew: "<",
+ passwordValues: "=", //TODO: Do we need bi-directional vals?
+ config: "=" //TODO: Do we need bi-directional vals?
+ //TODO: Do we need callbacks?
+ }
};
- $scope.cancelChange = function () {
- $scope.changing = false;
- //set model to null
- $scope.passwordValues = null;
- };
-
- var unsubscribe = [];
-
- //listen for the saved event, when that occurs we'll
- //change to changing = false;
- unsubscribe.push($scope.$on("formSubmitted", function () {
- if ($scope.config.disableToggle === false) {
- $scope.changing = false;
- }
- }));
- unsubscribe.push($scope.$on("formSubmitting", function () {
- //if there was a previously generated password displaying, clear it
- if ($scope.changing && $scope.passwordValues) {
- $scope.passwordValues.generatedPassword = null;
- }
- else if (!$scope.changing) {
- //we are not changing, so the model needs to be null
- $scope.passwordValues = null;
- }
- }));
-
- //when the scope is destroyed we need to unsubscribe
- $scope.$on('$destroy', function () {
- for (var u in unsubscribe) {
- unsubscribe[u]();
- }
- });
-
- $scope.showOldPass = function () {
- return $scope.config.hasPassword &&
- !$scope.config.allowManuallyChangingPassword &&
- !$scope.config.enablePasswordRetrieval && !$scope.showReset;
- };
-
- // TODO: I don't think we need this or the cancel button, this can be up to the editor rendering this directive
- $scope.showCancelBtn = function () {
- return $scope.config.disableToggle !== true && $scope.config.hasPassword;
- };
-
- }
-
- function ChangePasswordDirective() {
-
- var directive = {
- restrict: 'E',
- replace: true,
- templateUrl: 'views/components/users/change-password.html',
- controller: 'Umbraco.Editors.Users.ChangePasswordDirectiveController',
- scope: {
- isNew: "=?",
- passwordValues: "=",
- config: "="
- }
- };
-
- return directive;
-
- }
-
- angular.module('umbraco.directives').controller('Umbraco.Editors.Users.ChangePasswordDirectiveController', ChangePasswordController);
- angular.module('umbraco.directives').directive('changePassword', ChangePasswordDirective);
+ angular.module('umbraco.directives').component('changePassword', component);
})();
diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/contenttype.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/contenttype.resource.js
index 4e4c8d2eb5..64accc18c1 100644
--- a/src/Umbraco.Web.UI.Client/src/common/resources/contenttype.resource.js
+++ b/src/Umbraco.Web.UI.Client/src/common/resources/contenttype.resource.js
@@ -16,7 +16,7 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter, loca
'Failed to retrieve count');
},
- getAvailableCompositeContentTypes: function (contentTypeId, filterContentTypes, filterPropertyTypes) {
+ getAvailableCompositeContentTypes: function (contentTypeId, filterContentTypes, filterPropertyTypes, isElement) {
if (!filterContentTypes) {
filterContentTypes = [];
}
@@ -27,7 +27,8 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter, loca
var query = {
contentTypeId: contentTypeId,
filterContentTypes: filterContentTypes,
- filterPropertyTypes: filterPropertyTypes
+ filterPropertyTypes: filterPropertyTypes,
+ isElement: isElement
};
return umbRequestHelper.resourcePromise(
diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js
index a910629f4a..9cf1181cfa 100644
--- a/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js
+++ b/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js
@@ -104,21 +104,26 @@ function entityResource($q, $http, umbRequestHelper) {
*
* @param {Int} id Id of node to return the public url to
* @param {string} type Object type name
+ * @param {string} culture Culture
* @returns {Promise} resourcePromise object containing the url.
*
*/
- getUrl: function (id, type) {
+ getUrl: function (id, type, culture) {
if (id === -1 || id === "-1") {
return "";
}
+ if (!culture) {
+ culture = "";
+ }
+
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"entityApiBaseUrl",
"GetUrl",
- [{ id: id }, {type: type }])),
+ [{ id: id }, {type: type }, {culture: culture }])),
'Failed to retrieve url for id:' + id);
},
@@ -133,7 +138,7 @@ function entityResource($q, $http, umbRequestHelper) {
* ##usage
*
* //get media by id
- * entityResource.getEntityById(0, "Media")
+ * entityResource.getById(0, "Media")
* .then(function(ent) {
* var myDoc = ent;
* alert('its here!');
@@ -204,7 +209,7 @@ function entityResource($q, $http, umbRequestHelper) {
* ##usage
*
* //Get templates for ids
- * entityResource.getEntitiesByIds( [1234,2526,28262], "Template")
+ * entityResource.getByIds( [1234,2526,28262], "Template")
* .then(function(templateArray) {
* var myDoc = contentArray;
* alert('they are here!');
diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/logviewer.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/logviewer.resource.js
index b52021ed38..d2d008640d 100644
--- a/src/Umbraco.Web.UI.Client/src/common/resources/logviewer.resource.js
+++ b/src/Umbraco.Web.UI.Client/src/common/resources/logviewer.resource.js
@@ -7,64 +7,44 @@
**/
function logViewerResource($q, $http, umbRequestHelper) {
+ /**
+ * verb => 'get', 'post',
+ * method => API method to call
+ * params => additional data to send
+ * error => error message when things go wrong...
+ */
+ const request = (verb, method, params, error) =>
+ umbRequestHelper.resourcePromise(
+ (verb === 'GET' ?
+ $http.get(umbRequestHelper.getApiUrl("logViewerApiBaseUrl", method) + (params ? params : '')) :
+ $http.post(umbRequestHelper.getApiUrl("logViewerApiBaseUrl", method), params)),
+ error);
+
//the factory object returned
return {
- getNumberOfErrors: function (startDate, endDate) {
- return umbRequestHelper.resourcePromise(
- $http.get(
- umbRequestHelper.getApiUrl(
- "logViewerApiBaseUrl",
- "GetNumberOfErrors")+ '?startDate='+startDate+ '&endDate='+ endDate ),
- 'Failed to retrieve number of errors in logs');
- },
+ getNumberOfErrors: (startDate, endDate) =>
+ request('GET', 'GetNumberOfErrors', '?startDate=' + startDate + '&endDate=' + endDate, 'Failed to retrieve number of errors in logs'),
- getLogLevelCounts: function (startDate, endDate) {
- return umbRequestHelper.resourcePromise(
- $http.get(
- umbRequestHelper.getApiUrl(
- "logViewerApiBaseUrl",
- "GetLogLevelCounts")+ '?startDate='+startDate+ '&endDate='+ endDate ),
- 'Failed to retrieve log level counts');
- },
+ getLogLevel: () =>
+ request('GET', 'GetLogLevel', null, 'Failed to retrieve log level'),
- getMessageTemplates: function (startDate, endDate) {
- return umbRequestHelper.resourcePromise(
- $http.get(
- umbRequestHelper.getApiUrl(
- "logViewerApiBaseUrl",
- "GetMessageTemplates")+ '?startDate='+startDate+ '&endDate='+ endDate ),
- 'Failed to retrieve log templates');
- },
+ getLogLevelCounts: (startDate, endDate) =>
+ request('GET', 'GetLogLevelCounts', '?startDate=' + startDate + '&endDate=' + endDate, 'Failed to retrieve log level counts'),
- getSavedSearches: function () {
- return umbRequestHelper.resourcePromise(
- $http.get(
- umbRequestHelper.getApiUrl(
- "logViewerApiBaseUrl",
- "GetSavedSearches")),
- 'Failed to retrieve saved searches');
- },
+ getMessageTemplates: (startDate, endDate) =>
+ request('GET', 'GetMessageTemplates', '?startDate=' + startDate + '&endDate=' + endDate, 'Failed to retrieve log templates'),
- postSavedSearch: function (name, query) {
- return umbRequestHelper.resourcePromise(
- $http.post(
- umbRequestHelper.getApiUrl(
- "logViewerApiBaseUrl",
- "PostSavedSearch"), { 'name': name, 'query': query }),
- 'Failed to add new saved search');
- },
+ getSavedSearches: () =>
+ request('GET', 'GetSavedSearches', null, 'Failed to retrieve saved searches'),
- deleteSavedSearch: function (name, query) {
- return umbRequestHelper.resourcePromise(
- $http.post(
- umbRequestHelper.getApiUrl(
- "logViewerApiBaseUrl",
- "DeleteSavedSearch"), { 'name': name, 'query': query }),
- 'Failed to delete saved search');
- },
+ postSavedSearch: (name, query) =>
+ request('POST', 'PostSavedSearch', { 'name': name, 'query': query }, 'Failed to add new saved search'),
- getLogs: function (options) {
+ deleteSavedSearch: (name, query) =>
+ request('POST', 'DeleteSavedSearch', { 'name': name, 'query': query }, 'Failed to delete saved search'),
+
+ getLogs: options => {
var defaults = {
pageSize: 100,
@@ -83,7 +63,6 @@ function logViewerResource($q, $http, umbRequestHelper) {
//now copy back to the options we will use
options = defaults;
-
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
@@ -93,15 +72,8 @@ function logViewerResource($q, $http, umbRequestHelper) {
'Failed to retrieve common log messages');
},
- canViewLogs: function (startDate, endDate) {
- return umbRequestHelper.resourcePromise(
- $http.get(
- umbRequestHelper.getApiUrl(
- "logViewerApiBaseUrl",
- "GetCanViewLogs") + '?startDate='+startDate+ '&endDate='+ endDate ),
- 'Failed to retrieve state if logs can be viewed');
- }
-
+ canViewLogs: (startDate, endDate) =>
+ request('GET', 'GetCanViewLogs', '?startDate=' + startDate + '&endDate=' + endDate, 'Failed to retrieve state if logs can be viewed')
};
}
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js
index 732f682082..200e61ee96 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js
@@ -1,4 +1,4 @@
-
+
/**
* @ngdoc service
* @name umbraco.services.contentEditingHelper
@@ -53,6 +53,12 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, editorSt
}
if (args.showNotifications === undefined) {
args.showNotifications = true;
+ }
+ // needed for infinite editing to create new items
+ if (args.create === undefined) {
+ if ($routeParams.create) {
+ args.create = true;
+ }
}
if (args.softRedirect === undefined) {
//when true, the url will change but it won't actually re-route
@@ -61,6 +67,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, editorSt
args.softRedirect = false;
}
+
var self = this;
//we will use the default one for content if not specified
@@ -68,7 +75,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, editorSt
if (formHelper.submitForm({ scope: args.scope, action: args.action })) {
- return args.saveMethod(args.content, $routeParams.create, fileManager.getFiles(), args.showNotifications)
+ return args.saveMethod(args.content, args.create, fileManager.getFiles(), args.showNotifications)
.then(function (data) {
formHelper.resetForm({ scope: args.scope });
@@ -484,7 +491,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, editorSt
var savedVariants = [];
if (origContent.variants) {
isContent = true;
- //it's contnet so assign the variants as they exist
+ //it's content so assign the variants as they exist
origVariants = origContent.variants;
savedVariants = savedContent.variants;
}
@@ -510,7 +517,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, editorSt
//special case for content, don't sync this variant if it wasn't tagged
//for saving in the first place
- if (!origVariant.save) {
+ if (isContent && !origVariant.save) {
continue;
}
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js b/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js
index 72957e1c72..ad565412d9 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js
@@ -261,7 +261,7 @@ When building a custom infinite editor view you can use the same components as a
*/
unbindKeyboardShortcuts();
- // set flag so we know when the editor is open in "infinie mode"
+ // set flag so we know when the editor is open in "infinite mode"
editor.infiniteMode = true;
editors.push(editor);
@@ -331,13 +331,17 @@ When building a custom infinite editor view you can use the same components as a
* @methodOf umbraco.services.editorService
*
* @description
- * Opens a media editor in infinite editing, the submit callback returns the updated content item
+ * Opens a content editor in infinite editing, the submit callback returns the updated content item
* @param {Object} editor rendering options
* @param {String} editor.id The id of the content item
* @param {Boolean} editor.create Create new content item
* @param {Function} editor.submit Callback function when the publish and close button is clicked. Returns the editor model object
* @param {Function} editor.close Callback function when the close button is clicked.
- *
+ * @param {String} editor.parentId If editor.create is true, provide parentId for the creation of the content item
+ * @param {String} editor.documentTypeAlias If editor.create is true, provide document type alias for the creation of the content item
+ * @param {Boolean} editor.allowSaveAndClose If editor is being used in infinite editing allows the editor to close when the save action is performed
+ * @param {Boolean} editor.allowPublishAndClose If editor is being used in infinite editing allows the editor to close when the publish action is performed
+ *
* @returns {Object} editor object
*/
function contentEditor(editor) {
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/mediahelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/mediahelper.service.js
index 9350af1c47..c8acdec353 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/mediahelper.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/mediahelper.service.js
@@ -378,7 +378,7 @@ function mediaHelper(umbRequestHelper, $log) {
getFileExtension: function (filePath) {
if (!filePath) {
- return false;
+ return null;
}
var lowered = filePath.toLowerCase();
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js
index e61bd38bc0..5578c7a609 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js
@@ -233,17 +233,22 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
//this would be for a theme other than inlite
toolbar: args.toolbar.join(" "),
+
//these are for the inlite theme to work
insert_toolbar: toolbars.insertToolbar,
selection_toolbar: toolbars.selectionToolbar,
body_class: 'umb-rte',
+
//see http://archive.tinymce.com/wiki.php/Configuration:cache_suffix
cache_suffix: "?umb__rnd=" + Umbraco.Sys.ServerVariables.application.cacheBuster,
//this is used to style the inline macro bits, sorry hard coding this form now since we don't have a standalone
//stylesheet to load in for this with only these styles (the color is @pinkLight)
- content_style: ".mce-content-body .umb-macro-holder { border: 3px dotted #f5c1bc; padding: 7px; display: block; margin: 3px; } .umb-rte .mce-content-body .umb-macro-holder.loading {background: url(assets/img/loader.gif) right no-repeat; background-size: 18px; background-position-x: 99%;}"
+ content_style: ".mce-content-body .umb-macro-holder { border: 3px dotted #f5c1bc; padding: 7px; display: block; margin: 3px; } .umb-rte .mce-content-body .umb-macro-holder.loading {background: url(assets/img/loader.gif) right no-repeat; background-size: 18px; background-position-x: 99%;}",
+
+ // This allows images to be pasted in & stored as Base64 until they get uploaded to server
+ paste_data_images: true
};
if (tinyMceConfig.customConfig) {
diff --git a/src/Umbraco.Web.UI.Client/src/installer/installer.service.js b/src/Umbraco.Web.UI.Client/src/installer/installer.service.js
index 50b9f2f3c0..f6f162f04f 100644
--- a/src/Umbraco.Web.UI.Client/src/installer/installer.service.js
+++ b/src/Umbraco.Web.UI.Client/src/installer/installer.service.js
@@ -31,7 +31,7 @@ angular.module("umbraco.install").factory('installerService', function ($rootSco
"At least 4 people have the Umbraco logo tattooed on them",
"'Umbraco' is the Danish name for an allen key",
"Umbraco has been around since 2005, that's a looong time in IT",
- "More than 600 people from all over the world meet each year in Denmark in May for our annual conference CodeGarden",
+ "More than 700 people from all over the world meet each year in Denmark in May for our annual conference CodeGarden",
"While you are installing Umbraco someone else on the other side of the planet is probably doing it too",
"You can extend Umbraco without modifying the source code using either JavaScript or C#",
"Umbraco has been installed in more than 198 countries"
diff --git a/src/Umbraco.Web.UI.Client/src/less/belle.less b/src/Umbraco.Web.UI.Client/src/less/belle.less
index bd1cdd5b4f..b0b7e80762 100644
--- a/src/Umbraco.Web.UI.Client/src/less/belle.less
+++ b/src/Umbraco.Web.UI.Client/src/less/belle.less
@@ -112,7 +112,7 @@
@import "components/umb-editor-navigation-item.less";
@import "components/umb-editor-sub-views.less";
@import "components/editor/subheader/umb-editor-sub-header.less";
-@import "components/umb-flatpickr.less";
+@import "components/umb-date-time-picker.less";
@import "components/umb-grid-selector.less";
@import "components/umb-child-selector.less";
@import "components/umb-group-builder.less";
@@ -124,6 +124,7 @@
@import "components/umb-form-check.less";
@import "components/umb-locked-field.less";
@import "components/umb-tabs.less";
+@import "components/umb-loader.less";
@import "components/umb-load-indicator.less";
@import "components/umb-breadcrumbs.less";
@import "components/umb-media-grid.less";
diff --git a/src/Umbraco.Web.UI.Client/src/less/canvas-designer.less b/src/Umbraco.Web.UI.Client/src/less/canvas-designer.less
index 7440a5723a..4db2e434d2 100644
--- a/src/Umbraco.Web.UI.Client/src/less/canvas-designer.less
+++ b/src/Umbraco.Web.UI.Client/src/less/canvas-designer.less
@@ -163,7 +163,8 @@ a, a:hover{
background-clip: padding-box;
}
-.dropdown-menu > li > a {
+.dropdown-menu > li > a,
+.dropdown-menu > li > button {
display: block;
padding: 3px 20px;
clear: both;
@@ -174,7 +175,12 @@ a, a:hover{
cursor:pointer;
}
-.dropdown-menu > li > a:hover, .dropdown-menu > li > a:focus, .dropdown-submenu:hover > a, .dropdown-submenu:focus > a {
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus,
+.dropdown-menu > li > button:hover,
+.dropdown-menu > li > button:focus,
+.dropdown-submenu:hover > a,
+.dropdown-submenu:focus > a {
color: #000000;
background: #e4e0dd;
}
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/application/umb-drawer.less b/src/Umbraco.Web.UI.Client/src/less/components/application/umb-drawer.less
index 8c3b059a94..064ad67438 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/application/umb-drawer.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/application/umb-drawer.less
@@ -194,7 +194,6 @@
.umb-help-list-item__title {
font-size: 14px;
display: block;
- margin-left: 26px;
}
.umb-help-list-item__description {
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/application/umb-tour.less b/src/Umbraco.Web.UI.Client/src/less/components/application/umb-tour.less
index 315cd91dbd..33a723a3f7 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/application/umb-tour.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/application/umb-tour.less
@@ -1,8 +1,12 @@
-.umb-tour__loader {
- background: @white;
- z-index: @zindexTourModal;
+.umb-loader-wrapper.umb-tour__loader {
+ margin: 0;
position: fixed;
- height: 5px;
+ z-index: @zindexTourModal;
+
+ .umb-loader {
+ background-color: @white;
+ height: 5px;
+ }
}
.umb-tour__pulse {
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button-group.less b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button-group.less
index e40282cb58..0465881387 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button-group.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button-group.less
@@ -9,6 +9,7 @@
left: auto;
}
+.umb-button-group__sub-buttons>li>button,
.umb-button-group__sub-buttons>li>a {
display: flex;
}
@@ -20,7 +21,7 @@
}
.umb-button-group__toggle {
- border-radius: 0px @baseBorderRadius @baseBorderRadius 0;
+ border-radius: 0 @baseBorderRadius @baseBorderRadius 0;
border-left: 1px solid rgba(0,0,0,0.09);
margin-left: -2px;
padding-left: 10px;
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/editor.less b/src/Umbraco.Web.UI.Client/src/less/components/editor.less
index 52dd7ea678..85fcc249f9 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/editor.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/editor.less
@@ -74,8 +74,11 @@
}
.umb-editor-header__back {
- color: @gray-6;
- margin-bottom: 1px;
+ background: transparent;
+ border: 0;
+ color: @gray-6;
+ margin: 0 0 1px 0;
+ padding: 0;
transition: color 0.1s ease-in-out;
}
@@ -373,14 +376,3 @@ a.umb-variant-switcher__toggle {
margin-right: auto;
padding-right: 10px;
}
-
-/* Confirm */
-.umb-editor-confirm {
- background-color: @white;
- padding: 20px;
- position: absolute;
- left: 0;
- bottom: 0;
- z-index: 10;
- box-shadow: 0 -3px 12px 0px rgba(0,0,0,0.16);
-}
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/editor/subheader/umb-editor-sub-header.less b/src/Umbraco.Web.UI.Client/src/less/components/editor/subheader/umb-editor-sub-header.less
index 6cf3598638..649aa89055 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/editor/subheader/umb-editor-sub-header.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/editor/subheader/umb-editor-sub-header.less
@@ -1,14 +1,11 @@
.umb-editor-sub-header {
padding: 10px 0;
- margin-bottom: 10px;
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;
+ margin: -10px -5px 10px;
position: relative;
top: 0;
box-sizing: border-box;
@@ -34,30 +31,25 @@
[umb-sticky-bar] {
transition: box-shadow 240ms;
- margin-top: 0;
- margin-bottom: 0;
position:sticky;
z-index: 99;
&.umb-sticky-bar--active {
box-shadow: 0 6px 3px -3px rgba(0,0,0,.16);
}
+
+ .umb-dashboard__content & {
+ top:-20px; // umb-dashboard__content has 20px padding - offset here prevents sticky position from firing when page loads
+ }
}
.umb-sticky-sentinel {
- position: absolute;
- left: 0;
- width: 100%;
pointer-events: none;
+ z-index: 5050;
&.-top {
- top:0px;
height:1px;
- }
-
- &.-bottom {
- bottom:50px;
- height:10px;
+ transform:translateY(-10px);
}
}
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-editor.less b/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-editor.less
index a9d879ab7f..3665f7d8fd 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-editor.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-editor.less
@@ -17,7 +17,7 @@
z-index: @zIndexEditor;
}
-.umb-editor--infinityMode {
+.umb-editor--infiniteMode {
transform: none;
will-change: transform;
transition: transform 400ms ease-in-out;
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/notifications/umb-notifications.less b/src/Umbraco.Web.UI.Client/src/less/components/notifications/umb-notifications.less
index 7f04fef9a9..5d78bed2a3 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/notifications/umb-notifications.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/notifications/umb-notifications.less
@@ -1,5 +1,5 @@
.umb-notifications {
- z-index: 1000;
+ z-index: 1100;
position: absolute;
bottom: @editorFooterHeight;
left: 0;
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-actions.less b/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-actions.less
index d6e792de73..0c231830de 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-actions.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-actions.less
@@ -94,6 +94,7 @@
font-size: 14px;
color: @black;
margin-left: 10px;
+ text-align: left;
}
small {
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree-item.less b/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree-item.less
index 8f0b55f9ed..8945d15ec6 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree-item.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree-item.less
@@ -39,17 +39,10 @@
// Loading Animation
// ------------------------
- .l {
+ .umb-tree-item__loader {
width: 100%;
- height: 2px;
- overflow: hidden;
position: absolute;
- left: 0;
- bottom: -1px;
-
- div {
- .umb-loader;
- }
+ margin: 0;
}
.umb-tree-item__label {
@@ -57,19 +50,20 @@
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
- flex: 1 0 auto;
+ flex: 1 1 auto;
}
}
// active is equivilant to selected, its the item that is begin affected by the actions performed in the right-click-dialog.
.umb-tree-item.active > .umb-tree-item__inner {
+ border-color: @ui-selected-border;
+ box-shadow: 0 0 2px 0 fade(@ui-selected-border, 80%);
color: @ui-selected-type;
+
a {
color: @ui-selected-type;
}
-
- border-color: @ui-selected-border;
- box-shadow: 0 0 2px 0 fade(@ui-selected-border, 80%);
+
&::before {
content: "";
position: absolute;
@@ -79,8 +73,10 @@
bottom: 0;
border: 2px solid fade(white, 80%);
}
+
&:hover {
color: @ui-selected-type-hover;
+
a {
color: @ui-selected-type-hover;
}
@@ -88,7 +84,6 @@
}
.umb-tree-item.current > .umb-tree-item__inner {
-
background: @ui-active;
color:@ui-active-type;
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree.less b/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree.less
index 5c54232200..93850656f0 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree.less
@@ -33,12 +33,6 @@
display: none;
}
}
-
- //loader defaults
- .umb-loader {
- height: 10px;
- margin: 10px 10px 10px 10px;
- }
.search-subtitle {
color: @gray-7;
@@ -72,8 +66,7 @@ body.touch .umb-tree {
overflow: hidden;
display: flex;
flex-wrap: nowrap;
- align-items: center;
-
+ align-items: center;
border:2px solid transparent;
color: @ui-option-type;
@@ -183,7 +176,6 @@ body.touch .umb-tree {
&:hover {
background: @btnBackgroundHighlight;
}
-
// NOTE - We're having to repeat ourselves here due to an .sr-only class appearing in umbraco/lib/font-awesome/css/font-awesome.min.css
&.sr-only--hoverable:hover,
&.sr-only--focusable:focus {
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-box.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-box.less
index c0e91e28c2..1fe59ab9dd 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/umb-box.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-box.less
@@ -1,12 +1,14 @@
+@boxUnit: 10px;
+
.umb-box {
background: @white;
border-radius: 3px;
- margin-bottom: 20px;
+ margin-bottom: @boxUnit * 2;
box-shadow: 0 1px 1px 0 rgba(0,0,0,.16);
}
.umb-box-header {
- padding: 10px 20px;
+ padding: @boxUnit @boxUnit * 2;
border-bottom: 1px solid @gray-9;
display: flex;
align-items: center;
@@ -27,5 +29,19 @@
}
.umb-box-content {
- padding: 20px;
+ padding: @boxUnit * 2;
}
+
+// allow side-by-side boxes
+.umb-box-row {
+ margin-left:-@boxUnit;
+ margin-right:-@boxUnit;
+ display:flex;
+ justify-content: space-around;
+
+ .umb-box {
+ margin-left:@boxUnit;
+ margin-right:@boxUnit;
+ flex:1;
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-content-grid.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-content-grid.less
index 84cfe04263..f27e1e4ec8 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/umb-content-grid.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-content-grid.less
@@ -105,6 +105,7 @@
.umb-content-grid__details-value {
display: inline-block;
word-break: break-word;
+ margin-left: 3px;
}
.umb-content-grid__checkmark {
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-flatpickr.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-date-time-picker.less
similarity index 90%
rename from src/Umbraco.Web.UI.Client/src/less/components/umb-flatpickr.less
rename to src/Umbraco.Web.UI.Client/src/less/components/umb-date-time-picker.less
index 8cdcc8b877..2df0cc5fd8 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/umb-flatpickr.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-date-time-picker.less
@@ -1,4 +1,4 @@
-.flatpickr-calendar.flatpickr-calendar {
+.flatpickr-calendar {
border-radius: @baseBorderRadius;
box-shadow: 0 5px 10px 0 rgba(0,0,0,0.16);
}
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation-item.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation-item.less
index e6b3fdbfa9..8a8032ee16 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation-item.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation-item.less
@@ -2,12 +2,16 @@
position: relative;
display: block;
}
+
+.umb-sub-views-nav-item__action,
.umb-sub-views-nav-item > a {
+ background: transparent;
text-align: center;
cursor: pointer;
display: block;
padding: 4px 10px 0 10px;
min-width: 70px;
+ border: 0 none;
border-right: 1px solid @gray-9;
box-sizing: border-box;
display: flex;
@@ -19,6 +23,7 @@
color: @ui-active-type;
+ &:focus,
&:hover {
color: @ui-active-type-hover !important;
}
@@ -37,18 +42,23 @@
}
}
+.umb-sub-views-nav-item__action:focus,
+.umb-sub-views-nav-item__action:active,
.umb-sub-views-nav-item > a:active {
.box-shadow(~"inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05)");
}
+.umb-sub-views-nav-item__action:focus,
.umb-sub-views-nav-item > a:focus {
outline: none;
}
+.umb-sub-views-nav-item__action:hover,
+.umb-sub-views-nav-item__action:focus,
.umb-sub-views-nav-item > a:hover,
.umb-sub-views-nav-item > a:focus {
text-decoration: none;
}
-
+.umb-sub-views-nav-item__action.is-active,
.umb-sub-views-nav-item > a.is-active {
color: @ui-light-active-type;
@@ -59,6 +69,7 @@
}
}
+.umb-sub-views-nav-item__action.-has-error,
.show-validation .umb-sub-views-nav-item > a.-has-error {
color: @red;
&::after {
@@ -114,11 +125,19 @@
// center align horizontal
left: 50%;
transform: translateX(-50%);
-
- visibility:hidden;
opacity: 0;
- transition: visibility 0s 500ms, opacity 250ms 250ms;
+ transition: opacity 250ms 250ms;
}
+
+// Currently Edge 18 does unfortunately not support :focus-within so for now we will use the "old" behavior - Support is coming with the upcoming release of Edge 76
+// See https://caniuse.com/#search=focus-within
+@supports (-ms-ime-align:auto) {
+ .umb-sub-views-nav-item__anchor_dropdown {
+ visibility: hidden;
+ transition: visibility 0 500ms, opacity 250ms 250ms;
+ }
+}
+
.umb-sub-views-nav-item__anchor_dropdown li a {
border-left: 4px solid transparent;
}
@@ -126,12 +145,20 @@
border-left-color: @ui-selected-border;
}
+.umb-sub-views-nav-item:focus-within .umb-sub-views-nav-item__anchor_dropdown,
.umb-sub-views-nav-item:hover .umb-sub-views-nav-item__anchor_dropdown {
visibility:visible;
opacity: 1;
- transition: visibility 0s 0s, opacity 20ms 0s;
+ transition: opacity 20ms 0;
}
+// Currently Edge 18 does unfortunately not support :focus-within so for now we will use the "old" behavior - Support is coming with the upcoming release of Edge 76
+// See https://caniuse.com/#search=focus-within
+@supports (-ms-ime-align:auto) {
+ .umb-sub-views-nav-item:hover .umb-sub-views-nav-item__anchor_dropdown {
+ transition: visibility 0 0, opacity 20ms 0;
+ }
+}
// --------------------------------
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-file-dropzone.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-file-dropzone.less
index 5071091fcc..b5d8c3cced 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/umb-file-dropzone.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-file-dropzone.less
@@ -14,15 +14,18 @@
margin: 0 0 20px 0;
position: relative;
transition: height 0.8s;
+
.illustration {
width: 300px;
}
+
&.is-small {
height: 100px;
.illustration {
width: 200px;
}
}
+
&.drag-over {
border: 1px dashed @gray-1;
}
@@ -35,15 +38,19 @@
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
+ display: flex;
+ flex-direction: column;
}
// file select link
.file-select {
+ background: transparent;
+ border: 0;
+ padding: 0;
font-size: 15px;
color: @ui-action-discreet-type;
cursor: pointer;
-
margin-top: 10px;
&:hover {
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-grid.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-grid.less
index 2eafe9b3d7..ba0b32bb0d 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/umb-grid.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-grid.less
@@ -408,7 +408,19 @@
margin-bottom: 10px;
}
+.umb-grid .umb-editor-preview {
+ position: relative;
+ .umb-editor-preview-overlay {
+ cursor: pointer;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 1;
+ }
+}
// Active states
// -------------------------
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-layout-selector.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-layout-selector.less
index cf407b667f..cdc6cfcb63 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/umb-layout-selector.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-layout-selector.less
@@ -4,6 +4,7 @@
}
.umb-layout-selector__active-layout {
+ background: transparent;
box-sizing: border-box;
border: 1px solid @inputBorder;
cursor: pointer;
@@ -33,6 +34,7 @@
}
.umb-layout-selector__dropdown-item {
+ background: transparent;
padding: 5px;
margin: 3px 5px;
display: flex;
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-loader.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-loader.less
new file mode 100644
index 0000000000..260710ce72
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-loader.less
@@ -0,0 +1,42 @@
+// Loading Animation
+// ------------------------
+
+.umb-loader {
+ background-color: @blue;
+ margin-top: 0;
+ margin-left: -100%;
+ animation-name: bounce_loadingProgressG;
+ animation-duration: 1s;
+ animation-iteration-count: infinite;
+ animation-timing-function: linear;
+ width: 100%;
+ height: 2px;
+}
+
+@keyframes bounce_loadingProgressG {
+ 0% {
+ margin-left: -100%;
+ }
+
+ 100% {
+ margin-left: 100%;
+ }
+}
+
+.umb-loader-wrapper {
+ position: absolute;
+ right: 0;
+ left: 0;
+ margin: 10px 0;
+ overflow: hidden;
+}
+
+.umb-loader-wrapper.-top {
+ top: 0;
+ bottom: auto;
+}
+
+.umb-loader-wrapper.-bottom {
+ top: auto;
+ bottom: 0;
+}
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-media-grid.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-media-grid.less
index 68973b4c7c..8c8e4b101c 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/umb-media-grid.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-media-grid.less
@@ -21,15 +21,9 @@
margin: 10px;
position: relative;
- //overflow: hidden;
-
- user-select: none;
-
+ user-select: none;
cursor: pointer;
-
box-shadow: 0 1px 1px 0 rgba(0,0,0,.2);
- //border: 2px solid transparent;
-
transition: box-shadow 150ms ease-in-out;
}
@@ -69,16 +63,34 @@
}
}
-.umb-media-grid__item-file-icon > span {
- color: @white;
- background: @gray-4;
- padding: 1px 3px;
- font-size: 10px;
- line-height: 130%;
- display: block;
- margin-top: -30px;
- margin-left: -10px;
- position: relative;
+.umb-media-grid__item-file-icon {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ transform: translate(-50%,-50%);
+ position: absolute;
+ top: 45%;
+ left: 50%;
+
+ .umb-media-grid__item-icon {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ color: @gray-4;
+ font-size: 50px !important;
+ }
+
+ > span {
+ color: @white;
+ background: @ui-active;
+ padding: 1px 3px;
+ font-size: 10px;
+ line-height: 130%;
+ display: block;
+ margin-top: -15px;
+ margin-left: 5px;
+ position: relative;
+ }
}
.umb-media-grid__item:hover {
@@ -86,34 +98,27 @@
}
.umb-media-grid__item-image {
- //max-width: 100% !important;
- //height: auto;
position: relative;
-
object-fit: contain;
height: 100%;
}
.umb-media-grid__item-image-placeholder {
width: 100%;
- //max-width: 100%;
- //height: auto;
position: relative;
-
object-fit: contain;
height: 100%;
}
.umb-media-grid__image-background {
content: "";
- background: url("../img/checkered-background.png");
- background-repeat: repeat;
opacity: 0.5;
top: 0;
left: 0;
bottom: 0;
right: 0;
position: absolute;
+ .checkeredBackground();
}
.umb-media-grid__item-overlay {
@@ -139,19 +144,6 @@
}
}
-/*
-.umb-media-grid__item.-file .umb-media-grid__item-overlay {
- opacity: 1;
- color: @gray-4;
- background: @white;
-}
-
-.umb-media-grid__item.-file:hover .umb-media-grid__item-overlay,
-.umb-media-grid__item.-file.-selected .umb-media-grid__item-overlay {
- color: @white;
- background: @blueExtraDark;
-}
-*/
.umb-media-grid__info {
margin-right: 5px;
}
@@ -173,33 +165,7 @@
text-overflow: ellipsis;
}
-.umb-media-grid__item-icon {
- color: @gray-4;
- position: absolute;
- top: 45%;
- left: 50%;
- font-size: 40px !important;
- transform: translate(-50%,-50%);
-}
-/*
-.umb-media-grid__checkmark {
- position: absolute;
- z-index: 2;
- top: 10px;
- left: 10px;
- width: 26px;
- height: 26px;
- border: 2px solid @white;
- background: @green;
- border-radius: 50px;
- box-sizing: border-box;
- display: flex;
- justify-content: center;
- align-items: center;
- color: @white;
- transition: background 100ms;
-}
-*/
+
.umb-media-grid__edit {
position: absolute;
opacity: 0;
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-packages.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-packages.less
index f704dd48e2..16457787a3 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/umb-packages.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-packages.less
@@ -264,12 +264,16 @@
flex-flow: row wrap;
}
-a.umb-package-details__back-link {
+.umb-package-details__back-action {
font-weight: bold;
color: @black;
+ padding: 0;
+ border: 0;
+ background-color: transparent;
}
-.umb-package-details__back-link:hover {
+.umb-package-details__back-action:focus,
+.umb-package-details__back-action:hover {
color: @gray-4;
text-decoration: none;
}
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less
index f387b6540b..27b64f85fb 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less
@@ -295,7 +295,11 @@ input.umb-table__input {
.umb-table__row-expand {
font-size: 12px;
text-decoration: none;
- color: @black;
+ color: @gray-4;
+
+ &:hover {
+ color: @black;
+ }
}
.umb-table__row-expand--hidden {
diff --git a/src/Umbraco.Web.UI.Client/src/less/dashboards/healthcheck.less b/src/Umbraco.Web.UI.Client/src/less/dashboards/healthcheck.less
index 449cc4066b..b3af476406 100644
--- a/src/Umbraco.Web.UI.Client/src/less/dashboards/healthcheck.less
+++ b/src/Umbraco.Web.UI.Client/src/less/dashboards/healthcheck.less
@@ -22,15 +22,18 @@
.umb-healthcheck-group {
display: flex;
flex-wrap: wrap;
- flex-direction: column;
- background: @white;
+ flex-direction: column;
+ align-items: center;
+ background: @white;
+ border: 0;
border-radius: 3px;
padding: 20px;
box-sizing: border-box;
text-align: center;
box-shadow: 0 1px 1px 0 rgba(0,0,0,0.16);
height: 100%;
- box-sizing: border-box;
+ box-sizing: border-box;
+ width: 100%;
}
.umb-healthcheck-group:hover {
diff --git a/src/Umbraco.Web.UI.Client/src/less/installer.less b/src/Umbraco.Web.UI.Client/src/less/installer.less
index 798252c394..8090b971fc 100644
--- a/src/Umbraco.Web.UI.Client/src/less/installer.less
+++ b/src/Umbraco.Web.UI.Client/src/less/installer.less
@@ -13,6 +13,9 @@
@import "../../lib/bootstrap/less/thumbnails.less";
@import "../../lib/bootstrap/less/media.less";
+// Umbraco Components
+@import "components/umb-loader.less";
+
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
display: none !important;
@@ -165,45 +168,17 @@ input.ng-dirty.ng-invalid{border-color: #b94a48; color: #b94a48;}
opacity:1;
}
+.umb-installer-loader {
+ margin: 0;
+ width: 0;
+ z-index: 777;
-.umb-loader{
- background-color: @white;
- margin-top:0;
- margin-left:-100%;
- animation-name:bounce_loadingProgressG;
- animation-duration:1s;
- animation-iteration-count:infinite;
- animation-timing-function:linear;
- width:100%;
- height: 5px;
-}
-
-@keyframes bounce_loadingProgressG{
- 0%{
- margin-left:-100%;
- }
- 100%{
- margin-left:100%;
+ .umb-loader {
+ background-color: @white;
+ height: 5px;
}
}
-//loader defaults
-.umb-loader-container, .umb-loader-done{
- height: 3px;
- position: absolute;
- bottom: 0;
- left: 0;
- overflow: hidden;
- width: 0%;
- z-index: 777;
-}
-
-.umb-loader-done{
- right: 0%;
- background: @white;
-}
-
-
.permissions-report {
overflow:auto;
height:320px;
diff --git a/src/Umbraco.Web.UI.Client/src/less/main.less b/src/Umbraco.Web.UI.Client/src/less/main.less
index 9f9bbce310..920fcdb1eb 100644
--- a/src/Umbraco.Web.UI.Client/src/less/main.less
+++ b/src/Umbraco.Web.UI.Client/src/less/main.less
@@ -486,42 +486,6 @@ table thead a {
color:@green;
}
-// Loading Animation
-// ------------------------
-
-.umb-loader{
- background-color: @blue;
- margin-top:0;
- margin-left:-100%;
- animation-name:bounce_loadingProgressG;
- animation-duration:1s;
- animation-iteration-count:infinite;
- animation-timing-function:linear;
- width:100%;
- height:2px;
-}
-
-@keyframes bounce_loadingProgressG{
- 0%{
- margin-left:-100%;
- }
- 100%{
- margin-left:100%;
- }
-}
-
-.umb-loader-wrapper {
- position: absolute;
- right: 0;
- left: 0;
- margin: 10px 0;
- overflow: hidden;
-}
-
-.umb-loader-wrapper.-bottom {
- bottom: 0;
-}
-
// Helpers
.strong {
@@ -592,13 +556,3 @@ input[type=checkbox]:checked + .input-label--small {
background-color: @green-l3;
text-decoration: none;
}
-
-.visuallyhidden{
- position: absolute !important;
- clip: rect(1px, 1px, 1px, 1px);
- padding:0 !important;
- border:0 !important;
- height: 1px !important;
- width: 1px !important;
- overflow: hidden;
-}
diff --git a/src/Umbraco.Web.UI.Client/src/less/mixins.less b/src/Umbraco.Web.UI.Client/src/less/mixins.less
index ce35097658..60132edab5 100644
--- a/src/Umbraco.Web.UI.Client/src/less/mixins.less
+++ b/src/Umbraco.Web.UI.Client/src/less/mixins.less
@@ -397,11 +397,19 @@
}
}
-
+.checkeredBackground(@backgroundColor: #eee, @fillColor: #000, @fillOpacity: 0.25) {
+ background-image: url('data:image/svg+xml;charset=utf-8,\
+ ');
+ background-color: @backgroundColor;
+ background-size: 10px 10px;
+ background-repeat: repeat;
+}
// COMPONENT MIXINS
// --------------------------------------------------
-
// Limit width of specific property editors
.umb-property-editor--limit-width {
max-width: 800px;
diff --git a/src/Umbraco.Web.UI.Client/src/less/navs.less b/src/Umbraco.Web.UI.Client/src/less/navs.less
index a2710fab6c..5b97464e31 100644
--- a/src/Umbraco.Web.UI.Client/src/less/navs.less
+++ b/src/Umbraco.Web.UI.Client/src/less/navs.less
@@ -237,7 +237,27 @@
color: @ui-option-type;
}
-.dropdown-menu > li > a:hover, .dropdown-menu > li > a:focus, .dropdown-submenu:hover > a, .dropdown-submenu:focus > a {
+.dropdown-menu > li > button {
+ background: transparent;
+ border: 0;
+ padding: 8px 20px;
+ color: @ui-option-type;
+ display: block;
+ clear: both;
+ font-weight: normal;
+ line-height: 20px;
+ white-space: nowrap;
+ cursor:pointer;
+ width: 100%;
+ text-align: left;
+}
+
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus,
+.dropdown-menu > li > button:hover,
+.dropdown-menu > li > button:focus,
+.dropdown-submenu:hover > a,
+.dropdown-submenu:focus > a {
color: @ui-option-type-hover;
background: @ui-option-hover;
}
diff --git a/src/Umbraco.Web.UI.Client/src/less/property-editors.less b/src/Umbraco.Web.UI.Client/src/less/property-editors.less
index 1c91be2c8f..3328d9cf02 100644
--- a/src/Umbraco.Web.UI.Client/src/less/property-editors.less
+++ b/src/Umbraco.Web.UI.Client/src/less/property-editors.less
@@ -1,11 +1,8 @@
-@checkered-background: url(../img/checkered-background.png);
-
//
// Container styles
// --------------------------------------------------
-.umb-property-editor {
+.umb-property-editor {
width: 100%;
- position:relative;
}
.umb-property-editor-tiny {
@@ -366,7 +363,6 @@
padding: 5px;
margin: 5px;
background: @white;
- //border: 1px solid @gray-10;
max-width: 100%;
}
.umb-mediapicker {
@@ -377,14 +373,9 @@
}
-
-
.umb-mediapicker .umb-sortable-thumbnails li {
flex-direction: column;
}
-/*.umb-mediapicker .umb-sortable-thumbnails li.add-wrapper {
- padding: 0px;
-}*/
.umb-sortable-thumbnails li:hover a {
display: flex;
@@ -393,11 +384,11 @@
}
.umb-sortable-thumbnails li img {
- max-width:100%;
- max-height:100%;
- margin:auto;
- display:block;
- background-image: @checkered-background;
+ max-width: 100%;
+ max-height: 100%;
+ margin: auto;
+ display: block;
+ .checkeredBackground();
}
.umb-sortable-thumbnails li .trashed {
@@ -411,31 +402,40 @@
.umb-sortable-thumbnails .umb-icon-holder {
text-align: center;
-}
+ display: flex;
+ flex-direction: column;
+ align-items: center;
-.umb-sortable-thumbnails .umb-icon-holder .icon {
- font-size: 40px;
- line-height: 50px;
- color: @gray-3;
- display: block;
-}
+ .file-icon {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
-.umb-sortable-thumbnails .umb-icon-holder .file-icon > span {
- color: @white;
- background: @gray-4;
- padding: 1px 3px;
- font-size: 10px;
- line-height: 130%;
- display: block;
- margin-top: -30px;
- width: 2em;
-}
+ > .icon {
+ font-size: 50px;
+ line-height: 50px;
+ color: @gray-4;
+ display: block;
+ text-align: center;
+ }
-.umb-sortable-thumbnails .umb-icon-holder .file-icon + small {
- display: block;
- margin-top: 1em;
-}
+ > span {
+ color: @white;
+ background: @ui-active;
+ padding: 1px 3px;
+ font-size: 10px;
+ line-height: 130%;
+ display: block;
+ margin-top: -25px;
+ min-width: 2em;
+ }
+ & + small {
+ display: block;
+ margin-top: 1em;
+ }
+ }
+}
.umb-sortable-thumbnails .umb-sortable-thumbnails__wrapper {
width: 124px;
@@ -487,8 +487,6 @@
align-items: center;
margin-left: 5px;
text-decoration: none;
-
- //border-color: @inputBorder;
.box-shadow(0 1px 2px rgba(0,0,0,0.25));
}
@@ -628,7 +626,13 @@
.viewport {
max-width: 600px;
- background: @checkered-background;
+ .checkeredBackground();
+
+ img {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+ }
&:hover {
cursor: pointer;
@@ -648,7 +652,7 @@
}
.viewport img {
- background: @checkered-background;
+ .checkeredBackground();
}
}
@@ -767,13 +771,13 @@
}
.umb-fileupload ul {
- list-style: none;
- vertical-align: middle;
- margin-bottom: 0;
+ list-style: none;
+ vertical-align: middle;
+ margin-bottom: 0;
- img {
- background: @checkered-background;
- }
+ img {
+ .checkeredBackground();
+ }
}
.umb-fileupload label {
@@ -792,28 +796,38 @@
padding-top: 27px;
}
-.umb-fileupload .file-icon {
- display: inline-block;
- position: relative;
- padding: 5px 0;
-
- > .icon {
- font-size: 70px;
- line-height: 110%;
- color: @gray-4;
+.umb-fileupload .umb-icon-holder {
text-align: center;
- }
+ display: flex;
+ flex-direction: column;
+ align-items: center;
- > span {
- color: @white;
- background: @gray-4;
- padding: 1px 3px;
- font-size: 12px;
- line-height: 130%;
- position: absolute;
- top: 45px;
- left: 10px;
- }
+ .file-icon {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ position: relative;
+ padding: 15px 0;
+
+ > .icon {
+ display: block;
+ font-size: 70px;
+ line-height: 110%;
+ color: @gray-4;
+ text-align: center;
+ }
+
+ > span {
+ color: @white;
+ background: @ui-active;
+ padding: 1px 3px;
+ font-size: 12px;
+ line-height: 130%;
+ display: block;
+ margin-top: -35px;
+ min-width: 2em;
+ }
+ }
}
.umb-fileupload input {
diff --git a/src/Umbraco.Web.UI.Client/src/less/sections.less b/src/Umbraco.Web.UI.Client/src/less/sections.less
index ef6c5f5046..5551ba6376 100644
--- a/src/Umbraco.Web.UI.Client/src/less/sections.less
+++ b/src/Umbraco.Web.UI.Client/src/less/sections.less
@@ -2,129 +2,135 @@
// -------------------------
ul.sections {
- margin: 0;
- display: flex;
- margin-left: -20px;
-}
-
-ul.sections>li {
- display: flex;
- justify-content: center;
- align-items: center;
- position: relative;
-}
-
-ul.sections>li>a {
- color: @white;
- height: @appHeaderHeight;
+ margin: 0;
display: flex;
- align-items: center;
- justify-content: center;
- position: relative;
- padding: 0 10px;
- text-decoration: none;
- outline: none;
- cursor: pointer;
-}
+ margin-left: -20px;
-ul.sections>li>a .section__name {
- border-radius: 3px;
- margin-top:1px;
- padding: 3px 10px 4px 10px;
- opacity: 0.8;
- transition: opacity .1s linear, box-shadow .1s;
-}
+ > li {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ position: relative;
-ul.sections>li>a::after {
- content: "";
- left: 10px;
- right: 10px;
- height: 4px;
- bottom: 0;
- transform: translateY(4px);
- background-color: @pinkLight;
- position: absolute;
- border-radius: 3px 3px 0 0;
- opacity: 0;
- padding: 0 2px;
- transition: transform 240ms ease-in-out;
-}
+ > a {
+ color: @white;
+ height: @appHeaderHeight;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ position: relative;
+ padding: 0 10px;
+ text-decoration: none;
+ outline: none;
+ cursor: pointer;
-ul.sections>li.current>a {
- color:@pinkLight;
-}
-ul.sections>li.current>a::after {
- opacity: 1;
- transform: translateY(0px);
-}
-ul.sections > li.current > a .section__name,
-ul.sections > li > a:hover .section__name {
- opacity: 1;
- -webkit-font-smoothing: subpixel-antialiased;
-}
+ &::after {
+ content: "";
+ left: 10px;
+ right: 10px;
+ height: 4px;
+ bottom: 0;
+ transform: translateY(4px);
+ background-color: @ui-active;
+ position: absolute;
+ border-radius: 3px 3px 0 0;
+ opacity: 0;
+ padding: 0 2px;
+ transition: transform 240ms ease-in-out;
+ }
-ul.sections > li > a:focus .section__name {
- .tabbing-active & {
-
- border: 1px solid;
- border-color: @gray-9;
+ &:focus .section__name {
+ .tabbing-active & {
+ border: 1px solid;
+ border-color: @gray-9;
+ }
+ }
+ }
+
+ .section__name {
+ border-radius: 3px;
+ margin-top: 1px;
+ padding: 3px 10px 4px 10px;
+ opacity: 0.8;
+ transition: opacity .1s linear, box-shadow .1s;
+ }
+
+ &.current a {
+ color: @ui-active;
+
+ &::after {
+ opacity: 1;
+ transform: translateY(0px);
+ }
+ }
+
+ &.expand {
+ i {
+ height: 5px;
+ width: 5px;
+ border-radius: 50%;
+ background: @white;
+ display: inline-block;
+ margin: 0 5px 0 0;
+ opacity: 0.6;
+ transition: opacity .1s linear;
+ }
+
+ &:hover i {
+ opacity:1;
+ }
+ }
+
+ &.current .section__name,
+ a:hover .section__name {
+ opacity: 1;
+ -webkit-font-smoothing: subpixel-antialiased;
+ }
}
}
-
-
/* Sections tray */
-ul.sections>li.expand i {
- height: 5px;
- width: 5px;
- border-radius: 50%;
- background: #fff;
- display: inline-block;
- margin: 0 5px 0 0;
- opacity: 0.6;
-}
-
ul.sections-tray {
- position: absolute;
- top: @appHeaderHeight;
- left: 0;
- margin: 0;
+ position: absolute;
+ top: @appHeaderHeight;
+ left: 0;
+ margin: 0;
list-style: none;
- background: @purple;
- z-index: 10000;
- border-radius: 0 0 3px 3px;
-}
+ background: @blueExtraDark;
+ z-index: 10000;
+ border-radius: 0 0 3px 3px;
-ul.sections-tray>li>a {
- padding: 8px 24px;
- color: @white;
- text-decoration: none;
- display: block;
- position: relative;
-}
+ li {
-ul.sections-tray>li>a::after {
- content: "";
- width: 4px;
- height: 100%;
- background-color: @ui-active;
- position: absolute;
- border-radius: 0 3px 3px 0;
- opacity: 0;
- transition: all .2s linear;
- top: 0;
- left: 0;
-}
+ &.current a {
+ color: @ui-active;
+ opacity: 1;
-ul.sections-tray>li.current>a::after {
- opacity: 1;
-}
+ &::after {
+ opacity: 1;
+ }
+ }
-ul.sections-tray>li>a .section__name {
- opacity: 0.6;
-}
+ a {
+ padding: 8px 24px;
+ color: @white;
+ text-decoration: none;
+ display: block;
+ position: relative;
-ul.sections-tray>li>a:hover .section__name {
- opacity: 1;
+ &::after {
+ content: "";
+ width: 4px;
+ height: 100%;
+ background-color: @ui-active;
+ position: absolute;
+ border-radius: 0 3px 3px 0;
+ opacity: 0;
+ transition: all .2s linear;
+ top: 0;
+ left: 0;
+ }
+ }
+ }
}
diff --git a/src/Umbraco.Web.UI.Client/src/less/utilities/_flexbox.less b/src/Umbraco.Web.UI.Client/src/less/utilities/_flexbox.less
index c0815fa8ac..a3427074cd 100644
--- a/src/Umbraco.Web.UI.Client/src/less/utilities/_flexbox.less
+++ b/src/Umbraco.Web.UI.Client/src/less/utilities/_flexbox.less
@@ -1,7 +1,5 @@
/*
-
Flexbox
-
*/
.flex { display: flex; }
diff --git a/src/Umbraco.Web.UI.Client/src/less/variables.less b/src/Umbraco.Web.UI.Client/src/less/variables.less
index a1dc0ba187..166640829b 100644
--- a/src/Umbraco.Web.UI.Client/src/less/variables.less
+++ b/src/Umbraco.Web.UI.Client/src/less/variables.less
@@ -517,7 +517,7 @@
@heroUnitLeadColor: inherit;
-// alerts
+// Alerts
// -------------------------
@warningText: @white;
@warningBackground: @yellow-d2;
diff --git a/src/Umbraco.Web.UI.Client/src/controllers/main.controller.js b/src/Umbraco.Web.UI.Client/src/main.controller.js
similarity index 96%
rename from src/Umbraco.Web.UI.Client/src/controllers/main.controller.js
rename to src/Umbraco.Web.UI.Client/src/main.controller.js
index 654bbb1d03..93870f8a56 100644
--- a/src/Umbraco.Web.UI.Client/src/controllers/main.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/main.controller.js
@@ -10,7 +10,7 @@
*/
function MainController($scope, $location, appState, treeService, notificationsService,
userService, historyService, updateChecker, navigationService, eventsService,
- tmhDynamicLocale, localStorageService, editorService, overlayService) {
+ tmhDynamicLocale, localStorageService, editorService, overlayService, assetsService, tinyMceAssets) {
//the null is important because we do an explicit bool check on this in the view
$scope.authenticated = null;
@@ -21,7 +21,13 @@ function MainController($scope, $location, appState, treeService, notificationsS
$scope.search = {};
$scope.login = {};
$scope.tabbingActive = false;
-
+
+ // Load TinyMCE assets ahead of time in the background for the user
+ // To help with first load of the RTE
+ tinyMceAssets.forEach(function (tinyJsAsset) {
+ assetsService.loadJs(tinyJsAsset, $scope);
+ });
+
// There are a number of ways to detect when a focus state should be shown when using the tab key and this seems to be the simplest solution.
// For more information about this approach, see https://hackernoon.com/removing-that-ugly-focus-ring-and-keeping-it-too-6c8727fefcd2
function handleFirstTab(evt) {
diff --git a/src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js b/src/Umbraco.Web.UI.Client/src/navigation.controller.js
similarity index 100%
rename from src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js
rename to src/Umbraco.Web.UI.Client/src/navigation.controller.js
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.html b/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.html
index 56db1fd88a..a0413ce1a6 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.html
+++ b/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.html
@@ -38,8 +38,8 @@
{{ tour.name }}
-
-
+
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.controller.js
index 75bf414099..c9d2e43a98 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.controller.js
@@ -1,7 +1,7 @@
(function () {
"use strict";
- function CompositionsController($scope, $location, $filter) {
+ function CompositionsController($scope, $location, $filter, overlayService) {
var vm = this;
var oldModel = null;
@@ -56,19 +56,35 @@
if ($scope.model && $scope.model.submit) {
// check if any compositions has been removed
- vm.compositionRemoved = false;
+ var compositionRemoved = false;
for (var i = 0; oldModel.compositeContentTypes.length > i; i++) {
var oldComposition = oldModel.compositeContentTypes[i];
if (_.contains($scope.model.compositeContentTypes, oldComposition) === false) {
- vm.compositionRemoved = true;
+ compositionRemoved = true;
}
}
/* submit the form if there havne't been removed any composition
or the confirm checkbox has been checked */
- if (!vm.compositionRemoved || vm.allowSubmit) {
- $scope.model.submit($scope.model);
+ if (compositionRemoved) {
+ vm.allowSubmit = false;
+ const dialog = {
+ view: "views/common/infiniteeditors/compositions/overlays/confirmremove.html",
+ submitButtonLabelKey: "general_ok",
+ closeButtonLabelKey: "general_cancel",
+ submit: function (model) {
+ $scope.model.submit($scope.model);
+ overlayService.close();
+ },
+ close: function () {
+ overlayService.close();
+ }
+ };
+ overlayService.open(dialog);
+ return;
}
+
+ $scope.model.submit($scope.model);
}
}
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.html
index bf74431d96..bb0804e2bf 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.html
+++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.html
@@ -92,16 +92,6 @@
-
-
-
Warning
-
Removing a composition will delete all the associated property data. Once you save the document type there's no way back, are you sure?
-
-
-
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/overlays/confirmremove.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/overlays/confirmremove.html
new file mode 100644
index 0000000000..dd5e244ba5
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/overlays/confirmremove.html
@@ -0,0 +1,6 @@
+
+
+
Warning
+
Removing a composition will delete all the associated property data. Once you save the document type there's no way back, are you sure?
- Confirm new password
-
+ Confirm new password
+
RequiredThe confirmed password doesn't match the new password!
@@ -138,7 +138,7 @@
id="{{login.authType}}" name="provider" value="{{login.authType}}"
title="Log in using your {{login.caption}} account">
- Sign in with {{login.caption}}
+ Sign in with {{login.caption}}