From 1ffa8a8fb3e16bd5a3338d18782ddda0c2ffca03 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sun, 16 Mar 2025 21:15:00 -0400 Subject: a lot of code cleanup for doc creators templates --- src/client/views/Main.tsx | 6 +- .../DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx | 89 ++- .../DocCreatorMenu/FieldTypes/DecorationField.tsx | 3 - .../DocCreatorMenu/FieldTypes/DynamicField.tsx | 189 ----- .../DataVizBox/DocCreatorMenu/FieldTypes/Field.tsx | 167 ----- .../DocCreatorMenu/FieldTypes/FieldUtils.tsx | 64 -- .../FieldTypes/StaticContentField.tsx | 90 --- .../nodes/DataVizBox/DocCreatorMenu/Template.ts | 138 ++++ .../nodes/DataVizBox/DocCreatorMenu/Template.tsx | 139 ---- .../DataVizBox/DocCreatorMenu/TemplateBackend.ts | 768 ++++++++++++++++++++ .../DataVizBox/DocCreatorMenu/TemplateBackend.tsx | 771 --------------------- .../TemplateFieldTypes/DecorationField.ts | 11 + .../TemplateFieldTypes/DynamicField.ts | 164 +++++ .../TemplateFieldTypes/StaticContentField.ts | 72 ++ .../TemplateFieldTypes/TemplateField.ts | 159 +++++ .../TemplateFieldTypes/TemplateFieldUtils.ts | 71 ++ .../DataVizBox/DocCreatorMenu/TemplateManager.ts | 33 + .../DataVizBox/DocCreatorMenu/TemplateManager.tsx | 34 - 18 files changed, 1461 insertions(+), 1507 deletions(-) delete mode 100644 src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/DecorationField.tsx delete mode 100644 src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/DynamicField.tsx delete mode 100644 src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/Field.tsx delete mode 100644 src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/FieldUtils.tsx delete mode 100644 src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/StaticContentField.tsx create mode 100644 src/client/views/nodes/DataVizBox/DocCreatorMenu/Template.ts delete mode 100644 src/client/views/nodes/DataVizBox/DocCreatorMenu/Template.tsx create mode 100644 src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateBackend.ts delete mode 100644 src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateBackend.tsx create mode 100644 src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateFieldTypes/DecorationField.ts create mode 100644 src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateFieldTypes/DynamicField.ts create mode 100644 src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateFieldTypes/StaticContentField.ts create mode 100644 src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateFieldTypes/TemplateField.ts create mode 100644 src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateFieldTypes/TemplateFieldUtils.ts create mode 100644 src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateManager.ts delete mode 100644 src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateManager.tsx (limited to 'src') diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index fc2d7f572..b335432c9 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -65,8 +65,8 @@ import { PresBox, PresElementBox } from './nodes/trails'; import { FaceRecognitionHandler } from './search/FaceRecognitionHandler'; import { SearchBox } from './search/SearchBox'; import { StickerPalette } from './smartdraw/StickerPalette'; -import { Field } from './nodes/DataVizBox/DocCreatorMenu/FieldTypes/Field'; -import { FieldUtils } from './nodes/DataVizBox/DocCreatorMenu/FieldTypes/FieldUtils'; +import { TemplateField } from './nodes/DataVizBox/DocCreatorMenu/TemplateFieldTypes/TemplateField'; +import { TemplateFieldUtils } from './nodes/DataVizBox/DocCreatorMenu/TemplateFieldTypes/TemplateFieldUtils'; dotenv.config(); @@ -102,7 +102,7 @@ FieldLoader.ServerLoadStatus = { requested: 0, retrieved: 0, message: 'cache' }; new PingManager(); new KeyManager(); new FaceRecognitionHandler(); - Field.initField = FieldUtils.initField; // set the init function for fields + TemplateField.initField = TemplateFieldUtils.initField; // set the init function for fields // initialize plugins and classes that require plugins CollectionDockingView.Init(TabDocView); diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx index a702218b0..97faf01c2 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx @@ -27,7 +27,7 @@ import { DocumentView, DocumentViewInternal } from '../../DocumentView'; import { OpenWhere } from '../../OpenWhere'; import { DataVizBox } from '../DataVizBox'; import './DocCreatorMenu.scss'; -import { Field, ViewType } from './FieldTypes/Field'; +import { TemplateField, ViewType } from './TemplateFieldTypes/TemplateField'; import { Template } from './Template'; import { TemplateFieldSize, TemplateFieldType, TemplateLayouts } from './TemplateBackend'; import { TemplateManager } from './TemplateManager'; @@ -371,7 +371,7 @@ export class DocCreatorMenu extends ObservableReactComponent } @action updateRenderedPreviewCollection = async (template: Template) => { - this._fullyRenderedDocs = (await this.createDocsFromTemplate(template)) ?? []; + this._fullyRenderedDocs = ((await this.createDocsFromTemplate(template)) ?? []).filter(doc => doc).map(doc => doc!); console.log(this._fullyRenderedDocs); this.updateRenderedDocCollection(); }; @@ -630,7 +630,7 @@ export class DocCreatorMenu extends ObservableReactComponent await Promise.all(renderedTemplatePromises); } - templates.forEach(template => template.mainField.initializeDocument({ subfields: [], title: template.title, opts: {}, viewType: ViewType.FREEFORM, tl: [0, 0], br: [900, 900] })); + templates.forEach(template => template.mainField.initializeDocument({ title: template.title, opts: {}, viewType: ViewType.FREEFORM, tl: [0, 0], br: [900, 900] }, [])); setTimeout(() => { this.setSuggestedTemplates(templates); @@ -638,10 +638,10 @@ export class DocCreatorMenu extends ObservableReactComponent }); }; - renderGPTImageCall = async (template: Template, col: Col, fieldNumber: number): Promise => { + renderGPTImageCall = async (template: Template, col: Col, fieldNumber: number | undefined): Promise => { const generateAndLoadImage = async (fieldNum: string, column: Col, prompt: string) => { const url = await this.generateGPTImage(prompt); - const field: Field = template.getFieldByID(Number(fieldNum)); + const field: TemplateField = template.getFieldByID(Number(fieldNum)); field.setContent(url ?? '', ViewType.IMG); field.setTitle(col.title); @@ -665,7 +665,7 @@ export class DocCreatorMenu extends ObservableReactComponent return true; }; - renderGPTTextCall = async (template: Template, col: Col, fieldNum: number): Promise => { + renderGPTTextCall = async (template: Template, col: Col, fieldNum: number | undefined): Promise => { const wordLimit = (size: TemplateFieldSize) => { switch (size) { case TemplateFieldSize.TINY: @@ -697,7 +697,7 @@ export class DocCreatorMenu extends ObservableReactComponent if (res) { const assignments: { [title: string]: { number: string; content: string } } = JSON.parse(res); Object.entries(assignments).forEach(([, /* title */ info]) => { - const field: Field = template.getFieldByID(Number(info.number)); + const field: TemplateField = template.getFieldByID(Number(info.number)); // const column = this.getColByTitle(title); field.setContent(info.content ?? '', ViewType.TEXT); @@ -771,7 +771,7 @@ export class DocCreatorMenu extends ObservableReactComponent return templateCopy.mainField.renderedDoc; }; - let docs: Promise[]; + let docs: Promise[]; if (this.DEBUG_MODE) { docs = [1, 2, 3, 4].map(() => processContent({})); } else { @@ -868,30 +868,31 @@ export class DocCreatorMenu extends ObservableReactComponent get templatesPreviewContents() { const GPTOptions =
; - const previewDoc = (doc: Doc, template: Template) => ( - (this._selectedTemplate === template ? 104 : 111)} - PanelHeight={() => (this._selectedTemplate === template ? 104 : 111)} - ScreenToLocalTransform={() => new Transform(-this._pageX - 5, -this._pageY - 35, 1)} - renderDepth={1} - whenChildContentsActiveChanged={emptyFunction} - focus={emptyFunction} - styleProvider={DefaultStyleProvider} - addDocTab={this._props.addDocTab} - pinToPres={() => undefined} - childFilters={returnEmptyFilter} - childFiltersByRanges={returnEmptyFilter} - searchFilterDocs={returnEmptyDoclist} - fitContentsToBox={returnFalse} - fitWidth={returnFalse} - hideDecorations={true} - /> - ); + const previewDoc = (doc: Doc | undefined, template: Template) => + !doc ? null : ( + (this._selectedTemplate === template ? 104 : 111)} + PanelHeight={() => (this._selectedTemplate === template ? 104 : 111)} + ScreenToLocalTransform={() => new Transform(-this._pageX - 5, -this._pageY - 35, 1)} + renderDepth={1} + whenChildContentsActiveChanged={emptyFunction} + focus={emptyFunction} + styleProvider={DefaultStyleProvider} + addDocTab={this._props.addDocTab} + pinToPres={() => undefined} + childFilters={returnEmptyFilter} + childFiltersByRanges={returnEmptyFilter} + searchFilterDocs={returnEmptyDoclist} + fitContentsToBox={returnFalse} + fitWidth={returnFalse} + hideDecorations={true} + /> + ); // @@ -1096,19 +1097,13 @@ export class DocCreatorMenu extends ObservableReactComponent const collectionFactory = (): ((docs: Doc[], options: DocumentOptions) => Doc) => { switch (this._layout.type) { - case LayoutType.CAROUSEL3D: - return Docs.Create.Carousel3DDocument; - case LayoutType.FREEFORM: - return Docs.Create.FreeformDocument; - case LayoutType.CARD: - return Docs.Create.CardDeckDocument; - case LayoutType.MASONRY: - return Docs.Create.MasonryDocument; - case LayoutType.CAROUSEL: - return Docs.Create.CarouselDocument; - default: - return Docs.Create.FreeformDocument; - } + case LayoutType.CAROUSEL3D: return Docs.Create.Carousel3DDocument; + case LayoutType.FREEFORM: return Docs.Create.FreeformDocument; + case LayoutType.CARD: return Docs.Create.CardDeckDocument; + case LayoutType.MASONRY: return Docs.Create.MasonryDocument; + case LayoutType.CAROUSEL: return Docs.Create.CarouselDocument; + default: return Docs.Create.FreeformDocument; + } // prettier-ignore }; const collection = collectionFactory()(this._fullyRenderedDocs, { @@ -1241,9 +1236,9 @@ export class DocCreatorMenu extends ObservableReactComponent emptyFunction, undoable(clickEv => { clickEv.stopPropagation(); - if (!this._selectedTemplate) return; + if (!this._selectedTemplate || !this._selectedTemplate.getRenderedDoc()) return; const layout: DataVizTemplateLayout = { - template: this._selectedTemplate.getRenderedDoc(), + template: this._selectedTemplate.getRenderedDoc()!, layout: { type: this._layout.type, xMargin: this._layout.xMargin, yMargin: this._layout.yMargin, repeat: 0 }, columns: this.columnsCount, rows: this.rowsCount, diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/DecorationField.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/DecorationField.tsx deleted file mode 100644 index 98a9dc7a6..000000000 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/DecorationField.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import { DynamicField } from './DynamicField'; - -export class DecorationField extends DynamicField {} diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/DynamicField.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/DynamicField.tsx deleted file mode 100644 index f100830d3..000000000 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/DynamicField.tsx +++ /dev/null @@ -1,189 +0,0 @@ -import { Doc, DocListCast } from '../../../../../../fields/Doc'; -import { Docs } from '../../../../../documents/Documents'; -import { Field, FieldSettings, ViewType } from './Field'; -import { List } from '../../../../../../fields/List'; -import { DocData } from '../../../../../../fields/DocSymbols'; -import { DocumentType } from '../../../../../documents/DocumentTypes'; -import { reaction } from 'mobx'; -import { IDisposer } from 'mobx-utils'; - -export class DynamicField extends Field { - protected subfields!: Field[]; - - protected disposers: { [name: string]: IDisposer } = {}; - init(settings: FieldSettings, id: number, parent?: DynamicField) { - super.baseinit(undefined as unknown as Doc, settings, parent, id); - const { doc, subFields } = this.initializeDocument(settings); - this.Document = doc; - this.subfields = subFields; - - this.disposers.fieldList = reaction( - () => DocListCast(this.Document[Doc.LayoutFieldKey(this.Document)]), - docs => { - console.log('updated'); - this.handleFieldUpdate(docs); - } - ); - return this; - } - - static setupSubfields(subFieldSettings: FieldSettings[] | undefined, parent?: DynamicField): Field[] { - return subFieldSettings?.map((fieldSettings, index) => Field.initField!(fieldSettings, index, parent)) || []; - } - - get getSubfields(): Field[] { - return this.subfields ?? []; - } - get getAllSubfields() { - let fields: Field[] = []; - this.subfields?.forEach(field => { - fields.push(field); - fields = fields.concat(field instanceof DynamicField ? field.getAllSubfields : ([] as Field[])); - }); - return fields; - } - - setSubFields = (fields: Field[]) => { - this.subfields = fields; - }; - handleFieldUpdate = (newDocsList: Doc[]) => { - const currRenderedDocs: Set = new Set(); - this.subfields.forEach(field => currRenderedDocs.add(field.Document)); - newDocsList.forEach(doc => { - if (!currRenderedDocs.has(doc)) { - this.addFieldFromDoc(doc); - } - }); - currRenderedDocs.forEach(doc => { - if (!newDocsList.includes(doc)) { - const fields = this.subfields.filter(field => field.Document === doc); - fields.forEach(field => this.removeField(field)); - } - }); - }; - - addFieldFromDoc = (doc: Doc) => { - const par = this.Document; - const settings: FieldSettings = { - tl: [Number(doc._x) / Number(par._width), Number(doc._y) / Number(par._height)], - br: [(Number(doc._x) + Number(doc._width)) / Number(par._width), (Number(doc._y) + Number(doc._height)) / Number(par._height)], - viewType: doc.type === DocumentType.COL ? ViewType.FREEFORM : ViewType.STATIC, - opts: {}, - }; - - const newField: Field = Field.initField!(settings, this.subfields.length, this); - this.subfields.push(newField); - }; - - addField = (field: Field) => { - if (!this.subfields.includes(field)) { - this.subfields.push(field); - console.log('field added'); - // Doc.SetContainer(field.Document, this.Document); - } - }; - - dispose = () => { - Object.values(this.disposers).forEach(disposer => disposer?.()); - }; - - removeField = (field: Field) => { - // var childDocs: Doc[] = DocListCast(this.Document[Doc.LayoutFieldKey(this.Document)]); - // this.Document[Doc.LayoutFieldKey(this.Document)] = new List([...childDocs.splice(childDocs.indexOf(field.Document), 1)]); - this.subfields.splice(this.subfields.indexOf(field), 1); - field instanceof DynamicField && field.dispose(); - }; - - exchangeFields = (newField: Field, oldField: Field) => { - this.subfields.splice(this.subfields.indexOf(oldField), 1, newField); - // this.renderedDoc. - }; - // eslint-disable-next-line @typescript-eslint/no-unused-vars - setContent = (content: string, type: ViewType) => { - return; - }; - getContent = () => { - return ''; - }; - get isContentField(): boolean { - return false; - } - - addChildToDocument = (doc: Doc) => { - Doc.SetContainer(doc, this.Document); - }; - - matches = (): Array => { - return []; - }; - - async makeClone(parent?: DynamicField): Promise { - const field = (await super.makeClone(parent)) as unknown as DynamicField; - field.subfields = await Promise.all(this.subfields.map(async cloneField => await cloneField.makeClone(field))); - field.Document[DocData].data = new List(field.subfields.map(subfield => subfield.renderedDoc)); - return field; - } - initializeDocument = (settings: FieldSettings) => { - const subFields = DynamicField.setupSubfields(settings.subfields, this); - const renderedSubfields = subFields.map(field => field.renderedDoc); - settings.opts.title = settings.title; - switch (settings.viewType) { - case ViewType.CAROUSEL3D: - return { doc: Docs.Create.Carousel3DDocument(renderedSubfields, settings.opts), subFields }; - case ViewType.FREEFORM: - return { doc: Docs.Create.FreeformDocument(renderedSubfields, settings.opts), subFields }; - default: - return { doc: Docs.Create.FreeformDocument(renderedSubfields, settings.opts), subFields }; - } - }; -} - -// export class DynamicField extends Field { -// protected subfields: Field[]; - -// protected Document!: Doc; - -// constructor(settings: FieldSettings, id: number, parent?: Field) { -// super(settings, id, parent); -// this.subfields = this.setupSubfields(this); -// this.initializeDocument(); -// } - -// setContent = (content: string, type: ViewType) => { return }; -// getContent = () => { return '' }; -// get isContentField(): boolean { return false }; - -// addChildToDocument = (doc: Doc) => { -// Doc.SetContainer(doc, this.Document); -// } - -// matches = (cols: Col[]): Array => { -// return []; -// } - -// initializeDocument = (): Doc => { -// let doc: Doc; -// const renderedSubfields: Doc[] = this.subfields.map(field => field.renderedDoc); -// switch (this.settings.viewType) { -// case ViewType.CAROUSEL3D: -// doc = Docs.Create.Carousel3DDocument(renderedSubfields, { -// title: this.title, -// }); -// break; -// case ViewType.FREEFORM: -// doc = Docs.Create.FreeformDocument(renderedSubfields, { -// title: this.title, -// }); -// break; -// default: -// doc = Docs.Create.FreeformDocument(renderedSubfields, { -// title: this.title, -// }); -// break; -// } - -// this.Document = doc; -// return doc; -// } - -// } diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/Field.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/Field.tsx deleted file mode 100644 index 111ad8328..000000000 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/Field.tsx +++ /dev/null @@ -1,167 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -/* eslint-disable no-use-before-define */ -import { computed } from 'mobx'; -import { Doc } from '../../../../../../fields/Doc'; -import { DocData } from '../../../../../../fields/DocSymbols'; -import { Copy } from '../../../../../../fields/FieldSymbols'; -import { ObjectField } from '../../../../../../fields/ObjectField'; -import { ComputedField } from '../../../../../../fields/ScriptField'; -import { DocumentOptions } from '../../../../../documents/Documents'; -import { Col } from '../DocCreatorMenu'; -import { TemplateFieldSize, TemplateFieldType } from '../TemplateBackend'; - -export abstract class Field { - Document!: Doc; - - static initField?: (settings: FieldSettings, index: number, parent: any /* DynamicField */ | undefined, sameId?: boolean) => Field = undefined; - - protected parent?: any; - protected id!: number; - settings!: FieldSettings; - protected title: string = ''; - dimensions!: FieldDimensions; - - constructor() {} - - baseinit(doc: Doc, settings: FieldSettings, parent?: any, id: number = 1) { - this.id = id; - this.Document = doc; - this.parent = parent; - this.settings = settings; - this.title = settings.title ?? ''; - this.dimensions = this.getLocalDimensions({ tl: this.settings.tl, br: this.settings.br }, this.parent?.getDimensions); - this.applyBasicOpts(this.dimensions, settings); - return this; - } - - get renderedDoc() { - return this.Document; - } - get getDimensions() { - return this.dimensions; - } - get getID() { - return this.id; - } - get getDescription(): string { - return this.settings.description ?? ''; - } - get viewType(): ViewType { - return this.settings.viewType; - } - - setTitle = (title: string) => { - this.title = title; - this.Document.title = title; - }; - getTitle = () => { - return this.title; - }; - - abstract get isContentField(): boolean; - abstract setContent(content: string, type: ViewType): void; - abstract getContent(): string; - - async makeClone(parent?: any /* DynamicField*/): Promise { - const field = Field.initField!(this.settings, this.id, parent, true); // create a value for this.Document/subfields that we want to ignore - field.Document = (await Doc.MakeClone(this.Document)).clone; - field.title = this.title; - field.dimensions = this.dimensions; - return field; - } - - @computed get documentOptions(): DocumentOptions { - const opts: DocumentOptions = {}; - Object.assign(opts, this.Document[DocData]); - Object.entries(opts).forEach(([key, field]) => { - if (field instanceof ObjectField) { - Object.assign(opts, { [key]: ObjectField.MakeCopy(field) }); - } else if (field instanceof ComputedField) { - Object.assign(opts, { [key]: field[Copy]() }); - } - }); - return opts; - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - changeFieldType = (newType: ViewType): Field => { - const newField = Field.initField!(this.settings, this.id, this.parent, true); - this.parent?.exchangeFields(newField, this); - return newField; - }; - - matches = (cols: Col[]): number[] => { - const colMatchesField = (col: Col) => { - const isMatch: boolean = (this.settings.sizes?.some(size => col.sizes?.includes(size)) && this.settings.types?.includes(col.type)) ?? false; - return isMatch; - }; - - const matches: Array = []; - - cols.forEach((col, v) => { - if (colMatchesField(col)) { - matches.push(v); - } - }); - - return matches; - }; - - private getLocalDimensions = (coords: { tl: [number, number]; br: [number, number] }, parentDimensions?: FieldDimensions): FieldDimensions => { - if (!parentDimensions) { - return { width: coords.br[0] - coords.tl[0], height: coords.br[1] - coords.tl[1], coord: { x: coords.tl[0], y: coords.tl[1] } }; - } - const l = (coords.tl[0] * parentDimensions.width) / 2; - const t = coords.tl[1] * parentDimensions.height / 2; //prettier-ignore - const r = (coords.br[0] * parentDimensions.width) / 2; - const b = coords.br[1] * parentDimensions.height / 2; //prettier-ignore - const width = r - l; - const height = b - t; - const coord = { x: l, y: t }; - return { width, height, coord }; - }; - - private applyBasicOpts = (dimensions: FieldDimensions, settings: FieldSettings) => { - const opts: DocumentOptions = settings.opts; - opts.isDefaultTemplateDoc ??= true; - opts._layout_hideScroll ??= true; - opts.x ??= dimensions.coord.x; - opts.y ??= dimensions.coord.y; - opts._height ??= dimensions.height; - opts._width ??= dimensions.width; - opts._nativeWidth ??= dimensions.width; - opts._nativeHeight ??= dimensions.height; - opts._layout_nativeDimEditable ??= true; - }; -} - -export type FieldSettings = { - tl: [number, number]; - br: [number, number]; - opts: DocumentOptions; - viewType: ViewType; - title?: string; - subfields?: FieldSettings[]; - types?: TemplateFieldType[]; - sizes?: TemplateFieldSize[]; - description?: string; -}; - -export enum ViewType { - CAROUSEL3D = 'carousel3d', - FREEFORM = 'freeform', - STATIC = 'static', - DEC = 'decoration', - IMG = 'image', - TEXT = 'text', -} - -export type FieldDimensions = { - width: number; - height: number; - coord: { x: number; y: number }; -}; - -export type FieldTree = { - node: { field: Field; subfields: FieldTree[] }; -}; diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/FieldUtils.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/FieldUtils.tsx deleted file mode 100644 index 0582c9ed3..000000000 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/FieldUtils.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { Field, FieldSettings, ViewType } from './Field'; -import { TextTemplateField, ImageTemplateField } from './StaticContentField'; -import { DecorationField } from './DecorationField'; -import { DynamicField } from './DynamicField'; - -export class FieldUtils { - public static initField = (settings: FieldSettings, index: number, parent: DynamicField | undefined, sameId: boolean = false): Field => { - const id = sameId ? index : parent ? Number(`${parent.getID}${index}`) : 1; - switch (settings.viewType) { - case ViewType.FREEFORM: - case ViewType.CAROUSEL3D: - return new DynamicField().init(settings, id, parent); - case ViewType.IMG: - return new ImageTemplateField().init(settings, id, parent); - case ViewType.TEXT: - return new TextTemplateField().init(settings, id, parent); - case ViewType.DEC: - return new DecorationField().init(settings, id, parent); - } - return new TextTemplateField().init(settings, id, parent); - }; - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - public static calculateFontSize = (contWidth: number, contHeight: number, text: string, uppercase: boolean): number => { - const words: string[] = text.split(/\s+/).filter(Boolean); - - let currFontSize = 1; - let rowsCount = 1; - let currTextHeight = currFontSize * rowsCount * 2; - - while (currTextHeight <= contHeight) { - let wordIndex = 0; - let currentRowWidth = 0; - let wordsInCurrRow = 0; - rowsCount = 1; - - while (wordIndex < words.length) { - const word = words[wordIndex]; - const wordWidth = word.length * currFontSize * 0.7; - - if (currentRowWidth + wordWidth <= contWidth) { - currentRowWidth += wordWidth; - ++wordsInCurrRow; - } else { - if (words.length !== 1 && words.length > wordsInCurrRow) { - rowsCount++; - currentRowWidth = wordWidth; - wordsInCurrRow = 1; - } else { - break; - } - } - - wordIndex++; - } - - currTextHeight = rowsCount * currFontSize * 2; - - currFontSize += 1; - } - - return currFontSize - 1; - }; -} diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/StaticContentField.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/StaticContentField.tsx deleted file mode 100644 index 75aea5440..000000000 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/StaticContentField.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import { DocData } from '../../../../../../fields/DocSymbols'; -import { RichTextField } from '../../../../../../fields/RichTextField'; -import { ImageField } from '../../../../../../fields/URLField'; -import { Docs } from '../../../../../documents/Documents'; -import { Field, FieldSettings, ViewType } from './Field'; -import { FieldUtils } from './FieldUtils'; -import { DynamicField } from './DynamicField'; - -export abstract class StaticContentField extends Field { - protected content: string = ''; - - abstract setContent(content: string, type?: ViewType): void; - getContent = () => { - return this.content ?? 'unset'; - }; - get isContentField(): boolean { - return true; - } -} - -export class ImageTemplateField extends StaticContentField { - init(settings: FieldSettings, id: number, parent: DynamicField | undefined) { - super.baseinit(this.initializeDocument(settings), settings, parent, id); - return this; - } - - setContent = (url: string, type?: ViewType) => { - this.settings.viewType = type ?? this.settings.viewType; - - if (type === ViewType.IMG || type === undefined) { - const imgField = new ImageField(url); - this.Document[DocData].data = imgField; - this.content = url; - } else { - const updatedField = this.changeFieldType(type); - updatedField.setContent(url, type); - } - }; - - initializeDocument = (settings: FieldSettings) => { - settings.opts.title = settings.title; - settings.opts._layout_fitWidth = false; - - return Docs.Create.ImageDocument('', settings.opts); - }; -} - -export class TextTemplateField extends StaticContentField { - init(settings: FieldSettings, id: number, parent?: DynamicField) { - super.baseinit(this.initializeDocument(settings), settings, parent, id); - this.Document.text_fontSize = `${FieldUtils.calculateFontSize(this.dimensions.width, this.dimensions.height, '', true)}`; - return this; - } - setContent = (text: string, type?: ViewType) => { - this.settings.viewType = type ?? this.settings.viewType; - - if (type === ViewType.TEXT || type === undefined) { - const rtf = { - doc: { - type: 'doc', - content: [ - { - type: 'paragraph', - content: [ - { - type: 'text', - text, - }, - ], - }, - ], - }, - selection: { type: 'text', anchor: 1, head: 1 }, - storedMarks: [], - }; - this.content = text; - const field = new RichTextField(JSON.stringify(rtf), text); - this.Document[DocData]['text'] = field; - } else { - const updatedField = this.changeFieldType(type); - updatedField.setContent(text, type); - } - }; - - initializeDocument = (settings: FieldSettings) => { - const opts = settings.opts; - opts.title = settings.title; - return Docs.Create.TextDocument('', opts); - }; -} diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/Template.ts b/src/client/views/nodes/DataVizBox/DocCreatorMenu/Template.ts new file mode 100644 index 000000000..ef6867e32 --- /dev/null +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/Template.ts @@ -0,0 +1,138 @@ +import { makeAutoObservable } from 'mobx'; +import { Col } from './DocCreatorMenu'; +import { DynamicField } from './TemplateFieldTypes/DynamicField'; +import { TemplateField, FieldSettings } from './TemplateFieldTypes/TemplateField'; +import { TemplateLayouts } from './TemplateBackend'; + +export class Template { + mainField: DynamicField; + private settings: FieldSettings; + + constructor(templateInfo: FieldSettings) { + makeAutoObservable(this); + this.settings = templateInfo; + this.mainField = this.setupMainField(templateInfo); + } + + get childFields(): TemplateField[] { + return this.mainField.getSubfields; + } + get allFields(): TemplateField[] { + return this.mainField.getAllSubfields; + } + get contentFields(): TemplateField[] { + return this.allFields.filter(field => field.isContentField); + } + get doc() { + return this.mainField.renderedDoc; + } + get title() { + return this.mainField.getTitle(); + } + + cleanup = () => { + //dispose each subfields disposers, etc. + }; + + cloneBase = async (): Promise