mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-04 13:12:10 +00:00
Execution Error Dialog Revamp (One click issue searching and filing) (#595)
* Add basic error dialog * 2 level error report * Add find issue button * nit * Add file issue button * Single dialog * nit * Fix long text wrapping * Merge component * Test execution error dialog
This commit is contained in:
182
src/components/dialog/content/ExecutionErrorDialogContent.vue
Normal file
182
src/components/dialog/content/ExecutionErrorDialogContent.vue
Normal file
@@ -0,0 +1,182 @@
|
||||
<template>
|
||||
<NoResultsPlaceholder
|
||||
icon="pi pi-exclamation-circle"
|
||||
:title="props.error.node_type"
|
||||
:message="props.error.exception_message"
|
||||
/>
|
||||
<div class="comfy-error-report">
|
||||
<Button
|
||||
v-show="!reportOpen"
|
||||
:label="$t('showReport')"
|
||||
@click="showReport"
|
||||
text
|
||||
/>
|
||||
<template v-if="reportOpen">
|
||||
<Divider />
|
||||
<ScrollPanel style="width: 100%; height: 400px; max-width: 80vw">
|
||||
<pre class="wrapper-pre">{{ reportContent }}</pre>
|
||||
</ScrollPanel>
|
||||
<Divider />
|
||||
</template>
|
||||
|
||||
<div class="action-container">
|
||||
<FindIssueButton
|
||||
:errorMessage="props.error.exception_message"
|
||||
:repoOwner="repoOwner"
|
||||
:repoName="repoName"
|
||||
/>
|
||||
<Button
|
||||
:label="$t('openNewIssue')"
|
||||
icon="pi pi-github"
|
||||
@click="openNewGithubIssue"
|
||||
class="p-button-secondary"
|
||||
/>
|
||||
<Button
|
||||
v-if="reportOpen"
|
||||
:label="$t('copyToClipboard')"
|
||||
icon="pi pi-copy"
|
||||
@click="copyReportToClipboard"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useClipboard } from '@vueuse/core'
|
||||
import { useToast } from 'primevue/usetoast'
|
||||
import Button from 'primevue/button'
|
||||
import Divider from 'primevue/divider'
|
||||
import ScrollPanel from 'primevue/scrollpanel'
|
||||
import FindIssueButton from '@/components/dialog/content/error/FindIssueButton.vue'
|
||||
import NoResultsPlaceholder from '@/components/common/NoResultsPlaceholder.vue'
|
||||
import type { ExecutionErrorWsMessage, SystemStats } from '@/types/apiTypes'
|
||||
import { api } from '@/scripts/api'
|
||||
import { app } from '@/scripts/app'
|
||||
|
||||
const props = defineProps<{
|
||||
error: ExecutionErrorWsMessage
|
||||
}>()
|
||||
|
||||
const repoOwner = 'comfyanonymous'
|
||||
const repoName = 'ComfyUI'
|
||||
const reportContent = ref('')
|
||||
const reportOpen = ref(false)
|
||||
const showReport = () => {
|
||||
reportOpen.value = true
|
||||
}
|
||||
|
||||
const toast = useToast()
|
||||
const { copy, isSupported } = useClipboard()
|
||||
|
||||
onMounted(async () => {
|
||||
generateReport(await api.getSystemStats())
|
||||
})
|
||||
|
||||
const generateReport = (systemStats: SystemStats) => {
|
||||
const MAX_JSON_LENGTH = 50000
|
||||
const workflowJSONString = JSON.stringify(app.graph.serialize())
|
||||
const workflowText =
|
||||
workflowJSONString.length > MAX_JSON_LENGTH
|
||||
? 'Workflow too large. Please manually upload the workflow from local file system.'
|
||||
: workflowJSONString
|
||||
|
||||
reportContent.value = `
|
||||
# ComfyUI Error Report
|
||||
## Error Details
|
||||
- **Node Type:** ${props.error.node_type}
|
||||
- **Exception Type:** ${props.error.exception_type}
|
||||
- **Exception Message:** ${props.error.exception_message}
|
||||
## Stack Trace
|
||||
\`\`\`
|
||||
${props.error.traceback.join('\n')}
|
||||
\`\`\`
|
||||
## System Information
|
||||
- **OS:** ${systemStats.system.os}
|
||||
- **Python Version:** ${systemStats.system.python_version}
|
||||
- **Embedded Python:** ${systemStats.system.embedded_python}
|
||||
## Devices
|
||||
${systemStats.devices
|
||||
.map(
|
||||
(device) => `
|
||||
- **Name:** ${device.name}
|
||||
- **Type:** ${device.type}
|
||||
- **VRAM Total:** ${device.vram_total}
|
||||
- **VRAM Free:** ${device.vram_free}
|
||||
- **Torch VRAM Total:** ${device.torch_vram_total}
|
||||
- **Torch VRAM Free:** ${device.torch_vram_free}
|
||||
`
|
||||
)
|
||||
.join('\n')}
|
||||
|
||||
## Attached Workflow
|
||||
Please make sure that workflow does not contain any sensitive information such as API keys or passwords.
|
||||
\`\`\`
|
||||
${workflowText}
|
||||
\`\`\`
|
||||
|
||||
## Additional Context
|
||||
(Please add any additional context or steps to reproduce the error here)
|
||||
`
|
||||
}
|
||||
|
||||
const copyReportToClipboard = async () => {
|
||||
if (isSupported) {
|
||||
try {
|
||||
await copy(reportContent.value)
|
||||
toast.add({
|
||||
severity: 'success',
|
||||
summary: 'Success',
|
||||
detail: 'Report copied to clipboard',
|
||||
life: 3000
|
||||
})
|
||||
} catch (err) {
|
||||
toast.add({
|
||||
severity: 'error',
|
||||
summary: 'Error',
|
||||
detail: 'Failed to copy report',
|
||||
life: 3000
|
||||
})
|
||||
}
|
||||
} else {
|
||||
toast.add({
|
||||
severity: 'error',
|
||||
summary: 'Error',
|
||||
detail: 'Clipboard API not supported in your browser',
|
||||
life: 3000
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const openNewGithubIssue = () => {
|
||||
const issueTitle = encodeURIComponent(
|
||||
`[Bug]: ${props.error.exception_type} in ${props.error.node_type}`
|
||||
)
|
||||
const issueBody = encodeURIComponent(reportContent.value)
|
||||
const url = `https://github.com/${repoOwner}/${repoName}/issues/new?title=${issueTitle}&body=${issueBody}`
|
||||
window.open(url, '_blank')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.comfy-error-report {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.action-container {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.wrapper-pre {
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.no-results-placeholder {
|
||||
padding-top: 0;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user