aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2025-06-01 16:07:30 -0400
committerbobzel <zzzman@gmail.com>2025-06-01 16:07:30 -0400
commit215f874c5f7f28964a3428909fcee0f667388bae (patch)
treee9881d33b845032725e75cdf880d4637507e9a32 /src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu
parent451891b0e34c84873ccc89dde55442bb9bf23f3d (diff)
a number of fixes to document creator to fix preview of templates and templates with images.
Diffstat (limited to 'src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu')
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateEditingWindow.tsx277
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateMenuFieldOptions.tsx252
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplatePreviewBox.tsx113
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateRenderPreviewWindow.tsx97
4 files changed, 354 insertions, 385 deletions
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateEditingWindow.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateEditingWindow.tsx
index b50fff9e0..c35099e82 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateEditingWindow.tsx
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateEditingWindow.tsx
@@ -1,25 +1,25 @@
-import { action, makeObservable, observable, reaction, runInAction } from "mobx";
-import React from "react";
-import { returnFalse, returnEmptyFilter } from "../../../../../../ClientUtils";
-import { emptyFunction } from "../../../../../../Utils";
-import { Doc, returnEmptyDoclist } from "../../../../../../fields/Doc";
-import { DefaultStyleProvider } from "../../../../StyleProvider";
-import { DocumentView, DocumentViewInternal } from "../../../DocumentView";
-import { DocCreatorMenu } from "../DocCreatorMenu";
-import { TemplatePreviewGrid } from "./TemplatePreviewGrid";
-import { observer } from "mobx-react";
-import { Transform } from "../../../../../util/Transform";
-import { Template } from "../Template";
-import { ObservableReactComponent } from "../../../../ObservableReactComponent";
-import { IDisposer } from "mobx-utils";
-import { DocCreatorMenuButton } from "./DocCreatorMenuButton";
-import { IconProp } from "@fortawesome/fontawesome-svg-core";
+import { action, makeObservable, observable, reaction } from 'mobx';
+import React from 'react';
+import { returnFalse, returnEmptyFilter } from '../../../../../../ClientUtils';
+import { emptyFunction } from '../../../../../../Utils';
+import { returnEmptyDoclist } from '../../../../../../fields/Doc';
+import { DefaultStyleProvider } from '../../../../StyleProvider';
+import { DocumentView, DocumentViewInternal } from '../../../DocumentView';
+import { DocCreatorMenu } from '../DocCreatorMenu';
+import { TemplatePreviewGrid } from './TemplatePreviewGrid';
+import { observer } from 'mobx-react';
+import { Transform } from '../../../../../util/Transform';
+import { Template } from '../Template';
+import { ObservableReactComponent } from '../../../../ObservableReactComponent';
+import { IDisposer } from 'mobx-utils';
+import { DocCreatorMenuButton } from './DocCreatorMenuButton';
+import { IconProp } from '@fortawesome/fontawesome-svg-core';
export type FireflyStructureOptions = {
numVariations: number;
temperature: number;
useStyleRef: boolean;
-}
+};
interface FireflyVariationsTabProps {
menu: DocCreatorMenu;
@@ -28,112 +28,93 @@ interface FireflyVariationsTabProps {
@observer
export class FireflyVariationsTab extends ObservableReactComponent<FireflyVariationsTabProps> {
+ private _prompt: string = 'Use this template to generate an empty baseball card template.';
+ private _optionsButtonOpts: [IconProp, () => void] = ['gear', emptyFunction];
+ private _previewBoxRightButtonOpts: [IconProp, () => void] = ['gear', () => this.forceUpdate()];
- private prompt: string = 'Use this template to generate an empty baseball card template.';
-
- @observable private promptInput: HTMLTextAreaElement | null = null;
-
+ @observable _fireflyOptions: FireflyStructureOptions = { numVariations: 3, temperature: 0, useStyleRef: false };
+ @observable _promptInput: HTMLTextAreaElement | null = null;
@observable _loading: boolean = false;
@observable _variationsTabOpen: boolean = false;
@observable _variationURLs: string[] = [];
- @observable private fireflyOptions: FireflyStructureOptions = {numVariations: 3, temperature: 0, useStyleRef: false};
-
constructor(props: FireflyVariationsTabProps) {
super(props);
makeObservable(this);
}
- generateVariations = async () => {
+ generateVariations = action(async () => {
this._props.menu._variations = [];
this._loading = true;
const cloneTemplate = this._props.template.clone(false);
cloneTemplate.setMatteBackground();
- const doc: Doc = cloneTemplate.getRenderedDoc()!;
- this._variationURLs = await this._props.menu.generateVariations(doc, this.prompt, this.fireflyOptions);
- this._variationURLs.forEach(() => {
- const newTemplate: Template = this._props.template.clone(true);
- this._props.menu._variations.push(newTemplate);
- });
- setTimeout(() => {
- this._variationURLs.forEach((url, i) => {
- this._props.menu._variations[i].setImageAsBackground(url, true);
- });
- this._loading = false;
- });
- }
-
- setPromptInputRef: React.LegacyRef<HTMLTextAreaElement> = (node) => {
- this.promptInput = node;
- }
-
- // eslint-disable-next-line
- private optionsButtonOpts: [IconProp, () => any] = ['gear', () => {}];
- // eslint-disable-next-line
- private previewBoxRightButtonOpts: [IconProp, () => any] = ['gear', () => this.forceUpdate()];
+ const doc = cloneTemplate.getRenderedDoc()!;
+ this._props.menu.generateVariations(doc, this._prompt, this._fireflyOptions).then(
+ action((urls: string[]) => {
+ (this._variationURLs = urls).forEach(url => {
+ const template = this._props.template.clone(true);
+ template.setImageAsBackground(url, true);
+ this._props.menu._variations.push(template);
+ });
+ this._loading = false;
+ })
+ );
+ });
render() {
return (
- <div className='docCreatorMenu-editing-firefly-section'>
- <div className="docCreatorMenu-option-divider full no-margin-bottom"/>
+ <div className="docCreatorMenu-editing-firefly-section">
+ <div className="docCreatorMenu-option-divider full no-margin-bottom" />
<TemplatePreviewGrid
menu={this._props.menu}
- title={'Generate Variations'}
+ title="Generate Variations"
loading={this._loading}
- styles={'scrolling'}
+ styles="scrolling"
templates={this._props.menu._variations}
- optionsButtonOpts={this.optionsButtonOpts}
- previewBoxRightButtonOpts={this.previewBoxRightButtonOpts}
+ optionsButtonOpts={this._optionsButtonOpts}
+ previewBoxRightButtonOpts={this._previewBoxRightButtonOpts}
/>
<div className="docCreatorMenu-firefly-options">
<div className="docCreatorMenu-variation-prompt-row">
<textarea
className="docCreatorMenu-variation-prompt-input-textbox"
- ref={this.setPromptInputRef}
- onChange={e => { this.prompt = e.target.value }}
+ ref={action((node: HTMLTextAreaElement | null) => (this._promptInput = node))}
+ onChange={e => (this._prompt = e.target.value)}
onInput={() => {
- if (this.promptInput !== null) {
- this.promptInput.style.height = 'auto';
- this.promptInput.style.height = this.promptInput.scrollHeight + 'px';
+ if (this._promptInput !== null) {
+ this._promptInput.style.height = 'auto';
+ this._promptInput.style.height = this._promptInput.scrollHeight + 'px';
}
}}
- defaultValue={''}
- placeholder={'Enter a custom prompt here (optional)'}
+ defaultValue=""
+ placeholder="Enter a custom prompt here (optional)"
/>
- <DocCreatorMenuButton icon={'arrows-rotate'} styles={'border'} function={this.generateVariations}/>
+ <DocCreatorMenuButton icon={'arrows-rotate'} styles={'border'} function={this.generateVariations} />
</div>
- <nav className="options‑menu">
- <label className="menu‑item switch">
- <input type="checkbox" checked={this.fireflyOptions.useStyleRef}
- onChange={(e) => runInAction(() => { this.fireflyOptions.useStyleRef = e.target.checked })}
- />
- <span className="slider round"></span>
- <span className="firefly-option-label">Use template as style guide</span>
- </label>
- <div className="menu‑item">
- <span className="firefly-option-label">Variations</span>
- <input type="range" id="variations"
- min="1"
- max="5"
- value={this.fireflyOptions.numVariations}
- onChange={(e) => runInAction(() => { this.fireflyOptions.numVariations = Number(e.target.value) })}
- />
- <span className="value" id="varVal">{this.fireflyOptions.numVariations}</span>
- </div>
- <div className="menu‑item">
- <span className="firefly-option-label">Temperature</span>
- <input type="range" id="temperature"
- min="1"
- max="100"
- value={this.fireflyOptions.temperature}
- onChange={(e) => runInAction(() => { this.fireflyOptions.temperature = Number(e.target.value) })}
- />
- <span className="value" id="tempVal">{this.fireflyOptions.temperature}</span>
- </div>
- </nav>
+ <nav className="options‑menu">
+ <label className="menu‑item switch">
+ <input type="checkbox" checked={this._fireflyOptions.useStyleRef} onChange={action(e => (this._fireflyOptions.useStyleRef = e.target.checked))} />
+ <span className="slider round"></span>
+ <span className="firefly-option-label">Use template as style guide</span>
+ </label>
+ <div className="menu‑item">
+ <span className="firefly-option-label">Variations</span>
+ <input type="range" id="variations" min="1" max="5" value={this._fireflyOptions.numVariations} onChange={action(e => (this._fireflyOptions.numVariations = Number(e.target.value)))} />
+ <span className="value" id="varVal">
+ {this._fireflyOptions.numVariations}
+ </span>
+ </div>
+ <div className="menu‑item">
+ <span className="firefly-option-label">Temperature</span>
+ <input type="range" id="temperature" min="1" max="100" value={this._fireflyOptions.temperature} onChange={action(e => (this._fireflyOptions.temperature = Number(e.target.value)))} />
+ <span className="value" id="tempVal">
+ {this._fireflyOptions.temperature}
+ </span>
+ </div>
+ </nav>
</div>
</div>
- )
+ );
}
}
@@ -144,11 +125,9 @@ interface TemplateEditingWindowProps {
@observer
export class TemplateEditingWindow extends ObservableReactComponent<TemplateEditingWindowProps> {
-
private disposers: { [name: string]: IDisposer } = {};
- @observable private previewWindow: HTMLDivElement | null = null;
-
+ @observable private _previewWindow: HTMLDivElement | null = null;
@observable _variationsTabOpen: boolean = false;
constructor(props: TemplateEditingWindowProps) {
@@ -157,83 +136,85 @@ export class TemplateEditingWindow extends ObservableReactComponent<TemplateEdit
}
componentDidMount(): void {
- this.disposers.windowDimensions = reaction(() =>
- this._props.menu._resizing,
- () => { this.forceUpdate() },
+ this.disposers.windowDimensions = reaction(
+ () => this._props.menu._resizing,
+ () => this.forceUpdate(),
{ fireImmediately: true }
- );
+ );
}
componentWillUnmount() {
Object.values(this.disposers).forEach(disposer => disposer?.());
}
- setContainerRef: React.LegacyRef<HTMLDivElement> = (node) => {
- this.previewWindow = node;
- }
-
@action setVariationTab = (open: boolean) => {
this._variationsTabOpen = open;
- if (this.previewWindow && open) {
- this.previewWindow.style.height = String(Number(this.previewWindow.clientHeight) * .6);
- } else if (this.previewWindow && !open) {
- this.previewWindow.style.height = String(Number(this.previewWindow.clientHeight) * 5/3);
+ if (this._previewWindow && open) {
+ this._previewWindow.style.height = String(Number(this._previewWindow.clientHeight) * 0.6);
+ } else if (this._previewWindow && !open) {
+ this._previewWindow.style.height = String((Number(this._previewWindow.clientHeight) * 5) / 3);
}
- }
-
- get renderedDocPreview(){
- const doc: Doc = this._props.template.getRenderedDoc() as unknown as Doc;
+ };
+ previewPanelWidth = () => this._previewWindow?.clientWidth ?? 500;
+ previewPanelHeight = () => this._previewWindow?.clientHeight ?? 500;
+ previewScreenToLocalXf = () => new Transform(-this._props.menu._pageX - 5, -this._props.menu._pageY - 35, 1);
+ get renderedDocPreview() {
+ const doc = this._props.template.getRenderedDoc();
return (
- <div className="docCreatorMenu-expanded-template-preview" ref={this.setContainerRef}>
- {this.previewWindow ? <DocumentView
- Document={doc}
- isContentActive={emptyFunction}
- addDocument={returnFalse}
- moveDocument={returnFalse}
- removeDocument={returnFalse}
- PanelWidth={() => this.previewWindow?.clientWidth ?? 500}
- PanelHeight={() => this.previewWindow?.clientHeight ?? 500}
- ScreenToLocalTransform={() => new Transform(-this._props.menu._pageX - 5, -this._props.menu._pageY - 35, 1)}
- renderDepth={5}
- whenChildContentsActiveChanged={emptyFunction}
- focus={emptyFunction}
- styleProvider={DefaultStyleProvider}
- addDocTab={DocumentViewInternal.addDocTabFunc}
- pinToPres={() => undefined}
- childFilters={returnEmptyFilter}
- childFiltersByRanges={returnEmptyFilter}
- searchFilterDocs={returnEmptyDoclist}
- fitContentsToBox={returnFalse}
- fitWidth={returnFalse}
- /> : null}
+ <div className="docCreatorMenu-expanded-template-preview" ref={action((node: HTMLDivElement | null) => (this._previewWindow = node))}>
+ {this._previewWindow && doc ? (
+ <DocumentView
+ Document={doc}
+ isContentActive={emptyFunction}
+ addDocument={returnFalse}
+ moveDocument={returnFalse}
+ removeDocument={returnFalse}
+ PanelWidth={this.previewPanelWidth}
+ PanelHeight={this.previewPanelHeight}
+ ScreenToLocalTransform={this.previewScreenToLocalXf}
+ renderDepth={5}
+ whenChildContentsActiveChanged={emptyFunction}
+ focus={emptyFunction}
+ styleProvider={DefaultStyleProvider}
+ addDocTab={DocumentViewInternal.addDocTabFunc}
+ pinToPres={emptyFunction}
+ childFilters={returnEmptyFilter}
+ childFiltersByRanges={returnEmptyFilter}
+ searchFilterDocs={returnEmptyDoclist}
+ // fitContentsToBox={returnFalse}
+ // fitWidth={returnFalse}
+ />
+ ) : null}
</div>
- )
+ );
}
+ expandFunc = () => {
+ // if (this._props.template === this._props.menu._selectedTemplate) {
+ // this._props.menu.updateRenderedPreviewCollection(this._props.template);
+ // }
+ this._props.menu.setExpandedView(undefined);
+ };
+ lastFunc = () => {
+ this._props.menu.editLastTemplate();
+ this.forceUpdate();
+ };
+ variationFunc = () => this.setVariationTab(!this._variationsTabOpen);
render() {
return (
- <div className='docCreatorMenu-templates-view'>
+ <div className="docCreatorMenu-templates-view">
<div className="docCreatorMenu-expanded-template-preview">
- <div className="top-panel"/>
+ <div className="top-panel" />
{this.renderedDocPreview}
- {this._variationsTabOpen ? <FireflyVariationsTab
- menu={this._props.menu}
- template={this._props.template}
- />
- : null}
+ {this._variationsTabOpen ? <FireflyVariationsTab menu={this._props.menu} template={this._props.template} /> : null}
<div className="right-buttons-panel">
- <DocCreatorMenuButton icon={'minimize'} function={() => {
- // if (this._props.template === this._props.menu._selectedTemplate) {
- // this._props.menu.updateRenderedPreviewCollection(this._props.template);
- // }
- this._props.menu.setExpandedView(undefined);
- }}/>
- <DocCreatorMenuButton icon={'lightbulb'} function={() => this.setVariationTab(!this._variationsTabOpen)}/>
- <DocCreatorMenuButton icon={'arrow-rotate-backward'} function={() => { this._props.menu.editLastTemplate(); this.forceUpdate(); }}/>
+ <DocCreatorMenuButton icon="minimize" function={this.expandFunc} />
+ <DocCreatorMenuButton icon="lightbulb" function={this.variationFunc} />
+ <DocCreatorMenuButton icon="arrow-rotate-backward" function={this.lastFunc} />
</div>
</div>
</div>
);
}
-} \ No newline at end of file
+}
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateMenuFieldOptions.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateMenuFieldOptions.tsx
index a4da54392..f0e20837c 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateMenuFieldOptions.tsx
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateMenuFieldOptions.tsx
@@ -1,11 +1,11 @@
-import { makeObservable, observable, runInAction } from "mobx";
-import { observer } from "mobx-react";
-import { ObservableReactComponent } from "../../../../ObservableReactComponent";
-import { Col, DocCreatorMenu } from "../DocCreatorMenu";
-import React from "react";
-import { Conditional, TemplateManager } from "../Backend/TemplateManager";
-import { TemplateFieldType, TemplateFieldSize } from "../TemplateBackend";
-import { DocCreatorMenuButton } from "./DocCreatorMenuButton";
+import { action, makeObservable, observable } from 'mobx';
+import { observer } from 'mobx-react';
+import { ObservableReactComponent } from '../../../../ObservableReactComponent';
+import { Col, DocCreatorMenu } from '../DocCreatorMenu';
+import React from 'react';
+import { Conditional, TemplateManager } from '../Backend/TemplateManager';
+import { TemplateFieldType, TemplateFieldSize } from '../TemplateBackend';
+import { DocCreatorMenuButton } from './DocCreatorMenuButton';
interface TemplateMenuFieldOptionsProps {
menu: DocCreatorMenu;
@@ -14,7 +14,6 @@ interface TemplateMenuFieldOptionsProps {
@observer
export class TemplateMenuFieldOptions extends ObservableReactComponent<TemplateMenuFieldOptionsProps> {
-
@observable _collapsedCols: string[] = []; //any columns whose options panels are hidden
constructor(props: TemplateMenuFieldOptionsProps) {
@@ -34,160 +33,153 @@ export class TemplateMenuFieldOptions extends ObservableReactComponent<TemplateM
condition: '',
target: 'Own',
attribute: '',
- value: ''
+ value: '',
});
}
return this._newCondCache[title];
};
conditionForm = (title: string, parameters?: Conditional, empty: boolean = false) => {
-
- const contentFieldTitles = this._props.menu.fieldsInfos.filter(field => field.type !== TemplateFieldType.DATA).map(field => field.title).concat('Template');
+ const contentFieldTitles = this._props.menu.fieldsInfos
+ .filter(field => field.type !== TemplateFieldType.DATA)
+ .map(field => field.title)
+ .concat('Template');
const params: Conditional = this.getParams(title, parameters);
return (
- <div className='form'>
- <div className='form-row'>
- <div className='form-row-plain-text'>If</div>
- <div className='form-row-plain-text'>{title}</div>
- <div className="operator-options-dropdown">
- <span className="operator-dropdown-current">{params.operator ?? '='}</span>
- <div className='operator-dropdown-option' onPointerDown={() => {params.operator = '='}}>{'='}</div>
- </div>
- <input
- className="form-row-textarea"
- onChange={e => runInAction(() => { params.condition = e.target.value })}
- placeholder='value'
- value={params.condition}
- />
- <div className='form-row-plain-text'>then</div>
- <div className="operator-options-dropdown">
- <span className="operator-dropdown-current">{params.target ?? 'Own'}</span>
- {contentFieldTitles.map((fieldTitle, i) =>
- <div className='operator-dropdown-option' key={i} onPointerDown={() => {params.target = fieldTitle}}>{fieldTitle === title ? 'Own' : fieldTitle}</div>
- )}
+ <div className="form">
+ <div className="form-row">
+ <div className="form-row-plain-text">If</div>
+ <div className="form-row-plain-text">{title}</div>
+ <div className="operator-options-dropdown">
+ <span className="operator-dropdown-current">{params.operator ?? '='}</span>
+ <div className="operator-dropdown-option" onPointerDown={() => (params.operator = '=')}>
+ {'='}
+ </div>
+ </div>
+ <input className="form-row-textarea" onChange={action(e => (params.condition = e.target.value))} placeholder="value" value={params.condition} />
+ <div className="form-row-plain-text">then</div>
+ <div className="operator-options-dropdown">
+ <span className="operator-dropdown-current">{params.target ?? 'Own'}</span>
+ {contentFieldTitles.map((fieldTitle, i) => (
+ <div className="operator-dropdown-option" key={i} onPointerDown={() => (params.target = fieldTitle)}>
+ {fieldTitle === title ? 'Own' : fieldTitle}
+ </div>
+ ))}
+ </div>
+ <input className="form-row-textarea" onChange={action(e => (params.attribute = e.target.value))} placeholder="attribute" value={params.attribute} />
+ <div className="form-row-plain-text">{'becomes'}</div>
+ <input className="form-row-textarea" onChange={action(e => (params.value = e.target.value))} placeholder="value" value={params.value} />
</div>
- <input
- className="form-row-textarea"
- onChange={e => runInAction(() => { params.attribute = e.target.value })}
- placeholder='attribute'
- value={params.attribute}
- />
- <div className='form-row-plain-text'>{'becomes'}</div>
- <input
- className="form-row-textarea"
- onChange={e => runInAction(() => { params.value = e.target.value })}
- placeholder='value'
- value={params.value}
- />
+ {empty ? (
+ <DocCreatorMenuButton
+ icon={'plus'}
+ styles={'float-right border'}
+ function={() => {
+ this._newCondCache[title] = observable<Conditional>({
+ field: title,
+ operator: '=',
+ condition: '',
+ target: 'Own',
+ attribute: '',
+ value: '',
+ });
+ this._props.templateManager.addFieldCondition(title, params);
+ }}
+ />
+ ) : (
+ <DocCreatorMenuButton icon={'minus'} styles={'float-right border'} function={() => this._props.templateManager.removeFieldCondition(title, params)} />
+ )}
</div>
- {empty ?
- <DocCreatorMenuButton icon={'plus'} styles={'float-right border'} function={() => {
- this._newCondCache[title] = observable<Conditional>({
- field: title,
- operator: '=',
- condition: '',
- target: 'Own',
- attribute: '',
- value: ''
- });
- this._props.templateManager.addFieldCondition(title, params);
- }}/>
- :
- <DocCreatorMenuButton icon={'minus'} styles={'float-right border'} function={() => this._props.templateManager.removeFieldCondition(title, params)}/>
- }
- </div>
- )
- }
+ );
+ };
fieldPanel = (field: Col, id: number) => (
<div className="field-panel" key={id}>
- <div className="top-bar" onPointerDown={e => this._props.menu.setUpButtonClick(e, runInAction(() => () => {
- if (this._collapsedCols.includes(field.title)) {
- this._collapsedCols = this._collapsedCols.filter(col => col !== field.title);
- } else {
- this._collapsedCols.push(field.title);
- }
- }))}>
+ <div
+ className="top-bar"
+ onPointerDown={e =>
+ this._props.menu.setUpButtonClick(
+ e,
+ action(() => {
+ if (this._collapsedCols.includes(field.title)) {
+ this._collapsedCols = this._collapsedCols.filter(col => col !== field.title);
+ } else {
+ this._collapsedCols.push(field.title);
+ }
+ })
+ )
+ }>
<span className="field-title">{`${field.title} Field`}</span>
- <DocCreatorMenuButton icon={'minus'} styles={'no-margin absolute-right'} function={() => this._props.menu.removeField(field)}/>
+ <DocCreatorMenuButton icon={'minus'} styles={'no-margin absolute-right'} function={() => this._props.menu.removeField(field)} />
</div>
- { this._collapsedCols.includes(field.title) ? null :
+ {this._collapsedCols.includes(field.title) ? null : (
<>
- <div className="opts-bar">
- <div className="opt-box">
- <div className="top-bar"> Title </div>
- <textarea className="content" style={{ width: '100%', height: 'calc(100% - 20px)' }} value={field.title} placeholder={'Enter title'} onChange={e => this._props.menu.setColTitle(field, e.target.value)} />
- </div>
- <div className="opt-box">
- <div className="top-bar"> Type </div>
- <div className="content">
- <span className="type-display">{
- field.type === TemplateFieldType.TEXT ? 'Text Field'
- : field.type === TemplateFieldType.VISUAL ? 'File Field'
- : field.type === TemplateFieldType.DATA ? 'Data Field'
- : ''
- }</span>
- <div className="bubbles">
- <input className="bubble" type="radio" name="type" onClick={() => this._props.menu.setColType(field, TemplateFieldType.TEXT)} />
- <div className="text">Text</div>
- <input className="bubble" type="radio" name="type" onClick={() => this._props.menu.setColType(field, TemplateFieldType.VISUAL)} />
- <div className="text">File</div>
- <input className="bubble" type="radio" name="type" onClick={() => this._props.menu.setColType(field, TemplateFieldType.DATA)} />
- <div className="text">Data</div>
- </div>
+ <div className="opts-bar">
+ <div className="opt-box">
+ <div className="top-bar"> Title </div>
+ <textarea className="content" style={{ width: '100%', height: 'calc(100% - 20px)' }} value={field.title} placeholder={'Enter title'} onChange={e => this._props.menu.setColTitle(field, e.target.value)} />
</div>
- </div>
- </div>
- { field.type === TemplateFieldType.DATA ? null :
- (<>
- <div className="sizes-box">
- <div className="top-bar"> Valid Sizes </div>
+ <div className="opt-box">
+ <div className="top-bar"> Type </div>
<div className="content">
+ <span className="type-display">{field.type === TemplateFieldType.TEXT ? 'Text Field' : field.type === TemplateFieldType.VISUAL ? 'File Field' : field.type === TemplateFieldType.DATA ? 'Data Field' : ''}</span>
<div className="bubbles">
- {Object.values(TemplateFieldSize).map(size => (
- <div key={field + size}>
- <input className="bubble" type="checkbox" name="type" checked={field.sizes.includes(size)} onChange={e => this._props.menu.modifyColSizes(field, size, e.target.checked)} />
- <div className="text">{size}</div>
- </div>
- ))}
+ <input className="bubble" type="radio" name="type" onClick={() => this._props.menu.setColType(field, TemplateFieldType.TEXT)} />
+ <div className="text">Text</div>
+ <input className="bubble" type="radio" name="type" onClick={() => this._props.menu.setColType(field, TemplateFieldType.VISUAL)} />
+ <div className="text">File</div>
+ <input className="bubble" type="radio" name="type" onClick={() => this._props.menu.setColType(field, TemplateFieldType.DATA)} />
+ <div className="text">Data</div>
</div>
</div>
</div>
- <div className="desc-box">
- <div className="top-bar"> Prompt </div>
- <textarea
- className="content"
- onChange={e => this._props.menu.setColDesc(field, e.target.value)}
- defaultValue={field.desc === this._props.menu._dataViz?.GPTSummary?.get(field.title)?.desc ? '' : field.desc}
- placeholder={this._props.menu._dataViz?.GPTSummary?.get(field.title)?.desc ?? 'Add a description/prompt to help with template generation.'}
- />
- </div>
- </>)
- }
- <div className="conditionals-section">
- <span className="conditionals-title">Conditional Logic</span>
- {this.conditionForm(field.title, undefined, true)}
- {this._props.templateManager.conditionalFieldLogic[field.title]?.map(condition => this.conditionForm(condition.field, condition))}
- </div>
+ </div>
+ {field.type === TemplateFieldType.DATA ? null : (
+ <>
+ <div className="sizes-box">
+ <div className="top-bar"> Valid Sizes </div>
+ <div className="content">
+ <div className="bubbles">
+ {Object.values(TemplateFieldSize).map(size => (
+ <div key={field + size}>
+ <input className="bubble" type="checkbox" name="type" checked={field.sizes.includes(size)} onChange={e => this._props.menu.modifyColSizes(field, size, e.target.checked)} />
+ <div className="text">{size}</div>
+ </div>
+ ))}
+ </div>
+ </div>
+ </div>
+ <div className="desc-box">
+ <div className="top-bar"> Prompt </div>
+ <textarea
+ className="content"
+ onChange={e => this._props.menu.setColDesc(field, e.target.value)}
+ defaultValue={field.desc === this._props.menu._dataViz?.GPTSummary?.get(field.title)?.desc ? '' : field.desc}
+ placeholder={this._props.menu._dataViz?.GPTSummary?.get(field.title)?.desc ?? 'Add a description/prompt to help with template generation.'}
+ />
+ </div>
+ </>
+ )}
+ <div className="conditionals-section">
+ <span className="conditionals-title">Conditional Logic</span>
+ {this.conditionForm(field.title, undefined, true)}
+ {this._props.templateManager._conditionalFieldLogic[field.title]?.map(condition => this.conditionForm(condition.field, condition))}
+ </div>
</>
- }
+ )}
</div>
);
-
-
render() {
return (
<div className="docCreatorMenu-dashboard-view">
<div className="topbar">
- <DocCreatorMenuButton icon={'plus'} function={this._props.menu.addField}/>
- <DocCreatorMenuButton icon={'arrow-left'} styles={'float-right'} function={() => runInAction(() => (this._props.menu._menuContent = 'templates'))}/>
+ <DocCreatorMenuButton icon="plus" function={this._props.menu.addField} />
+ <DocCreatorMenuButton icon="arrow-left" styles="float-right" function={action(() => (this._props.menu._menuContent = 'templates'))} />
</div>
<div className="panels-container">{this._props.menu.fieldsInfos.map((field, i) => this.fieldPanel(field, i))}</div>
</div>
);
}
-
-
-} \ No newline at end of file
+}
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplatePreviewBox.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplatePreviewBox.tsx
index dc4c35789..7d02fff12 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplatePreviewBox.tsx
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplatePreviewBox.tsx
@@ -1,35 +1,30 @@
-import { Colors } from "@dash/components/src";
-import { FontAwesomeIcon} from "@fortawesome/react-fontawesome";
-import { Template } from "../Template";
-import { makeObservable, observable } from "mobx";
-import React from "react";
-import { ObservableReactComponent } from "../../../../ObservableReactComponent";
-import { DocCreatorMenu } from "../DocCreatorMenu";
-import { IconProp } from "@fortawesome/fontawesome-svg-core";
-import { DocumentView } from "../../../DocumentView";
-import { emptyFunction } from "../../../../../../Utils";
-import { returnEmptyFilter, returnFalse } from "../../../../../../ClientUtils";
-import { Transform } from "../../../../../util/Transform";
-import { DefaultStyleProvider } from "../../../../StyleProvider";
-import { Doc, returnEmptyDoclist } from "../../../../../../fields/Doc";
-import { observer } from "mobx-react";
+import { Colors } from '@dash/components/src';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { Template } from '../Template';
+import { action, makeObservable, observable } from 'mobx';
+import React from 'react';
+import { ObservableReactComponent } from '../../../../ObservableReactComponent';
+import { DocCreatorMenu } from '../DocCreatorMenu';
+import { IconProp } from '@fortawesome/fontawesome-svg-core';
+import { DocumentView } from '../../../DocumentView';
+import { emptyFunction } from '../../../../../../Utils';
+import { returnEmptyFilter, returnFalse } from '../../../../../../ClientUtils';
+import { Transform } from '../../../../../util/Transform';
+import { DefaultStyleProvider } from '../../../../StyleProvider';
+import { Doc, returnEmptyDoclist } from '../../../../../../fields/Doc';
+import { observer } from 'mobx-react';
export interface TemplatePreviewBoxProps {
template: Template;
menu: DocCreatorMenu; // eslint-disable-next-line
- leftButtonOpts?: [icon: IconProp, func: (...args: any) => void] // eslint-disable-next-line
- rightButtonOpts?: [icon: IconProp, func: (...args: any) => void]
+ leftButtonOpts?: [icon: IconProp, func: (...args: any) => void]; // eslint-disable-next-line
+ rightButtonOpts?: [icon: IconProp, func: (...args: any) => void];
}
@observer
export class TemplatePreviewBox extends ObservableReactComponent<TemplatePreviewBoxProps> {
-
@observable private previewWindow: HTMLDivElement | null = null;
- setContainerRef: React.LegacyRef<HTMLDivElement> = (node) => {
- this.previewWindow = node;
- }
-
constructor(props: TemplatePreviewBoxProps) {
super(props);
makeObservable(this);
@@ -39,6 +34,10 @@ export class TemplatePreviewBox extends ObservableReactComponent<TemplatePreview
return this._props.template.getRenderedDoc() as Doc;
}
+ docPanelWidth = () => this.previewWindow?.clientWidth ?? this._props.menu._menuDimensions.height * 0.3;
+ docPanelHeight = () => this.previewWindow?.clientHeight ?? this._props.menu._menuDimensions.height * 0.3;
+ docScreenToLocalXf = () => new Transform(-this._props.menu._pageX - 5, -this._props.menu._pageY - 35, 1);
+
render() {
const template = this._props.template;
@@ -46,49 +45,45 @@ export class TemplatePreviewBox extends ObservableReactComponent<TemplatePreview
<div
key={template.title}
className="docCreatorMenu-preview-window"
- ref={this.setContainerRef}
+ ref={action((node: HTMLDivElement | null) => (this.previewWindow = node))}
style={{
border: this._props.menu._selectedTemplate === template ? `solid 3px ${Colors.MEDIUM_BLUE}` : '',
boxShadow: this._props.menu._selectedTemplate === template ? `0 0 15px rgba(68, 118, 247, .8)` : '',
}}
- onPointerDown={e => this._props.menu.setUpButtonClick(e, () => this._props.menu.updateSelectedTemplate(template))}
- >
- { this._props.leftButtonOpts ?
- <button
- className="option-button left"
- onPointerDown={e =>
- this._props.menu.setUpButtonClick(e, () => this._props.leftButtonOpts![1](template))
- }>
+ onPointerDown={e => this._props.menu.setUpButtonClick(e, () => this._props.menu.updateSelectedTemplate(template))}>
+ {this._props.leftButtonOpts ? (
+ <button className="option-button left" onPointerDown={e => this._props.menu.setUpButtonClick(e, () => this._props.leftButtonOpts![1](template))}>
<FontAwesomeIcon icon={this._props.leftButtonOpts![0]} color="white" />
- </button> : null
- }
- { this._props.rightButtonOpts ?
+ </button>
+ ) : null}
+ {this._props.rightButtonOpts ? (
<button className="option-button right" onPointerDown={e => this._props.menu.setUpButtonClick(e, () => this._props.rightButtonOpts![1](template))}>
<FontAwesomeIcon icon={this._props.rightButtonOpts![0]} color="white" />
- </button> : null }
- <DocumentView
- Document={this.doc}
- isContentActive={emptyFunction} // !!! should be return false
- addDocument={returnFalse}
- moveDocument={returnFalse}
- removeDocument={returnFalse}
- PanelWidth={() => this.previewWindow?.clientWidth ?? this._props.menu._menuDimensions.height * .3}
- PanelHeight={() => this.previewWindow?.clientHeight ?? this._props.menu._menuDimensions.height * .3}
- ScreenToLocalTransform={() => new Transform(-this._props.menu._pageX - 5, -this._props.menu._pageY - 35, 1)}
- renderDepth={1}
- whenChildContentsActiveChanged={emptyFunction}
- focus={emptyFunction}
- styleProvider={DefaultStyleProvider}
- addDocTab={this._props.menu._props.addDocTab}
- pinToPres={() => undefined}
- childFilters={returnEmptyFilter}
- childFiltersByRanges={returnEmptyFilter}
- searchFilterDocs={returnEmptyDoclist}
- fitContentsToBox={returnFalse}
- fitWidth={returnFalse}
- hideDecorations={true}
- />
+ </button>
+ ) : null}
+ <DocumentView
+ Document={this.doc}
+ isContentActive={emptyFunction} // !!! should be return false
+ addDocument={returnFalse}
+ moveDocument={returnFalse}
+ removeDocument={returnFalse}
+ PanelWidth={this.docPanelWidth}
+ PanelHeight={this.docPanelHeight}
+ ScreenToLocalTransform={this.docScreenToLocalXf}
+ renderDepth={1}
+ whenChildContentsActiveChanged={emptyFunction}
+ focus={emptyFunction}
+ styleProvider={DefaultStyleProvider}
+ addDocTab={this._props.menu._props.addDocTab}
+ pinToPres={emptyFunction}
+ childFilters={returnEmptyFilter}
+ childFiltersByRanges={returnEmptyFilter}
+ searchFilterDocs={returnEmptyDoclist}
+ // fitContentsToBox={returnFalse}
+ // fitWidth={returnFalse}
+ hideDecorations={true}
+ />
</div>
- )
+ );
}
-} \ No newline at end of file
+}
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateRenderPreviewWindow.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateRenderPreviewWindow.tsx
index f281f770e..9222d7349 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateRenderPreviewWindow.tsx
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateRenderPreviewWindow.tsx
@@ -1,20 +1,20 @@
-import { action, computed, makeObservable, observable, runInAction } from "mobx";
-import { observer } from "mobx-react";
-import { ObservableReactComponent } from "../../../../ObservableReactComponent";
-import { DocCreatorMenu, LayoutType } from "../DocCreatorMenu";
-import React from "react";
-import { IconProp } from "@fortawesome/fontawesome-svg-core";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { setupMoveUpEvents, returnFalse, returnEmptyFilter } from "../../../../../../ClientUtils";
-import { emptyFunction } from "../../../../../../Utils";
-import { undoable } from "../../../../../util/UndoManager";
-import ReactLoading from "react-loading";
-import { Doc, NumListCast, returnEmptyDoclist } from "../../../../../../fields/Doc";
-import { StrCast } from "../../../../../../fields/Types";
-import { DefaultStyleProvider } from "../../../../StyleProvider";
-import { DocumentView } from "../../../DocumentView";
-import { Transform } from "../../../../../util/Transform";
-import { Docs, DocumentOptions } from "../../../../../documents/Documents";
+import { action, computed, makeObservable, observable, runInAction } from 'mobx';
+import { observer } from 'mobx-react';
+import { ObservableReactComponent } from '../../../../ObservableReactComponent';
+import { DocCreatorMenu, LayoutType } from '../DocCreatorMenu';
+import React from 'react';
+import { IconProp } from '@fortawesome/fontawesome-svg-core';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { setupMoveUpEvents, returnFalse, returnEmptyFilter } from '../../../../../../ClientUtils';
+import { emptyFunction } from '../../../../../../Utils';
+import { undoable } from '../../../../../util/UndoManager';
+import ReactLoading from 'react-loading';
+import { Doc, NumListCast, returnEmptyDoclist } from '../../../../../../fields/Doc';
+import { NumCast, StrCast } from '../../../../../../fields/Types';
+import { DefaultStyleProvider } from '../../../../StyleProvider';
+import { DocumentView } from '../../../DocumentView';
+import { Transform } from '../../../../../util/Transform';
+import { Docs, DocumentOptions } from '../../../../../documents/Documents';
interface TemplatesRenderPreviewWindowProps {
menu: DocCreatorMenu;
@@ -22,8 +22,7 @@ interface TemplatesRenderPreviewWindowProps {
@observer
export class TemplatesRenderPreviewWindow extends ObservableReactComponent<TemplatesRenderPreviewWindowProps> {
-
- @observable private _layout: { type: LayoutType; yMargin: number; xMargin: number; columns?: number; repeat: number } = { type: LayoutType.FREEFORM, yMargin: 10, xMargin: 10, columns: 0, repeat: 0 };
+ @observable private _layout: { type: LayoutType; yMargin: number; xMargin: number; columns?: number; repeat: number } = { type: LayoutType.FREEFORM, yMargin: 10, xMargin: 10, columns: 1, repeat: 0 };
@observable private renderedDocs: Doc[] = [];
@observable private renderedDocCollection: Doc | undefined = undefined;
@@ -62,7 +61,7 @@ export class TemplatesRenderPreviewWindow extends ObservableReactComponent<Templ
@computed get columnsCount() {
switch (this._layout.type) {
case LayoutType.FREEFORM:
- return this._layout.columns ?? 0;
+ return this._layout.columns ?? 1;
case LayoutType.CAROUSEL3D:
return 3;
default:
@@ -130,28 +129,27 @@ export class TemplatesRenderPreviewWindow extends ObservableReactComponent<Templ
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;
+ collection.layout_fitWidth = true;
+ collection.freeform_fitContentsToBox = true;
+
+ const columns = (this._layout.columns ?? this.columnsCount) || 1;
+ const xGap = this._layout.xMargin;
+ const yGap = this._layout.yMargin;
+ const startX = -collection._width / 2;
+ const startY = -collection._height / 2;
+ const docHeight = NumCast(docs[0]?._height);
+ const docWidth = NumCast(docs[0]?._width);
+
+ let i = 0;
+ let docsChanged = 0;
+ let curX = startX;
+ let curY = startY;
while (docsChanged < docs.length) {
while (i < columns && docsChanged < docs.length) {
docs[docsChanged].x = curX;
docs[docsChanged].y = curY;
+ docs[docsChanged].layout_fitWidth = false;
curX += docWidth + xGap;
++docsChanged;
++i;
@@ -164,8 +162,8 @@ export class TemplatesRenderPreviewWindow extends ObservableReactComponent<Templ
@computed
get previewInfo() {
- const docHeight: number = Number(this.renderedDocs[0]._height);
- const docWidth: number = Number(this.renderedDocs[0]._width);
+ const docHeight = NumCast(this.renderedDocs[0]?._height);
+ const docWidth = NumCast(this.renderedDocs[0]?._width);
const layout = this._layout;
return {
docHeight: docHeight,
@@ -201,6 +199,10 @@ export class TemplatesRenderPreviewWindow extends ObservableReactComponent<Templ
}
}
+ layoutPanelWidth = () => this._props.menu._menuDimensions.width - 80;
+ layoutPanelHeight = () => this._props.menu._menuDimensions.height - 105;
+ layoutScreenToLocalXf = () => new Transform(-this._props.menu._pageX - 5, -this._props.menu._pageY - 35, 1);
+
layoutPreviewContents = action(() => {
return this.loading ? (
<div className="docCreatorMenu-layout-preview-window-wrapper loading">
@@ -216,20 +218,18 @@ export class TemplatesRenderPreviewWindow extends ObservableReactComponent<Templ
addDocument={returnFalse}
moveDocument={returnFalse}
removeDocument={returnFalse}
- PanelWidth={() => this._props.menu._menuDimensions.width - 80}
- PanelHeight={() => this._props.menu._menuDimensions.height - 105}
- ScreenToLocalTransform={() => new Transform(-this._props.menu._pageX - 5, -this._props.menu._pageY - 35, 1)}
+ PanelWidth={this.layoutPanelWidth}
+ PanelHeight={this.layoutPanelHeight}
+ ScreenToLocalTransform={this.layoutScreenToLocalXf}
renderDepth={5}
whenChildContentsActiveChanged={emptyFunction}
focus={emptyFunction}
styleProvider={DefaultStyleProvider}
addDocTab={this._props.menu._props.addDocTab}
- pinToPres={() => undefined}
+ pinToPres={emptyFunction}
childFilters={returnEmptyFilter}
childFiltersByRanges={returnEmptyFilter}
searchFilterDocs={returnEmptyDoclist}
- fitContentsToBox={returnFalse}
- fitWidth={returnFalse}
hideDecorations={true}
/>
</div>
@@ -273,7 +273,6 @@ export class TemplatesRenderPreviewWindow extends ObservableReactComponent<Templ
};
get optionsMenuContents() {
-
const repeatOptions = [0, 1, 2, 3, 4, 5];
return (
@@ -341,5 +340,7 @@ export class TemplatesRenderPreviewWindow extends ObservableReactComponent<Templ
);
}
- render() { return this.optionsMenuContents }
-} \ No newline at end of file
+ render() {
+ return this.optionsMenuContents;
+ }
+}