Compare commits
108 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a4c1a59e23 | |||
| e164be1823 | |||
| f32451fffa | |||
| a541dbd038 | |||
| 69e0bb70e5 | |||
| c22a2623c2 | |||
| c229cc9953 | |||
| 7d155ee176 | |||
| 93659e5a22 | |||
| 46bbf24edf | |||
| da1057c681 | |||
| 81881a5734 | |||
| 25678a812c | |||
| ec2edce74c | |||
| 4756551518 | |||
| e053b42950 | |||
| ff21951ea1 | |||
| 18935b4a69 | |||
| cd93e17494 | |||
| 3a2190b232 | |||
| 46b0396652 | |||
| 0c3fcce58b | |||
| cef7a36bd4 | |||
| 03d511ca80 | |||
| 123546b11c | |||
| 4aa6b83d82 | |||
| 6f3a414c4d | |||
| 4443d628dc | |||
| 0f9a44c539 | |||
| dd47218bd3 | |||
| 5e3e37af31 | |||
| dbf1bffe34 | |||
| cbf87264ac | |||
| 353c3da22a | |||
| 9d15e0c696 | |||
| 7dc7b8f938 | |||
| f8302b0926 | |||
| 1cb3f4e266 | |||
| d2b7a9a92b | |||
| 245f4ed972 | |||
| 19ef383a71 | |||
| af2287d2fc | |||
| e4c206211f | |||
| 57a199d235 | |||
| 2a98005ae7 | |||
| 69a7256538 | |||
| 38dc405183 | |||
| d6874e7cd8 | |||
| c1e732e3de | |||
| 02ffe4db4a | |||
| c79be2f6db | |||
| f0c15ade5d | |||
| 9f8acedf6f | |||
| aba3bdd2c4 | |||
| de491f9687 | |||
| 2becf8a1ba | |||
| 68a5a9893d | |||
| 3ed08c447c | |||
| 9a2e14d8f6 | |||
| d557ec1edb | |||
| 4fb7cdc5e5 | |||
| 5fa225b460 | |||
| b1f8c6a732 | |||
| 7d8a6e28fa | |||
| 6a9c56df58 | |||
| fa265d3019 | |||
| 078f4a506e | |||
| 42661c27f4 | |||
| b398e0e677 | |||
| a54170b915 | |||
| 757ba890f5 | |||
| a127dac03a | |||
| 62e481d49c | |||
| 77ec2d7a9c | |||
| 0d55f0ed86 | |||
| 6a7ac205bc | |||
| 1cb2139137 | |||
| b14645f13f | |||
| b8741726bc | |||
| d392c4f705 | |||
| 119b0c7680 | |||
| b9179f4140 | |||
| d46d64c52b | |||
| 45318cf061 | |||
| b9abf0d6a3 | |||
| e00229984c | |||
| 155f212062 | |||
| 86a8112fbd | |||
| 810fa95c65 | |||
| 9bcd9d67ae | |||
| bae1ee508b | |||
| 20b6a78af1 | |||
| 014b407abb | |||
| 5aa16a6636 | |||
| 7206bba46a | |||
| af9db94fb6 | |||
| d2014be81b | |||
| 01b8b3b508 | |||
| 734125fa25 | |||
| 76678f538d | |||
| 7fe23fdf4c | |||
| c956c12cdf | |||
| 8706feb882 | |||
| c8364986a2 | |||
| 4d24150bdc | |||
| a16c4b4da9 | |||
| 75a312c309 | |||
| 7bc9584940 |
+6
-2
@@ -85,6 +85,7 @@ module.exports = function(grunt) {
|
||||
'app/controllers/controller_versioned.js',
|
||||
'app/controllers/config.controller.js',
|
||||
'app/controllers/config.dialog.controller.js',
|
||||
'app/controllers/config.global.controller.js',
|
||||
'app/directives/archetypeproperty.js',
|
||||
'app/directives/archetypesubmitwatcher.js',
|
||||
'app/directives/archetypecustomview.js',
|
||||
@@ -95,7 +96,8 @@ module.exports = function(grunt) {
|
||||
'app/resources/archetypePropertyEditorResource.js',
|
||||
'app/services/archetypeService.js',
|
||||
'app/services/archetypeLabelService.js',
|
||||
'app/services/archetypeCacheService.js'
|
||||
'app/services/archetypeCacheService.js',
|
||||
'app/services/archetypeGlobalConfigService.js'
|
||||
],
|
||||
dest: '<%= basePath %>/js/archetype.js'
|
||||
}
|
||||
@@ -269,7 +271,8 @@ module.exports = function(grunt) {
|
||||
'app/controllers/*.js',
|
||||
'!app/controllers/controller.js',
|
||||
'!app/controllers/config.controller.js',
|
||||
'!app/controllers/config.dialog.controller.js'
|
||||
'!app/controllers/config.dialog.controller.js',
|
||||
'!app/controllers/config.global.controller.js'
|
||||
],
|
||||
less: [
|
||||
'app/less/*.less',
|
||||
@@ -319,4 +322,5 @@ module.exports = function(grunt) {
|
||||
grunt.registerTask('nuget', ['copy:nuget', 'template:nuspec', 'template:nuspec_binaries', 'template:nuspec_courier', 'nugetpack']);
|
||||
grunt.registerTask('umbraco', ['copy:umbraco', 'umbracoPackage']);
|
||||
grunt.registerTask('package', ['clean:tmp', 'default', 'nuget', 'copy:umbraco', 'umbracoPackage', 'clean:tmp']);
|
||||
grunt.registerTask('assets', ['clean', 'string-replace', 'less', 'concat', 'assemblyinfo', 'copy:assets', 'copy:html', 'copy:config', 'clean:html', 'clean:js', 'clean:less']);
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
# Information Collection Disclosure
|
||||
|
||||
As of version v1.16.0, we are checking your installed version of Archetype against the current version. In this process we collect the current version of Archetype along with the current version of Umbraco that you are running. We use these values to help determine a response message to you. You may opt-out of this process by 'un-checking' the option in any of the Archetypes you have configured in the `Developer->Data Types` section of Umbraco.
|
||||
|
||||

|
||||
|
||||
This is a global setting that will set an `AppSetting` and update a file located at `~/config/archetype.config.js`. If you manually change the setting it will require an app reload to refresh to runtime values. If somehow this file becomes corrupt, a new file will be generated and you will again have to opt out.
|
||||
|
||||
We identify your install only by a randomly generated GUID. We WILL NOT store your IP address or hostname during the update check.
|
||||
|
||||
Part of the reason we collect this information is to also ascertain how many active installs exist. If this number is sufficiently high, we can plan accordingly and attempt to keep this project going.
|
||||
|
||||
We would ask that you reach out to the Archetype team via creating an issue on this site if you have any questions or concerns. We truly want Archetype to be a win-win for all involved.
|
||||
@@ -1,26 +1,37 @@
|
||||
Archetype
|
||||
=========
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
## Installation
|
||||
Install the selected <a href='https://github.com/imulus/Archetype/releases'>release</a> through the Umbraco package installer or via <a href='http://www.nuget.org/packages/Archetype/'>NuGet</a>.
|
||||
Install the selected <a href='https://github.com/kgiszewski/Archetype/releases'>release</a> through the Umbraco package installer or via <a href='http://www.nuget.org/packages/Archetype/'>NuGet</a>.
|
||||
|
||||
## Official Docs ##
|
||||
https://github.com/kgiszewski/ArchetypeManual
|
||||
|
||||
Get up and running in 15 minutes! https://www.youtube.com/watch?v=79LksNwGjLk
|
||||
|
||||
## News and Updates ##
|
||||
Follow us on Twitter https://twitter.com/ArchetypeKit
|
||||
|
||||
## Core Team ##
|
||||
* Kevin Giszewski (founder/project lead) - University of Notre Dame - https://kevin.giszewski.com/
|
||||
* Kevin Giszewski (founder/project lead) - Tonic - https://kevin.giszewski.com/
|
||||
* Tom Fulton (founder) - Tonic - http://hellotonic.com/
|
||||
* Lee Kelleher - Umbrella - http://www.umbrellainc.co.uk/
|
||||
* Matt Brailsford - The Outfield - http://www.theoutfield.co.uk/
|
||||
* Kenn Jacobsen - Vertica - http://kennjacobsen.dk/
|
||||
|
||||
## Sponsor us\Donate!
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KBKWLURGLGU6L)
|
||||
|
||||
This project is funded by the core team members' time only. We don't charge for Archetype but it does take quite a bit of effort to keep it up-to-date with Umbraco core changes. If you're making a few bucks off of Archetype, we wouldn't refuse a donation :)
|
||||
|
||||
[Learn more](Sponsors.md) about sponsorship!
|
||||
|
||||
## Information Collection Disclosure
|
||||
Please read the information disclosure [here](Information%20Collection%20Disclosure.md).
|
||||
|
||||
## Contribute ##
|
||||
|
||||
Want to contribute to Archetype? You'll want to use Grunt (our task runner) to help you integrate with a local copy of Umbraco.
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
# Sponsorship
|
||||
|
||||
Are you a company that depends on Archetype? We would love for you to sponsor us! Here's some suggested ways below!
|
||||
|
||||
## Sponsor a Sprint
|
||||
|
||||
We have a [backlog](https://github.com/kgiszewski/Archetype/issues), it gets worked on when either we have a personal need, we get bored or when we get a sponsorship. If you want to sponsor a sprint, we can give you thanks on social media and if you're really generous, we can put your logo and link on a well placed spot in a version release. [Contact us](https://twitter.com/ArchetypeKit) to get started.
|
||||
|
||||
## Donations
|
||||
|
||||
If you want to quietly support us, you can also send us a donation:
|
||||
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KBKWLURGLGU6L)
|
||||
@@ -1,9 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Web.Http;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core.Models;
|
||||
@@ -11,32 +9,57 @@ using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.Editors;
|
||||
using Archetype.Extensions;
|
||||
using Archetype.Models;
|
||||
|
||||
namespace Archetype.Api
|
||||
{
|
||||
/// <summary>
|
||||
/// Controller that handles datatype related interactions.
|
||||
/// </summary>
|
||||
/// <seealso cref="Umbraco.Web.Editors.UmbracoAuthorizedJsonController" />
|
||||
[PluginController("ArchetypeApi")]
|
||||
public class ArchetypeDataTypeController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
private static DateTime _lastVersionCheck;
|
||||
private const int IntervalInDaysBetweenVersionChecks = 7;
|
||||
|
||||
public IEnumerable<object> GetAllPropertyEditors()
|
||||
{
|
||||
return
|
||||
global::Umbraco.Core.PropertyEditors.PropertyEditorResolver.Current.PropertyEditors
|
||||
.Select(x => new {defaultPreValues = x.DefaultPreValuesForArchetype(), alias = x.Alias, view = x.ValueEditor.View});
|
||||
.Select(x => new { defaultPreValues = x.DefaultPreValuesForArchetype(), alias = x.Alias, view = x.ValueEditor.View });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all datatypes.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public object GetAll()
|
||||
/// <returns>System.Object.</returns>
|
||||
public object GetAll()
|
||||
{
|
||||
var dataTypes = Services.DataTypeService.GetAllDataTypeDefinitions();
|
||||
return dataTypes.Select(t => new { guid = t.Key, name = t.Name });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all details.
|
||||
/// </summary>
|
||||
/// <returns>System.Object.</returns>
|
||||
public object GetAllDetails()
|
||||
{
|
||||
var dataTypes = Services.DataTypeService.GetAllDataTypeDefinitions();
|
||||
|
||||
var list = new List<object>();
|
||||
|
||||
foreach (var dataType in dataTypes)
|
||||
{
|
||||
var dataTypeDisplay = Mapper.Map<IDataTypeDefinition, DataTypeDisplay>(dataType);
|
||||
|
||||
list.Add(new { selectedEditor = dataTypeDisplay.SelectedEditor, preValues = dataTypeDisplay.PreValues, dataTypeGuid = dataType.Key });
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the datatype by GUID.
|
||||
/// </summary>
|
||||
@@ -68,11 +91,14 @@ namespace Archetype.Api
|
||||
public object GetByGuid(Guid guid, string contentTypeAlias, string propertyTypeAlias, string archetypeAlias, int nodeId)
|
||||
{
|
||||
var dataType = Services.DataTypeService.GetDataTypeDefinitionById(guid);
|
||||
|
||||
if (dataType == null)
|
||||
{
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
var dataTypeDisplay = Mapper.Map<IDataTypeDefinition, DataTypeDisplay>(dataType);
|
||||
|
||||
return new { selectedEditor = dataTypeDisplay.SelectedEditor, preValues = dataTypeDisplay.PreValues, contentTypeAlias = contentTypeAlias, propertyTypeAlias = propertyTypeAlias, archetypeAlias = archetypeAlias, nodeId = nodeId };
|
||||
}
|
||||
|
||||
@@ -82,19 +108,64 @@ namespace Archetype.Api
|
||||
/// <returns></returns>
|
||||
public object GetDllVersion()
|
||||
{
|
||||
return new {dllVersion = _version()};
|
||||
return new { dllVersion = ArchetypeHelper.Instance.DllVersion() };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the DLL version from the file.
|
||||
/// Globals the settings.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private string _version()
|
||||
/// <returns>System.Object.</returns>
|
||||
[HttpGet]
|
||||
public object GlobalSettings()
|
||||
{
|
||||
var asm = Assembly.GetExecutingAssembly();
|
||||
var fvi = FileVersionInfo.GetVersionInfo(asm.Location);
|
||||
return new
|
||||
{
|
||||
isCheckingForUpdates = ArchetypeGlobalSettings.Instance.CheckForUpdates
|
||||
};
|
||||
}
|
||||
|
||||
return fvi.FileVersion;
|
||||
/// <summary>
|
||||
/// Sets the check for updates.
|
||||
/// </summary>
|
||||
/// <param name="isChecking">if set to <c>true</c> [is checking].</param>
|
||||
[HttpPost]
|
||||
public void SetCheckForUpdates([FromBody] bool isChecking)
|
||||
{
|
||||
ArchetypeGlobalSettings.Instance.CheckForUpdates = isChecking;
|
||||
ArchetypeGlobalSettings.Instance.Save();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks for updates.
|
||||
/// </summary>
|
||||
/// <returns>System.Object.</returns>
|
||||
[HttpPost]
|
||||
public object CheckForUpdates()
|
||||
{
|
||||
if (!ArchetypeGlobalSettings.Instance.CheckForUpdates || !IsItTimeToCheck())
|
||||
{
|
||||
return new
|
||||
{
|
||||
isUpdateAvailable = false
|
||||
};
|
||||
}
|
||||
|
||||
var updateNotificationModel = ArchetypeHelper.Instance.CheckForUpdates();
|
||||
_lastVersionCheck = DateTime.UtcNow;
|
||||
|
||||
return new
|
||||
{
|
||||
isUpdateAvailable = updateNotificationModel.IsUpdateAvailable,
|
||||
headline = updateNotificationModel.Headline,
|
||||
type = updateNotificationModel.Type,
|
||||
message = updateNotificationModel.Message,
|
||||
url = updateNotificationModel.Url
|
||||
};
|
||||
}
|
||||
|
||||
internal bool IsItTimeToCheck()
|
||||
{
|
||||
return _lastVersionCheck.AddDays(IntervalInDaysBetweenVersionChecks) < DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +129,7 @@
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
@@ -238,6 +239,8 @@
|
||||
<Compile Include="Extensions\ArchetypePropertyModelExtensions.cs" />
|
||||
<Compile Include="Extensions\PropertyEditorExtensions.cs" />
|
||||
<Compile Include="Extensions\StringExtensions.cs" />
|
||||
<Compile Include="Models\ArchetypeConfigFileModel.cs" />
|
||||
<Compile Include="Models\ArchetypeGlobalSettings.cs" />
|
||||
<Compile Include="Models\ArchetypeModel.cs" />
|
||||
<Compile Include="Models\ArchetypePreValue.cs" />
|
||||
<Compile Include="Models\ArchetypePreValueFieldset.cs" />
|
||||
@@ -248,6 +251,7 @@
|
||||
<Compile Include="Models\ArchetypePublishedContent.cs" />
|
||||
<Compile Include="Models\ArchetypePublishedContentSet.cs" />
|
||||
<Compile Include="Models\ArchetypePublishedProperty.cs" />
|
||||
<Compile Include="Models\ArchetypeUpdateNotification.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Properties\VersionInfo.cs" />
|
||||
<Compile Include="PropertyConverters\ArchetypeValueConverter.cs" />
|
||||
|
||||
@@ -12,5 +12,8 @@
|
||||
public const string CacheKey_DataTypeByGuid = "";
|
||||
|
||||
public const string CacheKey_PreValueFromDataTypeId = "Archetype_GetArchetypePreValueFromDataTypeId_";
|
||||
|
||||
public const string UmbracoVersionAlias = "umbracoConfigurationStatus";
|
||||
public const string NotificationUrl = "https://api.gizmo42.com/v1/archetype/check-for-updates";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using Archetype.Models;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using System.Reflection;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
|
||||
/// <summary>
|
||||
/// The Extensions namespace.
|
||||
/// </summary>
|
||||
namespace Archetype.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
@@ -14,20 +23,52 @@ namespace Archetype.Extensions
|
||||
/// </summary>
|
||||
public class ArchetypeHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// The json settings
|
||||
/// </summary>
|
||||
protected JsonSerializerSettings _jsonSettings;
|
||||
/// <summary>
|
||||
/// The application
|
||||
/// </summary>
|
||||
protected ApplicationContext _app;
|
||||
|
||||
private static readonly ArchetypeHelper _instance = new ArchetypeHelper();
|
||||
|
||||
internal static ArchetypeHelper Instance { get { return _instance; } }
|
||||
/// <summary>
|
||||
/// The pad lock
|
||||
/// </summary>
|
||||
private static readonly object _padLock = new object();
|
||||
/// <summary>
|
||||
/// The instance
|
||||
/// </summary>
|
||||
private static ArchetypeHelper _instance = new ArchetypeHelper();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ArchetypeHelper"/> class.
|
||||
/// Gets the instance.
|
||||
/// </summary>
|
||||
internal ArchetypeHelper()
|
||||
/// <value>The instance.</value>
|
||||
internal static ArchetypeHelper Instance {
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
lock (_padLock)
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = new ArchetypeHelper();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ArchetypeHelper" /> class.
|
||||
/// </summary>
|
||||
private ArchetypeHelper()
|
||||
{
|
||||
var dcr = new Newtonsoft.Json.Serialization.DefaultContractResolver();
|
||||
dcr.DefaultMembersSearchFlags |= System.Reflection.BindingFlags.NonPublic;
|
||||
dcr.DefaultMembersSearchFlags |= BindingFlags.NonPublic;
|
||||
|
||||
_jsonSettings = new JsonSerializerSettings { ContractResolver = dcr };
|
||||
_app = ApplicationContext.Current;
|
||||
@@ -36,9 +77,7 @@ namespace Archetype.Extensions
|
||||
/// <summary>
|
||||
/// Gets the json serializer settings.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The json serializer settings.
|
||||
/// </value>
|
||||
/// <value>The json serializer settings.</value>
|
||||
internal JsonSerializerSettings JsonSerializerSettings { get { return _jsonSettings; } }
|
||||
|
||||
/// <summary>
|
||||
@@ -46,7 +85,7 @@ namespace Archetype.Extensions
|
||||
/// </summary>
|
||||
/// <param name="sourceJson">The source JSON.</param>
|
||||
/// <param name="dataTypePreValues">The data type pre values.</param>
|
||||
/// <returns></returns>
|
||||
/// <returns>ArchetypeModel.</returns>
|
||||
internal ArchetypeModel DeserializeJsonToArchetype(string sourceJson, PreValueCollection dataTypePreValues)
|
||||
{
|
||||
try
|
||||
@@ -78,7 +117,7 @@ namespace Archetype.Extensions
|
||||
/// <param name="sourceJson">The source JSON.</param>
|
||||
/// <param name="dataTypeId">The data type identifier.</param>
|
||||
/// <param name="hostContentType">Type of the host content.</param>
|
||||
/// <returns></returns>
|
||||
/// <returns>ArchetypeModel.</returns>
|
||||
internal ArchetypeModel DeserializeJsonToArchetype(string sourceJson, int dataTypeId, PublishedContentType hostContentType = null)
|
||||
{
|
||||
try
|
||||
@@ -108,21 +147,66 @@ namespace Archetype.Extensions
|
||||
/// Determines whether datatypeId has had it's PVC overridden.
|
||||
/// </summary>
|
||||
/// <param name="dataTypeId">The data type identifier.</param>
|
||||
/// <returns></returns>
|
||||
/// <returns><c>true</c> if [is property value converter overridden] [the specified data type identifier]; otherwise, <c>false</c>.</returns>
|
||||
internal bool IsPropertyValueConverterOverridden(int dataTypeId)
|
||||
{
|
||||
var prevalues = GetArchetypePreValueFromDataTypeId(dataTypeId);
|
||||
|
||||
if (prevalues == null)
|
||||
return false;
|
||||
|
||||
return prevalues.OverrideDefaultPropertyValueConverter;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks for updates.
|
||||
/// </summary>
|
||||
/// <returns>ArchetypeUpdateNotification.</returns>
|
||||
internal ArchetypeUpdateNotification CheckForUpdates()
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
var content = new StringContent(JsonConvert.SerializeObject(new
|
||||
{
|
||||
umbracoVersion = ConfigurationManager.AppSettings[Constants.UmbracoVersionAlias],
|
||||
archetypeVersion = DllVersion(),
|
||||
id = ArchetypeGlobalSettings.Instance.Id
|
||||
}), Encoding.UTF8, "application/json");
|
||||
|
||||
client.DefaultRequestHeaders.Add("x-api-key-id", ArchetypeGlobalSettings.Instance.ApiKey.ToString());
|
||||
|
||||
var response = client.PostAsync(new Uri(Constants.NotificationUrl), content).Result;
|
||||
|
||||
if (response.StatusCode == HttpStatusCode.OK)
|
||||
{
|
||||
var responseString = response.Content.ReadAsStringAsync().Result;
|
||||
|
||||
return JsonConvert.DeserializeObject<ArchetypeUpdateNotification>(responseString);
|
||||
}
|
||||
|
||||
return new ArchetypeUpdateNotification
|
||||
{
|
||||
IsUpdateAvailable = false
|
||||
};
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//if anything goes wrong let's make sure we don't break their site
|
||||
return new ArchetypeUpdateNotification
|
||||
{
|
||||
IsUpdateAvailable = false
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the archetype pre value from data type identifier.
|
||||
/// </summary>
|
||||
/// <param name="dataTypeId">The data type identifier.</param>
|
||||
/// <returns></returns>
|
||||
/// <returns>ArchetypePreValue.</returns>
|
||||
private ArchetypePreValue GetArchetypePreValueFromDataTypeId(int dataTypeId)
|
||||
{
|
||||
return _app.ApplicationCache.RuntimeCache.GetCacheItem(
|
||||
@@ -147,7 +231,7 @@ namespace Archetype.Extensions
|
||||
/// Gets the archetype pre value from pre values collection.
|
||||
/// </summary>
|
||||
/// <param name="dataTypePreValues">The data type pre values.</param>
|
||||
/// <returns></returns>
|
||||
/// <returns>ArchetypePreValue.</returns>
|
||||
private ArchetypePreValue GetArchetypePreValueFromPreValuesCollection(PreValueCollection dataTypePreValues)
|
||||
{
|
||||
var preValueAsString = dataTypePreValues.PreValuesAsDictionary.First().Value.Value;
|
||||
@@ -159,7 +243,7 @@ namespace Archetype.Extensions
|
||||
/// Gets the data type by unique identifier.
|
||||
/// </summary>
|
||||
/// <param name="guid">The unique identifier.</param>
|
||||
/// <returns></returns>
|
||||
/// <returns>IDataTypeDefinition.</returns>
|
||||
internal IDataTypeDefinition GetDataTypeByGuid(Guid guid)
|
||||
{
|
||||
return (IDataTypeDefinition)ApplicationContext.Current.ApplicationCache.RuntimeCache.GetCacheItem(
|
||||
@@ -172,6 +256,7 @@ namespace Archetype.Extensions
|
||||
/// </summary>
|
||||
/// <param name="archetype">The Archetype to add the additional metadata to</param>
|
||||
/// <param name="preValue">The configuration of the Archetype</param>
|
||||
/// <param name="hostContentType">Type of the host content.</param>
|
||||
private void RetrieveAdditionalProperties(ref ArchetypeModel archetype, ArchetypePreValue preValue, PublishedContentType hostContentType = null)
|
||||
{
|
||||
foreach (var fieldset in preValue.Fieldsets)
|
||||
@@ -197,7 +282,6 @@ namespace Archetype.Extensions
|
||||
/// <summary>
|
||||
/// Retrieves additional metadata that isn't available on the stored model of an ArchetypePreValue
|
||||
/// </summary>
|
||||
/// <param name="archetype">The Archetype to add the additional metadata to</param>
|
||||
/// <param name="preValue">The configuration of the Archetype</param>
|
||||
private void RetrieveAdditionalProperties(ref ArchetypePreValue preValue)
|
||||
{
|
||||
@@ -209,5 +293,18 @@ namespace Archetype.Extensions
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the DLL version from the file.
|
||||
/// </summary>
|
||||
/// <returns>System.String.</returns>
|
||||
internal string DllVersion()
|
||||
{
|
||||
var asm = Assembly.GetExecutingAssembly();
|
||||
var fvi = FileVersionInfo.GetVersionInfo(asm.Location);
|
||||
|
||||
return fvi.FileVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
|
||||
namespace Archetype.Models
|
||||
{
|
||||
public class ArchetypeConfigFileModel
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public bool CheckForUpdates { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Archetype.Models
|
||||
{
|
||||
public class ArchetypeGlobalSettings
|
||||
{
|
||||
public bool CheckForUpdates { get; set; }
|
||||
public Guid Id { get; set; }
|
||||
|
||||
public Guid ApiKey = _getApiKey();
|
||||
|
||||
private static ArchetypeGlobalSettings _instance;
|
||||
|
||||
private static string _pathToConfig = @"~/Config/Archetype.config.js";
|
||||
|
||||
private static readonly string _mappedPathToConfig = IOHelper.MapPath(_pathToConfig);
|
||||
|
||||
private static object _padLock = new object();
|
||||
|
||||
private ArchetypeGlobalSettings()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static ArchetypeGlobalSettings Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
lock (_padLock)
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = new ArchetypeGlobalSettings();
|
||||
|
||||
_loadSettingsFromConfigFile();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
lock (_padLock)
|
||||
{
|
||||
//write to JSON
|
||||
var configFileModel = new ArchetypeConfigFileModel
|
||||
{
|
||||
Id = _instance.Id,
|
||||
CheckForUpdates = _instance.CheckForUpdates
|
||||
};
|
||||
|
||||
var serializedJson = JsonConvert.SerializeObject(configFileModel, Formatting.Indented);
|
||||
|
||||
File.WriteAllText(_mappedPathToConfig, serializedJson);
|
||||
}
|
||||
}
|
||||
|
||||
private static void _loadSettingsFromConfigFile()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(_mappedPathToConfig))
|
||||
{
|
||||
//load
|
||||
var deserializedConfigFile = JsonConvert.DeserializeObject<ArchetypeConfigFileModel>(File.ReadAllText(_mappedPathToConfig));
|
||||
|
||||
if (deserializedConfigFile != null)
|
||||
{
|
||||
_instance.Id = deserializedConfigFile.Id;
|
||||
_instance.CheckForUpdates = deserializedConfigFile.CheckForUpdates;
|
||||
}
|
||||
else
|
||||
{
|
||||
_createNewConfigFile("Config file model was null!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_createNewConfigFile("Config file was missing!");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error<ArchetypeGlobalSettings>(ex.Message, ex);
|
||||
|
||||
_createNewConfigFile("Exception!");
|
||||
}
|
||||
}
|
||||
|
||||
private static void _createNewConfigFile(string reason)
|
||||
{
|
||||
//write a new file with defaults
|
||||
LogHelper.Info<ArchetypeGlobalSettings>(string.Format("Generating a new config file reason: {0}", reason));
|
||||
|
||||
_instance.Id = Guid.NewGuid();
|
||||
_instance.CheckForUpdates = true;
|
||||
_instance.Save();
|
||||
}
|
||||
|
||||
private static Guid _getApiKey()
|
||||
{
|
||||
//this is just obfuscation and an attempt to keep out most but not the determined hacker
|
||||
var array = new []
|
||||
{
|
||||
"RTA4MUZDRjA=",
|
||||
"NzkzQS1BRDIw",
|
||||
"OTI3QjFDNjkwQTYy",
|
||||
"MjI0OQ=="
|
||||
};
|
||||
|
||||
return new Guid(string.Format("{0}-{1}-{3}-{2}",
|
||||
_decodeBase64(array[0]),
|
||||
_decodeBase64(array[1]),
|
||||
_decodeBase64(array[2]),
|
||||
_decodeBase64(array[3])
|
||||
));
|
||||
}
|
||||
|
||||
private static string _decodeBase64(string input)
|
||||
{
|
||||
return Encoding.UTF8.GetString(Convert.FromBase64String(input));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,9 @@ namespace Archetype.Models
|
||||
[JsonProperty("hidePropertyLabel")]
|
||||
public bool HidePropertyLabel { get; set; }
|
||||
|
||||
[JsonProperty("minFieldsets", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public int MinFieldsets { get; set; }
|
||||
|
||||
[JsonProperty("maxFieldsets", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public int MaxFieldsets { get; set; }
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using Archetype.Extensions;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
@@ -24,14 +25,22 @@ namespace Archetype.Models
|
||||
_property = property;
|
||||
_rawValue = property.Value;
|
||||
|
||||
_propertyType = property.CreateDummyPropertyType();
|
||||
// #418 - need to wrap this in a try/catch to prevent orphaned properties from breaking everything
|
||||
try
|
||||
{
|
||||
_propertyType = property.CreateDummyPropertyType();
|
||||
|
||||
if (_propertyType != null)
|
||||
{
|
||||
_sourceValue = new Lazy<object>(() => _propertyType.ConvertDataToSource(_rawValue, preview));
|
||||
_objectValue = new Lazy<object>(() => _propertyType.ConvertSourceToObject(_sourceValue.Value, preview));
|
||||
_xpathValue = new Lazy<object>(() => _propertyType.ConvertSourceToXPath(_sourceValue.Value, preview));
|
||||
}
|
||||
if (_propertyType != null)
|
||||
{
|
||||
_sourceValue = new Lazy<object>(() => _propertyType.ConvertDataToSource(_rawValue, preview));
|
||||
_objectValue = new Lazy<object>(() => _propertyType.ConvertSourceToObject(_sourceValue.Value, preview));
|
||||
_xpathValue = new Lazy<object>(() => _propertyType.ConvertSourceToXPath(_sourceValue.Value, preview));
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
LogHelper.Warn<ArchetypePublishedProperty>(string.Format("Could not create an IPublishedProperty for property: {0} - the error was: {1}", property.Alias, ex.Message));
|
||||
}
|
||||
}
|
||||
|
||||
internal ArchetypePropertyModel ArchetypeProperty
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace Archetype.Models
|
||||
{
|
||||
public class ArchetypeUpdateNotification
|
||||
{
|
||||
public bool IsUpdateAvailable { get; set; }
|
||||
public string Headline { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string Message { get; set; }
|
||||
public string Url { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ using System.Runtime.InteropServices;
|
||||
[assembly: AssemblyTitle("Archetype")]
|
||||
[assembly: AssemblyDescription("Archetype's supporting code library for Umbraco")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Imulus")]
|
||||
[assembly: AssemblyCompany("Kevin Giszewski LLC")]
|
||||
[assembly: AssemblyProduct("Archetype")]
|
||||
[assembly: AssemblyCopyright("MIT Licensed")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Reflection;
|
||||
|
||||
[assembly: AssemblyVersion("1.14.1")]
|
||||
[assembly: AssemblyFileVersion("1.14.1")]
|
||||
[assembly: AssemblyVersion("1.17.1")]
|
||||
[assembly: AssemblyFileVersion("1.17.1")]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module("umbraco").controller("Imulus.ArchetypeConfigController", function ($scope, $http, assetsService, dialogService, archetypePropertyEditorResource) {
|
||||
angular.module("umbraco").controller("Imulus.ArchetypeConfigController", function ($scope, $http, assetsService, dialogService, archetypePropertyEditorResource, archetypeGlobalConfigService, notificationsService) {
|
||||
|
||||
//$scope.model.value = "";
|
||||
//console.log($scope.model.value);
|
||||
@@ -16,6 +16,17 @@ angular.module("umbraco").controller("Imulus.ArchetypeConfigController", functio
|
||||
archetypePropertyEditorResource.getDllVersion().then(function(data){
|
||||
$scope.dllVersion = data.dllVersion;
|
||||
});
|
||||
|
||||
archetypeGlobalConfigService.checkForUpdates().then(function(data) {
|
||||
if(data.isUpdateAvailable) {
|
||||
notificationsService.add({
|
||||
headline: data.headline,
|
||||
type: data.type,
|
||||
message: data.message,
|
||||
url: data.url
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
//ini the render model
|
||||
initConfigRenderModel();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
angular.module('umbraco').controller('ArchetypeConfigOptionsController', function ($scope) {
|
||||
|
||||
//handles a fieldset group add
|
||||
$scope.addFieldsetGroup = function () {
|
||||
$scope.dialogData.model.fieldsetGroups.push({ name: "" });
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
angular.module('umbraco').controller('ArchetypeConfigGlobalOptionsController', function ($scope, archetypeGlobalConfigService) {
|
||||
$scope.globalSettings = {};
|
||||
|
||||
$scope.confirmCheckNewVersionChange = function() {
|
||||
archetypeGlobalConfigService.setCheckForUpdates($scope.globalSettings.checkForNewVersion);
|
||||
}
|
||||
|
||||
function getGlobalSettings()
|
||||
{
|
||||
archetypeGlobalConfigService.globalSettings().then(function(data) {
|
||||
$scope.globalSettings.checkForNewVersion = data.isCheckingForUpdates;
|
||||
});
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
function init()
|
||||
{
|
||||
getGlobalSettings();
|
||||
}
|
||||
});
|
||||
@@ -1,8 +1,10 @@
|
||||
{{VERSION}}
|
||||
angular.module("umbraco").controller("Imulus.ArchetypeController", function ($scope, $http, $filter, assetsService, angularHelper, notificationsService, $timeout, fileManager, entityResource, archetypeService, archetypeLabelService, archetypeCacheService, archetypePropertyEditorResource) {
|
||||
angular.module("umbraco").controller("Imulus.ArchetypeController", function ($scope, $http, $filter, $interpolate, assetsService, angularHelper, notificationsService, $timeout, fileManager, entityResource, archetypeService, archetypeLabelService, archetypeCacheService, archetypePropertyEditorResource, archetypeLocalizationService) {
|
||||
|
||||
// Variables.
|
||||
var draggedParent;
|
||||
|
||||
var isCacheInitialized = false;
|
||||
|
||||
//$scope.model.value = "";
|
||||
$scope.model.hideLabel = $scope.model.config.hideLabel == 1;
|
||||
@@ -27,23 +29,54 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
|
||||
};
|
||||
|
||||
init();
|
||||
|
||||
//hold references to helper resources
|
||||
$scope.resources = {
|
||||
entityResource: entityResource,
|
||||
archetypePropertyEditorResource: archetypePropertyEditorResource
|
||||
}
|
||||
|
||||
//hold references to helper services
|
||||
$scope.services = {
|
||||
archetypeService: archetypeService,
|
||||
archetypeLabelService: archetypeLabelService,
|
||||
archetypeCacheService: archetypeCacheService
|
||||
}
|
||||
|
||||
|
||||
//helper to get $eval the labelTemplate
|
||||
$scope.fieldsetTitles = [];
|
||||
$scope.getFieldsetTitle = function (fieldsetConfigModel, fieldsetIndex) {
|
||||
return archetypeLabelService.getFieldsetTitle($scope, fieldsetConfigModel, fieldsetIndex);
|
||||
|
||||
if(!isCacheInitialized) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// Ensure the collection of titles is large enough.
|
||||
ensureEnoughTitles(fieldsetIndex + 1);
|
||||
var title = $scope.fieldsetTitles[fieldsetIndex];
|
||||
|
||||
// Return the title if it's already been loaded.
|
||||
if (title.loaded) {
|
||||
return title.value;
|
||||
}
|
||||
|
||||
// Return early if the title is still loading.
|
||||
if (title.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Start loading the title.
|
||||
title.loading = true;
|
||||
title.loaded = false;
|
||||
title.value = null;
|
||||
|
||||
archetypeLabelService.getFieldsetTitle($scope, fieldsetConfigModel, fieldsetIndex).then(function(value) {
|
||||
// Finished loading the title.
|
||||
title.loaded = true;
|
||||
title.loading = false;
|
||||
title.value = value;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Ensure the collection of fieldset titles is large enough to accommodate the number of fieldsets.
|
||||
* @param count The number of fieldsets.
|
||||
*/
|
||||
function ensureEnoughTitles(count) {
|
||||
while ($scope.fieldsetTitles.length < count) {
|
||||
$scope.fieldsetTitles.push({
|
||||
loading: false,
|
||||
loaded: false,
|
||||
value: null
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//sort config
|
||||
@@ -81,6 +114,7 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
|
||||
|
||||
},
|
||||
start: function(ev, ui) {
|
||||
archetypeService.getEditors().addClass('archetypeDragging');
|
||||
archetypeService.storeEditors(ui.item.parent());
|
||||
$scope.$apply(function() {
|
||||
draggedParent = ui.item.parent();
|
||||
@@ -142,7 +176,6 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
|
||||
|
||||
},
|
||||
stop: function (ev, ui) {
|
||||
|
||||
// Done sorting.
|
||||
draggedParent.scope().doingSort = false;
|
||||
|
||||
@@ -157,6 +190,7 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
|
||||
}
|
||||
archetypeService.restoreEditors(parent);
|
||||
|
||||
archetypeService.getEditors().removeClass('archetypeDragging');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -455,6 +489,13 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
|
||||
|
||||
//helpers for determining if the add button should be shown
|
||||
$scope.showAddButton = function () {
|
||||
var visible = countVisible();
|
||||
return (visible === 0 && $scope.model.config.startWithAddButton)
|
||||
|| (visible > 0 && $scope.canAdd());
|
||||
}
|
||||
|
||||
//helper for determining if no content is available yet
|
||||
$scope.showEmptyContentHint = function () {
|
||||
return $scope.model.config.startWithAddButton
|
||||
&& countVisible() === 0;
|
||||
///&& $scope.model.config.fieldsets.length == 1;
|
||||
@@ -537,10 +578,21 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
|
||||
function init() {
|
||||
$scope.model.value = removeNulls($scope.model.value);
|
||||
addDefaultProperties($scope.model.value.fieldsets);
|
||||
|
||||
archetypeCacheService.initialize().then(function() {
|
||||
isCacheInitialized = true;
|
||||
});
|
||||
|
||||
$timeout(function () {
|
||||
$scope.handleMandatoryValidation();
|
||||
}, 50);
|
||||
|
||||
// localize the message for minimum fieldsets validation errors
|
||||
archetypeLocalizationService.localize("minFieldsetsMessage").then(function (value) {
|
||||
value = value || "You must add minimum {{minFieldsets}} items";
|
||||
var exp = $interpolate(value);
|
||||
$scope.minFieldsetsMessage = exp({ minFieldsets: $scope.model.config.minFieldsets });
|
||||
});
|
||||
}
|
||||
|
||||
function addDefaultProperties(fieldsets)
|
||||
@@ -690,6 +742,14 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
|
||||
fileManager.setFiles($scope.model.alias, archetypeFiles);
|
||||
}
|
||||
|
||||
// Deep watch for changes.
|
||||
$scope.$watch('model.value', function () {
|
||||
|
||||
// Empty titles. If the value has changed, the titles may have changed.
|
||||
$scope.fieldsetTitles = [];
|
||||
|
||||
}, true);
|
||||
|
||||
//watch for changes
|
||||
$scope.$watch('model.value', function (v) {
|
||||
if ($scope.model.config.developerMode) {
|
||||
@@ -798,6 +858,13 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
|
||||
}
|
||||
}
|
||||
|
||||
$scope.minFieldsetsFulfilled = function () {
|
||||
if (!$scope.model.config.minFieldsets) {
|
||||
return true;
|
||||
}
|
||||
return $scope.numberOfEnabledFieldsets() >= $scope.model.config.minFieldsets;
|
||||
}
|
||||
|
||||
//custom js
|
||||
if ($scope.model.config.customJsPath) {
|
||||
assetsService.loadJs($scope.model.config.customJsPath);
|
||||
@@ -931,5 +998,4 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module("umbraco.directives").directive('archetypeProperty', function ($compile, $http, archetypePropertyEditorResource, umbPropEditorHelper, $timeout, $rootScope, $q, fileManager, editorState, archetypeService, archetypeCacheService) {
|
||||
angular.module("umbraco.directives").directive('archetypeProperty', function ($compile, $http, archetypePropertyEditorResource, umbPropEditorHelper, $timeout, $rootScope, $q, fileManager, editorState, archetypeService) {
|
||||
|
||||
var linker = function (scope, element, attrs, ngModelCtrl) {
|
||||
var configFieldsetModel = archetypeService.getFieldsetByAlias(scope.archetypeConfig.fieldsets, scope.fieldset.alias);
|
||||
@@ -25,9 +25,6 @@ angular.module("umbraco.directives").directive('archetypeProperty', function ($c
|
||||
|
||||
config = configObj;
|
||||
|
||||
//caching for use by label templates later
|
||||
archetypeCacheService.addDatatypeToCache(data, dataTypeGuid);
|
||||
|
||||
//determine the view to use [...] and load it
|
||||
archetypePropertyEditorResource.getPropertyEditorMapping(data.selectedEditor).then(function(propertyEditor) {
|
||||
var pathToView = umbPropEditorHelper.getViewPath(propertyEditor.view);
|
||||
@@ -65,7 +62,8 @@ angular.module("umbraco.directives").directive('archetypeProperty', function ($c
|
||||
|
||||
if (!scope.renderModelPropertyIndex)
|
||||
{
|
||||
archetypeService.getFieldset(scope).properties.push(JSON.parse('{"alias": "' + alias + '", "value": "' + defaultValue + '"}'));
|
||||
var propertyValue = { alias: alias, value: defaultValue };
|
||||
archetypeService.getFieldset(scope).properties.push(propertyValue);
|
||||
scope.renderModelPropertyIndex = archetypeService.getPropertyIndexByAlias(archetypeService.getFieldset(scope).properties, alias);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,70 +1,51 @@
|
||||
var ArchetypeSampleLabelTemplates = (function() {
|
||||
//create a namespace (optional)
|
||||
var ArchetypeSampleLabelHelpers = {};
|
||||
|
||||
//public functions
|
||||
return {
|
||||
Entity: function (value, scope, args) {
|
||||
|
||||
if(!args.entityType) {
|
||||
args = {entityType: "Document", propertyName: "name"}
|
||||
}
|
||||
|
||||
if (value) {
|
||||
//if handed a csv list, take the first only
|
||||
var id = value.split(",")[0];
|
||||
|
||||
if (id) {
|
||||
var entity = scope.services.archetypeCacheService.getEntityById(scope, id, args.entityType);
|
||||
|
||||
if(entity) {
|
||||
return entity[args.propertyName];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
},
|
||||
UrlPicker: function(value, scope, args) {
|
||||
|
||||
if(!args.propertyName) {
|
||||
args = {propertyName: "name"}
|
||||
}
|
||||
|
||||
var entity;
|
||||
|
||||
switch (value.type) {
|
||||
case "content":
|
||||
if(value.typeData.contentId) {
|
||||
entity = scope.services.archetypeCacheService.getEntityById(scope, value.typeData.contentId, "Document");
|
||||
}
|
||||
break;
|
||||
|
||||
case "media":
|
||||
if(value.typeData.mediaId) {
|
||||
entity = scope.services.archetypeCacheService.getEntityById(scope, value.typeData.mediaId, "Media");
|
||||
}
|
||||
break;
|
||||
|
||||
case "url":
|
||||
return value.typeData.url;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if(entity) {
|
||||
return entity[args.propertyName];
|
||||
}
|
||||
|
||||
return "";
|
||||
},
|
||||
Rte: function (value, scope, args) {
|
||||
|
||||
if(!args.contentLength) {
|
||||
args = {contentLength: 50}
|
||||
}
|
||||
|
||||
return $(value).text().substring(0, args.contentLength);
|
||||
}
|
||||
//create a function
|
||||
//you will add it to your label template field as `{{ArchetypeSampleLabelHelpers.testPromise(someArchetypePropertyAlias)}}`
|
||||
ArchetypeSampleLabelHelpers.testPromise = function(value) {
|
||||
//you can inject services
|
||||
return function ($timeout, archetypeCacheService) {
|
||||
//best to return a promise
|
||||
//NOTE: $timeout returns a promise
|
||||
return $timeout(function () {
|
||||
return "As Promised: " + value;
|
||||
}, 1000);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
ArchetypeSampleLabelHelpers.testEntityPromise = function(value, scope, args) {
|
||||
//hey look, args!
|
||||
//{{ArchetypeSampleLabelHelpers.testEntityPromise(someArchetypePropertyAlias, {foo: 1})}}
|
||||
console.log(args);
|
||||
|
||||
return function ($q, entityResource) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
entityResource.getById(args.foo, 'document').then(function(entity) {
|
||||
console.log("Hello from testEntityPromise");
|
||||
console.log(entity);
|
||||
deferred.resolve(entity.name);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
}
|
||||
|
||||
ArchetypeSampleLabelHelpers.testEntityPromise2 = function(value, scope, args) {
|
||||
//hey look, args but we're also using the built-in archetypeCacheService
|
||||
//{{ArchetypeSampleLabelHelpers.testEntityPromise(someArchetypePropertyAlias, {foo: 1234})}}
|
||||
console.log(args);
|
||||
|
||||
return function ($q, archetypeCacheService) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
archetypeCacheService.getEntityById(args.foo, 'document').then(function(entity) {
|
||||
console.log("Hello from testEntityPromise2");
|
||||
console.log(entity);
|
||||
deferred.resolve(entity.name);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -11,7 +11,7 @@
|
||||
"maxFieldsets": "Max Fieldsets",
|
||||
"maxFieldsetsDescription": "How many Fieldsets are allowed? Entering '1' will disable the controls. Default is unlimited.",
|
||||
"enableMultipleFieldsets": "Enable Multiple Fieldsets?",
|
||||
"enableMultipleFieldsetsDescription": "Allows multiple types of fieldsets within this archetype.",
|
||||
"enableMultipleFieldsetsDescription": "Allows multiple types of fieldsets within this Archetype.",
|
||||
"hideFieldsetToolbar": "Hide Fieldset Toolbar?",
|
||||
"hideFieldsetToolbarDescription": "Hides the fieldset toolbar that appears when more than one fieldset model appears.",
|
||||
"customWrapperClass": "Custom Wrapper Class",
|
||||
@@ -23,7 +23,7 @@
|
||||
"toggleDeveloperMode": "Toggle Developer Mode",
|
||||
"toggleDeveloperModeDescription": "Turn on for developer options.",
|
||||
"configModel": "Config Model",
|
||||
"configModelDescription": "Be careful editing the text below, it controls the schema for this archetype.",
|
||||
"configModelDescription": "Be careful editing the text below, it controls the schema for this Archetype.",
|
||||
"helpText": "Help Text",
|
||||
"defaultValue": "Default Value",
|
||||
"dataType": "DataType",
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@
|
||||
"maxFieldsets": "Max Fieldsets",
|
||||
"maxFieldsetsDescription": "How many Fieldsets are allowed? Entering '1' will disable the controls. Default is unlimited.",
|
||||
"enableMultipleFieldsets": "Enable Multiple Fieldsets?",
|
||||
"enableMultipleFieldsetsDescription": "Allows multiple types of fieldsets within this archetype.",
|
||||
"enableMultipleFieldsetsDescription": "Allows multiple types of fieldsets within this Archetype.",
|
||||
"hideFieldsetToolbar": "Hide Fieldset Toolbar?",
|
||||
"hideFieldsetToolbarDescription": "Hides the fieldset toolbar that appears when more than one fieldset model appears.",
|
||||
"customWrapperClass": "Custom Wrapper Class",
|
||||
@@ -23,7 +23,7 @@
|
||||
"toggleDeveloperMode": "Toggle Developer Mode",
|
||||
"toggleDeveloperModeDescription": "Turn on for developer options.",
|
||||
"configModel": "Config Model",
|
||||
"configModelDescription": "Be careful editing the text below, it controls the schema for this archetype.",
|
||||
"configModelDescription": "Be careful editing the text below, it controls the schema for this Archetype.",
|
||||
"helpText": "Help Text",
|
||||
"defaultValue": "Default Value",
|
||||
"dataType": "DataType",
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@
|
||||
"maxFieldsets": "Max Fieldsets",
|
||||
"maxFieldsetsDescription": "How many Fieldsets are allowed? Entering '1' will disable the controls. Default is unlimited.",
|
||||
"enableMultipleFieldsets": "Enable Multiple Fieldsets?",
|
||||
"enableMultipleFieldsetsDescription": "Allows multiple types of fieldsets within this archetype.",
|
||||
"enableMultipleFieldsetsDescription": "Allows multiple types of fieldsets within this Archetype.",
|
||||
"hideFieldsetToolbar": "Hide Fieldset Toolbar?",
|
||||
"hideFieldsetToolbarDescription": "Hides the fieldset toolbar that appears when more than one fieldset model appears.",
|
||||
"customWrapperClass": "Custom Wrapper Class",
|
||||
@@ -23,7 +23,7 @@
|
||||
"toggleDeveloperMode": "Toggle Developer Mode",
|
||||
"toggleDeveloperModeDescription": "Turn on for developer options.",
|
||||
"configModel": "Config Model",
|
||||
"configModelDescription": "Be careful editing the text below, it controls the schema for this archetype.",
|
||||
"configModelDescription": "Be careful editing the text below, it controls the schema for this Archetype.",
|
||||
"helpText": "Help Text",
|
||||
"defaultValue": "Default Value",
|
||||
"dataType": "DataType",
|
||||
|
||||
+170
-53
@@ -35,8 +35,7 @@
|
||||
|
||||
.fieldsetIcon {
|
||||
float: left;
|
||||
padding: 0 4px 0 0;
|
||||
color: #333;
|
||||
padding: 0 10px 0 0;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
|
||||
@@ -54,7 +53,6 @@
|
||||
fieldset {
|
||||
border-bottom: 1px dashed #dddddd;
|
||||
padding: 0;
|
||||
margin-bottom: 5px;
|
||||
clear: both;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
@@ -93,10 +91,10 @@
|
||||
.archetypeFieldsetLabel {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
min-height: 42px;
|
||||
background: white;
|
||||
|
||||
.label-sub {
|
||||
padding: 8px 0 8px 0;
|
||||
padding: 18px 0;
|
||||
display: inline-block;
|
||||
min-height: 20px; /* this makes the header clickable when there's no icon and no text */
|
||||
&.module-label {
|
||||
@@ -106,9 +104,9 @@
|
||||
cursor: pointer;
|
||||
|
||||
label {
|
||||
span {
|
||||
text-decoration: underline;
|
||||
}
|
||||
// span {
|
||||
// text-decoration: underline;
|
||||
// }
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -129,7 +127,7 @@
|
||||
}
|
||||
|
||||
span {
|
||||
font-weight: bold;
|
||||
// font-weight: bold;
|
||||
|
||||
&.menu-label { font-weight: normal; }
|
||||
}
|
||||
@@ -145,57 +143,99 @@
|
||||
label {
|
||||
margin-bottom: 0;
|
||||
margin-left: 18px;
|
||||
white-space: nowrap;
|
||||
padding: 0;
|
||||
width: ~"calc(100% - 144px)";
|
||||
position: absolute;
|
||||
display: block;
|
||||
span {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-height: 40px;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
display: -webkit-box;
|
||||
}
|
||||
&.dimmed {
|
||||
i, span {
|
||||
color: #d9d9d9 !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.dimmed {
|
||||
label {
|
||||
color: #d9d9d9 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.archetypeEditorControls {
|
||||
float: none;
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
right: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
opacity: 0;
|
||||
transition: opacity .15s ease-in-out;
|
||||
-moz-transition: opacity .15s ease-in-out;
|
||||
-webkit-transition: opacity .15s ease-in-out;
|
||||
background: white;
|
||||
|
||||
&:before {
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
display: block;
|
||||
left: -40px;
|
||||
width: 40px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background: -webkit-linear-gradient(90deg, rgba(255,255,255,0), white);
|
||||
background: -moz-linear-gradient(90deg, rgba(255,255,255,0), white);
|
||||
background: linear-gradient(90deg, rgba(255,255,255,0), white);
|
||||
}
|
||||
|
||||
.icon {
|
||||
color: #ddd;
|
||||
padding: 2px;
|
||||
display: inline-block;
|
||||
height: 28px;
|
||||
width: 28px;
|
||||
line-height: 28px;
|
||||
border-radius: 14px;
|
||||
border: 1px solid #d6d6d6;
|
||||
color: #5f5f5f;
|
||||
background: white;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
margin-left: 8px;
|
||||
|
||||
&:hover {
|
||||
color: #333;
|
||||
background: #f3f3f5;
|
||||
}
|
||||
&.icon-delete:hover {
|
||||
color: #b94a48;
|
||||
&.icon-trash:hover {
|
||||
background: #fe5b57;
|
||||
border-color: #fe5b57;
|
||||
color: white;
|
||||
}
|
||||
&.icon-disabled {
|
||||
cursor: default;
|
||||
&:hover {
|
||||
color: #ddd;
|
||||
background: white;
|
||||
}
|
||||
}
|
||||
&.icon-active {
|
||||
color: #333;
|
||||
color: #bbb;
|
||||
&:hover {
|
||||
color: #333;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
|
||||
&:hover .archetypeEditorControls {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-open > .archetypeFieldsetLabel .archetypeEditorControls {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.archetypePropertyError {
|
||||
margin-bottom: 5px;
|
||||
padding-top: 3px;
|
||||
@@ -213,9 +253,24 @@
|
||||
.archetypeCollapser {
|
||||
clear: both;
|
||||
height: 100%;
|
||||
padding: 12px 0 0 20px;
|
||||
background-color: #fff;
|
||||
border-radius: 0 0 0 5px;
|
||||
padding: 24px 20px 0 20px;
|
||||
background-color: #fafafa;
|
||||
border-top: 1px dashed #e0e0e0;
|
||||
line-height: 20px;
|
||||
|
||||
.archetypeFieldsetLabel {
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.archetypeEditorControls {
|
||||
background: #fafafa;
|
||||
|
||||
&:before {
|
||||
background: -webkit-linear-gradient(90deg, rgba(250,250,250,0), #fafafa);
|
||||
background: -moz-linear-gradient(90deg, rgba(250,250,250,0), #fafafa);
|
||||
background: linear-gradient(90deg, rgba(250,250,250,0), #fafafa);
|
||||
}
|
||||
}
|
||||
|
||||
form {
|
||||
margin-left:20px;
|
||||
@@ -246,25 +301,69 @@
|
||||
border: 1px solid #b94a48;
|
||||
}
|
||||
|
||||
.archetypeFooter {
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.archetypeAddButton {
|
||||
color: #ddd;
|
||||
.icon {
|
||||
vertical-align: middle;
|
||||
}
|
||||
display: inline-block;
|
||||
height: 28px;
|
||||
width: 28px;
|
||||
line-height: 28px;
|
||||
border-radius: 14px;
|
||||
border: 1px solid #b6b6b6;
|
||||
color: #5f5f5f;
|
||||
background: white;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: #333;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
|
||||
.archetypeAddButtonText {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.icon {
|
||||
color: #333;
|
||||
}
|
||||
background: #00aea2;
|
||||
border-color: #00aea2;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
.archetypeEmptyContent {
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
padding: 10px 20px;
|
||||
clear: both;
|
||||
font-size: 14px;
|
||||
color: #555;
|
||||
background: #f8f8f8;
|
||||
border-radius: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.archetypeCrossDraggable + .archetypeEmptyContent {
|
||||
margin-top: -42px;
|
||||
}
|
||||
|
||||
&.archetypeDragging .archetypeCrossDraggable + .archetypeEmptyContent {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Necessary to ensure empty lists can be dropped onto when sorting nested fieldsets.
|
||||
.archetypeSortable.archetypeEmpty.archetypeCrossDraggable {
|
||||
min-height: 40px;
|
||||
border: 1px dashed transparent;
|
||||
}
|
||||
|
||||
&.archetypeDragging .archetypeSortable.archetypeEmpty.archetypeCrossDraggable {
|
||||
min-height: 56px;
|
||||
border-color: #dddddd;
|
||||
}
|
||||
|
||||
|
||||
.archetypeCollapser .archetypeEmptyContent span {
|
||||
background: #f2f2f2;
|
||||
}
|
||||
|
||||
.multiPropertyTextbox {
|
||||
@@ -275,6 +374,9 @@
|
||||
list-style: none;
|
||||
margin-left: 0;
|
||||
}
|
||||
li {
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.show-validation.ng-invalid .control-group.error .control-label {
|
||||
span {
|
||||
@@ -357,6 +459,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.settings {
|
||||
padding: 14px;
|
||||
background-color: #f8f8f8;
|
||||
@@ -376,21 +479,13 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Necessary to ensure empty lists can be dropped onto when sorting nested fieldsets.
|
||||
.archetypeSortable.archetypeEmpty {
|
||||
&.archetypeCrossDraggable {
|
||||
min-height: 42px;
|
||||
border: 1px dashed #dddddd;
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.archetypeEditor, .archetypeConfig {
|
||||
.archetypeEditorControls {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.archetypeEditorControls, .archetypeFieldsetGroups {
|
||||
i {
|
||||
cursor: pointer;
|
||||
@@ -429,6 +524,26 @@
|
||||
.manual-link {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.donate-link {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.sponsors {
|
||||
padding-bottom: 10px;
|
||||
margin-bottom: 5px;
|
||||
margin-left: 5px;
|
||||
display: inline-table;
|
||||
float: right;
|
||||
|
||||
a {
|
||||
float: none;
|
||||
}
|
||||
|
||||
h4 {
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
@@ -449,6 +564,8 @@
|
||||
|
||||
.archetypeFieldsets {
|
||||
margin-left: 0;
|
||||
border-top: 5px solid;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
.archetypeFieldsetWrapper {
|
||||
|
||||
@@ -6,6 +6,11 @@ angular.module('umbraco.resources').factory('archetypePropertyEditorResource', f
|
||||
$http.get("backoffice/ArchetypeApi/ArchetypeDataType/GetAll"), 'Failed to retrieve datatypes from tree service'
|
||||
);
|
||||
},
|
||||
getAllDataTypesForCache: function() {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get("backoffice/ArchetypeApi/ArchetypeDataType/GetAllDetails"), 'Failed to retrieve datatypes from tree service'
|
||||
);
|
||||
},
|
||||
getDataType: function (guid, useDeepDatatypeLookup, contentTypeAlias, propertyTypeAlias, archetypeAlias, nodeId) {
|
||||
if(useDeepDatatypeLookup) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
|
||||
@@ -1,106 +1,87 @@
|
||||
angular.module('umbraco.services').factory('archetypeCacheService', function (archetypePropertyEditorResource) {
|
||||
angular.module('umbraco.services').factory('archetypeCacheService', function (archetypePropertyEditorResource, $q, entityResource) {
|
||||
//private
|
||||
|
||||
var isEntityLookupLoading = false;
|
||||
var entityCache = [];
|
||||
|
||||
var isDatatypeLookupLoading = false;
|
||||
var datatypeCache = [];
|
||||
|
||||
|
||||
return {
|
||||
getDataTypeFromCache: function(guid) {
|
||||
return _.find(datatypeCache, function (dt){
|
||||
return dt.dataTypeGuid == guid;
|
||||
});
|
||||
},
|
||||
|
||||
addDatatypeToCache: function(datatype, dataTypeGuid) {
|
||||
var cachedDatatype = this.getDataTypeFromCache(dataTypeGuid);
|
||||
|
||||
if(!cachedDatatype) {
|
||||
datatype.dataTypeGuid = dataTypeGuid;
|
||||
datatypeCache.push(datatype);
|
||||
}
|
||||
},
|
||||
initialize: function() {
|
||||
return archetypePropertyEditorResource.getAllDataTypesForCache().then(function(data) {
|
||||
_.each(data, function(datatype) {
|
||||
datatypeCache[datatype.dataTypeGuid] = datatype;
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
getDataTypeFromCache: function(guid) {
|
||||
return datatypeCache[guid];
|
||||
},
|
||||
|
||||
getDatatypeByGuid: function(guid) {
|
||||
var cachedDatatype = this.getDataTypeFromCache(guid);
|
||||
getDatatypeByGuid: function(guid) {
|
||||
var cachedDatatype = this.getDataTypeFromCache(guid);
|
||||
|
||||
if(cachedDatatype) {
|
||||
return cachedDatatype;
|
||||
}
|
||||
|
||||
if(cachedDatatype) {
|
||||
return cachedDatatype;
|
||||
}
|
||||
|
||||
//go get it from server, but this should already be pre-populated from the directive, but I suppose I'll leave this in in case used ad-hoc
|
||||
if (!isDatatypeLookupLoading) {
|
||||
isDatatypeLookupLoading = true;
|
||||
|
||||
archetypePropertyEditorResource.getDataType(guid).then(function(datatype) {
|
||||
|
||||
datatype.dataTypeGuid = guid;
|
||||
|
||||
datatypeCache.push(datatype);
|
||||
|
||||
isDatatypeLookupLoading = false;
|
||||
|
||||
return datatype;
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
return null;
|
||||
},
|
||||
|
||||
getEntityById: function(scope, id, type) {
|
||||
var cachedEntity = _.find(entityCache, function (e){
|
||||
return e.id == id;
|
||||
});
|
||||
getEntityById: function(id, type) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
//console.log(entityCache);
|
||||
|
||||
var cachedEntity = entityCache[id];
|
||||
|
||||
if(cachedEntity) {
|
||||
return cachedEntity;
|
||||
}
|
||||
if(cachedEntity) {
|
||||
//console.log("Found ID " + id);
|
||||
|
||||
deferred.resolve(cachedEntity);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
//go get it from server
|
||||
if (!isEntityLookupLoading) {
|
||||
isEntityLookupLoading = true;
|
||||
//go get it from server
|
||||
entityResource.getById(id, type).then(function(entity) {
|
||||
entityCache[id] = entity;
|
||||
|
||||
//console.log("entity ID is now resolved into cache...");
|
||||
//console.log(entityCache);
|
||||
|
||||
deferred.resolve(entity);
|
||||
});
|
||||
|
||||
scope.resources.entityResource.getById(id, type).then(function(entity) {
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
entityCache.push(entity);
|
||||
//perhaps this should return a promise?
|
||||
getEntityByUmbracoId: function(udi, type) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
var cachedEntity = entityCache[udi];
|
||||
|
||||
isEntityLookupLoading = false;
|
||||
if(cachedEntity) {
|
||||
//console.log("Found UDI " + udi);
|
||||
|
||||
deferred.resolve(cachedEntity);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
return entity;
|
||||
});
|
||||
}
|
||||
//go get it from server
|
||||
entityResource.getByIds([udi], type).then(function (entities) {
|
||||
// prevent infinite lookups with a default entity
|
||||
var entity = entities.length > 0 ? entities[0] : { udi: udi, name: "" };
|
||||
|
||||
return null;
|
||||
},
|
||||
entityCache[udi] = entity;
|
||||
|
||||
//console.log("entity UDI is now resolved into cache...");
|
||||
//console.log(entityCache);
|
||||
|
||||
getEntityByUmbracoId: function(scope, udi, type) {
|
||||
var cachedEntity = _.find(entityCache, function (e){
|
||||
return e.udi == udi;
|
||||
});
|
||||
deferred.resolve(entity);
|
||||
});
|
||||
|
||||
if(cachedEntity) {
|
||||
return cachedEntity;
|
||||
}
|
||||
|
||||
//go get it from server
|
||||
if (!isEntityLookupLoading) {
|
||||
isEntityLookupLoading = true;
|
||||
|
||||
scope.resources.entityResource.getByIds([udi], type).then(function (entities) {
|
||||
// prevent infinite lookups with a default entity
|
||||
var entity = entities.length > 0 ? entities[0] : { udi: udi, name: "" };
|
||||
|
||||
entityCache.push(entity);
|
||||
|
||||
isEntityLookupLoading = false;
|
||||
|
||||
return entity;
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
return deferred.promise;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
angular.module('umbraco.services').factory('archetypeGlobalConfigService', function ($q, $http, umbRequestHelper) {
|
||||
return {
|
||||
globalSettings: function () {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get("backoffice/ArchetypeApi/ArchetypeDataType/globalSettings"), 'Failed to get whether or not we are checking for updates!'
|
||||
);
|
||||
},
|
||||
setCheckForUpdates: function (isChecking) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post("backoffice/ArchetypeApi/ArchetypeDataType/SetCheckForUpdates", isChecking), 'Failed to update check status!'
|
||||
);
|
||||
},
|
||||
checkForUpdates: function () {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post("backoffice/ArchetypeApi/ArchetypeDataType/checkForUpdates", { }), 'Failed to check for updates!'
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,6 +1,172 @@
|
||||
angular.module('umbraco.services').factory('archetypeLabelService', function (archetypeCacheService) {
|
||||
angular.module('umbraco.services').factory('archetypeLabelService', function (archetypeCacheService, $q, $injector, $timeout) {
|
||||
//private
|
||||
|
||||
/**
|
||||
* This will repeatedly wait for all promises in an array of promises to resolve, and it allows
|
||||
* for promises to be added to the array (i.e., if you add more promises, those added promises
|
||||
* will also be resolved too).
|
||||
* @param promises The array of promises.
|
||||
* @returns {*} The promise that will resolve once all promises in the array resolve.
|
||||
*/
|
||||
function repeatedlyWaitForPromises(promises) {
|
||||
|
||||
// Remember the original number of promises being resolved.
|
||||
var originalLength = promises.length;
|
||||
|
||||
return $q.all(promises).then(function () {
|
||||
|
||||
// If there are new promises, resolve those too.
|
||||
if (promises.length > originalLength) {
|
||||
promises = promises.slice(originalLength);
|
||||
return repeatedlyWaitForPromises(promises);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a value to be used in a fieldset label. Since it might be a promise or a function, the
|
||||
* value is repeatedly processed until it becomes a string.
|
||||
* @param labelValue The value to be used in the fieldset label.
|
||||
* @param promises The collection of promises to add any promises to.
|
||||
* @param match The current matched substring object in a label template.
|
||||
*/
|
||||
function processLabelValue(labelValue, promises, match) {
|
||||
|
||||
// Normalize null/undefined values to an empty string.
|
||||
if(!labelValue) {
|
||||
labelValue = "";
|
||||
}
|
||||
|
||||
// Check the type of value (may be a string, promise, function, or other).
|
||||
if (isString(labelValue)) {
|
||||
|
||||
// handle collapsing dollar signs in labels (#387)
|
||||
if (labelValue.indexOf("$$") >= 0) {
|
||||
labelValue = labelValue.replace(/\$\$/g, "$$$$$$$$");
|
||||
}
|
||||
|
||||
// Set a new value now that it has been processed.
|
||||
//console.log("Processing string..." + labelValue);
|
||||
match.value = labelValue;
|
||||
} else if (isPromise(labelValue)) {
|
||||
// Remember the promise so we can wait for it to be completed before constructing the
|
||||
// fieldset label.
|
||||
promises.push(labelValue);
|
||||
labelValue.then(function (value) {
|
||||
//console.log("Processing final value..." + value);
|
||||
// The value will probably be a string, but recursively process it in case it's
|
||||
// something else.
|
||||
processLabelValue(value, promises, match);
|
||||
});
|
||||
} else if (_.isFunction(labelValue)) {
|
||||
|
||||
// Allow for the function to accept injected parameters, and invoke it.
|
||||
labelValue = $injector.invoke(labelValue);
|
||||
|
||||
// Recursively check result (may be a string, promise, or another function (another
|
||||
// function would be pretty strange, though I see no reason to disallow it).
|
||||
processLabelValue(labelValue, promises, match);
|
||||
} else {
|
||||
// Some other data type (e.g., number, date, object).
|
||||
match.value = labelValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified value is of type string.
|
||||
* @param value The value to check the type of.
|
||||
* @returns {boolean} True, if the value is a string; otherwise, false.
|
||||
*/
|
||||
function isString(value) {
|
||||
if (value === null) {
|
||||
return false;
|
||||
} else if (typeof value === 'string') {
|
||||
return true;
|
||||
} else if (value instanceof String) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified value is a JavaScript promise.
|
||||
* @param value The value that may be a promise.
|
||||
* @returns {*} True, if the value appears to be a promise; otherwise, false.
|
||||
*/
|
||||
function isPromise(value) {
|
||||
return value && _.isFunction(value.then);
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits a string value into a collection based on a regular expression.
|
||||
* @param rgx The regular expression to use to find matches in the string value.
|
||||
* @param value The string value to split.
|
||||
* @returns {Array} A collection of objects, each representing a portion of the supplied
|
||||
* string. Each object will contain the substring value, as well as a property
|
||||
* indicating whether or not that substring was matched the regular expression.
|
||||
*/
|
||||
function splitByRegex(rgx, value) {
|
||||
// Validate input.
|
||||
if (!rgx || !value) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Variables.
|
||||
var substring,
|
||||
splitParts = [],
|
||||
nextIndex = 0,
|
||||
index;
|
||||
|
||||
// Reset regex so we get all the matches.
|
||||
rgx.lastIndex = 0;
|
||||
|
||||
// Loop through each match until there are no more matches.
|
||||
var match = rgx.exec(value);
|
||||
while (match) {
|
||||
|
||||
// Extract match index.
|
||||
index = match.index;
|
||||
|
||||
// Is there text between the prior match and this one?
|
||||
if (nextIndex < index) {
|
||||
substring = value.substring(nextIndex, index);
|
||||
splitParts.push({
|
||||
isMatch: false,
|
||||
value: substring
|
||||
});
|
||||
}
|
||||
|
||||
// Remember the end of this match for the next loop iteration.
|
||||
nextIndex = rgx.lastIndex;
|
||||
|
||||
// Store info about this match.
|
||||
substring = value.substring(index, nextIndex);
|
||||
splitParts.push({
|
||||
isMatch: true,
|
||||
value: substring
|
||||
});
|
||||
|
||||
// Get next match.
|
||||
match = rgx.exec(value);
|
||||
}
|
||||
|
||||
// The text after the last match.
|
||||
if (nextIndex < value.length) {
|
||||
substring = value.substring(nextIndex);
|
||||
splitParts.push({
|
||||
isMatch: false,
|
||||
value: substring
|
||||
});
|
||||
}
|
||||
|
||||
// Reset regex in case somebody else wants to use it.
|
||||
rgx.lastIndex = 0;
|
||||
|
||||
// Return information about the matches.
|
||||
return splitParts;
|
||||
}
|
||||
|
||||
function executeFunctionByName(functionName, context) {
|
||||
var args = Array.prototype.slice.call(arguments).splice(2);
|
||||
|
||||
@@ -19,31 +185,31 @@ angular.module('umbraco.services').factory('archetypeLabelService', function (ar
|
||||
}
|
||||
|
||||
function getNativeLabel(datatype, value, scope) {
|
||||
switch (datatype.selectedEditor) {
|
||||
case "Imulus.UrlPicker":
|
||||
return imulusUrlPicker(value, scope, {});
|
||||
case "Umbraco.TinyMCEv3":
|
||||
return coreTinyMce(value, scope, {});
|
||||
case "Umbraco.MultiNodeTreePicker":
|
||||
return coreMntp(value, scope, datatype);
|
||||
case "Umbraco.MultiNodeTreePicker2":
|
||||
return coreMntpV2(value, scope, datatype);
|
||||
case "Umbraco.MultipleMediaPicker":
|
||||
case "Umbraco.MediaPicker":
|
||||
return coreMediaPicker(value, scope, datatype);
|
||||
case "Umbraco.MediaPicker2":
|
||||
return coreMediaPickerV2(value, scope, datatype);
|
||||
case "Umbraco.DropDown":
|
||||
return coreDropdown(value, scope, datatype);
|
||||
case "RJP.MultiUrlPicker":
|
||||
return rjpMultiUrlPicker(value, scope, {});
|
||||
case "Umbraco.ContentPickerAlias":
|
||||
return coreContentPicker(value, scope, datatype);
|
||||
case "Umbraco.ContentPicker2":
|
||||
return coreContentPickerV2(value, scope, datatype);
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
switch (datatype.selectedEditor) {
|
||||
case "Imulus.UrlPicker":
|
||||
return imulusUrlPicker(value, scope, {});
|
||||
case "Umbraco.TinyMCEv3":
|
||||
return coreTinyMce(value, scope, {});
|
||||
case "Umbraco.MultiNodeTreePicker":
|
||||
return coreMntp(value, scope, datatype);
|
||||
case "Umbraco.MultiNodeTreePicker2":
|
||||
return coreMntpV2(value, scope, datatype);
|
||||
case "Umbraco.MultipleMediaPicker":
|
||||
case "Umbraco.MediaPicker":
|
||||
return coreMediaPicker(value, scope, datatype);
|
||||
case "Umbraco.MediaPicker2":
|
||||
return coreMediaPickerV2(value, scope, datatype);
|
||||
case "Umbraco.DropDown":
|
||||
return coreDropdown(value, scope, datatype);
|
||||
case "RJP.MultiUrlPicker":
|
||||
return rjpMultiUrlPicker(value, scope, {});
|
||||
case "Umbraco.ContentPickerAlias":
|
||||
return coreContentPicker(value, scope, datatype);
|
||||
case "Umbraco.ContentPicker2":
|
||||
return coreContentPickerV2(value, scope, datatype);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function coreDropdown(value, scope, args) {
|
||||
@@ -63,6 +229,7 @@ angular.module('umbraco.services').factory('archetypeLabelService', function (ar
|
||||
function coreMntp(value, scope, args) {
|
||||
var ids = value.split(',');
|
||||
var type = "Document";
|
||||
var deferred = $q.defer();
|
||||
|
||||
switch(args.preValues[0].value.type) {
|
||||
case 'content':
|
||||
@@ -74,32 +241,39 @@ angular.module('umbraco.services').factory('archetypeLabelService', function (ar
|
||||
case 'member':
|
||||
type = 'member';
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
var entityArray = [];
|
||||
var promises = [];
|
||||
|
||||
_.each(ids, function(id){
|
||||
if(id) {
|
||||
|
||||
var entity = archetypeCacheService.getEntityById(scope, id, type);
|
||||
|
||||
if(entity) {
|
||||
entityArray.push(entity.name);
|
||||
}
|
||||
promises.push(archetypeCacheService.getEntityById(id, type).then(function(entity){
|
||||
if(entity) {
|
||||
entityArray.push(entity.name);
|
||||
}
|
||||
}).promise);
|
||||
}
|
||||
});
|
||||
|
||||
return entityArray.join(', ');
|
||||
$q.all(promises).then(function() {
|
||||
deferred.resolve(entityArray.join(', '));
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function coreMntpV2(value, scope, args) {
|
||||
function coreMntpV2(value, scope, args) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
var ids = value.split(',');
|
||||
|
||||
if (ids.length == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
var type = "document";
|
||||
|
||||
switch(args.preValues[0].value.type) {
|
||||
@@ -116,119 +290,173 @@ angular.module('umbraco.services').factory('archetypeLabelService', function (ar
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
var entity;
|
||||
|
||||
var entityArray = [];
|
||||
var promises = [];
|
||||
|
||||
_.each(ids, function (id) {
|
||||
if(id && !entity) {
|
||||
entity = archetypeCacheService.getEntityByUmbracoId(scope, id, type);
|
||||
if(id) {
|
||||
promises.push(archetypeCacheService.getEntityByUmbracoId(id, type).then(function(entity) {
|
||||
if(entity) {
|
||||
entityArray.push(entity.name);
|
||||
}
|
||||
}).promise);
|
||||
}
|
||||
});
|
||||
|
||||
return (entity != null ? entity.name : "") + (ids.length > 1 ? ", ..." : "");
|
||||
|
||||
$q.all(promises).then(function() {
|
||||
if(entityArray.length == 0) {
|
||||
deferred.resolve("");
|
||||
}
|
||||
|
||||
var firstEntityName = entityArray[0];
|
||||
|
||||
var value = firstEntityName + (ids.length > 1 ? ", ..." : "");
|
||||
|
||||
deferred.resolve(value);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function coreMediaPicker(value, scope, args) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
if(value) {
|
||||
var entity = archetypeCacheService.getEntityById(scope, value, "media");
|
||||
|
||||
if(entity) {
|
||||
return entity.name;
|
||||
}
|
||||
archetypeCacheService.getEntityById(value, "media").then(function(entity) {
|
||||
deferred.resolve(entity.name);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
deferred.resolve("");
|
||||
}
|
||||
|
||||
return "";
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function coreMediaPickerV2(value, scope, args) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
//console.log("value=");
|
||||
//console.log(value);
|
||||
|
||||
if(value) {
|
||||
var entity = archetypeCacheService.getEntityByUmbracoId(scope, value, "media");
|
||||
|
||||
if(entity) {
|
||||
return entity.name;
|
||||
}
|
||||
archetypeCacheService.getEntityByUmbracoId(value, "media").then(function(entity) {
|
||||
deferred.resolve(entity.name);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
deferred.resolve("");
|
||||
}
|
||||
|
||||
return "";
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function coreContentPicker(value, scope, args) {
|
||||
if (value) {
|
||||
var entity = archetypeCacheService.getEntityById(scope, value, "document");
|
||||
|
||||
if (entity) {
|
||||
return entity.name;
|
||||
var deferred = $q.defer();
|
||||
|
||||
if(value) {
|
||||
archetypeCacheService.getEntityById(value, "document").then(function(entity) {
|
||||
deferred.resolve(entity.name);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
else
|
||||
{
|
||||
deferred.resolve("");
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function coreContentPickerV2(value, scope, args) {
|
||||
if (value) {
|
||||
var entity = archetypeCacheService.getEntityByUmbracoId(scope, value, "document");
|
||||
|
||||
if (entity) {
|
||||
return entity.name;
|
||||
var deferred = $q.defer();
|
||||
|
||||
if (value) {
|
||||
archetypeCacheService.getEntityByUmbracoId(value, "document").then(function(entity) {
|
||||
deferred.resolve(entity.name);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
deferred.resolve("");
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function imulusUrlPicker(value, scope, args) {
|
||||
|
||||
var deferred = $q.defer();
|
||||
|
||||
if(!value) {
|
||||
deferred.resolve("");
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
if(!args.propertyName) {
|
||||
args = {propertyName: "name"}
|
||||
}
|
||||
|
||||
if(typeof(value) != "object") {
|
||||
value = JSON.parse(value);
|
||||
}
|
||||
|
||||
var entity;
|
||||
|
||||
//console.log("urlpicker value...");
|
||||
//console.log(value);
|
||||
|
||||
if(value.length) {
|
||||
value = value[0];
|
||||
}
|
||||
|
||||
switch (value.type) {
|
||||
case "content":
|
||||
if(value.typeData.contentId) {
|
||||
entity = archetypeCacheService.getEntityById(scope, value.typeData.contentId, "Document");
|
||||
archetypeCacheService.getEntityById(value.typeData.contentId, "Document").then(function(entity) {
|
||||
//console.log("Retrived entity from cache!");
|
||||
//console.log("Resolving the entity name with " + entity[args.propertyName]);
|
||||
deferred.resolve(entity[args.propertyName]);
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
case "media":
|
||||
if(value.typeData.mediaId) {
|
||||
entity = archetypeCacheService.getEntityById(scope, value.typeData.mediaId, "Media");
|
||||
archetypeCacheService.getEntityById(value.typeData.mediaId, "Media").then(function(entity) {
|
||||
deferred.resolve(entity[args.propertyName]);
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
case "url":
|
||||
return value.typeData.url;
|
||||
deferred.resolve(value.typeData.url);
|
||||
|
||||
return deferred.promise;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if(entity) {
|
||||
return entity[args.propertyName];
|
||||
}
|
||||
|
||||
return "";
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function coreTinyMce(value, scope, args) {
|
||||
|
||||
if(!args.contentLength) {
|
||||
args = {contentLength: 50}
|
||||
args = {contentLength: 160}
|
||||
}
|
||||
|
||||
var suffix = "";
|
||||
var strippedText = $("<div/>").html(value).text();
|
||||
|
||||
if(strippedText.length > args.contentLength) {
|
||||
suffix = "…";
|
||||
suffix = "…";
|
||||
}
|
||||
|
||||
return strippedText.substring(0, args.contentLength) + suffix;
|
||||
}
|
||||
|
||||
function rjpMultiUrlPicker(values, scope, args) {
|
||||
function rjpMultiUrlPicker(values, scope, args) {
|
||||
var names = [];
|
||||
|
||||
_.each(values, function (value) {
|
||||
@@ -239,45 +467,38 @@ angular.module('umbraco.services').factory('archetypeLabelService', function (ar
|
||||
|
||||
return names.join(", ");
|
||||
}
|
||||
|
||||
return {
|
||||
getFieldsetTitle: function(scope, fieldsetConfigModel, fieldsetIndex) {
|
||||
|
||||
//console.log(scope.model.config);
|
||||
|
||||
return {
|
||||
getFieldsetTitle: function(scope, fieldsetConfigModel, fieldsetIndex) {
|
||||
|
||||
if(!fieldsetConfigModel)
|
||||
return "";
|
||||
return $q.when("");
|
||||
|
||||
var fieldset = scope.model.value.fieldsets[fieldsetIndex];
|
||||
var fieldsetConfig = scope.getConfigFieldsetByAlias(fieldset.alias);
|
||||
var template = fieldsetConfigModel.labelTemplate;
|
||||
var promises = [];
|
||||
|
||||
if (template.length < 1)
|
||||
return fieldsetConfig.label;
|
||||
return $q.when(fieldsetConfig.label);
|
||||
|
||||
var rgx = /({{(.*?)}})*/g;
|
||||
var results;
|
||||
var parsedTemplate = template;
|
||||
|
||||
var rawMatches = template.match(rgx);
|
||||
|
||||
var matches = [];
|
||||
|
||||
_.each(rawMatches, function(match){
|
||||
if(match) {
|
||||
matches.push(match);
|
||||
}
|
||||
});
|
||||
var rgx = /{{.*?}}/g;
|
||||
var matches = splitByRegex(rgx, template);
|
||||
|
||||
_.each(matches, function (match) {
|
||||
|
||||
// Skip over substrings that didn't match the regex (they do not require a transformation).
|
||||
if (!match.isMatch) {
|
||||
return;
|
||||
}
|
||||
|
||||
// split the template in case it consists of multiple property aliases and/or functions
|
||||
var templates = match.replace("{{", '').replace("}}", '').split("|");
|
||||
var templates = match.value.replace("{{", '').replace("}}", '').split("|");
|
||||
var templateLabelValue = "";
|
||||
|
||||
for(var i = 0; i < templates.length; i++) {
|
||||
// stop looking for a template label value if a previous template part already yielded a value
|
||||
if(templateLabelValue != "") {
|
||||
if(templateLabelValue !== "") {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -288,7 +509,7 @@ angular.module('umbraco.services').factory('archetypeLabelService', function (ar
|
||||
var endParamsIndexOf = template.indexOf(")");
|
||||
|
||||
//if passed a function
|
||||
if(beginParamsIndexOf != -1 && endParamsIndexOf != -1)
|
||||
if(beginParamsIndexOf !== -1 && endParamsIndexOf !== -1)
|
||||
{
|
||||
var functionName = template.substring(0, beginParamsIndexOf);
|
||||
var propertyAlias = template.substring(beginParamsIndexOf + 1, endParamsIndexOf).split(',')[0];
|
||||
@@ -297,7 +518,7 @@ angular.module('umbraco.services').factory('archetypeLabelService', function (ar
|
||||
|
||||
var beginArgsIndexOf = template.indexOf(',');
|
||||
|
||||
if(beginArgsIndexOf != -1) {
|
||||
if(beginArgsIndexOf !== -1) {
|
||||
|
||||
var argsString = template.substring(beginArgsIndexOf + 1, endParamsIndexOf).trim();
|
||||
|
||||
@@ -305,55 +526,57 @@ angular.module('umbraco.services').factory('archetypeLabelService', function (ar
|
||||
|
||||
args = JSON.parse(normalizedJsonString);
|
||||
}
|
||||
|
||||
|
||||
templateLabelValue = executeFunctionByName(functionName, window, scope.getPropertyValueByAlias(fieldset, propertyAlias), scope, args);
|
||||
}
|
||||
//normal {{foo}} syntax
|
||||
else {
|
||||
propertyAlias = template;
|
||||
|
||||
var rawValue = scope.getPropertyValueByAlias(fieldset, propertyAlias);
|
||||
|
||||
templateLabelValue = rawValue;
|
||||
|
||||
//determine the type of editor
|
||||
var propertyConfig = _.find(fieldsetConfigModel.properties, function(property){
|
||||
return property.alias == propertyAlias;
|
||||
return property.alias === propertyAlias;
|
||||
});
|
||||
|
||||
if(propertyConfig) {
|
||||
var datatype = archetypeCacheService.getDatatypeByGuid(propertyConfig.dataTypeGuid);
|
||||
var datatype = archetypeCacheService.getDatatypeByGuid(propertyConfig.dataTypeGuid);
|
||||
|
||||
if(datatype) {
|
||||
|
||||
//try to get built-in label
|
||||
var label = getNativeLabel(datatype, templateLabelValue, scope);
|
||||
|
||||
if(label) {
|
||||
templateLabelValue = label;
|
||||
}
|
||||
else {
|
||||
templateLabelValue = templateLabelValue;
|
||||
}
|
||||
}
|
||||
if(datatype) {
|
||||
//try to get built-in label
|
||||
var label = getNativeLabel(datatype, rawValue, scope);
|
||||
|
||||
if (label) {
|
||||
templateLabelValue = label;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return templateLabelValue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!templateLabelValue) {
|
||||
templateLabelValue = "";
|
||||
}
|
||||
// handle collapsing dollar signs in labels (#387)
|
||||
if (templateLabelValue.indexOf("$$") >= 0) {
|
||||
templateLabelValue = templateLabelValue.replace(/\$\$/g, "$$$$$$$$");
|
||||
}
|
||||
parsedTemplate = parsedTemplate.replace(match, templateLabelValue);
|
||||
// Process the value (i.e., reduce any functions or promises down to strings).
|
||||
processLabelValue(templateLabelValue, promises, match);
|
||||
});
|
||||
|
||||
return parsedTemplate;
|
||||
// Wait for all of the promises to resolve before constructing the full fieldset label.
|
||||
return repeatedlyWaitForPromises(promises).then(function () {
|
||||
|
||||
//console.log("done waiting...")
|
||||
// Extract string values and combine them into a single string.
|
||||
var substrings = _.map(matches, function (value) {
|
||||
return value.value;
|
||||
});
|
||||
|
||||
var combinedSubstrings = substrings.join('');
|
||||
|
||||
//console.log(combinedSubstrings);
|
||||
|
||||
// Return the title.
|
||||
return combinedSubstrings;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -2,6 +2,7 @@ angular.module('umbraco.services').factory('archetypeService', function () {
|
||||
|
||||
// Variables.
|
||||
var draggedRteArchetype;
|
||||
var archetypeEditors;
|
||||
var rteClass = ".archetypeEditor .umb-rte textarea";
|
||||
var editorSettings = {};
|
||||
var disabledSortables = [];
|
||||
@@ -215,6 +216,13 @@ angular.module('umbraco.services').factory('archetypeService', function () {
|
||||
sortable.enable();
|
||||
});
|
||||
disabledSortables = [];
|
||||
},
|
||||
// Get all active archetype editors on the current page
|
||||
getEditors: function() {
|
||||
if (archetypeEditors == null) {
|
||||
archetypeEditors = $('.archetypeEditor');
|
||||
}
|
||||
return archetypeEditors;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -11,9 +11,11 @@
|
||||
<div>
|
||||
<label for="archetypeOverrideDefaultConverter"><input type="checkbox" id="archetypeOverrideDefaultConverter" ng-model="dialogData.model.overrideDefaultPropertyValueConverter" /><archetype-localize key="overrideDefaultConverter">Override Default Property Value Converter?</archetype-localize><small><archetype-localize key="overrideDefaultConverterDescription">Check this if you wish to use your own custom property value converter.</archetype-localize></small></label>
|
||||
</div>
|
||||
|
||||
<div ng-controller="ArchetypeConfigGlobalOptionsController">
|
||||
<label for="archetypeCheckForNewVersion"><input type="checkbox" id="archetypeCheckForNewVersion" ng-model="globalSettings.checkForNewVersion" ng-click="confirmCheckNewVersionChange();" /><archetype-localize key="checkForNewVersion">Automatically check for newer versions?</archetype-localize><small><archetype-localize key="checkForNewVersionDescription">Check this if you wish to be notified when a newer version of Archetype is available. This is a application level setting.</archetype-localize> <a class="manual-link" href="https://github.com/kgiszewski/Archetype/blob/master/Information%20Collection%20Disclosure.md" target="_blank">Information Collection Disclosure</a></small></label>
|
||||
</div>
|
||||
<div>
|
||||
<label for="archetypeAdvancedOptionsConfigModel"><archetype-localize key="configModel">Config Model</archetype-localize><small><archetype-localize key="configModelDescription">Be careful editing the text below, it controls the schema for this archetype.</archetype-localize></small></label>
|
||||
<label for="archetypeAdvancedOptionsConfigModel"><archetype-localize key="configModel">Config Model</archetype-localize><small><archetype-localize key="configModelDescription">Be careful editing the text below, it controls the schema for this Archetype.</archetype-localize></small></label>
|
||||
<textarea class="archetypeDeveloperModel" id="archetypeAdvancedOptionsConfigModel" ng-model="dialogData.model" ng-change="dialogData.modelChanged = true"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
<div>
|
||||
<label for="archetypeAdvancedOptionsMultipleOpen"><input type="checkbox" id="archetypeAdvancedOptionsMultipleOpen" ng-model="dialogData.model.enableMultipleOpen" /><archetype-localize key="enableMultipleOpen">Enable Multiple Open Fieldsets?</archetype-localize><small><archetype-localize key="enableMultipleOpenDescription">When fieldset collapsing is enabled, this allows multiple fieldsets to be open at the same time.</archetype-localize></small></label>
|
||||
</div>
|
||||
<div>
|
||||
<label for="archetypeAdvancedOptionsMinFieldsets"><archetype-localize key="minFieldsets">Min Fieldsets</archetype-localize><small><archetype-localize key="minFieldsetsDescription">How many Fieldsets are required? Default is none.</archetype-localize></small></label>
|
||||
<input type="number" id="archetypeAdvancedOptionsMinFieldsets" class="archetypeMaxFieldsets" ng-model="dialogData.model.minFieldsets" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="archetypeAdvancedOptionsMaxFieldsets"><archetype-localize key="maxFieldsets">Max Fieldsets</archetype-localize><small><archetype-localize key="maxFieldsetsDescription">How many Fieldsets are allowed? Entering '1' will disable the controls. Default is unlimited.</archetype-localize></small></label>
|
||||
<input type="number" id="archetypeAdvancedOptionsMaxFieldsets" class="archetypeMaxFieldsets" ng-model="dialogData.model.maxFieldsets"/>
|
||||
|
||||
@@ -1,8 +1,17 @@
|
||||
{{VERSION_HTML}}
|
||||
<div class="archetypeConfig" ng-controller="Imulus.ArchetypeConfigController">
|
||||
<h2 class="archetype-headline"><img src="../App_Plugins/Archetype/assets/logo_50.png"/>Archetype<small>{{dllVersion}}</small><a href="https://twitter.com/archetypekit" target="_blank"><img src="../App_Plugins/Archetype/assets/twitter.png"/></a></h2>
|
||||
<p>At a minimum your Archetype needs at least one fieldset with at least one property. You can configure it to allow for multiple types of fieldsets within a single Archetype and you can even add another Archetype as a property. Please use the link below for the full manual:</p>
|
||||
<p><a class="manual-link" href="https://github.com/kgiszewski/ArchetypeManual" target="_blank">Archetype Manual</a></p>
|
||||
<h2 class="archetype-headline"><img src="../App_Plugins/Archetype/assets/logo_50.png"/>Archetype<small>{{dllVersion}}</small></h2>
|
||||
<p>At a minimum your Archetype needs at least one fieldset with at least one property. Please use the link below for the full manual. We would really love a donation if you find Archetype useful. Your company can also sponsor a sprint!</p>
|
||||
<p>
|
||||
<a class="manual-link" href="https://github.com/kgiszewski/ArchetypeManual" target="_blank">Archetype Manual</a> |
|
||||
<a class="manual-link" href="https://github.com/kgiszewski/Archetype/blob/master/Information%20Collection%20Disclosure.md" target="_blank">Information Collection Disclosure</a> |
|
||||
<a class="manual-link" href="https://www.youtube.com/watch?v=79LksNwGjLk" target="_blank">Quick Start Video</a> |
|
||||
<a class="manual-link" href="https://twitter.com/archetypekit" target="_blank">Twitter</a> |
|
||||
<a class="manual-link" href="https://github.com/kgiszewski/Archetype" target="_blank">GitHub</a> |
|
||||
<a class="manual-link" href="https://github.com/kgiszewski/Archetype/blob/master/Sponsors.md" target="_blank">Become a sponsor</a> |
|
||||
<a class="manual-link donate-link" href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KBKWLURGLGU6L" target="_blank">Donate!</a>
|
||||
</p>
|
||||
|
||||
<ul class="archetypeFieldsets" ui-sortable="sortableOptions" ng-model="archetypeConfigRenderModel.fieldsets">
|
||||
<li ng-repeat="fieldset in archetypeConfigRenderModel.fieldsets" ng-hide="fieldset.remove">
|
||||
<div class="archetypeFieldsetWrapper" >
|
||||
@@ -53,7 +62,7 @@
|
||||
<i class="icon icon-navigation handle" ng-show="canSortProperty(fieldset)"></i>
|
||||
</div>
|
||||
<div class="archetypePropertyTitle" ng-click="focusProperty(fieldset.properties, property)">
|
||||
{{property.label}} ({{property.alias}}) - <span>{{getDataTypeNameByGuid(property.dataTypeGuid)}}</span>
|
||||
{{property.label}}<span ng-if="property.required" class="property-required">*</span> ({{property.alias}}) - <span>{{getDataTypeNameByGuid(property.dataTypeGuid)}}</span>
|
||||
</div>
|
||||
<div class="archetypePropertyCollapser" ng-hide="property.collapse && property.label">
|
||||
<div>
|
||||
|
||||
@@ -2,26 +2,22 @@
|
||||
<div class="archetypeEditor ng-class:model.config.customCssClass">
|
||||
<textarea class="archetypeDeveloperModel" ng-show="model.config.developerMode" ng-model="model.value"></textarea>
|
||||
|
||||
<!-- "Add" button. -->
|
||||
<div ng-show="showAddButton()">
|
||||
<a class="archetypeAddButton" ng-click="openFieldsetPicker(0, $event)" prevent-default>
|
||||
<i class="icon icon-add"></i>
|
||||
<archetype-localize key="addFieldset">Add an item</archetype-localize>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Mandatory validation. -->
|
||||
<input type="hidden" name="archetypeMandatory" ng-model="model.mandatoryValidation" ng-required="model.validation.mandatory" />
|
||||
<div><span class="help-inline" val-msg-for="archetypeMandatory" val-toggle-msg="required"><archetype-localize key="required">Required</archetype-localize></span></div>
|
||||
|
||||
<!-- Min fieldsets validation. -->
|
||||
<input type="hidden" name="archetypeMinFieldsets" ng-model="model.mandatoryMinFieldsets" ng-required="!minFieldsetsFulfilled()" />
|
||||
<div><span class="help-inline" val-msg-for="archetypeMinFieldsets" val-toggle-msg="required">{{minFieldsetsMessage}}</span></div>
|
||||
|
||||
<!-- Fieldsets. -->
|
||||
<ul ui-sortable="sortableOptions" class="archetypeSortable" ng-class="{archetypeEmpty: model.value.fieldsets.length === 0 || sortingLastItem(), archetypeCrossDraggable: model.config.enableCrossDragging}" ng-model="model.value.fieldsets">
|
||||
<li ng-repeat="fieldset in model.value.fieldsets">
|
||||
<fieldset ng-class="['archetype-fieldset-' + fieldset.alias, (getFieldsetValidity(fieldset) == false ? 'archetypeFieldsetError' : '')]" ng-init="fieldsetConfigModel = getConfigFieldsetByAlias(fieldset.alias)">
|
||||
<div class="archetypeFieldsetLabel" ng-class="{enableCollapsing: model.config.enableCollapsing}">
|
||||
<fieldset ng-class="['archetype-fieldset-' + fieldset.alias, (getFieldsetValidity(fieldset) == false ? 'archetypeFieldsetError' : ''), (isCollapsed(fieldset) ? '' : 'is-open')]" ng-init="fieldsetConfigModel = getConfigFieldsetByAlias(fieldset.alias)">
|
||||
<div class="archetypeFieldsetLabel" ng-class="{enableCollapsing: model.config.enableCollapsing, dimmed: isDisabled(fieldset)}">
|
||||
<div ng-click="focusFieldset(fieldset)" class="label-sub module-label">
|
||||
<span class="caret" ng-class="{'caret-right': isCollapsed(fieldset)}" ng-show="model.config.enableCollapsing"></span>
|
||||
<label ng-class="{dimmed: isDisabled(fieldset)}">
|
||||
<label>
|
||||
<i class="fieldsetIcon icon ng-class:fieldsetConfigModel.icon"></i>
|
||||
<span ng-bind="getFieldsetTitle(fieldsetConfigModel, $index)"></span>
|
||||
</label>
|
||||
@@ -30,9 +26,9 @@
|
||||
<i class="icon icon-add" ng-show="canAdd()" ng-click="openFieldsetPicker($index, $event)"></i>
|
||||
<i class="icon icon-navigation handle" ng-show="canSort()"></i>
|
||||
<i class="icon icon-documents" ng-click="cloneRow($index)" ng-show="canClone()"></i>
|
||||
<i class="icon icon-power" ng-class="{'icon-active': fieldset.disabled}" ng-click="enableDisable(fieldset)" ng-show="showDisableIcon(fieldset)"></i>
|
||||
<i class="icon icon-eye" ng-class="{'icon-active': fieldset.disabled}" ng-click="enableDisable(fieldset)" ng-show="showDisableIcon(fieldset)"></i>
|
||||
<i class="icon icon-time icon-disabled" ng-class="{'icon-active': isDisabledByPublishing(fieldset)}" ng-show="showPublishingIcon(fieldset)"></i>
|
||||
<i class="icon icon-delete" ng-click="removeRow($index)" ng-show="canRemove()"></i>
|
||||
<i class="icon icon-trash" ng-click="removeRow($index)" ng-show="canRemove()"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="archetypeCollapser animate-hide" ng-hide="model.config.enableCollapsing && isCollapsed(fieldset)" ng-if="isLoaded(fieldset)">
|
||||
@@ -105,6 +101,20 @@
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Empty content display. -->
|
||||
<div class="archetypeEmptyContent" ng-show="showEmptyContentHint()">
|
||||
<span>
|
||||
<archetype-localize key="addFieldset">Add an item</archetype-localize>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- "Add" button. -->
|
||||
<div class="archetypeFooter" ng-show="showAddButton()">
|
||||
<a class="archetypeAddButton" ng-click="openFieldsetPicker(model.value.fieldsets.length, $event)" prevent-default>
|
||||
<i class="icon icon-add"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Fieldset picker. -->
|
||||
<div class="usky-grid fieldsetPicker" ng-class="{withGroups: overlayMenu.fieldsetGroups.length > 1}" ng-if="overlayMenu.show">
|
||||
<div class="cell-tools-menu" ng-style="overlayMenu.style" delayed-mouseleave="closeFieldsetPicker()" archetype-click-outside="closeFieldsetPicker()">
|
||||
@@ -140,7 +150,7 @@
|
||||
</div>
|
||||
<div class="fieldsetPreviewImage">
|
||||
<a href="{{overlayMenu.fieldsetPreview.previewImage}}" target="_blank">
|
||||
<img src="{{overlayMenu.fieldsetPreview.previewImage}}" />
|
||||
<img ng-src="{{overlayMenu.fieldsetPreview.previewImage}}" />
|
||||
</a>
|
||||
</div>
|
||||
<div class="fieldsetPreviewClose">
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 4.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 134 KiB |
+4
-4
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"name": "Archetype",
|
||||
"version": "1.14.1",
|
||||
"url": "http://github.com/imulus/archetype/",
|
||||
"author": "Imulus - Kevin Giszewski - Tom Fulton - Lee Kelleher - Matt Brailsford - Kenn Jacobsen - Et. Al.",
|
||||
"authorUrl": "http://imulus.com/",
|
||||
"version": "1.17.1",
|
||||
"url": "http://github.com/kgiszewski/archetype/",
|
||||
"author": "Kevin Giszewski - Tom Fulton - Lee Kelleher - Matt Brailsford - Kenn Jacobsen - Nicholas Westby - Et. Al.",
|
||||
"authorUrl": "http://github.com/kgiszewski/archetype/",
|
||||
"license": "MIT",
|
||||
"licenseUrl": "http://opensource.org/licenses/MIT"
|
||||
}
|
||||
@@ -4,15 +4,15 @@
|
||||
<id>Archetype</id>
|
||||
<version><%= version %></version>
|
||||
<title><%= name %></title>
|
||||
<authors>imulus, kgiszewski, tomfulton</authors>
|
||||
<owners>imulus, kgiszewski, tomfulton</owners>
|
||||
<projectUrl>http://github.com/imulus/archetype</projectUrl>
|
||||
<authors>kgiszewski, tomfulton</authors>
|
||||
<owners>kgiszewski, tomfulton</owners>
|
||||
<projectUrl>http://github.com/kgiszewski/archetype</projectUrl>
|
||||
<description><![CDATA[Archetype for Umbraco]]></description>
|
||||
<tags>umbraco</tags>
|
||||
<iconUrl>http://github.com/imulus/archetype/raw/master/assets/logo.png</iconUrl>
|
||||
<iconUrl>http://kgiszewski.github.io/Archetype/images/logo.png</iconUrl>
|
||||
<licenseUrl><%= licenseUrl %></licenseUrl>
|
||||
<dependencies>
|
||||
<dependency id="Archetype.Binaries" version="<%= version %>" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
</package>
|
||||
</package>
|
||||
|
||||
@@ -4,15 +4,15 @@
|
||||
<id>Archetype.Binaries</id>
|
||||
<version><%= version %></version>
|
||||
<title><%= name %></title>
|
||||
<authors>imulus, kgiszewski, tomfulton</authors>
|
||||
<owners>imulus, kgiszewski, tomfulton</owners>
|
||||
<projectUrl>http://github.com/imulus/archetype</projectUrl>
|
||||
<authors>kgiszewski, tomfulton</authors>
|
||||
<owners>kgiszewski, tomfulton</owners>
|
||||
<projectUrl>http://github.com/kgiszewski/archetype</projectUrl>
|
||||
<description><![CDATA[Archetype binaries for Umbraco]]></description>
|
||||
<tags>umbraco</tags>
|
||||
<iconUrl>http://github.com/imulus/archetype/raw/master/assets/logo.png</iconUrl>
|
||||
<iconUrl>http://kgiszewski.github.io/Archetype/images/logo.png</iconUrl>
|
||||
<licenseUrl><%= licenseUrl %></licenseUrl>
|
||||
<dependencies>
|
||||
<dependency id="UmbracoCms.Core" version="7.2.2" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
</package>
|
||||
</package>
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
<title><%= name %></title>
|
||||
<authors>leekelleher</authors>
|
||||
<owners>kgiszewski, leekelleher</owners>
|
||||
<projectUrl>http://github.com/imulus/archetype</projectUrl>
|
||||
<projectUrl>http://github.com/kgiszewski/archetype</projectUrl>
|
||||
<description><![CDATA[Archetype Courier extension for Umbraco]]></description>
|
||||
<tags>umbraco</tags>
|
||||
<iconUrl>http://github.com/imulus/archetype/raw/master/assets/logo.png</iconUrl>
|
||||
<iconUrl>http://kgiszewski.github.io/Archetype/images/logo.png</iconUrl>
|
||||
<licenseUrl><%= licenseUrl %></licenseUrl>
|
||||
<dependencies>
|
||||
<dependency id="Archetype.Binaries" version="<%= version %>" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
</package>
|
||||
</package>
|
||||
|
||||
Reference in New Issue
Block a user