web/satellite/vuetify: added notifications
Added notifications to Vuetify app. Populated existing functionality with notifications. Issue: https://github.com/storj/storj/issues/6087 Change-Id: I8339c372bb32fbf1e0ea136c92383494c129b4b6
This commit is contained in:
parent
f57bc81ce7
commit
185ebe3dcf
@ -3,12 +3,14 @@
|
||||
|
||||
<template>
|
||||
<router-view />
|
||||
<Notifications />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue';
|
||||
|
||||
import { useConfigStore } from '@/store/modules/configStore';
|
||||
import Notifications from '@poc/layouts/default/Notifications.vue';
|
||||
|
||||
const configStore = useConfigStore();
|
||||
|
||||
|
@ -99,7 +99,8 @@ 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 { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { useNotify } from '@/utils/hooks';
|
||||
|
||||
import IconProject from '@poc/components/icons/IconProject.vue';
|
||||
import IconSettings from '@poc/components/icons/IconSettings.vue';
|
||||
@ -116,6 +117,7 @@ const emit = defineEmits<{
|
||||
const analyticsStore = useAnalyticsStore();
|
||||
const projectsStore = useProjectsStore();
|
||||
const router = useRouter();
|
||||
const notify = useNotify();
|
||||
|
||||
const isDeclining = ref<boolean>(false);
|
||||
|
||||
@ -139,10 +141,18 @@ async function declineInvitation(): Promise<void> {
|
||||
try {
|
||||
await projectsStore.respondToInvitation(props.item.id, ProjectInvitationResponse.Decline);
|
||||
analyticsStore.eventTriggered(AnalyticsEvent.PROJECT_INVITATION_DECLINED);
|
||||
} catch { /* empty */ }
|
||||
} catch (error) {
|
||||
error.message = `Failed to decline project invitation. ${error.message}`;
|
||||
notify.notifyError(error, AnalyticsErrorEventSource.PROJECT_INVITATION);
|
||||
}
|
||||
|
||||
await projectsStore.getUserInvitations().catch(_ => {});
|
||||
await projectsStore.getProjects().catch(_ => {});
|
||||
try {
|
||||
await projectsStore.getUserInvitations();
|
||||
await projectsStore.getProjects();
|
||||
} catch (error) {
|
||||
error.message = `Failed to reload projects and invitations list. ${error.message}`;
|
||||
notify.notifyError(error, AnalyticsErrorEventSource.PROJECT_INVITATION);
|
||||
}
|
||||
|
||||
isDeclining.value = false;
|
||||
}
|
||||
|
@ -131,7 +131,8 @@ 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 { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { useNotify } from '@/utils/hooks';
|
||||
|
||||
import IconSettings from '@poc/components/icons/IconSettings.vue';
|
||||
import IconTeam from '@poc/components/icons/IconTeam.vue';
|
||||
@ -150,6 +151,7 @@ const decliningIds = ref(new Set<string>());
|
||||
const analyticsStore = useAnalyticsStore();
|
||||
const projectsStore = useProjectsStore();
|
||||
const router = useRouter();
|
||||
const notify = useNotify();
|
||||
|
||||
const sortBy = [{ key: 'name', order: 'asc' }];
|
||||
const headers = [
|
||||
@ -186,10 +188,18 @@ async function declineInvitation(item: ProjectItemModel): Promise<void> {
|
||||
try {
|
||||
await projectsStore.respondToInvitation(item.id, ProjectInvitationResponse.Decline);
|
||||
analyticsStore.eventTriggered(AnalyticsEvent.PROJECT_INVITATION_DECLINED);
|
||||
} catch { /* empty */ }
|
||||
} catch (error) {
|
||||
error.message = `Failed to decline project invitation. ${error.message}`;
|
||||
notify.notifyError(error, AnalyticsErrorEventSource.PROJECT_INVITATION);
|
||||
}
|
||||
|
||||
await projectsStore.getUserInvitations().catch(_ => {});
|
||||
await projectsStore.getProjects().catch(_ => {});
|
||||
try {
|
||||
await projectsStore.getUserInvitations();
|
||||
await projectsStore.getProjects();
|
||||
} catch (error) {
|
||||
error.message = `Failed to reload projects and invitations list. ${error.message}`;
|
||||
notify.notifyError(error, AnalyticsErrorEventSource.PROJECT_INVITATION);
|
||||
}
|
||||
|
||||
decliningIds.value.delete(item.id);
|
||||
}
|
||||
|
@ -93,8 +93,9 @@ import {
|
||||
import { useLoading } from '@/composables/useLoading';
|
||||
import { useUsersStore } from '@/store/modules/usersStore';
|
||||
import { UpdatedUser } from '@/types/users';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { useAnalyticsStore } from '@/store/modules/analyticsStore';
|
||||
import { useNotify } from '@/utils/hooks';
|
||||
|
||||
const rules = [
|
||||
(value: string) => (!!value || 'Can\'t be empty'),
|
||||
@ -103,6 +104,7 @@ const rules = [
|
||||
const analyticsStore = useAnalyticsStore();
|
||||
const userStore = useUsersStore();
|
||||
const { isLoading, withLoading } = useLoading();
|
||||
const notify = useNotify();
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: boolean,
|
||||
@ -129,8 +131,10 @@ async function onChangeName(): Promise<void> {
|
||||
try {
|
||||
await userStore.updateUser(new UpdatedUser(name.value, name.value));
|
||||
|
||||
notify.success('Account info successfully updated!');
|
||||
analyticsStore.eventTriggered(AnalyticsEvent.PROFILE_UPDATED);
|
||||
} catch (error) {
|
||||
notify.notifyError(error, AnalyticsErrorEventSource.EDIT_PROFILE_MODAL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,8 @@ 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';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { useNotify } from '@/utils/hooks';
|
||||
|
||||
const DELAY_BEFORE_REDIRECT = 2000; // 2 sec
|
||||
const auth: AuthHttpApi = new AuthHttpApi();
|
||||
@ -140,6 +141,7 @@ const analyticsStore = useAnalyticsStore();
|
||||
const { config } = useConfigStore().state;
|
||||
const { isLoading, withLoading } = useLoading();
|
||||
const router = useRouter();
|
||||
const notify = useNotify();
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: boolean,
|
||||
@ -167,8 +169,10 @@ async function onChangePassword(): Promise<void> {
|
||||
try {
|
||||
await auth.changePassword(oldPassword.value, newPassword.value);
|
||||
|
||||
notify.success('Password successfully changed!');
|
||||
analyticsStore.eventTriggered(AnalyticsEvent.PASSWORD_CHANGED);
|
||||
} catch (error) {
|
||||
notify.notifyError(error, AnalyticsErrorEventSource.CHANGE_PASSWORD_MODAL);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -180,7 +184,9 @@ async function onChangePassword(): Promise<void> {
|
||||
// TODO: this reload will be unnecessary once vuetify poc has its own login and/or becomes the primary app
|
||||
location.reload();
|
||||
}, DELAY_BEFORE_REDIRECT);
|
||||
} catch (error) { /* empty */ }
|
||||
} catch (error) {
|
||||
notify.notifyError(error, AnalyticsErrorEventSource.CHANGE_PASSWORD_MODAL);
|
||||
}
|
||||
|
||||
emit('update:modelValue', false);
|
||||
});
|
||||
|
@ -162,8 +162,9 @@ 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 { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { useAnalyticsStore } from '@/store/modules/analyticsStore';
|
||||
import { useNotify } from '@/utils/hooks';
|
||||
|
||||
const rules = [
|
||||
(value: string) => (!!value || 'Can\'t be empty'),
|
||||
@ -176,6 +177,7 @@ const analyticsStore = useAnalyticsStore();
|
||||
const { config } = useConfigStore().state;
|
||||
const usersStore = useUsersStore();
|
||||
const { isLoading, withLoading } = useLoading();
|
||||
const notify = useNotify();
|
||||
|
||||
const canvas = ref<HTMLCanvasElement>();
|
||||
const innerContent = ref<Component | null>(null);
|
||||
@ -240,6 +242,7 @@ function enable(): void {
|
||||
|
||||
analyticsStore.eventTriggered(AnalyticsEvent.MFA_ENABLED);
|
||||
} catch (error) {
|
||||
notify.notifyError(error, AnalyticsErrorEventSource.ENABLE_MFA_MODAL);
|
||||
isError.value = true;
|
||||
}
|
||||
});
|
||||
@ -253,7 +256,7 @@ async function showCodes() {
|
||||
await usersStore.generateUserMFARecoveryCodes();
|
||||
step.value = 2;
|
||||
} catch (error) {
|
||||
/* empty */
|
||||
notify.notifyError(error, AnalyticsErrorEventSource.ENABLE_MFA_MODAL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -267,7 +270,7 @@ watch(canvas, async val => {
|
||||
try {
|
||||
await QRCode.toCanvas(canvas.value, qrLink.value);
|
||||
} catch (error) {
|
||||
/* empty */
|
||||
notify.notifyError(error, AnalyticsErrorEventSource.ENABLE_MFA_MODAL);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -77,9 +77,9 @@ import {
|
||||
|
||||
import { ProjectInvitationResponse } from '@/types/projects';
|
||||
import { useProjectsStore } from '@/store/modules/projectsStore';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { useAnalyticsStore } from '@/store/modules/analyticsStore';
|
||||
import { RouteConfig } from '@/types/router';
|
||||
import { useNotify } from '@/utils/hooks';
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: boolean,
|
||||
@ -99,6 +99,7 @@ const emit = defineEmits<{
|
||||
const analyticsStore = useAnalyticsStore();
|
||||
const projectsStore = useProjectsStore();
|
||||
const router = useRouter();
|
||||
const notify = useNotify();
|
||||
|
||||
const isAccepting = ref<boolean>(false);
|
||||
const isDeclining = ref<boolean>(false);
|
||||
@ -108,6 +109,7 @@ const isDeclining = ref<boolean>(false);
|
||||
*/
|
||||
function openProject(): void {
|
||||
projectsStore.selectProject(props.id);
|
||||
notify.success('Invite accepted!');
|
||||
router.push(`/projects/${props.id}/dashboard`);
|
||||
analyticsStore.pageVisit('/projects/dashboard');
|
||||
}
|
||||
@ -118,7 +120,8 @@ function openProject(): void {
|
||||
async function respondToInvitation(response: ProjectInvitationResponse): Promise<void> {
|
||||
if (isDeclining.value || isAccepting.value) return;
|
||||
|
||||
const isLoading = response === ProjectInvitationResponse.Accept ? isAccepting : isDeclining;
|
||||
const accepted = response === ProjectInvitationResponse.Accept;
|
||||
const isLoading = accepted ? isAccepting : isDeclining;
|
||||
isLoading.value = true;
|
||||
|
||||
let success = false;
|
||||
@ -126,16 +129,26 @@ async function respondToInvitation(response: ProjectInvitationResponse): Promise
|
||||
await projectsStore.respondToInvitation(props.id, response);
|
||||
success = true;
|
||||
analyticsStore.eventTriggered(
|
||||
response === ProjectInvitationResponse.Accept ?
|
||||
accepted ?
|
||||
AnalyticsEvent.PROJECT_INVITATION_ACCEPTED :
|
||||
AnalyticsEvent.PROJECT_INVITATION_DECLINED,
|
||||
);
|
||||
} catch { /* empty */ }
|
||||
} catch (error) {
|
||||
const action = accepted ? 'accept' : 'decline';
|
||||
error.message = `Failed to ${action} project invitation. ${error.message}`;
|
||||
notify.notifyError(error, AnalyticsErrorEventSource.JOIN_PROJECT_MODAL);
|
||||
}
|
||||
|
||||
await projectsStore.getUserInvitations().catch(_ => {});
|
||||
await projectsStore.getProjects().catch(_ => { success = false; });
|
||||
try {
|
||||
await projectsStore.getUserInvitations();
|
||||
await projectsStore.getProjects();
|
||||
} catch (error) {
|
||||
success = false;
|
||||
error.message = `Failed to reload projects and invitations list. ${error.message}`;
|
||||
notify.notifyError(error, AnalyticsErrorEventSource.JOIN_PROJECT_MODAL);
|
||||
}
|
||||
|
||||
if (response === ProjectInvitationResponse.Accept && success) openProject();
|
||||
if (accepted && success) openProject();
|
||||
|
||||
isLoading.value = false;
|
||||
}
|
||||
|
@ -95,9 +95,12 @@ import {
|
||||
import { useLoading } from '@/composables/useLoading';
|
||||
import { useUsersStore } from '@/store/modules/usersStore';
|
||||
import { Duration } from '@/utils/time';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
import { useNotify } from '@/utils/hooks';
|
||||
|
||||
const usersStore = useUsersStore();
|
||||
const { isLoading, withLoading } = useLoading();
|
||||
const notify = useNotify();
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: boolean,
|
||||
@ -137,7 +140,9 @@ async function onChangeTimeout(): Promise<void> {
|
||||
await withLoading(async () => {
|
||||
try {
|
||||
await usersStore.updateSettings({ sessionDuration: duration.value.nanoseconds });
|
||||
notify.success(`Session timeout changed successfully. Your session timeout is ${duration.value?.shortString}.`);
|
||||
} catch (error) {
|
||||
notify.notifyError(error, AnalyticsErrorEventSource.EDIT_TIMEOUT_MODAL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -16,8 +16,11 @@ import DefaultBar from './AppBar.vue';
|
||||
import DefaultView from './View.vue';
|
||||
|
||||
import { useUsersStore } from '@/store/modules/usersStore';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
import { useNotify } from '@/utils/hooks';
|
||||
|
||||
const usersStore = useUsersStore();
|
||||
const notify = useNotify();
|
||||
|
||||
/**
|
||||
* Lifecycle hook after initial render.
|
||||
@ -26,6 +29,8 @@ const usersStore = useUsersStore();
|
||||
onBeforeMount(async () => {
|
||||
try {
|
||||
await usersStore.getSettings();
|
||||
} catch (error) { /* empty */ }
|
||||
} catch (error) {
|
||||
notify.notifyError(error, AnalyticsErrorEventSource.ALL_PROJECT_DASHBOARD);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
@ -31,9 +31,12 @@ import { useABTestingStore } from '@/store/modules/abTestingStore';
|
||||
import { useProjectsStore } from '@/store/modules/projectsStore';
|
||||
import { useAppStore } from '@poc/store/appStore';
|
||||
import { useAnalyticsStore } from '@/store/modules/analyticsStore';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
import { useNotify } from '@/utils/hooks';
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const notify = useNotify();
|
||||
|
||||
const analyticsStore = useAnalyticsStore();
|
||||
const billingStore = useBillingStore();
|
||||
@ -75,7 +78,7 @@ watch(() => route.params.projectId, async newId => selectProject(newId as string
|
||||
|
||||
/**
|
||||
* Lifecycle hook after initial render.
|
||||
* Pre fetches user`s and project information.
|
||||
* Pre-fetches user`s and project information.
|
||||
*/
|
||||
onBeforeMount(async () => {
|
||||
try {
|
||||
@ -85,6 +88,7 @@ onBeforeMount(async () => {
|
||||
usersStore.getSettings(),
|
||||
]);
|
||||
} catch (error) {
|
||||
notify.notifyError(error, AnalyticsErrorEventSource.OVERALL_APP_WRAPPER_ERROR);
|
||||
setTimeout(async () => await router.push(RouteConfig.Login.path), 1000);
|
||||
|
||||
return;
|
||||
@ -92,11 +96,17 @@ onBeforeMount(async () => {
|
||||
|
||||
try {
|
||||
await billingStore.setupAccount();
|
||||
} catch (error) { /* empty */ }
|
||||
} catch (error) {
|
||||
error.message = `Unable to setup account. ${error.message}`;
|
||||
notify.notifyError(error, AnalyticsErrorEventSource.OVERALL_APP_WRAPPER_ERROR);
|
||||
}
|
||||
|
||||
try {
|
||||
await billingStore.getCreditCards();
|
||||
} catch (error) { /* empty */ }
|
||||
} catch (error) {
|
||||
error.message = `Unable to get credit cards. ${error.message}`;
|
||||
notify.notifyError(error, AnalyticsErrorEventSource.OVERALL_APP_WRAPPER_ERROR);
|
||||
}
|
||||
|
||||
selectProject(route.params.projectId as string);
|
||||
});
|
||||
|
@ -0,0 +1,94 @@
|
||||
// Copyright (C) 2023 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template>
|
||||
<v-snackbar
|
||||
v-model="doNotificationsExist"
|
||||
position="fixed"
|
||||
location="top right"
|
||||
z-index="99999"
|
||||
variant="text"
|
||||
contained
|
||||
>
|
||||
<v-alert
|
||||
v-for="item in notifications"
|
||||
:key="item.id"
|
||||
closable
|
||||
variant="elevated"
|
||||
:title="title(item.type)"
|
||||
:text="item.message"
|
||||
:type="getType(item.type)"
|
||||
rounded="lg"
|
||||
class="my-2"
|
||||
border
|
||||
@mouseover="() => onMouseOver(item.id)"
|
||||
@mouseleave="() => onMouseLeave(item.id)"
|
||||
/>
|
||||
</v-snackbar>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { VAlert, VSnackbar } from 'vuetify/components';
|
||||
|
||||
import { useNotificationsStore } from '@/store/modules/notificationsStore';
|
||||
import { DelayedNotification, NOTIFICATION_TYPES } from '@/types/DelayedNotification';
|
||||
|
||||
const notificationsStore = useNotificationsStore();
|
||||
|
||||
/**
|
||||
* Indicates if any notifications are in queue.
|
||||
*/
|
||||
const doNotificationsExist = computed((): boolean => {
|
||||
return notifications.value.length > 0;
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns all notification queue from store.
|
||||
*/
|
||||
const notifications = computed((): DelayedNotification[] => {
|
||||
return notificationsStore.state.notificationQueue as DelayedNotification[];
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns notification title based on type.
|
||||
* @param itemType
|
||||
*/
|
||||
function title(itemType: string): string {
|
||||
const type = getType(itemType);
|
||||
const [firstLetter, ...rest] = type;
|
||||
|
||||
return `${firstLetter.toUpperCase()}${rest.join('')}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns notification type.
|
||||
* @param itemType
|
||||
*/
|
||||
function getType(itemType: string): string {
|
||||
switch (itemType) {
|
||||
case NOTIFICATION_TYPES.SUCCESS:
|
||||
return 'success';
|
||||
case NOTIFICATION_TYPES.ERROR:
|
||||
return 'error';
|
||||
case NOTIFICATION_TYPES.WARNING:
|
||||
return 'warning';
|
||||
default:
|
||||
return 'info';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces notification to stay on page on mouse over it.
|
||||
*/
|
||||
function onMouseOver(id: string): void {
|
||||
notificationsStore.pauseNotification(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume notification flow when mouse leaves notification.
|
||||
*/
|
||||
function onMouseLeave(id: string): void {
|
||||
notificationsStore.resumeNotification(id);
|
||||
}
|
||||
</script>
|
@ -8,6 +8,7 @@
|
||||
*/
|
||||
|
||||
// Plugins
|
||||
import { App } from 'vue';
|
||||
import { createPinia, setActivePinia } from 'pinia';
|
||||
|
||||
import router from '../router';
|
||||
@ -15,13 +16,16 @@ import router from '../router';
|
||||
import { loadFonts } from './webfontloader';
|
||||
import vuetify from './vuetify';
|
||||
|
||||
import NotificatorPlugin from '@/utils/plugins/notificator';
|
||||
|
||||
const pinia = createPinia();
|
||||
setActivePinia(pinia);
|
||||
|
||||
export function registerPlugins (app) {
|
||||
export function registerPlugins(app: App<Element>) {
|
||||
loadFonts();
|
||||
app
|
||||
.use(vuetify)
|
||||
.use(router)
|
||||
.use(pinia);
|
||||
.use(pinia)
|
||||
.use(NotificatorPlugin);
|
||||
}
|
||||
|
@ -175,6 +175,8 @@ import {
|
||||
|
||||
import { User, UserSettings } from '@/types/users';
|
||||
import { useUsersStore } from '@/store/modules/usersStore';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
import { useNotify } from '@/utils/hooks';
|
||||
import { Duration } from '@/utils/time';
|
||||
|
||||
import ChangePasswordDialog from '@poc/components/dialogs/ChangePasswordDialog.vue';
|
||||
@ -183,6 +185,7 @@ import EnableMFADialog from '@poc/components/dialogs/EnableMFADialog.vue';
|
||||
import SetSessionTimeoutDialog from '@poc/components/dialogs/SetSessionTimeoutDialog.vue';
|
||||
|
||||
const usersStore = useUsersStore();
|
||||
const notify = useNotify();
|
||||
|
||||
const isChangePasswordDialogShown = ref<boolean>(false);
|
||||
const isChangeNameDialogShown = ref<boolean>(false);
|
||||
@ -208,7 +211,7 @@ async function toggleEnableMFADialog() {
|
||||
await usersStore.generateUserMFASecret();
|
||||
isEnableMFADialogShown.value = true;
|
||||
} catch (error) {
|
||||
/* empty */
|
||||
notify.notifyError(error, AnalyticsErrorEventSource.ACCOUNT_SETTINGS_AREA);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,6 +91,8 @@ import { useBucketsStore } from '@/store/modules/bucketsStore';
|
||||
import { DataStamp, Project, ProjectLimits } from '@/types/projects';
|
||||
import { Dimensions, Size } from '@/utils/bytesSize';
|
||||
import { ChartUtils } from '@/utils/chart';
|
||||
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||
import { useNotify } from '@/utils/hooks';
|
||||
|
||||
import PageTitleComponent from '@poc/components/PageTitleComponent.vue';
|
||||
import PageSubtitleComponent from '@poc/components/PageSubtitleComponent.vue';
|
||||
@ -106,6 +108,8 @@ const agStore = useAccessGrantsStore();
|
||||
const billingStore = useBillingStore();
|
||||
const bucketsStore = useBucketsStore();
|
||||
|
||||
const notify = useNotify();
|
||||
|
||||
const isDataFetching = ref<boolean>(true);
|
||||
const chartWidth = ref<number>(0);
|
||||
const chartContainer = ref<ComponentPublicInstance>();
|
||||
@ -323,7 +327,9 @@ onMounted(async (): Promise<void> => {
|
||||
agStore.getAccessGrants(FIRST_PAGE, projectID),
|
||||
bucketsStore.getBuckets(FIRST_PAGE, projectID),
|
||||
]);
|
||||
} catch (error) { /* empty */ } finally {
|
||||
} catch (error) {
|
||||
notify.notifyError(error, AnalyticsErrorEventSource.PROJECT_DASHBOARD_PAGE);
|
||||
} finally {
|
||||
isDataFetching.value = false;
|
||||
}
|
||||
});
|
||||
|
@ -134,8 +134,9 @@ import {
|
||||
|
||||
import { useProjectMembersStore } from '@/store/modules/projectMembersStore';
|
||||
import { useProjectsStore } from '@/store/modules/projectsStore';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { useAnalyticsStore } from '@/store/modules/analyticsStore';
|
||||
import { useNotify } from '@/utils/hooks';
|
||||
|
||||
import PageTitleComponent from '@poc/components/PageTitleComponent.vue';
|
||||
import PageSubtitleComponent from '@poc/components/PageSubtitleComponent.vue';
|
||||
@ -144,6 +145,7 @@ import TeamTableComponent from '@poc/components/TeamTableComponent.vue';
|
||||
const analyticsStore = useAnalyticsStore();
|
||||
const pmStore = useProjectMembersStore();
|
||||
const projectsStore = useProjectsStore();
|
||||
const notify = useNotify();
|
||||
|
||||
const isLoading = ref<boolean>(false);
|
||||
const dialog = ref<boolean>(false);
|
||||
@ -167,7 +169,10 @@ async function onAddUsersClick(): Promise<void> {
|
||||
|
||||
try {
|
||||
await pmStore.inviteMembers([email.value], selectedProjectID.value);
|
||||
} catch (_) {
|
||||
notify.notify('Invites sent!');
|
||||
} catch (error) {
|
||||
error.message = `Error adding project members. ${error.message}`;
|
||||
notify.notifyError(error, AnalyticsErrorEventSource.ADD_PROJECT_MEMBER_MODAL);
|
||||
isLoading.value = false;
|
||||
return;
|
||||
}
|
||||
@ -176,7 +181,10 @@ async function onAddUsersClick(): Promise<void> {
|
||||
|
||||
try {
|
||||
await pmStore.getProjectMembers(1, selectedProjectID.value);
|
||||
} catch (error) { /* empty */ }
|
||||
} catch (error) {
|
||||
error.message = `Unable to fetch project members. ${error.message}`;
|
||||
notify.notifyError(error, AnalyticsErrorEventSource.ADD_PROJECT_MEMBER_MODAL);
|
||||
}
|
||||
|
||||
dialog.value = false;
|
||||
isLoading.value = false;
|
||||
|
Loading…
Reference in New Issue
Block a user