1 /** 2 * @class A version of MonkBase which uses <a href="http://extjs.com/">Ext 2.0</a> to create a workflow layout. 3 * @extends Monk.feature.MonkBase 4 * @author Andrew 5 * 6 * @property {Ext.Window} initialProgressWin Stores the progress window for loading metadata, etc. 7 * @property {Ext.util.MixedCollection} initialParameters Holds parameters passed in through the URL. 8 * See {@link Monk.feature.Workflow.initialParameterNames} for allowed parameter names. 9 * Possible combinations: 10 * <ul> 11 * <li>projectId and instanceId (for loading a result)</li> 12 * <li>projectId and worksetId and/or toolsetId</li> 13 * </ul> 14 * @property {Array} initialParameterNames The recognized request parameter names. 15 * <ul> 16 * <li>projectId</li> 17 * <li>worksetId</li> 18 * <li>toolsetId</li> 19 * <li>instanceId</li> 20 * </ul> 21 * @property {Array} initialDestination Where should we go after loading everything. 22 * @property {Ext.util.MixedCollection} toolWindowRegistry Used for tracking component/window relation. Format: key = windowId, item = {@link Workbench.component.Component}. 23 * @property {Ext.ux.WindowManager} windowManager Keeps track of component windows and provides layout functions. 24 * @property {Monk.component.FlowManager} flowManager Manages movement between the steps of the workflow. 25 * @property {Monk.component.ToolFlowManager} toolFlowManager Manages movement between the steps of the toolset. 26 * @property {Ext.util.MixedCollection} components The list of components (pulled from {@link Monk.feature.MonkBase#plugins}). See {@link Monk.feature.Workflow#initializeTools}. 27 * @property {Ext.util.MixedCollection} componentGroups The list of component groups (pulled from {@link Monk.feature.MonkBase#plugins}). 28 * @property {Ext.util.MixedCollection} toolsets The list of toolsets. See {@link Monk.feature.Workflow#initializeToolsets}. 29 * @property {Ext.Panel} headerPanel Contains the header. See {@link Monk.feature.Workflow#initializeHeader}. 30 * @property {Monk.framework.component.SearchComponent} searchComponent Used to perform searches in components and in the workbench. 31 * @property {Monk.component.HelpComponent} helpComponent Used to display help for each step of the workflow. 32 */ 33 Monk.feature.Workflow = function(args) { 34 35 // register the feature with the component manager 36 Workbench.component["manager"].register(this); 37 38 this.initialProgressWin = null; 39 this.initialParameters = new Ext.util.MixedCollection(); 40 this.initialParameterNames = ['projectId', 'worksetId', 'toolsetId', 'instanceId']; 41 this.initialDestination = null; 42 43 this.toolWindowRegistry = new Ext.util.MixedCollection(); 44 this.windowManager = new Ext.ux.WindowManager(); 45 this.flowManager = new Monk.component.FlowManager(); 46 this.toolFlowManager = new Monk.component.ToolFlowManager(); 47 48 this.components = new Ext.util.MixedCollection(); 49 this.componentGroups = new Ext.util.MixedCollection(); 50 this.toolsets = new Ext.util.MixedCollection(); 51 52 this.headerPanel = null; 53 this.searchComponent = new Monk.framework.component.SearchComponent(); 54 this.helpComponent = new Monk.component.HelpComponent(); 55 56 Monk.feature.Workflow.superclass.constructor.call(this, args); 57 } 58 59 Workbench.extend(Monk.feature.Workflow, Monk.feature.MonkBase, { 60 /** @lends Monk.feature.Workflow.prototype */ 61 62 label: 'Classification Tool', 63 description: 'A Classification tool using the Workflow interface.', 64 "window" : this.window, 65 66 /** 67 * Events handled by this component: 68 * <ul> 69 * <li>{@link Workbench.event.ComponentLoaded}</li> 70 * <li>{@link Workbench.event.ComponentRemoved}</li> 71 * <li>{@link Monk.event.workbench.LocalWindowFocus}</li> 72 * <li>{@link Monk.event.CollectionsMetadataHierarchyLoaded}</li> 73 * <li>{@link Monk.event.workbench.InitialParametersProcessed}</li> 74 * </ul> 75 */ 76 handle : function(monkEvent, data) { 77 if (monkEvent.instanceOf(Workbench.event.ComponentLoaded)) { 78 if (monkEvent.component != this) { 79 if (monkEvent.component.window) { 80 // update the registry entry for this component, 81 // adding the actual component for reference later 82 var componentSource = monkEvent.component.window.location.pathname; 83 var trimmedPath = componentSource.match(/\/tools.+$/); 84 if (trimmedPath != null) { 85 componentSource = trimmedPath[0]; 86 var registryKey = null; 87 var toolWindow = this.toolWindowRegistry.find(function(item, key) { 88 // only string items need to be replaced 89 if (typeof item == 'string') { 90 var value = item.indexOf(componentSource); 91 if (value != -1) { 92 registryKey = key; 93 return true; 94 } else { 95 return false; 96 } 97 } else { 98 return false; 99 } 100 }); 101 if (toolWindow) { 102 this.toolWindowRegistry.replace(registryKey, monkEvent.component); 103 } 104 } 105 } 106 } 107 } else if (monkEvent.instanceOf(Workbench.event.ComponentRemoved)) { 108 // perform additional cleanup if necessary 109 } else if (monkEvent.instanceOf(Monk.event.workbench.LocalWindowFocus)) { 110 var windowId = null; 111 var window = this.toolWindowRegistry.find(function(item, key) { 112 if (item == monkEvent.component) { 113 windowId = key; 114 return true; 115 } else { 116 return false; 117 } 118 }); 119 this.windowManager.setActive(Ext.getCmp(windowId)); 120 } else if (monkEvent.instanceOf(Monk.event.CollectionsMetadataHierarchyLoaded)) { 121 if (this.initialDestination != null) { 122 this.goToDestination(); 123 } else { 124 this.initialProgressWin.updateProgress(1.0, 'Loading Initial Parameters'); 125 this.metaDataLoaded = true; 126 } 127 } else if (monkEvent.instanceOf(Monk.event.workbench.InitialParametersProcessed)) { 128 if (this.metaDataLoaded) { 129 this.goToDestination(); 130 } 131 } 132 }, 133 134 /** 135 * Go to the destination stored in {@link Monk.feature.Workflow#initialDestination} using {@link Monk.component.FlowManager} (and {@link Monk.component.ToolFlowManager}). 136 */ 137 goToDestination : function() { 138 this.initialProgressWin.updateProgress(1, ' '); 139 this.initialProgressWin.hide(); 140 var workbenchDestination = this.initialDestination[0]; 141 var toolsetDestination = this.initialDestination[1]; 142 feature.flowManager.goToStep(workbenchDestination, true); 143 if (toolsetDestination != null) feature.toolFlowManager.getStep(toolsetDestination, false); 144 var mask = Ext.get('loading-mask'); 145 mask.setOpacity(0.9); 146 mask.shift({ 147 remove:true, 148 duration:1, 149 opacity:0.0, 150 easing:'easeIn' 151 }); 152 }, 153 154 /** 155 * Initialize everything and load the collections meta data. 156 */ 157 initialize : function() { 158 this.initialProgressWin = Monk.component.messenger.progress( 159 'Monk Workbench', 160 'Loading collections, please wait.', 161 'Loading collections list' 162 ); 163 164 Ext.Ajax.request({ 165 url: Monk.data.PROXY_URL + 'get/UserManager.setFakeUser', 166 success: function(){ 167 168 Monk.data.collection.loadMetaDataHierarchy(this.initialProgressWin); 169 170 this.getURLParameters(); 171 this.initializeTools(); 172 this.initializeToolsets(); 173 this.initializeLayout(); 174 }, 175 failure: function() { 176 Monk.component.messenger.alert('MONK Workbench', 'An server error has occurred, please restart the workbench.'); 177 }, 178 scope: this 179 }); 180 181 }, 182 183 /** 184 * Parse any parameters included in the URL and set them in {@link Monk.feature.Workflow#initialParameters}. 185 */ 186 getURLParameters : function() { 187 var params = this.window.location.search.split(/\?|&/); 188 if (params.length > 0) { 189 for (var i = 0, length = params.length; i < length; i++) { 190 var param = params[i].split('='); 191 if (param[1] != null) { 192 this.initialParameters.add(param[0],param[1]); 193 } 194 } 195 } 196 }, 197 198 /** 199 * Initialize the tools. 200 */ 201 initializeTools : function() { 202 for (var i = 0; i < this.plugins.length; i++) { 203 var plugin = this.plugins[i]; 204 205 // temp code to assign an icon to the tool 206 var toolIcon = ''; 207 208 var paths = plugin.source.split('/'); 209 paths[paths.length-1] = 'icon.gif'; 210 toolIcon = paths.join('/'); 211 212 var tool = { 213 id: plugin.id, 214 label: plugin.label, 215 icon: toolIcon, 216 clone: plugin.clone || false, 217 source: plugin.source, 218 description : plugin.description, 219 helptext : plugin.helptext, 220 group : plugin.group || plugin.id 221 }; 222 this.components.add(plugin.id, tool); 223 224 if (thisGroup = this.componentGroups.get(plugin.group)) { 225 thisGroup.push(plugin.id); 226 } else { 227 this.componentGroups.add(plugin.group, [plugin.id]) 228 } 229 } 230 }, 231 232 /** 233 * Initialize toolsets. 234 */ 235 initializeToolsets : function() { 236 var toolsetList = [ 237 238 239 /* { 240 id: 'toolset-dunnings' 241 ,label:"Dunnings Word Cloud" 242 ,pathToIcon :"resources/images/toolsets/Toolset-default.gif" 243 ,description: 'This toolset needs to be explained.' 244 ,tools:[ 245 { 246 id: "toolstep-883", 247 label: "Tool Label", 248 components: ["worksets-selector", "word-cloud", "workset-manager","collections-tree-browser"], 249 layouts: [{ 250 id: "worksets-selector-window", 251 x: 0, 252 y: 0, 253 width: 0.333, 254 height: 0.25 255 }, { 256 id: "word-cloud-window", 257 x: 0.333, 258 y: 0, 259 width: 0.666, 260 height: .97 261 }, { 262 id: "workset-manager-window", 263 x: 0, 264 y: 0.25, 265 width: 0.333, 266 height: 0.35 267 }, { 268 id: "collections-tree-browser-window", 269 x: 0, 270 y: 0.6, 271 width: 0.333, 272 height: 0.37 273 }] 274 }] 275 } 276 ,*/ 277 278 { 279 id: 'toolset-searchAndbrowse', 280 label: 'Define Worksets', 281 pathToIcon: 'resources/images/toolsets/Toolset-faces-search.gif', 282 description: 'This toolset allows you to search the collections and' + 283 ' create worksets', 284 tools: [ 285 {id: 'toolstep-001-search-and-browse', 286 label: 'Search and select works', 287 helpUrl: '../../public/tutorial/defineWorksets/defineWorksets.html#defineWorksets-step1', 288 components: ['searchAndbrowse', 'resultSummary'], 289 layouts: [ 290 {id:'searchAndbrowse-window', x: 0, y: 0, width: 0.38, height: 0.9602}, 291 {id:'resultSummary-window', x: 0.38, y: 0, width: 0.62, height: 0.9602} 292 ]}, 293 {id: 'toolstep-002-search-and-browse', 294 label: 'View Text', 295 helpUrl: '../../public/tutorial/defineWorksets/defineWorksets.html#defineWorksets-step2', 296 components: ['resultSummary', 'advanced-viewer'], 297 layouts: [ 298 {id:'resultSummary-window', x: 0, y: 0, width: 0.38, height: 0.9602}, 299 {id:'advanced-viewer-window', x: 0.38, y: 0, width: 0.62, height: 0.9602} 300 ]} 301 302 ] 303 }, 304 305 306 { 307 id: 'toolset-features', 308 label: 'Compare Worksets', 309 pathToIcon: 'resources/images/toolsets/Toolset-faces-concordance.gif', 310 description: 'This toolset allows you to compare two worksets using TF/IDF '+ 311 'frequency analysis and Dunnings Log likelihood word cloud.', 312 tools: [ 313 {id: 'toolstep-001-features', 314 label: 'Feature Comparison', 315 components: ['worksetComparisonTool','featureTool'], 316 layouts: [ 317 {id:'worksetComparisonTool-window', x: 0, y: 0, width: 0.40, height: 0.9602}, 318 {id:'featureTool-window', x: 0.40, y: 0, width: 0.60, height: 0.9602} 319 ] 320 }, 321 322 { 323 id: 'toolstep-002-feature', 324 label: 'Document Comparison', 325 components: ['resultSummary','advanced-viewer'], 326 layouts: [ 327 {id:'resultSummary-window', x: 0, y: 0, width: 0.38, height: 0.9602}, 328 {id:'advanced-viewer-window', x: 0.38, y: 0, width: 0.62, height: 0.9602} 329 ] 330 } 331 ] 332 }, 333 334 { 335 id: 'toolset-zoteroimport', 336 label: 'Import Worksets', 337 pathToIcon: 'resources/images/toolsets/Toolset-faces-import.gif', 338 description: 'This toolset allows you to import the Zotero collections and' + 339 ' create worksets', 340 tools: [ 341 {id: 'toolstep-001-zoteroimport', 342 label: 'Search and select works', 343 components: ['zoteroImporter', 'resultSummary'], 344 layouts: [ 345 {id:'zoteroImporter-window', x: 0, y: 0, width: 0.38, height: 0.9602}, 346 {id:'resultSummary-window', x: 0.38, y: 0, width: 0.62, height: 0.9602} 347 ]}, 348 {id: 'toolstep-002-zoteroimport', 349 label: 'View Text', 350 components: ['resultSummary', 'advanced-viewer'], 351 layouts: [ 352 {id:'resultSummary-window', x: 0, y: 0, width: 0.38, height: 0.9602}, 353 {id:'advanced-viewer-window', x: 0.38, y: 0, width: 0.62, height: 0.9602} 354 ]} 355 356 ] 357 }, 358 359 /* { 360 id: 'toolset-search', 361 label: 'Search By Example', 362 pathToIcon: 'resources/images/toolsets/Toolset-faces-search-by-example.gif', 363 description: 'This toolset allows you to select two worksets one of them as the training set '+ 364 ' and find documents similar by the virtue of the Lemma or Spelling Term and Inverse Document Frequency in' + 365 ' the other selected workset of documents. These two worksets could be arbitrary. ', 366 tools: [ 367 {id: 'toolstep-001-search-by-example', 368 label: 'Compare', 369 components: ['worksetSimilarityComparisonTool', 'resultSummary'], 370 layouts: [ 371 {id:'worksetSimilarityComparisonTool-window', x: 0, y: 0, width: 0.38, height: 0.9602}, 372 {id:'resultSummary-window', x: 0.38, y: 0, width: 0.62, height: 0.9602} 373 ]}, 374 375 {id: 'toolstep-002-search-by-example', 376 label: 'Browse Results', 377 components: ['resultSummary','advanced-viewer'], 378 layouts: [ 379 {id:'resultSummary-window', x: 0, y: 0, width: 0.38, height: 0.9602}, 380 {id:'advanced-viewer-window', x: 0.38, y: 0, width: 0.62, height: 0.9602} 381 ]} 382 ] 383 },*/ 384 { 385 id: 'toolset-classification', 386 label: 'Classification', 387 pathToIcon: 'resources/images/toolsets/Toolset-faces-search-by-example.gif', 388 description: 'This toolset allows you to rate works in a workset to indicate work '+ 389 'parts of interest (e.g. in 2 classes: sentimental or not sentimental texts), '+ 390 'and then to find other texts in the workset that have statistical word usage '+ 391 'characteristics similar to those you rated.', 392 tools: [ 393 { 394 id: 'toolstep-001', 395 label: 'workset selection and rating', 396 components: [/*'collections-tree-browser',*/ 'workset-manager', 'advanced-viewer'], 397 layouts: [ 398 /* {id:'collections-tree-browser-window', x: 0, y: 0, width: 0.4499, height: 0.4506},*/ 399 {id:'workset-manager-window', x: 0, y: 0, width: 0.4499, height:0.9702}, 400 {id:'advanced-viewer-window', x: 0.4499, y: 0, width: 0.55, height: 0.9702} 401 ]}, 402 { 403 id: 'toolstep-002', 404 label: 'options', 405 components: ['seasr-manager']}, 406 { 407 id: 'toolstep-003', 408 label: 'prediction', 409 components: ['workset-manager','advanced-viewer'], 410 layout:[ 411 {id:'workset-manager-window', x: 0, y: 0, width: 0.4499, height: 0.9702}, 412 {id:'advanced-viewer-window', x: 0.4499, y: 0, width: 0.55, height: 0.9702} 413 ] 414 }, 415 { 416 id: 'toolstep-004', 417 label: 'features', 418 components: [ 'features-chart', 'advanced-viewer'], 419 layouts: [ 420 {id:'features-chart-window', x: 0, y: 0, width: 0.4499, height: 0.9702}, 421 {id:'advanced-viewer-window', x: 0.4499, y: 0, width: 0.55, height: 0.9702} 422 ]} 423 ] 424 }, 425 { 426 id: 'toolset-editworkset', 427 label: 'Edit Worksets', 428 pathToIcon: 'resources/images/toolsets/Toolset-faces-edit.gif', 429 description: 'This toolset allows you modify a workset -create a new workset or ' + 430 ' remove works from a workset', 431 tools: [ 432 {id: 'toolstep-001-edit', 433 label: 'Select Workset', 434 helpUrl: '../../public/tutorial/editWorkset/editWorkset.html#editWorkset-step1', 435 components: ['worksetselector', 'searchAndbrowse', 'resultSummary'], 436 layouts: [ 437 {id:'worksetselector-window', x: 0, y: 0, width: 0.38, height: 0.3}, 438 {id:'searchAndbrowse-window', x: 0, y: 0.3, width: 0.38, height: 0.6602}, 439 {id:'resultSummary-window', x: 0.38, y: 0, width: 0.62, height: 0.9602} 440 ]}, 441 {id: 'toolstep-002-edit', 442 label: 'View Text', 443 helpUrl: '../../public/tutorial/editWorkset/editWorksets.html#editWorksets-step2', 444 components: ['resultSummary', 'advanced-viewer'], 445 layouts: [ 446 {id:'resultSummary-window', x: 0, y: 0, width: 0.38, height: 0.9602}, 447 {id:'advanced-viewer-window', x: 0.38, y: 0, width: 0.62, height: 0.9602} 448 ]} 449 450 ] 451 } 452 453 454 /*, { 455 id: 'toolset-browse', 456 label: 'Browse Works', 457 pathToIcon: 'resources/images/toolsets/Toolset-faces-browse.gif', 458 description: 'This toolset allows you to browse for works by authors, collection and worksets.' + 459 'It allows you to create new worksets, based on a search criterion.', 460 tools: [ 461 {id: 'toolstep-001-browse', 462 label: 'Authors, Worksets and Collections', 463 components: ['browseTool', 'resultSummary'], 464 layouts: [ 465 {id:'browseTool-window', x: 0, y: 0, width: 0.50, height: 0.9602}, 466 {id:'resultSummary-window', x: 0.50, y: 0, width: 0.50, height: 0.9602} 467 ] 468 }, 469 {id: 'toolstep-002-browse', 470 label: 'View Documents', 471 components: ['resultSummary','advanced-viewer'], 472 layouts: [ 473 {id:'resultSummary-window', x: 0, y: 0, width: 0.38, height: 0.9602}, 474 {id:'advanced-viewer-window', x: 0.38, y: 0, width: 0.62, height: 0.9602} 475 ]} 476 ] 477 } 478 */ 479 /* , 480 { 481 id: 'toolset-concordance' 482 ,label:"Concordance Viewer" 483 ,pathToIcon:"resources/images/toolsets/Toolset-default.gif" 484 ,description: 'This toolset needs to be explained.' 485 ,tools:[ 486 { 487 id:"toolstep-2801" 488 ,label:"workset selection and rating" 489 ,components:["collections-tree-browser","workset-manager","concordance"] 490 } 491 ] 492 } 493 */ 494 /*{ 495 id: 'toolset-search-beta', 496 label: 'beta search by example', 497 pathToIcon: 'resources/images/toolsets/Toolset-default.gif', 498 description: 'This is a beta version of the search by example toolset.', 499 tools: [ 500 {id: 'toolstep-000', 501 label: 'workset selection', 502 components: ['collections-tree-browser', 'mandala']}, 503 {id: 'toolstep-001', 504 label: 'workset rating', 505 components: ['workset-manager', 'chunk-viewer']}, 506 {id: 'toolstep-002', 507 label: 'options', 508 components: ['seasr-manager']}, 509 {id: 'toolstep-003', 510 label: 'results', 511 components: ['workset-manager', 'features-chart', 'chunk-viewer'], 512 layouts: [ 513 {id:'features-chart-window', x: 0, y: 0, width: 0.4499, height: 0.4806}, 514 {id:'workset-manager-window', x: 0, y: 0.4792, width: 0.4499, height: 0.4896}, 515 {id:'chunk-viewer-window', x: 0.4499, y: 0, width: 0.55, height: 0.9702} 516 ]}, 517 {id: 'toolstep-004', 518 label: 'visualize results', 519 components: ['decision-tree']} 520 ] 521 }*/ 522 /*,{ 523 id: 'toolset-java-apps', 524 label: 'mandala & decision tree', 525 pathToIcon: 'resources/images/toolsets/Toolset-default.gif', 526 description: 'This is the help description for the mandala and decision tree toolset.', 527 tools: [ 528 {id: 'toolstep-001', 529 label: 'workset selection', 530 components: ['collections-tree-browser', 'mandala']}, 531 {id: 'toolstep-002', 532 label: 'workset rating', 533 components: ['workset-manager', 'chunk-viewer']}, 534 {id: 'toolstep-003', 535 label: 'run analysis', 536 components: ['seasr-manager']}, 537 {id: 'toolstep-004', 538 label: 'visualize results', 539 components: ['decision-tree']} 540 ] 541 }*/ 542 /*,{ 543 id: 'toolset-clone', 544 label: 'clone test', 545 pathToIcon: 'resources/images/toolsets/Toolset-default.gif', 546 description: 'This is the help description for the clone test toolset.', 547 tools: [ 548 {id: 'toolstep-001', 549 label: 'test clones', 550 components: ['collections-tree-browser', 'chunk-viewer', 'chunk-viewer-clone']} 551 ] 552 }*/ 553 /* ,{ 554 id: 'toolset-collection-overview', 555 label: 'simple charts', 556 pathToIcon: 'resources/images/toolsets/Toolset-faces-simple-charts.gif', 557 description: 'This is the help description for the simple charts toolset.', 558 tools: [ 559 {id: 'toolstep-001', 560 label: 'simple charts', 561 components: ['charts-config', 'google-charts'], 562 layouts: [ 563 {id:'charts-config-window', x: 0, y: 0, width: 0.38, height: 0.9602}, 564 {id:'google-charts-window', x: 0.38, y: 0, width: 0.62, height: 0.9602}, 565 ]} 566 ] 567 } 568 */ 569 /*,{ 570 id: 'toolset-faceted-browser', 571 label: 'Faceted Browser', 572 pathToIcon: 'resources/images/toolsets/Toolset-default.gif', 573 description: 'This is the help description for the faceted browser toolset.', 574 tools: [ 575 {id: 'toolstep-001', 576 label: 'Faceted Browser', 577 components: ['collections-ripper-browser']} 578 ] 579 }*/ 580 ]; 581 582 for (var i = 0; i < toolsetList.length; i++) { 583 this.toolsets.add(toolsetList[i].id, new Monk.component.Toolset(toolsetList[i])); 584 } 585 }, 586 587 /** 588 * Analyze request parameters and perform various loading operations based on their contents. 589 */ 590 initializeParameters : function() { 591 this.initialDestination = null; 592 593 // try to get the parameters 594 var projectId = this.initialParameters.get('projectId'); 595 var worksetId = this.initialParameters.get('worksetId'); 596 var toolsetId = this.initialParameters.get('toolsetId'); 597 var instanceId = this.initialParameters.get('instanceId'); 598 599 var finished = function(destination, toolstep) { 600 feature.initialDestination = [destination, toolstep]; 601 Workbench.component.manager.notify( 602 new Monk.event.workbench.InitialParametersProcessed({ 603 label: 'Initial parameters have been processed.' 604 }) 605 ); 606 } 607 608 // create the handlers 609 getInfoHandler = function(options, success, response) { 610 var projectElement = response.responseXML.getElementsByTagName('project')[0]; 611 projectData = Monk.component.dataManager.createNewProject(projectElement); 612 613 Ext.Ajax.purgeListeners(); 614 Ext.Ajax.request({ 615 url: Monk.data.PROXY_URL + 'get/SeasrManager.getSavedResultsForProject', 616 params: {projectId: projectId, value: false}, 617 method: 'GET', 618 callback: getResultsHandler, 619 scope: this 620 }); 621 622 } 623 624 getResultsHandler = function(options, success, response) { 625 var results = response.responseXML.getElementsByTagName('results')[0]; 626 Monk.component.dataManager.addResultsToProject(results, projectData); 627 Monk.component.dataManager.setProjectId(projectId); 628 629 Ext.Ajax.purgeListeners(); 630 Ext.Ajax.request({ 631 url: Monk.data.PROXY_URL + 'get/ProjectManager.getWorksets', 632 params: {projectId : projectId}, 633 method: 'GET', 634 callback: getWorksetsHandler, 635 scope: this 636 }); 637 638 } 639 640 getWorksetsHandler = function(options, success, response) { 641 var json = Monk.utils.xml2json(response.responseXML, " "); 642 var worksetsJSON = ""; 643 (eval('worksetsJSON='+json)); 644 645 projectData.worksetsToProcess = response.responseXML.getElementsByTagName('workset').length; 646 if (projectData.worksetsToProcess > 0) { 647 if (worksetsJSON.worksets.workset.length == null) { // json array fix 648 worksetsJSON.worksets.workset = [worksetsJSON.worksets.workset]; 649 } 650 for (var i = 0, length = worksetsJSON.worksets.workset.length; i < length; i++) { 651 var workset = worksetsJSON.worksets.workset[i]; 652 if (workset.workListRating == null) { 653 workset.workListRating = ""; 654 } 655 projectData.worksets.add(workset.id, workset); 656 657 Ext.Ajax.purgeListeners(); 658 Ext.Ajax.request({ 659 url: Monk.data.PROXY_URL + 'get/ProjectManager.getToolSets', 660 params: {worksetId: workset.id}, 661 method: 'GET', 662 callback: getToolsetsHandler, 663 scope: this 664 }); 665 666 } 667 } else { 668 Monk.component.dataManager.setProjectData(projectData); 669 670 feature.flowManager.addStep(new Monk.component.ProjectSelector()); 671 var project = new Monk.component.Project() 672 feature.flowManager.addStep(project); 673 project.setProjectLabel(projectData.label); 674 675 if (toolsetId != null) { 676 var toolsetConfig = Monk.component.dataManager.createToolsetConfig(toolsetId); 677 var toolsetObject = new Monk.component.Toolset(toolsetConfig); 678 679 Monk.component.dataManager.setToolsetId(toolsetObject.id); 680 feature.toolFlowManager.setToolset(toolsetObject); 681 feature.flowManager.addStep(feature.toolFlowManager, false); 682 683 finished(feature.toolFlowManager.id); 684 } else { 685 finished('project'); 686 } 687 } 688 } 689 690 getToolsetsHandler = function(options, success, response) { 691 var info = Ext.decode(response.responseText); 692 693 for (var i = 0; i < info.toolsets.length; i++) { 694 var toolset = info.toolsets[i].configuration; 695 // TODO temporary fix to unify custom and default label params 696 // change server response to label, not toolSetLabel 697 toolset.label = toolset.toolSetLabel; 698 toolset.id = info.toolsets[i].id; 699 projectData.toolsets.add(toolset.id, toolset); 700 } 701 projectData.worksetsToProcess--; 702 if (projectData.worksetsToProcess == 0) { 703 Monk.component.dataManager.setProjectData(projectData); 704 705 feature.flowManager.addStep(new Monk.component.ProjectSelector()); 706 var project = new Monk.component.Project() 707 feature.flowManager.addStep(project); 708 project.setProjectLabel(projectData.label); 709 710 if (worksetId != null) { 711 var workset = Monk.component.dataManager.getProjectData().worksets.get(worksetId); 712 if (workset != null) { 713 Monk.component.dataManager.setWorkset(workset); 714 } 715 } 716 717 if (toolsetId != null) { 718 var toolsetConfig = Monk.component.dataManager.createToolsetConfig(toolsetId); 719 var toolsetObject = new Monk.component.Toolset(toolsetConfig); 720 721 Monk.component.dataManager.setToolsetId(toolsetObject.id); 722 feature.toolFlowManager.setToolset(toolsetObject); 723 feature.flowManager.addStep(feature.toolFlowManager, false); 724 725 finished(feature.toolFlowManager.id); 726 } else if (instanceId != null) { 727 instanceId = unescape(instanceId); 728 Ext.Ajax.purgeListeners(); 729 Ext.Ajax.request({ 730 url: Monk.data.PROXY_URL + 'get/SeasrManager.getConfigParameters', 731 params: {instanceId : instanceId}, 732 method: 'GET', 733 callback : getConfigParamsHandler, 734 scope : this 735 }); 736 737 } else { 738 finished('project'); 739 } 740 } 741 } 742 743 getConfigParamsHandler = function(options, success, response) { 744 var params = response.responseXML.getElementsByTagName('ConfigParameters')[0]; 745 toolsetId = Ext.DomQuery.selectNode('params[name=toolsetId] value', params).firstChild.data; 746 Monk.component.dataManager.getProjectData().results.get(instanceId)[0].toolsetId = toolsetId; 747 748 Ext.Ajax.purgeListeners(); 749 Ext.Ajax.request({ 750 url: Monk.data.PROXY_URL + 'get/SeasrManager.getPrediction', 751 params: {instanceId : instanceId}, 752 method: 'GET', 753 callback: getResultValuesHandler, 754 scope : this 755 }); 756 757 } 758 759 getResultValuesHandler = function(options, success, response) { 760 var results = response.responseXML.getElementsByTagName('results')[0]; 761 var projectData = Monk.component.dataManager.getProjectData(); 762 Monk.component.dataManager.addResultsToProject(results, projectData); 763 results = projectData.results.get(instanceId); 764 765 var worksetId = results[0].worksetId; 766 var workset = projectData.worksets.get(worksetId); 767 if (workset != null) { 768 Monk.component.dataManager.setWorkset(workset); 769 } 770 771 Monk.component.dataManager.processResults(instanceId, results); 772 773 var toolsetConfig = Monk.component.dataManager.createToolsetConfig(toolsetId); 774 var toolsetObject = new Monk.component.Toolset(toolsetConfig); 775 var lastStep = toolsetObject.tools.last().id; 776 777 Monk.component.dataManager.setToolsetId(toolsetObject.id); 778 feature.toolFlowManager.setToolset(toolsetObject); 779 feature.flowManager.addStep(feature.toolFlowManager, false); 780 781 finished(feature.toolFlowManager.id, lastStep); 782 } 783 784 // start the process, which requires at least projectId 785 if (projectId != null) { 786 feature.flowManager.currentStep = 'project-selector'; 787 788 var projectData = null; 789 790 Ext.Ajax.request({ 791 url: Monk.data.PROXY_URL + 'get/ProjectManager.getProjectInfo', 792 params: {projectId: projectId}, 793 method: 'GET', 794 callback: getInfoHandler, 795 scope: this 796 }) 797 } 798 }, 799 800 /** 801 * Initialize the layout. 802 */ 803 initializeLayout : function(){ 804 this.initializeHeader(); 805 806 this.viewport = new Ext.Viewport({ 807 layout: 'row-fit', 808 items: [ 809 this.headerPanel, 810 this.flowManager.panel 811 ] 812 }); 813 814 var paramMatch = false; 815 for (var i = 0, len = this.initialParameterNames.length; i < len; i++) { 816 if (this.initialParameters.containsKey(this.initialParameterNames[i])) { 817 paramMatch = true; 818 this.initializeParameters(); 819 break; 820 } 821 } 822 if (!paramMatch) this.initialDestination = ['project-selector']; 823 }, 824 825 /** 826 * Initialize the header. 827 */ 828 initializeHeader : function () { 829 830 this.headerPanel = new Ext.Panel({ 831 id: 'main-header', 832 split: false, 833 collapsible: false, 834 border: false, 835 height: 45, 836 bodyStyle: "background: transparent repeat scroll left top; padding-top: 5px;", 837 defaults: { 838 bodyStyle: "background: transparent;", 839 border: false 840 }, 841 layout: 'column', 842 items: [ 843 { 844 columnWidth: 0.6, 845 layout: 'fit', 846 html: '<div style="float: left;"> </div><div style="background: transparent url(resources/images/monk_logo_swirl.gif) no-repeat 0px 0px; width: 240px; height: 65px; position: absolute; top: 2px; left: 2px;"><img src="resources/images/monk_logo_text.gif" style="position: relative; top: 10px; left: 65px;" alt="MONK"/></div>' 847 }, 848 { 849 columnWidth: 0.2, 850 hideMode: 'visibility', 851 layout: 'fit', 852 id: 'loading-indicator', 853 html: '<div style="text-align: center;"><img src="../../resources/images/ajax-loader-bar.gif" /></div>', 854 listeners: { 855 'afterlayout': { 856 fn: function (){ 857 Ext.getCmp('loading-indicator').hide(); 858 }, 859 single: true 860 } 861 } 862 }, 863 { 864 columnWidth: 0.2, 865 layout: 'fit', 866 html: '<br/>' 867 }, 868 { 869 width: 460, 870 layout: 'table', 871 layoutConfig: {columns: 5}, 872 defaults: { 873 border: false, 874 bodyStyle: "background: transparent;" 875 }, 876 items: [ 877 this.searchComponent.panel, 878 { 879 id: 'searchPanelSplit', 880 hideMode: 'visibility', 881 html: '<div class="split"></div>', 882 width: 16 883 }, 884 { 885 id: 'userLogInfo', 886 html: '<div>Logged in as '+currentUser.username+'</div>'+ 887 '<div><a href="https://monk.lis.uiuc.edu:7443/cas/logout">Logout</a></div>' 888 }, 889 { 890 html: '<div class="split"></div>', 891 width: 16 892 }, 893 this.helpComponent.panel 894 ] 895 } 896 ] 897 }); 898 899 Ext.EventManager.onWindowResize(function(w, h) { 900 this.headerPanel.doLayout(); 901 }, this); 902 }, 903 904 /** 905 * Replace one component with another. 906 * @param {String} oldComponentId The old component's ID. 907 * @param {String} newComponentId The new component's ID. 908 */ 909 switchComponent: function (oldComponentId, newComponentId) { 910 var oldWindowId = oldComponentId + '-window'; 911 var oldWin = this.windowManager.getWindow(oldWindowId); 912 913 var layout = this.windowManager.getWindowLayout(oldWin); 914 915 oldWin.close(); 916 917 var newWindowId = newComponentId + '-window'; 918 var newWin = this.initializeComponent(newComponentId); 919 newWin.show(); 920 layout.id = newWindowId; 921 this.windowManager.setWindowLayout(layout); 922 }, 923 924 /** 925 * Initialize a component. 926 * @param {String} componentId The ID of the component to initialize. 927 * @returns {Ext.Window} An Ext.Window containing the component IFRAME. 928 */ 929 initializeComponent : function(componentId) { 930 if (componentId.split('_').length > 1) { 931 alert('old style tool id'); 932 } 933 934 var component = this.components.get(componentId); 935 var windowId = componentId+'-window'; 936 var iframeId = componentId+'-iframe'; 937 938 // Meta tool select 939 var thisGroup = this.componentGroups.get(component.group); 940 var componentAlternatives = []; 941 942 Ext.each(thisGroup, function(oneCompId) { 943 944 var oneComponent = feature.components.get(oneCompId); 945 componentAlternatives.push( 946 { 947 text : oneComponent.label, 948 handler : function() { 949 feature.switchComponent(component.id+'', oneComponent.id+''); 950 } 951 } 952 ); 953 }); 954 955 // component window 956 957 var componentWin = this.windowManager.createWindow({ 958 id: windowId, 959 title: component.label, 960 cls: 'tool-window', 961 html : '<iframe name="'+iframeId+'" id="'+iframeId+'" style="width:100%;height:100%;border:none;" frameborder="0" src="'+component.source+'"></iframe>', 962 shim: false, 963 animCollapse: false, 964 constrainHeader: true, 965 minimizable: false, 966 collapsible: true, 967 plugins: [ 968 new Ext.ux.plugins.HeaderMenu({ 969 title: component.label, 970 items: componentAlternatives 971 }) 972 ], 973 tools: [{ 974 id:'help', 975 qtip: component.description+' Click for more...', 976 handler: function(event, toolEl, panel){ 977 Monk.component.help.dynamic(component.label+' Help', component.helptext); 978 } 979 }] 980 }); 981 982 // add a partial entry to the registry 983 // later on we'll associate the actual tool/component with this key 984 // when the tool gets loaded 985 this.toolWindowRegistry.add(windowId, component.source); 986 987 return componentWin; 988 }, 989 990 /** 991 * Give the component focus if desktop window has been clicked 992 * @param {Ext.Window} componentWindow The component window. 993 */ 994 focusComponent : function(componentWindow) { 995 var component = this.toolWindowRegistry.get(componentWindow.id); 996 if (component.window) { 997 component.window.focus(); 998 } 999 }, 1000 1001 /** 1002 * Destroy a component. Called when a component window gets closed. 1003 * @param {Ext.Window} componentWindow The component window. 1004 */ 1005 destroyComponent : function(componentWindow) { 1006 var component = this.toolWindowRegistry.get(componentWindow.id); 1007 this.toolWindowRegistry.remove(component); 1008 Workbench.component.manager.unregister(component); 1009 } 1010 }); 1011 1012 1013 /** 1014 * @class A class encompassing an Ext.Panel and related methods. 1015 * These typically get rendered as "steps" in the workflow. 1016 * @extends Workbench.lang.Object 1017 */ 1018 Monk.component.Component = function(){ 1019 // add this component to the manager 1020 Workbench.component["manager"].register(this); 1021 1022 Monk.component.Component.superclass.constructor.call(this, arguments[0]); 1023 }; 1024 1025 Workbench.extend(Monk.component.Component, Workbench.lang.Object, { 1026 /** @lends Monk.component.Component.prototype */ 1027 1028 /** 1029 * The ID for this component. 1030 * @type String 1031 */ 1032 id : null, 1033 1034 /** 1035 * A label for the component, used for the corresponding toolbar button. 1036 * @type String 1037 */ 1038 label : "", 1039 1040 /** 1041 * The base panel for this component. 1042 * @type Ext.Panel 1043 */ 1044 panel : null, 1045 1046 /** 1047 * Used to determine if the afterRenderFirstTime method has been called. 1048 * @type Boolean 1049 */ 1050 afterRenderFirstTimeCalled : false, 1051 1052 /** 1053 * A method called after the panel has been rendered for the first time, typically for initiallizing drag n drop. 1054 * @type Function 1055 */ 1056 afterRenderFirstTime : null, 1057 1058 /** 1059 * A method called every time the panel has been rendered. 1060 * @type Function 1061 */ 1062 afterRenderEveryTime : null, 1063 1064 /** 1065 * A method to call before the user "exits" the panel (by switching to a different one). 1066 * @type Function 1067 */ 1068 beforeExit : null, 1069 1070 /** 1071 * Overwrite to handle Monk events. 1072 * @type Function 1073 */ 1074 handle : function(){}, 1075 1076 /** 1077 * Notify the component manager of this event. 1078 * @param {Workbench.event.Event} workbenchEvent The Workbench event that has occured 1079 * @param {Workbench.data.DataStore} [resultsData] Data attached to this event 1080 */ 1081 notify : function(workbenchEvent, resultsData){ 1082 workbenchEvent.component = this; 1083 Workbench.component.manager.notify(workbenchEvent, resultsData); 1084 Workbench.console.info(workbenchEvent.label); 1085 1086 }, 1087 1088 /** 1089 * Is this component's panel is currently being displayed? 1090 * Typically used to determine if the component should handle certain events. 1091 * @type Function 1092 * @returns Boolean 1093 */ 1094 isVisible : function() { 1095 return !this.panel.hidden && this.panel.isVisible(); 1096 } 1097 }); 1098