-
Notifications
You must be signed in to change notification settings - Fork 2
UI improvements #56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
UI improvements #56
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -327,93 +327,72 @@ Object.assign(TorcDashboard.prototype, { | |||||
| content.innerHTML = '<div class="placeholder-message">Loading execution plan...</div>'; | ||||||
|
|
||||||
| try { | ||||||
| // Get jobs and dependencies | ||||||
| const [jobs, dependencies] = await Promise.all([ | ||||||
| api.listJobs(workflowId), | ||||||
| api.getJobsDependencies(workflowId), | ||||||
| ]); | ||||||
|
|
||||||
| // Build dependency graph and compute stages | ||||||
| const stages = this.computeExecutionStages(jobs, dependencies); | ||||||
| content.innerHTML = this.renderExecutionPlan(stages, jobs); | ||||||
| } catch (error) { | ||||||
| content.innerHTML = `<div class="placeholder-message">Error loading execution plan: ${error.message}</div>`; | ||||||
| } | ||||||
| }, | ||||||
| // Get execution plan from CLI (includes scheduler allocations) | ||||||
| const result = await api.cliExecutionPlan(workflowId); | ||||||
|
|
||||||
| computeExecutionStages(jobs, dependencies) { | ||||||
| // Build a map of job dependencies | ||||||
| const blockedBy = {}; | ||||||
| dependencies.forEach(dep => { | ||||||
| if (!blockedBy[dep.job_id]) blockedBy[dep.job_id] = []; | ||||||
| blockedBy[dep.job_id].push(dep.depends_on_job_id); | ||||||
| }); | ||||||
|
|
||||||
| // Create job map | ||||||
| const jobMap = {}; | ||||||
| jobs.forEach(j => jobMap[j.id] = j); | ||||||
|
|
||||||
| // Compute stages using topological sort levels | ||||||
| const stages = []; | ||||||
| const completed = new Set(); | ||||||
| const remaining = new Set(jobs.map(j => j.id)); | ||||||
|
|
||||||
| let stageNum = 1; | ||||||
| while (remaining.size > 0) { | ||||||
| const ready = []; | ||||||
| remaining.forEach(jobId => { | ||||||
| const deps = blockedBy[jobId] || []; | ||||||
| if (deps.every(d => completed.has(d))) { | ||||||
| ready.push(jobId); | ||||||
| } | ||||||
| }); | ||||||
|
|
||||||
| if (ready.length === 0 && remaining.size > 0) { | ||||||
| // Circular dependency or error - break to avoid infinite loop | ||||||
| break; | ||||||
| if (!result.success) { | ||||||
| content.innerHTML = `<div class="placeholder-message">Error: ${this.escapeHtml(result.stderr || result.stdout || 'Unknown error')}</div>`; | ||||||
| return; | ||||||
| } | ||||||
|
|
||||||
| stages.push({ | ||||||
| stageNumber: stageNum++, | ||||||
| jobs: ready.map(id => jobMap[id]), | ||||||
| }); | ||||||
|
|
||||||
| ready.forEach(id => { | ||||||
| completed.add(id); | ||||||
| remaining.delete(id); | ||||||
| }); | ||||||
| // Parse the JSON output | ||||||
| const plan = JSON.parse(result.stdout); | ||||||
| content.innerHTML = this.renderExecutionPlan(plan); | ||||||
| } catch (error) { | ||||||
| content.innerHTML = `<div class="placeholder-message">Error loading execution plan: ${error.message}</div>`; | ||||||
|
||||||
| content.innerHTML = `<div class="placeholder-message">Error loading execution plan: ${error.message}</div>`; | |
| content.innerHTML = `<div class="placeholder-message">Error loading execution plan: ${this.escapeHtml(error.message)}</div>`; |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -24,7 +24,8 @@ Object.assign(TorcDashboard.prototype, { | |||||||||
|
|
||||||||||
| this.resourcePresets = { | ||||||||||
| 'small': { name: 'Small', num_cpus: 1, memory: '1g', num_gpus: 0 }, | ||||||||||
| 'medium': { name: 'Medium', num_cpus: 8, memory: '50g', num_gpus: 0 }, | ||||||||||
| 'medium': { name: 'Medium', num_cpus: 4, memory: '10g', num_gpus: 0 }, | ||||||||||
| 'large': { name: 'Large', num_cpus: 8, memory: '50g', num_gpus: 0 }, | ||||||||||
| 'gpu': { name: 'GPU', num_cpus: 1, memory: '10g', num_gpus: 1 }, | ||||||||||
| 'custom': { name: 'Custom', num_cpus: 1, memory: '1g', num_gpus: 0 } | ||||||||||
| }; | ||||||||||
|
|
@@ -373,16 +374,22 @@ Object.assign(TorcDashboard.prototype, { | |||||||||
|
|
||||||||||
| wizardAddSchedulerFromJob(jobId) { | ||||||||||
| const schedulerId = ++this.wizardSchedulerIdCounter; | ||||||||||
| const schedulerName = `scheduler-${schedulerId}`; | ||||||||||
| const defaultName = `scheduler-${schedulerId}`; | ||||||||||
| const schedulerName = prompt('Enter a name for the new scheduler:', defaultName); | ||||||||||
|
||||||||||
| if (!schedulerName) { | ||||||||||
| // User cancelled | ||||||||||
|
||||||||||
| if (!schedulerName) { | |
| // User cancelled | |
| if (!schedulerName || !schedulerName.trim()) { | |
| // User cancelled or entered only whitespace |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The JSON.parse() call can throw an exception if the stdout contains invalid JSON. This would be caught by the outer try-catch block, but the error message would be generic ("Error loading execution plan: ...") rather than indicating it was a JSON parsing error. Consider wrapping this in a try-catch block to provide a more specific error message, such as "Invalid JSON response from server".