From f92a02ec5d676359cb268a35d30e5bf9886199c1 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Fri, 30 May 2025 03:27:03 -0400 Subject: couple more component refactors --- .../DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx | 601 +-------------------- .../Menu/ExpandedTemplatePreview.tsx | 0 .../DocCreatorMenu/Menu/FieldOptionsScreen.tsx | 0 .../DocCreatorMenu/Menu/TemplateEditingWindow.tsx | 6 +- .../Menu/TemplateMenuFieldOptions.tsx | 193 +++++++ .../Menu/TemplateRenderPreviewWindow.tsx | 346 ++++++++++++ .../TemplateFieldTypes/StaticContentField.ts | 8 +- src/server/ApiManagers/FireflyManager.ts | 4 +- 8 files changed, 580 insertions(+), 578 deletions(-) delete mode 100644 src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/ExpandedTemplatePreview.tsx delete mode 100644 src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/FieldOptionsScreen.tsx create mode 100644 src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateMenuFieldOptions.tsx create mode 100644 src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateRenderPreviewWindow.tsx (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx index 1e54c0628..9a84e69a9 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx @@ -39,6 +39,8 @@ import { TemplatePreviewGrid } from './Menu/TemplatePreviewGrid'; import { FireflyStructureOptions, TemplateEditingWindow } from './Menu/TemplateEditingWindow'; import { DocCreatorMenuButton } from './Menu/DocCreatorMenuButton'; import { ConditionalsTextArea } from './Menu/ConditionalsTextarea'; +import { TemplatesRenderPreviewWindow } from './Menu/TemplateRenderPreviewWindow'; +import { TemplateMenuFieldOptions } from './Menu/TemplateMenuFieldOptions'; export enum LayoutType { FREEFORM = 'Freeform', @@ -81,12 +83,10 @@ export class DocCreatorMenu extends ObservableReactComponent // eslint-disable-next-line no-use-before-define static Instance: DocCreatorMenu; - private DEBUG_MODE: boolean = false; + DEBUG_MODE: boolean = false; private _ref: HTMLDivElement | null = null; private templateManager: TemplateManager; - @observable _fullyRenderedDocs: Doc[] = []; // collection of templates filled in with content - @observable _renderedDocCollection: Doc | undefined = undefined; // fullyRenderedDocs in a parent collection @observable _docsRendering: boolean = false; // dictates loading symbol @observable _userTemplates: Template[] = []; @@ -95,12 +95,6 @@ export class DocCreatorMenu extends ObservableReactComponent @observable _editedTemplateTrail: Template[] = []; @observable _userCreatedFields: Col[] = []; - @observable _collapsedCols: String[] = []; //any columns whose options panels are hidden - @observable _currEditingConditional: Conditional = {} as Conditional; - - @observable _layout: { type: LayoutType; yMargin: number; xMargin: number; columns?: number; repeat: number } = { type: LayoutType.FREEFORM, yMargin: 10, xMargin: 10, columns: 3, repeat: 0 }; - @observable _savedLayouts: DataVizTemplateLayout[] = []; - @observable _loadingVariants: boolean = false; @observable _suggestedTemplates: Template[] = []; @observable _GPTLoading: boolean = false; @@ -114,7 +108,7 @@ export class DocCreatorMenu extends ObservableReactComponent @observable _startPos?: { x: number; y: number }; @observable _shouldDisplay: boolean = false; - @observable _menuContent: 'templates' | 'options' | 'saved' | 'dashboard' | 'templateEditing' = 'templates'; + @observable _menuContent: 'templates' | 'renderPreview' | 'saved' | 'dashboard' | 'templateEditing' = 'templates'; @observable _dragging: boolean = false; @observable _dataViz?: DataVizBox; @observable _interactionLock: boolean | undefined; @@ -138,8 +132,6 @@ export class DocCreatorMenu extends ObservableReactComponent @action setDataViz = (dataViz: DataVizBox) => { this._dataViz = dataViz; this._selectedTemplate = undefined; - this._renderedDocCollection = undefined; - this._fullyRenderedDocs = []; this._suggestedTemplates = []; this._userCreatedFields = []; }; @@ -147,36 +139,6 @@ export class DocCreatorMenu extends ObservableReactComponent this._suggestedTemplates = templates; //prettier-ignore }; - @computed get docsToRender() { - if (this.DEBUG_MODE) { - return [1, 2, 3, 4]; - } else { - return this._selectedTemplate ? NumListCast(this._dataViz?.layoutDoc.dataViz_selectedRows) : []; - } - } - - @computed get rowsCount() { - switch (this._layout.type) { - case LayoutType.FREEFORM: - return Math.ceil(this.docsToRender.length / (this._layout.columns ?? 1)) ?? 0; - case LayoutType.CAROUSEL3D: - return 1.8; - default: - return 1; - } - } - - @computed get columnsCount() { - switch (this._layout.type) { - case LayoutType.FREEFORM: - return this._layout.columns ?? 0; - case LayoutType.CAROUSEL3D: - return 3; - default: - return 1; - } - } - @computed get selectedFields() { return StrListCast(this._dataViz?.layoutDoc._dataViz_axes); } @@ -203,10 +165,6 @@ export class DocCreatorMenu extends ObservableReactComponent .concat(this._userCreatedFields); } - @computed get canMakeDocs() { - return this._selectedTemplate !== undefined && this._layout !== undefined; - } - get bounds(): { t: number; b: number; l: number; r: number } { const rect = this._ref?.getBoundingClientRect(); const bounds = { t: rect?.top ?? 0, b: rect?.bottom ?? 0, l: rect?.left ?? 0, r: rect?.right ?? 0 }; @@ -356,12 +314,8 @@ export class DocCreatorMenu extends ObservableReactComponent this._pageX = x + translation.x; this._pageY = y + translation.y; }; - - @action updateRenderedPreviewCollection = async (template: Template) => { - this._docsRendering = true; - this._fullyRenderedDocs = this._dataViz ? ((await this.templateManager.createDocsFromTemplate(this._dataViz, template, this.fieldsInfos, this.DEBUG_MODE)).filter(doc => doc).map(doc => doc!) ?? []) as unknown as Doc[] : []; - this.updateRenderedDocCollection(); - }; + + async createDocsForPreview(): Promise { return this._dataViz && this._selectedTemplate ? ((await this.templateManager.createDocsFromTemplate(this._dataViz, this._selectedTemplate, this.fieldsInfos, this.DEBUG_MODE)).filter(doc => doc).map(doc => doc!) ?? []) as unknown as Doc[] : []; } @action updateSelectedTemplate = async (template: Template) => { if (this._selectedTemplate === template) { @@ -369,53 +323,12 @@ export class DocCreatorMenu extends ObservableReactComponent return; } else { this._selectedTemplate = template; - this.updateRenderedPreviewCollection(template); } }; - @action updateSelectedSavedLayout = (layout: DataVizTemplateLayout) => { - this._layout.xMargin = layout.layout.xMargin; - this._layout.yMargin = layout.layout.yMargin; - this._layout.type = layout.layout.type; - this._layout.columns = layout.columns; - }; - - isSelectedLayout = (layout: DataVizTemplateLayout) => { - return this._layout.xMargin === layout.layout.xMargin && this._layout.yMargin === layout.layout.yMargin && this._layout.type === layout.layout.type && this._layout.columns === layout.columns; - }; - - editTemplate = (doc: Doc) => { - DocumentViewInternal.addDocTabFunc(doc, OpenWhere.addRight); - DocumentView.DeselectAll(); - Doc.UnBrushDoc(doc); - }; - - testTemplate = async () => { - this._suggestedTemplates = this.templateManager.templates; //prettier-ignore - - //console.log(this.templateManager.templates) - - // const mainCollection = this._dataViz?.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView; - - // this.templateManager.templates.forEach(template => { - // const doc = template.mainField.renderedDoc(); - // mainCollection.addDocument(doc); - // }) - - // this.forceUpdate(); - - // try { - // const res = await gptImageCall('Image of panda eating a cookie'); - - // if (res) { - // const result = await Networking.PostToServer('/uploadRemoteImage', { sources: res }); - - // console.log(result); - // } - // } catch (e) { - // console.log(e); - // } - }; + // testTemplate = async () => { + // this._suggestedTemplates = this.templateManager.templates; //prettier-ignore + // }; @action addField = () => { const newFields: Col[] = this._userCreatedFields.concat([{ title: '', type: TemplateFieldType.UNSET, desc: '', sizes: [], AIGenerated: true }]); @@ -607,8 +520,7 @@ export class DocCreatorMenu extends ObservableReactComponent this.variations.push(url); } - addRenderedCollectionToMainview = () => { - const collection = this._renderedDocCollection; + addRenderedCollectionToMainview = (collection: Doc) => { if (collection) { const mainCollection = this._dataViz?.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView; collection.x = this._pageX - this._menuDimensions.width; @@ -634,484 +546,34 @@ export class DocCreatorMenu extends ObservableReactComponent //Docs.Create.FreeformDocument([doc], { _height: NumListCast(doc._height)[0], _width: NumListCast(doc._width)[0], title: ''}); }; - @action updateXMargin = (input: string) => { - this._layout.xMargin = Number(input); - setTimeout(() => { - if (!this._renderedDocCollection || !this._fullyRenderedDocs) return; - this.applyLayout(this._renderedDocCollection, this._fullyRenderedDocs); - }); - }; - @action updateYMargin = (input: string) => { - this._layout.yMargin = Number(input); - setTimeout(() => { - if (!this._renderedDocCollection || !this._fullyRenderedDocs) return; - this.applyLayout(this._renderedDocCollection, this._fullyRenderedDocs); - }); - }; - @action updateColumns = (input: string) => { - this._layout.columns = Number(input); - this.updateRenderedDocCollection(); - }; - - get layoutConfigOptions() { - const optionInput = (icon: string, func: (input: string) => void, def?: number, key?: string, noMargin?: boolean) => { - return ( -
-
- -
- func(e.currentTarget.value)} className="docCreatorMenu-input config layout-config" /> -
- ); - }; - - switch (this._layout.type) { - case LayoutType.FREEFORM: - return ( -
- {optionInput('arrows-up-down', this.updateYMargin, this._layout.xMargin, '2')} - {optionInput('arrows-left-right', this.updateXMargin, this._layout.xMargin, '3')} - {optionInput('table-columns', this.updateColumns, this._layout.columns, '4', true)} -
- ); - default: - break; - } - } - - applyLayout = (collection: Doc, docs: Doc[]) => { - const { horizontalSpan, verticalSpan } = this.previewInfo; - collection._height = verticalSpan; - collection._width = horizontalSpan; - - const columns: number = this._layout.columns ?? this.columnsCount; - const xGap: number = this._layout.xMargin; - const yGap: number = this._layout.yMargin; - const startX: number = -Number(collection._width) / 2; - const startY: number = -Number(collection._height) / 2; - const docHeight: number = Number(docs[0]._height); - const docWidth: number = Number(docs[0]._width); - - if (columns === 0 || docs.length === 0) { - return; - } - - let i: number = 0; - let docsChanged: number = 0; - let curX: number = startX; - let curY: number = startY; - - while (docsChanged < docs.length) { - while (i < columns && docsChanged < docs.length) { - docs[docsChanged].x = curX; - docs[docsChanged].y = curY; - curX += docWidth + xGap; - ++docsChanged; - ++i; - } - i = 0; - curX = startX; - curY += docHeight + yGap; - } - }; - - @computed - get previewInfo() { - const docHeight: number = Number(this._fullyRenderedDocs[0]._height); - const docWidth: number = Number(this._fullyRenderedDocs[0]._width); - const layout = this._layout; - return { - docHeight: docHeight, - docWidth: docWidth, - horizontalSpan: (docWidth + layout.xMargin) * this.columnsCount - layout.xMargin, - verticalSpan: (docHeight + layout.yMargin) * this.rowsCount - layout.yMargin, - }; - } - - /** - * Updates the preview that shows how all docs will be rendered in the chosen collection type. - @type the type of collection the docs should render to (ie. freeform, carousel, card) - */ - updateRenderedDocCollection = () => { - if (!this._fullyRenderedDocs) return; - - 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; - } // prettier-ignore - }; - - const collection = collectionFactory()(this._fullyRenderedDocs, { - isDefaultTemplateDoc: true, - title: 'title', - backgroundColor: 'gray', - x: 200, - y: 200, - _width: 4000, - _height: 4000, - }); - - this.applyLayout(collection, this._fullyRenderedDocs); - - this._renderedDocCollection = collection; - - this._docsRendering = false; - - this.forceUpdate(); - }; - - layoutPreviewContents = action(() => { - return this._docsRendering ? ( -
-
- -
-
- ) : !this._renderedDocCollection ? null : ( -
- this._menuDimensions.width - 80} - PanelHeight={() => this._menuDimensions.height - 105} - ScreenToLocalTransform={() => new Transform(-this._pageX - 5, -this._pageY - 35, 1)} - renderDepth={5} - whenChildContentsActiveChanged={emptyFunction} - focus={emptyFunction} - styleProvider={DefaultStyleProvider} - addDocTab={this._props.addDocTab} - pinToPres={() => undefined} - childFilters={returnEmptyFilter} - childFiltersByRanges={returnEmptyFilter} - searchFilterDocs={returnEmptyDoclist} - fitContentsToBox={returnFalse} - fitWidth={returnFalse} - hideDecorations={true} + @computed + get templatesView() { return ( +
+
+ -
- ); - }); - - get optionsMenuContents() { - const layoutOption = (option: LayoutType, optStyle?: object, specialFunc?: () => void) => { - return ( -
- this.setUpButtonClick(e, () => { - specialFunc?.(); - runInAction(() => { - this._layout.type = option; - this.updateRenderedDocCollection(); - }); - }) - }> - {option} -
- ); - }; - - const selectionBox = (width: number, height: number, icon: string, specClass?: string, options?: JSX.Element[], manual?: boolean): JSX.Element => { - return ( -
-
- +
+
+
- {manual ? ( - - ) : ( - - )} -
- ); - }; - - const repeatOptions = [0, 1, 2, 3, 4, 5]; - - return ( -
-
-
-
{this._layout.type ? this._layout.type.toUpperCase() : 'Choose Layout'}
-
- {layoutOption(LayoutType.FREEFORM, undefined, () => { - if (!this._layout.columns) this._layout.columns = Math.ceil(Math.sqrt(this.docsToRender.length)); - })} - {layoutOption(LayoutType.CAROUSEL)} - {layoutOption(LayoutType.CAROUSEL3D)} - {layoutOption(LayoutType.MASONRY)} -
-
-
- {this._layout.type ? this.layoutConfigOptions : null} - {this.layoutPreviewContents()} - {selectionBox( - 60, - 20, - 'repeat', - undefined, - repeatOptions.map(num => ) - )} -
-
- -
- ); - } - - @observable private _newCondCache: Record = {}; - - getParams = (title: string, parameters?: Conditional): Conditional => { - if (parameters) return parameters; - - if (!this._newCondCache[title]) { - this._newCondCache[title] = observable({ - field: title, - operator: '=', - condition: '', - target: '', - attribute: '', - value: '' - }); - } - return this._newCondCache[title]; - }; - - get dashboardContents() { - const contentFieldTitles = this.fieldsInfos.filter(field => field.type !== TemplateFieldType.DATA).map(field => field.title).concat('Template'); - - const conditionForm = (title: string, parameters?: Conditional, empty: boolean = false) => { - - var params: Conditional = this.getParams(title, parameters); - - return ( -
-
-
If
-
{title}
-
- {params.operator ?? '='} -
{params.operator = '='}}>{'='}
-
{params.operator = '>'}}>{'>'}
-
{params.operator = '<'}}>{'<'}
-
{params.operator = 'contains'}}>{'has'}
-
- runInAction(() => params.condition = e.target.value)} - placeholder='value' - value={params.condition} - /> -
then
-
- {params.target} - {contentFieldTitles.map(fieldTitle => -
{params.target = fieldTitle}}>{fieldTitle === title ? 'Own' : fieldTitle}
- )} -
- runInAction(() => params.attribute = e.target.value)} - placeholder='attribute' - value={params.attribute} - /> -
{'becomes'}
- runInAction(() => params.value = e.target.value)} - placeholder='value' - value={params.value} - /> -
- {empty ? - { - this._newCondCache[title] = observable({ - field: title, - operator: '=', - condition: '', - target: '', - attribute: '', - value: '' - }); - this.templateManager.addFieldCondition(title, params); - }}/> - : - this.templateManager.removeFieldCondition(title, params)}/> - } -
- ) - } - - const fieldPanel = (field: Col, id: number) => ( -
-
this.setUpButtonClick(e, runInAction(() => () => { - if (this._collapsedCols.includes(field.title)) { - this._collapsedCols = this._collapsedCols.filter(col => col !== field.title); - } else { - this._collapsedCols.push(field.title); - } - }))}> - {`${field.title} Field`} - this.removeField(field)}/> -
- { this._collapsedCols.includes(field.title) ? null : - <> -
-
-
Title
-