/* * Copyright (c) 2012-2016 Kaarle Ritvanen * See LICENSE file for license details */ angular.module("aconf").directive("aconfFields", function() { return { restrict: "E", scope: {node: "=", value: "=path"}, templateUrl: "directive/fields.html", link: function(scope) { scope.layout = scope.node && scope.node.meta.widget || "default"; } } }).directive("aconfInline", function() { return { restrict: "E", scope: true, transclude: true, template: '
', link: function(scope, element, attrs, ctrl, transclude) { scope.$watch("node", function(node) { if (node) transclude(scope, function(clone) { element.children().append(clone); }); }); } }; }).directive("aconfNode", function() { return { restrict: "C", require: ["?aconfField", "?^^aconfNode", "^^aconfLayout"], link: { pre: function(scope, element, attrs, ctrl) { var field = ctrl[0]; var parent = ctrl[1]; var layout = ctrl[2]; var fscope = field ? field.scope : scope; if (parent) { scope.level = parent.level + 1; layout.query(fscope.value).then(function(node) { scope.node = node; fscope.node = node; }); } else scope.level = 1; scope.$watch("node", function(node) { if (!node) return; scope.checkValidity = function(initial) { var valid = node.validate(); fscope.invalid = !node.isNodeValid(); if (!(initial && valid)) layout.validationReady(valid); }; scope.checkValidity(true); }); } }, controller: function($scope) { Object.defineProperty(this, "level", {get: function() { return $scope.level; }}); Object.defineProperty(this, "data", {get: function() { return $scope.node; }}); this.updated = function(field) { $scope.checkValidity(); $scope.$broadcast("updated", field); }; } }; }).directive("aconfHeader", function() { return { restrict: "E", link: function(scope, element) { element.html( $("") .text(scope.node.meta["ui-name"]) ); scope.$watch("invalid", function(invalid) { if (invalid) element.addClass("invalid"); else element.removeClass("invalid"); }); } }; }).directive("aconfCheckboxes", function() { return { restrict: "E", scope: true, templateUrl: "directive/checkboxes.html", link: function(scope) { scope.choices = _.filter( scope.node.meta.members.choice, function(ch) { ch.checked = _.contains(scope.node.data, ch.value); return ch.enabled || ch.checked; } ); } }; }).directive("aconfSetCheckbox", function() { return { restrict: "E", scope: {choice: "="}, templateUrl: "directive/set-checkbox.html", link: function(scope) { scope.name = scope.choice.value; scope.value = scope.choice.checked; scope.set = true; } }; }).directive("aconfModel", function() { return { restrict: "E", scope: true, transclude: true, template: '
', link: { pre: function(scope, element, attrs, ctrl, transclude) { scope.isRelevant = function(field) { return scope.node.match(field.condition); }; scope.$on("updated", function(event, updatedField) { _.each(scope.fields, function(field, i, fields) { if (field.name == updatedField || !scope.isRelevant(field)) return; if (field.dynamic) scope.node.metaRequest(field.name).success( function(data) { fields[i] = data; } ); if (field.dynamic || (field.condition && updatedField in field.condition)) fields[i] = _.clone(field); }); }); transclude(scope, function(clone) { element.children().append(clone); }); } } }; }).directive("aconfModelFields", function() { return { restrict: "C", require: "?aconfField", link: function(scope, element, attrs, ctrl) { if (ctrl) scope = ctrl.scope; scope.$watch("node", function(node) { if (!node) return; scope.fields = _.where(node.meta.fields, {visible: true}); scope.columns = _.filter(scope.fields, function(field) { return !(field.detail || field.condition); }); scope.$emit("columns", _.pluck(scope.columns, "ui-name")); scope.invoke = function(action) { node.invoke(action).then(function() { alert("Done"); }, function() { alert("Fail"); }); }; }); } }; }).directive( "aconfCollection", function($modal, $q, aconfErrorFormat, aconfType) { return { restrict: "E", scope: true, templateUrl: "directive/collection.html", require: "^^aconfLayout", link: function(scope, element, attrs, ctrl) { var node = scope.node; var meta = node.meta; scope.$watch("node.data", function(data) { if (!aconfType.isCollection(meta)) return; scope.fields = _.map(data, function(value, name) { if (meta.type == "set") name = data[name]; else if (_.isArray(data)) name++; var set = meta.type == "set"; return { name: name, label: set ? null : meta["ui-member"] + " " + name, editable: meta.editable && !set, removable: _.contains(meta.removable, name), meta: meta.members }; }); }, true); if (!meta.editable) return; var list = meta.type == "list"; var set = meta.type == "set"; function insert(name) { return $q(function(resolve, reject) { var task; if (aconfType.isTreeNode(meta.members)) task = node.set(name, {}); else if (set) task = node.add(name); if (task) task.then(resolve, function(resp) { node.delete(name); reject(resp); }); else node.set(name, null).catch(function(resp) { resolve(false); }); }); } if (list) { scope.$watch( "!node.data.length || node.get(node.data.length, true) != null", function(saved) { scope.insert = saved && function() { ctrl.updateRequest(insert(node.data.length + 1)); }; } ); scope.sortable = { start: function(event, ui) { var index = ui.item.index(); if (!node.isSubtreeValid()) { ui.item.sortable.cancel(); index = -1; } ui.item.data("index", index); }, stop: function(event, ui) { var oldIndex = ui.item.data("index") + 1; var newIndex = ui.item.index() + 1; if (oldIndex && newIndex != oldIndex) ctrl.updateRequest( node.move(oldIndex, newIndex) ); } }; return; } scope.insert = function() { $modal.open({ backdrop: false, templateUrl: "insert.html", controller: function($scope, $modalInstance) { $scope.submit = function() { var name = $scope.value; if (set ? _.contains(node.data, name) : name in node.data) { ctrl.validationReady( "Already exists: " + name ); return; } insert(name).then(function(txnValid) { $modalInstance.close(); ctrl.validationReady(txnValid); }, function(resp) { $scope.error = aconfErrorFormat(resp); }); }; $scope.close = function() { $modalInstance.dismiss(); }; } }).rendered.then(function($element) { $(".modal-body input[type=text]").focus(); }); }; } }; } ).directive("aconfTabularLayout", function() { return { restrict: "E", scope: true, templateUrl: "directive/tabular-layout.html", link: { pre: function(scope) { scope.$on("columns", function(event, columns) { scope.columns = columns; }); } } }; });