fix: notification dashboard issues (#3624)
* refactor: Notification helper refactor, fixes a lot of issues. * fix: lint issues
This commit is contained in:
parent
e4adbb9469
commit
6d57da2053
@ -335,7 +335,7 @@ import ThreadSummary from "~/components/ui/thread/ThreadSummary.vue";
|
|||||||
import { getProjectLink, getVersionLink } from "~/helpers/projects.js";
|
import { getProjectLink, getVersionLink } from "~/helpers/projects.js";
|
||||||
import { getUserLink } from "~/helpers/users.js";
|
import { getUserLink } from "~/helpers/users.js";
|
||||||
import { acceptTeamInvite, removeSelfFromTeam } from "~/helpers/teams.js";
|
import { acceptTeamInvite, removeSelfFromTeam } from "~/helpers/teams.js";
|
||||||
import { markAsRead } from "~/helpers/notifications.js";
|
import { markAsRead } from "~/helpers/notifications.ts";
|
||||||
import DoubleIcon from "~/components/ui/DoubleIcon.vue";
|
import DoubleIcon from "~/components/ui/DoubleIcon.vue";
|
||||||
import Avatar from "~/components/ui/Avatar.vue";
|
import Avatar from "~/components/ui/Avatar.vue";
|
||||||
import Badge from "~/components/ui/Badge.vue";
|
import Badge from "~/components/ui/Badge.vue";
|
||||||
|
|||||||
@ -1,170 +0,0 @@
|
|||||||
import { useNuxtApp } from "#imports";
|
|
||||||
|
|
||||||
async function getBulk(type, ids, apiVersion = 2) {
|
|
||||||
if (ids.length === 0) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
const url = `${type}?ids=${encodeURIComponent(JSON.stringify([...new Set(ids)]))}`;
|
|
||||||
return await useBaseFetch(url, { apiVersion });
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function fetchExtraNotificationData(notifications) {
|
|
||||||
const bulk = {
|
|
||||||
projects: [],
|
|
||||||
reports: [],
|
|
||||||
threads: [],
|
|
||||||
users: [],
|
|
||||||
versions: [],
|
|
||||||
organizations: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const notification of notifications) {
|
|
||||||
if (notification.body) {
|
|
||||||
if (notification.body.project_id) {
|
|
||||||
bulk.projects.push(notification.body.project_id);
|
|
||||||
}
|
|
||||||
if (notification.body.version_id) {
|
|
||||||
bulk.versions.push(notification.body.version_id);
|
|
||||||
}
|
|
||||||
if (notification.body.report_id) {
|
|
||||||
bulk.reports.push(notification.body.report_id);
|
|
||||||
}
|
|
||||||
if (notification.body.thread_id) {
|
|
||||||
bulk.threads.push(notification.body.thread_id);
|
|
||||||
}
|
|
||||||
if (notification.body.invited_by) {
|
|
||||||
bulk.users.push(notification.body.invited_by);
|
|
||||||
}
|
|
||||||
if (notification.body.organization_id) {
|
|
||||||
bulk.organizations.push(notification.body.organization_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const reports = await getBulk("reports", bulk.reports);
|
|
||||||
for (const report of reports) {
|
|
||||||
if (report.item_type === "project") {
|
|
||||||
bulk.projects.push(report.item_id);
|
|
||||||
} else if (report.item_type === "user") {
|
|
||||||
bulk.users.push(report.item_id);
|
|
||||||
} else if (report.item_type === "version") {
|
|
||||||
bulk.versions.push(report.item_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const versions = await getBulk("versions", bulk.versions);
|
|
||||||
for (const version of versions) {
|
|
||||||
bulk.projects.push(version.project_id);
|
|
||||||
}
|
|
||||||
const [projects, threads, users, organizations] = await Promise.all([
|
|
||||||
getBulk("projects", bulk.projects),
|
|
||||||
getBulk("threads", bulk.threads),
|
|
||||||
getBulk("users", bulk.users),
|
|
||||||
getBulk("organizations", bulk.organizations, 3),
|
|
||||||
]);
|
|
||||||
for (const notification of notifications) {
|
|
||||||
notification.extra_data = {};
|
|
||||||
if (notification.body) {
|
|
||||||
if (notification.body.project_id) {
|
|
||||||
notification.extra_data.project = projects.find(
|
|
||||||
(x) => x.id === notification.body.project_id,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (notification.body.organization_id) {
|
|
||||||
notification.extra_data.organization = organizations.find(
|
|
||||||
(x) => x.id === notification.body.organization_id,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (notification.body.report_id) {
|
|
||||||
notification.extra_data.report = reports.find((x) => x.id === notification.body.report_id);
|
|
||||||
|
|
||||||
const type = notification.extra_data.report.item_type;
|
|
||||||
if (type === "project") {
|
|
||||||
notification.extra_data.project = projects.find(
|
|
||||||
(x) => x.id === notification.extra_data.report.item_id,
|
|
||||||
);
|
|
||||||
} else if (type === "user") {
|
|
||||||
notification.extra_data.user = users.find(
|
|
||||||
(x) => x.id === notification.extra_data.report.item_id,
|
|
||||||
);
|
|
||||||
} else if (type === "version") {
|
|
||||||
notification.extra_data.version = versions.find(
|
|
||||||
(x) => x.id === notification.extra_data.report.item_id,
|
|
||||||
);
|
|
||||||
notification.extra_data.project = projects.find(
|
|
||||||
(x) => x.id === notification.extra_data.version.project_id,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (notification.body.thread_id) {
|
|
||||||
notification.extra_data.thread = threads.find((x) => x.id === notification.body.thread_id);
|
|
||||||
}
|
|
||||||
if (notification.body.invited_by) {
|
|
||||||
notification.extra_data.invited_by = users.find(
|
|
||||||
(x) => x.id === notification.body.invited_by,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (notification.body.version_id) {
|
|
||||||
notification.extra_data.version = versions.find(
|
|
||||||
(x) => x.id === notification.body.version_id,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return notifications;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function groupNotifications(notifications) {
|
|
||||||
const grouped = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < notifications.length; i++) {
|
|
||||||
const current = notifications[i];
|
|
||||||
const next = notifications[i + 1];
|
|
||||||
if (current.body && i < notifications.length - 1 && isSimilar(current, next)) {
|
|
||||||
current.grouped_notifs = [next];
|
|
||||||
|
|
||||||
let j = i + 2;
|
|
||||||
while (j < notifications.length && isSimilar(current, notifications[j])) {
|
|
||||||
current.grouped_notifs.push(notifications[j]);
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
|
|
||||||
grouped.push(current);
|
|
||||||
i = j - 1; // skip i to the last ungrouped
|
|
||||||
} else {
|
|
||||||
grouped.push(current);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return grouped;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isSimilar(notifA, notifB) {
|
|
||||||
return !!notifA.body.project_id && notifA.body.project_id === notifB.body.project_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function markAsRead(ids) {
|
|
||||||
try {
|
|
||||||
await useBaseFetch(`notifications?ids=${JSON.stringify([...new Set(ids)])}`, {
|
|
||||||
method: "PATCH",
|
|
||||||
});
|
|
||||||
return (notifications) => {
|
|
||||||
const newNotifs = notifications;
|
|
||||||
newNotifs.forEach((notif) => {
|
|
||||||
if (ids.includes(notif.id)) {
|
|
||||||
notif.read = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return newNotifs;
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
const app = useNuxtApp();
|
|
||||||
app.$notify({
|
|
||||||
group: "main",
|
|
||||||
title: "Error marking notification as read",
|
|
||||||
text: err.data ? err.data.description : err,
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
return () => {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
185
apps/frontend/src/helpers/notifications.ts
Normal file
185
apps/frontend/src/helpers/notifications.ts
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
import { useNuxtApp } from "#imports";
|
||||||
|
|
||||||
|
// TODO: There needs to be a standardized way to get these types, eg; @modrinth/types generated from api schema. Later problem.
|
||||||
|
type Project = { id: string };
|
||||||
|
type Version = { id: string; project_id: string };
|
||||||
|
type Report = { id: string; item_type: "project" | "user" | "version"; item_id: string };
|
||||||
|
type Thread = { id: string };
|
||||||
|
type User = { id: string };
|
||||||
|
type Organization = { id: string };
|
||||||
|
|
||||||
|
export type NotificationAction = {
|
||||||
|
title: string;
|
||||||
|
action_route: [string, string];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type NotificationBody = {
|
||||||
|
project_id?: string;
|
||||||
|
version_id?: string;
|
||||||
|
report_id?: string;
|
||||||
|
thread_id?: string;
|
||||||
|
invited_by?: string;
|
||||||
|
organization_id?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Notification = {
|
||||||
|
id: string;
|
||||||
|
user_id: string;
|
||||||
|
type: "project_update" | "team_invite" | "status_change" | "moderator_message";
|
||||||
|
title: string;
|
||||||
|
text: string;
|
||||||
|
link: string;
|
||||||
|
read: boolean;
|
||||||
|
created: string;
|
||||||
|
actions: NotificationAction[];
|
||||||
|
body?: NotificationBody;
|
||||||
|
extra_data?: Record<string, unknown>;
|
||||||
|
grouped_notifs?: Notification[];
|
||||||
|
};
|
||||||
|
|
||||||
|
async function getBulk<T extends { id: string }>(
|
||||||
|
type: string,
|
||||||
|
ids: string[],
|
||||||
|
apiVersion = 2,
|
||||||
|
): Promise<T[]> {
|
||||||
|
if (!ids || ids.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const url = `${type}?ids=${encodeURIComponent(JSON.stringify([...new Set(ids)]))}`;
|
||||||
|
try {
|
||||||
|
const res = await useBaseFetch(url, { apiVersion });
|
||||||
|
return Array.isArray(res) ? res : [];
|
||||||
|
} catch {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchExtraNotificationData(
|
||||||
|
notifications: Notification[],
|
||||||
|
): Promise<Notification[]> {
|
||||||
|
const bulk = {
|
||||||
|
projects: [] as string[],
|
||||||
|
reports: [] as string[],
|
||||||
|
threads: [] as string[],
|
||||||
|
users: [] as string[],
|
||||||
|
versions: [] as string[],
|
||||||
|
organizations: [] as string[],
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const notification of notifications) {
|
||||||
|
if (notification.body) {
|
||||||
|
if (notification.body.project_id) bulk.projects.push(notification.body.project_id);
|
||||||
|
if (notification.body.version_id) bulk.versions.push(notification.body.version_id);
|
||||||
|
if (notification.body.report_id) bulk.reports.push(notification.body.report_id);
|
||||||
|
if (notification.body.thread_id) bulk.threads.push(notification.body.thread_id);
|
||||||
|
if (notification.body.invited_by) bulk.users.push(notification.body.invited_by);
|
||||||
|
if (notification.body.organization_id)
|
||||||
|
bulk.organizations.push(notification.body.organization_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const reports = (await getBulk<Report>("reports", bulk.reports)).filter(Boolean);
|
||||||
|
for (const r of reports) {
|
||||||
|
if (!r?.item_type) continue;
|
||||||
|
if (r.item_type === "project") bulk.projects.push(r.item_id);
|
||||||
|
else if (r.item_type === "user") bulk.users.push(r.item_id);
|
||||||
|
else if (r.item_type === "version") bulk.versions.push(r.item_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
const versions = (await getBulk<Version>("versions", bulk.versions)).filter(Boolean);
|
||||||
|
for (const v of versions) bulk.projects.push(v.project_id);
|
||||||
|
|
||||||
|
const [projects, threads, users, organizations] = await Promise.all([
|
||||||
|
getBulk<Project>("projects", bulk.projects),
|
||||||
|
getBulk<Thread>("threads", bulk.threads),
|
||||||
|
getBulk<User>("users", bulk.users),
|
||||||
|
getBulk<Organization>("organizations", bulk.organizations, 3),
|
||||||
|
]);
|
||||||
|
|
||||||
|
for (const n of notifications) {
|
||||||
|
n.extra_data = {};
|
||||||
|
if (n.body) {
|
||||||
|
if (n.body.project_id)
|
||||||
|
n.extra_data.project = projects.find((x) => x.id === n.body!.project_id);
|
||||||
|
if (n.body.organization_id)
|
||||||
|
n.extra_data.organization = organizations.find((x) => x.id === n.body!.organization_id);
|
||||||
|
if (n.body.report_id) {
|
||||||
|
n.extra_data.report = reports.find((x) => x.id === n.body!.report_id);
|
||||||
|
const t = (n.extra_data.report as Report | undefined)?.item_type;
|
||||||
|
if (t === "project")
|
||||||
|
n.extra_data.project = projects.find(
|
||||||
|
(x) => x.id === (n.extra_data?.report as Report | undefined)?.item_id,
|
||||||
|
);
|
||||||
|
else if (t === "user")
|
||||||
|
n.extra_data.user = users.find(
|
||||||
|
(x) => x.id === (n.extra_data?.report as Report | undefined)?.item_id,
|
||||||
|
);
|
||||||
|
else if (t === "version") {
|
||||||
|
n.extra_data.version = versions.find(
|
||||||
|
(x) => x.id === (n.extra_data?.report as Report | undefined)?.item_id,
|
||||||
|
);
|
||||||
|
n.extra_data.project = projects.find(
|
||||||
|
(x) => x.id === (n.extra_data?.version as Version | undefined)?.project_id,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (n.body.thread_id) n.extra_data.thread = threads.find((x) => x.id === n.body!.thread_id);
|
||||||
|
if (n.body.invited_by)
|
||||||
|
n.extra_data.invited_by = users.find((x) => x.id === n.body!.invited_by);
|
||||||
|
if (n.body.version_id)
|
||||||
|
n.extra_data.version = versions.find((x) => x.id === n.body!.version_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return notifications;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function groupNotifications(notifications: Notification[]): Notification[] {
|
||||||
|
const grouped: Notification[] = [];
|
||||||
|
for (let i = 0; i < notifications.length; i++) {
|
||||||
|
const current = notifications[i];
|
||||||
|
const next = notifications[i + 1];
|
||||||
|
if (current.body && i < notifications.length - 1 && isSimilar(current, next)) {
|
||||||
|
current.grouped_notifs = [next];
|
||||||
|
let j = i + 2;
|
||||||
|
while (j < notifications.length && isSimilar(current, notifications[j])) {
|
||||||
|
current.grouped_notifs.push(notifications[j]);
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
grouped.push(current);
|
||||||
|
i = j - 1;
|
||||||
|
} else {
|
||||||
|
grouped.push(current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return grouped;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSimilar(a: Notification, b: Notification | undefined): boolean {
|
||||||
|
return !!a?.body?.project_id && a.body!.project_id === b?.body?.project_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function markAsRead(
|
||||||
|
ids: string[],
|
||||||
|
): Promise<(notifications: Notification[]) => Notification[]> {
|
||||||
|
try {
|
||||||
|
await useBaseFetch(`notifications?ids=${JSON.stringify([...new Set(ids)])}`, {
|
||||||
|
method: "PATCH",
|
||||||
|
});
|
||||||
|
return (notifications: Notification[]) => {
|
||||||
|
const newNotifs = notifications ?? [];
|
||||||
|
newNotifs.forEach((n) => {
|
||||||
|
if (ids.includes(n.id)) n.read = true;
|
||||||
|
});
|
||||||
|
return newNotifs;
|
||||||
|
};
|
||||||
|
} catch (err: any) {
|
||||||
|
const app: any = useNuxtApp();
|
||||||
|
app.$notify({
|
||||||
|
group: "main",
|
||||||
|
title: "Error marking notification as read",
|
||||||
|
text: err?.data?.description ?? err,
|
||||||
|
type: "error",
|
||||||
|
});
|
||||||
|
return () => [];
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -99,7 +99,7 @@
|
|||||||
import { ChevronRightIcon, HistoryIcon } from "@modrinth/assets";
|
import { ChevronRightIcon, HistoryIcon } from "@modrinth/assets";
|
||||||
import Avatar from "~/components/ui/Avatar.vue";
|
import Avatar from "~/components/ui/Avatar.vue";
|
||||||
import NotificationItem from "~/components/ui/NotificationItem.vue";
|
import NotificationItem from "~/components/ui/NotificationItem.vue";
|
||||||
import { fetchExtraNotificationData, groupNotifications } from "~/helpers/notifications.js";
|
import { fetchExtraNotificationData, groupNotifications } from "~/helpers/notifications.ts";
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
title: "Dashboard - Modrinth",
|
title: "Dashboard - Modrinth",
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
<h2 v-else class="text-2xl">Notifications</h2>
|
<h2 v-else class="text-2xl">Notifications</h2>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="!history">
|
<template v-if="!history">
|
||||||
<Button v-if="hasRead" @click="updateRoute()">
|
<Button v-if="data.hasRead" @click="updateRoute()">
|
||||||
<HistoryIcon />
|
<HistoryIcon />
|
||||||
View history
|
View history
|
||||||
</Button>
|
</Button>
|
||||||
@ -60,7 +60,7 @@ import {
|
|||||||
fetchExtraNotificationData,
|
fetchExtraNotificationData,
|
||||||
groupNotifications,
|
groupNotifications,
|
||||||
markAsRead,
|
markAsRead,
|
||||||
} from "~/helpers/notifications.js";
|
} from "~/helpers/notifications.ts";
|
||||||
import NotificationItem from "~/components/ui/NotificationItem.vue";
|
import NotificationItem from "~/components/ui/NotificationItem.vue";
|
||||||
import Breadcrumbs from "~/components/ui/Breadcrumbs.vue";
|
import Breadcrumbs from "~/components/ui/Breadcrumbs.vue";
|
||||||
import Pagination from "~/components/ui/Pagination.vue";
|
import Pagination from "~/components/ui/Pagination.vue";
|
||||||
@ -70,93 +70,69 @@ useHead({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const auth = await useAuth();
|
const auth = await useAuth();
|
||||||
|
|
||||||
const route = useNativeRoute();
|
const route = useNativeRoute();
|
||||||
const router = useNativeRouter();
|
const router = useNativeRouter();
|
||||||
|
|
||||||
const history = computed(() => {
|
const history = computed(() => route.name === "dashboard-notifications-history");
|
||||||
return route.name === "dashboard-notifications-history";
|
|
||||||
});
|
|
||||||
|
|
||||||
const selectedType = ref("all");
|
const selectedType = ref("all");
|
||||||
const page = ref(1);
|
const page = ref(1);
|
||||||
|
|
||||||
const perPage = ref(50);
|
const perPage = ref(50);
|
||||||
|
|
||||||
const { data, pending, error, refresh } = await useAsyncData(
|
const { data, pending, error, refresh } = await useAsyncData(
|
||||||
async () => {
|
async () => {
|
||||||
const pageNum = page.value - 1;
|
const pageNum = page.value - 1;
|
||||||
|
|
||||||
const notifications = await useBaseFetch(`user/${auth.value.user.id}/notifications`);
|
|
||||||
const showRead = history.value;
|
const showRead = history.value;
|
||||||
const hasRead = notifications.some((notif) => notif.read);
|
const notifications = await useBaseFetch(`user/${auth.value.user.id}/notifications`);
|
||||||
|
|
||||||
const types = [
|
const typesInFeed = [
|
||||||
...new Set(
|
...new Set(notifications.filter((n) => showRead || !n.read).map((n) => n.type)),
|
||||||
notifications
|
|
||||||
.filter((notification) => {
|
|
||||||
return showRead || !notification.read;
|
|
||||||
})
|
|
||||||
.map((notification) => notification.type),
|
|
||||||
),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const filteredNotifications = notifications.filter(
|
const filtered = notifications.filter(
|
||||||
(notification) =>
|
(n) =>
|
||||||
(selectedType.value === "all" || notification.type === selectedType.value) &&
|
(selectedType.value === "all" || n.type === selectedType.value) && (showRead || !n.read),
|
||||||
(showRead || !notification.read),
|
|
||||||
);
|
);
|
||||||
const pages = Math.ceil(filteredNotifications.length / perPage.value);
|
|
||||||
|
const pages = Math.max(1, Math.ceil(filtered.length / perPage.value));
|
||||||
|
|
||||||
return fetchExtraNotificationData(
|
return fetchExtraNotificationData(
|
||||||
filteredNotifications.slice(pageNum * perPage.value, perPage.value + pageNum * perPage.value),
|
filtered.slice(pageNum * perPage.value, pageNum * perPage.value + perPage.value),
|
||||||
).then((notifications) => {
|
).then((notifs) => ({
|
||||||
return {
|
notifications: notifs,
|
||||||
notifications,
|
notifTypes: typesInFeed.length > 1 ? ["all", ...typesInFeed] : typesInFeed,
|
||||||
types: types.length > 1 ? ["all", ...types] : types,
|
|
||||||
pages,
|
pages,
|
||||||
hasRead,
|
hasRead: notifications.some((n) => n.read),
|
||||||
};
|
}));
|
||||||
});
|
|
||||||
},
|
},
|
||||||
{ watch: [page, history, selectedType] },
|
{ watch: [page, history, selectedType] },
|
||||||
);
|
);
|
||||||
|
|
||||||
const notifications = computed(() => {
|
const notifications = computed(() =>
|
||||||
if (data.value === null) {
|
data.value ? groupNotifications(data.value.notifications, history.value) : [],
|
||||||
return [];
|
);
|
||||||
}
|
|
||||||
return groupNotifications(data.value.notifications, history.value);
|
const notifTypes = computed(() => data.value?.notifTypes || []);
|
||||||
});
|
const pages = computed(() => data.value?.pages ?? 1);
|
||||||
const notifTypes = computed(() => data.value.types);
|
|
||||||
const pages = computed(() => data.value.pages);
|
|
||||||
const hasRead = computed(() => data.value.hasRead);
|
|
||||||
|
|
||||||
function updateRoute() {
|
function updateRoute() {
|
||||||
if (history.value) {
|
router.push(history.value ? "/dashboard/notifications" : "/dashboard/notifications/history");
|
||||||
router.push("/dashboard/notifications");
|
|
||||||
} else {
|
|
||||||
router.push("/dashboard/notifications/history");
|
|
||||||
}
|
|
||||||
selectedType.value = "all";
|
selectedType.value = "all";
|
||||||
page.value = 1;
|
page.value = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function readAll() {
|
async function readAll() {
|
||||||
const ids = notifications.value.flatMap((notification) => [
|
const ids = notifications.value.flatMap((n) => [
|
||||||
notification.id,
|
n.id,
|
||||||
...(notification.grouped_notifs ? notification.grouped_notifs.map((notif) => notif.id) : []),
|
...(n.grouped_notifs ? n.grouped_notifs.map((g) => g.id) : []),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const updateNotifs = await markAsRead(ids);
|
await markAsRead(ids);
|
||||||
allNotifs.value = updateNotifs(allNotifs.value);
|
await refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
function changePage(newPage) {
|
function changePage(newPage) {
|
||||||
page.value = newPage;
|
page.value = newPage;
|
||||||
if (import.meta.client) {
|
if (import.meta.client) window.scrollTo({ top: 0, behavior: "smooth" });
|
||||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user