From d6bbe79c88910722d1aa3d54605c9e8e381d9864 Mon Sep 17 00:00:00 2001 From: Kristina Date: Wed, 9 Oct 2024 11:46:48 +0400 Subject: [PATCH] Analytics channels fixes (#6847) Signed-off-by: Kristina Fefelova --- .vscode/launch.json | 2 +- .../src/components/ChatWidgetTab.svelte | 2 +- .../src/components/sidebar/SidebarTab.svelte | 2 +- plugins/workbench-resources/src/sidebar.ts | 12 ++-- plugins/workbench/src/analytics.ts | 4 +- plugins/workbench/src/index.ts | 1 - .../ai-bot/pod-ai-bot/src/workspaceClient.ts | 22 +++--- .../pod-analytics-collector/package.json | 2 + .../pod-analytics-collector/src/format.ts | 67 +++++++++++++++++-- .../pod-analytics-collector/src/loaders.ts | 5 +- .../src/supportWsClient.ts | 2 +- .../src/workspaceClient.ts | 2 - 12 files changed, 93 insertions(+), 30 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index eb10412154..c1f2a92066 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -432,7 +432,7 @@ "request": "launch", "args": ["src/index.ts"], "env": { - "PORT": "4007", + "PORT": "4017", "SECRET": "secret", "MONGO_URL": "mongodb://localhost:27017", "MINIO_ENDPOINT": "localhost", diff --git a/plugins/chunter-resources/src/components/ChatWidgetTab.svelte b/plugins/chunter-resources/src/components/ChatWidgetTab.svelte index 5bfc57a6db..da4e207ef2 100644 --- a/plugins/chunter-resources/src/components/ChatWidgetTab.svelte +++ b/plugins/chunter-resources/src/components/ChatWidgetTab.svelte @@ -87,7 +87,7 @@ ): void { } widgetsState.delete(widget) - Analytics.handleEvent('workbench.CloseSidebarWidget', { widget }) + Analytics.handleEvent(WorkbenchEvents.SidebarCloseWidget, { widget }) if (state.widget === widget) { sidebarStore.set({ ...state, @@ -162,7 +162,7 @@ export async function closeWidgetTab (widget: Widget, tab: string): Promise it.id !== tab) const closedTab = tabs.find((it) => it.id === tab) - Analytics.handleEvent('workbench.CloseSidebarWidget', { widget: widget._id, tab }) + Analytics.handleEvent(WorkbenchEvents.SidebarCloseWidget, { widget: widget._id, tab: closedTab?.name }) if (widget.onTabClose !== undefined && closedTab !== undefined) { const fn = await getResource(widget.onTabClose) @@ -208,7 +208,7 @@ export function openWidgetTab (widget: Ref, tab: string): void { if (newTab === undefined) return widgetsState.set(widget, { ...widgetState, tab }) - Analytics.handleEvent('workbench.OpenSidebarWidget', { widget, tab }) + Analytics.handleEvent(WorkbenchEvents.SidebarOpenWidget, { widget, tab: newTab?.name }) sidebarStore.set({ ...state, widgetsState @@ -243,7 +243,7 @@ export function createWidgetTab (widget: Widget, tab: WidgetTab, newTab = false) tab: tab.id }) - Analytics.handleEvent('workbench.OpenSidebarWidget', { widget: widget._id, tab: tab.id }) + Analytics.handleEvent(WorkbenchEvents.SidebarOpenWidget, { widget: widget._id, tab: tab.name }) sidebarStore.set({ ...state, widget: widget._id, diff --git a/plugins/workbench/src/analytics.ts b/plugins/workbench/src/analytics.ts index 5c83dc185c..82cceda572 100644 --- a/plugins/workbench/src/analytics.ts +++ b/plugins/workbench/src/analytics.ts @@ -1,4 +1,6 @@ export enum WorkbenchEvents { DocumentationOpened = 'workbench.help.DocumentationOpened', - KeyboardShortcutsOpened = 'workbench.help.KeyboardShortcutsOpened' + KeyboardShortcutsOpened = 'workbench.help.KeyboardShortcutsOpened', + SidebarCloseWidget = 'workbench.sidebar.CloseWidget', + SidebarOpenWidget = 'workbench.sidebar.OpenWidget' } diff --git a/plugins/workbench/src/index.ts b/plugins/workbench/src/index.ts index e34c555b7c..2bdf78decf 100644 --- a/plugins/workbench/src/index.ts +++ b/plugins/workbench/src/index.ts @@ -87,7 +87,6 @@ export interface WidgetPreference extends Preference { export interface WidgetTab { id: string name?: string - nameIntl?: IntlString icon?: Asset | AnySvelteComponent iconComponent?: AnyComponent iconProps?: Record diff --git a/services/ai-bot/pod-ai-bot/src/workspaceClient.ts b/services/ai-bot/pod-ai-bot/src/workspaceClient.ts index 2e9071b74a..bd425f0e1a 100644 --- a/services/ai-bot/pod-ai-bot/src/workspaceClient.ts +++ b/services/ai-bot/pod-ai-bot/src/workspaceClient.ts @@ -130,27 +130,27 @@ export class WorkspaceClient { this.ctx.info('Upload avatar file', { workspace: this.workspace }) try { - await this.checkPersonData(client) - const stat = fs.statSync(config.AvatarPath) const lastModified = stat.mtime.getTime() - if ( + const isAlreadyUploaded = this.info !== undefined && this.info.avatarPath === config.AvatarPath && this.info.avatarLastModified === lastModified - ) { - this.ctx.info('Avatar file already uploaded', { workspace: this.workspace, path: config.AvatarPath }) - return - } - const data = fs.readFileSync(config.AvatarPath) + if (!isAlreadyUploaded) { + const data = fs.readFileSync(config.AvatarPath) - await this.blobClient.upload(this.ctx, config.AvatarName, data.length, config.AvatarContentType, data) - await this.controller.updateAvatarInfo(this.workspace, config.AvatarPath, lastModified) - this.ctx.info('Uploaded avatar file', { workspace: this.workspace, path: config.AvatarPath }) + await this.blobClient.upload(this.ctx, config.AvatarName, data.length, config.AvatarContentType, data) + await this.controller.updateAvatarInfo(this.workspace, config.AvatarPath, lastModified) + this.ctx.info('Avatar file uploaded successfully', { workspace: this.workspace, path: config.AvatarPath }) + } else { + this.ctx.info('Avatar file already uploaded', { workspace: this.workspace, path: config.AvatarPath }) + } } catch (e) { this.ctx.error('Failed to upload avatar file', { e }) } + + await this.checkPersonData(client) } private async tryLogin (): Promise { diff --git a/services/analytics-collector/pod-analytics-collector/package.json b/services/analytics-collector/pod-analytics-collector/package.json index 7198911f2d..1b9ea5cb50 100644 --- a/services/analytics-collector/pod-analytics-collector/package.json +++ b/services/analytics-collector/pod-analytics-collector/package.json @@ -57,6 +57,8 @@ "@hcengineering/analytics-collector": "^0.6.0", "@hcengineering/analytics-collector-assets": "^0.6.0", "@hcengineering/analytics-service": "^0.6.0", + "@hcengineering/calendar": "^0.6.24", + "@hcengineering/calendar-assets": "^0.6.22", "@hcengineering/chunter": "^0.6.20", "@hcengineering/chunter-assets": "^0.6.18", "@hcengineering/client": "^0.6.18", diff --git a/services/analytics-collector/pod-analytics-collector/src/format.ts b/services/analytics-collector/pod-analytics-collector/src/format.ts index b44286d3bc..629f963fad 100644 --- a/services/analytics-collector/pod-analytics-collector/src/format.ts +++ b/services/analytics-collector/pod-analytics-collector/src/format.ts @@ -23,14 +23,19 @@ import notification, { notificationId } from '@hcengineering/notification' import recruit, { recruitId } from '@hcengineering/recruit' import time, { timeId } from '@hcengineering/time' import tracker, { trackerId } from '@hcengineering/tracker' -import { Class, Doc, Hierarchy, Markup, Ref } from '@hcengineering/core' +import workbench, { WorkbenchEvents } from '@hcengineering/workbench' +import { Class, Doc, Hierarchy, Markup, Ref, TxOperations } from '@hcengineering/core' import { MarkupNode, MarkupNodeType, MarkupMark, MarkupMarkType } from '@hcengineering/text' import { translate } from '@hcengineering/platform' -export async function eventToMarkup (event: AnalyticEvent, hierarchy: Hierarchy): Promise { +export async function eventToMarkup ( + event: AnalyticEvent, + hierarchy: Hierarchy, + client: TxOperations +): Promise { switch (event.event) { case AnalyticEventType.CustomEvent: - return formatCustomEvent(event) + return await formatCustomEvent(event, client) case AnalyticEventType.Error: return await formatErrorEvent(event) case AnalyticEventType.Navigation: @@ -67,10 +72,15 @@ function toText (text: string, display: 'normal' | 'bold' | 'code' = 'normal'): return { type: MarkupNodeType.text, text, marks } } -function formatCustomEvent (event: AnalyticEvent): string | undefined { +async function formatCustomEvent (event: AnalyticEvent, client: TxOperations): Promise { const text = event.params.event as string | undefined if (text === undefined || text === '') return + if (eventsToSkip.includes(event.params.event)) return + if (sidebarEvents.includes(text)) { + return await formatSidebarEvent(text, event.params, client) + } + const paramsTexts = [] for (const key in event.params) { @@ -85,6 +95,41 @@ function formatCustomEvent (event: AnalyticEvent): string | undefined { return toMarkup([toText(text + ' '), toText(paramsTexts.join(', '), 'code')]) } +async function formatSidebarEvent ( + event: string, + params: Record, + client: TxOperations +): Promise { + let text = event + switch (event) { + case WorkbenchEvents.SidebarOpenWidget: + text = 'open widget' + break + case WorkbenchEvents.SidebarCloseWidget: + text = 'close widget' + break + default: + break + } + const paramsTexts = [] + + if (params.widget !== undefined) { + const widget = client.getModel().findAllSync(workbench.class.Widget, { _id: params.widget })[0] + if (widget !== undefined) { + const widgetName = await translate(widget.label, {}) + paramsTexts.push(`widget: ${widgetName}`) + } else { + paramsTexts.push(`widget: ${params.widget}`) + } + } + + if (params.tab !== undefined) { + paramsTexts.push(`tab: ${params.tab}`) + } + + return toMarkup([toText('Sidebar: ', 'bold'), toText(text + ' '), toText(paramsTexts.join(', '), 'code')]) +} + async function formatErrorEvent (event: AnalyticEvent): Promise { const error = event.params.error @@ -427,3 +472,17 @@ export function getOnboardingMessage (email: string, workspace: string, name: st return toMarkup(nodes) } + +const eventsToSkip = [ + 'Fetch workspace', + 'Create Tab', + 'Update Tab', + 'document.Opened', + 'Create Message', + 'chunter.MessageCreated', + 'Create Time', + 'Create Tag', + 'SetCollectionItems' +] + +const sidebarEvents = [WorkbenchEvents.SidebarOpenWidget, WorkbenchEvents.SidebarCloseWidget] as string[] diff --git a/services/analytics-collector/pod-analytics-collector/src/loaders.ts b/services/analytics-collector/pod-analytics-collector/src/loaders.ts index bb9ad3a056..1c028922ac 100644 --- a/services/analytics-collector/pod-analytics-collector/src/loaders.ts +++ b/services/analytics-collector/pod-analytics-collector/src/loaders.ts @@ -14,6 +14,7 @@ // import { analyticsCollectorId } from '@hcengineering/analytics-collector' +import { calendarId } from '@hcengineering/calendar' import { chunterId } from '@hcengineering/chunter' import { contactId } from '@hcengineering/contact' import { coreId } from '@hcengineering/core' @@ -32,6 +33,7 @@ import { viewId } from '@hcengineering/view' import { workbenchId } from '@hcengineering/workbench' import analyticsCollectorEn from '@hcengineering/analytics-collector-assets/lang/en.json' +import calendarEn from '@hcengineering/calendar-assets/lang/en.json' import chunterEn from '@hcengineering/chunter-assets/lang/en.json' import contactEn from '@hcengineering/contact-assets/lang/en.json' import coreEng from '@hcengineering/core/lang/en.json' @@ -57,12 +59,14 @@ export function registerLoaders (): void { addStringsLoader(platformId, async (lang: string) => platformEng) addStringsLoader(analyticsCollectorId, async (lang: string) => analyticsCollectorEn) + addStringsLoader(calendarId, async (lang: string) => calendarEn) addStringsLoader(chunterId, async (lang: string) => chunterEn) addStringsLoader(contactId, async (lang: string) => contactEn) addStringsLoader(documentId, async (lang: string) => documentEn) addStringsLoader(driveId, async (lang: string) => driveEn) addStringsLoader(hrId, async (lang: string) => hrEn) addStringsLoader(leadId, async (lang: string) => leadEn) + addStringsLoader(loveId, async (lang: string) => loveEn) addStringsLoader(notificationId, async (lang: string) => notificationEn) addStringsLoader(preferenceId, async (lang: string) => preferenceEn) addStringsLoader(recruitId, async (lang: string) => recruitEn) @@ -71,5 +75,4 @@ export function registerLoaders (): void { addStringsLoader(trackerId, async (lang: string) => trackerEn) addStringsLoader(viewId, async (lang: string) => viewEn) addStringsLoader(workbenchId, async (lang: string) => workbenchEn) - addStringsLoader(loveId, async (lang: string) => loveEn) } diff --git a/services/analytics-collector/pod-analytics-collector/src/supportWsClient.ts b/services/analytics-collector/pod-analytics-collector/src/supportWsClient.ts index 46bb3ee282..83f10029a5 100644 --- a/services/analytics-collector/pod-analytics-collector/src/supportWsClient.ts +++ b/services/analytics-collector/pod-analytics-collector/src/supportWsClient.ts @@ -245,7 +245,7 @@ export class SupportWsClient extends WorkspaceClient { const hierarchy = client.getHierarchy() for (const event of events) { - const markup = await eventToMarkup(event, hierarchy) + const markup = await eventToMarkup(event, hierarchy, client) if (markup === undefined) { continue diff --git a/services/analytics-collector/pod-analytics-collector/src/workspaceClient.ts b/services/analytics-collector/pod-analytics-collector/src/workspaceClient.ts index a2795eadf1..66c503f9e0 100644 --- a/services/analytics-collector/pod-analytics-collector/src/workspaceClient.ts +++ b/services/analytics-collector/pod-analytics-collector/src/workspaceClient.ts @@ -23,8 +23,6 @@ export class WorkspaceClient { client: Client | undefined opClient: Promise | TxOperations - initializePromise: Promise | undefined = undefined - constructor ( readonly ctx: MeasureContext, readonly workspace: WorkspaceId