feat: wire remaining PostHog analytics events #111
@@ -2,6 +2,7 @@ import { useState, useRef, useEffect, useCallback } from 'react'
|
||||
import { X, Send, Sparkles, Loader2 } from 'lucide-react'
|
||||
import { MarkdownContent } from '@/components/ui/MarkdownContent'
|
||||
import { copilotApi } from '@/api/copilot'
|
||||
import { analytics } from '@/lib/analytics'
|
||||
import { SuggestedFlowCard } from '@/components/assistant/SuggestedFlowCard'
|
||||
import type { CopilotMessage, SuggestedFlow } from '@/types/copilot'
|
||||
|
||||
@@ -32,6 +33,7 @@ export function CopilotPanel({ isOpen, onClose, treeId, sessionId, currentNodeId
|
||||
current_node_id: currentNodeId,
|
||||
})
|
||||
setConversationId(response.conversation_id)
|
||||
analytics.aiFeatureUsed({ feature: 'copilot' })
|
||||
setMessages([{ role: 'assistant', content: response.greeting }])
|
||||
} catch {
|
||||
setMessages([{ role: 'assistant', content: 'Failed to start copilot. Please try again.' }])
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
import { Copy, Check, Globe, Users, Clock, Trash2, Link2 } from 'lucide-react'
|
||||
import type { SessionShare, SessionShareVisibility } from '@/types'
|
||||
import { analytics } from '@/lib/analytics'
|
||||
import { sessionsApi } from '@/api/sessions'
|
||||
import { buildSessionShareUrl, filterSharesForSession } from '@/lib/sessionShare'
|
||||
import { cn } from '@/lib/utils'
|
||||
@@ -122,6 +123,7 @@ export function ShareSessionModal({ sessionId, sessionLabel, isOpen, onClose }:
|
||||
expires_at,
|
||||
})
|
||||
setShares([newShare, ...shares])
|
||||
analytics.sessionShared({ session_id: sessionId, visibility })
|
||||
toast.success('Share link generated')
|
||||
setShareName('')
|
||||
setExpirationPreset('never')
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useState, useCallback, useRef } from 'react'
|
||||
import { editorAIApi } from '@/api/editorAI'
|
||||
import { analytics } from '@/lib/analytics'
|
||||
import type {
|
||||
AIActionType,
|
||||
EditorAIChatMessage,
|
||||
@@ -101,6 +102,7 @@ export function useEditorAI({ flowType, treeId, getFlowContext, onFlowUpdate }:
|
||||
focalNodeId: currentFocalNodeId,
|
||||
flowContext: getFlowContext?.() || null,
|
||||
})
|
||||
analytics.aiFeatureUsed({ feature: 'flow_assist' })
|
||||
|
||||
setMessages((prev) => [
|
||||
...prev,
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useLocation, useNavigate } from 'react-router-dom'
|
||||
import { Sparkles, Send, Loader2, Flag } from 'lucide-react'
|
||||
import { PageMeta } from '@/components/common/PageMeta'
|
||||
import { assistantChatApi } from '@/api/assistantChat'
|
||||
import { analytics } from '@/lib/analytics'
|
||||
import { toast } from '@/lib/toast'
|
||||
import { ChatSidebar } from '@/components/assistant/ChatSidebar'
|
||||
import { ChatMessage } from '@/components/assistant/ChatMessage'
|
||||
@@ -147,6 +148,7 @@ export default function AssistantChatPage() {
|
||||
|
||||
try {
|
||||
const response = await assistantChatApi.sendMessage(activeChatId, userMessage)
|
||||
analytics.aiFeatureUsed({ feature: 'assistant_chat' })
|
||||
setMessages(prev => [
|
||||
...prev,
|
||||
{ role: 'assistant', content: response.content, suggestedFlows: response.suggested_flows },
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useState, useEffect, useCallback, useRef } from 'react'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { Sparkles, Loader2 } from 'lucide-react'
|
||||
import { analytics } from '@/lib/analytics'
|
||||
import { toast } from '@/lib/toast'
|
||||
import { kbAcceleratorApi } from '@/api'
|
||||
import { UploadScreen } from '@/components/kb-accelerator/UploadScreen'
|
||||
@@ -64,6 +65,7 @@ export default function KBAcceleratorPage() {
|
||||
target_type: targetType,
|
||||
})
|
||||
setImportId(resp.id)
|
||||
analytics.aiFeatureUsed({ feature: 'kb_accelerator' })
|
||||
setPhase('processing')
|
||||
startPolling(resp.id)
|
||||
} catch (err: unknown) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useEffect, useState, useCallback } from 'react'
|
||||
import { useParams, useNavigate, useSearchParams } from 'react-router-dom'
|
||||
import { Save, ArrowLeft, ListOrdered, Wrench, Settings, FileText, Calendar, Sparkles, Layers } from 'lucide-react'
|
||||
import { analytics } from '@/lib/analytics'
|
||||
import { Button } from '@/components/ui/Button'
|
||||
import { treesApi } from '@/api/trees'
|
||||
import { useProceduralEditorStore } from '@/store/proceduralEditorStore'
|
||||
@@ -222,6 +223,7 @@ export function ProceduralEditorPage() {
|
||||
toast.success(`${flowLabel} saved`)
|
||||
} else {
|
||||
const created = await treesApi.create(payload)
|
||||
analytics.flowCreated({ flow_type: payload.tree_type || 'procedural', method: 'manual' })
|
||||
markSaved()
|
||||
toast.success(`${flowLabel} created`)
|
||||
navigate(`/flows/${created.id}/edit`, { replace: true })
|
||||
|
||||
@@ -8,6 +8,7 @@ import { treesApi } from '@/api/trees'
|
||||
import { sessionToFlowApi } from '@/api/sessionToFlow'
|
||||
import { ExportPreviewModal } from '@/components/session/ExportPreviewModal'
|
||||
import { SaveSessionAsTreeModal } from '@/components/session/SaveSessionAsTreeModal'
|
||||
import { analytics } from '@/lib/analytics'
|
||||
import { ShareSessionModal } from '@/components/session/ShareSessionModal'
|
||||
import { SessionOutcomeModal } from '@/components/session/SessionOutcomeModal'
|
||||
import { SessionTimeline } from '@/components/session/SessionTimeline'
|
||||
@@ -150,6 +151,7 @@ export function SessionDetailPage() {
|
||||
setCopied(true)
|
||||
setTimeout(() => setCopied(false), 2000)
|
||||
toast.success('Copied to clipboard')
|
||||
analytics.exportGenerated({ session_id: session?.id || '', format: exportFormat })
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Copy failed:', err)
|
||||
@@ -168,6 +170,7 @@ export function SessionDetailPage() {
|
||||
setCopiedPsa(true)
|
||||
setTimeout(() => setCopiedPsa(false), 2000)
|
||||
toast.success('Copied ticket notes to clipboard')
|
||||
analytics.exportGenerated({ session_id: session.id, format: 'psa' })
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Copy for ticket failed:', err)
|
||||
@@ -177,6 +180,7 @@ export function SessionDetailPage() {
|
||||
|
||||
const handleDownload = (content: string) => {
|
||||
if (!session) return
|
||||
analytics.exportGenerated({ session_id: session.id, format: exportFormat })
|
||||
const blob = new Blob([content], { type: 'text/plain' })
|
||||
const url = URL.createObjectURL(blob)
|
||||
const a = document.createElement('a')
|
||||
@@ -256,6 +260,7 @@ export function SessionDetailPage() {
|
||||
setIsGeneratingFlow(true)
|
||||
try {
|
||||
const flowData = await sessionToFlowApi.generate(session.id)
|
||||
analytics.aiFeatureUsed({ feature: 'session_to_flow' })
|
||||
const tree = await treesApi.create({
|
||||
name: flowData.name,
|
||||
description: flowData.description,
|
||||
@@ -264,6 +269,7 @@ export function SessionDetailPage() {
|
||||
tags: flowData.tags,
|
||||
})
|
||||
toast.success('Flow generated! Opening editor...')
|
||||
analytics.flowCreated({ flow_type: 'procedural', method: 'session_to_flow' })
|
||||
navigate(getTreeEditorPath(tree.id, 'procedural'))
|
||||
} catch (err) {
|
||||
console.error('Failed to generate flow from session:', err)
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useEffect, useState, useCallback, useRef } from 'react'
|
||||
import { useParams, useNavigate, useBlocker } from 'react-router-dom'
|
||||
import { useStore } from 'zustand'
|
||||
import { Undo2, Redo2, Save, CheckCircle2, Monitor, FileText, Code2, LayoutList, BarChart3, Settings, Download, Sparkles } from 'lucide-react'
|
||||
import { analytics } from '@/lib/analytics'
|
||||
import { Button } from '@/components/ui/Button'
|
||||
import { getMonacoEditor } from '@/components/tree-editor/code-mode'
|
||||
import { treesApi } from '@/api/trees'
|
||||
@@ -364,6 +365,7 @@ export function TreeEditorPage() {
|
||||
toast.success('Draft saved successfully')
|
||||
} else {
|
||||
const newTree = await treesApi.create(treeData as TreeCreate)
|
||||
analytics.flowCreated({ flow_type: 'troubleshooting', method: 'manual' })
|
||||
setTreeStatus('draft')
|
||||
markSaved()
|
||||
toast.success('Draft created successfully')
|
||||
@@ -443,6 +445,7 @@ export function TreeEditorPage() {
|
||||
toast.success('Tree published successfully')
|
||||
} else {
|
||||
const newTree = await treesApi.create(treeData as TreeCreate)
|
||||
analytics.flowCreated({ flow_type: 'troubleshooting', method: 'manual' })
|
||||
setTreeStatus('published')
|
||||
markSaved()
|
||||
toast.success('Tree published successfully')
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Plug, CheckCircle2, AlertCircle, Loader2, Pencil, Trash2, Shield, History, Ticket, Users, Zap, Save } from 'lucide-react'
|
||||
import { analytics } from '@/lib/analytics'
|
||||
import { PageMeta } from '@/components/common/PageMeta'
|
||||
import { integrationsApi } from '@/api/integrations'
|
||||
import type { PsaConnectionResponse, PsaConnectionCreate, PsaConnectionUpdate, PsaConnectionTestResponse } from '@/types'
|
||||
@@ -97,6 +98,7 @@ export function IntegrationsPage() {
|
||||
}
|
||||
const created = await integrationsApi.createConnection(payload)
|
||||
setConnection(created)
|
||||
analytics.psaConnected({ provider: 'connectwise' })
|
||||
setMode('view')
|
||||
setForm(emptyForm)
|
||||
} catch (err) {
|
||||
|
||||
Reference in New Issue
Block a user