Ctrl K
ComunidadGuías…

app/models/Notification.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import type { TFunction } from "i18next";
import { action, computed, observable } from "mobx";
import type { NotificationData } from "@shared/types";
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 Group from "./Group";
import User from "./User";
import Model from "./base/Model";
import Field from "./decorators/Field";
import Relation from "./decorators/Relation";

export type NotificationFilter =
  | "all"
  | "mentions"
  | "comments"
  | "reactions"
  | "documents"
  | "collections"
  | "system";

class Notification extends Model {
  static modelName = "Notification";

  constructor(fields: Record<string, unknown>, store: Model["store"]) {
    super(fields, store);
    this.initialize(fields);
  }

  static filterCategories: Record<NotificationFilter, NotificationEventType[]> =
    {
      all: [],
      mentions: [
        NotificationEventType.MentionedInDocument,
        NotificationEventType.MentionedInComment,
        NotificationEventType.GroupMentionedInDocument,
        NotificationEventType.GroupMentionedInComment,
      ],
      comments: [
        NotificationEventType.CreateComment,
        NotificationEventType.ResolveComment,
        NotificationEventType.ReactionsCreate,
      ],
      reactions: [NotificationEventType.ReactionsCreate],
      documents: [
        NotificationEventType.PublishDocument,
        NotificationEventType.UpdateDocument,
        NotificationEventType.CreateRevision,
        NotificationEventType.AddUserToDocument,
        NotificationEventType.RequestDocumentAccess,
      ],
      collections: [
        NotificationEventType.CreateCollection,
        NotificationEventType.AddUserToCollection,
      ],
      system: [
        NotificationEventType.InviteAccepted,
        NotificationEventType.Onboarding,
        NotificationEventType.Features,
        NotificationEventType.ExportCompleted,
        NotificationEventType.AddUserToGroup,
        NotificationEventType.RemoveUserFromGroup,
      ],
    };

  /**
   * The date the notification was marked as read.
   */
  @Field
  @observable
  viewedAt: Date | null;

  /**
   * The date the notification was archived.
   */
  @Field
  @observable
  archivedAt: Date | null;

  /**
   * Request ID on notifications for access requests.
   */
  @Field
  @observable
  accessRequestId?: string = undefined;
  /**
   * Status of the associated access request.
   */
  @Field
  @observable
  accessRequestStatus?: string = undefined;
  /**
   * 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;

  /**
   * The group ID that the notification is associated with.
   */
  groupId?: string;

  /**
   * The group that the notification is associated with.
   */
  @Relation(() => Group, { onDelete: "cascade" })
  group?: Group;

  commentId?: string;

  /**
   * The comment that the notification is associated with.
   */
  @Relation(() => Comment, { onDelete: "cascade" })
  comment?: Comment;

  /**
   * The type of notification.
   */
  event: NotificationEventType;

  /**
   * Additional data associated with the notification.
   */
  data: NotificationData;

  /**
   * 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();
  }

  /**
   * Archive the notification
   *
   * @returns A promise that resolves when the notification has been archived.
   */
  @action
  archive() {
    if (this.archivedAt) {
      return;
    }

    this.archivedAt = 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.GroupMentionedInComment:
      case NotificationEventType.GroupMentionedInDocument:
        return t("mentioned your group in");
      case NotificationEventType.CreateComment:
        return t("left a comment on");
      case NotificationEventType.ResolveComment:
        return t("resolved a comment on");
      case NotificationEventType.ReactionsCreate:
        return t("reacted {{ emoji }} to your comment on", {
          emoji: this.data.emoji,
        });
      case NotificationEventType.AddUserToDocument:
        return t("shared");
      case NotificationEventType.AddUserToCollection:
        return t("invited you to");
      case NotificationEventType.AddUserToGroup:
        return t("added you to the group");
      case NotificationEventType.RemoveUserFromGroup:
        return t("removed you from the group");
      case NotificationEventType.RequestDocumentAccess:
        if (this.accessRequestStatus === "approved") {
          return t("was granted access to");
        }
        if (this.accessRequestStatus === "dismissed") {
          return t("requested access to");
        }
        return t("is requesting access to");
      default:
        return this.event;
    }
  }

  /**
   * Returns translated text for the subject of the notification. This is the
   * name of the associated document, collection, or group.
   *
   * @param t - The translation function.
   * @returns The subject.
   */
  subject(t: TFunction): string {
    if (this.documentId) {
      return this.document?.title ?? t("a document");
    }
    if (this.collectionId) {
      return this.collection?.displayName ?? t("a collection");
    }
    if (this.groupId) {
      return this.group?.name ?? t("a group");
    }
    return t("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) : "";
      }
      case NotificationEventType.RequestDocumentAccess:
      case NotificationEventType.AddUserToDocument:
      case NotificationEventType.GroupMentionedInDocument:
      case NotificationEventType.MentionedInDocument: {
        return this.document?.path;
      }
      case NotificationEventType.GroupMentionedInComment:
      case NotificationEventType.MentionedInComment:
      case NotificationEventType.ResolveComment:
      case NotificationEventType.CreateComment:
      case NotificationEventType.ReactionsCreate: {
        return this.document && this.comment
          ? commentPath(this.document, this.comment)
          : this.document?.path;
      }
      case NotificationEventType.InviteAccepted: {
        return settingsPath("users");
      }
      case NotificationEventType.Onboarding:
      case NotificationEventType.Features: {
        return "";
      }
      case NotificationEventType.ExportCompleted: {
        return settingsPath("export");
      }
      case NotificationEventType.AddUserToGroup:
      case NotificationEventType.RemoveUserFromGroup: {
        return this.groupId
          ? settingsPath("groups", this.groupId, "members")
          : "";
      }
      default:
        this.event satisfies never;
        return;
    }
  }
}

export default Notification;