200 lines
5.0 KiB
TypeScript
200 lines
5.0 KiB
TypeScript
import { TFunction } from "i18next";
|
|
import { action, computed, observable } from "mobx";
|
|
import { NotificationEventType } from "@shared/types";
|
|
import {
|
|
collectionPath,
|
|
commentPath,
|
|
documentPath,
|
|
settingsPath,
|
|
} from "~/utils/routeHelpers";
|
|
import Collection from "./Collection";
|
|
import Comment from "./Comment";
|
|
import Document from "./Document";
|
|
import User from "./User";
|
|
import Model from "./base/Model";
|
|
import Field from "./decorators/Field";
|
|
import Relation from "./decorators/Relation";
|
|
|
|
class Notification extends Model {
|
|
static modelName = "Notification";
|
|
|
|
@Field
|
|
@observable
|
|
id: string;
|
|
|
|
/**
|
|
* The date the notification was marked as read.
|
|
*/
|
|
@Field
|
|
@observable
|
|
viewedAt: Date | null;
|
|
|
|
/**
|
|
* The date the notification was archived.
|
|
*/
|
|
@Field
|
|
@observable
|
|
archivedAt: Date | null;
|
|
|
|
/**
|
|
* The user that triggered the notification.
|
|
*/
|
|
@Relation(() => User)
|
|
actor?: User;
|
|
|
|
/**
|
|
* The document ID that the notification is associated with.
|
|
*/
|
|
documentId?: string;
|
|
|
|
/**
|
|
* The document that the notification is associated with.
|
|
*/
|
|
@Relation(() => Document, { onDelete: "cascade" })
|
|
document?: Document;
|
|
|
|
/**
|
|
* The collection ID that the notification is associated with.
|
|
*/
|
|
collectionId?: string;
|
|
|
|
/**
|
|
* The collection that the notification is associated with.
|
|
*/
|
|
@Relation(() => Collection, { onDelete: "cascade" })
|
|
collection?: Collection;
|
|
|
|
commentId?: string;
|
|
|
|
/**
|
|
* The comment that the notification is associated with.
|
|
*/
|
|
@Relation(() => Comment, { onDelete: "cascade" })
|
|
comment?: Comment;
|
|
|
|
/**
|
|
* The type of notification.
|
|
*/
|
|
event: NotificationEventType;
|
|
|
|
/**
|
|
* Mark the notification as read or unread
|
|
*
|
|
* @returns A promise that resolves when the notification has been saved.
|
|
*/
|
|
@action
|
|
toggleRead() {
|
|
this.viewedAt = this.viewedAt ? null : new Date();
|
|
return this.save();
|
|
}
|
|
|
|
/**
|
|
* Mark the notification as read
|
|
*
|
|
* @returns A promise that resolves when the notification has been saved.
|
|
*/
|
|
@action
|
|
markAsRead() {
|
|
if (this.viewedAt) {
|
|
return;
|
|
}
|
|
|
|
this.viewedAt = new Date();
|
|
return this.save();
|
|
}
|
|
|
|
/**
|
|
* Returns translated text that describes the notification
|
|
*
|
|
* @param t - The translation function
|
|
* @returns The event text
|
|
*/
|
|
eventText(t: TFunction): string {
|
|
switch (this.event) {
|
|
case NotificationEventType.PublishDocument:
|
|
return t("published");
|
|
case NotificationEventType.UpdateDocument:
|
|
case NotificationEventType.CreateRevision:
|
|
return t("edited");
|
|
case NotificationEventType.CreateCollection:
|
|
return t("created the collection");
|
|
case NotificationEventType.MentionedInDocument:
|
|
case NotificationEventType.MentionedInComment:
|
|
return t("mentioned you in");
|
|
case NotificationEventType.CreateComment:
|
|
return t("left a comment on");
|
|
case NotificationEventType.AddUserToDocument:
|
|
return t("shared");
|
|
case NotificationEventType.AddUserToCollection:
|
|
return t("invited you to");
|
|
default:
|
|
return this.event;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the subject of the notification. This is the title of the associated
|
|
* document.
|
|
*
|
|
* @returns The subject
|
|
*/
|
|
get subject() {
|
|
if (this.documentId) {
|
|
return this.document?.title ?? "a document";
|
|
}
|
|
if (this.collectionId) {
|
|
return this.collection?.name ?? "a collection";
|
|
}
|
|
return "Unknown";
|
|
}
|
|
|
|
/**
|
|
* Returns the path to the model associated with the notification that can be
|
|
* used with the router.
|
|
*
|
|
* @returns The router path.
|
|
*/
|
|
@computed
|
|
get path() {
|
|
switch (this.event) {
|
|
case NotificationEventType.PublishDocument:
|
|
case NotificationEventType.UpdateDocument:
|
|
case NotificationEventType.CreateRevision: {
|
|
return this.document ? documentPath(this.document) : "";
|
|
}
|
|
case NotificationEventType.AddUserToCollection:
|
|
case NotificationEventType.CreateCollection: {
|
|
const collection = this.collectionId
|
|
? this.store.rootStore.collections.get(this.collectionId)
|
|
: undefined;
|
|
return collection ? collectionPath(collection.path) : "";
|
|
}
|
|
case NotificationEventType.AddUserToDocument:
|
|
case NotificationEventType.MentionedInDocument: {
|
|
return this.document?.path;
|
|
}
|
|
case NotificationEventType.MentionedInComment:
|
|
case NotificationEventType.CreateComment: {
|
|
return this.document && this.comment
|
|
? commentPath(this.document, this.comment)
|
|
: this.document?.path;
|
|
}
|
|
case NotificationEventType.InviteAccepted: {
|
|
return settingsPath("members");
|
|
}
|
|
case NotificationEventType.Onboarding:
|
|
case NotificationEventType.Features: {
|
|
return "";
|
|
}
|
|
case NotificationEventType.ExportCompleted: {
|
|
return settingsPath("export");
|
|
}
|
|
default:
|
|
this.event satisfies never;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
export default Notification;
|