1 /**
  2  * @author Amit Kumar
  3  * @date 02/19/2008
  4  * @since 1.2M1
  5  * @extends Workbench.component.Component
  6  * @description This component displays the works in worksets/collections and by authors
  7  * It allows users to select two worksets and submit them for feature comparison.
  8  * @extends Workbench.component.Component
  9  * @class Monk.component.IntegratedBrowserComponent
 10  */
 11 
 12 
 13 String.prototype.ellipse = function(maxLength){
 14     if(this.length > maxLength){
 15         return this.substr(0, maxLength-3) + '...';
 16     }
 17     return this;
 18 };
 19 
 20 
 21 Monk.component.IntegratedBrowserComponent = function(args) {
 22   this.loopback=false;
 23 
 24   var worksetReader=new Ext.data.XmlReader({record : 'workset', id : '@id'}
 25                 , new Ext.data.Record.create([
 26                 {name : 'id', mapping : '@id'},
 27                 {name: 'label', mapping:'label'},
 28                 'workList',
 29                 'trainingList',
 30                 'trainingListRating',
 31                 {name: 'type',mapping: 'label', convert: function(value){return 'workset'}},
 32                 {name:'countWorks', mapping:'workList', type: 'int', convert: function(value){
 33                     if(value==null){
 34                         return 0;
 35                     }
 36                     return value.split(',').length;
 37                 }},
 38                 {name: 'dateValue', mapping:'date[@type=created]'}
 39                 ]));
 40 
 41      var authorReader=new Ext.data.XmlReader({record : 'author', id : '@id'}
 42                 , new Ext.data.Record.create([
 43                 {name : 'id', mapping : '@id'},
 44                 {name: 'label', mapping:'label'},
 45                 {name: 'type',mapping: 'label', convert: function(value){return 'author'}},
 46                 {name:'countWorks', mapping:'numWorks', type: 'int'},
 47                 {name: 'dateValue', mapping:'@birthYear'}
 48        ]));
 49 
 50 
 51        var collectionReader=new Ext.data.XmlReader({record : 'collection', id : '@id'}
 52                 , new Ext.data.Record.create([
 53                 {name : 'id', mapping : '@id'},
 54                 {name: 'label', mapping:'label'},
 55                 {name: 'type',mapping: 'label', convert: function(value){return 'collection'}},
 56                 {name:'countWorks', mapping:'numWorks', type: 'int'},
 57                 {name: 'dateValue', mapping: 'label', convert: function(value){return ''}}
 58 
 59        ]));
 60 
 61         this.worksetStore = new Ext.data.Store({
 62             reader: worksetReader,
 63             url: Monk.data.PROXY_URL + 'get/ProjectManager.getWorksets',
 64             baseParams: {projectId: Monk.component.dataManager.getProjectId()},
 65             autoLoad: true,
 66             listeners: {
 67                 load: {
 68                     fn: function(store, records, options) {
 69                         this.collectionStore.load();
 70                         this.objectStore.add(records);
 71                     },
 72                     scope: this
 73                 },
 74                 loadexception: {
 75                     fn: function() {
 76                         this.collectionStore.load();
 77                     },
 78                     scope: this
 79                 }
 80             }
 81         });
 82 
 83          this.collectionStore = new Ext.data.Store({
 84             reader: collectionReader,
 85             url: Monk.data.PROXY_URL + 'get/CorpusManager.getCorpora',
 86             //autoLoad: true,
 87             listeners: {
 88                 load: {
 89                     fn: function(store, records, options) {
 90                         this.authorStore.load();
 91                         this.objectStore.add(records);
 92                     },
 93                     scope: this
 94                 },
 95                 loadexception: {
 96                     fn: function() {
 97                         this.authorStore.load();
 98                     },
 99                     scope: this
100                 }
101             }
102         });
103 
104         this.authorStore = new Ext.data.Store({
105             reader: authorReader,
106             url: Monk.data.PROXY_URL + 'get/CorpusManager.getAuthors',
107             baseParams: {corpusId: 'all'},
108             //autoLoad: true,
109             listeners: {
110                 load: {
111                     fn: function(store, records, options) {
112                         this.objectStore.add(records);
113                         this.view.setStore(this.objectStore);
114                     },
115                     scope: this
116                 },
117                 loadexception: {
118                     fn: function() {
119                         this.view.setStore(this.objectStore);
120                     },
121                     scope: this
122                 }
123             }
124         });
125 
126  	   this.objectStore = new Ext.data.SimpleStore({
127             fields: ['id','label','type','countWorks','dateValue'],
128             sortInfo: {field: 'type', direction: 'DESC'}
129         });
130 
131         this.selectedStore = new Ext.data.SimpleStore({
132             fields: ['id','label','type','countWorks','dateValue'],
133             listeners: {
134                 add: {
135                     fn: function(store, records, index) {
136                         if (store.getCount() > 2) {
137                             store.remove(store.getAt(0));
138                         }
139                         if (store.getCount() == 2) {
140                             Ext.getCmp('submit-works').enable();
141                         } else {
142                             Ext.getCmp('submit-works').disable();
143                         }
144                     },
145                     scope: this
146                 },
147                 remove: {
148                     fn: function(store, record, index) {
149                         if (store.getCount() == 2) {
150                             Ext.getCmp('submit-works').enable();
151                         } else {
152                             Ext.getCmp('submit-works').disable();
153                         }
154                     },
155                     scope: this
156                 }
157             }
158         });
159 
160    Monk.component.IntegratedBrowserComponent.superclass.constructor.call(this, args);
161  }
162 
163 
164 Workbench.extend(Monk.component.IntegratedBrowserComponent, Workbench.component.Component, {
165 label : "Browse Works by Authors, Collections and Worksets",
166 description : "This component is for browse interface",
167 "window" : this.window,
168 
169     // cache the workset information
170     lookup : {},
171     initTemplates : function(){
172         this.thumbTemplate = new Ext.XTemplate(
173             '<tpl for=".">',
174                 '<div class="thumb-wrap {type} x-unselectable">',
175                     '<div class="shadow1">',
176                     '<div class="shadow2">',
177                     '<div class="thumb">',
178                         '<tpl if="type == \'collection\'">',
179                             'Collection:<br/>',
180                         '</tpl>',
181                         '<tpl if="type == \'workset\'">',
182                             'Workset:<br/>',
183                         '</tpl>',
184                         '<tpl if="type == \'author\'">',
185                             'Works by:<br/>',
186                         '</tpl>',
187                         '{label}',
188                     '</div>',
189                     '</div>',
190                     '</div>',
191                 '</div>',
192             '</tpl>'
193         );
194         this.thumbTemplate.compile();
195         this.detailsTemplate = new Ext.XTemplate(
196             '<div class="details-info">',
197                 '<tpl for=".">',
198                     '<ul>',
199                         '<li>',
200                             '<tpl if="type == \'collection\'">',
201                                 'Collection:',
202                             '</tpl>',
203                             '<tpl if="type == \'workset\'">',
204                                 'Workset:',
205                             '</tpl>',
206                             '<tpl if="type == \'author\'">',
207                                 'Works by:',
208                             '</tpl>',
209                         '</li>',
210                         '<li><b>{label}</b></li>',
211                         '<li>{countWorks} Work/Workparts</li>',
212                     '</ul>',
213                   '</tpl>',
214             '</div>'
215         );
216         this.detailsTemplate.compile();
217     },
218     // called when user clicks on a workset thumbnail
219     showDetails : function(dataview, selections){
220         var selNode = selections[0];
221         var detailEl = Ext.getCmp('details-panel').body;
222         var paramValues = new Array();
223         if (selNode != null) {
224             var selRecord = dataview.getRecord(selNode);
225             Workbench.console.info("NODE ID: " + selRecord.get('id'));
226             var data = this.lookup[selRecord.get('id')];
227             Workbench.console.info("DATA: " + data);
228             this.detailsTemplate.overwrite(detailEl, data);
229 
230             //var featureType1="feature_spelling_gender";
231             //var featureType2 ="feature_lemma_gender";
232 
233             var featureType1 = "spelling";
234             var featureType2 = "lemma";
235 
236 
237             if(data.type=="collection"){
238                 paramValues.corpusCriterion =data.id;
239     
240                 this.notify(new Monk.event.workbench.AdvancedSearchQuery({
241                     label: 'new search request: '
242                 }), [paramValues]);
243     
244                 this.notify(new Monk.event.chart.FeatureComparison({
245                     label: 'compare features: '
246                 }), {"type":"collection","featureType":featureType1,"queryParam": paramValues});
247     
248                 this.notify(new Monk.event.chart.FeatureComparison({
249                     label: 'compare features: '
250                  }), {"type":"collection","featureType":featureType2,"queryParam": paramValues});
251 
252             }else if(data.type=="author"){
253                 // search
254                  paramValues.authorName =data.id;
255                  this.notify(new Monk.event.workbench.AdvancedSearchQuery({
256                         label: 'new search request: '
257                  }), [paramValues]);
258                  
259             }else{
260 
261                 // workset selection
262                  this.notify(new Monk.event.project.LoadSelectedWorkset({
263                         label: 'workset selection request: '
264                  }), data.id);
265                  this.notify(new Monk.event.chart.FeatureComparison({
266                         label: 'compare features: '
267                  }), {"type":"workset","featureType":featureType1,"queryParam": data.id});
268                  this.notify(new Monk.event.chart.FeatureComparison({
269                         label: 'compare features: '
270                   }), {"type":"workset","featureType":featureType2,"queryParam": data.id});
271             }
272         }else{
273             detailEl.update('<div style="padding:10px;">Click a work from the list to view its details.</div>');
274         }
275     },
276     // filter function for searching a project for worksets
277     filter : function(){
278         var filter = Ext.getCmp('filter');
279         this.view.store.filter('label', filter.getValue(),true,false);
280         this.view.clearSelections();
281     },
282     // reset show all the worksets
283     reset : function(){
284         if(this.win.rendered){
285             Ext.getCmp('filter').reset();
286             this.view.getEl().dom.scrollTop = 0;
287         }
288         this.view.store.clearFilter();
289         this.view.clearSelections();
290     },
291 
292 
293     /**Throw notification that two containers have been selected
294      * for feature comparisons
295      *
296      */
297     sendContainersSelectedNotification: function(container1, container2){
298         Workbench.console.info("throw notification: " + container1.type  + "   " + container2.type);
299     },
300 
301     onLoadException : function(v,o){
302         this.view.getEl().update('<div style="padding:10px;">Error loading worksets.</div>');
303     },
304 
305 
306 handle : function(monkEvent, data) {
307     if (monkEvent.instanceOf(Monk.event.chunk.ChunksSimilarRetrieved)) {
308         var store = Monk.component.dataManager.getResultStore();
309 
310         if (store.getCount() > 0) {
311             var authors = [];
312             store.each(function(record) {
313                 var author = record.get('author');
314                 if (authors.indexOf(author) == -1) authors.push(author);
315             }, this);
316             var authorCount = authors.length;
317             if (authorCount == 1) authorCount += ' Author';
318             else authorCount += ' Authors';
319     
320             var genres = [];
321             store.each(function(record) {
322                 var genre = record.get('genre');
323                 if (genres.indexOf(genre) == -1) genres.push(genre);
324             }, this);
325             var genreCount = genres.length;
326             if (genreCount == 1) genreCount += ' Genre';
327             else genreCount += ' Genres';
328     
329             var earliestCirculation = 0;
330             var latestCirculation = 0;
331             store.each(function(record) {
332                 var circulationStart = record.get('circulationStart');
333                 var circulationEnd = record.get('circulationEnd');
334                 if (circulationStart < earliestCirculation || earliestCirculation == 0) earliestCirculation = circulationStart;
335                 if (circulationEnd > latestCirculation) latestCirculation = circulationEnd;
336             }, this);
337             var circulationPeriod = 'Circulation: '+earliestCirculation + '-' + latestCirculation;
338             
339             var detailsList = Ext.DomQuery.selectNode('ul', Ext.getCmp('details-panel').body.dom);
340             var lastItem = Ext.get(detailsList).last('li');
341             
342             Ext.DomHelper.insertAfter(lastItem, {
343                 tag: 'li', html: genreCount
344             });
345             Ext.DomHelper.insertAfter(lastItem, {
346                 tag: 'li', html: authorCount
347             });
348             Ext.DomHelper.insertAfter(lastItem, {
349                 tag: 'li', html: circulationPeriod
350             });
351         }
352     }
353 },
354 
355 init: function(){
356    this.initTemplates();
357    this.objectStore.on('afterload', function(){this.view. clearSelections();},this);
358 
359    var formatData = function(data){
360         //debugger;
361         data.id=data.id;
362         data.name = data.label;
363         data.shortName = data.label.ellipse(15);
364         format="Y-m-d H:i:s.0";
365         var dt = new Date();
366         if(data.dateCreated!=null){
367             try{
368                 dt = Date.parseDate(data.dateCreated,format);
369             }catch(err){
370 
371             }
372         }
373         data.date = dt;
374         this.lookup[data.id] = data;
375         return data;
376     };
377 
378     this.view = new Ext.DataView({
379         id: 'works-view',
380         tpl: this.thumbTemplate,
381         singleSelect: true,
382         overClass:'x-view-over',
383         itemSelector: 'div.thumb-wrap',
384         emptyText : '<div style="padding:10px;">No works match the specified filter.</div>',
385         listeners: {
386             'selectionchange': {fn:this.showDetails, scope:this, buffer:100},
387 //            'click'          : {
388 //                fn: function(dataview, index, node, event) {
389 //                    Workbench.console.info(node);
390 //                }, scope: this
391 //            },
392             'dblclick'       : {fn:
393                 function(dataview, index, node, event){
394                     if(node != null){
395                         var record = dataview.getRecord(node);
396                         var data = this.lookup[record.id];
397                         if (this.selectedStore.indexOf(record) == -1) {
398                             this.selectedStore.add(record);
399                         } else {
400                             this.selectedStore.remove(record);
401                         }
402                     }
403                 },
404                 scope:this
405             },
406             'loadexception'  : {fn:this.onLoadException, scope:this},
407             'beforeselect'   : {fn:function(view){
408                 return view.store.getRange().length > 0;
409             }},
410             'render'         : {
411                 fn: function(view) {
412                     Ext.DomHelper.insertFirst(view.getEl(), '<div class="loading-indicator">Loading works...</div>');
413                 }
414             }
415         },
416         prepareData: formatData.createDelegate(this)
417     });
418 
419     var viewport = new Ext.Viewport({
420          layout: 'fit',
421          renderTo: 'container',
422          items: {
423             title: 'Browse and Select Works by Authors, from Collections and Project Worksets',
424             id: 'img-chooser-dlg',
425             layout: 'border',
426             minWidth: 500,
427             minHeight: 300,
428             border: false,
429             items:[{
430                 id: 'img-chooser-view',
431                 region: 'center',
432                 autoScroll: true,
433                 items: this.view,
434                 tbar:[
435                     'Filter:',
436                 {
437                     xtype: 'textfield',
438                     id: 'filter',
439                     selectOnFocus: true,
440                     width: 100,
441                     listeners: {
442                         'render': {fn:function(){
443                             Ext.getCmp('filter').getEl().on('keyup', function(){
444                                 this.filter();
445                             }, this, {buffer:500});
446                         }, scope:this}
447                     }
448                 }, '-',
449                     'Sort By:',
450                 {
451                     id: 'sortSelect',
452                     xtype: 'combo',
453                     triggerAction: 'all',
454                     width: 65,
455                     editable: false,
456                     mode: 'local',
457                     displayField: 'name',
458                     valueField: 'value',
459                     lazyInit: false,
460                     value: 'type',
461                     store: new Ext.data.SimpleStore({
462                         fields: ['name','value'],
463                         data : [['Type', 'type'], ['Label', 'label'], ['# Works', 'countWorks']]
464                     }),
465                     listeners: {
466                         'select': {
467                             fn: function(combo, record, index) {
468                                 var sortValue = record.get('value');
469                                 var sortDir = Ext.getCmp('sortDir').getText() == 'Asc.' ? 'ASC' : 'DESC';
470                                 this.view.store.sort(sortValue, sortDir);
471                                 this.view.clearSelections();
472                             },
473                             scope:this
474                         }
475                     }
476                 },' ',
477                 {
478                     id: 'sortDir',
479                     xtype: 'tbbutton',
480                     text: 'Desc.',
481                     iconCls: 'sortDesc',
482                     minWidth: 55,
483                     handler: function(button, event) {
484                         var sortDir = 'ASC';
485                         if (button.getText() == 'Asc.') {
486                             button.setText('Desc.');
487                             button.setIconClass('sortDesc');
488                             sortDir = 'DESC';
489                         } else {
490                             button.setText('Asc.');
491                             button.setIconClass('sortAsc');
492                         }
493                         var sortValue = Ext.getCmp('sortSelect').getValue();
494                         this.view.store.sort(sortValue, sortDir);
495                         this.view.clearSelections();
496                     },
497                     scope: this
498                 }, '-',
499                 'Show:',
500                 {
501                     id: 'restrictSelect',
502                     xtype: 'combo',
503                     triggerAction: 'all',
504                     width: 90,
505                     editable: false,
506                     mode: 'local',
507                     displayField: 'name',
508                     valueField: 'value',
509                     lazyInit: false,
510                     value: 'all',
511                     store: new Ext.data.SimpleStore({
512                         fields: ['name','value'],
513                         data : [['All', 'all'], ['Collections', 'collection'], ['Worksets', 'workset'], ['Authors', 'author']]
514                     }),
515                     listeners: {
516                        'select': {
517                             fn: function(combo, record, index) {
518                                 var filterValue = record.get('value');
519                                 if (filterValue == 'all') {
520                                     this.view.store.clearFilter();
521                                 } else {
522                                     this.view.store.filterBy(function(record, id) {
523                                         return record.get('type') == filterValue;
524                                     }, this);
525                                 }
526                                 this.view.clearSelections();
527                             },
528                             scope:this
529                         }
530                     }
531                 }]
532             },
533             {
534                 id: 'img-detail-panel',
535                 layout: 'border',
536                 region: 'east',
537                 split: true,
538                 width: 170,
539                 minWidth: 150,
540                 maxWidth: 250,
541                 items: [{
542                     id: 'details-panel',
543                     region: 'center',
544                     title: 'Details',
545                     split: true,
546                     border: false,
547                     html: '<div style="padding:10px;">Click a work from the list to view its details.</div>'
548                 },{
549                     title: 'Selected Works',
550                     region: 'south',
551                     width: 170,
552                     height: 200,
553                     minWidth: 250,
554                     border: false,
555                     items: {
556                         id: 'selected-works',
557                         xtype: 'dataview',
558                         border: false,
559                         tpl: this.thumbTemplate,
560                         //singleSelect: true,
561                         overClass:'x-view-over',
562                         itemSelector: 'div.thumb-wrap',
563                         emptyText : '<div style="padding:10px;">Double-click a work from the list to add/remove it here.</div>',
564                         store: this.selectedStore,
565                         listeners: {
566                             'selectionchange': {fn:function(){
567 
568                             }, scope:this, buffer:100},
569                             //'dblclick'       : {fn:this.doCallback, scope:this},
570                             //'loadexception'  : {fn:this.onLoadException, scope:this},
571                             'beforeselect'   : {fn:function(view){
572                                 return view.store.getRange().length > 0;
573                             }},
574                             'dblclick' : {
575                                 fn: function(dataview, index, node, event){
576                                     if(node != null){
577                                         var record = dataview.getRecord(node);
578                                         this.selectedStore.remove(record);
579                                     }
580                                 },
581                                 scope: this
582                             }
583                         }
584                     },
585                     bbar: [{
586                         xtype: 'tbfill'
587                     },{
588                         id: 'submit-works',
589                         text: 'Submit Selected Works',
590                         disabled: true,
591                         handler: function() {
592                             
593                         },
594                         scope: this
595                     }]
596                 }]
597             }]
598         }
599 
600     });
601 }
602 
603 });