From c8f31f1649fc155a6339033274068b334767c824 Mon Sep 17 00:00:00 2001 From: Jeremy Wharton Date: Fri, 9 Jun 2023 14:14:53 -0500 Subject: [PATCH] web/satellite: send analytics events for project invitation responses This change causes the satellite frontend to send analytics events for project invitation responses. In addition, it more properly sources reported project invitation response errors. References #5855 Change-Id: I374e064c39920d3af829cb8467790d864a417115 --- .../src/components/modals/JoinProjectModal.vue | 12 ++++++++---- .../notifications/ProjectInvitationBanner.vue | 10 +++++++--- .../src/utils/constants/analyticsEventNames.ts | 4 ++++ .../components/ProjectInvitationItem.vue | 10 +++++++--- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/web/satellite/src/components/modals/JoinProjectModal.vue b/web/satellite/src/components/modals/JoinProjectModal.vue index b9c584aa5..2cf60c6c3 100644 --- a/web/satellite/src/components/modals/JoinProjectModal.vue +++ b/web/satellite/src/components/modals/JoinProjectModal.vue @@ -49,6 +49,7 @@ import { useProjectsStore } from '@/store/modules/projectsStore'; import { useNotify } from '@/utils/hooks'; import { ProjectInvitation, ProjectInvitationResponse } from '@/types/projects'; import { AnalyticsHttpApi } from '@/api/analytics'; +import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames'; import { LocalData } from '@/utils/localData'; import { RouteConfig } from '@/types/router'; @@ -80,20 +81,23 @@ async function respondToInvitation(response: ProjectInvitationResponse): Promise if (isLoading.value) return; isLoading.value = true; + const accepted = response === ProjectInvitationResponse.Accept; + let success = false; try { await projectsStore.respondToInvitation(invite.value.projectID, response); + analytics.eventTriggered(accepted ? AnalyticsEvent.PROJECT_INVITATION_ACCEPTED : AnalyticsEvent.PROJECT_INVITATION_DECLINED); success = true; } catch (error) { - const action = response === ProjectInvitationResponse.Accept ? 'accept' : 'decline'; - notify.error(`Failed to ${action} project invitation. ${error.message}`, null); + const action = accepted ? 'accept' : 'decline'; + notify.error(`Failed to ${action} project invitation. ${error.message}`, AnalyticsErrorEventSource.JOIN_PROJECT_MODAL); } try { await projectsStore.getUserInvitations(); await projectsStore.getProjects(); } catch (error) { - notify.error(`Failed to reload projects and invitations list. ${error.message}`, null); + notify.error(`Failed to reload projects and invitations list. ${error.message}`, AnalyticsErrorEventSource.JOIN_PROJECT_MODAL); } if (!success) { @@ -101,7 +105,7 @@ async function respondToInvitation(response: ProjectInvitationResponse): Promise return; } - if (response === ProjectInvitationResponse.Accept) { + if (accepted) { projectsStore.selectProject(invite.value.projectID); LocalData.setSelectedProjectId(invite.value.projectID); diff --git a/web/satellite/src/components/notifications/ProjectInvitationBanner.vue b/web/satellite/src/components/notifications/ProjectInvitationBanner.vue index c468da842..d808e66b8 100644 --- a/web/satellite/src/components/notifications/ProjectInvitationBanner.vue +++ b/web/satellite/src/components/notifications/ProjectInvitationBanner.vue @@ -27,7 +27,8 @@ import { useAppStore } from '@/store/modules/appStore'; import { useProjectsStore } from '@/store/modules/projectsStore'; import { useNotify } from '@/utils/hooks'; import { MODALS } from '@/utils/constants/appStatePopUps'; -import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames'; +import { AnalyticsHttpApi } from '@/api/analytics'; +import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames'; import VLoader from '@/components/common/VLoader.vue'; @@ -38,6 +39,8 @@ const appStore = useAppStore(); const projectsStore = useProjectsStore(); const notify = useNotify(); +const analytics: AnalyticsHttpApi = new AnalyticsHttpApi(); + const isLoading = ref(false); const hidden = ref>(new Set()); @@ -84,15 +87,16 @@ async function onDeclineClicked(): Promise { try { await projectsStore.respondToInvitation(invite.value.projectID, ProjectInvitationResponse.Decline); + analytics.eventTriggered(AnalyticsEvent.PROJECT_INVITATION_DECLINED); } catch (error) { - notify.error(`Failed to decline project invitation. ${error.message}`, AnalyticsErrorEventSource.OVERALL_APP_WRAPPER_ERROR); + notify.error(`Failed to decline project invitation. ${error.message}`, AnalyticsErrorEventSource.PROJECT_INVITATION); } try { await projectsStore.getUserInvitations(); await projectsStore.getProjects(); } catch (error) { - notify.error(`Failed to reload projects and invitations list. ${error.message}`, AnalyticsErrorEventSource.OVERALL_APP_WRAPPER_ERROR); + notify.error(`Failed to reload projects and invitations list. ${error.message}`, AnalyticsErrorEventSource.PROJECT_INVITATION); } isLoading.value = false; diff --git a/web/satellite/src/utils/constants/analyticsEventNames.ts b/web/satellite/src/utils/constants/analyticsEventNames.ts index 050d100e2..8aed4f661 100644 --- a/web/satellite/src/utils/constants/analyticsEventNames.ts +++ b/web/satellite/src/utils/constants/analyticsEventNames.ts @@ -52,6 +52,8 @@ export enum AnalyticsEvent { PROJECT_STORAGE_LIMIT_UPDATED = 'Project Storage Limit Updated', PROJECT_BANDWIDTH_LIMIT_UPDATED = 'Project Bandwidth Limit Updated', GALLERY_VIEW_CLICKED = 'Gallery View Clicked', + PROJECT_INVITATION_ACCEPTED = 'Project Invitation Accepted', + PROJECT_INVITATION_DECLINED = 'Project Invitation Declined', } export enum AnalyticsErrorEventSource { @@ -112,4 +114,6 @@ export enum AnalyticsErrorEventSource { PRICING_PLAN_STEP = 'Onboarding Pricing Plan step error', EDIT_TIMEOUT_MODAL = 'Edit session timeout error', SKIP_PASSPHRASE_MODAL = 'Remember skip passphrase error', + JOIN_PROJECT_MODAL = 'Join project modal', + PROJECT_INVITATION = 'Project invitation', } diff --git a/web/satellite/src/views/all-dashboard/components/ProjectInvitationItem.vue b/web/satellite/src/views/all-dashboard/components/ProjectInvitationItem.vue index ed07713c4..7089a6f42 100644 --- a/web/satellite/src/views/all-dashboard/components/ProjectInvitationItem.vue +++ b/web/satellite/src/views/all-dashboard/components/ProjectInvitationItem.vue @@ -40,7 +40,8 @@ import { ref } from 'vue'; import { ProjectInvitation, ProjectInvitationResponse } from '@/types/projects'; import { useNotify } from '@/utils/hooks'; -import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames'; +import { AnalyticsHttpApi } from '@/api/analytics'; +import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames'; import { MODALS } from '@/utils/constants/appStatePopUps'; import { useAppStore } from '@/store/modules/appStore'; import { useProjectsStore } from '@/store/modules/projectsStore'; @@ -52,6 +53,8 @@ const appStore = useAppStore(); const projectsStore = useProjectsStore(); const notify = useNotify(); +const analytics: AnalyticsHttpApi = new AnalyticsHttpApi(); + const isLoading = ref(false); const props = withDefaults(defineProps<{ @@ -77,15 +80,16 @@ async function onDeclineClicked(): Promise { try { await projectsStore.respondToInvitation(props.invitation.projectID, ProjectInvitationResponse.Decline); + analytics.eventTriggered(AnalyticsEvent.PROJECT_INVITATION_DECLINED); } catch (error) { - notify.error(`Failed to decline project invitation. ${error.message}`, AnalyticsErrorEventSource.ALL_PROJECT_DASHBOARD); + notify.error(`Failed to decline project invitation. ${error.message}`, AnalyticsErrorEventSource.PROJECT_INVITATION); } try { await projectsStore.getUserInvitations(); await projectsStore.getProjects(); } catch (error) { - notify.error(`Failed to reload projects and invitations list. ${error.message}`, AnalyticsErrorEventSource.ALL_PROJECT_DASHBOARD); + notify.error(`Failed to reload projects and invitations list. ${error.message}`, AnalyticsErrorEventSource.PROJECT_INVITATION); } isLoading.value = false;