web/satellite/vuetify-poc: invite through all projects dashboard
This change allows project owners to invite members through the all projects dashboard. Resolves #6394 Change-Id: Id36d21432ab7b18532679e900d3e00c52fa21fc9
This commit is contained in:
parent
0cc04208db
commit
dd3779a623
@ -60,7 +60,7 @@
|
|||||||
|
|
||||||
<v-divider class="my-2" />
|
<v-divider class="my-2" />
|
||||||
|
|
||||||
<v-list-item link class="mt-1" rounded="lg">
|
<v-list-item link class="mt-1" rounded="lg" @click="emit('inviteClick')">
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<icon-team size="18" />
|
<icon-team size="18" />
|
||||||
</template>
|
</template>
|
||||||
@ -112,8 +112,9 @@ const props = defineProps<{
|
|||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
'joinClick': [];
|
joinClick: [];
|
||||||
'createClick': [];
|
createClick: [];
|
||||||
|
inviteClick: [];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const analyticsStore = useAnalyticsStore();
|
const analyticsStore = useAnalyticsStore();
|
||||||
|
@ -0,0 +1,162 @@
|
|||||||
|
// Copyright (C) 2023 Storj Labs, Inc.
|
||||||
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<v-dialog
|
||||||
|
v-model="model"
|
||||||
|
width="auto"
|
||||||
|
max-width="420px"
|
||||||
|
transition="fade-transition"
|
||||||
|
:persistent="isLoading"
|
||||||
|
>
|
||||||
|
<v-card rounded="xlg">
|
||||||
|
<v-sheet>
|
||||||
|
<v-card-item class="pl-7 py-4">
|
||||||
|
<template #prepend>
|
||||||
|
<v-card-title class="font-weight-bold">
|
||||||
|
Add Members
|
||||||
|
</v-card-title>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #append>
|
||||||
|
<v-btn
|
||||||
|
icon="$close"
|
||||||
|
variant="text"
|
||||||
|
size="small"
|
||||||
|
color="default"
|
||||||
|
:disabled="isLoading"
|
||||||
|
@click="model = false"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</v-card-item>
|
||||||
|
</v-sheet>
|
||||||
|
|
||||||
|
<v-divider />
|
||||||
|
|
||||||
|
<v-form v-model="valid" class="pa-7 pb-4" @submit.prevent="onAddUsersClick">
|
||||||
|
<v-row>
|
||||||
|
<v-col cols="12">
|
||||||
|
<p class="mb-5">Invite team members to join you in this project.</p>
|
||||||
|
<v-alert
|
||||||
|
variant="tonal"
|
||||||
|
color="info"
|
||||||
|
title="Important Information"
|
||||||
|
text="All team members should use the same passphrase to access the same data."
|
||||||
|
rounded="lg"
|
||||||
|
density="comfortable"
|
||||||
|
border
|
||||||
|
/>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12">
|
||||||
|
<v-text-field
|
||||||
|
v-model="email"
|
||||||
|
variant="outlined"
|
||||||
|
:rules="emailRules"
|
||||||
|
label="Enter e-mail"
|
||||||
|
hint="Members will have read & write permissions."
|
||||||
|
required
|
||||||
|
autofocus
|
||||||
|
class="my-2"
|
||||||
|
/>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-form>
|
||||||
|
|
||||||
|
<v-divider />
|
||||||
|
|
||||||
|
<v-card-actions class="pa-7">
|
||||||
|
<v-row>
|
||||||
|
<v-col>
|
||||||
|
<v-btn variant="outlined" color="default" block :disabled="isLoading" @click="model = false">Cancel</v-btn>
|
||||||
|
</v-col>
|
||||||
|
<v-col>
|
||||||
|
<v-btn color="primary" variant="flat" block :loading="isLoading" @click="onAddUsersClick">Send Invite</v-btn>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
|
</v-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref } from 'vue';
|
||||||
|
import {
|
||||||
|
VDialog,
|
||||||
|
VCard,
|
||||||
|
VSheet,
|
||||||
|
VCardItem,
|
||||||
|
VCardTitle,
|
||||||
|
VBtn,
|
||||||
|
VDivider,
|
||||||
|
VForm,
|
||||||
|
VRow,
|
||||||
|
VCol,
|
||||||
|
VAlert,
|
||||||
|
VTextField,
|
||||||
|
VCardActions,
|
||||||
|
} from 'vuetify/components';
|
||||||
|
|
||||||
|
import { RequiredRule, ValidationRule } from '@poc/types/common';
|
||||||
|
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||||
|
import { useAnalyticsStore } from '@/store/modules/analyticsStore';
|
||||||
|
import { useProjectMembersStore } from '@/store/modules/projectMembersStore';
|
||||||
|
import { useNotify } from '@/utils/hooks';
|
||||||
|
import { useLoading } from '@/composables/useLoading';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
modelValue: boolean,
|
||||||
|
projectId: string,
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
'update:modelValue': [value: boolean],
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const model = computed<boolean>({
|
||||||
|
get: () => props.modelValue,
|
||||||
|
set: value => emit('update:modelValue', value),
|
||||||
|
});
|
||||||
|
|
||||||
|
const analyticsStore = useAnalyticsStore();
|
||||||
|
const pmStore = useProjectMembersStore();
|
||||||
|
const notify = useNotify();
|
||||||
|
const { isLoading, withLoading } = useLoading();
|
||||||
|
|
||||||
|
const valid = ref<boolean>(false);
|
||||||
|
const email = ref<string>('');
|
||||||
|
|
||||||
|
const emailRules: ValidationRule<string>[] = [
|
||||||
|
RequiredRule,
|
||||||
|
v => ((/.+@.+\..+/.test(v)) || 'E-mail must be valid.'),
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a project invitation to the input email.
|
||||||
|
*/
|
||||||
|
async function onAddUsersClick(): Promise<void> {
|
||||||
|
if (!valid.value) return;
|
||||||
|
|
||||||
|
await withLoading(async () => {
|
||||||
|
try {
|
||||||
|
await pmStore.inviteMembers([email.value], props.projectId);
|
||||||
|
notify.notify('Invites sent!');
|
||||||
|
email.value = '';
|
||||||
|
} catch (error) {
|
||||||
|
error.message = `Error adding project members. ${error.message}`;
|
||||||
|
notify.notifyError(error, AnalyticsErrorEventSource.ADD_PROJECT_MEMBER_MODAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
analyticsStore.eventTriggered(AnalyticsEvent.PROJECT_MEMBERS_INVITE_SENT);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await pmStore.getProjectMembers(1, props.projectId);
|
||||||
|
} catch (error) {
|
||||||
|
error.message = `Unable to fetch project members. ${error.message}`;
|
||||||
|
notify.notifyError(error, AnalyticsErrorEventSource.ADD_PROJECT_MEMBER_MODAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
model.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
@ -91,7 +91,7 @@
|
|||||||
<ProjectCard class="h-100" @create-click="isCreateProjectDialogShown = true" />
|
<ProjectCard class="h-100" @create-click="isCreateProjectDialogShown = true" />
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col v-for="item in items" v-else :key="item.id" cols="12" sm="6" md="4" lg="3">
|
<v-col v-for="item in items" v-else :key="item.id" cols="12" sm="6" md="4" lg="3">
|
||||||
<ProjectCard :item="item" class="h-100" @join-click="onJoinClicked(item)" />
|
<ProjectCard :item="item" class="h-100" @join-click="onJoinClicked(item)" @invite-click="onInviteClicked(item)" />
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
</v-container>
|
</v-container>
|
||||||
@ -103,6 +103,7 @@
|
|||||||
:name="joiningItem.name"
|
:name="joiningItem.name"
|
||||||
/>
|
/>
|
||||||
<create-project-dialog v-model="isCreateProjectDialogShown" />
|
<create-project-dialog v-model="isCreateProjectDialogShown" />
|
||||||
|
<add-team-member-dialog v-model="isAddMemberDialogShown" :project-id="addMemberProjectId" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@ -112,15 +113,6 @@ import {
|
|||||||
VRow,
|
VRow,
|
||||||
VCol,
|
VCol,
|
||||||
VBtn,
|
VBtn,
|
||||||
VDialog,
|
|
||||||
VCard,
|
|
||||||
VSheet,
|
|
||||||
VCardItem,
|
|
||||||
VCardTitle,
|
|
||||||
VDivider,
|
|
||||||
VForm,
|
|
||||||
VTextField,
|
|
||||||
VCardActions,
|
|
||||||
VSpacer,
|
VSpacer,
|
||||||
VBtnToggle,
|
VBtnToggle,
|
||||||
VProgressCircular,
|
VProgressCircular,
|
||||||
@ -137,24 +129,19 @@ import PageTitleComponent from '@poc/components/PageTitleComponent.vue';
|
|||||||
import ProjectsTableComponent from '@poc/components/ProjectsTableComponent.vue';
|
import ProjectsTableComponent from '@poc/components/ProjectsTableComponent.vue';
|
||||||
import JoinProjectDialog from '@poc/components/dialogs/JoinProjectDialog.vue';
|
import JoinProjectDialog from '@poc/components/dialogs/JoinProjectDialog.vue';
|
||||||
import CreateProjectDialog from '@poc/components/dialogs/CreateProjectDialog.vue';
|
import CreateProjectDialog from '@poc/components/dialogs/CreateProjectDialog.vue';
|
||||||
|
import AddTeamMemberDialog from '@poc/components/dialogs/AddTeamMemberDialog.vue';
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const projectsStore = useProjectsStore();
|
const projectsStore = useProjectsStore();
|
||||||
const usersStore = useUsersStore();
|
const usersStore = useUsersStore();
|
||||||
|
|
||||||
const dialog = ref<boolean>(false);
|
|
||||||
const valid = ref<boolean>(false);
|
|
||||||
const name = ref<string>('');
|
|
||||||
const isLoading = ref<boolean>(true);
|
const isLoading = ref<boolean>(true);
|
||||||
|
|
||||||
const joiningItem = ref<ProjectItemModel | null>(null);
|
const joiningItem = ref<ProjectItemModel | null>(null);
|
||||||
const isJoinProjectDialogShown = ref<boolean>(false);
|
const isJoinProjectDialogShown = ref<boolean>(false);
|
||||||
const isCreateProjectDialogShown = ref<boolean>(false);
|
const isCreateProjectDialogShown = ref<boolean>(false);
|
||||||
|
const addMemberProjectId = ref<string>('');
|
||||||
const nameRules = [
|
const isAddMemberDialogShown = ref<boolean>(false);
|
||||||
value => (!!value || 'Project name is required.'),
|
|
||||||
value => ((value?.length <= 100) || 'Name must be less than 100 characters.'),
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether to use the table view.
|
* Returns whether to use the table view.
|
||||||
@ -207,6 +194,14 @@ function onJoinClicked(item: ProjectItemModel): void {
|
|||||||
isJoinProjectDialogShown.value = true;
|
isJoinProjectDialogShown.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the Add Members dialog.
|
||||||
|
*/
|
||||||
|
function onInviteClicked(item: ProjectItemModel): void {
|
||||||
|
addMemberProjectId.value = item.id;
|
||||||
|
isAddMemberDialogShown.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(async (): Promise<void> => {
|
onMounted(async (): Promise<void> => {
|
||||||
await usersStore.getUser().catch(_ => {});
|
await usersStore.getUser().catch(_ => {});
|
||||||
await projectsStore.getProjects().catch(_ => {});
|
await projectsStore.getProjects().catch(_ => {});
|
||||||
|
@ -11,97 +11,11 @@
|
|||||||
|
|
||||||
<v-col class="pb-0">
|
<v-col class="pb-0">
|
||||||
<v-row class="mt-2 mb-0">
|
<v-row class="mt-2 mb-0">
|
||||||
<v-btn>
|
<v-btn @click="isAddMemberDialogShown = true">
|
||||||
<svg width="16" height="16" class="mr-2" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="16" height="16" class="mr-2" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M10 1C14.9706 1 19 5.02944 19 10C19 14.9706 14.9706 19 10 19C5.02944 19 1 14.9706 1 10C1 5.02944 5.02944 1 10 1ZM10 2.65C5.94071 2.65 2.65 5.94071 2.65 10C2.65 14.0593 5.94071 17.35 10 17.35C14.0593 17.35 17.35 14.0593 17.35 10C17.35 5.94071 14.0593 2.65 10 2.65ZM10.7496 6.8989L10.7499 6.91218L10.7499 9.223H12.9926C13.4529 9.223 13.8302 9.58799 13.8456 10.048C13.8602 10.4887 13.5148 10.8579 13.0741 10.8726L13.0608 10.8729L10.7499 10.873L10.75 13.171C10.75 13.6266 10.3806 13.996 9.925 13.996C9.48048 13.996 9.11807 13.6444 9.10066 13.2042L9.1 13.171L9.09985 10.873H6.802C6.34637 10.873 5.977 10.5036 5.977 10.048C5.977 9.60348 6.32857 9.24107 6.76882 9.22366L6.802 9.223H9.09985L9.1 6.98036C9.1 6.5201 9.46499 6.14276 9.925 6.12745C10.3657 6.11279 10.7349 6.45818 10.7496 6.8989Z" fill="currentColor" />
|
<path d="M10 1C14.9706 1 19 5.02944 19 10C19 14.9706 14.9706 19 10 19C5.02944 19 1 14.9706 1 10C1 5.02944 5.02944 1 10 1ZM10 2.65C5.94071 2.65 2.65 5.94071 2.65 10C2.65 14.0593 5.94071 17.35 10 17.35C14.0593 17.35 17.35 14.0593 17.35 10C17.35 5.94071 14.0593 2.65 10 2.65ZM10.7496 6.8989L10.7499 6.91218L10.7499 9.223H12.9926C13.4529 9.223 13.8302 9.58799 13.8456 10.048C13.8602 10.4887 13.5148 10.8579 13.0741 10.8726L13.0608 10.8729L10.7499 10.873L10.75 13.171C10.75 13.6266 10.3806 13.996 9.925 13.996C9.48048 13.996 9.11807 13.6444 9.10066 13.2042L9.1 13.171L9.09985 10.873H6.802C6.34637 10.873 5.977 10.5036 5.977 10.048C5.977 9.60348 6.32857 9.24107 6.76882 9.22366L6.802 9.223H9.09985L9.1 6.98036C9.1 6.5201 9.46499 6.14276 9.925 6.12745C10.3657 6.11279 10.7349 6.45818 10.7496 6.8989Z" fill="currentColor" />
|
||||||
</svg>
|
</svg>
|
||||||
Add Members
|
Add Members
|
||||||
|
|
||||||
<v-dialog
|
|
||||||
v-model="dialog"
|
|
||||||
activator="parent"
|
|
||||||
width="auto"
|
|
||||||
max-width="420px"
|
|
||||||
transition="fade-transition"
|
|
||||||
>
|
|
||||||
<v-card rounded="xlg">
|
|
||||||
<v-sheet>
|
|
||||||
<v-card-item class="pl-7 py-4">
|
|
||||||
<template #prepend>
|
|
||||||
<v-card-title class="font-weight-bold">
|
|
||||||
<!-- <v-icon>
|
|
||||||
<img src="../assets/icon-team.svg" alt="Team">
|
|
||||||
</v-icon> -->
|
|
||||||
Add Members
|
|
||||||
</v-card-title>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- <v-btn
|
|
||||||
class="text-none text-subtitle-1"
|
|
||||||
color="#5865f2"
|
|
||||||
size="small"
|
|
||||||
variant="flat"
|
|
||||||
>
|
|
||||||
+ Add More
|
|
||||||
</v-btn> -->
|
|
||||||
|
|
||||||
<template #append>
|
|
||||||
<v-btn
|
|
||||||
icon="$close"
|
|
||||||
variant="text"
|
|
||||||
size="small"
|
|
||||||
color="default"
|
|
||||||
@click="dialog = false"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</v-card-item>
|
|
||||||
</v-sheet>
|
|
||||||
|
|
||||||
<v-divider />
|
|
||||||
|
|
||||||
<v-form v-model="valid" class="pa-7 pb-4" @submit.prevent="onAddUsersClick">
|
|
||||||
<v-row>
|
|
||||||
<v-col cols="12">
|
|
||||||
<p class="mb-5">Invite team members to join you in this project.</p>
|
|
||||||
<v-alert
|
|
||||||
variant="tonal"
|
|
||||||
color="info"
|
|
||||||
title="Important Information"
|
|
||||||
text="All team members should use the same passphrase to access the same data."
|
|
||||||
rounded="lg"
|
|
||||||
density="comfortable"
|
|
||||||
border
|
|
||||||
/>
|
|
||||||
</v-col>
|
|
||||||
<v-col cols="12">
|
|
||||||
<v-text-field
|
|
||||||
v-model="email"
|
|
||||||
variant="outlined"
|
|
||||||
:rules="emailRules"
|
|
||||||
label="Enter e-mail"
|
|
||||||
hint="Members will have read & write permissions."
|
|
||||||
required
|
|
||||||
autofocus
|
|
||||||
class="my-2"
|
|
||||||
/>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
</v-form>
|
|
||||||
|
|
||||||
<v-divider />
|
|
||||||
|
|
||||||
<v-card-actions class="pa-7">
|
|
||||||
<v-row>
|
|
||||||
<v-col>
|
|
||||||
<v-btn variant="outlined" color="default" block @click="dialog = false">Cancel</v-btn>
|
|
||||||
</v-col>
|
|
||||||
<v-col>
|
|
||||||
<v-btn color="primary" variant="flat" block :loading="isLoading" @click="onAddUsersClick">Send Invite</v-btn>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
</v-card-actions>
|
|
||||||
</v-card>
|
|
||||||
</v-dialog>
|
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn
|
<v-btn
|
||||||
v-if="selectedMembers.length"
|
v-if="selectedMembers.length"
|
||||||
@ -118,92 +32,33 @@
|
|||||||
|
|
||||||
<TeamTableComponent ref="tableComponent" v-model="selectedMembers" />
|
<TeamTableComponent ref="tableComponent" v-model="selectedMembers" />
|
||||||
</v-container>
|
</v-container>
|
||||||
|
|
||||||
|
<add-team-member-dialog v-model="isAddMemberDialogShown" :project-id="selectedProjectID" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import {
|
import { VContainer, VCol, VRow, VBtn } from 'vuetify/components';
|
||||||
VContainer,
|
|
||||||
VCol,
|
|
||||||
VRow,
|
|
||||||
VBtn,
|
|
||||||
VDialog,
|
|
||||||
VCard,
|
|
||||||
VSheet,
|
|
||||||
VCardItem,
|
|
||||||
VCardTitle,
|
|
||||||
VDivider,
|
|
||||||
VForm,
|
|
||||||
VCardActions,
|
|
||||||
VTextField,
|
|
||||||
VAlert,
|
|
||||||
} from 'vuetify/components';
|
|
||||||
|
|
||||||
import { useProjectMembersStore } from '@/store/modules/projectMembersStore';
|
|
||||||
import { useProjectsStore } from '@/store/modules/projectsStore';
|
import { useProjectsStore } from '@/store/modules/projectsStore';
|
||||||
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 PageTitleComponent from '@poc/components/PageTitleComponent.vue';
|
||||||
import PageSubtitleComponent from '@poc/components/PageSubtitleComponent.vue';
|
import PageSubtitleComponent from '@poc/components/PageSubtitleComponent.vue';
|
||||||
import TeamTableComponent from '@poc/components/TeamTableComponent.vue';
|
import TeamTableComponent from '@poc/components/TeamTableComponent.vue';
|
||||||
|
import AddTeamMemberDialog from '@poc/components/dialogs/AddTeamMemberDialog.vue';
|
||||||
|
|
||||||
interface DeleteDialog {
|
interface DeleteDialog {
|
||||||
showDeleteDialog(): void;
|
showDeleteDialog(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const analyticsStore = useAnalyticsStore();
|
|
||||||
const pmStore = useProjectMembersStore();
|
|
||||||
const projectsStore = useProjectsStore();
|
const projectsStore = useProjectsStore();
|
||||||
const notify = useNotify();
|
|
||||||
|
|
||||||
const isLoading = ref<boolean>(false);
|
|
||||||
const dialog = ref<boolean>(false);
|
|
||||||
const valid = ref<boolean>(false);
|
|
||||||
const email = ref<string>('');
|
|
||||||
const selectedMembers = ref<string[]>([]);
|
const selectedMembers = ref<string[]>([]);
|
||||||
const tableComponent = ref<InstanceType<typeof TeamTableComponent> & DeleteDialog>();
|
const tableComponent = ref<InstanceType<typeof TeamTableComponent> & DeleteDialog>();
|
||||||
|
const isAddMemberDialogShown = ref<boolean>(false);
|
||||||
const emailRules = [
|
|
||||||
(value: string): string | boolean => (!!value || 'E-mail is requred.'),
|
|
||||||
(value: string): string | boolean => ((/.+@.+\..+/.test(value)) || 'E-mail must be valid.'),
|
|
||||||
];
|
|
||||||
|
|
||||||
const selectedProjectID = computed((): string => projectsStore.state.selectedProject.id);
|
const selectedProjectID = computed((): string => projectsStore.state.selectedProject.id);
|
||||||
|
|
||||||
/**
|
|
||||||
* Tries to add users related to entered emails list to current project.
|
|
||||||
*/
|
|
||||||
async function onAddUsersClick(): Promise<void> {
|
|
||||||
if (isLoading.value || !valid.value) return;
|
|
||||||
|
|
||||||
isLoading.value = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
await pmStore.inviteMembers([email.value], selectedProjectID.value);
|
|
||||||
notify.notify('Invites sent!');
|
|
||||||
email.value = '';
|
|
||||||
} catch (error) {
|
|
||||||
error.message = `Error adding project members. ${error.message}`;
|
|
||||||
notify.notifyError(error, AnalyticsErrorEventSource.ADD_PROJECT_MEMBER_MODAL);
|
|
||||||
isLoading.value = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
analyticsStore.eventTriggered(AnalyticsEvent.PROJECT_MEMBERS_INVITE_SENT);
|
|
||||||
|
|
||||||
try {
|
|
||||||
await pmStore.getProjectMembers(1, selectedProjectID.value);
|
|
||||||
} 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes delete project members dialog visible.
|
* Makes delete project members dialog visible.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user