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 id_field = egCore.idl.classes[cls].pkey;
143 var selector = egCore.idl.classes[cls].field_map[id_field].selector || id_field;
144 angular.forEach(list, function(item) {
146 id : item[id_field](),
147 name : item[selector]()
153 function get_field_list() {
154 var fields = egCore.idl.classes[$scope.idlClass].fields;
156 angular.forEach(fields, function(field) {
157 field.readonly = (field.name in $scope.readonly);
158 if (angular.isObject($scope.isRequiredOverride) &&
159 field.name in $scope.isRequiredOverride) {
160 field.is_required = function() {
161 return $scope.isRequiredOverride[field.name](field.name, $scope.rec);
164 field.is_required = function() {
165 return field.required || (field.name in $scope.required);
168 if (field.datatype == 'link') {
169 egCore.pcrud.retrieveAll(
170 field.class, {}, {atomic : true}
171 ).then(function(list) {
172 field.linked_values = flatten_linked_values(field.class, list);
175 if (field.datatype == 'org_unit') {
176 $scope.rec_orgs[field.name] = function(org) {
177 if (arguments.length == 1) $scope.rec[field.name](org.id());
178 return egCore.org.get($scope.rec[field.name]());
180 if ($scope.rec[field.name]()) {
181 $scope.rec_org_values[field.name] = $scope.rec_orgs[field.name]();
183 field.org_default_allowed = (field.name in $scope.org_default_allowed);
185 if (angular.isObject($scope.customFieldTemplates) && (field.name in $scope.customFieldTemplates)) {
186 field.use_custom_template = true;
187 field.custom_template = $scope.customFieldTemplates[field.name].template;
188 field.handlers = $scope.customFieldTemplates[field.name].handlers;
189 $scope.rec_flat[field.name] = $scope.rec[field.name]();
192 return fields.filter(function(field) { return !(field.name in $scope.hidden) });
195 $scope.ok = function($event) {
196 var recToSave = egCore.idl.Clone($scope.rec)
197 convert_datatypes_to_idl(recToSave);
198 if ($scope.mode == 'update') {
199 egCore.pcrud.update(recToSave).then(function() {
200 $scope.onSave($event);
203 egCore.pcrud.create(recToSave).then(function() {
204 $scope.onSave($event);
208 $scope.cancel = function($event) {
209 $scope.onCancel($event);
215 .directive('egFmCustomFieldInput', function($compile) {
222 link : function(scope, element, attrs) {
223 element.html(scope.template);
224 $compile(element.contents())(scope.$parent);