fix: Initials do not display on notification avatars (#5803)

This commit is contained in:
Tom Moor
2023-09-09 21:01:14 -04:00
committed by GitHub
parent 80ef0a38d6
commit 5c839998c1
65 changed files with 238 additions and 165 deletions

View File

@@ -3,8 +3,8 @@ import { shallow } from "enzyme";
import { TFunction } from "i18next"; import { TFunction } from "i18next";
import * as React from "react"; import * as React from "react";
import { getI18n } from "react-i18next"; import { getI18n } from "react-i18next";
import { DEFAULT_PAGINATION_LIMIT } from "~/stores/BaseStore";
import RootStore from "~/stores/RootStore"; import RootStore from "~/stores/RootStore";
import { DEFAULT_PAGINATION_LIMIT } from "~/stores/base/Store";
import { runAllPromises } from "~/test/support"; import { runAllPromises } from "~/test/support";
import { Component as PaginatedList } from "./PaginatedList"; import { Component as PaginatedList } from "./PaginatedList";

View File

@@ -5,8 +5,8 @@ import * as React from "react";
import { withTranslation, WithTranslation } from "react-i18next"; import { withTranslation, WithTranslation } from "react-i18next";
import { Waypoint } from "react-waypoint"; import { Waypoint } from "react-waypoint";
import { CompositeStateReturn } from "reakit/Composite"; import { CompositeStateReturn } from "reakit/Composite";
import { DEFAULT_PAGINATION_LIMIT } from "~/stores/BaseStore";
import RootStore from "~/stores/RootStore"; import RootStore from "~/stores/RootStore";
import { DEFAULT_PAGINATION_LIMIT } from "~/stores/base/Store";
import ArrowKeyNavigation from "~/components/ArrowKeyNavigation"; import ArrowKeyNavigation from "~/components/ArrowKeyNavigation";
import DelayedMount from "~/components/DelayedMount"; import DelayedMount from "~/components/DelayedMount";
import PlaceholderList from "~/components/List/Placeholder"; import PlaceholderList from "~/components/List/Placeholder";

View File

@@ -317,7 +317,7 @@ class WebsocketProvider extends React.Component<Props> {
}); });
} }
auth.team?.updateFromJson(event); auth.team?.updateData(event);
}); });
this.socket.on( this.socket.on(

View File

@@ -1,5 +1,5 @@
import * as React from "react"; import * as React from "react";
import BaseModel from "~/models/BaseModel"; import Model from "~/models/base/Model";
import useStores from "./useStores"; import useStores from "./useStores";
/** /**
@@ -9,7 +9,7 @@ import useStores from "./useStores";
* @param entity The model or model id * @param entity The model or model id
* @returns The policy for the model * @returns The policy for the model
*/ */
export default function usePolicy(entity?: string | BaseModel | null) { export default function usePolicy(entity?: string | Model | null) {
const { policies } = useStores(); const { policies } = useStores();
const triggered = React.useRef(false); const triggered = React.useRef(false);
const entityId = entity const entityId = entity

View File

@@ -1,8 +1,8 @@
import { observable } from "mobx"; import { observable } from "mobx";
import BaseModel from "./BaseModel"; import Model from "./base/Model";
import Field from "./decorators/Field"; import Field from "./decorators/Field";
class ApiKey extends BaseModel { class ApiKey extends Model {
@Field @Field
@observable @observable
id: string; id: string;

View File

@@ -1,8 +1,8 @@
import { computed, observable } from "mobx"; import { computed, observable } from "mobx";
import BaseModel from "./BaseModel"; import Model from "./base/Model";
import Field from "./decorators/Field"; import Field from "./decorators/Field";
class AuthenticationProvider extends BaseModel { class AuthenticationProvider extends Model {
id: string; id: string;
displayName: string; displayName: string;

View File

@@ -8,7 +8,7 @@ import {
import { sortNavigationNodes } from "@shared/utils/collections"; import { sortNavigationNodes } from "@shared/utils/collections";
import type CollectionsStore from "~/stores/CollectionsStore"; import type CollectionsStore from "~/stores/CollectionsStore";
import Document from "~/models/Document"; import Document from "~/models/Document";
import ParanoidModel from "~/models/ParanoidModel"; import ParanoidModel from "~/models/base/ParanoidModel";
import { client } from "~/utils/ApiClient"; import { client } from "~/utils/ApiClient";
import Field from "./decorators/Field"; import Field from "./decorators/Field";

View File

@@ -1,8 +1,8 @@
import { observable } from "mobx"; import { observable } from "mobx";
import { CollectionPermission } from "@shared/types"; import { CollectionPermission } from "@shared/types";
import BaseModel from "./BaseModel"; import Model from "./base/Model";
class CollectionGroupMembership extends BaseModel { class CollectionGroupMembership extends Model {
id: string; id: string;
groupId: string; groupId: string;

View File

@@ -3,10 +3,11 @@ import { computed, observable } from "mobx";
import { now } from "mobx-utils"; import { now } from "mobx-utils";
import type { ProsemirrorData } from "@shared/types"; import type { ProsemirrorData } from "@shared/types";
import User from "~/models/User"; import User from "~/models/User";
import BaseModel from "./BaseModel"; import Model from "./base/Model";
import Field from "./decorators/Field"; import Field from "./decorators/Field";
import Relation from "./decorators/Relation";
class Comment extends BaseModel { class Comment extends Model {
/** /**
* Map to keep track of which users are currently typing a reply in this * Map to keep track of which users are currently typing a reply in this
* comments thread. * comments thread.
@@ -40,18 +41,16 @@ class Comment extends BaseModel {
@observable @observable
documentId: string; documentId: string;
createdAt: string; @Relation(() => User)
createdBy: User; createdBy: User;
createdById: string; createdById: string;
resolvedAt: string; resolvedAt: string;
@Relation(() => User)
resolvedBy: User; resolvedBy: User;
updatedAt: string;
/** /**
* An array of users that are currently typing a reply in this comments thread. * An array of users that are currently typing a reply in this comments thread.
*/ */
@@ -60,7 +59,7 @@ class Comment extends BaseModel {
return Array.from(this.typingUsers.entries()) return Array.from(this.typingUsers.entries())
.filter(([, lastReceivedDate]) => lastReceivedDate > subSeconds(now(), 3)) .filter(([, lastReceivedDate]) => lastReceivedDate > subSeconds(now(), 3))
.map(([userId]) => this.store.rootStore.users.get(userId)) .map(([userId]) => this.store.rootStore.users.get(userId))
.filter(Boolean); .filter(Boolean) as User[];
} }
} }

View File

@@ -8,8 +8,8 @@ import { isRTL } from "@shared/utils/rtl";
import DocumentsStore from "~/stores/DocumentsStore"; import DocumentsStore from "~/stores/DocumentsStore";
import User from "~/models/User"; import User from "~/models/User";
import { client } from "~/utils/ApiClient"; import { client } from "~/utils/ApiClient";
import ParanoidModel from "./ParanoidModel";
import View from "./View"; import View from "./View";
import ParanoidModel from "./base/ParanoidModel";
import Field from "./decorators/Field"; import Field from "./decorators/Field";
type SaveOptions = { type SaveOptions = {

View File

@@ -1,7 +1,8 @@
import BaseModel from "./BaseModel";
import User from "./User"; import User from "./User";
import Model from "./base/Model";
import Relation from "./decorators/Relation";
class Event extends BaseModel { class Event extends Model {
id: string; id: string;
name: string; name: string;
@@ -18,8 +19,7 @@ class Event extends BaseModel {
userId: string; userId: string;
createdAt: string; @Relation(() => User)
actor: User; actor: User;
data: { data: {

View File

@@ -1,10 +1,10 @@
import { computed } from "mobx"; import { computed } from "mobx";
import { FileOperationFormat, FileOperationType } from "@shared/types"; import { FileOperationFormat, FileOperationType } from "@shared/types";
import { bytesToHumanReadable } from "@shared/utils/files"; import { bytesToHumanReadable } from "@shared/utils/files";
import BaseModel from "./BaseModel";
import User from "./User"; import User from "./User";
import Model from "./base/Model";
class FileOperation extends BaseModel { class FileOperation extends Model {
id: string; id: string;
state: string; state: string;
@@ -23,8 +23,6 @@ class FileOperation extends BaseModel {
user: User; user: User;
createdAt: string;
@computed @computed
get sizeInMB(): string { get sizeInMB(): string {
return bytesToHumanReadable(this.size); return bytesToHumanReadable(this.size);

View File

@@ -1,8 +1,8 @@
import { observable } from "mobx"; import { observable } from "mobx";
import BaseModel from "./BaseModel"; import Model from "./base/Model";
import Field from "./decorators/Field"; import Field from "./decorators/Field";
class Group extends BaseModel { class Group extends Model {
@Field @Field
@observable @observable
id: string; id: string;
@@ -12,8 +12,6 @@ class Group extends BaseModel {
name: string; name: string;
memberCount: number; memberCount: number;
updatedAt: string;
} }
export default Group; export default Group;

View File

@@ -1,7 +1,7 @@
import BaseModel from "./BaseModel";
import User from "./User"; import User from "./User";
import Model from "./base/Model";
class GroupMembership extends BaseModel { class GroupMembership extends Model {
id: string; id: string;
userId: string; userId: string;

View File

@@ -4,10 +4,10 @@ import type {
IntegrationSettings, IntegrationSettings,
IntegrationType, IntegrationType,
} from "@shared/types"; } from "@shared/types";
import BaseModel from "~/models/BaseModel"; import Model from "~/models/base/Model";
import Field from "./decorators/Field"; import Field from "./decorators/Field";
class Integration<T = unknown> extends BaseModel { class Integration<T = unknown> extends Model {
id: string; id: string;
type: IntegrationType; type: IntegrationType;

View File

@@ -1,8 +1,8 @@
import { observable } from "mobx"; import { observable } from "mobx";
import { CollectionPermission } from "@shared/types"; import { CollectionPermission } from "@shared/types";
import BaseModel from "./BaseModel"; import Model from "./base/Model";
class Membership extends BaseModel { class Membership extends Model {
id: string; id: string;
userId: string; userId: string;

View File

@@ -7,13 +7,14 @@ import {
documentPath, documentPath,
settingsPath, settingsPath,
} from "~/utils/routeHelpers"; } from "~/utils/routeHelpers";
import BaseModel from "./BaseModel";
import Comment from "./Comment"; import Comment from "./Comment";
import Document from "./Document"; import Document from "./Document";
import User from "./User"; import User from "./User";
import Model from "./base/Model";
import Field from "./decorators/Field"; import Field from "./decorators/Field";
import Relation from "./decorators/Relation";
class Notification extends BaseModel { class Notification extends Model {
@Field @Field
@observable @observable
id: string; id: string;
@@ -35,6 +36,7 @@ class Notification extends BaseModel {
/** /**
* The user that triggered the notification. * The user that triggered the notification.
*/ */
@Relation(() => User)
actor?: User; actor?: User;
/** /**
@@ -45,6 +47,7 @@ class Notification extends BaseModel {
/** /**
* The document that the notification is associated with. * The document that the notification is associated with.
*/ */
@Relation(() => Document)
document?: Document; document?: Document;
/** /**
@@ -55,6 +58,7 @@ class Notification extends BaseModel {
/** /**
* The comment that the notification is associated with. * The comment that the notification is associated with.
*/ */
@Relation(() => Comment)
comment?: Comment; comment?: Comment;
/** /**
@@ -137,9 +141,9 @@ class Notification extends BaseModel {
return this.document ? documentPath(this.document) : ""; return this.document ? documentPath(this.document) : "";
} }
case NotificationEventType.CreateCollection: { case NotificationEventType.CreateCollection: {
const collection = this.store.rootStore.documents.get( const collection = this.collectionId
this.collectionId ? this.store.rootStore.documents.get(this.collectionId)
); : undefined;
return collection ? collectionPath(collection.url) : ""; return collection ? collectionPath(collection.url) : "";
} }
case NotificationEventType.MentionedInDocument: { case NotificationEventType.MentionedInDocument: {

View File

@@ -1,5 +0,0 @@
import BaseModel from "./BaseModel";
export default abstract class ParanoidModel extends BaseModel {
deletedAt: string | undefined;
}

View File

@@ -1,8 +1,8 @@
import { observable } from "mobx"; import { observable } from "mobx";
import BaseModel from "./BaseModel"; import Model from "./base/Model";
import Field from "./decorators/Field"; import Field from "./decorators/Field";
class Pin extends BaseModel { class Pin extends Model {
id: string; id: string;
collectionId: string; collectionId: string;
documentId: string; documentId: string;

View File

@@ -1,6 +1,6 @@
import BaseModel from "./BaseModel"; import Model from "./base/Model";
class Policy extends BaseModel { class Policy extends Model {
id: string; id: string;
abilities: Record<string, boolean>; abilities: Record<string, boolean>;

View File

@@ -1,9 +1,10 @@
import { computed } from "mobx"; import { computed } from "mobx";
import { isRTL } from "@shared/utils/rtl"; import { isRTL } from "@shared/utils/rtl";
import BaseModel from "./BaseModel";
import User from "./User"; import User from "./User";
import Model from "./base/Model";
import Relation from "./decorators/Relation";
class Revision extends BaseModel { class Revision extends Model {
id: string; id: string;
documentId: string; documentId: string;
@@ -20,8 +21,7 @@ class Revision extends BaseModel {
/** HTML string representing the revision as a diff from the previous version */ /** HTML string representing the revision as a diff from the previous version */
html: string; html: string;
createdAt: string; @Relation(() => User)
createdBy: User; createdBy: User;
/** /**

View File

@@ -1,13 +1,11 @@
import { client } from "~/utils/ApiClient"; import { client } from "~/utils/ApiClient";
import BaseModel from "./BaseModel"; import Model from "./base/Model";
class SearchQuery extends BaseModel { class SearchQuery extends Model {
id: string; id: string;
query: string; query: string;
createdAt: string;
delete = async () => { delete = async () => {
this.isSaving = true; this.isSaving = true;

View File

@@ -1,9 +1,9 @@
import { observable } from "mobx"; import { observable } from "mobx";
import BaseModel from "./BaseModel";
import User from "./User"; import User from "./User";
import Model from "./base/Model";
import Field from "./decorators/Field"; import Field from "./decorators/Field";
class Share extends BaseModel { class Share extends Model {
@Field @Field
@observable @observable
id: string; id: string;

View File

@@ -1,8 +1,9 @@
import { observable } from "mobx"; import { observable } from "mobx";
import BaseModel from "./BaseModel"; import type StarsStore from "~/stores/StarsStore";
import Model from "./base/Model";
import Field from "./decorators/Field"; import Field from "./decorators/Field";
class Star extends BaseModel { class Star extends Model {
id: string; id: string;
@Field @Field
@@ -13,8 +14,7 @@ class Star extends BaseModel {
collectionId: string; collectionId: string;
createdAt: string; store: StarsStore;
updatedAt: string;
next(): Star | undefined { next(): Star | undefined {
const index = this.store.orderedData.indexOf(this); const index = this.store.orderedData.indexOf(this);

View File

@@ -1,12 +1,12 @@
import { observable } from "mobx"; import { observable } from "mobx";
import BaseModel from "./BaseModel"; import Model from "./base/Model";
import Field from "./decorators/Field"; import Field from "./decorators/Field";
/** /**
* A subscription represents a request for a user to receive notifications for * A subscription represents a request for a user to receive notifications for
* a document. * a document.
*/ */
class Subscription extends BaseModel { class Subscription extends Model {
@Field @Field
@observable @observable
id: string; id: string;
@@ -21,9 +21,6 @@ class Subscription extends BaseModel {
@Field @Field
@observable @observable
event: string; event: string;
createdAt: string;
updatedAt: string;
} }
export default Subscription; export default Subscription;

View File

@@ -2,10 +2,10 @@ import { computed, observable } from "mobx";
import { TeamPreferenceDefaults } from "@shared/constants"; import { TeamPreferenceDefaults } from "@shared/constants";
import { TeamPreference, TeamPreferences } from "@shared/types"; import { TeamPreference, TeamPreferences } from "@shared/types";
import { stringToColor } from "@shared/utils/color"; import { stringToColor } from "@shared/utils/color";
import BaseModel from "./BaseModel"; import Model from "./base/Model";
import Field from "./decorators/Field"; import Field from "./decorators/Field";
class Team extends BaseModel { class Team extends Model {
@Field @Field
@observable @observable
id: string; id: string;

View File

@@ -12,7 +12,7 @@ import {
} from "@shared/types"; } from "@shared/types";
import type { NotificationSettings } from "@shared/types"; import type { NotificationSettings } from "@shared/types";
import { client } from "~/utils/ApiClient"; import { client } from "~/utils/ApiClient";
import ParanoidModel from "./ParanoidModel"; import ParanoidModel from "./base/ParanoidModel";
import Field from "./decorators/Field"; import Field from "./decorators/Field";
class User extends ParanoidModel { class User extends ParanoidModel {
@@ -96,7 +96,9 @@ class User extends ParanoidModel {
get separateEditMode(): boolean { get separateEditMode(): boolean {
return !this.getPreference( return !this.getPreference(
UserPreference.SeamlessEdit, UserPreference.SeamlessEdit,
this.store.rootStore.auth.team.getPreference(TeamPreference.SeamlessEdit) this.store.rootStore.auth?.team?.getPreference(
TeamPreference.SeamlessEdit
)
); );
} }

View File

@@ -1,8 +1,8 @@
import { action } from "mobx"; import { action } from "mobx";
import BaseModel from "./BaseModel";
import User from "./User"; import User from "./User";
import Model from "./base/Model";
class View extends BaseModel { class View extends Model {
id: string; id: string;
documentId: string; documentId: string;

View File

@@ -1,8 +1,8 @@
import { observable } from "mobx"; import { observable } from "mobx";
import BaseModel from "./BaseModel"; import Model from "./base/Model";
import Field from "./decorators/Field"; import Field from "./decorators/Field";
class WebhookSubscription extends BaseModel { class WebhookSubscription extends Model {
@Field @Field
@observable @observable
id: string; id: string;

View File

@@ -1,9 +1,10 @@
import pick from "lodash/pick"; import pick from "lodash/pick";
import { set, observable } from "mobx"; import { set, observable, action } from "mobx";
import type Store from "~/stores/base/Store";
import Logger from "~/utils/Logger"; import Logger from "~/utils/Logger";
import { getFieldsForModel } from "./decorators/Field"; import { getFieldsForModel } from "../decorators/Field";
export default abstract class BaseModel { export default abstract class Model {
@observable @observable
id: string; id: string;
@@ -17,12 +18,12 @@ export default abstract class BaseModel {
updatedAt: string; updatedAt: string;
store: any; store: Store<Model>;
constructor(fields: Record<string, any>, store: any) { constructor(fields: Record<string, any>, store: Store<Model>) {
this.updateFromJson(fields);
this.isNew = !this.id;
this.store = store; this.store = store;
this.updateData(fields);
this.isNew = !this.id;
} }
save = async ( save = async (
@@ -59,10 +60,14 @@ export default abstract class BaseModel {
} }
}; };
updateFromJson = (data: any) => { updateData = action((data: any) => {
set(this, { ...data, isNew: false }); for (const key in data) {
this[key] = data[key];
}
this.isNew = false;
this.persistedAttributes = this.toAPI(); this.persistedAttributes = this.toAPI();
}; });
fetch = (options?: any) => this.store.fetch(this.id, options); fetch = (options?: any) => this.store.fetch(this.id, options);
@@ -134,5 +139,5 @@ export default abstract class BaseModel {
); );
} }
protected persistedAttributes: Partial<BaseModel> = {}; protected persistedAttributes: Partial<Model> = {};
} }

View File

@@ -0,0 +1,5 @@
import Model from "./Model";
export default abstract class ParanoidModel extends Model {
deletedAt: string | undefined;
}

View File

@@ -1,6 +1,8 @@
import type Model from "../base/Model";
const fields = new Map(); const fields = new Map();
export const getFieldsForModel = (target: any) => export const getFieldsForModel = (target: Model) =>
fields.get(target.constructor.name); fields.get(target.constructor.name);
/** /**

View File

@@ -0,0 +1,59 @@
import invariant from "invariant";
import type Model from "../base/Model";
type RelationOptions = {
/** Whether this relation is required */
required?: boolean;
};
/**
* A decorator that records this key as a relation field on the model.
* Properties decorated with @Relation will merge and read their data from
* the associated store.
*
* @param classResolver A function that returns the class of the relation
* @param options Optional options for the relation definition
*/
export default function Relation<T extends typeof Model>(
classResolver: () => T,
options?: RelationOptions
) {
return function (target: any, propertyKey: string) {
const idKey = `${String(propertyKey)}Id`;
const relationClass = classResolver();
const relationClassName = relationClass.name;
Object.defineProperty(target, propertyKey, {
get() {
const id: string | undefined = this[idKey];
if (!id) {
return undefined;
}
const store =
this.store.rootStore[`${relationClassName.toLowerCase()}s`];
invariant(store, `Store for ${relationClassName} not found`);
return store.get(id);
},
set(newValue: Model | Partial<Model> | undefined) {
this[idKey] = newValue ? newValue.id : undefined;
if (newValue) {
const store =
this.store.rootStore[`${relationClassName.toLowerCase()}s`];
invariant(store, `Store for ${relationClassName} not found`);
store.add(newValue);
} else if (options?.required) {
throw new Error(
`Cannot set required ${String(propertyKey)} to undefined`
);
}
},
enumerable: true,
configurable: true,
});
};
}

View File

@@ -3,7 +3,7 @@ import { observer } from "mobx-react";
import * as React from "react"; import * as React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import styled from "styled-components"; import styled from "styled-components";
import { PAGINATION_SYMBOL } from "~/stores/BaseStore"; import { PAGINATION_SYMBOL } from "~/stores/base/Store";
import Collection from "~/models/Collection"; import Collection from "~/models/Collection";
import User from "~/models/User"; import User from "~/models/User";
import Avatar from "~/components/Avatar"; import Avatar from "~/components/Avatar";

View File

@@ -21,7 +21,7 @@ function GroupNew({ onSubmit }: Props) {
const { showToast } = useToasts(); const { showToast } = useToasts();
const [name, setName] = React.useState<string | undefined>(); const [name, setName] = React.useState<string | undefined>();
const [isSaving, setIsSaving] = React.useState(false); const [isSaving, setIsSaving] = React.useState(false);
const [group, setGroup] = React.useState(); const [group, setGroup] = React.useState<Group | undefined>();
const handleSubmit = async (ev: React.SyntheticEvent) => { const handleSubmit = async (ev: React.SyntheticEvent) => {
ev.preventDefault(); ev.preventDefault();
@@ -35,7 +35,8 @@ function GroupNew({ onSubmit }: Props) {
); );
try { try {
setGroup(await group.save()); await group.save();
setGroup(group);
} catch (err) { } catch (err) {
showToast(err.message, { showToast(err.message, {
type: "error", type: "error",

View File

@@ -10,9 +10,9 @@ import styled from "styled-components";
import breakpoint from "styled-components-breakpoint"; import breakpoint from "styled-components-breakpoint";
import { v4 as uuidv4 } from "uuid"; import { v4 as uuidv4 } from "uuid";
import { DateFilter as TDateFilter } from "@shared/types"; import { DateFilter as TDateFilter } from "@shared/types";
import { DEFAULT_PAGINATION_LIMIT } from "~/stores/BaseStore";
import { SearchParams } from "~/stores/DocumentsStore"; import { SearchParams } from "~/stores/DocumentsStore";
import RootStore from "~/stores/RootStore"; import RootStore from "~/stores/RootStore";
import { DEFAULT_PAGINATION_LIMIT } from "~/stores/base/Store";
import ArrowKeyNavigation from "~/components/ArrowKeyNavigation"; import ArrowKeyNavigation from "~/components/ArrowKeyNavigation";
import DocumentListItem from "~/components/DocumentListItem"; import DocumentListItem from "~/components/DocumentListItem";
import Empty from "~/components/Empty"; import Empty from "~/components/Empty";

View File

@@ -5,7 +5,7 @@ import * as React from "react";
import { Trans, useTranslation } from "react-i18next"; import { Trans, useTranslation } from "react-i18next";
import { useHistory, useLocation } from "react-router-dom"; import { useHistory, useLocation } from "react-router-dom";
import styled from "styled-components"; import styled from "styled-components";
import { PAGINATION_SYMBOL } from "~/stores/BaseStore"; import { PAGINATION_SYMBOL } from "~/stores/base/Store";
import User from "~/models/User"; import User from "~/models/User";
import Invite from "~/scenes/Invite"; import Invite from "~/scenes/Invite";
import { Action } from "~/components/Actions"; import { Action } from "~/components/Actions";

View File

@@ -4,7 +4,7 @@ import { LinkIcon, WarningIcon } from "outline-icons";
import * as React from "react"; import * as React from "react";
import { useTranslation, Trans } from "react-i18next"; import { useTranslation, Trans } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { PAGINATION_SYMBOL } from "~/stores/BaseStore"; import { PAGINATION_SYMBOL } from "~/stores/base/Store";
import Share from "~/models/Share"; import Share from "~/models/Share";
import Heading from "~/components/Heading"; import Heading from "~/components/Heading";
import Notice from "~/components/Notice"; import Notice from "~/components/Notice";

View File

@@ -1,8 +1,8 @@
import ApiKey from "~/models/ApiKey"; import ApiKey from "~/models/ApiKey";
import BaseStore, { RPCAction } from "./BaseStore";
import RootStore from "./RootStore"; import RootStore from "./RootStore";
import Store, { RPCAction } from "./base/Store";
export default class ApiKeysStore extends BaseStore<ApiKey> { export default class ApiKeysStore extends Store<ApiKey> {
actions = [RPCAction.List, RPCAction.Create, RPCAction.Delete]; actions = [RPCAction.List, RPCAction.Create, RPCAction.Delete];
constructor(rootStore: RootStore) { constructor(rootStore: RootStore) {

View File

@@ -138,8 +138,8 @@ export default class AuthStore {
@action @action
rehydrate(data: PersistedData) { rehydrate(data: PersistedData) {
this.user = data.user ? new User(data.user, this) : undefined; this.user = data.user ? new User(data.user, this as any) : undefined;
this.team = data.team ? new Team(data.team, this) : undefined; this.team = data.team ? new Team(data.team, this as any) : undefined;
this.collaborationToken = data.collaborationToken; this.collaborationToken = data.collaborationToken;
this.lastSignedIn = getCookie("lastSignedIn"); this.lastSignedIn = getCookie("lastSignedIn");
this.addPolicies(data.policies); this.addPolicies(data.policies);
@@ -188,8 +188,8 @@ export default class AuthStore {
runInAction("AuthStore#fetch", () => { runInAction("AuthStore#fetch", () => {
this.addPolicies(res.policies); this.addPolicies(res.policies);
const { user, team } = res.data; const { user, team } = res.data;
this.user = new User(user, this); this.user = new User(user, this as any);
this.team = new Team(team, this); this.team = new Team(team, this as any);
this.availableTeams = res.data.availableTeams; this.availableTeams = res.data.availableTeams;
this.collaborationToken = res.data.collaborationToken; this.collaborationToken = res.data.collaborationToken;
@@ -283,13 +283,13 @@ export default class AuthStore {
const previousData = this.user?.toAPI(); const previousData = this.user?.toAPI();
try { try {
this.user?.updateFromJson(params); this.user?.updateData(params);
const res = await client.post(`/users.update`, params); const res = await client.post(`/users.update`, params);
invariant(res?.data, "User response not available"); invariant(res?.data, "User response not available");
this.user?.updateFromJson(res.data); this.user?.updateData(res.data);
this.addPolicies(res.policies); this.addPolicies(res.policies);
} catch (err) { } catch (err) {
this.user?.updateFromJson(previousData); this.user?.updateData(previousData);
throw err; throw err;
} finally { } finally {
this.isSaving = false; this.isSaving = false;
@@ -310,13 +310,13 @@ export default class AuthStore {
const previousData = this.team?.toAPI(); const previousData = this.team?.toAPI();
try { try {
this.team?.updateFromJson(params); this.team?.updateData(params);
const res = await client.post(`/team.update`, params); const res = await client.post(`/team.update`, params);
invariant(res?.data, "Team response not available"); invariant(res?.data, "Team response not available");
this.team?.updateFromJson(res.data); this.team?.updateData(res.data);
this.addPolicies(res.policies); this.addPolicies(res.policies);
} catch (err) { } catch (err) {
this.team?.updateFromJson(previousData); this.team?.updateData(previousData);
throw err; throw err;
} finally { } finally {
this.isSaving = false; this.isSaving = false;

View File

@@ -1,8 +1,8 @@
import AuthenticationProvider from "~/models/AuthenticationProvider"; import AuthenticationProvider from "~/models/AuthenticationProvider";
import BaseStore, { RPCAction } from "./BaseStore";
import RootStore from "./RootStore"; import RootStore from "./RootStore";
import Store, { RPCAction } from "./base/Store";
export default class AuthenticationProvidersStore extends BaseStore<AuthenticationProvider> { export default class AuthenticationProvidersStore extends Store<AuthenticationProvider> {
actions = [RPCAction.List, RPCAction.Update]; actions = [RPCAction.List, RPCAction.Update];
constructor(rootStore: RootStore) { constructor(rootStore: RootStore) {

View File

@@ -4,10 +4,10 @@ import { CollectionPermission } from "@shared/types";
import CollectionGroupMembership from "~/models/CollectionGroupMembership"; import CollectionGroupMembership from "~/models/CollectionGroupMembership";
import { PaginationParams } from "~/types"; import { PaginationParams } from "~/types";
import { client } from "~/utils/ApiClient"; import { client } from "~/utils/ApiClient";
import BaseStore, { PAGINATION_SYMBOL, RPCAction } from "./BaseStore";
import RootStore from "./RootStore"; import RootStore from "./RootStore";
import Store, { PAGINATION_SYMBOL, RPCAction } from "./base/Store";
export default class CollectionGroupMembershipsStore extends BaseStore<CollectionGroupMembership> { export default class CollectionGroupMembershipsStore extends Store<CollectionGroupMembership> {
actions = [RPCAction.Create, RPCAction.Delete]; actions = [RPCAction.Create, RPCAction.Delete];
constructor(rootStore: RootStore) { constructor(rootStore: RootStore) {

View File

@@ -12,8 +12,8 @@ import {
import Collection from "~/models/Collection"; import Collection from "~/models/Collection";
import { client } from "~/utils/ApiClient"; import { client } from "~/utils/ApiClient";
import { AuthorizationError, NotFoundError } from "~/utils/errors"; import { AuthorizationError, NotFoundError } from "~/utils/errors";
import BaseStore from "./BaseStore";
import RootStore from "./RootStore"; import RootStore from "./RootStore";
import Store from "./base/Store";
enum DocumentPathItemType { enum DocumentPathItemType {
Collection = "collection", Collection = "collection",
@@ -32,7 +32,7 @@ export type DocumentPath = DocumentPathItem & {
path: DocumentPathItem[]; path: DocumentPathItem[];
}; };
export default class CollectionsStore extends BaseStore<Collection> { export default class CollectionsStore extends Store<Collection> {
constructor(rootStore: RootStore) { constructor(rootStore: RootStore) {
super(rootStore, Collection); super(rootStore, Collection);
} }

View File

@@ -6,10 +6,10 @@ import Comment from "~/models/Comment";
import Document from "~/models/Document"; import Document from "~/models/Document";
import { PaginationParams } from "~/types"; import { PaginationParams } from "~/types";
import { client } from "~/utils/ApiClient"; import { client } from "~/utils/ApiClient";
import BaseStore from "./BaseStore";
import RootStore from "./RootStore"; import RootStore from "./RootStore";
import Store from "./base/Store";
export default class CommentsStore extends BaseStore<Comment> { export default class CommentsStore extends Store<Comment> {
apiEndpoint = "comments"; apiEndpoint = "comments";
constructor(rootStore: RootStore) { constructor(rootStore: RootStore) {

View File

@@ -10,8 +10,8 @@ import { subtractDate } from "@shared/utils/date";
import { bytesToHumanReadable } from "@shared/utils/files"; import { bytesToHumanReadable } from "@shared/utils/files";
import naturalSort from "@shared/utils/naturalSort"; import naturalSort from "@shared/utils/naturalSort";
import { DocumentValidation } from "@shared/validations"; import { DocumentValidation } from "@shared/validations";
import BaseStore from "~/stores/BaseStore";
import RootStore from "~/stores/RootStore"; import RootStore from "~/stores/RootStore";
import Store from "~/stores/base/Store";
import Document from "~/models/Document"; import Document from "~/models/Document";
import env from "~/env"; import env from "~/env";
import { FetchOptions, PaginationParams, SearchResult } from "~/types"; import { FetchOptions, PaginationParams, SearchResult } from "~/types";
@@ -38,7 +38,7 @@ type ImportOptions = {
publish?: boolean; publish?: boolean;
}; };
export default class DocumentsStore extends BaseStore<Document> { export default class DocumentsStore extends Store<Document> {
sharedCache: Map< sharedCache: Map<
string, string,
{ sharedTree: NavigationNode; team: PublicTeam } | undefined { sharedTree: NavigationNode; team: PublicTeam } | undefined
@@ -574,7 +574,7 @@ export default class DocumentsStore extends BaseStore<Document> {
invariant(res?.data, "Data should be available"); invariant(res?.data, "Data should be available");
const collection = this.getCollectionForDocument(document); const collection = this.getCollectionForDocument(document);
if (collection) { if (collection) {
collection.refresh(); await collection.refresh();
} }
this.addPolicies(res.policies); this.addPolicies(res.policies);
return this.add(res.data); return this.add(res.data);
@@ -686,7 +686,7 @@ export default class DocumentsStore extends BaseStore<Document> {
this.addPolicies(res.policies); this.addPolicies(res.policies);
const document = this.add(res.data.document); const document = this.add(res.data.document);
const collection = this.getCollectionForDocument(document); const collection = this.getCollectionForDocument(document);
collection?.updateFromJson(res.data.collection); collection?.updateData(res.data.collection);
return document; return document;
} finally { } finally {
this.isSaving = false; this.isSaving = false;
@@ -711,7 +711,7 @@ export default class DocumentsStore extends BaseStore<Document> {
const collection = this.getCollectionForDocument(document); const collection = this.getCollectionForDocument(document);
if (collection) { if (collection) {
collection.refresh(); await collection.refresh();
} }
} }
@@ -722,12 +722,12 @@ export default class DocumentsStore extends BaseStore<Document> {
}); });
runInAction("Document#archive", () => { runInAction("Document#archive", () => {
invariant(res?.data, "Data should be available"); invariant(res?.data, "Data should be available");
document.updateFromJson(res.data); document.updateData(res.data);
this.addPolicies(res.policies); this.addPolicies(res.policies);
}); });
const collection = this.getCollectionForDocument(document); const collection = this.getCollectionForDocument(document);
if (collection) { if (collection) {
collection.refresh(); await collection.refresh();
} }
}; };
@@ -746,12 +746,12 @@ export default class DocumentsStore extends BaseStore<Document> {
}); });
runInAction("Document#restore", () => { runInAction("Document#restore", () => {
invariant(res?.data, "Data should be available"); invariant(res?.data, "Data should be available");
document.updateFromJson(res.data); document.updateData(res.data);
this.addPolicies(res.policies); this.addPolicies(res.policies);
}); });
const collection = this.getCollectionForDocument(document); const collection = this.getCollectionForDocument(document);
if (collection) { if (collection) {
collection.refresh(); await collection.refresh();
} }
}; };
@@ -764,9 +764,9 @@ export default class DocumentsStore extends BaseStore<Document> {
runInAction("Document#unpublish", () => { runInAction("Document#unpublish", () => {
invariant(res?.data, "Data should be available"); invariant(res?.data, "Data should be available");
document.updateFromJson(res.data.document); document.updateData(res.data.document);
const collection = this.getCollectionForDocument(document); const collection = this.getCollectionForDocument(document);
collection?.updateFromJson(res.data.collection); collection?.updateData(res.data.collection);
this.addPolicies(res.policies); this.addPolicies(res.policies);
}); });
}; };

View File

@@ -2,10 +2,10 @@ import filter from "lodash/filter";
import sortBy from "lodash/sortBy"; import sortBy from "lodash/sortBy";
import { computed } from "mobx"; import { computed } from "mobx";
import Event from "~/models/Event"; import Event from "~/models/Event";
import BaseStore, { RPCAction } from "./BaseStore";
import RootStore from "./RootStore"; import RootStore from "./RootStore";
import Store, { RPCAction } from "./base/Store";
export default class EventsStore extends BaseStore<Event> { export default class EventsStore extends Store<Event> {
actions = [RPCAction.List]; actions = [RPCAction.List];
constructor(rootStore: RootStore) { constructor(rootStore: RootStore) {

View File

@@ -2,10 +2,10 @@ import orderBy from "lodash/orderBy";
import { computed } from "mobx"; import { computed } from "mobx";
import { FileOperationType } from "@shared/types"; import { FileOperationType } from "@shared/types";
import FileOperation from "~/models/FileOperation"; import FileOperation from "~/models/FileOperation";
import BaseStore, { RPCAction } from "./BaseStore";
import RootStore from "./RootStore"; import RootStore from "./RootStore";
import Store, { RPCAction } from "./base/Store";
export default class FileOperationsStore extends BaseStore<FileOperation> { export default class FileOperationsStore extends Store<FileOperation> {
actions = [RPCAction.List, RPCAction.Info, RPCAction.Delete]; actions = [RPCAction.List, RPCAction.Info, RPCAction.Delete];
constructor(rootStore: RootStore) { constructor(rootStore: RootStore) {

View File

@@ -4,10 +4,10 @@ import { action, runInAction } from "mobx";
import GroupMembership from "~/models/GroupMembership"; import GroupMembership from "~/models/GroupMembership";
import { PaginationParams } from "~/types"; import { PaginationParams } from "~/types";
import { client } from "~/utils/ApiClient"; import { client } from "~/utils/ApiClient";
import BaseStore, { RPCAction } from "./BaseStore";
import RootStore from "./RootStore"; import RootStore from "./RootStore";
import Store, { RPCAction } from "./base/Store";
export default class GroupMembershipsStore extends BaseStore<GroupMembership> { export default class GroupMembershipsStore extends Store<GroupMembership> {
actions = [RPCAction.Create, RPCAction.Delete]; actions = [RPCAction.Create, RPCAction.Delete];
constructor(rootStore: RootStore) { constructor(rootStore: RootStore) {

View File

@@ -5,12 +5,12 @@ import naturalSort from "@shared/utils/naturalSort";
import Group from "~/models/Group"; import Group from "~/models/Group";
import { PaginationParams } from "~/types"; import { PaginationParams } from "~/types";
import { client } from "~/utils/ApiClient"; import { client } from "~/utils/ApiClient";
import BaseStore from "./BaseStore";
import RootStore from "./RootStore"; import RootStore from "./RootStore";
import Store from "./base/Store";
type FetchPageParams = PaginationParams & { query?: string }; type FetchPageParams = PaginationParams & { query?: string };
export default class GroupsStore extends BaseStore<Group> { export default class GroupsStore extends Store<Group> {
constructor(rootStore: RootStore) { constructor(rootStore: RootStore) {
super(rootStore, Group); super(rootStore, Group);
} }

View File

@@ -2,11 +2,11 @@ import filter from "lodash/filter";
import { computed } from "mobx"; import { computed } from "mobx";
import { IntegrationService } from "@shared/types"; import { IntegrationService } from "@shared/types";
import naturalSort from "@shared/utils/naturalSort"; import naturalSort from "@shared/utils/naturalSort";
import BaseStore from "~/stores/BaseStore";
import RootStore from "~/stores/RootStore"; import RootStore from "~/stores/RootStore";
import Store from "~/stores/base/Store";
import Integration from "~/models/Integration"; import Integration from "~/models/Integration";
class IntegrationsStore extends BaseStore<Integration> { class IntegrationsStore extends Store<Integration> {
constructor(rootStore: RootStore) { constructor(rootStore: RootStore) {
super(rootStore, Integration); super(rootStore, Integration);
} }

View File

@@ -4,10 +4,10 @@ import { CollectionPermission } from "@shared/types";
import Membership from "~/models/Membership"; import Membership from "~/models/Membership";
import { PaginationParams } from "~/types"; import { PaginationParams } from "~/types";
import { client } from "~/utils/ApiClient"; import { client } from "~/utils/ApiClient";
import BaseStore, { PAGINATION_SYMBOL, RPCAction } from "./BaseStore";
import RootStore from "./RootStore"; import RootStore from "./RootStore";
import Store, { PAGINATION_SYMBOL, RPCAction } from "./base/Store";
export default class MembershipsStore extends BaseStore<Membership> { export default class MembershipsStore extends Store<Membership> {
actions = [RPCAction.Create, RPCAction.Delete]; actions = [RPCAction.Create, RPCAction.Delete];
constructor(rootStore: RootStore) { constructor(rootStore: RootStore) {

View File

@@ -5,10 +5,10 @@ import { action, computed, runInAction } from "mobx";
import Notification from "~/models/Notification"; import Notification from "~/models/Notification";
import { PaginationParams } from "~/types"; import { PaginationParams } from "~/types";
import { client } from "~/utils/ApiClient"; import { client } from "~/utils/ApiClient";
import BaseStore, { RPCAction } from "./BaseStore";
import RootStore from "./RootStore"; import RootStore from "./RootStore";
import Store, { RPCAction } from "./base/Store";
export default class NotificationsStore extends BaseStore<Notification> { export default class NotificationsStore extends Store<Notification> {
actions = [RPCAction.List, RPCAction.Update]; actions = [RPCAction.List, RPCAction.Update];
constructor(rootStore: RootStore) { constructor(rootStore: RootStore) {

View File

@@ -3,12 +3,12 @@ import { action, runInAction, computed } from "mobx";
import Pin from "~/models/Pin"; import Pin from "~/models/Pin";
import { PaginationParams } from "~/types"; import { PaginationParams } from "~/types";
import { client } from "~/utils/ApiClient"; import { client } from "~/utils/ApiClient";
import BaseStore from "./BaseStore";
import RootStore from "./RootStore"; import RootStore from "./RootStore";
import Store from "./base/Store";
type FetchParams = PaginationParams & { collectionId?: string }; type FetchParams = PaginationParams & { collectionId?: string };
export default class PinsStore extends BaseStore<Pin> { export default class PinsStore extends Store<Pin> {
constructor(rootStore: RootStore) { constructor(rootStore: RootStore) {
super(rootStore, Pin); super(rootStore, Pin);
} }

View File

@@ -1,8 +1,8 @@
import Policy from "~/models/Policy"; import Policy from "~/models/Policy";
import BaseStore from "./BaseStore";
import RootStore from "./RootStore"; import RootStore from "./RootStore";
import Store from "./base/Store";
export default class PoliciesStore extends BaseStore<Policy> { export default class PoliciesStore extends Store<Policy> {
actions = []; actions = [];
constructor(rootStore: RootStore) { constructor(rootStore: RootStore) {

View File

@@ -1,13 +1,13 @@
import invariant from "invariant"; import invariant from "invariant";
import filter from "lodash/filter"; import filter from "lodash/filter";
import { action, runInAction } from "mobx"; import { action, runInAction } from "mobx";
import BaseStore, { RPCAction } from "~/stores/BaseStore";
import RootStore from "~/stores/RootStore"; import RootStore from "~/stores/RootStore";
import Store, { RPCAction } from "~/stores/base/Store";
import Revision from "~/models/Revision"; import Revision from "~/models/Revision";
import { PaginationParams } from "~/types"; import { PaginationParams } from "~/types";
import { client } from "~/utils/ApiClient"; import { client } from "~/utils/ApiClient";
export default class RevisionsStore extends BaseStore<Revision> { export default class RevisionsStore extends Store<Revision> {
actions = [RPCAction.List, RPCAction.Info]; actions = [RPCAction.List, RPCAction.Info];
constructor(rootStore: RootStore) { constructor(rootStore: RootStore) {

View File

@@ -1,10 +1,10 @@
import uniqBy from "lodash/uniqBy"; import uniqBy from "lodash/uniqBy";
import { computed } from "mobx"; import { computed } from "mobx";
import SearchQuery from "~/models/SearchQuery"; import SearchQuery from "~/models/SearchQuery";
import BaseStore, { RPCAction } from "./BaseStore";
import RootStore from "./RootStore"; import RootStore from "./RootStore";
import Store, { RPCAction } from "./base/Store";
export default class SearchesStore extends BaseStore<SearchQuery> { export default class SearchesStore extends Store<SearchQuery> {
actions = [RPCAction.List, RPCAction.Delete]; actions = [RPCAction.List, RPCAction.Delete];
apiEndpoint = "searches"; apiEndpoint = "searches";

View File

@@ -6,10 +6,10 @@ import sortBy from "lodash/sortBy";
import { action, computed } from "mobx"; import { action, computed } from "mobx";
import Share from "~/models/Share"; import Share from "~/models/Share";
import { client } from "~/utils/ApiClient"; import { client } from "~/utils/ApiClient";
import BaseStore, { RPCAction } from "./BaseStore";
import RootStore from "./RootStore"; import RootStore from "./RootStore";
import Store, { RPCAction } from "./base/Store";
export default class SharesStore extends BaseStore<Share> { export default class SharesStore extends Store<Share> {
actions = [ actions = [
RPCAction.Info, RPCAction.Info,
RPCAction.List, RPCAction.List,

View File

@@ -3,10 +3,10 @@ import { action, runInAction, computed } from "mobx";
import Star from "~/models/Star"; import Star from "~/models/Star";
import { PaginationParams } from "~/types"; import { PaginationParams } from "~/types";
import { client } from "~/utils/ApiClient"; import { client } from "~/utils/ApiClient";
import BaseStore from "./BaseStore";
import RootStore from "./RootStore"; import RootStore from "./RootStore";
import Store from "./base/Store";
export default class StarsStore extends BaseStore<Star> { export default class StarsStore extends Store<Star> {
constructor(rootStore: RootStore) { constructor(rootStore: RootStore) {
super(rootStore, Star); super(rootStore, Star);
} }

View File

@@ -1,8 +1,8 @@
import Subscription from "~/models/Subscription"; import Subscription from "~/models/Subscription";
import BaseStore, { RPCAction } from "./BaseStore";
import RootStore from "./RootStore"; import RootStore from "./RootStore";
import Store, { RPCAction } from "./base/Store";
export default class SubscriptionsStore extends BaseStore<Subscription> { export default class SubscriptionsStore extends Store<Subscription> {
actions = [RPCAction.List, RPCAction.Create, RPCAction.Delete]; actions = [RPCAction.List, RPCAction.Create, RPCAction.Delete];
constructor(rootStore: RootStore) { constructor(rootStore: RootStore) {

View File

@@ -5,10 +5,10 @@ import { observable, computed, action, runInAction } from "mobx";
import { UserRole } from "@shared/types"; import { UserRole } from "@shared/types";
import User from "~/models/User"; import User from "~/models/User";
import { client } from "~/utils/ApiClient"; import { client } from "~/utils/ApiClient";
import BaseStore from "./BaseStore";
import RootStore from "./RootStore"; import RootStore from "./RootStore";
import Store from "./base/Store";
export default class UsersStore extends BaseStore<User> { export default class UsersStore extends Store<User> {
@observable @observable
counts: { counts: {
active: number; active: number;

View File

@@ -3,10 +3,10 @@ import find from "lodash/find";
import orderBy from "lodash/orderBy"; import orderBy from "lodash/orderBy";
import reduce from "lodash/reduce"; import reduce from "lodash/reduce";
import View from "~/models/View"; import View from "~/models/View";
import BaseStore, { RPCAction } from "./BaseStore";
import RootStore from "./RootStore"; import RootStore from "./RootStore";
import Store, { RPCAction } from "./base/Store";
export default class ViewsStore extends BaseStore<View> { export default class ViewsStore extends Store<View> {
actions = [RPCAction.List, RPCAction.Create]; actions = [RPCAction.List, RPCAction.Create];
constructor(rootStore: RootStore) { constructor(rootStore: RootStore) {

View File

@@ -1,9 +1,9 @@
import { computed } from "mobx"; import { computed } from "mobx";
import WebhookSubscription from "~/models/WebhookSubscription"; import WebhookSubscription from "~/models/WebhookSubscription";
import BaseStore, { RPCAction } from "./BaseStore";
import RootStore from "./RootStore"; import RootStore from "./RootStore";
import Store, { RPCAction } from "./base/Store";
export default class WebhookSubscriptionsStore extends BaseStore<WebhookSubscription> { export default class WebhookSubscriptionsStore extends Store<WebhookSubscription> {
actions = [ actions = [
RPCAction.List, RPCAction.List,
RPCAction.Create, RPCAction.Create,

View File

@@ -4,8 +4,8 @@ import orderBy from "lodash/orderBy";
import { observable, action, computed, runInAction } from "mobx"; import { observable, action, computed, runInAction } from "mobx";
import { Class } from "utility-types"; import { Class } from "utility-types";
import RootStore from "~/stores/RootStore"; import RootStore from "~/stores/RootStore";
import BaseModel from "~/models/BaseModel";
import Policy from "~/models/Policy"; import Policy from "~/models/Policy";
import Model from "~/models/base/Model";
import { PaginationParams, PartialWithId } from "~/types"; import { PaginationParams, PartialWithId } from "~/types";
import { client } from "~/utils/ApiClient"; import { client } from "~/utils/ApiClient";
import { AuthorizationError, NotFoundError } from "~/utils/errors"; import { AuthorizationError, NotFoundError } from "~/utils/errors";
@@ -25,7 +25,7 @@ export const DEFAULT_PAGINATION_LIMIT = 25;
export const PAGINATION_SYMBOL = Symbol.for("pagination"); export const PAGINATION_SYMBOL = Symbol.for("pagination");
export default abstract class BaseStore<T extends BaseModel> { export default abstract class Store<T extends Model> {
@observable @observable
data: Map<string, T> = new Map(); data: Map<string, T> = new Map();
@@ -84,7 +84,7 @@ export default abstract class BaseStore<T extends BaseModel> {
const existingModel = this.data.get(item.id); const existingModel = this.data.get(item.id);
if (existingModel) { if (existingModel) {
existingModel.updateFromJson(item); existingModel.updateData(item);
return existingModel; return existingModel;
} }

View File

@@ -1,5 +1,11 @@
import RootStore from "~/stores/RootStore"; import RootStore from "~/stores/RootStore";
import env from "~/env";
const stores = new RootStore(); const stores = new RootStore();
// Expose stores on window in development for easier debugging
if (env.ENVIRONMENT === "development") {
window.stores = stores;
}
export default stores; export default stores;

View File

@@ -1,3 +1,5 @@
import type RootStore from "~/stores/RootStore";
declare global { declare global {
interface ImportMeta { interface ImportMeta {
/** /**
@@ -10,6 +12,8 @@ declare global {
dataLayer: any[]; dataLayer: any[];
gtag: (...args: any[]) => void; gtag: (...args: any[]) => void;
stores: RootStore;
DesktopBridge: { DesktopBridge: {
/** /**
* The name of the platform running on. * The name of the platform running on.