mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-06-24 08:44:55 +00:00
Compare commits
3 Commits
main
...
refactor/d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd6c9a56bd | ||
|
|
a2bc5cd8f0 | ||
|
|
49a4c81ad8 |
@@ -427,7 +427,6 @@ import { useIntersectionObserver } from '@/composables/useIntersectionObserver'
|
||||
import { useLazyPagination } from '@/composables/useLazyPagination'
|
||||
import { usePrimeVueOverlayChildStyle } from '@/composables/usePopoverSizing'
|
||||
import { useTemplateFiltering } from '@/composables/useTemplateFiltering'
|
||||
import { isCloud } from '@/platform/distribution/types'
|
||||
import { useTelemetry } from '@/platform/telemetry'
|
||||
import { useTemplateWorkflows } from '@/platform/workflow/templates/composables/useTemplateWorkflows'
|
||||
import type { TemplateInfo } from '@/platform/workflow/templates/types/template'
|
||||
@@ -453,16 +452,14 @@ onMounted(() => {
|
||||
|
||||
// Wrap onClose to track session end
|
||||
const onClose = () => {
|
||||
if (isCloud) {
|
||||
const timeSpentSeconds = Math.floor(
|
||||
(Date.now() - sessionStartTime.value) / 1000
|
||||
)
|
||||
const timeSpentSeconds = Math.floor(
|
||||
(Date.now() - sessionStartTime.value) / 1000
|
||||
)
|
||||
|
||||
useTelemetry()?.trackTemplateLibraryClosed({
|
||||
template_selected: templateWasSelected.value,
|
||||
time_spent_seconds: timeSpentSeconds
|
||||
})
|
||||
}
|
||||
useTelemetry()?.trackTemplateLibraryClosed({
|
||||
template_selected: templateWasSelected.value,
|
||||
time_spent_seconds: timeSpentSeconds
|
||||
})
|
||||
|
||||
originalOnClose()
|
||||
}
|
||||
|
||||
@@ -135,7 +135,6 @@ import Button from '@/components/ui/button/Button.vue'
|
||||
import { useAuthActions } from '@/composables/auth/useAuthActions'
|
||||
import { useFreeTierOnboarding } from '@/platform/cloud/onboarding/composables/useFreeTierOnboarding'
|
||||
import { usePostAuthRedirect } from '@/platform/cloud/onboarding/composables/usePostAuthRedirect'
|
||||
import { isCloud } from '@/platform/distribution/types'
|
||||
import { useTelemetry } from '@/platform/telemetry'
|
||||
import type { SignUpData } from '@/schemas/signInSchema'
|
||||
import { isInChina } from '@/utils/networkUtil'
|
||||
@@ -188,9 +187,7 @@ const signUpWithEmail = async (values: SignUpData) => {
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
if (isCloud) {
|
||||
telemetry?.trackSignupOpened()
|
||||
}
|
||||
telemetry?.trackSignupOpened()
|
||||
|
||||
userIsInChina.value = await isInChina()
|
||||
})
|
||||
|
||||
@@ -18,7 +18,6 @@ import {
|
||||
getSurveyCompletedStatus,
|
||||
submitSurvey
|
||||
} from '@/platform/cloud/onboarding/auth'
|
||||
import { isCloud } from '@/platform/distribution/types'
|
||||
import { remoteConfig } from '@/platform/remoteConfig/remoteConfig'
|
||||
import { useTelemetry } from '@/platform/telemetry'
|
||||
|
||||
@@ -46,9 +45,7 @@ onMounted(async () => {
|
||||
await router.replace({ name: 'cloud-user-check' })
|
||||
return
|
||||
}
|
||||
if (isCloud) {
|
||||
useTelemetry()?.trackSurvey('opened')
|
||||
}
|
||||
useTelemetry()?.trackSurvey('opened')
|
||||
} catch (error) {
|
||||
console.error('Failed to check survey status:', error)
|
||||
}
|
||||
@@ -62,9 +59,7 @@ const onSubmitSurvey = async (payload: Record<string, unknown>) => {
|
||||
isSubmitting.value = true
|
||||
try {
|
||||
await submitSurvey(payload)
|
||||
if (isCloud) {
|
||||
useTelemetry()?.trackSurvey('submitted', payload)
|
||||
}
|
||||
useTelemetry()?.trackSurvey('submitted', payload)
|
||||
await router.push({ name: 'cloud-user-check' })
|
||||
} finally {
|
||||
isSubmitting.value = false
|
||||
|
||||
@@ -53,11 +53,9 @@ watch(
|
||||
)
|
||||
|
||||
const handleSubscribe = () => {
|
||||
if (isCloud) {
|
||||
useTelemetry()?.trackSubscription('subscribe_clicked', {
|
||||
current_tier: subscriptionTier.value?.toLowerCase()
|
||||
})
|
||||
}
|
||||
useTelemetry()?.trackSubscription('subscribe_clicked', {
|
||||
current_tier: subscriptionTier.value?.toLowerCase()
|
||||
})
|
||||
isAwaitingStripeSubscription.value = true
|
||||
showSubscriptionDialog()
|
||||
}
|
||||
|
||||
@@ -237,12 +237,10 @@ function useSubscriptionInternal() {
|
||||
const showSubscriptionDialog = (options?: {
|
||||
reason?: SubscriptionDialogReason
|
||||
}) => {
|
||||
if (isCloud) {
|
||||
useTelemetry()?.trackSubscription('modal_opened', {
|
||||
current_tier: subscriptionTier.value?.toLowerCase(),
|
||||
reason: options?.reason
|
||||
})
|
||||
}
|
||||
useTelemetry()?.trackSubscription('modal_opened', {
|
||||
current_tier: subscriptionTier.value?.toLowerCase(),
|
||||
reason: options?.reason
|
||||
})
|
||||
|
||||
void showSubscriptionRequiredDialog(options)
|
||||
}
|
||||
|
||||
@@ -38,6 +38,19 @@ vi.mock('@/stores/commandStore', () => ({
|
||||
})
|
||||
}))
|
||||
|
||||
// useTelemetry() returns null in OSS, a dispatcher in cloud — toggle via mockIsCloud.
|
||||
const { mockIsCloud, mockTrackHelpResourceClicked } = vi.hoisted(() => ({
|
||||
mockIsCloud: { value: true },
|
||||
mockTrackHelpResourceClicked: vi.fn()
|
||||
}))
|
||||
|
||||
vi.mock('@/platform/telemetry', () => ({
|
||||
useTelemetry: () =>
|
||||
mockIsCloud.value
|
||||
? { trackHelpResourceClicked: mockTrackHelpResourceClicked }
|
||||
: null
|
||||
}))
|
||||
|
||||
// Mock window.open
|
||||
const mockOpen = vi.fn()
|
||||
Object.defineProperty(window, 'open', {
|
||||
@@ -48,6 +61,7 @@ Object.defineProperty(window, 'open', {
|
||||
describe('useSubscriptionActions', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
mockIsCloud.value = true
|
||||
})
|
||||
|
||||
describe('handleAddApiCredits', () => {
|
||||
@@ -73,6 +87,27 @@ describe('useSubscriptionActions', () => {
|
||||
expect(isLoadingSupport.value).toBe(false)
|
||||
})
|
||||
|
||||
it('tracks help-resource telemetry when messaging support in cloud', async () => {
|
||||
const { handleMessageSupport } = useSubscriptionActions()
|
||||
|
||||
await handleMessageSupport()
|
||||
|
||||
expect(mockTrackHelpResourceClicked).toHaveBeenCalledWith({
|
||||
resource_type: 'help_feedback',
|
||||
is_external: true,
|
||||
source: 'subscription'
|
||||
})
|
||||
})
|
||||
|
||||
it('does not fire telemetry when messaging support in OSS builds', async () => {
|
||||
mockIsCloud.value = false
|
||||
const { handleMessageSupport } = useSubscriptionActions()
|
||||
|
||||
await handleMessageSupport()
|
||||
|
||||
expect(mockTrackHelpResourceClicked).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should handle errors gracefully', async () => {
|
||||
mockExecute.mockRejectedValueOnce(new Error('Command failed'))
|
||||
const { handleMessageSupport, isLoadingSupport } =
|
||||
|
||||
@@ -2,7 +2,6 @@ import { onMounted, ref } from 'vue'
|
||||
|
||||
import { useBillingContext } from '@/composables/billing/useBillingContext'
|
||||
import { useAuthActions } from '@/composables/auth/useAuthActions'
|
||||
import { isCloud } from '@/platform/distribution/types'
|
||||
import { useTelemetry } from '@/platform/telemetry'
|
||||
import { useDialogService } from '@/services/dialogService'
|
||||
import { useCommandStore } from '@/stores/commandStore'
|
||||
@@ -30,13 +29,11 @@ export function useSubscriptionActions() {
|
||||
const handleMessageSupport = async () => {
|
||||
try {
|
||||
isLoadingSupport.value = true
|
||||
if (isCloud) {
|
||||
telemetry?.trackHelpResourceClicked({
|
||||
resource_type: 'help_feedback',
|
||||
is_external: true,
|
||||
source: 'subscription'
|
||||
})
|
||||
}
|
||||
telemetry?.trackHelpResourceClicked({
|
||||
resource_type: 'help_feedback',
|
||||
is_external: true,
|
||||
source: 'subscription'
|
||||
})
|
||||
await commandStore.execute('Comfy.ContactSupport')
|
||||
} catch (error) {
|
||||
console.error('[useSubscriptionActions] Error contacting support:', error)
|
||||
|
||||
@@ -49,6 +49,17 @@ vi.mock('@/stores/dialogStore', () => ({
|
||||
}))
|
||||
}))
|
||||
|
||||
// useTelemetry() returns null in OSS, a dispatcher in cloud — toggle via mockIsCloud.
|
||||
const { mockIsCloud, mockTrackTemplate } = vi.hoisted(() => ({
|
||||
mockIsCloud: { value: true },
|
||||
mockTrackTemplate: vi.fn()
|
||||
}))
|
||||
|
||||
vi.mock('@/platform/telemetry', () => ({
|
||||
useTelemetry: () =>
|
||||
mockIsCloud.value ? { trackTemplate: mockTrackTemplate } : null
|
||||
}))
|
||||
|
||||
// Mock fetch
|
||||
global.fetch = vi.fn()
|
||||
|
||||
@@ -58,6 +69,9 @@ describe('useTemplateWorkflows', () => {
|
||||
let mockWorkflowTemplatesStore: MockWorkflowTemplatesStore
|
||||
|
||||
beforeEach(() => {
|
||||
mockIsCloud.value = true
|
||||
mockTrackTemplate.mockClear()
|
||||
|
||||
mockWorkflowTemplatesStore = {
|
||||
isLoaded: false,
|
||||
loadWorkflowTemplates: vi.fn().mockResolvedValue(true),
|
||||
@@ -285,6 +299,30 @@ describe('useTemplateWorkflows', () => {
|
||||
expect(fetch).toHaveBeenCalledWith('mock-file-url/templates/template1.json')
|
||||
})
|
||||
|
||||
it('tracks template telemetry on load in cloud builds', async () => {
|
||||
const { loadWorkflowTemplate } = useTemplateWorkflows()
|
||||
|
||||
mockWorkflowTemplatesStore.isLoaded = true
|
||||
await loadWorkflowTemplate('template1', 'default')
|
||||
await flushPromises()
|
||||
|
||||
expect(mockTrackTemplate).toHaveBeenCalledWith({
|
||||
workflow_name: 'template1',
|
||||
template_source: 'default'
|
||||
})
|
||||
})
|
||||
|
||||
it('does not fire template telemetry in OSS builds', async () => {
|
||||
mockIsCloud.value = false
|
||||
const { loadWorkflowTemplate } = useTemplateWorkflows()
|
||||
|
||||
mockWorkflowTemplatesStore.isLoaded = true
|
||||
await loadWorkflowTemplate('template1', 'default')
|
||||
await flushPromises()
|
||||
|
||||
expect(mockTrackTemplate).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should handle errors when loading templates', async () => {
|
||||
const { loadWorkflowTemplate, loadingTemplateId } = useTemplateWorkflows()
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { computed, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { isCloud } from '@/platform/distribution/types'
|
||||
import { useTelemetry } from '@/platform/telemetry'
|
||||
import { useWorkflowTemplatesStore } from '@/platform/workflow/templates/repositories/workflowTemplatesStore'
|
||||
import type {
|
||||
@@ -132,12 +131,10 @@ export function useTemplateWorkflows() {
|
||||
? t(`templateWorkflows.template.${id}`, id)
|
||||
: id
|
||||
|
||||
if (isCloud) {
|
||||
useTelemetry()?.trackTemplate({
|
||||
workflow_name: id,
|
||||
template_source: sourceModule
|
||||
})
|
||||
}
|
||||
useTelemetry()?.trackTemplate({
|
||||
workflow_name: id,
|
||||
template_source: sourceModule
|
||||
})
|
||||
|
||||
dialogStore.closeDialog()
|
||||
await app.loadGraphData(json, true, true, workflowName, {
|
||||
|
||||
@@ -43,8 +43,6 @@ function getBasePath(): string {
|
||||
const basePath = getBasePath()
|
||||
|
||||
function trackPageView(): void {
|
||||
if (!isCloud || typeof window === 'undefined') return
|
||||
|
||||
useTelemetry()?.trackPageView(document.title, {
|
||||
path: window.location.href
|
||||
})
|
||||
|
||||
@@ -361,15 +361,13 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
{ createCustomer: true }
|
||||
)
|
||||
|
||||
if (isCloud) {
|
||||
useTelemetry()?.trackAuth({
|
||||
method: 'email',
|
||||
is_new_user: false,
|
||||
user_id: result.user.uid,
|
||||
email: result.user.email ?? undefined,
|
||||
...getShareAuthMetadata()
|
||||
})
|
||||
}
|
||||
useTelemetry()?.trackAuth({
|
||||
method: 'email',
|
||||
is_new_user: false,
|
||||
user_id: result.user.uid,
|
||||
email: result.user.email ?? undefined,
|
||||
...getShareAuthMetadata()
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -384,15 +382,13 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
{ createCustomer: true }
|
||||
)
|
||||
|
||||
if (isCloud) {
|
||||
useTelemetry()?.trackAuth({
|
||||
method: 'email',
|
||||
is_new_user: true,
|
||||
user_id: result.user.uid,
|
||||
email: result.user.email ?? undefined,
|
||||
...getShareAuthMetadata()
|
||||
})
|
||||
}
|
||||
useTelemetry()?.trackAuth({
|
||||
method: 'email',
|
||||
is_new_user: true,
|
||||
user_id: result.user.uid,
|
||||
email: result.user.email ?? undefined,
|
||||
...getShareAuthMetadata()
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -405,17 +401,14 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
{ createCustomer: true }
|
||||
)
|
||||
|
||||
if (isCloud) {
|
||||
const additionalUserInfo = getAdditionalUserInfo(result)
|
||||
useTelemetry()?.trackAuth({
|
||||
method: 'google',
|
||||
is_new_user:
|
||||
options?.isNewUser || additionalUserInfo?.isNewUser || false,
|
||||
user_id: result.user.uid,
|
||||
email: result.user.email ?? undefined,
|
||||
...getShareAuthMetadata()
|
||||
})
|
||||
}
|
||||
const additionalUserInfo = getAdditionalUserInfo(result)
|
||||
useTelemetry()?.trackAuth({
|
||||
method: 'google',
|
||||
is_new_user: options?.isNewUser || additionalUserInfo?.isNewUser || false,
|
||||
user_id: result.user.uid,
|
||||
email: result.user.email ?? undefined,
|
||||
...getShareAuthMetadata()
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -428,17 +421,14 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
{ createCustomer: true }
|
||||
)
|
||||
|
||||
if (isCloud) {
|
||||
const additionalUserInfo = getAdditionalUserInfo(result)
|
||||
useTelemetry()?.trackAuth({
|
||||
method: 'github',
|
||||
is_new_user:
|
||||
options?.isNewUser || additionalUserInfo?.isNewUser || false,
|
||||
user_id: result.user.uid,
|
||||
email: result.user.email ?? undefined,
|
||||
...getShareAuthMetadata()
|
||||
})
|
||||
}
|
||||
const additionalUserInfo = getAdditionalUserInfo(result)
|
||||
useTelemetry()?.trackAuth({
|
||||
method: 'github',
|
||||
is_new_user: options?.isNewUser || additionalUserInfo?.isNewUser || false,
|
||||
user_id: result.user.uid,
|
||||
email: result.user.email ?? undefined,
|
||||
...getShareAuthMetadata()
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user