Merge branch 'v8/dev' into v8/feature/284-npoco-mappers
This commit is contained in:
@@ -22,7 +22,7 @@ namespace Umbraco.Core.Compose
|
||||
|
||||
private static void ContentService_Moved(IContentService sender, MoveEventArgs<IContent> e)
|
||||
{
|
||||
foreach (var item in e.MoveInfoCollection.Where(x => x.OriginalPath.Contains(Constants.System.RecycleBinContent.ToInvariantString())))
|
||||
foreach (var item in e.MoveInfoCollection.Where(x => x.OriginalPath.Contains(Constants.System.RecycleBinContentString)))
|
||||
{
|
||||
var relationService = Current.Services.RelationService;
|
||||
const string relationTypeAlias = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias;
|
||||
@@ -37,7 +37,7 @@ namespace Umbraco.Core.Compose
|
||||
|
||||
private static void MediaService_Moved(IMediaService sender, MoveEventArgs<IMedia> e)
|
||||
{
|
||||
foreach (var item in e.MoveInfoCollection.Where(x => x.OriginalPath.Contains(Constants.System.RecycleBinMedia.ToInvariantString())))
|
||||
foreach (var item in e.MoveInfoCollection.Where(x => x.OriginalPath.Contains(Constants.System.RecycleBinMediaString)))
|
||||
{
|
||||
var relationService = Current.Services.RelationService;
|
||||
const string relationTypeAlias = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias;
|
||||
|
||||
@@ -203,6 +203,28 @@ namespace Umbraco.Core
|
||||
composition.RegisterUnique(_ => registrar);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the database server messenger options.
|
||||
/// </summary>
|
||||
/// <param name="composition">The composition.</param>
|
||||
/// <param name="factory">A function creating the options.</param>
|
||||
/// <remarks>Use DatabaseServerRegistrarAndMessengerComposer.GetDefaultOptions to get the options that Umbraco would use by default.</remarks>
|
||||
public static void SetDatabaseServerMessengerOptions(this Composition composition, Func<IFactory, DatabaseServerMessengerOptions> factory)
|
||||
{
|
||||
composition.RegisterUnique(factory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the database server messenger options.
|
||||
/// </summary>
|
||||
/// <param name="composition">The composition.</param>
|
||||
/// <param name="options">Options.</param>
|
||||
/// <remarks>Use DatabaseServerRegistrarAndMessengerComposer.GetDefaultOptions to get the options that Umbraco would use by default.</remarks>
|
||||
public static void SetDatabaseServerMessengerOptions(this Composition composition, DatabaseServerMessengerOptions options)
|
||||
{
|
||||
composition.RegisterUnique(_ => options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the short string helper.
|
||||
/// </summary>
|
||||
|
||||
@@ -93,7 +93,6 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public const string DisableElectionForSingleServer = "Umbraco.Core.DisableElectionForSingleServer";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Debug specific web.config AppSetting keys for Umbraco
|
||||
/// </summary>
|
||||
|
||||
@@ -145,11 +145,11 @@
|
||||
|
||||
public const string PartialViewMacros = "partialViewMacros";
|
||||
|
||||
public const string LogViewer = "logViewer";
|
||||
public const string LogViewer = "logViewer";
|
||||
|
||||
public static class Groups
|
||||
{
|
||||
public const string Settings = "settingsGroup";
|
||||
public const string Settings = "settingsGroup";
|
||||
|
||||
public const string Templating = "templatingGroup";
|
||||
|
||||
|
||||
@@ -92,10 +92,10 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public const string Extension = "umbracoExtension";
|
||||
|
||||
/// <summary>
|
||||
/// The default height/width of an image file if the size can't be determined from the metadata
|
||||
/// </summary>
|
||||
public const int DefaultSize = 200;
|
||||
/// <summary>
|
||||
/// The default height/width of an image file if the size can't be determined from the metadata
|
||||
/// </summary>
|
||||
public const int DefaultSize = 200;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -209,71 +209,71 @@ namespace Umbraco.Core
|
||||
public static Dictionary<string, PropertyType> GetStandardPropertyTypeStubs()
|
||||
{
|
||||
return new Dictionary<string, PropertyType>
|
||||
{
|
||||
{
|
||||
Comments,
|
||||
new PropertyType(PropertyEditors.Aliases.TextArea, ValueStorageType.Ntext, true, Comments)
|
||||
{
|
||||
Comments,
|
||||
new PropertyType(PropertyEditors.Aliases.TextArea, ValueStorageType.Ntext, true, Comments)
|
||||
{
|
||||
Name = CommentsLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
FailedPasswordAttempts,
|
||||
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Integer, true, FailedPasswordAttempts)
|
||||
{
|
||||
Name = FailedPasswordAttemptsLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
IsApproved,
|
||||
new PropertyType(PropertyEditors.Aliases.Boolean, ValueStorageType.Integer, true, IsApproved)
|
||||
{
|
||||
Name = IsApprovedLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
IsLockedOut,
|
||||
new PropertyType(PropertyEditors.Aliases.Boolean, ValueStorageType.Integer, true, IsLockedOut)
|
||||
{
|
||||
Name = IsLockedOutLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
LastLockoutDate,
|
||||
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Date, true, LastLockoutDate)
|
||||
{
|
||||
Name = LastLockoutDateLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
LastLoginDate,
|
||||
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Date, true, LastLoginDate)
|
||||
{
|
||||
Name = LastLoginDateLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
LastPasswordChangeDate,
|
||||
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Date, true, LastPasswordChangeDate)
|
||||
{
|
||||
Name = LastPasswordChangeDateLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
PasswordAnswer,
|
||||
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Nvarchar, true, PasswordAnswer)
|
||||
{
|
||||
Name = PasswordAnswerLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
PasswordQuestion,
|
||||
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Nvarchar, true, PasswordQuestion)
|
||||
{
|
||||
Name = PasswordQuestionLabel
|
||||
}
|
||||
Name = CommentsLabel
|
||||
}
|
||||
};
|
||||
},
|
||||
{
|
||||
FailedPasswordAttempts,
|
||||
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Integer, true, FailedPasswordAttempts)
|
||||
{
|
||||
Name = FailedPasswordAttemptsLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
IsApproved,
|
||||
new PropertyType(PropertyEditors.Aliases.Boolean, ValueStorageType.Integer, true, IsApproved)
|
||||
{
|
||||
Name = IsApprovedLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
IsLockedOut,
|
||||
new PropertyType(PropertyEditors.Aliases.Boolean, ValueStorageType.Integer, true, IsLockedOut)
|
||||
{
|
||||
Name = IsLockedOutLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
LastLockoutDate,
|
||||
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Date, true, LastLockoutDate)
|
||||
{
|
||||
Name = LastLockoutDateLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
LastLoginDate,
|
||||
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Date, true, LastLoginDate)
|
||||
{
|
||||
Name = LastLoginDateLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
LastPasswordChangeDate,
|
||||
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Date, true, LastPasswordChangeDate)
|
||||
{
|
||||
Name = LastPasswordChangeDateLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
PasswordAnswer,
|
||||
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Nvarchar, true, PasswordAnswer)
|
||||
{
|
||||
Name = PasswordAnswerLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
PasswordQuestion,
|
||||
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Nvarchar, true, PasswordQuestion)
|
||||
{
|
||||
Name = PasswordQuestionLabel
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Umbraco.Core
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public static partial class Constants
|
||||
{
|
||||
public static class Icons
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// System contenttype icon
|
||||
/// </summary>
|
||||
@@ -42,12 +34,10 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public const string MemberType = "icon-users";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// System member icon
|
||||
/// </summary>
|
||||
public const string Template = "icon-layout";
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Umbraco.Core
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public static partial class Constants
|
||||
{
|
||||
|
||||
@@ -123,7 +123,6 @@ namespace Umbraco.Core
|
||||
public static readonly Guid Template = new Guid(Strings.Template);
|
||||
|
||||
public static readonly Guid ContentItem = new Guid(Strings.ContentItem);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
public static partial class Constants
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the constants used for the Umbraco package repository
|
||||
/// Defines the constants used for the Umbraco package repository
|
||||
/// </summary>
|
||||
public static class PackageRepository
|
||||
{
|
||||
|
||||
@@ -34,7 +34,6 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public const string ContentPicker = "Umbraco.ContentPicker";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// DateTime.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Umbraco.Core
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public static partial class Constants
|
||||
{
|
||||
@@ -22,7 +19,6 @@ namespace Umbraco.Core
|
||||
public const string PreviewCookieName = "UMB_PREVIEW";
|
||||
|
||||
public const string InstallerCookieName = "umb_installId";
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,22 +151,22 @@ namespace Umbraco.Core.Models
|
||||
|
||||
internal static bool HasContentRootAccess(this IUser user, IEntityService entityService)
|
||||
{
|
||||
return ContentPermissionsHelper.HasPathAccess(Constants.System.Root.ToInvariantString(), user.CalculateContentStartNodeIds(entityService), Constants.System.RecycleBinContent);
|
||||
return ContentPermissionsHelper.HasPathAccess(Constants.System.RootString, user.CalculateContentStartNodeIds(entityService), Constants.System.RecycleBinContent);
|
||||
}
|
||||
|
||||
internal static bool HasContentBinAccess(this IUser user, IEntityService entityService)
|
||||
{
|
||||
return ContentPermissionsHelper.HasPathAccess(Constants.System.RecycleBinContent.ToInvariantString(), user.CalculateContentStartNodeIds(entityService), Constants.System.RecycleBinContent);
|
||||
return ContentPermissionsHelper.HasPathAccess(Constants.System.RecycleBinContentString, user.CalculateContentStartNodeIds(entityService), Constants.System.RecycleBinContent);
|
||||
}
|
||||
|
||||
internal static bool HasMediaRootAccess(this IUser user, IEntityService entityService)
|
||||
{
|
||||
return ContentPermissionsHelper.HasPathAccess(Constants.System.Root.ToInvariantString(), user.CalculateMediaStartNodeIds(entityService), Constants.System.RecycleBinMedia);
|
||||
return ContentPermissionsHelper.HasPathAccess(Constants.System.RootString, user.CalculateMediaStartNodeIds(entityService), Constants.System.RecycleBinMedia);
|
||||
}
|
||||
|
||||
internal static bool HasMediaBinAccess(this IUser user, IEntityService entityService)
|
||||
{
|
||||
return ContentPermissionsHelper.HasPathAccess(Constants.System.RecycleBinMedia.ToInvariantString(), user.CalculateMediaStartNodeIds(entityService), Constants.System.RecycleBinMedia);
|
||||
return ContentPermissionsHelper.HasPathAccess(Constants.System.RecycleBinMediaString, user.CalculateMediaStartNodeIds(entityService), Constants.System.RecycleBinMedia);
|
||||
}
|
||||
|
||||
internal static bool HasPathAccess(this IUser user, IContent content, IEntityService entityService)
|
||||
@@ -327,7 +327,7 @@ namespace Umbraco.Core.Models
|
||||
? entityService.GetAllPaths(objectType, asn).ToDictionary(x => x.Id, x => x.Path)
|
||||
: new Dictionary<int, string>();
|
||||
|
||||
paths[Constants.System.Root] = Constants.System.Root.ToString(); // entityService does not get that one
|
||||
paths[Constants.System.Root] = Constants.System.RootString; // entityService does not get that one
|
||||
|
||||
var binPath = GetBinPath(objectType);
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace Umbraco.Core
|
||||
|
||||
public const string Tag = /*TableNamePrefix*/ "cms" + "Tags";
|
||||
public const string TagRelationship = /*TableNamePrefix*/ "cms" + "TagRelationship";
|
||||
|
||||
|
||||
public const string KeyValue = TableNamePrefix + "KeyValue";
|
||||
|
||||
public const string AuditEntry = TableNamePrefix + "Audit";
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
// move to parent (or -1), update path, save
|
||||
moving.ParentId = parentId;
|
||||
var movingPath = moving.Path + ","; // save before changing
|
||||
moving.Path = (container == null ? Constants.System.Root.ToString() : container.Path) + "," + moving.Id;
|
||||
moving.Path = (container == null ? Constants.System.RootString : container.Path) + "," + moving.Id;
|
||||
moving.Level = container == null ? 1 : container.Level + 1;
|
||||
Save(moving);
|
||||
|
||||
|
||||
@@ -533,7 +533,7 @@ namespace Umbraco.Core.Services.Implement
|
||||
//null check otherwise we get exceptions
|
||||
if (content.Path.IsNullOrWhiteSpace()) return Enumerable.Empty<IContent>();
|
||||
|
||||
var rootId = Constants.System.Root.ToInvariantString();
|
||||
var rootId = Constants.System.RootString;
|
||||
var ids = content.Path.Split(',')
|
||||
.Where(x => x != rootId && x != content.Id.ToString(CultureInfo.InvariantCulture)).Select(int.Parse).ToArray();
|
||||
if (ids.Any() == false)
|
||||
@@ -1922,7 +1922,7 @@ namespace Umbraco.Core.Services.Implement
|
||||
// if uow is not immediate, content.Path will be updated only when the UOW commits,
|
||||
// and because we want it now, we have to calculate it by ourselves
|
||||
//paths[content.Id] = content.Path;
|
||||
paths[content.Id] = (parent == null ? (parentId == Constants.System.RecycleBinContent ? "-1,-20" : "-1") : parent.Path) + "," + content.Id;
|
||||
paths[content.Id] = (parent == null ? (parentId == Constants.System.RecycleBinContent ? "-1,-20" : Constants.System.RootString) : parent.Path) + "," + content.Id;
|
||||
|
||||
const int pageSize = 500;
|
||||
var page = 0;
|
||||
|
||||
@@ -995,7 +995,7 @@ namespace Umbraco.Core.Services.Implement
|
||||
// if uow is not immediate, content.Path will be updated only when the UOW commits,
|
||||
// and because we want it now, we have to calculate it by ourselves
|
||||
//paths[media.Id] = media.Path;
|
||||
paths[media.Id] = (parent == null ? (parentId == Constants.System.RecycleBinMedia ? "-1,-21" : "-1") : parent.Path) + "," + media.Id;
|
||||
paths[media.Id] = (parent == null ? (parentId == Constants.System.RecycleBinMedia ? "-1,-21" : Constants.System.RootString) : parent.Path) + "," + media.Id;
|
||||
|
||||
const int pageSize = 500;
|
||||
var page = 0;
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Umbraco.Core
|
||||
|
||||
internal static Dictionary<string, UdiType> GetTypes()
|
||||
{
|
||||
return new Dictionary<string,UdiType>
|
||||
return new Dictionary<string, UdiType>
|
||||
{
|
||||
{ Unknown, UdiType.Unknown },
|
||||
|
||||
|
||||
+10
-6
@@ -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();
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
+1
-1
@@ -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 () {
|
||||
|
||||
+8
-9
@@ -13,7 +13,12 @@ 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));
|
||||
@@ -34,7 +39,7 @@ angular.module("umbraco.directives")
|
||||
var tinyMceEditor = null;
|
||||
|
||||
promises.push(tinyMceService.getTinyMceEditorConfig({
|
||||
htmlId: scope.uniqueId,
|
||||
htmlId: scope.textAreaHtmlId,
|
||||
stylesheets: editorConfig.stylesheets,
|
||||
toolbar: editorConfig.toolbar,
|
||||
mode: editorConfig.mode
|
||||
@@ -145,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);
|
||||
|
||||
+15
-4
@@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
})
|
||||
|
||||
+42
-12
@@ -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);
|
||||
}
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@@ -137,6 +137,7 @@
|
||||
@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";
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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%;
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,17 @@
|
||||
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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -199,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;}
|
||||
|
||||
@@ -113,12 +113,7 @@ var app = angular.module("umbraco.preview", ['umbraco.resources', 'umbraco.servi
|
||||
$scope.exitPreview = function () {
|
||||
|
||||
var culture = $location.search().culture || getParameterByName("culture");
|
||||
var relativeUrl = "/" + $scope.pageId;
|
||||
|
||||
if(culture){
|
||||
relativeUrl +='?culture='+ culture;
|
||||
}
|
||||
|
||||
var relativeUrl = "/" + $scope.pageId +'?culture='+ culture;
|
||||
window.top.location.href = "../preview/end?redir=" + encodeURIComponent(relativeUrl);
|
||||
};
|
||||
|
||||
|
||||
+24
-17
@@ -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;
|
||||
|
||||
@@ -103,27 +104,33 @@
|
||||
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -6,6 +6,6 @@
|
||||
|
||||
<p>
|
||||
<strong>Name:</strong><br/>
|
||||
<input ng-model="model.name" type="text" name="queryName" ng-change="model.disableSubmitButton = model.name.length === 0"/>
|
||||
<input style="width: 100%" ng-model="model.name" type="text" name="queryName" ng-change="model.disableSubmitButton = model.name.length === 0"/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<div class="umb-rte"
|
||||
id="{{uniqueId}}">
|
||||
id="{{textAreaHtmlId}}">
|
||||
</div>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
{{vm.variants[0].releaseDateFormatted}}
|
||||
</button>
|
||||
|
||||
<a ng-hide="vm.variants[0].releaseDate" href="" class="bold" style="color: #00aea2; text-decoration: underline;">
|
||||
<a ng-hide="vm.variants[0].releaseDate" href="">
|
||||
<localize key="content_setDate">Set date</localize>
|
||||
</a>
|
||||
</div>
|
||||
@@ -59,7 +59,7 @@
|
||||
{{vm.variants[0].expireDateFormatted}}
|
||||
</button>
|
||||
|
||||
<a ng-hide="vm.variants[0].expireDate" href="" class="bold" style="color: #00aea2; text-decoration: underline;">
|
||||
<a ng-hide="vm.variants[0].expireDate" href="">
|
||||
<localize key="content_setDate">Set date</localize>
|
||||
</a>
|
||||
</div>
|
||||
@@ -84,8 +84,8 @@
|
||||
|
||||
<div class="umb-list umb-list--condensed">
|
||||
|
||||
<div class="umb-list-item" ng-repeat="variant in vm.variants | filter:vm.dirtyVariantFilter">
|
||||
<ng-form name="scheduleSelectorForm">
|
||||
<div class="umb-list-item" ng-repeat="variant in vm.variants">
|
||||
<ng-form name="scheduleSelectorForm" style="width:100%;">
|
||||
<div class="flex">
|
||||
|
||||
<umb-checkbox
|
||||
@@ -106,9 +106,9 @@
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<div class="flex items-center" style="margin-top: 10px; margin-bottom: 10px;">
|
||||
<div class="date-wrapper-mini">
|
||||
<div class="date-wrapper-mini__date" ng-if="vm.dirtyVariantFilter(variant) && (variant.releaseDate || variant.save)">
|
||||
|
||||
<div class="flex items-center" ng-if="variant.releaseDate || variant.save">
|
||||
<div style="font-size: 13px; margin-right: 5px;">Publish:<em ng-show="!variant.save"> {{variant.releaseDateFormatted}}</em></div>
|
||||
|
||||
<div class="btn-group flex" style="font-size: 14px; margin-right: 10px;" ng-if="variant.save">
|
||||
@@ -123,7 +123,7 @@
|
||||
{{variant.releaseDateFormatted}}
|
||||
</button>
|
||||
|
||||
<a ng-hide="variant.releaseDate" href="" class="bold" style="color: #00aea2; text-decoration: underline;">
|
||||
<a ng-hide="variant.releaseDate" href="">
|
||||
<localize key="content_setDate">Set date</localize>
|
||||
</a>
|
||||
</div>
|
||||
@@ -134,7 +134,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center" ng-if="variant.expireDate || variant.save">
|
||||
<div class="date-wrapper-mini__date" ng-if="variant.expireDate || variant.save">
|
||||
<div style="font-size: 13px; margin-right: 5px;">Unpublish:<em ng-show="!variant.save"> {{variant.expireDateFormatted}}</em></div>
|
||||
|
||||
<div class="btn-group flex" style="font-size: 14px;" ng-if="variant.save">
|
||||
@@ -149,7 +149,7 @@
|
||||
{{variant.expireDateFormatted}}
|
||||
</button>
|
||||
|
||||
<a ng-hide="variant.expireDate" href="" class="bold" style="color: #00aea2; text-decoration: underline;">
|
||||
<a ng-hide="variant.expireDate" href="">
|
||||
<localize key="content_setDate">Set date</localize>
|
||||
</a>
|
||||
</div>
|
||||
@@ -182,24 +182,6 @@
|
||||
<br />
|
||||
</div>
|
||||
|
||||
<div class="umb-list umb-list--condensed" ng-if="vm.hasPristineVariants">
|
||||
<div style="margin-bottom: 15px; font-weight: bold;">
|
||||
<p><localize key="content_publishedLanguages"></localize></p>
|
||||
</div>
|
||||
|
||||
<div class="umb-list-item" ng-repeat="variant in vm.variants | filter:vm.pristineVariantFilter track by variant.language.culture">
|
||||
<div>
|
||||
<div style="margin-bottom: 2px;">
|
||||
<span>{{ variant.language.name }}</span>
|
||||
</div>
|
||||
<div class="umb-permission__description">
|
||||
<umb-variant-state variant="variant"></umb-variant-state>
|
||||
<span ng-show="variant.language.isMandatory"> - <localize key="languages_mandatoryLanguage"></localize></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div data-element="editor-logs" ng-controller="Umbraco.Editors.LogViewer.OverviewController as vm" class="clearfix">
|
||||
<div data-element="editor-logs" ng-controller="Umbraco.Editors.LogViewer.OverviewController as vm" class="clearfix" id="logview">
|
||||
|
||||
<umb-editor-view footer="false">
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
</umb-box>
|
||||
</div>
|
||||
|
||||
<div class="umb-package-details" ng-show="!vm.loading && vm.canLoadLogs">
|
||||
<div class="umb-package-details__main-content">
|
||||
<div class="umb-logviewer" ng-show="!vm.loading && vm.canLoadLogs">
|
||||
<div class="umb-logviewer__main-content">
|
||||
<!-- Saved Searches -->
|
||||
<umb-box>
|
||||
<umb-box-header title="Saved Searches"></umb-box-header>
|
||||
@@ -68,7 +68,7 @@
|
||||
</umb-box>
|
||||
</div>
|
||||
|
||||
<div class="umb-package-details__sidebar">
|
||||
<div class="umb-logviewer__sidebar">
|
||||
<!-- No of Errors -->
|
||||
<umb-box ng-click="vm.searchLogQuery('Has(@Exception)')" style="cursor:pointer;">
|
||||
<umb-box-header title="Number of Errors"></umb-box-header>
|
||||
@@ -95,4 +95,4 @@
|
||||
</div>
|
||||
</umb-editor-container>
|
||||
</umb-editor-view>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -51,18 +51,19 @@
|
||||
|
||||
<div style="position:relative; width:100%;">
|
||||
<!-- Search/expression filter -->
|
||||
<input class="form-control search-input" type="text" ng-model="vm.logOptions.filterExpression" style="width:100%;" placeholder="Search logs…" />
|
||||
<input class="form-control search-input" type="text" ng-model="vm.logOptions.filterExpression" style="width:100%; padding-right: 160px;" placeholder="Search logs…" />
|
||||
|
||||
<!-- Save Search & Clear Search icon buttons -->
|
||||
<ins class="icon-rate" ng-if="vm.checkForSavedSearch()" ng-click="vm.addToSavedSearches()" style="float: left; position: absolute; top: 0; line-height: 32px; right: 160px; color: #fdb45c; cursor: pointer;"> </ins>
|
||||
<ins class="icon-wrong" ng-if="vm.logOptions.filterExpression" ng-click="vm.resetSearch()" style="float: left; position: absolute; top: 0; line-height: 32px; right: 140px; color: #bbbabf; cursor: pointer;"> </ins>
|
||||
<ins class="icon-rate" ng-show="vm.checkForSavedSearch()" ng-click="vm.addToSavedSearches()" style="position: absolute; top: 0; line-height: 32px; right: 140px; color: #fdb45c; cursor: pointer;"> </ins>
|
||||
<ins class="icon-wrong" ng-show="vm.logOptions.filterExpression" ng-click="vm.resetSearch()" style="position: absolute; top: 0; line-height: 32px; right: 120px; color: #bbbabf; cursor: pointer;"> </ins>
|
||||
|
||||
<a class="umb-variant-switcher__toggle ng-scope" href="" ng-click="vm.dropdownOpen = !vm.dropdownOpen" style="top:0;">
|
||||
<span class="ng-binding">Example Searches</span>
|
||||
<ins class="umb-variant-switcher__expand icon-navigation-down" ng-class="{'icon-navigation-down': !vm.dropdownOpen, 'icon-navigation-up': vm.dropdownOpen}"> </ins>
|
||||
<!-- Saved Searches -->
|
||||
<a class="umb-variant-switcher__toggle ng-scope" href="" ng-click="vm.dropdownOpen = !vm.dropdownOpen" style="top: 1px; right: 0; position: absolute;">
|
||||
<span class="ng-binding">Saved Searches</span>
|
||||
<ins class="umb-variant-switcher__expand icon-navigation-down" ng-class="{'icon-navigation-down': !vm.dropdownOpen, 'icon-navigation-up': vm.dropdownOpen}" style="margin-top: 0;"></ins>
|
||||
</a>
|
||||
|
||||
<!-- Common Searches Dropdown -->
|
||||
<!-- Saved Searches Dropdown -->
|
||||
<umb-dropdown ng-if="vm.dropdownOpen" style="width: 100%; max-height: 250px; overflow-y: scroll; margin-top: -10px;" on-close="vm.dropdownOpen = false" umb-keyboard-list>
|
||||
<umb-dropdown-item class="umb-variant-switcher__item" ng-class="{'umb-variant-switcher_item--current': variant.active}" ng-repeat="search in vm.searches">
|
||||
<a href="" class="umb-variant-switcher__name-wrapper" ng-click="vm.selectSearch(search)" prevent-default>
|
||||
|
||||
+17
-17
@@ -1,25 +1,26 @@
|
||||
angular.module("umbraco")
|
||||
.controller("Umbraco.PropertyEditors.Grid.EmbedController",
|
||||
function ($scope, $timeout, $sce, editorService) {
|
||||
|
||||
function onInit() {
|
||||
$scope.trustedValue = null;
|
||||
$scope.trustedValue = $sce.trustAsHtml($scope.control.value);
|
||||
|
||||
if(!$scope.control.value) {
|
||||
$timeout(function(){
|
||||
if($scope.control.$initializing){
|
||||
$scope.setEmbed();
|
||||
}
|
||||
}, 200);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function getEmbed() {
|
||||
return $sce.trustAsHtml($scope.control.value);
|
||||
}
|
||||
|
||||
$scope.setEmbed = function(){
|
||||
|
||||
|
||||
$scope.embedHtml = getEmbed();
|
||||
$scope.$watch('control.value', function(newValue, oldValue) {
|
||||
if(angular.equals(newValue, oldValue)){
|
||||
return; // simply skip that
|
||||
}
|
||||
|
||||
$scope.embedHtml = getEmbed();
|
||||
}, false);
|
||||
$scope.setEmbed = function() {
|
||||
var embed = {
|
||||
submit: function(model) {
|
||||
$scope.control.value = model.embed.preview;
|
||||
$scope.trustedValue = $sce.trustAsHtml(model.embed.preview);
|
||||
editorService.close();
|
||||
},
|
||||
close: function() {
|
||||
@@ -28,6 +29,5 @@ angular.module("umbraco")
|
||||
};
|
||||
editorService.embed(embed);
|
||||
};
|
||||
|
||||
onInit();
|
||||
|
||||
});
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<div ng-controller="Umbraco.PropertyEditors.Grid.EmbedController">
|
||||
|
||||
<div class="umb-editor-placeholder" ng-click="setEmbed()" ng-if="trustedValue === null">
|
||||
<div class="umb-editor-placeholder" ng-click="setEmbed()" ng-if="control.value === null">
|
||||
<i class="icon icon-movie-alt"></i>
|
||||
<div class="help-text"><localize key="grid_clickToEmbed">Click to embed</localize></div>
|
||||
</div>
|
||||
|
||||
<div ng-if="control.value" ng-bind-html="trustedValue"></div>
|
||||
<div ng-if="control.value" ng-bind-html="embedHtml"></div>
|
||||
|
||||
</div>
|
||||
|
||||
+22
-18
@@ -1,20 +1,18 @@
|
||||
angular.module("umbraco")
|
||||
.controller("Umbraco.PropertyEditors.Grid.MediaController",
|
||||
function ($scope, $timeout, userService, editorService) {
|
||||
|
||||
|
||||
|
||||
$scope.thumbnailUrl = getThumbnailUrl();
|
||||
|
||||
|
||||
if (!$scope.model.config.startNodeId) {
|
||||
userService.getCurrentUser().then(function (userData) {
|
||||
$scope.model.config.startNodeId = userData.startMediaIds.length !== 1 ? -1 : userData.startMediaIds[0];
|
||||
$scope.model.config.startNodeIsVirtual = userData.startMediaIds.length !== 1;
|
||||
});
|
||||
}
|
||||
|
||||
function onInit() {
|
||||
if($scope.control.value){
|
||||
$scope.setUrl();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$scope.setImage = function(){
|
||||
var startNodeId = $scope.model.config && $scope.model.config.startNodeId ? $scope.model.config.startNodeId : undefined;
|
||||
var startNodeIsVirtual = startNodeId ? $scope.model.config.startNodeIsVirtual : undefined;
|
||||
@@ -34,10 +32,8 @@ angular.module("umbraco")
|
||||
id: selectedImage.id,
|
||||
udi: selectedImage.udi,
|
||||
image: selectedImage.image,
|
||||
altText: selectedImage.altText
|
||||
};
|
||||
|
||||
$scope.setUrl();
|
||||
caption: selectedImage.altText
|
||||
};
|
||||
|
||||
editorService.close();
|
||||
},
|
||||
@@ -48,10 +44,18 @@ angular.module("umbraco")
|
||||
|
||||
editorService.mediaPicker(mediaPicker);
|
||||
};
|
||||
|
||||
$scope.$watch('control.value', function(newValue, oldValue) {
|
||||
if(angular.equals(newValue, oldValue)){
|
||||
return; // simply skip that
|
||||
}
|
||||
|
||||
$scope.thumbnailUrl = getThumbnailUrl();
|
||||
}, true);
|
||||
|
||||
function getThumbnailUrl() {
|
||||
|
||||
$scope.setUrl = function(){
|
||||
|
||||
if($scope.control.value.image){
|
||||
if($scope.control.value && $scope.control.value.image) {
|
||||
var url = $scope.control.value.image;
|
||||
|
||||
if($scope.control.editor.config && $scope.control.editor.config.size){
|
||||
@@ -70,10 +74,10 @@ angular.module("umbraco")
|
||||
{
|
||||
url += "?width=800&upscale=false&animationprocessmode=false"
|
||||
}
|
||||
$scope.url = url;
|
||||
return url;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
onInit();
|
||||
|
||||
});
|
||||
|
||||
@@ -5,11 +5,10 @@
|
||||
<div ng-id="!control.$inserted" class="help-text"><localize key="grid_clickToInsertImage">Click to insert image</localize></div>
|
||||
</div>
|
||||
|
||||
<div ng-if="control.value">
|
||||
<div ng-if="thumbnailUrl !== null">
|
||||
<img
|
||||
ng-if="url"
|
||||
ng-click="setImage()"
|
||||
ng-src="{{url}}"
|
||||
ng-src="{{thumbnailUrl}}"
|
||||
class="fullSizeImage" />
|
||||
<input type="text" class="caption" ng-model="control.value.caption" localize="placeholder" placeholder="@grid_placeholderImageCaption" />
|
||||
</div>
|
||||
|
||||
@@ -13,11 +13,16 @@ angular.module("umbraco")
|
||||
// Grid status variables
|
||||
var placeHolder = "";
|
||||
var currentForm = angularHelper.getCurrentForm($scope);
|
||||
|
||||
|
||||
$scope.currentRowWithActiveChild = null;
|
||||
$scope.currentCellWithActiveChild = null;
|
||||
$scope.active = null;
|
||||
|
||||
$scope.currentRow = null;
|
||||
$scope.currentCell = null;
|
||||
$scope.currentToolsControl = null;
|
||||
$scope.currentControl = null;
|
||||
|
||||
$scope.openRTEToolbarId = null;
|
||||
$scope.hasSettings = false;
|
||||
$scope.showRowConfigurations = true;
|
||||
@@ -237,10 +242,13 @@ angular.module("umbraco")
|
||||
});
|
||||
|
||||
$scope.$apply(function () {
|
||||
|
||||
var cell = event.target.getScope_HackForSortable().area;
|
||||
cell.hasActiveChild = hasActiveChild(cell, cell.controls);
|
||||
cell.active = false;
|
||||
|
||||
if(hasActiveChild(cell, cell.controls)) {
|
||||
$scope.currentCellWithActiveChild = cell;
|
||||
}
|
||||
$scope.active = cell;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@@ -309,12 +317,12 @@ angular.module("umbraco")
|
||||
// Row management function
|
||||
// *********************************************
|
||||
|
||||
$scope.clickRow = function (index, rows) {
|
||||
rows[index].active = true;
|
||||
};
|
||||
|
||||
$scope.clickOutsideRow = function (index, rows) {
|
||||
rows[index].active = false;
|
||||
$scope.clickRow = function(index, rows, $event) {
|
||||
|
||||
$scope.currentRowWithActiveChild = null;
|
||||
$scope.active = rows[index];
|
||||
|
||||
$event.stopPropagation();
|
||||
};
|
||||
|
||||
function getAllowedLayouts(section) {
|
||||
@@ -361,6 +369,7 @@ angular.module("umbraco")
|
||||
if (section.rows.length > 0) {
|
||||
section.rows.splice($index, 1);
|
||||
$scope.currentRow = null;
|
||||
$scope.currentRowWithActiveChild = null;
|
||||
$scope.openRTEToolbarId = null;
|
||||
currentForm.$setDirty();
|
||||
}
|
||||
@@ -515,14 +524,13 @@ angular.module("umbraco")
|
||||
// Area management functions
|
||||
// *********************************************
|
||||
|
||||
$scope.clickCell = function (index, cells, row) {
|
||||
cells[index].active = true;
|
||||
row.hasActiveChild = true;
|
||||
};
|
||||
|
||||
$scope.clickOutsideCell = function (index, cells, row) {
|
||||
cells[index].active = false;
|
||||
row.hasActiveChild = hasActiveChild(row, cells);
|
||||
$scope.clickCell = function(index, cells, row, $event) {
|
||||
|
||||
$scope.currentCellWithActiveChild = null;
|
||||
|
||||
$scope.active = cells[index];
|
||||
$scope.currentRowWithActiveChild = row;
|
||||
$event.stopPropagation();
|
||||
};
|
||||
|
||||
$scope.cellPreview = function (cell) {
|
||||
@@ -538,14 +546,12 @@ angular.module("umbraco")
|
||||
// *********************************************
|
||||
// Control management functions
|
||||
// *********************************************
|
||||
$scope.clickControl = function (index, controls, cell) {
|
||||
controls[index].active = true;
|
||||
cell.hasActiveChild = true;
|
||||
};
|
||||
|
||||
$scope.clickOutsideControl = function (index, controls, cell) {
|
||||
controls[index].active = false;
|
||||
cell.hasActiveChild = hasActiveChild(cell, controls);
|
||||
$scope.clickControl = function (index, controls, cell, $event) {
|
||||
|
||||
$scope.active = controls[index];
|
||||
$scope.currentCellWithActiveChild = cell;
|
||||
|
||||
$event.stopPropagation();
|
||||
};
|
||||
|
||||
function hasActiveChild(item, children) {
|
||||
@@ -596,8 +602,8 @@ angular.module("umbraco")
|
||||
if (index === undefined) {
|
||||
index = cell.controls.length;
|
||||
}
|
||||
|
||||
newControl.active = true;
|
||||
|
||||
$scope.active = newControl;
|
||||
|
||||
//populate control
|
||||
$scope.initControl(newControl, index + 1);
|
||||
|
||||
@@ -68,13 +68,13 @@
|
||||
<!-- ng-mouseleave="disableCurrentRow()" -->
|
||||
<div class="umb-row"
|
||||
ng-repeat="row in section.rows"
|
||||
ng-click="clickRow($index, section.rows)"
|
||||
ng-click="clickRow($index, section.rows, $event)"
|
||||
ng-class="{
|
||||
'-has-config': row.hasConfig,
|
||||
'-active': row.active,
|
||||
'-active-child': row.hasActiveChild}"
|
||||
on-outside-click="clickOutsideRow($index, section.rows)"
|
||||
bind-click-on="{{row.active}}"
|
||||
'-active': row === active,
|
||||
'-active-child': row === currentRowWithActiveChild}"
|
||||
|
||||
bind-click-on="{{row === active || row === currentRowWithActiveChild}}"
|
||||
data-rowid="{{row.$uniqueId}}">
|
||||
|
||||
<div class="umb-row-title-bar">
|
||||
@@ -88,7 +88,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Row tool -->
|
||||
<div class="umb-tools row-tools" ng-show="row.active && !sortMode">
|
||||
<div class="umb-tools row-tools" ng-show="(row === active || row === currentRowWithActiveChild) && !sortMode">
|
||||
|
||||
<div class="cell-tools-edit row-tool" ng-if="hasSettings">
|
||||
<i class="icon icon-settings" title="@grid_settings" localize="title" ng-click="editGridItemSettings(row, 'row')"></i>
|
||||
@@ -122,17 +122,17 @@
|
||||
ng-style="{width: area.$percentage + '%'}"
|
||||
ng-class="{
|
||||
'-has-config': area.hasConfig,
|
||||
'-active': area.active,
|
||||
'-active-child': area.hasActiveChild}"
|
||||
'-active': area === active,
|
||||
'-active-child': area === currentCellWithActiveChild}"
|
||||
ng-model="area.controls"
|
||||
ng-click="clickCell($index, row.areas, row)"
|
||||
on-outside-click="clickOutsideCell($index, row.areas, row)"
|
||||
bind-click-on="{{area.active}}">
|
||||
ng-click="clickCell($index, row.areas, row, $event)"
|
||||
|
||||
bind-click-on="{{area === active}}">
|
||||
|
||||
<!-- Cell -->
|
||||
<div class="umb-cell-content"
|
||||
ng-class="
|
||||
{'-active': area.active,
|
||||
{'-active': area === active,
|
||||
'-has-editors': area.controls.length > 0,
|
||||
'-collapsed': sortMode}">
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
<localize key="grid_settingsApplied" />
|
||||
</div>
|
||||
|
||||
<div class="cell-tools" ng-if="area.active && !sortMode">
|
||||
<div class="cell-tools" ng-if="(area === active || area === currentCellWithActiveChild) && !sortMode">
|
||||
<div class="cell-tool" ng-click="editGridItemSettings(area, 'cell')">
|
||||
<i class="icon-settings"></i>
|
||||
</div>
|
||||
@@ -172,14 +172,14 @@
|
||||
<div class="umb-control"
|
||||
umb-grid-hack-scope
|
||||
ng-repeat="control in area.controls"
|
||||
ng-click="clickControl($index, area.controls, area)"
|
||||
ng-class="{'-active': control.active}"
|
||||
on-outside-click="clickOutsideControl($index, area.controls, area)"
|
||||
bind-click-on="{{control.active}}"
|
||||
ng-click="clickControl($index, area.controls, area, $event)"
|
||||
ng-class="{'-active': control === active}"
|
||||
|
||||
bind-click-on="{{control === active}}"
|
||||
umb-set-dirty-on-change="{{control.value}}"
|
||||
data-itemid="{{control.$uniqueId}}">
|
||||
|
||||
<div class="umb-control-click-overlay" ng-show="!control.active && !sortMode"></div>
|
||||
<div class="umb-control-click-overlay" ng-show="control !== active && !sortMode"></div>
|
||||
|
||||
<div class="umb-control-collapsed umb-control-handle" ng-show="sortMode">
|
||||
{{control.editor.name}}
|
||||
@@ -189,11 +189,11 @@
|
||||
|
||||
<div class="umb-control-bar umb-control-handle">
|
||||
|
||||
<div class="umb-control-title" ng-if="control.active">
|
||||
<div class="umb-control-title" ng-if="control === active">
|
||||
{{control.editor.name}}
|
||||
</div>
|
||||
|
||||
<div class="umb-tools" ng-if="control.active">
|
||||
<div class="umb-tools" ng-if="control === active">
|
||||
|
||||
<div class="umb-control-tool" ng-if="control.editor.config.settings">
|
||||
<i class="umb-control-tool-icon icon-settings" ng-click="editGridItemSettings(control, 'control')"></i>
|
||||
|
||||
@@ -9,9 +9,7 @@ angular.module("umbraco")
|
||||
//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.
|
||||
var d = new Date();
|
||||
var n = d.getTime();
|
||||
$scope.textAreaHtmlId = $scope.model.alias + "_" + n + "_rte";
|
||||
$scope.textAreaHtmlId = $scope.model.alias + "_" + String.CreateGuid();
|
||||
|
||||
var editorConfig = $scope.model.config ? $scope.model.config.editor : null;
|
||||
if (!editorConfig || angular.isString(editorConfig)) {
|
||||
|
||||
+5
-19
@@ -13,25 +13,11 @@ function textAreaController($scope) {
|
||||
$scope.model.maxlength = false;
|
||||
if ($scope.model.config && $scope.model.config.maxChars) {
|
||||
$scope.model.maxlength = true;
|
||||
if($scope.model.value == undefined) {
|
||||
$scope.model.count = ($scope.model.config.maxChars * 1);
|
||||
} else {
|
||||
$scope.model.count = ($scope.model.config.maxChars * 1) - $scope.model.value.length;
|
||||
}
|
||||
}
|
||||
|
||||
$scope.model.change = function() {
|
||||
if ($scope.model.config && $scope.model.config.maxChars) {
|
||||
if($scope.model.value == undefined) {
|
||||
$scope.model.count = ($scope.model.config.maxChars * 1);
|
||||
} else {
|
||||
$scope.model.count = ($scope.model.config.maxChars * 1) - $scope.model.value.length;
|
||||
}
|
||||
if($scope.model.count < 0) {
|
||||
$scope.model.value = $scope.model.value.substring(0, ($scope.model.config.maxChars * 1));
|
||||
$scope.model.count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
$scope.model.change = function () {
|
||||
$scope.model.count = $scope.model.value.length;
|
||||
}
|
||||
$scope.model.change();
|
||||
}
|
||||
angular.module('umbraco').controller("Umbraco.PropertyEditors.textAreaController", textAreaController);
|
||||
angular.module('umbraco').controller("Umbraco.PropertyEditors.textAreaController", textAreaController);
|
||||
|
||||
@@ -7,9 +7,12 @@
|
||||
<span class="help-inline" ng-message="valServer">{{textareaFieldForm.textarea.errorMsg}}</span>
|
||||
</span>
|
||||
|
||||
<div class="help" ng-if="model.maxlength">
|
||||
<strong>{{model.count}}</strong>
|
||||
<localize key="textbox_characters_left">characters left</localize>
|
||||
<div class="help" ng-if="model.maxlength === true && model.count >= (model.config.maxChars*.8) && model.count <= model.config.maxChars">
|
||||
<localize key="textbox_characters_left" tokens="[model.config.maxChars - model.count]" watch-tokens="true">%0% characters left.</localize>
|
||||
</div>
|
||||
<div class="help text-error" ng-if="model.maxlength === true && model.count > model.config.maxChars">
|
||||
<localize key="textbox_characters_exceed" tokens="[model.config.maxChars, model.count - model.config.maxChars]" watch-tokens="true">Maximum %0% characters, <strong>%1%</strong> too many.</localize>
|
||||
</div>
|
||||
|
||||
</ng-form>
|
||||
</div>
|
||||
|
||||
@@ -4,39 +4,18 @@ function textboxController($scope) {
|
||||
if (!$scope.model.config) {
|
||||
$scope.model.config = {};
|
||||
}
|
||||
|
||||
$scope.model.maxlength = false;
|
||||
if ($scope.model.config && $scope.model.config.maxChars) {
|
||||
$scope.model.maxlength = true;
|
||||
}
|
||||
|
||||
|
||||
if (!$scope.model.config.maxChars) {
|
||||
// 500 is the maximum number that can be stored
|
||||
// in the database, so set it to the max, even
|
||||
// if no max is specified in the config
|
||||
$scope.model.config.maxChars = 500;
|
||||
}
|
||||
|
||||
if ($scope.model.maxlength) {
|
||||
if ($scope.model.value === undefined) {
|
||||
$scope.model.count = ($scope.model.config.maxChars * 1);
|
||||
} else {
|
||||
$scope.model.count = ($scope.model.config.maxChars * 1) - $scope.model.value.length;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$scope.model.change = function () {
|
||||
if ($scope.model.config && $scope.model.config.maxChars) {
|
||||
if ($scope.model.value === undefined) {
|
||||
$scope.model.count = ($scope.model.config.maxChars * 1);
|
||||
} else {
|
||||
$scope.model.count = ($scope.model.config.maxChars * 1) - $scope.model.value.length;
|
||||
}
|
||||
if ($scope.model.count < 0) {
|
||||
$scope.model.value = $scope.model.value.substring(0, ($scope.model.config.maxChars * 1));
|
||||
$scope.model.count = 0;
|
||||
}
|
||||
}
|
||||
$scope.model.count = $scope.model.value.length;
|
||||
}
|
||||
$scope.model.change();
|
||||
|
||||
}
|
||||
angular.module('umbraco').controller("Umbraco.PropertyEditors.textboxController", textboxController);
|
||||
|
||||
@@ -12,9 +12,12 @@
|
||||
<span class="help-inline" ng-message="required"><localize key="general_required">Required</localize></span>
|
||||
</span>
|
||||
|
||||
<div class="help" ng-if="model.maxlength">
|
||||
<strong>{{model.count}}</strong>
|
||||
<localize key="textbox_characters_left">characters left</localize>
|
||||
<div class="help" ng-if="model.count >= (model.config.maxChars*.8) && model.count <= model.config.maxChars">
|
||||
<localize key="textbox_characters_left" tokens="[model.config.maxChars - model.count]" watch-tokens="true">%0% characters left.</localize>
|
||||
</div>
|
||||
<div class="help text-error" ng-if="model.count > model.config.maxChars">
|
||||
<localize key="textbox_characters_exceed" tokens="[model.config.maxChars, model.count - model.config.maxChars]" watch-tokens="true">Maximum %0% characters, <strong>%1%</strong> too many.</localize>
|
||||
</div>
|
||||
|
||||
</ng-form>
|
||||
</div>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<base href="@ViewBag.UmbracoBaseFolder/" />
|
||||
<base href="@ViewData.GetUmbracoBaseFolder()/" />
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
@@ -66,8 +66,8 @@
|
||||
var Umbraco = {};
|
||||
Umbraco.Sys = {};
|
||||
Umbraco.Sys.ServerVariables = {
|
||||
"installApiBaseUrl": "@ViewBag.InstallApiBaseUrl",
|
||||
"umbracoBaseUrl": "@ViewBag.UmbracoBaseFolder"
|
||||
"installApiBaseUrl": "@ViewData.GetInstallApiBaseUrl()",
|
||||
"umbracoBaseUrl": "@ViewData.GetUmbracoBaseFolder()"
|
||||
};
|
||||
</script>
|
||||
<script src="lib/lazyload-js/lazyload.min.js"></script>
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
@{
|
||||
var externalLoginUrl = Url.Action("ExternalLogin", "BackOffice", new
|
||||
{
|
||||
area = ViewBag.UmbracoPath,
|
||||
area = ViewData.GetUmbracoPath(),
|
||||
//Custom redirect URL since we don't want to just redirect to the back office since this is for authing upgrades
|
||||
redirectUrl = Url.Action("AuthorizeUpgrade", "BackOffice")
|
||||
});
|
||||
@@ -61,7 +61,7 @@
|
||||
<script type="text/javascript">
|
||||
document.angularReady = function (app) {
|
||||
|
||||
@Html.AngularValueExternalLoginInfoScript((IEnumerable<string>)ViewBag.ExternalSignInError)
|
||||
@Html.AngularValueExternalLoginInfoScript(ViewData.GetExternalSignInError())
|
||||
@Html.AngularValueResetPasswordCodeInfoScript(ViewData["PasswordResetCode"])
|
||||
|
||||
}
|
||||
|
||||
@@ -112,12 +112,12 @@
|
||||
on-login="hideLoginScreen()">
|
||||
</umb-login>
|
||||
|
||||
@Html.BareMinimumServerVariablesScript(Url, Url.Action("ExternalLogin", "BackOffice", new { area = ViewBag.UmbracoPath }), Model.Features, Current.Configs.Global())
|
||||
@Html.BareMinimumServerVariablesScript(Url, Url.Action("ExternalLogin", "BackOffice", new { area = ViewData.GetUmbracoPath() }), Model.Features, Current.Configs.Global())
|
||||
|
||||
<script>
|
||||
|
||||
document.angularReady = function(app) {
|
||||
@Html.AngularValueExternalLoginInfoScript((IEnumerable<string>)ViewBag.ExternalSignInError)
|
||||
@Html.AngularValueExternalLoginInfoScript(ViewData.GetExternalSignInError())
|
||||
@Html.AngularValueResetPasswordCodeInfoScript(ViewData["PasswordResetCode"])
|
||||
//required for the noscript trick
|
||||
document.getElementById("mainwrapper").style.display = "inherit";
|
||||
|
||||
@@ -1568,8 +1568,9 @@ Mange hilsner fra Umbraco robotten
|
||||
<area alias="emptyStates">
|
||||
<key alias="emptyDictionaryTree">Ingen ordbog elementer at vælge imellem</key>
|
||||
</area>
|
||||
<area alias="textbox">
|
||||
<key alias="characters_left">Karakterer tilbage</key>
|
||||
<area alias="textbox">
|
||||
<key alias="characters_left"><![CDATA[<strong>%0%</strong> tegn tilbage.]]></key>
|
||||
<key alias="characters_exceed"><![CDATA[Maksimum %0% tegn, <strong>%1%</strong> for mange.]]></key>
|
||||
</area>
|
||||
<area alias="recycleBin">
|
||||
<key alias="contentTrashed">Slettet indhold med Id: {0} Relateret til original "parent" med id: {1}</key>
|
||||
|
||||
@@ -2078,8 +2078,9 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<area alias="emptyStates">
|
||||
<key alias="emptyDictionaryTree">No Dictionary items to choose from</key>
|
||||
</area>
|
||||
<area alias="textbox">
|
||||
<key alias="characters_left">characters left</key>
|
||||
<area alias="textbox">
|
||||
<key alias="characters_left"><![CDATA[<strong>%0%</strong> characters left.]]></key>
|
||||
<key alias="characters_exceed"><![CDATA[Maximum %0% characters, <strong>%1%</strong> too many.]]></key>
|
||||
</area>
|
||||
<area alias="recycleBin">
|
||||
<key alias="contentTrashed">Trashed content with Id: {0} related to original parent content with Id: {1}</key>
|
||||
|
||||
@@ -2090,8 +2090,9 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<area alias="emptyStates">
|
||||
<key alias="emptyDictionaryTree">No Dictionary items to choose from</key>
|
||||
</area>
|
||||
<area alias="textbox">
|
||||
<key alias="characters_left">characters left</key>
|
||||
<area alias="textbox">
|
||||
<key alias="characters_left"><![CDATA[<strong>%0%</strong> characters left.]]></key>
|
||||
<key alias="characters_exceed"><![CDATA[Maximum %0% characters, <strong>%1%</strong> too many.]]></key>
|
||||
</area>
|
||||
<area alias="recycleBin">
|
||||
<key alias="contentTrashed">Trashed content with Id: {0} related to original parent content with Id: {1}</key>
|
||||
|
||||
@@ -27,9 +27,8 @@ namespace Umbraco.Web
|
||||
private readonly IUmbracoDatabaseFactory _databaseFactory;
|
||||
|
||||
public BatchedDatabaseServerMessenger(
|
||||
IRuntimeState runtime, IUmbracoDatabaseFactory databaseFactory, IScopeProvider scopeProvider, ISqlContext sqlContext, IProfilingLogger proflog, IGlobalSettings globalSettings,
|
||||
bool enableDistCalls, DatabaseServerMessengerOptions options)
|
||||
: base(runtime, scopeProvider, sqlContext, proflog, globalSettings, enableDistCalls, options)
|
||||
IRuntimeState runtime, IUmbracoDatabaseFactory databaseFactory, IScopeProvider scopeProvider, ISqlContext sqlContext, IProfilingLogger proflog, IGlobalSettings globalSettings, DatabaseServerMessengerOptions options)
|
||||
: base(runtime, scopeProvider, sqlContext, proflog, globalSettings, true, options)
|
||||
{
|
||||
_databaseFactory = databaseFactory;
|
||||
}
|
||||
|
||||
@@ -38,54 +38,44 @@ namespace Umbraco.Web.Compose
|
||||
|
||||
public sealed class DatabaseServerRegistrarAndMessengerComposer : ComponentComposer<DatabaseServerRegistrarAndMessengerComponent>, ICoreComposer
|
||||
{
|
||||
public static DatabaseServerMessengerOptions GetDefaultOptions(IFactory factory)
|
||||
{
|
||||
var logger = factory.GetInstance<ILogger>();
|
||||
var indexRebuilder = factory.GetInstance<IndexRebuilder>();
|
||||
|
||||
return new DatabaseServerMessengerOptions
|
||||
{
|
||||
//These callbacks will be executed if the server has not been synced
|
||||
// (i.e. it is a new server or the lastsynced.txt file has been removed)
|
||||
InitializingCallbacks = new Action[]
|
||||
{
|
||||
//rebuild the xml cache file if the server is not synced
|
||||
() =>
|
||||
{
|
||||
// rebuild the published snapshot caches entirely, if the server is not synced
|
||||
// this is equivalent to DistributedCache RefreshAll... but local only
|
||||
// (we really should have a way to reuse RefreshAll... locally)
|
||||
// note: refresh all content & media caches does refresh content types too
|
||||
var svc = Current.PublishedSnapshotService;
|
||||
svc.Notify(new[] { new DomainCacheRefresher.JsonPayload(0, DomainChangeTypes.RefreshAll) });
|
||||
svc.Notify(new[] { new ContentCacheRefresher.JsonPayload(0, TreeChangeTypes.RefreshAll) }, out _, out _);
|
||||
svc.Notify(new[] { new MediaCacheRefresher.JsonPayload(0, TreeChangeTypes.RefreshAll) }, out _);
|
||||
},
|
||||
|
||||
//rebuild indexes if the server is not synced
|
||||
// NOTE: This will rebuild ALL indexes including the members, if developers want to target specific
|
||||
// indexes then they can adjust this logic themselves.
|
||||
() => { ExamineComponent.RebuildIndexes(indexRebuilder, logger, false, 5000); }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public override void Compose(Composition composition)
|
||||
{
|
||||
base.Compose(composition);
|
||||
|
||||
composition.SetServerMessenger(factory =>
|
||||
{
|
||||
var runtime = factory.GetInstance<IRuntimeState>();
|
||||
var databaseFactory = factory.GetInstance<IUmbracoDatabaseFactory>();
|
||||
var globalSettings = factory.GetInstance<IGlobalSettings>();
|
||||
var proflog = factory.GetInstance<IProfilingLogger>();
|
||||
var scopeProvider = factory.GetInstance<IScopeProvider>();
|
||||
var sqlContext = factory.GetInstance<ISqlContext>();
|
||||
var logger = factory.GetInstance<ILogger>();
|
||||
var indexRebuilder = factory.GetInstance<IndexRebuilder>();
|
||||
|
||||
return new BatchedDatabaseServerMessenger(
|
||||
runtime, databaseFactory, scopeProvider, sqlContext, proflog, globalSettings,
|
||||
true,
|
||||
//Default options for web including the required callbacks to build caches
|
||||
new DatabaseServerMessengerOptions
|
||||
{
|
||||
//These callbacks will be executed if the server has not been synced
|
||||
// (i.e. it is a new server or the lastsynced.txt file has been removed)
|
||||
InitializingCallbacks = new Action[]
|
||||
{
|
||||
//rebuild the xml cache file if the server is not synced
|
||||
() =>
|
||||
{
|
||||
// rebuild the published snapshot caches entirely, if the server is not synced
|
||||
// this is equivalent to DistributedCache RefreshAll... but local only
|
||||
// (we really should have a way to reuse RefreshAll... locally)
|
||||
// note: refresh all content & media caches does refresh content types too
|
||||
var svc = Current.PublishedSnapshotService;
|
||||
svc.Notify(new[] { new DomainCacheRefresher.JsonPayload(0, DomainChangeTypes.RefreshAll) });
|
||||
svc.Notify(new[] { new ContentCacheRefresher.JsonPayload(0, TreeChangeTypes.RefreshAll) }, out _, out _);
|
||||
svc.Notify(new[] { new MediaCacheRefresher.JsonPayload(0, TreeChangeTypes.RefreshAll) }, out _);
|
||||
},
|
||||
|
||||
//rebuild indexes if the server is not synced
|
||||
// NOTE: This will rebuild ALL indexes including the members, if developers want to target specific
|
||||
// indexes then they can adjust this logic themselves.
|
||||
() =>
|
||||
{
|
||||
ExamineComponent.RebuildIndexes(indexRebuilder, logger, false, 5000);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
composition.SetDatabaseServerMessengerOptions(GetDefaultOptions);
|
||||
composition.SetServerMessenger<BatchedDatabaseServerMessenger>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +118,7 @@ namespace Umbraco.Web.Compose
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
{
|
||||
//We will start the whole process when a successful request is made
|
||||
if (_registrar != null || _messenger != null)
|
||||
UmbracoModule.RouteAttempt += RegisterBackgroundTasksOnce;
|
||||
|
||||
@@ -45,10 +45,6 @@ namespace Umbraco.Web.Editors
|
||||
private BackOfficeUserManager<BackOfficeIdentityUser> _userManager;
|
||||
private BackOfficeSignInManager _signInManager;
|
||||
|
||||
private const string TokenExternalSignInError = "ExternalSignInError";
|
||||
private const string TokenPasswordResetCode = "PasswordResetCode";
|
||||
private static readonly string[] TempDataTokenNames = { TokenExternalSignInError, TokenPasswordResetCode };
|
||||
|
||||
public BackOfficeController(ManifestParser manifestParser, UmbracoFeatures features, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper)
|
||||
: base(globalSettings, umbracoContextAccessor, services, appCaches, profilingLogger, umbracoHelper)
|
||||
{
|
||||
@@ -294,13 +290,13 @@ namespace Umbraco.Web.Editors
|
||||
if (result)
|
||||
{
|
||||
//Add a flag and redirect for it to be displayed
|
||||
TempData[TokenPasswordResetCode] = new ValidatePasswordResetCodeModel { UserId = userId, ResetCode = resetCode };
|
||||
TempData[ViewDataExtensions.TokenPasswordResetCode] = new ValidatePasswordResetCodeModel { UserId = userId, ResetCode = resetCode };
|
||||
return RedirectToLocal(Url.Action("Default", "BackOffice"));
|
||||
}
|
||||
}
|
||||
|
||||
//Add error and redirect for it to be displayed
|
||||
TempData[TokenPasswordResetCode] = new[] { Services.TextService.Localize("login/resetCodeExpired") };
|
||||
TempData[ViewDataExtensions.TokenPasswordResetCode] = new[] { Services.TextService.Localize("login/resetCodeExpired") };
|
||||
return RedirectToLocal(Url.Action("Default", "BackOffice"));
|
||||
}
|
||||
|
||||
@@ -314,7 +310,7 @@ namespace Umbraco.Web.Editors
|
||||
if (loginInfo == null)
|
||||
{
|
||||
//Add error and redirect for it to be displayed
|
||||
TempData[TokenExternalSignInError] = new[] { "An error occurred, could not get external login info" };
|
||||
TempData[ViewDataExtensions.TokenExternalSignInError] = new[] { "An error occurred, could not get external login info" };
|
||||
return RedirectToLocal(Url.Action("Default", "BackOffice"));
|
||||
}
|
||||
|
||||
@@ -325,7 +321,7 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
|
||||
//Add errors and redirect for it to be displayed
|
||||
TempData[TokenExternalSignInError] = result.Errors;
|
||||
TempData[ViewDataExtensions.TokenExternalSignInError] = result.Errors;
|
||||
return RedirectToLocal(Url.Action("Default", "BackOffice"));
|
||||
}
|
||||
|
||||
@@ -341,17 +337,12 @@ namespace Umbraco.Web.Editors
|
||||
if (defaultResponse == null) throw new ArgumentNullException("defaultResponse");
|
||||
if (externalSignInResponse == null) throw new ArgumentNullException("externalSignInResponse");
|
||||
|
||||
ViewBag.UmbracoPath = GlobalSettings.GetUmbracoMvcArea();
|
||||
ViewData.SetUmbracoPath(GlobalSettings.GetUmbracoMvcArea());
|
||||
|
||||
//check if there is the TempData with the any token name specified, if so, assign to view bag and render the view
|
||||
foreach (var tempDataTokenName in TempDataTokenNames)
|
||||
{
|
||||
if (TempData[tempDataTokenName] != null)
|
||||
{
|
||||
ViewData[tempDataTokenName] = TempData[tempDataTokenName];
|
||||
return defaultResponse();
|
||||
}
|
||||
}
|
||||
if (ViewData.FromTempData(TempData, ViewDataExtensions.TokenExternalSignInError) ||
|
||||
ViewData.FromTempData(TempData, ViewDataExtensions.TokenPasswordResetCode))
|
||||
return defaultResponse();
|
||||
|
||||
//First check if there's external login info, if there's not proceed as normal
|
||||
var loginInfo = await OwinContext.Authentication.GetExternalLoginInfoAsync(
|
||||
@@ -416,7 +407,7 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
if (await AutoLinkAndSignInExternalAccount(loginInfo, autoLinkOptions) == false)
|
||||
{
|
||||
ViewData[TokenExternalSignInError] = new[] { "The requested provider (" + loginInfo.Login.LoginProvider + ") has not been linked to an account" };
|
||||
ViewData.SetExternalSignInError(new[] { "The requested provider (" + loginInfo.Login.LoginProvider + ") has not been linked to an account" });
|
||||
}
|
||||
|
||||
//Remove the cookie otherwise this message will keep appearing
|
||||
@@ -440,7 +431,7 @@ namespace Umbraco.Web.Editors
|
||||
//we are allowing auto-linking/creating of local accounts
|
||||
if (loginInfo.Email.IsNullOrWhiteSpace())
|
||||
{
|
||||
ViewData[TokenExternalSignInError] = new[] { "The requested provider (" + loginInfo.Login.LoginProvider + ") has not provided an email address, the account cannot be linked." };
|
||||
ViewData.SetExternalSignInError(new[] { "The requested provider (" + loginInfo.Login.LoginProvider + ") has not provided an email address, the account cannot be linked." });
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -448,7 +439,7 @@ namespace Umbraco.Web.Editors
|
||||
var foundByEmail = Services.UserService.GetByEmail(loginInfo.Email);
|
||||
if (foundByEmail != null)
|
||||
{
|
||||
ViewData[TokenExternalSignInError] = new[] { "A user with this email address already exists locally. You will need to login locally to Umbraco and link this external provider: " + loginInfo.Login.LoginProvider };
|
||||
ViewData.SetExternalSignInError(new[] { "A user with this email address already exists locally. You will need to login locally to Umbraco and link this external provider: " + loginInfo.Login.LoginProvider });
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -477,21 +468,21 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
if (userCreationResult.Succeeded == false)
|
||||
{
|
||||
ViewData[TokenExternalSignInError] = userCreationResult.Errors;
|
||||
ViewData.SetExternalSignInError(userCreationResult.Errors);
|
||||
}
|
||||
else
|
||||
{
|
||||
var linkResult = await UserManager.AddLoginAsync(autoLinkUser.Id, loginInfo.Login);
|
||||
if (linkResult.Succeeded == false)
|
||||
{
|
||||
ViewData[TokenExternalSignInError] = linkResult.Errors;
|
||||
ViewData.SetExternalSignInError(linkResult.Errors);
|
||||
|
||||
//If this fails, we should really delete the user since it will be in an inconsistent state!
|
||||
var deleteResult = await UserManager.DeleteAsync(autoLinkUser);
|
||||
if (deleteResult.Succeeded == false)
|
||||
{
|
||||
//DOH! ... this isn't good, combine all errors to be shown
|
||||
ViewData[TokenExternalSignInError] = linkResult.Errors.Concat(deleteResult.Errors);
|
||||
ViewData.SetExternalSignInError(linkResult.Errors.Concat(deleteResult.Errors));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -94,7 +94,7 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
// if the parentId is root (-1) then we just need an empty string as we are
|
||||
// creating the path below and we don't want -1 in the path
|
||||
if (parentId == Core.Constants.System.Root.ToInvariantString())
|
||||
if (parentId == Core.Constants.System.RootString)
|
||||
{
|
||||
parentId = string.Empty;
|
||||
}
|
||||
@@ -276,7 +276,7 @@ namespace Umbraco.Web.Editors
|
||||
// Make sure that the root virtual path ends with '/'
|
||||
codeFileDisplay.VirtualPath = codeFileDisplay.VirtualPath.EnsureEndsWith("/");
|
||||
|
||||
if (id != Core.Constants.System.Root.ToInvariantString())
|
||||
if (id != Core.Constants.System.RootString)
|
||||
{
|
||||
codeFileDisplay.VirtualPath += id.TrimStart("/").EnsureEndsWith("/");
|
||||
//if it's not new then it will have a path, otherwise it won't
|
||||
|
||||
@@ -60,10 +60,10 @@ namespace Umbraco.Web.Install.Controllers
|
||||
}
|
||||
|
||||
// gen the install base url
|
||||
ViewBag.InstallApiBaseUrl = Url.GetUmbracoApiService("GetSetup", "InstallApi", "UmbracoInstall").TrimEnd("GetSetup");
|
||||
ViewData.SetInstallApiBaseUrl(Url.GetUmbracoApiService("GetSetup", "InstallApi", "UmbracoInstall").TrimEnd("GetSetup"));
|
||||
|
||||
// get the base umbraco folder
|
||||
ViewBag.UmbracoBaseFolder = IOHelper.ResolveUrl(SystemDirectories.Umbraco);
|
||||
ViewData.SetUmbracoBaseFolder(IOHelper.ResolveUrl(SystemDirectories.Umbraco));
|
||||
|
||||
_installHelper.InstallStatus(false, "");
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Umbraco.Web.Models.Trees
|
||||
[DataContract(Name = "node", Namespace = "")]
|
||||
public sealed class TreeRootNode : TreeNode
|
||||
{
|
||||
private static readonly string RootId = Core.Constants.System.Root.ToString(CultureInfo.InvariantCulture);
|
||||
private static readonly string RootId = Core.Constants.System.RootString;
|
||||
private bool _isGroup;
|
||||
private bool _isSingleNodeTree;
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace Umbraco.Web.Trees
|
||||
//if there are no trees defined for this section but the section is defined then we can have a simple
|
||||
//full screen section without trees
|
||||
var name = Services.TextService.Localize("sections/" + application);
|
||||
return TreeRootNode.CreateSingleTreeRoot(Constants.System.Root.ToInvariantString(), null, null, name, TreeNodeCollection.Empty, true);
|
||||
return TreeRootNode.CreateSingleTreeRoot(Constants.System.RootString, null, null, name, TreeNodeCollection.Empty, true);
|
||||
}
|
||||
|
||||
// handle request for a specific tree / or when there is only one tree
|
||||
@@ -114,7 +114,7 @@ namespace Umbraco.Web.Trees
|
||||
|
||||
// otherwise it's a section with all empty trees, aka a fullscreen section
|
||||
// todo is this true? what if we just failed to TryGetRootNode on all of them? SD: Yes it's true but we should check the result of TryGetRootNode and throw?
|
||||
return TreeRootNode.CreateSingleTreeRoot(Constants.System.Root.ToInvariantString(), null, null, name, TreeNodeCollection.Empty, true);
|
||||
return TreeRootNode.CreateSingleTreeRoot(Constants.System.RootString, null, null, name, TreeNodeCollection.Empty, true);
|
||||
}
|
||||
|
||||
// for many groups
|
||||
@@ -180,7 +180,7 @@ namespace Umbraco.Web.Trees
|
||||
var rootNode = await GetRootNode(tree, querystring);
|
||||
|
||||
var sectionRoot = TreeRootNode.CreateSingleTreeRoot(
|
||||
Constants.System.Root.ToInvariantString(),
|
||||
Constants.System.RootString,
|
||||
rootNode.ChildNodesUrl,
|
||||
rootNode.MenuUrl,
|
||||
rootNode.Name,
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Umbraco.Web.Trees
|
||||
var entities = Services.EntityService.GetChildren(Constants.System.Root, UmbracoObjectTypes.DocumentBlueprint).ToArray();
|
||||
|
||||
//check if we're rendering the root in which case we'll render the content types that have blueprints
|
||||
if (id == Constants.System.Root.ToInvariantString())
|
||||
if (id == Constants.System.RootString)
|
||||
{
|
||||
//get all blueprint content types
|
||||
var contentTypeAliases = entities.Select(x => ((ContentEntitySlim) x).ContentTypeAlias).Distinct();
|
||||
@@ -91,7 +91,7 @@ namespace Umbraco.Web.Trees
|
||||
{
|
||||
var menu = new MenuItemCollection();
|
||||
|
||||
if (id == Constants.System.Root.ToInvariantString())
|
||||
if (id == Constants.System.RootString)
|
||||
{
|
||||
// root actions
|
||||
menu.Items.Add<ActionNew>(Services.TextService, opensDialog: true);
|
||||
|
||||
@@ -109,7 +109,7 @@ namespace Umbraco.Web.Trees
|
||||
|
||||
protected override MenuItemCollection PerformGetMenuForNode(string id, FormDataCollection queryStrings)
|
||||
{
|
||||
if (id == Constants.System.Root.ToInvariantString())
|
||||
if (id == Constants.System.RootString)
|
||||
{
|
||||
var menu = new MenuItemCollection();
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ namespace Umbraco.Web.Trees
|
||||
{
|
||||
var nodes = new TreeNodeCollection();
|
||||
|
||||
var rootIdString = Constants.System.Root.ToString(CultureInfo.InvariantCulture);
|
||||
var rootIdString = Constants.System.RootString;
|
||||
var hasAccessToRoot = UserStartNodes.Contains(Constants.System.Root);
|
||||
|
||||
var startNodeId = queryStrings.HasKey(TreeQueryStringParameters.StartNodeId)
|
||||
@@ -256,7 +256,7 @@ namespace Umbraco.Web.Trees
|
||||
protected sealed override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings)
|
||||
{
|
||||
//check if we're rendering the root
|
||||
if (id == Constants.System.Root.ToInvariantString() && UserStartNodes.Contains(Constants.System.Root))
|
||||
if (id == Constants.System.RootString && UserStartNodes.Contains(Constants.System.Root))
|
||||
{
|
||||
var altStartId = string.Empty;
|
||||
|
||||
@@ -264,7 +264,7 @@ namespace Umbraco.Web.Trees
|
||||
altStartId = queryStrings.GetValue<string>(TreeQueryStringParameters.StartNodeId);
|
||||
|
||||
//check if a request has been made to render from a specific start node
|
||||
if (string.IsNullOrEmpty(altStartId) == false && altStartId != "undefined" && altStartId != Constants.System.Root.ToString(CultureInfo.InvariantCulture))
|
||||
if (string.IsNullOrEmpty(altStartId) == false && altStartId != "undefined" && altStartId != Constants.System.RootString)
|
||||
{
|
||||
id = altStartId;
|
||||
}
|
||||
@@ -272,7 +272,7 @@ namespace Umbraco.Web.Trees
|
||||
var nodes = GetTreeNodesInternal(id, queryStrings);
|
||||
|
||||
//only render the recycle bin if we are not in dialog and the start id id still the root
|
||||
if (IsDialog(queryStrings) == false && id == Constants.System.Root.ToInvariantString())
|
||||
if (IsDialog(queryStrings) == false && id == Constants.System.RootString)
|
||||
{
|
||||
nodes.Add(CreateTreeNode(
|
||||
RecycleBinId.ToInvariantString(),
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace Umbraco.Web.Trees
|
||||
{
|
||||
var menu = new MenuItemCollection();
|
||||
|
||||
if (id == Constants.System.Root.ToInvariantString())
|
||||
if (id == Constants.System.RootString)
|
||||
{
|
||||
//set the default to create
|
||||
menu.DefaultMenuAlias = ActionNew.ActionAlias;
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace Umbraco.Web.Trees
|
||||
{
|
||||
var menu = new MenuItemCollection();
|
||||
|
||||
if (id == Constants.System.Root.ToInvariantString())
|
||||
if (id == Constants.System.RootString)
|
||||
{
|
||||
//set the default to create
|
||||
menu.DefaultMenuAlias = ActionNew.ActionAlias;
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace Umbraco.Web.Trees
|
||||
|
||||
Func<IDictionaryItem, string> ItemSort() => item => item.ItemKey;
|
||||
|
||||
if (id == Constants.System.Root.ToInvariantString())
|
||||
if (id == Constants.System.RootString)
|
||||
{
|
||||
nodes.AddRange(
|
||||
Services.LocalizationService.GetRootDictionaryItems().OrderBy(ItemSort()).Select(
|
||||
@@ -104,7 +104,7 @@ namespace Umbraco.Web.Trees
|
||||
|
||||
menu.Items.Add<ActionNew>(Services.TextService, opensDialog: true);
|
||||
|
||||
if (id != Constants.System.Root.ToInvariantString())
|
||||
if (id != Constants.System.RootString)
|
||||
menu.Items.Add<ActionDelete>(Services.TextService, true, opensDialog: true);
|
||||
|
||||
menu.Items.Add(new RefreshNode(Services.TextService, true));
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace Umbraco.Web.Trees
|
||||
|
||||
protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings)
|
||||
{
|
||||
var path = string.IsNullOrEmpty(id) == false && id != Constants.System.Root.ToInvariantString()
|
||||
var path = string.IsNullOrEmpty(id) == false && id != Constants.System.RootString
|
||||
? HttpUtility.UrlDecode(id).TrimStart("/")
|
||||
: "";
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace Umbraco.Web.Trees
|
||||
{
|
||||
var root = base.CreateRootNode(queryStrings);
|
||||
//check if there are any children
|
||||
root.HasChildren = GetTreeNodes(Constants.System.Root.ToInvariantString(), queryStrings).Any();
|
||||
root.HasChildren = GetTreeNodes(Constants.System.RootString, queryStrings).Any();
|
||||
return root;
|
||||
}
|
||||
|
||||
@@ -139,14 +139,14 @@ namespace Umbraco.Web.Trees
|
||||
protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings)
|
||||
{
|
||||
//if root node no need to visit the filesystem so lets just create the menu and return it
|
||||
if (id == Constants.System.Root.ToInvariantString())
|
||||
if (id == Constants.System.RootString)
|
||||
{
|
||||
return GetMenuForRootNode(queryStrings);
|
||||
}
|
||||
|
||||
var menu = new MenuItemCollection();
|
||||
|
||||
var path = string.IsNullOrEmpty(id) == false && id != Constants.System.Root.ToInvariantString()
|
||||
var path = string.IsNullOrEmpty(id) == false && id != Constants.System.RootString
|
||||
? HttpUtility.UrlDecode(id).TrimStart("/")
|
||||
: "";
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Umbraco.Web.Trees
|
||||
{
|
||||
var nodes = new TreeNodeCollection();
|
||||
|
||||
if (id == Constants.System.Root.ToInvariantString())
|
||||
if (id == Constants.System.RootString)
|
||||
{
|
||||
foreach (var macro in Services.MacroService.GetAll())
|
||||
{
|
||||
@@ -50,7 +50,7 @@ namespace Umbraco.Web.Trees
|
||||
{
|
||||
var menu = new MenuItemCollection();
|
||||
|
||||
if (id == Constants.System.Root.ToInvariantString())
|
||||
if (id == Constants.System.RootString)
|
||||
{
|
||||
//Create the normal create action
|
||||
menu.Items.Add<ActionNew>(Services.TextService);
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace Umbraco.Web.Trees
|
||||
//set the default
|
||||
menu.DefaultMenuAlias = ActionNew.ActionAlias;
|
||||
|
||||
if (id == Constants.System.Root.ToInvariantString())
|
||||
if (id == Constants.System.RootString)
|
||||
{
|
||||
// if the user's start node is not the root then the only menu item to display is refresh
|
||||
if (UserStartNodes.Contains(Constants.System.Root) == false)
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace Umbraco.Web.Trees
|
||||
{
|
||||
var menu = new MenuItemCollection();
|
||||
|
||||
if (id == Constants.System.Root.ToInvariantString())
|
||||
if (id == Constants.System.RootString)
|
||||
{
|
||||
// set the default to create
|
||||
menu.DefaultMenuAlias = ActionNew.ActionAlias;
|
||||
|
||||
@@ -121,7 +121,7 @@ namespace Umbraco.Web.Trees
|
||||
{
|
||||
var nodes = new TreeNodeCollection();
|
||||
|
||||
if (id == Constants.System.Root.ToInvariantString())
|
||||
if (id == Constants.System.RootString)
|
||||
{
|
||||
nodes.Add(
|
||||
CreateTreeNode(Constants.Conventions.MemberTypes.AllMembersListId, id, queryStrings, Services.TextService.Localize("member/allMembers"), "icon-users", true,
|
||||
@@ -148,7 +148,7 @@ namespace Umbraco.Web.Trees
|
||||
{
|
||||
var menu = new MenuItemCollection();
|
||||
|
||||
if (id == Constants.System.Root.ToInvariantString())
|
||||
if (id == Constants.System.RootString)
|
||||
{
|
||||
// root actions
|
||||
if (_provider.IsUmbracoMembershipProvider())
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Umbraco.Web.Trees
|
||||
{
|
||||
var menu = new MenuItemCollection();
|
||||
|
||||
if (id == Constants.System.Root.ToInvariantString())
|
||||
if (id == Constants.System.RootString)
|
||||
{
|
||||
// root actions
|
||||
menu.Items.Add(new CreateChildEntity(Services.TextService));
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Umbraco.Web.Trees
|
||||
{
|
||||
var menu = new MenuItemCollection();
|
||||
|
||||
if (id == Constants.System.Root.ToInvariantString())
|
||||
if (id == Constants.System.RootString)
|
||||
{
|
||||
//Create the normal create action
|
||||
menu.Items.Add<ActionNew>(Services.TextService.Localize("actions", ActionNew.ActionAlias));
|
||||
@@ -41,7 +41,7 @@ namespace Umbraco.Web.Trees
|
||||
{
|
||||
var nodes = new TreeNodeCollection();
|
||||
|
||||
if (id == Constants.System.Root.ToInvariantString())
|
||||
if (id == Constants.System.RootString)
|
||||
{
|
||||
nodes.AddRange(Services.RelationService.GetAllRelationTypes()
|
||||
.Select(rt => CreateTreeNode(rt.Id.ToString(), id, queryStrings, rt.Name,
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Umbraco.Web.Trees
|
||||
{
|
||||
var nodes = new TreeNodeCollection();
|
||||
|
||||
var found = id == Constants.System.Root.ToInvariantString()
|
||||
var found = id == Constants.System.RootString
|
||||
? Services.FileService.GetTemplates(-1)
|
||||
: Services.FileService.GetTemplates(int.Parse(id));
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace Umbraco.Web.Trees
|
||||
var item = menu.Items.Add<ActionNew>(Services.TextService, opensDialog: true);
|
||||
item.NavigateToRoute($"{queryStrings.GetRequiredValue<string>("application")}/templates/edit/{id}?create=true");
|
||||
|
||||
if (id == Constants.System.Root.ToInvariantString())
|
||||
if (id == Constants.System.RootString)
|
||||
{
|
||||
//refresh action
|
||||
menu.Items.Add(new RefreshNode(Services.TextService, true));
|
||||
|
||||
@@ -173,7 +173,7 @@ namespace Umbraco.Web.Trees
|
||||
/// <returns></returns>
|
||||
protected virtual TreeNode CreateRootNode(FormDataCollection queryStrings)
|
||||
{
|
||||
var rootNodeAsString = Constants.System.Root.ToString(CultureInfo.InvariantCulture);
|
||||
var rootNodeAsString = Constants.System.RootString;
|
||||
var currApp = queryStrings.GetValue<string>(TreeQueryStringParameters.Application);
|
||||
|
||||
var node = new TreeNode(
|
||||
|
||||
@@ -216,6 +216,7 @@
|
||||
<Compile Include="Models\TemplateQuery\OperatorFactory.cs" />
|
||||
<Compile Include="UmbracoContextFactory.cs" />
|
||||
<Compile Include="UmbracoContextReference.cs" />
|
||||
<Compile Include="ViewDataExtensions.cs" />
|
||||
<Compile Include="WebApi\Filters\AdminUsersAuthorizeAttribute.cs" />
|
||||
<Compile Include="WebApi\Filters\OnlyLocalRequestsAttribute.cs" />
|
||||
<Compile Include="PropertyEditors\MultiUrlPickerConfiguration.cs" />
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Web.Mvc;
|
||||
|
||||
namespace Umbraco.Web
|
||||
{
|
||||
public static class ViewDataExtensions
|
||||
{
|
||||
public const string TokenUmbracoPath = "UmbracoPath";
|
||||
public const string TokenInstallApiBaseUrl = "InstallApiBaseUrl";
|
||||
public const string TokenUmbracoBaseFolder = "UmbracoBaseFolder";
|
||||
public const string TokenExternalSignInError = "ExternalSignInError";
|
||||
public const string TokenPasswordResetCode = "PasswordResetCode";
|
||||
|
||||
public static bool FromTempData(this ViewDataDictionary viewData, TempDataDictionary tempData, string token)
|
||||
{
|
||||
if (tempData[token] == null) return false;
|
||||
viewData[token] = tempData[token];
|
||||
return true;
|
||||
}
|
||||
|
||||
public static string GetUmbracoPath(this ViewDataDictionary viewData)
|
||||
{
|
||||
return (string)viewData[TokenUmbracoPath];
|
||||
}
|
||||
|
||||
public static void SetUmbracoPath(this ViewDataDictionary viewData, string value)
|
||||
{
|
||||
viewData[TokenUmbracoPath] = value;
|
||||
}
|
||||
|
||||
public static string GetInstallApiBaseUrl(this ViewDataDictionary viewData)
|
||||
{
|
||||
return (string)viewData[TokenInstallApiBaseUrl];
|
||||
}
|
||||
|
||||
public static void SetInstallApiBaseUrl(this ViewDataDictionary viewData, string value)
|
||||
{
|
||||
viewData[TokenInstallApiBaseUrl] = value;
|
||||
}
|
||||
|
||||
public static string GetUmbracoBaseFolder(this ViewDataDictionary viewData)
|
||||
{
|
||||
return (string)viewData[TokenUmbracoBaseFolder];
|
||||
}
|
||||
|
||||
public static void SetUmbracoBaseFolder(this ViewDataDictionary viewData, string value)
|
||||
{
|
||||
viewData[TokenUmbracoBaseFolder] = value;
|
||||
}
|
||||
|
||||
public static IEnumerable<string> GetExternalSignInError(this ViewDataDictionary viewData)
|
||||
{
|
||||
return (IEnumerable<string>)viewData[TokenExternalSignInError];
|
||||
}
|
||||
|
||||
public static void SetExternalSignInError(this ViewDataDictionary viewData, IEnumerable<string> value)
|
||||
{
|
||||
viewData[TokenExternalSignInError] = value;
|
||||
}
|
||||
|
||||
public static string GetPasswordResetCode(this ViewDataDictionary viewData)
|
||||
{
|
||||
return (string)viewData[TokenPasswordResetCode];
|
||||
}
|
||||
|
||||
public static void SetPasswordResetCode(this ViewDataDictionary viewData, string value)
|
||||
{
|
||||
viewData[TokenPasswordResetCode] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user