mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-07 08:30:06 +00:00
[feat] Add dual mode support to NodeConflictDialogContent and fix TypeScript errors
- Add dual mode support to NodeConflictDialogContent: - Support props (conflictedPackages/conflicts) for specific conflicts - Fallback to global composable data for SidebarHelpCenterIcon usage - Import failed extensions section shows at top with package names - Conditional description display for post-What's-New scenarios - Fix TypeScript errors: - PackEnableToggle: Add missing parameter to showConflictModal call - InfoTabs: Update conflictResult prop to allow undefined - WarningTabPanel: Update conflictResult prop to accept undefined - Update tests for comprehensive dual mode functionality coverage
This commit is contained in:
@@ -169,24 +169,41 @@ import { useI18n } from 'vue-i18n'
|
||||
|
||||
import ContentDivider from '@/components/common/ContentDivider.vue'
|
||||
import { useConflictDetection } from '@/composables/useConflictDetection'
|
||||
import type { ConflictDetectionResult } from '@/types/conflictDetectionTypes'
|
||||
import { getConflictMessage } from '@/utils/conflictMessageUtil'
|
||||
|
||||
interface Props {
|
||||
conflicts?: ConflictDetectionResult[]
|
||||
conflictedPackages?: ConflictDetectionResult[]
|
||||
showAfterWhatsNew?: boolean
|
||||
}
|
||||
|
||||
const { showAfterWhatsNew } = withDefaults(defineProps<Props>(), {
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
conflicts: () => [],
|
||||
conflictedPackages: () => [],
|
||||
showAfterWhatsNew: false
|
||||
})
|
||||
|
||||
const { t } = useI18n()
|
||||
const { conflictedPackages } = useConflictDetection()
|
||||
const { conflictedPackages: globalConflictedPackages } = useConflictDetection()
|
||||
|
||||
const conflictsExpanded = ref<boolean>(false)
|
||||
const extensionsExpanded = ref<boolean>(false)
|
||||
const importFailedExpanded = ref<boolean>(false)
|
||||
|
||||
const conflictData = computed(() => conflictedPackages.value)
|
||||
// Use props if provided, otherwise use composable data
|
||||
const conflictData = computed(() => {
|
||||
// If props have conflictedPackages, prioritize them
|
||||
if (props.conflictedPackages.length > 0) {
|
||||
return props.conflictedPackages
|
||||
}
|
||||
// If props have conflicts, use them
|
||||
if (props.conflicts.length > 0) {
|
||||
return props.conflicts
|
||||
}
|
||||
// Otherwise, use global conflicted packages from composable
|
||||
return globalConflictedPackages.value
|
||||
})
|
||||
|
||||
const allConflictDetails = computed(() => {
|
||||
const allConflicts = flatMap(conflictData.value, (result) => result.conflicts)
|
||||
|
||||
@@ -147,7 +147,7 @@ const onToggle = debounce(
|
||||
const handleToggleInteraction = async (event: Event) => {
|
||||
if (!canToggleDirectly.value) {
|
||||
event.preventDefault()
|
||||
showConflictModal()
|
||||
showConflictModal(false)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -55,7 +55,7 @@ import { ImportFailedKey } from '@/types/importFailedTypes'
|
||||
const { nodePack, hasCompatibilityIssues, conflictResult } = defineProps<{
|
||||
nodePack: components['schemas']['Node']
|
||||
hasCompatibilityIssues?: boolean
|
||||
conflictResult?: ConflictDetectionResult | null
|
||||
conflictResult?: ConflictDetectionResult | null | undefined
|
||||
}>()
|
||||
|
||||
// Inject import failed context from parent
|
||||
|
||||
@@ -35,7 +35,7 @@ import { getConflictMessage } from '@/utils/conflictMessageUtil'
|
||||
|
||||
const { nodePack, conflictResult } = defineProps<{
|
||||
nodePack: components['schemas']['Node']
|
||||
conflictResult: ConflictDetectionResult | null
|
||||
conflictResult: ConflictDetectionResult | null | undefined
|
||||
}>()
|
||||
|
||||
const packageId = computed(() => nodePack?.id || '')
|
||||
|
||||
@@ -124,8 +124,12 @@ const handleWhatsNewDismissed = async () => {
|
||||
* Show the node conflict dialog with current conflict data
|
||||
*/
|
||||
const showConflictModal = () => {
|
||||
const conflictData = {
|
||||
conflictedPackages: conflictDetection.conflictedPackages.value,
|
||||
showAfterWhatsNew: true
|
||||
}
|
||||
showNodeConflictDialog({
|
||||
showAfterWhatsNew: true,
|
||||
...conflictData,
|
||||
dialogComponentProps: {
|
||||
onClose: () => {
|
||||
markConflictsAsSeen()
|
||||
|
||||
@@ -432,19 +432,14 @@ export const useDialogService = () => {
|
||||
}
|
||||
|
||||
function showNodeConflictDialog(
|
||||
options: {
|
||||
showAfterWhatsNew?: boolean
|
||||
options: InstanceType<typeof NodeConflictDialogContent>['$props'] & {
|
||||
dialogComponentProps?: DialogComponentProps
|
||||
buttonText?: string
|
||||
onButtonClick?: () => void
|
||||
} = {}
|
||||
) {
|
||||
const {
|
||||
dialogComponentProps,
|
||||
buttonText,
|
||||
onButtonClick,
|
||||
showAfterWhatsNew
|
||||
} = options
|
||||
const { dialogComponentProps, buttonText, onButtonClick, ...props } =
|
||||
options
|
||||
|
||||
return dialogStore.showDialog({
|
||||
key: 'global-node-conflict',
|
||||
@@ -466,9 +461,7 @@ export const useDialogService = () => {
|
||||
},
|
||||
...dialogComponentProps
|
||||
},
|
||||
props: {
|
||||
showAfterWhatsNew
|
||||
},
|
||||
props,
|
||||
footerProps: {
|
||||
buttonText,
|
||||
onButtonClick
|
||||
|
||||
@@ -9,7 +9,7 @@ import type { ConflictDetectionResult } from '@/types/conflictDetectionTypes'
|
||||
|
||||
// Mock getConflictMessage utility
|
||||
vi.mock('@/utils/conflictMessageUtil', () => ({
|
||||
getConflictMessage: vi.fn((conflict, t) => {
|
||||
getConflictMessage: vi.fn((conflict) => {
|
||||
return `${conflict.type}: ${conflict.current_value} vs ${conflict.required_value}`
|
||||
})
|
||||
}))
|
||||
@@ -195,6 +195,70 @@ describe('NodeConflictDialogContent', () => {
|
||||
expect(conflictsSection.text()).toContain('3')
|
||||
expect(conflictsSection.text()).toContain('Conflicts')
|
||||
})
|
||||
|
||||
it('should render with conflict data from props (conflictedPackages)', () => {
|
||||
// Clear composable data to ensure props are used
|
||||
mockConflictData.value = []
|
||||
|
||||
const wrapper = createWrapper({
|
||||
conflictedPackages: mockConflictResults
|
||||
})
|
||||
|
||||
// Should show 3 total conflicts (2 from Package1 + 1 from Package2, excluding import_failed)
|
||||
expect(wrapper.text()).toContain('3')
|
||||
expect(wrapper.text()).toContain('Conflicts')
|
||||
// Should show 3 extensions at risk (all packages)
|
||||
expect(wrapper.text()).toContain('Extensions at Risk')
|
||||
// Should show import failed section
|
||||
expect(wrapper.text()).toContain('Import Failed Extensions')
|
||||
expect(wrapper.text()).toContain('1') // 1 import failed package
|
||||
})
|
||||
|
||||
it('should render with conflict data from props (conflicts)', () => {
|
||||
// Clear composable data to ensure props are used
|
||||
mockConflictData.value = []
|
||||
|
||||
const wrapper = createWrapper({
|
||||
conflicts: mockConflictResults
|
||||
})
|
||||
|
||||
// Should show 3 total conflicts (excluding import_failed)
|
||||
expect(wrapper.text()).toContain('3')
|
||||
expect(wrapper.text()).toContain('Conflicts')
|
||||
expect(wrapper.text()).toContain('Extensions at Risk')
|
||||
expect(wrapper.text()).toContain('Import Failed Extensions')
|
||||
})
|
||||
|
||||
it('should prioritize conflictedPackages over conflicts prop', () => {
|
||||
const singleConflict: ConflictDetectionResult[] = [
|
||||
{
|
||||
package_id: 'SinglePackage',
|
||||
package_name: 'Single Package',
|
||||
has_conflict: true,
|
||||
is_compatible: false,
|
||||
conflicts: [
|
||||
{
|
||||
type: 'os',
|
||||
current_value: 'macOS',
|
||||
required_value: 'Windows'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
// Clear composable data
|
||||
mockConflictData.value = []
|
||||
|
||||
const wrapper = createWrapper({
|
||||
conflicts: mockConflictResults, // 4 conflicts total
|
||||
conflictedPackages: singleConflict // 1 conflict
|
||||
})
|
||||
|
||||
// Should use conflictedPackages (1 conflict) instead of conflicts (4 conflicts)
|
||||
expect(wrapper.text()).toContain('1')
|
||||
expect(wrapper.text()).toContain('Conflicts')
|
||||
expect(wrapper.text()).toContain('Extensions at Risk')
|
||||
})
|
||||
})
|
||||
|
||||
describe('panel interactions', () => {
|
||||
|
||||
Reference in New Issue
Block a user