Compare commits
78 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d51082f651 | |||
| f2fb275b34 | |||
| c5f388f6bc | |||
| 4419af427b | |||
| dbdee5fc2c | |||
| 25f5179b29 | |||
| 1a03bd9624 | |||
| 6a1d60c5a7 | |||
| 4fef17190f | |||
| 143b9c605b | |||
| db809f30fe | |||
| dcb50d10c4 | |||
| a91a67ed8d | |||
| 1f3e568a0d | |||
| cb539e82d0 | |||
| 1432d602ba | |||
| 841d2a7010 | |||
| 7cdb48b6c9 | |||
| a667058422 | |||
| 4ffa6bb41b | |||
| 77af16db55 | |||
| 2a44b73056 | |||
| 85d85fa587 | |||
| bd27ed739d | |||
| 3938868115 | |||
| 140792430f | |||
| c04cf1fe2e | |||
| d1d83c84a0 | |||
| 98acc50e13 | |||
| 1a0a02463e | |||
| 96c499a47e | |||
| f7e8aefeab | |||
| dfa803293f | |||
| 7ade64f855 | |||
| 346e8dcaf0 | |||
| ddfd07bf4a | |||
| a9fe46da0c | |||
| aca1f0d186 | |||
| 9eb415d398 | |||
| 8f6b728534 | |||
| 2e0c09ab39 | |||
| f211344786 | |||
| f8764cdd20 | |||
| 1d17bfd59a | |||
| 98ad6ad366 | |||
| 68702b98f5 | |||
| f93caf277b | |||
| 32db674397 | |||
| e0a7698780 | |||
| 783c74d3ba | |||
| 96d7bc3898 | |||
| 21963c03a2 | |||
| a2a9794fdb | |||
| 879a132077 | |||
| 9650d314c6 | |||
| fcc0c452bb | |||
| 606ebcae92 | |||
| af10ae9e34 | |||
| a23c150738 | |||
| 085a678266 | |||
| c73fb6144b | |||
| 5a2b4f031b | |||
| cf7cafeb4c | |||
| 870657affa | |||
| fe11d4770d | |||
| ac75d8148d | |||
| 4a32cddf08 | |||
| 7461e7c55b | |||
| c8fe9030c7 | |||
| b90cccbfff | |||
| 22f0641c54 | |||
| e465a937c5 | |||
| d2164bc94d | |||
| df9d09725b | |||
| 0a56f46b12 | |||
| 972f9b3546 | |||
| 28ab176466 | |||
| 4093fd9b79 |
@@ -33,7 +33,7 @@
|
||||
<dependency id="ClientDependency-Mvc5" version="[1.8.0.0, 2.0.0)" />
|
||||
<dependency id="AutoMapper" version="[3.3.1, 4.0.0)" />
|
||||
<dependency id="Newtonsoft.Json" version="[9.0.1, 10.0.0)" />
|
||||
<dependency id="Examine" version="[0.1.81, 1.0.0)" />
|
||||
<dependency id="Examine" version="[0.1.82, 1.0.0)" />
|
||||
<dependency id="ImageProcessor" version="[2.5.2, 3.0.0)" />
|
||||
<dependency id="ImageProcessor.Web" version="[4.8.2, 5.0.0)" />
|
||||
<dependency id="semver" version="[2.0.4, 3.0.0)" />
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
<httpRuntime xdt:Transform="InsertIfMissing" />
|
||||
<httpRuntime maxRequestLength="51200" fcnMode="Single" xdt:Transform="SetAttributes(fcnMode,maxRequestLength)" />
|
||||
<httpRuntime targetFramework="4.5" xdt:Locator="Condition(count(@targetFramework) != 1)" xdt:Transform="SetAttributes(targetFramework)" />
|
||||
|
||||
|
||||
<membership defaultProvider="DefaultMembershipProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove" />
|
||||
<roleManager defaultProvider="DefaultRoleProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove"/>
|
||||
<profile defaultProvider="DefaultProfileProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove"/>>
|
||||
@@ -337,7 +337,7 @@
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="HtmlAgilityPack" publicKeyToken="bd319b19eaf3b43a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.4.9.0" newVersion="1.4.9.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.4.9.5" newVersion="1.4.9.5" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="AutoMapper" publicKeyToken="be96cd2c38ef1005" culture="neutral" />
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
|
||||
7.6.0
|
||||
beta05
|
||||
beta06
|
||||
|
||||
+1
-1
@@ -12,4 +12,4 @@ using System.Resources;
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.6.0")]
|
||||
[assembly: AssemblyInformationalVersion("7.6.0-beta05")]
|
||||
[assembly: AssemblyInformationalVersion("7.6.0-beta06")]
|
||||
@@ -17,9 +17,12 @@ namespace Umbraco.Core
|
||||
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
|
||||
}
|
||||
|
||||
private static readonly Regex Log4NetAssemblyPattern = new Regex("log4net, Version=([\\d\\.]+?), Culture=neutral, PublicKeyToken=null", RegexOptions.Compiled);
|
||||
private static readonly Regex Log4NetAssemblyPattern = new Regex("log4net, Version=([\\d\\.]+?), Culture=neutral, PublicKeyToken=null");
|
||||
private const string Log4NetReplacement = "log4net, Version=1.2.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a";
|
||||
|
||||
|
||||
private static readonly Regex HtmlAgilityAssemblyPattern = new Regex("HtmlAgilityPack, Version=([\\d\\.]+?), Culture=neutral, PublicKeyToken=bd319b19eaf3b43a");
|
||||
private const string HtmlAgilityReplacement = "HtmlAgilityPack, Version=1.4.9.5, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a";
|
||||
|
||||
/// <summary>
|
||||
/// This is used to do an assembly binding redirect via code - normally required due to signature changes in assemblies
|
||||
/// </summary>
|
||||
@@ -28,13 +31,18 @@ namespace Umbraco.Core
|
||||
/// <returns></returns>
|
||||
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
|
||||
{
|
||||
//log4net:
|
||||
// Use regex to match and replace
|
||||
//log4net:
|
||||
if (Log4NetAssemblyPattern.IsMatch(args.Name) && args.Name != Log4NetReplacement)
|
||||
{
|
||||
return Assembly.Load(Log4NetAssemblyPattern.Replace(args.Name, Log4NetReplacement));
|
||||
}
|
||||
|
||||
//HtmlAgility:
|
||||
if (HtmlAgilityAssemblyPattern.IsMatch(args.Name) && args.Name != HtmlAgilityReplacement)
|
||||
{
|
||||
return Assembly.Load(HtmlAgilityAssemblyPattern.Replace(args.Name, HtmlAgilityReplacement));
|
||||
}
|
||||
|
||||
//AutoMapper:
|
||||
// ensure the assembly is indeed AutoMapper and that the PublicKeyToken is null before trying to Load again
|
||||
// do NOT just replace this with 'return Assembly', as it will cause an infinite loop -> stackoverflow
|
||||
|
||||
@@ -26,6 +26,9 @@ namespace Umbraco.Core.Cache
|
||||
|
||||
public DeepCloneRuntimeCacheProvider(IRuntimeCacheProvider innerProvider)
|
||||
{
|
||||
if (innerProvider.GetType() == typeof(DeepCloneRuntimeCacheProvider))
|
||||
throw new InvalidOperationException("A " + typeof(DeepCloneRuntimeCacheProvider) + " cannot wrap another instance of " + typeof(DeepCloneRuntimeCacheProvider));
|
||||
|
||||
InnerProvider = innerProvider;
|
||||
}
|
||||
|
||||
@@ -105,9 +108,11 @@ namespace Umbraco.Core.Cache
|
||||
var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache
|
||||
if (value == null) return null; // do not store null values (backward compat)
|
||||
|
||||
//Clone/reset to go into the cache
|
||||
return CheckCloneableAndTracksChanges(value);
|
||||
}, timeout, isSliding, priority, removedCallback, dependentFiles);
|
||||
|
||||
//Clone/reset to go out of the cache
|
||||
return CheckCloneableAndTracksChanges(cached);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Umbraco.Core.Configuration
|
||||
/// Gets the version comment (like beta or RC).
|
||||
/// </summary>
|
||||
/// <value>The version comment.</value>
|
||||
public static string CurrentComment { get { return "beta05"; } }
|
||||
public static string CurrentComment { get { return "beta06"; } }
|
||||
|
||||
// Get the version of the umbraco.dll by looking at a class in that dll
|
||||
// Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx
|
||||
|
||||
@@ -274,6 +274,9 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
public bool HasPublishedVersion { get { return PublishedVersionGuid != default(Guid); } }
|
||||
|
||||
[IgnoreDataMember]
|
||||
internal DateTime PublishedDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Changes the Trashed state of the content object
|
||||
/// </summary>
|
||||
|
||||
@@ -19,5 +19,8 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
|
||||
[Column("newest")]
|
||||
public bool Newest { get; set; }
|
||||
|
||||
[Column("updateDate")]
|
||||
public DateTime VersionDate { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
private readonly string _httpContextKey;
|
||||
private readonly List<Type> _instanceTypes = new List<Type>();
|
||||
private IEnumerable<TResolved> _sortedValues;
|
||||
private readonly Func<HttpContextBase> _httpContextGetter;
|
||||
|
||||
private int _defaultPluginWeight = 100;
|
||||
|
||||
@@ -42,12 +43,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
if (logger == null) throw new ArgumentNullException("logger");
|
||||
CanResolveBeforeFrozen = false;
|
||||
if (scope == ObjectLifetimeScope.HttpRequest)
|
||||
{
|
||||
if (HttpContext.Current == null)
|
||||
throw new InvalidOperationException("Use alternative constructor accepting a HttpContextBase object in order to set the lifetime scope to HttpRequest when HttpContext.Current is null");
|
||||
|
||||
CurrentHttpContext = new HttpContextWrapper(HttpContext.Current);
|
||||
}
|
||||
_httpContextGetter = () => new HttpContextWrapper(HttpContext.Current);
|
||||
|
||||
ServiceProvider = serviceProvider;
|
||||
Logger = logger;
|
||||
@@ -84,7 +80,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
LifetimeScope = ObjectLifetimeScope.HttpRequest;
|
||||
_httpContextKey = GetType().FullName;
|
||||
ServiceProvider = serviceProvider;
|
||||
CurrentHttpContext = httpContext;
|
||||
_httpContextGetter = () => httpContext;
|
||||
_instanceTypes = new List<Type>();
|
||||
|
||||
InitializeAppInstances();
|
||||
@@ -160,7 +156,16 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// Gets or sets the <see cref="HttpContextBase"/> used to initialize this object, if any.
|
||||
/// </summary>
|
||||
/// <remarks>If not null, then <c>LifetimeScope</c> will be <c>ObjectLifetimeScope.HttpRequest</c>.</remarks>
|
||||
protected HttpContextBase CurrentHttpContext { get; private set; }
|
||||
protected HttpContextBase CurrentHttpContext
|
||||
{
|
||||
get
|
||||
{
|
||||
var context = _httpContextGetter == null ? null : _httpContextGetter();
|
||||
if (context == null)
|
||||
throw new InvalidOperationException("Cannot use this resolver with lifetime 'HttpRequest' when there is no current HttpContext. Either use the ctor accepting an HttpContextBase, or use the resolver from within a request exclusively.");
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the service provider used to instantiate objects
|
||||
@@ -196,7 +201,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// <summary>
|
||||
/// Gets or sets the default type weight.
|
||||
/// </summary>
|
||||
/// <remarks>Determines the weight of types that do not have a <c>WeightAttribute</c> set on
|
||||
/// <remarks>Determines the weight of types that do not have a <c>WeightAttribute</c> set on
|
||||
/// them, when calling <c>GetSortedValues</c>.</remarks>
|
||||
protected virtual int DefaultPluginWeight
|
||||
{
|
||||
@@ -276,7 +281,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// Removes a type.
|
||||
/// </summary>
|
||||
/// <param name="value">The type to remove.</param>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support removing types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support removing types, or
|
||||
/// the type is not a valid type for the resolver.</exception>
|
||||
public virtual void RemoveType(Type value)
|
||||
{
|
||||
@@ -296,7 +301,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// Removes a type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to remove.</typeparam>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support removing types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support removing types, or
|
||||
/// the type is not a valid type for the resolver.</exception>
|
||||
public void RemoveType<T>()
|
||||
where T : TResolved
|
||||
@@ -309,7 +314,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// </summary>
|
||||
/// <param name="types">The types to add.</param>
|
||||
/// <remarks>The types are appended at the end of the list.</remarks>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
|
||||
/// a type is not a valid type for the resolver, or a type is already in the collection of types.</exception>
|
||||
protected void AddTypes(IEnumerable<Type> types)
|
||||
{
|
||||
@@ -336,7 +341,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// </summary>
|
||||
/// <param name="value">The type to add.</param>
|
||||
/// <remarks>The type is appended at the end of the list.</remarks>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
|
||||
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
|
||||
public virtual void AddType(Type value)
|
||||
{
|
||||
@@ -362,7 +367,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to add.</typeparam>
|
||||
/// <remarks>The type is appended at the end of the list.</remarks>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
|
||||
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
|
||||
public void AddType<T>()
|
||||
where T : TResolved
|
||||
@@ -404,7 +409,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// </summary>
|
||||
/// <param name="index">The zero-based index at which the type should be inserted.</param>
|
||||
/// <param name="value">The type to insert.</param>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is out of range.</exception>
|
||||
public virtual void InsertType(int index, Type value)
|
||||
@@ -430,7 +435,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// Inserts a type at the beginning of the list.
|
||||
/// </summary>
|
||||
/// <param name="value">The type to insert.</param>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
|
||||
public virtual void InsertType(Type value)
|
||||
{
|
||||
@@ -464,7 +469,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// </summary>
|
||||
/// <param name="existingType">The existing type before which to insert.</param>
|
||||
/// <param name="value">The type to insert.</param>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||
/// one of the types is not a valid type for the resolver, or the existing type is not in the collection,
|
||||
/// or the new type is already in the collection of types.</exception>
|
||||
public virtual void InsertTypeBefore(Type existingType, Type value)
|
||||
@@ -498,7 +503,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// </summary>
|
||||
/// <typeparam name="TExisting">The existing type before which to insert.</typeparam>
|
||||
/// <typeparam name="T">The type to insert.</typeparam>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||
/// one of the types is not a valid type for the resolver, or the existing type is not in the collection,
|
||||
/// or the new type is already in the collection of types.</exception>
|
||||
public void InsertTypeBefore<TExisting, T>()
|
||||
|
||||
@@ -72,6 +72,9 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
content.PublishedVersionGuid = publishedDto == null
|
||||
? (dto.DocumentPublishedReadOnlyDto == null ? default(Guid) : dto.DocumentPublishedReadOnlyDto.VersionId)
|
||||
: publishedDto.VersionId;
|
||||
content.PublishedDate = publishedDto == null
|
||||
? (dto.DocumentPublishedReadOnlyDto == null ? default(DateTime) : dto.DocumentPublishedReadOnlyDto.VersionDate)
|
||||
: publishedDto.VersionDate;
|
||||
|
||||
//on initial construction we don't want to have dirty properties tracked
|
||||
// http://issues.umbraco.org/issue/U4-1946
|
||||
|
||||
@@ -513,11 +513,13 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
dto.DocumentPublishedReadOnlyDto = new DocumentPublishedReadOnlyDto
|
||||
{
|
||||
VersionId = dto.VersionId,
|
||||
VersionDate = dto.UpdateDate,
|
||||
Newest = true,
|
||||
NodeId = dto.NodeId,
|
||||
Published = true
|
||||
Published = true
|
||||
};
|
||||
((Content)entity).PublishedVersionGuid = dto.VersionId;
|
||||
((Content) entity).PublishedVersionGuid = dto.VersionId;
|
||||
((Content) entity).PublishedDate = dto.UpdateDate;
|
||||
}
|
||||
|
||||
entity.ResetDirtyProperties();
|
||||
@@ -688,22 +690,26 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
dto.DocumentPublishedReadOnlyDto = new DocumentPublishedReadOnlyDto
|
||||
{
|
||||
VersionId = dto.VersionId,
|
||||
VersionDate = dto.UpdateDate,
|
||||
Newest = true,
|
||||
NodeId = dto.NodeId,
|
||||
Published = true
|
||||
};
|
||||
((Content)entity).PublishedVersionGuid = dto.VersionId;
|
||||
((Content) entity).PublishedVersionGuid = dto.VersionId;
|
||||
((Content) entity).PublishedDate = dto.UpdateDate;
|
||||
}
|
||||
else if (publishedStateChanged)
|
||||
{
|
||||
dto.DocumentPublishedReadOnlyDto = new DocumentPublishedReadOnlyDto
|
||||
{
|
||||
VersionId = default(Guid),
|
||||
VersionId = default (Guid),
|
||||
VersionDate = default (DateTime),
|
||||
Newest = false,
|
||||
NodeId = dto.NodeId,
|
||||
Published = false
|
||||
};
|
||||
((Content)entity).PublishedVersionGuid = default(Guid);
|
||||
((Content) entity).PublishedVersionGuid = default(Guid);
|
||||
((Content) entity).PublishedDate = default (DateTime);
|
||||
}
|
||||
|
||||
entity.ResetDirtyProperties();
|
||||
@@ -975,7 +981,7 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder",
|
||||
}
|
||||
|
||||
//order by update date DESC, if there is corrupted published flags we only want the latest!
|
||||
var publishedSql = new Sql(@"SELECT cmsDocument.nodeId, cmsDocument.published, cmsDocument.versionId, cmsDocument.newest
|
||||
var publishedSql = new Sql(@"SELECT cmsDocument.nodeId, cmsDocument.published, cmsDocument.versionId, cmsDocument.updateDate, cmsDocument.newest
|
||||
FROM cmsDocument INNER JOIN cmsContentVersion ON cmsContentVersion.VersionId = cmsDocument.versionId
|
||||
WHERE cmsDocument.published = 1 AND cmsDocument.nodeId IN
|
||||
(" + parsedOriginalSql + @")
|
||||
|
||||
@@ -1252,5 +1252,19 @@ WHERE cmsContentType." + aliasColumn + @" LIKE @pattern",
|
||||
while (aliases.Contains(test = alias + i)) i++;
|
||||
return test;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given the path of a content item, this will return true if the content item exists underneath a list view content item
|
||||
/// </summary>
|
||||
/// <param name="contentPath"></param>
|
||||
/// <returns></returns>
|
||||
public bool HasContainerInPath(string contentPath)
|
||||
{
|
||||
var ids = contentPath.Split(',').Select(int.Parse);
|
||||
var sql = new Sql(@"SELECT COUNT(*) FROM cmsContentType
|
||||
INNER JOIN cmsContent ON cmsContentType.nodeId=cmsContent.contentType
|
||||
WHERE cmsContent.nodeId IN (@ids) AND cmsContentType.isContainer=@isContainer", new { ids, isContainer = true });
|
||||
return Database.ExecuteScalar<int>(sql) > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,47 +276,33 @@ AND umbracoNode.id <> @id",
|
||||
|
||||
public PreValueCollection GetPreValuesCollectionByDataTypeId(int dataTypeId)
|
||||
{
|
||||
var cached = IsolatedCache.GetCacheItemsByKeySearch<PreValueCollection>(GetPrefixedCacheKey(dataTypeId));
|
||||
if (cached != null && cached.Any())
|
||||
{
|
||||
//return from the cache, ensure it's a cloned result
|
||||
return (PreValueCollection)cached.First().DeepClone();
|
||||
}
|
||||
|
||||
return GetAndCachePreValueCollection(dataTypeId);
|
||||
}
|
||||
|
||||
internal static string GetCacheKeyRegex(int preValueId)
|
||||
{
|
||||
return CacheKeys.DataTypePreValuesCacheKey + @"[-\d]+-([\d]*,)*" + preValueId + @"(?!\d)[,\d$]*";
|
||||
var collection = GetCachedPreValueCollection(dataTypeId);
|
||||
return collection;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a specific PreValue by its Id
|
||||
/// </summary>
|
||||
/// <param name="preValueId">Id of the PreValue to retrieve the value from</param>
|
||||
/// <returns>PreValue as a string</returns>
|
||||
public string GetPreValueAsString(int preValueId)
|
||||
{
|
||||
//We need to see if we can find the cached PreValueCollection based on the cache key above
|
||||
var collections = IsolatedCache.GetCacheItemsByKeySearch<PreValueCollection>(CacheKeys.DataTypePreValuesCacheKey + "_");
|
||||
|
||||
var cached = IsolatedCache.GetCacheItemsByKeyExpression<PreValueCollection>(GetCacheKeyRegex(preValueId));
|
||||
if (cached != null && cached.Any())
|
||||
{
|
||||
//return from the cache
|
||||
var collection = cached.First();
|
||||
var preVal = collection.FormatAsDictionary().Single(x => x.Value.Id == preValueId);
|
||||
return preVal.Value.Value;
|
||||
}
|
||||
var preValue = collections.SelectMany(x => x.FormatAsDictionary().Values).FirstOrDefault(x => x.Id == preValueId);
|
||||
if (preValue != null)
|
||||
return preValue.Value;
|
||||
|
||||
//go and find the data type id for the pre val id passed in
|
||||
|
||||
var dto = Database.FirstOrDefault<DataTypePreValueDto>("WHERE id = @preValueId", new { preValueId = preValueId });
|
||||
var dto = Database.FirstOrDefault<DataTypePreValueDto>("WHERE id = @preValueId", new { preValueId });
|
||||
if (dto == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
// go cache the collection
|
||||
var preVals = GetAndCachePreValueCollection(dto.DataTypeNodeId);
|
||||
|
||||
//return the single value for this id
|
||||
var pv = preVals.FormatAsDictionary().Single(x => x.Value.Id == preValueId);
|
||||
return pv.Value.Value;
|
||||
var collection = GetCachedPreValueCollection(dto.DataTypeNodeId);
|
||||
if (collection == null)
|
||||
return string.Empty;
|
||||
|
||||
preValue = collection.FormatAsDictionary().Values.FirstOrDefault(x => x.Id == preValueId);
|
||||
return preValue == null ? string.Empty : preValue.Value;
|
||||
}
|
||||
|
||||
public void AddOrUpdatePreValues(int dataTypeId, IDictionary<string, PreValue> values)
|
||||
@@ -441,40 +427,28 @@ AND umbracoNode.id <> @id",
|
||||
|
||||
sortOrder++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private string GetPrefixedCacheKey(int dataTypeId)
|
||||
private static string GetPrefixedCacheKey(int dataTypeId)
|
||||
{
|
||||
return CacheKeys.DataTypePreValuesCacheKey + dataTypeId + "-";
|
||||
return CacheKeys.DataTypePreValuesCacheKey + "_" + dataTypeId;
|
||||
}
|
||||
|
||||
private PreValueCollection GetAndCachePreValueCollection(int dataTypeId)
|
||||
private PreValueCollection GetCachedPreValueCollection(int datetypeId)
|
||||
{
|
||||
//go get the data
|
||||
var dtos = Database.Fetch<DataTypePreValueDto>("WHERE datatypeNodeId = @Id", new { Id = dataTypeId });
|
||||
var list = dtos.Select(x => new Tuple<PreValue, string, int>(new PreValue(x.Id, x.Value, x.SortOrder), x.Alias, x.SortOrder)).ToList();
|
||||
var collection = PreValueConverter.ConvertToPreValuesCollection(list);
|
||||
|
||||
//now create the cache key, this needs to include all pre-value ids so that we can use this cached item in the GetPreValuesAsString method
|
||||
//the key will be: "UmbracoPreValDATATYPEID-CSVOFPREVALIDS
|
||||
|
||||
var key = GetPrefixedCacheKey(dataTypeId)
|
||||
+ string.Join(",", collection.FormatAsDictionary().Select(x => x.Value.Id).ToArray());
|
||||
|
||||
//store into cache
|
||||
IsolatedCache.InsertCacheItem(key, () => collection,
|
||||
//30 mins
|
||||
new TimeSpan(0, 0, 30),
|
||||
//sliding is true
|
||||
true);
|
||||
|
||||
return collection;
|
||||
var key = GetPrefixedCacheKey(datetypeId);
|
||||
return IsolatedCache.GetCacheItem<PreValueCollection>(key, () =>
|
||||
{
|
||||
var dtos = Database.Fetch<DataTypePreValueDto>("WHERE datatypeNodeId = @Id", new { Id = datetypeId });
|
||||
var list = dtos.Select(x => new Tuple<PreValue, string, int>(new PreValue(x.Id, x.Value, x.SortOrder), x.Alias, x.SortOrder)).ToList();
|
||||
var collection = PreValueConverter.ConvertToPreValuesCollection(list);
|
||||
return collection;
|
||||
}, TimeSpan.FromMinutes(20), isSliding: true);
|
||||
}
|
||||
|
||||
private string EnsureUniqueNodeName(string nodeName, int id = 0)
|
||||
{
|
||||
|
||||
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
@@ -575,7 +549,7 @@ AND umbracoNode.id <> @id",
|
||||
}
|
||||
|
||||
//NOTE: We used to check that the Alias was unique for the given DataTypeNodeId prevalues list, BUT
|
||||
// in reality there is no need to check the uniqueness of this alias because the only way that this code executes is
|
||||
// in reality there is no need to check the uniqueness of this alias because the only way that this code executes is
|
||||
// based on an IDictionary<string, PreValue> dictionary being passed to this repository and a dictionary
|
||||
// must have unique aliases by definition, so there is no need for this additional check
|
||||
|
||||
@@ -595,10 +569,10 @@ AND umbracoNode.id <> @id",
|
||||
{
|
||||
throw new InvalidOperationException("Cannot update a pre value for a data type that has no identity");
|
||||
}
|
||||
|
||||
|
||||
//NOTE: We used to check that the Alias was unique for the given DataTypeNodeId prevalues list, BUT
|
||||
// this causes issues when sorting the pre-values (http://issues.umbraco.org/issue/U4-5670) but in reality
|
||||
// there is no need to check the uniqueness of this alias because the only way that this code executes is
|
||||
// there is no need to check the uniqueness of this alias because the only way that this code executes is
|
||||
// based on an IDictionary<string, PreValue> dictionary being passed to this repository and a dictionary
|
||||
// must have unique aliases by definition, so there is no need for this additional check
|
||||
|
||||
@@ -613,7 +587,7 @@ AND umbracoNode.id <> @id",
|
||||
Database.Update(dto);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
internal static class PreValueConverter
|
||||
|
||||
@@ -8,6 +8,13 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
public interface IContentTypeRepository : IContentTypeCompositionRepository<IContentType>
|
||||
{
|
||||
/// <summary>
|
||||
/// Given the path of a content item, this will return true if the content item exists underneath a list view content item
|
||||
/// </summary>
|
||||
/// <param name="contentPath"></param>
|
||||
/// <returns></returns>
|
||||
bool HasContainerInPath(string contentPath);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all entities of the specified <see cref="PropertyType"/> query
|
||||
/// </summary>
|
||||
|
||||
@@ -49,7 +49,12 @@ namespace Umbraco.Core.Persistence
|
||||
_cacheHelper.IsolatedRuntimeCache.CacheFactory = type =>
|
||||
{
|
||||
var cache = origFactory(type);
|
||||
return new DeepCloneRuntimeCacheProvider(cache);
|
||||
|
||||
//if the result is already a DeepCloneRuntimeCacheProvider then return it, otherwise
|
||||
//wrap the result with a DeepCloneRuntimeCacheProvider
|
||||
return cache is DeepCloneRuntimeCacheProvider
|
||||
? cache
|
||||
: new DeepCloneRuntimeCacheProvider(cache);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Manifest;
|
||||
using Umbraco.Core.ObjectResolution;
|
||||
@@ -17,11 +19,13 @@ namespace Umbraco.Core.PropertyEditors
|
||||
internal class ParameterEditorResolver : LazyManyObjectsResolverBase<ParameterEditorResolver, IParameterEditor>
|
||||
{
|
||||
private readonly ManifestBuilder _builder;
|
||||
private readonly IContentSection _contentSection;
|
||||
|
||||
public ParameterEditorResolver(IServiceProvider serviceProvider, ILogger logger, Func<IEnumerable<Type>> typeListProducerList, ManifestBuilder builder)
|
||||
: base(serviceProvider, logger, typeListProducerList, ObjectLifetimeScope.Application)
|
||||
{
|
||||
_builder = builder;
|
||||
_contentSection = UmbracoConfig.For.UmbracoSettings().Content;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -31,20 +35,27 @@ namespace Umbraco.Core.PropertyEditors
|
||||
{
|
||||
get
|
||||
{
|
||||
//This will by default include all property editors and parameter editors but we need to filter this
|
||||
//list to ensure that none of the property editors that do not have the IsParameterEditor flag set to true
|
||||
//are filtered.
|
||||
var filtered = Values.Select(x => x as PropertyEditor)
|
||||
.WhereNotNull()
|
||||
.Where(x => x.IsParameterEditor == false);
|
||||
|
||||
return Values
|
||||
//exclude the non parameter editor c# property editors
|
||||
.Except(filtered)
|
||||
//include the manifest parameter editors
|
||||
.Union(_builder.ParameterEditors)
|
||||
//include the manifest prop editors that are parameter editors
|
||||
// all property editors and parameter editors
|
||||
// except property editors where !IsParameterEditor
|
||||
var values = Values
|
||||
.Where(x => x is PropertyEditor == false || ((PropertyEditor) x).IsParameterEditor);
|
||||
|
||||
// union all manifest parameter editors
|
||||
values = values
|
||||
.Union(_builder.ParameterEditors);
|
||||
|
||||
// union all manifest property editors where IsParameterEditor
|
||||
values = values
|
||||
.Union(_builder.PropertyEditors.Where(x => x.IsParameterEditor));
|
||||
|
||||
if (_contentSection.ShowDeprecatedPropertyEditors == false)
|
||||
{
|
||||
// except deprecated property editors
|
||||
values = values
|
||||
.Where(x => x is PropertyEditor == false || ((PropertyEditor) x).IsDeprecated == false);
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
@@ -74,5 +75,20 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
return Enumerable.Empty<IContentTypeBase>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given the path of a content item, this will return true if the content item exists underneath a list view content item
|
||||
/// </summary>
|
||||
/// <param name="contentPath"></param>
|
||||
/// <returns></returns>
|
||||
public bool HasContainerInPath(string contentPath)
|
||||
{
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
{
|
||||
// can use same repo for both content and media
|
||||
var repository = RepositoryFactory.CreateContentTypeRepository(uow);
|
||||
return repository.HasContainerInPath(contentPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,13 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
public interface IContentTypeService : IService
|
||||
{
|
||||
/// <summary>
|
||||
/// Given the path of a content item, this will return true if the content item exists underneath a list view content item
|
||||
/// </summary>
|
||||
/// <param name="contentPath"></param>
|
||||
/// <returns></returns>
|
||||
bool HasContainerInPath(string contentPath);
|
||||
|
||||
int CountContentTypes();
|
||||
int CountMediaTypes();
|
||||
|
||||
|
||||
@@ -46,23 +46,6 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
return new EntityContainerRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of<ILogger>(), SqlSyntax, Constants.ObjectTypes.DataTypeContainerGuid);
|
||||
}
|
||||
|
||||
[TestCase("UmbracoPreVal87-21,3,48", 3, true)]
|
||||
[TestCase("UmbracoPreVal87-21,33,48", 3, false)]
|
||||
[TestCase("UmbracoPreVal87-21,33,48", 33, true)]
|
||||
[TestCase("UmbracoPreVal87-21,3,48", 33, false)]
|
||||
[TestCase("UmbracoPreVal87-21,3,48", 21, true)]
|
||||
[TestCase("UmbracoPreVal87-21,3,48", 48, true)]
|
||||
[TestCase("UmbracoPreVal87-22,33,48", 2, false)]
|
||||
[TestCase("UmbracoPreVal87-22,33,48", 22, true)]
|
||||
[TestCase("UmbracoPreVal87-22,33,44", 4, false)]
|
||||
[TestCase("UmbracoPreVal87-22,33,44", 44, true)]
|
||||
[TestCase("UmbracoPreVal87-22,333,44", 33, false)]
|
||||
[TestCase("UmbracoPreVal87-22,333,44", 333, true)]
|
||||
public void Pre_Value_Cache_Key_Tests(string cacheKey, int preValueId, bool outcome)
|
||||
{
|
||||
Assert.AreEqual(outcome, Regex.IsMatch(cacheKey, DataTypeDefinitionRepository.GetCacheKeyRegex(preValueId)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Move()
|
||||
{
|
||||
@@ -537,7 +520,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
}
|
||||
|
||||
var cached = cache.IsolatedRuntimeCache.GetCache<IDataTypeDefinition>().Result
|
||||
.GetCacheItemsByKeySearch<PreValueCollection>(CacheKeys.DataTypePreValuesCacheKey + dtd.Id + "-");
|
||||
.GetCacheItemsByKeySearch<PreValueCollection>(CacheKeys.DataTypePreValuesCacheKey + "_" + dtd.Id);
|
||||
|
||||
Assert.IsNotNull(cached);
|
||||
Assert.AreEqual(1, cached.Count());
|
||||
@@ -581,7 +564,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
}
|
||||
|
||||
var cached = cache.IsolatedRuntimeCache.GetCache<IDataTypeDefinition>().Result
|
||||
.GetCacheItemsByKeySearch<PreValueCollection>(CacheKeys.DataTypePreValuesCacheKey + dtd.Id + "-");
|
||||
.GetCacheItemsByKeySearch<PreValueCollection>(CacheKeys.DataTypePreValuesCacheKey + "_" + dtd.Id);
|
||||
|
||||
Assert.IsNotNull(cached);
|
||||
Assert.AreEqual(1, cached.Count());
|
||||
|
||||
@@ -58,8 +58,8 @@
|
||||
<Reference Include="AutoMapper.Net4, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Examine, Version=0.1.81.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.81\lib\net45\Examine.dll</HintPath>
|
||||
<Reference Include="Examine, Version=0.1.82.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.82\lib\net45\Examine.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<packages>
|
||||
<package id="AspNetWebApi.SelfHost" version="4.0.20710.0" targetFramework="net45" />
|
||||
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
|
||||
<package id="Examine" version="0.1.81" targetFramework="net45" />
|
||||
<package id="Examine" version="0.1.82" targetFramework="net45" />
|
||||
<package id="log4net" version="2.0.5" targetFramework="net45" />
|
||||
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
|
||||
<package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net45" />
|
||||
|
||||
+3
-2
@@ -17,6 +17,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat
|
||||
hideheader: '@',
|
||||
cachekey: '@',
|
||||
isdialog: '@',
|
||||
onlyinitialized: '@',
|
||||
//Custom query string arguments to pass in to the tree as a string, example: "startnodeid=123&something=value"
|
||||
customtreeparams: '@',
|
||||
eventhandler: '=',
|
||||
@@ -252,7 +253,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat
|
||||
deleteAnimations = false;
|
||||
|
||||
//default args
|
||||
var args = { section: scope.section, tree: scope.treealias, cacheKey: scope.cachekey, isDialog: scope.isdialog ? scope.isdialog : false };
|
||||
var args = { section: scope.section, tree: scope.treealias, cacheKey: scope.cachekey, isDialog: scope.isdialog ? scope.isdialog : false, onlyinitialized: scope.onlyinitialized };
|
||||
|
||||
//add the extra query string params if specified
|
||||
if (scope.customtreeparams) {
|
||||
@@ -305,7 +306,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat
|
||||
scope.selectEnabledNodeClass = function (node) {
|
||||
return node ?
|
||||
node.selected ?
|
||||
'icon umb-tree-icon sprTree icon-check blue temporary' :
|
||||
'icon umb-tree-icon sprTree icon-check green temporary' :
|
||||
'' :
|
||||
'';
|
||||
};
|
||||
|
||||
+11
-1
@@ -1,7 +1,7 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function MiniListViewDirective(entityResource) {
|
||||
function MiniListViewDirective(entityResource, iconHelper) {
|
||||
|
||||
function link(scope, el, attr, ctrl) {
|
||||
|
||||
@@ -19,6 +19,11 @@
|
||||
|
||||
function open(node) {
|
||||
|
||||
// convert legacy icon for node
|
||||
if(node && node.icon) {
|
||||
node.icon = iconHelper.convertFromLegacyIcon(node.icon);
|
||||
}
|
||||
|
||||
goingForward = true;
|
||||
|
||||
var miniListView = {
|
||||
@@ -58,6 +63,11 @@
|
||||
// update children
|
||||
miniListView.children = data.items;
|
||||
_.each(miniListView.children, function(c) {
|
||||
// convert legacy icon for node
|
||||
if(c.icon) {
|
||||
c.icon = iconHelper.convertFromLegacyIcon(c.icon);
|
||||
}
|
||||
// set published state for content
|
||||
if (c.metaData) {
|
||||
c.hasChildren = c.metaData.HasChildren;
|
||||
if(scope.entityType === "Document") {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function TableDirective() {
|
||||
function TableDirective(iconHelper) {
|
||||
|
||||
function link(scope, el, attr, ctrl) {
|
||||
|
||||
@@ -43,6 +43,10 @@
|
||||
}
|
||||
};
|
||||
|
||||
scope.getIcon = function (entry) {
|
||||
return iconHelper.convertFromLegacyIcon(entry.icon);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
var directive = {
|
||||
|
||||
@@ -343,8 +343,13 @@ angular.module('umbraco.mocks').
|
||||
{
|
||||
results.push(decodeURIComponent(match[1].replace(/\+/g, " ")));
|
||||
}
|
||||
|
||||
|
||||
return results;
|
||||
},
|
||||
|
||||
getObjectPropertyFromJsonString: function(data, name) {
|
||||
var obj = JSON.parse(data);
|
||||
return obj[name];
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
@@ -21,8 +21,27 @@ angular.module('umbraco.mocks').
|
||||
if (!mocksUtils.checkAuth()) {
|
||||
return [401, null, null];
|
||||
}
|
||||
|
||||
|
||||
var ids = mocksUtils.getParametersByName(data, "ids") || [1234, 23324, 2323, 23424];
|
||||
|
||||
var nodes = [];
|
||||
|
||||
$(ids).each(function (i, id) {
|
||||
var _id = parseInt(id, 10);
|
||||
nodes.push(mocksUtils.getMockEntity(_id));
|
||||
});
|
||||
|
||||
return [200, nodes, null];
|
||||
}
|
||||
|
||||
function returnEntitybyIdsPost(method, url, data, headers) {
|
||||
|
||||
if (!mocksUtils.checkAuth()) {
|
||||
return [401, null, null];
|
||||
}
|
||||
|
||||
var ids = mocksUtils.getObjectPropertyFromJsonString(data, "ids") || [1234, 23324, 2323, 23424];
|
||||
|
||||
var nodes = [];
|
||||
|
||||
$(ids).each(function (i, id) {
|
||||
@@ -52,7 +71,7 @@ angular.module('umbraco.mocks').
|
||||
|
||||
$httpBackend
|
||||
.whenPOST(mocksUtils.urlRegex('/umbraco/UmbracoApi/Entity/GetByIds'))
|
||||
.respond(returnEntitybyIds);
|
||||
.respond(returnEntitybyIdsPost);
|
||||
|
||||
$httpBackend
|
||||
.whenGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/Entity/GetAncestors'))
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
* @ngdoc service
|
||||
* @name umbraco.resources.macroResource
|
||||
* @description Deals with data for macros
|
||||
*
|
||||
*
|
||||
**/
|
||||
function macroResource($q, $http, umbRequestHelper) {
|
||||
|
||||
//the factory object returned
|
||||
return {
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.macroResource#getMacroParameters
|
||||
@@ -20,7 +20,7 @@ function macroResource($q, $http, umbRequestHelper) {
|
||||
* @param {int} macroId The macro id to get parameters for
|
||||
*
|
||||
*/
|
||||
getMacroParameters: function (macroId) {
|
||||
getMacroParameters: function (macroId) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
@@ -29,7 +29,7 @@ function macroResource($q, $http, umbRequestHelper) {
|
||||
[{ macroId: macroId }])),
|
||||
'Failed to retrieve macro parameters for macro with id ' + macroId);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.macroResource#getMacroResult
|
||||
@@ -55,6 +55,27 @@ function macroResource($q, $http, umbRequestHelper) {
|
||||
macroParams: macroParamDictionary
|
||||
}),
|
||||
'Failed to retrieve macro result for macro with alias ' + macroAlias);
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {} filename
|
||||
* @returns {}
|
||||
*/
|
||||
createPartialViewMacroWithFile: function(parent, filename) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"macroApiBaseUrl",
|
||||
"CreatePartialViewMacroWithFile"), {
|
||||
parent: parent,
|
||||
filename: filename
|
||||
}
|
||||
),
|
||||
'Failed to create macro "' + filename + '"'
|
||||
);
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -51,10 +51,15 @@ function treeResource($q, $http, umbRequestHelper) {
|
||||
if (!options.isDialog) {
|
||||
options.isDialog = false;
|
||||
}
|
||||
|
||||
|
||||
//create the query string for the tree request, these are the mandatory options:
|
||||
var query = "application=" + options.section + "&tree=" + options.tree + "&isDialog=" + options.isDialog;
|
||||
|
||||
//if you need to load a not initialized tree set this value to false - default is true
|
||||
if (options.onlyinitialized) {
|
||||
query += "&onlyInitialized=" + options.onlyinitialized;
|
||||
}
|
||||
|
||||
//the options can contain extra query string parameters
|
||||
if (options.queryString) {
|
||||
query += "&" + options.queryString;
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function entityHelper() {
|
||||
|
||||
function getEntityTypeFromSection(section) {
|
||||
if (section === "member") {
|
||||
return "Member";
|
||||
}
|
||||
else if (section === "media") {
|
||||
return "Media";
|
||||
} else {
|
||||
return "Document";
|
||||
}
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
var service = {
|
||||
getEntityTypeFromSection: getEntityTypeFromSection
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
}
|
||||
|
||||
angular.module('umbraco.services').factory('entityHelper', entityHelper);
|
||||
|
||||
})();
|
||||
@@ -8,8 +8,15 @@
|
||||
return "@Umbraco.GetDictionaryValue(\"" + nodeName + "\")";
|
||||
}
|
||||
|
||||
function getInsertPartialSnippet(nodeName) {
|
||||
return "@Html.Partial(\"" + nodeName + "\")";
|
||||
function getInsertPartialSnippet(parentId, nodeName) {
|
||||
|
||||
var partialViewName = nodeName.replace(".cshtml", "");
|
||||
|
||||
if(parentId) {
|
||||
partialViewName = parentId + "/" + partialViewName;
|
||||
}
|
||||
|
||||
return "@Html.Partial(\"" + partialViewName + "\")";
|
||||
}
|
||||
|
||||
function getQuerySnippet(queryExpression) {
|
||||
|
||||
@@ -139,6 +139,7 @@
|
||||
//page specific styles
|
||||
@import "pages/document-type-editor.less";
|
||||
@import "pages/login.less";
|
||||
@import "pages/welcome-dashboard.less";
|
||||
|
||||
|
||||
//used for property editors
|
||||
|
||||
@@ -138,16 +138,6 @@ input.umb-group-builder__group-title-input {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 10px;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
input.umb-group-builder__group-sort-value {
|
||||
font-size: 12px;
|
||||
padding: 0px 0 0px 5px;
|
||||
width: 40px;
|
||||
margin-bottom: 0;
|
||||
border-color: @gray-8;
|
||||
}
|
||||
|
||||
/* ---------- PROPERTIES ---------- */
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
// Title
|
||||
.welcome-dashboard__intro {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.welcome-dashboard__title {
|
||||
font-size: 30px;
|
||||
color: @gray-2;
|
||||
line-height: 1.3em;
|
||||
text-align: center;
|
||||
max-width: 750px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-bottom: 15px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.welcome-dashboard__intro-text {
|
||||
font-size: 18px;
|
||||
text-align: center;
|
||||
max-width: 750px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
line-height: 1.6em;
|
||||
}
|
||||
|
||||
// Info box
|
||||
.welcome-dashboard__info-box-boxes {
|
||||
display: flex;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.welcome-dashboard__info-box {
|
||||
background-color: @turquoise-washed;
|
||||
border-radius: 3px;
|
||||
border: 2px solid transparent;
|
||||
padding: 25px;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.welcome-dashboard__info-box:hover {
|
||||
border: 2px solid @turquoise;
|
||||
cursor: pointer;
|
||||
transition: border-color 150ms ease-in-out;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.welcome-dashboard__info-box:active,
|
||||
.welcome-dashboard__info-box:focus {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
||||
.welcome-dashboard__info-box-title {
|
||||
color: @turquoise-d1;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
margin-bottom: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.welcome-dashboard__info-box-description {
|
||||
text-align: center;
|
||||
line-height: 1.4em;
|
||||
}
|
||||
|
||||
// Articles
|
||||
.welcome-dashboard__cards {
|
||||
display: flex;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.welcome-dashboard__card {
|
||||
background-color: @gray-10;
|
||||
border-radius: 3px;
|
||||
margin: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.welcome-dashboard__card-image-wrapper {
|
||||
flex: 0 0 auto;
|
||||
width: 100%;
|
||||
margin-bottom: 30px;
|
||||
max-height: 225px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.welcome-dashboard__card-image {
|
||||
cursor: pointer;
|
||||
border-radius: 3px 3px 0 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.welcome-dashboard__card-image-wrapper + .welcome-dashboard__card-content {
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
.welcome-dashboard__card-content {
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.welcome-dashboard__card-title {
|
||||
color: @gray-2;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
line-height: 1.6em;
|
||||
}
|
||||
|
||||
.welcome-dashboard__card-teaser {
|
||||
font-size: 14px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
}
|
||||
|
||||
.umb-editor-tiny {
|
||||
width: 50px;
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.umb-editor-small {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
function CopyOverlay($scope, localizationService, eventsService) {
|
||||
function CopyOverlay($scope, localizationService, eventsService, entityHelper) {
|
||||
|
||||
var vm = this;
|
||||
|
||||
@@ -32,54 +32,30 @@
|
||||
selectedSearchResults: []
|
||||
};
|
||||
|
||||
// get entity type based on the section
|
||||
$scope.entityType = entityHelper.getEntityTypeFromSection(dialogOptions.section);
|
||||
|
||||
function nodeSelectHandler(ev, args) {
|
||||
args.event.preventDefault();
|
||||
args.event.stopPropagation();
|
||||
|
||||
if (args.node.metaData.listViewNode) {
|
||||
//check if list view 'search' node was selected
|
||||
|
||||
vm.searchInfo.showSearch = true;
|
||||
vm.searchInfo.searchFromId = args.node.metaData.listViewNode.id;
|
||||
vm.searchInfo.searchFromName = args.node.metaData.listViewNode.name;
|
||||
}
|
||||
else {
|
||||
//eventsService.emit("editors.content.copyController.select", args);
|
||||
|
||||
if ($scope.model.target) {
|
||||
//un-select if there's a current one selected
|
||||
$scope.model.target.selected = false;
|
||||
}
|
||||
|
||||
$scope.model.target = args.node;
|
||||
$scope.model.target.selected = true;
|
||||
if(args && args.event) {
|
||||
args.event.preventDefault();
|
||||
args.event.stopPropagation();
|
||||
}
|
||||
|
||||
//eventsService.emit("editors.content.copyController.select", args);
|
||||
|
||||
if ($scope.model.target) {
|
||||
//un-select if there's a current one selected
|
||||
$scope.model.target.selected = false;
|
||||
}
|
||||
|
||||
$scope.model.target = args.node;
|
||||
$scope.model.target.selected = true;
|
||||
}
|
||||
|
||||
function nodeExpandedHandler(ev, args) {
|
||||
if (angular.isArray(args.children)) {
|
||||
|
||||
//iterate children
|
||||
_.each(args.children, function (child) {
|
||||
//check if any of the items are list views, if so we need to add a custom
|
||||
// child: A node to activate the search
|
||||
if (child.metaData.isContainer) {
|
||||
child.hasChildren = true;
|
||||
child.children = [
|
||||
{
|
||||
level: child.level + 1,
|
||||
hasChildren: false,
|
||||
name: searchText,
|
||||
metaData: {
|
||||
listViewNode: child,
|
||||
},
|
||||
cssClass: "icon umb-tree-icon sprTree icon-search",
|
||||
cssClasses: ["not-published"]
|
||||
}
|
||||
];
|
||||
}
|
||||
});
|
||||
// open mini list view for list views
|
||||
if (args.node.metaData.isContainer) {
|
||||
openMiniListView(args.node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,6 +86,20 @@
|
||||
$scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler);
|
||||
});
|
||||
|
||||
// Mini list view
|
||||
$scope.selectListViewNode = function (node) {
|
||||
node.selected = node.selected === true ? false : true;
|
||||
nodeSelectHandler({}, { node: node });
|
||||
};
|
||||
|
||||
$scope.closeMiniListView = function () {
|
||||
$scope.miniListView = undefined;
|
||||
};
|
||||
|
||||
function openMiniListView(node) {
|
||||
$scope.miniListView = node;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,34 +1,47 @@
|
||||
<div ng-controller="Umbraco.Overlays.CopyOverlay as vm">
|
||||
|
||||
<div class="umb-control-group">
|
||||
<umb-tree-search-box
|
||||
hide-search-callback="vm.hideSearch"
|
||||
search-callback="vm.onSearchResults"
|
||||
search-from-id="{{vm.searchInfo.searchFromId}}"
|
||||
search-from-name="{{vm.searchInfo.searchFromName}}"
|
||||
show-search="{{vm.searchInfo.showSearch}}"
|
||||
section="{{model.section}}">
|
||||
</umb-tree-search-box>
|
||||
</div>
|
||||
<div ng-hide="miniListView">
|
||||
<div class="umb-control-group">
|
||||
<umb-tree-search-box
|
||||
hide-search-callback="vm.hideSearch"
|
||||
search-callback="vm.onSearchResults"
|
||||
search-from-id="{{vm.searchInfo.searchFromId}}"
|
||||
search-from-name="{{vm.searchInfo.searchFromName}}"
|
||||
show-search="{{vm.searchInfo.showSearch}}"
|
||||
section="{{model.section}}">
|
||||
</umb-tree-search-box>
|
||||
</div>
|
||||
|
||||
<div class="umb-control-group" ng-show="vm.searchInfo.showSearch">
|
||||
<umb-tree-search-results
|
||||
ng-if="vm.searchInfo.showSearch"
|
||||
results="vm.searchInfo.results"
|
||||
select-result-callback="vm.selectResult">
|
||||
</umb-tree-search-results>
|
||||
</div>
|
||||
<div class="umb-control-group" ng-show="vm.searchInfo.showSearch">
|
||||
<umb-tree-search-results
|
||||
ng-if="vm.searchInfo.showSearch"
|
||||
results="vm.searchInfo.results"
|
||||
select-result-callback="vm.selectResult">
|
||||
</umb-tree-search-results>
|
||||
</div>
|
||||
|
||||
<div class="umb-control-group -no-border" ng-hide="vm.searchInfo.showSearch">
|
||||
<umb-tree
|
||||
section="{{model.section}}"
|
||||
hideheader="false"
|
||||
hideoptions="true"
|
||||
isdialog="true"
|
||||
eventhandler="dialogTreeEventHandler"
|
||||
enablelistviewexpand="true"
|
||||
enablecheckboxes="true">
|
||||
</umb-tree>
|
||||
</div>
|
||||
|
||||
<div class="umb-control-group -no-border" ng-hide="vm.searchInfo.showSearch">
|
||||
<umb-tree
|
||||
section="{{model.section}}"
|
||||
hideheader="false"
|
||||
hideoptions="true"
|
||||
isdialog="true"
|
||||
eventhandler="dialogTreeEventHandler"
|
||||
enablecheckboxes="true">
|
||||
</umb-tree>
|
||||
</div>
|
||||
|
||||
<div ng-if="miniListView" class="umb-control-group">
|
||||
<umb-mini-list-view
|
||||
node="miniListView"
|
||||
entity-type="{{entityType}}"
|
||||
on-select="selectListViewNode(node)"
|
||||
on-close="closeMiniListView()">
|
||||
</umb-mini-list-view>
|
||||
</div>
|
||||
|
||||
<div class="umb-control-group -no-border">
|
||||
<label>
|
||||
|
||||
@@ -104,13 +104,18 @@
|
||||
function openPartialOverlay() {
|
||||
vm.partialItemOverlay = {
|
||||
view: "treepicker",
|
||||
section: "settings",
|
||||
section: "settings",
|
||||
treeAlias: "partialViews",
|
||||
entityType: "partialView",
|
||||
multiPicker: false,
|
||||
show: true,
|
||||
filter: function(i) {
|
||||
if(i.name.indexOf(".cshtml") === -1 && i.name.indexOf(".vbhtml") === -1) {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
filterCssClass: "not-allowed",
|
||||
title: localizationService.localize("template_insertPartialView"),
|
||||
|
||||
show: true,
|
||||
select: function(node){
|
||||
|
||||
$scope.model.insert = {
|
||||
|
||||
+44
-54
@@ -47,69 +47,44 @@ angular.module("umbraco").controller("Umbraco.Overlays.LinkPickerController",
|
||||
}
|
||||
|
||||
function nodeSelectHandler(ev, args) {
|
||||
args.event.preventDefault();
|
||||
args.event.stopPropagation();
|
||||
|
||||
if (args.node.metaData.listViewNode) {
|
||||
//check if list view 'search' node was selected
|
||||
if(args && args.event) {
|
||||
args.event.preventDefault();
|
||||
args.event.stopPropagation();
|
||||
}
|
||||
|
||||
$scope.searchInfo.showSearch = true;
|
||||
$scope.searchInfo.searchFromId = args.node.metaData.listViewNode.id;
|
||||
$scope.searchInfo.searchFromName = args.node.metaData.listViewNode.name;
|
||||
}
|
||||
else {
|
||||
eventsService.emit("dialogs.linkPicker.select", args);
|
||||
eventsService.emit("dialogs.linkPicker.select", args);
|
||||
|
||||
if ($scope.currentNode) {
|
||||
//un-select if there's a current one selected
|
||||
$scope.currentNode.selected = false;
|
||||
}
|
||||
if ($scope.currentNode) {
|
||||
//un-select if there's a current one selected
|
||||
$scope.currentNode.selected = false;
|
||||
}
|
||||
|
||||
$scope.currentNode = args.node;
|
||||
$scope.currentNode.selected = true;
|
||||
$scope.model.target.id = args.node.id;
|
||||
$scope.model.target.udi = args.node.udi;
|
||||
$scope.model.target.name = args.node.name;
|
||||
$scope.currentNode = args.node;
|
||||
$scope.currentNode.selected = true;
|
||||
$scope.model.target.id = args.node.id;
|
||||
$scope.model.target.udi = args.node.udi;
|
||||
$scope.model.target.name = args.node.name;
|
||||
|
||||
if (args.node.id < 0) {
|
||||
$scope.model.target.url = "/";
|
||||
}
|
||||
else {
|
||||
contentResource.getNiceUrl(args.node.id).then(function (url) {
|
||||
$scope.model.target.url = url;
|
||||
});
|
||||
}
|
||||
if (args.node.id < 0) {
|
||||
$scope.model.target.url = "/";
|
||||
}
|
||||
else {
|
||||
contentResource.getNiceUrl(args.node.id).then(function (url) {
|
||||
$scope.model.target.url = url;
|
||||
});
|
||||
}
|
||||
|
||||
if (!angular.isUndefined($scope.model.target.isMedia)) {
|
||||
delete $scope.model.target.isMedia;
|
||||
}
|
||||
}
|
||||
if (!angular.isUndefined($scope.model.target.isMedia)) {
|
||||
delete $scope.model.target.isMedia;
|
||||
}
|
||||
}
|
||||
|
||||
function nodeExpandedHandler(ev, args) {
|
||||
if (angular.isArray(args.children)) {
|
||||
|
||||
//iterate children
|
||||
_.each(args.children, function (child) {
|
||||
//check if any of the items are list views, if so we need to add a custom
|
||||
// child: A node to activate the search
|
||||
if (child.metaData.isContainer) {
|
||||
child.hasChildren = true;
|
||||
child.children = [
|
||||
{
|
||||
level: child.level + 1,
|
||||
hasChildren: false,
|
||||
name: searchText,
|
||||
metaData: {
|
||||
listViewNode: child,
|
||||
},
|
||||
cssClass: "icon umb-tree-icon sprTree icon-search",
|
||||
cssClasses: ["not-published"]
|
||||
}
|
||||
];
|
||||
}
|
||||
});
|
||||
}
|
||||
// open mini list view for list views
|
||||
if (args.node.metaData.isContainer) {
|
||||
openMiniListView(args.node);
|
||||
}
|
||||
}
|
||||
|
||||
$scope.switchToMediaPicker = function () {
|
||||
@@ -160,4 +135,19 @@ angular.module("umbraco").controller("Umbraco.Overlays.LinkPickerController",
|
||||
$scope.dialogTreeEventHandler.unbind("treeNodeSelect", nodeSelectHandler);
|
||||
$scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler);
|
||||
});
|
||||
|
||||
// Mini list view
|
||||
$scope.selectListViewNode = function (node) {
|
||||
node.selected = node.selected === true ? false : true;
|
||||
nodeSelectHandler({}, { node: node });
|
||||
};
|
||||
|
||||
$scope.closeMiniListView = function () {
|
||||
$scope.miniListView = undefined;
|
||||
};
|
||||
|
||||
function openMiniListView(node) {
|
||||
$scope.miniListView = node;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -28,34 +28,45 @@
|
||||
<localize key="defaultdialogs_linkToPage">Link to page</localize>
|
||||
</h5>
|
||||
|
||||
<umb-tree-search-box
|
||||
hide-search-callback="hideSearch"
|
||||
search-callback="onSearchResults"
|
||||
search-from-id="{{searchInfo.searchFromId}}"
|
||||
search-from-name="{{searchInfo.searchFromName}}"
|
||||
show-search="{{searchInfo.showSearch}}"
|
||||
section="{{section}}">
|
||||
</umb-tree-search-box>
|
||||
<div ng-hide="miniListView">
|
||||
<umb-tree-search-box
|
||||
hide-search-callback="hideSearch"
|
||||
search-callback="onSearchResults"
|
||||
search-from-id="{{searchInfo.searchFromId}}"
|
||||
search-from-name="{{searchInfo.searchFromName}}"
|
||||
show-search="{{searchInfo.showSearch}}"
|
||||
section="{{section}}">
|
||||
</umb-tree-search-box>
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
<umb-tree-search-results
|
||||
ng-if="searchInfo.showSearch"
|
||||
results="searchInfo.results"
|
||||
select-result-callback="selectResult">
|
||||
</umb-tree-search-results>
|
||||
<umb-tree-search-results
|
||||
ng-if="searchInfo.showSearch"
|
||||
results="searchInfo.results"
|
||||
select-result-callback="selectResult">
|
||||
</umb-tree-search-results>
|
||||
|
||||
<div ng-hide="searchInfo.showSearch">
|
||||
<umb-tree
|
||||
section="content"
|
||||
hideheader="true"
|
||||
hideoptions="true"
|
||||
eventhandler="dialogTreeEventHandler"
|
||||
isdialog="true"
|
||||
enablecheckboxes="true">
|
||||
</umb-tree>
|
||||
<div ng-hide="searchInfo.showSearch">
|
||||
<umb-tree
|
||||
section="content"
|
||||
hideheader="true"
|
||||
hideoptions="true"
|
||||
eventhandler="dialogTreeEventHandler"
|
||||
enablelistviewexpand="true"
|
||||
isdialog="true"
|
||||
enablecheckboxes="true">
|
||||
</umb-tree>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<umb-mini-list-view
|
||||
ng-if="miniListView"
|
||||
node="miniListView"
|
||||
entity-type="Document"
|
||||
on-select="selectListViewNode(node)"
|
||||
on-close="closeMiniListView()">
|
||||
</umb-mini-list-view>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="umb-control-group">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
function MoveOverlay($scope, localizationService, eventsService) {
|
||||
function MoveOverlay($scope, localizationService, eventsService, entityHelper) {
|
||||
|
||||
var vm = this;
|
||||
|
||||
@@ -32,54 +32,32 @@
|
||||
selectedSearchResults: []
|
||||
};
|
||||
|
||||
// get entity type based on the section
|
||||
$scope.entityType = entityHelper.getEntityTypeFromSection(dialogOptions.section);
|
||||
|
||||
function nodeSelectHandler(ev, args) {
|
||||
args.event.preventDefault();
|
||||
args.event.stopPropagation();
|
||||
|
||||
if (args.node.metaData.listViewNode) {
|
||||
//check if list view 'search' node was selected
|
||||
|
||||
vm.searchInfo.showSearch = true;
|
||||
vm.searchInfo.searchFromId = args.node.metaData.listViewNode.id;
|
||||
vm.searchInfo.searchFromName = args.node.metaData.listViewNode.name;
|
||||
if(args && args.event) {
|
||||
args.event.preventDefault();
|
||||
args.event.stopPropagation();
|
||||
}
|
||||
else {
|
||||
//eventsService.emit("editors.content.copyController.select", args);
|
||||
|
||||
if ($scope.model.target) {
|
||||
//un-select if there's a current one selected
|
||||
$scope.model.target.selected = false;
|
||||
}
|
||||
//eventsService.emit("editors.content.copyController.select", args);
|
||||
|
||||
$scope.model.target = args.node;
|
||||
$scope.model.target.selected = true;
|
||||
if ($scope.model.target) {
|
||||
//un-select if there's a current one selected
|
||||
$scope.model.target.selected = false;
|
||||
}
|
||||
|
||||
$scope.model.target = args.node;
|
||||
$scope.model.target.selected = true;
|
||||
|
||||
}
|
||||
|
||||
function nodeExpandedHandler(ev, args) {
|
||||
if (angular.isArray(args.children)) {
|
||||
|
||||
//iterate children
|
||||
_.each(args.children, function (child) {
|
||||
//check if any of the items are list views, if so we need to add a custom
|
||||
// child: A node to activate the search
|
||||
if (child.metaData.isContainer) {
|
||||
child.hasChildren = true;
|
||||
child.children = [
|
||||
{
|
||||
level: child.level + 1,
|
||||
hasChildren: false,
|
||||
name: searchText,
|
||||
metaData: {
|
||||
listViewNode: child,
|
||||
},
|
||||
cssClass: "icon umb-tree-icon sprTree icon-search",
|
||||
cssClasses: ["not-published"]
|
||||
}
|
||||
];
|
||||
}
|
||||
});
|
||||
// open mini list view for list views
|
||||
if (args.node.metaData.isContainer) {
|
||||
openMiniListView(args.node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,6 +88,19 @@
|
||||
$scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler);
|
||||
});
|
||||
|
||||
// Mini list view
|
||||
$scope.selectListViewNode = function (node) {
|
||||
node.selected = node.selected === true ? false : true;
|
||||
nodeSelectHandler({}, { node: node });
|
||||
};
|
||||
|
||||
$scope.closeMiniListView = function () {
|
||||
$scope.miniListView = undefined;
|
||||
};
|
||||
|
||||
function openMiniListView(node) {
|
||||
$scope.miniListView = node;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,33 +1,43 @@
|
||||
<div ng-controller="Umbraco.Overlays.MoveOverlay as vm">
|
||||
<div ng-hide="miniListView">
|
||||
<div class="umb-control-group">
|
||||
<umb-tree-search-box
|
||||
hide-search-callback="vm.hideSearch"
|
||||
search-callback="vm.onSearchResults"
|
||||
search-from-id="{{vm.searchInfo.searchFromId}}"
|
||||
search-from-name="{{vm.searchInfo.searchFromName}}"
|
||||
show-search="{{vm.searchInfo.showSearch}}"
|
||||
section="{{model.section}}">
|
||||
</umb-tree-search-box>
|
||||
</div>
|
||||
|
||||
<div class="umb-control-group">
|
||||
<umb-tree-search-box
|
||||
hide-search-callback="vm.hideSearch"
|
||||
search-callback="vm.onSearchResults"
|
||||
search-from-id="{{vm.searchInfo.searchFromId}}"
|
||||
search-from-name="{{vm.searchInfo.searchFromName}}"
|
||||
show-search="{{vm.searchInfo.showSearch}}"
|
||||
section="{{model.section}}">
|
||||
</umb-tree-search-box>
|
||||
<div class="umb-control-group" ng-show="vm.searchInfo.showSearch">
|
||||
<umb-tree-search-results
|
||||
ng-if="vm.searchInfo.showSearch"
|
||||
results="vm.searchInfo.results"
|
||||
select-result-callback="vm.selectResult">
|
||||
</umb-tree-search-results>
|
||||
</div>
|
||||
|
||||
<div class="umb-control-group -no-border" ng-hide="vm.searchInfo.showSearch">
|
||||
<umb-tree
|
||||
section="{{model.section}}"
|
||||
hideheader="false"
|
||||
hideoptions="true"
|
||||
isdialog="true"
|
||||
eventhandler="dialogTreeEventHandler"
|
||||
enablelistviewexpand="true"
|
||||
enablecheckboxes="true">
|
||||
</umb-tree>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-control-group" ng-show="vm.searchInfo.showSearch">
|
||||
<umb-tree-search-results
|
||||
ng-if="vm.searchInfo.showSearch"
|
||||
results="vm.searchInfo.results"
|
||||
select-result-callback="vm.selectResult">
|
||||
</umb-tree-search-results>
|
||||
</div>
|
||||
|
||||
<div class="umb-control-group -no-border" ng-hide="vm.searchInfo.showSearch">
|
||||
<umb-tree
|
||||
section="{{model.section}}"
|
||||
hideheader="false"
|
||||
hideoptions="true"
|
||||
isdialog="true"
|
||||
eventhandler="dialogTreeEventHandler"
|
||||
enablecheckboxes="true">
|
||||
</umb-tree>
|
||||
</div>
|
||||
<umb-mini-list-view
|
||||
ng-if="miniListView"
|
||||
node="miniListView"
|
||||
entity-type="{{entityType}}"
|
||||
on-select="selectListViewNode(node)"
|
||||
on-close="closeMiniListView()">
|
||||
</umb-mini-list-view>
|
||||
|
||||
</div>
|
||||
|
||||
+2
@@ -10,6 +10,8 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController",
|
||||
$scope.treeAlias = dialogOptions.treeAlias;
|
||||
$scope.multiPicker = dialogOptions.multiPicker;
|
||||
$scope.hideHeader = true;
|
||||
// if you need to load a not initialized tree set this value to false - default is true
|
||||
$scope.onlyInitialized = dialogOptions.onlyInitialized;
|
||||
$scope.searchInfo = {
|
||||
searchFromId: dialogOptions.startNodeId,
|
||||
searchFromName: null,
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
hideheader="{{hideHeader}}"
|
||||
hideoptions="true"
|
||||
isdialog="true"
|
||||
onlyinitialized="{{onlyInitialized}}"
|
||||
customtreeparams="{{customTreeParams}}"
|
||||
eventhandler="dialogTreeEventHandler"
|
||||
enablelistviewsearch="true"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<a class="icon icon-arrow-left" ng-if="showSearch == 'true'" title="Back" ng-click="hideSearch()"></a>
|
||||
<input type="text"
|
||||
ng-model="term"
|
||||
class="umb-search-field search-query"
|
||||
class="umb-search-field search-query -full-width-input"
|
||||
placeholder="{{searchPlaceholderText}}"
|
||||
focus-when="{{showSearch}}">
|
||||
<h4 ng-if="showSearch && searchFromName">
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
|
||||
<ng-form name="groupSortOrderForm">
|
||||
<div class="umb-group-builder__group-sort-order" ng-if="sortingMode">
|
||||
<input name="groupSortOrder" type="number" class="umb-group-builder__group-sort-value" ng-model="tab.sortOrder" ng-disabled="tab.inherited" on-blur="changeSortOrderValue(tab)" required />
|
||||
<input name="groupSortOrder" type="number" class="umb-editor-tiny" style="margin-bottom: 0;" ng-model="tab.sortOrder" ng-disabled="tab.inherited" on-blur="changeSortOrderValue(tab)" required />
|
||||
<div class="umb-validation-label -arrow-left" ng-if="groupSortOrderForm.groupSortOrder.$error.required && tab.showSortOrderMissing"><localize key="required"></localize></div>
|
||||
<div class="umb-validation-label -arrow-left" ng-if="!tab.showSortOrderMissing" val-msg-for="groupSortOrder" val-toggle-msg="required"><localize key="required"></localize></div>
|
||||
</div>
|
||||
|
||||
@@ -22,54 +22,29 @@ angular.module("umbraco").controller("Umbraco.Editors.Content.CopyController",
|
||||
var node = dialogOptions.currentNode;
|
||||
|
||||
function nodeSelectHandler(ev, args) {
|
||||
args.event.preventDefault();
|
||||
args.event.stopPropagation();
|
||||
|
||||
if (args.node.metaData.listViewNode) {
|
||||
//check if list view 'search' node was selected
|
||||
if(args && args.event) {
|
||||
args.event.preventDefault();
|
||||
args.event.stopPropagation();
|
||||
}
|
||||
|
||||
$scope.searchInfo.showSearch = true;
|
||||
$scope.searchInfo.searchFromId = args.node.metaData.listViewNode.id;
|
||||
$scope.searchInfo.searchFromName = args.node.metaData.listViewNode.name;
|
||||
}
|
||||
else {
|
||||
eventsService.emit("editors.content.copyController.select", args);
|
||||
eventsService.emit("editors.content.copyController.select", args);
|
||||
|
||||
if ($scope.target) {
|
||||
//un-select if there's a current one selected
|
||||
$scope.target.selected = false;
|
||||
}
|
||||
if ($scope.target) {
|
||||
//un-select if there's a current one selected
|
||||
$scope.target.selected = false;
|
||||
}
|
||||
|
||||
$scope.target = args.node;
|
||||
$scope.target.selected = true;
|
||||
}
|
||||
$scope.target = args.node;
|
||||
$scope.target.selected = true;
|
||||
|
||||
}
|
||||
|
||||
function nodeExpandedHandler(ev, args) {
|
||||
if (angular.isArray(args.children)) {
|
||||
|
||||
//iterate children
|
||||
_.each(args.children, function (child) {
|
||||
//check if any of the items are list views, if so we need to add a custom
|
||||
// child: A node to activate the search
|
||||
if (child.metaData.isContainer) {
|
||||
child.hasChildren = true;
|
||||
child.children = [
|
||||
{
|
||||
level: child.level + 1,
|
||||
hasChildren: false,
|
||||
name: searchText,
|
||||
metaData: {
|
||||
listViewNode: child,
|
||||
},
|
||||
cssClass: "icon umb-tree-icon sprTree icon-search",
|
||||
cssClasses: ["not-published"]
|
||||
}
|
||||
];
|
||||
}
|
||||
});
|
||||
}
|
||||
// open mini list view for list views
|
||||
if (args.node.metaData.isContainer) {
|
||||
openMiniListView(args.node);
|
||||
}
|
||||
}
|
||||
|
||||
$scope.hideSearch = function () {
|
||||
@@ -136,4 +111,19 @@ angular.module("umbraco").controller("Umbraco.Editors.Content.CopyController",
|
||||
$scope.dialogTreeEventHandler.unbind("treeNodeSelect", nodeSelectHandler);
|
||||
$scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler);
|
||||
});
|
||||
|
||||
// Mini list view
|
||||
$scope.selectListViewNode = function (node) {
|
||||
node.selected = node.selected === true ? false : true;
|
||||
nodeSelectHandler({}, { node: node });
|
||||
};
|
||||
|
||||
$scope.closeMiniListView = function () {
|
||||
$scope.miniListView = undefined;
|
||||
};
|
||||
|
||||
function openMiniListView(node) {
|
||||
$scope.miniListView = node;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -20,53 +20,29 @@ angular.module("umbraco").controller("Umbraco.Editors.Content.MoveController",
|
||||
var node = dialogOptions.currentNode;
|
||||
|
||||
function nodeSelectHandler(ev, args) {
|
||||
args.event.preventDefault();
|
||||
args.event.stopPropagation();
|
||||
|
||||
if (args.node.metaData.listViewNode) {
|
||||
//check if list view 'search' node was selected
|
||||
if(args && args.event) {
|
||||
args.event.preventDefault();
|
||||
args.event.stopPropagation();
|
||||
}
|
||||
|
||||
$scope.searchInfo.showSearch = true;
|
||||
$scope.searchInfo.searchFromId = args.node.metaData.listViewNode.id;
|
||||
$scope.searchInfo.searchFromName = args.node.metaData.listViewNode.name;
|
||||
}
|
||||
else {
|
||||
eventsService.emit("editors.content.moveController.select", args);
|
||||
eventsService.emit("editors.content.moveController.select", args);
|
||||
|
||||
if ($scope.target) {
|
||||
//un-select if there's a current one selected
|
||||
$scope.target.selected = false;
|
||||
}
|
||||
if ($scope.target) {
|
||||
//un-select if there's a current one selected
|
||||
$scope.target.selected = false;
|
||||
}
|
||||
|
||||
$scope.target = args.node;
|
||||
$scope.target.selected = true;
|
||||
|
||||
$scope.target = args.node;
|
||||
$scope.target.selected = true;
|
||||
}
|
||||
}
|
||||
|
||||
function nodeExpandedHandler(ev, args) {
|
||||
if (angular.isArray(args.children)) {
|
||||
|
||||
//iterate children
|
||||
_.each(args.children, function (child) {
|
||||
//check if any of the items are list views, if so we need to add a custom
|
||||
// child: A node to activate the search
|
||||
if (child.metaData.isContainer) {
|
||||
child.hasChildren = true;
|
||||
child.children = [
|
||||
{
|
||||
level: child.level + 1,
|
||||
hasChildren: false,
|
||||
name: searchText,
|
||||
metaData: {
|
||||
listViewNode: child,
|
||||
},
|
||||
cssClass: "icon umb-tree-icon sprTree icon-search",
|
||||
cssClasses: ["not-published"]
|
||||
}
|
||||
];
|
||||
}
|
||||
});
|
||||
}
|
||||
// open mini list view for list views
|
||||
if (args.node.metaData.isContainer) {
|
||||
openMiniListView(args.node);
|
||||
}
|
||||
}
|
||||
|
||||
$scope.hideSearch = function () {
|
||||
@@ -136,4 +112,19 @@ angular.module("umbraco").controller("Umbraco.Editors.Content.MoveController",
|
||||
$scope.dialogTreeEventHandler.unbind("treeNodeSelect", nodeSelectHandler);
|
||||
$scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler);
|
||||
});
|
||||
|
||||
// Mini list view
|
||||
$scope.selectListViewNode = function (node) {
|
||||
node.selected = node.selected === true ? false : true;
|
||||
nodeSelectHandler({}, { node: node });
|
||||
};
|
||||
|
||||
$scope.closeMiniListView = function () {
|
||||
$scope.miniListView = undefined;
|
||||
};
|
||||
|
||||
function openMiniListView(node) {
|
||||
$scope.miniListView = node;
|
||||
}
|
||||
|
||||
});
|
||||
@@ -1,6 +1,22 @@
|
||||
<div ng-controller="Umbraco.Editors.Content.CopyController">
|
||||
<div class="umb-dialog-body form-horizontal">
|
||||
<div class="umb-dialog-body form-horizontal" ng-cloak>
|
||||
<div class="umb-pane">
|
||||
|
||||
<div ng-show="error">
|
||||
<div class="alert alert-error">
|
||||
<div><strong>{{error.errorMsg}}</strong></div>
|
||||
<div>{{error.data.message}}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-show="success">
|
||||
<div class="alert alert-success">
|
||||
<strong>{{currentNode.name}}</strong> was copied to
|
||||
<strong>{{target.name}}</strong>
|
||||
</div>
|
||||
<button class="btn btn-primary" ng-click="nav.hideDialog()">Ok</button>
|
||||
</div>
|
||||
|
||||
<p class="abstract" ng-hide="success">
|
||||
Choose where to copy <strong>{{currentNode.name}}</strong> to in the tree structure below
|
||||
</p>
|
||||
@@ -9,52 +25,51 @@
|
||||
<div class="umb-loader"></div>
|
||||
</div>
|
||||
|
||||
<div ng-show="error">
|
||||
<h5 class="text-error">{{error.errorMsg}}</h5>
|
||||
<p class="text-error">{{error.data.message}}</p>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-success" ng-show="success">
|
||||
<p>
|
||||
<strong>{{currentNode.name}}</strong> was copied to
|
||||
<strong>{{target.name}}</strong>
|
||||
</p>
|
||||
|
||||
<button class="btn btn-primary" ng-click="nav.hideDialog()">Ok</button>
|
||||
</div>
|
||||
|
||||
<div ng-hide="success">
|
||||
|
||||
<umb-tree-search-box hide-search-callback="hideSearch"
|
||||
search-callback="onSearchResults"
|
||||
search-from-id="{{searchInfo.searchFromId}}"
|
||||
search-from-name="{{searchInfo.searchFromName}}"
|
||||
show-search="{{searchInfo.showSearch}}"
|
||||
section="{{section}}">
|
||||
</umb-tree-search-box>
|
||||
<div ng-hide="miniListView">
|
||||
<umb-tree-search-box
|
||||
hide-search-callback="hideSearch"
|
||||
search-callback="onSearchResults"
|
||||
search-from-id="{{searchInfo.searchFromId}}"
|
||||
search-from-name="{{searchInfo.searchFromName}}"
|
||||
show-search="{{searchInfo.showSearch}}"
|
||||
section="{{section}}">
|
||||
</umb-tree-search-box>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<umb-tree-search-results ng-if="searchInfo.showSearch"
|
||||
results="searchInfo.results"
|
||||
select-result-callback="selectResult">
|
||||
</umb-tree-search-results>
|
||||
<umb-tree-search-results
|
||||
ng-if="searchInfo.showSearch"
|
||||
results="searchInfo.results"
|
||||
select-result-callback="selectResult">
|
||||
</umb-tree-search-results>
|
||||
|
||||
<div ng-hide="searchInfo.showSearch">
|
||||
<umb-tree section="content"
|
||||
hideheader="false"
|
||||
hideoptions="true"
|
||||
isdialog="true"
|
||||
eventhandler="dialogTreeEventHandler"
|
||||
enablecheckboxes="true">
|
||||
</umb-tree>
|
||||
<div ng-hide="searchInfo.showSearch">
|
||||
<umb-tree
|
||||
section="content"
|
||||
hideheader="false"
|
||||
hideoptions="true"
|
||||
isdialog="true"
|
||||
eventhandler="dialogTreeEventHandler"
|
||||
enablelistviewexpand="true"
|
||||
enablecheckboxes="true">
|
||||
</umb-tree>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<umb-mini-list-view
|
||||
ng-if="miniListView"
|
||||
node="miniListView"
|
||||
entity-type="Document"
|
||||
on-select="selectListViewNode(node)"
|
||||
on-close="closeMiniListView()">
|
||||
</umb-mini-list-view>
|
||||
|
||||
<umb-pane>
|
||||
<umb-control-group localize="label" label="@defaultdialogs_relateToOriginalLabel">
|
||||
<input type="checkbox" ng-model="$parent.$parent.relateToOriginal"/>
|
||||
</umb-control-group>
|
||||
|
||||
</umb-pane>
|
||||
|
||||
<umb-pane>
|
||||
|
||||
@@ -1,7 +1,21 @@
|
||||
<div ng-controller="Umbraco.Editors.Content.MoveController">
|
||||
<div class="umb-dialog-body">
|
||||
<div class="umb-dialog-body" ng-cloak>
|
||||
<div class="umb-pane">
|
||||
|
||||
<div ng-show="error">
|
||||
<div class="alert alert-error">
|
||||
<div><strong>{{error.errorMsg}}</strong></div>
|
||||
<div>{{error.data.message}}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-show="success">
|
||||
<div class="alert alert-success">
|
||||
<strong>{{currentNode.name}}</strong> was moved underneath <strong>{{target.name}}</strong>
|
||||
</div>
|
||||
<button class="btn btn-primary" ng-click="nav.hideDialog()">Ok</button>
|
||||
</div>
|
||||
|
||||
<p class="abstract" ng-hide="success">
|
||||
<localize key="actions_chooseWhereToMove">Choose where to move</localize>
|
||||
<strong>{{currentNode.name}}</strong>
|
||||
@@ -12,43 +26,47 @@
|
||||
<div class="umb-loader"></div>
|
||||
</div>
|
||||
|
||||
<div ng-show="error">
|
||||
<h5 class="text-error">{{error.errorMsg}}</h5>
|
||||
<p class="text-error">{{error.data.message}}</p>
|
||||
</div>
|
||||
|
||||
<div ng-show="success">
|
||||
<h5 class="text-success"><strong>{{currentNode.name}}</strong> was moved underneath <strong>{{target.name}}</strong></h5>
|
||||
<button class="btn btn-primary" ng-click="nav.hideDialog()">Ok</button>
|
||||
</div>
|
||||
|
||||
<div ng-hide="success">
|
||||
|
||||
<umb-tree-search-box hide-search-callback="hideSearch"
|
||||
search-callback="onSearchResults"
|
||||
search-from-id="{{searchInfo.searchFromId}}"
|
||||
search-from-name="{{searchInfo.searchFromName}}"
|
||||
show-search="{{searchInfo.showSearch}}"
|
||||
section="{{section}}">
|
||||
</umb-tree-search-box>
|
||||
<div ng-hide="miniListView">
|
||||
<umb-tree-search-box
|
||||
hide-search-callback="hideSearch"
|
||||
search-callback="onSearchResults"
|
||||
search-from-id="{{searchInfo.searchFromId}}"
|
||||
search-from-name="{{searchInfo.searchFromName}}"
|
||||
show-search="{{searchInfo.showSearch}}"
|
||||
section="{{section}}">
|
||||
</umb-tree-search-box>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<umb-tree-search-results ng-if="searchInfo.showSearch"
|
||||
results="searchInfo.results"
|
||||
select-result-callback="selectResult">
|
||||
</umb-tree-search-results>
|
||||
<umb-tree-search-results
|
||||
ng-if="searchInfo.showSearch"
|
||||
results="searchInfo.results"
|
||||
select-result-callback="selectResult">
|
||||
</umb-tree-search-results>
|
||||
|
||||
<div ng-hide="searchInfo.showSearch">
|
||||
<umb-tree section="content"
|
||||
hideheader="false"
|
||||
hideoptions="true"
|
||||
isdialog="true"
|
||||
eventhandler="dialogTreeEventHandler"
|
||||
enablecheckboxes="true">
|
||||
</umb-tree>
|
||||
<div ng-hide="searchInfo.showSearch">
|
||||
<umb-tree
|
||||
section="content"
|
||||
hideheader="false"
|
||||
hideoptions="true"
|
||||
isdialog="true"
|
||||
eventhandler="dialogTreeEventHandler"
|
||||
enablelistviewexpand="true"
|
||||
enablecheckboxes="true">
|
||||
</umb-tree>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<umb-mini-list-view
|
||||
ng-if="miniListView"
|
||||
node="miniListView"
|
||||
entity-type="Document"
|
||||
on-select="selectListViewNode(node)"
|
||||
on-close="closeMiniListView()">
|
||||
</umb-mini-list-view>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -22,6 +22,51 @@ function startUpDynamicContentController(dashboardResource, assetsService) {
|
||||
var vm = this;
|
||||
vm.loading = true;
|
||||
vm.showDefault = false;
|
||||
|
||||
// default dashboard content
|
||||
vm.defaultDashboard = {
|
||||
infoBoxes: [
|
||||
{
|
||||
title: "Documentation",
|
||||
description: "Find the answers to your Umbraco questions",
|
||||
url: "https://our.umbraco.org/documentation/?utm_source=core&utm_medium=dashboard&utm_content=text&utm_campaign=documentation/"
|
||||
},
|
||||
{
|
||||
title: "Community",
|
||||
description: "Find the answers or ask your Umbraco questions",
|
||||
url: "https://our.umbraco.org/?utm_source=core&utm_medium=dashboard&utm_content=text&utm_campaign=our_forum"
|
||||
},
|
||||
{
|
||||
title: "Umbraco.tv",
|
||||
description: "Tutorial videos (some are free, some are on subscription)",
|
||||
url: "https://umbraco.tv/?utm_source=core&utm_medium=dashboard&utm_content=text&utm_campaign=tutorial_videos"
|
||||
},
|
||||
{
|
||||
title: "Training",
|
||||
description: "Real-life training and official Umbraco certifications",
|
||||
url: "https://umbraco.com/training/?utm_source=core&utm_medium=dashboard&utm_content=text&utm_campaign=training"
|
||||
}
|
||||
],
|
||||
articles: [
|
||||
{
|
||||
title: "Umbraco.TV - Learn from the source!",
|
||||
description: "Umbraco.TV will help you go from zero to Umbraco hero at a pace that suits you. Our easy to follow online training videos will give you the fundamental knowledge to start building awesome Umbraco websites.",
|
||||
img: "views/dashboard/default/umbracotv.jpg",
|
||||
url: "https://umbraco.tv/?utm_source=core&utm_medium=dashboard&utm_content=image&utm_campaign=tv",
|
||||
altText: "Umbraco.TV - Hours of Umbraco Video Tutorials",
|
||||
buttonText: "Visit Umbraco.TV"
|
||||
},
|
||||
{
|
||||
title: "Our Umbraco - The Friendliest Community",
|
||||
description: "Our Umbraco - the official community site is your one stop for everything Umbraco. Whether you need a question answered or looking for cool plugins, the world's best and friendliest community is just a click away.",
|
||||
img: "views/dashboard/default/ourumbraco.jpg",
|
||||
url: "https://our.umbraco.org/?utm_source=core&utm_medium=dashboard&utm_content=image&utm_campaign=our",
|
||||
altText: "Our Umbraco",
|
||||
buttonText: "Visit Our Umbraco"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
//proxy remote css through the local server
|
||||
assetsService.loadCss( dashboardResource.getRemoteDashboardCssUrl("content") );
|
||||
|
||||
@@ -38,58 +38,34 @@
|
||||
|
||||
<!-- Default content in case we cannot fetch content from the outside -->
|
||||
<div style="max-width: 1200px" ng-if="vm.showDefault">
|
||||
<h3><strong>Welcome to The Friendly CMS</strong></h3>
|
||||
<p style="font-size: 16px; line-height: 1.5; margin-bottom: 30px; max-width: 760px;">
|
||||
<span>Thank you for choosing Umbraco - we think this could be the beginning of something beautiful. While it may feel overwhelming at first, we've done a lot to make the learning curve as smooth and fast as possible.</span>
|
||||
</p>
|
||||
<h4>Find out more:</h4>
|
||||
<ul>
|
||||
<li>Find the answers to your Umbraco questions in <a href="https://our.umbraco.org/documentation/" target="_blank" class="btn-link-underline">our Documentation</a></li>
|
||||
<li>Ask a question in the <a href="https://our.umbraco.org" target="_blank" class="btn-link-underline">Community Forum</a></li>
|
||||
<li>Find <a href="https://our.umbraco.org/projects" target="_blank" class="btn-link-underline">an add-on package</a> to help you get going quickly</li>
|
||||
<li>Watch <a href="https://umbraco.tv" class="btn-link-underline">our tutorial videos</a> (some are free, some require a subscription)</li>
|
||||
<li>Find out about <a href="https://umbraco.com/products-and-support" target="_blank" class="btn-link-underline">our productivity boosting tools and commercial support</a></li>
|
||||
<li>Find out about <a href="https://umbraco.com/products/training" target="_blank" class="btn-link-underline">real-life training and certification opportunities</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="row">
|
||||
<div class="span4">
|
||||
<a href="https://umbraco.tv/?utm_source=core&utm_medium=dashboard&utm_content=image&utm_campaign=tv" target="_blank" class="nounderline">
|
||||
<img src="views/dashboard/default/umbracotv.png" alt="Umbraco.TV - Hours of Umbraco Video Tutorials" style="margin: 10px 0 10px 0" />
|
||||
</a>
|
||||
<div class="welcome-dashboard__intro">
|
||||
<h1 class="welcome-dashboard__title">Welcome to The Friendly CMS</h1>
|
||||
<p class="welcome-dashboard__intro-text">Thank you for choosing Umbraco - we think this could be the beginning of something beautiful. While it may feel overwhelming at first, we've done a lot to make the learning curve as smooth and fast as possible.</p>
|
||||
</div>
|
||||
|
||||
<div class="welcome-dashboard__info-box-boxes">
|
||||
<a ng-href="{{infoBox.url}}" target="_blank" class="welcome-dashboard__info-box" ng-repeat="infoBox in vm.defaultDashboard.infoBoxes">
|
||||
<div class="welcome-dashboard__info-box-title">{{ infoBox.title }}</div>
|
||||
<div class="welcome-dashboard__info-box-description">{{ infoBox.description }}</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<a href="https://umbraco.tv/?utm_source=core&utm_medium=dashboard&utm_content=header&utm_campaign=tv" target="_blank" class="btn-link -underline">
|
||||
<h4> <strong>Umbraco.TV - Learn from the source!</strong> </h4>
|
||||
</a>
|
||||
|
||||
<p style="line-height: 1.5;">
|
||||
Umbraco.TV will help you go from zero to Umbraco
|
||||
hero at a pace that suits you. Our easy to follow
|
||||
online training videos will give you the fundamental
|
||||
knowledge to start building awesome Umbraco websites.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="span4 offset1">
|
||||
|
||||
<a href="https://our.umbraco.org/?utm_source=core&utm_medium=dashboard&utm_content=image&utm_campaign=our" target="_blank" class="nounderline">
|
||||
<img src="views/dashboard/default/ourumbraco.png" alt="Our Umbraco" style="margin: 10px 0 10px 0" />
|
||||
</a>
|
||||
|
||||
<a href="https://our.umbraco.org/?utm_source=core&utm_medium=dashboard&utm_content=header&utm_campaign=our" target="_blank" class="btn-link -underline">
|
||||
<h4><strong>Our Umbraco - The Friendliest Community</strong></h4>
|
||||
</a>
|
||||
|
||||
<p style="line-height: 1.5;">
|
||||
Our Umbraco - the official community site is your one
|
||||
stop for everything Umbraco. Whether you need a
|
||||
question answered or looking for cool plugins, the
|
||||
worlds best community is just a click away.
|
||||
</p>
|
||||
|
||||
<div class="welcome-dashboard__cards">
|
||||
<div class="welcome-dashboard__card" ng-repeat="article in vm.defaultDashboard.articles">
|
||||
<div class="welcome-dashboard__card-image-wrapper">
|
||||
<a ng-href="{{article.url}}" target="_blank">
|
||||
<img class="welcome-dashboard__card-image" ng-src="{{article.img}}" alt="{{ article.altText }}" />
|
||||
</a>
|
||||
</div>
|
||||
<div class="welcome-dashboard__card-content">
|
||||
<h2 class="welcome-dashboard__card-title">{{ article.title }}</h2>
|
||||
<div class="welcome-dashboard__card-teaser">{{ article.description }}</div>
|
||||
<a class="btn btn-success" ng-href="{{article.url}}" target="_blank">{{article.buttonText}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 22 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 104 KiB |
@@ -7,8 +7,11 @@ angular.module("umbraco").controller("Umbraco.Editors.Media.MoveController",
|
||||
var node = dialogOptions.currentNode;
|
||||
|
||||
function nodeSelectHandler(ev, args) {
|
||||
args.event.preventDefault();
|
||||
args.event.stopPropagation();
|
||||
|
||||
if(args && args.event) {
|
||||
args.event.preventDefault();
|
||||
args.event.stopPropagation();
|
||||
}
|
||||
|
||||
eventsService.emit("editors.media.moveController.select", args);
|
||||
|
||||
@@ -21,8 +24,15 @@ angular.module("umbraco").controller("Umbraco.Editors.Media.MoveController",
|
||||
$scope.target.selected = true;
|
||||
}
|
||||
|
||||
$scope.dialogTreeEventHandler.bind("treeNodeSelect", nodeSelectHandler);
|
||||
function nodeExpandedHandler(ev, args) {
|
||||
// open mini list view for list views
|
||||
if (args.node.metaData.isContainer) {
|
||||
openMiniListView(args.node);
|
||||
}
|
||||
}
|
||||
|
||||
$scope.dialogTreeEventHandler.bind("treeNodeSelect", nodeSelectHandler);
|
||||
$scope.dialogTreeEventHandler.bind("treeNodeExpanded", nodeExpandedHandler);
|
||||
|
||||
$scope.move = function () {
|
||||
mediaResource.move({ parentId: $scope.target.id, id: node.id })
|
||||
@@ -55,5 +65,21 @@ angular.module("umbraco").controller("Umbraco.Editors.Media.MoveController",
|
||||
|
||||
$scope.$on('$destroy', function () {
|
||||
$scope.dialogTreeEventHandler.unbind("treeNodeSelect", nodeSelectHandler);
|
||||
$scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler);
|
||||
});
|
||||
|
||||
// Mini list view
|
||||
$scope.selectListViewNode = function (node) {
|
||||
node.selected = node.selected === true ? false : true;
|
||||
nodeSelectHandler({}, { node: node });
|
||||
};
|
||||
|
||||
$scope.closeMiniListView = function () {
|
||||
$scope.miniListView = undefined;
|
||||
};
|
||||
|
||||
function openMiniListView(node) {
|
||||
$scope.miniListView = node;
|
||||
}
|
||||
|
||||
});
|
||||
@@ -1,33 +1,49 @@
|
||||
<div ng-controller="Umbraco.Editors.Media.MoveController">
|
||||
<div class="umb-dialog-body">
|
||||
<div class="umb-dialog-body" ng-cloak>
|
||||
<div class="umb-pane">
|
||||
|
||||
<div ng-show="error">
|
||||
<div class="alert alert-error">
|
||||
<div><strong>{{error.errorMsg}}</strong></div>
|
||||
<div>{{error.data.message}}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-show="success">
|
||||
<div class="alert alert-success">
|
||||
<strong>{{currentNode.name}}</strong> was moved underneath <strong>{{target.name}}</strong>
|
||||
</div>
|
||||
<button class="btn btn-primary" ng-click="nav.hideDialog()">Ok</button>
|
||||
</div>
|
||||
|
||||
<p class="abstract" ng-hide="success">
|
||||
<localize key="actions_chooseWhereToMove">Choose where to move</localize>
|
||||
<strong>{{currentNode.name}}</strong>
|
||||
<localize key="actions_toInTheTreeStructureBelow">to in the tree structure below</localize>
|
||||
</p>
|
||||
|
||||
<div class="alert alert-error" ng-show="error" ng-cloak>
|
||||
<h4>{{error.errorMsg}}</h4>
|
||||
<p>{{error.data.Message}}</p>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-success" ng-show="success" ng-cloak>
|
||||
<p><strong>{{currentNode.name}}</strong> was moved underneath
|
||||
<strong>{{target.name}}</strong></p>
|
||||
|
||||
<button class="btn btn-primary" ng-click="nav.hideDialog()">Ok</button>
|
||||
</div>
|
||||
|
||||
<div ng-hide="success">
|
||||
<umb-tree section="media"
|
||||
hideheader="false"
|
||||
hideoptions="true"
|
||||
isdialog="true"
|
||||
eventhandler="dialogTreeEventHandler"
|
||||
enablecheckboxes="true">
|
||||
</umb-tree>
|
||||
|
||||
<div ng-hide="miniListView">
|
||||
<umb-tree
|
||||
section="media"
|
||||
hideheader="false"
|
||||
hideoptions="true"
|
||||
isdialog="true"
|
||||
eventhandler="dialogTreeEventHandler"
|
||||
enablelistviewexpand="true"
|
||||
enablecheckboxes="true">
|
||||
</umb-tree>
|
||||
</div>
|
||||
|
||||
<umb-mini-list-view
|
||||
ng-if="miniListView"
|
||||
node="miniListView"
|
||||
entity-type="Media"
|
||||
on-select="selectListViewNode(node)"
|
||||
on-close="closeMiniListView()">
|
||||
</umb-mini-list-view>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,47 +1,42 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function PartialViewMacrosCreateController($scope, codefileResource, $location, navigationService, formHelper, localizationService, appState) {
|
||||
function PartialViewMacrosCreateController($scope, codefileResource, macroResource, $location, navigationService, formHelper, localizationService, appState) {
|
||||
|
||||
var vm = this;
|
||||
var node = $scope.dialogOptions.currentNode;
|
||||
var localizeCreateFolder = localizationService.localize("defaultdialog_createFolder");
|
||||
|
||||
vm.snippets = [];
|
||||
vm.showSnippets = false;
|
||||
vm.creatingFolder = false;
|
||||
vm.snippet = "Empty";
|
||||
vm.createMacro = false;
|
||||
vm.createFolderError = "";
|
||||
vm.folderName = "";
|
||||
vm.fileName = "";
|
||||
|
||||
vm.creatingFolder = false;
|
||||
vm.creatingFile = false;
|
||||
|
||||
vm.createPartialViewMacro = createPartialViewMacro;
|
||||
vm.showCreateFolder = showCreateFolder;
|
||||
vm.showCreateFile = showCreateFile;
|
||||
vm.createFolder = createFolder;
|
||||
vm.showCreateFromSnippet = showCreateFromSnippet;
|
||||
vm.createFile = createFile;
|
||||
|
||||
function onInit() {
|
||||
codefileResource.getSnippets('partialViewMacros')
|
||||
.then(function(snippets) {
|
||||
.then(function (snippets) {
|
||||
vm.snippets = snippets;
|
||||
});
|
||||
}
|
||||
|
||||
function createPartialViewMacro(selectedSnippet) {
|
||||
|
||||
var snippet = null;
|
||||
|
||||
if(selectedSnippet && selectedSnippet.fileName) {
|
||||
snippet = selectedSnippet.fileName;
|
||||
}
|
||||
|
||||
$location.path("/developer/partialviewmacros/edit/" + node.id).search("create", "true").search("snippet", snippet);
|
||||
navigationService.hideMenu();
|
||||
|
||||
}
|
||||
|
||||
function showCreateFolder() {
|
||||
vm.creatingFolder = true;
|
||||
}
|
||||
|
||||
function showCreateFile() {
|
||||
vm.creatingFile = true;
|
||||
}
|
||||
|
||||
function createFolder(form) {
|
||||
if (formHelper.submitForm({scope: $scope, formCtrl: form, statusMessage: localizeCreateFolder})) {
|
||||
|
||||
@@ -75,11 +70,32 @@
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function showCreateFromSnippet() {
|
||||
vm.showSnippets = true;
|
||||
|
||||
function createFile(form) {
|
||||
if (formHelper.submitForm({ scope: $scope, formCtrl: form, statusMessage: 'create file' })) {
|
||||
|
||||
if (vm.createMacro) {
|
||||
var path = decodeURIComponent(node.id);
|
||||
macroResource.createPartialViewMacroWithFile(path, vm.fileName).then(function(created) {
|
||||
$location.path("/developer/partialviewmacros/edit/" + node.id).search("create", "true").search("name", vm.fileName).search("snippet", vm.snippet);
|
||||
navigationService.hideMenu();
|
||||
}, function(err) {
|
||||
vm.createFileError = err;
|
||||
|
||||
//show any notifications
|
||||
if (angular.isArray(err.data.notifications)) {
|
||||
for (var i = 0; i < err.data.notifications.length; i++) {
|
||||
notificationsService.showNotification(err.data.notifications[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
$location.path("/developer/partialviewmacros/edit/" + node.id).search("create", "true").search("name", vm.fileName).search("snippet", vm.snippet);
|
||||
navigationService.hideMenu();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onInit();
|
||||
|
||||
}
|
||||
|
||||
@@ -2,46 +2,61 @@
|
||||
|
||||
<div class="umbracoDialog umb-dialog-body with-footer">
|
||||
|
||||
<div class="umb-pane" ng-if="!vm.creatingFolder">
|
||||
|
||||
<div class="umb-pane" ng-if="!vm.creatingFolder && !vm.creatingFile">
|
||||
|
||||
<h5><localize key="create_createUnder">Create an item under</localize> {{currentNode.name}}</h5>
|
||||
|
||||
<!-- Main options -->
|
||||
<div ng-if="!vm.showSnippets">
|
||||
<ul class="umb-actions umb-actions-child">
|
||||
<li>
|
||||
<a href="" ng-click="vm.createPartialViewMacro()" umb-auto-focus>
|
||||
<i class="large icon-article"></i>
|
||||
<span class="menu-label"><localize key="create_newEmptyPartialViewMacro">New empty partial view macro</localize></span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="" ng-click="vm.showCreateFromSnippet()">
|
||||
<i class="large icon-article"></i>
|
||||
<span class="menu-label"><localize key="create_newPartialViewMacroFromSnippet">New partial view macro from snippet</localize></span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="" ng-click="vm.showCreateFolder()">
|
||||
<i class="large icon-folder"></i>
|
||||
<span class="menu-label"><localize key="general_folder"></localize></span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<ul class="umb-actions umb-actions-child">
|
||||
<li>
|
||||
<a href="" ng-click="vm.showCreateFile()" umb-auto-focus>
|
||||
<i class="large icon-article"></i>
|
||||
<span class="menu-label"><localize key="create_newPartialViewMacro">New partial view macro</localize></span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="" ng-click="vm.showCreateFolder()">
|
||||
<i class="large icon-folder"></i>
|
||||
<span class="menu-label"><localize key="general_folder"></localize></span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Snippets list -->
|
||||
<div ng-if="vm.showSnippets">
|
||||
<ul class="umb-actions umb-actions-child">
|
||||
<li ng-repeat="snippet in vm.snippets">
|
||||
<a href="" ng-click="vm.createPartialViewMacro(snippet)" style="padding-top: 6px; padding-bottom: 6px;">
|
||||
<i class="icon-article" style="font-size: 20px;"></i>
|
||||
<span class="menu-label" style="margin-left: 0; padding-left: 5px;">{{ snippet.name }}</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Create file -->
|
||||
<div class="umb-pane" ng-if="vm.creatingFile">
|
||||
<form novalidate name="createFileForm"
|
||||
ng-submit="vm.createFile(createFileForm)"
|
||||
val-form-manager>
|
||||
|
||||
<div ng-show="vm.createFileError">
|
||||
<h5 class="text-error">{{vm.createFileError.errorMsg}}</h5>
|
||||
<p class="text-error">{{vm.createFileError.data.message}}</p>
|
||||
</div>
|
||||
|
||||
<umb-control-group label="Enter a file name" hide-label="false">
|
||||
<input type="text" name="fileName" ng-model="vm.fileName" class="umb-textstring textstring input-block-level" umb-auto-focus required no-dirty-check />
|
||||
|
||||
<div>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" name="createMacro" ng-model="vm.createMacro" ng-true-value="true" ng-false-value="false" no-dirty-check/>
|
||||
Create corresponding macro
|
||||
</label>
|
||||
</div>
|
||||
</umb-control-group>
|
||||
|
||||
<umb-control-group label="Select a snippet (or create an empty file)" hide-label="false">
|
||||
|
||||
<select name="snippet"
|
||||
class="umb-editor umb-dropdown"
|
||||
ng-model="vm.snippet"
|
||||
ng-options="snippet.fileName as snippet.name for snippet in vm.snippets"></select>
|
||||
|
||||
</umb-control-group>
|
||||
|
||||
<button type="submit" class="btn btn-primary"><localize key="general_create">Create</localize></button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Create folder -->
|
||||
@@ -49,14 +64,14 @@
|
||||
<form novalidate name="createFolderForm"
|
||||
ng-submit="vm.createFolder(createFolderForm)"
|
||||
val-form-manager>
|
||||
|
||||
|
||||
<div ng-show="vm.createFolderError">
|
||||
<h5 class="text-error">{{vm.createFolderError.errorMsg}}</h5>
|
||||
<p class="text-error">{{vm.createFolderError.data.message}}</p>
|
||||
</div>
|
||||
|
||||
<umb-control-group label="Enter a folder name" hide-label="false">
|
||||
<input type="text" name="folderName" ng-model="vm.folderName" class="umb-textstring textstring input-block-level" umb-auto-focus required />
|
||||
<input type="text" name="folderName" ng-model="vm.folderName" class="umb-textstring textstring input-block-level" umb-auto-focus required no-dirty-check />
|
||||
</umb-control-group>
|
||||
|
||||
<button type="submit" class="btn btn-primary"><localize key="general_create">Create</localize></button>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
/* Functions bound to view model */
|
||||
|
||||
function save() {
|
||||
|
||||
|
||||
vm.page.saveButtonState = "busy";
|
||||
vm.partialViewMacro.content = vm.editor.getValue();
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
}, function (err) {
|
||||
|
||||
vm.page.saveButtonState = "error";
|
||||
|
||||
|
||||
localizationService.localize("speechBubbles_validationFailedHeader").then(function (headerValue) {
|
||||
localizationService.localize("speechBubbles_validationFailedMessage").then(function(msgValue) {
|
||||
notificationsService.error(headerValue, msgValue);
|
||||
@@ -104,7 +104,7 @@
|
||||
var code = templateHelper.getInsertDictionarySnippet(model.insert.node.name);
|
||||
insert(code);
|
||||
break;
|
||||
|
||||
|
||||
case "umbracoField":
|
||||
insert(model.insert.umbracoField);
|
||||
break;
|
||||
@@ -169,7 +169,7 @@
|
||||
vm.pageFieldOverlay.show = false;
|
||||
vm.pageFieldOverlay = null;
|
||||
// focus editor
|
||||
vm.editor.focus();
|
||||
vm.editor.focus();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -212,7 +212,7 @@
|
||||
|
||||
var code = templateHelper.getQuerySnippet(model.result.queryExpression);
|
||||
insert(code);
|
||||
|
||||
|
||||
vm.queryBuilderOverlay.show = false;
|
||||
vm.queryBuilderOverlay = null;
|
||||
},
|
||||
@@ -222,7 +222,7 @@
|
||||
vm.queryBuilderOverlay.show = false;
|
||||
vm.queryBuilderOverlay = null;
|
||||
// focus editor
|
||||
vm.editor.focus();
|
||||
vm.editor.focus();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -232,9 +232,9 @@
|
||||
function init() {
|
||||
//we need to load this somewhere, for now its here.
|
||||
assetsService.loadCss("lib/ace-razor-mode/theme/razor_chrome.css");
|
||||
|
||||
|
||||
if ($routeParams.create) {
|
||||
|
||||
|
||||
var snippet = "Empty";
|
||||
|
||||
if($routeParams.snippet) {
|
||||
@@ -242,6 +242,9 @@
|
||||
}
|
||||
|
||||
codefileResource.getScaffold("partialViewMacros", $routeParams.id, snippet).then(function (partialViewMacro) {
|
||||
if ($routeParams.name) {
|
||||
partialViewMacro.name = $routeParams.name;
|
||||
}
|
||||
ready(partialViewMacro, false);
|
||||
});
|
||||
|
||||
@@ -276,7 +279,7 @@
|
||||
},
|
||||
onLoad: function(_editor) {
|
||||
vm.editor = _editor;
|
||||
|
||||
|
||||
// initial cursor placement
|
||||
// Keep cursor in name field if we are create a new template
|
||||
// else set the cursor at the bottom of the code editor
|
||||
@@ -291,6 +294,8 @@
|
||||
//change on blur, focus
|
||||
vm.editor.on("blur", persistCurrentLocation);
|
||||
vm.editor.on("focus", persistCurrentLocation);
|
||||
vm.editor.on("change", changeAceEditor);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,8 +314,12 @@
|
||||
vm.currentPosition = vm.editor.getCursorPosition();
|
||||
}
|
||||
|
||||
function changeAceEditor() {
|
||||
setFormState("dirty");
|
||||
}
|
||||
|
||||
function setFormState(state) {
|
||||
|
||||
|
||||
// get the current form
|
||||
var currentForm = angularHelper.getCurrentForm($scope);
|
||||
|
||||
@@ -322,7 +331,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
init();
|
||||
|
||||
}
|
||||
|
||||
@@ -367,6 +367,8 @@
|
||||
//change on blur, focus
|
||||
vm.editor.on("blur", persistCurrentLocation);
|
||||
vm.editor.on("focus", persistCurrentLocation);
|
||||
vm.editor.on("change", changeAceEditor);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -385,6 +387,10 @@
|
||||
vm.currentPosition = vm.editor.getCursorPosition();
|
||||
}
|
||||
|
||||
function changeAceEditor() {
|
||||
setFormState("dirty");
|
||||
}
|
||||
|
||||
function setFormState(state) {
|
||||
|
||||
// get the current form
|
||||
|
||||
+2
-2
@@ -30,10 +30,10 @@
|
||||
<div class="control-group">
|
||||
<label>Size</label>
|
||||
<input name="newItem.width" type="number" placeholder="Width"
|
||||
ng-model="newItem.width" class="umb-editor-tiny" val-highlight="{{hasError}}" />
|
||||
ng-model="newItem.width" class="umb-editor-small" val-highlight="{{hasError}}" />
|
||||
×
|
||||
<input name="newItem.height" type="number" placeholder="Height"
|
||||
ng-model="newItem.height" class="umb-editor-tiny" val-highlight="{{hasError}}" />
|
||||
ng-model="newItem.height" class="umb-editor-small" val-highlight="{{hasError}}" />
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function ScriptsEditController($scope, $routeParams, $timeout, appState, editorState, navigationService, assetsService, codefileResource, contentEditingHelper, notificationsService, localizationService, templateHelper) {
|
||||
function ScriptsEditController($scope, $routeParams, $timeout, appState, editorState, navigationService, assetsService, codefileResource, contentEditingHelper, notificationsService, localizationService, templateHelper, angularHelper) {
|
||||
|
||||
var vm = this;
|
||||
var currentPosition = null;
|
||||
@@ -169,9 +169,29 @@
|
||||
});
|
||||
}
|
||||
|
||||
vm.editor.on("change", changeAceEditor);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function changeAceEditor() {
|
||||
setFormState("dirty");
|
||||
}
|
||||
|
||||
function setFormState(state) {
|
||||
|
||||
// get the current form
|
||||
var currentForm = angularHelper.getCurrentForm($scope);
|
||||
|
||||
// set state
|
||||
if(state === "dirty") {
|
||||
currentForm.$setDirty();
|
||||
} else if(state === "pristine") {
|
||||
currentForm.$setPristine();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
@@ -264,6 +264,7 @@
|
||||
//change on blur, focus
|
||||
vm.editor.on("blur", persistCurrentLocation);
|
||||
vm.editor.on("focus", persistCurrentLocation);
|
||||
vm.editor.on("change", changeAceEditor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,7 +309,7 @@
|
||||
break;
|
||||
|
||||
case "partial":
|
||||
var code = templateHelper.getInsertPartialSnippet(model.insert.node.name);
|
||||
var code = templateHelper.getInsertPartialSnippet(model.insert.node.parentId, model.insert.node.name);
|
||||
insert(code);
|
||||
break;
|
||||
|
||||
@@ -418,9 +419,15 @@
|
||||
multiPicker: false,
|
||||
show: true,
|
||||
title: localizationService.localize("template_insertPartialView"),
|
||||
filter: function(i) {
|
||||
if(i.name.indexOf(".cshtml") === -1 && i.name.indexOf(".vbhtml") === -1) {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
filterCssClass: "not-allowed",
|
||||
select: function(node){
|
||||
|
||||
var code = templateHelper.getInsertPartialSnippet(node.name);
|
||||
|
||||
var code = templateHelper.getInsertPartialSnippet(node.parentId, node.name);
|
||||
insert(code);
|
||||
|
||||
vm.partialItemOverlay.show = false;
|
||||
@@ -632,6 +639,10 @@
|
||||
vm.currentPosition = vm.editor.getCursorPosition();
|
||||
}
|
||||
|
||||
function changeAceEditor() {
|
||||
setFormState("dirty");
|
||||
}
|
||||
|
||||
function setFormState(state) {
|
||||
|
||||
// get the current form
|
||||
|
||||
+9
-2
@@ -49,7 +49,11 @@
|
||||
setValue: function() {},
|
||||
focus: function() {},
|
||||
clearSelection: function() {},
|
||||
navigateFileStart: function() {}
|
||||
navigateFileStart: function() {},
|
||||
commands: {
|
||||
bindKey: function() {},
|
||||
addCommands: function() {}
|
||||
}
|
||||
};
|
||||
|
||||
controller = createController();
|
||||
@@ -107,7 +111,10 @@
|
||||
getInsertPartialSnippet: function() { return ""; },
|
||||
getQuerySnippet: function() { return ""; },
|
||||
getRenderBodySnippet: function() { return ""; },
|
||||
getRenderSectionSnippet: function() { return ""; }
|
||||
getRenderSectionSnippet: function() { return ""; },
|
||||
getGeneralShortcuts: function() { return ""; },
|
||||
getEditorShortcuts: function() { return ""; },
|
||||
getTemplateEditorShortcuts: function() { return ""; }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -23,9 +23,32 @@ describe('service: templateHelper', function () {
|
||||
|
||||
describe('getInsertPartialSnippet', function () {
|
||||
|
||||
it('should return the snippet for inserting a partial', function () {
|
||||
var snippet = '@Html.Partial("nodeName")';
|
||||
expect(templateHelper.getInsertPartialSnippet("nodeName")).toBe(snippet);
|
||||
it('should return the snippet for inserting a partial from the root', function () {
|
||||
var parentId = "";
|
||||
var nodeName = "Footer.cshtml";
|
||||
var snippet = '@Html.Partial("Footer")';
|
||||
expect(templateHelper.getInsertPartialSnippet(parentId, nodeName)).toBe(snippet);
|
||||
});
|
||||
|
||||
it('should return the snippet for inserting a partial from a folder', function () {
|
||||
var parentId = "Folder";
|
||||
var nodeName = "Footer.cshtml";
|
||||
var snippet = '@Html.Partial("Folder/Footer")';
|
||||
expect(templateHelper.getInsertPartialSnippet(parentId, nodeName)).toBe(snippet);
|
||||
});
|
||||
|
||||
it('should return the snippet for inserting a partial from a nested folder', function () {
|
||||
var parentId = "Folder/NestedFolder";
|
||||
var nodeName = "Footer.cshtml";
|
||||
var snippet = '@Html.Partial("Folder/NestedFolder/Footer")';
|
||||
expect(templateHelper.getInsertPartialSnippet(parentId, nodeName)).toBe(snippet);
|
||||
});
|
||||
|
||||
it('should return the snippet for inserting a partial from a folder with spaces in its name', function () {
|
||||
var parentId = "Folder with spaces";
|
||||
var nodeName = "Footer.cshtml";
|
||||
var snippet = '@Html.Partial("Folder with spaces/Footer")';
|
||||
expect(templateHelper.getInsertPartialSnippet(parentId, nodeName)).toBe(snippet);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -127,8 +127,8 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\dotless.1.4.1.0\lib\dotless.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Examine, Version=0.1.81.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.81\lib\net45\Examine.dll</HintPath>
|
||||
<Reference Include="Examine, Version=0.1.82.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.82\lib\net45\Examine.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<package id="ClientDependency" version="1.9.2" targetFramework="net45" />
|
||||
<package id="ClientDependency-Mvc5" version="1.8.0.0" targetFramework="net45" />
|
||||
<package id="dotless" version="1.4.1.0" targetFramework="net45" />
|
||||
<package id="Examine" version="0.1.81" targetFramework="net45" />
|
||||
<package id="Examine" version="0.1.82" targetFramework="net45" />
|
||||
<package id="ImageProcessor" version="2.5.2" targetFramework="net45" />
|
||||
<package id="ImageProcessor.Web" version="4.8.2" targetFramework="net45" />
|
||||
<package id="ImageProcessor.Web.Config" version="2.3.0" targetFramework="net45" />
|
||||
|
||||
@@ -201,6 +201,7 @@
|
||||
<key alias="newDataType">New data type</key>
|
||||
<key alias="newJavascriptFile">New javascript file</key>
|
||||
<key alias="newEmptyPartialView">New empty partial view</key>
|
||||
<key alias="newPartialViewMacro">New partial view macro</key>
|
||||
<key alias="newPartialViewFromSnippet">New partial view from snippet</key>
|
||||
<key alias="newEmptyPartialViewMacro">New empty partial view macro</key>
|
||||
<key alias="newPartialViewMacroFromSnippet">New partial view macro from snippet</key>
|
||||
@@ -992,7 +993,7 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="dictionaryItemSaved">Dictionary item saved</key>
|
||||
<key alias="editContentPublishedFailedByParent">Publishing failed because the parent page isn't published</key>
|
||||
<key alias="editContentPublishedHeader">Content published</key>
|
||||
<key alias="editContentPublishedText">and visible at the website</key>
|
||||
<key alias="editContentPublishedText">and visible on the website</key>
|
||||
<key alias="editContentSavedHeader">Content saved</key>
|
||||
<key alias="editContentSavedText">Remember to publish to make changes visible</key>
|
||||
<key alias="editContentSendToPublish">Sent For Approval</key>
|
||||
|
||||
@@ -982,7 +982,7 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="dictionaryItemSaved">Dictionary item saved</key>
|
||||
<key alias="editContentPublishedFailedByParent">Publishing failed because the parent page isn't published</key>
|
||||
<key alias="editContentPublishedHeader">Content published</key>
|
||||
<key alias="editContentPublishedText">and visible at the website</key>
|
||||
<key alias="editContentPublishedText">and visible on the website</key>
|
||||
<key alias="editContentSavedHeader">Content saved</key>
|
||||
<key alias="editContentSavedText">Remember to publish to make changes visible</key>
|
||||
<key alias="editContentSendToPublish">Sent For Approval</key>
|
||||
|
||||
@@ -123,7 +123,6 @@
|
||||
<key alias="saveListView">Сохранить список</key>
|
||||
<key alias="select">Выбрать</key>
|
||||
<key alias="selectCurrentFolder">Выбрать текущую папку</key>
|
||||
<key alias="selected">выбранные</key>
|
||||
<key alias="showPage">Предварительный просмотр</key>
|
||||
<key alias="showPageDisabled">Предварительный просмотр запрещен, так как документу не сопоставлен шаблон</key>
|
||||
<key alias="somethingElse">Другие действия</key>
|
||||
@@ -993,6 +992,7 @@
|
||||
<key alias="installStateInstalling">Установка...</key>
|
||||
<key alias="installStateRestarting">Перезапуск, подождите, пожалуйста...</key>
|
||||
<key alias="installStateComplete">Все готово, сейчас браузер перезагрузит страницу, подождите, пожалуйста...</key>
|
||||
<key alias="installStateCompleted">Пожалуйста, нажмите кнопку 'finish' для завершения установки и перезагрузки страницы.</key>
|
||||
</area>
|
||||
<area alias="paste">
|
||||
<key alias="doNothing">Вставить, полностью сохранив форматирование (не рекомендуется)</key>
|
||||
@@ -1119,9 +1119,9 @@
|
||||
<key alias="statistics">Статистика</key>
|
||||
<key alias="translation">Перевод</key>
|
||||
<key alias="users">Пользователи</key>
|
||||
<key alias="addIcon">Добавить значок</key>
|
||||
</area>
|
||||
<area alias="settings">
|
||||
<key alias="addIcon">Добавить значок</key>
|
||||
<key alias="asAContentMasterType">в качестве родительского типа. Вкладки родительского типа не показаны и могут быть изменены непосредственно в родительском типе</key>
|
||||
<key alias="contentTypeEnabled">Родительский тип контента разрешен</key>
|
||||
<key alias="contentTypeUses">Данный тип контента использует</key>
|
||||
@@ -1158,6 +1158,16 @@
|
||||
|
||||
<key alias="toggleListView">В формате списка</key>
|
||||
<key alias="toggleAllowAsRoot">Разрешить в качестве корневого</key>
|
||||
|
||||
<key alias="commentLine">Закомментировать/раскомментировать строки</key>
|
||||
<key alias="removeLine">Удалить строку</key>
|
||||
<key alias="copyLineUp">Копировать строки вверх</key>
|
||||
<key alias="copyLineDown">Копировать строки вниз</key>
|
||||
<key alias="moveLineUp">Переместить строки вверх</key>
|
||||
<key alias="moveLineDown">Переместить строки вниз</key>
|
||||
|
||||
<key alias="generalHeader">Общее</key>
|
||||
<key alias="editorHeader">Редактор</key>
|
||||
</area>
|
||||
<area alias="sort">
|
||||
<key alias="sortOrder">Порядок сортировки</key>
|
||||
@@ -1178,6 +1188,7 @@
|
||||
<key alias="contentTypeTabDeletedText">Вкладка с идентификатором (id): %0% удалена</key>
|
||||
<key alias="contentUnpublished">Документ скрыт (публикация отменена)</key>
|
||||
<key alias="cssErrorHeader">Стиль CSS не сохранен</key>
|
||||
<key alias="cssErrorText">При сохранении файла произошла ошибка.</key>
|
||||
<key alias="cssSavedHeader">Стиль CSS сохранен</key>
|
||||
<key alias="cssSavedText">Стиль CSS сохранен без ошибок</key>
|
||||
<key alias="dataTypeSaved">Тип данных сохранен</key>
|
||||
@@ -1202,9 +1213,13 @@
|
||||
<key alias="fileErrorText">Файл не может быть сохранен. Пожалуйста, проверьте установки файловых разрешений</key>
|
||||
<key alias="fileSavedHeader">Файл сохранен</key>
|
||||
<key alias="fileSavedText">Файл сохранен без ошибок</key>
|
||||
<key alias="invalidUserPermissionsText">У текущего пользователя недостаточно прав, невозможно завершить операцию</key>
|
||||
<key alias="languageSaved">Язык сохранен</key>
|
||||
<key alias="mediaTypeSavedHeader">Тип медиа сохранен</key>
|
||||
<key alias="memberTypeSavedHeader">Тип участника сохранен</key>
|
||||
<key alias="operationCancelledHeader">Отменено</key>
|
||||
<key alias="operationCancelledText">Операция отменена установленным сторонним расширением или блоком кода</key>
|
||||
<key alias="operationFailedHeader">Ошибка</key>
|
||||
<key alias="partialViewErrorHeader">Представление не сохранено</key>
|
||||
<key alias="partialViewErrorText">Произошла ошибка при сохранении файла</key>
|
||||
<key alias="partialViewSavedHeader">Представление сохранено</key>
|
||||
@@ -1213,10 +1228,16 @@
|
||||
<key alias="pythonErrorText">Cкрипт Python не может быть сохранен в связи с ошибками</key>
|
||||
<key alias="pythonSavedHeader">Cкрипт Python сохранен</key>
|
||||
<key alias="pythonSavedText">Cкрипт Python сохранен без ошибок</key>
|
||||
<key alias="scriptErrorHeader">Скрипт не сохранен</key>
|
||||
<key alias="scriptErrorText">При сохранении файла скрипта произошла ошибка</key>
|
||||
<key alias="scriptSavedHeader">Скрипт сохранен</key>
|
||||
<key alias="scriptSavedText">Файл скрипта сохранен без ошибок</key>
|
||||
<key alias="templateErrorHeader">Шаблон не сохранен</key>
|
||||
<key alias="templateErrorText">Пожалуйста, проверьте, что нет двух шаблонов с одним и тем же алиасом (названием)</key>
|
||||
<key alias="templateSavedHeader">Шаблон сохранен</key>
|
||||
<key alias="templateSavedText">Шаблон сохранен без ошибок</key>
|
||||
<key alias="validationFailedHeader">Проверка значений</key>
|
||||
<key alias="validationFailedMessage">Ошибки, найденные при проверке значений, должны быть исправлены, чтобы было возможно сохранить документ</key>
|
||||
<key alias="xsltErrorHeader">XSLT-документ не сохранен</key>
|
||||
<key alias="xsltErrorText">XSLT-документ содержит одну или несколько ошибок</key>
|
||||
<key alias="xsltPermissionErrorText">XSLT-документ не может быть сохранен, проверьте установки файловых разрешений</key>
|
||||
@@ -1232,14 +1253,106 @@
|
||||
<key alias="styles">Стили</key>
|
||||
</area>
|
||||
<area alias="template">
|
||||
<key alias="edittemplate">Править шаблон</key>
|
||||
<key alias="edittemplate">Изменить шаблон</key>
|
||||
|
||||
<key alias="insertSections">Секции</key>
|
||||
<key alias="insertContentArea">Вставить контент-область</key>
|
||||
<key alias="insertContentAreaPlaceHolder">Вставить контейнер (placeholder)</key>
|
||||
<key alias="insertDictionaryItem">Вставить статью словаря</key>
|
||||
<key alias="insertMacro">Вставить макрос</key>
|
||||
<key alias="insertPageField">Вставить поле документа</key>
|
||||
|
||||
<key alias="insert">Вставить</key>
|
||||
<key alias="insertDesc">Выберите, что хотите вставить в шаблон</key>
|
||||
|
||||
<key alias="insertDictionaryItem">Статью словаря</key>
|
||||
<key alias="insertDictionaryItemDesc">Статья словаря - это контейнер для части текста, переводимой на разные языки, это позволяет упростить создание многоязычных сайтов.</key>
|
||||
|
||||
<key alias="insertMacro">Макрос</key>
|
||||
<key alias="insertMacroDesc">
|
||||
Макросы - это настраиваемые компоненты, которые хорошо подходят для
|
||||
реализации переиспользуемых блоков, (особенно, если необходимо менять их внешний вид и/или поведение при помощи параметров)
|
||||
таких как галереи, формы, списки и т.п.
|
||||
</key>
|
||||
|
||||
<key alias="insertPageField">Значение поля</key>
|
||||
<key alias="insertPageFieldDesc">Отображает значение указанного поля данных текущей страницы,
|
||||
с возможностью указать альтернативные поля и/или подстановку константы.
|
||||
</key>
|
||||
|
||||
<key alias="insertPartialView">Частичное представление</key>
|
||||
<key alias="insertPartialViewDesc">
|
||||
Частичное представление - это шаблон в отдельном файле, который может быть вызван для отображения внутри
|
||||
другого шаблона, хорошо подходит для реализации переиспользуемых фрагментов разметки или для разбиения сложных шаблонов на составные части.
|
||||
</key>
|
||||
|
||||
<key alias="mastertemplate">Мастер-шаблон</key>
|
||||
<key alias="quickGuide">Краткая справка по тэгам шаблонов Umbraco</key>
|
||||
<key alias="noMastertemplate">Без мастер-шаблона</key>
|
||||
<key alias="noMaster">Не выбран</key>
|
||||
|
||||
<key alias="renderBody">Вставить дочерний шаблон</key>
|
||||
<key alias="renderBodyDesc">
|
||||
<![CDATA[
|
||||
Отображает содержимое дочернего шаблона, при помощи вставки конструкции
|
||||
<code>@RenderBody()</code> в выбранном месте.
|
||||
]]>
|
||||
</key>
|
||||
|
||||
<key alias="defineSection">Определить именованную секцию</key>
|
||||
<key alias="defineSectionDesc">
|
||||
<![CDATA[
|
||||
Определяет специальную область шаблона как именованную секцию путем оборачивания ее в конструкцию
|
||||
<code>@section { ... }</code>. Такая секци может быть отображена в нужном месте родительского шаблона
|
||||
при помощи конструкции <code>@RenderSection</code>.
|
||||
]]>
|
||||
</key>
|
||||
|
||||
<key alias="renderSection">Вставить именованную секцию</key>
|
||||
<key alias="renderSectionDesc">
|
||||
<![CDATA[
|
||||
Отображает содержимое именованной области дочернего шаблона, при помощи вставки конструкции <code>@RenderSection(name)</code>.
|
||||
Таким образом из дочернего шаблона отображается содержимое внутри конструкции <code>@section [name]{ ... }</code>.
|
||||
]]>
|
||||
</key>
|
||||
|
||||
<key alias="sectionName">Название секции</key>
|
||||
<key alias="sectionMandatory">Секция обязательна</key>
|
||||
<key alias="sectionMandatoryDesc">
|
||||
Если секция помечена как обязательная, то дочерний шаблон должен обязательно содержать ее определение <code>@section</code>, в противном случае генерируется ошибка.
|
||||
</key>
|
||||
|
||||
<key alias="queryBuilder">Генератор запросов</key>
|
||||
<key alias="itemsReturned">элементов в результате, за</key>
|
||||
|
||||
<key alias="iWant">Мне нужны</key>
|
||||
<key alias="allContent">все документы</key>
|
||||
<key alias="contentOfType">документы типа "%0%"</key>
|
||||
<key alias="from">из</key>
|
||||
<key alias="websiteRoot">всего сайта</key>
|
||||
<key alias="where">где</key>
|
||||
<key alias="and">и</key>
|
||||
|
||||
<key alias="is">равна</key>
|
||||
<key alias="isNot">не равна</key>
|
||||
<key alias="before">до</key>
|
||||
<key alias="beforeIncDate">до (включая выбранную дату)</key>
|
||||
<key alias="after">после</key>
|
||||
<key alias="afterIncDate">после (включая выбранную дату)</key>
|
||||
<key alias="equals">равно</key>
|
||||
<key alias="doesNotEqual">не равно</key>
|
||||
<key alias="contains">содержит</key>
|
||||
<key alias="doesNotContain">не содержит</key>
|
||||
<key alias="greaterThan">больше, чем</key>
|
||||
<key alias="greaterThanEqual">больше или равно</key>
|
||||
<key alias="lessThan">меньше, чем</key>
|
||||
<key alias="lessThanEqual">меньше или равно</key>
|
||||
|
||||
<key alias="id">Id</key>
|
||||
<key alias="name">Название</key>
|
||||
<key alias="createdDate">Создан</key>
|
||||
<key alias="lastUpdatedDate">Обновлен</key>
|
||||
|
||||
<key alias="orderBy">сортировать</key>
|
||||
<key alias="ascending">по возрастанию</key>
|
||||
<key alias="descending">по убыванию</key>
|
||||
|
||||
<key alias="template">Шаблон</key>
|
||||
</area>
|
||||
<area alias="templateEditor">
|
||||
@@ -1343,6 +1456,7 @@
|
||||
<key alias="packager">Пакеты дополнений</key>
|
||||
<key alias="packages">Пакеты дополнений</key>
|
||||
<key alias="python">Скрипты Python</key>
|
||||
<key alias="relationTypes">Типы связей</key>
|
||||
<key alias="repositories">Установить из репозитория</key>
|
||||
<key alias="runway">Установить Runway</key>
|
||||
<key alias="runwayModules">Модули Runway </key>
|
||||
@@ -1361,6 +1475,7 @@
|
||||
<area alias="user">
|
||||
<key alias="administrators">Администратор</key>
|
||||
<key alias="categoryField">Поле категории</key>
|
||||
<key alias="change">Изменить</key>
|
||||
<key alias="changePassword">Изменить пароль</key>
|
||||
<key alias="changePasswordDescription">Вы можете сменить свой пароль для доступа к административной панели Umbraco, заполнив нижеследующие поля и нажав на кнопку 'Изменить пароль'</key>
|
||||
<key alias="confirmNewPassword">Подтверждение нового пароля</key>
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
<add path="GoogleSpellChecker.ashx" xdt:Transform="Remove" xdt:Locator="Match(path)" />
|
||||
</httpHandlers>
|
||||
</system.web>
|
||||
|
||||
|
||||
<system.web>
|
||||
<compilation xdt:Transform="InsertIfMissing" />
|
||||
<compilation>
|
||||
@@ -308,10 +308,10 @@
|
||||
<add name=" UmbracoModule" xdt:Locator="Match(name)" xdt:Transform="Remove" />
|
||||
<add name="UmbracoModule" type="Umbraco.Web.UmbracoModule,umbraco" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
</httpModules>
|
||||
|
||||
|
||||
</system.web>
|
||||
|
||||
|
||||
|
||||
<system.web.extensions xdt:Transform="Remove" />
|
||||
|
||||
<system.codedom xdt:Transform="Remove" />
|
||||
@@ -386,7 +386,7 @@
|
||||
xdt:Locator="Condition(_defaultNamespace:assemblyIdentity[@name='HtmlAgilityPack']])" />
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="HtmlAgilityPack" publicKeyToken="bd319b19eaf3b43a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="1.4.5.0-1.4.6.0" newVersion="1.4.6.0" />
|
||||
<bindingRedirect oldVersion="1.4.5.0-1.4.9.5" newVersion="1.4.9.5" />
|
||||
</dependentAssembly>
|
||||
|
||||
<dependentAssembly xdt:Transform="Remove"
|
||||
|
||||
@@ -176,7 +176,7 @@
|
||||
<remove assembly="System.Threading.Tasks.Parallel" />
|
||||
<remove assembly="System.Xml.ReaderWriter" />
|
||||
<remove assembly="System.Xml.XDocument" />
|
||||
<remove assembly="System.Xml.XmlSerializer" />
|
||||
<remove assembly="System.Xml.XmlSerializer" />
|
||||
<add assembly="System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<add assembly="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
|
||||
<add assembly="Umbraco.ModelsBuilder"/>
|
||||
@@ -229,7 +229,7 @@
|
||||
<add assembly="System.Threading.Tasks.Parallel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<add assembly="System.Xml.ReaderWriter, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<add assembly="System.Xml.XDocument, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<add assembly="System.Xml.XmlSerializer, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<add assembly="System.Xml.XmlSerializer, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
</assemblies>
|
||||
<buildProviders>
|
||||
<add extension=".cshtml" type="umbraco.MacroEngines.RazorBuildProvider, umbraco.MacroEngines" />
|
||||
@@ -383,7 +383,7 @@
|
||||
<!-- Ensure correct version of HtmlAgilityPack -->
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="HtmlAgilityPack" publicKeyToken="bd319b19eaf3b43a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.4.9.0" newVersion="1.4.9.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.4.9.5" newVersion="1.4.9.5" />
|
||||
</dependentAssembly>
|
||||
|
||||
<dependentAssembly>
|
||||
@@ -395,7 +395,7 @@
|
||||
<assemblyIdentity name="AutoMapper" publicKeyToken="be96cd2c38ef1005" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.3.1.0" newVersion="3.3.1.0" />
|
||||
</dependentAssembly>
|
||||
|
||||
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="9.0.0.0" />
|
||||
|
||||
@@ -103,13 +103,13 @@ namespace Umbraco.Web.Cache
|
||||
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.IdToKeyCacheKey);
|
||||
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.KeyToIdCacheKey);
|
||||
|
||||
var dataTypeCache = ApplicationContext.Current.ApplicationCache.IsolatedRuntimeCache.GetCache<IDataTypeDefinition>();
|
||||
payloads.ForEach(payload =>
|
||||
{
|
||||
//clears the prevalue cache
|
||||
var dataTypeCache = ApplicationContext.Current.ApplicationCache.IsolatedRuntimeCache.GetCache<IDataTypeDefinition>();
|
||||
if (dataTypeCache)
|
||||
dataTypeCache.Result.ClearCacheByKeySearch(string.Format("{0}{1}", CacheKeys.DataTypePreValuesCacheKey, payload.Id));
|
||||
|
||||
dataTypeCache.Result.ClearCacheByKeySearch(string.Format("{0}_{1}", CacheKeys.DataTypePreValuesCacheKey, payload.Id));
|
||||
|
||||
PublishedContentType.ClearDataType(payload.Id);
|
||||
});
|
||||
|
||||
|
||||
@@ -254,7 +254,7 @@ namespace Umbraco.Web.Editors
|
||||
},
|
||||
{
|
||||
"treeApplicationApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<ApplicationTreeController>(
|
||||
controller => controller.GetApplicationTrees(null, null, null))
|
||||
controller => controller.GetApplicationTrees(null, null, null, true))
|
||||
},
|
||||
{
|
||||
"contentTypeApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<ContentTypeController>(
|
||||
|
||||
@@ -10,6 +10,7 @@ using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Web.Mvc;
|
||||
using umbraco;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
@@ -29,7 +30,7 @@ namespace Umbraco.Web.Editors
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// Note that ALL logged in users have access to this method because editors will need to isnert macros into rte (content/media/members) and it's used for
|
||||
/// Note that ALL logged in users have access to this method because editors will need to isnert macros into rte (content/media/members) and it's used for
|
||||
/// inserting into templates/views/etc... it doesn't expose any sensitive data.
|
||||
/// </remarks>
|
||||
public IEnumerable<MacroParameter> GetMacroParameters(int macroId)
|
||||
@@ -50,9 +51,9 @@ namespace Umbraco.Web.Editors
|
||||
/// <param name="pageId"></param>
|
||||
/// <param name="macroParams">
|
||||
/// To send a dictionary as a GET parameter the query should be structured like:
|
||||
///
|
||||
///
|
||||
/// ?macroAlias=Test&pageId=3634¯oParams[0].key=myKey¯oParams[0].value=myVal¯oParams[1].key=anotherKey¯oParams[1].value=anotherVal
|
||||
///
|
||||
///
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
@@ -129,6 +130,26 @@ namespace Umbraco.Web.Editors
|
||||
"text/html");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
[HttpPost]
|
||||
public HttpResponseMessage CreatePartialViewMacroWithFile(CreatePartialViewMacroWithFileModel model)
|
||||
{
|
||||
var macro = new Macro
|
||||
{
|
||||
|
||||
Alias = model.Filename,
|
||||
Name = model.Filename, // will be "aliased"
|
||||
ScriptPath = "~/Views/MacroPartials/" + model.Parent + "/" + model.Filename + ".cshtml"
|
||||
};
|
||||
|
||||
Services.MacroService.Save(macro); // may throw
|
||||
return new HttpResponseMessage(HttpStatusCode.OK);
|
||||
}
|
||||
|
||||
public class CreatePartialViewMacroWithFileModel
|
||||
{
|
||||
public string Parent { get; set; }
|
||||
public string Filename { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,8 @@ namespace Umbraco.Web.HealthCheck.Checks.Security
|
||||
var url = HealthCheckContext.HttpContext.Request.Url;
|
||||
|
||||
// Access the site home page and check for the click-jack protection header or meta tag
|
||||
var useSsl = GlobalSettings.UseSSL || HealthCheckContext.HttpContext.Request.ServerVariables["SERVER_PORT"] == "443";
|
||||
var serverVariables = HealthCheckContext.HttpContext.Request.ServerVariables;
|
||||
var useSsl = GlobalSettings.UseSSL || serverVariables["SERVER_PORT"] == "443";
|
||||
var address = string.Format("http{0}://{1}:{2}", useSsl ? "s" : "", url.Host.ToLower(), url.Port);
|
||||
var request = WebRequest.Create(address);
|
||||
request.Method = "GET";
|
||||
|
||||
@@ -49,7 +49,8 @@ namespace Umbraco.Web.HealthCheck.Checks.Security
|
||||
var url = HealthCheckContext.HttpContext.Request.Url;
|
||||
|
||||
// Access the site home page and check for the headers
|
||||
var useSsl = GlobalSettings.UseSSL || HealthCheckContext.HttpContext.Request.ServerVariables["SERVER_PORT"] == "443";
|
||||
var serverVariables = HealthCheckContext.HttpContext.Request.ServerVariables;
|
||||
var useSsl = GlobalSettings.UseSSL || serverVariables["SERVER_PORT"] == "443";
|
||||
var address = string.Format("http{0}://{1}:{2}", useSsl ? "s" : "", url.Host.ToLower(), url.Port);
|
||||
var request = WebRequest.Create(address);
|
||||
request.Method = "HEAD";
|
||||
|
||||
@@ -48,12 +48,22 @@ namespace Umbraco.Web.HealthCheck
|
||||
return healthCheckGroups;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public object GetStatus(Guid id)
|
||||
{
|
||||
var check = _healthCheckResolver.HealthChecks.FirstOrDefault(x => x.Id == id);
|
||||
if (check == null) throw new InvalidOperationException("No health check found with ID " + id);
|
||||
|
||||
return check.GetStatus();
|
||||
try
|
||||
{
|
||||
//Core.Logging.LogHelper.Debug<HealthCheckController>("Running health check: " + check.Name);
|
||||
return check.GetStatus();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Core.Logging.LogHelper.Error<HealthCheckController>("Exception in health check: " + check.Name, e);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Umbraco.Web.HealthCheck
|
||||
/// </remarks>
|
||||
internal class HealthCheckResolver : LazyManyObjectsResolverBase<HealthCheckResolver, HealthCheck>, IHealthCheckResolver
|
||||
{
|
||||
public HealthCheckResolver(ILogger logger, Func<IEnumerable<Type>> lazyTypeList)
|
||||
public HealthCheckResolver(ILogger logger, Func<IEnumerable<Type>> lazyTypeList)
|
||||
: base(new HealthCheckServiceProvider(), logger, lazyTypeList, ObjectLifetimeScope.HttpRequest)
|
||||
{
|
||||
}
|
||||
@@ -51,7 +51,7 @@ namespace Umbraco.Web.HealthCheck
|
||||
new HealthCheckContext(new HttpContextWrapper(HttpContext.Current), UmbracoContext.Current)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//use normal ctor
|
||||
return Activator.CreateInstance(serviceType);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(display => display.IsContainer, expression => expression.MapFrom(content => content.ContentType.IsContainer))
|
||||
.ForMember(display => display.IsChildOfListView, expression => expression.Ignore())
|
||||
.ForMember(display => display.Trashed, expression => expression.MapFrom(content => content.Trashed))
|
||||
.ForMember(display => display.PublishDate, expression => expression.MapFrom(content => GetPublishedDate(content, applicationContext)))
|
||||
.ForMember(display => display.PublishDate, expression => expression.MapFrom(content => GetPublishedDate(content)))
|
||||
.ForMember(display => display.TemplateAlias, expression => expression.MapFrom(content => content.Template.Alias))
|
||||
.ForMember(display => display.HasPublishedVersion, expression => expression.MapFrom(content => content.HasPublishedVersion))
|
||||
.ForMember(display => display.Urls,
|
||||
@@ -78,6 +78,12 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(dto => dto.Alias, expression => expression.Ignore());
|
||||
}
|
||||
|
||||
private static DateTime? GetPublishedDate(IContent content)
|
||||
{
|
||||
var date = ((Content) content).PublishedDate;
|
||||
return date == default (DateTime) ? (DateTime?) null : date;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps the generic tab with custom properties for content
|
||||
/// </summary>
|
||||
@@ -89,31 +95,9 @@ namespace Umbraco.Web.Models.Mapping
|
||||
private static void AfterMap(IContent content, ContentItemDisplay display, IDataTypeService dataTypeService,
|
||||
ILocalizedTextService localizedText, IContentTypeService contentTypeService)
|
||||
{
|
||||
//map the IsChildOfListView (this is actually if it is a descendant of a list view!)
|
||||
//TODO: Fix this shorthand .Ancestors() lookup, at least have an overload to use the current
|
||||
if (content.HasIdentity)
|
||||
{
|
||||
var ancesctorListView = content.Ancestors().FirstOrDefault(x => x.ContentType.IsContainer);
|
||||
display.IsChildOfListView = ancesctorListView != null;
|
||||
}
|
||||
else
|
||||
{
|
||||
//it's new so it doesn't have a path, so we need to look this up by it's parent + ancestors
|
||||
var parent = content.Parent();
|
||||
if (parent == null)
|
||||
{
|
||||
display.IsChildOfListView = false;
|
||||
}
|
||||
else if (parent.ContentType.IsContainer)
|
||||
{
|
||||
display.IsChildOfListView = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var ancesctorListView = parent.Ancestors().FirstOrDefault(x => x.ContentType.IsContainer);
|
||||
display.IsChildOfListView = ancesctorListView != null;
|
||||
}
|
||||
}
|
||||
// map the IsChildOfListView (this is actually if it is a descendant of a list view!)
|
||||
var parent = content.Parent();
|
||||
display.IsChildOfListView = parent != null && (parent.ContentType.IsContainer || contentTypeService.HasContainerInPath(parent.Path));
|
||||
|
||||
//map the tree node url
|
||||
if (HttpContext.Current != null)
|
||||
@@ -229,26 +213,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the published date value for the IContent object
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="applicationContext"></param>
|
||||
/// <returns></returns>
|
||||
private static DateTime? GetPublishedDate(IContent content, ApplicationContext applicationContext)
|
||||
{
|
||||
if (content.Published)
|
||||
{
|
||||
return content.UpdateDate;
|
||||
}
|
||||
if (content.HasPublishedVersion)
|
||||
{
|
||||
var published = applicationContext.Services.ContentService.GetPublishedVersion(content.Id);
|
||||
return published.UpdateDate;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
//TODO: This is horribly inneficient
|
||||
/// Creates the list of action buttons allowed for this user - Publish, Send to publish, save, unpublish returned as the button's 'letter'
|
||||
/// </summary>
|
||||
private class ActionButtonsResolver : ValueResolver<IContent, IEnumerable<char>>
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(display => display.IsContainer, expression => expression.Ignore())
|
||||
.ForMember(display => display.HasPublishedVersion, expression => expression.Ignore())
|
||||
.ForMember(display => display.Tabs, expression => expression.ResolveUsing(new TabsAndPropertiesResolver(applicationContext.Services.TextService)))
|
||||
.AfterMap((media, display) => AfterMap(media, display, applicationContext.Services.DataTypeService, applicationContext.Services.TextService, applicationContext.ProfilingLogger.Logger));
|
||||
.AfterMap((media, display) => AfterMap(media, display, applicationContext.Services.DataTypeService, applicationContext.Services.TextService, applicationContext.Services.ContentTypeService, applicationContext.ProfilingLogger.Logger));
|
||||
|
||||
//FROM IMedia TO ContentItemBasic<ContentPropertyBasic, IMedia>
|
||||
config.CreateMap<IMedia, ContentItemBasic<ContentPropertyBasic, IMedia>>()
|
||||
@@ -67,34 +67,12 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(dto => dto.HasPublishedVersion, expression => expression.Ignore());
|
||||
}
|
||||
|
||||
private static void AfterMap(IMedia media, MediaItemDisplay display, IDataTypeService dataTypeService, ILocalizedTextService localizedText, ILogger logger)
|
||||
private static void AfterMap(IMedia media, MediaItemDisplay display, IDataTypeService dataTypeService, ILocalizedTextService localizedText, IContentTypeService contentTypeService, ILogger logger)
|
||||
{
|
||||
// Adapted from ContentModelMapper
|
||||
//map the IsChildOfListView (this is actually if it is a descendant of a list view!)
|
||||
//TODO: Fix this shorthand .Ancestors() lookup, at least have an overload to use the current
|
||||
if (media.HasIdentity)
|
||||
{
|
||||
var ancesctorListView = media.Ancestors().FirstOrDefault(x => x.ContentType.IsContainer);
|
||||
display.IsChildOfListView = ancesctorListView != null;
|
||||
}
|
||||
else
|
||||
{
|
||||
//it's new so it doesn't have a path, so we need to look this up by it's parent + ancestors
|
||||
var parent = media.Parent();
|
||||
if (parent == null)
|
||||
{
|
||||
display.IsChildOfListView = false;
|
||||
}
|
||||
else if (parent.ContentType.IsContainer)
|
||||
{
|
||||
display.IsChildOfListView = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var ancesctorListView = parent.Ancestors().FirstOrDefault(x => x.ContentType.IsContainer);
|
||||
display.IsChildOfListView = ancesctorListView != null;
|
||||
}
|
||||
}
|
||||
var parent = media.Parent();
|
||||
display.IsChildOfListView = parent != null && (parent.ContentType.IsContainer || contentTypeService.HasContainerInPath(parent.Path));
|
||||
|
||||
//map the tree node url
|
||||
if (HttpContext.Current != null)
|
||||
|
||||
@@ -175,6 +175,7 @@ namespace Umbraco.Web.Mvc
|
||||
public IModelBinder GetBinder(Type modelType)
|
||||
{
|
||||
// can bind to RenderModel (exact type match)
|
||||
// You might be tempted to change this to IRenderModel but do not change this: http://issues.umbraco.org/issue/U4-8216
|
||||
if (modelType == typeof(RenderModel)) return this;
|
||||
|
||||
// can bind to RenderModel<TContent> (exact generic type match)
|
||||
|
||||
@@ -30,16 +30,17 @@ namespace Umbraco.Web.Trees
|
||||
/// <param name="application">The application to load tree for</param>
|
||||
/// <param name="tree">An optional single tree alias, if specified will only load the single tree for the request app</param>
|
||||
/// <param name="queryStrings"></param>
|
||||
/// <param name="onlyInitialized">An optional bool (defaults to true), if set to false it will also load uninitialized trees</param>
|
||||
/// <returns></returns>
|
||||
[HttpQueryStringFilter("queryStrings")]
|
||||
public async Task<SectionRootNode> GetApplicationTrees(string application, string tree, FormDataCollection queryStrings)
|
||||
public async Task<SectionRootNode> GetApplicationTrees(string application, string tree, FormDataCollection queryStrings, bool onlyInitialized = true)
|
||||
{
|
||||
if (string.IsNullOrEmpty(application)) throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
|
||||
var rootId = Constants.System.Root.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
//find all tree definitions that have the current application alias
|
||||
var appTrees = ApplicationContext.Current.Services.ApplicationTreeService.GetApplicationTrees(application, true).ToArray();
|
||||
var appTrees = ApplicationContext.Current.Services.ApplicationTreeService.GetApplicationTrees(application, onlyInitialized).ToArray();
|
||||
|
||||
if (appTrees.Count() == 1 || string.IsNullOrEmpty(tree) == false )
|
||||
{
|
||||
|
||||
@@ -117,8 +117,8 @@
|
||||
<HintPath>..\packages\dotless.1.4.1.0\lib\dotless.Core.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Examine, Version=0.1.81.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.81\lib\net45\Examine.dll</HintPath>
|
||||
<Reference Include="Examine, Version=0.1.82.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.82\lib\net45\Examine.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="HtmlAgilityPack, Version=1.4.9.5, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
|
||||
|
||||
@@ -1389,10 +1389,15 @@ namespace Umbraco.Web
|
||||
return test ? new HtmlString(valueIfTrue) : new HtmlString(string.Empty);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Prevalues
|
||||
|
||||
/// <summary>
|
||||
/// Gets a specific PreValue by its Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the PreValue to retrieve the value from</param>
|
||||
/// <returns>PreValue as a string</returns>
|
||||
public string GetPreValueAsString(int id)
|
||||
{
|
||||
return DataTypeService.GetPreValueAsString(id);
|
||||
|
||||
@@ -579,6 +579,15 @@ namespace Umbraco.Web
|
||||
// is complete and cancel this current event so the rebuild process doesn't start right now.
|
||||
args.Cancel = true;
|
||||
IndexesToRebuild.Add((BaseIndexProvider)args.Indexer);
|
||||
|
||||
//check if the index is rebuilding due to an error and log it
|
||||
if (args.IsHealthy == false)
|
||||
{
|
||||
var baseIndex = args.Indexer as BaseIndexProvider;
|
||||
var name = baseIndex != null ? baseIndex.Name : "[UKNOWN]";
|
||||
|
||||
ProfilingLogger.Logger.Error<WebBootManager>(string.Format("The index {0} is rebuilding due to being unreadable/corrupt", name), args.UnhealthyException);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
|
||||
<package id="ClientDependency" version="1.9.2" targetFramework="net45" />
|
||||
<package id="dotless" version="1.4.1.0" targetFramework="net45" />
|
||||
<package id="Examine" version="0.1.81" targetFramework="net45" />
|
||||
<package id="Examine" version="0.1.82" targetFramework="net45" />
|
||||
<package id="HtmlAgilityPack" version="1.4.9.5" targetFramework="net45" />
|
||||
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
|
||||
<package id="Markdown" version="1.14.7" targetFramework="net45" />
|
||||
|
||||
@@ -36,6 +36,7 @@ namespace UmbracoExamine
|
||||
private readonly IUserService _userService;
|
||||
private readonly IContentTypeService _contentTypeService;
|
||||
private readonly EntityXmlSerializer _serializer = new EntityXmlSerializer();
|
||||
private const int PageSize = 2;
|
||||
|
||||
#region Constructors
|
||||
|
||||
@@ -408,8 +409,7 @@ namespace UmbracoExamine
|
||||
{
|
||||
if (SupportedTypes.Contains(type) == false)
|
||||
return;
|
||||
|
||||
const int pageSize = 10000;
|
||||
|
||||
var pageIndex = 0;
|
||||
|
||||
DataService.LogService.AddInfoLog(-1, string.Format("PerformIndexAll - Start data queries - {0}", type));
|
||||
@@ -445,6 +445,7 @@ namespace UmbracoExamine
|
||||
|
||||
//sorted by: umbracoNode.level, umbracoNode.parentID, umbracoNode.sortOrder
|
||||
var result = _contentService.GetPagedXmlEntries(path, pIndex, pSize, out totalContent).ToArray();
|
||||
var more = result.Length == pSize;
|
||||
|
||||
//then like we do in the ContentRepository.BuildXmlCache we need to track what Parents have been processed
|
||||
// already so that we can then exclude implicitly unpublished content items
|
||||
@@ -480,7 +481,7 @@ namespace UmbracoExamine
|
||||
filtered.Add(xml);
|
||||
}
|
||||
|
||||
return new Tuple<long, XElement[]>(totalContent, filtered.ToArray());
|
||||
return Tuple.Create(filtered.ToArray(), more);
|
||||
},
|
||||
i => _contentService.GetById(i));
|
||||
}
|
||||
@@ -498,13 +499,13 @@ namespace UmbracoExamine
|
||||
IContent[] descendants;
|
||||
if (SupportUnpublishedContent)
|
||||
{
|
||||
descendants = _contentService.GetPagedDescendants(contentParentId, pageIndex, pageSize, out total, "umbracoNode.id").ToArray();
|
||||
descendants = _contentService.GetPagedDescendants(contentParentId, pageIndex, PageSize, out total, "umbracoNode.id").ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
//get all paged records but order by level ascending, we need to do this because we need to track which nodes are not published so that we can determine
|
||||
// which descendent nodes are implicitly not published
|
||||
descendants = _contentService.GetPagedDescendants(contentParentId, pageIndex, pageSize, out total, "level", Direction.Ascending, true, (string)null).ToArray();
|
||||
descendants = _contentService.GetPagedDescendants(contentParentId, pageIndex, PageSize, out total, "level", Direction.Ascending, true, (string)null).ToArray();
|
||||
}
|
||||
|
||||
// need to store decendants count before filtering, in order for loop to work correctly
|
||||
@@ -528,7 +529,7 @@ namespace UmbracoExamine
|
||||
content, notPublished).WhereNotNull(), type);
|
||||
|
||||
pageIndex++;
|
||||
} while (currentPageSize == pageSize);
|
||||
} while (currentPageSize == PageSize);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -546,7 +547,8 @@ namespace UmbracoExamine
|
||||
{
|
||||
long totalMedia;
|
||||
var result = _mediaService.GetPagedXmlEntries(path, pIndex, pSize, out totalMedia).ToArray();
|
||||
return new Tuple<long, XElement[]>(totalMedia, result);
|
||||
var more = result.Length == pSize;
|
||||
return Tuple.Create(result, more);
|
||||
},
|
||||
i => _mediaService.GetById(i));
|
||||
|
||||
@@ -574,39 +576,37 @@ namespace UmbracoExamine
|
||||
string type,
|
||||
int parentId,
|
||||
Func<TContentType[]> getContentTypes,
|
||||
Func<string, int, int, Tuple<long, XElement[]>> getPagedXmlEntries,
|
||||
Func<string, int, int, Tuple<XElement[], bool>> getPagedXmlEntries,
|
||||
Func<int, IContentBase> getContent)
|
||||
where TContentType: IContentTypeComposition
|
||||
{
|
||||
const int pageSize = 10000;
|
||||
var pageIndex = 0;
|
||||
|
||||
XElement[] xElements;
|
||||
var pageIndex = 0;
|
||||
|
||||
var contentTypes = getContentTypes();
|
||||
var icons = contentTypes.ToDictionary(x => x.Id, y => y.Icon);
|
||||
var parent = parentId == -1 ? null : getContent(parentId);
|
||||
bool more;
|
||||
|
||||
do
|
||||
{
|
||||
long total;
|
||||
XElement[] xElements;
|
||||
|
||||
if (parentId == -1)
|
||||
{
|
||||
var pagedElements = getPagedXmlEntries("-1", pageIndex, pageSize);
|
||||
total = pagedElements.Item1;
|
||||
xElements = pagedElements.Item2;
|
||||
var pagedElements = getPagedXmlEntries("-1", pageIndex, PageSize);
|
||||
xElements = pagedElements.Item1;
|
||||
more = pagedElements.Item2;
|
||||
}
|
||||
else if (parent == null)
|
||||
{
|
||||
xElements = new XElement[0];
|
||||
more = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Get the parent
|
||||
var parent = getContent(parentId);
|
||||
if (parent == null)
|
||||
xElements = new XElement[0];
|
||||
else
|
||||
{
|
||||
var pagedElements = getPagedXmlEntries(parent.Path, pageIndex, pageSize);
|
||||
total = pagedElements.Item1;
|
||||
xElements = pagedElements.Item2;
|
||||
}
|
||||
var pagedElements = getPagedXmlEntries(parent.Path, pageIndex, PageSize);
|
||||
xElements = pagedElements.Item1;
|
||||
more = pagedElements.Item2;
|
||||
}
|
||||
|
||||
//if specific types are declared we need to post filter them
|
||||
@@ -627,7 +627,7 @@ namespace UmbracoExamine
|
||||
|
||||
AddNodesToIndex(xElements, type);
|
||||
pageIndex++;
|
||||
} while (xElements.Length == pageSize);
|
||||
} while (more);
|
||||
}
|
||||
|
||||
internal static IEnumerable<XElement> GetSerializedContent(
|
||||
|
||||
@@ -82,8 +82,8 @@
|
||||
<AssemblyOriginatorKeyFile>..\Solution Items\TheFARM-Public.snk</AssemblyOriginatorKeyFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Examine, Version=0.1.81.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.81\lib\net45\Examine.dll</HintPath>
|
||||
<Reference Include="Examine, Version=0.1.82.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.82\lib\net45\Examine.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
|
||||
|
||||
@@ -117,7 +117,7 @@ namespace UmbracoExamine
|
||||
if (indexerData.UserFields.Any(x => x.Name == "_searchEmail") == false)
|
||||
{
|
||||
var field = new IndexField { Name = "_searchEmail" };
|
||||
|
||||
|
||||
StaticField policy;
|
||||
if (IndexFieldPolicies.TryGetValue("_searchEmail", out policy))
|
||||
{
|
||||
@@ -173,7 +173,8 @@ namespace UmbracoExamine
|
||||
{
|
||||
long totalContent;
|
||||
var result = _memberService.GetPagedXmlEntries(pIndex, pSize, out totalContent).ToArray();
|
||||
return new Tuple<long, XElement[]>(totalContent, result);
|
||||
var more = result.Length == pSize;
|
||||
return Tuple.Create(result, more);
|
||||
},
|
||||
i => _memberService.GetById(i));
|
||||
}
|
||||
@@ -219,7 +220,7 @@ namespace UmbracoExamine
|
||||
{
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
DataService.LogService.AddInfoLog(-1, string.Format("PerformIndexAll - End data queries - {0}, took {1}ms", type, stopwatch.ElapsedMilliseconds));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Examine" version="0.1.81" targetFramework="net45" />
|
||||
<package id="Examine" version="0.1.82" targetFramework="net45" />
|
||||
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
|
||||
<package id="SharpZipLib" version="0.86.0" targetFramework="net45" />
|
||||
</packages>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Examine" version="0.1.81" targetFramework="net45" />
|
||||
<package id="Examine" version="0.1.82" targetFramework="net45" />
|
||||
<package id="HtmlAgilityPack" version="1.4.9.5" targetFramework="net45" />
|
||||
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
|
||||
<package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net45" />
|
||||
|
||||
@@ -45,8 +45,8 @@
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Examine, Version=0.1.81.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.81\lib\net45\Examine.dll</HintPath>
|
||||
<Reference Include="Examine, Version=0.1.82.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.82\lib\net45\Examine.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="HtmlAgilityPack, Version=1.4.9.5, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
|
||||
|
||||
@@ -43,23 +43,28 @@ namespace umbraco.cms.businesslogic.packager.standardPackageActions
|
||||
|
||||
if (xmlData.HasChildNodes)
|
||||
{
|
||||
string sectionAlias = xmlData.Attributes["dashboardAlias"].Value;
|
||||
string dbConfig = SystemFiles.DashboardConfig;
|
||||
string sectionAlias = xmlData.Attributes["dashboardAlias"].Value;
|
||||
string dbConfig = SystemFiles.DashboardConfig;
|
||||
|
||||
XmlNode section = xmlData.SelectSingleNode("./section");
|
||||
XmlDocument dashboardFile = XmlHelper.OpenAsXmlDocument(dbConfig);
|
||||
XmlNode section = xmlData.SelectSingleNode("./section");
|
||||
XmlDocument dashboardFile = XmlHelper.OpenAsXmlDocument(dbConfig);
|
||||
|
||||
XmlNode importedSection = dashboardFile.ImportNode(section, true);
|
||||
//don't continue if it already exists
|
||||
var found = dashboardFile.SelectNodes("//section[@alias='" + sectionAlias + "']");
|
||||
if (found == null || found.Count <= 0)
|
||||
{
|
||||
XmlNode importedSection = dashboardFile.ImportNode(section, true);
|
||||
|
||||
XmlAttribute alias = XmlHelper.AddAttribute(dashboardFile, "alias", sectionAlias);
|
||||
importedSection.Attributes.Append(alias);
|
||||
XmlAttribute alias = XmlHelper.AddAttribute(dashboardFile, "alias", sectionAlias);
|
||||
importedSection.Attributes.Append(alias);
|
||||
|
||||
dashboardFile.DocumentElement.AppendChild(importedSection);
|
||||
dashboardFile.DocumentElement.AppendChild(importedSection);
|
||||
|
||||
dashboardFile.Save(IOHelper.MapPath(dbConfig));
|
||||
dashboardFile.Save(IOHelper.MapPath(dbConfig));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user