mirror of
https://github.com/outline/outline.git
synced 2026-06-13 11:25:03 +03:00
0139b91b5d
* chore: Replace lodash with es-toolkit Migrate all direct lodash imports to es-toolkit/compat for a smaller, faster, lodash-compatible utility library. Transitive lodash usage from other packages remains unchanged. * fix: Restore isPlainObject semantics in CanCan policy The lodash migration aliased `isObject` to `lodash/isPlainObject` and the codemod incorrectly mapped the local name to es-toolkit's `isObject`, which also returns true for arrays and functions. This caused condition objects in policy definitions to be skipped, breaking authorization checks across the codebase. * fix: Restore unicode-aware length counting in validators es-toolkit/compat's size() returns string.length, while lodash's _.size() counts unicode code points. Switch to [...value].length to preserve the previous behavior so multi-byte characters like emoji count as one.
82 lines
1.9 KiB
TypeScript
82 lines
1.9 KiB
TypeScript
import { filter, orderBy } from "es-toolkit/compat";
|
|
import { action, computed } from "mobx";
|
|
import { invariant } from "mobx-utils";
|
|
import naturalSort from "@shared/utils/naturalSort";
|
|
import Template from "~/models/Template";
|
|
import { client } from "~/utils/ApiClient";
|
|
import type RootStore from "./RootStore";
|
|
import Store from "./base/Store";
|
|
|
|
export default class TemplatesStore extends Store<Template> {
|
|
constructor(rootStore: RootStore) {
|
|
super(rootStore, Template);
|
|
}
|
|
|
|
@computed
|
|
get alphabetical(): Template[] {
|
|
return naturalSort(Array.from(this.data.values()), "title");
|
|
}
|
|
|
|
@computed
|
|
get all(): Template[] {
|
|
return filter(this.orderedData, (d) => !d.deletedAt);
|
|
}
|
|
|
|
@action
|
|
duplicate = async (
|
|
template: Template,
|
|
options?: {
|
|
title?: string;
|
|
publish?: boolean;
|
|
}
|
|
) => {
|
|
const res = await client.post("/templates.duplicate", {
|
|
id: template.id,
|
|
...options,
|
|
});
|
|
invariant(res?.data, "Data should be available");
|
|
|
|
this.addPolicies(res.policies);
|
|
this.add(res.data);
|
|
};
|
|
|
|
@action
|
|
templatize = async ({
|
|
id,
|
|
collectionId,
|
|
publish,
|
|
}: {
|
|
id: string;
|
|
collectionId: string | null;
|
|
publish: boolean;
|
|
}): Promise<Template | undefined> => {
|
|
const res = await client.post("/documents.templatize", {
|
|
id,
|
|
collectionId,
|
|
publish,
|
|
});
|
|
invariant(res?.data, "Data should be available");
|
|
|
|
this.addPolicies(res.policies);
|
|
this.add(res.data);
|
|
return this.data.get(res.data.id);
|
|
};
|
|
|
|
get(id: string): Template | undefined {
|
|
return id
|
|
? (this.data.get(id) ??
|
|
this.orderedData.find((doc) => id.endsWith(doc.urlId)))
|
|
: undefined;
|
|
}
|
|
|
|
@computed
|
|
get active(): Template | undefined {
|
|
return this.rootStore.ui.getActiveModels(Template)?.[0];
|
|
}
|
|
|
|
@computed
|
|
get orderedData(): Template[] {
|
|
return orderBy(Array.from(this.data.values()), "createdAt", "desc");
|
|
}
|
|
}
|