Tags are now saved with content. Added support for legacy tags database
[ajatus.git] / js / ajatus.tags.js
bloba2c0ed281dbf4437a0cbc68d243c26136a65a502
1 /*
2  * This file is part of
3  *
4  * Ajatus - Distributed CRM
5  * @requires jQuery v1.2.1
6  * 
7  * Copyright (c) 2007 Jerry Jalava <jerry.jalava@gmail.com>
8  * Copyright (c) 2007 Nemein Oy <http://nemein.com>
9  * Website: http://ajatus.info
10  * Licensed under the GPL license
11  * http://www.gnu.org/licenses/gpl.html
12  * 
13  */
15 (function($){
16     $.ajatus = $.ajatus || {};
17     
18     /**
19      * Holds all tag methods
20      * @accessor {String} cache Holds all cached tag names
21      * @accessor {String} active Currently active tag name
22      * @constructor
23      */
24     $.ajatus.tags = {
25         cache: [],
26         used_contexts: [],
27         active: ''
28     };
29     $.extend($.ajatus.tags, {
31         /**
32          * Initializes the tags
33          * @see ajatus.core.init
34          * @see ajatus.tags.load
35          * @see ajatus.tags.update_app_tag_list
36          */
37         init: function() {
38             $.ajatus.events.lock_pool.increase();
39             $.ajatus.tags.load();
40             $.ajatus.events.lock_pool.decrease();
41             $.ajatus.tags.update_app_tag_list();
42         },
43         load: function() {
44             $.ajatus.tags.used_contexts = [];
45             $.ajatus.tags.cache = [];
46             
47             var legacy_tags_db = $.ajatus.preferences.client.application_database + '_tags';
48             if ($.jqCouch.connection('db').exists(legacy_tags_db)) {
49                 $.ajatus.events.lock_pool.increase();
50                 
51                 var on_success = function(data) {
52                     if (data.total_rows == 0) {
53                         return data;
54                     }
55                     
56                     $.each(data.rows, function(i,doc){
57                         var doc = new $.ajatus.document(doc);
58                         if (! $.ajatus.tags.exists(doc.value.title.val, doc.value.title.widget.config.context, doc.value.title.widget.config.value)) {
59                             $.jqCouch.connection('doc').save($.ajatus.preferences.client.content_database, doc);
60                         }
61                     });
62                 };
63                 
64                 var list_map = function(doc) {
65                     if (   doc.value.metadata.archived.val != false
66                         && doc.value.metadata.deleted.val != false)
67                     {
68                         map(doc._id, doc);
69                     }
70                 };
71                 $.jqCouch.connection('view', on_success).temp(legacy_tags_db, list_map);
72                 
73                 $.jqCouch.connection('db').del(legacy_tags_db);                
74                 $.ajatus.events.lock_pool.decrease();
75             }
76             
77             var on_success = function(data) {
78                 if (data.total_rows <= 0) {
79                     return false;
80                 }
82                 $.each(data.rows, function(i,n){
83                     if (   typeof(n.value.title.widget.config['context']) != 'undefined'
84                         && n.value.title.widget.config['context'] != '')
85                     {
86                         var found = $.inArray(n.value.title.widget.config['context'], $.ajatus.tags.used_contexts);
87                         if (found == -1) {
88                             $.ajatus.tags.used_contexts.push(n.value.title.widget.config['context']);
89                         }
90                     }
91                     $.ajatus.tags.cache.push(n);
92                 });
93                 
94                 return data;
95             };
96             
97             $.jqCouch.connection('view', on_success).temp($.ajatus.preferences.client.content_database, function(doc){
98                 if (   doc.value._type == 'tag'
99                     && doc.value.metadata.archived.val == false
100                     && doc.value.metadata.deleted.val == false)
101                 {
102                     map(doc._id, doc.value);
103                 }
104             });
105         },
106         refresh_cache: function() {
107             $.ajatus.tags.load();
108             $.ajatus.tags.update_cache();
109         },
110         update_cache: function() {
111             $.ajatus.tags.update_app_tag_list();
112             if ($.ajatus.tags.active != '') {
113                 $.ajatus.tags.set_active($.ajatus.tags.active);
114             }
115         },
116         set_active: function(id) {
117             var select = $('#application-tags select');
118             $('option', select).each(function(i,o){
119                 if (o.value == id) {
120                     o.selected = 'selected';
121                 }
122             });
123                         
124             if (id == '') {
125                 $.ajatus.tags.active = '';
126                 return;
127             }
128             
129             var tag = $.ajatus.tags.get(id);
130             if (tag) {                
131                 $.ajatus.tags.active = tag;                
132             }
133         },
134         update_app_tag_list: function() {
135             var select = $('#application-tags select');
136             select.html('');
137             
138             var opt_groups = {};                        
139             var def_opt_grp = $('<optgroup label="' + $.ajatus.i10n.get('No context') + '" />');
140             def_opt_grp.appendTo(select);
141             
142             $.each($.ajatus.tags.used_contexts, function(i){
143                 var opt_grp = $('<optgroup label="' + this + '" />');
144                 opt_grp.prependTo(select);
145                 opt_groups[this] = opt_grp;
146             });
147             
148             $.each($.ajatus.tags.cache, function(i){
149                 var opt = $('<option>'+this.value.title.val+'</option>').attr({
150                     value: this.id
151                 });
152                 
153                 if (   typeof(this.value.title.widget.config['context']) != 'undefined'
154                     && this.value.title.widget.config['context'] != '')
155                 {
156                     var context = this.value.title.widget.config.context;
157                     opt.appendTo(opt_groups[context]);
158                 } else {
159                     opt.appendTo(def_opt_grp);
160                 }
161             });
162             
163             var def = $('<option />').attr({
164                 value: '',
165                 selected: 'selected'
166             }).html($.ajatus.i10n.get('Global Tag') + '&nbsp;');
167             def.prependTo(select);
168             select.bind('change', function(e){
169                 $.ajatus.tags.set_active(e.currentTarget.value);
170             });
171         },
172         search: function(query, context, max_res) {
173             // console.log("Search tags with: "+query);
174             
175             var results = [];
176             var context_key = false;
177             
178             if (typeof max_res != 'number') {
179                 var max_res = 20;
180             }
182             query = $.ajatus.tags._prepare_query(query);
184             var on_success = function(data) {
185                 if (data.total_rows == 0) {
186                     return [];
187                 }
188                 
189                 $.each(data.rows, function(i,n){
190                     var doc = new $.ajatus.document(n);
191                     results.push(doc);
192                 });
193                 
194                 return data;
195             };
196             
197             var rel_view = 'if (doc.value._type == "tag" ';
198             rel_view += '&& doc.value.title.val.match(/\\\\b'+query+'(.*?)\\\\b/) ';
199             if (   typeof context != 'undefined'
200                 && context != '')
201             {
202                 rel_view += '&& typeof(doc.value.title.widget.config["context"]) != "undefined" ';
203                 rel_view += '&& doc.value.title.widget.config.context == "+context+" ';
204             }
205             rel_view += '&& doc.value.metadata.archived.val == "" && doc.value.metadata.deleted.val != 1){';
206             rel_view += 'map( doc._id, doc.value );}';
208             $.jqCouch.connection('view', on_success).temp($.ajatus.preferences.client.content_database,
209                 "$.ajatus.views.generate('"+rel_view+"')", {
210                     count: max_res
211                 }
212             );
214             return results;                        
215         },
216         search_cache: function(query, context, max_res) {
217             // console.log("Search tags cache with: "+query);
219             if (typeof max_res != 'number') {
220                 var max_res = 20;
221             }
222             
223             var results = [];
224             query = $.ajatus.tags._prepare_query(query);
225             var re = new RegExp("\\b"+query+"(.*?)\\b");
226             
227             $.each($.ajatus.tags.cache, function(i, tag){
228                 if (results.length > max_res) {
229                     return;
230                 }
231                 
232                 if (tag.value.title.val.toString().match(re)) {
233                     if (   typeof context != 'undefined'
234                         && context != '')
235                     {
236                         if (   typeof(tag.value.title.widget.config['context']) != 'undefined'
237                             && tag.value.title.widget.config['context'] == context)
238                         {
239                             results.push(tag);
240                         }
241                     } else {
242                         results.push(tag);
243                     }
244                 }
245             });
246             
247             return results;
248         },
249         _prepare_query: function(query) {
250             query = query.replace(/[\(|\)|\.|\?|\;|\/]/, '');
251             query = query.replace('\\', '');
252             query = query.replace('*', '(.*?)');
253             
254             return query;
255         },
256         get: function(tag, rev, skip_cache, callback) {
257             var result = false;
258             if (typeof skip_cache == 'undefined') {
259                 var skip_cache = false;
260             }
261             
262             if (   typeof rev == 'undefined'
263                 && !skip_cache)
264             {
265                 $.each($.ajatus.tags.cache, function(i,t){
266                     if (t.id == tag) {
267                         result = t;
268                     }
269                 });
271                 if (result) {
272                     return result;
273                 }
274             }
275             
276             var on_success = function(data) {
277                 var doc = new $.ajatus.document(data);
278                 result = doc;
279                 
280                 if (typeof callback == 'function') {
281                     var fn = eval('('+callback+')');
282                     fn.apply(fn, [result]);
283                 }
284                 
285                 return data;
286             };
288             var args = {};
289             if (typeof rev != 'undefined') {
290                 args['_rev'] = rev;
291             }
293             $.jqCouch.connection('doc', on_success).get($.ajatus.preferences.client.content_database + '/' + tag, args);
294             
295             return result;
296         },
297         exists: function(tag, context, value) {            
298             var tag_ids = [];
299             var found = false;
301             $.each($.ajatus.tags.cache, function(i,t){
302                 if (t.value.title.val == tag) {
303                     found = true;
304                     
305                     if (   typeof context != 'undefined'
306                         && context != '')
307                     {
308                         if (t.value.title.widget.config.context == context) {
309                             found = true;
310                         } else {
311                             found = false;
312                         }
313                     }
314                     
315                     if (   typeof value != 'undefined'
316                         && value != '')
317                     {
318                         if (t.value.title.widget.config.value == value) {
319                             found = true;
320                         } else {
321                             found = false;
322                         }
323                     }
324                 }
325             });
327             return found;
328         },        
329         create: function(name, data, dc) {
330             if (typeof data == 'undefined') {
331                 var data = {
332                     color: '',
333                     context: '',
334                     value: ''
335                 };
336             }
337             if (typeof data == 'string') {
338                 var data = {
339                     color: '',
340                     context: data,
341                     value: ''
342                 };
343             }
344             
345             var color = data.color;
346             var context = data.context;
347             var value = data.value;
348             
349             if ($.ajatus.tags.exists(name, context, value)) {
350                 return false;
351             }
352             
353             if (typeof dc == 'undefined') {
354                 var on_success = function(data) {
355                     if (data.ok) {
356                         var msg = $.ajatus.elements.messages.create(
357                             $.ajatus.i10n.get('New tag created'),
358                             $.ajatus.i10n.get("Created new tag '%s'", [data.value.title.val])
359                         );
361                         $.ajatus.debug("saved tag: "+data.id);
363                         var tag = $.ajatus.tags.get(data.id, data.rev, true);
364                         $.ajatus.tags.cache.push(tag);
365                     }
366                     
367                     return data;
368                 };
370                 var dc = $.jqCouch.connection('doc', on_success);
371                 $.ajatus.views.on_change_actions.add('$.ajatus.tags.update_cache();');
372             }
373             
374             var tag = {
375                 value: {
376                     _type: 'tag',
377                     title: {
378                         val: name,
379                         widget: {
380                             name: 'tag',
381                             config: {
382                                 color: (color || '8596b6'),
383                                 context: (context || ''),
384                                 value: value
385                             }
386                         }
387                     }
388                 }
389             };
390             tag = new $.ajatus.document(tag);
391             
392             var now = $.ajatus.formatter.date.js_to_iso8601(new Date());
393             var new_metadata = {
394                 created: now,
395                 creator: $.ajatus.preferences.local.user.email,
396                 revised: now,
397                 revisor: $.ajatus.preferences.local.user.email
398             };
399             tag = $.ajatus.document.modify_metadata(tag, new_metadata);
400             dc.save($.ajatus.preferences.client.content_database, tag);
401             
402             return true;
403         },
404         remove: function(tag, dc) {
405             if (typeof dc == 'undefined') {
406                 var on_success = function(data) {
407                     var msg = $.ajatus.elements.messages.create(
408                         $.ajatus.i10n.get('Object deleted'),
409                         $.ajatus.i10n.get('Tag %s removed from Ajatus.', [tag.value.title.val])
410                     );
411                 };
412                 var dc = $.jqCouch.connection('doc', on_success);
413             }
415             dc.del($.ajatus.preferences.client.content_database + '/' + tag.id);
416         },
417         related: function(tags, skip_docs) {
418             var related = [];
420             if (typeof skip_docs != 'object') {
421                 var skip_docs = [];
422             }
424             var on_success = function(data) {
425                 if (data.total_rows == 0) {
426                     return;
427                 }
428                 
429                 $.each(data.rows, function(i,n){
430                     if ($.ajatus.utils.array.has_match(tags, n.value.tags.val)) {
431                         if (skip_docs.length > 0) {
432                             if ($.inArray(n.id, skip_docs) == -1) {
433                                 var doc = new $.ajatus.document(n);
434                                 related.push(doc);
435                             }
436                         } else {
437                             var doc = new $.ajatus.document(n);
438                             related.push(doc);
439                         }
440                     }
441                 });
442                 
443                 return data;
444             };
445             
446             var rel_view = 'if (typeof(doc.value.tags) != "undefined" && doc.value.tags.val.length > 0 ';
447             rel_view += '&& doc.value.metadata.archived.val == "" && doc.value.metadata.deleted.val != 1){';
448             rel_view += 'map( doc.value._type, {"_id": doc._id, "_rev": doc._rev, "_type": doc.value._type,';
449             rel_view += '"title": doc.value.title,';
450             
451             $.each($.ajatus.preferences.client.content_types, function(key,type){
452                 if (type['title_item']) {
453                     $.each(type['title_item'], function(i,part){
454                         if (type.schema[part]) {
455                             rel_view += '"'+part+'": doc.value.'+part+',';
456                         }
457                     });
458                 }
459             });
461             rel_view += '"tags": doc.value.tags })}';
462             
463             $.jqCouch.connection('view', on_success).temp($.ajatus.preferences.client.content_database, "$.ajatus.views.generate('"+rel_view+"')");
464             
465             return related;
466         }
467     });
468     
469 })(jQuery);