Compare commits
94 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 75c2b07ad3 | |||
| 969fe30f6e | |||
| 0f90d357cf | |||
| d955daab0f | |||
| 617b17ca9e | |||
| 9e3d7a1cce | |||
| f04071d7c7 | |||
| 2cce9395da | |||
| 6ad56863d4 | |||
| 2703fa7ea2 | |||
| b3c6654d41 | |||
| 0071651621 | |||
| 4dbc27f1fe | |||
| 3f8bbc2f02 | |||
| 999be9c578 | |||
| b36b1693dd | |||
| 99b2192ab7 | |||
| 5230f55f44 | |||
| f93fee28dd | |||
| fc7cfea4ad | |||
| bc5f651c64 | |||
| ecdca378c6 | |||
| 4628c1f858 | |||
| 5af4d02f44 | |||
| 2f9b526465 | |||
| 800e02bccf | |||
| 693b0dba24 | |||
| 2004f6a51e | |||
| f650b6238c | |||
| 7c179a7868 | |||
| 7a7e0edfa7 | |||
| 69adec1d68 | |||
| 0cf6548f86 | |||
| 111ee66b60 | |||
| fedcd6f970 | |||
| 8e82ff5450 | |||
| 81459c3659 | |||
| 8907c9855b | |||
| e1bf30ec26 | |||
| 6bb9c5b81c | |||
| 6aafbfb245 | |||
| d5fe8c11c8 | |||
| 3fdb122e91 | |||
| 710dda164f | |||
| 07d0d82bd1 | |||
| 91eb3ea59e | |||
| 096f1b6ff9 | |||
| f24c0d3e7a | |||
| 104338c817 | |||
| 568f098445 | |||
| f46d595f00 | |||
| 46826ad590 | |||
| a8bd34b77e | |||
| 40774cfff2 | |||
| 5dde898205 | |||
| 249287e101 | |||
| 3e458e2ba6 | |||
| 4f293a8be1 | |||
| 3b9d9ab8c4 | |||
| 83f875dadd | |||
| 89df81d3df | |||
| 2e4ee42c90 | |||
| a03858a726 | |||
| 253174d4b3 | |||
| 947889fae6 | |||
| 7ee0b582dd | |||
| 7bec4efc60 | |||
| 571d8086c8 | |||
| 8abeefe6bb | |||
| 0aaf3eea02 | |||
| 8fc84f9b09 | |||
| 493b98a771 | |||
| 114a9b4d33 | |||
| 824b1e7c08 | |||
| dfa9b297db | |||
| adceb24651 | |||
| c7f1a1419a | |||
| 8878b5e21c | |||
| 6ebb1d1b4b | |||
| 583cd2d1e9 | |||
| 86c6b01e73 | |||
| 1170e222e3 | |||
| fe004db7d5 | |||
| 9e75ffb332 | |||
| d0bb6b7aa4 | |||
| 91da14b0c6 | |||
| f361e286ed | |||
| e60e4e52fc | |||
| af1fe425a2 | |||
| 22385d40db | |||
| 367073e02e | |||
| 1a4322eb48 | |||
| e8f84cfec0 | |||
| 6effcdfce9 |
@@ -17,7 +17,7 @@
|
||||
<dependencies>
|
||||
<dependency id="UmbracoCms.Core" version="[$version$]" />
|
||||
<dependency id="Newtonsoft.Json" version="[6.0.8, 9.0.0)" />
|
||||
<dependency id="Umbraco.ModelsBuilder" version="[3.0.0, 4.0.0)" />
|
||||
<dependency id="Umbraco.ModelsBuilder" version="[3.0.2, 4.0.0)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
|
||||
7.4.1
|
||||
7.4.2
|
||||
+2
-2
@@ -11,5 +11,5 @@ using System.Resources;
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.4.1")]
|
||||
[assembly: AssemblyInformationalVersion("7.4.1")]
|
||||
[assembly: AssemblyFileVersion("7.4.2")]
|
||||
[assembly: AssemblyInformationalVersion("7.4.2")]
|
||||
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class UmbracoVersion
|
||||
{
|
||||
private static readonly Version Version = new Version("7.4.1");
|
||||
private static readonly Version Version = new Version("7.4.2");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
|
||||
@@ -487,11 +487,8 @@ namespace Umbraco.Core.Models
|
||||
var oldPropertyGroup = PropertyGroups.FirstOrDefault(x =>
|
||||
x.PropertyTypes.Any(y => y.Alias == propertyTypeAlias));
|
||||
|
||||
// reset PropertyGroupId, which will be re-evaluated when the content type
|
||||
// is saved - what is important is group.PropertyTypes - see code in
|
||||
// ContentTypeBaseRepository.PersistUpdatedBaseContentType
|
||||
propertyType.PropertyGroupId = new Lazy<int>(() => default(int));
|
||||
propertyType.ResetDirtyProperties(); // PropertyGroupId must not be dirty
|
||||
// set new group
|
||||
propertyType.PropertyGroupId = newPropertyGroup == null ? null : new Lazy<int>(() => newPropertyGroup.Id, false);
|
||||
|
||||
// remove from old group, if any - add to new group, if any
|
||||
if (oldPropertyGroup != null)
|
||||
@@ -540,7 +537,7 @@ namespace Umbraco.Core.Models
|
||||
// re-assign the group's properties to no group
|
||||
foreach (var property in group.PropertyTypes)
|
||||
{
|
||||
property.PropertyGroupId = new Lazy<int>(() => 0);
|
||||
property.PropertyGroupId = null;
|
||||
_propertyTypes.Add(property);
|
||||
}
|
||||
|
||||
|
||||
@@ -221,8 +221,9 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the PropertyGroup's Id for which this PropertyType belongs
|
||||
/// Gets or sets the identifier of the PropertyGroup this PropertyType belongs to.
|
||||
/// </summary>
|
||||
/// <remarks>For generic properties, the value is <c>null</c>.</remarks>
|
||||
[DataMember]
|
||||
internal Lazy<int> PropertyGroupId
|
||||
{
|
||||
|
||||
@@ -164,7 +164,7 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
Name = typeDto.Name,
|
||||
SortOrder = typeDto.SortOrder,
|
||||
ValidationRegExp = typeDto.ValidationRegExp,
|
||||
PropertyGroupId = new Lazy<int>(() => default(int)),
|
||||
PropertyGroupId = null,
|
||||
CreateDate = dto.CreateDate,
|
||||
UpdateDate = dto.CreateDate
|
||||
};
|
||||
|
||||
@@ -180,7 +180,7 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
case "COALESCE":
|
||||
return string.Format("{0}({1},{2})", operand, left, right);
|
||||
default:
|
||||
return left + " " + operand + " " + right;
|
||||
return "(" + left + " " + operand + " " + right + ")";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,7 +277,7 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
case ExpressionType.MemberAccess:
|
||||
// false property , i.e. x => !Trashed
|
||||
SqlParameters.Add(true);
|
||||
return "NOT (" + o + " = @0)";
|
||||
return string.Format("NOT ({0} = @{1})", o, SqlParameters.Count - 1);
|
||||
default:
|
||||
// could be anything else, such as: x => !x.Path.StartsWith("-20")
|
||||
return "NOT (" + o + ")";
|
||||
@@ -293,7 +293,7 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
case ExpressionType.MemberAccess:
|
||||
// true property, i.e. x => Trashed
|
||||
SqlParameters.Add(true);
|
||||
return o + " = @0";
|
||||
return string.Format("({0} = @{1})", o, SqlParameters.Count - 1);
|
||||
default:
|
||||
// could be anything else, such as: x => x.Path.StartsWith("-20")
|
||||
return o;
|
||||
|
||||
@@ -914,7 +914,7 @@ AND umbracoNode.id <> @id",
|
||||
//check for default templates
|
||||
bool? isDefaultTemplate = Convert.ToBoolean(ct.dtIsDefault);
|
||||
int? templateId = ct.dtTemplateId;
|
||||
if (currDefaultTemplate == -1 && isDefaultTemplate.HasValue && templateId.HasValue)
|
||||
if (currDefaultTemplate == -1 && isDefaultTemplate.HasValue && isDefaultTemplate.Value && templateId.HasValue)
|
||||
{
|
||||
currDefaultTemplate = templateId.Value;
|
||||
}
|
||||
|
||||
@@ -103,10 +103,18 @@ namespace Umbraco.Core.Security
|
||||
var backOfficeIdentity = http.User.Identity as UmbracoBackOfficeIdentity;
|
||||
if (backOfficeIdentity != null) return backOfficeIdentity;
|
||||
|
||||
//Check if there's more than one identity assigned and see if it's a UmbracoBackOfficeIdentity and use that
|
||||
var claimsPrincipal = http.User as ClaimsPrincipal;
|
||||
if (claimsPrincipal != null)
|
||||
{
|
||||
backOfficeIdentity = claimsPrincipal.Identities.OfType<UmbracoBackOfficeIdentity>().FirstOrDefault();
|
||||
if (backOfficeIdentity != null) return backOfficeIdentity;
|
||||
}
|
||||
|
||||
//Otherwise convert to a UmbracoBackOfficeIdentity if it's auth'd and has the back office session
|
||||
var claimsIdentity = http.User.Identity as ClaimsIdentity;
|
||||
if (claimsIdentity != null && claimsIdentity.IsAuthenticated)
|
||||
{
|
||||
{
|
||||
try
|
||||
{
|
||||
return UmbracoBackOfficeIdentity.FromClaimsIdentity(claimsIdentity);
|
||||
|
||||
@@ -267,11 +267,15 @@ namespace Umbraco.Core.Services
|
||||
structure.Add(new XElement("MediaType", allowedType.Alias));
|
||||
}
|
||||
|
||||
var genericProperties = new XElement("GenericProperties");
|
||||
var genericProperties = new XElement("GenericProperties"); // actually, all of them
|
||||
foreach (var propertyType in mediaType.PropertyTypes)
|
||||
{
|
||||
var definition = dataTypeService.GetDataTypeDefinitionById(propertyType.DataTypeDefinitionId);
|
||||
var propertyGroup = mediaType.PropertyGroups.FirstOrDefault(x => x.Id == propertyType.PropertyGroupId.Value);
|
||||
|
||||
var propertyGroup = propertyType.PropertyGroupId == null // true generic property
|
||||
? null
|
||||
: mediaType.PropertyGroups.FirstOrDefault(x => x.Id == propertyType.PropertyGroupId.Value);
|
||||
|
||||
var genericProperty = new XElement("GenericProperty",
|
||||
new XElement("Name", propertyType.Name),
|
||||
new XElement("Alias", propertyType.Alias),
|
||||
@@ -381,14 +385,14 @@ namespace Umbraco.Core.Services
|
||||
structure.Add(new XElement("DocumentType", allowedType.Alias));
|
||||
}
|
||||
|
||||
var genericProperties = new XElement("GenericProperties");
|
||||
var genericProperties = new XElement("GenericProperties"); // actually, all of them
|
||||
foreach (var propertyType in contentType.PropertyTypes)
|
||||
{
|
||||
var definition = dataTypeService.GetDataTypeDefinitionById(propertyType.DataTypeDefinitionId);
|
||||
|
||||
var propertyGroup = propertyType.PropertyGroupId == null
|
||||
? null
|
||||
: contentType.PropertyGroups.FirstOrDefault(x => x.Id == propertyType.PropertyGroupId.Value);
|
||||
var propertyGroup = propertyType.PropertyGroupId == null // true generic property
|
||||
? null
|
||||
: contentType.PropertyGroups.FirstOrDefault(x => x.Id == propertyType.PropertyGroupId.Value);
|
||||
|
||||
var genericProperty = new XElement("GenericProperty",
|
||||
new XElement("Name", propertyType.Name),
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
.InnerJoin("[cmsContentVersion]").On("[cmsDocument].[versionId] = [cmsContentVersion].[VersionId]")
|
||||
.InnerJoin("[cmsContent]").On("[cmsContentVersion].[ContentId] = [cmsContent].[nodeId]")
|
||||
.InnerJoin("[umbracoNode]").On("[cmsContent].[nodeId] = [umbracoNode].[id]")
|
||||
.Where("[umbracoNode].[nodeObjectType] = @0", new Guid("c66ba18e-eaf3-4cff-8a22-41b16d66a972"));
|
||||
.Where("([umbracoNode].[nodeObjectType] = @0)", new Guid("c66ba18e-eaf3-4cff-8a22-41b16d66a972"));
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
@@ -56,8 +56,8 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
.InnerJoin("[cmsContentVersion]").On("[cmsDocument].[versionId] = [cmsContentVersion].[VersionId]")
|
||||
.InnerJoin("[cmsContent]").On("[cmsContentVersion].[ContentId] = [cmsContent].[nodeId]")
|
||||
.InnerJoin("[umbracoNode]").On("[cmsContent].[nodeId] = [umbracoNode].[id]")
|
||||
.Where("[umbracoNode].[nodeObjectType] = @0", new Guid("c66ba18e-eaf3-4cff-8a22-41b16d66a972"))
|
||||
.Where("[umbracoNode].[id] = @0", 1050);
|
||||
.Where("([umbracoNode].[nodeObjectType] = @0)", new Guid("c66ba18e-eaf3-4cff-8a22-41b16d66a972"))
|
||||
.Where("([umbracoNode].[id] = @0)", 1050);
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
@@ -94,9 +94,9 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
.InnerJoin("[cmsContentVersion]").On("[cmsDocument].[versionId] = [cmsContentVersion].[VersionId]")
|
||||
.InnerJoin("[cmsContent]").On("[cmsContentVersion].[ContentId] = [cmsContent].[nodeId]")
|
||||
.InnerJoin("[umbracoNode]").On("[cmsContent].[nodeId] = [umbracoNode].[id]")
|
||||
.Where("[umbracoNode].[nodeObjectType] = @0", new Guid("c66ba18e-eaf3-4cff-8a22-41b16d66a972"))
|
||||
.Where("[umbracoNode].[id] = @0", 1050)
|
||||
.Where("[cmsContentVersion].[VersionId] = @0", new Guid("2b543516-a944-4ee6-88c6-8813da7aaa07"))
|
||||
.Where("([umbracoNode].[nodeObjectType] = @0)", new Guid("c66ba18e-eaf3-4cff-8a22-41b16d66a972"))
|
||||
.Where("([umbracoNode].[id] = @0)", 1050)
|
||||
.Where("([cmsContentVersion].[VersionId] = @0)", new Guid("2b543516-a944-4ee6-88c6-8813da7aaa07"))
|
||||
.OrderBy("[cmsContentVersion].[VersionDate] DESC");
|
||||
|
||||
var sql = new Sql();
|
||||
@@ -133,8 +133,8 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
expected.Select("*");
|
||||
expected.From("[cmsPropertyData]");
|
||||
expected.InnerJoin("[cmsPropertyType]").On("[cmsPropertyData].[propertytypeid] = [cmsPropertyType].[id]");
|
||||
expected.Where("[cmsPropertyData].[contentNodeId] = @0", 1050);
|
||||
expected.Where("[cmsPropertyData].[versionId] = @0", new Guid("2b543516-a944-4ee6-88c6-8813da7aaa07"));
|
||||
expected.Where("([cmsPropertyData].[contentNodeId] = @0)", 1050);
|
||||
expected.Where("([cmsPropertyData].[versionId] = @0)", new Guid("2b543516-a944-4ee6-88c6-8813da7aaa07"));
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
|
||||
@@ -22,8 +22,8 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
.On("[cmsContentType].[nodeId] = [cmsDocumentType].[contentTypeNodeId]")
|
||||
.InnerJoin("[umbracoNode]")
|
||||
.On("[cmsContentType].[nodeId] = [umbracoNode].[id]")
|
||||
.Where("[umbracoNode].[nodeObjectType] = @0", new Guid("a2cb7800-f571-4787-9638-bc48539a0efb"))
|
||||
.Where("[cmsDocumentType].[IsDefault] = @0", true);
|
||||
.Where("([umbracoNode].[nodeObjectType] = @0)", new Guid("a2cb7800-f571-4787-9638-bc48539a0efb"))
|
||||
.Where("([cmsDocumentType].[IsDefault] = @0)", true);
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
@@ -58,9 +58,9 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
.On("[cmsContentType].[nodeId] = [cmsDocumentType].[contentTypeNodeId]")
|
||||
.InnerJoin("[umbracoNode]")
|
||||
.On("[cmsContentType].[nodeId] = [umbracoNode].[id]")
|
||||
.Where("[umbracoNode].[nodeObjectType] = @0", new Guid("a2cb7800-f571-4787-9638-bc48539a0efb"))
|
||||
.Where("([umbracoNode].[nodeObjectType] = @0)", new Guid("a2cb7800-f571-4787-9638-bc48539a0efb"))
|
||||
.Where("[cmsDocumentType].[IsDefault] = @0", true)
|
||||
.Where("[umbracoNode].[id] = @0", 1050);
|
||||
.Where("([umbracoNode].[id] = @0)", 1050);
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
@@ -112,7 +112,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
var expected = new Sql();
|
||||
expected.Select("*")
|
||||
.From("[cmsContentTypeAllowedContentType]")
|
||||
.Where("[cmsContentTypeAllowedContentType].[Id] = @0", 1050);
|
||||
.Where("([cmsContentTypeAllowedContentType].[Id] = @0)", 1050);
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
@@ -138,7 +138,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
.From("[cmsPropertyTypeGroup]")
|
||||
.RightJoin("[cmsPropertyType]").On("[cmsPropertyTypeGroup].[id] = [cmsPropertyType].[propertyTypeGroupId]")
|
||||
.InnerJoin("[cmsDataType]").On("[cmsPropertyType].[dataTypeId] = [cmsDataType].[nodeId]")
|
||||
.Where("[cmsPropertyType].[contentTypeId] = @0", 1050);
|
||||
.Where("([cmsPropertyType].[contentTypeId] = @0)", 1050);
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
expected.Select("*")
|
||||
.From("[cmsDataType]")
|
||||
.InnerJoin("[umbracoNode]").On("[cmsDataType].[nodeId] = [umbracoNode].[id]")
|
||||
.Where("[umbracoNode].[nodeObjectType] = @0", new Guid("30a2a501-1978-4ddb-a57b-f7efed43ba3c"));
|
||||
.Where("([umbracoNode].[nodeObjectType] = @0)", new Guid("30a2a501-1978-4ddb-a57b-f7efed43ba3c"));
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
|
||||
Console.WriteLine("Model to Sql ExpressionHelper: \n" + result);
|
||||
|
||||
Assert.AreEqual("[umbracoNode].[parentID] = @0", result);
|
||||
Assert.AreEqual("([umbracoNode].[parentID] = @0)", result);
|
||||
Assert.AreEqual(-1, modelToSqlExpressionHelper.GetSqlParameters()[0]);
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
|
||||
Console.WriteLine("Model to Sql ExpressionHelper: \n" + result);
|
||||
|
||||
Assert.AreEqual("[umbracoUser].[userLogin] = @0", result);
|
||||
Assert.AreEqual("([umbracoUser].[userLogin] = @0)", result);
|
||||
Assert.AreEqual("hello@world.com", modelToSqlExpressionHelper.GetSqlParameters()[0]);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
.From("[cmsContentVersion]")
|
||||
.InnerJoin("[cmsContent]").On("[cmsContentVersion].[ContentId] = [cmsContent].[nodeId]")
|
||||
.InnerJoin("[umbracoNode]").On("[cmsContent].[nodeId] = [umbracoNode].[id]")
|
||||
.Where("[umbracoNode].[nodeObjectType] = @0", new Guid("b796f64c-1f99-4ffb-b886-4bf4bc011a9c"));
|
||||
.Where("([umbracoNode].[nodeObjectType] = @0)", new Guid("b796f64c-1f99-4ffb-b886-4bf4bc011a9c"));
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
expected.Select("*")
|
||||
.From("[cmsContentType]")
|
||||
.InnerJoin("[umbracoNode]").On("[cmsContentType].[nodeId] = [umbracoNode].[id]")
|
||||
.Where("[umbracoNode].[nodeObjectType] = @0", new Guid("4ea4382b-2f5a-4c2b-9587-ae9b3cf3602e"));
|
||||
.Where("([umbracoNode].[nodeObjectType] = @0)", new Guid("4ea4382b-2f5a-4c2b-9587-ae9b3cf3602e"));
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
var content = new NodeDto() {NodeId = 123, Path = "-1,123"};
|
||||
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.Path.StartsWith(content.Path) && x.NodeId != content.NodeId);
|
||||
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE (upper([umbracoNode].[path]) LIKE upper(@0) AND [umbracoNode].[id] <> @1)", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ((upper([umbracoNode].[path]) LIKE upper(@0) AND ([umbracoNode].[id] <> @1)))", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual(2, sql.Arguments.Length);
|
||||
Assert.AreEqual(content.Path + "%", sql.Arguments[0]);
|
||||
Assert.AreEqual(content.NodeId, sql.Arguments[1]);
|
||||
@@ -45,7 +45,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
var level = 1;
|
||||
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.Level == level && !x.Path.StartsWith("-20"));
|
||||
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ([umbracoNode].[level] = @0 AND NOT (upper([umbracoNode].[path]) LIKE upper(@1)))", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ((([umbracoNode].[level] = @0) AND NOT (upper([umbracoNode].[path]) LIKE upper(@1))))", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual(2, sql.Arguments.Length);
|
||||
Assert.AreEqual(level, sql.Arguments[0]);
|
||||
Assert.AreEqual("-20%", sql.Arguments[1]);
|
||||
@@ -57,7 +57,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
var level = 1;
|
||||
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.Level == level && x.Path.StartsWith("-20") == false);
|
||||
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ([umbracoNode].[level] = @0 AND NOT (upper([umbracoNode].[path]) LIKE upper(@1)))", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ((([umbracoNode].[level] = @0) AND NOT (upper([umbracoNode].[path]) LIKE upper(@1))))", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual(2, sql.Arguments.Length);
|
||||
Assert.AreEqual(level, sql.Arguments[0]);
|
||||
Assert.AreEqual("-20%", sql.Arguments[1]);
|
||||
@@ -108,7 +108,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
{
|
||||
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.Text.ToUpper() == "hello".ToUpper());
|
||||
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE (upper([umbracoNode].[text]) = upper(@0))", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ((upper([umbracoNode].[text]) = upper(@0)))", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual(1, sql.Arguments.Length);
|
||||
Assert.AreEqual("hello", sql.Arguments[0]);
|
||||
}
|
||||
@@ -118,7 +118,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
{
|
||||
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.Text == 1.ToString());
|
||||
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ([umbracoNode].[text] = @0)", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE (([umbracoNode].[text] = @0))", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual(1, sql.Arguments.Length);
|
||||
Assert.AreEqual("1", sql.Arguments[0]);
|
||||
}
|
||||
@@ -138,7 +138,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
{
|
||||
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.NodeId == 2);
|
||||
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ([umbracoNode].[id] = @0)", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE (([umbracoNode].[id] = @0))", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual(1, sql.Arguments.Length);
|
||||
Assert.AreEqual(2, sql.Arguments[0]);
|
||||
}
|
||||
@@ -148,7 +148,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
{
|
||||
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.NodeId != 2 && x.NodeId != 3);
|
||||
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ([umbracoNode].[id] <> @0 AND [umbracoNode].[id] <> @1)", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ((([umbracoNode].[id] <> @0) AND ([umbracoNode].[id] <> @1)))", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual(2, sql.Arguments.Length);
|
||||
Assert.AreEqual(2, sql.Arguments[0]);
|
||||
Assert.AreEqual(3, sql.Arguments[1]);
|
||||
@@ -159,7 +159,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
{
|
||||
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.Text == "hello" || x.NodeId == 3);
|
||||
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ([umbracoNode].[text] = @0 OR [umbracoNode].[id] = @1)", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ((([umbracoNode].[text] = @0) OR ([umbracoNode].[id] = @1)))", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual(2, sql.Arguments.Length);
|
||||
Assert.AreEqual("hello", sql.Arguments[0]);
|
||||
Assert.AreEqual(3, sql.Arguments[1]);
|
||||
@@ -230,7 +230,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
public void Can_Use_Where_Predicate()
|
||||
{
|
||||
var expected = new Sql();
|
||||
expected.Select("*").From("[cmsContent]").Where("[cmsContent].[nodeId] = @0", 1045);
|
||||
expected.Select("*").From("[cmsContent]").Where("([cmsContent].[nodeId] = @0)", 1045);
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*").From<ContentDto>().Where<ContentDto>(x => x.NodeId == 1045);
|
||||
@@ -246,8 +246,8 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
var expected = new Sql();
|
||||
expected.Select("*")
|
||||
.From("[cmsContent]")
|
||||
.Where("[cmsContent].[nodeId] = @0", 1045)
|
||||
.Where("[cmsContent].[contentType] = @0", 1050);
|
||||
.Where("([cmsContent].[nodeId] = @0)", 1045)
|
||||
.Where("([cmsContent].[contentType] = @0)", 1050);
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
var result = translator.Translate();
|
||||
var strResult = result.SQL;
|
||||
|
||||
string expectedResult = "SELECT *\nFROM umbracoNode\nWHERE ([umbracoNode].[parentID] = @0)";
|
||||
string expectedResult = "SELECT *\nFROM umbracoNode\nWHERE (([umbracoNode].[parentID] = @0))";
|
||||
|
||||
// Assert
|
||||
Assert.That(strResult, Is.Not.Empty);
|
||||
@@ -83,7 +83,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
var result = translator.Translate();
|
||||
var strResult = result.SQL;
|
||||
|
||||
string expectedResult = "SELECT *\nFROM umbracoNode\nWHERE ([cmsContentType].[alias] = @0)";
|
||||
string expectedResult = "SELECT *\nFROM umbracoNode\nWHERE (([cmsContentType].[alias] = @0))";
|
||||
|
||||
// Assert
|
||||
Assert.That(strResult, Is.Not.Empty);
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
templateRepo.AddOrUpdate(template);
|
||||
}
|
||||
unitOfWork.Commit();
|
||||
|
||||
|
||||
var contentType = MockedContentTypes.CreateSimpleContentType();
|
||||
contentType.AllowedTemplates = new[] {templates[0], templates[1]};
|
||||
contentType.SetDefaultTemplate(templates[0]);
|
||||
@@ -127,7 +127,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
repository.AddOrUpdate(contentType);
|
||||
unitOfWork.Commit();
|
||||
|
||||
//create a
|
||||
//create a
|
||||
var contentType2 = (IContentType)new ContentType(contentType, "hello")
|
||||
{
|
||||
Name = "Blahasdfsadf"
|
||||
@@ -293,7 +293,9 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
using (var repository = CreateRepository(unitOfWork))
|
||||
{
|
||||
// Act
|
||||
var contentType = (IContentType)MockedContentTypes.CreateSimpleContentType("test", "Test", propertyGroupName: "testGroup");
|
||||
var contentType = (IContentType)MockedContentTypes.CreateSimpleContentType2("test", "Test", propertyGroupName: "testGroup");
|
||||
|
||||
Assert.AreEqual(4, contentType.PropertyTypes.Count());
|
||||
|
||||
// there is NO mapping from display to contentType, but only from save
|
||||
// to contentType, so if we want to test, let's to it properly!
|
||||
@@ -301,12 +303,18 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
var save = MapToContentTypeSave(display);
|
||||
var mapped = Mapper.Map<IContentType>(save);
|
||||
|
||||
Assert.AreEqual(4, mapped.PropertyTypes.Count());
|
||||
|
||||
repository.AddOrUpdate(mapped);
|
||||
unitOfWork.Commit();
|
||||
|
||||
Assert.AreEqual(4, mapped.PropertyTypes.Count());
|
||||
|
||||
//re-get
|
||||
contentType = repository.Get(mapped.Id);
|
||||
|
||||
Assert.AreEqual(4, contentType.PropertyTypes.Count());
|
||||
|
||||
// Assert
|
||||
Assert.That(contentType.HasIdentity, Is.True);
|
||||
Assert.That(contentType.PropertyGroups.All(x => x.HasIdentity), Is.True);
|
||||
@@ -316,7 +324,11 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
Assert.That(contentType.PropertyGroups.ElementAt(0).Name == "testGroup", Is.True);
|
||||
var groupId = contentType.PropertyGroups.ElementAt(0).Id;
|
||||
Assert.That(contentType.PropertyTypes.All(x => x.PropertyGroupId.Value == groupId), Is.True);
|
||||
|
||||
var propertyTypes = contentType.PropertyTypes.ToArray();
|
||||
Assert.AreEqual("gen", propertyTypes[0].Alias); // just to be sure
|
||||
Assert.IsNull(propertyTypes[0].PropertyGroupId);
|
||||
Assert.IsTrue(propertyTypes.Skip(1).All((x => x.PropertyGroupId.Value == groupId)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -353,7 +365,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
Assert.That(contentType.PropertyTypes.Any(x => x.Alias == "subtitle"), Is.True);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
// this is for tests only because it makes no sense at all to have such a
|
||||
@@ -491,16 +503,16 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
var provider = new PetaPocoUnitOfWorkProvider(Logger);
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
using (var repository = CreateRepository(unitOfWork))
|
||||
{
|
||||
{
|
||||
var ctMain = MockedContentTypes.CreateSimpleContentType();
|
||||
var ctChild1 = MockedContentTypes.CreateSimpleContentType("child1", "Child 1", ctMain, true);
|
||||
var ctChild2 = MockedContentTypes.CreateSimpleContentType("child2", "Child 2", ctChild1, true);
|
||||
|
||||
|
||||
repository.AddOrUpdate(ctMain);
|
||||
repository.AddOrUpdate(ctChild1);
|
||||
repository.AddOrUpdate(ctChild2);
|
||||
repository.AddOrUpdate(ctChild2);
|
||||
unitOfWork.Commit();
|
||||
|
||||
|
||||
// Act
|
||||
|
||||
var resolvedParent = repository.Get(ctMain.Id);
|
||||
@@ -528,7 +540,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
var child3 = MockedContentTypes.CreateSimpleContentType("zyx", "zyx", contentType, randomizeAliases: true);
|
||||
repository.AddOrUpdate(child3);
|
||||
var child2 = MockedContentTypes.CreateSimpleContentType("a123", "a123", contentType, randomizeAliases: true);
|
||||
repository.AddOrUpdate(child2);
|
||||
repository.AddOrUpdate(child2);
|
||||
unitOfWork.Commit();
|
||||
|
||||
// Act
|
||||
@@ -540,7 +552,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
Assert.AreEqual("aabc", contentTypes.ElementAt(1).Name);
|
||||
Assert.AreEqual("zyx", contentTypes.ElementAt(2).Name);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -671,7 +683,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
{
|
||||
var contentType = repository.Get(NodeDto.NodeIdSeed + 1);
|
||||
|
||||
// Act
|
||||
// Act
|
||||
contentType.PropertyGroups["Meta"].PropertyTypes.Remove("description");
|
||||
repository.AddOrUpdate(contentType);
|
||||
unitOfWork.Commit();
|
||||
@@ -841,7 +853,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
Assert.That(contentType.PropertyTypes.Count(), Is.EqualTo(5));
|
||||
Assert.That(contentType.PropertyTypes.Any(x => x.Alias == "metaAuthor"), Is.True);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Umbraco.Tests.Persistence.SyntaxProvider
|
||||
FROM [cmsContentXml]
|
||||
INNER JOIN [umbracoNode]
|
||||
ON [cmsContentXml].[nodeId] = [umbracoNode].[id]
|
||||
WHERE ([umbracoNode].[nodeObjectType] = @0)) x)".Replace(Environment.NewLine, " ").Replace("\n", " ").Replace("\r", " "),
|
||||
WHERE (([umbracoNode].[nodeObjectType] = @0))) x)".Replace(Environment.NewLine, " ").Replace("\n", " ").Replace("\r", " "),
|
||||
sqlOutput.SQL.Replace(Environment.NewLine, " ").Replace("\n", " ").Replace("\r", " "));
|
||||
|
||||
Assert.AreEqual(1, sqlOutput.Arguments.Length);
|
||||
|
||||
@@ -164,6 +164,24 @@ namespace Umbraco.Tests.TestHelpers.Entities
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public static ContentType CreateSimpleContentType2(string alias, string name, IContentType parent = null, bool randomizeAliases = false, string propertyGroupName = "Content")
|
||||
{
|
||||
var contentType = CreateSimpleContentType(alias, name, parent, randomizeAliases, propertyGroupName);
|
||||
|
||||
var propertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = RandomAlias("gen", randomizeAliases),
|
||||
Name = "Gen",
|
||||
Description = "",
|
||||
Mandatory = false,
|
||||
SortOrder = 1,
|
||||
DataTypeDefinitionId = -88
|
||||
};
|
||||
contentType.AddPropertyType(propertyType);
|
||||
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public static ContentType CreateSimpleContentType(string alias, string name, IContentType parent = null, bool randomizeAliases = false, string propertyGroupName = "Content")
|
||||
{
|
||||
var contentType = parent == null ? new ContentType(-1) : new ContentType(parent, alias);
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:autoScale
|
||||
* @element div
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Resize div's automatically to fit to the bottom of the screen, as an optional parameter an y-axis offset can be set
|
||||
* So if you only want to scale the div to 70 pixels from the bottom you pass "70"
|
||||
*
|
||||
* @example
|
||||
<example module="umbraco.directives">
|
||||
<file name="index.html">
|
||||
<div auto-scale="70" class="input-block-level"></div>
|
||||
</file>
|
||||
</example>
|
||||
*/
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:autoScale
|
||||
* @element div
|
||||
* @deprecated
|
||||
* We plan to remove this directive in the next major version of umbraco (8.0). The directive is not recommended to use.
|
||||
* @function
|
||||
* @description
|
||||
* Resize div's automatically to fit to the bottom of the screen, as an optional parameter an y-axis offset can be set
|
||||
* So if you only want to scale the div to 70 pixels from the bottom you pass "70"
|
||||
|
||||
* @example
|
||||
* <example module="umbraco.directives">
|
||||
* <file name="index.html">
|
||||
* <div auto-scale="70" class="input-block-level"></div>
|
||||
* </file>
|
||||
* </example>
|
||||
**/
|
||||
|
||||
angular.module("umbraco.directives")
|
||||
.directive('autoScale', function ($window) {
|
||||
return function (scope, el, attrs) {
|
||||
@@ -35,4 +37,4 @@ angular.module("umbraco.directives")
|
||||
});
|
||||
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbPanel
|
||||
* @name umbraco.directives.directive:detectFold
|
||||
* @deprecated
|
||||
* We plan to remove this directive in the next major version of umbraco (8.0). The directive is not recommended to use.
|
||||
* @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
|
||||
* exceeds the height of the window
|
||||
**/
|
||||
|
||||
angular.module("umbraco.directives.html")
|
||||
.directive('detectFold', function ($timeout, $log, windowResizeListener) {
|
||||
return {
|
||||
|
||||
+4
-1
@@ -1,11 +1,14 @@
|
||||
/**
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbItemSorter
|
||||
* @deprecated
|
||||
* We plan to remove this directive in the next major version of umbraco (8.0). The directive is not recommended to use.
|
||||
* @function
|
||||
* @element ANY
|
||||
* @restrict E
|
||||
* @description A re-usable directive for sorting items
|
||||
**/
|
||||
|
||||
function umbItemSorter(angularHelper) {
|
||||
return {
|
||||
scope: {
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbContentName
|
||||
* @deprecated
|
||||
* We plan to remove this directive in the next major version of umbraco (8.0). The directive is not recommended to use.
|
||||
* @restrict E
|
||||
* @function
|
||||
* @description
|
||||
* Used by editors that require naming an entity. Shows a textbox/headline with a required validator within it's own form.
|
||||
**/
|
||||
|
||||
angular.module("umbraco.directives")
|
||||
.directive('umbContentName', function ($timeout, localizationService) {
|
||||
return {
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbHeader
|
||||
* @deprecated
|
||||
* We plan to remove this directive in the next major version of umbraco (8.0). The directive is not recommended to use.
|
||||
* @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) {
|
||||
return {
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
/**
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:login
|
||||
* @name umbraco.directives.directive:umbLogin
|
||||
* @deprecated
|
||||
* We plan to remove this directive in the next major version of umbraco (8.0). The directive is not recommended to use.
|
||||
* @function
|
||||
* @element ANY
|
||||
* @restrict E
|
||||
**/
|
||||
|
||||
function loginDirective() {
|
||||
return {
|
||||
restrict: "E", // restrict to an element
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbOptionsMenu
|
||||
* @deprecated
|
||||
* We plan to remove this directive in the next major version of umbraco (8.0). The directive is not recommended to use.
|
||||
* @function
|
||||
* @element ANY
|
||||
* @restrict E
|
||||
**/
|
||||
|
||||
angular.module("umbraco.directives")
|
||||
.directive('umbOptionsMenu', function ($injector, treeService, navigationService, umbModelMapper, appState) {
|
||||
return {
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbPhotoFolder
|
||||
* @deprecated
|
||||
* We plan to remove this directive in the next major version of umbraco (8.0). The directive is not recommended to use.
|
||||
* @restrict E
|
||||
**/
|
||||
|
||||
angular.module("umbraco.directives.html")
|
||||
.directive('umbPhotoFolder', function($compile, $log, $timeout, $filter, umbPhotoFolderHelper) {
|
||||
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbSort
|
||||
* @element div
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Resize div's automatically to fit to the bottom of the screen, as an optional parameter an y-axis offset can be set
|
||||
* So if you only want to scale the div to 70 pixels from the bottom you pass "70"
|
||||
*
|
||||
* @example
|
||||
<example module="umbraco.directives">
|
||||
<file name="index.html">
|
||||
<div umb-sort="70" class="input-block-level"></div>
|
||||
</file>
|
||||
</example>
|
||||
*/
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbSort
|
||||
* @deprecated
|
||||
* We plan to remove this directive in the next major version of umbraco (8.0). The directive is not recommended to use.
|
||||
*
|
||||
* @element div
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Resize div's automatically to fit to the bottom of the screen, as an optional parameter an y-axis offset can be set
|
||||
* So if you only want to scale the div to 70 pixels from the bottom you pass "70"
|
||||
*
|
||||
* @example
|
||||
* <example module="umbraco.directives">
|
||||
* <file name="index.html">
|
||||
* <div umb-sort="70" class="input-block-level"></div>
|
||||
* </file>
|
||||
* </example>
|
||||
**/
|
||||
|
||||
angular.module("umbraco.directives")
|
||||
.value('umbSortContextInternal',{})
|
||||
.directive('umbSort', function($log,umbSortContextInternal) {
|
||||
@@ -165,4 +169,4 @@ angular.module("umbraco.directives")
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
});
|
||||
@@ -1,8 +1,12 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbTabView
|
||||
* @deprecated
|
||||
* We plan to remove this directive in the next major version of umbraco (8.0). The directive is not recommended to use.
|
||||
*
|
||||
* @restrict E
|
||||
**/
|
||||
|
||||
angular.module("umbraco.directives")
|
||||
.directive('umbTabView', function($timeout, $log){
|
||||
return {
|
||||
|
||||
+4
@@ -1,8 +1,12 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbUploadDropzone
|
||||
* @deprecated
|
||||
* We plan to remove this directive in the next major version of umbraco (8.0). The directive is not recommended to use.
|
||||
*
|
||||
* @restrict E
|
||||
**/
|
||||
|
||||
angular.module("umbraco.directives.html")
|
||||
.directive('umbUploadDropzone', function(){
|
||||
return {
|
||||
|
||||
+68
@@ -1,3 +1,71 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbButton
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
Use this directive to render an umbraco button. The directive can be used to generate all types of buttons, set type, style, translation, shortcut and much more.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="My.Controller as vm">
|
||||
|
||||
<umb-button
|
||||
action="vm.clickButton()"
|
||||
type="button"
|
||||
button-style="success"
|
||||
state="vm.buttonState"
|
||||
shortcut="ctrl+c"
|
||||
label="My button"
|
||||
disabled="vm.buttonState === 'busy'">
|
||||
</umb-button>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Controller example</h3>
|
||||
<pre>
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function Controller(myService) {
|
||||
|
||||
var vm = this;
|
||||
vm.buttonState = "init";
|
||||
|
||||
vm.clickButton = clickButton;
|
||||
|
||||
function clickButton() {
|
||||
|
||||
vm.buttonState = "busy";
|
||||
|
||||
myService.clickButton().then(function() {
|
||||
vm.buttonState = "success";
|
||||
}, function() {
|
||||
vm.buttonState = "error";
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("My.Controller", Controller);
|
||||
|
||||
})();
|
||||
</pre>
|
||||
|
||||
@param {callback} action The button action which should be performed when the button is clicked.
|
||||
@param {string=} href Url/Path to navigato to.
|
||||
@param {string=} type Set the button type ("button" or "submit").
|
||||
@param {string=} buttonStyle Set the style of the button. The directive uses the default bootstrap styles ("primary", "info", "success", "warning", "danger", "inverse", "link").
|
||||
@param {string=} state Set a progress state on the button ("init", "busy", "success", "error").
|
||||
@param {string=} shortcut Set a keyboard shortcut for the button ("ctrl+c").
|
||||
@param {string=} label Set the button label.
|
||||
@param {string=} labelKey Set a localization key to make a multi lingual button ("general_buttonText").
|
||||
@param {string=} icon Set a button icon. Can only be used when buttonStyle is "link".
|
||||
@param {boolean=} disabled Set to <code>true</code> to disable the button.
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
|
||||
+91
@@ -1,3 +1,94 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbButtonGroup
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
Use this directive to render a button with a dropdown of alternative actions.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="My.Controller as vm">
|
||||
|
||||
<umb-button-group
|
||||
ng-if="vm.buttonGroup"
|
||||
default-button="vm.buttonGroup.defaultButton"
|
||||
sub-buttons="vm.buttonGroup.subButtons"
|
||||
direction="down"
|
||||
float="right">
|
||||
</umb-button-group>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Controller example</h3>
|
||||
<pre>
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function Controller() {
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.buttonGroup = {
|
||||
defaultButton: {
|
||||
labelKey: "general_defaultButton",
|
||||
hotKey: "ctrl+d",
|
||||
hotKeyWhenHidden: true,
|
||||
handler: function() {
|
||||
// do magic here
|
||||
}
|
||||
},
|
||||
subButtons: [
|
||||
{
|
||||
labelKey: "general_subButton",
|
||||
hotKey: "ctrl+b",
|
||||
hotKeyWhenHidden: true,
|
||||
handler: function() {
|
||||
// do magic here
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("My.Controller", Controller);
|
||||
|
||||
})();
|
||||
</pre>
|
||||
|
||||
<h3>Button model description</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>labekKey</strong>
|
||||
<small>(string)</small> -
|
||||
Set a localization key to make a multi lingual button ("general_buttonText").
|
||||
</li>
|
||||
<li>
|
||||
<strong>hotKey</strong>
|
||||
<small>(array)</small> -
|
||||
Set a keyboard shortcut for the button ("ctrl+c").
|
||||
</li>
|
||||
<li>
|
||||
<strong>hotKeyWhenHidden</strong>
|
||||
<small>(boolean)</small> -
|
||||
As a default the hotkeys only works on elements visible in the UI. Set to <code>true</code> to set a hotkey on the hidden sub buttons.
|
||||
</li>
|
||||
<li>
|
||||
<strong>handler</strong>
|
||||
<small>(callback)</small> -
|
||||
Set a callback to handle button click events.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@param {object} defaultButton The model of the default button.
|
||||
@param {array} subButtons Array of sub buttons.
|
||||
@param {string=} state Set a progress state on the button ("init", "busy", "success", "error").
|
||||
@param {string=} direction Set the direction of the dropdown ("up", "down").
|
||||
@param {string=} float Set the float of the dropdown. ("left", "right").
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
|
||||
+40
@@ -1,3 +1,43 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbEditorSubHeader
|
||||
@restrict E
|
||||
|
||||
@description
|
||||
Use this directive to construct a sub header in the main editor window.
|
||||
The sub header is sticky and will follow along down the page when scrolling.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="MySection.Controller as vm">
|
||||
|
||||
<form name="mySectionForm" novalidate>
|
||||
|
||||
<umb-editor-view>
|
||||
|
||||
<umb-editor-container>
|
||||
|
||||
<umb-editor-sub-header>
|
||||
// sub header content here
|
||||
</umb-editor-sub-header>
|
||||
|
||||
</umb-editor-container>
|
||||
|
||||
</umb-editor-view>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Use in combination with</h3>
|
||||
<ul>
|
||||
<li>{@link umbraco.directives.directive:umbEditorSubHeaderContentLeft umbEditorSubHeaderContentLeft}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorSubHeaderContentRight umbEditorSubHeaderContentRight}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorSubHeaderSection umbEditorSubHeaderSection}</li>
|
||||
</ul>
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
|
||||
+47
@@ -1,3 +1,50 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbEditorSubHeaderContentLeft
|
||||
@restrict E
|
||||
|
||||
@description
|
||||
Use this directive to left align content in a sub header in the main editor window.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="MySection.Controller as vm">
|
||||
|
||||
<form name="mySectionForm" novalidate>
|
||||
|
||||
<umb-editor-view>
|
||||
|
||||
<umb-editor-container>
|
||||
|
||||
<umb-editor-sub-header>
|
||||
|
||||
<umb-editor-sub-header-content-left>
|
||||
// left content here
|
||||
</umb-editor-sub-header-content-left>
|
||||
|
||||
<umb-editor-sub-header-content-right>
|
||||
// right content here
|
||||
</umb-editor-sub-header-content-right>
|
||||
|
||||
</umb-editor-sub-header>
|
||||
|
||||
</umb-editor-container>
|
||||
|
||||
</umb-editor-view>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Use in combination with</h3>
|
||||
<ul>
|
||||
<li>{@link umbraco.directives.directive:umbEditorSubHeader umbEditorSubHeader}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorSubHeaderContentRight umbEditorSubHeaderContentRight}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorSubHeaderSection umbEditorSubHeaderSection}</li>
|
||||
</ul>
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
|
||||
+47
@@ -1,3 +1,50 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbEditorSubHeaderContentRight
|
||||
@restrict E
|
||||
|
||||
@description
|
||||
Use this directive to rigt align content in a sub header in the main editor window.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="MySection.Controller as vm">
|
||||
|
||||
<form name="mySectionForm" novalidate>
|
||||
|
||||
<umb-editor-view>
|
||||
|
||||
<umb-editor-container>
|
||||
|
||||
<umb-editor-sub-header>
|
||||
|
||||
<umb-editor-sub-header-content-left>
|
||||
// left content here
|
||||
</umb-editor-sub-header-content-left>
|
||||
|
||||
<umb-editor-sub-header-content-right>
|
||||
// right content here
|
||||
</umb-editor-sub-header-content-right>
|
||||
|
||||
</umb-editor-sub-header>
|
||||
|
||||
</umb-editor-container>
|
||||
|
||||
</umb-editor-view>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Use in combination with</h3>
|
||||
<ul>
|
||||
<li>{@link umbraco.directives.directive:umbEditorSubHeader umbEditorSubHeader}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorSubHeaderContentLeft umbEditorSubHeaderContentLeft}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorSubHeaderSection umbEditorSubHeaderSection}</li>
|
||||
</ul>
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
|
||||
+55
@@ -1,3 +1,58 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbEditorSubHeaderSection
|
||||
@restrict E
|
||||
|
||||
@description
|
||||
Use this directive to create sections, divided by borders, in a sub header in the main editor window.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="MySection.Controller as vm">
|
||||
|
||||
<form name="mySectionForm" novalidate>
|
||||
|
||||
<umb-editor-view>
|
||||
|
||||
<umb-editor-container>
|
||||
|
||||
<umb-editor-sub-header>
|
||||
|
||||
<umb-editor-sub-header-content-right>
|
||||
|
||||
<umb-editor-sub-header-section>
|
||||
// section content here
|
||||
</umb-editor-sub-header-section>
|
||||
|
||||
<umb-editor-sub-header-section>
|
||||
// section content here
|
||||
</umb-editor-sub-header-section>
|
||||
|
||||
<umb-editor-sub-header-section>
|
||||
// section content here
|
||||
</umb-editor-sub-header-section>
|
||||
|
||||
</umb-editor-sub-header-content-right>
|
||||
|
||||
</umb-editor-sub-header>
|
||||
|
||||
</umb-editor-container>
|
||||
|
||||
</umb-editor-view>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Use in combination with</h3>
|
||||
<ul>
|
||||
<li>{@link umbraco.directives.directive:umbEditorSubHeader umbEditorSubHeader}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorSubHeaderContentLeft umbEditorSubHeaderContentLeft}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorSubHeaderContentRight umbEditorSubHeaderContentRight}</li>
|
||||
</ul>
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
|
||||
+44
@@ -1,3 +1,47 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbBreadcrumbs
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
Use this directive to generate a list of breadcrumbs.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="My.Controller as vm">
|
||||
<umb-breadcrumbs
|
||||
ng-if="vm.ancestors && vm.ancestors.length > 0"
|
||||
ancestors="vm.ancestors"
|
||||
entity-type="content">
|
||||
</umb-breadcrumbs>
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Controller example</h3>
|
||||
<pre>
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function Controller(myService) {
|
||||
|
||||
var vm = this;
|
||||
vm.ancestors = [];
|
||||
|
||||
myService.getAncestors().then(function(ancestors){
|
||||
vm.ancestors = ancestors;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("My.Controller", Controller);
|
||||
})();
|
||||
</pre>
|
||||
|
||||
@param {array} ancestors Array of ancestors
|
||||
@param {string} entityType The content entity type (member, media, content).
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
|
||||
+39
@@ -1,3 +1,42 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbEditorContainer
|
||||
@restrict E
|
||||
|
||||
@description
|
||||
Use this directive to construct a main content area inside the main editor window.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="Umbraco.Controller as vm">
|
||||
|
||||
<umb-editor-view>
|
||||
|
||||
<umb-editor-header
|
||||
// header configuration>
|
||||
</umb-editor-header>
|
||||
|
||||
<umb-editor-container>
|
||||
// main content here
|
||||
</umb-editor-container>
|
||||
|
||||
<umb-editor-footer>
|
||||
// footer content here
|
||||
</umb-editor-footer>
|
||||
|
||||
</umb-editor-view>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Use in combination with</h3>
|
||||
<ul>
|
||||
<li>{@link umbraco.directives.directive:umbEditorView umbEditorView}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorHeader umbEditorHeader}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorFooter umbEditorFooter}</li>
|
||||
</ul>
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
|
||||
+45
@@ -1,3 +1,48 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbEditorFooter
|
||||
@restrict E
|
||||
|
||||
@description
|
||||
Use this directive to construct a footer inside the main editor window.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="MySection.Controller as vm">
|
||||
|
||||
<form name="mySectionForm" novalidate>
|
||||
|
||||
<umb-editor-view>
|
||||
|
||||
<umb-editor-header
|
||||
// header configuration>
|
||||
</umb-editor-header>
|
||||
|
||||
<umb-editor-container>
|
||||
// main content here
|
||||
</umb-editor-container>
|
||||
|
||||
<umb-editor-footer>
|
||||
// footer content here
|
||||
</umb-editor-footer>
|
||||
|
||||
</umb-editor-view>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Use in combination with</h3>
|
||||
<ul>
|
||||
<li>{@link umbraco.directives.directive:umbEditorView umbEditorView}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorHeader umbEditorHeader}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorContainer umbEditorContainer}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorFooterContentLeft umbEditorFooterContentLeft}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorFooterContentRight umbEditorFooterContentRight}</li>
|
||||
</ul>
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
|
||||
+45
@@ -1,3 +1,48 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbEditorFooterContentLeft
|
||||
@restrict E
|
||||
|
||||
@description
|
||||
Use this directive to align content left inside the main editor footer.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="MySection.Controller as vm">
|
||||
|
||||
<form name="mySectionForm" novalidate>
|
||||
|
||||
<umb-editor-view>
|
||||
|
||||
<umb-editor-footer>
|
||||
|
||||
<umb-editor-footer-content-left>
|
||||
// align content left
|
||||
</umb-editor-footer-content-left>
|
||||
|
||||
<umb-editor-footer-content-right>
|
||||
// align content right
|
||||
</umb-editor-footer-content-right>
|
||||
|
||||
</umb-editor-footer>
|
||||
|
||||
</umb-editor-view>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Use in combination with</h3>
|
||||
<ul>
|
||||
<li>{@link umbraco.directives.directive:umbEditorView umbEditorView}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorHeader umbEditorHeader}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorContainer umbEditorContainer}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorFooter umbEditorFooter}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorFooterContentRight umbEditorFooterContentRight}</li>
|
||||
</ul>
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
|
||||
+45
@@ -1,3 +1,48 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbEditorFooterContentRight
|
||||
@restrict E
|
||||
|
||||
@description
|
||||
Use this directive to align content right inside the main editor footer.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="MySection.Controller as vm">
|
||||
|
||||
<form name="mySectionForm" novalidate>
|
||||
|
||||
<umb-editor-view>
|
||||
|
||||
<umb-editor-footer>
|
||||
|
||||
<umb-editor-footer-content-left>
|
||||
// align content left
|
||||
</umb-editor-footer-content-left>
|
||||
|
||||
<umb-editor-footer-content-right>
|
||||
// align content right
|
||||
</umb-editor-footer-content-right>
|
||||
|
||||
</umb-editor-footer>
|
||||
|
||||
</umb-editor-view>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Use in combination with</h3>
|
||||
<ul>
|
||||
<li>{@link umbraco.directives.directive:umbEditorView umbEditorView}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorHeader umbEditorHeader}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorContainer umbEditorContainer}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorFooter umbEditorFooter}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorFooterContentLeft umbEditorFooterContentLeft}</li>
|
||||
</ul>
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
|
||||
+203
@@ -1,3 +1,206 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbEditorHeader
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
Use this directive to construct a header inside the main editor window.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="MySection.Controller as vm">
|
||||
|
||||
<form name="mySectionForm" novalidate>
|
||||
|
||||
<umb-editor-view>
|
||||
|
||||
<umb-editor-header
|
||||
name="vm.content.name"
|
||||
hide-alias="true"
|
||||
hide-description="true"
|
||||
hide-icon="true">
|
||||
</umb-editor-header>
|
||||
|
||||
<umb-editor-container>
|
||||
// main content here
|
||||
</umb-editor-container>
|
||||
|
||||
<umb-editor-footer>
|
||||
// footer content here
|
||||
</umb-editor-footer>
|
||||
|
||||
</umb-editor-view>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Markup example - with tabs</h3>
|
||||
<pre>
|
||||
<div ng-controller="MySection.Controller as vm">
|
||||
|
||||
<form name="mySectionForm" val-form-manager novalidate>
|
||||
|
||||
<umb-editor-view umb-tabs>
|
||||
|
||||
<umb-editor-header
|
||||
name="vm.content.name"
|
||||
tabs="vm.content.tabs"
|
||||
hide-alias="true"
|
||||
hide-description="true"
|
||||
hide-icon="true">
|
||||
</umb-editor-header>
|
||||
|
||||
<umb-editor-container>
|
||||
<umb-tabs-content class="form-horizontal" view="true">
|
||||
<umb-tab id="tab{{tab.id}}" ng-repeat="tab in vm.content.tabs" rel="{{tab.id}}">
|
||||
|
||||
<div ng-show="tab.alias==='tab1'">
|
||||
// tab 1 content
|
||||
</div>
|
||||
|
||||
<div ng-show="tab.alias==='tab2'">
|
||||
// tab 2 content
|
||||
</div>
|
||||
|
||||
</umb-tab>
|
||||
</umb-tabs-content>
|
||||
</umb-editor-container>
|
||||
|
||||
<umb-editor-footer>
|
||||
// footer content here
|
||||
</umb-editor-footer>
|
||||
|
||||
</umb-editor-view>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Controller example - with tabs</h3>
|
||||
<pre>
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function Controller() {
|
||||
|
||||
var vm = this;
|
||||
vm.content = {
|
||||
name: "",
|
||||
tabs: [
|
||||
{
|
||||
id: 1,
|
||||
label: "Tab 1",
|
||||
alias: "tab1",
|
||||
active: true
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
label: "Tab 2",
|
||||
alias: "tab2",
|
||||
active: false
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("MySection.Controller", Controller);
|
||||
})();
|
||||
</pre>
|
||||
|
||||
<h3>Markup example - with sub views</h3>
|
||||
<pre>
|
||||
<div ng-controller="MySection.Controller as vm">
|
||||
|
||||
<form name="mySectionForm" val-form-manager novalidate>
|
||||
|
||||
<umb-editor-view>
|
||||
|
||||
<umb-editor-header
|
||||
name="vm.content.name"
|
||||
navigation="vm.content.navigation"
|
||||
hide-alias="true"
|
||||
hide-description="true"
|
||||
hide-icon="true">
|
||||
</umb-editor-header>
|
||||
|
||||
<umb-editor-container>
|
||||
|
||||
<umb-editor-sub-views
|
||||
sub-views="vm.content.navigation"
|
||||
model="vm.content">
|
||||
</umb-editor-sub-views>
|
||||
|
||||
</umb-editor-container>
|
||||
|
||||
<umb-editor-footer>
|
||||
// footer content here
|
||||
</umb-editor-footer>
|
||||
|
||||
</umb-editor-view>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Controller example - with sub views</h3>
|
||||
<pre>
|
||||
(function () {
|
||||
|
||||
"use strict";
|
||||
|
||||
function Controller() {
|
||||
|
||||
var vm = this;
|
||||
vm.content = {
|
||||
name: "",
|
||||
navigation: [
|
||||
{
|
||||
"name": "Section 1",
|
||||
"icon": "icon-document-dashed-line",
|
||||
"view": "/App_Plugins/path/to/html.html",
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"name": "Section 2",
|
||||
"icon": "icon-list",
|
||||
"view": "/App_Plugins/path/to/html.html",
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("MySection.Controller", Controller);
|
||||
})();
|
||||
</pre>
|
||||
|
||||
<h3>Use in combination with</h3>
|
||||
<ul>
|
||||
<li>{@link umbraco.directives.directive:umbEditorView umbEditorView}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorContainer umbEditorContainer}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorFooter umbEditorFooter}</li>
|
||||
</ul>
|
||||
|
||||
@param {string} name The content name.
|
||||
@param {array=} tabs Array of tabs. See example above.
|
||||
@param {array=} navigation Array of sub views. See example above.
|
||||
@param {boolean=} nameLocked Set to <code>true</code> to lock the name.
|
||||
@param {object=} menu Add a context menu to the editor.
|
||||
@param {string=} icon Show and edit the content icon. Opens an overlay to change the icon.
|
||||
@param {boolean=} hideIcon Set to <code>true</code> to hide icon.
|
||||
@param {string=} alias show and edit the content alias.
|
||||
@param {boolean=} hideAlias Set to <code>true</code> to hide alias.
|
||||
@param {string=} description Add a description to the content.
|
||||
@param {boolean=} hideDescription Set to <code>true</code> to hide description.
|
||||
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
|
||||
+63
@@ -1,3 +1,66 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbEditorView
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
Use this directive to construct the main editor window.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="MySection.Controller as vm">
|
||||
|
||||
<form name="mySectionForm" novalidate>
|
||||
|
||||
<umb-editor-view>
|
||||
|
||||
<umb-editor-header
|
||||
name="vm.content.name"
|
||||
hide-alias="true"
|
||||
hide-description="true"
|
||||
hide-icon="true">
|
||||
</umb-editor-header>
|
||||
|
||||
<umb-editor-container>
|
||||
// main content here
|
||||
</umb-editor-container>
|
||||
|
||||
<umb-editor-footer>
|
||||
// footer content here
|
||||
</umb-editor-footer>
|
||||
|
||||
</umb-editor-view>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
<h3>Controller example</h3>
|
||||
<pre>
|
||||
(function () {
|
||||
|
||||
"use strict";
|
||||
|
||||
function Controller() {
|
||||
|
||||
var vm = this;
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("MySection.Controller", Controller);
|
||||
})();
|
||||
</pre>
|
||||
|
||||
|
||||
<h3>Use in combination with</h3>
|
||||
<ul>
|
||||
<li>{@link umbraco.directives.directive:umbEditorHeader umbEditorHeader}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorContainer umbEditorContainer}</li>
|
||||
<li>{@link umbraco.directives.directive:umbEditorFooter umbEditorFooter}</li>
|
||||
</ul>
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
|
||||
+4
-3
@@ -1,7 +1,8 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:headline
|
||||
**/
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:hotkey
|
||||
**/
|
||||
|
||||
angular.module("umbraco.directives")
|
||||
.directive('hotkey', function($window, keyboardService, $log) {
|
||||
|
||||
|
||||
+14
-4
@@ -1,13 +1,23 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:preventDefault
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:preventDefault
|
||||
|
||||
@description
|
||||
Use this directive to prevent default action of an element. Effectively implementing <a href="https://api.jquery.com/event.preventdefault/">jQuery's preventdefault</a>
|
||||
|
||||
<h3>Markup example</h3>
|
||||
|
||||
<pre>
|
||||
<a href="https://umbraco.com" prevent-default>Don't go to Umbraco.com</a>
|
||||
</pre>
|
||||
|
||||
**/
|
||||
angular.module("umbraco.directives")
|
||||
.directive('preventDefault', function() {
|
||||
return function(scope, element, attrs) {
|
||||
|
||||
var enabled = true;
|
||||
//check if there's a value for the attribute, if there is and it's false then we conditionally don't
|
||||
//check if there's a value for the attribute, if there is and it's false then we conditionally don't
|
||||
//prevent default.
|
||||
if (attrs.preventDefault) {
|
||||
attrs.$observe("preventDefault", function (newVal) {
|
||||
@@ -26,4 +36,4 @@ angular.module("umbraco.directives")
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbProperty
|
||||
* @name umbraco.directives.directive:umbControlGroup
|
||||
* @restrict E
|
||||
**/
|
||||
angular.module("umbraco.directives.html")
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbProperty
|
||||
* @name umbraco.directives.directive:umbPane
|
||||
* @restrict E
|
||||
**/
|
||||
angular.module("umbraco.directives.html")
|
||||
|
||||
+1
-2
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbCropsy
|
||||
* @name umbraco.directives.directive:umbImageGravity
|
||||
* @restrict E
|
||||
* @function
|
||||
* @description
|
||||
* Used by editors that require naming an entity. Shows a textbox/headline with a required validator within it's own form.
|
||||
**/
|
||||
angular.module("umbraco.directives")
|
||||
.directive('umbImageGravity', function ($timeout, localizationService, $log) {
|
||||
|
||||
+1
-2
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbCropsy
|
||||
* @name umbraco.directives.directive:umbImageThumbnail
|
||||
* @restrict E
|
||||
* @function
|
||||
* @description
|
||||
* Used by editors that require naming an entity. Shows a textbox/headline with a required validator within it's own form.
|
||||
**/
|
||||
angular.module("umbraco.directives")
|
||||
.directive('umbImageThumbnail',
|
||||
|
||||
+405
-4
@@ -1,8 +1,409 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbProperty
|
||||
* @restrict E
|
||||
**/
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbOverlay
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="My.Controller as vm">
|
||||
|
||||
<button type="button" ng-click="vm.openOverlay()"></button>
|
||||
|
||||
<umb-overlay
|
||||
ng-if="vm.overlay.show"
|
||||
model="vm.overlay"
|
||||
view="vm.overlay.view"
|
||||
position="right">
|
||||
</umb-overlay>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Controller example</h3>
|
||||
<pre>
|
||||
(function () {
|
||||
|
||||
"use strict";
|
||||
|
||||
function Controller() {
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.openOverlay = openOverlay;
|
||||
|
||||
function openOverlay() {
|
||||
|
||||
vm.overlay = {
|
||||
view: "mediapicker",
|
||||
show: true,
|
||||
submit: function(model) {
|
||||
|
||||
vm.overlay.show = false;
|
||||
vm.overlay = null;
|
||||
},
|
||||
close: function(oldModel) {
|
||||
vm.overlay.show = false;
|
||||
vm.overlay = null;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("My.Controller", Controller);
|
||||
})();
|
||||
</pre>
|
||||
|
||||
<h1>General Options</h1>
|
||||
Lorem ipsum dolor sit amet..
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Param</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>model.title</td>
|
||||
<td>String</td>
|
||||
<td>Set the title of the overlay.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>model.subTitle</td>
|
||||
<td>String</td>
|
||||
<td>Set the subtitle of the overlay.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>model.submitButtonLabel</td>
|
||||
<td>String</td>
|
||||
<td>Set an alternate submit button text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>model.submitButtonLabelKey</td>
|
||||
<td>String</td>
|
||||
<td>Set an alternate submit button label key for localized texts</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>model.hideSubmitButton</td>
|
||||
<td>Boolean</td>
|
||||
<td>Hides the submit button</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>model.closeButtonLabel</td>
|
||||
<td>String</td>
|
||||
<td>Set an alternate close button text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>model.closeButtonLabelKey</td>
|
||||
<td>String</td>
|
||||
<td>Set an alternate close button label key for localized texts</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>model.show</td>
|
||||
<td>Boolean</td>
|
||||
<td>Show/hide the overlay</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>model.submit</td>
|
||||
<td>Function</td>
|
||||
<td>Callback function when the overlay submits. Returns the overlay model object</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>model.close</td>
|
||||
<td>Function</td>
|
||||
<td>Callback function when the overlay closes. Returns a copy of the overlay model object before being modified</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
<h1>Content Picker</h1>
|
||||
Opens a content picker.</br>
|
||||
<strong>view: </strong>contentpicker
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Param</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>model.multiPicker</td>
|
||||
<td>Boolean</td>
|
||||
<td>Pick one or multiple items</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>model.selection</td>
|
||||
<td>Array</td>
|
||||
<td>Array of content objects</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
<h1>Icon Picker</h1>
|
||||
Opens an icon picker.</br>
|
||||
<strong>view: </strong>iconpicker
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>model.icon</td>
|
||||
<td>String</td>
|
||||
<td>The icon class</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1>Item Picker</h1>
|
||||
Opens an item picker.</br>
|
||||
<strong>view: </strong>itempicker
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Param</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>model.availableItems</td>
|
||||
<td>Array</td>
|
||||
<td>Array of available items</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>model.selectedItems</td>
|
||||
<td>Array</td>
|
||||
<td>Array of selected items. When passed in the selected items will be filtered from the available items.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>model.filter</td>
|
||||
<td>Boolean</td>
|
||||
<td>Set to false to hide the filter</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>model.selectedItem</td>
|
||||
<td>Object</td>
|
||||
<td>The selected item</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1>Macro Picker</h1>
|
||||
Opens a media picker.</br>
|
||||
<strong>view: </strong>macropicker
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Param</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>model.dialogData</td>
|
||||
<td>Object</td>
|
||||
<td>Object which contains array of allowedMacros. Set to <code>null</code> to allow all.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>model.macroParams</td>
|
||||
<td>Array</td>
|
||||
<td>Array of macro params</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>model.selectedMacro</td>
|
||||
<td>Object</td>
|
||||
<td>The selected macro</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h1>Media Picker</h1>
|
||||
Opens a media picker.</br>
|
||||
<strong>view: </strong>mediapicker
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Param</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>model.multiPicker</td>
|
||||
<td>Boolean</td>
|
||||
<td>Pick one or multiple items</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>model.onlyImages</td>
|
||||
<td>Boolean</td>
|
||||
<td>Only display files that have an image file-extension</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>model.disableFolderSelect</td>
|
||||
<td>Boolean</td>
|
||||
<td>Disable folder selection</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>model.selectedImages</td>
|
||||
<td>Array</td>
|
||||
<td>Array of selected images</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h1>Member Group Picker</h1>
|
||||
Opens a member group picker.</br>
|
||||
<strong>view: </strong>membergrouppicker
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Param</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>model.multiPicker</td>
|
||||
<td>Boolean</td>
|
||||
<td>Pick one or multiple items</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>model.selectedMemberGroup</td>
|
||||
<td>String</td>
|
||||
<td>The selected member group</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>model.selectedMemberGroups (multiPicker)</td>
|
||||
<td>Array</td>
|
||||
<td>The selected member groups</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h1>Member Picker</h1>
|
||||
Opens a member picker. </br>
|
||||
<strong>view: </strong>memberpicker
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Param</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>model.multiPicker</td>
|
||||
<td>Boolean</td>
|
||||
<td>Pick one or multiple items</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>model.selection</td>
|
||||
<td>Array</td>
|
||||
<td>Array of selected members/td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h1>YSOD</h1>
|
||||
Opens an overlay to show a custom YSOD. </br>
|
||||
<strong>view: </strong>ysod
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Param</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>model.error</td>
|
||||
<td>Object</td>
|
||||
<td>Error object</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@param {object} model Overlay options.
|
||||
@param {string} view Path to view or one of the default view names.
|
||||
@param {string} position The overlay position ("left", "right", "center": "target").
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
+49
@@ -1,3 +1,52 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbGenerateAlias
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
Use this directive to generate a camelCased umbraco alias.
|
||||
When the aliasFrom value is changed the directive will get a formatted alias from the server and update the alias model. If "enableLock" is set to <code>true</code>
|
||||
the directive will use {@link umbraco.directives.directive:umbLockedField umbLockedField} to lock and unlock the alias.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="My.Controller as vm">
|
||||
|
||||
<input type="text" ng-model="vm.name" />
|
||||
|
||||
<umb-generate-alias
|
||||
enable-lock="true"
|
||||
alias-from="vm.name"
|
||||
alias="vm.alias">
|
||||
</umb-generate-alias>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Controller example</h3>
|
||||
<pre>
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function Controller() {
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.name = "";
|
||||
vm.alias = "";
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("My.Controller", Controller);
|
||||
})();
|
||||
</pre>
|
||||
|
||||
@param {string} alias (<code>binding</code>): The model where the alias is bound.
|
||||
@param {string} aliasFrom (<code>binding</code>): The model to generate the alias from.
|
||||
@param {boolean=} enableLock (<code>binding</code>): Set to <code>true</code> to add a lock next to the alias from where it can be unlocked and changed.
|
||||
**/
|
||||
|
||||
angular.module("umbraco.directives")
|
||||
.directive('umbGenerateAlias', function ($timeout, entityResource) {
|
||||
return {
|
||||
|
||||
+114
@@ -1,3 +1,117 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbChildSelector
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
Use this directive to render a ui component for selecting child items to a parent node.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="My.Controller as vm">
|
||||
|
||||
<umb-child-selector
|
||||
selected-children="vm.selectedChildren"
|
||||
available-children="vm.availableChildren"
|
||||
parent-name="vm.name"
|
||||
parent-icon="vm.icon"
|
||||
parent-id="vm.id"
|
||||
on-add="vm.addChild"
|
||||
on-remove="vm.removeChild">
|
||||
</umb-child-selector>
|
||||
|
||||
<!-- use overlay to select children from -->
|
||||
<umb-overlay
|
||||
ng-if="vm.overlay.show"
|
||||
model="vm.overlay"
|
||||
position="target"
|
||||
view="vm.overlay.view">
|
||||
</umb-overlay>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Controller example</h3>
|
||||
<pre>
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function Controller() {
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.id = 1;
|
||||
vm.name = "My Parent element";
|
||||
vm.icon = "icon-document";
|
||||
vm.selectedChildren = [];
|
||||
vm.availableChildren = [
|
||||
{
|
||||
id: 1,
|
||||
alias: "item1",
|
||||
name: "Item 1",
|
||||
icon: "icon-document"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
alias: "item2",
|
||||
name: "Item 2",
|
||||
icon: "icon-document"
|
||||
}
|
||||
];
|
||||
|
||||
vm.addChild = addChild;
|
||||
vm.removeChild = removeChild;
|
||||
|
||||
function addChild($event) {
|
||||
vm.overlay = {
|
||||
view: "itempicker",
|
||||
title: "Choose child",
|
||||
availableItems: vm.availableChildren,
|
||||
selectedItems: vm.selectedChildren,
|
||||
event: $event,
|
||||
show: true,
|
||||
submit: function(model) {
|
||||
|
||||
// add selected child
|
||||
vm.selectedChildren.push(model.selectedItem);
|
||||
|
||||
// close overlay
|
||||
vm.overlay.show = false;
|
||||
vm.overlay = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function removeChild($index) {
|
||||
vm.selectedChildren.splice($index, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("My.Controller", Controller);
|
||||
|
||||
})();
|
||||
</pre>
|
||||
|
||||
@param {array} selectedChildren (<code>binding</code>): Array of selected children.
|
||||
@param {array} availableChildren (<code>binding</code>: Array of items available for selection.
|
||||
@param {string} parentName (<code>binding</code>): The parent name.
|
||||
@param {string} parentIcon (<code>binding</code>): The parent icon.
|
||||
@param {number} parentId (<code>binding</code>): The parent id.
|
||||
@param {callback} onRemove (<code>binding</code>): Callback when the remove button is clicked on an item.
|
||||
<h3>The callback returns:</h3>
|
||||
<ul>
|
||||
<li><code>child</code>: The selected item.</li>
|
||||
<li><code>$index</code>: The selected item index.</li>
|
||||
</ul>
|
||||
@param {callback} onAdd (<code>binding</code>): Callback when the add button is clicked.
|
||||
<h3>The callback returns:</h3>
|
||||
<ul>
|
||||
<li><code>$event</code>: The select event.</li>
|
||||
</ul>
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
|
||||
+66
@@ -1,3 +1,69 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbConfirmAction
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
<p>Use this directive to toggle a confirmation prompt for an action.
|
||||
The prompt consists of a checkmark and a cross to confirm or cancel the action.
|
||||
The prompt can be opened in four direction up, down, left or right.</p>
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="My.Controller as vm">
|
||||
|
||||
<div class="my-action" style="position:relative;">
|
||||
<i class="icon-trash" ng-click="vm.showPrompt()"></i>
|
||||
<umb-confirm-action
|
||||
ng-if="vm.promptIsVisible"
|
||||
direction="left"
|
||||
on-confirm="vm.confirmAction()"
|
||||
on-cancel="vm.hidePrompt()">
|
||||
</umb-confirm-action>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Controller example</h3>
|
||||
<pre>
|
||||
(function () {
|
||||
|
||||
"use strict";
|
||||
|
||||
function Controller() {
|
||||
|
||||
var vm = this;
|
||||
vm.promptIsVisible = false;
|
||||
|
||||
vm.confirmAction = confirmAction;
|
||||
vm.showPrompt = showPrompt;
|
||||
vm.hidePrompt = hidePrompt;
|
||||
|
||||
function confirmAction() {
|
||||
// confirm logic here
|
||||
}
|
||||
|
||||
function showPrompt() {
|
||||
vm.promptIsVisible = true;
|
||||
}
|
||||
|
||||
function hidePrompt() {
|
||||
vm.promptIsVisible = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("My.Controller", Controller);
|
||||
})();
|
||||
</pre>
|
||||
|
||||
@param {string} direction The direction the prompt opens ("up", "down", "left", "right").
|
||||
@param {callback} onConfirm Callback when the checkmark is clicked.
|
||||
@param {callback} onCancel Callback when the cross is clicked.
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
|
||||
+105
@@ -1,3 +1,108 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbContentGrid
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
Use this directive to generate a list of content items presented as a flexbox grid.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="My.Controller as vm">
|
||||
|
||||
<umb-content-grid
|
||||
content="vm.contentItems"
|
||||
content-properties="vm.includeProperties"
|
||||
on-click="vm.selectItem"
|
||||
on-click-name="vm.clickItem">
|
||||
</umb-content-grid>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Controller example</h3>
|
||||
<pre>
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function Controller() {
|
||||
|
||||
var vm = this;
|
||||
vm.contentItems = [
|
||||
{
|
||||
"name": "Cape",
|
||||
"published": true,
|
||||
"icon": "icon-document",
|
||||
"updateDate": "15-02-2016",
|
||||
"owner": "Mr. Batman",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"name": "Utility Belt",
|
||||
"published": true,
|
||||
"icon": "icon-document",
|
||||
"updateDate": "15-02-2016",
|
||||
"owner": "Mr. Batman",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"name": "Cave",
|
||||
"published": true,
|
||||
"icon": "icon-document",
|
||||
"updateDate": "15-02-2016",
|
||||
"owner": "Mr. Batman",
|
||||
"selected": false
|
||||
}
|
||||
];
|
||||
vm.includeProperties = [
|
||||
{
|
||||
"alias": "updateDate",
|
||||
"header": "Last edited"
|
||||
},
|
||||
{
|
||||
"alias": "owner",
|
||||
"header": "Created by"
|
||||
}
|
||||
];
|
||||
|
||||
vm.clickItem = clickItem;
|
||||
vm.selectItem = selectItem;
|
||||
|
||||
|
||||
function clickItem(item, $event, $index){
|
||||
// do magic here
|
||||
}
|
||||
|
||||
function selectItem(item, $event, $index) {
|
||||
// set item.selected = true; to select the item
|
||||
// do magic here
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("My.Controller", Controller);
|
||||
})();
|
||||
</pre>
|
||||
|
||||
@param {array} content (<code>binding</code>): Array of content items.
|
||||
@param {array=} contentProperties (<code>binding</code>): Array of content item properties to include in the item. If left empty the item will only show the item icon and name.
|
||||
@param {callback=} onClick (<code>binding</code>): Callback method to handle click events on the content item.
|
||||
<h3>The callback returns:</h3>
|
||||
<ul>
|
||||
<li><code>item</code>: The clicked item</li>
|
||||
<li><code>$event</code>: The select event</li>
|
||||
<li><code>$index</code>: The item index</li>
|
||||
</ul>
|
||||
@param {callback=} onClickName (<code>binding</code>): Callback method to handle click events on the checkmark icon.
|
||||
<h3>The callback returns:</h3>
|
||||
<ul>
|
||||
<li><code>item</code>: The selected item</li>
|
||||
<li><code>$event</code>: The select event</li>
|
||||
<li><code>$index</code>: The item index</li>
|
||||
</ul>
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
|
||||
@@ -1,3 +1,29 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbEmptyState
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
Use this directive to show an empty state message.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="My.Controller as vm">
|
||||
|
||||
<umb-empty-state
|
||||
ng-if="!vm.items"
|
||||
position="center">
|
||||
// Empty state content
|
||||
</umb-empty-state>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
@param {string=} size Set the size of the text ("small", "large").
|
||||
@param {string=} position Set the position of the text ("center").
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
|
||||
@@ -1,3 +1,83 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbFolderGrid
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
Use this directive to generate a list of folders presented as a flexbox grid.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="My.Controller as vm">
|
||||
<umb-folder-grid
|
||||
ng-if="vm.folders.length > 0"
|
||||
folders="vm.folders"
|
||||
on-click="vm.clickFolder"
|
||||
on-select="vm.selectFolder">
|
||||
</umb-folder-grid>
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Controller example</h3>
|
||||
<pre>
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function Controller(myService) {
|
||||
|
||||
var vm = this;
|
||||
vm.folders = [
|
||||
{
|
||||
"name": "Folder 1",
|
||||
"icon": "icon-folder",
|
||||
"selected": false
|
||||
},
|
||||
{
|
||||
"name": "Folder 2",
|
||||
"icon": "icon-folder",
|
||||
"selected": false
|
||||
}
|
||||
|
||||
];
|
||||
|
||||
vm.clickFolder = clickFolder;
|
||||
vm.selectFolder = selectFolder;
|
||||
|
||||
myService.getFolders().then(function(folders){
|
||||
vm.folders = folders;
|
||||
});
|
||||
|
||||
function clickFolder(folder){
|
||||
// Execute when clicking folder name/link
|
||||
}
|
||||
|
||||
function selectFolder(folder, event, index) {
|
||||
// Execute when clicking folder
|
||||
// set folder.selected = true; to show checkmark icon
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("My.Controller", Controller);
|
||||
})();
|
||||
</pre>
|
||||
|
||||
@param {array} folders (<code>binding</code>): Array of folders
|
||||
@param {callback=} onClick (<code>binding</code>): Callback method to handle click events on the folder.
|
||||
<h3>The callback returns:</h3>
|
||||
<ul>
|
||||
<li><code>folder</code>: The selected folder</li>
|
||||
</ul>
|
||||
@param {callback=} onSelect (<code>binding</code>): Callback method to handle click events on the checkmark icon.
|
||||
<h3>The callback returns:</h3>
|
||||
<ul>
|
||||
<li><code>folder</code>: The selected folder</li>
|
||||
<li><code>$event</code>: The select event</li>
|
||||
<li><code>$index</code>: The folder index</li>
|
||||
</ul>
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
|
||||
+109
@@ -1,3 +1,112 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbkeyboardShortcutsOverview
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
|
||||
<p>Use this directive to show an overview of keyboard shortcuts in an editor.
|
||||
The directive will render an overview trigger wich shows how the overview is opened.
|
||||
When this combination is hit an overview is opened with shortcuts based on the model sent to the directive.</p>
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="My.Controller as vm">
|
||||
|
||||
<umb-keyboard-shortcuts-overview
|
||||
model="vm.keyboardShortcutsOverview">
|
||||
</umb-keyboard-shortcuts-overview>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Controller example</h3>
|
||||
<pre>
|
||||
(function () {
|
||||
|
||||
"use strict";
|
||||
|
||||
function Controller() {
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.keyboardShortcutsOverview = [
|
||||
{
|
||||
"name": "Sections",
|
||||
"shortcuts": [
|
||||
{
|
||||
"description": "Navigate sections",
|
||||
"keys": [
|
||||
{"key": "1"},
|
||||
{"key": "4"}
|
||||
],
|
||||
"keyRange": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Design",
|
||||
"shortcuts": [
|
||||
{
|
||||
"description": "Add tab",
|
||||
"keys": [
|
||||
{"key": "alt"},
|
||||
{"key": "shift"},
|
||||
{"key": "t"}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("My.Controller", Controller);
|
||||
})();
|
||||
</pre>
|
||||
|
||||
<h3>Model description</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>name</strong>
|
||||
<small>(string)</small> -
|
||||
Sets the shortcut section name.
|
||||
</li>
|
||||
<li>
|
||||
<strong>shortcuts</strong>
|
||||
<small>(array)</small> -
|
||||
Array of available shortcuts in the section.
|
||||
</li>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>description</strong>
|
||||
<small>(string)</small> -
|
||||
Short description of the shortcut.
|
||||
</li>
|
||||
<li>
|
||||
<strong>keys</strong>
|
||||
<small>(array)</small> -
|
||||
Array of keys in the shortcut.
|
||||
</li>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>key</strong>
|
||||
<small>(string)</small> -
|
||||
The invidual key in the shortcut.
|
||||
</li>
|
||||
</ul>
|
||||
<li>
|
||||
<strong>keyRange</strong>
|
||||
<small>(boolean)</small> -
|
||||
Set to <code>true</code> to show a key range. It combines the shortcut keys with "-" instead of "+".
|
||||
</li>
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
@param {object} model keyboard shortcut model. See description and example above.
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
|
||||
+47
@@ -1,3 +1,50 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbLoadIndicator
|
||||
@restrict E
|
||||
|
||||
@description
|
||||
Use this directive to generate a loading indicator.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="My.Controller as vm">
|
||||
|
||||
<umb-load-indicator
|
||||
ng-if="vm.loading">
|
||||
</umb-load-indicator>
|
||||
|
||||
<div class="content" ng-if="!vm.loading">
|
||||
<p>{{content}}</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Controller example</h3>
|
||||
<pre>
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function Controller(myService) {
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.content = "";
|
||||
vm.loading = true;
|
||||
|
||||
myService.getContent().then(function(content){
|
||||
vm.content = content;
|
||||
vm.loading = false;
|
||||
});
|
||||
|
||||
}
|
||||
½
|
||||
angular.module("umbraco").controller("My.Controller", Controller);
|
||||
})();
|
||||
</pre>
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
|
||||
+43
-6
@@ -1,11 +1,48 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbContentName
|
||||
* @restrict E
|
||||
* @function
|
||||
* @description
|
||||
* Used by editors that require naming an entity. Shows a textbox/headline with a required validator within it's own form.
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbLockedField
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
Use this directive to render a value with a lock next to it. When the lock is clicked the value gets unlocked and can be edited.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="My.Controller as vm">
|
||||
|
||||
<umb-locked-field
|
||||
ng-model="vm.value"
|
||||
placeholder-text="'Click to unlock...'">
|
||||
</umb-locked-field>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Controller example</h3>
|
||||
<pre>
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function Controller() {
|
||||
|
||||
var vm = this;
|
||||
vm.value = "My locked text";
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("My.Controller", Controller);
|
||||
|
||||
})();
|
||||
</pre>
|
||||
|
||||
@param {string} ngModel (<code>binding</code>): The locked text.
|
||||
@param {boolean=} locked (<code>binding</code>): <Code>true</code> by default. Set to <code>false</code> to unlock the text.
|
||||
@param {string=} placeholderText (<code>binding</code>): If ngModel is empty this text will be shown.
|
||||
@param {string=} regexValidation (<code>binding</code>): Set a regex expression for validation of the field.
|
||||
@param {string=} serverValidationField (<code>attribute</code>): Set a server validation field.
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
|
||||
@@ -1,3 +1,87 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbMediaGrid
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
Use this directive to generate a thumbnail grid of media items.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="My.Controller as vm">
|
||||
|
||||
<umb-media-grid
|
||||
items="vm.mediaItems"
|
||||
on-click="vm.clickItem"
|
||||
on-click-name="vm.clickItemName">
|
||||
</umb-media-grid>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Controller example</h3>
|
||||
<pre>
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function Controller() {
|
||||
|
||||
var vm = this;
|
||||
vm.mediaItems = [];
|
||||
|
||||
vm.clickItem = clickItem;
|
||||
vm.clickItemName = clickItemName;
|
||||
|
||||
myService.getMediaItems().then(function (mediaItems) {
|
||||
vm.mediaItems = mediaItems;
|
||||
});
|
||||
|
||||
function clickItem(item, $event, $index){
|
||||
// do magic here
|
||||
}
|
||||
|
||||
function clickItemName(item, $event, $index) {
|
||||
// set item.selected = true; to select the item
|
||||
// do magic here
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("My.Controller", Controller);
|
||||
})();
|
||||
</pre>
|
||||
|
||||
@param {array} items (<code>binding</code>): Array of media items.
|
||||
@param {callback=} onDetailsHover (<code>binding</code>): Callback method when the details icon is hovered.
|
||||
<h3>The callback returns:</h3>
|
||||
<ul>
|
||||
<li><code>item</code>: The hovered item</li>
|
||||
<li><code>$event</code>: The hover event</li>
|
||||
<li><code>hover</code>: Boolean to tell if the item is hovered or not</li>
|
||||
</ul>
|
||||
@param {callback=} onClick (<code>binding</code>): Callback method to handle click events on the media item.
|
||||
<h3>The callback returns:</h3>
|
||||
<ul>
|
||||
<li><code>item</code>: The clicked item</li>
|
||||
<li><code>$event</code>: The click event</li>
|
||||
<li><code>$index</code>: The item index</li>
|
||||
</ul>
|
||||
@param {callback=} onClickName (<code>binding</code>): Callback method to handle click events on the media item name.
|
||||
<h3>The callback returns:</h3>
|
||||
<ul>
|
||||
<li><code>item</code>: The clicked item</li>
|
||||
<li><code>$event</code>: The click event</li>
|
||||
<li><code>$index</code>: The item index</li>
|
||||
</ul>
|
||||
@param {string=} filterBy (<code>binding</code>): String to filter media items by
|
||||
@param {string=} itemMaxWidth (<code>attribute</code>): Sets a max width on the media item thumbnails.
|
||||
@param {string=} itemMaxHeight (<code>attribute</code>): Sets a max height on the media item thumbnails.
|
||||
@param {string=} itemMinWidth (<code>attribute</code>): Sets a min width on the media item thumbnails.
|
||||
@param {string=} itemMinHeight (<code>attribute</code>): Sets a min height on the media item thumbnails.
|
||||
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
|
||||
@@ -1,3 +1,88 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbPagination
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
Use this directive to generate a pagination.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="My.Controller as vm">
|
||||
|
||||
<umb-pagination
|
||||
page-number="vm.pagination.pageNumber"
|
||||
total-pages="vm.pagination.totalPages"
|
||||
on-next="vm.nextPage"
|
||||
on-prev="vm.prevPage"
|
||||
on-go-to-page="vm.goToPage">
|
||||
</umb-pagination>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Controller example</h3>
|
||||
<pre>
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function Controller() {
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.pagination = {
|
||||
pageNumber: 1,
|
||||
totalPages: 10
|
||||
}
|
||||
|
||||
vm.nextPage = nextPage;
|
||||
vm.prevPage = prevPage;
|
||||
vm.goToPage = goToPage;
|
||||
|
||||
function nextPage(pageNumber) {
|
||||
// do magic here
|
||||
console.log(pageNumber);
|
||||
alert("nextpage");
|
||||
}
|
||||
|
||||
function prevPage(pageNumber) {
|
||||
// do magic here
|
||||
console.log(pageNumber);
|
||||
alert("prevpage");
|
||||
}
|
||||
|
||||
function goToPage(pageNumber) {
|
||||
// do magic here
|
||||
console.log(pageNumber);
|
||||
alert("go to");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("My.Controller", Controller);
|
||||
})();
|
||||
</pre>
|
||||
|
||||
@param {number} pageNumber (<code>binding</code>): Current page number.
|
||||
@param {number} totalPages (<code>binding</code>): The total number of pages.
|
||||
@param {callback} onNext (<code>binding</code>): Callback method to go to the next page.
|
||||
<h3>The callback returns:</h3>
|
||||
<ul>
|
||||
<li><code>pageNumber</code>: The page number</li>
|
||||
</ul>
|
||||
@param {callback=} onPrev (<code>binding</code>): Callback method to go to the previous page.
|
||||
<h3>The callback returns:</h3>
|
||||
<ul>
|
||||
<li><code>pageNumber</code>: The page number</li>
|
||||
</ul>
|
||||
@param {callback=} onGoToPage (<code>binding</code>): Callback method to go to a specific page.
|
||||
<h3>The callback returns:</h3>
|
||||
<ul>
|
||||
<li><code>pageNumber</code>: The page number</li>
|
||||
</ul>
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
|
||||
@@ -1,3 +1,41 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbStickyBar
|
||||
@restrict A
|
||||
|
||||
@description
|
||||
Use this directive make an element sticky and follow the page when scrolling.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="My.Controller as vm">
|
||||
|
||||
<div
|
||||
class="my-sticky-bar"
|
||||
umb-sticky-bar
|
||||
scrollable-container=".container">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>CSS example</h3>
|
||||
<pre>
|
||||
.my-sticky-bar {
|
||||
padding: 15px 0;
|
||||
background: #000000;
|
||||
position: relative;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.my-sticky-bar.-umb-sticky-bar {
|
||||
top: 100px;
|
||||
}
|
||||
</pre>
|
||||
|
||||
@param {string} scrollableContainer Set the class (".element") or the id ("#element") of the scrollable container element.
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
|
||||
@@ -1,3 +1,71 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbTooltip
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
Use this directive to render a tooltip.
|
||||
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="My.Controller as vm">
|
||||
|
||||
<div
|
||||
ng-mouseover="vm.mouseOver($event)"
|
||||
ng-mouseleave="vm.mouseLeave()">
|
||||
Hover me
|
||||
</div>
|
||||
|
||||
<umb-tooltip
|
||||
ng-if="vm.tooltip.show"
|
||||
event="vm.tooltip.event">
|
||||
// tooltip content here
|
||||
</umb-tooltip>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Controller example</h3>
|
||||
<pre>
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function Controller() {
|
||||
|
||||
var vm = this;
|
||||
vm.tooltip = {
|
||||
show: false,
|
||||
event: null
|
||||
};
|
||||
|
||||
vm.mouseOver = mouseOver;
|
||||
vm.mouseLeave = mouseLeave;
|
||||
|
||||
function mouseOver($event) {
|
||||
vm.tooltip = {
|
||||
show: true,
|
||||
event: $event
|
||||
};
|
||||
}
|
||||
|
||||
function mouseLeave() {
|
||||
vm.tooltip = {
|
||||
show: false,
|
||||
event: null
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("My.Controller", Controller);
|
||||
|
||||
})();
|
||||
</pre>
|
||||
|
||||
@param {string} event Set the $event from the target element to position the tooltip relative to the mouse cursor.
|
||||
**/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbContentName
|
||||
* @name umbraco.directives.directive:umbFileDropzone
|
||||
* @restrict E
|
||||
* @function
|
||||
* @description
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbFileUpload
|
||||
* @name umbraco.directives.directive:umbSingleFileUpload
|
||||
* @function
|
||||
* @restrict A
|
||||
* @scope
|
||||
|
||||
@@ -282,7 +282,7 @@ function keyboardService($window, $timeout) {
|
||||
keyboardManagerService.keyboardEvent[label] = {
|
||||
'callback': callback,
|
||||
'target': elt,
|
||||
'opt': opt['type']
|
||||
'opt': opt
|
||||
};
|
||||
|
||||
if (!found) {
|
||||
|
||||
+2
-2
@@ -32,7 +32,7 @@
|
||||
<li class="umb-checkbox-list__item"
|
||||
|
||||
ng-repeat="compositeContentType in model.availableCompositeContentTypes | filter:searchTerm"
|
||||
ng-class="{'-disabled': compositeContentType.allowed===false, '-selected': vm.isSelected(compositeContentType.contentType.alias)}">
|
||||
ng-class="{'-disabled': compositeContentType.allowed===false || compositeContentType.inherited, '-selected': vm.isSelected(compositeContentType.contentType.alias)}">
|
||||
|
||||
<div class="umb-checkbox-list__item-checkbox"
|
||||
ng-class="{ '-selected': model.compositeContentTypes.indexOf(compositeContentType.contentType.alias)+1 }">
|
||||
@@ -41,7 +41,7 @@
|
||||
checklist-model="model.compositeContentTypes"
|
||||
checklist-value="compositeContentType.contentType.alias"
|
||||
ng-change="model.selectCompositeContentType(compositeContentType.contentType)"
|
||||
ng-disabled="compositeContentType.allowed===false"/>
|
||||
ng-disabled="compositeContentType.allowed===false || compositeContentType.inherited"/>
|
||||
</div>
|
||||
|
||||
<label for="umb-overlay-comp-{{compositeContentType.contentType.key}}" class="umb-checkbox-list__item-text" ng-class="{'-faded': compositeContentType.allowed===false}">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="umb-panel umb-editor-wrapper animated -half-second fadeIn"
|
||||
<div class="umb-panel umb-editor-wrapper"
|
||||
ng-class="{
|
||||
'-no-footer': footer === 'false'
|
||||
}"
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
|
||||
<ul class="umb-group-builder__properties" ui-sortable="sortableOptionsProperty" ng-model="tab.properties">
|
||||
|
||||
<li ng-class="{'umb-group-builder__property-sortable': sortingMode && !property.inherited && !property.locked}" ng-repeat="property in tab.properties">
|
||||
<li ng-class="{'umb-group-builder__property-sortable': sortingMode && !property.inherited}" ng-repeat="property in tab.properties">
|
||||
|
||||
<!-- Init property / Property placeholder / add new property -->
|
||||
<a href=""
|
||||
@@ -138,7 +138,7 @@
|
||||
|
||||
</a>
|
||||
|
||||
<div class="umb-group-builder__property" ng-if="property.propertyState!=='init'" ng-class="{'-active': property.dialogIsOpen, '-active': property.propertyState=='active', '-inherited': property.inherited, '-locked': property.locked, 'umb-group-builder__property-handle -sortable': sortingMode && !property.inherited && !property.locked, '-sortable-locked': sortingMode && (property.inherited || property.locked)}">
|
||||
<div class="umb-group-builder__property" ng-if="property.propertyState!=='init'" ng-class="{'-active': property.dialogIsOpen, '-active': property.propertyState=='active', '-inherited': property.inherited, '-locked': property.locked, 'umb-group-builder__property-handle -sortable': sortingMode && !property.inherited, '-sortable-locked': sortingMode && property.inherited}">
|
||||
|
||||
<!-- property meta text -->
|
||||
<div class="umb-group-builder__property-meta" ng-class="{'-full-width': sortingMode}">
|
||||
@@ -184,7 +184,7 @@
|
||||
</ng-form>
|
||||
|
||||
<div ng-if="sortingMode">
|
||||
<i class="icon icon-navigation" ng-if="!property.inherited && !property.locked"></i>
|
||||
<i class="icon icon-navigation" ng-if="!property.inherited"></i>
|
||||
<span class="umb-group-builder__property-meta-label">{{ property.label }}</span>
|
||||
<span class="umb-group-builder__property-meta-alias">({{ property.alias }})</span>
|
||||
</div>
|
||||
|
||||
@@ -166,17 +166,17 @@
|
||||
|
||||
<div class="row form-search">
|
||||
<div class="span8 input-append">
|
||||
<input type="text" class="search-query" ng-model="searcher.searchText" />
|
||||
<input type="text" class="search-query" ng-model="searcher.searchText" no-dirty-check />
|
||||
<button type="submit" class="btn btn-info" ng-click="search(searcher)" ng-disabled="searcher.isProcessing">Search</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label for="{{searcher.name}}-textSearch" class="radio inline">
|
||||
<input type="radio" name="searchType" id="{{searcher.name}}-textSearch" value="text" ng-model="searcher.searchType" />
|
||||
<input type="radio" name="searchType" id="{{searcher.name}}-textSearch" value="text" ng-model="searcher.searchType" no-dirty-check />
|
||||
Text Search
|
||||
</label>
|
||||
<label for="{{searcher.name}}-luceneSearch" class="radio inline">
|
||||
<input type="radio" name="searchType" id="{{searcher.name}}-luceneSearch" value="lucene" ng-model="searcher.searchType" />
|
||||
<input type="radio" name="searchType" id="{{searcher.name}}-luceneSearch" value="lucene" ng-model="searcher.searchType" no-dirty-check />
|
||||
Lucene Search
|
||||
</label>
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
vm.nodeId = $scope.contentId;
|
||||
//vm.acceptedFileTypes = mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.imageFileTypes);
|
||||
//instead of passing in a whitelist, we pass in a blacklist by adding ! to the ext
|
||||
vm.acceptedFileTypes = mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.disallowedUploadFiles).replace(/./g, "!.");
|
||||
vm.acceptedFileTypes = mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.disallowedUploadFiles).replace(/\./g, "!.");
|
||||
|
||||
vm.maxFileSize = Umbraco.Sys.ServerVariables.umbracoSettings.maxFileSize + "KB";
|
||||
vm.activeDrag = false;
|
||||
|
||||
@@ -59,6 +59,25 @@ function listViewController($rootScope, $scope, $routeParams, $injector, $cookie
|
||||
items: []
|
||||
};
|
||||
|
||||
$scope.currentNodePermissions = {}
|
||||
|
||||
//Just ensure we do have an editorState
|
||||
if (editorState.current) {
|
||||
//Fetch current node allowed actions for the current user
|
||||
//This is the current node & not each individual child node in the list
|
||||
var currentUserPermissions = editorState.current.allowedActions;
|
||||
|
||||
//Create a nicer model rather than the funky & hard to remember permissions strings
|
||||
$scope.currentNodePermissions = {
|
||||
"canCopy": _.contains(currentUserPermissions, 'O'), //Magic Char = O
|
||||
"canCreate": _.contains(currentUserPermissions, 'C'), //Magic Char = C
|
||||
"canDelete": _.contains(currentUserPermissions, 'D'), //Magic Char = D
|
||||
"canMove": _.contains(currentUserPermissions, 'M'), //Magic Char = M
|
||||
"canPublish": _.contains(currentUserPermissions, 'U'), //Magic Char = U
|
||||
"canUnpublish": _.contains(currentUserPermissions, 'U'), //Magic Char = Z (however UI says it can't be set, so if we can publish 'U' we can unpublish)
|
||||
};
|
||||
}
|
||||
|
||||
//when this is null, we don't check permissions
|
||||
$scope.buttonPermissions = null;
|
||||
|
||||
|
||||
@@ -348,8 +348,8 @@
|
||||
<Name>umbraco.providers</Name>
|
||||
</ProjectReference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="Umbraco.ModelsBuilder, Version=3.0.1.92, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Umbraco.ModelsBuilder.3.0.1\lib\Umbraco.ModelsBuilder.dll</HintPath>
|
||||
<Reference Include="Umbraco.ModelsBuilder, Version=3.0.2.93, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Umbraco.ModelsBuilder.3.0.2\lib\Umbraco.ModelsBuilder.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="UrlRewritingNet.UrlRewriter, Version=2.0.7.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
@@ -2411,9 +2411,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
|
||||
<WebProjectProperties>
|
||||
<UseIIS>True</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>7410</DevelopmentServerPort>
|
||||
<DevelopmentServerPort>7420</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:7410</IISUrl>
|
||||
<IISUrl>http://localhost:7420</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>False</UseCustomServer>
|
||||
<CustomServerUrl>
|
||||
|
||||
@@ -35,6 +35,6 @@
|
||||
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
|
||||
<package id="System.Collections.Immutable" version="1.1.36" targetFramework="net45" />
|
||||
<package id="System.Reflection.Metadata" version="1.0.21" targetFramework="net45" />
|
||||
<package id="Umbraco.ModelsBuilder" version="3.0.1" targetFramework="net45" />
|
||||
<package id="Umbraco.ModelsBuilder" version="3.0.2" targetFramework="net45" />
|
||||
<package id="UrlRewritingNet.UrlRewriter" version="2.0.7" targetFramework="net45" />
|
||||
</packages>
|
||||
@@ -839,43 +839,43 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à
|
||||
<key alias="template">Modèle</key>
|
||||
</area>
|
||||
<area alias="grid">
|
||||
<key alias="insertControl">Choose type of content</key>
|
||||
<key alias="chooseLayout">Choose a layout</key>
|
||||
<key alias="addRows">Add a row</key>
|
||||
<key alias="addElement">Add content</key>
|
||||
<key alias="dropElement">Drop content</key>
|
||||
<key alias="settingsApplied">Settings applied</key>
|
||||
<key alias="insertControl">Choisissez le type de contenu</key>
|
||||
<key alias="chooseLayout">Choisissez une mise en page</key>
|
||||
<key alias="addRows">Ajouter une ligne</key>
|
||||
<key alias="addElement">Ajouter du contenu</key>
|
||||
<key alias="dropElement">Contenu goutte</key>
|
||||
<key alias="settingsApplied">Paramètres appliqués</key>
|
||||
|
||||
<key alias="contentNotAllowed">This content is not allowed here</key>
|
||||
<key alias="contentAllowed">This content is allowed here</key>
|
||||
<key alias="contentNotAllowed">Ce contenu est pas autorisée ici</key>
|
||||
<key alias="contentAllowed">Ce contenu est permis ici</key>
|
||||
|
||||
<key alias="clickToEmbed">Click to embed</key>
|
||||
<key alias="clickToInsertImage">Click to insert image</key>
|
||||
<key alias="placeholderImageCaption">Image caption...</key>
|
||||
<key alias="placeholderWriteHere">Write here...</key>
|
||||
<key alias="clickToEmbed">Cliquez pour intégrer</key>
|
||||
<key alias="clickToInsertImage">Cliquez pour insérer l'image</key>
|
||||
<key alias="placeholderImageCaption">Légende de l'image...</key>
|
||||
<key alias="placeholderWriteHere">Ecrire ici...</key>
|
||||
|
||||
<key alias="gridLayouts">Grid Layouts</key>
|
||||
<key alias="gridLayoutsDetail">Layouts are the overall work area for the grid editor, usually you only need one or two different layouts</key>
|
||||
<key alias="addGridLayout">Add Grid Layout</key>
|
||||
<key alias="addGridLayoutDetail">Adjust the layout by setting column widths and adding additional sections</key>
|
||||
<key alias="rowConfigurations">Row configurations</key>
|
||||
<key alias="rowConfigurationsDetail">Rows are predefined cells arranged horizontally</key>
|
||||
<key alias="addRowConfiguration">Add row configuration</key>
|
||||
<key alias="addRowConfigurationDetail">Adjust the row by setting cell widths and adding additional cells</key>
|
||||
<key alias="gridLayouts">Layouts Grid</key>
|
||||
<key alias="gridLayoutsDetail">Layouts sont la superficie totale de travail pour l'éditeur de grille, en général, vous avez seulement besoin d'une ou deux configurations différentes</key>
|
||||
<key alias="addGridLayout">Ajouter Grid Layout</key>
|
||||
<key alias="addGridLayoutDetail">Ajustez la mise en page en définissant la largeur des colonnes et ajouter des sections supplémentaires</key>
|
||||
<key alias="rowConfigurations">Configurations des lignes</key>
|
||||
<key alias="rowConfigurationsDetail">Les lignes sont des cellules prédéfinies disposées horizontalement</key>
|
||||
<key alias="addRowConfiguration">Ajouter une configuration de la ligne</key>
|
||||
<key alias="addRowConfigurationDetail">Ajustez la ligne en réglant la largeur des cellules et en ajoutant des cellules supplémentaires</key>
|
||||
|
||||
<key alias="columns">Columns</key>
|
||||
<key alias="columnsDetails">Total combined number of columns in the grid layout</key>
|
||||
<key alias="columns">Colonnes</key>
|
||||
<key alias="columnsDetails">Nombre total combiné de colonnes dans la configuration de la grille</key>
|
||||
|
||||
<key alias="settings">Settings</key>
|
||||
<key alias="settingsDetails">Configure what settings editors can change</key>
|
||||
<key alias="settings">Paramètres</key>
|
||||
<key alias="settingsDetails">Configurer quels paramètres éditeurs peuvent changer</key>
|
||||
|
||||
<key alias="styles">Styles</key>
|
||||
<key alias="stylesDetails">Configure what styling editors can change</key>
|
||||
<key alias="styles">Modes</key>
|
||||
<key alias="stylesDetails">Configurer ce style éditeurs peuvent changer</key>
|
||||
|
||||
<key alias="settingDialogDetails">Settings will only save if the entered json configuration is valid</key>
|
||||
<key alias="settingDialogDetails">Les réglages seulement économiser si la configuration du json saisi est valide</key>
|
||||
|
||||
<key alias="allowAllEditors">Allow all editors</key>
|
||||
<key alias="allowAllRowConfigurations">Allow all row configurations</key>
|
||||
<key alias="allowAllEditors">Autoriser tous les éditeurs</key>
|
||||
<key alias="allowAllRowConfigurations">Autoriser toutes les configurations de lignes</key>
|
||||
</area>
|
||||
<area alias="templateEditor">
|
||||
<key alias="alternativeField">Champ alternatif</key>
|
||||
|
||||
@@ -35,9 +35,18 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls.CodeEditor");
|
||||
this._control.val(code);
|
||||
}
|
||||
else {
|
||||
//this is a wrapper for CodeMirror
|
||||
//this is a wrapper for CodeMirror
|
||||
this._editor.focus();
|
||||
|
||||
var codeChanged = this._editor.getValue() != code;
|
||||
var cursor = this._editor.doc.getCursor();
|
||||
|
||||
this._editor.setValue(code);
|
||||
|
||||
// Restore cursor position if the server saved code matches.
|
||||
if (!codeChanged)
|
||||
this._editor.setCursor(cursor);
|
||||
|
||||
this._editor.focus();
|
||||
}
|
||||
},
|
||||
|
||||
@@ -174,6 +174,9 @@
|
||||
}
|
||||
if (args.contents) {
|
||||
UmbEditor.SetCode(args.contents);
|
||||
} else if (!this.IsSimpleEditor) {
|
||||
// Restore focuse to text region. SetCode also does this.
|
||||
UmbEditor._editor.focus();
|
||||
}
|
||||
|
||||
UmbClientMgr.mainTree().setActiveTreeType(this._opts.currentTreeType);
|
||||
|
||||
@@ -22,8 +22,7 @@ namespace Umbraco.Web.Editors
|
||||
/// <summary>
|
||||
/// The API controller used for retrieving available stylesheets
|
||||
/// </summary>
|
||||
[PluginController("UmbracoApi")]
|
||||
[DisableBrowserCache]
|
||||
[PluginController("UmbracoApi")]
|
||||
public class StylesheetController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
public IEnumerable<Stylesheet> GetAll()
|
||||
|
||||
@@ -18,7 +18,6 @@ namespace Umbraco.Web.Editors
|
||||
/// The API controller used for building content queries within the template
|
||||
/// </summary>
|
||||
[PluginController("UmbracoApi")]
|
||||
[DisableBrowserCache]
|
||||
[JsonCamelCaseFormatter]
|
||||
public class TemplateQueryController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Umbraco.Web.Editors
|
||||
/// methods that are not called by Angular or don't contain a valid csrf header will NOT work.
|
||||
/// </remarks>
|
||||
[ValidateAngularAntiForgeryToken]
|
||||
[AngularJsonOnlyConfiguration]
|
||||
[AngularJsonOnlyConfiguration]
|
||||
public abstract class UmbracoAuthorizedJsonController : UmbracoAuthorizedApiController
|
||||
{
|
||||
protected UmbracoAuthorizedJsonController()
|
||||
|
||||
@@ -35,6 +35,14 @@ namespace Umbraco.Web.Models.ContentEditing
|
||||
[DataMember(Name = "contentTypeId")]
|
||||
[ReadOnly(true)]
|
||||
public int ContentTypeId { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// This is required for the UI editor to know which content type name this property belongs
|
||||
/// to based on the property inheritance structure
|
||||
/// </summary>
|
||||
[DataMember(Name = "contentTypeName")]
|
||||
[ReadOnly(true)]
|
||||
public string ContentTypeName { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,6 +256,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(g => g.View, expression => expression.Ignore())
|
||||
.ForMember(g => g.Config, expression => expression.Ignore())
|
||||
.ForMember(g => g.ContentTypeId, expression => expression.Ignore())
|
||||
.ForMember(g => g.ContentTypeName, expression => expression.Ignore())
|
||||
.ForMember(g => g.Locked, exp => exp.Ignore());
|
||||
|
||||
config.CreateMap<MemberPropertyTypeBasic, MemberPropertyTypeDisplay>()
|
||||
@@ -263,6 +264,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(g => g.View, expression => expression.Ignore())
|
||||
.ForMember(g => g.Config, expression => expression.Ignore())
|
||||
.ForMember(g => g.ContentTypeId, expression => expression.Ignore())
|
||||
.ForMember(g => g.ContentTypeName, expression => expression.Ignore())
|
||||
.ForMember(g => g.Locked, exp => exp.Ignore());
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -218,7 +218,8 @@ namespace Umbraco.Web.Models.Mapping
|
||||
Inherited = inherited,
|
||||
DataTypeId = p.DataTypeDefinitionId,
|
||||
SortOrder = p.SortOrder,
|
||||
ContentTypeId = contentType.Id
|
||||
ContentTypeId = contentType.Id,
|
||||
ContentTypeName = contentType.Name
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
|
||||
namespace Umbraco.Web.Mvc
|
||||
{
|
||||
/// <summary>
|
||||
/// Ensures that the request is not cached by the browser
|
||||
/// </summary>
|
||||
public class DisableBrowserCacheAttribute : ActionFilterAttribute
|
||||
{
|
||||
public override void OnActionExecuted(ActionExecutedContext filterContext)
|
||||
{
|
||||
base.OnActionExecuted(filterContext);
|
||||
|
||||
filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
|
||||
filterContext.HttpContext.Response.Cache.SetMaxAge(TimeSpan.Zero);
|
||||
filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
|
||||
filterContext.HttpContext.Response.Cache.SetNoStore();
|
||||
filterContext.HttpContext.Response.AddHeader("Pragma", "no-cache");
|
||||
filterContext.HttpContext.Response.Cache.SetExpires(new DateTime(1990, 1, 1, 0, 0, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System.IO;
|
||||
using System.Web.Mvc;
|
||||
|
||||
namespace Umbraco.Web.Mvc
|
||||
{
|
||||
/// <summary>
|
||||
/// This is a special filter which is required for the RTE to be able to render Partial View Macros that
|
||||
/// contain forms when the RTE value is resolved outside of an MVC view being rendered
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The entire way that we support partial view macros that contain forms isn't really great, these forms
|
||||
/// need to be executed as ChildActions so that the ModelState,ViewData,TempData get merged into that action
|
||||
/// so the form can show errors, viewdata, etc...
|
||||
/// Under normal circumstances, macros will be rendered after a ViewContext is created but in some cases
|
||||
/// developers will resolve the RTE value in the controller, in this case the Form won't be rendered correctly
|
||||
/// with merged ModelState from the controller because the special DataToken hasn't been set yet (which is
|
||||
/// normally done in the UmbracoViewPageOfModel when a real ViewContext is available.
|
||||
/// So we need to detect if the currently rendering controller is IRenderController and if so we'll ensure that
|
||||
/// this DataToken exists before the action executes in case the developer resolves an RTE value that contains
|
||||
/// a partial view macro form.
|
||||
/// </remarks>
|
||||
internal class EnsurePartialViewMacroViewContextFilterAttribute : ActionFilterAttribute
|
||||
{
|
||||
public override void OnActionExecuting(ActionExecutingContext filterContext)
|
||||
{
|
||||
//ignore anything that is not IRenderController
|
||||
if ((filterContext.Controller is IRenderController) == false)
|
||||
return;
|
||||
|
||||
var viewCtx = new ViewContext(
|
||||
filterContext.Controller.ControllerContext,
|
||||
new DummyView(),
|
||||
filterContext.Controller.ViewData, filterContext.Controller.TempData,
|
||||
new StringWriter());
|
||||
|
||||
//set the special data token
|
||||
filterContext.RequestContext.RouteData.DataTokens[Constants.DataTokenCurrentViewContext] = viewCtx;
|
||||
}
|
||||
|
||||
private class DummyView : IView
|
||||
{
|
||||
public void Render(ViewContext viewContext, TextWriter writer)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
@@ -35,7 +37,7 @@ namespace Umbraco.Web.Mvc
|
||||
{
|
||||
model = base.BindModel(controllerContext, bindingContext);
|
||||
if (model == null) return null;
|
||||
}
|
||||
}
|
||||
|
||||
//if for any reason the model is not either IRenderModel or IPublishedContent, then we return since those are the only
|
||||
// types this binder is dealing with.
|
||||
@@ -140,17 +142,31 @@ namespace Umbraco.Web.Mvc
|
||||
msg.Append(sourceType.FullName);
|
||||
msg.Append(" to model");
|
||||
if (modelContent) msg.Append(" content");
|
||||
msg.Append(" type");
|
||||
msg.Append(" type ");
|
||||
msg.Append(modelType.FullName);
|
||||
msg.Append(".");
|
||||
|
||||
if (sourceType.FullName == modelType.FullName)
|
||||
// compare FullName for the time being because when upgrading ModelsBuilder,
|
||||
// Umbraco does not know about the new attribute type - later on, can compare
|
||||
// on type directly (ie after v7.4.2).
|
||||
var sourceAttr = sourceType.Assembly.CustomAttributes.FirstOrDefault(x =>
|
||||
x.AttributeType.FullName == "Umbraco.ModelsBuilder.PureLiveAssemblyAttribute");
|
||||
var modelAttr = modelType.Assembly.CustomAttributes.FirstOrDefault(x =>
|
||||
x.AttributeType.FullName == "Umbraco.ModelsBuilder.PureLiveAssemblyAttribute");
|
||||
|
||||
// bah.. names are App_Web_all.generated.cs.8f9494c4.jjuvxz55 so they ARE different, fuck!
|
||||
// we cannot compare purely on type.FullName 'cos we might be trying to map Sub to Main = fails!
|
||||
if (sourceAttr != null && modelAttr != null
|
||||
&& sourceType.Assembly.GetName().Version.Revision != modelType.Assembly.GetName().Version.Revision)
|
||||
{
|
||||
msg.Append(". Same type name but different assemblies.");
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.Append(" ");
|
||||
msg.Append(modelType.FullName);
|
||||
msg.Append(".");
|
||||
msg.Append(" Types come from two PureLive assemblies with different versions,");
|
||||
msg.Append(" this usually indicates that the application is in an unstable state.");
|
||||
msg.Append(" The application is restarting now, reload the page and it should work.");
|
||||
var context = HttpContext.Current;
|
||||
if (context == null)
|
||||
AppDomain.Unload(AppDomain.CurrentDomain);
|
||||
else
|
||||
ApplicationContext.Current.RestartApplicationPool(new HttpContextWrapper(context));
|
||||
}
|
||||
|
||||
throw new ModelBindingException(msg.ToString());
|
||||
@@ -160,7 +176,7 @@ namespace Umbraco.Web.Mvc
|
||||
{
|
||||
return TypeHelper.IsTypeAssignableFrom<IRenderModel>(modelType) || TypeHelper.IsTypeAssignableFrom<IPublishedContent>(modelType)
|
||||
? this
|
||||
: null;
|
||||
: null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web.Mvc;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Web.Routing;
|
||||
using Umbraco.Web.Security;
|
||||
@@ -18,6 +17,7 @@ namespace Umbraco.Web.Mvc
|
||||
/// authorization of each method can use this attribute instead of inheriting from this controller.
|
||||
/// </remarks>
|
||||
[UmbracoAuthorize]
|
||||
[DisableBrowserCache]
|
||||
public abstract class UmbracoAuthorizedController : UmbracoController
|
||||
{
|
||||
|
||||
|
||||
@@ -120,10 +120,9 @@ namespace Umbraco.Web.Mvc
|
||||
base.InitializePage();
|
||||
if (ViewContext.IsChildAction == false)
|
||||
{
|
||||
if (ViewContext.RouteData.DataTokens.ContainsKey(Constants.DataTokenCurrentViewContext) == false)
|
||||
{
|
||||
ViewContext.RouteData.DataTokens.Add(Constants.DataTokenCurrentViewContext, ViewContext);
|
||||
}
|
||||
//always ensure the special data token is set - this is used purely for partial view macros that contain forms
|
||||
// and mostly just when rendered within the RTE
|
||||
ViewContext.RouteData.DataTokens[Constants.DataTokenCurrentViewContext] = ViewContext;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using Microsoft.AspNet.Identity;
|
||||
@@ -31,9 +32,7 @@ namespace Umbraco.Web.Security.Identity
|
||||
{
|
||||
app.SetLoggerFactory(new OwinLoggerFactory());
|
||||
}
|
||||
|
||||
#region Backoffice
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Configure Default Identity User Manager for Umbraco
|
||||
/// </summary>
|
||||
@@ -114,7 +113,24 @@ namespace Umbraco.Web.Security.Identity
|
||||
/// <param name="app"></param>
|
||||
/// <param name="appContext"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// By default this will be configured to execute on PipelineStage.Authenticate
|
||||
/// </remarks>
|
||||
public static IAppBuilder UseUmbracoBackOfficeCookieAuthentication(this IAppBuilder app, ApplicationContext appContext)
|
||||
{
|
||||
return app.UseUmbracoBackOfficeCookieAuthentication(appContext, PipelineStage.Authenticate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the UmbracoBackOfficeAuthenticationMiddleware is assigned to the pipeline
|
||||
/// </summary>
|
||||
/// <param name="app"></param>
|
||||
/// <param name="appContext"></param>
|
||||
/// <param name="stage">
|
||||
/// Configurable pipeline stage
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
public static IAppBuilder UseUmbracoBackOfficeCookieAuthentication(this IAppBuilder app, ApplicationContext appContext, PipelineStage stage)
|
||||
{
|
||||
if (app == null) throw new ArgumentNullException("app");
|
||||
if (appContext == null) throw new ArgumentNullException("appContext");
|
||||
@@ -131,28 +147,18 @@ namespace Umbraco.Web.Security.Identity
|
||||
identity => identity.GetUserId<int>()),
|
||||
};
|
||||
|
||||
var authOptions = new UmbracoBackOfficeCookieAuthOptions(
|
||||
UmbracoConfig.For.UmbracoSettings().Security,
|
||||
GlobalSettings.TimeOutInMinutes,
|
||||
GlobalSettings.UseSSL)
|
||||
{
|
||||
Provider = cookieAuthProvider
|
||||
};
|
||||
var authOptions = CreateCookieAuthOptions();
|
||||
authOptions.Provider = cookieAuthProvider;
|
||||
|
||||
app.UseUmbracoBackOfficeCookieAuthentication(authOptions, appContext);
|
||||
app.UseUmbracoBackOfficeCookieAuthentication(authOptions, appContext, stage);
|
||||
|
||||
//don't apply if app isnot ready
|
||||
if (appContext.IsUpgrading || appContext.IsConfigured)
|
||||
{
|
||||
var getSecondsOptions = new UmbracoBackOfficeCookieAuthOptions(
|
||||
var getSecondsOptions = CreateCookieAuthOptions(
|
||||
//This defines the explicit path read cookies from for this middleware
|
||||
new[]{string.Format("{0}/backoffice/UmbracoApi/Authentication/GetRemainingTimeoutSeconds", GlobalSettings.Path)},
|
||||
UmbracoConfig.For.UmbracoSettings().Security,
|
||||
GlobalSettings.TimeOutInMinutes,
|
||||
GlobalSettings.UseSSL)
|
||||
{
|
||||
Provider = cookieAuthProvider
|
||||
};
|
||||
new[] {string.Format("{0}/backoffice/UmbracoApi/Authentication/GetRemainingTimeoutSeconds", GlobalSettings.Path)});
|
||||
getSecondsOptions.Provider = cookieAuthProvider;
|
||||
|
||||
//This is a custom middleware, we need to return the user's remaining logged in seconds
|
||||
app.Use<GetUserSecondsMiddleWare>(
|
||||
@@ -164,7 +170,7 @@ namespace Umbraco.Web.Security.Identity
|
||||
return app;
|
||||
}
|
||||
|
||||
internal static IAppBuilder UseUmbracoBackOfficeCookieAuthentication(this IAppBuilder app, CookieAuthenticationOptions options, ApplicationContext appContext)
|
||||
internal static IAppBuilder UseUmbracoBackOfficeCookieAuthentication(this IAppBuilder app, CookieAuthenticationOptions options, ApplicationContext appContext, PipelineStage stage = PipelineStage.Authenticate)
|
||||
{
|
||||
if (app == null)
|
||||
{
|
||||
@@ -173,22 +179,21 @@ namespace Umbraco.Web.Security.Identity
|
||||
|
||||
//First the normal cookie middleware
|
||||
app.Use(typeof(CookieAuthenticationMiddleware), app, options);
|
||||
app.UseStageMarker(PipelineStage.Authenticate);
|
||||
|
||||
//don't apply if app isnot ready
|
||||
if (appContext.IsUpgrading || appContext.IsConfigured)
|
||||
{
|
||||
//Then our custom middlewares
|
||||
app.Use(typeof(ForceRenewalCookieAuthenticationMiddleware), app, options, new SingletonUmbracoContextAccessor());
|
||||
app.UseStageMarker(PipelineStage.Authenticate);
|
||||
app.Use(typeof(FixWindowsAuthMiddlware));
|
||||
app.UseStageMarker(PipelineStage.Authenticate);
|
||||
app.Use(typeof(FixWindowsAuthMiddlware));
|
||||
}
|
||||
|
||||
|
||||
//Marks all of the above middlewares to execute on Authenticate
|
||||
app.UseStageMarker(stage);
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the cookie middleware for validating external logins is assigned to the pipeline with the correct
|
||||
/// Umbraco back office configuration
|
||||
@@ -196,7 +201,23 @@ namespace Umbraco.Web.Security.Identity
|
||||
/// <param name="app"></param>
|
||||
/// <param name="appContext"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// By default this will be configured to execute on PipelineStage.Authenticate
|
||||
/// </remarks>
|
||||
public static IAppBuilder UseUmbracoBackOfficeExternalCookieAuthentication(this IAppBuilder app, ApplicationContext appContext)
|
||||
{
|
||||
return app.UseUmbracoBackOfficeExternalCookieAuthentication(appContext, PipelineStage.Authenticate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the cookie middleware for validating external logins is assigned to the pipeline with the correct
|
||||
/// Umbraco back office configuration
|
||||
/// </summary>
|
||||
/// <param name="app"></param>
|
||||
/// <param name="appContext"></param>
|
||||
/// <param name="stage"></param>
|
||||
/// <returns></returns>
|
||||
public static IAppBuilder UseUmbracoBackOfficeExternalCookieAuthentication(this IAppBuilder app, ApplicationContext appContext, PipelineStage stage)
|
||||
{
|
||||
if (app == null) throw new ArgumentNullException("app");
|
||||
if (appContext == null) throw new ArgumentNullException("appContext");
|
||||
@@ -213,15 +234,82 @@ namespace Umbraco.Web.Security.Identity
|
||||
CookieSecure = GlobalSettings.UseSSL ? CookieSecureOption.Always : CookieSecureOption.SameAsRequest,
|
||||
CookieHttpOnly = true,
|
||||
CookieDomain = UmbracoConfig.For.UmbracoSettings().Security.AuthCookieDomain
|
||||
});
|
||||
}, stage);
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// In order for preview to work this needs to be called
|
||||
/// </summary>
|
||||
/// <param name="app"></param>
|
||||
/// <param name="appContext"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This ensures that during a preview request that the back office use is also Authenticated and that the back office Identity
|
||||
/// is added as a secondary identity to the current IPrincipal so it can be used to Authorize the previewed document.
|
||||
/// </remarks>
|
||||
/// <remarks>
|
||||
/// By default this will be configured to execute on PipelineStage.PostAuthenticate
|
||||
/// </remarks>
|
||||
public static IAppBuilder UseUmbracoPreviewAuthentication(this IAppBuilder app, ApplicationContext appContext)
|
||||
{
|
||||
return app.UseUmbracoPreviewAuthentication(appContext, PipelineStage.PostAuthenticate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// In order for preview to work this needs to be called
|
||||
/// </summary>
|
||||
/// <param name="app"></param>
|
||||
/// <param name="appContext"></param>
|
||||
/// <param name="stage"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This ensures that during a preview request that the back office use is also Authenticated and that the back office Identity
|
||||
/// is added as a secondary identity to the current IPrincipal so it can be used to Authorize the previewed document.
|
||||
/// </remarks>
|
||||
public static IAppBuilder UseUmbracoPreviewAuthentication(this IAppBuilder app, ApplicationContext appContext, PipelineStage stage)
|
||||
{
|
||||
//don't apply if app isnot ready
|
||||
if (appContext.IsConfigured)
|
||||
{
|
||||
var authOptions = CreateCookieAuthOptions();
|
||||
app.Use(typeof(PreviewAuthenticationMiddleware), authOptions);
|
||||
|
||||
//This middleware must execute at least on PostAuthentication, by default it is on Authorize
|
||||
// The middleware needs to execute after the RoleManagerModule executes which is during PostAuthenticate,
|
||||
// currently I've had 100% success with ensuring this fires after RoleManagerModule even if this is set
|
||||
// to PostAuthenticate though not sure if that's always a guarantee so by default it's Authorize.
|
||||
if (stage < PipelineStage.PostAuthenticate)
|
||||
{
|
||||
throw new InvalidOperationException("The stage specified for UseUmbracoPreviewAuthentication must be greater than or equal to " + PipelineStage.PostAuthenticate);
|
||||
}
|
||||
|
||||
|
||||
app.UseStageMarker(stage);
|
||||
}
|
||||
|
||||
return app;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public static void SanitizeThreadCulture(this IAppBuilder app)
|
||||
{
|
||||
Thread.CurrentThread.SanitizeThreadCulture();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create the default umb cookie auth options
|
||||
/// </summary>
|
||||
/// <param name="explicitPaths"></param>
|
||||
/// <returns></returns>
|
||||
private static UmbracoBackOfficeCookieAuthOptions CreateCookieAuthOptions(string[] explicitPaths = null)
|
||||
{
|
||||
var authOptions = new UmbracoBackOfficeCookieAuthOptions(
|
||||
explicitPaths,
|
||||
UmbracoConfig.For.UmbracoSettings().Security,
|
||||
GlobalSettings.TimeOutInMinutes,
|
||||
GlobalSettings.UseSSL);
|
||||
return authOptions;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -101,9 +101,7 @@ namespace Umbraco.Web.Security.Identity
|
||||
//check back office
|
||||
|| request.Uri.IsBackOfficeRequest(HttpRuntime.AppDomainAppVirtualPath)
|
||||
//check installer
|
||||
|| request.Uri.IsInstallerRequest()
|
||||
//detect in preview
|
||||
|| (request.HasPreviewCookie() && request.Uri != null && request.Uri.AbsolutePath.StartsWith(IOHelper.ResolveUrl(SystemDirectories.Umbraco)) == false)
|
||||
|| request.Uri.IsInstallerRequest()
|
||||
//check for base
|
||||
|| BaseRest.BaseRestHandler.IsBaseRestRequest(originalRequestUrl))
|
||||
{
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using Microsoft.AspNet.Identity;
|
||||
using Microsoft.AspNet.Identity.Owin;
|
||||
using Microsoft.Owin;
|
||||
using Microsoft.Owin.Extensions;
|
||||
using Microsoft.Owin.Logging;
|
||||
using Microsoft.Owin.Security;
|
||||
using Microsoft.Owin.Security.Cookies;
|
||||
using Owin;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.Identity;
|
||||
using Umbraco.Core.Security;
|
||||
using Constants = Umbraco.Core.Constants;
|
||||
|
||||
namespace Umbraco.Web.Security.Identity
|
||||
{
|
||||
internal class PreviewAuthenticationMiddleware : OwinMiddleware
|
||||
{
|
||||
private readonly UmbracoBackOfficeCookieAuthOptions _cookieOptions;
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates the middleware with an optional pointer to the next component.
|
||||
/// </summary>
|
||||
/// <param name="next"/>
|
||||
/// <param name="cookieOptions"></param>
|
||||
public PreviewAuthenticationMiddleware(OwinMiddleware next,
|
||||
UmbracoBackOfficeCookieAuthOptions cookieOptions) : base(next)
|
||||
{
|
||||
_cookieOptions = cookieOptions;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process an individual request.
|
||||
/// </summary>
|
||||
/// <param name="context"/>
|
||||
/// <returns/>
|
||||
public override async Task Invoke(IOwinContext context)
|
||||
{
|
||||
var request = context.Request;
|
||||
if (request.Uri.IsClientSideRequest() == false)
|
||||
{
|
||||
var claimsPrincipal = context.Request.User as ClaimsPrincipal;
|
||||
var isPreview = request.HasPreviewCookie()
|
||||
&& claimsPrincipal != null
|
||||
&& request.Uri != null
|
||||
&& request.Uri.IsBackOfficeRequest(HttpRuntime.AppDomainAppVirtualPath) == false;
|
||||
if (isPreview)
|
||||
{
|
||||
//If we've gotten this far it means a preview cookie has been set and a front-end umbraco document request is executing.
|
||||
// In this case, authentication will not have occurred for an Umbraco back office User, however we need to perform the authentication
|
||||
// for the user here so that the preview capability can be authorized otherwise only the non-preview page will be rendered.
|
||||
|
||||
var cookie = request.Cookies[_cookieOptions.CookieName];
|
||||
if (cookie.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
var unprotected = _cookieOptions.TicketDataFormat.Unprotect(cookie);
|
||||
if (unprotected != null)
|
||||
{
|
||||
//Ok, we've got a real ticket, now we can add this ticket's identity to the current
|
||||
// Principal, this means we'll have 2 identities assigned to the principal which we can
|
||||
// use to authorize the preview and allow for a back office User.
|
||||
claimsPrincipal.AddIdentity(UmbracoBackOfficeIdentity.FromClaimsIdentity(unprotected.Identity));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Next != null)
|
||||
{
|
||||
await Next.Invoke(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ using Umbraco.Core.Security;
|
||||
using Umbraco.Web.Models;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Web.Security.Providers;
|
||||
using MPE = global::Umbraco.Core.Security.MembershipProviderExtensions;
|
||||
|
||||
namespace Umbraco.Web.Security
|
||||
@@ -30,7 +31,7 @@ namespace Umbraco.Web.Security
|
||||
|
||||
#region Constructors
|
||||
public MembershipHelper(ApplicationContext applicationContext, HttpContextBase httpContext)
|
||||
: this(applicationContext, httpContext, MPE.GetMembersMembershipProvider(), Roles.Provider)
|
||||
: this(applicationContext, httpContext, MPE.GetMembersMembershipProvider(), Roles.Enabled ? Roles.Provider : new MembersRoleProvider(applicationContext.Services.MemberService))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -47,7 +48,7 @@ namespace Umbraco.Web.Security
|
||||
}
|
||||
|
||||
public MembershipHelper(UmbracoContext umbracoContext)
|
||||
: this(umbracoContext, MPE.GetMembersMembershipProvider(), Roles.Provider)
|
||||
: this(umbracoContext, MPE.GetMembersMembershipProvider(), Roles.Enabled ? Roles.Provider: new MembersRoleProvider(umbracoContext.Application.Services.MemberService))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -343,6 +343,8 @@
|
||||
<Compile Include="Models\Mapping\PropertyGroupDisplayResolver.cs" />
|
||||
<Compile Include="Models\PublishedContentWithKeyBase.cs" />
|
||||
<Compile Include="Mvc\ControllerContextExtensions.cs" />
|
||||
<Compile Include="Mvc\DisableBrowserCacheAttribute.cs" />
|
||||
<Compile Include="Mvc\EnsurePartialViewMacroViewContextFilterAttribute.cs" />
|
||||
<Compile Include="Mvc\IRenderController.cs" />
|
||||
<Compile Include="Mvc\ModelBindingException.cs" />
|
||||
<Compile Include="Mvc\RenderIndexActionSelectorAttribute.cs" />
|
||||
@@ -366,6 +368,7 @@
|
||||
<Compile Include="Media\EmbedProviders\OEmbedPhoto.cs" />
|
||||
<Compile Include="Security\Identity\IUmbracoBackOfficeTwoFactorOptions.cs" />
|
||||
<Compile Include="Models\Mapping\PropertyTypeGroupResolver.cs" />
|
||||
<Compile Include="Security\Identity\PreviewAuthenticationMiddleware.cs" />
|
||||
<Compile Include="SingletonHttpContextAccessor.cs" />
|
||||
<Compile Include="Trees\ContentTypeTreeController.cs" />
|
||||
<Compile Include="Trees\MediaTypeTreeController.cs" />
|
||||
|
||||
@@ -466,14 +466,11 @@ namespace Umbraco.Web
|
||||
var request = GetRequestFromContext();
|
||||
if (request == null || request.Url == null)
|
||||
return false;
|
||||
|
||||
var currentUrl = request.Url.AbsolutePath;
|
||||
// zb-00004 #29956 : refactor cookies names & handling
|
||||
|
||||
return
|
||||
//StateHelper.Cookies.Preview.HasValue // has preview cookie
|
||||
HttpContext.Request.HasPreviewCookie()
|
||||
&& currentUrl.StartsWith(IOHelper.ResolveUrl(SystemDirectories.Umbraco)) == false
|
||||
&& UmbracoUser != null; // has user
|
||||
&& request.Url.IsBackOfficeRequest(HttpRuntime.AppDomainAppVirtualPath) == false
|
||||
&& Security.CurrentUser != null; // has user
|
||||
}
|
||||
|
||||
private HttpRequestBase GetRequestFromContext()
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Microsoft.Owin;
|
||||
using System.Web;
|
||||
using Microsoft.Owin;
|
||||
using Microsoft.Owin.Extensions;
|
||||
using Microsoft.Owin.Logging;
|
||||
using Owin;
|
||||
using Umbraco.Core;
|
||||
@@ -19,23 +21,50 @@ namespace Umbraco.Web
|
||||
/// </remarks>
|
||||
public class UmbracoDefaultOwinStartup
|
||||
{
|
||||
/// <summary>
|
||||
/// Main startup method
|
||||
/// </summary>
|
||||
/// <param name="app"></param>
|
||||
public virtual void Configuration(IAppBuilder app)
|
||||
{
|
||||
app.SanitizeThreadCulture();
|
||||
|
||||
ConfigureServices(app);
|
||||
ConfigureMiddleware(app);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configures services to be created in the OWIN context (CreatePerOwinContext)
|
||||
/// </summary>
|
||||
/// <param name="app"></param>
|
||||
protected virtual void ConfigureServices(IAppBuilder app)
|
||||
{
|
||||
app.SetUmbracoLoggerFactory();
|
||||
|
||||
//Configure the Identity user manager for use with Umbraco Back office
|
||||
// (EXPERT: an overload accepts a custom BackOfficeUserStore implementation)
|
||||
app.ConfigureUserManagerForUmbracoBackOffice(
|
||||
ApplicationContext.Current,
|
||||
ApplicationContext,
|
||||
Core.Security.MembershipProviderExtensions.GetUsersMembershipProvider().AsUmbracoMembershipProvider());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configures middleware to be used (i.e. app.Use...)
|
||||
/// </summary>
|
||||
/// <param name="app"></param>
|
||||
protected virtual void ConfigureMiddleware(IAppBuilder app)
|
||||
{
|
||||
//Ensure owin is configured for Umbraco back office authentication. If you have any front-end OWIN
|
||||
// cookie configuration, this must be declared after it.
|
||||
app
|
||||
.UseUmbracoBackOfficeCookieAuthentication(ApplicationContext.Current)
|
||||
.UseUmbracoBackOfficeExternalCookieAuthentication(ApplicationContext.Current);
|
||||
.UseUmbracoBackOfficeCookieAuthentication(ApplicationContext, PipelineStage.Authenticate)
|
||||
.UseUmbracoBackOfficeExternalCookieAuthentication(ApplicationContext, PipelineStage.Authenticate)
|
||||
.UseUmbracoPreviewAuthentication(ApplicationContext, PipelineStage.Authorize);
|
||||
}
|
||||
|
||||
protected virtual ApplicationContext ApplicationContext
|
||||
{
|
||||
get { return ApplicationContext.Current; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@ using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Web.WebApi.Filters
|
||||
{
|
||||
/// <summary>
|
||||
/// Ensures that the request is not cached by the browser
|
||||
/// </summary>
|
||||
public class DisableBrowserCacheAttribute : ActionFilterAttribute
|
||||
{
|
||||
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
|
||||
@@ -21,23 +24,16 @@ namespace Umbraco.Web.WebApi.Filters
|
||||
|
||||
base.OnActionExecuted(actionExecutedContext);
|
||||
|
||||
//TODO: This should all work without issue! BUT it doesn't, i have a feeling this might be fixed
|
||||
// in the next webapi version. ASP.Net is overwriting the cachecontrol all the time, some docs are here:
|
||||
// http://stackoverflow.com/questions/11547618/output-caching-for-an-apicontroller-mvc4-web-api
|
||||
// and I've checked the source code so doing this should cause it to write the headers we want but it doesnt.
|
||||
//So I've reverted to brute force on the HttpContext.
|
||||
//actionExecutedContext.Response.Headers.CacheControl = new CacheControlHeaderValue()
|
||||
//{
|
||||
// NoCache = true,
|
||||
// NoStore = true,
|
||||
// MaxAge = new TimeSpan(0),
|
||||
// MustRevalidate = true
|
||||
//};
|
||||
|
||||
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
|
||||
HttpContext.Current.Response.Cache.SetMaxAge(TimeSpan.Zero);
|
||||
HttpContext.Current.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
|
||||
HttpContext.Current.Response.Cache.SetNoStore();
|
||||
//NOTE: Until we upgraded to WebApi 2, this didn't work correctly and we had to revert to using
|
||||
// HttpContext.Current responses. I've changed this back to what it should be now since it works
|
||||
// and now with WebApi2, the HttpContext.Current responses dont! Anyways, all good now.
|
||||
actionExecutedContext.Response.Headers.CacheControl = new CacheControlHeaderValue()
|
||||
{
|
||||
NoCache = true,
|
||||
NoStore = true,
|
||||
MaxAge = new TimeSpan(0),
|
||||
MustRevalidate = true
|
||||
};
|
||||
|
||||
actionExecutedContext.Response.Headers.Pragma.Add(new NameValueHeaderValue("no-cache"));
|
||||
if (actionExecutedContext.Response.Content != null)
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace Umbraco.Web.WebApi
|
||||
[IsBackOffice]
|
||||
[UmbracoUserTimeoutFilter]
|
||||
[UmbracoAuthorize]
|
||||
[DisableBrowserCache]
|
||||
public abstract class UmbracoAuthorizedApiController : UmbracoApiController
|
||||
{
|
||||
protected UmbracoAuthorizedApiController()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user