import { makeAutoObservable, reaction } from "mobx"; import { Doc, DocListCast, FieldType } from "../../../../../fields/Doc"; import { Docs } from "../../../../documents/Documents"; import { Col } from "./DocCreatorMenu"; import { DynamicField } from "./FieldTypes/DynamicField"; import { Field, FieldSettings, ViewType } from "./FieldTypes/Field"; import { } from "./FieldTypes/FieldUtils"; import { observer } from "mobx-react"; import { IDisposer } from "mobx-utils"; import { Width } from "../../../../../fields/DocSymbols"; export class Template { mainField: DynamicField; private settings: FieldSettings; constructor(templateInfo: FieldSettings) { makeAutoObservable(this); this.settings = templateInfo; this.mainField = this.setupMainField(templateInfo); console.log(templateInfo); } get childFields(): Field[] { return this.mainField.getSubfields }; get allFields(): Field[] { return this.mainField.getAllSubfields }; get contentFields(): Field[] { return this.allFields.filter(field => field !instanceof DynamicField) }; get doc(){ return this.mainField.renderedDoc; }; get title() { return this.mainField.getTitle() }; cleanup = () => { //dispose each subfields disposers, etc. } cloneBase = () => { const clone: Template = new Template(this.settings); this.mainField.applyAttributes(clone.mainField); clone.allFields.filter(field => field !== clone.mainField).forEach(field => { console.log('id:', field.getID); const matchingField: Field = this.allFields.filter(f => f.getID === field.getID)[0]; matchingField.applyAttributes(field); }) clone.mainField.updateRenderedDoc(); return clone; } printFieldInfo = () => { this.allFields.forEach(field => { const doc = field.renderedDoc; console.log('title: ', field.getTitle(), ' width: ', doc.width); }); } getRenderedDoc = () => { return this.doc; } getFieldByID = (id: number): Field => { return this.allFields.filter(field => field.getID === id)[0]; } getFieldByTitle = (title: string) => { return this.allFields.filter(field => field.getTitle() === title)[0]; } setupMainField = (templateInfo: FieldSettings) => { return new DynamicField(templateInfo, 1); } get descriptionSummary(): string { let summary: string = ''; this.contentFields.forEach(field => { summary += `--- Field #${field.getID} (title: ${field.getTitle()}): ${field.getDescription ?? ''} ---`; }); return summary; } get compiledContent(): string { let summary: string = ''; this.contentFields.forEach(field => { summary += `--- Field #${field.getID} (title: ${field.getTitle()}): ${field.getContent() ?? ''} ---`; }); return summary; } resetToBase = () => { this.allFields.forEach(field => { field.updateRenderedDoc(); }) } isValidTemplate = (cols: Col[]) => { const matches: number[][] = this.getMatches(cols); const maxMatches: number = this.maxMatches(matches); return maxMatches === this.contentFields.length; } getMatches = (cols: Col[]): number[][] => { const numFields = this.contentFields.length; if (cols.length !== numFields) return []; const matches: number[][] = Array(numFields) .fill([]) .map(() => []); this.contentFields.forEach((field, i) => { matches[i] = (field.matches(cols)); }); return matches; } maxMatches = (matches: number[][]) => { if (matches.length === 0) return 0; const fieldsCt = this.contentFields.length; const used: boolean[] = Array(fieldsCt).fill(false); const mt: number[] = Array(fieldsCt).fill(-1); const augmentingPath = (v: number): boolean => { if (used[v]) return false; used[v] = true; for (const to of matches[v]) { if (mt[to] === -1 || augmentingPath(mt[to])) { mt[to] = v; return true; } } return false; }; for (let v = 0; v < fieldsCt; ++v) { used.fill(false); augmentingPath(v); } let count: number = 0; for (let i = 0; i < fieldsCt; ++i) { if (mt[i] !== -1) ++count; } return count; }; }