Merge branch 'temp8' into v8-fix-copy-media-types
This commit is contained in:
@@ -1,39 +0,0 @@
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public static class ByteArrayExtensions
|
||||
{
|
||||
private static readonly char[] BytesToHexStringLookup = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
|
||||
public static string ToHexString(this byte[] bytes)
|
||||
{
|
||||
int i = 0, p = 0, bytesLength = bytes.Length;
|
||||
var chars = new char[bytesLength * 2];
|
||||
while (i < bytesLength)
|
||||
{
|
||||
var b = bytes[i++];
|
||||
chars[p++] = BytesToHexStringLookup[b / 0x10];
|
||||
chars[p++] = BytesToHexStringLookup[b % 0x10];
|
||||
}
|
||||
return new string(chars, 0, chars.Length);
|
||||
}
|
||||
|
||||
public static string ToHexString(this byte[] bytes, char separator, int blockSize, int blockCount)
|
||||
{
|
||||
int p = 0, bytesLength = bytes.Length, count = 0, size = 0;
|
||||
var chars = new char[bytesLength * 2 + blockCount];
|
||||
for (var i = 0; i < bytesLength; i++)
|
||||
{
|
||||
var b = bytes[i++];
|
||||
chars[p++] = BytesToHexStringLookup[b / 0x10];
|
||||
chars[p++] = BytesToHexStringLookup[b % 0x10];
|
||||
if (count == blockCount) continue;
|
||||
if (++size < blockSize) continue;
|
||||
|
||||
chars[p++] = '/';
|
||||
size = 0;
|
||||
count++;
|
||||
}
|
||||
return new string(chars, 0, chars.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
44
src/Umbraco.Core/GuidUtils.cs
Normal file
44
src/Umbraco.Core/GuidUtils.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Utility methods for the <see cref="Guid"/> struct.
|
||||
/// </summary>
|
||||
internal static class GuidUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// Combines two guid instances utilizing an exclusive disjunction.
|
||||
/// The resultant guid is not guaranteed to be unique since the number of unique bits is halved.
|
||||
/// </summary>
|
||||
/// <param name="a">The first guid.</param>
|
||||
/// <param name="b">The seconds guid.</param>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Guid Combine(Guid a, Guid b)
|
||||
{
|
||||
var ad = new DecomposedGuid(a);
|
||||
var bd = new DecomposedGuid(b);
|
||||
|
||||
ad.Hi ^= bd.Hi;
|
||||
ad.Lo ^= bd.Lo;
|
||||
|
||||
return ad.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A decomposed guid. Allows access to the high and low bits without unsafe code.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
private struct DecomposedGuid
|
||||
{
|
||||
[FieldOffset(00)] public Guid Value;
|
||||
[FieldOffset(00)] public long Hi;
|
||||
[FieldOffset(08)] public long Lo;
|
||||
|
||||
public DecomposedGuid(Guid value) : this() => this.Value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
84
src/Umbraco.Core/HexEncoder.cs
Normal file
84
src/Umbraco.Core/HexEncoder.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides methods for encoding byte arrays into hexidecimal strings.
|
||||
/// </summary>
|
||||
internal static class HexEncoder
|
||||
{
|
||||
// LUT's that provide the hexidecimal representation of each possible byte value.
|
||||
private static readonly char[] HexLutBase = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
|
||||
// The base LUT arranged in 16x each item order. 0 * 16, 1 * 16, .... F * 16
|
||||
private static readonly char[] HexLutHi = Enumerable.Range(0, 256).Select(x => HexLutBase[x / 0x10]).ToArray();
|
||||
|
||||
// The base LUT repeated 16x.
|
||||
private static readonly char[] HexLutLo = Enumerable.Range(0, 256).Select(x => HexLutBase[x % 0x10]).ToArray();
|
||||
|
||||
/// <summary>
|
||||
/// Converts a <see cref="T:byte[]"/> to a hexidecimal formatted <see cref="string"/> padded to 2 digits.
|
||||
/// </summary>
|
||||
/// <param name="bytes">The bytes.</param>
|
||||
/// <returns>The <see cref="string"/>.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static string Encode(byte[] bytes)
|
||||
{
|
||||
var length = bytes.Length;
|
||||
var chars = new char[length * 2];
|
||||
|
||||
var index = 0;
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
var byteIndex = bytes[i];
|
||||
chars[index++] = HexLutHi[byteIndex];
|
||||
chars[index++] = HexLutLo[byteIndex];
|
||||
}
|
||||
|
||||
return new string(chars, 0, chars.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a <see cref="T:byte[]"/> to a hexidecimal formatted <see cref="string"/> padded to 2 digits
|
||||
/// and split into blocks with the given char separator.
|
||||
/// </summary>
|
||||
/// <param name="bytes">The bytes.</param>
|
||||
/// <param name="separator">The separator.</param>
|
||||
/// <param name="blockSize">The block size.</param>
|
||||
/// <param name="blockCount">The block count.</param>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static string Encode(byte[] bytes, char separator, int blockSize, int blockCount)
|
||||
{
|
||||
var length = bytes.Length;
|
||||
var chars = new char[(length * 2) + blockCount];
|
||||
var count = 0;
|
||||
var size = 0;
|
||||
var index = 0;
|
||||
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
var byteIndex = bytes[i];
|
||||
chars[index++] = HexLutHi[byteIndex];
|
||||
chars[index++] = HexLutLo[byteIndex];
|
||||
|
||||
if (count == blockCount)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (++size < blockSize)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
chars[index++] = separator;
|
||||
size = 0;
|
||||
count++;
|
||||
}
|
||||
|
||||
return new string(chars, 0, chars.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,24 +20,11 @@ namespace Umbraco.Core.IO.MediaPathSchemes
|
||||
{
|
||||
// assumes that cuid and puid keys can be trusted - and that a single property type
|
||||
// for a single content cannot store two different files with the same name
|
||||
var directory = Combine(itemGuid, propertyGuid).ToHexString(/*'/', 2, 4*/); // could use ext to fragment path eg 12/e4/f2/...
|
||||
var directory = HexEncoder.Encode(GuidUtils.Combine(itemGuid, propertyGuid).ToByteArray()/*'/', 2, 4*/); // could use ext to fragment path eg 12/e4/f2/...
|
||||
return Path.Combine(directory, filename).Replace('\\', '/');
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetDeleteDirectory(string filepath)
|
||||
{
|
||||
return Path.GetDirectoryName(filepath);
|
||||
}
|
||||
|
||||
private static byte[] Combine(Guid guid1, Guid guid2)
|
||||
{
|
||||
var bytes1 = guid1.ToByteArray();
|
||||
var bytes2 = guid2.ToByteArray();
|
||||
var bytes = new byte[bytes1.Length];
|
||||
for (var i = 0; i < bytes1.Length; i++)
|
||||
bytes[i] = (byte) (bytes1[i] ^ bytes2[i]);
|
||||
return bytes;
|
||||
}
|
||||
public string GetDeleteDirectory(string filepath) => Path.GetDirectoryName(filepath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,8 +92,8 @@ namespace Umbraco.Core.Models
|
||||
public readonly PropertyInfo AllowedAsRootSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, bool>(x => x.AllowedAsRoot);
|
||||
public readonly PropertyInfo IsContainerSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, bool>(x => x.IsContainer);
|
||||
public readonly PropertyInfo AllowedContentTypesSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, IEnumerable<ContentTypeSort>>(x => x.AllowedContentTypes);
|
||||
public readonly PropertyInfo PropertyGroupCollectionSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, PropertyGroupCollection>(x => x.PropertyGroups);
|
||||
public readonly PropertyInfo PropertyTypeCollectionSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, IEnumerable<PropertyType>>(x => x.PropertyTypes);
|
||||
public readonly PropertyInfo PropertyGroupsSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, PropertyGroupCollection>(x => x.PropertyGroups);
|
||||
public readonly PropertyInfo PropertyTypesSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, IEnumerable<PropertyType>>(x => x.PropertyTypes);
|
||||
public readonly PropertyInfo HasPropertyTypeBeenRemovedSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, bool>(x => x.HasPropertyTypeBeenRemoved);
|
||||
public readonly PropertyInfo VaryBy = ExpressionHelper.GetPropertyInfo<ContentTypeBase, ContentVariation>(x => x.Variations);
|
||||
|
||||
@@ -106,12 +106,12 @@ namespace Umbraco.Core.Models
|
||||
|
||||
protected void PropertyGroupsChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged(Ps.Value.PropertyGroupCollectionSelector);
|
||||
OnPropertyChanged(Ps.Value.PropertyGroupsSelector);
|
||||
}
|
||||
|
||||
protected void PropertyTypesChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged(Ps.Value.PropertyTypeCollectionSelector);
|
||||
OnPropertyChanged(Ps.Value.PropertyTypesSelector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -263,6 +263,8 @@ namespace Umbraco.Core.Models
|
||||
get => _noGroupPropertyTypes;
|
||||
set
|
||||
{
|
||||
if (_noGroupPropertyTypes != null)
|
||||
_noGroupPropertyTypes.CollectionChanged -= PropertyTypesChanged;
|
||||
_noGroupPropertyTypes = new PropertyTypeCollection(IsPublishing, value);
|
||||
_noGroupPropertyTypes.CollectionChanged += PropertyTypesChanged;
|
||||
PropertyTypesChanged(_noGroupPropertyTypes, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
@@ -376,7 +378,7 @@ namespace Umbraco.Core.Models
|
||||
if (!HasPropertyTypeBeenRemoved)
|
||||
{
|
||||
HasPropertyTypeBeenRemoved = true;
|
||||
OnPropertyChanged(Ps.Value.PropertyTypeCollectionSelector);
|
||||
OnPropertyChanged(Ps.Value.PropertyTypesSelector);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -388,7 +390,7 @@ namespace Umbraco.Core.Models
|
||||
if (!HasPropertyTypeBeenRemoved)
|
||||
{
|
||||
HasPropertyTypeBeenRemoved = true;
|
||||
OnPropertyChanged(Ps.Value.PropertyTypeCollectionSelector);
|
||||
OnPropertyChanged(Ps.Value.PropertyTypesSelector);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -412,7 +414,7 @@ namespace Umbraco.Core.Models
|
||||
|
||||
// actually remove the group
|
||||
PropertyGroups.RemoveItem(propertyGroupName);
|
||||
OnPropertyChanged(Ps.Value.PropertyGroupCollectionSelector);
|
||||
OnPropertyChanged(Ps.Value.PropertyGroupsSelector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -35,12 +35,12 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<PropertyGroup, string>(x => x.Name);
|
||||
public readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<PropertyGroup, int>(x => x.SortOrder);
|
||||
public readonly PropertyInfo PropertyTypeCollectionSelector = ExpressionHelper.GetPropertyInfo<PropertyGroup, PropertyTypeCollection>(x => x.PropertyTypes);
|
||||
public readonly PropertyInfo PropertyTypes = ExpressionHelper.GetPropertyInfo<PropertyGroup, PropertyTypeCollection>(x => x.PropertyTypes);
|
||||
}
|
||||
|
||||
private void PropertyTypesChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged(Ps.Value.PropertyTypeCollectionSelector);
|
||||
OnPropertyChanged(Ps.Value.PropertyTypes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -76,6 +76,8 @@ namespace Umbraco.Core.Models
|
||||
get => _propertyTypes;
|
||||
set
|
||||
{
|
||||
if (_propertyTypes != null)
|
||||
_propertyTypes.CollectionChanged -= PropertyTypesChanged;
|
||||
_propertyTypes = value;
|
||||
|
||||
// since we're adding this collection to this group,
|
||||
@@ -83,6 +85,7 @@ namespace Umbraco.Core.Models
|
||||
foreach (var propertyType in _propertyTypes)
|
||||
propertyType.PropertyGroupId = new Lazy<int>(() => Id);
|
||||
|
||||
OnPropertyChanged(Ps.Value.PropertyTypes);
|
||||
_propertyTypes.CollectionChanged += PropertyTypesChanged;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,8 +190,8 @@ AND umbracoNode.nodeObjectType = @objectType",
|
||||
SortOrder = allowedContentType.SortOrder
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//Insert Tabs
|
||||
foreach (var propertyGroup in entity.PropertyGroups)
|
||||
{
|
||||
@@ -328,14 +328,14 @@ AND umbracoNode.id <> @id",
|
||||
// We check if the entity's own PropertyTypes has been modified and then also check
|
||||
// any of the property groups PropertyTypes has been modified.
|
||||
// This specifically tells us if any property type collections have changed.
|
||||
if (entity.IsPropertyDirty("PropertyTypes") || entity.PropertyTypes.Any(pt => pt.IsDirty()))
|
||||
if (entity.IsPropertyDirty("NoGroupPropertyTypes") || entity.PropertyGroups.Any(x => x.IsPropertyDirty("PropertyTypes")))
|
||||
{
|
||||
var dbPropertyTypes = Database.Fetch<PropertyTypeDto>("WHERE contentTypeId = @Id", new { entity.Id });
|
||||
var dbPropertyTypeAlias = dbPropertyTypes.Select(x => x.Id);
|
||||
var dbPropertyTypeIds = dbPropertyTypes.Select(x => x.Id);
|
||||
var entityPropertyTypes = entity.PropertyTypes.Where(x => x.HasIdentity).Select(x => x.Id);
|
||||
var items = dbPropertyTypeAlias.Except(entityPropertyTypes);
|
||||
foreach (var item in items)
|
||||
DeletePropertyType(entity.Id, item);
|
||||
var propertyTypeToDeleteIds = dbPropertyTypeIds.Except(entityPropertyTypes);
|
||||
foreach (var propertyTypeId in propertyTypeToDeleteIds)
|
||||
DeletePropertyType(entity.Id, propertyTypeId);
|
||||
}
|
||||
|
||||
// Delete tabs ... by excepting entries from db with entries from collections.
|
||||
@@ -620,7 +620,7 @@ AND umbracoNode.id <> @id",
|
||||
var sqlDelete = Sql()
|
||||
.Delete<RedirectUrlDto>()
|
||||
.WhereIn((System.Linq.Expressions.Expression<Func<RedirectUrlDto, object>>)(x => x.ContentKey), sqlSelect);
|
||||
|
||||
|
||||
Database.Execute(sqlDelete);
|
||||
}
|
||||
|
||||
@@ -690,7 +690,7 @@ AND umbracoNode.id <> @id",
|
||||
//first clear out any existing names that might already exists under the default lang
|
||||
//there's 2x tables to update
|
||||
|
||||
//clear out the versionCultureVariation table
|
||||
//clear out the versionCultureVariation table
|
||||
var sqlSelect = Sql().Select<ContentVersionCultureVariationDto>(x => x.Id)
|
||||
.From<ContentVersionCultureVariationDto>()
|
||||
.InnerJoin<ContentVersionDto>().On<ContentVersionDto, ContentVersionCultureVariationDto>(x => x.Id, x => x.VersionId)
|
||||
|
||||
@@ -111,7 +111,6 @@
|
||||
<Compile Include="AttemptOfTResultTStatus.cs" />
|
||||
<Compile Include="Components\AuditEventsComponent.cs" />
|
||||
<Compile Include="BindingRedirects.cs" />
|
||||
<Compile Include="ByteArrayExtensions.cs" />
|
||||
<Compile Include="Cache\CacheHelper.cs" />
|
||||
<Compile Include="Cache\CacheKeys.cs" />
|
||||
<Compile Include="Cache\CacheProviderExtensions.cs" />
|
||||
@@ -321,6 +320,8 @@
|
||||
<Compile Include="Events\ExportedMemberEventArgs.cs" />
|
||||
<Compile Include="Events\RolesEventArgs.cs" />
|
||||
<Compile Include="Events\UserGroupWithUsers.cs" />
|
||||
<Compile Include="GuidUtils.cs" />
|
||||
<Compile Include="HexEncoder.cs" />
|
||||
<Compile Include="IO\MediaPathSchemes\CombinedGuidsMediaPathScheme.cs" />
|
||||
<Compile Include="IO\IMediaPathScheme.cs" />
|
||||
<Compile Include="IO\MediaPathSchemes\OriginalMediaPathScheme.cs" />
|
||||
|
||||
13
src/Umbraco.Examine/IIndexCreator.cs
Normal file
13
src/Umbraco.Examine/IIndexCreator.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using Examine;
|
||||
|
||||
namespace Umbraco.Examine
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates <see cref="IIndex"/>'s
|
||||
/// </summary>
|
||||
public interface IIndexCreator
|
||||
{
|
||||
IEnumerable<IIndex> Create();
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Examine;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Examine
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Exposes diagnostic information about an index
|
||||
/// </summary>
|
||||
|
||||
@@ -5,18 +5,17 @@ using Umbraco.Core.Models;
|
||||
namespace Umbraco.Examine
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a collection of <see cref="ValueSet"/> to be indexed based on a collection of <see cref="TContent"/>
|
||||
/// Creates a collection of <see cref="ValueSet"/> to be indexed based on a collection of <see cref="T"/>
|
||||
/// </summary>
|
||||
/// <typeparam name="TContent"></typeparam>
|
||||
public interface IValueSetBuilder<in TContent>
|
||||
where TContent : IContentBase
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public interface IValueSetBuilder<in T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a collection of <see cref="ValueSet"/> to be indexed based on a collection of <see cref="TContent"/>
|
||||
/// Creates a collection of <see cref="ValueSet"/> to be indexed based on a collection of <see cref="T"/>
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<ValueSet> GetValueSets(params TContent[] content);
|
||||
IEnumerable<ValueSet> GetValueSets(params T[] content);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
43
src/Umbraco.Examine/LuceneIndexCreator.cs
Normal file
43
src/Umbraco.Examine/LuceneIndexCreator.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Examine;
|
||||
using Examine.LuceneEngine.Directories;
|
||||
using Lucene.Net.Store;
|
||||
using Umbraco.Core.IO;
|
||||
|
||||
namespace Umbraco.Examine
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Abstract class for creating Lucene based Indexes
|
||||
/// </summary>
|
||||
public abstract class LuceneIndexCreator : IIndexCreator
|
||||
{
|
||||
public abstract IEnumerable<IIndex> Create();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a file system based Lucene <see cref="Lucene.Net.Store.Directory"/> with the correct locking guidelines for Umbraco
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Lucene.Net.Store.Directory CreateFileSystemLuceneDirectory(string name)
|
||||
{
|
||||
//TODO: We should have a single AppSetting to be able to specify a default DirectoryFactory so we can have a single
|
||||
//setting to configure all indexes that use this to easily swap the directory to Sync/%temp%/blog, etc...
|
||||
|
||||
var dirInfo = new DirectoryInfo(Path.Combine(IOHelper.MapPath(SystemDirectories.Data), "TEMP", "ExamineIndexes", name));
|
||||
if (!dirInfo.Exists)
|
||||
System.IO.Directory.CreateDirectory(dirInfo.FullName);
|
||||
|
||||
var luceneDir = new SimpleFSDirectory(dirInfo);
|
||||
|
||||
//we want to tell examine to use a different fs lock instead of the default NativeFSFileLock which could cause problems if the appdomain
|
||||
//terminates and in some rare cases would only allow unlocking of the file if IIS is forcefully terminated. Instead we'll rely on the simplefslock
|
||||
//which simply checks the existence of the lock file
|
||||
// The full syntax of this is: new NoPrefixSimpleFsLockFactory(dirInfo)
|
||||
// however, we are setting the DefaultLockFactory in startup so we'll use that instead since it can be managed globally.
|
||||
luceneDir.SetLockFactory(DirectoryFactory.DefaultLockFactory(dirInfo));
|
||||
return luceneDir;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,6 +66,7 @@
|
||||
<Compile Include="ExamineExtensions.cs" />
|
||||
<Compile Include="IContentValueSetBuilder.cs" />
|
||||
<Compile Include="IContentValueSetValidator.cs" />
|
||||
<Compile Include="IIndexCreator.cs" />
|
||||
<Compile Include="IIndexDiagnostics.cs" />
|
||||
<Compile Include="IIndexPopulator.cs" />
|
||||
<Compile Include="IndexPopulator.cs" />
|
||||
@@ -88,6 +89,7 @@
|
||||
<Compile Include="UmbracoExamineIndexDiagnostics.cs" />
|
||||
<Compile Include="UmbracoExamineIndex.cs" />
|
||||
<Compile Include="UmbracoExamineSearcher.cs" />
|
||||
<Compile Include="LuceneIndexCreator.cs" />
|
||||
<Compile Include="UmbracoMemberIndex.cs" />
|
||||
<Compile Include="..\SolutionInfo.cs">
|
||||
<Link>Properties\SolutionInfo.cs</Link>
|
||||
|
||||
48
src/Umbraco.Tests.Benchmarks/CombineGuidBenchmarks.cs
Normal file
48
src/Umbraco.Tests.Benchmarks/CombineGuidBenchmarks.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Tests.Benchmarks.Config;
|
||||
|
||||
namespace Umbraco.Tests.Benchmarks
|
||||
{
|
||||
[QuickRunWithMemoryDiagnoserConfig]
|
||||
public class CombineGuidBenchmarks
|
||||
{
|
||||
private static readonly Guid _a = Guid.NewGuid();
|
||||
private static readonly Guid _b = Guid.NewGuid();
|
||||
|
||||
[Benchmark]
|
||||
public byte[] CombineUtils() => GuidUtils.Combine(_a, _b).ToByteArray();
|
||||
|
||||
[Benchmark]
|
||||
public byte[] CombineLoop() => Combine(_a, _b);
|
||||
|
||||
private static byte[] Combine(Guid guid1, Guid guid2)
|
||||
{
|
||||
var bytes1 = guid1.ToByteArray();
|
||||
var bytes2 = guid2.ToByteArray();
|
||||
var bytes = new byte[bytes1.Length];
|
||||
for (var i = 0; i < bytes1.Length; i++)
|
||||
{
|
||||
bytes[i] = (byte)(bytes1[i] ^ bytes2[i]);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
||||
// Nov 8 2018
|
||||
//BenchmarkDotNet=v0.11.2, OS=Windows 10.0.17763.55 (1809/October2018Update/Redstone5)
|
||||
//Intel Core i7-6600U CPU 2.60GHz(Skylake), 1 CPU, 4 logical and 2 physical cores
|
||||
// [Host] : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.7.3190.0
|
||||
// Job-JIATTD : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.7.3190.0
|
||||
|
||||
//IterationCount=3 IterationTime=100.0000 ms LaunchCount = 1
|
||||
//WarmupCount=3
|
||||
|
||||
// Method | Mean | Error | StdDev | Gen 0/1k Op | Gen 1/1k Op | Gen 2/1k Op | Allocated Memory/Op |
|
||||
//------------- |---------:|----------:|----------:|------------:|------------:|------------:|--------------------:|
|
||||
// CombineUtils | 33.34 ns | 8.086 ns | 0.4432 ns | 0.0133 | - | - | 28 B |
|
||||
// CombineLoop | 55.03 ns | 11.311 ns | 0.6200 ns | 0.0395 | - | - | 84 B |
|
||||
}
|
||||
|
||||
69
src/Umbraco.Tests.Benchmarks/HexStringBenchmarks.cs
Normal file
69
src/Umbraco.Tests.Benchmarks/HexStringBenchmarks.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Tests.Benchmarks.Config;
|
||||
|
||||
namespace Umbraco.Tests.Benchmarks
|
||||
{
|
||||
[QuickRunConfig]
|
||||
public class HexStringBenchmarks
|
||||
{
|
||||
private byte[] _buffer;
|
||||
|
||||
[Params(8, 16, 32, 64, 128, 256)]
|
||||
public int Count { get; set; }
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
this._buffer = new byte[this.Count];
|
||||
var random = new Random();
|
||||
random.NextBytes(this._buffer);
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public string ToHexStringBuilder()
|
||||
{
|
||||
var sb = new StringBuilder(this._buffer.Length * 2);
|
||||
for (var i = 0; i < this._buffer.Length; i++)
|
||||
{
|
||||
sb.Append(this._buffer[i].ToString("X2"));
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public string ToHexStringEncoder() => HexEncoder.Encode(this._buffer);
|
||||
}
|
||||
|
||||
// Nov 8 2018
|
||||
//BenchmarkDotNet=v0.11.2, OS=Windows 10.0.17763.55 (1809/October2018Update/Redstone5)
|
||||
//Intel Core i7-6600U CPU 2.60GHz(Skylake), 1 CPU, 4 logical and 2 physical cores
|
||||
// [Host] : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.7.3190.0
|
||||
// Job-JIATTD : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.7.3190.0
|
||||
|
||||
//IterationCount=3 IterationTime=100.0000 ms LaunchCount = 1
|
||||
//WarmupCount=3
|
||||
|
||||
// Method | Count | Mean | Error | StdDev | Ratio |
|
||||
//------------------- |------ |-------------:|-------------:|-----------:|------:|
|
||||
// ToHexStringBuilder | 8 | 786.49 ns | 319.92 ns | 17.536 ns | 1.00 |
|
||||
// ToHexStringEncoder | 8 | 64.19 ns | 30.21 ns | 1.656 ns | 0.08 |
|
||||
// | | | | | |
|
||||
// ToHexStringBuilder | 16 | 1,442.43 ns | 503.00 ns | 27.571 ns | 1.00 |
|
||||
// ToHexStringEncoder | 16 | 133.46 ns | 177.55 ns | 9.732 ns | 0.09 |
|
||||
// | | | | | |
|
||||
// ToHexStringBuilder | 32 | 2,869.23 ns | 924.35 ns | 50.667 ns | 1.00 |
|
||||
// ToHexStringEncoder | 32 | 181.03 ns | 96.64 ns | 5.297 ns | 0.06 |
|
||||
// | | | | | |
|
||||
// ToHexStringBuilder | 64 | 5,775.33 ns | 2,825.42 ns | 154.871 ns | 1.00 |
|
||||
// ToHexStringEncoder | 64 | 331.16 ns | 125.63 ns | 6.886 ns | 0.06 |
|
||||
// | | | | | |
|
||||
// ToHexStringBuilder | 128 | 11,662.35 ns | 4,908.03 ns | 269.026 ns | 1.00 |
|
||||
// ToHexStringEncoder | 128 | 633.78 ns | 57.56 ns | 3.155 ns | 0.05 |
|
||||
// | | | | | |
|
||||
// ToHexStringBuilder | 256 | 22,960.11 ns | 14,111.47 ns | 773.497 ns | 1.00 |
|
||||
// ToHexStringEncoder | 256 | 1,224.76 ns | 547.27 ns | 29.998 ns | 0.05 |
|
||||
}
|
||||
@@ -46,10 +46,12 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BulkInsertBenchmarks.cs" />
|
||||
<Compile Include="CombineGuidBenchmarks.cs" />
|
||||
<Compile Include="ConcurrentDictionaryBenchmarks.cs" />
|
||||
<Compile Include="Config\QuickRunConfigAttribute.cs" />
|
||||
<Compile Include="Config\QuickRunWithMemoryDiagnoserConfigAttribute.cs" />
|
||||
<Compile Include="CtorInvokeBenchmarks.cs" />
|
||||
<Compile Include="HexStringBenchmarks.cs" />
|
||||
<Compile Include="EnumeratorBenchmarks.cs" />
|
||||
<Compile Include="LinqCastBenchmarks.cs" />
|
||||
<Compile Include="ModelToSqlExpressionHelperBenchmarks.cs" />
|
||||
|
||||
32
src/Umbraco.Tests/CoreThings/GuidUtilsTests.cs
Normal file
32
src/Umbraco.Tests/CoreThings/GuidUtilsTests.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Tests.CoreThings
|
||||
{
|
||||
public class GuidUtilsTests
|
||||
{
|
||||
[Test]
|
||||
public void GuidCombineMethodsAreEqual()
|
||||
{
|
||||
var a = Guid.NewGuid();
|
||||
var b = Guid.NewGuid();
|
||||
|
||||
Assert.AreEqual(GuidUtils.Combine(a, b).ToByteArray(), Combine(a, b));
|
||||
}
|
||||
|
||||
// Reference implementation taken from original code.
|
||||
private static byte[] Combine(Guid guid1, Guid guid2)
|
||||
{
|
||||
var bytes1 = guid1.ToByteArray();
|
||||
var bytes2 = guid2.ToByteArray();
|
||||
var bytes = new byte[bytes1.Length];
|
||||
for (var i = 0; i < bytes1.Length; i++)
|
||||
{
|
||||
bytes[i] = (byte)(bytes1[i] ^ bytes2[i]);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
71
src/Umbraco.Tests/CoreThings/HexEncoderTests.cs
Normal file
71
src/Umbraco.Tests/CoreThings/HexEncoderTests.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Tests.CoreThings
|
||||
{
|
||||
public class HexEncoderTests
|
||||
{
|
||||
[Test]
|
||||
public void ToHexStringCreatesCorrectValue()
|
||||
{
|
||||
var buffer = new byte[255];
|
||||
var random = new Random();
|
||||
random.NextBytes(buffer);
|
||||
|
||||
var sb = new StringBuilder(buffer.Length * 2);
|
||||
for (var i = 0; i < buffer.Length; i++)
|
||||
{
|
||||
sb.Append(buffer[i].ToString("X2"));
|
||||
}
|
||||
|
||||
var expected = sb.ToString();
|
||||
|
||||
var actual = HexEncoder.Encode(buffer);
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ToHexStringWithSeparatorCreatesCorrectValue()
|
||||
{
|
||||
var buffer = new byte[255];
|
||||
var random = new Random();
|
||||
random.NextBytes(buffer);
|
||||
|
||||
var expected = ToHexString(buffer, '/', 2, 4);
|
||||
var actual = HexEncoder.Encode(buffer, '/', 2, 4);
|
||||
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
private static readonly char[] _bytesToHexStringLookup = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
|
||||
// Reference implementation taken from original extension method.
|
||||
private static string ToHexString(byte[] bytes, char separator, int blockSize, int blockCount)
|
||||
{
|
||||
int p = 0, bytesLength = bytes.Length, count = 0, size = 0;
|
||||
var chars = new char[(bytesLength * 2) + blockCount];
|
||||
for (var i = 0; i < bytesLength; i++)
|
||||
{
|
||||
var b = bytes[i];
|
||||
chars[p++] = _bytesToHexStringLookup[b / 0x10];
|
||||
chars[p++] = _bytesToHexStringLookup[b % 0x10];
|
||||
if (count == blockCount)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (++size < blockSize)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
chars[p++] = separator;
|
||||
size = 0;
|
||||
count++;
|
||||
}
|
||||
return new string(chars, 0, chars.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -148,7 +148,7 @@ namespace Umbraco.Tests.Services
|
||||
//change the content type to be invariant, we will also update the name here to detect the copy changes
|
||||
doc.SetCultureName("Hello2", "en-US");
|
||||
ServiceContext.ContentService.Save(doc);
|
||||
contentType.Variations = ContentVariation.Nothing;
|
||||
contentType.Variations = ContentVariation.Nothing;
|
||||
ServiceContext.ContentTypeService.Save(contentType);
|
||||
doc = ServiceContext.ContentService.GetById(doc.Id); //re-get
|
||||
|
||||
@@ -372,7 +372,7 @@ namespace Umbraco.Tests.Services
|
||||
doc2 = ServiceContext.ContentService.GetById(doc2.Id); //re-get
|
||||
|
||||
//this will be null because the doc type was changed back to variant but it's property types don't get changed back
|
||||
Assert.IsNull(doc.GetValue("title", "en-US"));
|
||||
Assert.IsNull(doc.GetValue("title", "en-US"));
|
||||
Assert.IsNull(doc2.GetValue("title", "en-US"));
|
||||
}
|
||||
|
||||
@@ -1622,50 +1622,65 @@ namespace Umbraco.Tests.Services
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
|
||||
// create 'page' content type with a 'Content_' group
|
||||
var page = MockedContentTypes.CreateSimpleContentType("page", "Page", null, false, "Content_");
|
||||
Assert.IsTrue(page.PropertyGroups.Contains("Content_"));
|
||||
Assert.AreEqual(3, page.PropertyTypes.Count());
|
||||
service.Save(page);
|
||||
|
||||
// create 'contentPage' content type as a child of 'page'
|
||||
var contentPage = MockedContentTypes.CreateSimpleContentType("contentPage", "Content Page", page, true);
|
||||
service.Save(contentPage);
|
||||
var composition = MockedContentTypes.CreateMetaContentType();
|
||||
composition.AddPropertyGroup("Content");
|
||||
service.Save(composition);
|
||||
//Adding Meta-composition to child doc type
|
||||
contentPage.AddContentType(composition);
|
||||
Assert.AreEqual(3, contentPage.PropertyTypes.Count());
|
||||
service.Save(contentPage);
|
||||
|
||||
// Act
|
||||
var propertyTypeOne = new PropertyType(Constants.PropertyEditors.Aliases.TextBox, ValueStorageType.Ntext, "testTextbox")
|
||||
// add 'Content' group to 'meta' content type
|
||||
var meta = MockedContentTypes.CreateMetaContentType();
|
||||
meta.AddPropertyGroup("Content");
|
||||
Assert.AreEqual(2, meta.PropertyTypes.Count());
|
||||
service.Save(meta);
|
||||
|
||||
// add 'meta' content type to 'contentPage' composition
|
||||
contentPage.AddContentType(meta);
|
||||
service.Save(contentPage);
|
||||
|
||||
// add property 'prop1' to 'contentPage' group 'Content_'
|
||||
var prop1 = new PropertyType(Constants.PropertyEditors.Aliases.TextBox, ValueStorageType.Ntext, "testTextbox")
|
||||
{
|
||||
Name = "Test Textbox", Description = "", Mandatory = false, SortOrder = 1, DataTypeId = -88
|
||||
};
|
||||
var firstOneAdded = contentPage.AddPropertyType(propertyTypeOne, "Content_");
|
||||
var propertyTypeTwo = new PropertyType(Constants.PropertyEditors.Aliases.TextBox, ValueStorageType.Ntext, "anotherTextbox")
|
||||
var prop1Added = contentPage.AddPropertyType(prop1, "Content_");
|
||||
Assert.IsTrue(prop1Added);
|
||||
|
||||
// add property 'prop2' to 'contentPage' group 'Content'
|
||||
var prop2 = new PropertyType(Constants.PropertyEditors.Aliases.TextBox, ValueStorageType.Ntext, "anotherTextbox")
|
||||
{
|
||||
Name = "Another Test Textbox", Description = "", Mandatory = false, SortOrder = 1, DataTypeId = -88
|
||||
};
|
||||
var secondOneAdded = contentPage.AddPropertyType(propertyTypeTwo, "Content");
|
||||
var prop2Added = contentPage.AddPropertyType(prop2, "Content");
|
||||
Assert.IsTrue(prop2Added);
|
||||
|
||||
// save 'contentPage' content type
|
||||
service.Save(contentPage);
|
||||
|
||||
Assert.That(page.PropertyGroups.Contains("Content_"), Is.True);
|
||||
var propertyGroup = page.PropertyGroups["Content_"];
|
||||
page.PropertyGroups.Add(new PropertyGroup(true) { Id = propertyGroup.Id, Name = "ContentTab", SortOrder = 0});
|
||||
var group = page.PropertyGroups["Content_"];
|
||||
group.Name = "ContentTab"; // rename the group
|
||||
service.Save(page);
|
||||
Assert.AreEqual(3, page.PropertyTypes.Count());
|
||||
|
||||
// Assert
|
||||
Assert.That(firstOneAdded, Is.True);
|
||||
Assert.That(secondOneAdded, Is.True);
|
||||
// get 'contentPage' content type again
|
||||
var contentPageAgain = service.Get("contentPage");
|
||||
Assert.IsNotNull(contentPageAgain);
|
||||
|
||||
var contentType = service.Get("contentPage");
|
||||
Assert.That(contentType, Is.Not.Null);
|
||||
// assert that 'Content_' group is still there because we don't propagate renames
|
||||
var findGroup = contentPageAgain.CompositionPropertyGroups.FirstOrDefault(x => x.Name == "Content_");
|
||||
Assert.IsNotNull(findGroup);
|
||||
|
||||
var compositionPropertyGroups = contentType.CompositionPropertyGroups;
|
||||
|
||||
// now it is still 1, because we don't propagate renames anymore
|
||||
Assert.That(compositionPropertyGroups.Count(x => x.Name.Equals("Content_")), Is.EqualTo(1));
|
||||
|
||||
var propertyTypeCount = contentType.PropertyTypes.Count();
|
||||
var compPropertyTypeCount = contentType.CompositionPropertyTypes.Count();
|
||||
// count all property types (local and composed)
|
||||
var propertyTypeCount = contentPageAgain.PropertyTypes.Count();
|
||||
Assert.That(propertyTypeCount, Is.EqualTo(5));
|
||||
|
||||
// count composed property types
|
||||
var compPropertyTypeCount = contentPageAgain.CompositionPropertyTypes.Count();
|
||||
Assert.That(compPropertyTypeCount, Is.EqualTo(10));
|
||||
}
|
||||
|
||||
|
||||
@@ -118,6 +118,8 @@
|
||||
<Compile Include="Collections\OrderedHashSetTests.cs" />
|
||||
<Compile Include="CoreThings\CallContextTests.cs" />
|
||||
<Compile Include="Components\ComponentTests.cs" />
|
||||
<Compile Include="CoreThings\GuidUtilsTests.cs" />
|
||||
<Compile Include="CoreThings\HexEncoderTests.cs" />
|
||||
<Compile Include="CoreXml\RenamedRootNavigatorTests.cs" />
|
||||
<Compile Include="Manifest\ManifestContentAppTests.cs" />
|
||||
<Compile Include="Migrations\MigrationPlanTests.cs" />
|
||||
|
||||
@@ -203,11 +203,14 @@
|
||||
}));
|
||||
|
||||
evts.push(eventsService.on("appState.editors.close", function (name, args) {
|
||||
removeEditor(args.editor);
|
||||
}));
|
||||
|
||||
evts.push(eventsService.on("appState.editors.closeAll", function (name, args) {
|
||||
scope.editors = [];
|
||||
// remove the closed editor
|
||||
if(args && args.editor) {
|
||||
removeEditor(args.editor);
|
||||
}
|
||||
// close all editors
|
||||
if(args && !args.editor && args.editors.length === 0) {
|
||||
scope.editors = [];
|
||||
}
|
||||
}));
|
||||
|
||||
//ensure to unregister from all events!
|
||||
|
||||
@@ -124,58 +124,6 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
<h1>Content Picker</h1>
|
||||
Opens a content picker.</br>
|
||||
<strong>view: </strong>contentpicker
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Param</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>model.multiPicker</td>
|
||||
<td>Boolean</td>
|
||||
<td>Pick one or multiple items</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>model.selection</td>
|
||||
<td>Array</td>
|
||||
<td>Array of content objects</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
<h1>Icon Picker</h1>
|
||||
Opens an icon picker.</br>
|
||||
<strong>view: </strong>iconpicker
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>model.icon</td>
|
||||
<td>String</td>
|
||||
<td>The icon class</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1>Item Picker</h1>
|
||||
Opens an item picker.</br>
|
||||
<strong>view: </strong>itempicker
|
||||
@@ -220,170 +168,6 @@ Opens an item picker.</br>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1>Macro Picker</h1>
|
||||
Opens a media picker.</br>
|
||||
<strong>view: </strong>macropicker
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Param</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>model.dialogData</td>
|
||||
<td>Object</td>
|
||||
<td>Object which contains array of allowedMacros. Set to <code>null</code> to allow all.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>model.macroParams</td>
|
||||
<td>Array</td>
|
||||
<td>Array of macro params</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>model.selectedMacro</td>
|
||||
<td>Object</td>
|
||||
<td>The selected macro</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h1>Media Picker</h1>
|
||||
Opens a media picker.</br>
|
||||
<strong>view: </strong>mediapicker
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Param</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>model.multiPicker</td>
|
||||
<td>Boolean</td>
|
||||
<td>Pick one or multiple items</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>model.onlyImages</td>
|
||||
<td>Boolean</td>
|
||||
<td>Only display files that have an image file-extension</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>model.disableFolderSelect</td>
|
||||
<td>Boolean</td>
|
||||
<td>Disable folder selection</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>model.selectedImages</td>
|
||||
<td>Array</td>
|
||||
<td>Array of selected images</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h1>Member Group Picker</h1>
|
||||
Opens a member group picker.</br>
|
||||
<strong>view: </strong>membergrouppicker
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Param</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>model.multiPicker</td>
|
||||
<td>Boolean</td>
|
||||
<td>Pick one or multiple items</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>model.selectedMemberGroup</td>
|
||||
<td>String</td>
|
||||
<td>The selected member group</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>model.selectedMemberGroups (multiPicker)</td>
|
||||
<td>Array</td>
|
||||
<td>The selected member groups</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h1>Member Picker</h1>
|
||||
Opens a member picker. </br>
|
||||
<strong>view: </strong>memberpicker
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Param</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>model.multiPicker</td>
|
||||
<td>Boolean</td>
|
||||
<td>Pick one or multiple items</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<th>Type</th>
|
||||
<th>Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>model.selection</td>
|
||||
<td>Array</td>
|
||||
<td>Array of selected members/td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h1>YSOD</h1>
|
||||
Opens an overlay to show a custom YSOD. </br>
|
||||
<strong>view: </strong>ysod
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name umbraco.resources.relationTypeResource
|
||||
* @description Loads in data for relation types.
|
||||
*/
|
||||
function relationTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
|
||||
return {
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.relationTypeResource#getById
|
||||
* @methodOf umbraco.resources.relationTypeResource
|
||||
*
|
||||
* @description
|
||||
* Gets a relation type with a given ID.
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* relationTypeResource.getById(1234)
|
||||
* .then(function() {
|
||||
* alert('Found it!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Int} id of the relation type to get.
|
||||
* @returns {Promise} resourcePromise containing relation type data.
|
||||
*/
|
||||
getById: function (id) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(umbRequestHelper.getApiUrl("relationTypeApiBaseUrl", "GetById", [{ id: id }])),
|
||||
"Failed to get item " + id
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.relationTypeResource#getRelationObjectTypes
|
||||
* @methodOf umbraco.resources.relationTypeResource
|
||||
*
|
||||
* @description
|
||||
* Gets a list of Umbraco object types which can be associated with a relation.
|
||||
*
|
||||
* @returns {Object} A collection of Umbraco object types.
|
||||
*/
|
||||
getRelationObjectTypes: function() {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl("relationTypeApiBaseUrl", "GetRelationObjectTypes")
|
||||
),
|
||||
"Failed to get object types"
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.relationTypeResource#save
|
||||
* @methodOf umbraco.resources.relationTypeResource
|
||||
*
|
||||
* @description
|
||||
* Updates a relation type.
|
||||
*
|
||||
* @param {Object} relationType The relation type object to update.
|
||||
* @returns {Promise} A resourcePromise object.
|
||||
*/
|
||||
save: function (relationType) {
|
||||
var saveModel = umbDataFormatter.formatRelationTypePostData(relationType);
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(umbRequestHelper.getApiUrl("relationTypeApiBaseUrl", "PostSave"), saveModel),
|
||||
"Failed to save data for relation type ID" + relationType.id
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.relationTypeResource#create
|
||||
* @methodOf umbraco.resources.relationTypeResource
|
||||
*
|
||||
* @description
|
||||
* Creates a new relation type.
|
||||
*
|
||||
* @param {Object} relationType The relation type object to create.
|
||||
* @returns {Promise} A resourcePromise object.
|
||||
*/
|
||||
create: function (relationType) {
|
||||
var createModel = umbDataFormatter.formatRelationTypePostData(relationType);
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(umbRequestHelper.getApiUrl("relationTypeApiBaseUrl", "PostCreate"), createModel),
|
||||
"Failed to create new realtion"
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.relationTypeResource#deleteById
|
||||
* @methodOf umbraco.resources.relationTypeResource
|
||||
*
|
||||
* @description
|
||||
* Deletes a relation type with a given ID.
|
||||
*
|
||||
* * ## Usage
|
||||
* <pre>
|
||||
* relationTypeResource.deleteById(1234).then(function() {
|
||||
* alert('Deleted it!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Int} id The ID of the relation type to delete.
|
||||
* @returns {Promose} resourcePromise object.
|
||||
*/
|
||||
deleteById: function (id) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(umbRequestHelper.getApiUrl("relationTypeApiBaseUrl", "DeleteById", [{ id: id }])),
|
||||
"Failed to delete item " + id
|
||||
);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
angular.module("umbraco.resources").factory("relationTypeResource", relationTypeResource);
|
||||
@@ -4,6 +4,76 @@
|
||||
*
|
||||
* @description
|
||||
* Added in Umbraco 8.0. Application-wide service for handling infinite editing.
|
||||
*
|
||||
*
|
||||
<h3>Markup example</h3>
|
||||
<pre>
|
||||
<div ng-controller="My.Controller as vm">
|
||||
|
||||
<button type="button" ng-click="vm.open()">Open</button>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Controller example</h3>
|
||||
<pre>
|
||||
(function () {
|
||||
|
||||
"use strict";
|
||||
|
||||
function Controller() {
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.open = open;
|
||||
|
||||
function open() {
|
||||
var mediaPickerOptions = {
|
||||
multiPicker: true,
|
||||
submit: function(model) {
|
||||
editorService.close();
|
||||
},
|
||||
close: function() {
|
||||
editorService.close();
|
||||
}
|
||||
}
|
||||
editorService.mediaPicker(mediaPickerOptions);
|
||||
};
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("My.Controller", Controller);
|
||||
})();
|
||||
</pre>
|
||||
|
||||
<h3>Custom view example</h3>
|
||||
<pre>
|
||||
(function () {
|
||||
|
||||
"use strict";
|
||||
|
||||
function Controller() {
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.open = open;
|
||||
|
||||
function open() {
|
||||
var options = {
|
||||
view: "path/to/view.html"
|
||||
submit: function(model) {
|
||||
editorService.close();
|
||||
},
|
||||
close: function() {
|
||||
editorService.close();
|
||||
}
|
||||
}
|
||||
editorService.open(options);
|
||||
};
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("My.Controller", Controller);
|
||||
})();
|
||||
</pre>
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
@@ -43,6 +113,10 @@
|
||||
*
|
||||
* @description
|
||||
* Method to open a new editor in infinite editing
|
||||
*
|
||||
* @param {Object} editor rendering options
|
||||
* @param {String} editor.view Path to view
|
||||
* @param {String} editor.size Sets the size of the editor ("Small"). If nothing is set it will use full width.
|
||||
*/
|
||||
function open(editor) {
|
||||
|
||||
@@ -98,7 +172,7 @@
|
||||
editor: null
|
||||
};
|
||||
|
||||
eventsService.emit("appState.editors.closeAll", args);
|
||||
eventsService.emit("appState.editors.close", args);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,8 +182,12 @@
|
||||
*
|
||||
* @description
|
||||
* Opens a media editor in infinite editing, the submit callback returns the updated content item
|
||||
* @param {Object} editor rendering options
|
||||
* @param {String} editor.id The id of the content item
|
||||
* @param {Boolean} editor.create Create new content item
|
||||
* @param {Function} editor.submit Callback function when the publish and close button is clicked. Returns the editor model object
|
||||
* @param {Function} editor.close Callback function when the close button is clicked.
|
||||
*
|
||||
* @returns {Object} editor object
|
||||
*/
|
||||
function contentEditor(editor) {
|
||||
@@ -124,6 +202,12 @@
|
||||
*
|
||||
* @description
|
||||
* Opens a content picker in infinite editing, the submit callback returns an array of selected items
|
||||
*
|
||||
* @param {Object} editor rendering options
|
||||
* @param {Boolean} editor.multiPicker Pick one or multiple items
|
||||
* @param {Function} editor.submit Callback function when the submit button is clicked. Returns the editor model object
|
||||
* @param {Function} editor.close Callback function when the close button is clicked.
|
||||
*
|
||||
* @returns {Object} editor object
|
||||
*/
|
||||
function contentPicker(editor) {
|
||||
@@ -218,11 +302,13 @@
|
||||
*
|
||||
* @description
|
||||
* Opens an embed editor in infinite editing.
|
||||
* @param {Object} editor rendering options
|
||||
* @param {String} editor.icon The icon class
|
||||
* @param {String} editor.color The color class
|
||||
* @param {Callback} editor.submit Saves, submits, and closes the editor
|
||||
* @param {Callback} editor.close Closes the editor
|
||||
* @returns {Object} editor object
|
||||
*/
|
||||
|
||||
function linkPicker(editor) {
|
||||
editor.view = "views/common/infiniteeditors/linkpicker/linkpicker.html";
|
||||
editor.size = "small";
|
||||
@@ -236,6 +322,7 @@
|
||||
*
|
||||
* @description
|
||||
* Opens a media editor in infinite editing, the submit callback returns the updated media item
|
||||
* @param {Object} editor rendering options
|
||||
* @param {String} editor.id The id of the media item
|
||||
* @param {Boolean} editor.create Create new media item
|
||||
* @param {Callback} editor.submit Saves, submits, and closes the editor
|
||||
@@ -254,6 +341,7 @@
|
||||
*
|
||||
* @description
|
||||
* Opens a media picker in infinite editing, the submit callback returns an array of selected media items
|
||||
* @param {Object} editor rendering options
|
||||
* @param {Boolean} editor.multiPicker Pick one or multiple items
|
||||
* @param {Boolean} editor.onlyImages Only display files that have an image file-extension
|
||||
* @param {Boolean} editor.disableFolderSelect Disable folder selection
|
||||
@@ -276,6 +364,7 @@
|
||||
*
|
||||
* @description
|
||||
* Opens an icon picker in infinite editing, the submit callback returns the selected icon
|
||||
* @param {Object} editor rendering options
|
||||
* @param {Callback} editor.submit Submits the editor
|
||||
* @param {Callback} editor.close Closes the editor
|
||||
* @returns {Object} editor object
|
||||
@@ -293,6 +382,7 @@
|
||||
*
|
||||
* @description
|
||||
* Opens the document type editor in infinite editing, the submit callback returns the saved document type
|
||||
* @param {Object} editor rendering options
|
||||
* @param {Callback} editor.submit Submits the editor
|
||||
* @param {Callback} editor.close Closes the editor
|
||||
* @returns {Object} editor object
|
||||
@@ -309,6 +399,7 @@
|
||||
*
|
||||
* @description
|
||||
* Opens the media type editor in infinite editing, the submit callback returns the saved media type
|
||||
* @param {Object} editor rendering options
|
||||
* @param {Callback} editor.submit Submits the editor
|
||||
* @param {Callback} editor.close Closes the editor
|
||||
* @returns {Object} editor object
|
||||
@@ -318,24 +409,75 @@
|
||||
open(editor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.editorService#queryBuilder
|
||||
* @methodOf umbraco.services.editorService
|
||||
*
|
||||
* @description
|
||||
* Opens the query builder in infinite editing, the submit callback returns the generted query
|
||||
* @param {Object} editor rendering options
|
||||
* @param {Callback} editor.submit Submits the editor
|
||||
* @param {Callback} editor.close Closes the editor
|
||||
* @returns {Object} editor object
|
||||
*/
|
||||
function queryBuilder(editor) {
|
||||
editor.view = "views/common/infiniteeditors/querybuilder/querybuilder.html";
|
||||
editor.size = "small";
|
||||
open(editor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.editorService#treePicker
|
||||
* @methodOf umbraco.services.editorService
|
||||
*
|
||||
* @description
|
||||
* Opens the query builder in infinite editing, the submit callback returns the generted query
|
||||
* @param {Object} editor rendering options
|
||||
* @param {String} options.section tree section to display
|
||||
* @param {String} options.treeAlias specific tree to display
|
||||
* @param {Boolean} options.multiPicker should the tree pick one or multiple items before returning
|
||||
* @param {Callback} editor.submit Submits the editor
|
||||
* @param {Callback} editor.close Closes the editor
|
||||
* @returns {Object} editor object
|
||||
*/
|
||||
function treePicker(editor) {
|
||||
editor.view = "views/common/infiniteeditors/treepicker/treepicker.html";
|
||||
editor.size = "small";
|
||||
open(editor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.editorService#nodePermissions
|
||||
* @methodOf umbraco.services.editorService
|
||||
*
|
||||
* @description
|
||||
* Opens the an editor to set node permissions.
|
||||
* @param {Object} editor rendering options
|
||||
* @param {Callback} editor.submit Submits the editor
|
||||
* @param {Callback} editor.close Closes the editor
|
||||
* @returns {Object} editor object
|
||||
*/
|
||||
function nodePermissions(editor) {
|
||||
editor.view = "views/common/infiniteeditors/nodepermissions/nodepermissions.html";
|
||||
editor.size = "small";
|
||||
open(editor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.editorService#insertCodeSnippet
|
||||
* @methodOf umbraco.services.editorService
|
||||
*
|
||||
* @description
|
||||
* Open an editor to insert code snippets into the code editor
|
||||
* @param {Object} editor rendering options
|
||||
* @param {Callback} editor.submit Submits the editor
|
||||
* @param {Callback} editor.close Closes the editor
|
||||
* @returns {Object} editor object
|
||||
*/
|
||||
function insertCodeSnippet(editor) {
|
||||
editor.view = "views/common/infiniteeditors/insertcodesnippet/insertcodesnippet.html";
|
||||
editor.size = "small";
|
||||
@@ -349,6 +491,7 @@
|
||||
*
|
||||
* @description
|
||||
* Opens the user group picker in infinite editing, the submit callback returns an array of the selected user groups
|
||||
* @param {Object} editor rendering options
|
||||
* @param {Callback} editor.submit Submits the editor
|
||||
* @param {Callback} editor.close Closes the editor
|
||||
* @returns {Object} editor object
|
||||
@@ -366,6 +509,7 @@
|
||||
*
|
||||
* @description
|
||||
* Opens the user group picker in infinite editing, the submit callback returns the saved template
|
||||
* @param {Object} editor rendering options
|
||||
* @param {String} editor.id The template id
|
||||
* @param {Callback} editor.submit Submits the editor
|
||||
* @param {Callback} editor.close Closes the editor
|
||||
@@ -382,7 +526,8 @@
|
||||
* @methodOf umbraco.services.editorService
|
||||
*
|
||||
* @description
|
||||
* Opens the section picker in infinite editing, the submit callback returns an array of the selected sections
|
||||
* Opens the section picker in infinite editing, the submit callback returns an array of the selected sections¨
|
||||
* @param {Object} editor rendering options
|
||||
* @param {Callback} editor.submit Submits the editor
|
||||
* @param {Callback} editor.close Closes the editor
|
||||
* @returns {Object} editor object
|
||||
@@ -400,6 +545,7 @@
|
||||
*
|
||||
* @description
|
||||
* Opens the insert field editor in infinite editing, the submit callback returns the code snippet
|
||||
* @param {Object} editor rendering options
|
||||
* @param {Callback} editor.submit Submits the editor
|
||||
* @param {Callback} editor.close Closes the editor
|
||||
* @returns {Object} editor object
|
||||
@@ -417,6 +563,7 @@
|
||||
*
|
||||
* @description
|
||||
* Opens the template sections editor in infinite editing, the submit callback returns the type to insert
|
||||
* @param {Object} editor rendering options
|
||||
* @param {Callback} editor.submit Submits the editor
|
||||
* @param {Callback} editor.close Closes the editor
|
||||
* @returns {Object} editor object
|
||||
@@ -429,11 +576,12 @@
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.editorService#sectionPicker
|
||||
* @name umbraco.services.editorService#userPicker
|
||||
* @methodOf umbraco.services.editorService
|
||||
*
|
||||
* @description
|
||||
* Opens the section picker in infinite editing, the submit callback returns an array of the selected users
|
||||
* @param {Object} editor rendering options
|
||||
* @param {Callback} editor.submit Submits the editor
|
||||
* @param {Callback} editor.close Closes the editor
|
||||
* @returns {Object} editor object
|
||||
@@ -452,6 +600,7 @@
|
||||
* @description
|
||||
* Opens the section picker in infinite editing, the submit callback returns an array of the selected items
|
||||
*
|
||||
* @param {Object} editor rendering options
|
||||
* @param {Array} editor.availableItems Array of available items.
|
||||
* @param {Array} editor.selectedItems Array of selected items. When passed in the selected items will be filtered from the available items.
|
||||
* @param {Boolean} editor.filter Set to false to hide the filter.
|
||||
@@ -485,12 +634,14 @@
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.editorService#macroPicker
|
||||
* @name umbraco.services.editorService#memberGroupPicker
|
||||
* @methodOf umbraco.services.editorService
|
||||
*
|
||||
* @description
|
||||
* Opens a member group picker in infinite editing.
|
||||
*
|
||||
* @param {Object} editor rendering options
|
||||
* @param {Object} editor.multiPicker Pick one or multiple items.
|
||||
* @param {Callback} editor.submit Submits the editor.
|
||||
* @param {Callback} editor.close Closes the editor.
|
||||
* @returns {Object} editor object
|
||||
|
||||
@@ -431,6 +431,24 @@
|
||||
}
|
||||
|
||||
return displayModel;
|
||||
},
|
||||
|
||||
/**
|
||||
* Formats the display model used to display the relation type to a model used to save the relation type.
|
||||
* @param {Object} relationType
|
||||
*/
|
||||
formatRelationTypePostData : function(relationType) {
|
||||
var saveModel = {
|
||||
id: relationType.id,
|
||||
name: relationType.name,
|
||||
alias: relationType.alias,
|
||||
key : relationType.key,
|
||||
isBidirectional: relationType.isBidirectional,
|
||||
parentObjectType: relationType.parentObjectType,
|
||||
childObjectType: relationType.childObjectType
|
||||
};
|
||||
|
||||
return saveModel;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
.umb-dashboards-forms-install {
|
||||
background: url('../img/forms/installer-background.png');
|
||||
background-repeat: repeat-x;
|
||||
position: relative;
|
||||
top: -30px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding-top: 30px;
|
||||
box-shadow: inset 0px -40px 30px 25px rgba(255,255,255,1);
|
||||
-moz-border-radius: 0px 0px 200px 200px;
|
||||
-webkit-border-radius: 0px 0px 200px 200px;
|
||||
border-radius: 0px 0px 200px 200px;
|
||||
background-color: @white;
|
||||
overflow: auto;
|
||||
|
||||
small {
|
||||
font-size: 14px;
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @ngdoc controller
|
||||
* @name Umbraco.Editors.RelationTypes.CreateController
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* The controller for creating relation types.
|
||||
*/
|
||||
function RelationTypeCreateController($scope, $location, relationTypeResource, navigationService, formHelper, appState, notificationsService) {
|
||||
var vm = this;
|
||||
vm.relationType = {};
|
||||
vm.objectTypes = {};
|
||||
|
||||
vm.createRelationType = createRelationType;
|
||||
|
||||
init();
|
||||
|
||||
function init() {
|
||||
relationTypeResource.getRelationObjectTypes().then(function (data) {
|
||||
vm.objectTypes = data;
|
||||
}, function (err) {
|
||||
notificationsService.error("Could not load form.")
|
||||
})
|
||||
}
|
||||
|
||||
function createRelationType() {
|
||||
if (formHelper.submitForm({ scope: $scope, formCtrl: this.createRelationTypeForm, statusMessage: "Creating relation type..." })) {
|
||||
var node = $scope.currentNode;
|
||||
|
||||
relationTypeResource.create(vm.relationType).then(function (data) {
|
||||
navigationService.hideMenu();
|
||||
|
||||
// Set the new item as active in the tree
|
||||
var currentPath = node.path ? node.path : "-1";
|
||||
navigationService.syncTree({ tree: "relationTypes", path: currentPath + "," + data, forceReload: true, activate: true });
|
||||
|
||||
formHelper.resetForm({ scope: $scope });
|
||||
|
||||
var currentSection = appState.getSectionState("currentSection");
|
||||
$location.path("/" + currentSection + "/relationTypes/edit/" + data);
|
||||
}, function (err) {
|
||||
if (err.data && err.data.message) {
|
||||
notificationsService.error(err.data.message);
|
||||
navigationService.hideMenu();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.Editors.RelationTypes.CreateController", RelationTypeCreateController);
|
||||
@@ -0,0 +1,58 @@
|
||||
<div class="umbracoDialog umb-dialog-body with-footer" ng-controller="Umbraco.Editors.RelationTypes.CreateController as vm" ng-cloak>
|
||||
<div class="umb-pane">
|
||||
<form name="createRelationTypeForm" val-form-manager ng-submit="vm.createRelationType()">
|
||||
<!-- Name -->
|
||||
<umb-control-group label="@relationType_name">
|
||||
<input type="text" name="relationTypeName" ng-model="vm.relationType.name" class="umb-textstring textstring input-block-level" umb-auto-focus required />
|
||||
</umb-control-group>
|
||||
|
||||
<!-- Direction -->
|
||||
<umb-control-group label="@relationType_direction">
|
||||
<ul class="unstyled">
|
||||
<li>
|
||||
<label class="radio">
|
||||
<input type="radio" name="relationType-direction" ng-model="vm.relationType.isBidirectional" ng-value="false">
|
||||
<localize key="relationType_parentToChild">Parent to child</localize>
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="radio">
|
||||
<input type="radio" name="relationType-direction" ng-model="vm.relationType.isBidirectional" ng-value="true">
|
||||
<localize key="relationType_bidirectional">Bidirectional</localize>
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
</umb-control-group>
|
||||
|
||||
<!-- Parent -->
|
||||
<umb-control-group label="@relationType_parent">
|
||||
<select name="relationType-parent"
|
||||
ng-model="vm.relationType.parentObjectType"
|
||||
class="umb-property-editor umb-dropdown"
|
||||
required>
|
||||
<option ng-repeat="objectType in vm.objectTypes" value="{{objectType.id}}">{{objectType.name}}</option>
|
||||
</select>
|
||||
</umb-control-group>
|
||||
|
||||
<!-- Child -->
|
||||
<umb-control-group label="@relationType_child">
|
||||
<select name="relationType-child"
|
||||
ng-model="vm.relationType.childObjectType"
|
||||
class="umb-property-editor umb-dropdown"
|
||||
required>
|
||||
<option ng-repeat="objectType in vm.objectTypes" value="{{objectType.id}}">{{objectType.name}}</option>
|
||||
</select>
|
||||
</umb-control-group>
|
||||
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<localize key="general_create">Create</localize>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-dialog-footer btn-toolbar umb-btn-toolbar">
|
||||
<button class="btn btn-info">
|
||||
<localize key="buttons_somethingElse">Do something else</localize>
|
||||
</button>
|
||||
</div>
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* @ngdoc controller
|
||||
* @name Umbraco.Editors.RelationTypes.DeleteController
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* The controller for deleting relation types.
|
||||
*/
|
||||
function RelationTypeDeleteController($scope, $location, relationTypeResource, treeService, navigationService, appState) {
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.cancel = cancel;
|
||||
vm.performDelete = performDelete;
|
||||
|
||||
function cancel() {
|
||||
navigationService.hideDialog();
|
||||
}
|
||||
|
||||
function performDelete() {
|
||||
// stop from firing again on double-click
|
||||
if ($scope.busy) { return false; }
|
||||
|
||||
//mark it for deletion (used in the UI)
|
||||
$scope.currentNode.loading = true;
|
||||
$scope.busy = true;
|
||||
|
||||
relationTypeResource.deleteById($scope.currentNode.id).then(function () {
|
||||
$scope.currentNode.loading = false;
|
||||
|
||||
treeService.removeNode($scope.currentNode);
|
||||
|
||||
navigationService.hideMenu();
|
||||
|
||||
var currentSection = appState.getSectionState("currentSection");
|
||||
$location.path("/" + currentSection + "/");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.Editors.RelationTypes.DeleteController", RelationTypeDeleteController);
|
||||
@@ -0,0 +1,12 @@
|
||||
<div class="umb-dialog umb-pane" ng-controller="Umbraco.Editors.RelationTypes.DeleteController as vm">
|
||||
<div class="umb-dialog-body" auto-scale="90">
|
||||
|
||||
<p class="umb-abstract">
|
||||
<localize key="defaultdialogs_confirmdelete">Are you sure you want to delete</localize> <strong>{{currentNode.name}}</strong>?
|
||||
</p>
|
||||
|
||||
<umb-confirm on-confirm="vm.performDelete" on-cancel="vm.cancel">
|
||||
</umb-confirm>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* @ngdoc controller
|
||||
* @name Umbraco.Editors.RelationTypes.EditController
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* The controller for editing relation types.
|
||||
*/
|
||||
function RelationTypeEditController($scope, $routeParams, relationTypeResource, editorState, navigationService, dateHelper, userService, entityResource, formHelper, contentEditingHelper, localizationService) {
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.page = {};
|
||||
vm.page.loading = false;
|
||||
vm.page.saveButtonState = "init";
|
||||
vm.page.menu = {}
|
||||
|
||||
vm.save = saveRelationType;
|
||||
|
||||
init();
|
||||
|
||||
function init() {
|
||||
vm.page.loading = true;
|
||||
|
||||
localizationService.localizeMany(["relationType_tabRelationType", "relationType_tabRelations"]).then(function (data) {
|
||||
vm.page.navigation = [
|
||||
{
|
||||
"name": data[0],
|
||||
"alias": "relationType",
|
||||
"icon": "icon-info",
|
||||
"view": "views/relationTypes/views/relationType.html",
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"name": data[1],
|
||||
"alias": "relations",
|
||||
"icon": "icon-trafic",
|
||||
"view": "views/relationTypes/views/relations.html"
|
||||
}
|
||||
];
|
||||
});
|
||||
|
||||
relationTypeResource.getById($routeParams.id)
|
||||
.then(function(data) {
|
||||
bindRelationType(data);
|
||||
vm.page.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
function bindRelationType(relationType) {
|
||||
formatDates(relationType.relations);
|
||||
getRelationNames(relationType);
|
||||
|
||||
vm.relationType = relationType;
|
||||
|
||||
editorState.set(vm.relationType);
|
||||
|
||||
navigationService.syncTree({ tree: "relationTypes", path: relationType.path, forceReload: true }).then(function (syncArgs) {
|
||||
vm.page.menu.currentNode = syncArgs.node;
|
||||
});
|
||||
}
|
||||
|
||||
function formatDates(relations) {
|
||||
if(relations) {
|
||||
userService.getCurrentUser().then(function (currentUser) {
|
||||
angular.forEach(relations, function (relation) {
|
||||
relation.timestampFormatted = dateHelper.getLocalDate(relation.createDate, currentUser.locale, 'LLL');
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function getRelationNames(relationType) {
|
||||
if(relationType.relations) {
|
||||
angular.forEach(relationType.relations, function(relation){
|
||||
entityResource.getById(relation.parentId, relationType.parentObjectTypeName).then(function(entity) {
|
||||
relation.parentName = entity.name;
|
||||
});
|
||||
entityResource.getById(relation.childId, relationType.childObjectTypeName).then(function(entity) {
|
||||
relation.childName = entity.name;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function saveRelationType() {
|
||||
vm.page.saveButtonState = "busy";
|
||||
|
||||
if (formHelper.submitForm({ scope: $scope, statusMessage: "Saving..." })) {
|
||||
relationTypeResource.save(vm.relationType).then(function (data) {
|
||||
formHelper.resetForm({ scope: $scope, notifications: data.notifications });
|
||||
bindRelationType(data);
|
||||
vm.page.saveButtonState = "success";
|
||||
}, function (error) {
|
||||
contentEditingHelper.handleSaveError({
|
||||
redirectOnFailure: false,
|
||||
err: error
|
||||
});
|
||||
|
||||
notificationsService.error(error.data.message);
|
||||
vm.page.saveButtonState = "error";
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.Editors.RelationTypes.EditController", RelationTypeEditController);
|
||||
33
src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html
Normal file
33
src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.html
Normal file
@@ -0,0 +1,33 @@
|
||||
<div data-element="editor-relation-types" ng-controller="Umbraco.Editors.RelationTypes.EditController as vm">
|
||||
<umb-load-indicator ng-if="vm.page.loading"></umb-load-indicator>
|
||||
|
||||
<form name="relationTypeForm" novalidate val-form-manager ng-submit="vm.save()">
|
||||
<umb-editor-view ng-if="!vm.page.loading">
|
||||
<umb-editor-header
|
||||
name="vm.relationType.name"
|
||||
alias="vm.relationType.alias"
|
||||
hide-description="true"
|
||||
hide-icon="true"
|
||||
navigation="vm.page.navigation">
|
||||
</umb-editor-header>
|
||||
|
||||
<umb-editor-container class="form-horizontal">
|
||||
<umb-editor-sub-views sub-views="vm.page.navigation" model="vm">
|
||||
</umb-editor-sub-views>
|
||||
</umb-editor-container>
|
||||
|
||||
<umb-editor-footer>
|
||||
<umb-editor-footer-content-right>
|
||||
<umb-button
|
||||
type="submit"
|
||||
button-style="success"
|
||||
state="vm.page.saveButtonState"
|
||||
shortcut="ctrl+s"
|
||||
label="Save"
|
||||
label-key="buttons_save">
|
||||
</umb-button>
|
||||
</umb-editor-footer-content-right>
|
||||
</umb-editor-footer>
|
||||
</umb-editor-view>
|
||||
</form>
|
||||
</div>
|
||||
@@ -0,0 +1,40 @@
|
||||
<umb-box>
|
||||
<umb-box-content>
|
||||
<!-- ID -->
|
||||
<umb-control-group label="Id">
|
||||
<div>{{model.relationType.id}}</div>
|
||||
<small>{{model.relationType.key}}</small>
|
||||
</umb-control-group>
|
||||
|
||||
<!-- Direction -->
|
||||
<umb-control-group label="@relationType_direction">
|
||||
<ul class="unstyled">
|
||||
<li>
|
||||
<label class="radio">
|
||||
<input type="radio" name="relationType-direction" ng-model="model.relationType.isBidirectional" ng-value="false"> <localize key="relationType_parentToChild">Parent to child</localize>
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="radio">
|
||||
<input type="radio" name="relationType-direction" ng-model="model.relationType.isBidirectional" ng-value="true"> <localize key="relationType_bidirectional">Bidirectional</localize>
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
</umb-control-group>
|
||||
|
||||
<!-- Parent-->
|
||||
<umb-control-group label="@relationType_parent">
|
||||
<div>{{model.relationType.parentObjectTypeName}}</div>
|
||||
</umb-control-group>
|
||||
|
||||
<!-- Child -->
|
||||
<umb-control-group label="@relationType_child">
|
||||
<div>{{model.relationType.childObjectTypeName}}</div>
|
||||
</umb-control-group>
|
||||
|
||||
<!-- Relation count -->
|
||||
<umb-control-group label="@relationType_count" ng-if="model.relationType.relations.length > 0">
|
||||
<div>{{model.relationType.relations.length}}</div>
|
||||
</umb-control-group>
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
@@ -0,0 +1,23 @@
|
||||
<umb-box>
|
||||
<umb-box-content>
|
||||
<!-- Relations -->
|
||||
<umb-control-group label="@relationType_relations" ng-if="model.relationType.relations.length > 0">
|
||||
<div>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<th><localize key="relationType_parent">Parent</localize></th>
|
||||
<th><localize key="relationType_child">Child</localize></th>
|
||||
<th><localize key="relationType_created">Created</localize></th>
|
||||
<th><localize key="relationType_comment">Comment</localize></th>
|
||||
</thead>
|
||||
<tr ng-repeat="relation in model.relationType.relations">
|
||||
<td>{{relation.parentName}}</td>
|
||||
<td>{{relation.childName}}</td>
|
||||
<td>{{relation.timestampFormatted}}</td>
|
||||
<td>{{relation.comment}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</umb-control-group>
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
@@ -452,10 +452,10 @@
|
||||
<WebPublishingTasks Condition="exists('$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v11.0\Web\Microsoft.Web.Publishing.Tasks.dll')">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v11.0\Web\Microsoft.Web.Publishing.Tasks.dll</WebPublishingTasks>
|
||||
<WebPublishingTasks Condition="exists('$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v12.0\Web\Microsoft.Web.Publishing.Tasks.dll')">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v12.0\Web\Microsoft.Web.Publishing.Tasks.dll</WebPublishingTasks>
|
||||
<WebPublishingTasks Condition="exists('$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v14.0\Web\Microsoft.Web.Publishing.Tasks.dll')">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v14.0\Web\Microsoft.Web.Publishing.Tasks.dll</WebPublishingTasks>
|
||||
<WebPublishingTasks Condition="exists('$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v15.0\Web\Microsoft.Web.Publishing.Tasks.dll')">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v15.0\Web\Microsoft.Web.Publishing.Tasks.dll</WebPublishingTasks>
|
||||
<WebPublishingTasks Condition="exists('$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v16.0\Web\Microsoft.Web.Publishing.Tasks.dll')">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v16.0\Web\Microsoft.Web.Publishing.Tasks.dll</WebPublishingTasks>
|
||||
<!-- Temporary addition for the VS2019 preview - can be removed when VS2019 final is released, then v16 above will be used -->
|
||||
<WebPublishingTasks Condition="exists('$(ProgramFiles32)\Microsoft Visual Studio\2019\Preview\MSBuild\Microsoft\VisualStudio\v16.0\Web\Microsoft.Web.Publishing.Tasks.dll')">$(ProgramFiles32)\Microsoft Visual Studio\2019\Preview\MSBuild\Microsoft\VisualStudio\v16.0\Web\Microsoft.Web.Publishing.Tasks.dll</WebPublishingTasks>
|
||||
<WebPublishingTasks Condition="exists('$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v15.0\Web\Microsoft.Web.Publishing.Tasks.dll')">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v15.0\Web\Microsoft.Web.Publishing.Tasks.dll</WebPublishingTasks>
|
||||
<WebPublishingTasks Condition="exists('$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v16.0\Web\Microsoft.Web.Publishing.Tasks.dll')">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v16.0\Web\Microsoft.Web.Publishing.Tasks.dll</WebPublishingTasks>
|
||||
<!-- Temporary addition for the VS2019 preview - can be removed when VS2019 final is released, then v16 above will be used -->
|
||||
<WebPublishingTasks Condition="exists('$(ProgramFiles32)\Microsoft Visual Studio\2019\Preview\MSBuild\Microsoft\VisualStudio\v16.0\Web\Microsoft.Web.Publishing.Tasks.dll')">$(ProgramFiles32)\Microsoft Visual Studio\2019\Preview\MSBuild\Microsoft\VisualStudio\v16.0\Web\Microsoft.Web.Publishing.Tasks.dll</WebPublishingTasks>
|
||||
</PropertyGroup>
|
||||
<!-- get TransformXml task from WebPublishingtasks -->
|
||||
<UsingTask TaskName="TransformXml" AssemblyFile="$(WebPublishingTasks)" Condition="'$(WebPublishingTasks)' != ''" />
|
||||
|
||||
@@ -1965,4 +1965,18 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="noRestoreRelation">There is no 'restore' relation found for this node. Use the Move menu item to move it manually.</key>
|
||||
<key alias="restoreUnderRecycled">The item you want to restore it under ('%0%') is in the recycle bin. Use the Move menu item to move the item manually.</key>
|
||||
</area>
|
||||
<area alias="relationType">
|
||||
<key alias="direction">Direction</key>
|
||||
<key alias="parentToChild">Parent to child</key>
|
||||
<key alias="bidirectional">Bidirectional</key>
|
||||
<key alias="parent">Parent</key>
|
||||
<key alias="child">Child</key>
|
||||
<key alias="count">Count</key>
|
||||
<key alias="relations">Relations</key>
|
||||
<key alias="created">Created</key>
|
||||
<key alias="comment">Comment</key>
|
||||
<key alias="name">Name</key>
|
||||
<key alias="tabRelationType">Relation Type</key>
|
||||
<key alias="tabRelations">Relations</key>
|
||||
</area>
|
||||
</language>
|
||||
|
||||
@@ -2020,4 +2020,18 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="notifySet">Select your notifications for</key>
|
||||
<key alias="notificationsSavedFor">Notification settings saved for </key>
|
||||
</area>
|
||||
<area alias="relationType">
|
||||
<key alias="direction">Direction</key>
|
||||
<key alias="parentToChild">Parent to child</key>
|
||||
<key alias="bidirectional">Bidirectional</key>
|
||||
<key alias="parent">Parent</key>
|
||||
<key alias="child">Child</key>
|
||||
<key alias="count">Count</key>
|
||||
<key alias="relations">Relations</key>
|
||||
<key alias="created">Created</key>
|
||||
<key alias="comment">Comment</key>
|
||||
<key alias="name">Name</key>
|
||||
<key alias="tabRelationType">Relation Type</key>
|
||||
<key alias="tabRelations">Relations</key>
|
||||
</area>
|
||||
</language>
|
||||
|
||||
@@ -30,9 +30,5 @@
|
||||
<add initialize="true" sortOrder="1" alias="memberGroups" application="member" title="Member Groups" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.MemberGroupTreeController, Umbraco.Web" />
|
||||
<!--Translation-->
|
||||
<add initialize="true" application="translation" alias="dictionary" title="Dictionary" type="Umbraco.Web.Trees.DictionaryTreeController, Umbraco.Web" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="0" />
|
||||
<!-- Custom -->
|
||||
<add initialize="true" sortOrder="2" alias="datasource" application="forms" title="Datasources" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Forms.Web.Trees.DataSourceTreeController, Umbraco.Forms.Web" />
|
||||
<add initialize="true" sortOrder="0" alias="form" application="forms" title="Forms" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Forms.Web.Trees.FormTreeController, Umbraco.Forms.Web" />
|
||||
<add initialize="true" sortOrder="3" alias="prevaluesource" application="forms" title="Prevalue sources" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Forms.Web.Trees.PreValueSourceTreeController, Umbraco.Forms.Web" />
|
||||
<add initialize="true" sortOrder="3" alias="formsecurity" application="users" title="Forms Security" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Forms.Web.Trees.FormSecurityTreeController, Umbraco.Forms.Web" />
|
||||
|
||||
</trees>
|
||||
|
||||
@@ -30,9 +30,5 @@
|
||||
<add initialize="true" sortOrder="1" alias="memberGroups" application="member" title="Member Groups" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.MemberGroupTreeController, Umbraco.Web" />
|
||||
<!--Translation-->
|
||||
<add initialize="true" application="translation" alias="dictionary" title="Dictionary" type="Umbraco.Web.Trees.DictionaryTreeController, Umbraco.Web" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="0" />
|
||||
<!-- Custom -->
|
||||
<add initialize="true" sortOrder="2" alias="datasource" application="forms" title="Datasources" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Forms.Web.Trees.DataSourceTreeController, Umbraco.Forms.Web" />
|
||||
<add initialize="true" sortOrder="0" alias="form" application="forms" title="Forms" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Forms.Web.Trees.FormTreeController, Umbraco.Forms.Web" />
|
||||
<add initialize="true" sortOrder="3" alias="prevaluesource" application="forms" title="Prevalue sources" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Forms.Web.Trees.PreValueSourceTreeController, Umbraco.Forms.Web" />
|
||||
<add initialize="true" sortOrder="3" alias="formsecurity" application="users" title="Forms Security" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Forms.Web.Trees.FormSecurityTreeController, Umbraco.Forms.Web" />
|
||||
|
||||
</trees>
|
||||
|
||||
@@ -299,6 +299,10 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
"languageApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<LanguageController>(
|
||||
controller => controller.GetAllLanguages())
|
||||
},
|
||||
{
|
||||
"relationTypeApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<RelationTypeController>(
|
||||
controller => controller.GetById(1))
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -118,6 +118,7 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
|
||||
[ValidateAngularAntiForgeryToken]
|
||||
[OutgoingEditorModelEvent]
|
||||
public IEnumerable<Tab<DashboardControl>> GetDashboard(string section)
|
||||
{
|
||||
return _dashboards.GetDashboards(section, Security.CurrentUser);
|
||||
|
||||
@@ -4,9 +4,13 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
public sealed class EditorModelEventArgs<T> : EditorModelEventArgs
|
||||
{
|
||||
private readonly EditorModelEventArgs _baseArgs;
|
||||
private T _model;
|
||||
|
||||
public EditorModelEventArgs(EditorModelEventArgs baseArgs)
|
||||
: base(baseArgs.Model, baseArgs.UmbracoContext)
|
||||
{
|
||||
_baseArgs = baseArgs;
|
||||
Model = (T)baseArgs.Model;
|
||||
}
|
||||
|
||||
@@ -16,7 +20,16 @@ namespace Umbraco.Web.Editors
|
||||
Model = model;
|
||||
}
|
||||
|
||||
public new T Model { get; private set; }
|
||||
public new T Model
|
||||
{
|
||||
get => _model;
|
||||
set
|
||||
{
|
||||
_model = value;
|
||||
if (_baseArgs != null)
|
||||
_baseArgs.Model = _model;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class EditorModelEventArgs : EventArgs
|
||||
@@ -27,7 +40,7 @@ namespace Umbraco.Web.Editors
|
||||
UmbracoContext = umbracoContext;
|
||||
}
|
||||
|
||||
public object Model { get; private set; }
|
||||
public UmbracoContext UmbracoContext { get; private set; }
|
||||
public object Model { get; set; }
|
||||
public UmbracoContext UmbracoContext { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Web.Http.Filters;
|
||||
using System.Collections.Generic;
|
||||
using System.Web.Http.Filters;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
|
||||
@@ -13,6 +14,13 @@ namespace Umbraco.Web.Editors
|
||||
public static event TypedEventHandler<HttpActionExecutedContext, EditorModelEventArgs<MediaItemDisplay>> SendingMediaModel;
|
||||
public static event TypedEventHandler<HttpActionExecutedContext, EditorModelEventArgs<MemberDisplay>> SendingMemberModel;
|
||||
public static event TypedEventHandler<HttpActionExecutedContext, EditorModelEventArgs<UserDisplay>> SendingUserModel;
|
||||
public static event TypedEventHandler<HttpActionExecutedContext, EditorModelEventArgs<IEnumerable<Tab<DashboardControl>>>> SendingDashboardModel;
|
||||
|
||||
private static void OnSendingDashboardModel(HttpActionExecutedContext sender, EditorModelEventArgs<IEnumerable<Tab<DashboardControl>>> e)
|
||||
{
|
||||
var handler = SendingDashboardModel;
|
||||
handler?.Invoke(sender, e);
|
||||
}
|
||||
|
||||
private static void OnSendingUserModel(HttpActionExecutedContext sender, EditorModelEventArgs<UserDisplay> e)
|
||||
{
|
||||
@@ -56,6 +64,9 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
if (e.Model is UserDisplay)
|
||||
OnSendingUserModel(sender, new EditorModelEventArgs<UserDisplay>(e));
|
||||
|
||||
if (e.Model is IEnumerable<Tab<DashboardControl>>)
|
||||
OnSendingDashboardModel(sender, new EditorModelEventArgs<IEnumerable<Tab<DashboardControl>>>(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,40 +6,40 @@ using System.Web.Http;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
using Constants = Umbraco.Core.Constants;
|
||||
using Relation = Umbraco.Web.Models.ContentEditing.Relation;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
[PluginController("UmbracoApi")]
|
||||
[UmbracoApplicationAuthorizeAttribute(Constants.Applications.Content)]
|
||||
[UmbracoApplicationAuthorize(Constants.Applications.Content)]
|
||||
public class RelationController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
public Relation GetById(int id)
|
||||
public RelationDisplay GetById(int id)
|
||||
{
|
||||
return Mapper.Map<IRelation, Relation>(Services.RelationService.GetById(id));
|
||||
return Mapper.Map<IRelation, RelationDisplay>(Services.RelationService.GetById(id));
|
||||
}
|
||||
|
||||
//[EnsureUserPermissionForContent("childId")]
|
||||
public IEnumerable<Relation> GetByChildId(int childId, string relationTypeAlias = "")
|
||||
public IEnumerable<RelationDisplay> GetByChildId(int childId, string relationTypeAlias = "")
|
||||
{
|
||||
var relations = Services.RelationService.GetByChildId(childId).ToArray();
|
||||
|
||||
if (relations.Any() == false)
|
||||
{
|
||||
return Enumerable.Empty<Relation>();
|
||||
return Enumerable.Empty<RelationDisplay>();
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(relationTypeAlias) == false)
|
||||
{
|
||||
return
|
||||
Mapper.Map<IEnumerable<IRelation>, IEnumerable<Relation>>(
|
||||
Mapper.Map<IEnumerable<IRelation>, IEnumerable<RelationDisplay>>(
|
||||
relations.Where(x => x.RelationType.Alias.InvariantEquals(relationTypeAlias)));
|
||||
}
|
||||
|
||||
return Mapper.Map<IEnumerable<IRelation>, IEnumerable<Relation>>(relations);
|
||||
return Mapper.Map<IEnumerable<IRelation>, IEnumerable<RelationDisplay>>(relations);
|
||||
}
|
||||
|
||||
[HttpDelete]
|
||||
|
||||
147
src/Umbraco.Web/Editors/RelationTypeController.cs
Normal file
147
src/Umbraco.Web/Editors/RelationTypeController.cs
Normal file
@@ -0,0 +1,147 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
using Constants = Umbraco.Core.Constants;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
/// <summary>
|
||||
/// The API controller for editing relation types.
|
||||
/// </summary>
|
||||
[PluginController("UmbracoApi")]
|
||||
[UmbracoTreeAuthorize(Constants.Trees.RelationTypes)]
|
||||
[EnableOverrideAuthorization]
|
||||
public class RelationTypeController : BackOfficeNotificationsController
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a relation type by ID.
|
||||
/// </summary>
|
||||
/// <param name="id">The relation type ID.</param>
|
||||
/// <returns>Returns the <see cref="RelationTypeDisplay"/>.</returns>
|
||||
public RelationTypeDisplay GetById(int id)
|
||||
{
|
||||
var relationType = Services.RelationService.GetRelationTypeById(id);
|
||||
|
||||
if (relationType == null)
|
||||
{
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
var relations = Services.RelationService.GetByRelationTypeId(relationType.Id);
|
||||
|
||||
var display = Mapper.Map<IRelationType, RelationTypeDisplay>(relationType);
|
||||
display.Relations = Mapper.Map<IEnumerable<IRelation>, IEnumerable<RelationDisplay>>(relations);
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of object types which can be associated via relations.
|
||||
/// </summary>
|
||||
/// <returns>A list of available object types.</returns>
|
||||
public List<ObjectType> GetRelationObjectTypes()
|
||||
{
|
||||
var objectTypes = new List<ObjectType>
|
||||
{
|
||||
new ObjectType{Id = UmbracoObjectTypes.Document.GetGuid(), Name = UmbracoObjectTypes.Document.GetFriendlyName()},
|
||||
new ObjectType{Id = UmbracoObjectTypes.Media.GetGuid(), Name = UmbracoObjectTypes.Media.GetFriendlyName()},
|
||||
new ObjectType{Id = UmbracoObjectTypes.Member.GetGuid(), Name = UmbracoObjectTypes.Member.GetFriendlyName()},
|
||||
new ObjectType{Id = UmbracoObjectTypes.DocumentType.GetGuid(), Name = UmbracoObjectTypes.DocumentType.GetFriendlyName()},
|
||||
new ObjectType{Id = UmbracoObjectTypes.MediaType.GetGuid(), Name = UmbracoObjectTypes.MediaType.GetFriendlyName()},
|
||||
new ObjectType{Id = UmbracoObjectTypes.MemberType.GetGuid(), Name = UmbracoObjectTypes.MemberType.GetFriendlyName()},
|
||||
new ObjectType{Id = UmbracoObjectTypes.DataType.GetGuid(), Name = UmbracoObjectTypes.DataType.GetFriendlyName()},
|
||||
new ObjectType{Id = UmbracoObjectTypes.MemberGroup.GetGuid(), Name = UmbracoObjectTypes.MemberGroup.GetFriendlyName()},
|
||||
new ObjectType{Id = UmbracoObjectTypes.Stylesheet.GetGuid(), Name = UmbracoObjectTypes.Stylesheet.GetFriendlyName()},
|
||||
new ObjectType{Id = UmbracoObjectTypes.ROOT.GetGuid(), Name = UmbracoObjectTypes.ROOT.GetFriendlyName()},
|
||||
new ObjectType{Id = UmbracoObjectTypes.RecycleBin.GetGuid(), Name = UmbracoObjectTypes.RecycleBin.GetFriendlyName()},
|
||||
};
|
||||
|
||||
return objectTypes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new relation type.
|
||||
/// </summary>
|
||||
/// <param name="relationType">The relation type to create.</param>
|
||||
/// <returns>A <see cref="HttpResponseMessage"/> containing the persisted relation type's ID.</returns>
|
||||
public HttpResponseMessage PostCreate(RelationTypeSave relationType)
|
||||
{
|
||||
var relationTypePersisted = new RelationType(relationType.ChildObjectType, relationType.ParentObjectType, relationType.Name.ToSafeAlias(true))
|
||||
{
|
||||
Name = relationType.Name,
|
||||
IsBidirectional = relationType.IsBidirectional
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
Services.RelationService.Save(relationTypePersisted);
|
||||
|
||||
return Request.CreateResponse(HttpStatusCode.OK, relationTypePersisted.Id);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error(GetType(), ex, "Error creating relation type with {Name}", relationType.Name);
|
||||
return Request.CreateNotificationValidationErrorResponse("Error creating relation type.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates an existing relation type.
|
||||
/// </summary>
|
||||
/// <param name="relationType">The relation type to update.</param>
|
||||
/// <returns>A display object containing the updated relation type.</returns>
|
||||
public RelationTypeDisplay PostSave(RelationTypeSave relationType)
|
||||
{
|
||||
var relationTypePersisted = Services.RelationService.GetRelationTypeById(relationType.Key);
|
||||
|
||||
if (relationTypePersisted == null)
|
||||
{
|
||||
throw new HttpResponseException(Request.CreateNotificationValidationErrorResponse("Relation type does not exist"));
|
||||
}
|
||||
|
||||
Mapper.Map(relationType, relationTypePersisted);
|
||||
|
||||
try
|
||||
{
|
||||
Services.RelationService.Save(relationTypePersisted);
|
||||
var display = Mapper.Map<RelationTypeDisplay>(relationTypePersisted);
|
||||
display.AddSuccessNotification("Relation type saved", "");
|
||||
|
||||
return display;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error(GetType(), ex, "Error saving relation type with {Id}", relationType.Id);
|
||||
throw new HttpResponseException(Request.CreateNotificationValidationErrorResponse("Something went wrong when saving the relation type"));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a relation type with a given ID.
|
||||
/// </summary>
|
||||
/// <param name="id">The ID of the relation type to delete.</param>
|
||||
/// <returns>A <see cref="HttpResponseMessage"/>.</returns>
|
||||
[HttpPost]
|
||||
[HttpDelete]
|
||||
public HttpResponseMessage DeleteById(int id)
|
||||
{
|
||||
var relationType = Services.RelationService.GetRelationTypeById(id);
|
||||
|
||||
if(relationType == null)
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
|
||||
Services.RelationService.Delete(relationType);
|
||||
|
||||
return Request.CreateResponse(HttpStatusCode.OK);
|
||||
}
|
||||
}
|
||||
}
|
||||
15
src/Umbraco.Web/Models/ContentEditing/ObjectType.cs
Normal file
15
src/Umbraco.Web/Models/ContentEditing/ObjectType.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Web.Models.ContentEditing
|
||||
{
|
||||
[DataContract(Name = "objectType", Namespace = "")]
|
||||
public class ObjectType
|
||||
{
|
||||
[DataMember(Name = "name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[DataMember(Name = "id")]
|
||||
public Guid Id { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Umbraco.Web.Models.ContentEditing
|
||||
{
|
||||
[DataContract(Name = "relation", Namespace = "")]
|
||||
public class Relation
|
||||
{
|
||||
|
||||
public Relation()
|
||||
{
|
||||
RelationType = new RelationType();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Parent Id of the Relation (Source)
|
||||
/// </summary>
|
||||
[DataMember(Name = "parentId")]
|
||||
public int ParentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Child Id of the Relation (Destination)
|
||||
/// </summary>
|
||||
[DataMember(Name = "childId")]
|
||||
public int ChildId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="RelationType"/> for the Relation
|
||||
/// </summary>
|
||||
[DataMember(Name = "relationType", IsRequired = true)]
|
||||
public RelationType RelationType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a comment for the Relation
|
||||
/// </summary>
|
||||
[DataMember(Name = "comment")]
|
||||
public string Comment { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
52
src/Umbraco.Web/Models/ContentEditing/RelationDisplay.cs
Normal file
52
src/Umbraco.Web/Models/ContentEditing/RelationDisplay.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Web.Models.ContentEditing
|
||||
{
|
||||
[DataContract(Name = "relation", Namespace = "")]
|
||||
public class RelationDisplay
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the Parent Id of the Relation (Source).
|
||||
/// </summary>
|
||||
[DataMember(Name = "parentId")]
|
||||
[ReadOnly(true)]
|
||||
public int ParentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Parent Name of the relation (Source).
|
||||
/// </summary>
|
||||
[DataMember(Name = "parentName")]
|
||||
[ReadOnly(true)]
|
||||
public string ParentName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Child Id of the Relation (Destination).
|
||||
/// </summary>
|
||||
[DataMember(Name = "childId")]
|
||||
[ReadOnly(true)]
|
||||
public int ChildId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Child Name of the relation (Destination).
|
||||
/// </summary>
|
||||
[DataMember(Name = "childName")]
|
||||
[ReadOnly(true)]
|
||||
public string ChildName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the date when the Relation was created.
|
||||
/// </summary>
|
||||
[DataMember(Name = "createDate")]
|
||||
[ReadOnly(true)]
|
||||
public DateTime CreateDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a comment for the Relation.
|
||||
/// </summary>
|
||||
[DataMember(Name = "comment")]
|
||||
[ReadOnly(true)]
|
||||
public string Comment { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Web.Models.ContentEditing
|
||||
{
|
||||
[DataContract(Name = "relationType", Namespace = "")]
|
||||
public class RelationType
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Name of the RelationType
|
||||
/// </summary>
|
||||
[DataMember(Name = "name", IsRequired = true)]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Alias of the RelationType
|
||||
/// </summary>
|
||||
[DataMember(Name = "alias", IsRequired = true)]
|
||||
public string Alias { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a boolean indicating whether the RelationType is Bidirectional (true) or Parent to Child (false)
|
||||
/// </summary>
|
||||
[DataMember(Name = "isBidirectional", IsRequired = true)]
|
||||
public bool IsBidirectional { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Parents object type id
|
||||
/// </summary>
|
||||
/// <remarks>Corresponds to the NodeObjectType in the umbracoNode table</remarks>
|
||||
[DataMember(Name = "parentObjectType", IsRequired = true)]
|
||||
public Guid ParentObjectType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Childs object type id
|
||||
/// </summary>
|
||||
/// <remarks>Corresponds to the NodeObjectType in the umbracoNode table</remarks>
|
||||
[DataMember(Name = "childObjectType", IsRequired = true)]
|
||||
public Guid ChildObjectType { get; set; }
|
||||
}
|
||||
}
|
||||
63
src/Umbraco.Web/Models/ContentEditing/RelationTypeDisplay.cs
Normal file
63
src/Umbraco.Web/Models/ContentEditing/RelationTypeDisplay.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Web.Models.ContentEditing
|
||||
{
|
||||
[DataContract(Name = "relationType", Namespace = "")]
|
||||
public class RelationTypeDisplay : EntityBasic, INotificationModel
|
||||
{
|
||||
public RelationTypeDisplay()
|
||||
{
|
||||
Notifications = new List<Notification>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a boolean indicating whether the RelationType is Bidirectional (true) or Parent to Child (false)
|
||||
/// </summary>
|
||||
[DataMember(Name = "isBidirectional", IsRequired = true)]
|
||||
public bool IsBidirectional { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Parents object type id
|
||||
/// </summary>
|
||||
/// <remarks>Corresponds to the NodeObjectType in the umbracoNode table</remarks>
|
||||
[DataMember(Name = "parentObjectType", IsRequired = true)]
|
||||
public Guid ParentObjectType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Parent's object type name.
|
||||
/// </summary>
|
||||
[DataMember(Name = "parentObjectTypeName")]
|
||||
[ReadOnly(true)]
|
||||
public string ParentObjectTypeName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Childs object type id
|
||||
/// </summary>
|
||||
/// <remarks>Corresponds to the NodeObjectType in the umbracoNode table</remarks>
|
||||
[DataMember(Name = "childObjectType", IsRequired = true)]
|
||||
public Guid ChildObjectType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Child's object type name.
|
||||
/// </summary>
|
||||
[DataMember(Name = "childObjectTypeName")]
|
||||
[ReadOnly(true)]
|
||||
public string ChildObjectTypeName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the relations associated with this relation type.
|
||||
/// </summary>
|
||||
[DataMember(Name = "relations")]
|
||||
[ReadOnly(true)]
|
||||
public IEnumerable<RelationDisplay> Relations { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This is used to add custom localized messages/strings to the response for the app to use for localized UI purposes.
|
||||
/// </summary>
|
||||
[DataMember(Name = "notifications")]
|
||||
public List<Notification> Notifications { get; private set; }
|
||||
}
|
||||
}
|
||||
27
src/Umbraco.Web/Models/ContentEditing/RelationTypeSave.cs
Normal file
27
src/Umbraco.Web/Models/ContentEditing/RelationTypeSave.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Web.Models.ContentEditing
|
||||
{
|
||||
[DataContract(Name = "relationType", Namespace = "")]
|
||||
public class RelationTypeSave : EntityBasic
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a boolean indicating whether the RelationType is Bidirectional (true) or Parent to Child (false)
|
||||
/// </summary>
|
||||
[DataMember(Name = "isBidirectional", IsRequired = true)]
|
||||
public bool IsBidirectional { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the parent object type ID.
|
||||
/// </summary>
|
||||
[DataMember(Name = "parentObjectType", IsRequired = false)]
|
||||
public Guid ParentObjectType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the child object type ID.
|
||||
/// </summary>
|
||||
[DataMember(Name = "childObjectType", IsRequired = false)]
|
||||
public Guid ChildObjectType { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using AutoMapper;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Relation = Umbraco.Web.Models.ContentEditing.Relation;
|
||||
using RelationType = Umbraco.Web.Models.ContentEditing.RelationType;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
|
||||
namespace Umbraco.Web.Models.Mapping
|
||||
{
|
||||
@@ -9,11 +9,39 @@ namespace Umbraco.Web.Models.Mapping
|
||||
{
|
||||
public RelationMapperProfile()
|
||||
{
|
||||
//FROM IRelationType TO RelationType
|
||||
CreateMap<IRelationType, RelationType>();
|
||||
// FROM IRelationType to RelationTypeDisplay
|
||||
CreateMap<IRelationType, RelationTypeDisplay>()
|
||||
.ForMember(dest => dest.Icon, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.Trashed, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.Alias, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.Path, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.AdditionalData, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.ChildObjectTypeName, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.ParentObjectTypeName, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.Relations, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.ParentId, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.Notifications, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.Udi, opt => opt.MapFrom(content => Udi.Create(Constants.UdiEntityType.RelationType, content.Key)))
|
||||
.AfterMap((src, dest) =>
|
||||
{
|
||||
// Build up the path
|
||||
dest.Path = "-1," + src.Id;
|
||||
|
||||
//FROM IRelation TO Relation
|
||||
CreateMap<IRelation, Relation>();
|
||||
// Set the "friendly" names for the parent and child object types
|
||||
dest.ParentObjectTypeName = ObjectTypes.GetUmbracoObjectType(src.ParentObjectType).GetFriendlyName();
|
||||
dest.ChildObjectTypeName = ObjectTypes.GetUmbracoObjectType(src.ChildObjectType).GetFriendlyName();
|
||||
});
|
||||
|
||||
// FROM IRelation to RelationDisplay
|
||||
CreateMap<IRelation, RelationDisplay>()
|
||||
.ForMember(dest => dest.ParentName, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.ChildName, opt => opt.Ignore());
|
||||
|
||||
// FROM RelationTypeSave to IRelationType
|
||||
CreateMap<RelationTypeSave, IRelationType>()
|
||||
.ForMember(dest => dest.CreateDate, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.UpdateDate, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.DeleteDate, opt => opt.Ignore());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
using System.Collections.Generic;
|
||||
using Examine;
|
||||
using Umbraco.Examine;
|
||||
|
||||
namespace Umbraco.Web.Search
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Used to create the Umbraco indexes
|
||||
/// </summary>
|
||||
public interface IUmbracoIndexesCreator
|
||||
public interface IUmbracoIndexesCreator : IIndexCreator
|
||||
{
|
||||
IEnumerable<IIndex> Create();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Umbraco.Web.Search
|
||||
/// <summary>
|
||||
/// Creates the indexes used by Umbraco
|
||||
/// </summary>
|
||||
public class UmbracoIndexesCreator : IUmbracoIndexesCreator
|
||||
public class UmbracoIndexesCreator : LuceneIndexCreator, IUmbracoIndexesCreator
|
||||
{
|
||||
//TODO: we should inject the different IValueSetValidator so devs can just register them instead of overriding this class?
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace Umbraco.Web.Search
|
||||
/// Creates the Umbraco indexes
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<IIndex> Create()
|
||||
public override IEnumerable<IIndex> Create()
|
||||
{
|
||||
return new []
|
||||
{
|
||||
@@ -61,7 +61,7 @@ namespace Umbraco.Web.Search
|
||||
Constants.UmbracoIndexes.InternalIndexName,
|
||||
//fixme - how to deal with languages like in UmbracoContentIndexer.CreateFieldValueTypes
|
||||
UmbracoExamineIndex.UmbracoIndexFieldDefinitions,
|
||||
GetFileSystemLuceneDirectory(Constants.UmbracoIndexes.InternalIndexPath),
|
||||
CreateFileSystemLuceneDirectory(Constants.UmbracoIndexes.InternalIndexPath),
|
||||
new CultureInvariantWhitespaceAnalyzer(),
|
||||
ProfilingLogger,
|
||||
LanguageService,
|
||||
@@ -75,7 +75,7 @@ namespace Umbraco.Web.Search
|
||||
Constants.UmbracoIndexes.ExternalIndexName,
|
||||
//fixme - how to deal with languages like in UmbracoContentIndexer.CreateFieldValueTypes
|
||||
UmbracoExamineIndex.UmbracoIndexFieldDefinitions,
|
||||
GetFileSystemLuceneDirectory(Constants.UmbracoIndexes.ExternalIndexPath),
|
||||
CreateFileSystemLuceneDirectory(Constants.UmbracoIndexes.ExternalIndexPath),
|
||||
new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30),
|
||||
ProfilingLogger,
|
||||
LanguageService,
|
||||
@@ -89,27 +89,13 @@ namespace Umbraco.Web.Search
|
||||
Constants.UmbracoIndexes.MembersIndexName,
|
||||
//fixme - how to deal with languages like in UmbracoContentIndexer.CreateFieldValueTypes
|
||||
UmbracoExamineIndex.UmbracoIndexFieldDefinitions,
|
||||
GetFileSystemLuceneDirectory(Constants.UmbracoIndexes.MembersIndexPath),
|
||||
CreateFileSystemLuceneDirectory(Constants.UmbracoIndexes.MembersIndexPath),
|
||||
new CultureInvariantWhitespaceAnalyzer(),
|
||||
ProfilingLogger,
|
||||
GetMemberValueSetValidator());
|
||||
return index;
|
||||
}
|
||||
|
||||
public virtual Lucene.Net.Store.Directory GetFileSystemLuceneDirectory(string name)
|
||||
{
|
||||
var dirInfo = new DirectoryInfo(Path.Combine(IOHelper.MapPath(SystemDirectories.Data), "TEMP", "ExamineIndexes", name));
|
||||
if (!dirInfo.Exists)
|
||||
System.IO.Directory.CreateDirectory(dirInfo.FullName);
|
||||
|
||||
var luceneDir = new SimpleFSDirectory(dirInfo);
|
||||
//we want to tell examine to use a different fs lock instead of the default NativeFSFileLock which could cause problems if the appdomain
|
||||
//terminates and in some rare cases would only allow unlocking of the file if IIS is forcefully terminated. Instead we'll rely on the simplefslock
|
||||
//which simply checks the existence of the lock file
|
||||
luceneDir.SetLockFactory(new NoPrefixSimpleFsLockFactory(dirInfo));
|
||||
return luceneDir;
|
||||
}
|
||||
|
||||
|
||||
public virtual IContentValueSetValidator GetContentValueSetValidator()
|
||||
{
|
||||
return new ContentValueSetValidator(false, true, PublicAccessService);
|
||||
|
||||
@@ -78,10 +78,20 @@ namespace Umbraco.Web.Trees
|
||||
}
|
||||
}
|
||||
|
||||
var multiTree = TreeRootNode.CreateMultiTreeRoot(collection);
|
||||
multiTree.Name = Services.TextService.Localize("sections/" + application);
|
||||
if(collection.Count > 0)
|
||||
{
|
||||
var multiTree = TreeRootNode.CreateMultiTreeRoot(collection);
|
||||
multiTree.Name = Services.TextService.Localize("sections/" + application);
|
||||
|
||||
return multiTree;
|
||||
return multiTree;
|
||||
}
|
||||
|
||||
//Otherwise its a application/section with no trees (aka a full screen app)
|
||||
//For example we do not have a Forms tree definied in C# & can not attribute with [Tree(isSingleNodeTree:true0]
|
||||
var rootId = Constants.System.Root.ToString(CultureInfo.InvariantCulture);
|
||||
var section = Services.TextService.Localize("sections/" + application);
|
||||
|
||||
return TreeRootNode.CreateSingleTreeRoot(rootId, null, null, section, TreeNodeCollection.Empty, true);
|
||||
}
|
||||
|
||||
var rootNodeGroups = new List<TreeRootNode>();
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
using System.Net.Http.Formatting;
|
||||
using Umbraco.Web.Models.Trees;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
using Umbraco.Core;
|
||||
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Entities;
|
||||
using Umbraco.Web.Actions;
|
||||
|
||||
namespace Umbraco.Web.Trees
|
||||
@@ -25,8 +21,8 @@ namespace Umbraco.Web.Trees
|
||||
if (id == Constants.System.Root.ToInvariantString())
|
||||
{
|
||||
//Create the normal create action
|
||||
var addMenuItem = menu.Items.Add<ActionNew>(Services.TextService, opensDialog: true);
|
||||
addMenuItem.LaunchDialogUrl("developer/RelationTypes/NewRelationType.aspx", "Create New RelationType");
|
||||
menu.Items.Add<ActionNew>(Services.TextService.Localize("actions", ActionNew.ActionAlias));
|
||||
|
||||
//refresh action
|
||||
menu.Items.Add(new RefreshNode(Services.TextService, true));
|
||||
|
||||
@@ -36,17 +32,7 @@ namespace Umbraco.Web.Trees
|
||||
var relationType = Services.RelationService.GetRelationTypeById(int.Parse(id));
|
||||
if (relationType == null) return new MenuItemCollection();
|
||||
|
||||
//add delete option for all macros
|
||||
menu.Items.Add<ActionDelete>(Services.TextService, opensDialog: true)
|
||||
//Since we haven't implemented anything for relationtypes in angular, this needs to be converted to
|
||||
//use the legacy format
|
||||
.ConvertLegacyMenuItem(new EntitySlim
|
||||
{
|
||||
Id = relationType.Id,
|
||||
Level = 1,
|
||||
ParentId = -1,
|
||||
Name = relationType.Name
|
||||
}, "relationTypes", queryStrings.GetValue<string>("application"));
|
||||
menu.Items.Add<ActionDelete>(Services.TextService.Localize("actions", ActionDelete.ActionAlias));
|
||||
|
||||
return menu;
|
||||
}
|
||||
@@ -57,18 +43,9 @@ namespace Umbraco.Web.Trees
|
||||
|
||||
if (id == Constants.System.Root.ToInvariantString())
|
||||
{
|
||||
nodes.AddRange(Services.RelationService
|
||||
.GetAllRelationTypes().Select(rt => CreateTreeNode(
|
||||
rt.Id.ToString(),
|
||||
id,
|
||||
queryStrings,
|
||||
rt.Name,
|
||||
"icon-trafic",
|
||||
false,
|
||||
//TODO: Rebuild the macro editor in angular, then we dont need to have this at all (which is just a path to the legacy editor)
|
||||
"/" + queryStrings.GetValue<string>("application") + "/framed/" +
|
||||
Uri.EscapeDataString("/umbraco/developer/RelationTypes/EditRelationType.aspx?id=" + rt.Id)
|
||||
)));
|
||||
nodes.AddRange(Services.RelationService.GetAllRelationTypes()
|
||||
.Select(rt => CreateTreeNode(rt.Id.ToString(), id, queryStrings, rt.Name,
|
||||
"icon-trafic", false)));
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
@@ -112,6 +112,7 @@
|
||||
<Compile Include="Components\BackOfficeUserAuditEventsComponent.cs" />
|
||||
<Compile Include="ContentApps\ListViewContentAppFactory.cs" />
|
||||
<Compile Include="Editors\BackOfficePreviewModel.cs" />
|
||||
<Compile Include="Editors\RelationTypeController.cs" />
|
||||
<Compile Include="Logging\WebProfiler.cs" />
|
||||
<Compile Include="Logging\WebProfilerComponent.cs" />
|
||||
<Compile Include="Logging\WebProfilerProvider.cs" />
|
||||
@@ -151,6 +152,10 @@
|
||||
<Compile Include="Media\TypeDetector\SvgDetector.cs" />
|
||||
<Compile Include="Media\TypeDetector\TIFFDetector.cs" />
|
||||
<Compile Include="Media\UploadAutoFillProperties.cs" />
|
||||
<Compile Include="Models\ContentEditing\ObjectType.cs" />
|
||||
<Compile Include="Models\ContentEditing\RelationDisplay.cs" />
|
||||
<Compile Include="Models\ContentEditing\RelationTypeDisplay.cs" />
|
||||
<Compile Include="Models\ContentEditing\RelationTypeSave.cs" />
|
||||
<Compile Include="Models\ContentEditing\RollbackVersion.cs" />
|
||||
<Compile Include="Models\ContentEditing\SearchResult.cs" />
|
||||
<Compile Include="Models\ContentEditing\SearchResults.cs" />
|
||||
@@ -627,9 +632,7 @@
|
||||
<Compile Include="UI\JavaScript\UmbracoClientDependencyLoader.cs" />
|
||||
<Compile Include="UmbracoDefaultOwinStartup.cs" />
|
||||
<Compile Include="IUmbracoContextAccessor.cs" />
|
||||
<Compile Include="Models\ContentEditing\Relation.cs" />
|
||||
<Compile Include="HtmlStringUtilities.cs" />
|
||||
<Compile Include="Models\ContentEditing\RelationType.cs" />
|
||||
<Compile Include="ITagQuery.cs" />
|
||||
<Compile Include="IUmbracoComponentRenderer.cs" />
|
||||
<Compile Include="Models\Mapping\RelationMapperProfile.cs" />
|
||||
@@ -1239,13 +1242,6 @@
|
||||
<Compile Include="umbraco.presentation\umbraco\dashboard\FeedProxy.aspx.designer.cs">
|
||||
<DependentUpon>FeedProxy.aspx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="umbraco.presentation\umbraco\developer\RelationTypes\NewRelationType.aspx.cs">
|
||||
<DependentUpon>NewRelationType.aspx</DependentUpon>
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
</Compile>
|
||||
<Compile Include="umbraco.presentation\umbraco\developer\RelationTypes\NewRelationType.aspx.designer.cs">
|
||||
<DependentUpon>NewRelationType.aspx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="umbraco.presentation\umbraco\dialogs\insertMasterpageContent.aspx.cs">
|
||||
<DependentUpon>insertMasterpageContent.aspx</DependentUpon>
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
@@ -1317,9 +1313,6 @@
|
||||
<EmbeddedResource Include="UI\JavaScript\PreviewInitialize.js" />
|
||||
<!--<Content Include="umbraco.presentation\umbraco\users\PermissionEditor.aspx" />-->
|
||||
<Content Include="PublishedCache\NuCache\notes.txt" />
|
||||
<Content Include="umbraco.presentation\umbraco\developer\RelationTypes\NewRelationType.aspx">
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
</Content>
|
||||
<Content Include="umbraco.presentation\umbraco\dashboard\FeedProxy.aspx" />
|
||||
<Content Include="umbraco.presentation\umbraco\dialogs\insertMasterpageContent.aspx">
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
|
||||
@@ -19,16 +19,17 @@ namespace Umbraco.Web.WebApi.Filters
|
||||
var user = UmbracoContext.Current.Security.CurrentUser;
|
||||
if (user == null) return;
|
||||
|
||||
var objectContent = actionExecutedContext.Response.Content as ObjectContent;
|
||||
if (objectContent != null)
|
||||
if (actionExecutedContext.Response.Content is ObjectContent objectContent)
|
||||
{
|
||||
var model = objectContent.Value;
|
||||
|
||||
if (model != null)
|
||||
{
|
||||
EditorModelEventManager.EmitEvent(actionExecutedContext, new EditorModelEventArgs(
|
||||
(dynamic)model,
|
||||
UmbracoContext.Current));
|
||||
var args = new EditorModelEventArgs(
|
||||
model,
|
||||
UmbracoContext.Current);
|
||||
EditorModelEventManager.EmitEvent(actionExecutedContext, args);
|
||||
objectContent.Value = args.Model;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="NewRelationType.aspx.cs" Inherits="umbraco.cms.presentation.developer.RelationTypes.NewRelationType" MasterPageFile="../../masterpages/umbracoPage.Master"%>
|
||||
<%@ Register TagPrefix="umb" Namespace="Umbraco.Web._Legacy.Controls" %>
|
||||
|
||||
|
||||
<asp:Content ID="bodyContent" ContentPlaceHolderID="body" runat="server">
|
||||
|
||||
|
||||
<umb:Pane ID="nameAliasPane" runat="server" Text="">
|
||||
|
||||
<umb:PropertyPanel runat="server" ID="nameProperyPanel" Text="Name">
|
||||
<asp:TextBox ID="descriptionTextBox" runat="server" Columns="40" AutoCompleteType="Disabled" style="width:200px;" />
|
||||
<asp:RequiredFieldValidator ID="descriptionRequiredFieldValidator" runat="server" ControlToValidate="descriptionTextBox" ValidationGroup="NewRelationType" ErrorMessage="Name Required" Display="Dynamic" />
|
||||
</umb:PropertyPanel>
|
||||
|
||||
<umb:PropertyPanel runat="server" id="aliasPropertyPanel" Text="Alias">
|
||||
<asp:TextBox ID="aliasTextBox" runat="server" Columns="40" AutoCompleteType="Disabled" style="width:200px;" />
|
||||
<asp:RequiredFieldValidator ID="aliasRequiredFieldValidator" runat="server" ControlToValidate="aliasTextBox" ValidationGroup="NewRelationType" ErrorMessage="Alias Required" Display="Dynamic" />
|
||||
<asp:CustomValidator ID="aliasCustomValidator" runat="server" ControlToValidate="aliasTextBox" ValidationGroup="NewRelationType" onservervalidate="AliasCustomValidator_ServerValidate" ErrorMessage="Duplicate Alias" Display="Dynamic" />
|
||||
</umb:PropertyPanel>
|
||||
|
||||
</umb:Pane>
|
||||
<umb:Pane ID="directionPane" runat="server" Text="">
|
||||
|
||||
<umb:PropertyPanel runat="server" id="PropertyPanel1" Text="Direction">
|
||||
<asp:RadioButtonList ID="dualRadioButtonList" runat="server" RepeatDirection="Horizontal">
|
||||
<asp:ListItem Enabled="true" Selected="True" Text="Parent to Child" Value="0"/>
|
||||
<asp:ListItem Enabled="true" Selected="False" Text="Bidirectional" Value="1"/>
|
||||
</asp:RadioButtonList>
|
||||
</umb:PropertyPanel>
|
||||
<% ///*<asp:RequiredFieldValidator ID="dualRequiredFieldValidator" runat="server" ControlToValidate="dualRadioButtonList" ValidationGroup="NewRelationType" ErrorMessage="Direction Required" Display="Dynamic" /> */ %>
|
||||
|
||||
|
||||
</umb:Pane>
|
||||
<umb:Pane ID="objectTypePane" runat="server" Text="">
|
||||
|
||||
<umb:PropertyPanel runat="server" id="PropertyPanel2" Text="Parent">
|
||||
<asp:DropDownList ID="parentDropDownList" runat="server" />
|
||||
</umb:PropertyPanel>
|
||||
|
||||
<umb:PropertyPanel runat="server" id="PropertyPanel3" Text="Child">
|
||||
<asp:DropDownList ID="childDropDownList" runat="server" />
|
||||
</umb:PropertyPanel>
|
||||
|
||||
</umb:Pane>
|
||||
|
||||
<div style="margin-top:15px">
|
||||
<asp:Button ID="addButton" runat="server" Text="Create" onclick="AddButton_Click" CausesValidation="true" ValidationGroup="NewRelationType" />
|
||||
<em>or</em>
|
||||
<a onclick="top.UmbClientMgr.closeModalWindow()" style="color: blue;" href="#">Cancel</a>
|
||||
</div>
|
||||
|
||||
|
||||
</asp:Content>
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
using System;
|
||||
using System.Web.UI.WebControls;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Web.UI.Pages;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace umbraco.cms.presentation.developer.RelationTypes
|
||||
{
|
||||
/// <summary>
|
||||
/// Add a new Relation Type
|
||||
/// </summary>
|
||||
[WebformsPageTreeAuthorize(Constants.Trees.RelationTypes)]
|
||||
public partial class NewRelationType : UmbracoEnsuredPage
|
||||
{
|
||||
/// <summary>
|
||||
/// On Load event
|
||||
/// </summary>
|
||||
/// <param name="sender">this aspx page</param>
|
||||
/// <param name="e">EventArgs (expect empty)</param>
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
{
|
||||
if (!this.Page.IsPostBack)
|
||||
{
|
||||
this.Form.DefaultFocus = this.descriptionTextBox.ClientID;
|
||||
}
|
||||
|
||||
this.AppendUmbracoObjectTypes(this.parentDropDownList);
|
||||
this.AppendUmbracoObjectTypes(this.childDropDownList);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Server side validation to ensure there are no existing relationshipTypes with the alias of
|
||||
/// the relation type being added
|
||||
/// </summary>
|
||||
/// <param name="source">the aliasCustomValidator control</param>
|
||||
/// <param name="args">to set validation respose</param>
|
||||
protected void AliasCustomValidator_ServerValidate(object source, ServerValidateEventArgs args)
|
||||
{
|
||||
var relationService = Services.RelationService;
|
||||
args.IsValid = relationService.GetRelationTypeByAlias(this.aliasTextBox.Text.Trim()) == null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a new relation type into the database, and redirects to it's editing page.
|
||||
/// </summary>
|
||||
/// <param name="sender">expects the addButton control</param>
|
||||
/// <param name="e">expects EventArgs for addButton</param>
|
||||
protected void AddButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (Page.IsValid)
|
||||
{
|
||||
var newRelationTypeAlias = this.aliasTextBox.Text.Trim();
|
||||
|
||||
var relationService = Services.RelationService;
|
||||
var relationType = new RelationType(new Guid(this.childDropDownList.SelectedValue),
|
||||
new Guid(this.parentDropDownList.SelectedValue), newRelationTypeAlias, this.descriptionTextBox.Text)
|
||||
{
|
||||
IsBidirectional = this.dualRadioButtonList.SelectedValue == "1"
|
||||
};
|
||||
|
||||
relationService.Save(relationType);
|
||||
|
||||
var newRelationTypeId = relationService.GetRelationTypeByAlias(newRelationTypeAlias).Id;
|
||||
|
||||
ClientTools.ChangeContentFrameUrl("developer/RelationTypes/EditRelationType.aspx?id=" + newRelationTypeId).CloseModalWindow().ChildNodeCreated();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the Umbraco Object types to a drop down list
|
||||
/// </summary>
|
||||
/// <param name="dropDownList">control for which to add the Umbraco object types</param>
|
||||
private void AppendUmbracoObjectTypes(ListControl dropDownList)
|
||||
{
|
||||
dropDownList.Items.Add(new ListItem(UmbracoObjectTypes.Document.GetFriendlyName(), Constants.ObjectTypes.Strings.Document));
|
||||
dropDownList.Items.Add(new ListItem(UmbracoObjectTypes.Media.GetFriendlyName(), Constants.ObjectTypes.Strings.Media));
|
||||
dropDownList.Items.Add(new ListItem(UmbracoObjectTypes.Member.GetFriendlyName(), Constants.ObjectTypes.Strings.Member));
|
||||
dropDownList.Items.Add(new ListItem(UmbracoObjectTypes.MediaType.GetFriendlyName(), Constants.ObjectTypes.Strings.MediaType));
|
||||
dropDownList.Items.Add(new ListItem(UmbracoObjectTypes.DocumentType.GetFriendlyName(), Constants.ObjectTypes.Strings.DocumentType));
|
||||
dropDownList.Items.Add(new ListItem(UmbracoObjectTypes.MemberType.GetFriendlyName(), Constants.ObjectTypes.Strings.MemberType));
|
||||
dropDownList.Items.Add(new ListItem(UmbracoObjectTypes.DataType.GetFriendlyName(), Constants.ObjectTypes.Strings.DataType));
|
||||
dropDownList.Items.Add(new ListItem(UmbracoObjectTypes.MemberGroup.GetFriendlyName(), Constants.ObjectTypes.Strings.MemberGroup));
|
||||
dropDownList.Items.Add(new ListItem(UmbracoObjectTypes.Stylesheet.GetFriendlyName(), Constants.ObjectTypes.Strings.Stylesheet));
|
||||
dropDownList.Items.Add(new ListItem(UmbracoObjectTypes.Template.GetFriendlyName(), Constants.ObjectTypes.Strings.Template));
|
||||
dropDownList.Items.Add(new ListItem(UmbracoObjectTypes.ROOT.GetFriendlyName(), Constants.ObjectTypes.Strings.SystemRoot));
|
||||
dropDownList.Items.Add(new ListItem(UmbracoObjectTypes.RecycleBin.GetFriendlyName(), Constants.ObjectTypes.Strings.ContentRecycleBin));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,168 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace umbraco.cms.presentation.developer.RelationTypes {
|
||||
|
||||
|
||||
public partial class NewRelationType {
|
||||
|
||||
/// <summary>
|
||||
/// nameAliasPane control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::Umbraco.Web._Legacy.Controls.Pane nameAliasPane;
|
||||
|
||||
/// <summary>
|
||||
/// nameProperyPanel control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::Umbraco.Web._Legacy.Controls.PropertyPanel nameProperyPanel;
|
||||
|
||||
/// <summary>
|
||||
/// descriptionTextBox control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.TextBox descriptionTextBox;
|
||||
|
||||
/// <summary>
|
||||
/// descriptionRequiredFieldValidator control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.RequiredFieldValidator descriptionRequiredFieldValidator;
|
||||
|
||||
/// <summary>
|
||||
/// aliasPropertyPanel control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::Umbraco.Web._Legacy.Controls.PropertyPanel aliasPropertyPanel;
|
||||
|
||||
/// <summary>
|
||||
/// aliasTextBox control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.TextBox aliasTextBox;
|
||||
|
||||
/// <summary>
|
||||
/// aliasRequiredFieldValidator control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.RequiredFieldValidator aliasRequiredFieldValidator;
|
||||
|
||||
/// <summary>
|
||||
/// aliasCustomValidator control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.CustomValidator aliasCustomValidator;
|
||||
|
||||
/// <summary>
|
||||
/// directionPane control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::Umbraco.Web._Legacy.Controls.Pane directionPane;
|
||||
|
||||
/// <summary>
|
||||
/// PropertyPanel1 control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::Umbraco.Web._Legacy.Controls.PropertyPanel PropertyPanel1;
|
||||
|
||||
/// <summary>
|
||||
/// dualRadioButtonList control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.RadioButtonList dualRadioButtonList;
|
||||
|
||||
/// <summary>
|
||||
/// objectTypePane control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::Umbraco.Web._Legacy.Controls.Pane objectTypePane;
|
||||
|
||||
/// <summary>
|
||||
/// PropertyPanel2 control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::Umbraco.Web._Legacy.Controls.PropertyPanel PropertyPanel2;
|
||||
|
||||
/// <summary>
|
||||
/// parentDropDownList control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.DropDownList parentDropDownList;
|
||||
|
||||
/// <summary>
|
||||
/// PropertyPanel3 control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::Umbraco.Web._Legacy.Controls.PropertyPanel PropertyPanel3;
|
||||
|
||||
/// <summary>
|
||||
/// childDropDownList control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.DropDownList childDropDownList;
|
||||
|
||||
/// <summary>
|
||||
/// addButton control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.Button addButton;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user