aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu/Backend/TemplateManager.ts20
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.scss5
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx93
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateEditingWindow.tsx4
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu/Template.ts26
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateBackend.ts1
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateFieldTypes/DataField.ts21
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateFieldTypes/TemplateField.ts1
8 files changed, 113 insertions, 58 deletions
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/Backend/TemplateManager.ts b/src/client/views/nodes/DataVizBox/DocCreatorMenu/Backend/TemplateManager.ts
index 030c6db95..760940127 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/Backend/TemplateManager.ts
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/Backend/TemplateManager.ts
@@ -1,6 +1,6 @@
import { action, makeAutoObservable } from 'mobx';
import { Col } from '../DocCreatorMenu';
-import { FieldSettings } from '../TemplateFieldTypes/TemplateField';
+import { FieldSettings, TemplateField } from '../TemplateFieldTypes/TemplateField';
import { Template } from '../Template';
import { Doc, NumListCast } from '../../../../../../fields/Doc';
import { DataVizBox } from '../../DataVizBox';
@@ -11,7 +11,7 @@ export type Conditional = {
field: string;
operator: '=' | '>' | '<';
condition: string;
- target: 'self' | 'template';
+ target: string;
attribute: string;
value: string;
}
@@ -53,13 +53,21 @@ export class TemplateManager {
}
}
+ addDataField = (title: string) => {
+ this.templates.forEach(template => template.addDataField(title));
+ }
+
+ removeDataField = (title: string) => {
+ this.templates.forEach(template => template.removeDataField(title));
+ }
+
createDocsFromTemplate = action((dv: DataVizBox, template: Template, cols: Col[], debug: boolean = false) => {
- const fields = Array.from(Object.keys(dv.records[0]));
+ const csvFields = Array.from(Object.keys(dv.records[0]));
const processContent = async (content: { [title: string]: string }) => {
const templateCopy = template.clone();
- fields
+ csvFields
.filter(title => title)
.forEach(title => {
const field = templateCopy.getFieldByTitle(title);
@@ -71,7 +79,7 @@ export class TemplateManager {
const promises = cols
.filter(field => field.AIGenerated)
.map(field => {
- const templateField = templateCopy.getFieldByTitle(field.title);
+ const templateField: TemplateField = templateCopy.getFieldByTitle(field.title) as TemplateField;
if (templateField !== undefined) {
return gptFunc(field.type)(templateCopy, field, templateField.getID);
}
@@ -92,7 +100,7 @@ export class TemplateManager {
const rowContents = debug
? [{}, {}, {}, {}]
: NumListCast(dv.layoutDoc.dataViz_selectedRows).map(row =>
- fields.reduce(
+ csvFields.reduce(
(values, col) => {
values[col] = dv.records[row][col];
return values;
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.scss
index 8ac718fb7..2f7b68c4d 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.scss
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.scss
@@ -1141,6 +1141,7 @@
.switch {
gap: 0.75rem;
+ margin-bottom: 0px;
}
.switch .slider {
@@ -1170,7 +1171,7 @@
}
.switch input:checked + .slider {
- background: #9fe29d;
+ background: #78c2f1;
}
.switch input:checked + .slider::before {
@@ -1182,6 +1183,8 @@
font-size: 100%;
color: whitesmoke;
text-align: center;
+ margin-bottom: 0px;
+ font-weight: 500;
}
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx
index 2565a9332..873bfa734 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx
@@ -30,7 +30,7 @@ import './DocCreatorMenu.scss';
import { TemplateField, ViewType } from './TemplateFieldTypes/TemplateField';
import { Template } from './Template';
import { TemplateFieldSize, TemplateFieldType, TemplateLayouts } from './TemplateBackend';
-import { TemplateManager } from './Backend/TemplateManager';
+import { Conditional, TemplateManager } from './Backend/TemplateManager';
import { DrawingFillHandler } from '../../../smartdraw/DrawingFillHandler';
import { CgPathIntersect } from 'react-icons/cg';
import { StaticContentField } from './TemplateFieldTypes/StaticContentField';
@@ -71,15 +71,6 @@ export type Col = {
AIGenerated?: boolean;
};
-export type Conditional = {
- field: string;
- operator: '=' | '>' | '<';
- condition: string;
- target: 'self' | 'template';
- attribute: string;
- value: string;
-}
-
interface DocCreateMenuProps {
addDocTab: (doc: Doc | Doc[], where: OpenWhere) => boolean;
}
@@ -364,15 +355,6 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
this._pageY = y + translation.y;
};
- async getIcon(doc: Doc) {
- const docView = DocumentView.getDocumentView(doc);
- if (docView) {
- docView.ComponentView?.updateIcon?.();
- return new Promise<ImageField | undefined>(res => setTimeout(() => res(ImageCast(docView.Document.icon)), 500));
- }
- return undefined;
- }
-
@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[] : [];
@@ -469,11 +451,18 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
};
@action setColType = (column: Col, type: TemplateFieldType) => {
+ if (type === TemplateFieldType.DATA) {
+ this.templateManager.addDataField(column.title);
+ } else if (column.type === TemplateFieldType.DATA) {
+ this.templateManager.removeDataField(column.title);
+ }
+
if (this.selectedFields.includes(column.title)) {
this._dataViz?.setColumnType(column.title, type);
} else {
column.type = type;
}
+
this.forceUpdate();
};
@@ -576,9 +565,11 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
} else {
this._dataViz?.updateColDefaults();
- templates.push(...this.templateManager.getValidTemplates(this.fieldsInfos));
+ const contentFields = this.fieldsInfos.filter(field => field.type !== TemplateFieldType.DATA);
+
+ templates.push(...this.templateManager.getValidTemplates(contentFields));
- const assignments = await this.assignColsToFields(templates, this.fieldsInfos);
+ const assignments = await this.assignColsToFields(templates, contentFields);
const renderedTemplatePromises = assignments.map(([template, assgns]) => TemplateMenuAIUtils.applyGPTContentToTemplate(template, assgns));
@@ -918,6 +909,8 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
}
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) => {
const params: Conditional = parameters ?? this._currEditingConditional;
@@ -942,8 +935,9 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
<div className='form-row-plain-text'>then</div>
<div className="operator-options-dropdown">
<span className="operator-dropdown-current">{params.target ?? 'self'}</span>
- <div className='operator-dropdown-option' onPointerDown={() => {params.target = 'self'}}>{'own'}</div>
- <div className='operator-dropdown-option' onPointerDown={() => {params.target = 'template'}}>{`template's`}</div>
+ {contentFieldTitles.map(fieldTitle =>
+ <div className='operator-dropdown-option' onPointerDown={() => {params.target = fieldTitle}}>{fieldTitle === title ? 'own' : fieldTitle}</div>
+ )}
</div>
<textarea
className="form-row-textarea"
@@ -990,38 +984,49 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
<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' : ''}</span>
+ <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.setColType(field, TemplateFieldType.TEXT)} />
<div className="text">Text</div>
<input className="bubble" type="radio" name="type" onClick={() => this.setColType(field, TemplateFieldType.VISUAL)} />
<div className="text">File</div>
+ <input className="bubble" type="radio" name="type" onClick={() => this.setColType(field, TemplateFieldType.DATA)} />
+ <div className="text">Data</div>
</div>
</div>
</div>
</div>
- <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.modifyColSizes(field, size, e.target.checked)} />
- <div className="text">{size}</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.modifyColSizes(field, size, e.target.checked)} />
+ <div className="text">{size}</div>
+ </div>
+ ))}
</div>
- ))}
+ </div>
</div>
- </div>
- </div>
- <div className="desc-box">
- <div className="top-bar"> Prompt </div>
- <textarea
- className="content"
- onChange={e => this.setColDesc(field, e.target.value)}
- defaultValue={field.desc === this._dataViz?.GPTSummary?.get(field.title)?.desc ? '' : field.desc}
- placeholder={this._dataViz?.GPTSummary?.get(field.title)?.desc ?? 'Add a description/prompt to help with template generation.'}
- />
- </div>
+ <div className="desc-box">
+ <div className="top-bar"> Prompt </div>
+ <textarea
+ className="content"
+ onChange={e => this.setColDesc(field, e.target.value)}
+ defaultValue={field.desc === this._dataViz?.GPTSummary?.get(field.title)?.desc ? '' : field.desc}
+ placeholder={this._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>
{conditionForm(field.title, this._currEditingConditional, true)}
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateEditingWindow.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateEditingWindow.tsx
index 4ff509d73..e1d8ea8a5 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateEditingWindow.tsx
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateEditingWindow.tsx
@@ -99,13 +99,13 @@ export class FireflyVariationsTab extends ObservableReactComponent<FireflyVariat
<DocCreatorMenuButton icon={'arrows-rotate'} styles={'border'} function={this.generateVariations}/>
</div>
<nav className="options‑menu">
- <div className="menu‑item switch">
+ <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>
- </div>
+ </label>
<div className="menu‑item">
<span className="firefly-option-label">Variations</span>
<input type="range" id="variations"
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/Template.ts b/src/client/views/nodes/DataVizBox/DocCreatorMenu/Template.ts
index fae0d06e4..1889e4984 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/Template.ts
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/Template.ts
@@ -6,10 +6,13 @@ import { FieldSettings, TemplateField, ViewType } from './TemplateFieldTypes/Tem
import { Conditional } from './Backend/TemplateManager';
import { ImageField } from '../../../../../fields/URLField';
import { Doc } from '../../../../../fields/Doc';
+import { TemplateDataField } from './TemplateFieldTypes/DataField';
export class Template {
_mainField: DynamicField;
+ private dataFields: TemplateDataField[] = [];
+
/**
* A Template can be created from a description of its fields (FieldSettings) or from a DynamicField
* @param definition definition of template as settings or DynamicField
@@ -55,13 +58,17 @@ export class Template {
//dispose each subfields disposers, etc.
};
- clone = (withContent: boolean = false) => new Template(this._mainField?.makeClone(undefined, withContent) ?? TemplateLayouts.BasicSettings);
+ clone = (withContent: boolean = false) => {
+ const clone = new Template(this._mainField?.makeClone(undefined, withContent) ?? TemplateLayouts.BasicSettings);
+ this.dataFields.forEach(field => clone.addDataField(field.title));
+ return clone;
+ };
getRenderedDoc = () => this.doc;
getFieldByID = (id: number): TemplateField => this.allFields.filter(field => field.getID === id)[0];
- getFieldByTitle = (title: string) => this.allFields.filter(field => field.getTitle() === title)[0];
+ getFieldByTitle = (title: string) => [...this.allFields, ...this.dataFields].filter(field => field.getTitle() === title)[0];
setupMainField = (templateInfo: FieldSettings) => TemplateField.CreateField(templateInfo, 1, undefined) as DynamicField;
@@ -77,12 +84,20 @@ export class Template {
field.setTitle(col.title);
}
+ addDataField = (title: string, content?: string) => {
+ this.dataFields.push(new TemplateDataField(title, content));
+ }
+
+ removeDataField = (title: string) => {
+ this.dataFields = this.dataFields.filter(field => !(field.title === title));
+ }
+
isValidTemplate = (cols: Col[]) => {
const maxMatches = this.maxMatches(this.getMatches(cols));
return maxMatches === this.contentFields.length && this.title !== 'template_framework';
};
- applyConditionalLogicToField = (field: TemplateField, logic: Record<string, Conditional[]>) => {
+ applyConditionalLogicToField = (field: TemplateField | TemplateDataField, logic: Record<string, Conditional[]>) => {
if (field instanceof DynamicField) return;
const fieldStatements: Conditional[] = logic[field.getTitle()];
const content = field.getContent()
@@ -91,7 +106,8 @@ export class Template {
if (statement.target === 'template') {
this._mainField.renderedDoc![statement.attribute] = statement.value;
} else {
- field.renderedDoc![statement.attribute] = statement.value;
+ const targetField: TemplateField = this.getFieldByTitle(statement.target) as TemplateField;
+ targetField && (targetField.renderedDoc![statement.attribute] = statement.value);
}
}
})
@@ -99,7 +115,7 @@ export class Template {
applyConditionalLogic = (logic: Record<string, Conditional[]>) => {
console.log('applying logic: ', logic)
- const fields: TemplateField[] = [...this.allFields];
+ const fields: (TemplateField | TemplateDataField)[] = [...this.allFields, ...this.dataFields];
fields.forEach(field => this.applyConditionalLogicToField(field, logic));
}
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateBackend.ts b/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateBackend.ts
index 06eab63f0..26fd3a8fc 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateBackend.ts
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateBackend.ts
@@ -4,6 +4,7 @@ export enum TemplateFieldType {
TEXT = 'text',
VISUAL = 'visual',
UNSET = 'unset',
+ DATA = 'data',
}
export enum TemplateFieldSize {
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateFieldTypes/DataField.ts b/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateFieldTypes/DataField.ts
new file mode 100644
index 000000000..aaa475bed
--- /dev/null
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateFieldTypes/DataField.ts
@@ -0,0 +1,21 @@
+
+import { Template } from "../Template";
+import { TemplateField, ViewType } from "./TemplateField";
+
+export class TemplateDataField {
+
+ viewType: ViewType = ViewType.NONE;
+
+ title: string = '';
+ content: string | undefined;
+
+ constructor(title: string, content?: string) {
+ this.title = title;
+ this.content = content;
+ }
+
+ setContent(content: string, viewType?: ViewType) { this.content = content }
+ getContent() { return this.content }
+
+ getTitle() { return this.title }
+} \ No newline at end of file
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateFieldTypes/TemplateField.ts b/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateFieldTypes/TemplateField.ts
index bc6b13c76..2c304247d 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateFieldTypes/TemplateField.ts
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateFieldTypes/TemplateField.ts
@@ -157,6 +157,7 @@ export enum ViewType {
DEC = 'decoration',
IMG = 'image',
TEXT = 'text',
+ NONE = 'none'
}
export type FieldDimensions = {