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 });