source: Dev/branches/rest-dojo-ui/client/rft/store.js @ 406

Last change on this file since 406 was 406, checked in by hendrikvanantwerpen, 13 years ago

Lots of small fixes.

Make it possible to read survey answers (when a question code is
provided), it is now displayed in place of the survey. More to come.

Some whitespace fixes.

File size: 9.4 KB
Line 
1define([
2    'dojo/_base/array',
3    'dojo/_base/declare',
4    'dojo/_base/Deferred',
5    'dojo/_base/json',
6    'dojo/_base/lang',
7    'dojo/_base/xhr',
8    'dojo/store/util/QueryResults'
9],function(array,declare,Deferred,json,lang,xhr,QueryResults){
10   
11    var CouchStore = declare(null, {
12        /** dojo.Store implementation for CouchDB
13         *
14         * See for details on the REST API, the wiki
15         * at http://wiki.apache.org/couchdb/HTTP_Document_API.
16         */
17        target: "",
18        accepts: "application/json",
19        idProperty: "_id",
20        revProperty: "_rev",
21        _responseIdProperty: "id",
22        _responseRevProperty: "rev",
23        constructor: function(options){
24            declare.safeMixin(this, options);
25        },
26        getIdentity: function(object){
27            return object[this.idProperty];
28        },
29        getRevision: function(object){
30            return object[this.revProperty];
31        },
32        get: function(id){
33            var dfd = new Deferred();
34            xhr("GET", {
35                url: this.target + id,
36                handleAs: "json",
37                headers: {
38                    Accept: this.accepts
39                }
40            }).then(function(result){
41                if ( result.error ) {
42                    dfd.reject(result.reason);
43                } else {
44                    dfd.resolve(result);
45                }
46            }, function(err){
47                dfd.reject(err);
48            });
49            return dfd.promise;
50        },
51        put: function(object, options){
52             // summary:
53             //     put an object in CouchDB
54             // object: Object
55             //     The object to put
56             // options: Object
57             //     Options object as
58             //         id: String
59             //
60            options = options || {};
61
62            var dfd = new Deferred();
63            var id = options.id ? options.id : this.getIdentity(object);
64            var hasId = typeof id != "undefined";
65            xhr(hasId ? "PUT" : "POST", {
66                url: hasId ? this.target + id : this.target,
67                postData: json.toJson(object),
68                handleAs: "json",
69                headers:{
70                    "Content-Type": "application/json",
71                    Accept: this.accepts
72                }
73            }).then(lang.hitch(this,function(result){
74                if ( result.error ) {
75                    dfd.reject(result.reason);
76                } else {
77                    object[this.idProperty] = result[this._responseIdProperty];
78                    object[this.revProperty] = result[this._responseRevProperty];
79                    dfd.resolve(object);
80                }
81            }), function(err){
82                dfd.reject(err);
83            });
84            return dfd.promise;
85        },
86        add: function(object, options){
87            return this.put(object,options);
88        },
89        remove: function(id,rev){
90            var dfd = new Deferred();
91            xhr("DELETE",{
92                url: this.target + id,
93                headers: {
94                    'If-Match': rev
95                }
96            }).then(function(result){
97                if ( result.error ) {
98                    dfd.reject(result.reason);
99                } else {
100                    dfd.resolve();
101                }
102            },function(err){
103                dfd.reject(err);
104            });
105            return dfd.promise;
106        },
107        query: function(query, options){
108            // summary:
109            //    query a couchdb view
110            // query: String
111            //    name of a couchdb view you want to query, relative to the current database
112            // options: Object
113            //     options object as
114            //        start: Number
115            //            Start results at this item
116            //        count: Number
117            //            Number of items to return
118            //        sort: [{attribute:'key',descending:true|false}]
119            //            CouchDB only support sorting by key, so only 'key'
120            //            is allowed as attribute value. Multiple sort items
121            //            are ignored.
122            //        key: String|Array|Object
123            //            Return only values with this key.
124            //            Excludes start/endkey usage.
125            //        startkey: String|Array|Object
126            //            Return values starting from this key.
127            //        endkey: String|Array|Object
128            //            Return values with key lower than this key.
129            //        include_docs: true|false
130            //            Return the full documents instead of the view
131            //            values.
132            //        reduce: true|false
133            //            Execute reduce on the view or not. Default depends
134            //            on if a reduce function is defined on the view.
135            //        group: true|false
136            //            Should values be grouped per key or not? Default
137            //            is false.
138            //        group_level: Number
139            //            When group = true and the key is an array,
140            //            determines which elements starting from the first
141            //            are used for grouping. Default is 0.
142            //        get_keys: true|false
143            //            Instead of returning the values or documents,
144            //            return the array of keys as the result.
145            //            This does not affect the forPairs function.
146            options = options || {};
147
148            var dfd = new Deferred();
149            var queryOpts = {};
150            if ( !query ) {
151                query = '_all_docs';
152            }
153
154            if (!lang.isString(query)) {
155                console.warn("Query must be a view name");
156            }
157
158            // Standard options
159            if (options.start >= 0) {
160                queryOpts.skip = options.start;
161            }
162            if (options.count >= 0) {
163                queryOpts.limit = options.count;
164            }
165            if (options.sort) {
166                if (options.sort[0]) {
167                    if (options.sort[0].attribute && options.sort[0].attribute !== "key") {
168                        console.warn("Can only sort on key");
169                    }
170                    if (options.sort[0].descending) {
171                        queryOpts.descending = true;
172                    }
173                }
174                if (options.sort.length > 1) {
175                    console.warn("multiple sort fields not supported");
176                }
177            }
178
179            // Custom options
180            if (options.key !== undefined) {
181                queryOpts.key = options.key;
182            } else if (options.keys !== undefined) {
183                queryOpts.keys = options.keys;
184            } else if (options.startkey !== undefined || options.endkey !== undefined) {
185                queryOpts.startkey = options.startkey;
186                queryOpts.endkey = options.endkey;
187            }
188            if (options.include_docs !== undefined) {
189                queryOpts.include_docs = options.include_docs;
190            }
191            if (options.reduce !== undefined) {
192                queryOpts.reduce = options.reduce;
193            }
194            if (options.group !== undefined) {
195                queryOpts.group = options.group;
196                if (options.group_level !== undefined) {
197                    queryOpts.group_level = options.group_level;
198                }
199            }
200
201            for (var qp in queryOpts) {
202                queryOpts[qp] = json.toJson(queryOpts[qp]);
203            }
204            query += '?' + xhr.objectToQuery(queryOpts);
205
206            xhr("GET", {
207                url: this.target + query,
208                handleAs: "json",
209                headers: {
210                    Accept: this.accepts
211                }
212            }).then(function(result){
213                if (result.error) {
214                    dfd.reject(result.reason);
215                } else  {
216                    var results;
217                    var values = array.map(result.rows,function(result){
218                        return options.include_docs === true ? result.doc : result.value;
219                    });
220                    var keys = array.map(result.rows,function(result){
221                        return result.key;
222                    });
223                    if (options.get_keys === true) {
224                        results = keys;
225                        results.values = values;
226                    } else {
227                        results = values;
228                        results.keys = keys;
229                    }
230                    dfd.resolve(results);
231                }
232            },function(err){
233                dfd.reject(err);
234            });
235            return CouchResults(dfd.promise);
236        }
237    });
238
239    function CouchResults(results) {
240        results = QueryResults(results);
241        results.forPairs = function(callback,thisObject) {
242            callback = lang.hitch(thisObject,callback);
243            return Deferred.when(results,function(results) {
244                var values = results.values || results;
245                var keys = results.keys || results;
246                return array.forEach(values, function(value,index) {
247                    callback(value,keys[index],index);
248                });
249            });
250        };
251        return results;
252    }
253
254    return new CouchStore({target: 'data/rft/'});
255
256});
Note: See TracBrowser for help on using the repository browser.