1 // ==========================================================================
  2 // Project:   Greenhouse
  3 // Copyright: ©2010-2010 Mike Ball
  4 // ==========================================================================
  5 /*globals Greenhouse */
  6 
  7 /**
  8   This DataSource connects to the SproutCore sc-server to retrieve files
  9 */
 10 Greenhouse.DataSource = SC.DataSource.extend({
 11 
 12   /**
 13     Fetch a group of records from the data source.
 14   */
 15   fetch: function(store, query) {
 16     var ret = NO, rt = query.get('recordType');
 17     if(rt === Greenhouse.File || rt === Greenhouse.Dir){
 18       ret = this.listFiles(store, query);
 19     }
 20     else if(rt === Greenhouse.Target){
 21       ret = this.fetchTargets(store, query);
 22     }
 23     else if(rt === Greenhouse.ViewConfig){
 24       ret = this.fetchViewConfigs(store,query);
 25     }
 26     return ret;
 27   },
 28 
 29   // ..........................................................
 30   // Get file list
 31   //
 32   listFiles: function(store, query){
 33     SC.Request.create({type: 'GET', isJSON: YES, address: '/sproutcore/fs/apps%@/?action=list'.fmt(query.get('urlPath'))})
 34       .notify(this,this.listFilesDidComplete, {query: query, store: store})
 35       .send();
 36   },
 37 
 38   listFilesDidComplete: function(request, options){
 39     var response = request.get('response'),
 40         query    = options.query,
 41         store    = options.store,
 42         storeKeys, recordTypes;
 43 
 44     if (!SC.$ok(response)) {
 45       console.error("Couldn't request files");
 46     }
 47     else {
 48       recordTypes = response.map(function(item){
 49         return item.type === 'File' ? Greenhouse.File : Greenhouse.Dir;
 50       });
 51       storeKeys = store.loadRecords(recordTypes, response);
 52       store.loadQueryResults(query, storeKeys);
 53       Greenhouse.sendAction('fileListCallDidComplete');
 54     }
 55   },
 56 
 57   // ..........................................................
 58   // FETCHING TARGETS
 59   //
 60 
 61   /**
 62     Fetch the actual targets.  Only understands how to handle a remote query.
 63   */
 64   fetchTargets: function(store, query) {
 65 
 66     if (!query.get('isRemote')) return NO ;
 67 
 68     SC.Request.getUrl('/sc/targets.json')
 69       .set('isJSON', YES)
 70       .notify(this, 'fetchTargetsDidComplete', { query: query, store: store })
 71       .send();
 72     return YES ;
 73   },
 74 
 75   fetchTargetsDidComplete: function(request, opts) {
 76     var response = request.get('response'),
 77         query    = opts.query,
 78         store    = opts.store,
 79         storeKeys;
 80 
 81     if (!SC.$ok(response)) {
 82       console.error("TODO: Add handler when fetching targets fails");
 83     } else {
 84       storeKeys = store.loadRecords(Greenhouse.Target, response);
 85       store.loadQueryResults(query, storeKeys);
 86       Greenhouse.sendAction('fetchTargetsDidComplete');
 87     }
 88   },
 89 
 90   // ..........................................................
 91   // FETCHING VIEW CONFIGS
 92   //
 93   fetchViewConfigs: function(store, query){
 94     if (!query.get('isRemote')) return NO ;
 95 
 96     SC.Request.getUrl('/sc/greenhouseconf.json?app=%@'.fmt(query.get('app')))
 97       .set('isJSON', YES)
 98       .notify(this, 'fetchViewConfigsDidComplete', { query: query, store: store })
 99       .send();
100     return YES ;
101   },
102   fetchViewConfigsDidComplete: function(request, opts){
103     var response = request.get('response'),
104         query    = opts.query,
105         store    = opts.store,
106         storeKeys;
107     if (!SC.$ok(response)) {
108       console.error("TODO: Add handler when fetching view configs fails");
109     } else {
110       storeKeys = store.loadRecords(Greenhouse.ViewConfig, response);
111       store.loadQueryResults(query, storeKeys);
112     }
113   },
114 
115   // ..........................................................
116   // Single File Actions
117   //
118   /**
119     updates a single record
120 
121     @param {SC.Store} store the requesting store
122     @param {Array} storeKey key to update
123     @param {Hash} params to be passed down to data source. originated
124       from the commitRecords() call on the store
125     @returns {Boolean} YES if handled
126   */
127   updateRecord: function(store, storeKey, params) {
128     var file = store.materializeRecord(storeKey);
129     var request = SC.Request.create({type: 'POST', address: "/sproutcore/fs/%@?action=overwrite".fmt(file.get('path')),
130          body: file.get('body')})
131         .notify(this,this.updateRecordDidComplete, {file: file, storeKey: storeKey, store: store})
132         .send();
133     return YES ;
134   },
135   updateRecordDidComplete: function(response, params){
136     var file = params.file, results = response.get('body'), store = params.store;
137     if(SC.ok(response)){
138       //HACK: for some reason the records are always 514 ready dirty not refreshing dirty...
139       status = store.readStatus(params.storeKey);
140       store.writeStatus(params.storeKey, SC.Record.BUSY_COMMITTING);
141       //end HACK
142       params.store.dataSourceDidComplete(params.storeKey);
143     }
144     else{
145       console.error("Couldn't update file!");
146     }
147   },
148 
149   /**
150     Called from retrieveRecords() to retrieve a single record.
151 
152     @param {SC.Store} store the requesting store
153     @param {Array} storeKey key to retrieve
154     @param {String} id the id to retrieve
155     @returns {Boolean} YES if handled
156   */
157   retrieveRecord: function(store, storeKey, params) {
158     var file = store.materializeRecord(storeKey), request;
159     if(file.kindOf(Greenhouse.File)){
160       request = SC.Request.create({type: 'GET', address: "/sproutcore/fs%@".fmt(file.get('path'))})
161           .notify(this, this.retrieveRecordDidComplete, {file: file, storeKey: storeKey, store: store})
162           .send();
163       return YES;
164     }
165     return NO;
166   },
167   retrieveRecordDidComplete: function(response, params){
168     var file = params.file, store = params.store, attributes, status;
169     if(SC.ok(response)){
170       attributes = file.get('attributes');//SC.clone(file.get('attributes'));
171       attributes.body = response.get('body');
172       //HACK: for some reason the records are always 514 ready dirty not refreshing dirty...
173       status = store.readStatus(params.storeKey);
174       store.writeStatus(params.storeKey, SC.Record.BUSY_REFRESH | (status & 0x03)) ;
175       //end HACK
176       store.dataSourceDidComplete(params.storeKey, attributes);
177     }
178     else{
179       console.error("Couldn't request file");
180     }
181   },
182   /**
183     Called from createdRecords() to created a single record.  This is the
184     most basic primitive to can implement to support creating a record.
185 
186     To support cascading data stores, be sure to return NO if you cannot
187     handle the passed storeKey or YES if you can.
188 
189     @param {SC.Store} store the requesting store
190     @param {Array} storeKey key to update
191     @param {Hash} params to be passed down to data source. originated
192       from the commitRecords() call on the store
193     @returns {Boolean} YES if handled
194   */
195   createRecord: function(store, storeKey, params) {
196     var file = store.materializeRecord(storeKey);
197     var request = SC.Request.create({type: 'POST', address: "/sproutcore/fs/%@?action=touch".fmt(file.get('path')),
198          body: file.get('body')})
199         .notify(this,this.createRecordDidComplete, {file: file, storeKey: storeKey, store: store})
200         .send();
201     return YES ;
202   },
203   createRecordDidComplete: function(response, params){
204     var file = params.file, results = response.get('body'), store = params.store;
205     if(SC.ok(response)){
206       //HACK: for some reason the records are always 514 ready dirty not refreshing dirty...
207       status = store.readStatus(params.storeKey);
208       store.writeStatus(params.storeKey, SC.Record.BUSY_COMMITTING);
209       //end HACK
210       params.store.dataSourceDidComplete(params.storeKey);
211     }
212     else{
213       console.error("Couldn't create file!");
214     }
215   },
216 
217   /**
218     Called from destroyRecords() to destroy a single record.  This is the
219     most basic primitive to can implement to support destroying a record.
220 
221     To support cascading data stores, be sure to return NO if you cannot
222     handle the passed storeKey or YES if you can.
223 
224     @param {SC.Store} store the requesting store
225     @param {Array} storeKey key to update
226     @param {Hash} params to be passed down to data source. originated
227       from the commitRecords() call on the store
228     @returns {Boolean} YES if handled
229   */
230   destroyRecord: function(store, storeKey, params) {
231     var request = SC.Request.create({type: 'POST'}), file = store.materializeRecord(storeKey);
232 
233     request.set('address', "/sproutcore/fs/%@?action=remove".fmt(file.get('path')));
234 
235     request.notify(this,this.destroyRecordDidComplete,{file: file, storeKey: storeKey, store: store}).send();
236 
237     return YES;
238   },
239 
240   destroyRecordDidComplete: function(response, params){
241     var status, store = params.store;
242     //HACK: for some reason the records are always 514 ready dirty not refreshing dirty...
243     status = store.readStatus(params.storeKey);
244     store.writeStatus(params.storeKey, SC.Record.BUSY_DESTROYING);
245     //end HACK
246     params.store.dataSourceDidDestroy(params.storeKey);
247   }
248 
249 
250 });
251