LP#1677416: unbreak use of egOrgSelector by egEditFmRecord
[working/Evergreen.git] / Open-ILS / web / js / ui / default / staff / services / fm_record_editor.js
1 angular.module('egFmRecordEditorMod',
2     ['egCoreMod', 'egUiMod', 'ui.bootstrap'])
3
4 .directive('egEditFmRecord', function() {
5     return {
6         restrict : 'AE',
7         transclude : true,
8         scope : {
9             // IDL class hint (e.g. "aou")
10             idlClass : '@',
11
12             // mode: 'create' for creating a new record,
13             //       'update' for editing an existing record
14             mode : '@',
15
16             // record ID to update
17             recordId : '=',
18
19             // comma-separated list of fields that should not be
20             // displayed
21             hiddenFields : '@',
22
23             // comma-separated list of fields that should always
24             // be read-only
25             readonlyFields : '@',
26
27             // comma-separated list of required fields; this
28             // supplements what the IDL considers required
29             requiredFields : '@',
30
31             // hash, keyed by field name, of functions to invoke
32             // to check whether a field is required.  Each
33             // callback is passed the field name and the record
34             // and should return a boolean value. This supports
35             // cases where whether a field is required or not
36             // depends on the current value of another field.
37             isRequiredOverride : '@',
38
39             // reference to handler to run upon saving
40             // record. The handler will be passed the
41             // record ID and a parameter indicating whether
42             // the save did a create or an update. Note that
43             // even if the mode of the egEditFmRecord is
44             // 'create', the onSave handler may still get
45             // 'update' if the user is permitted to create a
46             // record, then update it
47             onSave : '=',
48
49             // reference to handler to run if the user
50             // cancels the dialog
51             onCancel : '='
52
53         },
54
55         templateUrl : '/eg/staff/share/t_fm_record_editor',
56
57         controller : [
58                     '$scope','egCore',
59             function($scope , egCore) {
60
61             function list_to_hash(str) {
62                 var hash = {};
63                 if (angular.isString(str)) {
64                     str.split(/,/).map(function(s) {
65                         hash[s.trim()] = true;
66                     });
67                 }
68                 return hash;
69             }
70
71             $scope.required = list_to_hash($scope.requiredFields);
72             $scope.readonly = list_to_hash($scope.readonlyFields);
73             $scope.hidden = list_to_hash($scope.hiddenFields);
74
75             $scope.record_label = egCore.idl.classes[$scope.idlClass].label;
76             $scope.rec_orgs = {};
77             $scope.rec_org_values = {};
78
79             if ($scope.mode == 'update') {
80                 egCore.pcrud.retrieve($scope.idlClass, $scope.recordId).then(function(r) {
81                     $scope.rec = r;
82                     convert_datatypes_to_js($scope.rec);
83                     $scope.fields = get_field_list();
84                 });
85             } else {
86                 $scope.rec = new egCore.idl[$scope.idlClass]();
87                 $scope.fields = get_field_list();
88             }
89
90             function convert_datatypes_to_js(rec) {
91                 var fields = egCore.idl.classes[$scope.idlClass].fields;
92                 angular.forEach(fields, function(field) {
93                     if (field.datatype == 'bool') {
94                         if (rec[field.name]() == 't') {
95                             rec[field.name](true);
96                         } else if (rec[field.name]() == 'f') {
97                             rec[field.name](false);
98                         }
99                     }
100                 });
101             }
102
103             function convert_datatypes_to_idl(rec) {
104                 var fields = egCore.idl.classes[$scope.idlClass].fields;
105                 angular.forEach(fields, function(field) {
106                     if (field.datatype == 'bool') {
107                         if (rec[field.name]() == true) {
108                             rec[field.name]('t');
109                         } else if (rec[field.name]() == false) {
110                             rec[field.name]('f');
111                         }
112                     }
113                 });
114             }
115
116             function flatten_linked_values(cls, list) {
117                 var results = [];
118                 var fields = egCore.idl.classes[cls].fields;
119                 var id_field;
120                 var selector;
121                 angular.forEach(fields, function(fld) {
122                     if (fld.datatype == 'id') {
123                         id_field = fld.name;
124                         selector = fld.selector ? fld.selector : id_field;
125                         return;
126                     }
127                 });
128                 angular.forEach(list, function(item) {
129                     var rec = egCore.idl.toHash(item);
130                     results.push({
131                         id : rec[id_field],
132                         name : rec[selector]
133                     });
134                 });
135                 return results;
136             }
137
138             function get_field_list() {
139                 var fields = egCore.idl.classes[$scope.idlClass].fields;
140
141                 angular.forEach(fields, function(field) {
142                     field.readonly = (field.name in $scope.readonly);
143                     if (angular.isObject($scope.isRequiredOverride) &&
144                         field.name in $scope.isRequiredOverride) {
145                         field.is_required = function() {
146                             return $scope.isRequiredOverride[field.name](field.name, $scope.rec);
147                         }
148                     } else {
149                         field.is_required = function() {
150                             return field.required || (field.name in $scope.required);
151                         }
152                     }
153                     if (field.datatype == 'link') {
154                     egCore.pcrud.retrieveAll(
155                             field.class, {}, {atomic : true}
156                         ).then(function(list) {
157                             field.linked_values = flatten_linked_values(field.class, list);
158                         });
159                     }
160                     if (field.datatype == 'org_unit') {
161                         $scope.rec_orgs[field.name] = function(org) {
162                             if (arguments.length == 1) $scope.rec[field.name](org.id());
163                             return egCore.org.get($scope.rec[field.name]());
164                         }
165                         if ($scope.rec[field.name]()) {
166                             $scope.rec_org_values[field.name] = $scope.rec_orgs[field.name]();
167                         }
168                     }
169                 });
170                 return fields.filter(function(field) { return !(field.name in $scope.hidden) });
171             }
172
173             $scope.ok = function($event) {
174                 var recToSave = egCore.idl.Clone($scope.rec)
175                 convert_datatypes_to_idl(recToSave);
176                 if ($scope.mode == 'update') {
177                     egCore.pcrud.update(recToSave).then(function() {
178                         $scope.onSave($event);
179                     });
180                 } else {
181                     egCore.pcrud.create(recToSave).then(function() {
182                         $scope.onSave($event);
183                     });
184                 }
185             }
186             $scope.cancel = function($event) {
187                 $scope.onCancel($event);
188             }
189         }]
190     };
191 })