2014-01-15 17:31:31 -05:00
|
|
|
angular.module("umbraco").controller("Imulus.ArchetypeController", function ($scope, $http, $interpolate, assetsService, angularHelper, notificationsService) {
|
2014-01-13 12:47:21 -05:00
|
|
|
|
2014-01-10 17:20:35 -07:00
|
|
|
//$scope.model.value = "";
|
|
|
|
|
//set default value of the model
|
|
|
|
|
//this works by checking to see if there is a model; then cascades to the default model then to an empty fieldset
|
|
|
|
|
|
2014-01-15 17:31:31 -05:00
|
|
|
var form = angularHelper.getCurrentForm($scope);
|
|
|
|
|
|
2014-01-14 17:30:10 -05:00
|
|
|
$scope.model.config = $scope.model.config.archetypeConfig;
|
2014-01-14 12:10:26 -05:00
|
|
|
|
2014-01-16 13:42:08 -05:00
|
|
|
$scope.model.value = $scope.model.value || { fieldsets: [getEmptyRenderFieldset($scope.model.config.fieldsets[0])] };
|
2014-01-10 17:20:35 -07:00
|
|
|
|
|
|
|
|
//ini
|
|
|
|
|
$scope.archetypeRenderModel = {};
|
|
|
|
|
initArchetypeRenderModel();
|
2014-01-16 14:23:02 -05:00
|
|
|
|
2014-01-16 19:43:15 -05:00
|
|
|
//helper to get $eval the labelTemplate
|
2014-01-15 23:27:33 -07:00
|
|
|
$scope.getFieldsetTitle = function(fieldsetConfigModel, fieldsetIndex) {
|
|
|
|
|
var fieldset = $scope.archetypeRenderModel.fieldsets[fieldsetIndex];
|
2014-01-16 19:43:15 -05:00
|
|
|
var template = fieldsetConfigModel.labelTemplate;
|
2014-01-15 23:27:33 -07:00
|
|
|
var rgx = /{{(.*?)}}*/g;
|
|
|
|
|
var results;
|
|
|
|
|
var parsedTemplate = template;
|
|
|
|
|
|
|
|
|
|
while ((results = rgx.exec(template)) !== null) {
|
|
|
|
|
var propertyAlias = results[1];
|
|
|
|
|
var propertyValue = $scope.getPropertyValueByAlias(fieldset, propertyAlias);
|
|
|
|
|
parsedTemplate = parsedTemplate.replace(results[0], propertyValue);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return parsedTemplate;
|
|
|
|
|
};
|
2014-01-10 17:20:35 -07:00
|
|
|
|
|
|
|
|
/* add/remove/sort */
|
|
|
|
|
|
|
|
|
|
//defines the options for the jquery sortable
|
|
|
|
|
//i used an ng-model="archetypeRenderModel" so the sort updates the right model
|
2014-01-14 17:30:10 -05:00
|
|
|
$scope.sortableOptions = {
|
2014-01-10 17:20:35 -07:00
|
|
|
axis: 'y',
|
|
|
|
|
cursor: "move",
|
|
|
|
|
handle: ".handle",
|
|
|
|
|
update: function (ev, ui) {
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
|
stop: function (ev, ui) {
|
2014-01-12 14:05:39 -05:00
|
|
|
|
2014-01-10 17:20:35 -07:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2014-01-12 14:05:39 -05:00
|
|
|
//handles a fieldset add
|
|
|
|
|
$scope.addRow = function (fieldsetAlias, $index) {
|
|
|
|
|
if ($scope.canAdd())
|
2014-01-10 17:20:35 -07:00
|
|
|
{
|
2014-01-14 17:30:10 -05:00
|
|
|
if ($scope.model.config.fieldsets)
|
2014-01-10 17:20:35 -07:00
|
|
|
{
|
2014-01-16 13:42:08 -05:00
|
|
|
var newFieldset = getEmptyRenderFieldset($scope.getConfigFieldsetByAlias(fieldsetAlias));
|
2014-01-12 14:05:39 -05:00
|
|
|
|
|
|
|
|
if (typeof $index != 'undefined')
|
|
|
|
|
{
|
2014-01-14 20:09:45 -05:00
|
|
|
$scope.archetypeRenderModel.fieldsets.splice($index + 1, 0, newFieldset);
|
2014-01-12 14:05:39 -05:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2014-01-14 20:09:45 -05:00
|
|
|
$scope.archetypeRenderModel.fieldsets.push(newFieldset);
|
2014-01-12 14:05:39 -05:00
|
|
|
}
|
2014-01-10 17:20:35 -07:00
|
|
|
}
|
2014-01-14 20:09:45 -05:00
|
|
|
newFieldset.collapse = true;
|
|
|
|
|
$scope.focusFieldset(newFieldset);
|
2014-01-10 17:20:35 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//rather than splice the archetypeRenderModel, we're hiding this and cleaning onFormSubmitting
|
|
|
|
|
$scope.removeRow = function ($index) {
|
|
|
|
|
if ($scope.canRemove()) {
|
|
|
|
|
if (confirm('Are you sure you want to remove this?')) {
|
|
|
|
|
$scope.archetypeRenderModel.fieldsets[$index].remove = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//helpers for determining if a user can do something
|
|
|
|
|
$scope.canAdd = function ()
|
|
|
|
|
{
|
2014-01-14 17:30:10 -05:00
|
|
|
if ($scope.model.config.maxFieldsets)
|
2014-01-10 17:20:35 -07:00
|
|
|
{
|
2014-01-14 17:30:10 -05:00
|
|
|
return countVisible() < $scope.model.config.maxFieldsets;
|
2014-01-10 17:20:35 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-12 14:05:39 -05:00
|
|
|
//helper that returns if an item can be removed
|
2014-01-10 17:20:35 -07:00
|
|
|
$scope.canRemove = function ()
|
|
|
|
|
{
|
|
|
|
|
return countVisible() > 1;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-12 14:05:39 -05:00
|
|
|
//helper that returns if an item can be sorted
|
2014-01-10 17:20:35 -07:00
|
|
|
$scope.canSort = function ()
|
|
|
|
|
{
|
|
|
|
|
return countVisible() > 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//helper, ini the render model from the server (model.value)
|
|
|
|
|
function initArchetypeRenderModel() {
|
|
|
|
|
$scope.archetypeRenderModel = $scope.model.value;
|
2014-01-16 12:37:01 -05:00
|
|
|
|
|
|
|
|
_.each($scope.archetypeRenderModel.fieldsets, function (fieldset)
|
2014-01-14 17:30:10 -05:00
|
|
|
{
|
2014-01-16 12:37:01 -05:00
|
|
|
fieldset.remove = false;
|
|
|
|
|
fieldset.collapse = false;
|
|
|
|
|
fieldset.isValid = true;
|
|
|
|
|
});
|
2014-01-10 17:20:35 -07:00
|
|
|
}
|
|
|
|
|
|
2014-01-12 14:05:39 -05:00
|
|
|
//helper to get the correct fieldset from config
|
|
|
|
|
$scope.getConfigFieldsetByAlias = function(alias) {
|
2014-01-16 12:37:01 -05:00
|
|
|
return _.find($scope.model.config.fieldsets, function(fieldset){
|
|
|
|
|
return fieldset.alias == alias;
|
|
|
|
|
});
|
2014-01-12 14:05:39 -05:00
|
|
|
}
|
2014-01-15 23:27:33 -07:00
|
|
|
|
|
|
|
|
//helper to get a property by alias from a fieldset
|
|
|
|
|
$scope.getPropertyValueByAlias = function(fieldset, propertyAlias) {
|
|
|
|
|
var property = _.find(fieldset.properties, function(p) {
|
|
|
|
|
return p.alias == propertyAlias;
|
|
|
|
|
});
|
|
|
|
|
return (typeof property !== 'undefined') ? property.value : '';
|
|
|
|
|
};
|
2014-01-14 17:30:10 -05:00
|
|
|
|
|
|
|
|
//helper for collapsing
|
|
|
|
|
$scope.focusFieldset = function(fieldset){
|
2014-01-14 20:09:45 -05:00
|
|
|
|
2014-01-14 17:30:10 -05:00
|
|
|
var iniState;
|
|
|
|
|
|
|
|
|
|
if(fieldset)
|
|
|
|
|
{
|
|
|
|
|
iniState = fieldset.collapse;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-16 12:37:01 -05:00
|
|
|
_.each($scope.archetypeRenderModel.fieldsets, function(fieldset){
|
|
|
|
|
if($scope.archetypeRenderModel.fieldsets.length == 1 && fieldset.remove == false)
|
2014-01-14 20:09:45 -05:00
|
|
|
{
|
2014-01-16 12:37:01 -05:00
|
|
|
fieldset.collapse = false;
|
2014-01-14 20:09:45 -05:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-16 12:37:01 -05:00
|
|
|
fieldset.collapse = true;
|
|
|
|
|
});
|
2014-01-14 17:30:10 -05:00
|
|
|
|
|
|
|
|
if(iniState)
|
|
|
|
|
{
|
|
|
|
|
fieldset.collapse = !iniState;
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-01-14 20:09:45 -05:00
|
|
|
|
|
|
|
|
//ini
|
|
|
|
|
$scope.focusFieldset();
|
2014-01-12 14:05:39 -05:00
|
|
|
|
2014-01-10 17:20:35 -07:00
|
|
|
//helper returns valid JS or null
|
|
|
|
|
function getValidJson(variable, json)
|
|
|
|
|
{
|
|
|
|
|
if(!json) return null;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
return eval("(" + json + ")");
|
|
|
|
|
}
|
|
|
|
|
catch (e) {
|
|
|
|
|
console.log("There was an error while using 'eval' on " + variable);
|
|
|
|
|
console.log(json);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//developerMode helpers
|
|
|
|
|
$scope.archetypeRenderModel.toString = stringify;
|
|
|
|
|
|
2014-01-12 14:05:39 -05:00
|
|
|
//encapsulate stringify (should be built into browsers, not sure of IE support)
|
2014-01-10 17:20:35 -07:00
|
|
|
function stringify() {
|
|
|
|
|
return JSON.stringify(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//watch for changes
|
|
|
|
|
$scope.$watch('archetypeRenderModel', function (v) {
|
|
|
|
|
if ($scope.model.config.developerMode) {
|
2014-01-14 12:10:26 -05:00
|
|
|
console.log(v);
|
2014-01-10 17:20:35 -07:00
|
|
|
if (typeof v === 'string') {
|
|
|
|
|
$scope.archetypeRenderModel = JSON.parse(v);
|
|
|
|
|
$scope.archetypeRenderModel.toString = stringify;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
//helper to count what is visible
|
|
|
|
|
function countVisible()
|
|
|
|
|
{
|
|
|
|
|
var count = 0;
|
|
|
|
|
|
2014-01-16 12:37:01 -05:00
|
|
|
_.each($scope.archetypeRenderModel.fieldsets, function(fieldset){
|
|
|
|
|
if (fieldset.remove == false) {
|
2014-01-10 17:20:35 -07:00
|
|
|
count++;
|
|
|
|
|
}
|
2014-01-16 12:37:01 -05:00
|
|
|
});
|
2014-01-10 17:20:35 -07:00
|
|
|
|
|
|
|
|
return count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//helper to sync the model to the renderModel
|
|
|
|
|
function syncModelToRenderModel()
|
|
|
|
|
{
|
|
|
|
|
$scope.model.value = { fieldsets: [] };
|
|
|
|
|
|
2014-01-16 12:37:01 -05:00
|
|
|
_.each($scope.archetypeRenderModel.fieldsets, function(fieldset){
|
2014-01-15 20:23:59 -05:00
|
|
|
if (typeof fieldset != 'function' && !fieldset.remove){
|
2014-01-16 12:37:01 -05:00
|
|
|
|
|
|
|
|
//clone and clean
|
2014-01-15 20:23:59 -05:00
|
|
|
var tempFieldset = JSON.parse(JSON.stringify(fieldset));
|
2014-01-14 17:30:10 -05:00
|
|
|
delete tempFieldset.remove;
|
2014-01-15 20:23:59 -05:00
|
|
|
delete tempFieldset.isValid;
|
2014-01-16 12:37:01 -05:00
|
|
|
delete tempFieldset.collapse;
|
|
|
|
|
|
|
|
|
|
_.each(tempFieldset.properties, function(property){
|
|
|
|
|
delete property.isValid;
|
|
|
|
|
});
|
|
|
|
|
|
2014-01-14 17:30:10 -05:00
|
|
|
$scope.model.value.fieldsets.push(tempFieldset);
|
2014-01-10 17:20:35 -07:00
|
|
|
}
|
2014-01-16 12:37:01 -05:00
|
|
|
});
|
2014-01-10 17:20:35 -07:00
|
|
|
}
|
|
|
|
|
|
2014-01-12 14:05:39 -05:00
|
|
|
//helper to add an empty fieldset
|
2014-01-16 13:42:08 -05:00
|
|
|
function getEmptyRenderFieldset (fieldsetModel)
|
2014-01-12 14:05:39 -05:00
|
|
|
{
|
|
|
|
|
return eval("({ alias: '" + fieldsetModel.alias + "', remove: false, properties: []})");
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-15 17:31:31 -05:00
|
|
|
//helper for validation
|
|
|
|
|
function getValidation()
|
|
|
|
|
{
|
|
|
|
|
var validation = {}
|
2014-01-15 19:44:27 -05:00
|
|
|
validation.isValid = true;
|
2014-01-16 19:43:15 -05:00
|
|
|
validation.requiredAliases = [];
|
2014-01-15 20:23:59 -05:00
|
|
|
validation.invalidProperties = [];
|
2014-01-15 17:31:31 -05:00
|
|
|
|
|
|
|
|
//determine which fields are required
|
2014-01-16 12:37:01 -05:00
|
|
|
_.each($scope.model.config.fieldsets, function(fieldset){
|
2014-01-16 19:43:15 -05:00
|
|
|
_.each(fieldset.properties, function(property){
|
|
|
|
|
if(property.required)
|
|
|
|
|
{
|
|
|
|
|
validation.requiredAliases.push(property.alias);
|
|
|
|
|
}
|
|
|
|
|
});
|
2014-01-16 12:37:01 -05:00
|
|
|
});
|
2014-01-15 17:31:31 -05:00
|
|
|
|
|
|
|
|
//if nothing required; let's go
|
|
|
|
|
if(validation.requiredAliases.length == 0)
|
|
|
|
|
{
|
|
|
|
|
return validation;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//otherwise we need to check the required aliases
|
2014-01-16 12:37:01 -05:00
|
|
|
_.each($scope.archetypeRenderModel.fieldsets, function(fieldset){
|
2014-01-15 20:23:59 -05:00
|
|
|
fieldset.isValid = true;
|
|
|
|
|
|
2014-01-16 12:37:01 -05:00
|
|
|
_.each(fieldset.properties, function(property){
|
2014-01-15 20:23:59 -05:00
|
|
|
property.isValid = true;
|
|
|
|
|
|
2014-01-16 12:37:01 -05:00
|
|
|
//if a required field
|
|
|
|
|
if(_.find(validation.requiredAliases, function(alias){ return alias == property.alias }))
|
2014-01-15 20:23:59 -05:00
|
|
|
{
|
|
|
|
|
//TODO: do a better validation test
|
|
|
|
|
if(property.value == ""){
|
|
|
|
|
fieldset.isValid = false;
|
|
|
|
|
property.isValid = false;
|
2014-01-15 19:44:27 -05:00
|
|
|
validation.isValid = false;
|
2014-01-15 20:23:59 -05:00
|
|
|
|
2014-01-16 12:37:01 -05:00
|
|
|
validation.invalidProperties.push(property);
|
2014-01-15 19:44:27 -05:00
|
|
|
}
|
2014-01-15 17:31:31 -05:00
|
|
|
}
|
2014-01-16 12:37:01 -05:00
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2014-01-16 19:43:15 -05:00
|
|
|
if($scope.model.config.developerMode == '1')
|
|
|
|
|
{
|
|
|
|
|
console.log(validation);
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-16 12:37:01 -05:00
|
|
|
return validation;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$scope.getPropertyValidity = function(fieldsetIndex, alias)
|
|
|
|
|
{
|
|
|
|
|
if($scope.archetypeRenderModel.fieldsets[fieldsetIndex])
|
|
|
|
|
{
|
|
|
|
|
var property = _.find($scope.archetypeRenderModel.fieldsets[fieldsetIndex].properties, function(property){
|
|
|
|
|
return property.alias == alias;
|
|
|
|
|
});
|
2014-01-15 17:31:31 -05:00
|
|
|
}
|
|
|
|
|
|
2014-01-16 12:37:01 -05:00
|
|
|
return (typeof property == 'undefined') ? true : property.isValid;
|
2014-01-15 17:31:31 -05:00
|
|
|
}
|
|
|
|
|
|
2014-01-10 17:20:35 -07:00
|
|
|
//sync things up on save
|
|
|
|
|
$scope.$on("formSubmitting", function (ev, args) {
|
2014-01-15 17:31:31 -05:00
|
|
|
|
|
|
|
|
var validation = getValidation();
|
|
|
|
|
|
|
|
|
|
if(!validation.isValid)
|
|
|
|
|
{
|
|
|
|
|
notificationsService.warning("Cannot Save Document", "The document could not be saved because of missing required fields.")
|
|
|
|
|
form.$setValidity("archetypeError", false);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
syncModelToRenderModel();
|
2014-01-15 20:23:59 -05:00
|
|
|
form.$setValidity("archetypeError", true);
|
2014-01-15 17:31:31 -05:00
|
|
|
}
|
2014-01-10 17:20:35 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
//custom js
|
|
|
|
|
if ($scope.model.config.customJsPath) {
|
|
|
|
|
assetsService.loadJs($scope.model.config.customJsPath);
|
2014-01-12 14:33:09 -05:00
|
|
|
}
|
2014-01-10 17:20:35 -07:00
|
|
|
|
|
|
|
|
//archetype css
|
2014-01-16 14:23:02 -05:00
|
|
|
assetsService.loadCss("/App_Plugins/Archetype/css/archetype.css");
|
2014-01-10 17:20:35 -07:00
|
|
|
|
|
|
|
|
//custom css
|
|
|
|
|
if($scope.model.config.customCssPath)
|
|
|
|
|
{
|
|
|
|
|
assetsService.loadCss($scope.model.config.customCssPath);
|
|
|
|
|
}
|
|
|
|
|
});
|