0013214: allow to set fixed calendars as user preference
[tine20] / tine20 / Tinebase / js / Models.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) 2007-2013 Metaways Infosystems GmbH (http://www.metaways.de)
7  */
8 Ext.ns('Tine.Tinebase.Model');
9
10 /**
11  * @type {Array}
12  * 
13  * modlog Fields
14  */
15
16 Tine.Tinebase.Model.modlogFields = [
17     { name: 'creation_time',      type: 'date', dateFormat: Date.patterns.ISO8601Long, omitDuplicateResolving: true },
18     { name: 'created_by',                                                              omitDuplicateResolving: true },
19     { name: 'last_modified_time', type: 'date', dateFormat: Date.patterns.ISO8601Long, omitDuplicateResolving: true },
20     { name: 'last_modified_by',                                                        omitDuplicateResolving: true },
21     { name: 'is_deleted',         type: 'boolean',                                     omitDuplicateResolving: true },
22     { name: 'deleted_time',       type: 'date', dateFormat: Date.patterns.ISO8601Long, omitDuplicateResolving: true },
23     { name: 'deleted_by',                                                              omitDuplicateResolving: true },
24     { name: 'seq',                                                                     omitDuplicateResolving: true }
25 ];
26
27 /**
28  * @type {Array}
29  * generic Record fields
30  */
31 Tine.Tinebase.Model.genericFields = Tine.Tinebase.Model.modlogFields.concat([
32     { name: 'container_id', header: 'Container',                                       omitDuplicateResolving: false}
33 ]);
34     
35 /**
36  * Model of a language
37  */
38 Tine.Tinebase.Model.Language = Ext.data.Record.create([
39     { name: 'locale' },
40     { name: 'language' },
41     { name: 'region' }
42 ]);
43
44 /**
45  * Model of a timezone
46  */
47 Tine.Tinebase.Model.Timezone = Ext.data.Record.create([
48     { name: 'timezone' },
49     { name: 'timezoneTranslation' }
50 ]);
51
52 /**
53  * Model of a role
54  */
55 Tine.Tinebase.Model.Role = Tine.Tinebase.data.Record.create([
56     {name: 'id'},
57     {name: 'name'},
58     {name: 'description'}
59 ], {
60     appName: 'Tinebase',
61     modelName: 'Role',
62     idProperty: 'id',
63     titleProperty: 'name',
64     recordName: 'Role',
65     recordsName: 'Roles'
66 });
67
68 /**
69  * Model of a generalised account (user or group)
70  */
71 Tine.Tinebase.Model.Account = Ext.data.Record.create([
72     {name: 'id'},
73     {name: 'type'},
74     {name: 'name'},
75     {name: 'data'} // todo: throw away data
76 ]);
77
78 /**
79  * Model of a container
80  */
81 Tine.Tinebase.Model.Container = Tine.Tinebase.data.Record.create(Tine.Tinebase.Model.modlogFields.concat([
82     {name: 'id'},
83     {name: 'name'},
84     {name: 'type'},
85     {name: 'backend'},
86     {name: 'order'},
87     {name: 'color'},
88     {name: 'application_id'},
89     {name: 'owner_id'},
90     {name: 'model'},
91     {name: 'uuid'},
92     {name: 'content_seq'},
93     {name: 'account_grants'},
94     {name: 'path'},
95     {name: 'xprops'},
96     // virtual
97     {name: 'ownerContact'},
98     {name: 'is_container_node', type: 'boolean'},
99     {name: 'dtselect', type: 'number'},
100 ]), {
101     appName: 'Tinebase',
102     modelName: 'Container',
103     idProperty: 'id',
104     titleProperty: 'name'
105 });
106
107 /**
108  * Model of a grant
109  */
110 Tine.Tinebase.Model.Grant = Ext.data.Record.create([
111     {name: 'id'},
112     {name: 'record_id'},
113     {name: 'account_id'},
114     {name: 'account_type'},
115     {name: 'account_name', sortType: Tine.Tinebase.common.accountSortType},
116     {name: 'freebusyGrant',type: 'boolean'},
117     {name: 'readGrant',    type: 'boolean'},
118     {name: 'addGrant',     type: 'boolean'},
119     {name: 'editGrant',    type: 'boolean'},
120     {name: 'deleteGrant',  type: 'boolean'},
121     {name: 'privateGrant', type: 'boolean'},
122     {name: 'exportGrant',  type: 'boolean'},
123     {name: 'syncGrant',    type: 'boolean'},
124     {name: 'adminGrant',   type: 'boolean'}
125 ]);
126
127 /**
128  * Model of a tag
129  * 
130  * @constructor {Tine.Tinebase.data.Record}
131  */
132 Tine.Tinebase.Model.Tag = Tine.Tinebase.data.Record.create(Tine.Tinebase.Model.modlogFields.concat([
133     {name: 'id'         },
134     {name: 'app'        },
135     {name: 'owner'      },
136     {name: 'name'       },
137     {name: 'type'       },
138     {name: 'description'},
139     {name: 'color'      },
140     {name: 'occurrence' },
141     {name: 'rights'     },
142     {name: 'contexts'   },
143     {name: 'selection_occurrence', type: 'number'}
144 ]), {
145     appName: 'Tinebase',
146     modelName: 'Tag',
147     idProperty: 'id',
148     titleProperty: 'name',
149     // ngettext('Tag', 'Tags', n); gettext('Tag');
150     recordName: 'Tag',
151     recordsName: 'Tags'
152 });
153
154 /**
155  * replace template fields with data
156  * @static
157  */
158 Tine.Tinebase.Model.Tag.replaceTemplateField = function(tagData) {
159     if (Ext.isArray(tagData)) {
160         return Ext.each(tagData, Tine.Tinebase.Model.Tag.replaceTemplateField);
161     }
162     
163     if (Ext.isFunction(tagData.beginEdit)) {
164         tagData = tagData.data;
165     }
166     
167     var replace = {
168         'CURRENTDATE': Tine.Tinebase.common.dateRenderer(new Date()),
169         'CURRENTTIME': Tine.Tinebase.common.timeRenderer(new Date()),
170         'USERFULLNAME': Tine.Tinebase.registry.get('currentAccount').accountDisplayName
171     };
172     
173     Ext.each(['name', 'description'], function(field) {
174         for(var token in replace) {
175             if (replace.hasOwnProperty(token) && Ext.isString(tagData[field])) {
176                 tagData[field] = tagData[field].replace(new RegExp('###' + token + '###', 'g'), replace[token]);
177             }
178         }
179     }, this);
180     
181 };
182
183 /**
184  * Model of a PickerRecord
185  * 
186  * @constructor {Ext.data.Record}
187  * 
188  * @deprecated
189  */
190 Tine.Tinebase.PickerRecord = Ext.data.Record.create([
191     {name: 'id'}, 
192     {name: 'name'}, 
193     {name: 'data'}
194 ]);
195
196 /**
197  * Model of a note
198  * 
199  * @constructor {Ext.data.Record}
200  */
201 Tine.Tinebase.Model.Note = Ext.data.Record.create([
202     {name: 'id'             },
203     {name: 'note_type_id'   },
204     {name: 'note'           },
205     {name: 'creation_time', type: 'date', dateFormat: Date.patterns.ISO8601Long },
206     {name: 'created_by'     }
207 ]);
208
209 /**
210  * Model of a note type
211  * 
212  * @constructor {Ext.data.Record}
213  */
214 Tine.Tinebase.Model.NoteType = Ext.data.Record.create([
215     {name: 'id'             },
216     {name: 'name'           },
217     {name: 'icon'           },
218     {name: 'icon_class'     },
219     {name: 'description'    },
220     {name: 'is_user_type'   }
221 ]);
222
223 /**
224  * Model of a customfield definition
225  */
226 Tine.Tinebase.Model.Customfield = Ext.data.Record.create([
227     { name: 'id'             },
228     { name: 'application_id' },
229     { name: 'model'          },
230     { name: 'name'           },
231     { name: 'definition'     },
232     { name: 'account_grants' }
233 ]);
234
235 /**
236  * Model of a customfield value
237  */
238 Tine.Tinebase.Model.CustomfieldValue = Ext.data.Record.create([
239     { name: 'record_id'      },
240     { name: 'customfield_id' },
241     { name: 'value'          }
242 ]);
243
244 /**
245  * Model of a preference
246  * 
247  * @constructor {Ext.data.Record}
248  */
249 Tine.Tinebase.Model.Preference = Ext.data.Record.create([
250     {name: 'id'             },
251     {name: 'name'           },
252     {name: 'value'          },
253     {name: 'type'           },
254     {name: 'label'          },
255     {name: 'description'    },
256     {name: 'personal_only',         type: 'boolean' },
257     {name: 'locked',                type: 'boolean' },
258     {name: 'uiconfig'       },
259     {name: 'options'        }
260 ]);
261
262 /**
263  * Model of an alarm
264  * 
265  * @constructor {Ext.data.Record}
266  */
267 Tine.Tinebase.Model.Alarm = Tine.Tinebase.data.Record.create([
268     {name: 'id'             },
269     {name: 'record_id'      },
270     {name: 'model'          },
271     {name: 'alarm_time',      type: 'date', dateFormat: Date.patterns.ISO8601Long },
272     {name: 'minutes_before',  sortType: Ext.data.SortTypes.asInt},
273     {name: 'sent_time',       type: 'date', dateFormat: Date.patterns.ISO8601Long },
274     {name: 'sent_status'    },
275     {name: 'sent_message'   },
276     {name: 'options'        }
277 ], {
278     appName: 'Tinebase',
279     modelName: 'Alarm',
280     idProperty: 'id',
281     titleProperty: 'minutes_before',
282     // ngettext('Alarm', 'Alarms', n); gettext('Alarm');
283     recordName: 'Alarm',
284     recordsName: 'Alarms',
285     getOption: function(name) {
286         var encodedOptions = this.get('options'),
287             options = encodedOptions ? Ext.decode(encodedOptions) : {};
288         
289         return options[name];
290     },
291     setOption: function(name, value) {
292         var encodedOptions = this.get('options'),
293             options = encodedOptions ? Ext.decode(encodedOptions) : {};
294         
295         options[name] = value;
296         this.set('options', Ext.encode(options));
297     }
298 });
299
300 /**
301  * @namespace Tine.Tinebase.Model
302  * @class     Tine.Tinebase.Model.ImportJob
303  * @extends   Tine.Tinebase.data.Record
304  * 
305  * Model of an import job
306  */
307 Tine.Tinebase.Model.ImportJob = Tine.Tinebase.data.Record.create([
308     {name: 'files'                  },
309     {name: 'import_definition_id'   },
310     {name: 'model'                  },
311     {name: 'import_function'        },
312     {name: 'container_id'           },
313     {name: 'dry_run'                },
314     {name: 'options'                }
315 ], {
316     appName: 'Tinebase',
317     modelName: 'Import',
318     idProperty: 'id',
319     titleProperty: 'model',
320     // ngettext('Import', 'Imports', n); gettext('Import');
321     recordName: 'Import',
322     recordsName: 'Imports'
323 });
324
325 /**
326  * @namespace Tine.Tinebase.Model
327  * @class     Tine.Tinebase.Model.ExportJob
328  * @extends   Tine.Tinebase.data.Record
329  * 
330  * Model of an export job
331  */
332 Tine.Tinebase.Model.ExportJob = Tine.Tinebase.data.Record.create([
333     {name: 'scope'                  },
334     {name: 'filter'                 },
335     {name: 'export_definition_id'   },
336     {name: 'format'                 },
337     {name: 'exportFunction'         },
338     {name: 'recordsName'            },
339     {name: 'model'                  },
340     {name: 'count', type: 'int'     },
341     {name: 'options'                }
342 ], {
343     appName: 'Tinebase',
344     modelName: 'Export',
345     idProperty: 'id',
346     titleProperty: 'model',
347     // ngettext('Export', 'Export', n); gettext('Export');
348     recordName: 'Export',
349     recordsName: 'Exports'
350 });
351
352 /**
353  * Model of an export/import definition
354  * 
355  * @constructor {Ext.data.Record}
356  */
357 Tine.Tinebase.Model.ImportExportDefinition = Ext.data.Record.create(Tine.Tinebase.Model.genericFields.concat([
358     {name: 'id'             },
359     {name: 'name'           },
360     {name: 'label', sortType: Ext.data.SortTypes.asUCText },
361     {name: 'filename'       },
362     {name: 'plugin'         },
363     {name: 'description'    },
364     {name: 'model'          },
365     {name: 'plugin_options' }
366 ]));
367
368 /**
369  * @namespace Tine.Tinebase.Model
370  * @class     Tine.Tinebase.Model.Credentials
371  * @extends   Tine.Tinebase.data.Record
372  * 
373  * Model of user credentials
374  */
375 Tine.Tinebase.Model.Credentials = Tine.Tinebase.data.Record.create([
376     {name: 'id'},
377     {name: 'username'},
378     {name: 'password'}
379 ], {
380     appName: 'Tinebase',
381     modelName: 'Credentials',
382     idProperty: 'id',
383     titleProperty: 'username',
384     // ngettext('Credentials', 'Credentials', n); gettext('Credentials');
385     recordName: 'Credentials',
386     recordsName: 'Credentials'
387 });
388
389 /**
390  * @namespace Tine.Tinebase.Model
391  * @class     Tine.Tinebase.Model.Relation
392  * @extends   Tine.Tinebase.data.Record
393  * 
394  * Model of a Relation
395  */
396 Tine.Tinebase.Model.Relation = Tine.Tinebase.data.Record.create([
397     {name: 'id'},
398     {name: 'own_model'},
399     {name: 'own_id'},
400     {name: 'related_model'},
401     {name: 'related_id'},
402     {name: 'type'},
403     {name: 'remark'},
404     {name: 'related_record', sortType: Tine.Tinebase.common.recordSortType},
405     {name: 'creation_time'}
406 ], {
407     appName: 'Tinebase',
408     modelName: 'Relation',
409     idProperty: 'id',
410     titleProperty: 'related_model',
411     // ngettext('Relation', 'Relations', n); gettext('Relation');
412     recordName: 'Relation',
413     recordsName: 'Relations'
414 });
415
416 /**
417  * find duplicate relation in store
418  *
419  * @param store
420  * @param record
421  * @return int index in store
422  */
423 Tine.Tinebase.Model.Relation.findDuplicate = function(store, record) {
424     return store.findBy(function(r) {
425         return r.get('related_model') == record.get('related_model') &&
426             r.get('related_id') == record.get('related_id') &&
427             r.get('type') == record.get('type');
428     }, this);
429 };
430
431 /**
432  * @namespace Tine.Tinebase.Model
433  * @class     Tine.Tinebase.Model.Department
434  * @extends   Tine.Tinebase.data.Record
435  * 
436  * Model of a Department
437  */
438 Tine.Tinebase.Model.Department = Tine.Tinebase.data.Record.create([
439     {name: 'id'},
440     {name: 'name'},
441     {name: 'description'}
442 ], {
443     appName: 'Tinebase',
444     modelName: 'Department',
445     idProperty: 'id',
446     titleProperty: 'name',
447     // ngettext('Department', 'Departments', n); gettext('Department');
448     recordName: 'Department',
449     recordsName: 'Departments'
450 });
451
452 Tine.Tinebase.Model.Department.getFilterModel = function() {
453     return [
454         {label: i18n._('Name'),          field: 'name',       operators: ['contains']}
455     ];
456 };
457
458 /**
459  * @namespace Tine.Tinebase.Model
460  * @class     Tine.Tinebase.Model.Config
461  * @extends   Tine.Tinebase.data.Record
462  * 
463  * Model of a application config settings
464  */
465 Tine.Tinebase.Model.Config = Tine.Tinebase.data.Record.create([
466     {name: 'id'},
467     {name: 'application_id'},
468     {name: 'name'},
469     {name: 'value'},
470     {name: 'label'},
471     {name: 'description'},
472     {name: 'type'},
473     {name: 'clientRegistryInclude'},
474     {name: 'setByAdminModule'},
475     {name: 'setBySetupModule'},
476     {name: 'default'},
477     {name: 'source'}
478     //{name: 'settings'}
479 ], {
480     appName: 'Tinebase',
481     modelName: 'Config',
482     idProperty: 'id',
483     titleProperty: 'name',
484     // ngettext('Config', 'Configs', n); gettext('Configs');
485     recordName: 'Config',
486     recordsName: 'Configs'
487 });
488
489 Tine.Tinebase.Model.Tree_NodeArray = Tine.Tinebase.Model.modlogFields.concat([
490     { name: 'id' },
491     { name: 'name', label: 'Name' }, // _('Name')
492     { name: 'path', label: 'Path' }, // _('Path')
493     { name: 'size', label: 'Size' }, // _('Size')
494     { name: 'revision', label: 'Revision' }, // _('Revision')
495     { name: 'available_revisions', label: 'Available Revision' }, // _('Available Revision')
496     { name: 'type', label: 'Type' }, // _('Type')
497     { name: 'contenttype', label: 'Content Type' }, // _('Content Type')
498     { name: 'description', label: 'Description' }, // _('Description')
499     { name: 'account_grants' },
500     { name: 'grants' },
501     { name: 'acl_node' },
502     { name: 'object_id'},
503     { name: 'revision_size', label: 'Revision Size' }, // _('Revision Size')
504     { name: 'preview_count', label: 'Preview Count' }, // _('Preview Count')
505     { name: 'isIndexed', label: 'Indexed' }, // _('Indexed')
506
507     { name: 'relations' },
508     { name: 'customfields' },
509     { name: 'notes' },
510     { name: 'tags' },
511
512     { name: 'revisionProps' },
513     { name: 'notificationProps' }
514 ]);
515 /**
516  * @namespace   Tine.Tinebase.Model
517  * @class       Tine.Tinebase.Model.Tree_Node
518  * @extends     Tine.Tinebase.data.Record
519  */
520 Tine.Tinebase.Model.Tree_Node = Tine.Tinebase.data.Record.create(Tine.Tinebase.Model.Tree_NodeArray, {
521     appName: 'Tinebase',
522     modelName: 'Tree_Node',
523     idProperty: 'id',
524     titleProperty: 'name',
525     // ngettext('File', 'Files', n); gettext('File');
526     recordName: 'File',
527     recordsName: 'Files'
528 });
529
530 Tine.widgets.grid.RendererManager.register('Tinebase', 'Tree_Node', 'size', Tine.Tinebase.common.byteRenderer);
531 Tine.widgets.grid.RendererManager.register('Tinebase', 'Tree_Node', 'revision_size', Tine.Tinebase.common.byteRenderer);
532
533 Tine.Tinebase.Model.KeyFieldRecord = Tine.Tinebase.data.Record.create([
534     { name: 'id' },
535     { name: 'value' },
536     { name: 'i18nValue' },
537     { name: 'icon' },
538     { name: 'color' },
539     { name: 'system' }
540 ], {
541     appName: 'Tinebase',
542     modelName: 'KeyFieldRecord',
543     idProperty: 'id',
544     titleProperty: 'value'
545 });