ae4da8e5c214ddc1a664a9c0dfdb145a2f771cbe
[tine20] / tine20 / Tinebase / js / widgets / form / FieldManager.js
1 /*
2  * Tine 2.0
3  *
4  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
5  * @author      Cornelius Weiss <c.weiss@metaways.de>
6  * @copyright   Copyright (c) 2016 Metaways Infosystems GmbH (http://www.metaways.de)
7  */
8 Ext.ns('Tine.widgets.grid');
9
10 /**
11  * central form field manager
12  * - get form field for a given field
13  * - register form field for a given field
14  *
15  * @namespace   Tine.widgets.form
16  * @class       Tine.widgets.form.FieldManager
17  * @author      Cornelius Weiss <c.weiss@metaways.de>
18  * @singleton
19  */
20 Tine.widgets.form.FieldManager = function() {
21     var fields = {};
22
23     return {
24         /**
25          * const for category editDialog
26          */
27         CATEGORY_EDITDIALOG: 'editDialog',
28
29         /**
30          * const for category propertyGrid
31          */
32         CATEGORY_PROPERTYGRID: 'propertyGrid',
33
34         /**
35          * get form field of well known field names
36          *
37          * @param {String} fieldName
38          * @return {Object}
39          */
40         getByFieldname: function(fieldName) {
41             var field = null;
42
43             return field;
44         },
45
46         /**
47          * get form field by data type
48          *
49          * @param {String} appName
50          * @param {Record/String} modelName
51          * @param {String} fieldName
52          * @param {String} category {editDialog|propertyGrid} optional.
53          * @param {Object} config
54          * @return {Object}
55          */
56         getByModelConfig: function(appName, modelName, fieldName, category, config) {
57             var field = {},
58                 recordClass = Tine.Tinebase.data.RecordMgr.get(appName, modelName),
59                 modelConfig = recordClass ? recordClass.getModelConfiguration() : null,
60                 fieldDefinition = modelConfig && modelConfig.fields ? modelConfig.fields[fieldName] : {},
61                 fieldType = fieldDefinition.type || 'textfield',
62                 app = Tine.Tinebase.appMgr.get(appName),
63                 i18n = fieldDefinition.useGlobalTranslation ? i18n : app.i18n;
64
65             field.fieldLabel = i18n._hidden(fieldDefinition.label || fieldDefinition.fieldName);
66             field.name = fieldName;
67             field.disabled = !! (fieldDefinition.readOnly || fieldDefinition.disabled);
68             field.allowBlank = !! (fieldDefinition.validators && fieldDefinition.validators.allowEmpty);
69
70             if (fieldDefinition['default']) {
71                 field['default'] = i18n._hidden(fieldDefinition['default']);
72             }
73
74             switch(fieldType) {
75                 case 'money':
76                     field.xtype = 'extuxmoneyfield';
77                     break;
78                 case 'date':
79                     field.xtype = 'datefield';
80                     if (fieldDefinition.dateFormat) {
81                         field.dateFormat = fieldDefinition.dateFormat;
82                     }
83                     break;
84                 case 'time':
85                     field.xtype = 'timefield';
86                     break;
87                 case 'datetime':
88                     field.xtype = 'datetimefield'; // form ux.datetimefield
89                     break;
90                 case 'bool':
91                 case 'boolean':
92                     field.xtype = category == 'editDialg' ? 'checkbox' : 'booleancombo';
93                     field.boxLabel = field.fieldLabel;
94                     break;
95                 case 'integer':
96                     field.xtype = 'numberfield';
97                     field.allowDecimals = false;
98
99                     if (fieldDefinition.specialType && fieldDefinition.specialType === 'percent') {
100                         field.xtype = 'extuxnumberfield';
101                         field.useThousandSeparator = false;
102                         field.suffix = ' %';
103                     }
104
105                     if (fieldDefinition.max) {
106                         field.maxValue = fieldDefinition.max;
107                     }
108
109                     if (fieldDefinition.min) {
110                         field.minValue = fieldDefinition.min;
111                     }
112                     break;
113                 case 'float':
114                     field.xtype = 'numberfield';
115                     field.decimalPrecision = 2;
116
117                     if (fieldDefinition.specialType && fieldDefinition.specialType === 'percent') {
118                         field.xtype = 'extuxnumberfield';
119                         field.suffix = ' %';
120                     }
121
122                     if (fieldDefinition.max) {
123                         field.maxValue = fieldDefinition.max;
124                     }
125
126                     if (fieldDefinition.min) {
127                         field.minValue = fieldDefinition.min;
128                     }
129                     break;
130                 case 'user':
131                     field.xtype = 'addressbookcontactpicker';
132                     field.userOnly = true;
133                     break;
134                 case 'record':
135                     if (fieldDefinition.config && fieldDefinition.config.appName && fieldDefinition.config.modelName) {
136                         var picker = Tine.widgets.form.RecordPickerManager.get(fieldDefinition.config.appName, fieldDefinition.config.modelName, Ext.apply(field, config));
137                         field = picker;
138                     }
139                     break;
140                 case 'keyfield':
141                     field.xtype = 'widget-keyfieldcombo';
142                     field.app = app;
143                     field.keyFieldName = fieldDefinition.name;
144                     break;
145                 case 'text':
146                     field.xtype = 'textarea';
147                     field.height = 70; // 5 lines
148                     break;
149                 default:
150                     field.xtype = 'textfield';
151                     break;
152             }
153
154             Ext.apply(field, config);
155
156             return field;
157         },
158
159         /**
160          * returns form field for given field
161          *
162          * @param {String/Tine.Tinebase.Application} appName
163          * @param {Record/String} modelName
164          * @param {String} fieldName
165          * @param {String} category {editDialog|propertyGrid} optional.
166          * @param {Object} config
167          * @return {Object}
168          */
169         get: function(appName, modelName, fieldName, category, config) {
170             var appName = this.getAppName(appName),
171                 modelName = this.getModelName(modelName),
172                 categoryKey = this.getKey([appName, modelName, fieldName, category]),
173                 genericKey = this.getKey([appName, modelName, fieldName]),
174                 config = config || {};
175
176             // check for registered renderer
177             var field = fields[categoryKey] ? fields[categoryKey] : fields[genericKey];
178
179             // check for common names
180             if (! field) {
181                 field = this.getByFieldname(fieldName);
182             }
183
184             // check for known datatypes
185             if (! field) {
186                 field = this.getByModelConfig(appName, modelName, fieldName, category, config);
187             }
188
189             return field;
190         },
191
192         /**
193          * register renderer for given field
194          *
195          * @param {String/Tine.Tinebase.Application} appName
196          * @param {Record/String} modelName
197          * @param {String} fieldName
198          * @param {Object} field
199          * @param {String} category {editDialog|propertyGrid} optional.
200          */
201         register: function(appName, modelName, fieldName, field, category) {
202             var appName = this.getAppName(appName),
203                 modelName = this.getModelName(modelName),
204                 categoryKey = this.getKey([appName, modelName, fieldName, category]),
205                 genericKey = this.getKey([appName, modelName, fieldName]);
206
207             fields[category ? categoryKey : genericKey] = field;
208         },
209
210         /**
211          * check if a field is explicitly registered
212          *
213          * @param {String/Tine.Tinebase.Application} appName
214          * @param {Record/String} modelName
215          * @param {String} fieldName
216          * @param {String} category {editDialog|propertyGrid} optional.
217          * @return {Boolean}
218          */
219         has: function(appName, modelName, fieldName, category) {
220             var appName = this.getAppName(appName),
221                 modelName = this.getModelName(modelName),
222                 categoryKey = this.getKey([appName, modelName, fieldName, category]),
223                 genericKey = this.getKey([appName, modelName, fieldName]);
224
225             // check for registered renderer
226             return (fields[categoryKey] ? fields[categoryKey] : fields[genericKey]) ? true : false;
227         },
228
229         /**
230          * returns the modelName by modelName or record
231          *
232          * @param {Record/String} modelName
233          * @return {String}
234          */
235         getModelName: function(modelName) {
236             return Ext.isFunction(modelName) ? modelName.getMeta('modelName') : modelName;
237         },
238
239         /**
240          * returns the modelName by appName or application instance
241          *
242          * @param {String/Tine.Tinebase.Application} appName
243          * @return {String}
244          */
245         getAppName: function(appName) {
246             return Ext.isString(appName) ? appName : appName.appName;
247         },
248
249         /**
250          * returns a key by joining the array values
251          *
252          * @param {Array} params
253          * @return {String}
254          */
255         getKey: function(params) {
256             return params.join('_');
257         }
258     };
259 }();