1 angular.module('egFmRecordEditorMod',
2 ['egCoreMod', 'egUiMod', 'ui.bootstrap'])
4 .directive('egEditFmRecord', function() {
9 // IDL class hint (e.g. "aou")
12 // mode: 'create' for creating a new record,
13 // 'update' for editing an existing record
16 // record ID to update
19 // fields with custom templates
20 // hash keyed on field name; may contain
21 // template - Angular template; should access
22 // field value using rec_flat[field.name]
23 // handlers - any functions you want to pass
24 // in to the custom template
25 customFieldTemplates : '=?',
27 // comma-separated list of fields that should not be
31 // comma-separated list of fields that should always
35 // comma-separated list of required fields; this
36 // supplements what the IDL considers required
39 // comma-separated list of org_unit fields where
40 // the selector should default to the workstation OU
41 orgDefaultAllowed : '@',
43 // hash, keyed by field name, of functions to invoke
44 // to check whether a field is required. Each
45 // callback is passed the field name and the record
46 // and should return a boolean value. This supports
47 // cases where whether a field is required or not
48 // depends on the current value of another field.
49 isRequiredOverride : '@',
51 // reference to handler to run upon saving
52 // record. The handler will be passed the
53 // record ID and a parameter indicating whether
54 // the save did a create or an update. Note that
55 // even if the mode of the egEditFmRecord is
56 // 'create', the onSave handler may still get
57 // 'update' if the user is permitted to create a
58 // record, then update it
61 // reference to handler to run if the user
67 templateUrl : '/eg/staff/share/t_fm_record_editor',
71 function($scope , egCore) {
73 function list_to_hash(str) {
75 if (angular.isString(str)) {
76 str.split(/,/).map(function(s) {
77 hash[s.trim()] = true;
83 $scope.required = list_to_hash($scope.requiredFields);
84 $scope.readonly = list_to_hash($scope.readonlyFields);
85 $scope.hidden = list_to_hash($scope.hiddenFields);
86 $scope.org_default_allowed = list_to_hash($scope.orgDefaultAllowed);
88 $scope.record_label = egCore.idl.classes[$scope.idlClass].label;
91 $scope.rec_org_values = {};
92 $scope.id_is_editable = false;
94 if ($scope.mode == 'update') {
95 egCore.pcrud.retrieve($scope.idlClass, $scope.recordId).then(function(r) {
97 convert_datatypes_to_js($scope.rec);
98 $scope.fields = get_field_list();
101 if (!('pkey_sequence' in egCore.idl.classes[$scope.idlClass])) {
102 $scope.id_is_editable = true;
104 $scope.rec = new egCore.idl[$scope.idlClass]();
105 $scope.fields = get_field_list();
108 function convert_datatypes_to_js(rec) {
109 var fields = egCore.idl.classes[$scope.idlClass].fields;
110 angular.forEach(fields, function(field) {
111 if (field.datatype == 'bool') {
112 if (rec[field.name]() == 't') {
113 rec[field.name](true);
114 } else if (rec[field.name]() == 'f') {
115 rec[field.name](false);
121 function convert_datatypes_to_idl(rec) {
122 var fields = egCore.idl.classes[$scope.idlClass].fields;
123 angular.forEach(fields, function(field) {
124 if (field.datatype == 'bool') {
125 if (rec[field.name]() == true) {
126 rec[field.name]('t');
127 } else if (rec[field.name]() == false) {
128 rec[field.name]('f');
131 // retrieve values from any fields controlled
132 // by custom templates, which for the moment all
133 // expect to be passed an ordinary flat value
134 if (field.name in $scope.rec_flat) {
135 rec[field.name]($scope.rec_flat[field.name]);
140 function flatten_linked_values(cls, list) {
142 var fields = egCore.idl.classes[cls].fields;
145 angular.forEach(fields, function(fld) {
146 if (fld.datatype == 'id') {
148 selector = fld.selector ? fld.selector : id_field;
152 angular.forEach(list, function(item) {
153 var rec = egCore.idl.toHash(item);
162 function get_field_list() {
163 var fields = egCore.idl.classes[$scope.idlClass].fields;
165 angular.forEach(fields, function(field) {
166 field.readonly = (field.name in $scope.readonly);
167 if (angular.isObject($scope.isRequiredOverride) &&
168 field.name in $scope.isRequiredOverride) {
169 field.is_required = function() {
170 return $scope.isRequiredOverride[field.name](field.name, $scope.rec);
173 field.is_required = function() {
174 return field.required || (field.name in $scope.required);
177 if (field.datatype == 'link') {
178 egCore.pcrud.retrieveAll(
179 field.class, {}, {atomic : true}
180 ).then(function(list) {
181 field.linked_values = flatten_linked_values(field.class, list);
184 if (field.datatype == 'org_unit') {
185 $scope.rec_orgs[field.name] = function(org) {
186 if (arguments.length == 1) $scope.rec[field.name](org.id());
187 return egCore.org.get($scope.rec[field.name]());
189 if ($scope.rec[field.name]()) {
190 $scope.rec_org_values[field.name] = $scope.rec_orgs[field.name]();
192 field.org_default_allowed = (field.name in $scope.org_default_allowed);
194 if (angular.isObject($scope.customFieldTemplates) && (field.name in $scope.customFieldTemplates)) {
195 field.use_custom_template = true;
196 field.custom_template = $scope.customFieldTemplates[field.name].template;
197 field.handlers = $scope.customFieldTemplates[field.name].handlers;
198 $scope.rec_flat[field.name] = $scope.rec[field.name]();
201 return fields.filter(function(field) { return !(field.name in $scope.hidden) });
204 $scope.ok = function($event) {
205 var recToSave = egCore.idl.Clone($scope.rec)
206 convert_datatypes_to_idl(recToSave);
207 if ($scope.mode == 'update') {
208 egCore.pcrud.update(recToSave).then(function() {
209 $scope.onSave($event);
212 egCore.pcrud.create(recToSave).then(function() {
213 $scope.onSave($event);
217 $scope.cancel = function($event) {
218 $scope.onCancel($event);
224 .directive('egFmCustomFieldInput', function($compile) {
231 link : function(scope, element, attrs) {
232 element.html(scope.template);
233 $compile(element.contents())(scope.$parent);