Compare commits

...

38 Commits

Author SHA1 Message Date
kgiszewski 8610f69c88 Bump version to v1.8 2015-06-04 13:26:19 -04:00
kgiszewski 34b4209de7 For some reason sorting the RTE reared its head again and I killed it (again). 2015-06-02 10:49:47 -04:00
Kevin Giszewski b6145c9275 Merge pull request #275 from imulus/feature/label-library
Allow args to be passed to label templates and begin label library
2015-06-01 13:54:43 -04:00
kgiszewski f51ca65659 Expose archetypePropertyEditorResource to controller 2015-06-01 13:53:18 -04:00
kgiszewski d026af9fd2 Expose archetypeCacheService on controller 2015-06-01 13:49:34 -04:00
kgiszewski 11fff5da1a Add media picker support 2015-06-01 13:43:42 -04:00
kgiszewski 788a5dd720 Wire up MNTP 2015-06-01 13:35:53 -04:00
kgiszewski 24e232b2cc Renaming binge 2015-06-01 12:12:33 -04:00
kgiszewski 5bdcb23933 Cache datatypes as they come back from server 2015-06-01 11:16:12 -04:00
kgiszewski 34b3ed3b47 Add archetypeCacheService 2015-06-01 10:13:29 -04:00
kgiszewski 50a486a9ac Discovered we should probably use a datatype cache based on the directive, so maybe a archetypeCacheService? 2015-06-01 10:09:22 -04:00
kgiszewski 4f4128a744 Fix some broken-ness 2015-06-01 10:02:32 -04:00
kgiszewski 4851797a83 Refactor a ton of things, add archetypeLabelService 2015-06-01 09:45:10 -04:00
kgiszewski 54a435dce7 Begin archetypeService 2015-05-29 08:55:08 -04:00
kgiszewski 03a170d716 Add RTE label template 2015-05-27 13:56:33 -04:00
kgiszewski 37976abc84 Handle arg detection better and change UrlPicker functionname 2015-05-27 13:47:23 -04:00
kgiszewski f7e96438be Handle null ref 2015-05-27 13:41:58 -04:00
kgiszewski f1c3caae2d Allow args to be passed to label templates and begin label library 2015-05-27 13:31:25 -04:00
kgiszewski 8f8078e12f Merge branch 'master' into pr/272 2015-05-26 08:33:34 -04:00
kgiszewski dbc9b872d8 Fix #274 2015-05-26 08:28:32 -04:00
Nicholas-Westby eef1b94586 Hide long fieldset headers with an ellipsis before overlapping buttons: https://github.com/imulus/Archetype/issues/271 2015-05-23 00:01:25 -07:00
kgiszewski 9bbf366fe2 Bump version to v1.7.5 2015-05-11 15:32:46 -04:00
kgiszewski 368a9f6c07 Fix for #268 2015-05-11 15:31:46 -04:00
kgiszewski d3b3f80f3d Add Umbraco as a dependency 2015-05-11 15:20:28 -04:00
kgiszewski 11f7881dd7 Merge branch 'master' of github.com:imulus/Archetype 2015-05-04 13:46:07 -04:00
kgiszewski 9894357469 Fix #268 (This is a temp fix until a better solution can be found) 2015-05-04 13:45:49 -04:00
kgiszewski 146a3770a1 Bump version to v1.7.4 2015-05-03 16:41:41 -04:00
kgiszewski caf9d1ac15 Fix grunt for debug 2015-04-29 08:53:18 -04:00
kgiszewski 614595ceb3 Finesse PR #269 2015-04-29 08:53:05 -04:00
kgiszewski d1b21a1ca7 Merge branch 'pr/269' 2015-04-29 08:13:40 -04:00
kgiszewski 54bc507049 Merge branch 'pr/267' 2015-04-29 08:12:56 -04:00
kgiszewski 037585458c Merge branch 'pr/266' 2015-04-29 08:12:15 -04:00
kgiszewski f52649eb9e Add Courier to the build process for distro 2015-04-29 08:08:08 -04:00
kgiszewski 423fedb954 Undo add Courier to distro per @leekelleher 's suggestion that it causes a ysod if Courier is not installed already 2015-04-29 07:46:37 -04:00
Kim Pilgaard b39312ccd2 Properties which no longer exist have no GUID. Remove these when reading and writing the data. 2015-04-29 08:56:17 +02:00
Gavin Faux b9c4be0bb6 PropertyEditorAlias null check
Don't try `PropertyValueConverters` for properties with null or empty
`PropertyEditorAlias`, prevents `System.NullReferenceException`  in
`PropertyValueConverter.IsConverter` implementations
2015-04-28 14:30:08 +01:00
Tom Van Rompaey 29285607a9 Small UX update for add button
Added class "archetypeAddButton" to the button so it can make use of the
CSS that is writen for it.
The button should also have a cursor: pointer on hover.
2015-04-25 16:16:04 +02:00
kgiszewski 909b87cea0 Add Courier dll to the distribution 2015-04-21 08:43:44 -04:00
18 changed files with 578 additions and 250 deletions
+11 -8
View File
@@ -57,10 +57,13 @@ module.exports = function(grunt) {
'app/directives/archetypeproperty.js',
'app/directives/archetypesubmitwatcher.js',
'app/directives/archetypecustomview.js',
'app/directives/localize.js',
'app/services/localization.js',
'app/helpers/labelhelpers.js',
'app/resources/propertyeditor.js'
'app/directives/archetypeLocalize.js',
'app/services/archetypeLocalizationService.js',
'app/helpers/sampleLabelHelpers.js',
'app/resources/archetypePropertyEditorResource.js',
'app/services/archetypeService.js',
'app/services/archetypeLabelService.js',
'app/services/archetypeCacheService.js'
],
dest: '<%= basePath %>/js/archetype.js'
}
@@ -74,7 +77,7 @@ module.exports = function(grunt) {
expand: true
},
dll: {
cwd: 'app/Umbraco/Umbraco.Archetype/bin/Release/',
cwd: 'app/Umbraco/Umbraco.Archetype/bin/Debug/',
src: 'Archetype.dll',
dest: '<%= dest %>/bin/',
expand: true
@@ -164,7 +167,7 @@ module.exports = function(grunt) {
assemblyinfo: {
options: {
files: ['app/Umbraco/Umbraco.Archetype/Archetype.Umbraco.csproj'],
files: ['app/Umbraco/Umbraco.Archetype/Archetype.Umbraco.csproj', 'app/Umbraco/Umbraco.Archetype/Archetype.Courier.csproj'],
filename: 'VersionInfo.cs',
info: {
version: '<%= (pkgMeta.version.indexOf("-") > 0 ? pkgMeta.version.substring(0, pkgMeta.version.indexOf("-")) : pkgMeta.version) %>',
@@ -200,9 +203,9 @@ module.exports = function(grunt) {
}
},
dist: {
src: ['app/Umbraco/Umbraco.Archetype/Archetype.Umbraco.csproj'],
src: ['app/Umbraco/Umbraco.Archetype/Archetype.Umbraco.csproj','app/Umbraco/Archetype.Courier/Archetype.Courier.csproj'],
options: {
projectConfiguration: 'Release',
projectConfiguration: 'Debug',
targets: ['Clean', 'Rebuild'],
}
}
@@ -34,7 +34,7 @@ namespace Archetype.Models
// Try Umbraco's PropertyValueConverters
var converters = UmbracoContext.Current != null ? PropertyValueConvertersResolver.Current.Converters : Enumerable.Empty<IPropertyValueConverter>();
if (converters.Any())
if (!string.IsNullOrWhiteSpace(this.PropertyEditorAlias) && converters.Any())
{
var convertedAttempt = TryConvertWithPropertyValueConverters<T>(Value, converters);
if (convertedAttempt.Success)
@@ -1,4 +1,4 @@
using System.Reflection;
[assembly: AssemblyVersion("1.7.3")]
[assembly: AssemblyFileVersion("1.7.3")]
[assembly: AssemblyVersion("1.8")]
[assembly: AssemblyFileVersion("1.8")]
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Archetype.Extensions;
using ClientDependency.Core;
using Newtonsoft.Json;
@@ -56,13 +57,11 @@ namespace Archetype.PropertyEditors
if (property.Value == null || property.Value.ToString() == "")
return string.Empty;
//LogHelper.Info<ArchetypeHelper>(property.Value.ToString());
var archetype = ArchetypeHelper.Instance.DeserializeJsonToArchetype(property.Value.ToString(), propertyType.DataTypeDefinitionId);
foreach (var fieldset in archetype.Fieldsets)
{
foreach (var propDef in fieldset.Properties)
foreach (var propDef in fieldset.Properties.Where(p => p.DataTypeGuid != null))
{
try
{
@@ -86,15 +85,13 @@ namespace Archetype.PropertyEditors
public override object ConvertDbToEditor(Property property, PropertyType propertyType, IDataTypeService dataTypeService)
{
if (property.Value == null || property.Value.ToString() == "")
return string.Empty;
//LogHelper.Info<ArchetypeHelper>(property.Value.ToString());
return string.Empty;;
var archetype = ArchetypeHelper.Instance.DeserializeJsonToArchetype(property.Value.ToString(), propertyType.DataTypeDefinitionId);
foreach (var fieldset in archetype.Fieldsets)
{
foreach (var propDef in fieldset.Properties)
foreach (var propDef in fieldset.Properties.Where(p => p.DataTypeGuid != null))
{
try
{
@@ -118,13 +115,11 @@ namespace Archetype.PropertyEditors
if (editorValue.Value == null || editorValue.Value.ToString() == "")
return string.Empty;
//LogHelper.Info<ArchetypeHelper>(editorValue.Value.ToString());
var archetype = ArchetypeHelper.Instance.DeserializeJsonToArchetype(editorValue.Value.ToString(), editorValue.PreValues);
foreach (var fieldset in archetype.Fieldsets)
{
foreach (var propDef in fieldset.Properties)
{
foreach (var propDef in fieldset.Properties.Where(p => p.DataTypeGuid != null))
{
try
{
+36 -69
View File
@@ -1,4 +1,4 @@
angular.module("umbraco").controller("Imulus.ArchetypeController", function ($scope, $http, assetsService, angularHelper, notificationsService, $timeout, entityResource) {
angular.module("umbraco").controller("Imulus.ArchetypeController", function ($scope, $http, assetsService, angularHelper, notificationsService, $timeout, entityResource, archetypeService, archetypeLabelService, archetypeCacheService, archetypePropertyEditorResource) {
//$scope.model.value = "";
$scope.model.hideLabel = $scope.model.config.hideLabel == 1;
@@ -17,92 +17,58 @@
init();
//hold references to helper resources
//hold references to helper resources
$scope.resources = {
entityResource: entityResource
entityResource: entityResource,
archetypePropertyEditorResource: archetypePropertyEditorResource
}
//hold references to helper services
$scope.services = {
archetypeService: archetypeService,
archetypeLabelService: archetypeLabelService,
archetypeCacheService: archetypeCacheService
}
//helper to get $eval the labelTemplate
$scope.getFieldsetTitle = function(fieldsetConfigModel, fieldsetIndex) {
if(!fieldsetConfigModel)
return "";
var fieldset = $scope.model.value.fieldsets[fieldsetIndex];
var fieldsetConfig = $scope.getConfigFieldsetByAlias(fieldset.alias);
var template = fieldsetConfigModel.labelTemplate;
if (template.length < 1)
return fieldsetConfig.label;
var rgx = /{{(.*?)}}*/g;
var results;
var parsedTemplate = template;
while ((results = rgx.exec(template)) !== null) {
// split the template in case it consists of multiple property aliases and/or functions
var parts = results[1].split("|");
var templateLabelValue = "";
for(var i = 0; i < parts.length; i++) {
// stop looking for a template label value if a previous template part already yielded a value
if(templateLabelValue != "") {
break;
}
var part = parts[i];
//test for function
var beginIndexOf = part.indexOf("(");
var endIndexOf = part.indexOf(")");
if(beginIndexOf != -1 && endIndexOf != -1)
{
var functionName = part.substring(0, beginIndexOf);
var propertyAlias = part.substring(beginIndexOf + 1, endIndexOf);
templateLabelValue = executeFunctionByName(functionName, window, $scope.getPropertyValueByAlias(fieldset, propertyAlias), $scope);
}
else {
propertyAlias = part;
templateLabelValue = $scope.getPropertyValueByAlias(fieldset, propertyAlias);
}
}
parsedTemplate = parsedTemplate.replace(results[0], templateLabelValue);
}
return parsedTemplate;
};
function executeFunctionByName(functionName, context) {
var args = Array.prototype.slice.call(arguments).splice(2);
var namespaces = functionName.split(".");
var func = namespaces.pop();
for(var i = 0; i < namespaces.length; i++) {
context = context[namespaces[i]];
}
if(context && context[func]) {
return context[func].apply(this, args);
}
return "";
$scope.getFieldsetTitle = function (fieldsetConfigModel, fieldsetIndex) {
return archetypeLabelService.getFieldsetTitle($scope, fieldsetConfigModel, fieldsetIndex);
}
var draggedRteSettings;
var rteClass = ".mce-tinymce";
//sort config
$scope.sortableOptions = {
axis: 'y',
cursor: "move",
handle: ".handle",
start: function(ev, ui) {
ui.item.parent().find('.umb-rte textarea').each(function () {
tinyMCE.execCommand('mceRemoveEditor', false, $(this).attr('id'));
draggedRteSettings = {};
ui.item.parent().find(rteClass).each(function () {
// remove all RTEs in the dragged row and save their settings
var $element = $(this);
var wrapperId = $element.attr('id');
var $textarea = $element.siblings('textarea');
var textareaId = $textarea.attr('id');
draggedRteSettings[textareaId] = _.findWhere(tinyMCE.editors, { id: textareaId }).settings;
tinyMCE.execCommand('mceRemoveEditor', false, wrapperId);
});
},
update: function (ev, ui) {
$scope.setDirty();
},
stop: function (ev, ui) {
ui.item.parent().find('.umb-rte textarea').each(function () {
tinyMCE.execCommand('mceAddEditor', false, $(this).attr('id'));
ui.item.parent().find(rteClass).each(function () {
var $element = $(this);
var wrapperId = $element.attr('id');
var $textarea = $element.siblings('textarea');
var textareaId = $textarea.attr('id');
draggedRteSettings[textareaId] = draggedRteSettings[textareaId] || _.findWhere(tinyMCE.editors, { id: textareaId }).settings;
tinyMCE.execCommand('mceRemoveEditor', false, wrapperId);
tinyMCE.init(draggedRteSettings[textareaId]);
});
}
};
@@ -134,6 +100,7 @@
if (confirm('Are you sure you want to remove this?')) {
$scope.setDirty();
$scope.model.value.fieldsets.splice($index, 1);
$scope.$broadcast("archetypeRemoveFieldset", {index: $index});
}
}
}
+29 -98
View File
@@ -1,75 +1,33 @@
angular.module("umbraco.directives").directive('archetypeProperty', function ($compile, $http, archetypePropertyEditorResource, umbPropEditorHelper, $timeout, $rootScope, $q, editorState) {
function getFieldsetByAlias(fieldsets, alias)
{
return _.find(fieldsets, function(fieldset){
return fieldset.alias == alias;
});
}
function getPropertyIndexByAlias(properties, alias){
for (var i in properties)
{
if (properties[i].alias == alias) {
return i;
}
}
}
function getPropertyByAlias(fieldset, alias){
return _.find(fieldset.properties, function(property){
return property.alias == alias;
});
}
//helper that returns a JS ojbect from 'value' string or the original string
function jsonOrString(value, developerMode, debugLabel){
if(value && typeof value == 'string'){
try{
if(developerMode == '1'){
console.log("Trying to parse " + debugLabel + ": " + value);
}
value = JSON.parse(value);
}
catch(exception)
{
if(developerMode == '1'){
console.log("Failed to parse " + debugLabel + ".");
}
}
}
if(value && developerMode == '1'){
console.log(debugLabel + " post-parsing: ");
console.log(value);
}
return value;
}
angular.module("umbraco.directives").directive('archetypeProperty', function ($compile, $http, archetypePropertyEditorResource, umbPropEditorHelper, $timeout, $rootScope, $q, editorState, archetypeService, archetypeCacheService) {
var linker = function (scope, element, attrs, ngModelCtrl) {
var configFieldsetModel = getFieldsetByAlias(scope.archetypeConfig.fieldsets, scope.fieldset.alias);
var configFieldsetModel = archetypeService.getFieldsetByAlias(scope.archetypeConfig.fieldsets, scope.fieldset.alias);
var view = "";
var label = configFieldsetModel.properties[scope.propertyConfigIndex].label;
var dataTypeGuid = configFieldsetModel.properties[scope.propertyConfigIndex].dataTypeGuid;
var config = null;
var alias = configFieldsetModel.properties[scope.propertyConfigIndex].alias;
var defaultValue = configFieldsetModel.properties[scope.propertyConfigIndex].value;
var propertyAlias = getUniquePropertyAlias(scope);
propertyAliasParts = [];
var propertyAliasParts = [];
var propertyAlias = archetypeService.getUniquePropertyAlias(scope, propertyAliasParts);
//try to convert the defaultValue to a JS object
defaultValue = jsonOrString(defaultValue, scope.archetypeConfig.developerMode, "defaultValue");
defaultValue = archetypeService.jsonOrString(defaultValue, scope.archetypeConfig.developerMode, "defaultValue");
//grab info for the selected datatype, prepare for view
archetypePropertyEditorResource.getDataType(dataTypeGuid, scope.archetypeConfig.enableDeepDatatypeRequests, editorState.current.contentTypeAlias, scope.propertyEditorAlias, alias, editorState.current.id).then(function (data) {
//transform preValues array into object expected by propertyeditor views
var configObj = {};
_.each(data.preValues, function(p) {
configObj[p.key] = p.value;
});
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);
@@ -92,16 +50,15 @@ angular.module("umbraco.directives").directive('archetypeProperty', function ($c
validateProperty(scope.fieldset, property);
});
// set invalid state if the fieldset contains invalid properties
// we need an unique validation key per fieldset in this ngModelCtrl scope, which leaves us with a potential problem:
// if the user invalidates the last fieldset, attempts (and fails) to save and and subsequently deletes the invalid fieldset,
// the validation key will persist on ngModelCtrl and thus the form will not submit.
// to fix this problem, the controller probably needs to raise an event (in removeRow) that can be intercepted here to
// clear the validation key.
var validationKey = "validation-f" + scope.fieldsetIndex;
ngModelCtrl.$setValidity(validationKey, scope.fieldset.isValid);
});
scope.$on("archetypeRemoveFieldset", function (ev, args) {
var validationKey = "validation-f" + args.index;
ngModelCtrl.$setValidity(validationKey, true);
});
// called when the value of any property in a fieldset changes
function propertyValueChanged(fieldset, property) {
@@ -112,7 +69,7 @@ angular.module("umbraco.directives").directive('archetypeProperty', function ($c
// validate a property in a fieldset
function validateProperty(fieldset, property) {
var propertyConfig = getPropertyByAlias(configFieldsetModel, property.alias);
var propertyConfig = archetypeService.getPropertyByAlias(configFieldsetModel, property.alias);
if (propertyConfig) {
// use property.value !== property.value to check for NaN values on numeric inputs
if (propertyConfig.required && (property.value == null || property.value === "" || property.value !== property.value)) {
@@ -140,33 +97,6 @@ angular.module("umbraco.directives").directive('archetypeProperty', function ($c
}
}
var propertyAliasParts = [];
var getUniquePropertyAlias = function (currentScope) {
if (currentScope.hasOwnProperty('fieldsetIndex') && currentScope.hasOwnProperty('property') && currentScope.hasOwnProperty('propertyConfigIndex'))
{
var currentPropertyAlias = "f" + currentScope.fieldsetIndex + "-" + currentScope.property.alias + "-p" + currentScope.propertyConfigIndex;
propertyAliasParts.push(currentPropertyAlias);
}
else if (currentScope.hasOwnProperty('isPreValue')) // Crappy way to identify this is the umbraco property scope
{
var umbracoPropertyAlias = currentScope.$parent.$parent.property.alias; // Crappy way to get the umbraco host alias once we identify its scope
propertyAliasParts.push(umbracoPropertyAlias);
}
if (currentScope.$parent)
getUniquePropertyAlias(currentScope.$parent);
return _.unique(propertyAliasParts).reverse().join("-");
};
var getFieldset = function(scope) {
return scope.archetypeRenderModel.fieldsets[scope.fieldsetIndex];
}
var getFieldsetProperty = function (scope) {
return getFieldset(scope).properties[scope.renderModelPropertyIndex];
}
function loadView(view, config, defaultValue, alias, propertyAlias, scope, element, ngModelCtrl, propertyValueChanged) {
if (view)
{
@@ -183,15 +113,15 @@ angular.module("umbraco.directives").directive('archetypeProperty', function ($c
scope.model.config = {};
//ini the property value after test to make sure a prop exists in the renderModel
scope.renderModelPropertyIndex = getPropertyIndexByAlias(getFieldset(scope).properties, alias);
scope.renderModelPropertyIndex = archetypeService.getPropertyIndexByAlias(archetypeService.getFieldset(scope).properties, alias);
if (!scope.renderModelPropertyIndex)
{
getFieldset(scope).properties.push(JSON.parse('{"alias": "' + alias + '", "value": "' + defaultValue + '"}'));
scope.renderModelPropertyIndex = getPropertyIndexByAlias(getFieldset(scope).properties, alias);
archetypeService.getFieldset(scope).properties.push(JSON.parse('{"alias": "' + alias + '", "value": "' + defaultValue + '"}'));
scope.renderModelPropertyIndex = archetypeService.getPropertyIndexByAlias(archetypeService.getFieldset(scope).properties, alias);
}
scope.renderModel = {};
scope.model.value = getFieldsetProperty(scope).value;
scope.model.value = archetypeService.getFieldsetProperty(scope).value;
//set the config from the prevalues
scope.model.config = config;
@@ -211,27 +141,28 @@ angular.module("umbraco.directives").directive('archetypeProperty', function ($c
}
}
//console.log(scope.model.config);
//some items need an alias
scope.model.alias = "archetype-property-" + propertyAlias;
//watch for changes since there is no two-way binding with the local model.value
scope.$watch('model.value', function (newValue, oldValue) {
getFieldsetProperty(scope).value = newValue;
archetypeService.getFieldsetProperty(scope).value = newValue;
// notify the linker that the property value changed
propertyValueChanged(getFieldset(scope), getFieldsetProperty(scope));
propertyValueChanged(archetypeService.getFieldset(scope), archetypeService.getFieldsetProperty(scope));
});
scope.$on('archetypeFormSubmitting', function (ev, args) {
// did the value change (if it did, it most likely did so during the "formSubmitting" event)
var currentValue = getFieldsetProperty(scope).value;
var property = archetypeService.getFieldsetProperty(scope);
var currentValue = property.value;
if (currentValue != scope.model.value) {
getFieldsetProperty(scope).value = scope.model.value;
archetypeService.getFieldsetProperty(scope).value = scope.model.value;
// notify the linker that the property value changed
propertyValueChanged(getFieldset(scope), getFieldsetProperty(scope));
propertyValueChanged(archetypeService.getFieldset(scope), archetypeService.getFieldsetProperty(scope));
}
});
-41
View File
@@ -1,41 +0,0 @@
var ArchetypeLabels = (function() {
var isEntityLookupLoading = false;
var entityNameLookupCache = [];
function getEntityById(scope, id, type) {
for (var i in entityNameLookupCache) {
if (entityNameLookupCache[i].id == id) {
return entityNameLookupCache[i].value;
}
}
if (!isEntityLookupLoading) {
isEntityLookupLoading = true;
scope.resources.entityResource.getById(id, type).then(function(entity) {
entityNameLookupCache.push({id: id, value: entity.name});
isEntityLookupLoading = false;
return entity.name;
});
}
return "";
}
return {
GetFirstDocumentEntityName: function ($scope, value) {
if (value) {
var id = value.split(",")[0];
if (id) {
return getEntityById($scope, id, "Document");
}
}
return "";
}
}
})();
+70
View File
@@ -0,0 +1,70 @@
var ArchetypeSampleLabelTemplates = (function() {
//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.archetypeLabelService.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.archetypeLabelService.getEntityById(scope, value.typeData.contentId, "Document");
}
break;
case "media":
if(value.typeData.mediaId) {
entity = scope.services.archetypeLabelService.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);
}
}
})();
+19 -6
View File
@@ -2,11 +2,11 @@
.archetypeEditor {
width: 98%;
.open {
position: relative;
}
.dropdown-menu {
top: auto;
> li > a {
@@ -25,7 +25,12 @@
.icon {
color: #333;
}
.fieldsetIcon {
float: left;
padding-right: 4px;
}
fieldset {
border: 1px solid #dddddd;
padding: 0;
@@ -56,9 +61,10 @@
.archetypeFieldsetLabel {
position: relative;
width: 100%;
min-height: 42px;
.label-sub {
padding: 8px 0;
padding: 8px 0 4px 0;
display: inline-block;
&.module-label {
width: 100%;
@@ -98,6 +104,7 @@
.caret {
margin: 8px 1px 0 15px;
position: absolute;
&.caret-right {
border-bottom: 4px solid transparent;
@@ -110,10 +117,15 @@
label {
margin-bottom: 0;
margin-left: 5px;
margin-left: 38px;
white-space: nowrap;
padding: 0;
width: ~"calc(100% - 132px)";
position: absolute;
span {
display: inline-block;
display: block;
overflow: hidden;
text-overflow: ellipsis;
}
&.dimmed {
color: #d9d9d9;
@@ -181,6 +193,7 @@
.archetypeAddButton:hover {
text-decoration: none;
cursor: pointer;
.archetypeAddButtonText {
text-decoration: underline;
+77
View File
@@ -0,0 +1,77 @@
angular.module('umbraco.services').factory('archetypeCacheService', function (archetypePropertyEditorResource) {
//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);
}
},
getDatatypeByGuid: function(guid) {
var cachedDatatype = this.getDataTypeFromCache(guid);
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;
},
getEntityById: function(scope, id, type) {
var cachedEntity = _.find(entityCache, function (e){
return e.id == id;
});
if(cachedEntity) {
return cachedEntity;
}
//go get it from server
if (!isEntityLookupLoading) {
isEntityLookupLoading = true;
scope.resources.entityResource.getById(id, type).then(function(entity) {
entityCache.push(entity);
isEntityLookupLoading = false;
return entity;
});
}
return null;
}
}
});
+238
View File
@@ -0,0 +1,238 @@
angular.module('umbraco.services').factory('archetypeLabelService', function (archetypeCacheService) {
//private
var isEntityLookupLoading = false;
var entityCache = [];
var isDatatypeLookupLoading = false;
var datatypeCache = [];
function executeFunctionByName(functionName, context) {
var args = Array.prototype.slice.call(arguments).splice(2);
var namespaces = functionName.split(".");
var func = namespaces.pop();
for(var i = 0; i < namespaces.length; i++) {
context = context[namespaces[i]];
}
if(context && context[func]) {
return context[func].apply(this, args);
}
return "";
}
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.MediaPicker":
return coreMediaPicker(value, scope, datatype);
default:
return "";
}
}
function coreMntp(value, scope, args) {
var ids = value.split(',');
var type = "Document";
switch(args.preValues[0].value.type) {
case 'content':
type = 'Document';
break;
case 'media':
type = 'media';
break;
case 'member':
type = 'member';
break;
default:
break;
}
var entityArray = [];
_.each(ids, function(id){
if(id) {
var entity = archetypeCacheService.getEntityById(scope, id, type);
if(entity) {
entityArray.push(entity.name);
}
}
});
return entityArray.join(', ');
}
function coreMediaPicker(value, scope, args) {
if(value) {
var entity = archetypeCacheService.getEntityById(scope, value, "media");
if(entity) {
return entity.name;
}
}
return "";
}
function imulusUrlPicker(value, scope, args) {
if(!args.propertyName) {
args = {propertyName: "name"}
}
var entity;
switch (value.type) {
case "content":
if(value.typeData.contentId) {
entity = archetypeCacheService.getEntityById(scope, value.typeData.contentId, "Document");
}
break;
case "media":
if(value.typeData.mediaId) {
entity = archetypeCacheService.getEntityById(scope, value.typeData.mediaId, "Media");
}
break;
case "url":
return value.typeData.url;
default:
break;
}
if(entity) {
return entity[args.propertyName];
}
return "";
}
function coreTinyMce(value, scope, args) {
if(!args.contentLength) {
args = {contentLength: 50}
}
var suffix = "";
var strippedText = $(value).text();
if(strippedText.length > args.contentLength) {
suffix = "…";
}
return strippedText.substring(0, args.contentLength) + suffix;
}
return {
getFieldsetTitle: function(scope, fieldsetConfigModel, fieldsetIndex) {
//console.log(scope.model.config);
if(!fieldsetConfigModel)
return "";
var fieldset = scope.model.value.fieldsets[fieldsetIndex];
var fieldsetConfig = scope.getConfigFieldsetByAlias(fieldset.alias);
var template = fieldsetConfigModel.labelTemplate;
if (template.length < 1)
return fieldsetConfig.label;
var rgx = /{{([^)].*)}}/g;
var results;
var parsedTemplate = template;
while ((results = rgx.exec(template)) !== null) {
// split the template in case it consists of multiple property aliases and/or functions
var templates = results[0].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 != "") {
break;
}
var template = templates[i];
//test for function
var beginParamsIndexOf = template.indexOf("(");
var endParamsIndexOf = template.indexOf(")");
//if passed a function
if(beginParamsIndexOf != -1 && endParamsIndexOf != -1)
{
var functionName = template.substring(0, beginParamsIndexOf);
var propertyAlias = template.substring(beginParamsIndexOf + 1, endParamsIndexOf).split(',')[0];
var args = {};
var beginArgsIndexOf = template.indexOf(',');
if(beginArgsIndexOf != -1) {
var argsString = template.substring(beginArgsIndexOf + 1, endParamsIndexOf).trim();
var normalizedJsonString = argsString.replace(/(\w+)\s*:/g, '"$1":');
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;
});
if(propertyConfig) {
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;
}
}
}
else {
return templateLabelValue;
}
}
}
parsedTemplate = parsedTemplate.replace(results[0], templateLabelValue);
}
return parsedTemplate;
}
}
});
+72
View File
@@ -0,0 +1,72 @@
angular.module('umbraco.services').factory('archetypeService', function () {
//public
return {
//helper that returns a JS ojbect from 'value' string or the original string
jsonOrString: function (value, developerMode, debugLabel){
if(value && typeof value == 'string'){
try{
if(developerMode == '1'){
console.log("Trying to parse " + debugLabel + ": " + value);
}
value = JSON.parse(value);
}
catch(exception)
{
if(developerMode == '1'){
console.log("Failed to parse " + debugLabel + ".");
}
}
}
if(value && developerMode == '1'){
console.log(debugLabel + " post-parsing: ");
console.log(value);
}
return value;
},
getFieldsetByAlias: function (fieldsets, alias)
{
return _.find(fieldsets, function(fieldset){
return fieldset.alias == alias;
});
},
getPropertyIndexByAlias: function(properties, alias){
for (var i in properties)
{
if (properties[i].alias == alias) {
return i;
}
}
},
getPropertyByAlias: function (fieldset, alias){
return _.find(fieldset.properties, function(property){
return property.alias == alias;
});
},
getUniquePropertyAlias: function (currentScope, propertyAliasParts) {
if (currentScope.hasOwnProperty('fieldsetIndex') && currentScope.hasOwnProperty('property') && currentScope.hasOwnProperty('propertyConfigIndex'))
{
var currentPropertyAlias = "f" + currentScope.fieldsetIndex + "-" + currentScope.property.alias + "-p" + currentScope.propertyConfigIndex;
propertyAliasParts.push(currentPropertyAlias);
}
else if (currentScope.hasOwnProperty('isPreValue')) // Crappy way to identify this is the umbraco property scope
{
var umbracoPropertyAlias = currentScope.$parent.$parent.property.alias; // Crappy way to get the umbraco host alias once we identify its scope
propertyAliasParts.push(umbracoPropertyAlias);
}
if (currentScope.$parent)
this.getUniquePropertyAlias(currentScope.$parent, propertyAliasParts);
return _.unique(propertyAliasParts).reverse().join("-");
},
getFieldset: function(scope) {
return scope.archetypeRenderModel.fieldsets[scope.fieldsetIndex];
},
getFieldsetProperty: function (scope) {
return this.getFieldset(scope).properties[scope.renderModelPropertyIndex];
}
}
});
+1 -1
View File
@@ -49,7 +49,7 @@
</li>
</ul>
<div ng-show="showAddButton()">
<a data-toggle="{{ model.config.fieldsets.length > 1 ? 'dropdown' : ''}}" ng-click="model.config.fieldsets.length == 1 ? addRow(model.config.fieldsets[0].alias, 0) : return" prevent-default>
<a class="archetypeAddButton" data-toggle="{{ model.config.fieldsets.length > 1 ? 'dropdown' : ''}}" ng-click="model.config.fieldsets.length == 1 ? addRow(model.config.fieldsets[0].alias, 0) : return" prevent-default>
<i class="icon icon-add dropdown-toggle"></i>
<localize key="general_add" class="archetypeAddButtonText">Add</localize>
</a>
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "Archetype",
"version": "1.7.3",
"version": "1.8",
"url": "http://github.com/imulus/archetype/",
"author": "Imulus - Kevin Giszewski - Tom Fulton - Lee Kelleher - Matt Brailsford - Kenn Jacobsen - Et. Al.",
"authorUrl": "http://imulus.com/",
+15 -12
View File
@@ -1,15 +1,18 @@
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<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>
<description><![CDATA[Archetype for Umbraco]]></description>
<tags>umbraco</tags>
<iconUrl>http://github.com/imulus/archetype/raw/master/assets/logo.png</iconUrl>
<licenseUrl><%= licenseUrl %></licenseUrl>
</metadata>
<metadata>
<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>
<description><![CDATA[Archetype for Umbraco]]></description>
<tags>umbraco</tags>
<iconUrl>http://github.com/imulus/archetype/raw/master/assets/logo.png</iconUrl>
<licenseUrl><%= licenseUrl %></licenseUrl>
<dependencies>
<dependency id="UmbracoCms.Core" version="7.1.6" />
</dependencies>
</metadata>
</package>