mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-19 13:59:28 +00:00
## Summary - Surface missing models in the Error Tab for OSS environments, replacing the legacy modal dialog - Add Download button per model and Download All button in group header with file size display - Move download business logic from `components/dialog/content` to `platform/missingModel` - Remove legacy missing models dialog components and composable ## Changes - **Pipeline**: Remove `isCloud` guard from `scanAllModelCandidates` and `surfaceMissingModels` so OSS detects missing models - **Grouping**: Group non-asset-supported models by directory in OSS instead of lumping into UNSUPPORTED - **UI**: Add Download button (matching Install Node Pack design) and Download All header button - **Store**: Add `folderPaths`/`fileSizes` state with setter methods, race condition guard - **Cleanup**: Delete `MissingModelsContent`, `MissingModelsHeader`, `MissingModelsFooter`, `useMissingModelsDialog`, `missingModelsUtils` - **Tests**: Add OSS/Cloud grouping tests, migrate Playwright E2E to Error Tab, improve test isolation - **Snapshots**: Reset Playwright screenshot expectations since OSS missing model error detection now causes red highlights on affected nodes - **Accessibility**: Add `aria-label` with model name, `aria-expanded` on toggle, warning icon for unknown category ## Test plan - [x] Unit tests pass (86 tests) - [x] TypeScript typecheck passes - [x] knip passes - [x] Load workflow with missing models in OSS → Error Tab shows missing models grouped by directory - [x] Download button triggers browser download with correct URL - [x] Download All button downloads all downloadable models - [x] Cloud environment behavior unchanged - [x] Playwright E2E: `pnpm test:browser:local -- --grep "Missing models in Error Tab"` ## Screenshots https://github.com/user-attachments/assets/12f15e09-215a-4c58-87ed-39bbffd1359c ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9921-feat-surface-missing-models-in-Error-Tab-for-OSS-and-remove-legacy-dialog-3236d73d365081f0a9dfc291978f5ecf) by [Unito](https://www.unito.io) --------- Co-authored-by: GitHub Action <action@github.com> Co-authored-by: github-actions <github-actions@github.com>
85 lines
2.7 KiB
Vue
85 lines
2.7 KiB
Vue
<template>
|
|
<div class="px-4 pb-2">
|
|
<!-- Category groups (by directory) -->
|
|
<div
|
|
v-for="group in missingModelGroups"
|
|
:key="`${group.isAssetSupported ? 'supported' : 'unsupported'}::${group.directory ?? '__unknown__'}`"
|
|
class="flex w-full flex-col border-t border-interface-stroke py-2 first:border-t-0 first:pt-0"
|
|
>
|
|
<!-- Category header -->
|
|
<div class="flex h-8 w-full items-center">
|
|
<p
|
|
class="min-w-0 flex-1 truncate text-sm font-medium"
|
|
:class="
|
|
(isCloud && !group.isAssetSupported) || group.directory === null
|
|
? 'text-warning-background'
|
|
: 'text-destructive-background-hover'
|
|
"
|
|
>
|
|
<span v-if="isCloud && !group.isAssetSupported">
|
|
{{ t('rightSidePanel.missingModels.importNotSupported') }}
|
|
({{ group.models.length }})
|
|
</span>
|
|
<span v-else>
|
|
<i
|
|
v-if="group.directory === null"
|
|
aria-hidden="true"
|
|
class="mr-1 icon-[lucide--triangle-alert] size-3.5 align-text-bottom"
|
|
/>
|
|
{{
|
|
group.directory ??
|
|
t('rightSidePanel.missingModels.unknownCategory')
|
|
}}
|
|
({{ group.models.length }})
|
|
</span>
|
|
</p>
|
|
</div>
|
|
|
|
<!-- Asset unsupported group notice -->
|
|
<div
|
|
v-if="isCloud && !group.isAssetSupported"
|
|
class="flex items-start gap-1.5 px-0.5 py-1 pl-2"
|
|
>
|
|
<i
|
|
aria-hidden="true"
|
|
class="mt-0.5 icon-[lucide--info] size-3.5 shrink-0 text-muted-foreground"
|
|
/>
|
|
<span class="text-xs/tight text-muted-foreground">
|
|
{{ t('rightSidePanel.missingModels.customNodeDownloadDisabled') }}
|
|
</span>
|
|
</div>
|
|
|
|
<!-- Model rows -->
|
|
<div class="flex flex-col gap-1 overflow-hidden pl-2">
|
|
<MissingModelRow
|
|
v-for="model in group.models"
|
|
:key="model.name"
|
|
:model="model"
|
|
:directory="group.directory"
|
|
:show-node-id-badge="showNodeIdBadge"
|
|
:is-asset-supported="group.isAssetSupported"
|
|
@locate-model="emit('locateModel', $event)"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { useI18n } from 'vue-i18n'
|
|
import type { MissingModelGroup } from '@/platform/missingModel/types'
|
|
import { isCloud } from '@/platform/distribution/types'
|
|
import MissingModelRow from '@/platform/missingModel/components/MissingModelRow.vue'
|
|
|
|
const { missingModelGroups, showNodeIdBadge } = defineProps<{
|
|
missingModelGroups: MissingModelGroup[]
|
|
showNodeIdBadge: boolean
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
locateModel: [nodeId: string]
|
|
}>()
|
|
|
|
const { t } = useI18n()
|
|
</script>
|