aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx')
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx261
1 files changed, 100 insertions, 161 deletions
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx
index ed2e20843..48fea91e2 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx
@@ -34,8 +34,9 @@ import { TemplateManager } from './Backend/TemplateManager';
import { DrawingFillHandler } from '../../../smartdraw/DrawingFillHandler';
import { CgPathIntersect } from 'react-icons/cg';
import { StaticContentField } from './TemplateFieldTypes/StaticContentField';
-import { SuggestedTemplatesWindow } from './Menu/SuggestedTemplatesWindow';
-import { TemplateMenuGPTManager } from './Backend/TemplateMenuGPTManager';
+import { TemplateMenuAIUtils } from './Backend/TemplateMenuAIUtils'
+import { TemplateSidescrollView } from './Menu/TemplatesSidescrollDisplay';
+import { TemplateEditingWindow } from './Menu/TemplateEditingWindow';
export enum LayoutType {
FREEFORM = 'Freeform',
@@ -91,7 +92,6 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
private _disposers: { [name: string]: IDisposer } = {};
private _ref: HTMLDivElement | null = null;
private templateManager: TemplateManager;
- private GPTManager: TemplateMenuGPTManager;
@observable _fullyRenderedDocs: Doc[] = []; // collection of templates filled in with content
@observable _renderedDocCollection: Doc | undefined = undefined; // fullyRenderedDocs in a parent collection
@@ -102,27 +102,16 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
@observable _currEditingTemplate: Template | undefined = undefined;
@observable _userCreatedFields: Col[] = [];
- @observable _selectedCols: { title: string; type: string; desc: string }[] | undefined = [];
@observable _collapsedCols: String[] = []; //any columns whose options panels are hidden
@observable _conditions: Conditional[] = [];
@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 _expandedPreview: Doc | undefined = undefined;
- @observable _variationsTab: boolean = false;
- @observable _numVarsToGenerate: number = 3;
@observable _loadingVariants: boolean = false;
- @observable _currentVariations: Doc[] = [];
- @observable _variationPrompt: string = 'Use this template to generate an empty baseball card template.';
- _previewWindow: HTMLDivElement | null = null;
@observable _suggestedTemplates: Template[] = [];
- @observable _suggestedTemplatePreviews: { doc: Doc; template: Template }[] = [];
- @observable _GPTOpt: boolean = false;
- @observable _callCount: number = 0;
@observable _GPTLoading: boolean = false;
- @observable _DOCCC: Doc | undefined;
@observable _pageX: number = 0;
@observable _pageY: number = 0;
@@ -133,9 +122,8 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
@observable _startPos?: { x: number; y: number };
@observable _shouldDisplay: boolean = false;
- @observable _menuContent: 'templates' | 'options' | 'saved' | 'dashboard' = 'templates';
+ @observable _menuContent: 'templates' | 'options' | 'saved' | 'dashboard' | 'templateEditing' = 'templates';
@observable _dragging: boolean = false;
- @observable _draggingIndicator: boolean = false;
@observable _dataViz?: DataVizBox;
@observable _interactionLock: boolean | undefined;
@observable _snapPt: { x: number; y: number } = { x: 0, y: 0 };
@@ -145,20 +133,14 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
@observable _resizeUndo: UndoManager.Batch | undefined = undefined;
@observable _initDimensions: { width: number; height: number; x?: number; y?: number } = { width: 300, height: 400, x: undefined, y: undefined };
@observable _menuDimensions: { width: number; height: number } = { width: 400, height: 400 };
- @observable _editing: boolean = false;
constructor(props: DocCreateMenuProps) {
super(props);
makeObservable(this);
DocCreatorMenu.Instance = this;
this.templateManager = new TemplateManager(TemplateLayouts.allTemplates);
- this.GPTManager = new TemplateMenuGPTManager();
}
- setContainerRef: React.LegacyRef<HTMLDivElement> = (node) => {
- this._previewWindow = node;
- };
-
@action setDataViz = (dataViz: DataVizBox) => {
this._dataViz = dataViz;
this._selectedTemplate = undefined;
@@ -392,7 +374,7 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
}
@action updateRenderedPreviewCollection = async (template: Template) => {
- this._fullyRenderedDocs = this._dataViz ? ((await this.createDocsFromTemplate(this._dataViz, template)).filter(doc => doc).map(doc => doc!) ?? []) : [];
+ 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();
};
@@ -517,19 +499,88 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
this.forceUpdate();
};
- generatePresetTemplates = async (debug: boolean) => {
+ compileFieldDescriptions = (templates: Template[]): string => {
+ let descriptions: string = '';
+ templates.forEach(template => {
+ descriptions += `---------- NEW TEMPLATE TO INCLUDE: The title is: ${template.title}. Its fields are: `;
+ descriptions += template.descriptionSummary;
+ });
+
+ return descriptions;
+ };
+
+ compileColDescriptions = (cols: Col[]): string => {
+ let descriptions: string = ' ------------- COL DESCRIPTIONS START HERE:';
+ cols.forEach(col => (descriptions += `{title: ${col.title}, sizes: ${String(col.sizes)}, type: ${col.type}, descreiption: ${col.desc}} `));
+
+ return descriptions;
+ };
+
+ getColByTitle = (title: string) => {
+ return this.fieldsInfos.filter(col => col.title === title)[0];
+ };
+
+ @action
+ assignColsToFields = async (templates: Template[], cols: Col[]): Promise<[Template, { [field: number]: Col }][]> => {
+ const fieldDescriptions: string = this.compileFieldDescriptions(templates);
+ const colDescriptions: string = this.compileColDescriptions(cols);
+
+ const inputText = fieldDescriptions.concat(colDescriptions);
+
+ const prompt: string = `(${Math.random() * 100000}) ${inputText}`;
+
+ this._GPTLoading = true;
+
+ try {
+ const res = await gptAPICall(prompt, GPTCallType.TEMPLATE);
+
+ if (res) {
+ const assignments: { [templateTitle: string]: { [fieldID: string]: string } } = JSON.parse(res);
+ const brokenDownAssignments: [Template, { [fieldID: number]: Col }][] = [];
+
+ Object.entries(assignments).forEach(([tempTitle, assignment]) => {
+ const template = templates.filter(temp => temp.title === tempTitle)[0];
+ if (!template) return;
+ const toObj = Object.entries(assignment).reduce(
+ (a, [fieldID, colTitle]) => {
+ const col = this.getColByTitle(colTitle);
+ if (!this._userCreatedFields.includes(col)) {
+ // do the following for any fields not added by the user; will change in the future, for now only GPT content works with user-added field
+ const field = template.getFieldByID(Number(fieldID));
+ field.setContent(col.defaultContent ?? '', col.type === TemplateFieldType.VISUAL ? ViewType.IMG : ViewType.TEXT);
+ field.setTitle(col.title);
+ } else {
+ a[Number(fieldID)] = this.getColByTitle(colTitle);
+ }
+ return a;
+ },
+ {} as { [field: number]: Col }
+ );
+ brokenDownAssignments.push([template, toObj]);
+ });
+
+ return brokenDownAssignments;
+ }
+ } catch (err) {
+ console.error(err);
+ }
+
+ return [];
+ };
+
+ generatePresetTemplates = async () => {
const templates: Template[] = [];
- if (debug) {
+ if (this.DEBUG_MODE) {
templates.push(...this.templateManager.templates);
} else {
this._dataViz?.updateColDefaults();
templates.push(...this.templateManager.getValidTemplates(this.fieldsInfos));
- const assignments = await this.GPTManager.assignColsToFields(templates, this.fieldsInfos);
+ const assignments = await this.assignColsToFields(templates, this.fieldsInfos);
- const renderedTemplatePromises = assignments.map(([template, assgns]) => this.GPTManager.applyGPTContentToTemplate(template, assgns));
+ const renderedTemplatePromises = assignments.map(([template, assgns]) => TemplateMenuAIUtils.applyGPTContentToTemplate(template, assgns));
await Promise.all(renderedTemplatePromises);
}
@@ -542,16 +593,7 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
);
};
- @action setVariationTab = (open: boolean) => {
- this._variationsTab = 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);
- }
- }
-
- generateVariations = async (onDoc: Doc): Promise<Doc[]> => {
+ generateVariations = async (onDoc: Doc, prompt: string): Promise<Doc[]> => {
this._loadingVariants = true;
this.variationDocss = [];
const mainCollection = this._dataViz?.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView;
@@ -561,7 +603,7 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
clone.x = 10000;
clone.y = 10000;
- await DrawingFillHandler.drawingToImage(clone, 100, this._variationPrompt, undefined, this)
+ await DrawingFillHandler.drawingToImage(clone, 100, prompt, undefined, this)
this._loadingVariants = false;
@@ -591,130 +633,15 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
@action setExpandedView = (template: Template | undefined) => {
this._currEditingTemplate = template;
- this._expandedPreview = template?.doc; //Docs.Create.FreeformDocument([doc], { _height: NumListCast(doc._height)[0], _width: NumListCast(doc._width)[0], title: ''});
- };
-
- @action setVariationPrompt = (prompt: string) => {
- this._variationPrompt = prompt;
- }
-
- get editingWindow() {
- const rendered = !this._expandedPreview ? null : (
- <>
- <div className="docCreatorMenu-expanded-template-preview" ref={this.setContainerRef}>
- { this._previewWindow ? <DocumentView
- Document={this._expandedPreview}
- isContentActive={emptyFunction}
- addDocument={returnFalse}
- moveDocument={returnFalse}
- removeDocument={returnFalse}
- PanelWidth={() => this._previewWindow?.clientWidth ?? 1000 - 10}
- PanelHeight={() => this._previewWindow?.clientHeight ?? 1000 - 60}
- ScreenToLocalTransform={() => new Transform(-this._pageX - 5, -this._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>
- { this._variationsTab ?
- <div className="docCreatorMenu-section">
- <div className="docCreatorMenu-section-topbar">
- <div className="docCreatorMenu-section-title" style={{color: 'white'}}>Variations</div>
- <button className="docCreatorMenu-menu-button section-reveal-options" onPointerDown={e => this.setUpButtonClick(e, () => runInAction(() => (this._menuContent = 'dashboard')))}>
- <FontAwesomeIcon icon="gear" />
- </button>
- </div>
- <div className="docCreatorMenu-templates-preview-window">
- {this._currentVariations.map(variant =>
- <div className="docCreatorMenu-preview-window">
- {this.docPreview(variant)}
- </div>
- )}
- </div>
- <div className="docCreatorMenu-variation-prompt-input">
- <textarea
- className="docCreatorMenu-variation-prompt-input-textbox"
- onChange={e => this.setVariationPrompt(e.target.value)}
- defaultValue={''}
- placeholder={'Enter a custom prompt here (optional)'}
- />
- <button className="docCreatorMenu-menu-button"
- onPointerDown={e => this.setUpButtonClick(e, async () => {
- this._currentVariations = await this.generateVariations(this._currEditingTemplate?.getRenderedDoc()!);
- })
- }>
- <FontAwesomeIcon icon="arrows-rotate" />
- </button>
- </div>
- </div>
- : null
- }
- </>
- );
- return (
- <div className="docCreatorMenu-expanded-template-preview">
- <div className="top-panel" />
- {rendered}
- <div className="right-buttons-panel">
- <button
- className="docCreatorMenu-menu-button section-reveal-options top-right"
- onPointerDown={e =>
- this.setUpButtonClick(e, () => {
- if (!this._currEditingTemplate) return;
- if (this._currEditingTemplate === this._selectedTemplate) {
- this.updateRenderedPreviewCollection(this._currEditingTemplate);
- }
- this.setExpandedView(undefined);
- })
- }>
- <FontAwesomeIcon icon="minimize" />
- </button>
- <button className="docCreatorMenu-menu-button section-reveal-options top-right" onPointerDown={e => this.setUpButtonClick(e, async () => {
- if (!this._currEditingTemplate) return;
- this.setVariationTab(!this._variationsTab);
- })}>
- <FontAwesomeIcon icon="lightbulb" />
- </button>
- </div>
- </div>
- );
- }
+ if (template) {
+ this._menuContent = 'templateEditing';
+ } else {
+ this._menuContent = 'templates';
+ }
- docPreview = (doc: Doc | undefined) =>
- !doc ? null : (
- <DocumentView
- Document={doc}
- isContentActive={emptyFunction} // !!! should be return false
- addDocument={returnFalse}
- moveDocument={returnFalse}
- removeDocument={returnFalse}
- PanelWidth={() => this._menuDimensions.height * .3}
- PanelHeight={() => this._menuDimensions.height * .3}
- 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}
- />
- );
+ //Docs.Create.FreeformDocument([doc], { _height: NumListCast(doc._height)[0], _width: NumListCast(doc._width)[0], title: ''});
+ };
@action updateXMargin = (input: string) => {
this._layout.xMargin = Number(input);
@@ -1137,7 +1064,19 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
get renderSelectedViewType() {
switch (this._menuContent) {
- case 'templates': return <SuggestedTemplatesWindow menu={this} setupButtonClick={this.setUpButtonClick}/>;
+ case 'templates':
+ return <TemplateSidescrollView
+ title={'Suggested Templates'}
+ menu={this}
+ setupButtonClick={this.setUpButtonClick}
+ templates={this._suggestedTemplates}
+ />
+ case 'templateEditing':
+ return <TemplateEditingWindow
+ setupButtonClick={this.setUpButtonClick}
+ template={this._currEditingTemplate as Template}
+ menu={this}
+ />
case 'options': return this.optionsMenuContents;
case 'dashboard': return this.dashboardContents;
} // prettier-ignore