forked from jsnbuchanan/crowd-funder-for-time-pwa
add projectLink to onboarding meeting, plus enhancements to setup usability
This commit is contained in:
@@ -296,7 +296,7 @@ export default class MembersList extends Vue {
|
|||||||
this.decryptedMembers.length === 0 ||
|
this.decryptedMembers.length === 0 ||
|
||||||
this.decryptedMembers[0].member.memberId !== this.members[0].memberId
|
this.decryptedMembers[0].member.memberId !== this.members[0].memberId
|
||||||
) {
|
) {
|
||||||
return "Your password is not the same as the organizer. Reload or have them check their password.";
|
return "Your password is not the same as the organizer. Retry or have them check their password.";
|
||||||
} else {
|
} else {
|
||||||
// the first (organizer) member was decrypted OK
|
// the first (organizer) member was decrypted OK
|
||||||
return "";
|
return "";
|
||||||
@@ -337,7 +337,7 @@ export default class MembersList extends Vue {
|
|||||||
group: "alert",
|
group: "alert",
|
||||||
type: "info",
|
type: "info",
|
||||||
title: "Contact Exists",
|
title: "Contact Exists",
|
||||||
text: "They are in your contacts. If you want to remove them, you must do that from the contacts screen.",
|
text: "They are in your contacts. To remove them, use the contacts page.",
|
||||||
},
|
},
|
||||||
10000,
|
10000,
|
||||||
);
|
);
|
||||||
@@ -347,7 +347,7 @@ export default class MembersList extends Vue {
|
|||||||
group: "alert",
|
group: "alert",
|
||||||
type: "info",
|
type: "info",
|
||||||
title: "Contact Available",
|
title: "Contact Available",
|
||||||
text: "This is to add them to your contacts. If you want to remove them later, you must do that from the contacts screen.",
|
text: "This is to add them to your contacts. To remove them later, use the contacts page.",
|
||||||
},
|
},
|
||||||
10000,
|
10000,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -54,17 +54,12 @@
|
|||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="flex items-center bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-1 mr-1 rounded-md"
|
class="flex items-center bg-gradient-to-b from-green-400 to-green-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-1 mr-1 rounded-md"
|
||||||
>
|
>
|
||||||
<font-awesome
|
<font-awesome
|
||||||
icon="chair"
|
icon="chair"
|
||||||
class="fa-fw text-2xl"
|
class="fa-fw text-2xl"
|
||||||
@click="
|
@click="this.$router.push({ name: 'onboard-meeting-list' })"
|
||||||
warning(
|
|
||||||
'You must get registered before you can initiate an onboarding meeting.',
|
|
||||||
'Not Registered',
|
|
||||||
)
|
|
||||||
"
|
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -28,6 +28,16 @@
|
|||||||
|
|
||||||
<!-- Members List -->
|
<!-- Members List -->
|
||||||
<MembersList v-else :password="password" @error="handleError" />
|
<MembersList v-else :password="password" @error="handleError" />
|
||||||
|
|
||||||
|
<!-- Project Link Section -->
|
||||||
|
<div v-if="projectLink" class="mt-8 p-4 border rounded-lg bg-white shadow">
|
||||||
|
<router-link
|
||||||
|
:to="'/project/' + encodeURIComponent(projectLink)"
|
||||||
|
class="text-blue-600 hover:text-blue-800 transition-colors duration-200"
|
||||||
|
>
|
||||||
|
Go To Project Page
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<UserNameDialog
|
<UserNameDialog
|
||||||
@@ -69,6 +79,7 @@ export default class OnboardMeetingMembersView extends Vue {
|
|||||||
firstName = "";
|
firstName = "";
|
||||||
isRegistered = false;
|
isRegistered = false;
|
||||||
isLoading = true;
|
isLoading = true;
|
||||||
|
projectLink = "";
|
||||||
$route!: RouteLocationNormalizedLoaded;
|
$route!: RouteLocationNormalizedLoaded;
|
||||||
$router!: Router;
|
$router!: Router;
|
||||||
|
|
||||||
@@ -85,10 +96,12 @@ export default class OnboardMeetingMembersView extends Vue {
|
|||||||
async created() {
|
async created() {
|
||||||
if (!this.groupId) {
|
if (!this.groupId) {
|
||||||
this.errorMessage = "The group info is missing. Go back and try again.";
|
this.errorMessage = "The group info is missing. Go back and try again.";
|
||||||
|
this.isLoading = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!this.password) {
|
if (!this.password) {
|
||||||
this.errorMessage = "The password is missing. Go back and try again.";
|
this.errorMessage = "The password is missing. Go back and try again.";
|
||||||
|
this.isLoading = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const settings = await retrieveSettingsForActiveAccount();
|
const settings = await retrieveSettingsForActiveAccount();
|
||||||
@@ -129,6 +142,15 @@ export default class OnboardMeetingMembersView extends Vue {
|
|||||||
// updateMemberInMeeting sets isLoading to false
|
// updateMemberInMeeting sets isLoading to false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetch the meeting details to get the project link
|
||||||
|
const meetingResponse = await this.axios.get(
|
||||||
|
`${this.apiServer}/api/partner/groupOnboard/${this.groupId}`,
|
||||||
|
{ headers }
|
||||||
|
);
|
||||||
|
if (meetingResponse.data?.data?.projectLink) {
|
||||||
|
this.projectLink = meetingResponse.data.data.projectLink;
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.errorMessage =
|
this.errorMessage =
|
||||||
serverMessageForUser(error) ||
|
serverMessageForUser(error) ||
|
||||||
|
|||||||
@@ -49,12 +49,13 @@
|
|||||||
|
|
||||||
<div v-if="currentMeeting.password" class="mt-4">
|
<div v-if="currentMeeting.password" class="mt-4">
|
||||||
<p class="text-gray-600">
|
<p class="text-gray-600">
|
||||||
Share the password with the people you want to onboard.
|
Share the password with the members. You can also send them the
|
||||||
|
"shortcut page for members" link below.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="text-red-600">
|
<div v-else class="text-red-600">
|
||||||
Your copy of the password is not saved. Edit the meeting, or delete it
|
You must reenter your password. Edit this meeting, or delete it and
|
||||||
and create a new meeting.
|
create a new meeting.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -92,7 +93,7 @@
|
|||||||
v-if="
|
v-if="
|
||||||
!isLoading &&
|
!isLoading &&
|
||||||
isInEditOrCreateMode() &&
|
isInEditOrCreateMode() &&
|
||||||
newOrUpdatedMeeting != null /* duplicate check is for typechecks */
|
newOrUpdatedMeetingInputs != null /* duplicate check is for typechecks */
|
||||||
"
|
"
|
||||||
class="mt-8"
|
class="mt-8"
|
||||||
>
|
>
|
||||||
@@ -115,7 +116,7 @@
|
|||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
id="meetingName"
|
id="meetingName"
|
||||||
v-model="newOrUpdatedMeeting.name"
|
v-model="newOrUpdatedMeetingInputs.name"
|
||||||
type="text"
|
type="text"
|
||||||
required
|
required
|
||||||
class="mt-1 block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-blue-500 focus:outline-none"
|
class="mt-1 block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-blue-500 focus:outline-none"
|
||||||
@@ -131,7 +132,7 @@
|
|||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
id="expirationTime"
|
id="expirationTime"
|
||||||
v-model="newOrUpdatedMeeting.expiresAt"
|
v-model="newOrUpdatedMeetingInputs.expiresAt"
|
||||||
type="datetime-local"
|
type="datetime-local"
|
||||||
required
|
required
|
||||||
:min="minDateTime"
|
:min="minDateTime"
|
||||||
@@ -145,7 +146,7 @@
|
|||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
id="password"
|
id="password"
|
||||||
v-model="newOrUpdatedMeeting.password"
|
v-model="newOrUpdatedMeetingInputs.password"
|
||||||
type="text"
|
type="text"
|
||||||
required
|
required
|
||||||
class="mt-1 block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-blue-500 focus:outline-none"
|
class="mt-1 block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-blue-500 focus:outline-none"
|
||||||
@@ -159,7 +160,7 @@
|
|||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
id="userName"
|
id="userName"
|
||||||
v-model="newOrUpdatedMeeting.userFullName"
|
v-model="newOrUpdatedMeetingInputs.userFullName"
|
||||||
type="text"
|
type="text"
|
||||||
required
|
required
|
||||||
class="mt-1 block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-blue-500 focus:outline-none"
|
class="mt-1 block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-blue-500 focus:outline-none"
|
||||||
@@ -167,6 +168,19 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label for="projectLink" class="block text-sm font-medium text-gray-700"
|
||||||
|
>Project Link</label
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
id="projectLink"
|
||||||
|
v-model="newOrUpdatedMeetingInputs.projectLink"
|
||||||
|
type="text"
|
||||||
|
class="mt-1 block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-blue-500 focus:outline-none"
|
||||||
|
placeholder="Project ID"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
class="w-full bg-gradient-to-b from-green-400 to-green-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-4 py-2 rounded-md hover:from-green-500 hover:to-green-800"
|
class="w-full bg-gradient-to-b from-green-400 to-green-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-4 py-2 rounded-md hover:from-green-500 hover:to-green-800"
|
||||||
@@ -201,15 +215,25 @@
|
|||||||
<div class="flex items-center justify-between mb-4">
|
<div class="flex items-center justify-between mb-4">
|
||||||
<h2 class="text-2xl">Meeting Members</h2>
|
<h2 class="text-2xl">Meeting Members</h2>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
class="flex items-center gap-2 cursor-pointer text-blue-600"
|
||||||
|
@click="copyMembersLinkToClipboard"
|
||||||
|
title="Click to copy link for members"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
• Page for Members
|
||||||
|
<font-awesome icon="link" />
|
||||||
|
</span>
|
||||||
<router-link
|
<router-link
|
||||||
v-if="!!currentMeeting.password"
|
v-if="!!currentMeeting.password"
|
||||||
:to="onboardMeetingMembersLink()"
|
:to="onboardMeetingMembersLink()"
|
||||||
class="inline-block text-blue-600"
|
class="inline-block text-blue-600 ml-4"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
@click.stop
|
||||||
>
|
>
|
||||||
• Open shortcut page for members
|
|
||||||
<font-awesome icon="external-link" />
|
<font-awesome icon="external-link" />
|
||||||
</router-link>
|
</router-link>
|
||||||
|
</div>
|
||||||
|
|
||||||
<MembersList
|
<MembersList
|
||||||
:password="currentMeeting.password || ''"
|
:password="currentMeeting.password || ''"
|
||||||
@@ -219,6 +243,21 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="currentMeeting?.projectLink"
|
||||||
|
class="mt-8 p-4 border rounded-lg bg-white shadow"
|
||||||
|
>
|
||||||
|
<!-- Project Link Section -->
|
||||||
|
<div>
|
||||||
|
<router-link
|
||||||
|
:to="'/project/' + encodeURIComponent(currentMeeting.projectLink)"
|
||||||
|
class="text-blue-600 hover:text-blue-800 transition-colors duration-200"
|
||||||
|
>
|
||||||
|
Go To Project Page
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div v-else-if="isLoading">
|
<div v-else-if="isLoading">
|
||||||
<div class="flex justify-center items-center h-full">
|
<div class="flex justify-center items-center h-full">
|
||||||
<font-awesome icon="spinner" class="fa-spin-pulse" />
|
<font-awesome icon="spinner" class="fa-spin-pulse" />
|
||||||
@@ -229,6 +268,8 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Vue } from "vue-facing-decorator";
|
import { Component, Vue } from "vue-facing-decorator";
|
||||||
|
import { useClipboard } from "@vueuse/core";
|
||||||
|
|
||||||
import QuickNav from "../components/QuickNav.vue";
|
import QuickNav from "../components/QuickNav.vue";
|
||||||
import TopMessage from "../components/TopMessage.vue";
|
import TopMessage from "../components/TopMessage.vue";
|
||||||
import MembersList from "../components/MembersList.vue";
|
import MembersList from "../components/MembersList.vue";
|
||||||
@@ -240,19 +281,22 @@ import {
|
|||||||
} from "../libs/endorserServer";
|
} from "../libs/endorserServer";
|
||||||
import { encryptMessage } from "../libs/crypto";
|
import { encryptMessage } from "../libs/crypto";
|
||||||
import { logger } from "../utils/logger";
|
import { logger } from "../utils/logger";
|
||||||
|
|
||||||
interface ServerMeeting {
|
interface ServerMeeting {
|
||||||
groupId: number; // from the server
|
groupId: number; // from the server
|
||||||
name: string; // from the server
|
name: string; // to & from the server
|
||||||
expiresAt: string; // from the server
|
expiresAt: string; // to & from the server
|
||||||
userFullName?: string; // from the user's session
|
userFullName?: string; // from the user's session
|
||||||
password?: string; // from the user's session
|
password?: string; // from the user's session
|
||||||
|
projectLink?: string; // to & from the server
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MeetingSetupInfo {
|
interface MeetingSetupInputs {
|
||||||
name: string;
|
name: string;
|
||||||
expiresAt: string;
|
expiresAt: string;
|
||||||
userFullName: string;
|
userFullName: string;
|
||||||
password: string;
|
password: string;
|
||||||
|
projectLink: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -269,7 +313,7 @@ export default class OnboardMeetingView extends Vue {
|
|||||||
) => void;
|
) => void;
|
||||||
|
|
||||||
currentMeeting: ServerMeeting | null = null;
|
currentMeeting: ServerMeeting | null = null;
|
||||||
newOrUpdatedMeeting: MeetingSetupInfo | null = null;
|
newOrUpdatedMeetingInputs: MeetingSetupInputs | null = null;
|
||||||
activeDid = "";
|
activeDid = "";
|
||||||
apiServer = "";
|
apiServer = "";
|
||||||
isDeleting = false;
|
isDeleting = false;
|
||||||
@@ -295,11 +339,11 @@ export default class OnboardMeetingView extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isInCreateMode(): boolean {
|
isInCreateMode(): boolean {
|
||||||
return this.newOrUpdatedMeeting != null && this.currentMeeting == null;
|
return this.newOrUpdatedMeetingInputs != null && this.currentMeeting == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
isInEditOrCreateMode(): boolean {
|
isInEditOrCreateMode(): boolean {
|
||||||
return this.newOrUpdatedMeeting != null;
|
return this.newOrUpdatedMeetingInputs != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
getDefaultExpirationTime(): string {
|
getDefaultExpirationTime(): string {
|
||||||
@@ -324,13 +368,14 @@ export default class OnboardMeetingView extends Vue {
|
|||||||
return `${year}-${month}-${day}T${hours}:${minutes}`;
|
return `${year}-${month}-${day}T${hours}:${minutes}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
blankMeeting(): MeetingSetupInfo {
|
blankMeeting(): MeetingSetupInputs {
|
||||||
return {
|
return {
|
||||||
// no groupId yet
|
// no groupId yet
|
||||||
name: "",
|
name: "",
|
||||||
expiresAt: this.getDefaultExpirationTime(),
|
expiresAt: this.getDefaultExpirationTime(),
|
||||||
userFullName: this.fullName,
|
userFullName: this.fullName,
|
||||||
password: (this.currentMeeting?.password as string) || "",
|
password: (this.currentMeeting?.password as string) || "",
|
||||||
|
projectLink: (this.currentMeeting?.projectLink as string) || "",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,19 +387,20 @@ export default class OnboardMeetingView extends Vue {
|
|||||||
{ headers },
|
{ headers },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const queryPassword = this.$route.query["password"] as string;
|
||||||
if (response?.data?.data) {
|
if (response?.data?.data) {
|
||||||
this.currentMeeting = {
|
this.currentMeeting = {
|
||||||
...response.data.data,
|
...response.data.data,
|
||||||
userFullName: this.fullName,
|
userFullName: this.fullName,
|
||||||
password: this.currentMeeting?.password || "",
|
password: this.currentMeeting?.password || queryPassword || "",
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
// no meeting found
|
// no meeting found
|
||||||
this.newOrUpdatedMeeting = this.blankMeeting();
|
this.newOrUpdatedMeetingInputs = this.blankMeeting();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// no meeting found
|
// no meeting found
|
||||||
this.newOrUpdatedMeeting = this.blankMeeting();
|
this.newOrUpdatedMeetingInputs = this.blankMeeting();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,14 +408,14 @@ export default class OnboardMeetingView extends Vue {
|
|||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!this.newOrUpdatedMeeting) {
|
if (!this.newOrUpdatedMeetingInputs) {
|
||||||
throw Error(
|
throw Error(
|
||||||
"There was no meeting data to create. We should never get here.",
|
"There was no meeting data to create. We should never get here.",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert local time to UTC for comparison and server submission
|
// Convert local time to UTC for comparison and server submission
|
||||||
const localExpiresAt = new Date(this.newOrUpdatedMeeting.expiresAt);
|
const localExpiresAt = new Date(this.newOrUpdatedMeetingInputs.expiresAt);
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
if (localExpiresAt <= now) {
|
if (localExpiresAt <= now) {
|
||||||
this.$notify(
|
this.$notify(
|
||||||
@@ -383,7 +429,7 @@ export default class OnboardMeetingView extends Vue {
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!this.newOrUpdatedMeeting.userFullName) {
|
if (!this.newOrUpdatedMeetingInputs.userFullName) {
|
||||||
this.$notify(
|
this.$notify(
|
||||||
{
|
{
|
||||||
group: "alert",
|
group: "alert",
|
||||||
@@ -395,7 +441,7 @@ export default class OnboardMeetingView extends Vue {
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!this.newOrUpdatedMeeting.password) {
|
if (!this.newOrUpdatedMeetingInputs.password) {
|
||||||
this.$notify(
|
this.$notify(
|
||||||
{
|
{
|
||||||
group: "alert",
|
group: "alert",
|
||||||
@@ -408,35 +454,36 @@ export default class OnboardMeetingView extends Vue {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create content with user's name and DID encrypted with password
|
// create content with user's name & DID encrypted with password
|
||||||
const content = {
|
const content = {
|
||||||
name: this.newOrUpdatedMeeting.userFullName,
|
name: this.newOrUpdatedMeetingInputs.userFullName,
|
||||||
did: this.activeDid,
|
did: this.activeDid,
|
||||||
isRegistered: this.isRegistered,
|
isRegistered: this.isRegistered,
|
||||||
};
|
};
|
||||||
const encryptedContent = await encryptMessage(
|
const encryptedContent = await encryptMessage(
|
||||||
JSON.stringify(content),
|
JSON.stringify(content),
|
||||||
this.newOrUpdatedMeeting.password,
|
this.newOrUpdatedMeetingInputs.password,
|
||||||
);
|
);
|
||||||
|
|
||||||
const headers = await getHeaders(this.activeDid);
|
const headers = await getHeaders(this.activeDid);
|
||||||
const response = await this.axios.post(
|
const response = await this.axios.post(
|
||||||
this.apiServer + "/api/partner/groupOnboard",
|
this.apiServer + "/api/partner/groupOnboard",
|
||||||
{
|
{
|
||||||
name: this.newOrUpdatedMeeting.name,
|
name: this.newOrUpdatedMeetingInputs.name,
|
||||||
expiresAt: localExpiresAt.toISOString(),
|
expiresAt: localExpiresAt.toISOString(),
|
||||||
content: encryptedContent,
|
content: encryptedContent,
|
||||||
|
projectLink: this.newOrUpdatedMeetingInputs.projectLink,
|
||||||
},
|
},
|
||||||
{ headers },
|
{ headers },
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.data && response.data.success) {
|
if (response.data && response.data.success) {
|
||||||
this.currentMeeting = {
|
this.currentMeeting = {
|
||||||
...this.newOrUpdatedMeeting,
|
...this.newOrUpdatedMeetingInputs,
|
||||||
groupId: response.data.success.groupId,
|
groupId: response.data.success.groupId,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.newOrUpdatedMeeting = null;
|
this.newOrUpdatedMeetingInputs = null;
|
||||||
this.$notify(
|
this.$notify(
|
||||||
{
|
{
|
||||||
group: "alert",
|
group: "alert",
|
||||||
@@ -502,7 +549,7 @@ export default class OnboardMeetingView extends Vue {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.currentMeeting = null;
|
this.currentMeeting = null;
|
||||||
this.newOrUpdatedMeeting = this.blankMeeting();
|
this.newOrUpdatedMeetingInputs = this.blankMeeting();
|
||||||
this.showDeleteConfirm = false;
|
this.showDeleteConfirm = false;
|
||||||
|
|
||||||
this.$notify(
|
this.$notify(
|
||||||
@@ -534,11 +581,12 @@ export default class OnboardMeetingView extends Vue {
|
|||||||
// Populate form with existing meeting data
|
// Populate form with existing meeting data
|
||||||
if (this.currentMeeting) {
|
if (this.currentMeeting) {
|
||||||
const localExpiresAt = new Date(this.currentMeeting.expiresAt);
|
const localExpiresAt = new Date(this.currentMeeting.expiresAt);
|
||||||
this.newOrUpdatedMeeting = {
|
this.newOrUpdatedMeetingInputs = {
|
||||||
name: this.currentMeeting.name,
|
name: this.currentMeeting.name,
|
||||||
expiresAt: this.formatDateForInput(localExpiresAt),
|
expiresAt: this.formatDateForInput(localExpiresAt),
|
||||||
userFullName: this.currentMeeting.userFullName || "",
|
userFullName: this.currentMeeting.userFullName || "",
|
||||||
password: this.currentMeeting.password || "",
|
password: this.currentMeeting.password || "",
|
||||||
|
projectLink: this.currentMeeting.projectLink || "",
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
logger.error(
|
logger.error(
|
||||||
@@ -549,18 +597,18 @@ export default class OnboardMeetingView extends Vue {
|
|||||||
|
|
||||||
cancelEditing() {
|
cancelEditing() {
|
||||||
// Reset form data
|
// Reset form data
|
||||||
this.newOrUpdatedMeeting = null;
|
this.newOrUpdatedMeetingInputs = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateMeeting() {
|
async updateMeeting() {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
if (!this.newOrUpdatedMeeting) {
|
if (!this.newOrUpdatedMeetingInputs) {
|
||||||
throw Error("There was no meeting data to update.");
|
throw Error("There was no meeting data to update.");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Convert local time to UTC for comparison and server submission
|
// Convert local time to UTC for comparison and server submission
|
||||||
const localExpiresAt = new Date(this.newOrUpdatedMeeting.expiresAt);
|
const localExpiresAt = new Date(this.newOrUpdatedMeetingInputs.expiresAt);
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
if (localExpiresAt <= now) {
|
if (localExpiresAt <= now) {
|
||||||
this.$notify(
|
this.$notify(
|
||||||
@@ -574,7 +622,7 @@ export default class OnboardMeetingView extends Vue {
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!this.newOrUpdatedMeeting.userFullName) {
|
if (!this.newOrUpdatedMeetingInputs.userFullName) {
|
||||||
this.$notify(
|
this.$notify(
|
||||||
{
|
{
|
||||||
group: "alert",
|
group: "alert",
|
||||||
@@ -586,7 +634,7 @@ export default class OnboardMeetingView extends Vue {
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!this.newOrUpdatedMeeting.password) {
|
if (!this.newOrUpdatedMeetingInputs.password) {
|
||||||
this.$notify(
|
this.$notify(
|
||||||
{
|
{
|
||||||
group: "alert",
|
group: "alert",
|
||||||
@@ -598,15 +646,15 @@ export default class OnboardMeetingView extends Vue {
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// create content with user's name and DID encrypted with password
|
// create content with user's name & DID encrypted with password
|
||||||
const content = {
|
const content = {
|
||||||
name: this.newOrUpdatedMeeting.userFullName,
|
name: this.newOrUpdatedMeetingInputs.userFullName,
|
||||||
did: this.activeDid,
|
did: this.activeDid,
|
||||||
isRegistered: this.isRegistered,
|
isRegistered: this.isRegistered,
|
||||||
};
|
};
|
||||||
const encryptedContent = await encryptMessage(
|
const encryptedContent = await encryptMessage(
|
||||||
JSON.stringify(content),
|
JSON.stringify(content),
|
||||||
this.newOrUpdatedMeeting.password,
|
this.newOrUpdatedMeetingInputs.password,
|
||||||
);
|
);
|
||||||
|
|
||||||
const headers = await getHeaders(this.activeDid);
|
const headers = await getHeaders(this.activeDid);
|
||||||
@@ -614,9 +662,10 @@ export default class OnboardMeetingView extends Vue {
|
|||||||
this.apiServer + "/api/partner/groupOnboard",
|
this.apiServer + "/api/partner/groupOnboard",
|
||||||
{
|
{
|
||||||
// the groupId is in the currentMeeting but it's not necessary while users only have one meeting
|
// the groupId is in the currentMeeting but it's not necessary while users only have one meeting
|
||||||
name: this.newOrUpdatedMeeting.name,
|
name: this.newOrUpdatedMeetingInputs.name,
|
||||||
expiresAt: localExpiresAt.toISOString(),
|
expiresAt: localExpiresAt.toISOString(),
|
||||||
content: encryptedContent,
|
content: encryptedContent,
|
||||||
|
projectLink: this.newOrUpdatedMeetingInputs.projectLink,
|
||||||
},
|
},
|
||||||
{ headers },
|
{ headers },
|
||||||
);
|
);
|
||||||
@@ -624,10 +673,17 @@ export default class OnboardMeetingView extends Vue {
|
|||||||
if (response.data && response.data.success) {
|
if (response.data && response.data.success) {
|
||||||
// Update the current meeting with only the necessary fields
|
// Update the current meeting with only the necessary fields
|
||||||
this.currentMeeting = {
|
this.currentMeeting = {
|
||||||
...this.newOrUpdatedMeeting,
|
...this.newOrUpdatedMeetingInputs,
|
||||||
groupId: (this.currentMeeting?.groupId as number) || -1,
|
groupId: (this.currentMeeting?.groupId as number) || -1,
|
||||||
};
|
};
|
||||||
this.newOrUpdatedMeeting = null;
|
this.newOrUpdatedMeetingInputs = null;
|
||||||
|
|
||||||
|
if (this.currentMeeting?.password) {
|
||||||
|
this.$router.push({
|
||||||
|
name: "onboard-meeting-setup",
|
||||||
|
query: { password: this.currentMeeting?.password },
|
||||||
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw { response: response };
|
throw { response: response };
|
||||||
}
|
}
|
||||||
@@ -673,5 +729,21 @@ export default class OnboardMeetingView extends Vue {
|
|||||||
5000,
|
5000,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
copyMembersLinkToClipboard() {
|
||||||
|
useClipboard()
|
||||||
|
.copy(this.onboardMeetingMembersLink())
|
||||||
|
.then(() => {
|
||||||
|
this.$notify(
|
||||||
|
{
|
||||||
|
group: "alert",
|
||||||
|
type: "info",
|
||||||
|
title: "Copied",
|
||||||
|
text: "The member link is copied to the clipboard.",
|
||||||
|
},
|
||||||
|
5000,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user