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