Keep Enhance + Generate as one queue row with shared progress.
The PE stage now stays on the same jobId so the header and queue badge agree, and jobs behind it do not promote when enhance finishes. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -302,6 +302,14 @@
|
||||
<span class="left"><span class="dot" aria-hidden="true" />{{ card.statusLabel }}</span>
|
||||
<button v-if="card.cancelable" type="button" class="kebab" aria-label="Cancel job" @click.stop="cancel(card.job)">⋮</button>
|
||||
</div>
|
||||
<div v-if="card.progress" class="job-progress" :data-indeterminate="card.progress.indeterminate ? 'true' : undefined">
|
||||
<progress
|
||||
class="job-progress-bar"
|
||||
max="100"
|
||||
:value="card.progress.indeterminate ? undefined : card.progress.percent"
|
||||
/>
|
||||
<span v-if="card.elapsed != null" class="job-elapsed">{{ card.elapsed }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<p v-if="!queueCards.length" class="px-1 text-[var(--type-sm)] text-[var(--muted)]">No active jobs</p>
|
||||
</div>
|
||||
@@ -374,7 +382,7 @@ import {filterLorasForStudio,filterLorasForUse} from '~/utils/loras'
|
||||
import {sectionsFrom} from '~/shared/studio2/contracts.mjs'
|
||||
import {aspectOptions,resolveSize,bindClip,restoreAll,useAsHero,useAsSource,hydrateStudio2Job} from '~/shared/studio2/input.mjs'
|
||||
import {folderAssets,newestOutput,assetLabel,reconcileSelection,previewHidden} from '~/shared/studio2/viewer.mjs'
|
||||
import {queueJobs} from '~/shared/studio2/queue-view.mjs'
|
||||
import {queueJobs,jobStageLabel,jobProgressView,elapsedSeconds} from '~/shared/studio2/queue-view.mjs'
|
||||
import {gpuStatus} from '~/shared/studio2/status.mjs'
|
||||
import {applyUploadedStill} from '~/shared/studio2/upload.mjs'
|
||||
import {defaultNegatives,parseBatch} from '~/shared/studio2/styles.mjs'
|
||||
@@ -534,6 +542,7 @@ const slotPairHint=computed(()=>{
|
||||
})
|
||||
const queueCards=computed(()=>{
|
||||
const cards:any[]=[]
|
||||
const now=Date.now()
|
||||
for(const job of benchJobs.value){
|
||||
const action=job.request?.promptSections?.action || 'Job'
|
||||
const eng=job.request?.engine==='ltx'?'LTX':job.request?.engine==='krea'?'Krea 2':job.request?.engine==='qwen21'?'Qwen 2.1':job.request?.engine==='minimax'?'MiniMax H3':'Klein'
|
||||
@@ -541,6 +550,8 @@ const queueCards=computed(()=>{
|
||||
const modeLabel=mode.charAt(0).toUpperCase()+mode.slice(1)
|
||||
const aspect=job.request?.settings?.aspect || 'auto'
|
||||
const state=job.state==='waiting'?'queued':job.state
|
||||
const secs=elapsedSeconds(job,now)
|
||||
const progress=jobProgressView(job)
|
||||
cards.push({
|
||||
id:job.id,
|
||||
job,
|
||||
@@ -548,7 +559,9 @@ const queueCards=computed(()=>{
|
||||
title:action.slice(0,72),
|
||||
meta:`${modeLabel} · ${eng} · ${aspect}`,
|
||||
state,
|
||||
statusLabel:state==='queued'?'Queued':state==='rendering'||state==='submitting'||state==='waking'||state==='saving'?'Running':state==='complete'?'Ready':state,
|
||||
statusLabel:jobStageLabel(state),
|
||||
progress,
|
||||
elapsed:secs>0?`${Math.floor(secs/60)}m ${secs%60}s`:'',
|
||||
cancelable:!['complete','failed','cancelled'].includes(job.state)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
<div class="space-y-2 rounded-xl border border-white/10 p-3 text-sm" aria-live="polite">
|
||||
<div class="flex justify-between gap-3"><button class="text-left" @click="$emit('select')"><strong>{{ job.request.promptSections.action.slice(0,70) }}</strong><span class="block capitalize text-amber-200">{{ job.state==='waiting'?'queued':job.state }} · Shot {{ shot }}/{{ total }}</span></button><button v-if="!terminal" @click="$emit('cancel')">Cancel</button></div>
|
||||
<p>{{ elapsed }} {{ job.startedAt?'elapsed':'waiting' }} · {{ job.request.settings.duration }}s target<span v-if="job.state==='rendering' && job.progress"> · Step {{ job.progress.step }}/{{ job.progress.maxStep }} ({{ job.progress.percent }}%)</span></p>
|
||||
<progress v-if="job.state==='rendering'" class="h-2 w-full accent-amber-300" :value="job.progress?.percent" max="100" />
|
||||
<progress v-if="job.state==='enhancing'" class="h-2 w-full accent-amber-300" max="100" :value="enhancePercent" />
|
||||
<progress v-else-if="job.state==='rendering'" class="h-2 w-full accent-amber-300" :value="job.progress?.percent" max="100" />
|
||||
<p v-if="job.error" role="alert" class="text-red-300">{{ job.error }}</p>
|
||||
</div>
|
||||
</template>
|
||||
@@ -13,4 +14,9 @@ const terminal=computed(()=>['complete','failed','cancelled'].includes(props.job
|
||||
const total=computed(()=>props.job.prompts?.length || (props.job.request.batch?.length || 0)+1)
|
||||
const shot=computed(()=>Math.min(total.value,(props.job.index || 0)+1))
|
||||
const elapsed=computed(()=>{const seconds=elapsedSeconds(props.job,props.now);return `${Math.floor(seconds/60)}m ${seconds%60}s`})
|
||||
const enhancePercent=computed(()=>{
|
||||
const p=props.job.progress
|
||||
if(p && Number(p.maxStep)>0) return Number(p.percent)||Math.round(Number(p.step)/Number(p.maxStep)*100)
|
||||
return undefined // indeterminate while PE runs without Comfy step events
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -270,6 +270,14 @@
|
||||
<span>● {{ card.statusLabel }}</span>
|
||||
<button v-if="card.cancelable" type="button" @click.stop="ctx.cancel(card.job)">Cancel</button>
|
||||
</div>
|
||||
<div v-if="card.progress" class="m-job-progress" :data-indeterminate="card.progress.indeterminate ? 'true' : undefined">
|
||||
<progress
|
||||
class="m-job-progress-bar"
|
||||
max="100"
|
||||
:value="card.progress.indeterminate ? undefined : card.progress.percent"
|
||||
/>
|
||||
<span v-if="card.elapsed" class="m-muted">{{ card.elapsed }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<p v-if="!ctx.queueCards.length" class="m-muted">No active jobs</p>
|
||||
<button v-if="ctx.canClearFinished" type="button" class="m-link" @click="ctx.clearFinished">Clear finished</button>
|
||||
@@ -581,5 +589,7 @@ watch(() => props.ctx.form.mode, () => { sheet.value = '' })
|
||||
.m-job-id { color: var(--muted); font-size: 12px; }
|
||||
.m-job-title { font-weight: 600; }
|
||||
.m-job-status { display: flex; justify-content: space-between; margin-top: 6px; font-size: 12px; }
|
||||
.m-job-progress { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
|
||||
.m-job-progress-bar { flex: 1; height: 4px; accent-color: var(--amber); }
|
||||
.m-link { border: 0; background: transparent; color: var(--amber); text-align: left; }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user