web/satellite/vuetify: added analytics events for currently implemented functionality
Populated already implemented functionality with analytics events. Issue: https://github.com/storj/storj/issues/6122 Change-Id: I1e250ca02debc9bedbf78024f74e0dbfa9dfbcb9
This commit is contained in:
parent
e2e437dd95
commit
a4f7f0634d
@ -98,6 +98,8 @@ import { ProjectItemModel, PROJECT_ROLE_COLORS } from '@poc/types/projects';
|
||||
import { ProjectInvitationResponse } from '@/types/projects';
|
||||
import { ProjectRole } from '@/types/projectMembers';
|
||||
import { useProjectsStore } from '@/store/modules/projectsStore';
|
||||
import { useAnalyticsStore } from '@/store/modules/analyticsStore';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import IconProject from '@poc/components/icons/IconProject.vue';
|
||||
import IconSettings from '@poc/components/icons/IconSettings.vue';
|
||||
@ -111,6 +113,7 @@ const emit = defineEmits<{
|
||||
(event: 'joinClick'): void;
|
||||
}>();
|
||||
|
||||
const analyticsStore = useAnalyticsStore();
|
||||
const projectsStore = useProjectsStore();
|
||||
const router = useRouter();
|
||||
|
||||
@ -123,6 +126,7 @@ function openProject(): void {
|
||||
if (!props.item) return;
|
||||
projectsStore.selectProject(props.item.id);
|
||||
router.push(`/projects/${props.item.id}/dashboard`);
|
||||
analyticsStore.pageVisit('/projects/dashboard');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -132,7 +136,11 @@ async function declineInvitation(): Promise<void> {
|
||||
if (!props.item || isDeclining.value) return;
|
||||
isDeclining.value = true;
|
||||
|
||||
await projectsStore.respondToInvitation(props.item.id, ProjectInvitationResponse.Decline).catch(_ => {});
|
||||
try {
|
||||
await projectsStore.respondToInvitation(props.item.id, ProjectInvitationResponse.Decline);
|
||||
analyticsStore.eventTriggered(AnalyticsEvent.PROJECT_INVITATION_DECLINED);
|
||||
} catch { /* empty */ }
|
||||
|
||||
await projectsStore.getUserInvitations().catch(_ => {});
|
||||
await projectsStore.getProjects().catch(_ => {});
|
||||
|
||||
|
@ -130,6 +130,8 @@ import { ProjectInvitationResponse } from '@/types/projects';
|
||||
import { ProjectRole } from '@/types/projectMembers';
|
||||
import { SHORT_MONTHS_NAMES } from '@/utils/constants/date';
|
||||
import { useProjectsStore } from '@/store/modules/projectsStore';
|
||||
import { useAnalyticsStore } from '@/store/modules/analyticsStore';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
import IconSettings from '@poc/components/icons/IconSettings.vue';
|
||||
import IconTeam from '@poc/components/icons/IconTeam.vue';
|
||||
@ -145,6 +147,7 @@ const emit = defineEmits<{
|
||||
const search = ref<string>('');
|
||||
const decliningIds = ref(new Set<string>());
|
||||
|
||||
const analyticsStore = useAnalyticsStore();
|
||||
const projectsStore = useProjectsStore();
|
||||
const router = useRouter();
|
||||
|
||||
@ -170,6 +173,7 @@ function getFormattedDate(date: Date): string {
|
||||
function openProject(item: ProjectItemModel): void {
|
||||
projectsStore.selectProject(item.id);
|
||||
router.push(`/projects/${item.id}/dashboard`);
|
||||
analyticsStore.pageVisit('/projects/dashboard');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -179,7 +183,11 @@ async function declineInvitation(item: ProjectItemModel): Promise<void> {
|
||||
if (decliningIds.value.has(item.id)) return;
|
||||
decliningIds.value.add(item.id);
|
||||
|
||||
await projectsStore.respondToInvitation(item.id, ProjectInvitationResponse.Decline).catch(_ => {});
|
||||
try {
|
||||
await projectsStore.respondToInvitation(item.id, ProjectInvitationResponse.Decline);
|
||||
analyticsStore.eventTriggered(AnalyticsEvent.PROJECT_INVITATION_DECLINED);
|
||||
} catch { /* empty */ }
|
||||
|
||||
await projectsStore.getUserInvitations().catch(_ => {});
|
||||
await projectsStore.getProjects().catch(_ => {});
|
||||
|
||||
|
@ -93,11 +93,14 @@ import {
|
||||
import { useLoading } from '@/composables/useLoading';
|
||||
import { useUsersStore } from '@/store/modules/usersStore';
|
||||
import { UpdatedUser } from '@/types/users';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { useAnalyticsStore } from '@/store/modules/analyticsStore';
|
||||
|
||||
const rules = [
|
||||
(value: string) => (!!value || 'Can\'t be empty'),
|
||||
];
|
||||
|
||||
const analyticsStore = useAnalyticsStore();
|
||||
const userStore = useUsersStore();
|
||||
const { isLoading, withLoading } = useLoading();
|
||||
|
||||
@ -125,6 +128,8 @@ async function onChangeName(): Promise<void> {
|
||||
await withLoading(async () => {
|
||||
try {
|
||||
await userStore.updateUser(new UpdatedUser(name.value, name.value));
|
||||
|
||||
analyticsStore.eventTriggered(AnalyticsEvent.PROFILE_UPDATED);
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
|
@ -119,6 +119,8 @@ import { useLoading } from '@/composables/useLoading';
|
||||
import { useConfigStore } from '@/store/modules/configStore';
|
||||
import { AuthHttpApi } from '@/api/auth';
|
||||
import { RouteConfig } from '@/types/router';
|
||||
import { useAnalyticsStore } from '@/store/modules/analyticsStore';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
const DELAY_BEFORE_REDIRECT = 2000; // 2 sec
|
||||
const auth: AuthHttpApi = new AuthHttpApi();
|
||||
@ -134,6 +136,7 @@ const repeatRules = [
|
||||
(value: string) => (value && value === newPassword.value || 'Passwords are not the same.'),
|
||||
];
|
||||
|
||||
const analyticsStore = useAnalyticsStore();
|
||||
const { config } = useConfigStore().state;
|
||||
const { isLoading, withLoading } = useLoading();
|
||||
const router = useRouter();
|
||||
@ -163,6 +166,8 @@ async function onChangePassword(): Promise<void> {
|
||||
await withLoading(async () => {
|
||||
try {
|
||||
await auth.changePassword(oldPassword.value, newPassword.value);
|
||||
|
||||
analyticsStore.eventTriggered(AnalyticsEvent.PASSWORD_CHANGED);
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
|
@ -162,6 +162,8 @@ import QRCode from 'qrcode';
|
||||
import { useLoading } from '@/composables/useLoading';
|
||||
import { useConfigStore } from '@/store/modules/configStore';
|
||||
import { useUsersStore } from '@/store/modules/usersStore';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { useAnalyticsStore } from '@/store/modules/analyticsStore';
|
||||
|
||||
const rules = [
|
||||
(value: string) => (!!value || 'Can\'t be empty'),
|
||||
@ -170,6 +172,7 @@ const rules = [
|
||||
(value: string) => (value.length === 6 || 'Can only be 6 numbers long'),
|
||||
];
|
||||
|
||||
const analyticsStore = useAnalyticsStore();
|
||||
const { config } = useConfigStore().state;
|
||||
const usersStore = useUsersStore();
|
||||
const { isLoading, withLoading } = useLoading();
|
||||
@ -234,6 +237,8 @@ function enable(): void {
|
||||
await usersStore.enableUserMFA(confirmPasscode.value);
|
||||
await usersStore.getUser();
|
||||
await showCodes();
|
||||
|
||||
analyticsStore.eventTriggered(AnalyticsEvent.MFA_ENABLED);
|
||||
} catch (error) {
|
||||
isError.value = true;
|
||||
}
|
||||
|
@ -77,6 +77,9 @@ import {
|
||||
|
||||
import { ProjectInvitationResponse } from '@/types/projects';
|
||||
import { useProjectsStore } from '@/store/modules/projectsStore';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { useAnalyticsStore } from '@/store/modules/analyticsStore';
|
||||
import { RouteConfig } from '@/types/router';
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: boolean,
|
||||
@ -93,6 +96,7 @@ const emit = defineEmits<{
|
||||
(event: 'update:modelValue', value: boolean): void,
|
||||
}>();
|
||||
|
||||
const analyticsStore = useAnalyticsStore();
|
||||
const projectsStore = useProjectsStore();
|
||||
const router = useRouter();
|
||||
|
||||
@ -105,6 +109,7 @@ const isDeclining = ref<boolean>(false);
|
||||
function openProject(): void {
|
||||
projectsStore.selectProject(props.id);
|
||||
router.push(`/projects/${props.id}/dashboard`);
|
||||
analyticsStore.pageVisit('/projects/dashboard');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -117,7 +122,16 @@ async function respondToInvitation(response: ProjectInvitationResponse): Promise
|
||||
isLoading.value = true;
|
||||
|
||||
let success = false;
|
||||
await projectsStore.respondToInvitation(props.id, response).then(() => { success = true; }).catch(_ => {});
|
||||
try {
|
||||
await projectsStore.respondToInvitation(props.id, response);
|
||||
success = true;
|
||||
analyticsStore.eventTriggered(
|
||||
response === ProjectInvitationResponse.Accept ?
|
||||
AnalyticsEvent.PROJECT_INVITATION_ACCEPTED :
|
||||
AnalyticsEvent.PROJECT_INVITATION_DECLINED,
|
||||
);
|
||||
} catch { /* empty */ }
|
||||
|
||||
await projectsStore.getUserInvitations().catch(_ => {});
|
||||
await projectsStore.getProjects().catch(_ => { success = false; });
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
<v-sheet>
|
||||
<v-list class="px-2" color="default" variant="flat">
|
||||
<template v-if="pathBeforeAccountPage">
|
||||
<v-list-item class="pa-4 rounded-lg" link router-link :to="pathBeforeAccountPage">
|
||||
<v-list-item class="pa-4 rounded-lg" link router-link :to="pathBeforeAccountPage" @click="() => trackPageVisitEvent(pathBeforeAccountPage)">
|
||||
<template #prepend>
|
||||
<img src="@poc/assets/icon-back-tonal.svg" alt="Project">
|
||||
<!-- <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
@ -22,7 +22,7 @@
|
||||
</template>
|
||||
|
||||
<!-- All Projects -->
|
||||
<v-list-item class="pa-4 rounded-lg" link router-link to="/projects">
|
||||
<v-list-item class="pa-4 rounded-lg" link router-link to="/projects" @click="() => trackPageVisitEvent('/projects')">
|
||||
<template #prepend>
|
||||
<!-- <img src="@poc/assets/icon-prosject.svg" alt="Project" class="mr-3"> -->
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
@ -40,7 +40,7 @@
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item link router-link to="settings" class="my-1 py-3" rounded="lg">
|
||||
<v-list-item link router-link to="settings" class="my-1 py-3" rounded="lg" @click="() => trackPageVisitEvent('/settings')">
|
||||
<template #prepend>
|
||||
<!-- <img src="@poc/assets/icon-settings.svg" alt="Account Settings" class="mr-3"> -->
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
@ -52,7 +52,7 @@
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item link router-link to="billing" class="my-1" rounded="lg">
|
||||
<v-list-item link router-link to="billing" class="my-1" rounded="lg" @click="() => trackPageVisitEvent('/billing')">
|
||||
<template #prepend>
|
||||
<!-- <img src="@poc/assets/icon-card.svg" alt="Billing" class="mr-3"> -->
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
@ -82,7 +82,9 @@ import {
|
||||
} from 'vuetify/components';
|
||||
|
||||
import { useAppStore } from '@poc/store/appStore';
|
||||
import { useAnalyticsStore } from '@/store/modules/analyticsStore';
|
||||
|
||||
const analyticsStore = useAnalyticsStore();
|
||||
const appStore = useAppStore();
|
||||
|
||||
/**
|
||||
@ -93,4 +95,11 @@ const pathBeforeAccountPage = computed((): string | null => {
|
||||
if (!path || path === '/projects') return null;
|
||||
return path;
|
||||
});
|
||||
|
||||
/**
|
||||
* Sends "Page Visit" event to segment and opens link.
|
||||
*/
|
||||
function trackPageVisitEvent(page: string | null): void {
|
||||
if (page) analyticsStore.pageVisit(page);
|
||||
}
|
||||
</script>
|
||||
|
@ -30,10 +30,12 @@ import { useUsersStore } from '@/store/modules/usersStore';
|
||||
import { useABTestingStore } from '@/store/modules/abTestingStore';
|
||||
import { useProjectsStore } from '@/store/modules/projectsStore';
|
||||
import { useAppStore } from '@poc/store/appStore';
|
||||
import { useAnalyticsStore } from '@/store/modules/analyticsStore';
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
|
||||
const analyticsStore = useAnalyticsStore();
|
||||
const billingStore = useBillingStore();
|
||||
const usersStore = useUsersStore();
|
||||
const abTestingStore = useABTestingStore();
|
||||
@ -53,11 +55,15 @@ async function selectProject(projectId: string): Promise<void> {
|
||||
try {
|
||||
projects = await projectsStore.getProjects();
|
||||
} catch (_) {
|
||||
router.push('/projects');
|
||||
const path = '/projects';
|
||||
router.push(path);
|
||||
analyticsStore.pageVisit(path);
|
||||
return;
|
||||
}
|
||||
if (!projects.some(p => p.id === projectId)) {
|
||||
router.push('/projects');
|
||||
const path = '/projects';
|
||||
router.push(path);
|
||||
analyticsStore.pageVisit(path);
|
||||
return;
|
||||
}
|
||||
projectsStore.selectProject(projectId);
|
||||
|
@ -11,7 +11,7 @@
|
||||
<!-- Project Menu -->
|
||||
<v-list class="pa-2">
|
||||
<!-- My Projects -->
|
||||
<v-list-item rounded="lg" link router-link to="/projects">
|
||||
<v-list-item rounded="lg" link router-link to="/projects" @click="() => trackPageVisitEvent('/projects')">
|
||||
<template #prepend>
|
||||
<!-- <img src="@poc/assets/icon-project.svg" alt="Projects"> -->
|
||||
<IconProject />
|
||||
@ -36,7 +36,7 @@
|
||||
<v-divider class="my-2" />
|
||||
|
||||
<!-- Shared With Me -->
|
||||
<v-list-item rounded="lg" link router-link to="/projects">
|
||||
<v-list-item rounded="lg" link router-link to="/projects" @click="() => trackPageVisitEvent('/projects')">
|
||||
<template #prepend>
|
||||
<IconProject />
|
||||
</template>
|
||||
@ -69,7 +69,7 @@
|
||||
<!-- <v-divider class="my-2"></v-divider> -->
|
||||
|
||||
<!-- View All Projects -->
|
||||
<v-list-item link rounded="lg" router-link to="/projects">
|
||||
<v-list-item link rounded="lg" router-link to="/projects" @click="() => trackPageVisitEvent('/projects')">
|
||||
<template #prepend>
|
||||
<IconAllProjects />
|
||||
</template>
|
||||
@ -117,7 +117,7 @@
|
||||
|
||||
<v-divider class="my-2" />
|
||||
|
||||
<v-list-item link router-link to="dashboard" class="my-1 py-3" rounded="lg">
|
||||
<v-list-item link router-link to="dashboard" class="my-1 py-3" rounded="lg" @click="() => trackPageVisitEvent('/dashboard')">
|
||||
<template #prepend>
|
||||
<IconDashboard />
|
||||
</template>
|
||||
@ -126,7 +126,7 @@
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item link router-link to="buckets" class="my-1" rounded="lg">
|
||||
<v-list-item link router-link to="buckets" class="my-1" rounded="lg" @click="() => trackPageVisitEvent('/buckets')">
|
||||
<template #prepend>
|
||||
<IconBucket />
|
||||
</template>
|
||||
@ -135,7 +135,7 @@
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item link router-link to="bucket" class="my-1" rounded="lg">
|
||||
<v-list-item link router-link to="bucket" class="my-1" rounded="lg" @click="() => trackPageVisitEvent('/bucket')">
|
||||
<template #prepend>
|
||||
<IconBrowse />
|
||||
</template>
|
||||
@ -144,7 +144,7 @@
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item link router-link to="access" class="my-1" rounded="lg">
|
||||
<v-list-item link router-link to="access" class="my-1" rounded="lg" @click="() => trackPageVisitEvent('/access')">
|
||||
<template #prepend>
|
||||
<IconAccess />
|
||||
</template>
|
||||
@ -153,7 +153,7 @@
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item link router-link to="team" class="my-1" rounded="lg">
|
||||
<v-list-item link router-link to="team" class="my-1" rounded="lg" @click="() => trackPageVisitEvent('/team')">
|
||||
<template #prepend>
|
||||
<IconTeam />
|
||||
</template>
|
||||
@ -249,6 +249,7 @@ import {
|
||||
|
||||
import { Project } from '@/types/projects';
|
||||
import { useProjectsStore } from '@/store/modules/projectsStore';
|
||||
import { useAnalyticsStore } from '@/store/modules/analyticsStore';
|
||||
|
||||
import IconProject from '@poc/components/icons/IconProject.vue';
|
||||
import IconSettings from '@poc/components/icons/IconSettings.vue';
|
||||
@ -265,6 +266,7 @@ import IconForum from '@poc/components/icons/IconForum.vue';
|
||||
import IconSupport from '@poc/components/icons/IconSupport.vue';
|
||||
import IconResources from '@poc/components/icons/IconResources.vue';
|
||||
|
||||
const analyticsStore = useAnalyticsStore();
|
||||
const projectsStore = useProjectsStore();
|
||||
|
||||
/**
|
||||
@ -273,4 +275,11 @@ const projectsStore = useProjectsStore();
|
||||
const selectedProject = computed((): Project => {
|
||||
return projectsStore.state.selectedProject;
|
||||
});
|
||||
|
||||
/**
|
||||
* Sends "Page Visit" event to segment and opens link.
|
||||
*/
|
||||
function trackPageVisitEvent(page: string): void {
|
||||
analyticsStore.pageVisit(page);
|
||||
}
|
||||
</script>
|
||||
|
@ -134,11 +134,14 @@ import {
|
||||
|
||||
import { useProjectMembersStore } from '@/store/modules/projectMembersStore';
|
||||
import { useProjectsStore } from '@/store/modules/projectsStore';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { useAnalyticsStore } from '@/store/modules/analyticsStore';
|
||||
|
||||
import PageTitleComponent from '@poc/components/PageTitleComponent.vue';
|
||||
import PageSubtitleComponent from '@poc/components/PageSubtitleComponent.vue';
|
||||
import TeamTableComponent from '@poc/components/TeamTableComponent.vue';
|
||||
|
||||
const analyticsStore = useAnalyticsStore();
|
||||
const pmStore = useProjectMembersStore();
|
||||
const projectsStore = useProjectsStore();
|
||||
|
||||
@ -169,6 +172,8 @@ async function onAddUsersClick(): Promise<void> {
|
||||
return;
|
||||
}
|
||||
|
||||
analyticsStore.eventTriggered(AnalyticsEvent.PROJECT_MEMBERS_INVITE_SENT);
|
||||
|
||||
try {
|
||||
await pmStore.getProjectMembers(1, selectedProjectID.value);
|
||||
} catch (error) { /* empty */ }
|
||||
|
Loading…
Reference in New Issue
Block a user