Merge remote-tracking branch 'origin/7.4.0' into dev-v7-deploy
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -131,3 +131,4 @@ src/*.boltdata/
|
||||
src/umbraco.sln.ide/*
|
||||
build/UmbracoCms.*/
|
||||
src/.vs/
|
||||
src/Umbraco.Web.UI/umbraco/js/install.loader.js
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<dependency id="HtmlAgilityPack" version="[1.4.9, 2.0.0)" />
|
||||
<dependency id="Lucene.Net" version="[2.9.4.1, 3.0.0.0)" />
|
||||
<dependency id="SharpZipLib" version="[0.86.0, 1.0.0)" />
|
||||
<dependency id="MySql.Data" version="[6.9.7, 7.0.0)" />
|
||||
<dependency id="MySql.Data" version="[6.9.8, 7.0.0)" />
|
||||
<dependency id="xmlrpcnet" version="[2.5.0, 3.0.0)" />
|
||||
<dependency id="ClientDependency" version="[1.8.4, 2.0.0)" />
|
||||
<dependency id="ClientDependency-Mvc5" version="[1.8.0, 2.0.0)" />
|
||||
|
||||
@@ -62,13 +62,6 @@
|
||||
views/dashboard/default/startupdashboardintro.html
|
||||
</control>
|
||||
</tab>
|
||||
<tab caption="Change password" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
|
||||
<tab caption="Change Password" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
|
||||
<tab caption="Change Password" xdt:Transform="Insert">
|
||||
<control showOnce="false" addPanel="false" panelCaption="">
|
||||
views/dashboard/ChangePassword.html
|
||||
</control>
|
||||
</tab>
|
||||
<tab caption="Last Edits" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
|
||||
</section>
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ if ($project) {
|
||||
if(Test-Path $umbracoBinFolder\MiniProfiler.dll) { Remove-Item $umbracoBinFolder\MiniProfiler.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\MySql.Data.dll) { Remove-Item $umbracoBinFolder\MySql.Data.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\Newtonsoft.Json.dll) { Remove-Item $umbracoBinFolder\Newtonsoft.Json.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\System.Web.Helpers.dll) { Remove-Item $umbracoBinFolder\System.Web.Helpers.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\System.Net.Http.Formatting.dll) { Remove-Item $umbracoBinFolder\System.Net.Http.Formatting.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\System.Web.Http.dll) { Remove-Item $umbracoBinFolder\System.Web.Http.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\System.Web.Http.WebHost.dll) { Remove-Item $umbracoBinFolder\System.Web.Http.WebHost.dll -Force -Confirm:$false }
|
||||
|
||||
@@ -11,5 +11,5 @@ using System.Resources;
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.3.1")]
|
||||
[assembly: AssemblyInformationalVersion("7.3.1")]
|
||||
[assembly: AssemblyFileVersion("7.4.0")]
|
||||
[assembly: AssemblyInformationalVersion("7.4.0")]
|
||||
@@ -11,7 +11,7 @@ namespace Umbraco.Core
|
||||
/// <summary>
|
||||
/// A resolver to return all IAction objects
|
||||
/// </summary>
|
||||
internal sealed class ActionsResolver : LazyManyObjectsResolverBase<ActionsResolver, IAction>
|
||||
public sealed class ActionsResolver : LazyManyObjectsResolverBase<ActionsResolver, IAction>
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
|
||||
@@ -283,7 +283,12 @@ namespace Umbraco.Core
|
||||
{
|
||||
var configStatus = ConfigurationStatus;
|
||||
var currentVersion = UmbracoVersion.GetSemanticVersion();
|
||||
var ok = configStatus == currentVersion;
|
||||
|
||||
var ok =
|
||||
//we are not configured if this is null
|
||||
string.IsNullOrWhiteSpace(configStatus) == false
|
||||
//they must match
|
||||
&& configStatus == currentVersion;
|
||||
|
||||
if (ok)
|
||||
{
|
||||
@@ -308,8 +313,9 @@ namespace Umbraco.Core
|
||||
|
||||
return ok;
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error<ApplicationContext>("Error determining if application is configured, returning false", ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
public const string Users = "users";
|
||||
|
||||
/// <summary>
|
||||
/// Application alias for the users section.
|
||||
/// Application alias for the forms section.
|
||||
/// </summary>
|
||||
public const string Forms = "forms";
|
||||
}
|
||||
|
||||
@@ -315,13 +315,13 @@ namespace Umbraco.Core
|
||||
public const string TextboxAlias = "Umbraco.Textbox";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for the Textbox multiple datatype.
|
||||
/// Guid for the Textarea datatype.
|
||||
/// </summary>
|
||||
[Obsolete("GUIDs are no longer used to reference Property Editors, use the Alias constant instead. This will be removed in future versions")]
|
||||
public const string TextboxMultiple = "67DB8357-EF57-493E-91AC-936D305E0F2A";
|
||||
|
||||
/// <summary>
|
||||
/// Alias for the Textbox multiple datatype.
|
||||
/// Alias for the Textarea datatype.
|
||||
/// </summary>
|
||||
public const string TextboxMultipleAlias = "Umbraco.TextboxMultiple";
|
||||
|
||||
|
||||
31
src/Umbraco.Core/Constants-PropertyTypeGroups.cs
Normal file
31
src/Umbraco.Core/Constants-PropertyTypeGroups.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public static partial class Constants
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the identifiers for property-type groups conventions that are used within the Umbraco core.
|
||||
/// </summary>
|
||||
public static class PropertyTypeGroups
|
||||
{
|
||||
/// <summary>
|
||||
/// Guid for a Image PropertyTypeGroup object.
|
||||
/// </summary>
|
||||
public const string Image = "79ED4D07-254A-42CF-8FA9-EBE1C116A596";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a File PropertyTypeGroup object.
|
||||
/// </summary>
|
||||
public const string File = "50899F9C-023A-4466-B623-ABA9049885FE";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Image PropertyTypeGroup object.
|
||||
/// </summary>
|
||||
public const string Contents = "79995FA2-63EE-453C-A29B-2E66F324CDBE";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Image PropertyTypeGroup object.
|
||||
/// </summary>
|
||||
public const string Membership = "0756729D-D665-46E3-B84A-37ACEAA614F8";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
namespace Umbraco.Core
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public static partial class Constants
|
||||
{
|
||||
@@ -15,6 +18,8 @@
|
||||
/// <summary>
|
||||
/// The auth cookie name
|
||||
/// </summary>
|
||||
[Obsolete("DO NOT USE THIS, USE ISecuritySection.AuthCookieName, this will be removed in future versions")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public const string AuthCookieName = "UMB_UCONTEXT";
|
||||
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ namespace Umbraco.Core.IO
|
||||
{
|
||||
get
|
||||
{
|
||||
return IOHelper.ReturnPath("umbracoWebservicesPath", "~/umbraco/webservices");
|
||||
return IOHelper.ReturnPath("umbracoWebservicesPath", Umbraco.EnsureEndsWith("/") + "webservices");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -560,8 +560,7 @@ namespace Umbraco.Core.Models
|
||||
//Additional thumbnails configured as prevalues on the DataType
|
||||
if (thumbnailSizes != null)
|
||||
{
|
||||
var sep = (thumbnailSizes.Contains("") == false && thumbnailSizes.Contains(",")) ? ',' : ';';
|
||||
foreach (var thumb in thumbnailSizes.Split(sep))
|
||||
foreach (var thumb in thumbnailSizes.Split(new[] { ";", "," }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
int thumbSize;
|
||||
if (thumb != "" && int.TryParse(thumb, out thumbSize))
|
||||
|
||||
@@ -538,6 +538,18 @@ namespace Umbraco.Core.Models
|
||||
/// <param name="propertyGroupName">Name of the <see cref="PropertyGroup"/> to remove</param>
|
||||
public void RemovePropertyGroup(string propertyGroupName)
|
||||
{
|
||||
// if no group exists with that name, do nothing
|
||||
var group = PropertyGroups[propertyGroupName];
|
||||
if (group == null) return;
|
||||
|
||||
// re-assign the group's properties to no group
|
||||
foreach (var property in group.PropertyTypes)
|
||||
{
|
||||
property.PropertyGroupId = new Lazy<int>(() => 0);
|
||||
_propertyTypes.Add(property);
|
||||
}
|
||||
|
||||
// actually remove the group
|
||||
PropertyGroups.RemoveItem(propertyGroupName);
|
||||
OnPropertyChanged(PropertyGroupCollectionSelector);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using AutoMapper;
|
||||
|
||||
using Umbraco.Core.Models.Mapping;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Security;
|
||||
|
||||
namespace Umbraco.Core.Models.Identity
|
||||
{
|
||||
@@ -24,6 +25,18 @@ namespace Umbraco.Core.Models.Identity
|
||||
.ForMember(user => user.UserTypeAlias, expression => expression.MapFrom(user => user.UserType.Alias))
|
||||
.ForMember(user => user.AccessFailedCount, expression => expression.MapFrom(user => user.FailedPasswordAttempts))
|
||||
.ForMember(user => user.AllowedSections, expression => expression.MapFrom(user => user.AllowedSections.ToArray()));
|
||||
|
||||
config.CreateMap<BackOfficeIdentityUser, UserData>()
|
||||
.ConstructUsing((BackOfficeIdentityUser user) => new UserData(Guid.NewGuid().ToString("N"))) //this is the 'session id'
|
||||
.ForMember(detail => detail.Id, opt => opt.MapFrom(user => user.Id))
|
||||
.ForMember(detail => detail.AllowedApplications, opt => opt.MapFrom(user => user.AllowedSections))
|
||||
.ForMember(detail => detail.RealName, opt => opt.MapFrom(user => user.Name))
|
||||
.ForMember(detail => detail.Roles, opt => opt.MapFrom(user => new[] { user.UserTypeAlias }))
|
||||
.ForMember(detail => detail.StartContentNode, opt => opt.MapFrom(user => user.StartContentId))
|
||||
.ForMember(detail => detail.StartMediaNode, opt => opt.MapFrom(user => user.StartMediaId))
|
||||
.ForMember(detail => detail.Username, opt => opt.MapFrom(user => user.UserName))
|
||||
.ForMember(detail => detail.Culture, opt => opt.MapFrom(user => user.Culture))
|
||||
.ForMember(detail => detail.SessionId, opt => opt.MapFrom(user => user.SecurityStamp.IsNullOrWhiteSpace() ? Guid.NewGuid().ToString("N") : user.SecurityStamp));
|
||||
}
|
||||
|
||||
private string GetPasswordHash(string storedPass)
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace Umbraco.Core.Models
|
||||
[IgnoreDataMember]
|
||||
public CultureInfo CultureInfo
|
||||
{
|
||||
get { return CultureInfo.CreateSpecificCulture(IsoCode); }
|
||||
get { return CultureInfo.GetCultureInfo(IsoCode); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
internal class MigrationDto
|
||||
{
|
||||
[Column("id")]
|
||||
[PrimaryKeyColumn(AutoIncrement = true)]
|
||||
[PrimaryKeyColumn(AutoIncrement = true, IdentitySeed = 100)]
|
||||
public int Id { get; set; }
|
||||
|
||||
[Column("name")]
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Umbraco.Core.Models.Identity;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -21, Trashed = false, ParentId = -1, UserId = 0, Level = 0, Path = "-1,-21", SortOrder = 0, UniqueId = new Guid("BF7C7CBC-952F-4518-97A2-69E9C7B33842"), Text = "Recycle Bin", NodeObjectType = new Guid(Constants.ObjectTypes.MediaRecycleBin), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -92, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-92", SortOrder = 35, UniqueId = new Guid("f0bc4bfb-b499-40d6-ba86-058885a5178c"), Text = "Label", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -90, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-90", SortOrder = 34, UniqueId = new Guid("84c6b441-31df-4ffe-b67e-67d5bc3ae65a"), Text = "Upload", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -89, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-89", SortOrder = 33, UniqueId = new Guid("c6bac0dd-4ab9-45b1-8e30-e4b619ee5da3"), Text = "Textbox multiple", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -89, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-89", SortOrder = 33, UniqueId = new Guid("c6bac0dd-4ab9-45b1-8e30-e4b619ee5da3"), Text = "Textarea", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -88, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-88", SortOrder = 32, UniqueId = new Guid("0cc0eba1-9960-42c9-bf9b-60e150b429ae"), Text = "Textstring", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -87, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-87", SortOrder = 4, UniqueId = new Guid("ca90c950-0aff-4e72-b976-a30b1ac57dad"), Text = "Richtext editor", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -51, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-51", SortOrder = 2, UniqueId = new Guid("2e6d3631-066e-44b8-aec4-96f09099b2b5"), Text = "Numeric", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
@@ -178,11 +178,11 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
|
||||
private void CreateCmsPropertyTypeGroupData()
|
||||
{
|
||||
_database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 3, ContentTypeNodeId = 1032, Text = "Image", SortOrder = 1, UniqueId = new Guid("79ED4D07-254A-42CF-8FA9-EBE1C116A596") });
|
||||
_database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 4, ContentTypeNodeId = 1033, Text = "File", SortOrder = 1, UniqueId = new Guid("50899F9C-023A-4466-B623-ABA9049885FE") });
|
||||
_database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 5, ContentTypeNodeId = 1031, Text = "Contents", SortOrder = 1, UniqueId = new Guid("79995FA2-63EE-453C-A29B-2E66F324CDBE") });
|
||||
_database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 3, ContentTypeNodeId = 1032, Text = "Image", SortOrder = 1, UniqueId = new Guid(Constants.PropertyTypeGroups.Image) });
|
||||
_database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 4, ContentTypeNodeId = 1033, Text = "File", SortOrder = 1, UniqueId = new Guid(Constants.PropertyTypeGroups.File) });
|
||||
_database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 5, ContentTypeNodeId = 1031, Text = "Contents", SortOrder = 1, UniqueId = new Guid(Constants.PropertyTypeGroups.Contents) });
|
||||
//membership property group
|
||||
_database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 11, ContentTypeNodeId = 1044, Text = "Membership", SortOrder = 1, UniqueId = new Guid("0756729D-D665-46E3-B84A-37ACEAA614F8") });
|
||||
_database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 11, ContentTypeNodeId = 1044, Text = "Membership", SortOrder = 1, UniqueId = new Guid(Constants.PropertyTypeGroups.Membership) });
|
||||
}
|
||||
|
||||
private void CreateCmsPropertyTypeData()
|
||||
|
||||
@@ -46,19 +46,19 @@ ON cmsContentType.nodeId = umbracoNode.id"))
|
||||
// see BaseDataCreation... built-in groups have their own guids
|
||||
if (data.grId == 3)
|
||||
{
|
||||
guid = new Guid("79ED4D07-254A-42CF-8FA9-EBE1C116A596");
|
||||
guid = new Guid(Constants.PropertyTypeGroups.Image);
|
||||
}
|
||||
else if (data.grId == 4)
|
||||
{
|
||||
guid = new Guid("50899F9C-023A-4466-B623-ABA9049885FE");
|
||||
guid = new Guid(Constants.PropertyTypeGroups.File);
|
||||
}
|
||||
else if (data.grId == 5)
|
||||
{
|
||||
guid = new Guid("79995FA2-63EE-453C-A29B-2E66F324CDBE");
|
||||
guid = new Guid(Constants.PropertyTypeGroups.Contents);
|
||||
}
|
||||
else if (data.grId == 11)
|
||||
{
|
||||
guid = new Guid("0756729D-D665-46E3-B84A-37ACEAA614F8");
|
||||
guid = new Guid(Constants.PropertyTypeGroups.Membership);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -69,7 +69,7 @@ ON cmsContentType.nodeId = umbracoNode.id"))
|
||||
}
|
||||
|
||||
// set the Unique Id to the one we've generated
|
||||
Update.Table("cmsPropertyTypeGroup").Set(new { uniqueID = guid }).Where(new { id = data.ptId });
|
||||
Update.Table("cmsPropertyTypeGroup").Set(new { uniqueID = guid }).Where(new { id = data.grId });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
@@ -18,13 +19,28 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeTw
|
||||
|
||||
public override void Up()
|
||||
{
|
||||
Delete.FromTable("umbracoMigration").AllRows();
|
||||
var migrations = Context.Database.Fetch<MigrationDto>(new Sql().Select("*").From<MigrationDto>(SqlSyntax));
|
||||
foreach (var migration in migrations)
|
||||
// Due to the delayed execution of migrations, we have to wrap this code in Execute.Code to ensure the previous
|
||||
// migration steps (esp. creating the migrations table) have completed before trying to fetch migrations from
|
||||
// this table.
|
||||
List<MigrationDto> migrations = null;
|
||||
Execute.Code(db =>
|
||||
{
|
||||
Insert.IntoTable("umbracoMigration")
|
||||
.Row(new {name = migration.Name, createDate = migration.CreateDate, version = migration.Version});
|
||||
}
|
||||
migrations = Context.Database.Fetch<MigrationDto>(new Sql().Select("*").From<MigrationDto>(SqlSyntax));
|
||||
return string.Empty;
|
||||
});
|
||||
Delete.FromTable("umbracoMigration").AllRows();
|
||||
Execute.Code(database =>
|
||||
{
|
||||
if (migrations != null)
|
||||
{
|
||||
foreach (var migration in migrations)
|
||||
{
|
||||
database.Insert("umbracoMigration", "id", true,
|
||||
new {name = migration.Name, createDate = migration.CreateDate, version = migration.Version});
|
||||
}
|
||||
}
|
||||
return string.Empty;
|
||||
});
|
||||
}
|
||||
|
||||
public override void Down()
|
||||
|
||||
@@ -31,31 +31,31 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixZeroOne
|
||||
//Fetch all PropertyTypes that belongs to a PropertyTypeGroup
|
||||
//NOTE: We are writing the full query because we've added a column to the PropertyTypeDto in later versions so one of the columns
|
||||
// won't exist yet
|
||||
var propertyTypes = database.Fetch<PropertyTypeDto>("SELECT * FROM cmsPropertyType WHERE propertyTypeGroupId > 0");
|
||||
var propertyTypes = database.Fetch<dynamic>("SELECT * FROM cmsPropertyType WHERE propertyTypeGroupId > 0");
|
||||
|
||||
var propertyGroups = database.Fetch<PropertyTypeGroupDto>("WHERE id > 0");
|
||||
|
||||
foreach (var propertyType in propertyTypes)
|
||||
{
|
||||
// get the PropertyTypeGroup of the current PropertyType, skip if not found
|
||||
var propertyTypeGroup = propertyGroups.FirstOrDefault(x => x.Id == propertyType.PropertyTypeGroupId);
|
||||
var propertyTypeGroup = propertyGroups.FirstOrDefault(x => x.Id == propertyType.propertyTypeGroupId);
|
||||
if (propertyTypeGroup == null) continue;
|
||||
|
||||
// if the PropretyTypeGroup belongs to the same content type as the PropertyType, then fine
|
||||
if (propertyTypeGroup.ContentTypeNodeId == propertyType.ContentTypeId) continue;
|
||||
if (propertyTypeGroup.ContentTypeNodeId == propertyType.contentTypeId) continue;
|
||||
|
||||
// else we want to assign the PropertyType to a proper PropertyTypeGroup
|
||||
// ie one that does belong to the same content - look for it
|
||||
var okPropertyTypeGroup = propertyGroups.FirstOrDefault(x =>
|
||||
x.Text == propertyTypeGroup.Text && // same name
|
||||
x.ContentTypeNodeId == propertyType.ContentTypeId); // but for proper content type
|
||||
x.ContentTypeNodeId == propertyType.contentTypeId); // but for proper content type
|
||||
|
||||
if (okPropertyTypeGroup == null)
|
||||
{
|
||||
// does not exist, create a new PropertyTypeGroup,
|
||||
var propertyGroup = new PropertyTypeGroupDto
|
||||
{
|
||||
ContentTypeNodeId = propertyType.ContentTypeId,
|
||||
ContentTypeNodeId = propertyType.contentTypeId,
|
||||
Text = propertyTypeGroup.Text,
|
||||
SortOrder = propertyTypeGroup.SortOrder
|
||||
};
|
||||
@@ -66,14 +66,14 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixZeroOne
|
||||
propertyGroups.Add(propertyGroup);
|
||||
|
||||
// update the PropertyType to use the new PropertyTypeGroup
|
||||
propertyType.PropertyTypeGroupId = id;
|
||||
propertyType.propertyTypeGroupId = id;
|
||||
}
|
||||
else
|
||||
{
|
||||
// exists, update PropertyType to use the PropertyTypeGroup
|
||||
propertyType.PropertyTypeGroupId = okPropertyTypeGroup.Id;
|
||||
propertyType.propertyTypeGroupId = okPropertyTypeGroup.Id;
|
||||
}
|
||||
database.Update(propertyType);
|
||||
database.Update("cmsPropertyType", "id", propertyType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -172,12 +172,12 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
((ContentType)entity).AddingEntity();
|
||||
|
||||
PersistNewBaseContentType(entity);
|
||||
PersisteTemplates(entity, false);
|
||||
PersistTemplates(entity, false);
|
||||
|
||||
entity.ResetDirtyProperties();
|
||||
}
|
||||
|
||||
protected void PersisteTemplates(IContentType entity, bool clearAll)
|
||||
protected void PersistTemplates(IContentType entity, bool clearAll)
|
||||
{
|
||||
// remove and insert, if required
|
||||
Database.Delete<ContentTypeTemplateDto>("WHERE contentTypeNodeId = @Id", new { Id = entity.Id });
|
||||
@@ -225,7 +225,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
|
||||
PersistUpdatedBaseContentType(entity);
|
||||
PersisteTemplates(entity, true);
|
||||
PersistTemplates(entity, true);
|
||||
|
||||
entity.ResetDirtyProperties();
|
||||
}
|
||||
|
||||
@@ -701,14 +701,16 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
public RenderingEngine DetermineTemplateRenderingEngine(ITemplate template)
|
||||
{
|
||||
var engine = _templateConfig.DefaultRenderingEngine;
|
||||
|
||||
if (template.Content.IsNullOrWhiteSpace() == false && MasterPageHelper.IsMasterPageSyntax(template.Content))
|
||||
var viewHelper = new ViewHelper(_viewsFileSystem);
|
||||
if (!viewHelper.ViewExists(template))
|
||||
{
|
||||
//there is a design but its definitely a webforms design
|
||||
return RenderingEngine.WebForms;
|
||||
if (template.Content.IsNullOrWhiteSpace() == false && MasterPageHelper.IsMasterPageSyntax(template.Content))
|
||||
{
|
||||
//there is a design but its definitely a webforms design and we haven't got a MVC view already for it
|
||||
return RenderingEngine.WebForms;
|
||||
}
|
||||
}
|
||||
|
||||
var viewHelper = new ViewHelper(_viewsFileSystem);
|
||||
var masterPageHelper = new MasterPageHelper(_masterpagesFileSystem);
|
||||
|
||||
switch (engine)
|
||||
|
||||
@@ -117,7 +117,7 @@ namespace Umbraco.Core.Persistence
|
||||
|
||||
public override void OnException(Exception x)
|
||||
{
|
||||
_logger.Info<UmbracoDatabase>(x.StackTrace);
|
||||
_logger.Error<UmbracoDatabase>("Database exception occurred", x);
|
||||
base.OnException(x);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
@@ -15,7 +16,6 @@ using Microsoft.Owin;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Microsoft.Owin;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core.Security
|
||||
@@ -157,9 +157,6 @@ namespace Umbraco.Core.Security
|
||||
return new HttpContextWrapper(http).GetCurrentIdentity(authenticateRequestIfNotFound);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This clears the forms authentication cookie
|
||||
/// </summary>
|
||||
public static void UmbracoLogout(this HttpContextBase http)
|
||||
{
|
||||
if (http == null) throw new ArgumentNullException("http");
|
||||
@@ -170,6 +167,8 @@ namespace Umbraco.Core.Security
|
||||
/// This clears the forms authentication cookie for webapi since cookies are handled differently
|
||||
/// </summary>
|
||||
/// <param name="response"></param>
|
||||
[Obsolete("Use OWIN IAuthenticationManager.SignOut instead")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public static void UmbracoLogoutWebApi(this HttpResponseMessage response)
|
||||
{
|
||||
if (response == null) throw new ArgumentNullException("response");
|
||||
@@ -195,11 +194,8 @@ namespace Umbraco.Core.Security
|
||||
response.Headers.AddCookies(new[] { authCookie, prevCookie, extLoginCookie });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This adds the forms authentication cookie for webapi since cookies are handled differently
|
||||
/// </summary>
|
||||
/// <param name="response"></param>
|
||||
/// <param name="user"></param>
|
||||
[Obsolete("Use WebSecurity.SetPrincipalForRequest")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public static FormsAuthenticationTicket UmbracoLoginWebApi(this HttpResponseMessage response, IUser user)
|
||||
{
|
||||
if (response == null) throw new ArgumentNullException("response");
|
||||
@@ -250,26 +246,29 @@ namespace Umbraco.Core.Security
|
||||
if (http == null) throw new ArgumentNullException("http");
|
||||
new HttpContextWrapper(http).UmbracoLogout();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Renews the Umbraco authentication ticket
|
||||
/// This will force ticket renewal in the OWIN pipeline
|
||||
/// </summary>
|
||||
/// <param name="http"></param>
|
||||
/// <returns></returns>
|
||||
public static bool RenewUmbracoAuthTicket(this HttpContextBase http)
|
||||
{
|
||||
if (http == null) throw new ArgumentNullException("http");
|
||||
return RenewAuthTicket(http,
|
||||
UmbracoConfig.For.UmbracoSettings().Security.AuthCookieName,
|
||||
UmbracoConfig.For.UmbracoSettings().Security.AuthCookieDomain,
|
||||
//Umbraco has always persisted it's original cookie for 1 day so we'll keep it that way
|
||||
1440);
|
||||
http.Items["umbraco-force-auth"] = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will force ticket renewal in the OWIN pipeline
|
||||
/// </summary>
|
||||
/// <param name="http"></param>
|
||||
/// <returns></returns>
|
||||
internal static bool RenewUmbracoAuthTicket(this HttpContext http)
|
||||
{
|
||||
if (http == null) throw new ArgumentNullException("http");
|
||||
return new HttpContextWrapper(http).RenewUmbracoAuthTicket();
|
||||
http.Items["umbraco-force-auth"] = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -390,8 +389,7 @@ namespace Umbraco.Core.Security
|
||||
//ensure there's def an expired cookie
|
||||
http.Response.Cookies.Add(new HttpCookie(c) { Expires = DateTime.Now.AddYears(-1) });
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static FormsAuthenticationTicket GetAuthTicket(this HttpContextBase http, string cookieName)
|
||||
@@ -432,51 +430,6 @@ namespace Umbraco.Core.Security
|
||||
return FormsAuthentication.Decrypt(formsCookie);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renews the forms authentication ticket & cookie
|
||||
/// </summary>
|
||||
/// <param name="http"></param>
|
||||
/// <param name="cookieName"></param>
|
||||
/// <param name="cookieDomain"></param>
|
||||
/// <param name="minutesPersisted"></param>
|
||||
/// <returns>true if there was a ticket to renew otherwise false if there was no ticket</returns>
|
||||
private static bool RenewAuthTicket(this HttpContextBase http, string cookieName, string cookieDomain, int minutesPersisted)
|
||||
{
|
||||
if (http == null) throw new ArgumentNullException("http");
|
||||
//get the ticket
|
||||
var ticket = GetAuthTicket(http, cookieName);
|
||||
//renew the ticket
|
||||
var renewed = FormsAuthentication.RenewTicketIfOld(ticket);
|
||||
if (renewed == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//get the request cookie to get it's expiry date,
|
||||
//NOTE: this will never be null becaues we already do this
|
||||
// check in teh GetAuthTicket.
|
||||
var formsCookie = http.Request.Cookies[cookieName];
|
||||
|
||||
//encrypt it
|
||||
var hash = FormsAuthentication.Encrypt(renewed);
|
||||
//write it to the response
|
||||
var cookie = new HttpCookie(cookieName, hash)
|
||||
{
|
||||
Expires = DateTime.Now.AddMinutes(minutesPersisted),
|
||||
Domain = cookieDomain
|
||||
};
|
||||
|
||||
if (GlobalSettings.UseSSL)
|
||||
cookie.Secure = true;
|
||||
|
||||
//ensure http only, this should only be able to be accessed via the server
|
||||
cookie.HttpOnly = true;
|
||||
|
||||
//rewrite the cooke
|
||||
http.Response.Cookies.Set(cookie);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a custom FormsAuthentication ticket with the data specified
|
||||
/// </summary>
|
||||
|
||||
@@ -1,12 +1,38 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Owin;
|
||||
using Microsoft.Owin.Security.Cookies;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Security
|
||||
{
|
||||
public class BackOfficeCookieAuthenticationProvider : CookieAuthenticationProvider
|
||||
{
|
||||
public override void ResponseSignOut(CookieResponseSignOutContext context)
|
||||
{
|
||||
base.ResponseSignOut(context);
|
||||
|
||||
//Make sure the definitely all of these cookies are cleared when signing out with cookies
|
||||
context.Response.Cookies.Append(UmbracoConfig.For.UmbracoSettings().Security.AuthCookieName, "", new CookieOptions
|
||||
{
|
||||
Expires = DateTime.Now.AddYears(-1),
|
||||
Path = "/"
|
||||
});
|
||||
context.Response.Cookies.Append(Constants.Web.PreviewCookieName, "", new CookieOptions
|
||||
{
|
||||
Expires = DateTime.Now.AddYears(-1),
|
||||
Path = "/"
|
||||
});
|
||||
context.Response.Cookies.Append(Constants.Security.BackOfficeExternalCookieName, "", new CookieOptions
|
||||
{
|
||||
Expires = DateTime.Now.AddYears(-1),
|
||||
Path = "/"
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the culture is set correctly for the current back office user
|
||||
/// </summary>
|
||||
|
||||
@@ -53,6 +53,11 @@ namespace Umbraco.Core.Security
|
||||
switch (result)
|
||||
{
|
||||
case SignInStatus.Success:
|
||||
_logger.WriteCore(TraceEventType.Information, 0,
|
||||
string.Format(
|
||||
"User: {0} logged in from IP address {1}",
|
||||
userName,
|
||||
_request.RemoteIpAddress), null, null);
|
||||
break;
|
||||
case SignInStatus.LockedOut:
|
||||
_logger.WriteCore(TraceEventType.Information, 0,
|
||||
|
||||
@@ -152,6 +152,9 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
var contentType = FindContentTypeByAlias(contentTypeAlias);
|
||||
var content = new Content(name, parentId, contentType);
|
||||
var parent = GetById(content.ParentId);
|
||||
content.Path = string.Concat(parent.IfNotNull(x => x.Path, content.ParentId.ToString()), ",", content.Id);
|
||||
|
||||
|
||||
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IContent>(content, contentTypeAlias, parentId), this))
|
||||
{
|
||||
@@ -190,8 +193,11 @@ namespace Umbraco.Core.Services
|
||||
/// <returns><see cref="IContent"/></returns>
|
||||
public IContent CreateContent(string name, IContent parent, string contentTypeAlias, int userId = 0)
|
||||
{
|
||||
if (parent == null) throw new ArgumentNullException("parent");
|
||||
|
||||
var contentType = FindContentTypeByAlias(contentTypeAlias);
|
||||
var content = new Content(name, parent, contentType);
|
||||
content.Path = string.Concat(parent.Path, ",", content.Id);
|
||||
|
||||
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IContent>(content, contentTypeAlias, parent), this))
|
||||
{
|
||||
@@ -225,7 +231,7 @@ namespace Umbraco.Core.Services
|
||||
public IContent CreateContentWithIdentity(string name, int parentId, string contentTypeAlias, int userId = 0)
|
||||
{
|
||||
var contentType = FindContentTypeByAlias(contentTypeAlias);
|
||||
var content = new Content(name, parentId, contentType);
|
||||
var content = new Content(name, parentId, contentType);
|
||||
|
||||
//NOTE: I really hate the notion of these Creating/Created events - they are so inconsistent, I've only just found
|
||||
// out that in these 'WithIdentity' methods, the Saving/Saved events were not fired, wtf. Anyways, they're added now.
|
||||
@@ -276,6 +282,8 @@ namespace Umbraco.Core.Services
|
||||
/// <returns><see cref="IContent"/></returns>
|
||||
public IContent CreateContentWithIdentity(string name, IContent parent, string contentTypeAlias, int userId = 0)
|
||||
{
|
||||
if (parent == null) throw new ArgumentNullException("parent");
|
||||
|
||||
var contentType = FindContentTypeByAlias(contentTypeAlias);
|
||||
var content = new Content(name, parent, contentType);
|
||||
|
||||
|
||||
@@ -100,6 +100,8 @@ namespace Umbraco.Core.Services
|
||||
|
||||
xml.Add(new XAttribute("loginName", member.Username));
|
||||
xml.Add(new XAttribute("email", member.Email));
|
||||
|
||||
xml.Add(new XAttribute("icon", member.ContentType.Icon));
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
@@ -65,6 +65,8 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
var mediaType = FindMediaTypeByAlias(mediaTypeAlias);
|
||||
var media = new Models.Media(name, parentId, mediaType);
|
||||
var parent = GetById(media.ParentId);
|
||||
media.Path = string.Concat(parent.IfNotNull(x => x.Path, media.ParentId.ToString()), ",", media.Id);
|
||||
|
||||
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IMedia>(media, mediaTypeAlias, parentId), this))
|
||||
{
|
||||
@@ -97,8 +99,12 @@ namespace Umbraco.Core.Services
|
||||
/// <returns><see cref="IMedia"/></returns>
|
||||
public IMedia CreateMedia(string name, IMedia parent, string mediaTypeAlias, int userId = 0)
|
||||
{
|
||||
if (parent == null) throw new ArgumentNullException("parent");
|
||||
|
||||
var mediaType = FindMediaTypeByAlias(mediaTypeAlias);
|
||||
var media = new Models.Media(name, parent, mediaType);
|
||||
media.Path = string.Concat(parent.Path, ",", media.Id);
|
||||
|
||||
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IMedia>(media, mediaTypeAlias, parent), this))
|
||||
{
|
||||
media.WasCancelled = true;
|
||||
@@ -186,6 +192,8 @@ namespace Umbraco.Core.Services
|
||||
/// <returns><see cref="IMedia"/></returns>
|
||||
public IMedia CreateMediaWithIdentity(string name, IMedia parent, string mediaTypeAlias, int userId = 0)
|
||||
{
|
||||
if (parent == null) throw new ArgumentNullException("parent");
|
||||
|
||||
var mediaType = FindMediaTypeByAlias(mediaTypeAlias);
|
||||
var media = new Models.Media(name, parent, mediaType);
|
||||
|
||||
|
||||
51
src/Umbraco.Core/ThreadExtensions.cs
Normal file
51
src/Umbraco.Core/ThreadExtensions.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
static class ThreadExtensions
|
||||
{
|
||||
public static void SanitizeThreadCulture(this Thread thread)
|
||||
{
|
||||
// get the current culture
|
||||
var currentCulture = CultureInfo.CurrentCulture;
|
||||
|
||||
// at the top of any culture should be the invariant culture - find it
|
||||
// doing an .Equals comparison ensure that we *will* find it and not loop
|
||||
// endlessly
|
||||
var invariantCulture = currentCulture;
|
||||
while (invariantCulture.Equals(CultureInfo.InvariantCulture) == false)
|
||||
invariantCulture = invariantCulture.Parent;
|
||||
|
||||
// now that invariant culture should be the same object as CultureInfo.InvariantCulture
|
||||
// yet for some reasons, sometimes it is not - and this breaks anything that loops on
|
||||
// culture.Parent until a reference equality to CultureInfo.InvariantCulture. See, for
|
||||
// example, the following code in PerformanceCounterLib.IsCustomCategory:
|
||||
//
|
||||
// CultureInfo culture = CultureInfo.CurrentCulture;
|
||||
// while (culture != CultureInfo.InvariantCulture)
|
||||
// {
|
||||
// library = GetPerformanceCounterLib(machine, culture);
|
||||
// if (library.IsCustomCategory(category))
|
||||
// return true;
|
||||
// culture = culture.Parent;
|
||||
// }
|
||||
//
|
||||
// The reference comparisons never succeeds, hence the loop never ends, and the
|
||||
// application hangs.
|
||||
//
|
||||
// granted, that comparison should probably be a .Equals comparison, but who knows
|
||||
// how many times the framework assumes that it can do a reference comparison? So,
|
||||
// better fix the cultures.
|
||||
|
||||
if (ReferenceEquals(invariantCulture, CultureInfo.InvariantCulture))
|
||||
return;
|
||||
|
||||
// if we do not have equality, fix cultures by replacing them with a culture with
|
||||
// the same name, but obtained here and now, with a proper invariant top culture
|
||||
|
||||
thread.CurrentCulture = CultureInfo.GetCultureInfo(thread.CurrentCulture.Name);
|
||||
thread.CurrentUICulture = CultureInfo.GetCultureInfo(thread.CurrentUICulture.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,7 +86,7 @@
|
||||
</Reference>
|
||||
<Reference Include="MySql.Data">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\MySql.Data.6.9.7\lib\net45\MySql.Data.dll</HintPath>
|
||||
<HintPath>..\packages\MySql.Data.6.9.8\lib\net45\MySql.Data.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
@@ -1290,6 +1290,7 @@
|
||||
<Compile Include="Sync\ApplicationUrlHelper.cs" />
|
||||
<Compile Include="Sync\RefreshMethodType.cs" />
|
||||
<Compile Include="Sync\ServerMessengerBase.cs" />
|
||||
<Compile Include="ThreadExtensions.cs" />
|
||||
<Compile Include="TopologicalSorter.cs" />
|
||||
<Compile Include="Strings\DefaultUrlSegmentProvider.cs" />
|
||||
<Compile Include="Strings\IUrlSegmentProvider.cs" />
|
||||
@@ -1332,6 +1333,9 @@
|
||||
<Compile Include="Constants-PropertyEditors.cs">
|
||||
<DependentUpon>Constants.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Constants-PropertyTypeGroups.cs">
|
||||
<DependentUpon>Constants.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Constants-Packaging.cs">
|
||||
<DependentUpon>Constants.cs</DependentUpon>
|
||||
</Compile>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using System.Web.Hosting;
|
||||
using log4net;
|
||||
@@ -64,6 +65,7 @@ namespace Umbraco.Core
|
||||
/// <param name="e"></param>
|
||||
protected void Application_Start(object sender, EventArgs e)
|
||||
{
|
||||
Thread.CurrentThread.SanitizeThreadCulture();
|
||||
StartApplication(sender, e);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<package id="Microsoft.Owin.Security.Cookies" version="3.0.1" targetFramework="net45" />
|
||||
<package id="Microsoft.Owin.Security.OAuth" version="3.0.1" targetFramework="net45" />
|
||||
<package id="MiniProfiler" version="2.1.0" targetFramework="net45" />
|
||||
<package id="MySql.Data" version="6.9.7" targetFramework="net45" />
|
||||
<package id="MySql.Data" version="6.9.8" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="6.0.8" targetFramework="net45" />
|
||||
<package id="Owin" version="1.0" targetFramework="net45" />
|
||||
<package id="semver" version="1.1.2" targetFramework="net45" />
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
<appSettings>
|
||||
<add key="umbracoConfigurationStatus" value="6.0.0" />
|
||||
<add key="umbracoReservedUrls" value="~/config/splashes/booting.aspx,~/install/default.aspx,~/config/splashes/noNodes.aspx,~/VSEnterpriseHelper.axd" />
|
||||
<add key="umbracoReservedPaths" value="~/umbraco,~/install/" />
|
||||
<add key="umbracoReservedPaths" value="~/install/" />
|
||||
<add key="umbracoPath" value="~/umbraco" />
|
||||
<add key="umbracoHideTopLevelNodeFromPath" value="true" />
|
||||
<add key="umbracoUseDirectoryUrls" value="false" />
|
||||
@@ -203,4 +203,4 @@
|
||||
</assemblyBinding>
|
||||
|
||||
</runtime>
|
||||
</configuration>
|
||||
</configuration>
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
</control>
|
||||
</tab>
|
||||
<tab caption="Examine Management">
|
||||
<control>/umbraco/dashboard/ExamineManagement.ascx</control>
|
||||
<control>dashboard/ExamineManagement.ascx</control>
|
||||
</tab>
|
||||
</section>
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
</control>
|
||||
</tab>
|
||||
<tab caption="Last Edits">
|
||||
<control addPanel="true" MaxRecords="30">/umbraco/dashboard/latestEdits.ascx</control>
|
||||
<control addPanel="true" MaxRecords="30">dashboard/latestEdits.ascx</control>
|
||||
</tab>
|
||||
<tab caption="Change Password">
|
||||
<control addPanel="true">
|
||||
@@ -104,11 +104,11 @@
|
||||
views/dashboard/members/membersdashboardintro.html
|
||||
</control>
|
||||
<control showOnce="true" addPanel="true" panelCaption="">
|
||||
/umbraco/members/membersearch.ascx
|
||||
members/membersearch.ascx
|
||||
</control>
|
||||
<control showOnce="true" addPanel="true" panelCaption="">
|
||||
views/dashboard/members/membersdashboardvideos.html
|
||||
</control>
|
||||
</tab>
|
||||
</section>
|
||||
</dashBoard>
|
||||
</dashBoard>
|
||||
|
||||
@@ -173,7 +173,8 @@ namespace Umbraco.Tests.Logging
|
||||
Console.WriteLine("Flushed {0} events during shutdown", numberLoggedAfterClose - numberLoggedBeforeClose);
|
||||
}
|
||||
|
||||
[Test, Explicit("Long-running")]
|
||||
[NUnit.Framework.Ignore("Keeps failing very randomly")]
|
||||
[Test]
|
||||
public void WillShutdownIfBufferCannotBeFlushedFastEnough()
|
||||
{
|
||||
const int testSize = 250;
|
||||
|
||||
@@ -482,7 +482,7 @@ ALTER TABLE umbracoUser2NodePermission ADD CONSTRAINT PK_umbracoUser2NodePermiss
|
||||
INSERT INTO umbracoNode (id, trashed, parentID, nodeUser, level, path, sortOrder, uniqueID, text, nodeObjectType, createDate) VALUES
|
||||
(-92, 0, -1, 0, 11, '-1,-92', 37, 'f0bc4bfb-b499-40d6-ba86-058885a5178c', 'Label', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '2004/09/30 14:01:49.920'),
|
||||
(-90, 0, -1, 0, 11, '-1,-90', 35, '84c6b441-31df-4ffe-b67e-67d5bc3ae65a', 'Upload', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '2004/09/30 14:01:49.920'),
|
||||
(-89, 0, -1, 0, 11, '-1,-89', 34, 'c6bac0dd-4ab9-45b1-8e30-e4b619ee5da3', 'Textbox multiple', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '2004/09/30 14:01:49.920'),
|
||||
(-89, 0, -1, 0, 11, '-1,-89', 34, 'c6bac0dd-4ab9-45b1-8e30-e4b619ee5da3', 'Textarea', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '2004/09/30 14:01:49.920'),
|
||||
(-88, 0, -1, 0, 11, '-1,-88', 33, '0cc0eba1-9960-42c9-bf9b-60e150b429ae', 'Textstring', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '2004/09/30 14:01:49.920'),
|
||||
(-87, 0, -1, 0, 11, '-1,-87', 32, 'ca90c950-0aff-4e72-b976-a30b1ac57dad', 'Richtext editor', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '2004/09/30 14:01:49.920'),
|
||||
(-51, 0, -1, 0, 11, '-1,-51', 4, '2e6d3631-066e-44b8-aec4-96f09099b2b5', 'Numeric', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '2004/09/30 14:01:49.920'),
|
||||
|
||||
Binary file not shown.
@@ -624,7 +624,7 @@ ALTER TABLE [umbracoNode] DROP CONSTRAINT [FK_umbracoNode_umbracoNode]
|
||||
SET IDENTITY_INSERT [umbracoNode] ON
|
||||
INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-92, 0, -1, 0, 11, N'-1,-92', 37, 'f0bc4bfb-b499-40d6-ba86-058885a5178c', N'Label', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20040930 14:01:49.920')
|
||||
INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-90, 0, -1, 0, 11, N'-1,-90', 35, '84c6b441-31df-4ffe-b67e-67d5bc3ae65a', N'Upload', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20040930 14:01:49.920')
|
||||
INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-89, 0, -1, 0, 11, N'-1,-89', 34, 'c6bac0dd-4ab9-45b1-8e30-e4b619ee5da3', N'Textbox multiple', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20040930 14:01:49.920')
|
||||
INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-89, 0, -1, 0, 11, N'-1,-89', 34, 'c6bac0dd-4ab9-45b1-8e30-e4b619ee5da3', N'Textarea', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20040930 14:01:49.920')
|
||||
INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-88, 0, -1, 0, 11, N'-1,-88', 33, '0cc0eba1-9960-42c9-bf9b-60e150b429ae', N'Textstring', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20040930 14:01:49.920')
|
||||
INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-87, 0, -1, 0, 11, N'-1,-87', 32, 'ca90c950-0aff-4e72-b976-a30b1ac57dad', N'Richtext editor', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20040930 14:01:49.920')
|
||||
INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-51, 0, -1, 0, 11, N'-1,-51', 4, '2e6d3631-066e-44b8-aec4-96f09099b2b5', N'Numeric', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20040930 14:01:49.920')
|
||||
|
||||
173
src/Umbraco.Tests/Mvc/RenderIndexActionSelectorAttributeTests.cs
Normal file
173
src/Umbraco.Tests/Mvc/RenderIndexActionSelectorAttributeTests.cs
Normal file
@@ -0,0 +1,173 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Profiling;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.Models;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.Routing;
|
||||
using Umbraco.Web.Security;
|
||||
|
||||
namespace Umbraco.Tests.Mvc
|
||||
{
|
||||
[TestFixture]
|
||||
public class RenderIndexActionSelectorAttributeTests
|
||||
{
|
||||
private MethodInfo GetRenderMvcControllerIndexMethodFromCurrentType(Type currType)
|
||||
{
|
||||
return currType.GetMethods().Single(x =>
|
||||
{
|
||||
if (x.Name != "Index") return false;
|
||||
if (x.ReturnParameter == null || x.ReturnParameter.ParameterType != typeof (ActionResult)) return false;
|
||||
var p = x.GetParameters();
|
||||
if (p.Length != 1) return false;
|
||||
if (p[0].ParameterType != typeof (RenderModel)) return false;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Matches_Default_Index()
|
||||
{
|
||||
var attr = new RenderIndexActionSelectorAttribute();
|
||||
var req = new RequestContext();
|
||||
var appCtx = new ApplicationContext(
|
||||
CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
var umbCtx = UmbracoContext.EnsureContext(
|
||||
Mock.Of<HttpContextBase>(),
|
||||
appCtx,
|
||||
new Mock<WebSecurity>(null, null).Object,
|
||||
Mock.Of<IUmbracoSettingsSection>(),
|
||||
Enumerable.Empty<IUrlProvider>(),
|
||||
true);
|
||||
var ctrl = new MatchesDefaultIndexController(umbCtx);
|
||||
var controllerCtx = new ControllerContext(req, ctrl);
|
||||
var result = attr.IsValidForRequest(controllerCtx,
|
||||
GetRenderMvcControllerIndexMethodFromCurrentType(ctrl.GetType()));
|
||||
|
||||
Assert.IsTrue(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Matches_Overriden_Index()
|
||||
{
|
||||
var attr = new RenderIndexActionSelectorAttribute();
|
||||
var req = new RequestContext();
|
||||
var appCtx = new ApplicationContext(
|
||||
CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
var umbCtx = UmbracoContext.EnsureContext(
|
||||
Mock.Of<HttpContextBase>(),
|
||||
appCtx,
|
||||
new Mock<WebSecurity>(null, null).Object,
|
||||
Mock.Of<IUmbracoSettingsSection>(),
|
||||
Enumerable.Empty<IUrlProvider>(),
|
||||
true);
|
||||
var ctrl = new MatchesOverriddenIndexController(umbCtx);
|
||||
var controllerCtx = new ControllerContext(req, ctrl);
|
||||
var result = attr.IsValidForRequest(controllerCtx,
|
||||
GetRenderMvcControllerIndexMethodFromCurrentType(ctrl.GetType()));
|
||||
|
||||
Assert.IsTrue(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Matches_Custom_Index()
|
||||
{
|
||||
var attr = new RenderIndexActionSelectorAttribute();
|
||||
var req = new RequestContext();
|
||||
var appCtx = new ApplicationContext(
|
||||
CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
var umbCtx = UmbracoContext.EnsureContext(
|
||||
Mock.Of<HttpContextBase>(),
|
||||
appCtx,
|
||||
new Mock<WebSecurity>(null, null).Object,
|
||||
Mock.Of<IUmbracoSettingsSection>(),
|
||||
Enumerable.Empty<IUrlProvider>(),
|
||||
true);
|
||||
var ctrl = new MatchesCustomIndexController(umbCtx);
|
||||
var controllerCtx = new ControllerContext(req, ctrl);
|
||||
var result = attr.IsValidForRequest(controllerCtx,
|
||||
GetRenderMvcControllerIndexMethodFromCurrentType(ctrl.GetType()));
|
||||
|
||||
Assert.IsFalse(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Matches_Async_Index_Same_Signature()
|
||||
{
|
||||
var attr = new RenderIndexActionSelectorAttribute();
|
||||
var req = new RequestContext();
|
||||
var appCtx = new ApplicationContext(
|
||||
CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
var umbCtx = UmbracoContext.EnsureContext(
|
||||
Mock.Of<HttpContextBase>(),
|
||||
appCtx,
|
||||
new Mock<WebSecurity>(null, null).Object,
|
||||
Mock.Of<IUmbracoSettingsSection>(),
|
||||
Enumerable.Empty<IUrlProvider>(),
|
||||
true);
|
||||
var ctrl = new MatchesAsyncIndexController(umbCtx);
|
||||
var controllerCtx = new ControllerContext(req, ctrl);
|
||||
var result = attr.IsValidForRequest(controllerCtx,
|
||||
GetRenderMvcControllerIndexMethodFromCurrentType(ctrl.GetType()));
|
||||
|
||||
Assert.IsFalse(result);
|
||||
}
|
||||
|
||||
public class MatchesDefaultIndexController : RenderMvcController
|
||||
{
|
||||
public MatchesDefaultIndexController(UmbracoContext umbracoContext) : base(umbracoContext)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class MatchesOverriddenIndexController : RenderMvcController
|
||||
{
|
||||
public MatchesOverriddenIndexController(UmbracoContext umbracoContext) : base(umbracoContext)
|
||||
{
|
||||
}
|
||||
|
||||
public override ActionResult Index(RenderModel model)
|
||||
{
|
||||
return base.Index(model);
|
||||
}
|
||||
}
|
||||
|
||||
public class MatchesCustomIndexController : RenderMvcController
|
||||
{
|
||||
public MatchesCustomIndexController(UmbracoContext umbracoContext) : base(umbracoContext)
|
||||
{
|
||||
}
|
||||
|
||||
public ActionResult Index(RenderModel model, int page)
|
||||
{
|
||||
return base.Index(model);
|
||||
}
|
||||
}
|
||||
|
||||
public class MatchesAsyncIndexController : RenderMvcController
|
||||
{
|
||||
public MatchesAsyncIndexController(UmbracoContext umbracoContext) : base(umbracoContext)
|
||||
{
|
||||
}
|
||||
|
||||
public new async Task<ActionResult> Index(RenderModel model)
|
||||
{
|
||||
return await Task.FromResult(base.Index(model));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Web.Mvc;
|
||||
using NUnit.Framework;
|
||||
|
||||
@@ -141,6 +141,20 @@ namespace Umbraco.Tests.Services
|
||||
Assert.AreEqual(20, contentService.CountDescendants(parent.Id));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetAncestors_Returns_Empty_List_When_Path_Is_Null()
|
||||
{
|
||||
// Arrange
|
||||
var contentService = ServiceContext.ContentService;
|
||||
|
||||
// Act
|
||||
var current = new Mock<IContent>();
|
||||
var res = contentService.GetAncestors(current.Object);
|
||||
|
||||
// Assert
|
||||
Assert.IsEmpty(res);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Tags_For_Entity_Are_Not_Exposed_Via_Tag_Api_When_Content_Is_Recycled()
|
||||
{
|
||||
|
||||
@@ -1173,6 +1173,8 @@ namespace Umbraco.Tests.Services
|
||||
{
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
var basePage = (IContentType)MockedContentTypes.CreateBasicContentType();
|
||||
basePage.AddPropertyGroup("Content");
|
||||
basePage.AddPropertyGroup("Meta");
|
||||
service.Save(basePage);
|
||||
|
||||
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "author")
|
||||
@@ -1184,6 +1186,16 @@ namespace Umbraco.Tests.Services
|
||||
DataTypeDefinitionId = -88
|
||||
};
|
||||
var authorAdded = basePage.AddPropertyType(authorPropertyType, "Content");
|
||||
var titlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "title")
|
||||
{
|
||||
Name = "Title",
|
||||
Description = "",
|
||||
Mandatory = false,
|
||||
SortOrder = 1,
|
||||
DataTypeDefinitionId = -88
|
||||
};
|
||||
var titleAdded = basePage.AddPropertyType(authorPropertyType, "Meta");
|
||||
|
||||
service.Save(basePage);
|
||||
|
||||
basePage = service.GetContentType(basePage.Id);
|
||||
|
||||
109
src/Umbraco.Tests/Templates/TemplateRepositoryTests.cs
Normal file
109
src/Umbraco.Tests/Templates/TemplateRepositoryTests.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Tests.Templates
|
||||
{
|
||||
[TestFixture]
|
||||
public class TemplateRepositoryTests
|
||||
{
|
||||
private readonly Mock<IDatabaseUnitOfWork> _unitOfWorkMock = new Mock<IDatabaseUnitOfWork>();
|
||||
private readonly Mock<CacheHelper> _cacheMock = new Mock<CacheHelper>();
|
||||
private TemplateRepository _templateRepository;
|
||||
private readonly Mock<IFileSystem> _viewFileSystemMock = new Mock<IFileSystem>();
|
||||
private readonly Mock<IFileSystem> _masterpageFileSystemMock = new Mock<IFileSystem>();
|
||||
private readonly Mock<ITemplatesSection> _templateConfigMock = new Mock<Core.Configuration.UmbracoSettings.ITemplatesSection>();
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
var loggerMock = new Mock<ILogger>();
|
||||
var sqlSyntaxMock = new Mock<ISqlSyntaxProvider>();
|
||||
_templateRepository = new TemplateRepository(_unitOfWorkMock.Object, _cacheMock.Object, loggerMock.Object, sqlSyntaxMock.Object, _masterpageFileSystemMock.Object, _viewFileSystemMock.Object, _templateConfigMock.Object);
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DetermineTemplateRenderingEngine_Returns_MVC_When_ViewFile_Exists_And_Content_Has_Webform_Markup()
|
||||
{
|
||||
// Project in MVC mode
|
||||
_templateConfigMock.Setup(x => x.DefaultRenderingEngine).Returns(RenderingEngine.Mvc);
|
||||
|
||||
// Template has masterpage content
|
||||
var templateMock = new Mock<ITemplate>();
|
||||
templateMock.Setup(x => x.Alias).Returns("Something");
|
||||
templateMock.Setup(x => x.Content).Returns("<asp:Content />");
|
||||
|
||||
// but MVC View already exists
|
||||
_viewFileSystemMock.Setup(x => x.FileExists(It.IsAny<string>())).Returns(true);
|
||||
|
||||
var res = _templateRepository.DetermineTemplateRenderingEngine(templateMock.Object);
|
||||
Assert.AreEqual(RenderingEngine.Mvc, res);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DetermineTemplateRenderingEngine_Returns_WebForms_When_ViewFile_Doesnt_Exist_And_Content_Has_Webform_Markup()
|
||||
{
|
||||
// Project in MVC mode
|
||||
_templateConfigMock.Setup(x => x.DefaultRenderingEngine).Returns(RenderingEngine.Mvc);
|
||||
|
||||
// Template has masterpage content
|
||||
var templateMock = new Mock<ITemplate>();
|
||||
templateMock.Setup(x => x.Alias).Returns("Something");
|
||||
templateMock.Setup(x => x.Content).Returns("<asp:Content />");
|
||||
|
||||
// MVC View doesn't exist
|
||||
_viewFileSystemMock.Setup(x => x.FileExists(It.IsAny<string>())).Returns(false);
|
||||
|
||||
var res = _templateRepository.DetermineTemplateRenderingEngine(templateMock.Object);
|
||||
Assert.AreEqual(RenderingEngine.WebForms, res);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DetermineTemplateRenderingEngine_Returns_WebForms_When_MasterPage_Exists_And_In_Mvc_Mode()
|
||||
{
|
||||
// Project in MVC mode
|
||||
_templateConfigMock.Setup(x => x.DefaultRenderingEngine).Returns(RenderingEngine.Mvc);
|
||||
|
||||
var templateMock = new Mock<ITemplate>();
|
||||
templateMock.Setup(x => x.Alias).Returns("Something");
|
||||
|
||||
// but masterpage already exists
|
||||
_viewFileSystemMock.Setup(x => x.FileExists(It.IsAny<string>())).Returns(false);
|
||||
_masterpageFileSystemMock.Setup(x => x.FileExists(It.IsAny<string>())).Returns(true);
|
||||
|
||||
var res = _templateRepository.DetermineTemplateRenderingEngine(templateMock.Object);
|
||||
Assert.AreEqual(RenderingEngine.WebForms, res);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DetermineTemplateRenderingEngine_Returns_Mvc_When_ViewPage_Exists_And_In_Webforms_Mode()
|
||||
{
|
||||
// Project in WebForms mode
|
||||
_templateConfigMock.Setup(x => x.DefaultRenderingEngine).Returns(RenderingEngine.WebForms);
|
||||
|
||||
var templateMock = new Mock<ITemplate>();
|
||||
templateMock.Setup(x => x.Alias).Returns("Something");
|
||||
|
||||
// but MVC View already exists
|
||||
_viewFileSystemMock.Setup(x => x.FileExists(It.IsAny<string>())).Returns(true);
|
||||
_masterpageFileSystemMock.Setup(x => x.FileExists(It.IsAny<string>())).Returns(false);
|
||||
|
||||
var res = _templateRepository.DetermineTemplateRenderingEngine(templateMock.Object);
|
||||
Assert.AreEqual(RenderingEngine.Mvc, res);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ using System.Web;
|
||||
using System.Web.Routing;
|
||||
using Moq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Tests.TestHelpers
|
||||
{
|
||||
@@ -60,7 +61,7 @@ namespace Umbraco.Tests.TestHelpers
|
||||
|
||||
//Cookie collection
|
||||
var cookieCollection = new HttpCookieCollection();
|
||||
cookieCollection.Add(new HttpCookie(Constants.Web.AuthCookieName, "FBA996E7-D6BE-489B-B199-2B0F3D2DD826"));
|
||||
cookieCollection.Add(new HttpCookie("UMB_UCONTEXT", "FBA996E7-D6BE-489B-B199-2B0F3D2DD826"));
|
||||
|
||||
//Request
|
||||
var requestMock = new Mock<HttpRequestBase>();
|
||||
|
||||
@@ -181,6 +181,7 @@
|
||||
<Compile Include="Logging\AsyncRollingFileAppenderTest.cs" />
|
||||
<Compile Include="Logging\DebugAppender.cs" />
|
||||
<Compile Include="Logging\ParallelForwarderTest.cs" />
|
||||
<Compile Include="Mvc\RenderIndexActionSelectorAttributeTests.cs" />
|
||||
<Compile Include="Persistence\Repositories\AuditRepositoryTest.cs" />
|
||||
<Compile Include="Persistence\Repositories\DomainRepositoryTest.cs" />
|
||||
<Compile Include="Persistence\Repositories\PartialViewRepositoryTests.cs" />
|
||||
@@ -362,6 +363,7 @@
|
||||
<Compile Include="Services\MacroServiceTests.cs" />
|
||||
<Compile Include="Services\UserServiceTests.cs" />
|
||||
<Compile Include="Manifest\ManifestParserTests.cs" />
|
||||
<Compile Include="Templates\TemplateRepositoryTests.cs" />
|
||||
<Compile Include="TestHelpers\BaseSeleniumTest.cs" />
|
||||
<Compile Include="Integration\InstallPackage.cs" />
|
||||
<Compile Include="CoreXml\NavigableNavigatorTests.cs" />
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
"rgrove-lazyload": "*",
|
||||
"bootstrap-social": "~4.8.0",
|
||||
"jquery": "2.0.3",
|
||||
"jquery-ui": "1.10.3",
|
||||
"jquery-ui": "1.11.4",
|
||||
"angular-dynamic-locale": "~0.1.27",
|
||||
"ng-file-upload": "~7.3.8",
|
||||
"tinymce": "~4.1.10",
|
||||
|
||||
@@ -476,12 +476,11 @@ module.exports = function (grunt) {
|
||||
files: ['css/font-awesome.min.css', 'fonts/*']
|
||||
},
|
||||
"jquery": {
|
||||
keepExpandedHierarchy: false,
|
||||
files: ['dist/jquery.min.js', 'dist/jquery.min.map']
|
||||
},
|
||||
files: ['jquery.min.js', 'jquery.min.map']
|
||||
},
|
||||
'jquery-ui': {
|
||||
keepExpandedHierarchy: false,
|
||||
files: ['ui/minified/jquery-ui.min.js']
|
||||
files: ['jquery-ui.min.js']
|
||||
},
|
||||
'tinymce': {
|
||||
files: ['plugins/**', 'themes/**', 'tinymce.min.js']
|
||||
|
||||
180
src/Umbraco.Web.UI.Client/lib/jquery-ui-touch-punch/jquery.ui.touch-punch.js
vendored
Normal file
180
src/Umbraco.Web.UI.Client/lib/jquery-ui-touch-punch/jquery.ui.touch-punch.js
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
/*!
|
||||
* jQuery UI Touch Punch 0.2.3
|
||||
*
|
||||
* Copyright 2011–2014, Dave Furfero
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
*
|
||||
* Depends:
|
||||
* jquery.ui.widget.js
|
||||
* jquery.ui.mouse.js
|
||||
*/
|
||||
(function ($) {
|
||||
|
||||
// Detect touch support
|
||||
$.support.touch = 'ontouchend' in document;
|
||||
|
||||
// Ignore browsers without touch support
|
||||
if (!$.support.touch) {
|
||||
return;
|
||||
}
|
||||
|
||||
var mouseProto = $.ui.mouse.prototype,
|
||||
_mouseInit = mouseProto._mouseInit,
|
||||
_mouseDestroy = mouseProto._mouseDestroy,
|
||||
touchHandled;
|
||||
|
||||
/**
|
||||
* Simulate a mouse event based on a corresponding touch event
|
||||
* @param {Object} event A touch event
|
||||
* @param {String} simulatedType The corresponding mouse event
|
||||
*/
|
||||
function simulateMouseEvent (event, simulatedType) {
|
||||
|
||||
// Ignore multi-touch events
|
||||
if (event.originalEvent.touches.length > 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
var touch = event.originalEvent.changedTouches[0],
|
||||
simulatedEvent = document.createEvent('MouseEvents');
|
||||
|
||||
// Initialize the simulated mouse event using the touch event's coordinates
|
||||
simulatedEvent.initMouseEvent(
|
||||
simulatedType, // type
|
||||
true, // bubbles
|
||||
true, // cancelable
|
||||
window, // view
|
||||
1, // detail
|
||||
touch.screenX, // screenX
|
||||
touch.screenY, // screenY
|
||||
touch.clientX, // clientX
|
||||
touch.clientY, // clientY
|
||||
false, // ctrlKey
|
||||
false, // altKey
|
||||
false, // shiftKey
|
||||
false, // metaKey
|
||||
0, // button
|
||||
null // relatedTarget
|
||||
);
|
||||
|
||||
// Dispatch the simulated event to the target element
|
||||
event.target.dispatchEvent(simulatedEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the jQuery UI widget's touchstart events
|
||||
* @param {Object} event The widget element's touchstart event
|
||||
*/
|
||||
mouseProto._touchStart = function (event) {
|
||||
|
||||
var self = this;
|
||||
|
||||
// Ignore the event if another widget is already being handled
|
||||
if (touchHandled || !self._mouseCapture(event.originalEvent.changedTouches[0])) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the flag to prevent other widgets from inheriting the touch event
|
||||
touchHandled = true;
|
||||
|
||||
// Track movement to determine if interaction was a click
|
||||
self._touchMoved = false;
|
||||
|
||||
// Simulate the mouseover event
|
||||
simulateMouseEvent(event, 'mouseover');
|
||||
|
||||
// Simulate the mousemove event
|
||||
simulateMouseEvent(event, 'mousemove');
|
||||
|
||||
// Simulate the mousedown event
|
||||
simulateMouseEvent(event, 'mousedown');
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle the jQuery UI widget's touchmove events
|
||||
* @param {Object} event The document's touchmove event
|
||||
*/
|
||||
mouseProto._touchMove = function (event) {
|
||||
|
||||
// Ignore event if not handled
|
||||
if (!touchHandled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Interaction was not a click
|
||||
this._touchMoved = true;
|
||||
|
||||
// Simulate the mousemove event
|
||||
simulateMouseEvent(event, 'mousemove');
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle the jQuery UI widget's touchend events
|
||||
* @param {Object} event The document's touchend event
|
||||
*/
|
||||
mouseProto._touchEnd = function (event) {
|
||||
|
||||
// Ignore event if not handled
|
||||
if (!touchHandled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Simulate the mouseup event
|
||||
simulateMouseEvent(event, 'mouseup');
|
||||
|
||||
// Simulate the mouseout event
|
||||
simulateMouseEvent(event, 'mouseout');
|
||||
|
||||
// If the touch interaction did not move, it should trigger a click
|
||||
if (!this._touchMoved) {
|
||||
|
||||
// Simulate the click event
|
||||
simulateMouseEvent(event, 'click');
|
||||
}
|
||||
|
||||
// Unset the flag to allow other widgets to inherit the touch event
|
||||
touchHandled = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* A duck punch of the $.ui.mouse _mouseInit method to support touch events.
|
||||
* This method extends the widget with bound touch event handlers that
|
||||
* translate touch events to mouse events and pass them to the widget's
|
||||
* original mouse event handling methods.
|
||||
*/
|
||||
mouseProto._mouseInit = function () {
|
||||
|
||||
var self = this;
|
||||
|
||||
// Delegate the touch handlers to the widget's element
|
||||
self.element.bind({
|
||||
touchstart: $.proxy(self, '_touchStart'),
|
||||
touchmove: $.proxy(self, '_touchMove'),
|
||||
touchend: $.proxy(self, '_touchEnd')
|
||||
});
|
||||
|
||||
// Call the original $.ui.mouse init method
|
||||
_mouseInit.call(self);
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove the touch event handlers
|
||||
*/
|
||||
mouseProto._mouseDestroy = function () {
|
||||
|
||||
var self = this;
|
||||
|
||||
// Delegate the touch handlers to the widget's element
|
||||
self.element.unbind({
|
||||
touchstart: $.proxy(self, '_touchStart'),
|
||||
touchmove: $.proxy(self, '_touchMove'),
|
||||
touchend: $.proxy(self, '_touchEnd')
|
||||
});
|
||||
|
||||
// Call the original $.ui.mouse destroy method
|
||||
_mouseDestroy.call(self);
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,22 @@
|
||||
<svg class="illustration" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 140 75" enable-background="new 0 0 140 75" xml:space="preserve">
|
||||
<path fill="#FFFFFF" stroke="#D9D9D9" d="M132.4,68.6H43.1c-0.5,0-1-0.4-1-1V7.1c0-0.6,0.5-1,1-1h89.4c0.6,0,1,0.4,1,1v60.5
|
||||
C133.4,68.2,133,68.6,132.4,68.6z"/>
|
||||
<line fill="none" stroke="#D9D9D9" x1="42.1" y1="16.4" x2="133.4" y2="16.4"/>
|
||||
<circle fill="#df4949" cx="47" cy="11.6" r="1.5"/>
|
||||
<circle fill="#F4DD33" cx="52.5" cy="11.6" r="1.5"/>
|
||||
<circle fill="#49df5c" cx="58" cy="11.6" r="1.5"/>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="none" stroke="#D9D9D9" stroke-linecap="round" stroke-linejoin="round" d="M64.2,44.1c-12.7-11.9-32.7-11.7-45.1,0.8"
|
||||
/>
|
||||
<g>
|
||||
<polygon fill="#D9D9D9" points="64.4,38.9 63.4,39 63.9,43.9 58.9,44 59,45 65,44.9 "/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<rect x="4.8" y="23.9" fill="#FFFFFF" stroke="#D9D9D9" stroke-linecap="round" stroke-linejoin="round" width="30" height="25"/>
|
||||
<path fill="#FFFFFF" stroke="#D9D9D9" stroke-linecap="round" stroke-linejoin="round" d="M4.8,48.9c0,0,0-12.5,15-12.5
|
||||
s15,12.5,15,12.5H4.8z"/>
|
||||
<circle fill="#FFFFFF" stroke="#D9D9D9" stroke-linecap="round" stroke-linejoin="round" cx="28.7" cy="30.8" r="2.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -24,7 +24,7 @@ var app = angular.module("Umbraco.canvasdesigner", ['colorpicker', 'ui.slider',
|
||||
];
|
||||
$scope.previewDevice = $scope.devices[0];
|
||||
|
||||
var apiController = "/Umbraco/Api/Canvasdesigner/";
|
||||
var apiController = "../Api/Canvasdesigner/";
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Preview devices */
|
||||
@@ -40,7 +40,7 @@ var app = angular.module("Umbraco.canvasdesigner", ['colorpicker', 'ui.slider',
|
||||
/*****************************************************************************/
|
||||
|
||||
$scope.exitPreview = function () {
|
||||
window.top.location.href = "/umbraco/endPreview.aspx?redir=%2f" + $scope.pageId;
|
||||
window.top.location.href = "../endPreview.aspx?redir=%2f" + $scope.pageId;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Umbraco Canvas Designer</title>
|
||||
<link href="/Umbraco/assets/css/canvasdesigner.css" type="text/css" rel="stylesheet" />
|
||||
<link href="/Umbraco/lib/spectrum/spectrum.css" type="text/css" rel="stylesheet" />
|
||||
<link href="/Umbraco/lib/jquery-ui/jquery-ui-1.10.4.custom.min.css" type="text/css" rel="stylesheet" />
|
||||
<link href="../assets/css/canvasdesigner.css" type="text/css" rel="stylesheet" />
|
||||
<link href="../lib/spectrum/spectrum.css" type="text/css" rel="stylesheet" />
|
||||
<link href="../lib/jquery-ui/jquery-ui-1.10.4.custom.min.css" type="text/css" rel="stylesheet" />
|
||||
</head>
|
||||
|
||||
<body id="canvasdesignerPanel" ng-mouseover="outlinePositionHide()" ng-class="{ leftOpen: (showStyleEditor || showPalettePicker) && !showDevicesPreview }" ng-controller="Umbraco.canvasdesignerController">
|
||||
@@ -20,7 +20,7 @@
|
||||
<div class="fix-left-menu selected">
|
||||
|
||||
<div class="avatar">
|
||||
<img ng-src="/umbraco/assets/img/application/logo.png">
|
||||
<img ng-src="../assets/img/application/logo.png">
|
||||
</div>
|
||||
|
||||
<ul class="sections" ng-class="{selected: showDevicesPreview}">
|
||||
@@ -125,7 +125,7 @@
|
||||
<div class="canvasdesigner-panel-container" ng-show="categoriesVisibility[category] === true">
|
||||
<div class="canvasdesigner-panel-property" ng-repeat="item in configItem.editors" ng-show="item.category == category">
|
||||
<h5>{{item.name}} <i class="icon icon-help-alt"></i></h5>
|
||||
<div ng-include="'/Umbraco/preview/editors/' + item.type + '.html'"></div>
|
||||
<div ng-include="'../preview/editors/' + item.type + '.html'"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -154,8 +154,8 @@
|
||||
<p>Styles saved and published</p>
|
||||
</div>
|
||||
|
||||
<script src="/umbraco/lib/rgrove-lazyload/lazyload.js"></script>
|
||||
<script src="/umbraco/js/canvasdesigner.loader.js"></script>
|
||||
<script src="../lib/rgrove-lazyload/lazyload.js"></script>
|
||||
<script src="../js/canvasdesigner.loader.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
|
||||
@@ -146,6 +146,8 @@ angular.module('umbraco.directives')
|
||||
.directive('onOutsideClick', function ($timeout) {
|
||||
return function (scope, element, attrs) {
|
||||
|
||||
var eventBindings = [];
|
||||
|
||||
function oneTimeClick(event) {
|
||||
var el = event.target.nodeName;
|
||||
//ignore link and button clicks
|
||||
@@ -173,11 +175,33 @@ angular.module('umbraco.directives')
|
||||
scope.$apply(attrs.onOutsideClick);
|
||||
}
|
||||
|
||||
|
||||
$timeout(function(){
|
||||
$(document).on("click", oneTimeClick);
|
||||
|
||||
if ("bindClickOn" in attrs) {
|
||||
|
||||
eventBindings.push(scope.$watch(function() {
|
||||
return attrs.bindClickOn;
|
||||
}, function(newValue) {
|
||||
if (newValue === "true") {
|
||||
$(document).on("click", oneTimeClick);
|
||||
} else {
|
||||
$(document).off("click", oneTimeClick);
|
||||
}
|
||||
}));
|
||||
|
||||
} else {
|
||||
$(document).on("click", oneTimeClick);
|
||||
}
|
||||
|
||||
scope.$on("$destroy", function() {
|
||||
$(document).off("click", oneTimeClick);
|
||||
|
||||
// unbind watchers
|
||||
for (var e in eventBindings) {
|
||||
eventBindings[e]();
|
||||
}
|
||||
|
||||
});
|
||||
}); // Temp removal of 1 sec timeout to prevent bug where overlay does not open. We need to find a better solution.
|
||||
|
||||
|
||||
@@ -101,7 +101,8 @@ angular.module("umbraco.directives")
|
||||
relative_urls: false,
|
||||
toolbar: toolbar,
|
||||
content_css: stylesheets.join(','),
|
||||
style_formats: styleFormats
|
||||
style_formats: styleFormats,
|
||||
autoresize_bottom_margin: 0
|
||||
};
|
||||
|
||||
|
||||
@@ -122,11 +123,6 @@ angular.module("umbraco.directives")
|
||||
|
||||
editor.getBody().setAttribute('spellcheck', true);
|
||||
|
||||
//hide toolbar by default
|
||||
$(editor.editorContainer)
|
||||
.find(".mce-toolbar")
|
||||
.css("visibility", "hidden");
|
||||
|
||||
//force overflow to hidden to prevent no needed scroll
|
||||
editor.getBody().style.overflow = "hidden";
|
||||
|
||||
@@ -137,32 +133,6 @@ angular.module("umbraco.directives")
|
||||
}, 400);
|
||||
|
||||
});
|
||||
|
||||
// pin toolbar to top of screen if we have focus and it scrolls off the screen
|
||||
var pinToolbar = function () {
|
||||
|
||||
var _toolbar = $(editor.editorContainer).find(".mce-toolbar");
|
||||
var toolbarHeight = _toolbar.height();
|
||||
|
||||
var _tinyMce = $(editor.editorContainer);
|
||||
var tinyMceRect = _tinyMce[0].getBoundingClientRect();
|
||||
var tinyMceTop = tinyMceRect.top;
|
||||
var tinyMceBottom = tinyMceRect.bottom;
|
||||
|
||||
if (tinyMceTop < 100 && (tinyMceBottom > (100 + toolbarHeight))) {
|
||||
_toolbar
|
||||
.css("visibility", "visible")
|
||||
.css("position", "fixed")
|
||||
.css("top", "100px")
|
||||
.css("margin-top", "0");
|
||||
} else {
|
||||
_toolbar
|
||||
.css("visibility", "visible")
|
||||
.css("position", "absolute")
|
||||
.css("top", "auto")
|
||||
.css("margin-top", (-toolbarHeight - 2) + "px");
|
||||
}
|
||||
};
|
||||
|
||||
//when we leave the editor (maybe)
|
||||
editor.on('blur', function (e) {
|
||||
@@ -177,8 +147,6 @@ angular.module("umbraco.directives")
|
||||
scope.onBlur();
|
||||
}
|
||||
|
||||
_toolbar.css("visibility", "hidden");
|
||||
$('.umb-panel-body').off('scroll', pinToolbar);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -190,8 +158,6 @@ angular.module("umbraco.directives")
|
||||
scope.onFocus();
|
||||
}
|
||||
|
||||
pinToolbar();
|
||||
$('.umb-panel-body').on('scroll', pinToolbar);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -203,8 +169,6 @@ angular.module("umbraco.directives")
|
||||
scope.onClick();
|
||||
}
|
||||
|
||||
pinToolbar();
|
||||
$('.umb-panel-body').on('scroll', pinToolbar);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -144,8 +144,12 @@
|
||||
|
||||
function setTargetPosition() {
|
||||
|
||||
var viewportWidth = null;
|
||||
var viewportHeight = null;
|
||||
var container = $("#contentwrapper");
|
||||
var containerLeft = container[0].offsetLeft;
|
||||
var containerRight = containerLeft + container[0].offsetWidth;
|
||||
var containerTop = container[0].offsetTop;
|
||||
var containerBottom = containerTop + container[0].offsetHeight;
|
||||
|
||||
var mousePositionClickX = null;
|
||||
var mousePositionClickY = null;
|
||||
var elementHeight = null;
|
||||
@@ -161,10 +165,6 @@
|
||||
// if mouse click position is know place element with mouse in center
|
||||
if (scope.model.event && scope.model.event) {
|
||||
|
||||
// viewport size
|
||||
viewportWidth = $(window).innerWidth();
|
||||
viewportHeight = $(window).innerHeight();
|
||||
|
||||
// click position
|
||||
mousePositionClickX = scope.model.event.pageX;
|
||||
mousePositionClickY = scope.model.event.pageY;
|
||||
@@ -179,17 +179,29 @@
|
||||
|
||||
// check to see if element is outside screen
|
||||
// outside right
|
||||
if (position.left + elementWidth > viewportWidth) {
|
||||
position.right = 0;
|
||||
if (position.left + elementWidth > containerRight) {
|
||||
position.right = 10;
|
||||
position.left = "inherit";
|
||||
}
|
||||
|
||||
// outside bottom
|
||||
if (position.top + elementHeight > viewportHeight) {
|
||||
position.bottom = 0;
|
||||
if (position.top + elementHeight > containerBottom) {
|
||||
position.bottom = 10;
|
||||
position.top = "inherit";
|
||||
}
|
||||
|
||||
// outside left
|
||||
if (position.left < containerLeft) {
|
||||
position.left = containerLeft + 10;
|
||||
position.right = "inherit";
|
||||
}
|
||||
|
||||
// outside top
|
||||
if (position.top < containerTop) {
|
||||
position.top = 10;
|
||||
position.bottom = "inherit";
|
||||
}
|
||||
|
||||
el.css(position);
|
||||
|
||||
}
|
||||
|
||||
@@ -38,8 +38,8 @@ angular.module("umbraco.directives")
|
||||
'<div ng-class="getNodeCssClass(node)" ng-swipe-right="options(node, $event)" >' +
|
||||
//NOTE: This ins element is used to display the search icon if the node is a container/listview and the tree is currently in dialog
|
||||
//'<ins ng-if="tree.enablelistviewsearch && node.metaData.isContainer" class="umb-tree-node-search icon-search" ng-click="searchNode(node, $event)" alt="searchAltText"></ins>' +
|
||||
'<ins ng-class="{\'icon-navigation-right\': !node.expanded, \'icon-navigation-down\': node.expanded}" ng-click="load(node)"></ins>' +
|
||||
'<i class="icon umb-tree-icon sprTree"></i>' +
|
||||
'<ins ng-class="{\'icon-navigation-right\': !node.expanded, \'icon-navigation-down\': node.expanded}" ng-click="load(node)"> </ins>' +
|
||||
'<i class="icon umb-tree-icon sprTree" ng-click="select(node, $event)"></i>' +
|
||||
'<a href="#/{{node.routePath}}" ng-click="select(node, $event)"></a>' +
|
||||
//NOTE: These are the 'option' elipses
|
||||
'<a class="umb-options" ng-click="options(node, $event)"><i></i><i></i><i></i></a>' +
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function ConfirmAction() {
|
||||
|
||||
function link(scope, el, attr, ctrl) {
|
||||
|
||||
scope.clickConfirm = function() {
|
||||
if(scope.onConfirm) {
|
||||
scope.onConfirm();
|
||||
}
|
||||
};
|
||||
|
||||
scope.clickCancel = function() {
|
||||
if(scope.onCancel) {
|
||||
scope.onCancel();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
var directive = {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
templateUrl: 'views/components/umb-confirm-action.html',
|
||||
scope: {
|
||||
direction: "@",
|
||||
onConfirm: "&",
|
||||
onCancel: "&"
|
||||
},
|
||||
link: link
|
||||
};
|
||||
|
||||
return directive;
|
||||
}
|
||||
|
||||
angular.module('umbraco.directives').directive('umbConfirmAction', ConfirmAction);
|
||||
|
||||
})();
|
||||
@@ -1,35 +0,0 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function ConfirmDelete() {
|
||||
|
||||
function link(scope, el, attr, ctrl) {
|
||||
|
||||
scope.confirmOverlayOpen = false;
|
||||
|
||||
scope.toggleOverlay = function() {
|
||||
scope.confirmOverlayOpen = !scope.confirmOverlayOpen;
|
||||
};
|
||||
|
||||
scope.closeOverlay = function() {
|
||||
scope.confirmOverlayOpen = false;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
var directive = {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
templateUrl: 'views/components/umb-confirm-delete.html',
|
||||
scope: {
|
||||
confirmAction: "&"
|
||||
},
|
||||
link: link
|
||||
};
|
||||
|
||||
return directive;
|
||||
}
|
||||
|
||||
angular.module('umbraco.directives').directive('umbConfirmDelete', ConfirmDelete);
|
||||
|
||||
})();
|
||||
@@ -157,6 +157,16 @@
|
||||
|
||||
}
|
||||
|
||||
/* ---------- DELETE PROMT ---------- */
|
||||
|
||||
scope.togglePrompt = function (object) {
|
||||
object.deletePrompt = !object.deletePrompt;
|
||||
};
|
||||
|
||||
scope.hidePrompt = function (object) {
|
||||
object.deletePrompt = false;
|
||||
};
|
||||
|
||||
/* ---------- TOOLBAR ---------- */
|
||||
|
||||
scope.toggleSortingMode = function(tool) {
|
||||
@@ -404,13 +414,13 @@
|
||||
}
|
||||
};
|
||||
|
||||
scope.deleteProperty = function(tab, propertyIndex, group) {
|
||||
scope.deleteProperty = function(tab, propertyIndex) {
|
||||
|
||||
// remove property
|
||||
tab.properties.splice(propertyIndex, 1);
|
||||
|
||||
// if the last property in group is an placeholder - remove add new tab placeholder
|
||||
if(group.properties.length === 1 && group.properties[0].propertyState === "init") {
|
||||
if(tab.properties.length === 1 && tab.properties[0].propertyState === "init") {
|
||||
|
||||
angular.forEach(scope.model.groups, function(group, index, groups){
|
||||
if(group.tabState === 'init') {
|
||||
|
||||
@@ -46,32 +46,19 @@
|
||||
function setActiveLayout(layouts) {
|
||||
|
||||
for (var i = 0; layouts.length > i; i++) {
|
||||
|
||||
var layout = layouts[i];
|
||||
|
||||
if(layout.name === scope.activeLayout.name && layout.path === scope.activeLayout.path) {
|
||||
if(layout.path === scope.activeLayout.path) {
|
||||
layout.active = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
scope.pickLayout = function(selectedLayout) {
|
||||
|
||||
for (var i = 0; scope.layouts.length > i; i++) {
|
||||
|
||||
var layout = scope.layouts[i];
|
||||
|
||||
layout.active = false;
|
||||
}
|
||||
|
||||
selectedLayout.active = true;
|
||||
|
||||
scope.activeLayout = selectedLayout;
|
||||
|
||||
scope.layoutDropDownIsOpen = false;
|
||||
|
||||
if(scope.onLayoutSelect) {
|
||||
scope.onLayoutSelect(selectedLayout);
|
||||
scope.layoutDropDownIsOpen = false;
|
||||
}
|
||||
};
|
||||
|
||||
scope.toggleLayoutDropdown = function() {
|
||||
@@ -92,7 +79,8 @@
|
||||
templateUrl: 'views/components/umb-layout-selector.html',
|
||||
scope: {
|
||||
layouts: '=',
|
||||
activeLayout: '='
|
||||
activeLayout: '=',
|
||||
onLayoutSelect: "="
|
||||
},
|
||||
link: link
|
||||
};
|
||||
|
||||
@@ -25,10 +25,7 @@
|
||||
}
|
||||
|
||||
function setItemData(item) {
|
||||
|
||||
item.isFolder = !mediaHelper.hasFilePropertyType(item);
|
||||
item.hidden = item.isFolder;
|
||||
|
||||
if(!item.isFolder){
|
||||
item.thumbnail = mediaHelper.resolveFile(item, true);
|
||||
item.image = mediaHelper.resolveFile(item, false);
|
||||
|
||||
@@ -144,33 +144,60 @@ angular.module("umbraco.directives")
|
||||
|
||||
}).success(function (data, status, headers, config) {
|
||||
|
||||
// set done status on file
|
||||
file.uploadStatus = "done";
|
||||
if(data.notifications && data.notifications.length > 0) {
|
||||
|
||||
// set date/time for when done - used for sorting
|
||||
file.doneDate = new Date();
|
||||
// set error status on file
|
||||
file.uploadStatus = "error";
|
||||
|
||||
// Throw message back to user with the cause of the error
|
||||
file.serverErrorMessage = data.notifications[0].message;
|
||||
|
||||
// Put the file in the rejected pool
|
||||
scope.rejected.push(file);
|
||||
|
||||
} else {
|
||||
|
||||
// set done status on file
|
||||
file.uploadStatus = "done";
|
||||
|
||||
// set date/time for when done - used for sorting
|
||||
file.doneDate = new Date();
|
||||
|
||||
// Put the file in the done pool
|
||||
scope.done.push(file);
|
||||
|
||||
}
|
||||
|
||||
scope.done.push(file);
|
||||
scope.currentFile = undefined;
|
||||
|
||||
//after processing, test if everthing is done
|
||||
_processQueueItem();
|
||||
|
||||
}).error( function (evt, status, headers, config) {
|
||||
|
||||
// set status done
|
||||
file.uploadStatus = "error";
|
||||
|
||||
//if the service returns a detailed error
|
||||
if(evt.InnerException){
|
||||
file.errorMessage = evt.InnerException.ExceptionMessage;
|
||||
if (evt.InnerException) {
|
||||
file.serverErrorMessage = evt.InnerException.ExceptionMessage;
|
||||
|
||||
//Check if its the common "too large file" exception
|
||||
if(evt.InnerException.StackTrace && evt.InnerException.StackTrace.indexOf("ValidateRequestEntityLength") > 0){
|
||||
file.errorMessage = "File too large to upload";
|
||||
}
|
||||
//Check if its the common "too large file" exception
|
||||
if (evt.InnerException.StackTrace && evt.InnerException.StackTrace.indexOf("ValidateRequestEntityLength") > 0) {
|
||||
file.serverErrorMessage = "File too large to upload";
|
||||
}
|
||||
|
||||
} else if (evt.Message) {
|
||||
file.serverErrorMessage = evt.Message;
|
||||
}
|
||||
|
||||
// If file not found, server will return a 404 and display this message
|
||||
if(status === 404 ) {
|
||||
file.serverErrorMessage = "File not found";
|
||||
}
|
||||
|
||||
//after processing, test if everthing is done
|
||||
scope.done.push(file);
|
||||
scope.rejected.push(file);
|
||||
scope.currentFile = undefined;
|
||||
|
||||
_processQueueItem();
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Konami Code directive for AngularJS
|
||||
* @version v0.0.1
|
||||
* @license MIT License, http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
angular.module('umbraco.directives')
|
||||
.directive('konamiCode', ['$document', function ($document) {
|
||||
var konamiKeysDefault = [38, 38, 40, 40, 37, 39, 37, 39, 66, 65];
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function (scope, element, attr) {
|
||||
|
||||
if (!attr.konamiCode) {
|
||||
throw ('Konami directive must receive an expression as value.');
|
||||
}
|
||||
|
||||
// Let user define a custom code.
|
||||
var konamiKeys = attr.konamiKeys || konamiKeysDefault;
|
||||
var keyIndex = 0;
|
||||
|
||||
/**
|
||||
* Fired when konami code is type.
|
||||
*/
|
||||
function activated() {
|
||||
if ('konamiOnce' in attr) {
|
||||
stopListening();
|
||||
}
|
||||
// Execute expression.
|
||||
scope.$eval(attr.konamiCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle keydown events.
|
||||
*/
|
||||
function keydown(e) {
|
||||
if (e.keyCode === konamiKeys[keyIndex++]) {
|
||||
if (keyIndex === konamiKeys.length) {
|
||||
keyIndex = 0;
|
||||
activated();
|
||||
}
|
||||
} else {
|
||||
keyIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop to listen typing.
|
||||
*/
|
||||
function stopListening() {
|
||||
$document.off('keydown', keydown);
|
||||
}
|
||||
|
||||
// Start listening to key typing.
|
||||
$document.on('keydown', keydown);
|
||||
|
||||
// Stop listening when scope is destroyed.
|
||||
scope.$on('$destroy', stopListening);
|
||||
}
|
||||
};
|
||||
}]);
|
||||
@@ -36,7 +36,7 @@ function macroResource($q, $http, umbRequestHelper) {
|
||||
* @methodOf umbraco.resources.macroResource
|
||||
*
|
||||
* @description
|
||||
* Gets the result of a macro as html to display in the rich text editor
|
||||
* Gets the result of a macro as html to display in the rich text editor or in the Grid
|
||||
*
|
||||
* @param {int} macroId The macro id to get parameters for
|
||||
* @param {int} pageId The current page id
|
||||
@@ -45,39 +45,17 @@ function macroResource($q, $http, umbRequestHelper) {
|
||||
*/
|
||||
getMacroResultAsHtmlForEditor: function (macroAlias, pageId, macroParamDictionary) {
|
||||
|
||||
//need to format the query string for the custom dictionary
|
||||
var query = "macroAlias=" + macroAlias + "&pageId=" + pageId;
|
||||
if (macroParamDictionary) {
|
||||
var counter = 0;
|
||||
_.each(macroParamDictionary, function (val, key) {
|
||||
//check for null
|
||||
val = val ? val : "";
|
||||
//need to detect if the val is a string or an object
|
||||
if (!angular.isString(val)) {
|
||||
//if it's not a string we'll send it through the json serializer
|
||||
var json = angular.toJson(val);
|
||||
//then we need to url encode it so that it's safe
|
||||
val = encodeURIComponent(json);
|
||||
}
|
||||
else {
|
||||
//we still need to encode the string, it could contain line breaks, etc...
|
||||
val = encodeURIComponent(val);
|
||||
}
|
||||
|
||||
query += "¯oParams[" + counter + "].key=" + key + "¯oParams[" + counter + "].value=" + val;
|
||||
counter++;
|
||||
});
|
||||
}
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"macroApiBaseUrl",
|
||||
"GetMacroResultAsHtmlForEditor",
|
||||
query)),
|
||||
'Failed to retrieve macro result for macro with alias ' + macroAlias);
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"macroApiBaseUrl",
|
||||
"GetMacroResultAsHtmlForEditor"), {
|
||||
macroAlias: macroAlias,
|
||||
pageId: pageId,
|
||||
macroParams: macroParamDictionary
|
||||
}),
|
||||
'Failed to retrieve macro result for macro with alias ' + macroAlias);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,104 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function listViewHelper() {
|
||||
function listViewHelper($cookieStore) {
|
||||
|
||||
var firstSelectedIndex = 0;
|
||||
|
||||
function getLayout(nodeId, availableLayouts) {
|
||||
|
||||
var storedLayouts = [];
|
||||
|
||||
if ($cookieStore.get("umblistViewLayout")) {
|
||||
storedLayouts = $cookieStore.get("umblistViewLayout");
|
||||
}
|
||||
|
||||
if (storedLayouts && storedLayouts.length > 0) {
|
||||
for (var i = 0; storedLayouts.length > i; i++) {
|
||||
var layout = storedLayouts[i];
|
||||
if (layout.nodeId === nodeId) {
|
||||
return setLayout(nodeId, layout, availableLayouts);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return getFirstAllowedLayout(availableLayouts);
|
||||
|
||||
}
|
||||
|
||||
function setLayout(nodeId, selectedLayout, availableLayouts) {
|
||||
|
||||
var activeLayout = {};
|
||||
var layoutFound = false;
|
||||
|
||||
for (var i = 0; availableLayouts.length > i; i++) {
|
||||
var layout = availableLayouts[i];
|
||||
if (layout.path === selectedLayout.path) {
|
||||
activeLayout = layout;
|
||||
layout.active = true;
|
||||
layoutFound = true;
|
||||
} else {
|
||||
layout.active = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!layoutFound) {
|
||||
activeLayout = getFirstAllowedLayout(availableLayouts);
|
||||
}
|
||||
|
||||
setLayoutCookie(nodeId, activeLayout);
|
||||
|
||||
return activeLayout;
|
||||
|
||||
}
|
||||
|
||||
function setLayoutCookie(nodeId, selectedLayout) {
|
||||
|
||||
var layoutFound = false;
|
||||
var storedLayouts = [];
|
||||
|
||||
if($cookieStore.get("umblistViewLayout")) {
|
||||
storedLayouts = $cookieStore.get("umblistViewLayout");
|
||||
}
|
||||
|
||||
if(storedLayouts.length > 0) {
|
||||
for(var i = 0; storedLayouts.length > i; i++) {
|
||||
var layout = storedLayouts[i];
|
||||
if(layout.nodeId === nodeId) {
|
||||
layout.path = selectedLayout.path;
|
||||
layoutFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!layoutFound) {
|
||||
var cookieObject = {
|
||||
"nodeId": nodeId,
|
||||
"path": selectedLayout.path
|
||||
};
|
||||
storedLayouts.push(cookieObject);
|
||||
}
|
||||
|
||||
document.cookie="umblistViewLayout=" + JSON.stringify(storedLayouts);
|
||||
|
||||
}
|
||||
|
||||
function getFirstAllowedLayout(layouts) {
|
||||
|
||||
var firstAllowedLayout = {};
|
||||
|
||||
for (var i = 0; layouts.length > i; i++) {
|
||||
var layout = layouts[i];
|
||||
if (layout.selected === true) {
|
||||
firstAllowedLayout = layout;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return firstAllowedLayout;
|
||||
}
|
||||
|
||||
function selectHandler(selectedItem, selectedIndex, items, selection, $event) {
|
||||
|
||||
var start = 0;
|
||||
@@ -57,7 +151,7 @@
|
||||
isSelected = true;
|
||||
}
|
||||
}
|
||||
if(!isSelected && !item.hidden) {
|
||||
if(!isSelected) {
|
||||
selection.push({id: item.id});
|
||||
item.selected = true;
|
||||
}
|
||||
@@ -169,6 +263,10 @@
|
||||
|
||||
|
||||
var service = {
|
||||
getLayout: getLayout,
|
||||
getFirstAllowedLayout: getFirstAllowedLayout,
|
||||
setLayout: setLayout,
|
||||
setLayoutCookie: setLayoutCookie,
|
||||
selectHandler: selectHandler,
|
||||
selectItem: selectItem,
|
||||
deselectItem: deselectItem,
|
||||
|
||||
@@ -17,9 +17,9 @@ angular.module("umbraco.install").factory('installerService', function($rootScop
|
||||
|
||||
//add to umbraco installer facts here
|
||||
var facts = ['Umbraco helped millions of people watch a man jump from the edge of space',
|
||||
'Over 250.000 websites are currently powered by Umbraco',
|
||||
'Over 300 000 websites are currently powered by Umbraco',
|
||||
"At least 2 people have named their cat 'Umbraco'",
|
||||
'On an average day, more than 1.000 people download Umbraco',
|
||||
'On an average day, more than 1000 people download Umbraco',
|
||||
'<a target="_blank" href="http://umbraco.tv">umbraco.tv</a> is the premier source of Umbraco video tutorials to get you started',
|
||||
'You can find the world\'s friendliest CMS community at <a target="_blank" href="http://our.umbraco.org">our.umbraco.org</a>',
|
||||
'You can become a certified Umbraco developer by attending one of the official courses',
|
||||
@@ -31,7 +31,7 @@ angular.module("umbraco.install").factory('installerService', function($rootScop
|
||||
"At least 4 people have the Umbraco logo tattooed on them",
|
||||
"'Umbraco' is the danish name for an allen key",
|
||||
"Umbraco has been around since 2005, that's a looong time in IT",
|
||||
"More than 400 people from all over the world meet each year in Denmark in June for our annual conference <a target='_blank' href='http://codegarden14.com'>CodeGarden</a>",
|
||||
"More than 400 people from all over the world meet each year in Denmark in June for our annual conference <a target='_blank' href='http://codegarden15.com'>CodeGarden</a>",
|
||||
"While you are installing Umbraco someone else on the other side of the planet is probably doing it too",
|
||||
"You can extend Umbraco without modifying the source code and using either JavaScript or C#"
|
||||
];
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
@import "components/umb-group-builder.less";
|
||||
@import "components/umb-list-view.less";
|
||||
@import "components/umb-table.less";
|
||||
@import "components/umb-confirm-delete.less";
|
||||
@import "components/umb-confirm-action.less";
|
||||
@import "components/umb-keyboard-shortcuts-overview.less";
|
||||
@import "components/umb-checkbox-list.less";
|
||||
@import "components/umb-locked-field.less";
|
||||
@@ -105,6 +105,7 @@
|
||||
@import "components/tooltip/umb-tooltip.less";
|
||||
@import "components/tooltip/umb-tooltip-list.less";
|
||||
@import "components/overlays/umb-overlay-backdrop.less";
|
||||
@import "components/umb-grid.less";
|
||||
|
||||
@import "components/buttons/umb-button.less";
|
||||
@import "components/buttons/umb-button-group.less";
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
/******* font-face *******/
|
||||
|
||||
@font-face {
|
||||
src: url('/Umbraco/assets/fonts/helveticons/helveticons.eot') !important;
|
||||
src: url('/Umbraco/assets/fonts/helveticons/helveticons.eot?#iefix') format('embedded-opentype'), url('/Umbraco/assets/fonts/helveticons/helveticons.ttf') format('truetype'), url('/Umbraco/assets/fonts/helveticons/helveticons.svg#icomoon') format('svg') !important;
|
||||
src: url('assets/fonts/helveticons/helveticons.eot') !important;
|
||||
src: url('assets/fonts/helveticons/helveticons.eot?#iefix') format('embedded-opentype'), url('assets/fonts/helveticons/helveticons.ttf') format('truetype'), url('assets/fonts/helveticons/helveticons.svg#icomoon') format('svg') !important;
|
||||
}
|
||||
|
||||
/****************************/
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
// OVERLAY
|
||||
.umb_confirm-action__overlay {
|
||||
position: absolute;
|
||||
z-index: 999999;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
// positions
|
||||
.umb_confirm-action__overlay.-top {
|
||||
top: -50px;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
left: 0;
|
||||
animation: fadeInUp 0.2s;
|
||||
flex-direction: column;
|
||||
|
||||
.umb_confirm-action__overlay-action {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.umb_confirm-action__overlay-action.-confirm {
|
||||
order: 1;
|
||||
}
|
||||
|
||||
.umb_confirm-action__overlay-action.-cancel {
|
||||
order: 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.umb_confirm-action__overlay.-right {
|
||||
top: 0;
|
||||
right: -50px;
|
||||
bottom: auto;
|
||||
left: auto;
|
||||
animation: fadeInLeft 0.2s;
|
||||
flex-direction: row;
|
||||
|
||||
.umb_confirm-action__overlay-action {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.umb_confirm-action__overlay-action.-confirm {
|
||||
order: 2;
|
||||
}
|
||||
|
||||
.umb_confirm-action__overlay-action.-cancel {
|
||||
order: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.umb_confirm-action__overlay.-bottom {
|
||||
top: auto;
|
||||
right: auto;
|
||||
bottom: -50px;
|
||||
left: 0;
|
||||
animation: fadeInDown 0.2s;
|
||||
flex-direction: column;
|
||||
|
||||
.umb_confirm-action__overlay-action {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.umb_confirm-action__overlay-action.-confirm {
|
||||
order: 2;
|
||||
}
|
||||
|
||||
.umb_confirm-action__overlay-action.-cancel {
|
||||
order: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.umb_confirm-action__overlay.-left {
|
||||
top: 0;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
left: -50px;
|
||||
animation: fadeInRight 0.2s;
|
||||
flex-direction: row;
|
||||
|
||||
.umb_confirm-action__overlay-action {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.umb_confirm-action__overlay-action.-confirm {
|
||||
order: 1;
|
||||
}
|
||||
|
||||
.umb_confirm-action__overlay-action.-cancel {
|
||||
order: 2;
|
||||
}
|
||||
}
|
||||
|
||||
// BUTTONS
|
||||
.umb_confirm-action__overlay-action {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
border-radius: 40px;
|
||||
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.umb_confirm-action__overlay-action:hover {
|
||||
text-decoration: none;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
// confirm button
|
||||
.umb_confirm-action__overlay-action.-confirm {
|
||||
background: #ffffff;
|
||||
color: @green !important;
|
||||
}
|
||||
|
||||
.umb_confirm-action__overlay-action.-confirm:hover {
|
||||
color: @green !important;
|
||||
}
|
||||
|
||||
// cancel button
|
||||
.umb_confirm-action__overlay-action.-cancel {
|
||||
background: #ffffff;
|
||||
color: @red !important;
|
||||
}
|
||||
|
||||
.umb_confirm-action__overlay-action.-cancel:hover {
|
||||
color: @red !important;
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
.umb-confirm-delete {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.umb_confirm-delete__overlay-action {
|
||||
position: absolute;
|
||||
z-index: 999999;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
border-radius: 40px;
|
||||
animation: fadeInRight 0.2s;
|
||||
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
|
||||
}
|
||||
|
||||
.umb_confirm-delete__overlay-action:hover {
|
||||
text-decoration: none;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.umb_confirm-delete__overlay-action.-confirm {
|
||||
background: @green;
|
||||
top: 0;
|
||||
left: -50px;
|
||||
}
|
||||
|
||||
.umb_confirm-delete__overlay-action.-cancel {
|
||||
background: @red;
|
||||
top: 0;
|
||||
left: -25px;
|
||||
}
|
||||
@@ -41,11 +41,15 @@
|
||||
|
||||
// file select link
|
||||
.file-select {
|
||||
color: @gray;
|
||||
font-size: 16px;
|
||||
font-size: 15px;
|
||||
color: @blue;
|
||||
cursor: pointer;
|
||||
|
||||
margin-top: 10px;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
color: @blueDark;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1072
src/Umbraco.Web.UI.Client/src/less/components/umb-grid.less
Normal file
1072
src/Umbraco.Web.UI.Client/src/less/components/umb-grid.less
Normal file
File diff suppressed because it is too large
Load Diff
@@ -59,10 +59,12 @@
|
||||
position: absolute;
|
||||
top: -30px;
|
||||
right: 20px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.umb-group-builder__group-remove:hover {
|
||||
cursor: pointer;
|
||||
color: @blueDark;
|
||||
}
|
||||
|
||||
.umb-group-builder__group-title-wrapper {
|
||||
@@ -312,6 +314,12 @@ input.umb-group-builder__group-sort-value {
|
||||
margin: 0 0 10px 0;
|
||||
display: block;
|
||||
font-size: 18px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.umb-group-builder__property-action:hover {
|
||||
color: @blueDark;
|
||||
}
|
||||
|
||||
.umb-group-builder__property-inherited-label {
|
||||
|
||||
@@ -51,14 +51,13 @@ input.umb-table__input {
|
||||
text-decoration: none;
|
||||
color: fade(@gray, 75%);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&.sortable {
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
color: @black;
|
||||
}
|
||||
.umb-table-head__link .sortable {
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
color: @black;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,11 +118,12 @@ input.umb-table__input {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.umb-table-body__empty { // Styles of no items in the listview
|
||||
// Styles of no items in the listview
|
||||
.umb-table-body__empty {
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
|
||||
color: fade(@grayLight, 85%);
|
||||
color: @gray;
|
||||
|
||||
padding: 20px 0;
|
||||
|
||||
@@ -178,7 +178,7 @@ input.umb-table__input {
|
||||
|
||||
.umb-table-cell > * {
|
||||
overflow: hidden;
|
||||
white-space: nowrap; // Disable/Enable this to keep string on one line
|
||||
white-space: nowrap; //NOTE Disable/Enable this to keep textstring on one line
|
||||
text-overflow: ellipsis;
|
||||
|
||||
cursor: default;
|
||||
@@ -192,7 +192,7 @@ input.umb-table__input {
|
||||
}
|
||||
|
||||
|
||||
//NOTE Gives the title more wieght in width compared to other cells
|
||||
// Increases the space for the name cell
|
||||
.umb-table__name {
|
||||
flex: 1 1 25%;
|
||||
max-width: 25%;
|
||||
|
||||
@@ -521,3 +521,58 @@ height:1px;
|
||||
.umb-loader-wrapper.-bottom {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
// Helpers
|
||||
|
||||
.strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.inline {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
|
||||
// Input label styles
|
||||
// @Simon: not sure where to put this part yet
|
||||
// --- TODO Needs to be divided into the right .less directories
|
||||
|
||||
|
||||
// Titles for input fields
|
||||
.input-label--title {
|
||||
font-weight: bold;
|
||||
color: @black;
|
||||
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
|
||||
// Used for input checkmark fields
|
||||
.input-label--small {
|
||||
display: inline;
|
||||
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
color: fade(@black, 70);
|
||||
|
||||
&:hover {
|
||||
color: @black;
|
||||
}
|
||||
}
|
||||
|
||||
input[type=checkbox]:checked + .input-label--small {
|
||||
color: @blue;
|
||||
}
|
||||
|
||||
|
||||
// Use this for headers in the panels
|
||||
.panel-dialog--header {
|
||||
border-bottom: 1px solid @gray;
|
||||
|
||||
margin: 10px 0;
|
||||
padding-bottom: 10px;
|
||||
|
||||
font-size: @fontSizeLarge;
|
||||
font-weight: bold;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,23 @@
|
||||
bottom: 90px;
|
||||
}
|
||||
|
||||
.umb-mediapicker-upload {
|
||||
display: -ms-flexbox;
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
|
||||
.form-search {
|
||||
-webkit-flex: 1;
|
||||
-ms-flex: 1;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.upload-button {
|
||||
margin-left: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.umb-panel.editor-breadcrumb .umb-panel-body, .umb-panel.editor-breadcrumb .umb-bottom-bar {
|
||||
bottom: 31px !important;
|
||||
}
|
||||
@@ -140,6 +157,7 @@
|
||||
border-radius: @tabsBorderRadius;
|
||||
box-shadow: none;
|
||||
padding: 0;
|
||||
z-index: 6020;
|
||||
}
|
||||
|
||||
.umb-btn-toolbar .dropdown-menu small {
|
||||
|
||||
@@ -40,8 +40,16 @@
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.umb-contentpicker small a {
|
||||
.umb-contentpicker small {
|
||||
|
||||
&:not(:last-child) {
|
||||
padding-right: 3px;
|
||||
border-right: 1px solid @grayMed;
|
||||
}
|
||||
|
||||
a {
|
||||
color: @gray;
|
||||
}
|
||||
}
|
||||
|
||||
/* CODEMIRROR DATATYPE */
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
@grayDarker: #222;
|
||||
@grayDark: #343434;
|
||||
@gray: #555;
|
||||
@grayMed: #999;
|
||||
@grayLight: #d9d9d9;
|
||||
@grayLighter: #f8f8f8;
|
||||
@white: #fff;
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
<li class="span2" ng-repeat="video in videos">
|
||||
<div class="thumbnail" style="margin-right: 20px">
|
||||
<a target="_blank" href="{{video.link}}?utm_source=core&utm_medium=help&utm_content=link&utm_campaign=tv" title="{{video.title}}">
|
||||
<img ng-src="{{video.thumbnail}}" alt="{{video.title}}">
|
||||
<img ng-src="{{video.thumbnail}}?width=120" alt="{{video.title}}">
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
angular.module("umbraco").controller("Umbraco.Dialogs.LoginController",
|
||||
function ($scope, localizationService, userService, externalLoginInfo) {
|
||||
function ($scope, $cookies, localizationService, userService, externalLoginInfo) {
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
@@ -10,18 +10,39 @@
|
||||
* @description
|
||||
* signs the user in
|
||||
*/
|
||||
var d = new Date();
|
||||
//var weekday = new Array("Super Sunday", "Manic Monday", "Tremendous Tuesday", "Wonderful Wednesday", "Thunder Thursday", "Friendly Friday", "Shiny Saturday");
|
||||
localizationService.localize("login_greeting" + d.getDay()).then(function (label) {
|
||||
$scope.greeting = label;
|
||||
}); // weekday[d.getDay()];
|
||||
|
||||
|
||||
|
||||
var d = new Date();
|
||||
var konamiGreetings = new Array("Suze Sunday", "Malibu Monday", "Tequila Tuesday", "Whiskey Wednesday", "Negroni Day", "Fernet Friday", "Sancerre Saturday");
|
||||
var konamiMode = $cookies.konamiLogin;
|
||||
//var weekday = new Array("Super Sunday", "Manic Monday", "Tremendous Tuesday", "Wonderful Wednesday", "Thunder Thursday", "Friendly Friday", "Shiny Saturday");
|
||||
if (konamiMode == "1") {
|
||||
$scope.greeting = "Happy " + konamiGreetings[d.getDay()];
|
||||
} else {
|
||||
localizationService.localize("login_greeting" + d.getDay()).then(function (label) {
|
||||
$scope.greeting = label;
|
||||
}); // weekday[d.getDay()];
|
||||
}
|
||||
$scope.errorMsg = "";
|
||||
|
||||
$scope.externalLoginFormAction = Umbraco.Sys.ServerVariables.umbracoUrls.externalLoginsUrl;
|
||||
$scope.externalLoginProviders = externalLoginInfo.providers;
|
||||
$scope.externalLoginInfo = externalLoginInfo;
|
||||
|
||||
$scope.activateKonamiMode = function () {
|
||||
if ($cookies.konamiLogin == "1") {
|
||||
// somehow I can't update the cookie value using $cookies, so going native
|
||||
document.cookie = "konamiLogin=; expires=Thu, 01 Jan 1970 00:00:01 GMT;";
|
||||
document.location.reload();
|
||||
} else {
|
||||
document.cookie = "konamiLogin=1; expires=Tue, 01 Jan 2030 00:00:01 GMT;";
|
||||
$scope.$apply(function () {
|
||||
$scope.greeting = "Happy " + konamiGreetings[d.getDay()];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$scope.loginSubmit = function (login, password) {
|
||||
|
||||
//if the login and password are not empty we need to automatically
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div ng-controller="Umbraco.Dialogs.LoginController">
|
||||
<div id="login" class="umb-modalcolumn" ng-class="{'show-validation': loginForm.$invalid}" ng-cloak>
|
||||
<div id="login" class="umb-modalcolumn" ng-class="{'show-validation': loginForm.$invalid}" ng-cloak konami-code="activateKonamiMode()">
|
||||
<div class="form">
|
||||
<h1>{{greeting}}</h1>
|
||||
<p>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<div ng-controller="Umbraco.Dialogs.MediaPickerController"
|
||||
id="fileupload">
|
||||
<form ng-controller="Umbraco.Dialogs.MediaPickerController" id="fileupload"
|
||||
method="POST"
|
||||
enctype="multipart/form-data"
|
||||
umb-image-upload="options">
|
||||
|
||||
<div class="umb-panel umb-dialogs-mediapicker" ng-if="target">
|
||||
<div class="umb-panel-body no-header with-footer compact">
|
||||
@@ -67,18 +69,16 @@
|
||||
|
||||
<div class="umb-panel-header">
|
||||
|
||||
<div class="umb-el-wrap umb-panel-buttons">
|
||||
<div class="span5">
|
||||
<div class="form-search">
|
||||
<i class="icon-search"></i>
|
||||
<input type="text"
|
||||
ng-model="searchTerm"
|
||||
class="umb-search-field search-query"
|
||||
placeholder="Filter...">
|
||||
</div>
|
||||
<div class="umb-el-wrap umb-panel-buttons umb-mediapicker-upload">
|
||||
<div class="form-search">
|
||||
<i class="icon-search"></i>
|
||||
<input type="text"
|
||||
ng-model="searchTerm"
|
||||
class="umb-search-field search-query"
|
||||
placeholder="Filter...">
|
||||
</div>
|
||||
|
||||
<div class="pull-right">
|
||||
<div class="upload-button">
|
||||
<button class="btn fileinput-button" ng-click="upload()" ng-class="{disabled: disabled}">
|
||||
<i class="icon-page-up"></i>
|
||||
<localize key="general_upload">Upload</localize>
|
||||
@@ -156,4 +156,4 @@
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
angular.module("umbraco").controller('Umbraco.Dialogs.Template.SnippetController',
|
||||
function($scope) {
|
||||
$scope.type = $scope.dialogOptions.type;
|
||||
$scope.section = {
|
||||
name: "",
|
||||
required: false
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
<form novalidate name="contentForm"
|
||||
ng-controller="Umbraco.Dialogs.Template.SnippetController"
|
||||
ng-submit="close()"
|
||||
val-form-manager>
|
||||
<div class="umb-panel">
|
||||
|
||||
<div class="umb-panel-header">
|
||||
<div class="panel-dialog--header" style="border-bottom: 1px solid whitesmoke">Configure the section</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-panel-body with-footer umb-querybuilder">
|
||||
<label>
|
||||
<div class="input-label--title">
|
||||
Section name:
|
||||
</div>
|
||||
<input type="text" ng-model="section.name"/>
|
||||
</label>
|
||||
<label ng-show="type === 'rendersection'">
|
||||
<input style="margin: 0;" type="checkbox" ng-checked="section.required" ng-model="section.required"/>
|
||||
<div class="input-label--small">
|
||||
<localize key="general_required">Required</localize>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="umb-panel-footer">
|
||||
<div class="umb-el-wrap umb-panel-buttons">
|
||||
<div class="btn-toolbar umb-btn-toolbar pull-right">
|
||||
<a href ng-click="close()" class="btn btn-link">
|
||||
<localize key="general_close">Close</localize>
|
||||
</a>
|
||||
<a href ng-click="submit(section)" class="btn btn-primary">Insert</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@@ -8,6 +8,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<h1 class="headline">{{user.name}}</h1>
|
||||
<small class="umb-version">Umbraco version {{version}}</small>
|
||||
<p class="muted">
|
||||
<small>
|
||||
<localize key="user_sessionExpires" />: {{remainingAuthSeconds | timespan}}
|
||||
@@ -114,6 +115,5 @@
|
||||
|
||||
</div>
|
||||
|
||||
<small class="umb-version">Umbraco version {{version}}</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -95,7 +95,10 @@
|
||||
|
||||
if(editor.id === null) {
|
||||
|
||||
dataTypeResource.getScaffold().then(function(dataType) {
|
||||
// add scaffold in data type root
|
||||
var parentId = -1;
|
||||
|
||||
dataTypeResource.getScaffold(parentId).then(function(dataType) {
|
||||
|
||||
// set alias
|
||||
dataType.selectedEditor = editor.alias;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="form-search">
|
||||
<div class="form-search" ng-hide="model.filter === false">
|
||||
<i class="icon-search"></i>
|
||||
<input type="text"
|
||||
style="width: 100%"
|
||||
|
||||
@@ -12,6 +12,7 @@ angular.module("umbraco")
|
||||
$scope.cropSize = dialogOptions.cropSize;
|
||||
$scope.lastOpenedNode = $cookieStore.get("umbLastOpenedMediaNodeId");
|
||||
$scope.acceptedFileTypes = mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.imageFileTypes);
|
||||
$scope.maxFileSize = Umbraco.Sys.ServerVariables.umbracoSettings.maxFileSize + "KB";
|
||||
|
||||
$scope.model.selectedImages = [];
|
||||
|
||||
@@ -178,7 +179,7 @@ angular.module("umbraco")
|
||||
//default root item
|
||||
if (!$scope.target) {
|
||||
|
||||
if($scope.lastOpenedNode) {
|
||||
if($scope.lastOpenedNode && $scope.lastOpenedNode !== -1) {
|
||||
|
||||
entityResource.getById($scope.lastOpenedNode, "media")
|
||||
.then(function(node){
|
||||
@@ -186,13 +187,15 @@ angular.module("umbraco")
|
||||
// make sure that las opened node is on the same path as start node
|
||||
var nodePath = node.path.split(",");
|
||||
|
||||
if(nodePath.indexOf($scope.startNodeId) !== -1) {
|
||||
if(nodePath.indexOf($scope.startNodeId.toString()) !== -1) {
|
||||
$scope.gotoFolder({id: $scope.lastOpenedNode, name: "Media", icon: "icon-folder"});
|
||||
} else {
|
||||
$scope.gotoFolder({id: $scope.startNodeId, name: "Media", icon: "icon-folder"});
|
||||
}
|
||||
|
||||
});
|
||||
}, function (err) {
|
||||
$scope.gotoFolder({id: $scope.startNodeId, name: "Media", icon: "icon-folder"});
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
@@ -47,7 +47,8 @@
|
||||
parent-id="{{currentFolder.id}}"
|
||||
files-uploaded="onUploadComplete"
|
||||
files-queued="onFilesQueue"
|
||||
accept="{{acceptedFileTypes}}">
|
||||
accept="{{acceptedFileTypes}}"
|
||||
max-file-size="{{maxFileSize}}">
|
||||
</umb-file-dropzone>
|
||||
|
||||
<umb-photo-folder
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<div class="umb_confirm-action__overlay"
|
||||
ng-class="{
|
||||
'-top': direction === 'top',
|
||||
'-right': direction === 'right',
|
||||
'-bottom': direction === 'bottom',
|
||||
'-left': direction === 'left'}"
|
||||
on-outside-click="clickCancel()">
|
||||
|
||||
<a class="umb_confirm-action__overlay-action -confirm" href="" ng-click="clickConfirm()">
|
||||
<i class="icon-check"></i>
|
||||
</a>
|
||||
|
||||
<a class="umb_confirm-action__overlay-action -cancel" href="" ng-click="clickCancel()">
|
||||
<i class="icon-delete"></i>
|
||||
</a>
|
||||
</div>
|
||||
@@ -1,19 +0,0 @@
|
||||
<div class="umb-confirm-delete">
|
||||
|
||||
<a href="" ng-click="toggleOverlay()">
|
||||
<i class="icon-trash"></i>
|
||||
</a>
|
||||
|
||||
<div ng-if="confirmOverlayOpen" on-outside-click="closeOverlay()">
|
||||
|
||||
<a class="umb_confirm-delete__overlay-action -confirm" href="" ng-click="confirmAction()">
|
||||
<i class="icon-check"></i>
|
||||
</a>
|
||||
|
||||
<a class="umb_confirm-delete__overlay-action -cancel" href="" ng-click="closeOverlay()">
|
||||
<i class="icon-delete"></i>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -24,7 +24,13 @@
|
||||
<div class="umb-group-builder__group" ng-if="tab.tabState !== 'init'" ng-class="{'-active':tab.tabState=='active', '-inherited': tab.inherited, 'umb-group-builder__group-handle -sortable': sortingMode && !tab.inherited}" ng-click="activateGroup(tab)">
|
||||
|
||||
<div class="umb-group-builder__group-remove" ng-if="!sortingMode && tab.properties.length <= 1 && model.groups.length > 1">
|
||||
<umb-confirm-delete confirm-action="removeGroup($index)"></umbraco-confirm-delete>
|
||||
<i class="icon-trash" ng-click="togglePrompt(tab)"></i>
|
||||
<umb-confirm-action
|
||||
ng-if="tab.deletePrompt"
|
||||
direction="left"
|
||||
on-confirm="removeGroup($index)"
|
||||
on-cancel="hidePrompt(tab)">
|
||||
</umb-confirm-action>
|
||||
</div>
|
||||
|
||||
<div class="umb-group-builder__group-title-wrapper">
|
||||
@@ -97,7 +103,7 @@
|
||||
|
||||
<ng-form name="propertyTypeForm">
|
||||
<div class="control-group -no-margin" ng-if="!sortingMode">
|
||||
|
||||
|
||||
<div class="umb-group-builder__property-meta-alias" ng-if="property.inherited">{{ property.alias }}</div>
|
||||
<umb-locked-field ng-if="!property.inherited"
|
||||
locked="locked"
|
||||
@@ -146,17 +152,23 @@
|
||||
</div>
|
||||
|
||||
<!-- row tools -->
|
||||
<div tabindex="-1" class="umb-group-builder__property-actions" ng-if="!sortingMode">
|
||||
<div class="umb-group-builder__property-actions" ng-if="!sortingMode">
|
||||
|
||||
<div ng-if="!property.inherited">
|
||||
|
||||
<!-- delete property -->
|
||||
<div class="umb-group-builder__property-action">
|
||||
<umb-confirm-delete confirm-action="deleteProperty(tab, $index, tab)"></umbraco-confirm-delete>
|
||||
<i class="icon-trash" ng-click="togglePrompt(property)"></i>
|
||||
<umb-confirm-action
|
||||
ng-if="property.deletePrompt"
|
||||
direction="left"
|
||||
on-confirm="deleteProperty(tab, $index)"
|
||||
on-cancel="hidePrompt(property)">
|
||||
</umb-confirm-action>
|
||||
</div>
|
||||
|
||||
<!-- settings for property -->
|
||||
<a href="" class="umb-group-builder__property-action" ng-click="editPropertyTypeSettings(property, tab)">
|
||||
<div class="umb-group-builder__property-action" ng-click="editPropertyTypeSettings(property, tab)">
|
||||
<i class="icon icon-settings"></i>
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<div class="umb-media-grid">
|
||||
|
||||
<a href="" ng-click="clickItem(item)" ng-repeat="item in items" ng-style="item.flexStyle" class="umb-media-grid__item" ng-hide="item.hidden">
|
||||
<a href="" ng-click="clickItem(item)" ng-repeat="item in items" ng-style="item.flexStyle" class="umb-media-grid__item">
|
||||
|
||||
<div class="umb-media-grid__actions">
|
||||
<i ng-if="onDetailsHover" class="icon-info umb-media-grid__action -not-clickable" ng-mouseover="hoverItemDetails(item, $event, true)" ng-mouseleave="hoverItemDetails(item, $event, false)"></i>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<div>
|
||||
|
||||
<div class="umb-table" ng-if="items">
|
||||
|
||||
<!-- Listviews head section -->
|
||||
<div class="umb-table-head">
|
||||
<div class="umb-table-row">
|
||||
|
||||
@@ -31,7 +33,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Listview body section -->
|
||||
<div class="umb-table-body">
|
||||
<div class="umb-table-row"
|
||||
ng-repeat="item in items"
|
||||
@@ -61,6 +63,7 @@
|
||||
|
||||
</div>
|
||||
|
||||
<!-- If list is empty, then display -->
|
||||
<div ng-if="!items" class="umb-table-body__empty">
|
||||
<localize key="content_listViewNoItems">There are no items show in the list.</localize>
|
||||
</div>
|
||||
|
||||
@@ -17,29 +17,10 @@
|
||||
|
||||
|
||||
<div class="content" >
|
||||
|
||||
<!-- Drag and drop illustration -->
|
||||
<svg class="illustration" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 140 75" enable-background="new 0 0 140 75" xml:space="preserve">
|
||||
<path fill="#FFFFFF" stroke="#D9D9D9" d="M132.4,68.6H43.1c-0.5,0-1-0.4-1-1V7.1c0-0.6,0.5-1,1-1h89.4c0.6,0,1,0.4,1,1v60.5
|
||||
C133.4,68.2,133,68.6,132.4,68.6z"/>
|
||||
<line fill="none" stroke="#D9D9D9" x1="42.1" y1="16.4" x2="133.4" y2="16.4"/>
|
||||
<circle fill="#DF7F48" cx="47" cy="11.6" r="1.5"/>
|
||||
<circle fill="#DF7F48" cx="52.5" cy="11.6" r="1.5"/>
|
||||
<circle fill="#DF7F48" cx="58" cy="11.6" r="1.5"/>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="none" stroke="#D9D9D9" stroke-linecap="round" stroke-linejoin="round" d="M64.2,44.1c-12.7-11.9-32.7-11.7-45.1,0.8"
|
||||
/>
|
||||
<g>
|
||||
<polygon fill="#D9D9D9" points="64.4,38.9 63.4,39 63.9,43.9 58.9,44 59,45 65,44.9 "/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<rect x="4.8" y="23.9" fill="#FFFFFF" stroke="#D9D9D9" stroke-linecap="round" stroke-linejoin="round" width="30" height="25"/>
|
||||
<path fill="#FFFFFF" stroke="#D9D9D9" stroke-linecap="round" stroke-linejoin="round" d="M4.8,48.9c0,0,0-12.5,15-12.5
|
||||
s15,12.5,15,12.5H4.8z"/>
|
||||
<circle fill="#FFFFFF" stroke="#D9D9D9" stroke-linecap="round" stroke-linejoin="round" cx="28.7" cy="30.8" r="2.5"/>
|
||||
</svg>
|
||||
<img src="assets/img/uploader/upload-illustration.svg" alt="" />
|
||||
|
||||
|
||||
<!-- Select files -->
|
||||
<div class="file-select"
|
||||
@@ -71,6 +52,7 @@
|
||||
</li>
|
||||
|
||||
<li class="file" ng-if="currentFile">
|
||||
|
||||
<!-- file name -->
|
||||
<div class="file-name">{{ currentFile.name }}</div>
|
||||
|
||||
@@ -83,6 +65,7 @@
|
||||
|
||||
<!-- make list sort order the same as photo grid. The last uploaded photo in the top -->
|
||||
<li class="file" ng-repeat="queued in queue">
|
||||
|
||||
<!-- file name -->
|
||||
<div class="file-name">{{ queued.name }}</div>
|
||||
</li>
|
||||
@@ -92,11 +75,15 @@
|
||||
<!-- file name -->
|
||||
<div class="file-description">
|
||||
|
||||
{{ file.name }}
|
||||
<strong>{{ file.name }}</strong>
|
||||
|
||||
<span class="file-error" ng-if="file.$error">
|
||||
<span ng-if="file.$error === 'pattern'" class="errorMessage color-red">( Only allowed file types are: "{{ accept }}" )</span>
|
||||
<span ng-if="file.$error === 'maxSize'" class="errorMessage color-red">( Max file size is " {{ maxFileSize }} " )</span>
|
||||
<span ng-if="file.$error === 'pattern'" class="errorMessage color-red">(Only allowed file types are: "{{ accept }}")</span>
|
||||
<span ng-if="file.$error === 'maxSize'" class="errorMessage color-red">(Max file size is "{{maxFileSize}}")</span>
|
||||
</span>
|
||||
|
||||
<span class="file-error" ng-if="file.serverErrorMessage">
|
||||
<span class="errorMessage color-red">({{file.serverErrorMessage}})</span>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user