2025-03-06 23:52:01 +02:00
|
|
|
import type { AttachmentRow } from "../../../becca/entities/rows.js";
|
2025-01-09 18:36:24 +02:00
|
|
|
import type { AttributeType } from "../entities/fattribute.js";
|
|
|
|
import type { EntityChange } from "../server_types.js";
|
2024-07-25 00:09:34 +03:00
|
|
|
|
2024-12-25 08:54:33 +02:00
|
|
|
// TODO: Deduplicate with server.
|
|
|
|
|
|
|
|
interface NoteRow {
|
|
|
|
isDeleted?: boolean;
|
|
|
|
}
|
|
|
|
|
2025-02-24 10:10:34 +02:00
|
|
|
// TODO: Deduplicate with BranchRow from `rows.ts`/
|
|
|
|
export interface BranchRow {
|
2025-01-19 20:53:52 +02:00
|
|
|
noteId?: string;
|
2024-07-25 00:09:34 +03:00
|
|
|
branchId: string;
|
|
|
|
componentId: string;
|
2025-01-04 22:08:07 +02:00
|
|
|
parentNoteId?: string;
|
2025-02-24 10:10:34 +02:00
|
|
|
isDeleted?: boolean;
|
|
|
|
isExpanded?: boolean;
|
2024-07-25 00:09:34 +03:00
|
|
|
}
|
|
|
|
|
2024-12-22 21:59:08 +02:00
|
|
|
export interface AttributeRow {
|
|
|
|
noteId?: string;
|
2024-07-25 00:09:34 +03:00
|
|
|
attributeId: string;
|
|
|
|
componentId: string;
|
2024-12-22 21:59:08 +02:00
|
|
|
isInheritable?: boolean;
|
2024-12-23 21:47:36 +02:00
|
|
|
isDeleted?: boolean;
|
|
|
|
name?: string;
|
|
|
|
value?: string;
|
|
|
|
type?: AttributeType;
|
2024-07-25 00:09:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
interface RevisionRow {
|
|
|
|
revisionId: string;
|
2024-07-25 20:42:56 +03:00
|
|
|
noteId?: string;
|
|
|
|
componentId?: string | null;
|
2024-07-25 00:09:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
interface ContentNoteIdToComponentIdRow {
|
|
|
|
noteId: string;
|
|
|
|
componentId: string;
|
|
|
|
}
|
|
|
|
|
2024-12-23 21:47:36 +02:00
|
|
|
interface OptionRow {}
|
|
|
|
|
|
|
|
interface NoteReorderingRow {}
|
|
|
|
|
2024-07-25 00:09:34 +03:00
|
|
|
interface ContentNoteIdToComponentIdRow {
|
|
|
|
noteId: string;
|
|
|
|
componentId: string;
|
|
|
|
}
|
|
|
|
|
2024-12-23 15:16:41 +02:00
|
|
|
type EntityRowMappings = {
|
2025-01-09 18:07:02 +02:00
|
|
|
notes: NoteRow;
|
|
|
|
branches: BranchRow;
|
|
|
|
attributes: AttributeRow;
|
|
|
|
options: OptionRow;
|
|
|
|
revisions: RevisionRow;
|
|
|
|
note_reordering: NoteReorderingRow;
|
|
|
|
};
|
2024-12-23 15:16:41 +02:00
|
|
|
|
|
|
|
export type EntityRowNames = keyof EntityRowMappings;
|
|
|
|
|
2020-02-05 22:46:20 +01:00
|
|
|
export default class LoadResults {
|
2024-12-23 15:16:41 +02:00
|
|
|
private entities: Record<keyof EntityRowMappings, Record<string, any>>;
|
2024-07-25 00:09:34 +03:00
|
|
|
private noteIdToComponentId: Record<string, string[]>;
|
|
|
|
private componentIdToNoteIds: Record<string, string[]>;
|
|
|
|
private branchRows: BranchRow[];
|
|
|
|
private attributeRows: AttributeRow[];
|
|
|
|
private revisionRows: RevisionRow[];
|
|
|
|
private noteReorderings: string[];
|
|
|
|
private contentNoteIdToComponentId: ContentNoteIdToComponentIdRow[];
|
|
|
|
private optionNames: string[];
|
|
|
|
private attachmentRows: AttachmentRow[];
|
|
|
|
|
|
|
|
constructor(entityChanges: EntityChange[]) {
|
2024-12-23 15:16:41 +02:00
|
|
|
const entities: Record<string, Record<string, any>> = {};
|
2021-08-20 21:42:06 +02:00
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
for (const { entityId, entityName, entity } of entityChanges) {
|
2021-08-20 21:42:06 +02:00
|
|
|
if (entity) {
|
2024-12-23 15:16:41 +02:00
|
|
|
entities[entityName] = entities[entityName] || [];
|
|
|
|
entities[entityName][entityId] = entity;
|
2021-08-20 21:42:06 +02:00
|
|
|
}
|
|
|
|
}
|
2024-12-23 15:16:41 +02:00
|
|
|
this.entities = entities;
|
2020-01-29 21:38:58 +01:00
|
|
|
|
2022-01-09 20:16:39 +01:00
|
|
|
this.noteIdToComponentId = {};
|
|
|
|
this.componentIdToNoteIds = {};
|
2020-05-14 13:08:06 +02:00
|
|
|
|
2023-06-05 16:12:02 +02:00
|
|
|
this.branchRows = [];
|
2020-01-30 22:38:31 +01:00
|
|
|
|
2023-06-05 16:12:02 +02:00
|
|
|
this.attributeRows = [];
|
2020-01-30 22:38:31 +01:00
|
|
|
|
|
|
|
this.noteReorderings = [];
|
|
|
|
|
2023-06-05 16:12:02 +02:00
|
|
|
this.revisionRows = [];
|
2020-01-31 22:32:24 +01:00
|
|
|
|
2022-01-09 20:16:39 +01:00
|
|
|
this.contentNoteIdToComponentId = [];
|
2020-02-05 22:08:45 +01:00
|
|
|
|
2023-06-05 16:12:02 +02:00
|
|
|
this.optionNames = [];
|
2023-04-01 23:55:04 +02:00
|
|
|
|
2023-06-05 16:12:02 +02:00
|
|
|
this.attachmentRows = [];
|
2020-01-27 22:58:03 +01:00
|
|
|
}
|
|
|
|
|
2024-12-23 15:16:41 +02:00
|
|
|
getEntityRow<T extends EntityRowNames>(entityName: T, entityId: string): EntityRowMappings[T] {
|
2025-01-09 18:07:02 +02:00
|
|
|
return this.entities[entityName]?.[entityId];
|
2021-08-20 21:42:06 +02:00
|
|
|
}
|
|
|
|
|
2024-07-25 20:42:56 +03:00
|
|
|
addNote(noteId: string, componentId?: string | null) {
|
2022-01-09 20:16:39 +01:00
|
|
|
this.noteIdToComponentId[noteId] = this.noteIdToComponentId[noteId] || [];
|
2020-01-27 22:58:03 +01:00
|
|
|
|
2024-07-25 20:42:56 +03:00
|
|
|
if (componentId) {
|
|
|
|
if (!this.noteIdToComponentId[noteId].includes(componentId)) {
|
|
|
|
this.noteIdToComponentId[noteId].push(componentId);
|
|
|
|
}
|
2024-12-22 21:59:08 +02:00
|
|
|
|
2024-07-25 20:42:56 +03:00
|
|
|
this.componentIdToNoteIds[componentId] = this.componentIdToNoteIds[componentId] || [];
|
2024-12-22 21:59:08 +02:00
|
|
|
|
2024-10-26 10:29:15 +03:00
|
|
|
if (this.componentIdToNoteIds[componentId]) {
|
2024-07-25 20:42:56 +03:00
|
|
|
this.componentIdToNoteIds[componentId].push(noteId);
|
|
|
|
}
|
2020-01-27 22:58:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-25 00:09:34 +03:00
|
|
|
addBranch(branchId: string, componentId: string) {
|
2025-01-09 18:07:02 +02:00
|
|
|
this.branchRows.push({ branchId, componentId });
|
2020-01-29 20:14:02 +01:00
|
|
|
}
|
|
|
|
|
2023-06-05 16:12:02 +02:00
|
|
|
getBranchRows() {
|
2025-01-09 18:07:02 +02:00
|
|
|
return this.branchRows.map((row) => this.getEntityRow("branches", row.branchId)).filter((branch) => !!branch);
|
2020-01-29 21:38:58 +01:00
|
|
|
}
|
|
|
|
|
2024-07-25 00:09:34 +03:00
|
|
|
addNoteReordering(parentNoteId: string, componentId: string) {
|
2020-01-30 22:38:31 +01:00
|
|
|
this.noteReorderings.push(parentNoteId);
|
2020-01-29 20:14:02 +01:00
|
|
|
}
|
|
|
|
|
2020-01-29 21:38:58 +01:00
|
|
|
getNoteReorderings() {
|
2020-01-30 22:38:31 +01:00
|
|
|
return this.noteReorderings;
|
2020-01-29 21:38:58 +01:00
|
|
|
}
|
|
|
|
|
2024-07-25 00:09:34 +03:00
|
|
|
addAttribute(attributeId: string, componentId: string) {
|
2025-01-09 18:07:02 +02:00
|
|
|
this.attributeRows.push({ attributeId, componentId });
|
2020-01-29 20:14:02 +01:00
|
|
|
}
|
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
getAttributeRows(componentId = "none"): AttributeRow[] {
|
2023-06-05 16:12:02 +02:00
|
|
|
return this.attributeRows
|
2025-01-09 18:07:02 +02:00
|
|
|
.filter((row) => row.componentId !== componentId)
|
|
|
|
.map((row) => this.getEntityRow("attributes", row.attributeId))
|
|
|
|
.filter((attr) => !!attr) as AttributeRow[];
|
2020-01-29 21:38:58 +01:00
|
|
|
}
|
|
|
|
|
2024-07-25 20:42:56 +03:00
|
|
|
addRevision(revisionId: string, noteId?: string, componentId?: string | null) {
|
2025-01-09 18:07:02 +02:00
|
|
|
this.revisionRows.push({ revisionId, noteId, componentId });
|
2020-01-29 21:38:58 +01:00
|
|
|
}
|
|
|
|
|
2024-07-25 00:09:34 +03:00
|
|
|
hasRevisionForNote(noteId: string) {
|
2025-01-09 18:07:02 +02:00
|
|
|
return !!this.revisionRows.find((row) => row.noteId === noteId);
|
2020-01-29 21:38:58 +01:00
|
|
|
}
|
|
|
|
|
2020-01-27 22:58:03 +01:00
|
|
|
getNoteIds() {
|
2022-01-09 20:16:39 +01:00
|
|
|
return Object.keys(this.noteIdToComponentId);
|
2020-01-27 22:58:03 +01:00
|
|
|
}
|
|
|
|
|
2025-02-08 21:42:12 +02:00
|
|
|
isNoteReloaded(noteId: string | undefined | null, componentId: string | null = null) {
|
2020-01-28 21:54:28 +01:00
|
|
|
if (!noteId) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-01-09 20:16:39 +01:00
|
|
|
const componentIds = this.noteIdToComponentId[noteId];
|
2025-01-09 18:07:02 +02:00
|
|
|
return componentIds && componentIds.find((sId) => sId !== componentId) !== undefined;
|
2020-01-27 22:58:03 +01:00
|
|
|
}
|
2020-01-31 22:32:24 +01:00
|
|
|
|
2024-07-25 00:09:34 +03:00
|
|
|
addNoteContent(noteId: string, componentId: string) {
|
2025-01-09 18:07:02 +02:00
|
|
|
this.contentNoteIdToComponentId.push({ noteId, componentId });
|
2020-01-31 22:32:24 +01:00
|
|
|
}
|
|
|
|
|
2025-01-07 12:34:10 +02:00
|
|
|
isNoteContentReloaded(noteId: string, componentId?: string) {
|
2020-01-31 22:32:24 +01:00
|
|
|
if (!noteId) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
return this.contentNoteIdToComponentId.find((l) => l.noteId === noteId && l.componentId !== componentId);
|
2020-01-31 22:32:24 +01:00
|
|
|
}
|
2020-02-05 22:08:45 +01:00
|
|
|
|
2024-07-25 00:09:34 +03:00
|
|
|
addOption(name: string) {
|
2023-06-05 16:12:02 +02:00
|
|
|
this.optionNames.push(name);
|
2020-02-05 22:08:45 +01:00
|
|
|
}
|
|
|
|
|
2024-07-25 00:09:34 +03:00
|
|
|
isOptionReloaded(name: string) {
|
2023-06-05 16:12:02 +02:00
|
|
|
return this.optionNames.includes(name);
|
2020-02-05 22:08:45 +01:00
|
|
|
}
|
2020-03-10 21:33:03 +01:00
|
|
|
|
2023-06-05 21:14:33 +02:00
|
|
|
getOptionNames() {
|
|
|
|
return this.optionNames;
|
|
|
|
}
|
|
|
|
|
2024-07-25 00:09:34 +03:00
|
|
|
addAttachmentRow(attachment: AttachmentRow) {
|
2023-06-05 16:12:02 +02:00
|
|
|
this.attachmentRows.push(attachment);
|
2023-04-01 23:55:04 +02:00
|
|
|
}
|
|
|
|
|
2023-06-05 16:12:02 +02:00
|
|
|
getAttachmentRows() {
|
|
|
|
return this.attachmentRows;
|
2023-04-01 23:55:04 +02:00
|
|
|
}
|
|
|
|
|
2020-05-02 18:19:41 +02:00
|
|
|
/**
|
2023-01-05 23:38:41 +01:00
|
|
|
* @returns {boolean} true if there are changes which could affect the attributes (including inherited ones)
|
2020-05-14 13:08:06 +02:00
|
|
|
* notably changes in note itself should not have any effect on attributes
|
2020-05-02 18:19:41 +02:00
|
|
|
*/
|
|
|
|
hasAttributeRelatedChanges() {
|
2025-01-09 18:07:02 +02:00
|
|
|
return this.branchRows.length > 0 || this.attributeRows.length > 0;
|
2020-05-02 18:19:41 +02:00
|
|
|
}
|
|
|
|
|
2020-03-10 21:33:03 +01:00
|
|
|
isEmpty() {
|
2025-01-09 18:07:02 +02:00
|
|
|
return (
|
|
|
|
Object.keys(this.noteIdToComponentId).length === 0 &&
|
|
|
|
this.branchRows.length === 0 &&
|
|
|
|
this.attributeRows.length === 0 &&
|
|
|
|
this.noteReorderings.length === 0 &&
|
|
|
|
this.revisionRows.length === 0 &&
|
|
|
|
this.contentNoteIdToComponentId.length === 0 &&
|
|
|
|
this.optionNames.length === 0 &&
|
2025-03-06 23:52:01 +02:00
|
|
|
this.attachmentRows.length === 0
|
2025-01-09 18:07:02 +02:00
|
|
|
);
|
2020-03-10 21:33:03 +01:00
|
|
|
}
|
2020-08-16 22:57:48 +02:00
|
|
|
|
|
|
|
isEmptyForTree() {
|
2025-01-09 18:07:02 +02:00
|
|
|
return Object.keys(this.noteIdToComponentId).length === 0 && this.branchRows.length === 0 && this.attributeRows.length === 0 && this.noteReorderings.length === 0;
|
2020-08-16 22:57:48 +02:00
|
|
|
}
|
2020-05-14 13:08:06 +02:00
|
|
|
}
|