1 /** 2 * @class Monk.component.WorksetManagerComponent 3 * @description A {@link Worbench.component.Component} for viewing a text chunk. 4 * @extends Workbench.component.Component 5 * @author Stéfan Sinclair 6 * @version 0.1 7 * @since Monk 0.1 8 */ 9 Monk.component.WorksetManagerComponent = function(args) { 10 11 this.worksetGrid = null; 12 13 this.worksetId = null; 14 15 // initialize worksets store 16 this.worksetsStore = new Ext.data.Store({ 17 reader: new Ext.data.XmlReader( 18 {record: 'workset', id: '@id'}, 19 [{name: 'id', mapping: '@id'}, 20 'label', 21 'trainingList', 22 'trainingListRating', 23 'workList', 24 'workListRating', 25 'itinerary', 26 'feature'] 27 ), 28 proxy: new Ext.data.HttpProxy({ 29 url: Monk.data.PROXY_URL + 'get/ProjectManager.getWorksets', 30 method: 'GET' 31 }), 32 baseParams: {projectId: Monk.component.dataManager.getProjectId()} 33 }); 34 this.worksetsStore.load(); 35 36 this.loadDialog = null; 37 38 this.saveDialog = null; 39 40 this.cachedData = {chunks: null, ratings: null, hasSystemRating: false, modifier: null, minConfidence: null, maxConfidence: null}; 41 42 this.ratingStore = null; 43 44 this.pageSize = 10; // how many workparts to display per page 45 46 this.isValid = function() { 47 if (Monk.component.dataManager.isWorksetValid()) { 48 return true; 49 } else { 50 return 'Your workset is empty and/or it does not appear to have any training data - please load a workset and rate at least 2 items before proceeding.' 51 } 52 }; 53 54 Monk.component.WorksetManagerComponent.superclass.constructor.call(this, args); 55 } 56 57 Workbench.extend(Monk.component.WorksetManagerComponent, Workbench.component.Component, { 58 59 label : "Workset Manager", 60 description : "For managing worksets of text workparts in Monk.", 61 "window" : this.window, 62 handle : function(monkEvent, data){ 63 64 if (monkEvent.instanceOf(Monk.event.workbench.LocalWindowFocus)) { 65 //this.initializeWorksetGrid(); 66 }else if (monkEvent.instanceOf(Workbench.event.ComponentLoaded)) { 67 if (monkEvent.component == this) { 68 this.cacheChunks(Monk.component.dataManager.getWorklist()); 69 } 70 }else if (monkEvent.instanceOf(Monk.event.analysis.GotPrediction)) { 71 72 var json = Monk.utils.xml2json(data.response.responseXML, " "); 73 var workset = ""; 74 (eval('workset='+json)); 75 76 var worklistRating = workset.workset.workListRating.split(','); 77 var worklist = workset.workset.workList.split(','); 78 79 // update system ratings 80 var store = this.worksetGrid.getStore(); 81 for (var i = 0; i < worklist.length; i++) { 82 var id = worklist[i]; 83 var record = store.getById(id); 84 record.set('systemRating', worklistRating[i]); 85 } 86 } else if (monkEvent.instanceOf(Monk.event.workset.WorksetLoaded)) { 87 88 this.cacheChunks(Monk.component.dataManager.getWorklist()); 89 if (this.worksetGrid == null) { 90 this.initializeWorksetGrid(); 91 } else { 92 var systemRatingColumn = this.worksetGrid.getColumnModel().getIndexById('systemRating'); 93 this.worksetGrid.getColumnModel().setHidden(systemRatingColumn, !this.cachedData.hasSystemRating); 94 this.worksetGrid.getStore().proxy.update({nodes:this.cachedData.chunks}, false); 95 this.worksetGrid.getStore().load({params:{start:0, limit: this.pageSize}}); 96 this.ratingStore.loadData(this.cachedData.ratings, false); 97 } 98 var worksetName = Monk.component.dataManager.getWorksetName(); 99 Monk.component.messenger.growl('Monk Workbench','Workset Loaded: '+worksetName); 100 this.worksetGrid.setTitle(Monk.component.dataManager.getWorksetLabel()); 101 //Ext.get('componentContent').unmask(); 102 } else if (monkEvent.instanceOf(Monk.event.chunk.ChunkChecked)) { 103 // TODO add handling for chunkschecked 104 var store = this.worksetGrid.getStore(); 105 var index = store.proxy.contains(data.id); 106 if (index != -1) { 107 if (!data.checked) { 108 store.proxy.remove(data.id); 109 this.worksetGrid.getBottomToolbar().refresh(); 110 } 111 } else if (data.checked) { 112 data.workLabel = data.text; 113 var work = Monk.data.collection.getWork(data.id); 114 if (work != null) { 115 data.authorsLabel = work.authorsLabel; 116 data.publicationDates = work.publicationDates; 117 } 118 store.proxy.update({nodes:[data]}, true); 119 this.worksetGrid.getBottomToolbar().moveLast(); 120 } 121 } else if (monkEvent.instanceOf(Monk.event.chunk.ChunksRated)) { 122 this.worksetGrid.getStore().proxy.update({nodes:data}, true); 123 this.worksetGrid.getStore().load({params:{start:0, limit: this.pageSize}}); 124 125 for (var i = 0, len = data.length; i < len; i++) { 126 var rating = data[i].userRating; 127 if (this.ratingStore.getById(rating) == null && rating != '') { 128 var ratingData = [] 129 ratingData['value'] = rating; 130 var record = new Ext.data.Record(ratingData, rating); 131 this.ratingStore.add(record); 132 } 133 } 134 } else if (monkEvent.instanceOf(Monk.event.workset.WorksetCreated)) { 135 var recordDef = Ext.data.Record.create([ 136 {name: 'id'}, 137 {name: 'label'}, 138 {name: 'trainingList'}, 139 {name: 'trainingListRating'}, 140 {name: 'workList'}, 141 {name: 'workListRating'}, 142 {name: 'itinerary'}, 143 {name: 'feature'} 144 ]); 145 var workset = Monk.component.dataManager.getWorkset(); 146 workset.id = workset.worksetId; 147 workset.label = workset.worksetName; 148 var record = new recordDef(workset); // creates a record with auto-ID 149 var recordCopy = record.copy(workset.id); // make a copy with the correct ID 150 this.worksetsStore.add(recordCopy); 151 152 this.saveDialog.hide(); 153 var worksetName = Monk.component.dataManager.getWorksetName(); 154 Monk.component.messenger.growl('Monk Workbench','Workset Created: '+worksetName); 155 } else if (monkEvent.instanceOf(Monk.event.workset.WorksetSaved)) { 156 var worksetName = Monk.component.dataManager.getWorksetName(); 157 Monk.component.messenger.growl('Monk Workbench','Workset Saved: '+worksetName); 158 } else if (monkEvent.instanceOf(Monk.event.workset.WorksetReset)) { 159 this.resetGrid(); 160 //document.getElementById("count").innerHTML = 0; 161 } else if (monkEvent.instanceOf(Monk.event.chunk.ChunksContainingFeatureWithinWorksetRetrieved)) { 162 var json = Monk.utils.xml2json(data.response.responseXML, " "); 163 var works = ""; 164 (eval('works='+json)); 165 166 var combinedWorks = []; 167 if (works.works.work != null) { // json array fix 168 if (works.works.work.length == null) { 169 works.works.work = [works.works.work]; 170 } 171 combinedWorks = combinedWorks.concat(works.works.work); 172 } 173 if (works.works.workpart != null) { // json array fix 174 if (works.works.workpart.length == null) { 175 works.works.workpart = [works.works.workpart]; 176 } 177 combinedWorks = combinedWorks.concat(works.works.workpart); 178 } 179 180 var columns = this.worksetGrid.getColumnModel(); 181 if (columns.isHidden(4)) { 182 // show features if hidden 183 columns.setHidden(4, false); 184 } 185 186 for (var i = 0, length = combinedWorks.length; i < length; i++) { 187 var workId = combinedWorks[i].id; 188 var posTest = /\s+\(.+?\)$/; 189 var feature = data.feature.split(posTest)[0]; 190 Monk.component.dataManager.addTermsToChunk(workId, [feature]); 191 //var features = Monk.component.dataManager.getTermsForChunk(workId).join(', '); 192 //this.worksetGrid.getStore().proxy.updateRecord(workId, {features: features}); 193 } 194 this.worksetGrid.getBottomToolbar().refresh(); 195 } 196 197 }, 198 199 cacheChunks : function(worklist) { 200 var chunks = []; 201 var ratingsObject = {}; 202 this.cachedData.hasSystemRating = false; 203 var minConfidence = null; 204 var maxConfidence = null; 205 206 for (var chunkId in worklist) { 207 var work = Monk.data.collection.getWork(chunkId); 208 var chunk = worklist[chunkId]; 209 210 if (chunk.userRating != null) { 211 ratingsObject[chunk.userRating] = [chunk.userRating]; 212 } 213 if (chunk.systemRating) this.cachedData.hasSystemRating = true; 214 215 var confidence = parseFloat(chunk.confidence); 216 if (confidence < minConfidence || minConfidence == null) minConfidence = confidence; 217 if (confidence > maxConfidence || maxConfidence == null) maxConfidence = confidence; 218 219 chunk.id = chunkId; 220 if (work != null) { 221 chunk.workLabel = work.text; 222 chunk.authorsLabel = work.authorsLabel; 223 chunk.publicationDates = work.publicationDates; 224 } 225 chunks.push(chunk); 226 } 227 if (chunks.length > 0) { 228 var ratingsArray = []; 229 for (var rating in ratingsObject) { 230 ratingsArray.push(ratingsObject[rating]); 231 } 232 this.cachedData.chunks = chunks 233 this.cachedData.ratings = ratingsArray; 234 235 this.cachedData.modifier = minConfidence * -1; 236 this.cachedData.minConfidence = minConfidence + this.cachedData.modifier; 237 this.cachedData.maxConfidence = maxConfidence + this.cachedData.modifier; 238 } 239 }, 240 241 getFeatures : function(pager) { 242 pager.store.each(function(record){ 243 var id = record.get('id'); 244 var features = Monk.component.dataManager.getTermsForChunk(id); 245 if (features != null) { 246 record.set('features', features.join(', ')); 247 } 248 }, this); 249 }, 250 251 getWorksetFromStore : function(worksetId) { 252 var record = this.worksetsStore.getById(worksetId); 253 return { 254 id: worksetId, 255 label: record.get('label'), 256 projectId: Monk.component.dataManager.getProjectId(), 257 trainingList: trainingList = record.get('trainingList'), 258 trainingListRating: record.get('trainingListRating'), 259 workList: record.get('workList'), 260 workListRating: record.get('workListRating'), 261 itinerary: record.get('itinerary'), 262 feature: record.get('feature') 263 } 264 265 }, 266 267 initializeLoadDialog : function() { 268 var worksetsCombo = new Ext.form.ComboBox({ 269 fieldLabel: 'Workset', 270 name: 'workset', 271 width: 175, 272 maxHeight: 75, 273 store: this.worksetsStore, 274 triggerAction: 'all', 275 allowBlank: false, 276 editable: false, 277 forceSelection: true, 278 displayField: 'label', 279 hiddenName: 'worksetId', 280 valueField: 'id' 281 }); 282 283 var loadForm = new Ext.form.FormPanel({ 284 labelAlign: 'right', 285 labelWidth: 70, 286 border: false 287 }); 288 289 loadForm.add(worksetsCombo); 290 this.loadDialog = new Ext.Window({ 291 title: 'Load Workset', 292 height: 100, 293 width: 300, 294 modal: true, 295 shadow: true, 296 plain: true, 297 border: false, 298 collapsible: false, 299 items: loadForm, 300 buttons: [ 301 { 302 text: 'Load', 303 handler: function(){ 304 if (loadForm.getForm().isValid()) { 305 var values = loadForm.getForm().getValues(); 306 var worksetId = values.worksetId; 307 308 var workset = this.getWorksetFromStore(worksetId); 309 310 // reset grid for repopulating 311 var store = this.worksetGrid.getStore(); 312 store.removeAll(); 313 314 //Ext.get("componentContent").mask("Loading workset..."); 315 Monk.component.dataManager.setWorkset(workset); 316 317 loadForm.getForm().reset(); 318 this.loadDialog.hide(); 319 } 320 }, 321 scope: this 322 }, 323 { 324 text: 'Cancel', 325 handler: function(){ 326 this.loadDialog.hide(); 327 }, 328 scope: this 329 } 330 ] 331 }); 332 333 this.loadDialog.show(); 334 }, 335 336 initializeSaveDialog : function() { 337 var worksetName = new Ext.form.TextField({ 338 fieldLabel: 'Name', 339 name: 'name', 340 width: 175, 341 allowBlank: false 342 }); 343 344 var saveForm = new Ext.form.FormPanel({ 345 labelAlign: 'right', 346 labelWidth: 70, 347 border: false 348 }); 349 350 saveForm.add(worksetName); 351 352 this.saveDialog = new Ext.Window({ 353 title: 'Save Workset', 354 height: 100, 355 width: 300, 356 modal: true, 357 shadow: true, 358 plain: true, 359 border: false, 360 collapsible: false, 361 items: saveForm, 362 buttons: [ 363 { 364 text: 'Save', 365 handler: function(){ 366 if (saveForm.getForm().isValid()) { 367 var values = saveForm.getForm().getValues(); 368 var worksetName = values.name; 369 this.createNewWorkset(worksetName); 370 371 saveForm.getForm().reset(); 372 } 373 }, 374 scope: this 375 }, 376 { 377 text: 'Cancel', 378 handler: function(){ 379 this.saveDialog.hide(); 380 }, 381 scope: this 382 } 383 ] 384 }); 385 386 this.saveDialog.show(); 387 }, 388 389 createNewWorkset : function(worksetName) { 390 Monk.component.dataManager.setWorksetName(worksetName); 391 392 // TODO: make sure training list is being sent with training list ratings 393 var workset = Monk.component.dataManager.getWorkset(); 394 Monk.data.workset.createWorkset(workset); 395 }, 396 397 loadWorkset : function() { 398 if (this.loadDialog == null) { 399 this.initializeLoadDialog(); 400 } else { 401 this.loadDialog.show(); 402 } 403 }, 404 405 saveWorksetAs : function() { 406 this.saveWorkset(true); 407 }, 408 409 /** 410 * Compiles the workset and saves it. 411 * @param {Boolean} saveAs If true, save workset as a copy 412 */ 413 saveWorkset : function(saveAs) { 414 var worksetId = Monk.component.dataManager.getWorksetId(); 415 if (worksetId == null || saveAs == true) { 416 // create new workset (or save a new copy) 417 if (this.saveDialog == null){ 418 this.initializeSaveDialog(); 419 } else { 420 this.saveDialog.show(); 421 } 422 } else { 423 // save the workset 424 var workset = Monk.component.dataManager.getWorkset(); 425 if (workset.trainingSet == null) { 426 // dummy data 427 workset.trainingSet = workset.workList.split(',')[0]; 428 workset.trainingSetRating = 3; 429 } 430 if (workset.workListRating == null) { 431 var count = workset.workList.split(',').length; 432 var rating = "3"; 433 for (var i = 0; i < count - 1; i++){ 434 rating += ",3" 435 } 436 workset.workListRating = rating; 437 } 438 Monk.data.workset.saveWorkset(workset); 439 } 440 }, 441 442 resetWorkset : function() { 443 this.notify(new Monk.event.workset.WorksetReset({ 444 label: 'Workset reset' 445 }) 446 ); 447 }, 448 449 initializeWorksetGrid : function() { 450 451 // debugger; 452 var recordDef = Ext.data.Record.create([ 453 {name: 'id'}, 454 {name: 'corpus'}, 455 {name: 'text'}, 456 {name: 'chunkType'}, 457 {name: 'checked'}, 458 {name: 'userRating'}, 459 {name: 'systemRating'}, 460 {name: 'confidence', type: 'float'}, 461 {name: 'features'}, 462 {name: 'workLabel'}, 463 {name: 'authorsLabel'}, 464 {name: 'publicationDates'} 465 ]); 466 467 var reader = new Ext.data.JsonReader({ 468 root: 'nodes', 469 id: 'id' 470 }, recordDef); 471 472 var store = new Ext.data.GroupingStore({ 473 reader: reader, 474 proxy: new Ext.ux.data.PagingMemoryProxy({nodes:this.cachedData.chunks}, {reader: reader}), 475 remoteSort: true, 476 groupField: 'corpus', 477 sortInfo:{field: 'text', direction: "ASC"} 478 }); 479 480 this.ratingStore = new Ext.data.SimpleStore({ 481 fields: ['value'], 482 id: 0, 483 data: this.cachedData.ratings == null ? [] : this.cachedData.ratings 484 }); 485 486 var ratingCombo = new Ext.form.ComboBox({ 487 lazyRender: true, 488 triggerAction: 'all', 489 mode: 'local', 490 displayField:'value', 491 valueField:'value', 492 store: this.ratingStore, 493 editable: true, 494 forceSelection: false, 495 validateOnBlur: false, 496 listeners: { 497 specialkey: { 498 fn: function(field, event) { 499 if (event.getKey() == event.ENTER) { 500 // stop the editor from moving to the next row 501 this.worksetGrid.stopEditing(); 502 } 503 }, scope: this 504 } 505 } 506 }); 507 508 var confidenceGradient = function(value, metadata, record, rowIndex, colIndex, store, modifier, maxConfidence){ 509 var rValue = 255; 510 var gbValue = Math.floor((value + modifier) / maxConfidence * 255); 511 metadata.attr = 'style = "background-color: rgb('+rValue+','+gbValue+','+gbValue+');"'; 512 return '<div ext:qtip="The confidence in the rating predicted by the system." style="width: 50px;"> </div>'; // just show the colour 513 } 514 515 var columnModel = new Ext.grid.ColumnModel([ 516 {header: 'Corpus', width: 50, sortable: true, dataIndex: 'corpus', renderer: function(content, el, data) {return '<span ext:qtip="' + data.data.workLabel + ': ' + data.data.authorsLabel+'">'+content+"</span>"}}, 517 {header: 'Workpart ID', hidden: true, sortable: true, dataIndex: 'id', renderer: function(content, el, data) {return '<span ext:qtip="' + data.data.workLabel + ': ' + data.data.authorsLabel+'">'+content+"</span>"}}, 518 {header: 'User Rating', id: 'userRating', sortable: true, dataIndex: 'userRating', editor: ratingCombo, renderer: function(content){ 519 if (content == '') return '<span style="color: #999999;" ext:qtip="Click to assign a rating.">Click to Rate</span>'; 520 else return '<span ext:qtip="The rating assigned by the user.">'+content+'</span>'; 521 }}, 522 {header: 'Predicted Rating', id: 'systemRating', hidden: !this.cachedData.hasSystemRating, sortable: true, dataIndex: 'systemRating', renderer: function(content, el, data) {return '<span ext:qtip="The rating predicted by the system.">'+content+"</span>"}}, 523 {header: 'Confidence', width: 60, id: 'confidence', hidden: !this.cachedData.hasSystemRating, sortable: true, dataIndex: 'confidence', renderer: confidenceGradient.createDelegate(this, [this.cachedData.modifier, this.cachedData.maxConfidence], true)}, 524 {header: 'Title', sortable: true, dataIndex: 'text', renderer : function (content) {return content.length>22 ? '<span ext:qtip="'+content+'">'+content.substring(0,22)+"...</span>" : content}}, 525 {header: 'Features', sortable: true, dataIndex: 'features', hidden: true}, 526 // {header: 'Work', width: 150, sortable: true, dataIndex: 'workLabel'}, 527 {header: 'Author', sortable: true, dataIndex: 'authorsLabel', renderer : function (content) {return content.length>15 ? '<span ext:qtip="'+content+'">'+content.substring(0,15)+"...</span>" : content}}, 528 {header: 'Date', sortable: true, dataIndex: 'publicationDates', renderer : function (content) {return content.split(/-/)[0]}} 529 ]); 530 531 // var selectionModel = new Ext.grid.CheckboxSelectionModel(); 532 533 var thisComponent = this; 534 535 var viewport = new Ext.Viewport({ 536 layout: 'fit', 537 renderTo: 'gridParent', 538 items: this.worksetGrid 539 }); 540 541 Ext.EventManager.onWindowResize(function(w, h) { 542 this.worksetGrid.setHeight(h); 543 }, this); 544 545 this.worksetGrid = new Ext.grid.EditorGridPanel({ 546 id : 'workset-manager-grid', 547 store: store, 548 /*view: new Ext.grid.GroupingView({ 549 forceFit:true, 550 groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Items" : "Item"]})' 551 }), 552 */ 553 cm: columnModel, 554 sm: new Ext.grid.RowSelectionModel(), 555 clicksToEdit: 1, 556 renderTo: 'worksetGrid', 557 height: 300, 558 viewConfig: {forceFit: false}, 559 autoWidth: true, 560 listeners: { 561 'render': function(grid){ 562 var h = viewport.getBox().height; 563 grid.setHeight(h); 564 } 565 }, 566 title : 'Workset', 567 tbar : new Ext.Toolbar([ 568 /*new Ext.Button({ 569 text : "New", 570 iconCls : 'clearBtn', 571 handler : function() {Monk.component.messenger.confirm( 572 'Monk Workbench', 573 'This will create a new, empty, workset. Do you wish to continue?', 574 function(buttonId) { 575 if (buttonId == 'yes') {this.resetWorkset();} 576 }, this, this.window.parent ? this.window.parent.window : this.window)}, 577 scope : this 578 }), 579 */ 580 new Ext.Button({ 581 text : "Load", 582 iconCls : 'loadBtn', 583 handler : this.loadWorkset, 584 scope : this 585 }), 586 new Ext.Button({ 587 text : "Save", 588 menu : [ 589 new Ext.Action({ 590 text : 'Save', 591 iconCls : 'saveBtn', 592 handler : this.saveWorkset, 593 scope : this 594 }), 595 new Ext.Action({ 596 text : 'Save As...', 597 iconCls : 'saveasBtn', 598 handler : this.saveWorksetAs, 599 scope : this 600 }) 601 ], 602 iconCls : 'saveBtn' 603 }), 604 '-', 605 new Ext.Button({ 606 text : "Revert", 607 iconCls : 'revertBtn', 608 handler : function() { 609 Monk.component.messenger.confirm( 610 'Monk Workbench', 611 'This will revert the workset to the last time it was saved (and remove any changes made since then). Do you wish to continue?', 612 function(buttonId) { 613 if (buttonId == 'yes') { 614 615 // reset grid for repopulating 616 this.resetGrid(); 617 618 //Ext.get("componentContent").mask("Loading workset..."); 619 var worksetId = Monk.component.dataManager.getWorksetId(); 620 if (worksetId == null) { 621 Monk.component.messenger.alert('Monk Workbench', 'You have no workset to revert back to.', this.window.parent ? this.window.parent.window : this.window); 622 } else { 623 Monk.component.dataManager.setWorkset(this.getWorksetFromStore(worksetId)); 624 } 625 626 } 627 }, this, this.window.parent ? this.window.parent.window : this.window) 628 }, 629 scope : this 630 }), 631 new Ext.Button({ 632 text : "Import/Export", 633 iconCls : 'exportxmlBtn', 634 menu : [ 635 new Ext.Action({ 636 text : 'Import tab separated values', 637 handler : function () { 638 Monk.component.messenger.show({ 639 title: 'Import Workset Data', 640 msg: 'Paste in rows (copied from Excel, for instance) of only two columns where the workset ID and the optional rating are separated by a tab (or space):', 641 width:600, 642 defaultTextHeight: 25, 643 buttons: Ext.MessageBox.OKCANCEL, 644 multiline: true, 645 fn: function handleImport(btn, text) { 646 var rows = text.split(/(\r\n|\r|\n)+/); 647 var nodes = []; 648 var parts; 649 var id; 650 var workId; 651 for (var i=0;i<rows.length;i++) { 652 parts = rows[i].split(/\s+/); 653 id = parts[0]; 654 workId = id.split("-"); 655 workId = workId[0]+'-'+workId[1]; 656 if (parts[0]) { 657 var work = Monk.data.collection.getWork(workId); 658 nodes.push({ 659 id: id, 660 userRating: parts[1] || "", 661 text: (workId==id ? '' : "[from] ") + (work && work.text ? work.text : 'unknown') 662 }); 663 } 664 } 665 this.notify( 666 new Monk.event.chunk.ChunksRated({ 667 label: "number of text workparts rated: "+nodes.length 668 }), nodes); 669 }, 670 scope: this 671 }, this.window.parent ? this.window.parent.window : this.window); 672 }, 673 scope : this 674 }), 675 new Ext.Action({ 676 text : 'Export as tab separated values', 677 handler : function() { 678 var worklist = Monk.component.dataManager.getWorklist(); 679 var output = ["Workpart ID","User Rating","System Rating","Workpart Type","Workpart Label"].join("\t") + "\n"; 680 for (key in worklist) { 681 output += [worklist[key].id,worklist[key].userRating,worklist[key].systemRating,worklist[key].chunkType,worklist[key].text].join("\t") + "\n"; 682 } 683 Monk.component.messenger.show({ 684 title : 'Export Workset as Tab Separated Values (TSV)', 685 msg : 'Select all the data below, copy, and paste directly into your favourite spreadsheet program.', 686 width: 600, 687 defaultTextHeight: 25, 688 buttons: Ext.MessageBox.OK, 689 multiline : true, 690 value : output, 691 scope : this 692 }, this.window.parent ? this.window.parent.window : this.window) 693 }, 694 scope : thisComponent 695 })/*, 696 697 new Ext.Action({ 698 text : 'export as XML', 699 handler : function() { 700 var worklist = Monk.component.dataManager.getWorklist(); 701 var output = ["Workpart ID","User Rating","System Rating","Workpart Type","Workpart Label"].join("\t") + "\n"; 702 for (key in worklist) { 703 output += [worklist[key].id,worklist[key].userRating,worklist[key].systemRating,worklist[key].chunkType,worklist[key].text].join("\t") + "\n"; 704 } 705 Monk.component.messenger.show({ 706 title : 'Export Workset as Tab Separated Values (TSV)', 707 msg : 'Select all the data below, copy, and paste directly into your favourite spreadsheet program.', 708 width: 600, 709 defaultTextHeight: 25, 710 buttons: Ext.MessageBox.OK, 711 multiline : true, 712 value : output, 713 scope : this 714 }, this.window.parent ? this.window.parent.window : this.window) 715 }, 716 scope : thisComponent 717 }), 718 */ 719 ] 720 }), 721 '-', 722 new Ext.Button({ 723 text : "Remove Workpart", 724 iconCls : 'deleteBtn', 725 // handler: this.resetWorksetWithConfirmation, 726 handler : function() { 727 var selections = this.worksetGrid.getSelectionModel().getSelections(); 728 if (selections.length>0) { 729 Monk.component.messenger.confirm( 730 'Monk Workbench', 731 'Are you sure you want to remove the selected text(s) from the workset?', 732 function(buttonId) { 733 if (buttonId == 'yes') { 734 for (var i=0;i<selections.length;i++) { 735 var node = selections[i]; 736 this.notify(new Monk.event.chunk.ChunkChecked({ 737 label: "Text workpart unchecked: " + node.data.text + '"', 738 checked: false 739 }), { 740 id: node.id, 741 checked: false 742 }, this); 743 } 744 } 745 }, this, this.window.parent ? this.window.parent.window : this.window) 746 } 747 else { 748 Monk.component.messenger.alert('No Workpart Selected', 'Please select a workpart before attempting to remove it.', this.window.parent ? this.window.parent.window : this.window); 749 } 750 }, 751 scope : this 752 }) 753 ]), 754 bbar: new Ext.PagingToolbar({ 755 store: store, 756 pageSize: this.pageSize, 757 displayInfo: true, 758 displayMsg: '{0} - {1} of {2}', 759 emptyMsg: 'No workparts to display', 760 listeners: { 761 'pagechange': this.getFeatures, 762 scope: this 763 }, 764 plugins: [new Ext.ux.PageSizePlugin()] 765 }) 766 }); 767 768 this.worksetGrid.on('cellclick', function(grid, rowIndex, columnIndex, event) { 769 var store = grid.getStore(); 770 var record = store.getAt(rowIndex); 771 772 // send chunk selected event, unless it's the user rating column 773 var userRatingIndex = grid.getColumnModel().getIndexById('userRating'); 774 if (columnIndex != userRatingIndex) { 775 var text = record.get('text'); 776 var chunkType = record.get('chunkType'); 777 var id = record.get('id'); 778 var corpus = record.get('corpus'); 779 780 this.notify(new Monk.event.chunk.ChunkSelected({ 781 label: 'Text workpart selected: '+'"'+text+'"' 782 }), 783 {id: id, corpus: corpus, text: text, chunkType: chunkType, displayText:true} 784 ); 785 } 786 }, this); 787 788 this.worksetGrid.on('afteredit', function(editEvent){ 789 var rating = editEvent.value; 790 var rowId = editEvent.record.id; 791 792 var selections = editEvent.grid.getSelectionModel().getSelections(); 793 794 for (var i=0;i<selections.length;i++) { 795 var id = selections[i].id; 796 797 if (rowId != id) { 798 if (selections.length > 1) { 799 selections[i].set("userRating", rating); 800 } else { 801 // the user rated a chunk, then click on another chunk 802 // so assign the rating to the original chunk 803 id = rowId; 804 } 805 } 806 807 if (this.ratingStore.getById(rating) == null) { 808 var data = [] 809 data['value'] = rating; 810 var record = new Ext.data.Record(data, rating); 811 this.ratingStore.add(record); 812 } 813 814 this.worksetGrid.getStore().proxy.updateRecord(id, {userRating: rating}); 815 816 this.notify(new Monk.event.chunk.ChunkRated({ 817 label: 'Workpart '+id+' was given a rating of '+rating 818 }),{chunkId: id, rating: rating}); 819 } 820 }, this); 821 822 var autoSizeColumns = function() { 823 for (var i = 0; i < this.colModel.getColumnCount(); i++) { 824 autoSizeColumn(i, this); 825 } 826 this.store.removeListener('load', autoSizeColumns, this); // only run this the first time 827 } 828 829 var autoSizeColumn = function(c, grid) { 830 var w = grid.view.getHeaderCell(c).firstChild.scrollWidth; 831 for (var i = 0, l = grid.store.getCount(); i < l; i++) { 832 w = Math.max(w, grid.view.getCell(i, c).firstChild.scrollWidth); 833 } 834 grid.colModel.setColumnWidth(c, w+2); 835 return w; 836 } 837 838 store.on('load', autoSizeColumns, this.worksetGrid); 839 840 if (this.cachedData.chunks != null) { 841 store.load({params:{start:0, limit: this.pageSize}}); 842 this.cachedData == {chunks: null, ratings: null}; 843 this.worksetGrid.setTitle(Monk.component.dataManager.getWorksetLabel()); 844 } 845 846 }, 847 848 resetGrid : function() { 849 this.worksetGrid.getStore().removeAll(); 850 this.worksetGrid.getStore().proxy.update({nodes:[]}); 851 this.worksetGrid.getStore().load(); 852 this.ratingStore.removeAll(); 853 this.worksetGrid.setTitle('Workset'); 854 } 855 }); 856