mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-05 23:50:08 +00:00
Merge branch 'main' into manager/dialog-design-modify
This commit is contained in:
@@ -219,7 +219,7 @@ const extraMenuItems = computed(() => [
|
||||
{
|
||||
key: 'settings',
|
||||
label: t('g.settings'),
|
||||
icon: 'mdi mdi-cog-outline',
|
||||
icon: 'icon-[lucide--settings]',
|
||||
command: () => {
|
||||
telemetry?.trackUiButtonClicked({
|
||||
button_id: 'sidebar_settings_menu_opened'
|
||||
@@ -230,7 +230,7 @@ const extraMenuItems = computed(() => [
|
||||
{
|
||||
key: 'manage-extensions',
|
||||
label: t('menu.manageExtensions'),
|
||||
icon: 'mdi mdi-puzzle-outline',
|
||||
icon: 'icon-[lucide--puzzle]',
|
||||
command: showManageExtensions
|
||||
}
|
||||
])
|
||||
|
||||
@@ -5,6 +5,11 @@ import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
|
||||
import { useCommandStore } from '@/stores/commandStore'
|
||||
|
||||
const canvasStore = useCanvasStore()
|
||||
function toggleLinearMode() {
|
||||
useCommandStore().execute('Comfy.ToggleLinear', {
|
||||
metadata: { source: 'button' }
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<div class="p-1 bg-secondary-background rounded-lg w-10">
|
||||
@@ -12,7 +17,7 @@ const canvasStore = useCanvasStore()
|
||||
size="icon"
|
||||
:title="t('linearMode.linearMode')"
|
||||
:variant="canvasStore.linearMode ? 'inverted' : 'secondary'"
|
||||
@click="useCommandStore().execute('Comfy.ToggleLinear')"
|
||||
@click="toggleLinearMode"
|
||||
>
|
||||
<i class="icon-[lucide--panels-top-left]" />
|
||||
</Button>
|
||||
@@ -20,7 +25,7 @@ const canvasStore = useCanvasStore()
|
||||
size="icon"
|
||||
:title="t('linearMode.graphMode')"
|
||||
:variant="canvasStore.linearMode ? 'secondary' : 'inverted'"
|
||||
@click="useCommandStore().execute('Comfy.ToggleLinear')"
|
||||
@click="toggleLinearMode"
|
||||
>
|
||||
<i class="icon-[comfy--workflow]" />
|
||||
</Button>
|
||||
|
||||
@@ -6,7 +6,11 @@
|
||||
class="grid max-h-[50%] scrollbar-custom overflow-y-auto"
|
||||
:style="gridStyle"
|
||||
>
|
||||
<ActiveJobCard v-for="job in activeJobItems" :key="job.id" :job="job" />
|
||||
<ActiveMediaAssetCard
|
||||
v-for="job in activeJobItems"
|
||||
:key="job.id"
|
||||
:job="job"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Assets Header -->
|
||||
@@ -55,7 +59,7 @@ import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import VirtualGrid from '@/components/common/VirtualGrid.vue'
|
||||
import ActiveJobCard from '@/components/sidebar/tabs/assets/ActiveJobCard.vue'
|
||||
import ActiveMediaAssetCard from '@/platform/assets/components/ActiveMediaAssetCard.vue'
|
||||
import { useJobList } from '@/composables/queue/useJobList'
|
||||
import MediaAssetCard from '@/platform/assets/components/MediaAssetCard.vue'
|
||||
import type { AssetItem } from '@/platform/assets/schemas/assetSchema'
|
||||
|
||||
@@ -1235,8 +1235,11 @@ export function useCoreCommands(): ComfyCommand[] {
|
||||
id: 'Comfy.ToggleLinear',
|
||||
icon: 'pi pi-database',
|
||||
label: 'Toggle Simple Mode',
|
||||
function: () => {
|
||||
function: (metadata?: Record<string, unknown>) => {
|
||||
const source =
|
||||
typeof metadata?.source === 'string' ? metadata.source : 'keybind'
|
||||
const newMode = !canvasStore.linearMode
|
||||
if (newMode) useTelemetry()?.trackEnterLinear({ source })
|
||||
app.rootGraph.extra.linearMode = newMode
|
||||
workflowStore.activeWorkflow?.changeTracker?.checkState()
|
||||
canvasStore.linearMode = newMode
|
||||
|
||||
143
src/platform/assets/components/ActiveMediaAssetCard.stories.ts
Normal file
143
src/platform/assets/components/ActiveMediaAssetCard.stories.ts
Normal file
@@ -0,0 +1,143 @@
|
||||
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
||||
|
||||
import type { JobListItem } from '@/composables/queue/useJobList'
|
||||
|
||||
import ActiveMediaAssetCard from './ActiveMediaAssetCard.vue'
|
||||
|
||||
const meta: Meta<typeof ActiveMediaAssetCard> = {
|
||||
title: 'Platform/Assets/ActiveMediaAssetCard',
|
||||
component: ActiveMediaAssetCard
|
||||
}
|
||||
|
||||
export default meta
|
||||
type Story = StoryObj<typeof meta>
|
||||
|
||||
const SAMPLE_PREVIEW =
|
||||
'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/BigBuckBunny.jpg'
|
||||
|
||||
function createJob(overrides: Partial<JobListItem> = {}): JobListItem {
|
||||
return {
|
||||
id: 'job-1',
|
||||
title: 'Running...',
|
||||
meta: 'Step 5/10',
|
||||
state: 'running',
|
||||
progressTotalPercent: 50,
|
||||
progressCurrentPercent: 75,
|
||||
...overrides
|
||||
}
|
||||
}
|
||||
|
||||
export const Running: Story = {
|
||||
decorators: [
|
||||
() => ({
|
||||
template: '<div style="max-width: 220px;"><story /></div>'
|
||||
})
|
||||
],
|
||||
args: {
|
||||
job: createJob({
|
||||
state: 'running',
|
||||
progressTotalPercent: 65,
|
||||
iconImageUrl: SAMPLE_PREVIEW
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const RunningWithoutPreview: Story = {
|
||||
decorators: [
|
||||
() => ({
|
||||
template: '<div style="max-width: 220px;"><story /></div>'
|
||||
})
|
||||
],
|
||||
args: {
|
||||
job: createJob({
|
||||
state: 'running',
|
||||
progressTotalPercent: 30
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const Pending: Story = {
|
||||
decorators: [
|
||||
() => ({
|
||||
template: '<div style="max-width: 220px;"><story /></div>'
|
||||
})
|
||||
],
|
||||
args: {
|
||||
job: createJob({
|
||||
state: 'pending',
|
||||
title: 'In queue...',
|
||||
progressTotalPercent: undefined
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const Initialization: Story = {
|
||||
decorators: [
|
||||
() => ({
|
||||
template: '<div style="max-width: 220px;"><story /></div>'
|
||||
})
|
||||
],
|
||||
args: {
|
||||
job: createJob({
|
||||
state: 'initialization',
|
||||
title: 'Initializing...',
|
||||
progressTotalPercent: undefined
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const Failed: Story = {
|
||||
decorators: [
|
||||
() => ({
|
||||
template: '<div style="max-width: 220px;"><story /></div>'
|
||||
})
|
||||
],
|
||||
args: {
|
||||
job: createJob({
|
||||
state: 'failed',
|
||||
title: 'Failed'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const GridLayout: Story = {
|
||||
render: () => ({
|
||||
components: { ActiveMediaAssetCard },
|
||||
setup() {
|
||||
const jobs: JobListItem[] = [
|
||||
createJob({
|
||||
id: 'job-1',
|
||||
state: 'running',
|
||||
progressTotalPercent: 75,
|
||||
iconImageUrl: SAMPLE_PREVIEW
|
||||
}),
|
||||
createJob({
|
||||
id: 'job-2',
|
||||
state: 'running',
|
||||
progressTotalPercent: 45
|
||||
}),
|
||||
createJob({
|
||||
id: 'job-3',
|
||||
state: 'pending',
|
||||
title: 'In queue...',
|
||||
progressTotalPercent: undefined
|
||||
}),
|
||||
createJob({
|
||||
id: 'job-4',
|
||||
state: 'failed',
|
||||
title: 'Failed'
|
||||
})
|
||||
]
|
||||
return { jobs }
|
||||
},
|
||||
template: `
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 8px; padding: 8px;">
|
||||
<ActiveMediaAssetCard
|
||||
v-for="job in jobs"
|
||||
:key="job.id"
|
||||
:job="job"
|
||||
/>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import { mount } from '@vue/test-utils'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { createI18n } from 'vue-i18n'
|
||||
|
||||
import ActiveJobCard from './ActiveJobCard.vue'
|
||||
import ActiveJobCard from './ActiveMediaAssetCard.vue'
|
||||
|
||||
import type { JobListItem } from '@/composables/queue/useJobList'
|
||||
|
||||
@@ -17,6 +17,7 @@ import { reduceAllNodes } from '@/utils/graphTraversalUtil'
|
||||
import type {
|
||||
AuthMetadata,
|
||||
CreditTopupMetadata,
|
||||
EnterLinearMetadata,
|
||||
ExecutionContext,
|
||||
ExecutionTriggerSource,
|
||||
ExecutionErrorMetadata,
|
||||
@@ -354,6 +355,10 @@ export class MixpanelTelemetryProvider implements TelemetryProvider {
|
||||
this.trackEvent(TelemetryEvents.WORKFLOW_OPENED, metadata)
|
||||
}
|
||||
|
||||
trackEnterLinear(metadata: EnterLinearMetadata): void {
|
||||
this.trackEvent(TelemetryEvents.ENTER_LINEAR_MODE, metadata)
|
||||
}
|
||||
|
||||
trackPageVisibilityChanged(metadata: PageVisibilityMetadata): void {
|
||||
this.trackEvent(TelemetryEvents.PAGE_VISIBILITY_CHANGED, metadata)
|
||||
}
|
||||
|
||||
@@ -124,6 +124,10 @@ export interface WorkflowImportMetadata {
|
||||
open_source?: 'file_button' | 'file_drop' | 'template' | 'unknown'
|
||||
}
|
||||
|
||||
export interface EnterLinearMetadata {
|
||||
source?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Workflow open metadata
|
||||
*/
|
||||
@@ -297,6 +301,7 @@ export interface TelemetryProvider {
|
||||
// Workflow management events
|
||||
trackWorkflowImported(metadata: WorkflowImportMetadata): void
|
||||
trackWorkflowOpened(metadata: WorkflowImportMetadata): void
|
||||
trackEnterLinear(metadata: EnterLinearMetadata): void
|
||||
|
||||
// Page visibility events
|
||||
trackPageVisibilityChanged(metadata: PageVisibilityMetadata): void
|
||||
@@ -372,6 +377,7 @@ export const TelemetryEvents = {
|
||||
// Workflow Management
|
||||
WORKFLOW_IMPORTED: 'app:workflow_imported',
|
||||
WORKFLOW_OPENED: 'app:workflow_opened',
|
||||
ENTER_LINEAR_MODE: 'app:toggle_linear_mode',
|
||||
|
||||
// Page Visibility
|
||||
PAGE_VISIBILITY_CHANGED: 'app:page_visibility_changed',
|
||||
@@ -441,3 +447,4 @@ export type TelemetryEventProperties =
|
||||
| HelpResourceClickedMetadata
|
||||
| HelpCenterClosedMetadata
|
||||
| WorkflowCreatedMetadata
|
||||
| EnterLinearMetadata
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
ComfyWorkflow,
|
||||
useWorkflowStore
|
||||
} from '@/platform/workflow/management/stores/workflowStore'
|
||||
import { useTelemetry } from '@/platform/telemetry'
|
||||
import type { ComfyWorkflowJSON } from '@/platform/workflow/validation/schemas/workflowSchema'
|
||||
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
|
||||
import { useWorkflowThumbnail } from '@/renderer/core/thumbnail/useWorkflowThumbnail'
|
||||
@@ -315,8 +316,11 @@ export const useWorkflowService = () => {
|
||||
if (
|
||||
workflowData.extra?.linearMode !== undefined ||
|
||||
!workflowData.nodes.length
|
||||
)
|
||||
) {
|
||||
if (workflowData.extra?.linearMode && !useCanvasStore().linearMode)
|
||||
useTelemetry()?.trackEnterLinear({ source: 'workflow' })
|
||||
useCanvasStore().linearMode = !!workflowData.extra?.linearMode
|
||||
}
|
||||
|
||||
if (value === null || typeof value === 'string') {
|
||||
const path = value as string | null
|
||||
|
||||
Reference in New Issue
Block a user