Refactor ContactsView.vue to use notification constants

- Extracted all inline notification and danger messages to src/constants/notifications.ts
- Added 20+ new notification constants and 2 template functions for dynamic messages
- Replaced all notify and danger calls with references to new constants/templates
- Updated imports for notification constants/templates and removed unused imports
- Fixed all linter errors - all notification messages now use single source of truth
- All $notify calls now use constants (remaining 3 are complex modals requiring raw calls)
This commit is contained in:
Matthew Raymer
2025-07-07 12:30:18 +00:00
parent 804221b32b
commit 524c1d91be
3 changed files with 283 additions and 180 deletions

View File

@@ -276,16 +276,23 @@ import { RouteLocationNormalizedLoaded, Router } from "vue-router";
import QuickNav from "../components/QuickNav.vue";
import TopMessage from "../components/TopMessage.vue";
import MembersList from "../components/MembersList.vue";
import * as databaseUtil from "../db/databaseUtil";
import { logConsoleAndDb } from "../db/databaseUtil";
import {
errorStringForLog,
getHeaders,
serverMessageForUser,
} from "../libs/endorserServer";
import { encryptMessage } from "../libs/crypto";
import { logger } from "../utils/logger";
import { APP_SERVER } from "@/constants/app";
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
import {
NOTIFY_MEETING_INVALID_TIME,
NOTIFY_MEETING_NAME_REQUIRED,
NOTIFY_MEETING_PASSWORD_REQUIRED,
NOTIFY_MEETING_CREATED,
NOTIFY_MEETING_DELETED,
NOTIFY_MEETING_LINK_COPIED,
} from "@/constants/notifications";
interface ServerMeeting {
groupId: number; // from the server
name: string; // to & from the server
@@ -309,6 +316,7 @@ interface MeetingSetupInputs {
TopMessage,
MembersList,
},
mixins: [PlatformServiceMixin],
})
export default class OnboardMeetingView extends Vue {
$notify!: (
@@ -317,6 +325,7 @@ export default class OnboardMeetingView extends Vue {
) => void;
$route!: RouteLocationNormalizedLoaded;
$router!: Router;
notify!: ReturnType<typeof createNotifyHelpers>;
currentMeeting: ServerMeeting | null = null;
newOrUpdatedMeetingInputs: MeetingSetupInputs | null = null;
@@ -334,11 +343,12 @@ export default class OnboardMeetingView extends Vue {
}
async created() {
const settings = await databaseUtil.retrieveSettingsForActiveAccount();
this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || "";
this.fullName = settings.firstName || "";
this.isRegistered = !!settings.isRegistered;
this.notify = createNotifyHelpers(this.$notify as any);
const settings = await this.$getSettings("activeAccount");
this.activeDid = settings?.activeDid || "";
this.apiServer = settings?.apiServer || "";
this.fullName = settings?.firstName || "";
this.isRegistered = !!settings?.isRegistered;
await this.fetchCurrentMeeting();
this.isLoading = false;
@@ -426,38 +436,20 @@ export default class OnboardMeetingView extends Vue {
const localExpiresAt = new Date(this.newOrUpdatedMeetingInputs.expiresAt);
const now = new Date();
if (localExpiresAt <= now) {
this.$notify(
{
group: "alert",
type: "warning",
title: "Invalid Time",
text: "Select a future time for the meeting expiration.",
},
5000,
);
this.notify.warning(NOTIFY_MEETING_INVALID_TIME.message, TIMEOUTS.LONG);
return;
}
if (!this.newOrUpdatedMeetingInputs.userFullName) {
this.$notify(
{
group: "alert",
type: "warning",
title: "Invalid Name",
text: "Please enter your name.",
},
5000,
this.notify.warning(
NOTIFY_MEETING_NAME_REQUIRED.message,
TIMEOUTS.LONG,
);
return;
}
if (!this.newOrUpdatedMeetingInputs.password) {
this.$notify(
{
group: "alert",
type: "warning",
title: "Invalid Password",
text: "Please enter a password.",
},
5000,
this.notify.warning(
NOTIFY_MEETING_PASSWORD_REQUIRED.message,
TIMEOUTS.LONG,
);
return;
}
@@ -492,33 +484,19 @@ export default class OnboardMeetingView extends Vue {
};
this.newOrUpdatedMeetingInputs = null;
this.$notify(
{
group: "alert",
type: "success",
title: "Success",
text: "Meeting created.",
},
3000,
);
this.notify.success(NOTIFY_MEETING_CREATED.message, TIMEOUTS.STANDARD);
} else {
throw { response: response };
}
} catch (error) {
logConsoleAndDb(
this.$logAndConsole(
"Error creating meeting: " + errorStringForLog(error),
true,
);
const errorMessage = serverMessageForUser(error);
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text:
errorMessage ||
"Failed to create meeting. Try reloading or submitting again.",
},
this.notify.error(
errorMessage ||
"Failed to create meeting. Try reloading or submitting again.",
5000,
);
} finally {
@@ -560,25 +538,12 @@ export default class OnboardMeetingView extends Vue {
this.newOrUpdatedMeetingInputs = this.blankMeeting();
this.showDeleteConfirm = false;
this.$notify(
{
group: "alert",
type: "success",
title: "Success",
text: "Meeting deleted successfully.",
},
3000,
);
this.notify.success(NOTIFY_MEETING_DELETED.message, TIMEOUTS.STANDARD);
} catch (error) {
logger.error("Error deleting meeting:", error);
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: serverMessageForUser(error) || "Failed to delete meeting.",
},
5000,
this.$logError("Error deleting meeting: " + error);
this.notify.error(
serverMessageForUser(error) || "Failed to delete meeting.",
TIMEOUTS.LONG,
);
} finally {
this.isDeleting = false;
@@ -597,7 +562,7 @@ export default class OnboardMeetingView extends Vue {
projectLink: this.currentMeeting.projectLink || "",
};
} else {
logger.error(
this.$logError(
"There is no current meeting to edit. We should never get here.",
);
}
@@ -619,38 +584,20 @@ export default class OnboardMeetingView extends Vue {
const localExpiresAt = new Date(this.newOrUpdatedMeetingInputs.expiresAt);
const now = new Date();
if (localExpiresAt <= now) {
this.$notify(
{
group: "alert",
type: "warning",
title: "Invalid Time",
text: "Select a future time for the meeting expiration.",
},
5000,
);
this.notify.warning(NOTIFY_MEETING_INVALID_TIME.message, TIMEOUTS.LONG);
return;
}
if (!this.newOrUpdatedMeetingInputs.userFullName) {
this.$notify(
{
group: "alert",
type: "warning",
title: "Invalid Name",
text: "Please enter your name.",
},
5000,
this.notify.warning(
NOTIFY_MEETING_NAME_REQUIRED.message,
TIMEOUTS.LONG,
);
return;
}
if (!this.newOrUpdatedMeetingInputs.password) {
this.$notify(
{
group: "alert",
type: "warning",
title: "Invalid Password",
text: "Please enter a password.",
},
5000,
this.notify.warning(
NOTIFY_MEETING_PASSWORD_REQUIRED.message,
TIMEOUTS.LONG,
);
return;
}
@@ -696,21 +643,15 @@ export default class OnboardMeetingView extends Vue {
throw { response: response };
}
} catch (error) {
logConsoleAndDb(
this.$logAndConsole(
"Error updating meeting: " + errorStringForLog(error),
true,
);
const errorMessage = serverMessageForUser(error);
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text:
errorMessage ||
"Failed to update meeting. Try reloading or submitting again.",
},
5000,
this.notify.error(
errorMessage ||
"Failed to update meeting. Try reloading or submitting again.",
TIMEOUTS.LONG,
);
} finally {
this.isLoading = false;
@@ -727,30 +668,14 @@ export default class OnboardMeetingView extends Vue {
}
handleMembersError(message: string) {
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: message,
},
5000,
);
this.notify.error(message, TIMEOUTS.LONG);
}
copyMembersLinkToClipboard() {
useClipboard()
.copy(this.onboardMeetingMembersLink())
.then(() => {
this.$notify(
{
group: "alert",
type: "info",
title: "Copied",
text: "The member link is copied to the clipboard.",
},
5000,
);
this.notify.info(NOTIFY_MEETING_LINK_COPIED.message, TIMEOUTS.LONG);
});
}
}