mirror of
https://github.com/langgenius/dify.git
synced 2026-03-06 15:45:14 +00:00
Compare commits
2 Commits
feat/model
...
feat/ampli
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f01c06451 | ||
|
|
6b95723f1c |
@@ -3,6 +3,7 @@ import type { ReactNode } from 'react'
|
|||||||
import SwrInitializer from '@/app/components/swr-initializer'
|
import SwrInitializer from '@/app/components/swr-initializer'
|
||||||
import { AppContextProvider } from '@/context/app-context'
|
import { AppContextProvider } from '@/context/app-context'
|
||||||
import GA, { GaType } from '@/app/components/base/ga'
|
import GA, { GaType } from '@/app/components/base/ga'
|
||||||
|
import AmplitudeProvider from '@/app/components/amplitude'
|
||||||
import HeaderWrapper from '@/app/components/header/header-wrapper'
|
import HeaderWrapper from '@/app/components/header/header-wrapper'
|
||||||
import Header from '@/app/components/header'
|
import Header from '@/app/components/header'
|
||||||
import { EventEmitterContextProvider } from '@/context/event-emitter'
|
import { EventEmitterContextProvider } from '@/context/event-emitter'
|
||||||
@@ -17,6 +18,7 @@ const Layout = ({ children }: { children: ReactNode }) => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<GA gaType={GaType.admin} />
|
<GA gaType={GaType.admin} />
|
||||||
|
<AmplitudeProvider />
|
||||||
<SwrInitializer>
|
<SwrInitializer>
|
||||||
<AppContextProvider>
|
<AppContextProvider>
|
||||||
<EventEmitterContextProvider>
|
<EventEmitterContextProvider>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import Header from './header'
|
|||||||
import SwrInitor from '@/app/components/swr-initializer'
|
import SwrInitor from '@/app/components/swr-initializer'
|
||||||
import { AppContextProvider } from '@/context/app-context'
|
import { AppContextProvider } from '@/context/app-context'
|
||||||
import GA, { GaType } from '@/app/components/base/ga'
|
import GA, { GaType } from '@/app/components/base/ga'
|
||||||
|
import AmplitudeProvider from '@/app/components/amplitude'
|
||||||
import HeaderWrapper from '@/app/components/header/header-wrapper'
|
import HeaderWrapper from '@/app/components/header/header-wrapper'
|
||||||
import { EventEmitterContextProvider } from '@/context/event-emitter'
|
import { EventEmitterContextProvider } from '@/context/event-emitter'
|
||||||
import { ProviderContextProvider } from '@/context/provider-context'
|
import { ProviderContextProvider } from '@/context/provider-context'
|
||||||
@@ -13,6 +14,7 @@ const Layout = ({ children }: { children: ReactNode }) => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<GA gaType={GaType.admin} />
|
<GA gaType={GaType.admin} />
|
||||||
|
<AmplitudeProvider />
|
||||||
<SwrInitor>
|
<SwrInitor>
|
||||||
<AppContextProvider>
|
<AppContextProvider>
|
||||||
<EventEmitterContextProvider>
|
<EventEmitterContextProvider>
|
||||||
|
|||||||
43
web/app/components/amplitude/AmplitudeProvider.tsx
Normal file
43
web/app/components/amplitude/AmplitudeProvider.tsx
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import type { FC } from 'react'
|
||||||
|
import React, { useEffect } from 'react'
|
||||||
|
import * as amplitude from '@amplitude/analytics-browser'
|
||||||
|
import { sessionReplayPlugin } from '@amplitude/plugin-session-replay-browser'
|
||||||
|
|
||||||
|
export type IAmplitudeProps = {
|
||||||
|
apiKey?: string
|
||||||
|
enableSessionReplay?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const AmplitudeProvider: FC<IAmplitudeProps> = ({
|
||||||
|
apiKey = '702e89332ab88a7f14e665f417244e9d',
|
||||||
|
}) => {
|
||||||
|
useEffect(() => {
|
||||||
|
// // Only enable in non-CE edition
|
||||||
|
// if (IS_CE_EDITION) {
|
||||||
|
// console.warn('[Amplitude] Amplitude is disabled in CE edition')
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
const sessionReplay = sessionReplayPlugin({
|
||||||
|
sampleRate: 0.1,
|
||||||
|
})
|
||||||
|
|
||||||
|
amplitude.add(sessionReplay)
|
||||||
|
|
||||||
|
amplitude.init(apiKey, {
|
||||||
|
defaultTracking: {
|
||||||
|
sessions: true,
|
||||||
|
pageViews: true,
|
||||||
|
formInteractions: true,
|
||||||
|
fileDownloads: true,
|
||||||
|
},
|
||||||
|
logLevel: amplitude.Types.LogLevel.Warn,
|
||||||
|
})
|
||||||
|
}, [apiKey])
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
export default React.memo(AmplitudeProvider)
|
||||||
2
web/app/components/amplitude/index.ts
Normal file
2
web/app/components/amplitude/index.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export { default } from './AmplitudeProvider'
|
||||||
|
export { resetUser, setUserId, setUserProperties, trackEvent } from './utils'
|
||||||
37
web/app/components/amplitude/utils.ts
Normal file
37
web/app/components/amplitude/utils.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import * as amplitude from '@amplitude/analytics-browser'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Track custom event
|
||||||
|
* @param eventName Event name
|
||||||
|
* @param eventProperties Event properties (optional)
|
||||||
|
*/
|
||||||
|
export const trackEvent = (eventName: string, eventProperties?: Record<string, any>) => {
|
||||||
|
amplitude.track(eventName, eventProperties)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set user ID
|
||||||
|
* @param userId User ID
|
||||||
|
*/
|
||||||
|
export const setUserId = (userId: string) => {
|
||||||
|
amplitude.setUserId(userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set user properties
|
||||||
|
* @param properties User properties
|
||||||
|
*/
|
||||||
|
export const setUserProperties = (properties: Record<string, any>) => {
|
||||||
|
const identifyEvent = new amplitude.Identify()
|
||||||
|
Object.entries(properties).forEach(([key, value]) => {
|
||||||
|
identifyEvent.set(key, value)
|
||||||
|
})
|
||||||
|
amplitude.identify(identifyEvent)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset user (e.g., when user logs out)
|
||||||
|
*/
|
||||||
|
export const resetUser = () => {
|
||||||
|
amplitude.reset()
|
||||||
|
}
|
||||||
@@ -49,6 +49,7 @@ import { fetchInstalledAppList } from '@/service/explore'
|
|||||||
import { AppModeEnum } from '@/types/app'
|
import { AppModeEnum } from '@/types/app'
|
||||||
import type { PublishWorkflowParams } from '@/types/workflow'
|
import type { PublishWorkflowParams } from '@/types/workflow'
|
||||||
import { basePath } from '@/utils/var'
|
import { basePath } from '@/utils/var'
|
||||||
|
import { trackEvent } from '../../amplitude'
|
||||||
|
|
||||||
const ACCESS_MODE_MAP: Record<AccessMode, { label: string, icon: React.ElementType }> = {
|
const ACCESS_MODE_MAP: Record<AccessMode, { label: string, icon: React.ElementType }> = {
|
||||||
[AccessMode.ORGANIZATION]: {
|
[AccessMode.ORGANIZATION]: {
|
||||||
@@ -182,6 +183,12 @@ const AppPublisher = ({
|
|||||||
try {
|
try {
|
||||||
await onPublish?.(params)
|
await onPublish?.(params)
|
||||||
setPublished(true)
|
setPublished(true)
|
||||||
|
trackEvent('app·_published_time', {
|
||||||
|
app_mode: appDetail?.mode,
|
||||||
|
app_id: appDetail?.id,
|
||||||
|
app_name: appDetail?.name,
|
||||||
|
time: new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' }),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
setPublished(false)
|
setPublished(false)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { useCreatePipelineDataset } from '@/service/knowledge/use-create-dataset
|
|||||||
import { useInvalidDatasetList } from '@/service/knowledge/use-dataset'
|
import { useInvalidDatasetList } from '@/service/knowledge/use-dataset'
|
||||||
import Toast from '@/app/components/base/toast'
|
import Toast from '@/app/components/base/toast'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
|
import { trackEvent } from '@/app/components/amplitude'
|
||||||
|
|
||||||
const CreateCard = () => {
|
const CreateCard = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
@@ -22,6 +23,9 @@ const CreateCard = () => {
|
|||||||
type: 'success',
|
type: 'success',
|
||||||
message: t('datasetPipeline.creation.successTip'),
|
message: t('datasetPipeline.creation.successTip'),
|
||||||
})
|
})
|
||||||
|
trackEvent('create_datasets_from_scratch', {
|
||||||
|
name: data.name,
|
||||||
|
})
|
||||||
invalidDatasetList()
|
invalidDatasetList()
|
||||||
push(`/datasets/${id}/pipeline`)
|
push(`/datasets/${id}/pipeline`)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import Content from './content'
|
|||||||
import Actions from './actions'
|
import Actions from './actions'
|
||||||
import { useCreatePipelineDatasetFromCustomized } from '@/service/knowledge/use-create-dataset'
|
import { useCreatePipelineDatasetFromCustomized } from '@/service/knowledge/use-create-dataset'
|
||||||
import { useInvalidDatasetList } from '@/service/knowledge/use-dataset'
|
import { useInvalidDatasetList } from '@/service/knowledge/use-dataset'
|
||||||
|
import { trackEvent } from '@/app/components/amplitude'
|
||||||
|
|
||||||
type TemplateCardProps = {
|
type TemplateCardProps = {
|
||||||
pipeline: PipelineTemplate
|
pipeline: PipelineTemplate
|
||||||
@@ -63,6 +64,13 @@ const TemplateCard = ({
|
|||||||
type: 'success',
|
type: 'success',
|
||||||
message: t('datasetPipeline.creation.successTip'),
|
message: t('datasetPipeline.creation.successTip'),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
trackEvent('create_datasets_with_pipeline', {
|
||||||
|
template_type: type,
|
||||||
|
template_name: pipeline.name,
|
||||||
|
chunk_structure: pipeline.chunk_structure,
|
||||||
|
})
|
||||||
|
|
||||||
invalidDatasetList()
|
invalidDatasetList()
|
||||||
if (newDataset.pipeline_id)
|
if (newDataset.pipeline_id)
|
||||||
await handleCheckPluginDependencies(newDataset.pipeline_id, true)
|
await handleCheckPluginDependencies(newDataset.pipeline_id, true)
|
||||||
@@ -75,7 +83,7 @@ const TemplateCard = ({
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}, [getPipelineTemplateInfo, createDataset, t, handleCheckPluginDependencies, push, invalidDatasetList])
|
}, [getPipelineTemplateInfo, createDataset, t, handleCheckPluginDependencies, push, invalidDatasetList, pipeline, type])
|
||||||
|
|
||||||
const handleShowTemplateDetails = useCallback(() => {
|
const handleShowTemplateDetails = useCallback(() => {
|
||||||
setShowDetailModal(true)
|
setShowDetailModal(true)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import Button from '@/app/components/base/button'
|
|||||||
import { ToastContext } from '@/app/components/base/toast'
|
import { ToastContext } from '@/app/components/base/toast'
|
||||||
import { createEmptyDataset } from '@/service/datasets'
|
import { createEmptyDataset } from '@/service/datasets'
|
||||||
import { useInvalidDatasetList } from '@/service/knowledge/use-dataset'
|
import { useInvalidDatasetList } from '@/service/knowledge/use-dataset'
|
||||||
|
import { trackEvent } from '@/app/components/amplitude'
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
show: boolean
|
show: boolean
|
||||||
@@ -41,6 +42,9 @@ const EmptyDatasetCreationModal = ({
|
|||||||
const dataset = await createEmptyDataset({ name: inputValue })
|
const dataset = await createEmptyDataset({ name: inputValue })
|
||||||
invalidDatasetList()
|
invalidDatasetList()
|
||||||
onHide()
|
onHide()
|
||||||
|
trackEvent('create_empty_datasets', {
|
||||||
|
name: inputValue,
|
||||||
|
})
|
||||||
router.push(`/datasets/${dataset.id}/documents`)
|
router.push(`/datasets/${dataset.id}/documents`)
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/aler
|
|||||||
import { noop } from 'lodash-es'
|
import { noop } from 'lodash-es'
|
||||||
import { useDocLink } from '@/context/i18n'
|
import { useDocLink } from '@/context/i18n'
|
||||||
import { useInvalidDatasetList } from '@/service/knowledge/use-dataset'
|
import { useInvalidDatasetList } from '@/service/knowledge/use-dataset'
|
||||||
|
import { trackEvent } from '@/app/components/amplitude'
|
||||||
|
|
||||||
const TextLabel: FC<PropsWithChildren> = (props) => {
|
const TextLabel: FC<PropsWithChildren> = (props) => {
|
||||||
return <label className='system-sm-semibold text-text-secondary'>{props.children}</label>
|
return <label className='system-sm-semibold text-text-secondary'>{props.children}</label>
|
||||||
@@ -571,6 +572,12 @@ const StepTwo = ({
|
|||||||
updateIndexingTypeCache?.(indexType as string)
|
updateIndexingTypeCache?.(indexType as string)
|
||||||
updateResultCache?.(data)
|
updateResultCache?.(data)
|
||||||
updateRetrievalMethodCache?.(retrievalConfig.search_method as string)
|
updateRetrievalMethodCache?.(retrievalConfig.search_method as string)
|
||||||
|
|
||||||
|
trackEvent('create_datasets', {
|
||||||
|
data_source_type: dataSourceType,
|
||||||
|
indexing_technique: indexType,
|
||||||
|
doc_form: currentDocForm,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -581,6 +588,13 @@ const StepTwo = ({
|
|||||||
updateIndexingTypeCache?.(indexType as string)
|
updateIndexingTypeCache?.(indexType as string)
|
||||||
updateResultCache?.(data)
|
updateResultCache?.(data)
|
||||||
updateRetrievalMethodCache?.(retrievalConfig.search_method as string)
|
updateRetrievalMethodCache?.(retrievalConfig.search_method as string)
|
||||||
|
|
||||||
|
// Track document addition to existing dataset
|
||||||
|
trackEvent('dataset_document_added', {
|
||||||
|
data_source_type: dataSourceType,
|
||||||
|
indexing_technique: indexType,
|
||||||
|
doc_form: currentDocForm,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { useToastContext } from '@/app/components/base/toast'
|
|||||||
import ExternalKnowledgeBaseCreate from '@/app/components/datasets/external-knowledge-base/create'
|
import ExternalKnowledgeBaseCreate from '@/app/components/datasets/external-knowledge-base/create'
|
||||||
import type { CreateKnowledgeBaseReq } from '@/app/components/datasets/external-knowledge-base/create/declarations'
|
import type { CreateKnowledgeBaseReq } from '@/app/components/datasets/external-knowledge-base/create/declarations'
|
||||||
import { createExternalKnowledgeBase } from '@/service/datasets'
|
import { createExternalKnowledgeBase } from '@/service/datasets'
|
||||||
|
import { trackEvent } from '@/app/components/amplitude'
|
||||||
|
|
||||||
const ExternalKnowledgeBaseConnector = () => {
|
const ExternalKnowledgeBaseConnector = () => {
|
||||||
const { notify } = useToastContext()
|
const { notify } = useToastContext()
|
||||||
@@ -17,6 +18,9 @@ const ExternalKnowledgeBaseConnector = () => {
|
|||||||
setLoading(true)
|
setLoading(true)
|
||||||
const result = await createExternalKnowledgeBase({ body: formValue })
|
const result = await createExternalKnowledgeBase({ body: formValue })
|
||||||
if (result && result.id) {
|
if (result && result.id) {
|
||||||
|
trackEvent('create_external_knowledge_base', {
|
||||||
|
value: formValue,
|
||||||
|
})
|
||||||
notify({ type: 'success', message: 'External Knowledge Base Connected Successfully' })
|
notify({ type: 'success', message: 'External Knowledge Base Connected Successfully' })
|
||||||
router.back()
|
router.back()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ import { AUTO_UPDATE_MODE } from '../reference-setting-modal/auto-update-setting
|
|||||||
import { convertUTCDaySecondsToLocalSeconds, timeOfDayToDayjs } from '../reference-setting-modal/auto-update-setting/utils'
|
import { convertUTCDaySecondsToLocalSeconds, timeOfDayToDayjs } from '../reference-setting-modal/auto-update-setting/utils'
|
||||||
import type { PluginDetail } from '../types'
|
import type { PluginDetail } from '../types'
|
||||||
import { PluginCategoryEnum, PluginSource } from '../types'
|
import { PluginCategoryEnum, PluginSource } from '../types'
|
||||||
|
import { trackEvent } from '../../amplitude'
|
||||||
|
|
||||||
const i18nPrefix = 'plugin.action'
|
const i18nPrefix = 'plugin.action'
|
||||||
|
|
||||||
@@ -199,6 +200,14 @@ const DetailHeader = ({
|
|||||||
const handleDelete = useCallback(async () => {
|
const handleDelete = useCallback(async () => {
|
||||||
showDeleting()
|
showDeleting()
|
||||||
const res = await uninstallPlugin(id)
|
const res = await uninstallPlugin(id)
|
||||||
|
|
||||||
|
trackEvent('plugin_deleted', {
|
||||||
|
plugin_id: id,
|
||||||
|
plugin_name: label[locale],
|
||||||
|
plugin_category: category,
|
||||||
|
plugin_source: source,
|
||||||
|
plugin_version: version,
|
||||||
|
})
|
||||||
hideDeleting()
|
hideDeleting()
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
hideDeleteConfirm()
|
hideDeleteConfirm()
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import { useCategories } from '../hooks'
|
|||||||
import { usePluginPageContext } from '../plugin-page/context'
|
import { usePluginPageContext } from '../plugin-page/context'
|
||||||
import { PluginCategoryEnum, type PluginDetail, PluginSource } from '../types'
|
import { PluginCategoryEnum, type PluginDetail, PluginSource } from '../types'
|
||||||
import Action from './action'
|
import Action from './action'
|
||||||
|
import { trackEvent } from '../../amplitude'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
className?: string
|
className?: string
|
||||||
@@ -77,6 +78,10 @@ const PluginItem: FC<Props> = ({
|
|||||||
}, [status, deprecated_reason])
|
}, [status, deprecated_reason])
|
||||||
|
|
||||||
const handleDelete = useCallback(() => {
|
const handleDelete = useCallback(() => {
|
||||||
|
trackEvent('plugin_deleted', {
|
||||||
|
plugin_id,
|
||||||
|
plugin_name: name,
|
||||||
|
})
|
||||||
refreshPluginList({ category } as any)
|
refreshPluginList({ category } as any)
|
||||||
}, [category, refreshPluginList])
|
}, [category, refreshPluginList])
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { getKeyboardKeyNameBySystem } from '@/app/components/workflow/utils'
|
|||||||
import cn from '@/utils/classnames'
|
import cn from '@/utils/classnames'
|
||||||
import { RiCloseLine, RiDatabase2Line, RiLoader2Line, RiPlayLargeLine } from '@remixicon/react'
|
import { RiCloseLine, RiDatabase2Line, RiLoader2Line, RiPlayLargeLine } from '@remixicon/react'
|
||||||
import { StopCircle } from '@/app/components/base/icons/src/vender/line/mediaAndDevices'
|
import { StopCircle } from '@/app/components/base/icons/src/vender/line/mediaAndDevices'
|
||||||
|
import { trackEvent } from '@/app/components/amplitude'
|
||||||
|
|
||||||
type RunModeProps = {
|
type RunModeProps = {
|
||||||
text?: string
|
text?: string
|
||||||
@@ -53,6 +54,9 @@ const RunMode = ({
|
|||||||
isDisabled ? 'rounded-l-md' : 'rounded-md',
|
isDisabled ? 'rounded-l-md' : 'rounded-md',
|
||||||
)}
|
)}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
trackEvent('pipeline_start_action_time', {
|
||||||
|
time: new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' }),
|
||||||
|
})
|
||||||
handleWorkflowStartRunInWorkflow()
|
handleWorkflowStartRunInWorkflow()
|
||||||
}}
|
}}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import BlockIcon from '../../block-icon'
|
|||||||
import cn from '@/utils/classnames'
|
import cn from '@/utils/classnames'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { basePath } from '@/utils/var'
|
import { basePath } from '@/utils/var'
|
||||||
|
import { trackEvent } from '@/app/components/amplitude'
|
||||||
|
|
||||||
const normalizeProviderIcon = (icon: ToolWithProvider['icon']) => {
|
const normalizeProviderIcon = (icon: ToolWithProvider['icon']) => {
|
||||||
if (typeof icon === 'string' && basePath && icon.startsWith('/') && !icon.startsWith(`${basePath}/`))
|
if (typeof icon === 'string' && basePath && icon.startsWith('/') && !icon.startsWith(`${basePath}/`))
|
||||||
@@ -67,6 +68,13 @@ const ToolItem: FC<Props> = ({
|
|||||||
params[item.name] = ''
|
params[item.name] = ''
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
trackEvent('tool_selected', {
|
||||||
|
tool_name: payload.name,
|
||||||
|
tool_parameters: payload.parameters,
|
||||||
|
tool_params: params,
|
||||||
|
plugin_id: provider.plugin_id,
|
||||||
|
plugin_unique_identifier: provider.plugin_unique_identifier,
|
||||||
|
})
|
||||||
onSelect(BlockEnum.Tool, {
|
onSelect(BlockEnum.Tool, {
|
||||||
provider_id: provider.id,
|
provider_id: provider.id,
|
||||||
provider_type: provider.type,
|
provider_type: provider.type,
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { StopCircle } from '@/app/components/base/icons/src/vender/line/mediaAnd
|
|||||||
import { useDynamicTestRunOptions } from '../hooks/use-dynamic-test-run-options'
|
import { useDynamicTestRunOptions } from '../hooks/use-dynamic-test-run-options'
|
||||||
import TestRunMenu, { type TestRunMenuRef, type TriggerOption, TriggerType } from './test-run-menu'
|
import TestRunMenu, { type TestRunMenuRef, type TriggerOption, TriggerType } from './test-run-menu'
|
||||||
import { useToastContext } from '@/app/components/base/toast'
|
import { useToastContext } from '@/app/components/base/toast'
|
||||||
|
import { trackEvent } from '../../amplitude'
|
||||||
|
|
||||||
type RunModeProps = {
|
type RunModeProps = {
|
||||||
text?: string
|
text?: string
|
||||||
@@ -67,6 +68,11 @@ const RunMode = ({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trackEvent('app_start_action_time', {
|
||||||
|
time: new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' }),
|
||||||
|
action_type: option.type,
|
||||||
|
})
|
||||||
|
|
||||||
if (option.type === TriggerType.UserInput) {
|
if (option.type === TriggerType.UserInput) {
|
||||||
handleWorkflowStartRunInWorkflow()
|
handleWorkflowStartRunInWorkflow()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { useCallback } from 'react'
|
|||||||
import { produce } from 'immer'
|
import { produce } from 'immer'
|
||||||
import { useWorkflowStore } from '@/app/components/workflow/store'
|
import { useWorkflowStore } from '@/app/components/workflow/store'
|
||||||
import { WorkflowRunningStatus } from '@/app/components/workflow/types'
|
import { WorkflowRunningStatus } from '@/app/components/workflow/types'
|
||||||
|
import { trackEvent } from '@/app/components/amplitude'
|
||||||
|
|
||||||
export const useWorkflowFailed = () => {
|
export const useWorkflowFailed = () => {
|
||||||
const workflowStore = useWorkflowStore()
|
const workflowStore = useWorkflowStore()
|
||||||
@@ -18,6 +19,12 @@ export const useWorkflowFailed = () => {
|
|||||||
status: WorkflowRunningStatus.Failed,
|
status: WorkflowRunningStatus.Failed,
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
trackEvent('workflow_run_failed', {
|
||||||
|
workflow_id: workflowRunningData?.task_id,
|
||||||
|
error: workflowRunningData?.result.error,
|
||||||
|
data: workflowRunningData?.result,
|
||||||
|
})
|
||||||
}, [workflowStore])
|
}, [workflowStore])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { noop } from 'lodash-es'
|
|||||||
import { setZendeskConversationFields } from '@/app/components/base/zendesk/utils'
|
import { setZendeskConversationFields } from '@/app/components/base/zendesk/utils'
|
||||||
import { ZENDESK_FIELD_IDS } from '@/config'
|
import { ZENDESK_FIELD_IDS } from '@/config'
|
||||||
import { useGlobalPublicStore } from './global-public-context'
|
import { useGlobalPublicStore } from './global-public-context'
|
||||||
|
import { setUserId, setUserProperties } from '@/app/components/amplitude'
|
||||||
|
|
||||||
export type AppContextValue = {
|
export type AppContextValue = {
|
||||||
userProfile: UserProfileResponse
|
userProfile: UserProfileResponse
|
||||||
@@ -159,6 +160,29 @@ export const AppContextProvider: FC<AppContextProviderProps> = ({ children }) =>
|
|||||||
}, [currentWorkspace?.id])
|
}, [currentWorkspace?.id])
|
||||||
// #endregion Zendesk conversation fields
|
// #endregion Zendesk conversation fields
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (userProfile?.id) {
|
||||||
|
setUserId(userProfile.email)
|
||||||
|
setUserProperties({
|
||||||
|
email: userProfile.email,
|
||||||
|
name: userProfile.name,
|
||||||
|
has_password: userProfile.is_password_set,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [userProfile])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (currentWorkspace?.id && userProfile?.id) {
|
||||||
|
setUserProperties({
|
||||||
|
workspace_id: currentWorkspace.id,
|
||||||
|
workspace_name: currentWorkspace.name,
|
||||||
|
workspace_plan: currentWorkspace.plan,
|
||||||
|
workspace_status: currentWorkspace.status,
|
||||||
|
workspace_role: currentWorkspace.role,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [currentWorkspace])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppContext.Provider value={{
|
<AppContext.Provider value={{
|
||||||
userProfile,
|
userProfile,
|
||||||
|
|||||||
@@ -44,6 +44,8 @@
|
|||||||
"knip": "knip"
|
"knip": "knip"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@amplitude/analytics-browser": "^2.30.1",
|
||||||
|
"@amplitude/plugin-session-replay-browser": "^1.23.2",
|
||||||
"@emoji-mart/data": "^1.2.1",
|
"@emoji-mart/data": "^1.2.1",
|
||||||
"@floating-ui/react": "^0.26.28",
|
"@floating-ui/react": "^0.26.28",
|
||||||
"@formatjs/intl-localematcher": "^0.5.10",
|
"@formatjs/intl-localematcher": "^0.5.10",
|
||||||
|
|||||||
3047
web/pnpm-lock.yaml
generated
3047
web/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user