use checkbox instead of combobox in editdialogs for boolean fields
[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                     if (category === 'editDialog') {
93                         field.xtype = 'checkbox';
94                     } else {
95                         field.xtype = 'booleancombo';
96                     }
97                     break;
98                 case 'integer':
99                     field.xtype = 'numberfield';
100                     field.allowDecimals = false;
101
102                     if (fieldDefinition.specialType && fieldDefinition.specialType === 'percent') {
103                         field.xtype = 'extuxnumberfield';
104                         field.useThousandSeparator = false;
105                         field.suffix = ' %';
106                     }
107
108                     if (fieldDefinition.max) {
109                         field.maxValue = fieldDefinition.max;
110                     }
111
112                     if (fieldDefinition.min) {
113                         field.minValue = fieldDefinition.min;
114                     }
115                     break;
116                 case 'float':
117                     field.xtype = 'numberfield';
118                     field.decimalPrecision = 2;
119
120                     if (fieldDefinition.specialType && fieldDefinition.specialType === 'percent') {
121                         field.xtype = 'extuxnumberfield';
122                         field.suffix = ' %';
123                     }
124
125                     if (fieldDefinition.max) {
126                         field.maxValue = fieldDefinition.max;
127                     }
128
129                     if (fieldDefinition.min) {
130                         field.minValue = fieldDefinition.min;
131                     }
132                     break;
133                 case 'user':
134                     field.xtype = 'addressbookcontactpicker';
135                     field.userOnly = true;
136                     break;
137                 case 'record':
138                     if (fieldDefinition.config && fieldDefinition.config.appName && fieldDefinition.config.modelName) {
139                         var picker = Tine.widgets.form.RecordPickerManager.get(fieldDefinition.config.appName, fieldDefinition.config.modelName, Ext.apply(field, config));
140                         field = picker;
141                     }
142                     break;
143                 case 'keyfield':
144                     field.xtype = 'widget-keyfieldcombo';
145                     field.app = app;
146                     field.keyFieldName = fieldDefinition.name;
147                     break;
148                 case 'text':
149                     field.xtype = 'textarea';
150                     field.height = 70; // 5 lines
151                     break;
152                 default:
153                     field.xtype = 'textfield';
154                     break;
155             }
156
157             Ext.apply(field, config);
158
159             return field;
160         },
161
162         /**
163          * returns form field for given field
164          *
165          * @param {String/Tine.Tinebase.Application} appName
166          * @param {Record/String} modelName
167          * @param {String} fieldName
168          * @param {String} category {editDialog|propertyGrid} optional.
169          * @param {Object} config
170          * @return {Object}
171          */
172         get: function(appName, modelName, fieldName, category, config) {
173             var appName = this.getAppName(appName),
174                 modelName = this.getModelName(modelName),
175                 categoryKey = this.getKey([appName, modelName, fieldName, category]),
176                 genericKey = this.getKey([appName, modelName, fieldName]),
177                 config = config || {};
178
179             // check for registered renderer
180             var field = fields[categoryKey] ? fields[categoryKey] : fields[genericKey];
181
182             // check for common names
183             if (! field) {
184                 field = this.getByFieldname(fieldName);
185             }
186
187             // check for known datatypes
188             if (! field) {
189                 field = this.getByModelConfig(appName, modelName, fieldName, category, config);
190             }
191
192             return field;
193         },
194
195         /**
196          * register renderer for given field
197          *
198          * @param {String/Tine.Tinebase.Application} appName
199          * @param {Record/String} modelName
200          * @param {String} fieldName
201          * @param {Object} field
202          * @param {String} category {editDialog|propertyGrid} optional.
203          */
204         register: function(appName, modelName, fieldName, field, category) {
205             var appName = this.getAppName(appName),
206                 modelName = this.getModelName(modelName),
207                 categoryKey = this.getKey([appName, modelName, fieldName, category]),
208                 genericKey = this.getKey([appName, modelName, fieldName]);
209
210             fields[category ? categoryKey : genericKey] = field;
211         },
212
213         /**
214          * check if a field is explicitly registered
215          *
216          * @param {String/Tine.Tinebase.Application} appName
217          * @param {Record/String} modelName
218          * @param {String} fieldName
219          * @param {String} category {editDialog|propertyGrid} optional.
220          * @return {Boolean}
221          */
222         has: function(appName, modelName, fieldName, category) {
223             var appName = this.getAppName(appName),
224                 modelName = this.getModelName(modelName),
225                 categoryKey = this.getKey([appName, modelName, fieldName, category]),
226                 genericKey = this.getKey([appName, modelName, fieldName]);
227
228             // check for registered renderer
229             return (fields[categoryKey] ? fields[categoryKey] : fields[genericKey]) ? true : false;
230         },
231
232         /**
233          * returns the modelName by modelName or record
234          *
235          * @param {Record/String} modelName
236          * @return {String}
237          */
238         getModelName: function(modelName) {
239             return Ext.isFunction(modelName) ? modelName.getMeta('modelName') : modelName;
240         },
241
242         /**
243          * returns the modelName by appName or application instance
244          *
245          * @param {String/Tine.Tinebase.Application} appName
246          * @return {String}
247          */
248         getAppName: function(appName) {
249             return Ext.isString(appName) ? appName : appName.appName;
250         },
251
252         /**
253          * returns a key by joining the array values
254          *
255          * @param {Array} params
256          * @return {String}
257          */
258         getKey: function(params) {
259             return params.join('_');
260         }
261     };
262 }();