mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-02 22:37:32 +00:00
## Summary
Manual backport of #6518 to the `rh-test` branch.
Deduplicates workflow run telemetry and keeps a single source of truth
for execution while retaining click analytics and attributing initiator
source.
- Keep execution tracking in one place via `trackWorkflowExecution()`
- Keep click analytics via `trackRunButton(...)`
- Attribute initiator with `trigger_source` = 'button' | 'keybinding' |
'legacy_ui'
- Remove pre-tracking from keybindings to avoid double/triple counting
- Update legacy UI buttons to emit both click + execution events
## Backport Notes
This backport required manual conflict resolution in:
- `src/components/actionbar/ComfyRunButton/ComfyQueueButton.vue` - Added
batchCount tracking and trigger_source metadata
- `src/composables/useCoreCommands.ts` - Added error handling and
execution tracking
- `src/platform/telemetry/providers/cloud/MixpanelTelemetryProvider.ts`
- Updated trackRunButton signature with trigger_source support
Additionally added:
- `trackUiButtonClicked` method to TelemetryProvider interface
- `UiButtonClickMetadata` type definition
- `UI_BUTTON_CLICKED` event constant
All conflicts resolved intelligently to maintain the intent of the
original PR while adapting to the rh-test branch codebase.
## Original PR
- Original PR: #6518
- Original commit: 6fe88dba54
## Testing
- ✅ Typecheck passed
- ✅ Pre-commit hooks passed (lint, format)
- ✅ All conflicts resolved
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6552-Backport-to-rh-test-fix-telemetry-remove-redundant-run-tracking-keep-click-analytics-2a06d73d365081f78e4ad46a16be69f1)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Christian Byrne <c.byrne@comfy.org>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: Benjamin Lu <benjaminlu1107@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Christian Byrne <chrbyrne96@gmail.com>
182 lines
5.1 KiB
Vue
182 lines
5.1 KiB
Vue
<template>
|
|
<div class="queue-button-group flex">
|
|
<SplitButton
|
|
v-tooltip.bottom="{
|
|
value: workspaceStore.shiftDown
|
|
? $t('menu.runWorkflowFront')
|
|
: $t('menu.runWorkflow'),
|
|
showDelay: 600
|
|
}"
|
|
class="comfyui-queue-button"
|
|
:label="String(activeQueueModeMenuItem?.label ?? '')"
|
|
severity="primary"
|
|
size="small"
|
|
:model="queueModeMenuItems"
|
|
data-testid="queue-button"
|
|
@click="queuePrompt"
|
|
>
|
|
<template #icon>
|
|
<i v-if="workspaceStore.shiftDown" class="icon-[lucide--list-start]" />
|
|
<i v-else-if="queueMode === 'disabled'" class="icon-[lucide--play]" />
|
|
<i
|
|
v-else-if="queueMode === 'instant'"
|
|
class="icon-[lucide--fast-forward]"
|
|
/>
|
|
<i
|
|
v-else-if="queueMode === 'change'"
|
|
class="icon-[lucide--step-forward]"
|
|
/>
|
|
</template>
|
|
<template #item="{ item }">
|
|
<Button
|
|
v-tooltip="{
|
|
value: item.tooltip,
|
|
showDelay: 600
|
|
}"
|
|
:label="String(item.label ?? '')"
|
|
:icon="item.icon"
|
|
:severity="item.key === queueMode ? 'primary' : 'secondary'"
|
|
size="small"
|
|
text
|
|
/>
|
|
</template>
|
|
</SplitButton>
|
|
<BatchCountEdit />
|
|
<ButtonGroup class="execution-actions flex flex-nowrap">
|
|
<Button
|
|
v-tooltip.bottom="{
|
|
value: $t('menu.interrupt'),
|
|
showDelay: 600
|
|
}"
|
|
icon="pi pi-times"
|
|
:severity="executingPrompt ? 'danger' : 'secondary'"
|
|
:disabled="!executingPrompt"
|
|
text
|
|
:aria-label="$t('menu.interrupt')"
|
|
@click="() => commandStore.execute('Comfy.Interrupt')"
|
|
/>
|
|
<Button
|
|
v-tooltip.bottom="{
|
|
value: $t('sideToolbar.queueTab.clearPendingTasks'),
|
|
showDelay: 600
|
|
}"
|
|
icon="pi pi-stop"
|
|
:severity="hasPendingTasks ? 'danger' : 'secondary'"
|
|
:disabled="!hasPendingTasks"
|
|
text
|
|
:aria-label="$t('sideToolbar.queueTab.clearPendingTasks')"
|
|
@click="
|
|
() => {
|
|
if (queueCountStore.count.value > 1) {
|
|
commandStore.execute('Comfy.ClearPendingTasks')
|
|
}
|
|
queueMode = 'disabled'
|
|
}
|
|
"
|
|
/>
|
|
</ButtonGroup>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { storeToRefs } from 'pinia'
|
|
import Button from 'primevue/button'
|
|
import ButtonGroup from 'primevue/buttongroup'
|
|
import type { MenuItem } from 'primevue/menuitem'
|
|
import SplitButton from 'primevue/splitbutton'
|
|
import { computed } from 'vue'
|
|
import { useI18n } from 'vue-i18n'
|
|
|
|
import { isCloud } from '@/platform/distribution/types'
|
|
import { useTelemetry } from '@/platform/telemetry'
|
|
import { useCommandStore } from '@/stores/commandStore'
|
|
import {
|
|
useQueuePendingTaskCountStore,
|
|
useQueueSettingsStore
|
|
} from '@/stores/queueStore'
|
|
import { useWorkspaceStore } from '@/stores/workspaceStore'
|
|
|
|
import BatchCountEdit from '../BatchCountEdit.vue'
|
|
|
|
const workspaceStore = useWorkspaceStore()
|
|
const queueCountStore = storeToRefs(useQueuePendingTaskCountStore())
|
|
const { mode: queueMode, batchCount } = storeToRefs(useQueueSettingsStore())
|
|
|
|
const { t } = useI18n()
|
|
const queueModeMenuItemLookup = computed(() => {
|
|
const items: Record<string, MenuItem> = {
|
|
disabled: {
|
|
key: 'disabled',
|
|
label: t('menu.run'),
|
|
tooltip: t('menu.disabledTooltip'),
|
|
command: () => {
|
|
queueMode.value = 'disabled'
|
|
}
|
|
},
|
|
change: {
|
|
key: 'change',
|
|
label: `${t('menu.run')} (${t('menu.onChange')})`,
|
|
tooltip: t('menu.onChangeTooltip'),
|
|
command: () => {
|
|
queueMode.value = 'change'
|
|
}
|
|
}
|
|
}
|
|
if (!isCloud) {
|
|
items.instant = {
|
|
key: 'instant',
|
|
label: `${t('menu.run')} (${t('menu.instant')})`,
|
|
tooltip: t('menu.instantTooltip'),
|
|
command: () => {
|
|
queueMode.value = 'instant'
|
|
}
|
|
}
|
|
}
|
|
return items
|
|
})
|
|
|
|
const activeQueueModeMenuItem = computed(() => {
|
|
// Fallback to disabled mode if current mode is not available (e.g., instant mode in cloud)
|
|
return (
|
|
queueModeMenuItemLookup.value[queueMode.value] ||
|
|
queueModeMenuItemLookup.value.disabled
|
|
)
|
|
})
|
|
const queueModeMenuItems = computed(() =>
|
|
Object.values(queueModeMenuItemLookup.value)
|
|
)
|
|
|
|
const executingPrompt = computed(() => !!queueCountStore.count.value)
|
|
const hasPendingTasks = computed(
|
|
() => queueCountStore.count.value > 1 || queueMode.value !== 'disabled'
|
|
)
|
|
|
|
const commandStore = useCommandStore()
|
|
const queuePrompt = async (e: Event) => {
|
|
const isShiftPressed = 'shiftKey' in e && e.shiftKey
|
|
const commandId = isShiftPressed
|
|
? 'Comfy.QueuePromptFront'
|
|
: 'Comfy.QueuePrompt'
|
|
|
|
if (batchCount.value > 1) {
|
|
useTelemetry()?.trackUiButtonClicked({
|
|
button_id: 'queue_run_multiple_batches_submitted'
|
|
})
|
|
}
|
|
|
|
await commandStore.execute(commandId, {
|
|
metadata: {
|
|
subscribe_to_run: false,
|
|
trigger_source: 'button'
|
|
}
|
|
})
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.comfyui-queue-button :deep(.p-splitbutton-dropdown) {
|
|
border-top-right-radius: 0;
|
|
border-bottom-right-radius: 0;
|
|
}
|
|
</style>
|