Compare commits
82 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| add2f57397 | |||
| cd3c17d73f | |||
| fe6d783222 | |||
| fc8b0f1822 | |||
| 6102c970c8 | |||
| 29903058a9 | |||
| b3940dea1b | |||
| 3dac630d05 | |||
| 10108d75b8 | |||
| 24cb64579b | |||
| 86239cc777 | |||
| 685aea1728 | |||
| eb4e041682 | |||
| 477aa754b3 | |||
| 48bff0aa6c | |||
| 4ea9fec9e2 | |||
| f3a965841b | |||
| 08ddb5f4c4 | |||
| 4ec63ffd0d | |||
| 4cb3e82972 | |||
| 0a20741f39 | |||
| 4575748f16 | |||
| 028ee831b8 | |||
| 54981cd57c | |||
| 0aab8cacaa | |||
| 15b4d33e00 | |||
| 367ba5cddf | |||
| ff64efbcdf | |||
| 5bc0c499d8 | |||
| f667318b58 | |||
| 87c9d15ad5 | |||
| 127736d188 | |||
| 139ab8d4df | |||
| 4abb8035b8 | |||
| 0ca1807d64 | |||
| 5ae90d201c | |||
| 6c416009d7 | |||
| 50da9bcb50 | |||
| 9e6a2d8a7c | |||
| cfb84cae44 | |||
| 4239833713 | |||
| 4fa1a3948e | |||
| 1b78e854f0 | |||
| c62a2362d2 | |||
| eb1855fcb7 | |||
| d4863239cd | |||
| 4b7ddb9c15 | |||
| e5bb35b335 | |||
| 7eabd09b3a | |||
| 087f0c0ede | |||
| db9d6d9109 | |||
| 700e180522 | |||
| 8584997f5f | |||
| 4710b3b641 | |||
| 227e2489c1 | |||
| 91a5b19378 | |||
| 4c20441c4e | |||
| edfe1e6d54 | |||
| 7869f77704 | |||
| 34fd405bca | |||
| f03ee9f908 | |||
| b053638204 | |||
| d790194682 | |||
| 3fec2b9756 | |||
| bc7a31d791 | |||
| 05d84c6673 | |||
| f6645e3928 | |||
| 50b00b12b0 | |||
| 569371ffff | |||
| f7b72b225a | |||
| d1bed54cf1 | |||
| ba868887d4 | |||
| 3a7853dcbe | |||
| 60af7deacd | |||
| 49bc3151b0 | |||
| d6b7bae38a | |||
| 715cc22722 | |||
| 88b23e09b6 | |||
| 612484c0b6 | |||
| 0e4974babe | |||
| 5775984730 | |||
| cfa2a30006 |
@@ -30,9 +30,9 @@
|
||||
<dependency id="xmlrpcnet" version="[2.5.0, 3.0.0)" />
|
||||
<dependency id="ClientDependency" version="[1.8.4, 2.0.0)" />
|
||||
<dependency id="ClientDependency-Mvc5" version="[1.8.0, 2.0.0)" />
|
||||
<dependency id="AutoMapper" version="[3.3.1, 4.0.0)" />
|
||||
<dependency id="AutoMapper" version="[3.0.0, 3.1.0)" />
|
||||
<dependency id="Newtonsoft.Json" version="[6.0.8, 7.0.0)" />
|
||||
<dependency id="Examine" version="[0.1.66, 1.0.0)" />
|
||||
<dependency id="Examine" version="[0.1.68, 1.0.0)" />
|
||||
<dependency id="ImageProcessor" version="[1.9.5, 3.0.0)" />
|
||||
<dependency id="ImageProcessor.Web" version="[3.3.1, 5.0.0)" />
|
||||
<dependency id="semver" version="[1.1.2, 2.0.0)" />
|
||||
|
||||
@@ -51,6 +51,8 @@
|
||||
<system.web xdt:Transform="InsertIfMissing" />
|
||||
<system.web>
|
||||
<siteMap xdt:Transform="Remove" />
|
||||
<httpRuntime xdt:Transform="InsertIfMissing" />
|
||||
<httpRuntime targetFramework="4.5" 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"/>>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
|
||||
7.3.0
|
||||
beta3
|
||||
RC
|
||||
+1
-1
@@ -12,4 +12,4 @@ using System.Resources;
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.3.0")]
|
||||
[assembly: AssemblyInformationalVersion("7.3.0-beta3")]
|
||||
[assembly: AssemblyInformationalVersion("7.3.0-RC")]
|
||||
@@ -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 "beta3"; } }
|
||||
public static string CurrentComment { get { return "RC"; } }
|
||||
|
||||
// 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
|
||||
|
||||
@@ -380,14 +380,19 @@ namespace Umbraco.Core
|
||||
if (ApplicationContext.IsConfigured == false) return;
|
||||
if (ApplicationContext.DatabaseContext.IsDatabaseConfigured == false) return;
|
||||
|
||||
//try now
|
||||
if (ApplicationContext.DatabaseContext.CanConnect)
|
||||
return;
|
||||
|
||||
var currentTry = 0;
|
||||
while (currentTry < 5)
|
||||
{
|
||||
//first wait, then retry
|
||||
Thread.Sleep(1000);
|
||||
|
||||
if (ApplicationContext.DatabaseContext.CanConnect)
|
||||
break;
|
||||
|
||||
//wait and retry
|
||||
Thread.Sleep(1000);
|
||||
currentTry++;
|
||||
}
|
||||
|
||||
@@ -395,7 +400,6 @@ namespace Umbraco.Core
|
||||
{
|
||||
throw new UmbracoStartupFailedException("Umbraco cannot start. A connection string is configured but the Umbraco cannot connect to the database.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public static class DelegateExtensions
|
||||
{
|
||||
public static Attempt<T> RetryUntilSuccessOrTimeout<T>(this Func<Attempt<T>> task, TimeSpan timeout, TimeSpan pause)
|
||||
{
|
||||
if (pause.TotalMilliseconds < 0)
|
||||
{
|
||||
throw new ArgumentException("pause must be >= 0 milliseconds");
|
||||
}
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
do
|
||||
{
|
||||
var result = task();
|
||||
if (result) { return result; }
|
||||
Thread.Sleep((int)pause.TotalMilliseconds);
|
||||
}
|
||||
while (stopwatch.Elapsed < timeout);
|
||||
return Attempt<T>.Fail();
|
||||
}
|
||||
|
||||
public static Attempt<T> RetryUntilSuccessOrMaxAttempts<T>(this Func<int, Attempt<T>> task, int totalAttempts, TimeSpan pause)
|
||||
{
|
||||
if (pause.TotalMilliseconds < 0)
|
||||
{
|
||||
throw new ArgumentException("pause must be >= 0 milliseconds");
|
||||
}
|
||||
int attempts = 0;
|
||||
do
|
||||
{
|
||||
attempts++;
|
||||
var result = task(attempts);
|
||||
if (result) { return result; }
|
||||
Thread.Sleep((int)pause.TotalMilliseconds);
|
||||
}
|
||||
while (attempts < totalAttempts);
|
||||
return Attempt<T>.Fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,34 +8,6 @@ namespace Umbraco.Core.Events
|
||||
/// </summary>
|
||||
public static class EventExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Raises the event and checks if a cancelation has occurred, if so it checks if any messages have been
|
||||
/// added to the event messages collection and if not it adds a default cancelation message
|
||||
/// </summary>
|
||||
/// <typeparam name="TSender"></typeparam>
|
||||
/// <typeparam name="TArgs"></typeparam>
|
||||
/// <param name="eventHandler"></param>
|
||||
/// <param name="evtMsgs"></param>
|
||||
/// <param name="args"></param>
|
||||
/// <param name="sender"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsRaisedEventCancelled<TSender, TArgs>(
|
||||
this TypedEventHandler<TSender, TArgs> eventHandler,
|
||||
EventMessages evtMsgs,
|
||||
Func<EventMessages, TArgs> args,
|
||||
TSender sender)
|
||||
where TArgs : CancellableEventArgs
|
||||
{
|
||||
var evtArgs = args(evtMsgs);
|
||||
|
||||
if (eventHandler != null)
|
||||
{
|
||||
eventHandler(sender, evtArgs);
|
||||
}
|
||||
|
||||
return evtArgs.Cancel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the event and returns a boolean value indicating if the event was cancelled
|
||||
/// </summary>
|
||||
@@ -56,30 +28,7 @@ namespace Umbraco.Core.Events
|
||||
|
||||
return args.Cancel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the event with EventMessages
|
||||
/// </summary>
|
||||
/// <typeparam name="TSender"></typeparam>
|
||||
/// <typeparam name="TArgs"></typeparam>
|
||||
/// <param name="eventHandler"></param>
|
||||
/// <param name="evtMsgs"></param>
|
||||
/// <param name="args"></param>
|
||||
/// <param name="sender"></param>
|
||||
public static void RaiseEvent<TSender, TArgs>(
|
||||
this TypedEventHandler<TSender, TArgs> eventHandler,
|
||||
EventMessages evtMsgs,
|
||||
Func<EventMessages, TArgs> args,
|
||||
TSender sender)
|
||||
where TArgs : EventArgs
|
||||
{
|
||||
if (eventHandler != null)
|
||||
{
|
||||
var evtArgs = args(evtMsgs);
|
||||
eventHandler(sender, evtArgs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Raises the event
|
||||
/// </summary>
|
||||
|
||||
@@ -22,8 +22,8 @@ namespace Umbraco.Core.Logging
|
||||
private CancellationTokenSource _loggingCancelationTokenSource;
|
||||
private CancellationToken _loggingCancelationToken;
|
||||
private Task _loggingTask;
|
||||
private Double _shutdownFlushTimeout = 5;
|
||||
private TimeSpan _shutdownFlushTimespan = TimeSpan.FromSeconds(5);
|
||||
private Double _shutdownFlushTimeout = 1;
|
||||
private TimeSpan _shutdownFlushTimespan = TimeSpan.FromSeconds(1);
|
||||
private static readonly Type ThisType = typeof(ParallelForwardingAppender);
|
||||
private volatile bool _shutDownRequested;
|
||||
private int? _bufferSize = DefaultBufferSize;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
@@ -140,11 +141,22 @@ namespace Umbraco.Core.Manifest
|
||||
{
|
||||
var result = new List<PackageManifest>();
|
||||
foreach (var m in manifestFileContents)
|
||||
{
|
||||
if (m.IsNullOrWhiteSpace()) continue;
|
||||
{
|
||||
var manifestContent = m;
|
||||
|
||||
if (manifestContent.IsNullOrWhiteSpace()) continue;
|
||||
|
||||
// Strip byte object marker, JSON.NET does not like it
|
||||
var preamble = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
|
||||
|
||||
// Strangely StartsWith(preamble) would always return true
|
||||
if (manifestContent.Substring(0, 1) == preamble)
|
||||
manifestContent = manifestContent.Remove(0, preamble.Length);
|
||||
|
||||
if (manifestContent.IsNullOrWhiteSpace()) continue;
|
||||
|
||||
//remove any comments first
|
||||
var replaced = CommentsSurround.Replace(m, match => " ");
|
||||
var replaced = CommentsSurround.Replace(manifestContent, match => " ");
|
||||
replaced = CommentsLine.Replace(replaced, match => "");
|
||||
|
||||
JObject deserialized;
|
||||
@@ -154,7 +166,7 @@ namespace Umbraco.Core.Manifest
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error<ManifestParser>("An error occurred parsing manifest with contents: " + m, ex);
|
||||
LogHelper.Error<ManifestParser>("An error occurred parsing manifest with contents: " + manifestContent, ex);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -95,13 +95,7 @@ namespace Umbraco.Core.Models
|
||||
[DataMember]
|
||||
public virtual ITemplate Template
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_template == null)
|
||||
return _contentType.DefaultTemplate;
|
||||
|
||||
return _template;
|
||||
}
|
||||
get { return _template; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
|
||||
@@ -8,5 +8,10 @@ namespace Umbraco.Core.Models
|
||||
string DomainName { get; set; }
|
||||
int? RootContentId { get; set; }
|
||||
bool IsWildcard { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Readonly value of the language ISO code for the domain
|
||||
/// </summary>
|
||||
string LanguageIsoCode { get; }
|
||||
}
|
||||
}
|
||||
@@ -23,5 +23,11 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
|
||||
[Column("domainName")]
|
||||
public string DomainName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used for a result on the query to get the associated language for a domain if there is one
|
||||
/// </summary>
|
||||
[ResultColumn("languageISOCode")]
|
||||
public string IsoCode { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ namespace Umbraco.Core.Models
|
||||
public class Stylesheet : File
|
||||
{
|
||||
public Stylesheet(string path)
|
||||
: base(path)
|
||||
: base(path.EnsureEndsWith(".css"))
|
||||
{
|
||||
InitializeProperties();
|
||||
}
|
||||
|
||||
@@ -14,6 +14,12 @@ namespace Umbraco.Core.Models
|
||||
_domainName = domainName;
|
||||
}
|
||||
|
||||
public UmbracoDomain(string domainName, string languageIsoCode)
|
||||
: this(domainName)
|
||||
{
|
||||
LanguageIsoCode = languageIsoCode;
|
||||
}
|
||||
|
||||
private int? _contentId;
|
||||
private int? _languageId;
|
||||
private string _domainName;
|
||||
@@ -70,9 +76,9 @@ namespace Umbraco.Core.Models
|
||||
get { return string.IsNullOrWhiteSpace(DomainName) || DomainName.StartsWith("*"); }
|
||||
}
|
||||
|
||||
public string IsoCode
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
/// <summary>
|
||||
/// Readonly value of the language ISO code for the domain
|
||||
/// </summary>
|
||||
public string LanguageIsoCode { get; internal set; }
|
||||
}
|
||||
}
|
||||
@@ -43,12 +43,8 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
Path = dto.NodeDto.Path
|
||||
};
|
||||
|
||||
if (childDefinitions.Any(x => x.ParentId == dto.NodeId))
|
||||
{
|
||||
template.IsMasterTemplate = true;
|
||||
}
|
||||
template.IsMasterTemplate = childDefinitions.Any(x => x.ParentId == dto.NodeId);
|
||||
|
||||
//TODO: Change this to ParentId: http://issues.umbraco.org/issue/U4-5846
|
||||
if(dto.NodeDto.ParentId > 0)
|
||||
template.MasterTemplateId = new Lazy<int>(() => dto.NodeDto.ParentId);
|
||||
|
||||
|
||||
+18
-1
@@ -30,9 +30,26 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
|
||||
.NonClustered()
|
||||
.WithOptions()
|
||||
.Unique();
|
||||
|
||||
//now we need to fill in the data so that it is consistent, we can't have it generating random GUIDs for
|
||||
// the already existing data, see: http://issues.umbraco.org/issue/U4-6942
|
||||
|
||||
foreach (var data in Context.Database.Query<dynamic>(@"
|
||||
SELECT cmsPropertyType.id ptId, cmsPropertyType.Alias ptAlias, cmsContentType.alias ctAlias
|
||||
FROM cmsPropertyType
|
||||
INNER JOIN cmsContentType
|
||||
ON cmsPropertyType.contentTypeId = cmsContentType.nodeId"))
|
||||
{
|
||||
//create a guid from the concatenation of the property type alias + the doc type alias
|
||||
string concatAlias = data.ptAlias + data.ctAlias;
|
||||
var ptGuid = concatAlias.ToGuid();
|
||||
|
||||
//set the Unique Id to the one we've generated
|
||||
Update.Table("cmsPropertyType").Set(new {uniqueID = ptGuid}).Where(new {id = data.ptId });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override void Down()
|
||||
|
||||
@@ -340,6 +340,12 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
((Content)entity).AddingEntity();
|
||||
|
||||
//ensure the default template is assigned
|
||||
if (entity.Template == null)
|
||||
{
|
||||
entity.Template = entity.ContentType.DefaultTemplate;
|
||||
}
|
||||
|
||||
//Ensure unique name on the same level
|
||||
entity.Name = EnsureUniqueNodeName(entity.ParentId, entity.Name);
|
||||
|
||||
@@ -648,8 +654,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var translator = new SqlTranslator<IContent>(sqlClause, query);
|
||||
var sql = translator.Translate()
|
||||
.Where<DocumentDto>(x => x.Published)
|
||||
.OrderBy<NodeDto>(x => x.Level)
|
||||
.OrderBy<NodeDto>(x => x.SortOrder);
|
||||
.OrderBy<NodeDto>(x => x.Level, SqlSyntax)
|
||||
.OrderBy<NodeDto>(x => x.SortOrder, SqlSyntax);
|
||||
|
||||
//NOTE: This doesn't allow properties to be part of the query
|
||||
var dtos = Database.Fetch<DocumentDto, ContentVersionDto, ContentDto, NodeDto, DocumentPublishedReadOnlyDto>(sql);
|
||||
@@ -855,7 +861,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// <summary>
|
||||
/// Private method to create a content object from a DocumentDto, which is used by Get and GetByVersion.
|
||||
/// </summary>
|
||||
/// <param name="d"></param>
|
||||
/// <param name="dto"></param>
|
||||
/// <param name="contentType"></param>
|
||||
/// <param name="template"></param>
|
||||
/// <param name="propCollection"></param>
|
||||
@@ -873,6 +879,11 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
content.Template = template ?? _templateRepository.Get(dto.TemplateId.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
//ensure there isn't one set.
|
||||
content.Template = null;
|
||||
}
|
||||
|
||||
content.Properties = propCollection;
|
||||
|
||||
@@ -885,7 +896,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// <summary>
|
||||
/// Private method to create a content object from a DocumentDto, which is used by Get and GetByVersion.
|
||||
/// </summary>
|
||||
/// <param name="d"></param>
|
||||
/// <param name="dto"></param>
|
||||
/// <param name="versionId"></param>
|
||||
/// <param name="docSql"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
@@ -713,7 +713,7 @@ AND umbracoNode.id <> @id",
|
||||
var sql = @"SELECT cmsContentType.pk as ctPk, cmsContentType.alias as ctAlias, cmsContentType.allowAtRoot as ctAllowAtRoot, cmsContentType.description as ctDesc,
|
||||
cmsContentType.icon as ctIcon, cmsContentType.isContainer as ctIsContainer, cmsContentType.nodeId as ctId, cmsContentType.thumbnail as ctThumb,
|
||||
AllowedTypes.allowedId as ctaAllowedId, AllowedTypes.SortOrder as ctaSortOrder, AllowedTypes.alias as ctaAlias,
|
||||
ParentTypes.parentContentTypeId as chtParentId,
|
||||
ParentTypes.parentContentTypeId as chtParentId, ParentTypes.parentContentTypeKey as chtParentKey,
|
||||
umbracoNode.createDate as nCreateDate, umbracoNode." + sqlSyntax.GetQuotedColumnName("level") + @" as nLevel, umbracoNode.nodeObjectType as nObjectType, umbracoNode.nodeUser as nUser,
|
||||
umbracoNode.parentID as nParentId, umbracoNode." + sqlSyntax.GetQuotedColumnName("path") + @" as nPath, umbracoNode.sortOrder as nSortOrder, umbracoNode." + sqlSyntax.GetQuotedColumnName("text") + @" as nName, umbracoNode.trashed as nTrashed,
|
||||
umbracoNode.uniqueID as nUniqueId
|
||||
@@ -727,7 +727,12 @@ AND umbracoNode.id <> @id",
|
||||
ON cmsContentTypeAllowedContentType.AllowedId = cmsContentType.nodeId
|
||||
) AllowedTypes
|
||||
ON AllowedTypes.Id = cmsContentType.nodeId
|
||||
LEFT JOIN cmsContentType2ContentType as ParentTypes
|
||||
LEFT JOIN (
|
||||
SELECT cmsContentType2ContentType.parentContentTypeId, umbracoNode.uniqueID AS parentContentTypeKey, cmsContentType2ContentType.childContentTypeId
|
||||
FROM cmsContentType2ContentType
|
||||
INNER JOIN umbracoNode
|
||||
ON cmsContentType2ContentType.parentContentTypeId = umbracoNode." + sqlSyntax.GetQuotedColumnName("id") + @"
|
||||
) ParentTypes
|
||||
ON ParentTypes.childContentTypeId = cmsContentType.nodeId
|
||||
WHERE (umbracoNode.nodeObjectType = @nodeObjectType)";
|
||||
|
||||
@@ -842,7 +847,7 @@ AND umbracoNode.id <> @id",
|
||||
cmsContentType.pk as ctPk, cmsContentType.alias as ctAlias, cmsContentType.allowAtRoot as ctAllowAtRoot, cmsContentType.description as ctDesc,
|
||||
cmsContentType.icon as ctIcon, cmsContentType.isContainer as ctIsContainer, cmsContentType.nodeId as ctId, cmsContentType.thumbnail as ctThumb,
|
||||
AllowedTypes.allowedId as ctaAllowedId, AllowedTypes.SortOrder as ctaSortOrder, AllowedTypes.alias as ctaAlias,
|
||||
ParentTypes.parentContentTypeId as chtParentId,
|
||||
ParentTypes.parentContentTypeId as chtParentId,ParentTypes.parentContentTypeKey as chtParentKey,
|
||||
umbracoNode.createDate as nCreateDate, umbracoNode." + sqlSyntax.GetQuotedColumnName("level") + @" as nLevel, umbracoNode.nodeObjectType as nObjectType, umbracoNode.nodeUser as nUser,
|
||||
umbracoNode.parentID as nParentId, umbracoNode." + sqlSyntax.GetQuotedColumnName("path") + @" as nPath, umbracoNode.sortOrder as nSortOrder, umbracoNode." + sqlSyntax.GetQuotedColumnName("text") + @" as nName, umbracoNode.trashed as nTrashed,
|
||||
umbracoNode.uniqueID as nUniqueId,
|
||||
@@ -865,7 +870,12 @@ AND umbracoNode.id <> @id",
|
||||
ON cmsTemplate.nodeId = umbracoNode.id
|
||||
) as Template
|
||||
ON Template.nodeId = cmsDocumentType.templateNodeId
|
||||
LEFT JOIN cmsContentType2ContentType as ParentTypes
|
||||
LEFT JOIN (
|
||||
SELECT cmsContentType2ContentType.parentContentTypeId, umbracoNode.uniqueID AS parentContentTypeKey, cmsContentType2ContentType.childContentTypeId
|
||||
FROM cmsContentType2ContentType
|
||||
INNER JOIN umbracoNode
|
||||
ON cmsContentType2ContentType.parentContentTypeId = umbracoNode." + sqlSyntax.GetQuotedColumnName("id") + @"
|
||||
) ParentTypes
|
||||
ON ParentTypes.childContentTypeId = cmsContentType.nodeId
|
||||
WHERE (umbracoNode.nodeObjectType = @nodeObjectType)";
|
||||
|
||||
@@ -1043,7 +1053,14 @@ AND umbracoNode.id <> @id",
|
||||
? x.ctId == currentCtId
|
||||
: x.nUniqueId == currentCtId;
|
||||
})
|
||||
.Select(x => (TId?)x.chtParentId)
|
||||
.Select(x =>
|
||||
{
|
||||
//TODO: This is a bit hacky right now but don't have time to do a nice refactor to support both GUID and Int queries, so this is
|
||||
// how it is for now.
|
||||
return (typeof(TId) == typeof(int))
|
||||
? (TId?)x.chtParentId
|
||||
: (TId?)x.chtParentKey;
|
||||
})
|
||||
.Where(x => x.HasValue)
|
||||
.Distinct()
|
||||
.Select(x => x.Value).ToList());
|
||||
|
||||
@@ -14,6 +14,8 @@ using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
//TODO: We need to get a readonly ISO code for the domain assigned
|
||||
|
||||
internal class DomainRepository : PetaPocoRepositoryBase<int, IDomain>, IDomainRepository
|
||||
{
|
||||
private readonly RepositoryCacheOptions _cacheOptions;
|
||||
@@ -62,7 +64,18 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
protected override Sql GetBaseQuery(bool isCount)
|
||||
{
|
||||
var sql = new Sql();
|
||||
sql.Select(isCount ? "COUNT(*)" : "*").From<DomainDto>(SqlSyntax);
|
||||
if (isCount)
|
||||
{
|
||||
sql.Select("COUNT(*)").From<DomainDto>(SqlSyntax);
|
||||
}
|
||||
else
|
||||
{
|
||||
sql.Select("umbracoDomains.*, umbracoLanguage.languageISOCode")
|
||||
.From<DomainDto>(SqlSyntax)
|
||||
.LeftJoin<LanguageDto>(SqlSyntax)
|
||||
.On<DomainDto, LanguageDto>(SqlSyntax, dto => dto.DefaultLanguage, dto => dto.Id);
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
@@ -110,6 +123,12 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var id = Convert.ToInt32(Database.Insert(dto));
|
||||
entity.Id = id;
|
||||
|
||||
//if the language changed, we need to resolve the ISO code!
|
||||
if (entity.LanguageId.HasValue)
|
||||
{
|
||||
((UmbracoDomain)entity).LanguageIsoCode = Database.ExecuteScalar<string>("SELECT languageISOCode FROM umbracoLanguage WHERE id=@langId", new { langId = entity.LanguageId });
|
||||
}
|
||||
|
||||
entity.ResetDirtyProperties();
|
||||
}
|
||||
|
||||
@@ -139,6 +158,12 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
Database.Update(dto);
|
||||
|
||||
//if the language changed, we need to resolve the ISO code!
|
||||
if (entity.WasPropertyDirty("LanguageId"))
|
||||
{
|
||||
((UmbracoDomain)entity).LanguageIsoCode = Database.ExecuteScalar<string>("SELECT languageISOCode FROM umbracoLanguage WHERE id=@langId", new {langId = entity.LanguageId});
|
||||
}
|
||||
|
||||
entity.ResetDirtyProperties();
|
||||
}
|
||||
|
||||
@@ -176,7 +201,12 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
public IDomain BuildEntity(DomainDto dto)
|
||||
{
|
||||
var domain = new UmbracoDomain(dto.DomainName) { Id = dto.Id, LanguageId = dto.DefaultLanguage, RootContentId = dto.RootStructureId };
|
||||
var domain = new UmbracoDomain(dto.DomainName, dto.IsoCode)
|
||||
{
|
||||
Id = dto.Id,
|
||||
LanguageId = dto.DefaultLanguage,
|
||||
RootContentId = dto.RootStructureId
|
||||
};
|
||||
//on initial construction we don't want to have dirty properties tracked
|
||||
// http://issues.umbraco.org/issue/U4-1946
|
||||
domain.ResetDirtyProperties(false);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
@@ -10,12 +11,17 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
IEnumerable<ITemplate> GetAll(params string[] aliases);
|
||||
|
||||
IEnumerable<ITemplate> GetChildren(int masterTemplateId);
|
||||
IEnumerable<ITemplate> GetChildren(string alias);
|
||||
|
||||
IEnumerable<ITemplate> GetDescendants(int masterTemplateId);
|
||||
IEnumerable<ITemplate> GetDescendants(string alias);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a template as a template node which can be traversed (parent, children)
|
||||
/// </summary>
|
||||
/// <param name="alias"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Use GetDescendants instead")]
|
||||
TemplateNode GetTemplateNode(string alias);
|
||||
|
||||
/// <summary>
|
||||
@@ -24,6 +30,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// <param name="anyNode"></param>
|
||||
/// <param name="alias"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Use GetDescendants instead")]
|
||||
TemplateNode FindTemplateInTree(TemplateNode anyNode, string alias);
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -25,6 +25,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
public override Stylesheet Get(string id)
|
||||
{
|
||||
id = id.EnsureEndsWith(".css");
|
||||
|
||||
if (FileSystem.FileExists(id) == false)
|
||||
{
|
||||
return null;
|
||||
@@ -63,7 +65,10 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
public override IEnumerable<Stylesheet> GetAll(params string[] ids)
|
||||
{
|
||||
//ensure they are de-duplicated, easy win if people don't do this as this can cause many excess queries
|
||||
ids = ids.Distinct().ToArray();
|
||||
ids = ids
|
||||
.Select(x => x.EnsureEndsWith(".css"))
|
||||
.Distinct()
|
||||
.ToArray();
|
||||
|
||||
if (ids.Any())
|
||||
{
|
||||
|
||||
@@ -477,7 +477,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
tagSetSql,
|
||||
" inner join cmsTags as NewTags on (TagSet.Tag = NewTags.Tag and TagSet.",
|
||||
SqlSyntax.GetQuotedColumnName("group"),
|
||||
" = TagSet.",
|
||||
" = NewTags.",
|
||||
SqlSyntax.GetQuotedColumnName("group"),
|
||||
") ",
|
||||
") as NewTagsSet ",
|
||||
|
||||
@@ -67,7 +67,15 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
protected override ITemplate PerformGet(int id)
|
||||
{
|
||||
return GetAll(new[] { id }).FirstOrDefault();
|
||||
var sql = GetBaseQuery(false).Where<TemplateDto>(x => x.NodeId == id);
|
||||
var result = Database.Fetch<TemplateDto, NodeDto>(sql).FirstOrDefault();
|
||||
if (result == null) return null;
|
||||
|
||||
//look up the simple template definitions that have a master template assigned, this is used
|
||||
// later to populate the template item's properties
|
||||
var childIds = GetAxisDefinitions(result).ToArray();
|
||||
|
||||
return MapFromDto(result, childIds);
|
||||
}
|
||||
|
||||
protected override IEnumerable<ITemplate> PerformGetAll(params int[] ids)
|
||||
@@ -89,20 +97,15 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
//look up the simple template definitions that have a master template assigned, this is used
|
||||
// later to populate the template item's properties
|
||||
var childIdsSql = new Sql()
|
||||
.Select("nodeId,alias,parentID")
|
||||
.From<TemplateDto>()
|
||||
.InnerJoin<NodeDto>()
|
||||
.On<TemplateDto, NodeDto>(dto => dto.NodeId, dto => dto.NodeId)
|
||||
.Where<NodeDto>(t => t.ParentId > 0);
|
||||
var childIds = Database.Fetch<dynamic>(childIdsSql)
|
||||
.Select(x => new UmbracoEntity
|
||||
var childIds = (ids.Any()
|
||||
? GetAxisDefinitions(dtos.ToArray())
|
||||
: dtos.Select(x => new UmbracoEntity
|
||||
{
|
||||
Id = x.nodeId,
|
||||
ParentId = x.parentID,
|
||||
Name = x.alias
|
||||
});
|
||||
|
||||
Id = x.NodeId,
|
||||
ParentId = x.NodeDto.ParentId,
|
||||
Name = x.Alias
|
||||
})).ToArray();
|
||||
|
||||
return dtos.Select(d => MapFromDto(d, childIds));
|
||||
}
|
||||
|
||||
@@ -118,19 +121,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
//look up the simple template definitions that have a master template assigned, this is used
|
||||
// later to populate the template item's properties
|
||||
var childIdsSql = new Sql()
|
||||
.Select("nodeId,alias,parentID")
|
||||
.From<TemplateDto>()
|
||||
.InnerJoin<NodeDto>()
|
||||
.On<TemplateDto, NodeDto>(dto => dto.NodeId, dto => dto.NodeId)
|
||||
.Where<NodeDto>(t => t.ParentId > 0);
|
||||
var childIds = Database.Fetch<dynamic>(childIdsSql)
|
||||
.Select(x => new UmbracoEntity
|
||||
{
|
||||
Id = x.nodeId,
|
||||
ParentId = x.parentID,
|
||||
Name = x.alias
|
||||
});
|
||||
var childIds = GetAxisDefinitions(dtos.ToArray()).ToArray();
|
||||
|
||||
return dtos.Select(d => MapFromDto(d, childIds));
|
||||
}
|
||||
@@ -143,9 +134,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
var sql = new Sql();
|
||||
sql.Select(isCount ? "COUNT(*)" : "*")
|
||||
.From<TemplateDto>()
|
||||
.InnerJoin<NodeDto>()
|
||||
.On<TemplateDto, NodeDto>(left => left.NodeId, right => right.NodeId)
|
||||
.From<TemplateDto>(SqlSyntax)
|
||||
.InnerJoin<NodeDto>(SqlSyntax)
|
||||
.On<TemplateDto, NodeDto>(SqlSyntax, left => left.NodeId, right => right.NodeId)
|
||||
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId);
|
||||
return sql;
|
||||
}
|
||||
@@ -273,7 +264,11 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
Database.Update(dto.NodeDto);
|
||||
Database.Update(dto);
|
||||
|
||||
|
||||
//re-update if this is a master template, since it could have changed!
|
||||
var axisDefs = GetAxisDefinitions(dto);
|
||||
template.IsMasterTemplate = axisDefs.Any(x => x.ParentId == dto.NodeId);
|
||||
|
||||
//now do the file work
|
||||
|
||||
if (DetermineTemplateRenderingEngine(entity) == RenderingEngine.Mvc)
|
||||
@@ -304,34 +299,27 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
protected override void PersistDeletedItem(ITemplate entity)
|
||||
{
|
||||
var deletes = GetDeleteClauses().ToArray();
|
||||
|
||||
//TODO: This isn't the most ideal way to delete a template tree, because below it will actually end up
|
||||
// recursing back to this method for each descendant and re-looking up the template list causing an extrac
|
||||
// SQL call - not ideal but there shouldn't ever be a heaping list of descendant templates.
|
||||
//The easiest way to overcome this is to expose the underlying cache upwards so that the repository has access
|
||||
// to it, then in the PersistDeletedTemplate we wouldn't recurse the underlying function, we'd just call
|
||||
// PersistDeletedItem with a Template object and clear it's cache.
|
||||
var descendants = GetDescendants(entity.Id).ToList();
|
||||
|
||||
var sql = GetBaseQuery(false).Where<NodeDto>(dto => dto.ParentId > 0 || dto.NodeId == entity.Id);
|
||||
|
||||
var dtos = Database.Fetch<TemplateDto, NodeDto>(sql);
|
||||
|
||||
var self = dtos.Single(x => x.NodeId == entity.Id);
|
||||
var allChildren = dtos.Except(new[] { self });
|
||||
var hierarchy = GenerateTemplateHierarchy(self, allChildren);
|
||||
//remove ourselves
|
||||
hierarchy.Remove(self);
|
||||
//change the order so it goes bottom up!
|
||||
hierarchy.Reverse();
|
||||
//change the order so it goes bottom up! (deepest level first)
|
||||
descendants.Reverse();
|
||||
|
||||
//delete the hierarchy
|
||||
foreach (var descendant in hierarchy)
|
||||
foreach (var descendant in descendants)
|
||||
{
|
||||
PersistDeletedTemplate(descendant);
|
||||
foreach (var delete in deletes)
|
||||
{
|
||||
Database.Execute(delete, new { Id = GetEntityId(descendant) });
|
||||
}
|
||||
}
|
||||
|
||||
//now we can delete this one
|
||||
base.PersistDeletedItem(entity);
|
||||
foreach (var delete in deletes)
|
||||
{
|
||||
Database.Execute(delete, new { Id = GetEntityId(entity) });
|
||||
}
|
||||
|
||||
if (DetermineTemplateRenderingEngine(entity) == RenderingEngine.Mvc)
|
||||
{
|
||||
@@ -342,28 +330,57 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
var masterpageName = string.Concat(entity.Alias, ".master");
|
||||
_masterpagesFileSystem.DeleteFile(masterpageName);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private ITemplate MapFromDto(TemplateDto dto, IEnumerable<IUmbracoEntity> childDefinitions)
|
||||
private IEnumerable<IUmbracoEntity> GetAxisDefinitions(params TemplateDto[] templates)
|
||||
{
|
||||
//look up the simple template definitions that have a master template assigned, this is used
|
||||
// later to populate the template item's properties
|
||||
var childIdsSql = new Sql()
|
||||
.Select("nodeId,alias,parentID")
|
||||
.From<TemplateDto>(SqlSyntax)
|
||||
.InnerJoin<NodeDto>(SqlSyntax)
|
||||
.On<TemplateDto, NodeDto>(SqlSyntax, dto => dto.NodeId, dto => dto.NodeId)
|
||||
//lookup axis's
|
||||
.Where("umbracoNode." + SqlSyntax.GetQuotedColumnName("id") + " IN (@parentIds) OR umbracoNode.parentID IN (@childIds)",
|
||||
new {parentIds = templates.Select(x => x.NodeDto.ParentId), childIds = templates.Select(x => x.NodeId)});
|
||||
|
||||
var childIds = Database.Fetch<dynamic>(childIdsSql)
|
||||
.Select(x => new UmbracoEntity
|
||||
{
|
||||
Id = x.nodeId,
|
||||
ParentId = x.parentID,
|
||||
Name = x.alias
|
||||
});
|
||||
return childIds;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps from a dto to an ITemplate
|
||||
/// </summary>
|
||||
/// <param name="dto"></param>
|
||||
/// <param name="axisDefinitions">
|
||||
/// This is a collection of template definitions ... either all templates, or the collection of child templates and it's parent template
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
private ITemplate MapFromDto(TemplateDto dto, IUmbracoEntity[] axisDefinitions)
|
||||
{
|
||||
string csViewName = string.Concat(dto.Alias, ".cshtml");
|
||||
string vbViewName = string.Concat(dto.Alias, ".vbhtml");
|
||||
string masterpageName = string.Concat(dto.Alias, ".master");
|
||||
|
||||
var factory = new TemplateFactory();
|
||||
var template = factory.BuildEntity(dto, childDefinitions);
|
||||
var template = factory.BuildEntity(dto, axisDefinitions);
|
||||
|
||||
if (dto.NodeDto.ParentId > 0)
|
||||
{
|
||||
//TODO: Fix this n+1 query!
|
||||
var masterTemplate = Get(dto.NodeDto.ParentId);
|
||||
var masterTemplate = axisDefinitions.FirstOrDefault(x => x.Id == dto.NodeDto.ParentId);
|
||||
if (masterTemplate != null)
|
||||
{
|
||||
template.MasterTemplateAlias = masterTemplate.Alias;
|
||||
template.MasterTemplateAlias = masterTemplate.Name;
|
||||
template.MasterTemplateId = new Lazy<int>(() => dto.NodeDto.ParentId);
|
||||
}
|
||||
}
|
||||
@@ -390,36 +407,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
|
||||
private void PersistDeletedTemplate(TemplateDto dto)
|
||||
{
|
||||
//we need to get the real template for this item unfortunately to remove it
|
||||
var template = Get(dto.NodeId);
|
||||
if (template != null)
|
||||
{
|
||||
//NOTE: We must cast here so that it goes to the outter method to
|
||||
// ensure the cache is updated.
|
||||
PersistDeletedItem((IEntity)template);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of templates in order of descendants from the parent
|
||||
/// </summary>
|
||||
/// <param name="template"></param>
|
||||
/// <param name="allChildTemplates"></param>
|
||||
/// <returns></returns>
|
||||
private static List<TemplateDto> GenerateTemplateHierarchy(TemplateDto template, IEnumerable<TemplateDto> allChildTemplates)
|
||||
{
|
||||
var hierarchy = new List<TemplateDto> { template };
|
||||
foreach (var t in allChildTemplates.Where(x => x.NodeDto.ParentId == template.NodeId))
|
||||
{
|
||||
hierarchy.AddRange(GenerateTemplateHierarchy(t, allChildTemplates));
|
||||
}
|
||||
return hierarchy;
|
||||
}
|
||||
|
||||
|
||||
private void PopulateViewTemplate(ITemplate template, string fileName)
|
||||
{
|
||||
string content;
|
||||
@@ -460,49 +448,119 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
if (dto == null)
|
||||
return null;
|
||||
|
||||
return Get(dto.NodeId);
|
||||
return MapFromDto(dto, GetAxisDefinitions(dto).ToArray());
|
||||
}
|
||||
|
||||
public IEnumerable<ITemplate> GetAll(params string[] aliases)
|
||||
{
|
||||
var sql = GetBaseQuery(false);
|
||||
|
||||
if (aliases.Any())
|
||||
{
|
||||
foreach (var id in aliases)
|
||||
{
|
||||
yield return Get(id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var nodeDtos = Database.Fetch<NodeDto>("WHERE nodeObjectType = @NodeObjectType", new { NodeObjectType = NodeObjectTypeId });
|
||||
foreach (var nodeDto in nodeDtos)
|
||||
{
|
||||
yield return Get(nodeDto.NodeId);
|
||||
}
|
||||
sql.Where("cmsTemplate.alias IN (@aliases)", new {aliases = aliases});
|
||||
}
|
||||
|
||||
var dtos = Database.Fetch<TemplateDto, NodeDto>(sql).ToArray();
|
||||
if (dtos.Length == 0) return Enumerable.Empty<ITemplate>();
|
||||
|
||||
var axisDefos = GetAxisDefinitions(dtos).ToArray();
|
||||
return dtos.Select(x => MapFromDto(x, axisDefos));
|
||||
}
|
||||
|
||||
public IEnumerable<ITemplate> GetChildren(int masterTemplateId)
|
||||
{
|
||||
//TODO: Fix this N+1!
|
||||
|
||||
List<TemplateDto> found;
|
||||
if (masterTemplateId == -1)
|
||||
var sql = GetBaseQuery(false);
|
||||
if (masterTemplateId <= 0)
|
||||
{
|
||||
var sql = GetBaseQuery(false).Where<NodeDto>(x => x.ParentId <= 0);
|
||||
found = Database.Fetch<TemplateDto, NodeDto>(sql);
|
||||
sql.Where<NodeDto>(x => x.ParentId <= 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
var sql = GetBaseQuery(false).Where<NodeDto>(x => x.ParentId == masterTemplateId);
|
||||
found = Database.Fetch<TemplateDto, NodeDto>(sql);
|
||||
sql.Where<NodeDto>(x => x.ParentId == masterTemplateId);
|
||||
}
|
||||
|
||||
foreach (var templateDto in found)
|
||||
var dtos = Database.Fetch<TemplateDto, NodeDto>(sql).ToArray();
|
||||
if (dtos.Length == 0) return Enumerable.Empty<ITemplate>();
|
||||
|
||||
var axisDefos = GetAxisDefinitions(dtos).ToArray();
|
||||
return dtos.Select(x => MapFromDto(x, axisDefos));
|
||||
}
|
||||
|
||||
public IEnumerable<ITemplate> GetChildren(string alias)
|
||||
{
|
||||
var sql = GetBaseQuery(false);
|
||||
if (alias.IsNullOrWhiteSpace())
|
||||
{
|
||||
yield return Get(templateDto.NodeId);
|
||||
sql.Where<NodeDto>(x => x.ParentId <= 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
//unfortunately SQLCE doesn't support scalar subqueries in the where clause, otherwise we could have done this
|
||||
// in a single query, now we have to lookup the path to acheive the same thing
|
||||
var parent = Database.ExecuteScalar<int?>(new Sql().Select("nodeId").From<TemplateDto>(SqlSyntax).Where<TemplateDto>(dto => dto.Alias == alias));
|
||||
if (parent.HasValue == false) return Enumerable.Empty<ITemplate>();
|
||||
|
||||
sql.Where<NodeDto>(x => x.ParentId == parent.Value);
|
||||
}
|
||||
|
||||
var dtos = Database.Fetch<TemplateDto, NodeDto>(sql).ToArray();
|
||||
if (dtos.Length == 0) return Enumerable.Empty<ITemplate>();
|
||||
|
||||
var axisDefos = GetAxisDefinitions(dtos).ToArray();
|
||||
return dtos.Select(x => MapFromDto(x, axisDefos));
|
||||
}
|
||||
|
||||
public IEnumerable<ITemplate> GetDescendants(int masterTemplateId)
|
||||
{
|
||||
var sql = GetBaseQuery(false);
|
||||
if (masterTemplateId > 0)
|
||||
{
|
||||
//unfortunately SQLCE doesn't support scalar subqueries in the where clause, otherwise we could have done this
|
||||
// in a single query, now we have to lookup the path to acheive the same thing
|
||||
var path = Database.ExecuteScalar<string>(
|
||||
new Sql().Select(SqlSyntax.GetQuotedColumnName("path"))
|
||||
.From<TemplateDto>(SqlSyntax)
|
||||
.InnerJoin<NodeDto>(SqlSyntax)
|
||||
.On<TemplateDto, NodeDto>(SqlSyntax, dto => dto.NodeId, dto => dto.NodeId)
|
||||
.Where<NodeDto>(dto => dto.NodeId == masterTemplateId));
|
||||
|
||||
if (path.IsNullOrWhiteSpace()) return Enumerable.Empty<ITemplate>();
|
||||
|
||||
sql.Where(@"(umbracoNode." + SqlSyntax.GetQuotedColumnName("path") + @" LIKE @query)", new { query = path + ",%" });
|
||||
}
|
||||
|
||||
sql.OrderBy("umbracoNode." + SqlSyntax.GetQuotedColumnName("level"));
|
||||
|
||||
var dtos = Database.Fetch<TemplateDto, NodeDto>(sql).ToArray();
|
||||
if (dtos.Length == 0) return Enumerable.Empty<ITemplate>();
|
||||
|
||||
var axisDefos = GetAxisDefinitions(dtos).ToArray();
|
||||
return dtos.Select(x => MapFromDto(x, axisDefos));
|
||||
|
||||
}
|
||||
|
||||
public IEnumerable<ITemplate> GetDescendants(string alias)
|
||||
{
|
||||
var sql = GetBaseQuery(false);
|
||||
if (alias.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
//unfortunately SQLCE doesn't support scalar subqueries in the where clause, otherwise we could have done this
|
||||
// in a single query, now we have to lookup the path to acheive the same thing
|
||||
var path = Database.ExecuteScalar<string>(
|
||||
"SELECT umbracoNode.path FROM cmsTemplate INNER JOIN umbracoNode ON cmsTemplate.nodeId = umbracoNode.id WHERE cmsTemplate.alias = @alias", new { alias = alias });
|
||||
|
||||
if (path.IsNullOrWhiteSpace()) return Enumerable.Empty<ITemplate>();
|
||||
|
||||
sql.Where(@"(umbracoNode." + SqlSyntax.GetQuotedColumnName("path") + @" LIKE @query)", new {query = path + ",%" });
|
||||
}
|
||||
|
||||
sql.OrderBy("umbracoNode." + SqlSyntax.GetQuotedColumnName("level"));
|
||||
|
||||
var dtos = Database.Fetch<TemplateDto, NodeDto>(sql).ToArray();
|
||||
if (dtos.Length == 0) return Enumerable.Empty<ITemplate>();
|
||||
|
||||
var axisDefos = GetAxisDefinitions(dtos).ToArray();
|
||||
return dtos.Select(x => MapFromDto(x, axisDefos));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -510,13 +568,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// </summary>
|
||||
/// <param name="alias"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Use GetDescendants instead")]
|
||||
public TemplateNode GetTemplateNode(string alias)
|
||||
{
|
||||
//in order to do this we need to get all of the templates and then organize,
|
||||
// TODO: unfortunately our db structure does not use the path correctly for templates so we cannot just look
|
||||
// up a template tree easily.
|
||||
//TODO: We do use the 'path' now, so this might be able to be fixed up
|
||||
|
||||
{
|
||||
//first get all template objects
|
||||
var allTemplates = GetAll().ToArray();
|
||||
|
||||
@@ -525,23 +579,17 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
//then we need to get all template Dto's because those contain the master property
|
||||
var sql = GetBaseQuery(false);
|
||||
var allDtos = Database.Fetch<TemplateDto, NodeDto>(sql).ToArray();
|
||||
var selfDto = allDtos.Single(x => x.NodeId == selfTemplate.Id);
|
||||
|
||||
//need to get the top-most node of the current tree
|
||||
var top = selfDto;
|
||||
while (top.NodeDto.ParentId > 0)
|
||||
|
||||
var top = selfTemplate;
|
||||
while (top.MasterTemplateAlias.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
top = allDtos.Single(x => x.NodeId == top.NodeDto.ParentId);
|
||||
top = allTemplates.Single(x => x.Alias == top.MasterTemplateAlias);
|
||||
}
|
||||
|
||||
var topNode = new TemplateNode(allTemplates.Single(x => x.Id == top.NodeId));
|
||||
var childIds = allDtos.Where(x => x.NodeDto.ParentId == top.NodeId).Select(x => x.NodeId);
|
||||
var topNode = new TemplateNode(allTemplates.Single(x => x.Id == top.Id));
|
||||
var childTemplates = allTemplates.Where(x => x.MasterTemplateAlias == top.Alias);
|
||||
//This now creates the hierarchy recursively
|
||||
topNode.Children = CreateChildren(topNode, childIds, allTemplates, allDtos);
|
||||
topNode.Children = CreateChildren(topNode, childTemplates, allTemplates);
|
||||
|
||||
//now we'll return the TemplateNode requested
|
||||
return FindTemplateInTree(topNode, alias);
|
||||
@@ -568,6 +616,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// <param name="anyNode"></param>
|
||||
/// <param name="alias"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Use GetDescendants instead")]
|
||||
public TemplateNode FindTemplateInTree(TemplateNode anyNode, string alias)
|
||||
{
|
||||
//first get the root
|
||||
@@ -658,12 +707,12 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return validFile && validExtension;
|
||||
}
|
||||
|
||||
private static IEnumerable<TemplateNode> CreateChildren(TemplateNode parent, IEnumerable<int> childIds, ITemplate[] allTemplates, TemplateDto[] allDtos)
|
||||
private static IEnumerable<TemplateNode> CreateChildren(TemplateNode parent, IEnumerable<ITemplate> childTemplates, ITemplate[] allTemplates)
|
||||
{
|
||||
var children = new List<TemplateNode>();
|
||||
foreach (var i in childIds)
|
||||
foreach (var childTemplate in childTemplates)
|
||||
{
|
||||
var template = allTemplates.Single(x => x.Id == i);
|
||||
var template = allTemplates.Single(x => x.Id == childTemplate.Id);
|
||||
var child = new TemplateNode(template)
|
||||
{
|
||||
Parent = parent
|
||||
@@ -673,10 +722,11 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
children.Add(child);
|
||||
|
||||
//get this node's children
|
||||
var kids = allDtos.Where(x => x.NodeDto.ParentId == i).Select(x => x.NodeId).ToArray();
|
||||
var local = childTemplate;
|
||||
var kids = allTemplates.Where(x => x.MasterTemplateAlias == local.Alias);
|
||||
|
||||
//recurse
|
||||
child.Children = CreateChildren(child, kids, allTemplates, allDtos);
|
||||
child.Children = CreateChildren(child, kids, allTemplates);
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
@@ -41,14 +41,14 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
.From<ContentVersionDto>()
|
||||
.InnerJoin<ContentDto>()
|
||||
.On<ContentVersionDto, ContentDto>(left => left.NodeId, right => right.NodeId)
|
||||
.InnerJoin<NodeDto>()
|
||||
.On<ContentDto, NodeDto>(left => left.NodeId, right => right.NodeId)
|
||||
.From<ContentVersionDto>(SqlSyntax)
|
||||
.InnerJoin<ContentDto>(SqlSyntax)
|
||||
.On<ContentVersionDto, ContentDto>(SqlSyntax, left => left.NodeId, right => right.NodeId)
|
||||
.InnerJoin<NodeDto>(SqlSyntax)
|
||||
.On<ContentDto, NodeDto>(SqlSyntax, left => left.NodeId, right => right.NodeId)
|
||||
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId)
|
||||
.Where<NodeDto>(x => x.NodeId == id)
|
||||
.OrderByDescending<ContentVersionDto>(x => x.VersionDate);
|
||||
.OrderByDescending<ContentVersionDto>(x => x.VersionDate, SqlSyntax);
|
||||
|
||||
var dtos = Database.Fetch<ContentVersionDto, ContentDto, NodeDto>(sql);
|
||||
foreach (var dto in dtos)
|
||||
@@ -513,6 +513,8 @@ WHERE EXISTS(
|
||||
// of ContentItemBasic instances) to the database field names.
|
||||
switch (orderBy.ToUpperInvariant())
|
||||
{
|
||||
case "UPDATEDATE":
|
||||
return "cmsContentVersion.VersionDate";
|
||||
case "NAME":
|
||||
return "umbracoNode.text";
|
||||
case "OWNER":
|
||||
|
||||
@@ -38,9 +38,9 @@ using System.Security.Permissions;
|
||||
[assembly: InternalsVisibleTo("UmbracoExamine")]
|
||||
|
||||
[assembly: InternalsVisibleTo("Concorde.Sync")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.Belle")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.VisualStudio")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.Courier.Core")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.Courier.Persistence")]
|
||||
[assembly: InternalsVisibleTo("umbraco.providers")]
|
||||
|
||||
//allow this to be mocked in our unit tests
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
@@ -9,16 +10,16 @@ namespace Umbraco.Core.Publishing
|
||||
/// </summary>
|
||||
public class PublishStatus : OperationStatus<IContent, PublishStatusType>
|
||||
{
|
||||
public PublishStatus(IContent content, PublishStatusType statusType)
|
||||
: base(content, statusType)
|
||||
public PublishStatus(IContent content, PublishStatusType statusType, EventMessages eventMessages)
|
||||
: base(content, statusType, eventMessages)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a successful publish status
|
||||
/// </summary>
|
||||
public PublishStatus(IContent content)
|
||||
: this(content, PublishStatusType.Success)
|
||||
public PublishStatus(IContent content, EventMessages eventMessages)
|
||||
: this(content, PublishStatusType.Success, eventMessages)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -33,14 +33,14 @@ namespace Umbraco.Core.Publishing
|
||||
/// <param name="userId">Id of the User issueing the publish operation</param>
|
||||
internal Attempt<PublishStatus> PublishInternal(IContent content, int userId)
|
||||
{
|
||||
var evtMsgs = _eventMessagesFactory.Get();
|
||||
|
||||
if (Publishing.IsRaisedEventCancelled(
|
||||
_eventMessagesFactory.Get(),
|
||||
messages => new PublishEventArgs<IContent>(content), this))
|
||||
new PublishEventArgs<IContent>(content, evtMsgs), this))
|
||||
{
|
||||
_logger.Info<PublishingStrategy>(
|
||||
string.Format("Content '{0}' with Id '{1}' will not be published, the event was cancelled.", content.Name, content.Id));
|
||||
return Attempt<PublishStatus>.Fail(new PublishStatus(content, PublishStatusType.FailedCancelledByEvent));
|
||||
return Attempt<PublishStatus>.Fail(new PublishStatus(content, PublishStatusType.FailedCancelledByEvent, evtMsgs));
|
||||
}
|
||||
|
||||
//Check if the Content is Expired to verify that it can in fact be published
|
||||
@@ -49,7 +49,7 @@ namespace Umbraco.Core.Publishing
|
||||
_logger.Info<PublishingStrategy>(
|
||||
string.Format("Content '{0}' with Id '{1}' has expired and could not be published.",
|
||||
content.Name, content.Id));
|
||||
return Attempt<PublishStatus>.Fail(new PublishStatus(content, PublishStatusType.FailedHasExpired));
|
||||
return Attempt<PublishStatus>.Fail(new PublishStatus(content, PublishStatusType.FailedHasExpired, evtMsgs));
|
||||
}
|
||||
|
||||
//Check if the Content is Awaiting Release to verify that it can in fact be published
|
||||
@@ -58,7 +58,7 @@ namespace Umbraco.Core.Publishing
|
||||
_logger.Info<PublishingStrategy>(
|
||||
string.Format("Content '{0}' with Id '{1}' is awaiting release and could not be published.",
|
||||
content.Name, content.Id));
|
||||
return Attempt<PublishStatus>.Fail(new PublishStatus(content, PublishStatusType.FailedAwaitingRelease));
|
||||
return Attempt<PublishStatus>.Fail(new PublishStatus(content, PublishStatusType.FailedAwaitingRelease, evtMsgs));
|
||||
}
|
||||
|
||||
//Check if the Content is Trashed to verify that it can in fact be published
|
||||
@@ -67,7 +67,7 @@ namespace Umbraco.Core.Publishing
|
||||
_logger.Info<PublishingStrategy>(
|
||||
string.Format("Content '{0}' with Id '{1}' is trashed and could not be published.",
|
||||
content.Name, content.Id));
|
||||
return Attempt<PublishStatus>.Fail(new PublishStatus(content, PublishStatusType.FailedIsTrashed));
|
||||
return Attempt<PublishStatus>.Fail(new PublishStatus(content, PublishStatusType.FailedIsTrashed, evtMsgs));
|
||||
}
|
||||
|
||||
content.ChangePublishedState(PublishedState.Published);
|
||||
@@ -76,7 +76,7 @@ namespace Umbraco.Core.Publishing
|
||||
string.Format("Content '{0}' with Id '{1}' has been published.",
|
||||
content.Name, content.Id));
|
||||
|
||||
return Attempt.Succeed(new PublishStatus(content));
|
||||
return Attempt.Succeed(new PublishStatus(content, evtMsgs));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -136,10 +136,12 @@ namespace Umbraco.Core.Publishing
|
||||
// Because we're grouping I think this will execute all the queries anyways so need to fetch it all first.
|
||||
var fetchedContent = content.ToArray();
|
||||
|
||||
var evtMsgs = _eventMessagesFactory.Get();
|
||||
|
||||
//We're going to populate the statuses with all content that is already published because below we are only going to iterate over
|
||||
// content that is not published. We'll set the status to "AlreadyPublished"
|
||||
statuses.AddRange(fetchedContent.Where(x => x.Published)
|
||||
.Select(x => Attempt.Succeed(new PublishStatus(x, PublishStatusType.SuccessAlreadyPublished))));
|
||||
.Select(x => Attempt.Succeed(new PublishStatus(x, PublishStatusType.SuccessAlreadyPublished, evtMsgs))));
|
||||
|
||||
int? firstLevel = null;
|
||||
|
||||
@@ -179,13 +181,12 @@ namespace Umbraco.Core.Publishing
|
||||
|
||||
//Fire Publishing event
|
||||
if (Publishing.IsRaisedEventCancelled(
|
||||
_eventMessagesFactory.Get(),
|
||||
messages => new PublishEventArgs<IContent>(item, messages), this))
|
||||
new PublishEventArgs<IContent>(item, evtMsgs), this))
|
||||
{
|
||||
//the publishing has been cancelled.
|
||||
_logger.Info<PublishingStrategy>(
|
||||
string.Format("Content '{0}' with Id '{1}' will not be published, the event was cancelled.", item.Name, item.Id));
|
||||
statuses.Add(Attempt.Fail(new PublishStatus(item, PublishStatusType.FailedCancelledByEvent)));
|
||||
statuses.Add(Attempt.Fail(new PublishStatus(item, PublishStatusType.FailedCancelledByEvent, evtMsgs)));
|
||||
|
||||
//Does this document apply to our rule to cancel it's children being published?
|
||||
CheckCancellingOfChildPublishing(item, parentsIdsCancelled, includeUnpublishedDocuments);
|
||||
@@ -194,12 +195,12 @@ namespace Umbraco.Core.Publishing
|
||||
}
|
||||
|
||||
//Check if the content is valid if the flag is set to check
|
||||
if (!item.IsValid())
|
||||
if (item.IsValid() == false)
|
||||
{
|
||||
_logger.Info<PublishingStrategy>(
|
||||
string.Format("Content '{0}' with Id '{1}' will not be published because some of it's content is not passing validation rules.",
|
||||
item.Name, item.Id));
|
||||
statuses.Add(Attempt.Fail(new PublishStatus(item, PublishStatusType.FailedContentInvalid)));
|
||||
statuses.Add(Attempt.Fail(new PublishStatus(item, PublishStatusType.FailedContentInvalid, evtMsgs)));
|
||||
|
||||
//Does this document apply to our rule to cancel it's children being published?
|
||||
CheckCancellingOfChildPublishing(item, parentsIdsCancelled, includeUnpublishedDocuments);
|
||||
@@ -213,7 +214,7 @@ namespace Umbraco.Core.Publishing
|
||||
_logger.Info<PublishingStrategy>(
|
||||
string.Format("Content '{0}' with Id '{1}' has expired and could not be published.",
|
||||
item.Name, item.Id));
|
||||
statuses.Add(Attempt.Fail(new PublishStatus(item, PublishStatusType.FailedHasExpired)));
|
||||
statuses.Add(Attempt.Fail(new PublishStatus(item, PublishStatusType.FailedHasExpired, evtMsgs)));
|
||||
|
||||
//Does this document apply to our rule to cancel it's children being published?
|
||||
CheckCancellingOfChildPublishing(item, parentsIdsCancelled, includeUnpublishedDocuments);
|
||||
@@ -227,7 +228,7 @@ namespace Umbraco.Core.Publishing
|
||||
_logger.Info<PublishingStrategy>(
|
||||
string.Format("Content '{0}' with Id '{1}' is awaiting release and could not be published.",
|
||||
item.Name, item.Id));
|
||||
statuses.Add(Attempt.Fail(new PublishStatus(item, PublishStatusType.FailedAwaitingRelease)));
|
||||
statuses.Add(Attempt.Fail(new PublishStatus(item, PublishStatusType.FailedAwaitingRelease, evtMsgs)));
|
||||
|
||||
//Does this document apply to our rule to cancel it's children being published?
|
||||
CheckCancellingOfChildPublishing(item, parentsIdsCancelled, includeUnpublishedDocuments);
|
||||
@@ -241,7 +242,7 @@ namespace Umbraco.Core.Publishing
|
||||
_logger.Info<PublishingStrategy>(
|
||||
string.Format("Content '{0}' with Id '{1}' is trashed and could not be published.",
|
||||
item.Name, item.Id));
|
||||
statuses.Add(Attempt.Fail(new PublishStatus(item, PublishStatusType.FailedIsTrashed)));
|
||||
statuses.Add(Attempt.Fail(new PublishStatus(item, PublishStatusType.FailedIsTrashed, evtMsgs)));
|
||||
|
||||
//Does this document apply to our rule to cancel it's children being published?
|
||||
CheckCancellingOfChildPublishing(item, parentsIdsCancelled, includeUnpublishedDocuments);
|
||||
@@ -255,7 +256,7 @@ namespace Umbraco.Core.Publishing
|
||||
string.Format("Content '{0}' with Id '{1}' has been published.",
|
||||
item.Name, item.Id));
|
||||
|
||||
statuses.Add(Attempt.Succeed(new PublishStatus(item)));
|
||||
statuses.Add(Attempt.Succeed(new PublishStatus(item, evtMsgs)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -341,14 +342,15 @@ namespace Umbraco.Core.Publishing
|
||||
// if published != newest, then the published flags need to be reseted by whoever is calling that method
|
||||
// at the moment it's done by the content service
|
||||
|
||||
var evtMsgs = _eventMessagesFactory.Get();
|
||||
|
||||
//Fire UnPublishing event
|
||||
if (UnPublishing.IsRaisedEventCancelled(
|
||||
_eventMessagesFactory.Get(),
|
||||
messages => new PublishEventArgs<IContent>(content, messages), this))
|
||||
if (UnPublishing.IsRaisedEventCancelled(
|
||||
new PublishEventArgs<IContent>(content, evtMsgs), this))
|
||||
{
|
||||
_logger.Info<PublishingStrategy>(
|
||||
string.Format("Content '{0}' with Id '{1}' will not be unpublished, the event was cancelled.", content.Name, content.Id));
|
||||
return Attempt.Fail(new PublishStatus(content, PublishStatusType.FailedCancelledByEvent));
|
||||
return Attempt.Fail(new PublishStatus(content, PublishStatusType.FailedCancelledByEvent, evtMsgs));
|
||||
}
|
||||
|
||||
//If Content has a release date set to before now, it should be removed so it doesn't interrupt an unpublish
|
||||
@@ -370,7 +372,7 @@ namespace Umbraco.Core.Publishing
|
||||
string.Format("Content '{0}' with Id '{1}' has been unpublished.",
|
||||
content.Name, content.Id));
|
||||
|
||||
return Attempt.Succeed(new PublishStatus(content));
|
||||
return Attempt.Succeed(new PublishStatus(content, evtMsgs));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -402,9 +404,9 @@ namespace Umbraco.Core.Publishing
|
||||
/// <param name="content"><see cref="IContent"/> thats being published</param>
|
||||
public override void PublishingFinalized(IContent content)
|
||||
{
|
||||
Published.RaiseEvent(
|
||||
_eventMessagesFactory.Get(),
|
||||
messages => new PublishEventArgs<IContent>(content, false, false, messages), this);
|
||||
var evtMsgs = _eventMessagesFactory.Get();
|
||||
Published.RaiseEvent(
|
||||
new PublishEventArgs<IContent>(content, false, false, evtMsgs), this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -414,9 +416,9 @@ namespace Umbraco.Core.Publishing
|
||||
/// <param name="isAllRepublished">Boolean indicating whether its all content that is republished</param>
|
||||
public override void PublishingFinalized(IEnumerable<IContent> content, bool isAllRepublished)
|
||||
{
|
||||
var evtMsgs = _eventMessagesFactory.Get();
|
||||
Published.RaiseEvent(
|
||||
_eventMessagesFactory.Get(),
|
||||
messages => new PublishEventArgs<IContent>(content, false, isAllRepublished, messages), this);
|
||||
new PublishEventArgs<IContent>(content, false, isAllRepublished, evtMsgs), this);
|
||||
|
||||
}
|
||||
|
||||
@@ -426,9 +428,9 @@ namespace Umbraco.Core.Publishing
|
||||
/// <param name="content"><see cref="IContent"/> thats being unpublished</param>
|
||||
public override void UnPublishingFinalized(IContent content)
|
||||
{
|
||||
var evtMsgs = _eventMessagesFactory.Get();
|
||||
UnPublished.RaiseEvent(
|
||||
_eventMessagesFactory.Get(),
|
||||
messages => new PublishEventArgs<IContent>(content, false, false, messages), this);
|
||||
new PublishEventArgs<IContent>(content, false, false, evtMsgs), this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -437,9 +439,9 @@ namespace Umbraco.Core.Publishing
|
||||
/// <param name="content">An enumerable list of <see cref="IContent"/> thats being unpublished</param>
|
||||
public override void UnPublishingFinalized(IEnumerable<IContent> content)
|
||||
{
|
||||
var evtMsgs = _eventMessagesFactory.Get();
|
||||
UnPublished.RaiseEvent(
|
||||
_eventMessagesFactory.Get(),
|
||||
messages => new PublishEventArgs<IContent>(content, false, false, messages), this);
|
||||
new PublishEventArgs<IContent>(content, false, false, evtMsgs), this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
@@ -8,16 +9,16 @@ namespace Umbraco.Core.Publishing
|
||||
/// </summary>
|
||||
public class UnPublishStatus : OperationStatus<IContent, UnPublishedStatusType>
|
||||
{
|
||||
public UnPublishStatus(IContent content, UnPublishedStatusType statusType)
|
||||
: base(content, statusType)
|
||||
public UnPublishStatus(IContent content, UnPublishedStatusType statusType, EventMessages eventMessages)
|
||||
: base(content, statusType, eventMessages)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a successful unpublish status
|
||||
/// </summary>
|
||||
public UnPublishStatus(IContent content)
|
||||
: this(content, UnPublishedStatusType.Success)
|
||||
public UnPublishStatus(IContent content, EventMessages eventMessages)
|
||||
: this(content, UnPublishedStatusType.Success, eventMessages)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -889,16 +889,17 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="userId">Optional Id of the User deleting the Content</param>
|
||||
Attempt<OperationStatus> IContentServiceOperations.MoveToRecycleBin(IContent content, int userId)
|
||||
{
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
var originalPath = content.Path;
|
||||
|
||||
if (Trashing.IsRaisedEventCancelled(
|
||||
EventMessagesFactory.Get(),
|
||||
messages => new MoveEventArgs<IContent>(messages, new MoveEventInfo<IContent>(content, originalPath, Constants.System.RecycleBinContent)),
|
||||
if (Trashing.IsRaisedEventCancelled(
|
||||
new MoveEventArgs<IContent>(evtMsgs, new MoveEventInfo<IContent>(content, originalPath, Constants.System.RecycleBinContent)),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(OperationStatus.Cancelled);
|
||||
return Attempt.Fail(OperationStatus.Cancelled(evtMsgs));
|
||||
}
|
||||
|
||||
var moveInfo = new List<MoveEventInfo<IContent>>
|
||||
@@ -941,11 +942,11 @@ namespace Umbraco.Core.Services
|
||||
uow.Commit();
|
||||
}
|
||||
|
||||
Trashed.RaiseEvent(EventMessagesFactory.Get(), messages => new MoveEventArgs<IContent>(false, messages, moveInfo.ToArray()), this);
|
||||
Trashed.RaiseEvent(new MoveEventArgs<IContent>(false, evtMsgs, moveInfo.ToArray()), this);
|
||||
|
||||
Audit(AuditType.Move, "Move Content to Recycle Bin performed by user", userId, content.Id);
|
||||
|
||||
return Attempt.Succeed(OperationStatus.Success);
|
||||
return Attempt.Succeed(OperationStatus.Success(evtMsgs));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1060,14 +1061,15 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
var asArray = contents.ToArray();
|
||||
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
|
||||
if (raiseEvents)
|
||||
{
|
||||
if (Saving.IsRaisedEventCancelled(
|
||||
EventMessagesFactory.Get(),
|
||||
messages => new SaveEventArgs<IContent>(asArray, messages),
|
||||
new SaveEventArgs<IContent>(asArray, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(OperationStatus.Cancelled);
|
||||
return Attempt.Fail(OperationStatus.Cancelled(evtMsgs));
|
||||
}
|
||||
}
|
||||
using (new WriteLock(Locker))
|
||||
@@ -1107,11 +1109,11 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
if (raiseEvents)
|
||||
Saved.RaiseEvent(EventMessagesFactory.Get(), messages => new SaveEventArgs<IContent>(asArray, false, messages), this);
|
||||
Saved.RaiseEvent(new SaveEventArgs<IContent>(asArray, false, evtMsgs), this);
|
||||
|
||||
Audit(AuditType.Save, "Bulk Save content performed by user", userId == -1 ? 0 : userId, Constants.System.Root);
|
||||
|
||||
return Attempt.Succeed(OperationStatus.Success);
|
||||
return Attempt.Succeed(OperationStatus.Success(evtMsgs));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1126,14 +1128,15 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="userId">Optional Id of the User deleting the Content</param>
|
||||
Attempt<OperationStatus> IContentServiceOperations.Delete(IContent content, int userId)
|
||||
{
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
if (Deleting.IsRaisedEventCancelled(
|
||||
EventMessagesFactory.Get(),
|
||||
messages => new DeleteEventArgs<IContent>(content, messages),
|
||||
if (Deleting.IsRaisedEventCancelled(
|
||||
new DeleteEventArgs<IContent>(content, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(OperationStatus.Cancelled);
|
||||
return Attempt.Fail(OperationStatus.Cancelled(evtMsgs));
|
||||
}
|
||||
|
||||
//Make sure that published content is unpublished before being deleted
|
||||
@@ -1154,10 +1157,9 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
repository.Delete(content);
|
||||
uow.Commit();
|
||||
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
|
||||
var args = new DeleteEventArgs<IContent>(content, false, evtMsgs);
|
||||
Deleted.RaiseEvent(evtMsgs, messages => args, this);
|
||||
Deleted.RaiseEvent(args, this);
|
||||
|
||||
//remove any flagged media files
|
||||
repository.DeleteMediaFiles(args.MediaFilesToDelete);
|
||||
@@ -1165,7 +1167,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
Audit(AuditType.Delete, "Delete Content performed by user", userId, content.Id);
|
||||
|
||||
return Attempt.Succeed(OperationStatus.Success);
|
||||
return Attempt.Succeed(OperationStatus.Success(evtMsgs));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1772,6 +1774,8 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
if (content == null) throw new ArgumentNullException("content");
|
||||
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
var result = new List<Attempt<PublishStatus>>();
|
||||
@@ -1783,7 +1787,7 @@ namespace Umbraco.Core.Services
|
||||
string.Format(
|
||||
"Content '{0}' with Id '{1}' could not be published because its parent or one of its ancestors is not published.",
|
||||
content.Name, content.Id));
|
||||
result.Add(Attempt.Fail(new PublishStatus(content, PublishStatusType.FailedPathNotPublished)));
|
||||
result.Add(Attempt.Fail(new PublishStatus(content, PublishStatusType.FailedPathNotPublished, evtMsgs)));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1795,7 +1799,7 @@ namespace Umbraco.Core.Services
|
||||
content.Name, content.Id));
|
||||
result.Add(
|
||||
Attempt.Fail(
|
||||
new PublishStatus(content, PublishStatusType.FailedContentInvalid)
|
||||
new PublishStatus(content, PublishStatusType.FailedContentInvalid, evtMsgs)
|
||||
{
|
||||
InvalidProperties = ((ContentBase)content).LastInvalidProperties
|
||||
}));
|
||||
@@ -1857,14 +1861,17 @@ namespace Umbraco.Core.Services
|
||||
var newest = GetById(content.Id); // ensure we have the newest version
|
||||
if (content.Version != newest.Version) // but use the original object if it's already the newest version
|
||||
content = newest;
|
||||
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
|
||||
var published = content.Published ? content : GetPublishedVersion(content.Id); // get the published version
|
||||
if (published == null)
|
||||
{
|
||||
return Attempt.Succeed(new UnPublishStatus(content, UnPublishedStatusType.SuccessAlreadyUnPublished)); // already unpublished
|
||||
return Attempt.Succeed(new UnPublishStatus(content, UnPublishedStatusType.SuccessAlreadyUnPublished, evtMsgs)); // already unpublished
|
||||
}
|
||||
|
||||
var unpublished = _publishingStrategy.UnPublish(content, userId);
|
||||
if (unpublished == false) return Attempt.Fail(new UnPublishStatus(content, UnPublishedStatusType.FailedCancelledByEvent));
|
||||
if (unpublished == false) return Attempt.Fail(new UnPublishStatus(content, UnPublishedStatusType.FailedCancelledByEvent, evtMsgs));
|
||||
|
||||
var uow = UowProvider.GetUnitOfWork();
|
||||
using (var repository = RepositoryFactory.CreateContentRepository(uow))
|
||||
@@ -1884,7 +1891,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
Audit(AuditType.UnPublish, "UnPublish performed by user", userId, content.Id);
|
||||
|
||||
return Attempt.Succeed(new UnPublishStatus(content, UnPublishedStatusType.Success));
|
||||
return Attempt.Succeed(new UnPublishStatus(content, UnPublishedStatusType.Success, evtMsgs));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1896,13 +1903,14 @@ namespace Umbraco.Core.Services
|
||||
/// <returns>True if publishing succeeded, otherwise False</returns>
|
||||
private Attempt<PublishStatus> SaveAndPublishDo(IContent content, int userId = 0, bool raiseEvents = true)
|
||||
{
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
|
||||
if (raiseEvents)
|
||||
{
|
||||
if (Saving.IsRaisedEventCancelled(
|
||||
EventMessagesFactory.Get(),
|
||||
messages => new SaveEventArgs<IContent>(content, messages), this))
|
||||
new SaveEventArgs<IContent>(content, evtMsgs), this))
|
||||
{
|
||||
return Attempt.Fail(new PublishStatus(content, PublishStatusType.FailedCancelledByEvent));
|
||||
return Attempt.Fail(new PublishStatus(content, PublishStatusType.FailedCancelledByEvent, evtMsgs));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1910,7 +1918,7 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
//Has this content item previously been published? If so, we don't need to refresh the children
|
||||
var previouslyPublished = content.HasIdentity && HasPublishedVersion(content.Id); //content might not have an id
|
||||
var publishStatus = new PublishStatus(content, PublishStatusType.Success); //initially set to success
|
||||
var publishStatus = new PublishStatus(content, PublishStatusType.Success, evtMsgs); //initially set to success
|
||||
|
||||
//Check if parent is published (although not if its a root node) - if parent isn't published this Content cannot be published
|
||||
publishStatus.StatusType = CheckAndLogIsPublishable(content);
|
||||
@@ -1960,7 +1968,7 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
if (raiseEvents)
|
||||
Saved.RaiseEvent(EventMessagesFactory.Get(), messages => new SaveEventArgs<IContent>(content, false, messages), this);
|
||||
Saved.RaiseEvent(new SaveEventArgs<IContent>(content, false, evtMsgs), this);
|
||||
|
||||
//Save xml to db and call following method to fire event through PublishingStrategy to update cache
|
||||
if (published)
|
||||
@@ -1991,14 +1999,15 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="raiseEvents">Optional boolean indicating whether or not to raise events.</param>
|
||||
private Attempt<OperationStatus> Save(IContent content, bool changeState, int userId = 0, bool raiseEvents = true)
|
||||
{
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
|
||||
if (raiseEvents)
|
||||
{
|
||||
if (Saving.IsRaisedEventCancelled(
|
||||
EventMessagesFactory.Get(),
|
||||
messages => new SaveEventArgs<IContent>(content, messages),
|
||||
if (Saving.IsRaisedEventCancelled(
|
||||
new SaveEventArgs<IContent>(content, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(OperationStatus.Cancelled);
|
||||
return Attempt.Fail(OperationStatus.Cancelled(evtMsgs));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2026,11 +2035,11 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
if (raiseEvents)
|
||||
Saved.RaiseEvent(EventMessagesFactory.Get(), messages => new SaveEventArgs<IContent>(content, false, messages), this);
|
||||
Saved.RaiseEvent(new SaveEventArgs<IContent>(content, false, evtMsgs), this);
|
||||
|
||||
Audit(AuditType.Save, "Save Content performed by user", userId, content.Id);
|
||||
|
||||
return Attempt.Succeed(OperationStatus.Success);
|
||||
return Attempt.Succeed(OperationStatus.Success(evtMsgs));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -319,6 +319,53 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<ITemplate> GetTemplateDescendants(string alias)
|
||||
{
|
||||
using (var repository = _repositoryFactory.CreateTemplateRepository(_dataUowProvider.GetUnitOfWork()))
|
||||
{
|
||||
return repository.GetDescendants(alias);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the template descendants
|
||||
/// </summary>
|
||||
/// <param name="masterTemplateId"></param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<ITemplate> GetTemplateDescendants(int masterTemplateId)
|
||||
{
|
||||
using (var repository = _repositoryFactory.CreateTemplateRepository(_dataUowProvider.GetUnitOfWork()))
|
||||
{
|
||||
return repository.GetDescendants(masterTemplateId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the template children
|
||||
/// </summary>
|
||||
/// <param name="alias"></param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<ITemplate> GetTemplateChildren(string alias)
|
||||
{
|
||||
using (var repository = _repositoryFactory.CreateTemplateRepository(_dataUowProvider.GetUnitOfWork()))
|
||||
{
|
||||
return repository.GetChildren(alias);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the template children
|
||||
/// </summary>
|
||||
/// <param name="masterTemplateId"></param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<ITemplate> GetTemplateChildren(int masterTemplateId)
|
||||
{
|
||||
using (var repository = _repositoryFactory.CreateTemplateRepository(_dataUowProvider.GetUnitOfWork()))
|
||||
{
|
||||
return repository.GetChildren(masterTemplateId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a template as a template node which can be traversed (parent, children)
|
||||
/// </summary>
|
||||
|
||||
@@ -130,10 +130,38 @@ namespace Umbraco.Core.Services
|
||||
ITemplate GetTemplate(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a template as a template node which can be traversed (parent, children)
|
||||
/// Gets the template descendants
|
||||
/// </summary>
|
||||
/// <param name="alias"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<ITemplate> GetTemplateDescendants(string alias);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the template descendants
|
||||
/// </summary>
|
||||
/// <param name="masterTemplateId"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<ITemplate> GetTemplateDescendants(int masterTemplateId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the template children
|
||||
/// </summary>
|
||||
/// <param name="alias"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<ITemplate> GetTemplateChildren(string alias);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the template children
|
||||
/// </summary>
|
||||
/// <param name="masterTemplateId"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<ITemplate> GetTemplateChildren(int masterTemplateId);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a template as a template node which can be traversed (parent, children)
|
||||
/// </summary>
|
||||
/// <param name="alias"></param>
|
||||
/// <returns></returns>
|
||||
TemplateNode GetTemplateNode(string alias);
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -47,5 +47,13 @@ namespace Umbraco.Core.Services
|
||||
/// to resolve the full culture if possible.
|
||||
/// </remarks>
|
||||
CultureInfo ConvertToSupportedCultureWithRegionCode(CultureInfo currentCulture);
|
||||
|
||||
/// <summary>
|
||||
/// HAAAAAAAAAAACK! Used for backwards compat to convert a user's real culture code to a region code - normally this would be two letters
|
||||
/// TODO: REmove in v8
|
||||
/// </summary>
|
||||
/// <param name="currentCulture"></param>
|
||||
/// <returns></returns>
|
||||
string ConvertToRegionCodeFromSupportedCulture(CultureInfo currentCulture);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,6 +191,23 @@ namespace Umbraco.Core.Services
|
||||
return attempt ? attempt.Result : currentCulture;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// HAAAAAAAAAAACK! Used for backwards compat to convert a user's real culture code to a region code - normally this would be two letters
|
||||
/// </summary>
|
||||
/// <param name="currentCulture"></param>
|
||||
/// <returns></returns>
|
||||
public string ConvertToRegionCodeFromSupportedCulture(CultureInfo currentCulture)
|
||||
{
|
||||
if (currentCulture == null) throw new ArgumentNullException("currentCulture");
|
||||
|
||||
if (_fileSources == null) return currentCulture.Name;
|
||||
|
||||
var attempt = _fileSources.Value.TryConvert4LetterCultureTo2Letter(currentCulture);
|
||||
return attempt
|
||||
? attempt.Result
|
||||
: currentCulture.Name;
|
||||
}
|
||||
|
||||
private string GetFromDictionarySource(CultureInfo culture, string area, string key, IDictionary<string, string> tokens)
|
||||
{
|
||||
if (_dictionarySource.ContainsKey(culture) == false)
|
||||
|
||||
@@ -158,7 +158,7 @@ namespace Umbraco.Core.Services
|
||||
//TODO: See other notes in this class, this is purely a hack because we store 2 letter culture file names that contain 4 letter cultures :(
|
||||
public Attempt<CultureInfo> TryConvert2LetterCultureTo4Letter(string twoLetterCulture)
|
||||
{
|
||||
if (twoLetterCulture.Length != 2) Attempt<CultureInfo>.Fail();
|
||||
if (twoLetterCulture.Length != 2) return Attempt<CultureInfo>.Fail();
|
||||
|
||||
//This needs to be resolved before continuing so that the _twoLetterCultureConverter cache is initialized
|
||||
var resolved = _xmlSources.Value;
|
||||
@@ -168,6 +168,19 @@ namespace Umbraco.Core.Services
|
||||
: Attempt<CultureInfo>.Fail();
|
||||
}
|
||||
|
||||
//TODO: See other notes in this class, this is purely a hack because we store 2 letter culture file names that contain 4 letter cultures :(
|
||||
public Attempt<string> TryConvert4LetterCultureTo2Letter(CultureInfo culture)
|
||||
{
|
||||
if (culture == null) throw new ArgumentNullException("culture");
|
||||
|
||||
//This needs to be resolved before continuing so that the _twoLetterCultureConverter cache is initialized
|
||||
var resolved = _xmlSources.Value;
|
||||
|
||||
return _twoLetterCultureConverter.Values.Contains(culture)
|
||||
? Attempt.Succeed(culture.Name.Substring(0, 2))
|
||||
: Attempt<string>.Fail();
|
||||
}
|
||||
|
||||
private void MergeSupplementaryFiles(CultureInfo culture, XDocument xMasterDoc)
|
||||
{
|
||||
if (xMasterDoc.Root == null) return;
|
||||
|
||||
@@ -741,12 +741,12 @@ namespace Umbraco.Core.Services
|
||||
Attempt<OperationStatus> IMediaServiceOperations.Delete(IMedia media, int userId)
|
||||
{
|
||||
//TODO: IT would be much nicer to mass delete all in one trans in the repo level!
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
|
||||
if (Deleting.IsRaisedEventCancelled(
|
||||
EventMessagesFactory.Get(),
|
||||
messages => new DeleteEventArgs<IMedia>(media, messages), this))
|
||||
if (Deleting.IsRaisedEventCancelled(
|
||||
new DeleteEventArgs<IMedia>(media, evtMsgs), this))
|
||||
{
|
||||
return Attempt.Fail(OperationStatus.Cancelled);
|
||||
return Attempt.Fail(OperationStatus.Cancelled(evtMsgs));
|
||||
}
|
||||
|
||||
//Delete children before deleting the 'possible parent'
|
||||
@@ -762,9 +762,8 @@ namespace Umbraco.Core.Services
|
||||
repository.Delete(media);
|
||||
uow.Commit();
|
||||
|
||||
var msgs = EventMessagesFactory.Get();
|
||||
var args = new DeleteEventArgs<IMedia>(media, false, msgs);
|
||||
Deleted.RaiseEvent(msgs, messages => args, this);
|
||||
var args = new DeleteEventArgs<IMedia>(media, false, evtMsgs);
|
||||
Deleted.RaiseEvent(args, this);
|
||||
|
||||
//remove any flagged media files
|
||||
repository.DeleteMediaFiles(args.MediaFilesToDelete);
|
||||
@@ -772,7 +771,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
Audit(AuditType.Delete, "Delete Media performed by user", userId, media.Id);
|
||||
|
||||
return Attempt.Succeed(OperationStatus.Success);
|
||||
return Attempt.Succeed(OperationStatus.Success(evtMsgs));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -783,14 +782,15 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="raiseEvents">Optional boolean indicating whether or not to raise events.</param>
|
||||
Attempt<OperationStatus> IMediaServiceOperations.Save(IMedia media, int userId, bool raiseEvents)
|
||||
{
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
|
||||
if (raiseEvents)
|
||||
{
|
||||
if (Saving.IsRaisedEventCancelled(
|
||||
EventMessagesFactory.Get(),
|
||||
messages => new SaveEventArgs<IMedia>(media, messages),
|
||||
new SaveEventArgs<IMedia>(media, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(OperationStatus.Cancelled);
|
||||
return Attempt.Fail(OperationStatus.Cancelled(evtMsgs));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -811,11 +811,11 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
if (raiseEvents)
|
||||
Saved.RaiseEvent(EventMessagesFactory.Get(), messages => new SaveEventArgs<IMedia>(media, false, messages), this);
|
||||
Saved.RaiseEvent(new SaveEventArgs<IMedia>(media, false, evtMsgs), this);
|
||||
|
||||
Audit(AuditType.Save, "Save Media performed by user", userId, media.Id);
|
||||
|
||||
return Attempt.Succeed(OperationStatus.Success);
|
||||
return Attempt.Succeed(OperationStatus.Success(evtMsgs));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -827,15 +827,15 @@ namespace Umbraco.Core.Services
|
||||
Attempt<OperationStatus> IMediaServiceOperations.Save(IEnumerable<IMedia> medias, int userId, bool raiseEvents)
|
||||
{
|
||||
var asArray = medias.ToArray();
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
|
||||
if (raiseEvents)
|
||||
{
|
||||
if (Saving.IsRaisedEventCancelled(
|
||||
EventMessagesFactory.Get(),
|
||||
messages => new SaveEventArgs<IMedia>(asArray, messages),
|
||||
new SaveEventArgs<IMedia>(asArray, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(OperationStatus.Cancelled);
|
||||
return Attempt.Fail(OperationStatus.Cancelled(evtMsgs));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -859,11 +859,11 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
if (raiseEvents)
|
||||
Saved.RaiseEvent(EventMessagesFactory.Get(), messages => new SaveEventArgs<IMedia>(asArray, false, messages), this);
|
||||
Saved.RaiseEvent(new SaveEventArgs<IMedia>(asArray, false, evtMsgs), this);
|
||||
|
||||
Audit(AuditType.Save, "Save Media items performed by user", userId, -1);
|
||||
|
||||
return Attempt.Succeed(OperationStatus.Success);
|
||||
return Attempt.Succeed(OperationStatus.Success(evtMsgs));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -960,11 +960,12 @@ namespace Umbraco.Core.Services
|
||||
|
||||
var originalPath = media.Path;
|
||||
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
|
||||
if (Trashing.IsRaisedEventCancelled(
|
||||
EventMessagesFactory.Get(),
|
||||
messages => new MoveEventArgs<IMedia>(messages, new MoveEventInfo<IMedia>(media, originalPath, Constants.System.RecycleBinMedia)), this))
|
||||
new MoveEventArgs<IMedia>(new MoveEventInfo<IMedia>(media, originalPath, Constants.System.RecycleBinMedia)), this))
|
||||
{
|
||||
return Attempt.Fail(OperationStatus.Cancelled);
|
||||
return Attempt.Fail(OperationStatus.Cancelled(evtMsgs));
|
||||
}
|
||||
|
||||
var moveInfo = new List<MoveEventInfo<IMedia>>
|
||||
@@ -1002,12 +1003,11 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
Trashed.RaiseEvent(
|
||||
EventMessagesFactory.Get(),
|
||||
messages => new MoveEventArgs<IMedia>(false, messages, moveInfo.ToArray()), this);
|
||||
new MoveEventArgs<IMedia>(false, evtMsgs, moveInfo.ToArray()), this);
|
||||
|
||||
Audit(AuditType.Move, "Move Media to Recycle Bin performed by user", userId, media.Id);
|
||||
|
||||
return Attempt.Succeed(OperationStatus.Success);
|
||||
return Attempt.Succeed(OperationStatus.Success(evtMsgs));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
var content = (IContent) entity;
|
||||
//we'll lazily get these if we need to send notifications
|
||||
IContent[] allVersions = null;
|
||||
IEnumerable<IContent> allVersions = null;
|
||||
|
||||
int totalUsers;
|
||||
var allUsers = _userService.GetAll(0, int.MaxValue, out totalUsers);
|
||||
@@ -75,12 +75,17 @@ namespace Umbraco.Core.Services
|
||||
//lazy load versions if notifications are required
|
||||
if (allVersions == null)
|
||||
{
|
||||
allVersions = _contentService.GetVersions(entity.Id).ToArray();
|
||||
allVersions = _contentService.GetVersions(entity.Id);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
SendNotification(operatingUser, u, content, allVersions, actionName, http, createSubject, createBody);
|
||||
SendNotification(
|
||||
operatingUser, u, content,
|
||||
allVersions,
|
||||
actionName, http, createSubject, createBody);
|
||||
|
||||
|
||||
_logger.Debug<NotificationService>(string.Format("Notification type: {0} sent to {1} ({2})", action, u.Name, u.Email));
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -192,7 +197,7 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="http"></param>
|
||||
/// <param name="createSubject">Callback to create the mail subject</param>
|
||||
/// <param name="createBody">Callback to create the mail body</param>
|
||||
private void SendNotification(IUser performingUser, IUser mailingUser, IContent content, IContent[] allVersions, string actionName, HttpContextBase http,
|
||||
private void SendNotification(IUser performingUser, IUser mailingUser, IContent content, IEnumerable<IContent> allVersions, string actionName, HttpContextBase http,
|
||||
Func<IUser, string[], string> createSubject,
|
||||
Func<IUser, string[], string> createBody)
|
||||
{
|
||||
@@ -204,8 +209,11 @@ namespace Umbraco.Core.Services
|
||||
if (createSubject == null) throw new ArgumentNullException("createSubject");
|
||||
if (createBody == null) throw new ArgumentNullException("createBody");
|
||||
|
||||
int versionCount = (allVersions.Length > 1) ? (allVersions.Length - 2) : (allVersions.Length - 1);
|
||||
var oldDoc = _contentService.GetByVersion(allVersions[versionCount].Version);
|
||||
//Ensure they are sorted: http://issues.umbraco.org/issue/U4-5180
|
||||
var allVersionsAsArray = allVersions.OrderBy(x => x.UpdateDate).ToArray();
|
||||
|
||||
int versionCount = (allVersionsAsArray.Length > 1) ? (allVersionsAsArray.Length - 2) : (allVersionsAsArray.Length - 1);
|
||||
var oldDoc = _contentService.GetByVersion(allVersionsAsArray[versionCount].Version);
|
||||
|
||||
// build summary
|
||||
var summary = new StringBuilder();
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
@@ -8,7 +10,7 @@ namespace Umbraco.Core.Services
|
||||
public class OperationStatus<TEntity, TStatus> : OperationStatus<TStatus>
|
||||
where TStatus : struct
|
||||
{
|
||||
public OperationStatus(TEntity entity, TStatus statusType) : base(statusType)
|
||||
public OperationStatus(TEntity entity, TStatus statusType, EventMessages eventMessages) : base(statusType, eventMessages)
|
||||
{
|
||||
Entity = entity;
|
||||
}
|
||||
@@ -20,12 +22,15 @@ namespace Umbraco.Core.Services
|
||||
public class OperationStatus<TStatus>
|
||||
where TStatus : struct
|
||||
{
|
||||
public OperationStatus(TStatus statusType)
|
||||
public OperationStatus(TStatus statusType, EventMessages eventMessages)
|
||||
{
|
||||
if (eventMessages == null) throw new ArgumentNullException("eventMessages");
|
||||
StatusType = statusType;
|
||||
EventMessages = eventMessages;
|
||||
}
|
||||
|
||||
public TStatus StatusType { get; internal set; }
|
||||
public EventMessages EventMessages { get; private set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -33,21 +38,23 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
public class OperationStatus : OperationStatus<OperationStatusType>
|
||||
{
|
||||
public OperationStatus(OperationStatusType statusType) : base(statusType)
|
||||
public OperationStatus(OperationStatusType statusType, EventMessages eventMessages) : base(statusType, eventMessages)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#region Static Helper methods
|
||||
internal static OperationStatus Cancelled
|
||||
|
||||
internal static OperationStatus Cancelled(EventMessages eventMessages)
|
||||
{
|
||||
get { return new OperationStatus(OperationStatusType.FailedCancelledByEvent); }
|
||||
return new OperationStatus(OperationStatusType.FailedCancelledByEvent, eventMessages);
|
||||
}
|
||||
|
||||
internal static OperationStatus Success
|
||||
internal static OperationStatus Success(EventMessages eventMessages)
|
||||
{
|
||||
get { return new OperationStatus(OperationStatusType.Success); }
|
||||
}
|
||||
return new OperationStatus(OperationStatusType.Success, eventMessages);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
@@ -1409,5 +1409,18 @@ namespace Umbraco.Core
|
||||
{
|
||||
return string.IsNullOrEmpty(text) ? text : InvalidXmlChars.Replace(text, "");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a string to a Guid - WARNING, depending on the string, this may not be unique
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
/// <returns></returns>
|
||||
internal static Guid ToGuid(this string text)
|
||||
{
|
||||
var md5 = MD5.Create();
|
||||
byte[] myStringBytes = Encoding.ASCII.GetBytes(text);
|
||||
byte[] hash = md5.ComputeHash(myStringBytes);
|
||||
return new Guid(hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,13 +37,13 @@
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="AutoMapper, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.dll</HintPath>
|
||||
<Reference Include="AutoMapper, Version=3.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\AutoMapper.3.0.0\lib\net40\AutoMapper.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="AutoMapper.Net4, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
|
||||
<Reference Include="AutoMapper.Net4, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\AutoMapper.3.0.0\lib\net40\AutoMapper.Net4.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="HtmlAgilityPack, Version=1.4.9.0, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
@@ -302,6 +302,7 @@
|
||||
<Compile Include="DatabaseContext.cs" />
|
||||
<Compile Include="DataTableExtensions.cs" />
|
||||
<Compile Include="DateTimeExtensions.cs" />
|
||||
<Compile Include="DelegateExtensions.cs" />
|
||||
<Compile Include="DictionaryExtensions.cs" />
|
||||
<Compile Include="Dictionary\CultureDictionaryFactoryResolver.cs" />
|
||||
<Compile Include="Dictionary\ICultureDictionaryFactory.cs" />
|
||||
@@ -1386,7 +1387,6 @@
|
||||
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" />
|
||||
<Error Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
|
||||
</Target>
|
||||
<Import Project="..\packages\AutoMapper.3.3.1\tools\AutoMapper.targets" Condition="Exists('..\packages\AutoMapper.3.3.1\tools\AutoMapper.targets')" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
|
||||
<package id="AutoMapper" version="3.0.0" targetFramework="net45" />
|
||||
<package id="HtmlAgilityPack" version="1.4.9" targetFramework="net45" />
|
||||
<package id="log4net-mediumtrust" version="2.0.0" targetFramework="net4" />
|
||||
<package id="Microsoft.AspNet.Identity.Core" version="2.2.1" targetFramework="net45" />
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using Lucene.Net.Index;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class DelegateExtensionsTests
|
||||
{
|
||||
|
||||
[Test]
|
||||
public void Only_Executes_Specific_Count()
|
||||
{
|
||||
var maxTries = 5;
|
||||
var totalTries = 0;
|
||||
DelegateExtensions.RetryUntilSuccessOrMaxAttempts((currentTry) =>
|
||||
{
|
||||
totalTries = currentTry;
|
||||
return Attempt<IndexWriter>.Fail();
|
||||
}, 5, TimeSpan.FromMilliseconds(10));
|
||||
|
||||
Assert.AreEqual(maxTries, totalTries);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Quits_On_Success_Count()
|
||||
{
|
||||
var maxTries = 5;
|
||||
var totalTries = 0;
|
||||
DelegateExtensions.RetryUntilSuccessOrMaxAttempts((currentTry) =>
|
||||
{
|
||||
totalTries = currentTry;
|
||||
if (totalTries == 2)
|
||||
{
|
||||
return Attempt<string>.Succeed();
|
||||
}
|
||||
return Attempt<string>.Fail();
|
||||
}, 5, TimeSpan.FromMilliseconds(10));
|
||||
|
||||
Assert.AreEqual(2, totalTries);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -119,6 +119,7 @@ namespace Umbraco.Tests.Logging
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Ignore]
|
||||
public void CanLogAtleast1000MessagesASecond()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
@@ -460,13 +461,15 @@ javascript: ['~/test.js',/*** some note about stuff asd09823-4**09234*/ '~/test2
|
||||
var content2 = "{javascript: []}";
|
||||
var content3 = "{javascript: ['~/test.js', '~/test2.js']}";
|
||||
var content4 = "{propertyEditors: [], javascript: ['~/test.js', '~/test2.js']}";
|
||||
var content5 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble()) + "{propertyEditors: [], javascript: ['~/test.js', '~/test2.js']}";
|
||||
|
||||
var result = ManifestParser.CreateManifests(null, content1, content2, content3, content4);
|
||||
var result = ManifestParser.CreateManifests(null, content1, content2, content3, content4, content5);
|
||||
|
||||
Assert.AreEqual(4, result.Count());
|
||||
Assert.AreEqual(5, result.Count());
|
||||
Assert.AreEqual(0, result.ElementAt(1).JavaScriptInitialize.Count);
|
||||
Assert.AreEqual(2, result.ElementAt(2).JavaScriptInitialize.Count);
|
||||
Assert.AreEqual(2, result.ElementAt(3).JavaScriptInitialize.Count);
|
||||
Assert.AreEqual(2, result.ElementAt(4).JavaScriptInitialize.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -44,7 +44,13 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
private ContentRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository)
|
||||
{
|
||||
var templateRepository = new TemplateRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, Mock.Of<IFileSystem>(), Mock.Of<IFileSystem>(), Mock.Of<ITemplatesSection>());
|
||||
TemplateRepository tr;
|
||||
return CreateRepository(unitOfWork, out contentTypeRepository, out tr);
|
||||
}
|
||||
|
||||
private ContentRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository, out TemplateRepository templateRepository)
|
||||
{
|
||||
templateRepository = new TemplateRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, Mock.Of<IFileSystem>(), Mock.Of<IFileSystem>(), Mock.Of<ITemplatesSection>());
|
||||
var tagRepository = new TagRepository(unitOfWork, CacheHelper, Logger, SqlSyntax);
|
||||
contentTypeRepository = new ContentTypeRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, templateRepository);
|
||||
var repository = new ContentRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, contentTypeRepository, templateRepository, tagRepository, Mock.Of<IContentSection>());
|
||||
@@ -217,6 +223,37 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
// Assert
|
||||
Assert.That(contentType.HasIdentity, Is.True);
|
||||
Assert.That(textpage.HasIdentity, Is.True);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Perform_Add_With_Default_Template()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider(Logger);
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
ContentTypeRepository contentTypeRepository;
|
||||
TemplateRepository templateRepository;
|
||||
using (var repository = CreateRepository(unitOfWork, out contentTypeRepository, out templateRepository))
|
||||
{
|
||||
var template = new Template("hello", "hello");
|
||||
templateRepository.AddOrUpdate(template);
|
||||
unitOfWork.Commit();
|
||||
|
||||
ContentType contentType = MockedContentTypes.CreateSimpleContentType("umbTextpage2", "Textpage");
|
||||
contentType.SetDefaultTemplate(template);
|
||||
Content textpage = MockedContent.CreateSimpleContent(contentType);
|
||||
|
||||
// Act
|
||||
|
||||
contentTypeRepository.AddOrUpdate(contentType);
|
||||
repository.AddOrUpdate(textpage);
|
||||
unitOfWork.Commit();
|
||||
|
||||
// Assert
|
||||
Assert.That(textpage.Template, Is.Not.Null);
|
||||
Assert.That(textpage.Template, Is.EqualTo(contentType.DefaultTemplate));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,6 +364,28 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Update_With_Null_Template()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider(Logger);
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
ContentTypeRepository contentTypeRepository;
|
||||
using (var repository = CreateRepository(unitOfWork, out contentTypeRepository))
|
||||
{
|
||||
// Act
|
||||
var content = repository.Get(NodeDto.NodeIdSeed + 2);
|
||||
content.Template = null;
|
||||
repository.AddOrUpdate(content);
|
||||
unitOfWork.Commit();
|
||||
var updatedContent = repository.Get(NodeDto.NodeIdSeed + 2);
|
||||
|
||||
// Assert
|
||||
Assert.That(updatedContent.Template, Is.Null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Perform_Delete_On_ContentRepository()
|
||||
{
|
||||
|
||||
@@ -235,13 +235,16 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
using (var repository = CreateRepository(unitOfWork))
|
||||
{
|
||||
var contentType = repository.Get(NodeDto.NodeIdSeed + 1);
|
||||
var childContentType = MockedContentTypes.CreateSimpleContentType("blah", "Blah", contentType, randomizeAliases:true);
|
||||
repository.AddOrUpdate(childContentType);
|
||||
unitOfWork.Commit();
|
||||
|
||||
// Act
|
||||
contentType = repository.Get(contentType.Key);
|
||||
var result = repository.Get(childContentType.Key);
|
||||
|
||||
// Assert
|
||||
Assert.That(contentType, Is.Not.Null);
|
||||
Assert.That(contentType.Id, Is.EqualTo(NodeDto.NodeIdSeed + 1));
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.Id, Is.EqualTo(childContentType.Id));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -85,9 +85,41 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
Assert.AreEqual("test.com", domain.DomainName);
|
||||
Assert.AreEqual(content.Id, domain.RootContentId);
|
||||
Assert.AreEqual(lang.Id, domain.LanguageId);
|
||||
Assert.AreEqual(lang.IsoCode, domain.LanguageIsoCode);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Create_And_Get_By_Id_Empty_lang()
|
||||
{
|
||||
var provider = new PetaPocoUnitOfWorkProvider(Logger);
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
|
||||
ContentType ct;
|
||||
var contentId = CreateTestData("en-AU", out ct);
|
||||
|
||||
ContentRepository contentRepo;
|
||||
LanguageRepository langRepo;
|
||||
ContentTypeRepository contentTypeRepo;
|
||||
|
||||
using (var repo = CreateRepository(unitOfWork, out contentTypeRepo, out contentRepo, out langRepo))
|
||||
{
|
||||
var content = contentRepo.Get(contentId);
|
||||
|
||||
var domain = (IDomain)new UmbracoDomain("test.com") { RootContentId = content.Id };
|
||||
repo.AddOrUpdate(domain);
|
||||
unitOfWork.Commit();
|
||||
|
||||
//re-get
|
||||
domain = repo.Get(domain.Id);
|
||||
|
||||
Assert.NotNull(domain);
|
||||
Assert.IsTrue(domain.HasIdentity);
|
||||
Assert.Greater(domain.Id, 0);
|
||||
Assert.AreEqual("test.com", domain.DomainName);
|
||||
Assert.AreEqual(content.Id, domain.RootContentId);
|
||||
Assert.IsFalse(domain.LanguageId.HasValue);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -203,11 +235,13 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
Assert.AreEqual("blah.com", domain.DomainName);
|
||||
Assert.AreEqual(content2.Id, domain.RootContentId);
|
||||
Assert.AreEqual(lang2.Id, domain.LanguageId);
|
||||
Assert.AreEqual(lang2.IsoCode, domain.LanguageIsoCode);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void Exists()
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@@ -489,77 +490,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
using (var repository = CreateRepository(unitOfWork))
|
||||
{
|
||||
var parent = new Template("parent", "parent")
|
||||
{
|
||||
Content = @"<%@ Master Language=""C#"" %>"
|
||||
};
|
||||
|
||||
var child1 = new Template("child1", "child1")
|
||||
{
|
||||
Content = @"<%@ Master Language=""C#"" %>"
|
||||
};
|
||||
var toddler1 = new Template("toddler1", "toddler1")
|
||||
{
|
||||
Content = @"<%@ Master Language=""C#"" %>"
|
||||
};
|
||||
var toddler2 = new Template("toddler2", "toddler2")
|
||||
{
|
||||
Content = @"<%@ Master Language=""C#"" %>"
|
||||
};
|
||||
var baby1 = new Template("baby1", "baby1")
|
||||
{
|
||||
Content = @"<%@ Master Language=""C#"" %>"
|
||||
};
|
||||
|
||||
var child2 = new Template("child2", "child2")
|
||||
{
|
||||
Content = @"<%@ Master Language=""C#"" %>"
|
||||
};
|
||||
var toddler3 = new Template("toddler3", "toddler3")
|
||||
{
|
||||
Content = @"<%@ Master Language=""C#"" %>"
|
||||
};
|
||||
var toddler4 = new Template("toddler4", "toddler4")
|
||||
{
|
||||
Content = @"<%@ Master Language=""C#"" %>"
|
||||
};
|
||||
var baby2 = new Template("baby2", "baby2")
|
||||
{
|
||||
Content = @"<%@ Master Language=""C#"" %>"
|
||||
};
|
||||
|
||||
|
||||
child1.MasterTemplateAlias = parent.Alias;
|
||||
child1.MasterTemplateId = new Lazy<int>(() => parent.Id);
|
||||
child2.MasterTemplateAlias = parent.Alias;
|
||||
child2.MasterTemplateId = new Lazy<int>(() => parent.Id);
|
||||
|
||||
toddler1.MasterTemplateAlias = child1.Alias;
|
||||
toddler1.MasterTemplateId = new Lazy<int>(() => child1.Id);
|
||||
toddler2.MasterTemplateAlias = child1.Alias;
|
||||
toddler2.MasterTemplateId = new Lazy<int>(() => child1.Id);
|
||||
|
||||
toddler3.MasterTemplateAlias = child2.Alias;
|
||||
toddler3.MasterTemplateId = new Lazy<int>(() => child2.Id);
|
||||
toddler4.MasterTemplateAlias = child2.Alias;
|
||||
toddler4.MasterTemplateId = new Lazy<int>(() => child2.Id);
|
||||
|
||||
baby1.MasterTemplateAlias = toddler2.Alias;
|
||||
baby1.MasterTemplateId = new Lazy<int>(() => toddler2.Id);
|
||||
|
||||
baby2.MasterTemplateAlias = toddler4.Alias;
|
||||
baby2.MasterTemplateId = new Lazy<int>(() => toddler4.Id);
|
||||
|
||||
repository.AddOrUpdate(parent);
|
||||
repository.AddOrUpdate(child1);
|
||||
repository.AddOrUpdate(child2);
|
||||
repository.AddOrUpdate(toddler1);
|
||||
repository.AddOrUpdate(toddler2);
|
||||
repository.AddOrUpdate(toddler3);
|
||||
repository.AddOrUpdate(toddler4);
|
||||
repository.AddOrUpdate(baby1);
|
||||
repository.AddOrUpdate(baby2);
|
||||
unitOfWork.Commit();
|
||||
CreateHierarchy(repository, unitOfWork);
|
||||
|
||||
// Act
|
||||
var rootNode = repository.GetTemplateNode("parent");
|
||||
@@ -575,8 +506,102 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
Assert.IsNotNull(repository.FindTemplateInTree(rootNode, "baby1"));
|
||||
Assert.IsNotNull(repository.FindTemplateInTree(rootNode, "baby2"));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Get_All()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider(Logger);
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
using (var repository = CreateRepository(unitOfWork))
|
||||
{
|
||||
var created = CreateHierarchy(repository, unitOfWork).ToArray();
|
||||
|
||||
// Act
|
||||
var all = repository.GetAll();
|
||||
var allByAlias = repository.GetAll("parent", "child2", "baby2", "notFound");
|
||||
var allById = repository.GetAll(created[0].Id, created[2].Id, created[4].Id, created[5].Id, 999999);
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(9, all.Count());
|
||||
Assert.AreEqual(9, all.DistinctBy(x => x.Id).Count());
|
||||
|
||||
Assert.AreEqual(3, allByAlias.Count());
|
||||
Assert.AreEqual(3, allByAlias.DistinctBy(x => x.Id).Count());
|
||||
|
||||
Assert.AreEqual(4, allById.Count());
|
||||
Assert.AreEqual(4, allById.DistinctBy(x => x.Id).Count());
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Get_Children()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider(Logger);
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
using (var repository = CreateRepository(unitOfWork))
|
||||
{
|
||||
var created = CreateHierarchy(repository, unitOfWork).ToArray();
|
||||
|
||||
// Act
|
||||
var childrenById = repository.GetChildren(created[1].Id);
|
||||
var childrenByAlias = repository.GetChildren(created[1].Alias);
|
||||
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(2, childrenById.Count());
|
||||
Assert.AreEqual(2, childrenById.DistinctBy(x => x.Id).Count());
|
||||
Assert.AreEqual(2, childrenByAlias.Count());
|
||||
Assert.AreEqual(2, childrenByAlias.DistinctBy(x => x.Id).Count());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Get_Children_At_Root()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider(Logger);
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
using (var repository = CreateRepository(unitOfWork))
|
||||
{
|
||||
CreateHierarchy(repository, unitOfWork).ToArray();
|
||||
|
||||
// Act
|
||||
var children = repository.GetChildren(-1);
|
||||
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(1, children.Count());
|
||||
Assert.AreEqual(1, children.DistinctBy(x => x.Id).Count());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Get_Descendants()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider(Logger);
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
using (var repository = CreateRepository(unitOfWork))
|
||||
{
|
||||
var created = CreateHierarchy(repository, unitOfWork).ToArray();
|
||||
|
||||
// Act
|
||||
var descendantsById = repository.GetDescendants(created[1].Id);
|
||||
var descendantsByAlias = repository.GetDescendants(created[1].Alias);
|
||||
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(3, descendantsById.Count());
|
||||
Assert.AreEqual(3, descendantsById.DistinctBy(x => x.Id).Count());
|
||||
|
||||
Assert.AreEqual(3, descendantsByAlias.Count());
|
||||
Assert.AreEqual(3, descendantsByAlias.DistinctBy(x => x.Id).Count());
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -717,5 +742,82 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
private IEnumerable<ITemplate> CreateHierarchy(ITemplateRepository repository, IDatabaseUnitOfWork unitOfWork)
|
||||
{
|
||||
var parent = new Template("parent", "parent")
|
||||
{
|
||||
Content = @"<%@ Master Language=""C#"" %>"
|
||||
};
|
||||
|
||||
var child1 = new Template("child1", "child1")
|
||||
{
|
||||
Content = @"<%@ Master Language=""C#"" %>"
|
||||
};
|
||||
var toddler1 = new Template("toddler1", "toddler1")
|
||||
{
|
||||
Content = @"<%@ Master Language=""C#"" %>"
|
||||
};
|
||||
var toddler2 = new Template("toddler2", "toddler2")
|
||||
{
|
||||
Content = @"<%@ Master Language=""C#"" %>"
|
||||
};
|
||||
var baby1 = new Template("baby1", "baby1")
|
||||
{
|
||||
Content = @"<%@ Master Language=""C#"" %>"
|
||||
};
|
||||
|
||||
var child2 = new Template("child2", "child2")
|
||||
{
|
||||
Content = @"<%@ Master Language=""C#"" %>"
|
||||
};
|
||||
var toddler3 = new Template("toddler3", "toddler3")
|
||||
{
|
||||
Content = @"<%@ Master Language=""C#"" %>"
|
||||
};
|
||||
var toddler4 = new Template("toddler4", "toddler4")
|
||||
{
|
||||
Content = @"<%@ Master Language=""C#"" %>"
|
||||
};
|
||||
var baby2 = new Template("baby2", "baby2")
|
||||
{
|
||||
Content = @"<%@ Master Language=""C#"" %>"
|
||||
};
|
||||
|
||||
|
||||
child1.MasterTemplateAlias = parent.Alias;
|
||||
child1.MasterTemplateId = new Lazy<int>(() => parent.Id);
|
||||
child2.MasterTemplateAlias = parent.Alias;
|
||||
child2.MasterTemplateId = new Lazy<int>(() => parent.Id);
|
||||
|
||||
toddler1.MasterTemplateAlias = child1.Alias;
|
||||
toddler1.MasterTemplateId = new Lazy<int>(() => child1.Id);
|
||||
toddler2.MasterTemplateAlias = child1.Alias;
|
||||
toddler2.MasterTemplateId = new Lazy<int>(() => child1.Id);
|
||||
|
||||
toddler3.MasterTemplateAlias = child2.Alias;
|
||||
toddler3.MasterTemplateId = new Lazy<int>(() => child2.Id);
|
||||
toddler4.MasterTemplateAlias = child2.Alias;
|
||||
toddler4.MasterTemplateId = new Lazy<int>(() => child2.Id);
|
||||
|
||||
baby1.MasterTemplateAlias = toddler2.Alias;
|
||||
baby1.MasterTemplateId = new Lazy<int>(() => toddler2.Id);
|
||||
|
||||
baby2.MasterTemplateAlias = toddler4.Alias;
|
||||
baby2.MasterTemplateId = new Lazy<int>(() => toddler4.Id);
|
||||
|
||||
repository.AddOrUpdate(parent);
|
||||
repository.AddOrUpdate(child1);
|
||||
repository.AddOrUpdate(child2);
|
||||
repository.AddOrUpdate(toddler1);
|
||||
repository.AddOrUpdate(toddler2);
|
||||
repository.AddOrUpdate(toddler3);
|
||||
repository.AddOrUpdate(toddler4);
|
||||
repository.AddOrUpdate(baby1);
|
||||
repository.AddOrUpdate(baby2);
|
||||
unitOfWork.Commit();
|
||||
|
||||
return new[] {parent, child1, child2, toddler1, toddler2, toddler3, toddler4, baby1, baby2};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -454,6 +454,20 @@ namespace Umbraco.Tests.PublishedContent
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FirstChild()
|
||||
{
|
||||
var doc = GetNode(1173); // has child nodes
|
||||
Assert.IsNotNull(doc.FirstChild());
|
||||
Assert.IsNotNull(doc.FirstChild(x => true));
|
||||
Assert.IsNotNull(doc.FirstChild<IPublishedContent>());
|
||||
|
||||
doc = GetNode(1175); // does not have child nodes
|
||||
Assert.IsNull(doc.FirstChild());
|
||||
Assert.IsNull(doc.FirstChild(x => true));
|
||||
Assert.IsNull(doc.FirstChild<IPublishedContent>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HasProperty()
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Umbraco.Tests.Routing
|
||||
{
|
||||
SetupDomainServiceMock(new[]
|
||||
{
|
||||
new UmbracoDomain("domain1.com/") {Id = 1, LanguageId = LangDeId, RootContentId = 1001}
|
||||
new UmbracoDomain("domain1.com/") {Id = 1, LanguageId = LangDeId, RootContentId = 1001, LanguageIsoCode = "de-DE"}
|
||||
});
|
||||
|
||||
}
|
||||
@@ -22,12 +22,12 @@ namespace Umbraco.Tests.Routing
|
||||
{
|
||||
SetupDomainServiceMock(new[]
|
||||
{
|
||||
new UmbracoDomain("domain1.com/") {Id = 1, LanguageId = LangEngId, RootContentId = 1001},
|
||||
new UmbracoDomain("domain1.com/en") {Id = 1, LanguageId = LangEngId, RootContentId = 10011},
|
||||
new UmbracoDomain("domain1.com/fr") {Id = 1, LanguageId = LangFrId, RootContentId = 10012},
|
||||
new UmbracoDomain("http://domain3.com/") {Id = 1, LanguageId = LangEngId, RootContentId = 1003},
|
||||
new UmbracoDomain("http://domain3.com/en") {Id = 1, LanguageId = LangEngId, RootContentId = 10031},
|
||||
new UmbracoDomain("http://domain3.com/fr") {Id = 1, LanguageId = LangFrId, RootContentId = 10032}
|
||||
new UmbracoDomain("domain1.com/") {Id = 1, LanguageId = LangEngId, RootContentId = 1001, LanguageIsoCode = "en-US"},
|
||||
new UmbracoDomain("domain1.com/en") {Id = 1, LanguageId = LangEngId, RootContentId = 10011, LanguageIsoCode = "en-US"},
|
||||
new UmbracoDomain("domain1.com/fr") {Id = 1, LanguageId = LangFrId, RootContentId = 10012, LanguageIsoCode = "fr-FR"},
|
||||
new UmbracoDomain("http://domain3.com/") {Id = 1, LanguageId = LangEngId, RootContentId = 1003, LanguageIsoCode = "en-US"},
|
||||
new UmbracoDomain("http://domain3.com/en") {Id = 1, LanguageId = LangEngId, RootContentId = 10031, LanguageIsoCode = "en-US"},
|
||||
new UmbracoDomain("http://domain3.com/fr") {Id = 1, LanguageId = LangFrId, RootContentId = 10032, LanguageIsoCode = "fr-FR"}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@@ -30,19 +30,22 @@ namespace Umbraco.Tests.Routing
|
||||
{
|
||||
Id = 1,
|
||||
LanguageId = LangDeId,
|
||||
RootContentId = 1001
|
||||
RootContentId = 1001,
|
||||
LanguageIsoCode = "de-DE"
|
||||
},
|
||||
new UmbracoDomain("domain1.com/en")
|
||||
{
|
||||
Id = 1,
|
||||
LanguageId = LangEngId,
|
||||
RootContentId = 10011
|
||||
RootContentId = 10011,
|
||||
LanguageIsoCode = "en-US"
|
||||
},
|
||||
new UmbracoDomain("domain1.com/fr")
|
||||
{
|
||||
Id = 1,
|
||||
LanguageId = LangFrId,
|
||||
RootContentId = 10012
|
||||
RootContentId = 10012,
|
||||
LanguageIsoCode = "fr-FR"
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -55,55 +58,64 @@ namespace Umbraco.Tests.Routing
|
||||
{
|
||||
Id = 1,
|
||||
LanguageId = LangDeId,
|
||||
RootContentId = 1001
|
||||
RootContentId = 1001,
|
||||
LanguageIsoCode = "de-DE"
|
||||
},
|
||||
new UmbracoDomain("domain1.com/en")
|
||||
{
|
||||
Id = 1,
|
||||
LanguageId = LangEngId,
|
||||
RootContentId = 10011
|
||||
RootContentId = 10011,
|
||||
LanguageIsoCode = "en-US"
|
||||
},
|
||||
new UmbracoDomain("domain1.com/fr")
|
||||
{
|
||||
Id = 1,
|
||||
LanguageId = LangFrId,
|
||||
RootContentId = 10012
|
||||
RootContentId = 10012,
|
||||
LanguageIsoCode = "fr-FR"
|
||||
},
|
||||
new UmbracoDomain("*1001")
|
||||
{
|
||||
Id = 1,
|
||||
LanguageId = LangDeId,
|
||||
RootContentId = 1001
|
||||
RootContentId = 1001,
|
||||
LanguageIsoCode = "de-DE"
|
||||
},
|
||||
new UmbracoDomain("*10011")
|
||||
{
|
||||
Id = 1,
|
||||
LanguageId = LangCzId,
|
||||
RootContentId = 10011
|
||||
RootContentId = 10011,
|
||||
LanguageIsoCode = "cs-CZ"
|
||||
},
|
||||
new UmbracoDomain("*100112")
|
||||
{
|
||||
Id = 1,
|
||||
LanguageId = LangNlId,
|
||||
RootContentId = 100112
|
||||
RootContentId = 100112,
|
||||
LanguageIsoCode = "nl-NL"
|
||||
},
|
||||
new UmbracoDomain("*1001122")
|
||||
{
|
||||
Id = 1,
|
||||
LanguageId = LangDkId,
|
||||
RootContentId = 1001122
|
||||
RootContentId = 1001122,
|
||||
LanguageIsoCode = "da-DK"
|
||||
},
|
||||
new UmbracoDomain("*10012")
|
||||
{
|
||||
Id = 1,
|
||||
LanguageId = LangNlId,
|
||||
RootContentId = 10012
|
||||
RootContentId = 10012,
|
||||
LanguageIsoCode = "nl-NL"
|
||||
},
|
||||
new UmbracoDomain("*10031")
|
||||
{
|
||||
Id = 1,
|
||||
LanguageId = LangNlId,
|
||||
RootContentId =10031
|
||||
RootContentId =10031,
|
||||
LanguageIsoCode = "nl-NL"
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -343,19 +355,22 @@ namespace Umbraco.Tests.Routing
|
||||
{
|
||||
Id = 1,
|
||||
LanguageId = LangEngId,
|
||||
RootContentId = 1001
|
||||
RootContentId = 1001,
|
||||
LanguageIsoCode = "en-US"
|
||||
},
|
||||
new UmbracoDomain("domain1.fr/")
|
||||
{
|
||||
Id = 1,
|
||||
LanguageId = LangFrId,
|
||||
RootContentId = 1001
|
||||
RootContentId = 1001,
|
||||
LanguageIsoCode = "fr-FR"
|
||||
},
|
||||
new UmbracoDomain("*100112")
|
||||
{
|
||||
Id = 1,
|
||||
LanguageId = LangDeId,
|
||||
RootContentId = 100112
|
||||
RootContentId = 100112,
|
||||
LanguageIsoCode = "de-DE"
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Umbraco.Tests.Routing
|
||||
|
||||
SetupDomainServiceMock(new[]
|
||||
{
|
||||
new UmbracoDomain("domain1.com") {Id = 1, LanguageId = LangFrId, RootContentId = 1001}
|
||||
new UmbracoDomain("domain1.com") {Id = 1, LanguageId = LangFrId, RootContentId = 1001, LanguageIsoCode = "fr-FR"}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Umbraco.Tests.Routing
|
||||
{
|
||||
SetupDomainServiceMock(new[]
|
||||
{
|
||||
new UmbracoDomain("http://domain1.com/foo") {Id = 1, LanguageId = LangFrId, RootContentId = 1001}
|
||||
new UmbracoDomain("http://domain1.com/foo") {Id = 1, LanguageId = LangFrId, RootContentId = 1001, LanguageIsoCode = "fr-FR"}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Umbraco.Tests.Routing
|
||||
{
|
||||
SetupDomainServiceMock(new[]
|
||||
{
|
||||
new UmbracoDomain("http://domain1.com/") {Id = 1, LanguageId = LangFrId, RootContentId = 10011}
|
||||
new UmbracoDomain("http://domain1.com/") {Id = 1, LanguageId = LangFrId, RootContentId = 10011, LanguageIsoCode = "fr-FR"}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -52,12 +52,12 @@ namespace Umbraco.Tests.Routing
|
||||
{
|
||||
SetupDomainServiceMock(new[]
|
||||
{
|
||||
new UmbracoDomain("http://domain1.com/") {Id = 1, LanguageId = LangEngId, RootContentId = 1001},
|
||||
new UmbracoDomain("http://domain1.com/en") {Id = 1, LanguageId = LangEngId, RootContentId = 10011},
|
||||
new UmbracoDomain("http://domain1.com/fr") {Id = 1, LanguageId = LangFrId, RootContentId = 10012},
|
||||
new UmbracoDomain("http://domain3.com/") {Id = 1, LanguageId = LangEngId, RootContentId = 1003},
|
||||
new UmbracoDomain("http://domain3.com/en") {Id = 1, LanguageId = LangEngId, RootContentId = 10031},
|
||||
new UmbracoDomain("http://domain3.com/fr") {Id = 1, LanguageId = LangFrId, RootContentId = 10032}
|
||||
new UmbracoDomain("http://domain1.com/") {Id = 1, LanguageId = LangEngId, RootContentId = 1001, LanguageIsoCode = "en-US"},
|
||||
new UmbracoDomain("http://domain1.com/en") {Id = 1, LanguageId = LangEngId, RootContentId = 10011, LanguageIsoCode = "en-US"},
|
||||
new UmbracoDomain("http://domain1.com/fr") {Id = 1, LanguageId = LangFrId, RootContentId = 10012, LanguageIsoCode = "fr-FR"},
|
||||
new UmbracoDomain("http://domain3.com/") {Id = 1, LanguageId = LangEngId, RootContentId = 1003, LanguageIsoCode = "en-US"},
|
||||
new UmbracoDomain("http://domain3.com/en") {Id = 1, LanguageId = LangEngId, RootContentId = 10031, LanguageIsoCode = "en-US"},
|
||||
new UmbracoDomain("http://domain3.com/fr") {Id = 1, LanguageId = LangFrId, RootContentId = 10032, LanguageIsoCode = "fr-FR"}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -65,14 +65,14 @@ namespace Umbraco.Tests.Routing
|
||||
{
|
||||
SetupDomainServiceMock(new[]
|
||||
{
|
||||
new UmbracoDomain("http://domain1.com/en") {Id = 1, LanguageId = LangEngId, RootContentId = 10011},
|
||||
new UmbracoDomain("http://domain1a.com/en") {Id = 1, LanguageId = LangEngId, RootContentId = 10011},
|
||||
new UmbracoDomain("http://domain1b.com/en") {Id = 1, LanguageId = LangEngId, RootContentId = 10011},
|
||||
new UmbracoDomain("http://domain1.com/fr") {Id = 1, LanguageId = LangFrId, RootContentId = 10012},
|
||||
new UmbracoDomain("http://domain1a.com/fr") {Id = 1, LanguageId = LangFrId, RootContentId = 10012},
|
||||
new UmbracoDomain("http://domain1b.com/fr") {Id = 1, LanguageId = LangFrId, RootContentId = 10012},
|
||||
new UmbracoDomain("http://domain3.com/en") {Id = 1, LanguageId = LangEngId, RootContentId = 10031},
|
||||
new UmbracoDomain("http://domain3.com/fr") {Id = 1, LanguageId = LangFrId, RootContentId = 10032}
|
||||
new UmbracoDomain("http://domain1.com/en") {Id = 1, LanguageId = LangEngId, RootContentId = 10011, LanguageIsoCode = "en-US"},
|
||||
new UmbracoDomain("http://domain1a.com/en") {Id = 1, LanguageId = LangEngId, RootContentId = 10011, LanguageIsoCode = "en-US"},
|
||||
new UmbracoDomain("http://domain1b.com/en") {Id = 1, LanguageId = LangEngId, RootContentId = 10011, LanguageIsoCode = "en-US"},
|
||||
new UmbracoDomain("http://domain1.com/fr") {Id = 1, LanguageId = LangFrId, RootContentId = 10012, LanguageIsoCode = "fr-FR"},
|
||||
new UmbracoDomain("http://domain1a.com/fr") {Id = 1, LanguageId = LangFrId, RootContentId = 10012, LanguageIsoCode = "fr-FR"},
|
||||
new UmbracoDomain("http://domain1b.com/fr") {Id = 1, LanguageId = LangFrId, RootContentId = 10012, LanguageIsoCode = "fr-FR"},
|
||||
new UmbracoDomain("http://domain3.com/en") {Id = 1, LanguageId = LangEngId, RootContentId = 10031, LanguageIsoCode = "en-US"},
|
||||
new UmbracoDomain("http://domain3.com/fr") {Id = 1, LanguageId = LangFrId, RootContentId = 10032, LanguageIsoCode = "fr-FR"}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -42,19 +42,10 @@ namespace Umbraco.Tests.Routing
|
||||
domainService.Setup(service => service.GetAll(It.IsAny<bool>()))
|
||||
.Returns((bool incWildcards) => new[]
|
||||
{
|
||||
new UmbracoDomain("domain1.com/"){Id = 1, LanguageId = 333, RootContentId = 1001},
|
||||
new UmbracoDomain("domain1.com/en"){Id = 1, LanguageId = 334, RootContentId = 10011},
|
||||
new UmbracoDomain("domain1.com/fr"){Id = 1, LanguageId = 335, RootContentId = 10012}
|
||||
});
|
||||
|
||||
var langService = Mock.Get(svcCtx.LocalizationService);
|
||||
//setup mock domain service
|
||||
langService.Setup(service => service.GetLanguageById(LangDeId)).Returns(new Language("de-DE") {Id = LangDeId });
|
||||
langService.Setup(service => service.GetLanguageById(LangEngId)).Returns(new Language("en-US") { Id = LangEngId });
|
||||
langService.Setup(service => service.GetLanguageById(LangFrId)).Returns(new Language("fr-FR") { Id = LangFrId });
|
||||
langService.Setup(service => service.GetLanguageById(LangCzId)).Returns(new Language("cs-CZ") { Id = LangCzId });
|
||||
langService.Setup(service => service.GetLanguageById(LangNlId)).Returns(new Language("nl-NL") { Id = LangNlId });
|
||||
langService.Setup(service => service.GetLanguageById(LangDkId)).Returns(new Language("da-DK") { Id = LangDkId });
|
||||
new UmbracoDomain("domain1.com/"){Id = 1, LanguageId = LangDeId, RootContentId = 1001, LanguageIsoCode = "de-DE"},
|
||||
new UmbracoDomain("domain1.com/en"){Id = 1, LanguageId = LangEngId, RootContentId = 10011, LanguageIsoCode = "en-US"},
|
||||
new UmbracoDomain("domain1.com/fr"){Id = 1, LanguageId = LangFrId, RootContentId = 10012, LanguageIsoCode = "fr-FR"}
|
||||
});
|
||||
|
||||
return svcCtx;
|
||||
}
|
||||
|
||||
@@ -80,8 +80,8 @@ namespace Umbraco.Tests.Routing
|
||||
{
|
||||
SetupDomainServiceMock(new[]
|
||||
{
|
||||
new UmbracoDomain("http://domain1.com/") {Id = 1, LanguageId = LangEngId, RootContentId = 1001},
|
||||
new UmbracoDomain("http://domain2.com/") {Id = 1, LanguageId = LangEngId, RootContentId = 10011}
|
||||
new UmbracoDomain("http://domain1.com/") {Id = 1, LanguageId = LangEngId, RootContentId = 1001, LanguageIsoCode = "en-US"},
|
||||
new UmbracoDomain("http://domain2.com/") {Id = 1, LanguageId = LangEngId, RootContentId = 10011, LanguageIsoCode = "en-US"}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@@ -24,6 +24,18 @@ namespace Umbraco.Tests.Strings
|
||||
ShortStringHelperResolver.Reset();
|
||||
}
|
||||
|
||||
[TestCase("hello", "world", false)]
|
||||
[TestCase("hello", "hello", true)]
|
||||
[TestCase("hellohellohellohellohellohellohello", "hellohellohellohellohellohellohelloo", false)]
|
||||
[TestCase("hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello", "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohelloo", false)]
|
||||
[TestCase("hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello", "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello", true)]
|
||||
public void String_To_Guid(string first, string second, bool result)
|
||||
{
|
||||
Console.WriteLine("First: " + first.ToGuid());
|
||||
Console.WriteLine("Second: " + second.ToGuid());
|
||||
Assert.AreEqual(result, first.ToGuid() == second.ToGuid());
|
||||
}
|
||||
|
||||
[TestCase("alert('hello');", false)]
|
||||
[TestCase("~/Test.js", true)]
|
||||
[TestCase("../Test.js", true)]
|
||||
|
||||
@@ -51,16 +51,16 @@
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="AutoMapper, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.dll</HintPath>
|
||||
<Reference Include="AutoMapper, Version=3.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\AutoMapper.3.0.0\lib\net40\AutoMapper.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="AutoMapper.Net4, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
|
||||
<Reference Include="AutoMapper.Net4, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\AutoMapper.3.0.0\lib\net40\AutoMapper.Net4.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Examine, Version=0.1.66.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.66.0\lib\Examine.dll</HintPath>
|
||||
<Reference Include="Examine, Version=0.1.68.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.68.0\lib\Examine.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
|
||||
@@ -176,6 +176,7 @@
|
||||
<Compile Include="Cache\CacheRefresherTests.cs" />
|
||||
<Compile Include="Cache\DeepCloneRuntimeCacheProviderTests.cs" />
|
||||
<Compile Include="Controllers\BackOfficeControllerUnitTests.cs" />
|
||||
<Compile Include="DelegateExtensionsTests.cs" />
|
||||
<Compile Include="Logging\AsyncRollingFileAppenderTest.cs" />
|
||||
<Compile Include="Logging\DebugAppender.cs" />
|
||||
<Compile Include="Logging\ParallelForwarderTest.cs" />
|
||||
@@ -730,7 +731,6 @@
|
||||
xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.0\x86\*.* "$(TargetDir)x86\" /Y /F /E /D</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
|
||||
<Import Project="..\packages\AutoMapper.3.3.1\tools\AutoMapper.targets" Condition="Exists('..\packages\AutoMapper.3.3.1\tools\AutoMapper.targets')" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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.66.0" targetFramework="net45" />
|
||||
<package id="AutoMapper" version="3.0.0" targetFramework="net45" />
|
||||
<package id="Examine" version="0.1.68.0" targetFramework="net45" />
|
||||
<package id="log4net-mediumtrust" version="2.0.0" targetFramework="net45" />
|
||||
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
|
||||
<package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net45" />
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
"jquery-ui": "1.10.3",
|
||||
"angular-dynamic-locale": "~0.1.27",
|
||||
"tinymce": "~4.1.10",
|
||||
"bootstrap-tabdrop": "~1.0.0",
|
||||
"codemirror": "~5.3.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -418,7 +418,8 @@ module.exports = function (grunt) {
|
||||
ignorePackages: ['blueimp-canvas-to-blob', 'blueimp-tmpl', 'bootstrap'],
|
||||
packageSpecific: {
|
||||
'typeahead.js': {
|
||||
keepExpandedHierarchy: false
|
||||
keepExpandedHierarchy: false,
|
||||
files: ['dist/typeahead.bundle.min.js']
|
||||
},
|
||||
'underscore': {
|
||||
files: ['underscore-min.js', 'underscore-min.map']
|
||||
@@ -455,11 +456,7 @@ module.exports = function (grunt) {
|
||||
},
|
||||
'angular-dynamic-locale': {
|
||||
files: ['tmhDynamicLocale.min.js', 'tmhDynamicLocale.min.js.map']
|
||||
},
|
||||
'bootstrap-tabdrop': {
|
||||
keepExpandedHierarchy: false,
|
||||
files: ['build/js/bootstrap-tabdrop.min.js']
|
||||
},
|
||||
},
|
||||
'codemirror': {
|
||||
files: [
|
||||
'lib/codemirror.js',
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
bootstrap-tabdrop
|
||||
=================
|
||||
|
||||
*****************************************************************
|
||||
NOTE: THIS IS A CUSTOM FIXED VERSION!!!!!!!!!!!!!!!!!!!!!!
|
||||
- THE ORIGINAL HAS A MEMORY LEAK, SO WE'VE HAD TO EMBED THIS
|
||||
INTO THE CORE WITH THE FIX
|
||||
|
||||
--- UMBRACO CORE TEAM
|
||||
*****************************************************************
|
||||
|
||||
A dropdown tab tool for @twitter bootstrap forked from Stefan Petre's (of eyecon.ro),
|
||||
|
||||
The dropdown tab appears when your tabs do not all fit in the same row.
|
||||
|
||||
Original site and examples: http://www.eyecon.ro/bootstrap-tabdrop/
|
||||
|
||||
Added functionality: Displays the text of an active tab selected from the dropdown list instead of the text option on the dropdown tab.
|
||||
|
||||
|
||||
## Requirements
|
||||
|
||||
* [Bootstrap](http://twitter.github.com/bootstrap/) 2.0.4+
|
||||
* [jQuery](http://jquery.com/) 1.7.1+
|
||||
|
||||
## Example
|
||||
|
||||
No additional HTML needed - the script adds it when the dropdown tab is needed.
|
||||
|
||||
Using bootstrap-tabdrop.js
|
||||
Call the tab drop via javascript on .nav-tabs and .nav-pills:
|
||||
```js
|
||||
$('.nav-pills, .nav-tabs').tabdrop()
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
#### text
|
||||
Type: string
|
||||
Default: icon
|
||||
```html
|
||||
<i class="icon-align-justify"></i>
|
||||
```
|
||||
To change the default value, call
|
||||
```javascript
|
||||
.tabdrop({text: "your text here"});
|
||||
```
|
||||
when initalizing the tabdrop. The displayed value will change when a tab is selected from the dropdown list.
|
||||
|
||||
### Methods
|
||||
|
||||
```js
|
||||
.tabdrop(options)
|
||||
```
|
||||
|
||||
Initializes an tab drop.
|
||||
|
||||
```js
|
||||
.tabdrop('layout')
|
||||
```
|
||||
|
||||
Checks if the tabs fit in one single row.
|
||||
@@ -0,0 +1,132 @@
|
||||
/* =========================================================
|
||||
* bootstrap-tabdrop.js
|
||||
* http://www.eyecon.ro/bootstrap-tabdrop
|
||||
* =========================================================
|
||||
* Copyright 2012 Stefan Petre
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ========================================================= */
|
||||
|
||||
/*****************************************************************
|
||||
* NOTE: THIS IS A CUSTOM FIXED VERSION!!!!!!!!!!!!!!!!!!!!!!
|
||||
* - THE ORIGINAL HAS A MEMORY LEAK, SO WE'VE HAD TO EMBED THIS
|
||||
* INTO THE CORE WITH THE FIX
|
||||
*
|
||||
* --- UMBRACO CORE TEAM
|
||||
*****************************************************************/
|
||||
|
||||
!function( $ ) {
|
||||
|
||||
var WinReszier = (function(){
|
||||
var registered = [];
|
||||
var inited = false;
|
||||
var timer;
|
||||
var resize = function(ev) {
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(notify, 100);
|
||||
};
|
||||
var notify = function() {
|
||||
for(var i=0, cnt=registered.length; i<cnt; i++) {
|
||||
registered[i].apply();
|
||||
}
|
||||
};
|
||||
return {
|
||||
register: function(fn) {
|
||||
registered.push(fn);
|
||||
if (inited === false) {
|
||||
$(window).bind('resize', resize);
|
||||
inited = true;
|
||||
}
|
||||
},
|
||||
unregister: function(fn) {
|
||||
var index = registered.indexOf(fn);
|
||||
if (index > -1) {
|
||||
registered.splice(index, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
}());
|
||||
|
||||
var TabDrop = function(element, options) {
|
||||
this.element = $(element);
|
||||
this.dropdown = $('<li class="dropdown hide pull-right tabdrop">' +
|
||||
'<a class="dropdown-toggle" data-toggle="dropdown" href="#">' +
|
||||
options.text + ' <b class="caret"></b></a>' +
|
||||
'<ul class="dropdown-menu"></ul></li>').prependTo(this.element);
|
||||
if (this.element.parent().is('.tabs-below')) {
|
||||
this.dropdown.addClass('dropup');
|
||||
}
|
||||
this.resizeCallback = $.proxy(this.layout, this);
|
||||
WinReszier.register(this.resizeCallback);
|
||||
this.layout();
|
||||
};
|
||||
|
||||
TabDrop.prototype = {
|
||||
constructor: TabDrop,
|
||||
|
||||
layout: function() {
|
||||
var collection = [];
|
||||
this.dropdown.removeClass('hide');
|
||||
this.element
|
||||
.append(this.dropdown.find('li'))
|
||||
.find('>li')
|
||||
.not('.tabdrop')
|
||||
.each(function(){
|
||||
if(this.offsetTop > 0) {
|
||||
collection.push(this);
|
||||
}
|
||||
});
|
||||
if (collection.length > 0) {
|
||||
collection = $(collection);
|
||||
this.dropdown
|
||||
.find('ul')
|
||||
.empty()
|
||||
.append(collection);
|
||||
if (this.dropdown.find('.active').length == 1) {
|
||||
this.dropdown.addClass('active');
|
||||
} else {
|
||||
this.dropdown.removeClass('active');
|
||||
}
|
||||
} else {
|
||||
this.dropdown.addClass('hide');
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.dropdown.html();
|
||||
WinReszier.unregister(this.resizeCallback);
|
||||
}
|
||||
};
|
||||
|
||||
$.fn.tabdrop = function ( option ) {
|
||||
return this.each(function () {
|
||||
var $this = $(this),
|
||||
data = $this.data('tabdrop'),
|
||||
options = typeof option === 'object' && option;
|
||||
if (!data) {
|
||||
$this.data('tabdrop', (data = new TabDrop(this, $.extend({},
|
||||
$.fn.tabdrop.defaults,options))));
|
||||
}
|
||||
if (typeof option == 'string') {
|
||||
data[option]();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$.fn.tabdrop.defaults = {
|
||||
text: '<i class="icon-align-justify"></i>'
|
||||
};
|
||||
|
||||
$.fn.tabdrop.Constructor = TabDrop;
|
||||
|
||||
}(window.jQuery);
|
||||
+35
-26
@@ -1,32 +1,41 @@
|
||||
angular.module("umbraco.directives")
|
||||
.directive('umbAutoResize', function($timeout) {
|
||||
return {
|
||||
require: "^?umbTabs",
|
||||
link: function(scope, element, attr, tabsCtrl) {
|
||||
var domEl = element[0];
|
||||
var update = function(force) {
|
||||
if (force === true) {
|
||||
element.height(0);
|
||||
}
|
||||
|
||||
return function(scope, element, attr){
|
||||
var domEl = element[0];
|
||||
var update = function(force) {
|
||||
if (domEl.scrollHeight !== domEl.clientHeight) {
|
||||
element.height(domEl.scrollHeight);
|
||||
}
|
||||
};
|
||||
var blur = function() {
|
||||
update(true);
|
||||
};
|
||||
|
||||
if(force === true){
|
||||
element.height(0);
|
||||
element.bind('keyup keydown keypress change', update);
|
||||
element.bind('blur', blur);
|
||||
|
||||
$timeout(function() {
|
||||
update(true);
|
||||
}, 200);
|
||||
|
||||
|
||||
//listen for tab changes
|
||||
if (tabsCtrl != null) {
|
||||
tabsCtrl.onTabShown(function(args) {
|
||||
update();
|
||||
});
|
||||
}
|
||||
|
||||
if(domEl.scrollHeight !== domEl.clientHeight){
|
||||
element.height(domEl.scrollHeight);
|
||||
}
|
||||
};
|
||||
|
||||
element.bind('keyup keydown keypress change', update);
|
||||
element.bind('blur', function(){ update(true); });
|
||||
|
||||
$timeout(function() {
|
||||
update(true);
|
||||
}, 200);
|
||||
|
||||
|
||||
//I hate bootstrap tabs
|
||||
$('a[data-toggle="tab"]').on('shown', update);
|
||||
|
||||
scope.$on('$destroy', function() {
|
||||
$('a[data-toggle="tab"]').unbind("shown", update);
|
||||
});
|
||||
};
|
||||
});
|
||||
scope.$on('$destroy', function () {
|
||||
element.unbind('keyup keydown keypress change', update);
|
||||
element.unbind('blur', blur);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbHeader
|
||||
* @restrict E
|
||||
* @function
|
||||
* @description
|
||||
* The header on an editor that contains tabs using bootstrap tabs - THIS IS OBSOLETE, use umbTabHeader instead
|
||||
**/
|
||||
angular.module("umbraco.directives")
|
||||
.directive('umbHeader', function($parse, $timeout){
|
||||
.directive('umbHeader', function ($parse, $timeout) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
@@ -11,50 +19,13 @@ angular.module("umbraco.directives")
|
||||
tabs: "="
|
||||
},
|
||||
link: function (scope, iElement, iAttrs) {
|
||||
|
||||
var maxTabs = 4;
|
||||
|
||||
function collectFromDom(activeTab){
|
||||
var $panes = $('div.tab-content');
|
||||
|
||||
angular.forEach($panes.find('.tab-pane'), function (pane, index) {
|
||||
var $this = angular.element(pane);
|
||||
|
||||
var id = $this.attr("rel");
|
||||
var label = $this.attr("label");
|
||||
var tab = {id: id, label: label, active: false};
|
||||
if(!activeTab){
|
||||
tab.active = true;
|
||||
activeTab = tab;
|
||||
}
|
||||
|
||||
if ($this.attr("rel") === String(activeTab.id)) {
|
||||
$this.addClass('active');
|
||||
}
|
||||
else {
|
||||
$this.removeClass('active');
|
||||
}
|
||||
|
||||
if(label){
|
||||
scope.visibleTabs.push(tab);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
$('.nav-pills, .nav-tabs').tabdrop();
|
||||
}
|
||||
|
||||
|
||||
scope.showTabs = iAttrs.tabs ? true : false;
|
||||
scope.visibleTabs = [];
|
||||
scope.overflownTabs = [];
|
||||
|
||||
$timeout(function () {
|
||||
collectFromDom(undefined);
|
||||
}, 500);
|
||||
|
||||
//when the tabs change, we need to hack the planet a bit and force the first tab content to be active,
|
||||
//unfortunately twitter bootstrap tabs is not playing perfectly with angular.
|
||||
scope.$watch("tabs", function (newValue, oldValue) {
|
||||
//since tabs are loaded async, we need to put a watch on them to determine
|
||||
// when they are loaded, then we can close the watch
|
||||
var tabWatch = scope.$watch("tabs", function (newValue, oldValue) {
|
||||
|
||||
angular.forEach(newValue, function(val, index){
|
||||
var tab = {id: val.id, label: val.label};
|
||||
@@ -64,16 +35,25 @@ angular.module("umbraco.directives")
|
||||
//don't process if we cannot or have already done so
|
||||
if (!newValue) {return;}
|
||||
if (!newValue.length || newValue.length === 0){return;}
|
||||
|
||||
var activeTab = _.find(newValue, function (item) {
|
||||
return item.active;
|
||||
});
|
||||
|
||||
|
||||
//we need to do a timeout here so that the current sync operation can complete
|
||||
// and update the UI, then this will fire and the UI elements will be available.
|
||||
$timeout(function () {
|
||||
collectFromDom(activeTab);
|
||||
}, 500);
|
||||
|
||||
//use bootstrap tabs API to show the first one
|
||||
iElement.find(".nav-tabs a:first").tab('show');
|
||||
|
||||
//enable the tab drop
|
||||
iElement.find('.nav-pills, .nav-tabs').tabdrop();
|
||||
|
||||
//ensure to destroy tabdrop (unbinds window resize listeners)
|
||||
scope.$on('$destroy', function () {
|
||||
iElement.find('.nav-pills, .nav-tabs').tabdrop("destroy");
|
||||
});
|
||||
|
||||
//stop watching now
|
||||
tabWatch();
|
||||
}, 200);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
* @restrict E
|
||||
**/
|
||||
angular.module("umbraco.directives")
|
||||
.directive('umbTab', function(){
|
||||
return {
|
||||
.directive('umbTab', function ($parse, $timeout) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
transclude: 'true',
|
||||
templateUrl: 'views/directives/umb-tab.html'
|
||||
};
|
||||
replace: true,
|
||||
transclude: 'true',
|
||||
templateUrl: 'views/directives/umb-tab.html'
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbTabs
|
||||
* @restrict A
|
||||
* @description Used to bind to bootstrap tab events so that sub directives can use this API to listen to tab changes
|
||||
**/
|
||||
angular.module("umbraco.directives")
|
||||
.directive('umbTabs', function () {
|
||||
return {
|
||||
restrict: 'A',
|
||||
controller: function ($scope, $element, $attrs) {
|
||||
|
||||
var callbacks = [];
|
||||
this.onTabShown = function(cb) {
|
||||
callbacks.push(cb);
|
||||
};
|
||||
|
||||
function tabShown(event) {
|
||||
|
||||
var curr = $(event.target); // active tab
|
||||
var prev = $(event.relatedTarget); // previous tab
|
||||
|
||||
for (var c in callbacks) {
|
||||
callbacks[c].apply(this, [{current: curr, previous: prev}]);
|
||||
}
|
||||
}
|
||||
|
||||
//NOTE: it MUST be done this way - binding to an ancestor element that exists
|
||||
// in the DOM to bind to the dynamic elements that will be created.
|
||||
// It would be nicer to create this event handler as a directive for which child
|
||||
// directives can attach to.
|
||||
$element.on('shown', '.nav-tabs a', tabShown);
|
||||
|
||||
//ensure to unregister
|
||||
$scope.$on('$destroy', function () {
|
||||
$element.off('shown', '.nav-tabs a', tabShown);
|
||||
|
||||
for (var c in callbacks) {
|
||||
delete callbacks[c];
|
||||
}
|
||||
callbacks = null;
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -7,7 +7,7 @@
|
||||
* Handles how the navigation responds to window resizing and controls how the draggable resize panel works
|
||||
**/
|
||||
angular.module("umbraco.directives")
|
||||
.directive('navResize', function (appState, eventsService) {
|
||||
.directive('navResize', function (appState, eventsService, windowResizeListener) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function (scope, element, attrs, ctrl) {
|
||||
@@ -22,22 +22,28 @@ angular.module("umbraco.directives")
|
||||
function enableResize() {
|
||||
//only enable when the size is correct and it's not already enabled
|
||||
if (!resizeEnabled && appState.getGlobalState("isTablet") === false) {
|
||||
element.find(".navigation-inner-container").resizable(
|
||||
element.resizable(
|
||||
{
|
||||
containment: $("#mainwrapper"),
|
||||
autoHide: true,
|
||||
handles: 'e',
|
||||
handles: "e",
|
||||
alsoResize: ".navigation-inner-container",
|
||||
resize: function(e, ui) {
|
||||
var wrapper = $("#mainwrapper");
|
||||
var contentPanel = $("#leftcolumn").next();
|
||||
var contentPanel = $("#contentwrapper");
|
||||
var apps = $("#applications");
|
||||
var navOffeset = ui.element.next();
|
||||
var bottomBar = contentPanel.find(".umb-bottom-bar");
|
||||
var navOffeset = $("#navOffset");
|
||||
|
||||
var leftPanelWidth = ui.element.width() + apps.width();
|
||||
|
||||
contentPanel.css({ left: leftPanelWidth });
|
||||
bottomBar.css({ left: leftPanelWidth });
|
||||
|
||||
navOffeset.css({ "margin-left": ui.element.outerWidth() });
|
||||
},
|
||||
stop: function(e, ui) {
|
||||
stop: function (e, ui) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
@@ -47,14 +53,14 @@ angular.module("umbraco.directives")
|
||||
|
||||
function resetResize() {
|
||||
if (resizeEnabled) {
|
||||
var navInnerContainer = element.find(".navigation-inner-container");
|
||||
|
||||
//kill the resize
|
||||
navInnerContainer.resizable("destroy");
|
||||
element.resizable("destroy");
|
||||
|
||||
element.css("width", "");
|
||||
var navInnerContainer = element.find(".navigation-inner-container");
|
||||
navInnerContainer.css("width", "");
|
||||
$("#leftcolumn").next().css("left", "");
|
||||
navInnerContainer.next().css("margin-left", "");
|
||||
$("#contentwrapper").css("left", "");
|
||||
$("#navOffset").css("margin-left", "");
|
||||
|
||||
resizeEnabled = false;
|
||||
}
|
||||
@@ -74,16 +80,17 @@ angular.module("umbraco.directives")
|
||||
}
|
||||
}));
|
||||
|
||||
$(window).bind("resize", function () {
|
||||
|
||||
var resizeCallback = function(size) {
|
||||
//set the global app state
|
||||
appState.setGlobalState("isTablet", ($(window).width() <= minScreenSize));
|
||||
|
||||
appState.setGlobalState("isTablet", (size.width <= minScreenSize));
|
||||
setTreeMode();
|
||||
});
|
||||
};
|
||||
|
||||
windowResizeListener.register(resizeCallback);
|
||||
|
||||
//ensure to unregister from all events and kill jquery plugins
|
||||
scope.$on('$destroy', function () {
|
||||
windowResizeListener.unregister(resizeCallback);
|
||||
for (var e in evts) {
|
||||
eventsService.unsubscribe(evts[e]);
|
||||
}
|
||||
@@ -91,7 +98,6 @@ angular.module("umbraco.directives")
|
||||
navInnerContainer.resizable("destroy");
|
||||
});
|
||||
|
||||
|
||||
//init
|
||||
//set the global app state
|
||||
appState.setGlobalState("isTablet", ($(window).width() <= minScreenSize));
|
||||
|
||||
@@ -86,7 +86,7 @@ angular.module("umbraco.directives")
|
||||
icon.addClass(node.cssClass);
|
||||
icon.attr("title", node.routePath);
|
||||
|
||||
element.find("a:first").html(node.name);
|
||||
element.find("a:first").text(node.name);
|
||||
|
||||
if (!node.menuUrl) {
|
||||
element.find("a.umb-options").remove();
|
||||
|
||||
+17
-7
@@ -5,21 +5,31 @@ angular.module("umbraco.directives")
|
||||
link: function (scope, element, attrs, ctrl) {
|
||||
var active = false;
|
||||
var fn = $parse(attrs.delayedMouseleave);
|
||||
element.on("mouseleave", function(event) {
|
||||
var callback = function() {
|
||||
fn(scope, {$event:event});
|
||||
|
||||
function mouseLeave(event) {
|
||||
var callback = function () {
|
||||
fn(scope, { $event: event });
|
||||
};
|
||||
|
||||
active = false;
|
||||
$timeout(function(){
|
||||
if(active === false){
|
||||
$timeout(function () {
|
||||
if (active === false) {
|
||||
scope.$apply(callback);
|
||||
}
|
||||
}, 650);
|
||||
});
|
||||
}
|
||||
|
||||
element.on("mouseenter", function(event, args){
|
||||
function mouseEnter(event, args){
|
||||
active = true;
|
||||
}
|
||||
|
||||
element.on("mouseleave", mouseLeave);
|
||||
element.on("mouseenter", mouseEnter);
|
||||
|
||||
//unbind!!
|
||||
scope.$on('$destroy', function () {
|
||||
element.off("mouseleave", mouseLeave);
|
||||
element.off("mouseenter", mouseEnter);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,49 +1,80 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbPanel
|
||||
* @restrict E
|
||||
* @description This is used for the editor buttons to ensure they are displayed correctly if the horizontal overflow of the editor
|
||||
* exceeds the height of the window
|
||||
**/
|
||||
angular.module("umbraco.directives.html")
|
||||
.directive('detectFold', function($timeout, $log){
|
||||
return {
|
||||
.directive('detectFold', function ($timeout, $log, windowResizeListener) {
|
||||
return {
|
||||
require: "^?umbTabs",
|
||||
restrict: 'A',
|
||||
link: function (scope, el, attrs) {
|
||||
|
||||
var state = false,
|
||||
parent = $(".umb-panel-body"),
|
||||
winHeight = $(window).height(),
|
||||
calculate = _.throttle(function(){
|
||||
if(el && el.is(":visible") && !el.hasClass("umb-bottom-bar")){
|
||||
//var parent = el.parent();
|
||||
var hasOverflow = parent.innerHeight() < parent[0].scrollHeight;
|
||||
//var belowFold = (el.offset().top + el.height()) > winHeight;
|
||||
if(hasOverflow){
|
||||
el.addClass("umb-bottom-bar");
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}, 1000);
|
||||
link: function (scope, el, attrs, tabsCtrl) {
|
||||
|
||||
scope.$watch(calculate, function(newVal, oldVal) {
|
||||
if(newVal !== oldVal){
|
||||
if(newVal){
|
||||
el.addClass("umb-bottom-bar");
|
||||
}else{
|
||||
el.removeClass("umb-bottom-bar");
|
||||
}
|
||||
}
|
||||
});
|
||||
var firstRun = false;
|
||||
var parent = $(".umb-panel-body");
|
||||
var winHeight = $(window).height();
|
||||
var calculate = function () {
|
||||
if (el && el.is(":visible") && !el.hasClass("umb-bottom-bar")) {
|
||||
|
||||
$(window).bind("resize", function () {
|
||||
winHeight = $(window).height();
|
||||
el.removeClass("umb-bottom-bar");
|
||||
state = false;
|
||||
calculate();
|
||||
});
|
||||
//now that the element is visible, set the flag in a couple of seconds,
|
||||
// this will ensure that loading time of a current tab get's completed and that
|
||||
// we eventually stop watching to save on CPU time
|
||||
$timeout(function() {
|
||||
firstRun = true;
|
||||
}, 4000);
|
||||
|
||||
$('a[data-toggle="tab"]').on('shown', function (e) {
|
||||
calculate();
|
||||
});
|
||||
//var parent = el.parent();
|
||||
var hasOverflow = parent.innerHeight() < parent[0].scrollHeight;
|
||||
//var belowFold = (el.offset().top + el.height()) > winHeight;
|
||||
if (hasOverflow) {
|
||||
el.addClass("umb-bottom-bar");
|
||||
|
||||
//I wish we didn't have to put this logic here but unfortunately we
|
||||
// do. This needs to calculate the left offest to place the bottom bar
|
||||
// depending on if the left column splitter has been moved by the user
|
||||
// (based on the nav-resize directive)
|
||||
var wrapper = $("#mainwrapper");
|
||||
var contentPanel = $("#leftcolumn").next();
|
||||
var contentPanelLeftPx = contentPanel.css("left");
|
||||
|
||||
el.css({ left: contentPanelLeftPx });
|
||||
}
|
||||
}
|
||||
return firstRun;
|
||||
};
|
||||
|
||||
var resizeCallback = function(size) {
|
||||
winHeight = size.height;
|
||||
el.removeClass("umb-bottom-bar");
|
||||
calculate();
|
||||
};
|
||||
|
||||
windowResizeListener.register(resizeCallback);
|
||||
|
||||
//Only execute the watcher if this tab is the active (first) tab on load, otherwise there's no reason to execute
|
||||
// the watcher since it will be recalculated when the tab changes!
|
||||
if (el.closest(".umb-tab-pane").index() === 0) {
|
||||
//run a watcher to ensure that the calculation occurs until it's firstRun but ensure
|
||||
// the calculations are throttled to save a bit of CPU
|
||||
var listener = scope.$watch(_.throttle(calculate, 1000), function (newVal, oldVal) {
|
||||
if (newVal !== oldVal) {
|
||||
listener();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//listen for tab changes
|
||||
if (tabsCtrl != null) {
|
||||
tabsCtrl.onTabShown(function (args) {
|
||||
calculate();
|
||||
});
|
||||
}
|
||||
|
||||
//ensure to unregister
|
||||
scope.$on('$destroy', function() {
|
||||
windowResizeListener.unregister(resizeCallback);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -242,18 +242,19 @@ angular.module('umbraco.services')
|
||||
|
||||
_.each(assets, function (asset) {
|
||||
LazyLoad.js(appendRnd(asset.path), function () {
|
||||
asset.state = "loaded";
|
||||
if (!scope) {
|
||||
asset.state = "loaded";
|
||||
asset.deferred.resolve(true);
|
||||
} else {
|
||||
asset.state = "loaded";
|
||||
}
|
||||
else {
|
||||
angularHelper.safeApply(scope, function () {
|
||||
asset.deferred.resolve(true);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
//return and resolve
|
||||
var deferred = $q.defer();
|
||||
promise = deferred.promise;
|
||||
|
||||
@@ -55,6 +55,12 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
||||
err: err,
|
||||
rebindCallback: self.reBindChangedProperties(args.content, err.data)
|
||||
});
|
||||
//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]);
|
||||
}
|
||||
}
|
||||
args.scope.busy = false;
|
||||
deferred.reject(err);
|
||||
});
|
||||
@@ -466,13 +472,13 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
||||
* @description
|
||||
* Changes the location to be editing the newly created content after create was successful.
|
||||
* We need to decide if we need to redirect to edito mode or if we will remain in create mode.
|
||||
* We will only need to maintain create mode if we have not fulfilled the basic requirements for creating an entity which is at least having a name.
|
||||
* We will only need to maintain create mode if we have not fulfilled the basic requirements for creating an entity which is at least having a name and ID
|
||||
*/
|
||||
redirectToCreatedContent: function (id, modelState) {
|
||||
|
||||
//only continue if we are currently in create mode and if there is no 'Name' modelstate errors
|
||||
// since we need at least a name to create content.
|
||||
if ($routeParams.create && (!modelState || !modelState["Name"])) {
|
||||
if ($routeParams.create && (id > 0 && (!modelState || !modelState["Name"]))) {
|
||||
|
||||
//need to change the location to not be in 'create' mode. Currently the route will be something like:
|
||||
// /belle/#/content/edit/1234?doctype=newsArticle&create=true
|
||||
|
||||
@@ -248,7 +248,7 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ
|
||||
//This is a bit of a hack to check if the error is due to a file being uploaded that is too large,
|
||||
// we have to just check for the existence of a string value but currently that is the best way to
|
||||
// do this since it's very hacky/difficult to catch this on the server
|
||||
if (data.indexOf("Maximum request length exceeded") >= 0) {
|
||||
if (typeof data !== "undefined" && typeof data.indexOf === "function" && data.indexOf("Maximum request length exceeded") >= 0) {
|
||||
notificationsService.error("Server error", "The uploaded file was too large, check with your site administrator to adjust the maximum size allowed");
|
||||
}
|
||||
else if (Umbraco.Sys.ServerVariables["isDebuggingEnabled"] === true) {
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name umbraco.services.windowResizeListener
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* A single window resize listener... we don't want to have more than one in theory to ensure that
|
||||
* there aren't too many events raised. This will debounce the event with 100 ms intervals and force
|
||||
* a $rootScope.$apply when changed and notify all listeners
|
||||
*
|
||||
*/
|
||||
function windowResizeListener($rootScope) {
|
||||
|
||||
var WinReszier = (function () {
|
||||
var registered = [];
|
||||
var inited = false;
|
||||
var resize = _.debounce(function(ev) {
|
||||
notify();
|
||||
}, 100);
|
||||
var notify = function () {
|
||||
var h = $(window).height();
|
||||
var w = $(window).width();
|
||||
//execute all registrations inside of a digest
|
||||
$rootScope.$apply(function() {
|
||||
for (var i = 0, cnt = registered.length; i < cnt; i++) {
|
||||
registered[i].apply($(window), [{ width: w, height: h }]);
|
||||
}
|
||||
});
|
||||
};
|
||||
return {
|
||||
register: function (fn) {
|
||||
registered.push(fn);
|
||||
if (inited === false) {
|
||||
$(window).bind('resize', resize);
|
||||
inited = true;
|
||||
}
|
||||
},
|
||||
unregister: function (fn) {
|
||||
var index = registered.indexOf(fn);
|
||||
if (index > -1) {
|
||||
registered.splice(index, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
}());
|
||||
|
||||
return {
|
||||
|
||||
/**
|
||||
* Register a callback for resizing
|
||||
* @param {Function} cb
|
||||
*/
|
||||
register: function (cb) {
|
||||
WinReszier.register(cb);
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes a registered callback
|
||||
* @param {Function} cb
|
||||
*/
|
||||
unregister: function(cb) {
|
||||
WinReszier.unregister(cb);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
angular.module('umbraco.services').factory('windowResizeListener', windowResizeListener);
|
||||
@@ -1,12 +1,3 @@
|
||||
/*!
|
||||
* Belle v1.0.0
|
||||
*
|
||||
* Copyright 2013 Umbraco
|
||||
* Licensed under the Apache License v2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*/
|
||||
|
||||
// Core variables and mixins
|
||||
@import "fonts.less"; // Loading fonts
|
||||
@import "variables.less"; // Modify this for custom colors, font-sizes, etc
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
overflow-y:hidden!important;
|
||||
}
|
||||
|
||||
IFRAME {overflow:hidden;}
|
||||
.usky-grid IFRAME {overflow:hidden;}
|
||||
|
||||
|
||||
// Sortabel
|
||||
@@ -279,12 +279,12 @@ IFRAME {overflow:hidden;}
|
||||
|
||||
.usky-grid .usky-control-inner.selectedControl , .usky-grid .usky-row-inner.selectedRow{
|
||||
border: 1px dashed @grayLight;
|
||||
|
||||
|
||||
> ins.item-label {
|
||||
display: block;
|
||||
z-index:100000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -322,12 +322,12 @@ IFRAME {overflow:hidden;}
|
||||
padding-bottom: 30px;
|
||||
position: relative;
|
||||
background-color: white;
|
||||
border: 4px dashed @grayLight;
|
||||
border: 4px dashed @grayLighter;
|
||||
text-align: center;
|
||||
text-align: -moz-center;
|
||||
}
|
||||
.usky-grid .usky-editor-placeholder i{
|
||||
color: @grayLight;
|
||||
color: @grayLighter;
|
||||
font-size: 85px;
|
||||
line-height: 85px;
|
||||
display: block;
|
||||
@@ -380,7 +380,7 @@ IFRAME {overflow:hidden;}
|
||||
border-radius: 200px;
|
||||
background: rgba(255,255,255, 1);
|
||||
border:1px solid rgb(182, 182, 182);
|
||||
margin: 2px;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
.usky-grid .iconBox span.prompt {
|
||||
@@ -464,7 +464,7 @@ IFRAME {overflow:hidden;}
|
||||
// TINYMCE EDITOR
|
||||
// -------------------------
|
||||
.usky-grid .mce-panel {
|
||||
border:none !important;
|
||||
border: none !important;
|
||||
clear:both;
|
||||
}
|
||||
|
||||
@@ -499,6 +499,9 @@ IFRAME {overflow:hidden;}
|
||||
background-color: #F7F7F7 !important;
|
||||
}
|
||||
|
||||
.usky-cell-rte{
|
||||
border: 1px solid @grayLighter;
|
||||
}
|
||||
|
||||
// MEDIA EDITOR
|
||||
// -------------------------
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<div class="umb-panel" ng-controller="Umbraco.Dialogs.HelpController">
|
||||
<div class="umb-panel-header">
|
||||
<h1 class="headline">Help</h1>
|
||||
<h1 class="headline"><localize key="sections_help">Help</localize></h1>
|
||||
<small class="umb-version">Umbraco version {{version}}</small>
|
||||
</div>
|
||||
|
||||
<div class="umb-panel-body umb-scrollable">
|
||||
<div class="tab-content umb-control-group">
|
||||
<div class="umb-pane">
|
||||
<h5>Help topics for: {{section}}</h5>
|
||||
<h5><localize key="help_helpTopicsFor">Help topics for</localize>: {{section}}</h5>
|
||||
<ul class="unstyled list-icons" ng-show="topics">
|
||||
<li ng-repeat="topic in topics">
|
||||
<i class="icon icon-help-alt"></i>
|
||||
@@ -23,7 +23,7 @@
|
||||
<li>
|
||||
<i class="icon icon-favorite"></i>
|
||||
<a target="_blank" href="http://our.umbraco.org?utm_source=core&utm_medium=help&utm_content=link&utm_campaign=our">
|
||||
go to our.umbraco.org
|
||||
<localize key="help_goTo">go to</localize> our.umbraco.org
|
||||
</a>
|
||||
<small class="umb-detail">The friendliest community</small>
|
||||
</li>
|
||||
@@ -31,7 +31,7 @@
|
||||
</div>
|
||||
|
||||
<div class="umb-pane">
|
||||
<h5>Video chapters for: {{section}}</h5>
|
||||
<h5><localize key="help_videoChaptersFor">Video chapters for</localize>: {{section}}</h5>
|
||||
|
||||
<ul class="thumbnails" ng-show="videos">
|
||||
<li class="span2" ng-repeat="video in videos">
|
||||
@@ -47,9 +47,9 @@
|
||||
<li>
|
||||
<i class="icon icon-tv-old"></i>
|
||||
<a target="_blank" href="http://umbraco.tv?utm_source=core&utm_medium=help&utm_content=link&utm_campaign=tv">
|
||||
go to umbraco.tv
|
||||
<localize key="help_goTo">go to</localize> umbraco.tv
|
||||
</a>
|
||||
<small class="umb-detail">The best umbraco video tutorials</small>
|
||||
<small class="umb-detail"><localize key="help_theBestUmbracoVideoTutorials">The best Umbraco video tutorials</localize></small>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
<form method="POST" name="loginForm" ng-submit="loginSubmit(login, password)">
|
||||
<div class="control-group" ng-class="{error: loginForm.username.$invalid}">
|
||||
<input type="text" autofocus ng-model="login" name="username" class="input-xlarge" localize="placeholder" placeholder="@placeholders_username" autocomplete="off" />
|
||||
<input type="text" autofocus ng-model="login" name="username" class="input-xlarge" localize="placeholder" placeholder="@placeholders_username" />
|
||||
</div>
|
||||
|
||||
<div class="control-group" ng-class="{error: loginForm.password.$invalid}">
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
</div>
|
||||
|
||||
<div class="umb-dialog-footer btn-toolbar umb-btn-toolbar">
|
||||
<button class="btn" ng-click="nav.hideDialog(true)">
|
||||
<localize key="buttons_somethingElse">Do something else</localize>
|
||||
</button>
|
||||
<button class="btn" ng-click="nav.hideDialog(true)">
|
||||
<localize key="buttons_somethingElse">Do something else</localize>
|
||||
</button>
|
||||
</div>
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="umb-dialog-body" auto-scale="90">
|
||||
|
||||
<p class="umb-abstract">
|
||||
Are you sure you want to delete <strong>{{currentNode.name}}</strong> ?
|
||||
<localize key="defaultdialogs_confirmdelete">Are you sure you want to delete</localize> <strong>{{currentNode.name}}</strong> ?
|
||||
</p>
|
||||
|
||||
<umb-confirm on-confirm="performDelete" on-cancel="cancel">
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
ng-submit="save()"
|
||||
val-form-manager>
|
||||
|
||||
<umb-panel ng-class="{'editor-breadcrumb': ancestors && ancestors.length > 0}">
|
||||
<umb-panel umb-tabs ng-class="{'editor-breadcrumb': ancestors && ancestors.length > 0}">
|
||||
<umb-header tabs="content.tabs">
|
||||
|
||||
<div class="span7">
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
<umb-options-menu ng-show="currentNode"
|
||||
current-node="currentNode"
|
||||
current-section="{{currentSection}}">
|
||||
current-section="{{currentSection}}">
|
||||
</umb-options-menu>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
</div>
|
||||
</umb-header>
|
||||
<umb-tab-view>
|
||||
<umb-tab id="tabRecycleBin" rel="RecycleBin">
|
||||
<umb-tab id="tabRecycleBin" rel="RecycleBin" style="display: block;">
|
||||
<umb-pane>
|
||||
<div ng-include="listViewPath"></div>
|
||||
</umb-pane>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 22 KiB |
@@ -10,7 +10,7 @@ function examineMgmtController($scope, umbRequestHelper, $log, $http, $q, $timeo
|
||||
'Failed to check index processing')
|
||||
.then(function(data) {
|
||||
|
||||
if (data) {
|
||||
if (data !== null && data !== "null") {
|
||||
|
||||
//copy all resulting properties
|
||||
for (var k in data) {
|
||||
@@ -67,7 +67,9 @@ function examineMgmtController($scope, umbRequestHelper, $log, $http, $q, $timeo
|
||||
"Depending on how much content there is in your site this could take a while. " +
|
||||
"It is not recommended to rebuild an index during times of high website traffic " +
|
||||
"or when editors are editing content.")) {
|
||||
|
||||
indexer.isProcessing = true;
|
||||
indexer.processingAttempts = 0;
|
||||
|
||||
umbRequestHelper.resourcePromise(
|
||||
$http.post(umbRequestHelper.getApiUrl("examineMgmtBaseUrl", "PostRebuildIndex", { indexerName: indexer.name })),
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="umb-dialog-body">
|
||||
|
||||
<p class="umb-abstract">
|
||||
Are you sure you want to delete <strong>{{currentNode.name}}</strong> ?
|
||||
<localize key="defaultdialogs_confirmdelete">Are you sure you want to delete</localize> <strong>{{currentNode.name}}</strong> ?
|
||||
</p>
|
||||
|
||||
<umb-confirm on-confirm="performDelete" on-cancel="cancel">
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
<ul ng-show="showTabs" class="nav nav-tabs umb-nav-tabs span12">
|
||||
|
||||
<li ng-class="{active: $first, 'tab-error': tabHasError}" ng-repeat="tab in visibleTabs" val-tab>
|
||||
<li ng-class="{'tab-error': tabHasError}" ng-repeat="tab in visibleTabs" val-tab>
|
||||
<a href="#tab{{tab.id}}" data-toggle="tab">{{ tab.label }}</a>
|
||||
</li>
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="offset6" style="z-index: 10">
|
||||
<div class="offset6" id="navOffset" style="z-index: 10">
|
||||
|
||||
<!-- The context menu -->
|
||||
<div id='contextMenu' class="umb-modalcolumn fill shadow" ng-swipe-left="nav.hideMenu()" ng-show="showContextMenu" ng-animate="'slide'">
|
||||
@@ -97,4 +97,5 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -1,5 +1,5 @@
|
||||
<div class="umb-panel-body umb-scrollable row-fluid">
|
||||
<div class="tab-content form-horizontal" ng-transclude>
|
||||
<div class="tab-content form-horizontal" ng-transclude>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="umb-dialog-body" auto-scale="90">
|
||||
|
||||
<p class="umb-abstract">
|
||||
Are you sure you want to delete <strong>{{currentNode.name}}</strong> ?
|
||||
<localize key="defaultdialogs_confirmdelete">Are you sure you want to delete</localize> <strong>{{currentNode.name}}</strong> ?
|
||||
</p>
|
||||
|
||||
<umb-confirm on-confirm="performDelete" on-cancel="cancel"></umb-confirm>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
ng-show="loaded"
|
||||
ng-submit="save()"
|
||||
val-form-manager>
|
||||
<umb-panel ng-class="{'editor-breadcrumb': ancestors && ancestors.length > 0}">
|
||||
<umb-panel umb-tabs ng-class="{'editor-breadcrumb': ancestors && ancestors.length > 0}">
|
||||
<umb-header tabs="content.tabs">
|
||||
|
||||
<div class="span7">
|
||||
|
||||
@@ -108,6 +108,13 @@ function mediaEditController($scope, $routeParams, appState, mediaResource, enti
|
||||
rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, err.data)
|
||||
});
|
||||
|
||||
//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]);
|
||||
}
|
||||
}
|
||||
|
||||
editorState.set($scope.content);
|
||||
$scope.busy = false;
|
||||
});
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
</div>
|
||||
</umb-header>
|
||||
<umb-tab-view>
|
||||
<umb-tab id="tabRecycleBin" rel="RecycleBin">
|
||||
<umb-tab id="tabRecycleBin" rel="RecycleBin" style="display: block;">
|
||||
<umb-pane>
|
||||
<div ng-include="listViewPath"></div>
|
||||
</umb-pane>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<div class="umb-dialog-body with-footer" ng-controller="Umbraco.Editors.Member.CreateController">
|
||||
<div class="umb-pane">
|
||||
|
||||
<h5>Create a new member</h5>
|
||||
<h5><localize key="member_createNewMember">Create a new member</localize></h5>
|
||||
<ul class="umb-actions umb-actions-child">
|
||||
|
||||
<li ng-repeat="docType in allowedTypes">
|
||||
@@ -20,6 +20,8 @@
|
||||
</div>
|
||||
|
||||
<div class="umb-dialog-footer btn-toolbar umb-btn-toolbar" >
|
||||
<button type="button" class="btn" ng-click="nav.hideDialog()">Do something else</button>
|
||||
<button type="button" class="btn" ng-click="nav.hideDialog()">
|
||||
<localize key="buttons_somethingElse">Do something else</localize>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="umb-dialog-body" auto-scale="90">
|
||||
|
||||
<p class="umb-abstract">
|
||||
Are you sure you want to delete <strong>{{currentNode.name}}</strong> ?
|
||||
<localize key="defaultdialogs_confirmdelete">Are you sure you want to delete</localize> <strong>{{currentNode.name}}</strong> ?
|
||||
</p>
|
||||
|
||||
<umb-confirm on-confirm="performDelete" on-cancel="cancel">
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
ng-show="loaded"
|
||||
ng-submit="save()"
|
||||
val-form-manager>
|
||||
<umb-panel>
|
||||
<umb-panel umb-tabs>
|
||||
<umb-header tabs="content.tabs">
|
||||
|
||||
<div class="span7" ng-if="content.membershipScenario == 0">
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
assetsService.load([
|
||||
//"lib/spectrum/tinycolor.js",
|
||||
"lib/spectrum/spectrum.js"
|
||||
]).then(function () {
|
||||
], $scope).then(function () {
|
||||
var elem = $element.find("input");
|
||||
elem.spectrum({
|
||||
color: null,
|
||||
|
||||
+11
-17
@@ -17,6 +17,10 @@ function dateTimePickerController($scope, notificationsService, assetsService, a
|
||||
|
||||
//map the user config
|
||||
$scope.model.config = angular.extend(config, $scope.model.config);
|
||||
//ensure the format doesn't get overwritten with an empty string
|
||||
if ($scope.model.config.format === "" || $scope.model.config.format === undefined || $scope.model.config.format === null) {
|
||||
$scope.model.config.format = $scope.model.config.pickTime ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD";
|
||||
}
|
||||
|
||||
$scope.hasDatetimePickerValue = $scope.model.value ? true : false;
|
||||
$scope.datetimePickerValue = null;
|
||||
@@ -39,12 +43,7 @@ function dateTimePickerController($scope, notificationsService, assetsService, a
|
||||
if (e.date && e.date.isValid()) {
|
||||
$scope.datePickerForm.datepicker.$setValidity("pickerError", true);
|
||||
$scope.hasDatetimePickerValue = true;
|
||||
if (!$scope.model.config.format) {
|
||||
$scope.datetimePickerValue = e.date;
|
||||
}
|
||||
else {
|
||||
$scope.datetimePickerValue = e.date.format($scope.model.config.format);
|
||||
}
|
||||
$scope.datetimePickerValue = e.date.format($scope.model.config.format);
|
||||
}
|
||||
else {
|
||||
$scope.hasDatetimePickerValue = false;
|
||||
@@ -78,8 +77,8 @@ function dateTimePickerController($scope, notificationsService, assetsService, a
|
||||
$scope.model.config.language = user.locale;
|
||||
|
||||
|
||||
assetsService.load(filesToLoad).then(
|
||||
function () {
|
||||
assetsService.load(filesToLoad, $scope).then(
|
||||
function () {
|
||||
//The Datepicker js and css files are available and all components are ready to use.
|
||||
|
||||
// Get the id of the datepicker button that was clicked
|
||||
@@ -98,15 +97,10 @@ function dateTimePickerController($scope, notificationsService, assetsService, a
|
||||
|
||||
if ($scope.hasDatetimePickerValue) {
|
||||
|
||||
//assign value to plugin/picker
|
||||
element.datetimepicker("setValue", $scope.model.value ? new Date($scope.model.value) : moment());
|
||||
|
||||
if (!$scope.model.config.format) {
|
||||
$scope.datetimePickerValue = moment($scope.model.value);
|
||||
}
|
||||
else {
|
||||
$scope.datetimePickerValue = moment($scope.model.value).format($scope.model.config.format);
|
||||
}
|
||||
//assign value to plugin/picker
|
||||
var dateVal = $scope.model.value ? moment($scope.model.value, $scope.model.config.format) : moment();
|
||||
element.datetimepicker("setValue", dateVal);
|
||||
$scope.datetimePickerValue = moment($scope.model.value).format($scope.model.config.format);
|
||||
}
|
||||
|
||||
element.find("input").bind("blur", function() {
|
||||
|
||||
+15
-2
@@ -1,6 +1,6 @@
|
||||
angular.module("umbraco")
|
||||
.controller("Umbraco.PropertyEditors.GoogleMapsController",
|
||||
function ($rootScope, $scope, notificationsService, dialogService, assetsService, $log, $timeout) {
|
||||
function ($element, $rootScope, $scope, notificationsService, dialogService, assetsService, $log, $timeout) {
|
||||
|
||||
assetsService.loadJs('http://www.google.com/jsapi')
|
||||
.then(function () {
|
||||
@@ -58,8 +58,21 @@ angular.module("umbraco")
|
||||
});
|
||||
});
|
||||
|
||||
$('a[data-toggle="tab"]').on('shown', function (e) {
|
||||
var tabShown = function(e) {
|
||||
google.maps.event.trigger(map, 'resize');
|
||||
};
|
||||
|
||||
//listen for tab changes
|
||||
if (tabsCtrl != null) {
|
||||
tabsCtrl.onTabShown(function (args) {
|
||||
tabShown();
|
||||
});
|
||||
}
|
||||
|
||||
$element.closest('.umb-panel.tabbable').on('shown', '.nav-tabs a', tabShown);
|
||||
|
||||
$scope.$on('$destroy', function () {
|
||||
$element.closest('.umb-panel.tabbable').off('shown', '.nav-tabs a', tabShown);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ angular.module("umbraco")
|
||||
$timeout(function(){
|
||||
if($scope.control.$initializing){
|
||||
$scope.setImage();
|
||||
}else{
|
||||
}else if($scope.control.value){
|
||||
$scope.setUrl();
|
||||
}
|
||||
}, 200);
|
||||
|
||||
@@ -19,8 +19,8 @@ angular.module("umbraco")
|
||||
$scope.sortableOptions = {
|
||||
distance: 10,
|
||||
cursor: "move",
|
||||
placeholder: 'ui-sortable-placeholder',
|
||||
handle: '.cell-tools-move',
|
||||
placeholder: "ui-sortable-placeholder",
|
||||
handle: ".cell-tools-move",
|
||||
forcePlaceholderSize: true,
|
||||
tolerance: "pointer",
|
||||
zIndex: 999999999999999999,
|
||||
@@ -33,30 +33,30 @@ angular.module("umbraco")
|
||||
sort: function (event, ui) {
|
||||
/* prevent vertical scroll out of the screen */
|
||||
var max = $(".usky-grid").width() - 150;
|
||||
if (parseInt(ui.helper.css('left')) > max) {
|
||||
ui.helper.css({ 'left': max + "px" })
|
||||
if (parseInt(ui.helper.css("left")) > max) {
|
||||
ui.helper.css({ "left": max + "px" });
|
||||
}
|
||||
if (parseInt(ui.helper.css('left')) < 20) {
|
||||
ui.helper.css({ 'left': 20 })
|
||||
if (parseInt(ui.helper.css("left")) < 20) {
|
||||
ui.helper.css({ "left": 20 });
|
||||
}
|
||||
},
|
||||
|
||||
start: function (e, ui) {
|
||||
draggedRteSettings = {};
|
||||
ui.item.find('.mceNoEditor').each(function () {
|
||||
ui.item.find(".mceNoEditor").each(function () {
|
||||
// remove all RTEs in the dragged row and save their settings
|
||||
var id = $(this).attr('id');
|
||||
var id = $(this).attr("id");
|
||||
draggedRteSettings[id] = _.findWhere(tinyMCE.editors, { id: id }).settings;
|
||||
tinyMCE.execCommand('mceRemoveEditor', false, id);
|
||||
tinyMCE.execCommand("mceRemoveEditor", false, id);
|
||||
});
|
||||
},
|
||||
|
||||
stop: function (e, ui) {
|
||||
// reset all RTEs affected by the dragging
|
||||
ui.item.parents(".usky-column").find('.mceNoEditor').each(function () {
|
||||
var id = $(this).attr('id');
|
||||
ui.item.parents(".usky-column").find(".mceNoEditor").each(function () {
|
||||
var id = $(this).attr("id");
|
||||
draggedRteSettings[id] = draggedRteSettings[id] || _.findWhere(tinyMCE.editors, { id: id }).settings;
|
||||
tinyMCE.execCommand('mceRemoveEditor', false, id);
|
||||
tinyMCE.execCommand("mceRemoveEditor", false, id);
|
||||
tinyMCE.init(draggedRteSettings[id]);
|
||||
});
|
||||
}
|
||||
@@ -69,7 +69,7 @@ angular.module("umbraco")
|
||||
distance: 10,
|
||||
cursor: "move",
|
||||
placeholder: "ui-sortable-placeholder",
|
||||
handle: '.cell-tools-move',
|
||||
handle: ".cell-tools-move",
|
||||
connectWith: ".usky-cell",
|
||||
forcePlaceholderSize: true,
|
||||
tolerance: "pointer",
|
||||
@@ -82,18 +82,18 @@ angular.module("umbraco")
|
||||
|
||||
sort: function (event, ui) {
|
||||
/* prevent vertical scroll out of the screen */
|
||||
var position = parseInt(ui.item.parent().offset().left) + parseInt(ui.helper.css('left')) - parseInt($(".usky-grid").offset().left);
|
||||
var position = parseInt(ui.item.parent().offset().left) + parseInt(ui.helper.css("left")) - parseInt($(".usky-grid").offset().left);
|
||||
var max = $(".usky-grid").width() - 220;
|
||||
if (position > max) {
|
||||
ui.helper.css({ 'left': max - parseInt(ui.item.parent().offset().left) + parseInt($(".usky-grid").offset().left) + "px" })
|
||||
ui.helper.css({ "left": max - parseInt(ui.item.parent().offset().left) + parseInt($(".usky-grid").offset().left) + "px" });
|
||||
}
|
||||
if (position < 0) {
|
||||
ui.helper.css({ 'left': 0 - parseInt(ui.item.parent().offset().left) + parseInt($(".usky-grid").offset().left) + "px" })
|
||||
ui.helper.css({ "left": 0 - parseInt(ui.item.parent().offset().left) + parseInt($(".usky-grid").offset().left) + "px" });
|
||||
}
|
||||
},
|
||||
|
||||
over: function (event, ui) {
|
||||
allowedEditors = $(event.target).scope().area.allowed;
|
||||
var allowedEditors = $(event.target).scope().area.allowed;
|
||||
|
||||
if ($.inArray(ui.item.scope().control.editor.alias, allowedEditors) < 0 && allowedEditors) {
|
||||
ui.placeholder.hide();
|
||||
@@ -112,16 +112,16 @@ angular.module("umbraco")
|
||||
if (cancelMove) {
|
||||
ui.item.sortable.cancel();
|
||||
}
|
||||
ui.item.parents(".usky-cell").find('.mceNoEditor').each(function () {
|
||||
if ($.inArray($(this).attr('id'), notIncludedRte) < 0) {
|
||||
notIncludedRte.splice(0, 0, $(this).attr('id'));
|
||||
ui.item.parents(".usky-cell").find(".mceNoEditor").each(function () {
|
||||
if ($.inArray($(this).attr("id"), notIncludedRte) < 0) {
|
||||
notIncludedRte.splice(0, 0, $(this).attr("id"));
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
$(event.target).find('.mceNoEditor').each(function () {
|
||||
if ($.inArray($(this).attr('id'), notIncludedRte) < 0) {
|
||||
notIncludedRte.splice(0, 0, $(this).attr('id'));
|
||||
$(event.target).find(".mceNoEditor").each(function () {
|
||||
if ($.inArray($(this).attr("id"), notIncludedRte) < 0) {
|
||||
notIncludedRte.splice(0, 0, $(this).attr("id"));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -132,22 +132,22 @@ angular.module("umbraco")
|
||||
// reset dragged RTE settings in case a RTE isn't dragged
|
||||
draggedRteSettings = undefined;
|
||||
|
||||
ui.item.find('.mceNoEditor').each(function () {
|
||||
ui.item.find(".mceNoEditor").each(function () {
|
||||
notIncludedRte = [];
|
||||
|
||||
// save the dragged RTE settings
|
||||
draggedRteSettings = _.findWhere(tinyMCE.editors, { id: $(this).attr('id') }).settings;
|
||||
draggedRteSettings = _.findWhere(tinyMCE.editors, { id: $(this).attr("id") }).settings;
|
||||
|
||||
// remove the dragged RTE
|
||||
tinyMCE.execCommand('mceRemoveEditor', false, $(this).attr('id'));
|
||||
tinyMCE.execCommand("mceRemoveEditor", false, $(this).attr("id"));
|
||||
});
|
||||
},
|
||||
|
||||
stop: function (e, ui) {
|
||||
ui.item.parents(".usky-cell").find('.mceNoEditor').each(function () {
|
||||
if ($.inArray($(this).attr('id'), notIncludedRte) < 0) {
|
||||
ui.item.parents(".usky-cell").find(".mceNoEditor").each(function () {
|
||||
if ($.inArray($(this).attr("id"), notIncludedRte) < 0) {
|
||||
// add all dragged's neighbouring RTEs in the new cell
|
||||
notIncludedRte.splice(0, 0, $(this).attr('id'));
|
||||
notIncludedRte.splice(0, 0, $(this).attr("id"));
|
||||
}
|
||||
});
|
||||
$timeout(function () {
|
||||
@@ -158,9 +158,9 @@ angular.module("umbraco")
|
||||
|
||||
_.forEach(notIncludedRte, function (id) {
|
||||
// reset all the other RTEs
|
||||
if (draggedRteSettings === undefined || id != draggedRteSettings.id) {
|
||||
if (draggedRteSettings === undefined || id !== draggedRteSettings.id) {
|
||||
var rteSettings = _.findWhere(tinyMCE.editors, { id: id }).settings;
|
||||
tinyMCE.execCommand('mceRemoveEditor', false, id);
|
||||
tinyMCE.execCommand("mceRemoveEditor", false, id);
|
||||
tinyMCE.init(rteSettings);
|
||||
}
|
||||
});
|
||||
@@ -188,7 +188,6 @@ angular.module("umbraco")
|
||||
//todo calculate position...
|
||||
var offset = $(event.target).offset();
|
||||
var height = $(window).height();
|
||||
var width = $(window).width();
|
||||
|
||||
if ((height - offset.top) < 250) {
|
||||
$scope.overlayMenu.style.bottom = 0;
|
||||
@@ -260,11 +259,11 @@ angular.module("umbraco")
|
||||
});
|
||||
}
|
||||
else {
|
||||
|
||||
|
||||
|
||||
return layouts;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
$scope.addRow = function (section, layout) {
|
||||
|
||||
@@ -285,7 +284,8 @@ angular.module("umbraco")
|
||||
section.rows.splice($index, 1);
|
||||
$scope.currentRow = null;
|
||||
$scope.openRTEToolbarId = null;
|
||||
$scope.initContent();
|
||||
|
||||
//$scope.initContent();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -372,9 +372,6 @@ angular.module("umbraco")
|
||||
$scope.currentInfohighlightControl = null;
|
||||
};
|
||||
|
||||
$scope.setUniqueId = function (cell, index) {
|
||||
return guid();
|
||||
};
|
||||
|
||||
var guid = (function () {
|
||||
function s4() {
|
||||
@@ -383,18 +380,23 @@ angular.module("umbraco")
|
||||
.substring(1);
|
||||
}
|
||||
return function () {
|
||||
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
|
||||
s4() + '-' + s4() + s4() + s4();
|
||||
return s4() + s4() + "-" + s4() + "-" + s4() + "-" +
|
||||
s4() + "-" + s4() + s4() + s4();
|
||||
};
|
||||
})();
|
||||
|
||||
$scope.addControl = function (editor, cell, index) {
|
||||
$scope.setUniqueId = function (cell, index) {
|
||||
return guid();
|
||||
};
|
||||
|
||||
$scope.addControl = function (editor, cell, index, initialize) {
|
||||
$scope.closeItemOverlay();
|
||||
initialize = (initialize !== false);
|
||||
|
||||
var newControl = {
|
||||
value: null,
|
||||
editor: editor,
|
||||
$initializing: true
|
||||
$initializing: initialize
|
||||
};
|
||||
|
||||
if (index === undefined) {
|
||||
@@ -430,11 +432,11 @@ angular.module("umbraco")
|
||||
scopedObject.deletePrompt = false;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
$scope.showPrompt = function (scopedObject) {
|
||||
scopedObject.deletePrompt = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// *********************************************
|
||||
@@ -453,11 +455,12 @@ angular.module("umbraco")
|
||||
var clear = true;
|
||||
|
||||
//settings indicator shortcut
|
||||
if ($scope.model.config.items.config || $scope.model.config.items.styles) {
|
||||
if ( ($scope.model.config.items.config && $scope.model.config.items.config.length > 0) || ($scope.model.config.items.styles && $scope.model.config.items.styles.length > 0)) {
|
||||
$scope.hasSettings = true;
|
||||
}
|
||||
|
||||
//ensure the grid has a column value set, if nothing is found, set it to 12
|
||||
//ensure the grid has a column value set,
|
||||
//if nothing is found, set it to 12
|
||||
if ($scope.model.config.items.columns && angular.isString($scope.model.config.items.columns)) {
|
||||
$scope.model.config.items.columns = parseInt($scope.model.config.items.columns);
|
||||
} else {
|
||||
@@ -469,7 +472,7 @@ angular.module("umbraco")
|
||||
if ($scope.model.value.name && angular.isArray($scope.model.config.items.templates)) {
|
||||
|
||||
//This will occur if it is an existing value, in which case
|
||||
// we need to determine which layout was applied by looking up
|
||||
// we need to determine which layout was applied by looking up
|
||||
// the name
|
||||
// TODO: We need to change this to an immutable ID!!
|
||||
|
||||
@@ -479,14 +482,14 @@ angular.module("umbraco")
|
||||
|
||||
if (found && angular.isArray(found.sections) && found.sections.length === $scope.model.value.sections.length) {
|
||||
|
||||
//Cool, we've found the template associated with our current value with matching sections counts, now we need to
|
||||
//Cool, we've found the template associated with our current value with matching sections counts, now we need to
|
||||
// merge this template data on to our current value (as if it was new) so that we can preserve what is and isn't
|
||||
// allowed for this template based on the current config.
|
||||
|
||||
_.each(found.sections, function (templateSection, index) {
|
||||
angular.extend($scope.model.value.sections[index], angular.copy(templateSection));
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -505,6 +508,7 @@ angular.module("umbraco")
|
||||
});
|
||||
} else if ($scope.model.config.items.templates && $scope.model.config.items.templates.length === 1) {
|
||||
$scope.addTemplate($scope.model.config.items.templates[0]);
|
||||
clear = false;
|
||||
}
|
||||
|
||||
if (clear) {
|
||||
@@ -517,8 +521,11 @@ angular.module("umbraco")
|
||||
|
||||
section.$allowedLayouts = getAllowedLayouts(section);
|
||||
|
||||
if (!section.rows) {
|
||||
if (!section.rows || section.rows.length === 0) {
|
||||
section.rows = [];
|
||||
if(section.$allowedLayouts.length === 1){
|
||||
$scope.addRow(section, section.$allowedLayouts[0]);
|
||||
}
|
||||
} else {
|
||||
_.forEach(section.rows, function (row, index) {
|
||||
if (!row.$initialized) {
|
||||
@@ -565,22 +572,6 @@ angular.module("umbraco")
|
||||
area.styles = currentArea.styles;
|
||||
}
|
||||
|
||||
//copy over existing controls into the new areas
|
||||
if (row.areas.length > areaIndex && row.areas[areaIndex].controls) {
|
||||
area.controls = currentArea.controls;
|
||||
|
||||
_.forEach(area.controls, function (control, controlIndex) {
|
||||
$scope.initControl(control, controlIndex);
|
||||
});
|
||||
|
||||
} else {
|
||||
area.controls = [];
|
||||
}
|
||||
|
||||
//set width
|
||||
area.$percentage = $scope.percentage(area.grid);
|
||||
area.$uniqueId = $scope.setUniqueId();
|
||||
|
||||
//set editor permissions
|
||||
if (!area.allowed || area.allowAll === true) {
|
||||
area.$allowedEditors = $scope.availableEditors;
|
||||
@@ -594,6 +585,29 @@ angular.module("umbraco")
|
||||
area.$allowsRTE = true;
|
||||
}
|
||||
}
|
||||
|
||||
//copy over existing controls into the new areas
|
||||
if (row.areas.length > areaIndex && row.areas[areaIndex].controls) {
|
||||
area.controls = currentArea.controls;
|
||||
|
||||
_.forEach(area.controls, function (control, controlIndex) {
|
||||
$scope.initControl(control, controlIndex);
|
||||
});
|
||||
|
||||
} else {
|
||||
//if empty
|
||||
area.controls = [];
|
||||
|
||||
//if only one allowed editor
|
||||
if(area.$allowedEditors.length === 1){
|
||||
$scope.addControl(area.$allowedEditors[0], area, 0, false);
|
||||
}
|
||||
}
|
||||
|
||||
//set width
|
||||
area.$percentage = $scope.percentage(area.grid);
|
||||
area.$uniqueId = $scope.setUniqueId();
|
||||
|
||||
} else {
|
||||
original.areas.splice(areaIndex, 1);
|
||||
}
|
||||
@@ -623,7 +637,7 @@ angular.module("umbraco")
|
||||
control.$uniqueId = $scope.setUniqueId();
|
||||
|
||||
//error handling in case of missing editor..
|
||||
//should only happen if stripped earlier
|
||||
//should only happen if stripped earlier
|
||||
if (!control.editor) {
|
||||
control.$editorPath = "views/propertyeditors/grid/editors/error.html";
|
||||
}
|
||||
@@ -664,13 +678,13 @@ angular.module("umbraco")
|
||||
|
||||
});
|
||||
|
||||
//Clean the grid value before submitting to the server, we don't need
|
||||
//Clean the grid value before submitting to the server, we don't need
|
||||
// all of that grid configuration in the value to be stored!! All of that
|
||||
// needs to be merged in at runtime to ensure that the real config values are used
|
||||
// if they are ever updated.
|
||||
|
||||
var unsubscribe = $scope.$on("formSubmitting", function (ev, args) {
|
||||
|
||||
var unsubscribe = $scope.$on("formSubmitting", function () {
|
||||
|
||||
if ($scope.model.value && $scope.model.value.sections) {
|
||||
_.each($scope.model.value.sections, function(section) {
|
||||
if (section.rows) {
|
||||
@@ -692,7 +706,7 @@ angular.module("umbraco")
|
||||
var alias = control.editor.alias;
|
||||
control.editor = {
|
||||
alias: alias
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -705,7 +719,7 @@ angular.module("umbraco")
|
||||
});
|
||||
|
||||
//when the scope is destroyed we need to unsubscribe
|
||||
$scope.$on('$destroy', function () {
|
||||
$scope.$on("$destroy", function () {
|
||||
unsubscribe();
|
||||
});
|
||||
|
||||
|
||||
@@ -107,13 +107,13 @@
|
||||
<Project>{07fbc26b-2927-4a22-8d96-d644c667fecc}</Project>
|
||||
<Name>UmbracoExamine</Name>
|
||||
</ProjectReference>
|
||||
<Reference Include="AutoMapper, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.dll</HintPath>
|
||||
<Reference Include="AutoMapper, Version=3.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\AutoMapper.3.0.0\lib\net40\AutoMapper.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="AutoMapper.Net4, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
|
||||
<Reference Include="AutoMapper.Net4, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\AutoMapper.3.0.0\lib\net40\AutoMapper.Net4.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="ClientDependency.Core, Version=1.8.4.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\ClientDependency.1.8.4\lib\net45\ClientDependency.Core.dll</HintPath>
|
||||
@@ -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.66.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.66.0\lib\Examine.dll</HintPath>
|
||||
<Reference Include="Examine, Version=0.1.68.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.68.0\lib\Examine.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
|
||||
@@ -2456,5 +2456,4 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.0\x86\*.* "$(TargetDir)x86\"
|
||||
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" />
|
||||
<Error Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
|
||||
</Target>
|
||||
<Import Project="..\packages\AutoMapper.3.3.1\tools\AutoMapper.targets" Condition="Exists('..\packages\AutoMapper.3.3.1\tools\AutoMapper.targets')" />
|
||||
</Project>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user