diff options
8 files changed, 149 insertions, 19 deletions
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.scss index 2f7b68c4d..5232ad41c 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.scss @@ -388,7 +388,7 @@ justify-content: center; align-items: center; position: absolute; - width: calc(100% - 10px); + left: 50%; bottom: 0px; margin: 0px; margin-bottom: 10px; diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx index b024a6e9b..bd5c50aa0 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx @@ -38,6 +38,7 @@ import { TemplateMenuAIUtils } from './Backend/TemplateMenuAIUtils' import { TemplatePreviewGrid } from './Menu/TemplatePreviewGrid'; import { FireflyStructureOptions, TemplateEditingWindow } from './Menu/TemplateEditingWindow'; import { DocCreatorMenuButton } from './Menu/DocCreatorMenuButton'; +import { ConditionalsTextArea } from './Menu/ConditionalsTextarea'; export enum LayoutType { FREEFORM = 'Freeform', @@ -91,6 +92,7 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps> @observable _userTemplates: Template[] = []; @observable _selectedTemplate: Template | undefined = undefined; @observable _currEditingTemplate: Template | undefined = undefined; + @observable _editedTemplateTrail: Template[] = []; @observable _userCreatedFields: Col[] = []; @observable _collapsedCols: String[] = []; //any columns whose options panels are hidden @@ -589,8 +591,6 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps> this.variations = []; const mainCollection = this._dataViz?.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView; - console.log('styleref: ', useStyleRef); - const clone: Doc = (await Doc.MakeClone(onDoc)).clone; mainCollection.addDocument(clone); clone.x = 10000; @@ -618,15 +618,19 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps> } }; + @action editLastTemplate = () => { if (this._editedTemplateTrail.length) this._currEditingTemplate = this._editedTemplateTrail.pop()} + @action setExpandedView = (template: Template | undefined) => { - this._currEditingTemplate = template; if (template) { this._menuContent = 'templateEditing'; + this._currEditingTemplate && this._editedTemplateTrail.push(this._currEditingTemplate); } else { this._menuContent = 'templates'; } + this._currEditingTemplate = template; + //Docs.Create.FreeformDocument([doc], { _height: NumListCast(doc._height)[0], _width: NumListCast(doc._width)[0], title: ''}); }; @@ -910,15 +914,26 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps> ); } + private _newCondCache: Record<string, Conditional> = {}; + + getParams = (title: string, parameters?: Conditional): Conditional => { + if (parameters) return parameters; + + if (!this._newCondCache[title]) { + this._newCondCache[title] = { 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) => { - const params: Conditional = parameters ?? this._currEditingConditional; + const params: Conditional = this.getParams(title, parameters); return ( - <div className='form' id={String(Math.random() * 100000)}> + <div className='form'> <div className='form-row'> <div className='form-row-plain-text'>If</div> <div className='form-row-plain-text'>{title}</div> @@ -929,7 +944,7 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps> <div className='operator-dropdown-option' onPointerDown={() => {params.operator = '<'}}>{'<'}</div> <div className='operator-dropdown-option' onPointerDown={() => {params.operator = 'contains'}}>{'has'}</div> </div> - <textarea + <input className="form-row-textarea" onChange={e => runInAction(() => params.condition = e.target.value)} placeholder='value' @@ -957,9 +972,9 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps> /> </div> {empty ? - <DocCreatorMenuButton icon={'plus'} styles={'float-right'} function={() => this.templateManager.addFieldCondition(title, params)}/> + <DocCreatorMenuButton icon={'plus'} styles={'float-right border'} function={() => this.templateManager.addFieldCondition(title, params)}/> : - <DocCreatorMenuButton icon={'minus'} styles={'float-right'} function={() => this.templateManager.removeFieldCondition(title, params)}/> + <DocCreatorMenuButton icon={'minus'} styles={'float-right border'} function={() => this.templateManager.removeFieldCondition(title, params)}/> } </div> ) @@ -1032,7 +1047,7 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps> } <div className="conditionals-section"> <span className="conditionals-title">Conditional Logic</span> - {conditionForm(field.title, this._currEditingConditional, true)} + {conditionForm(field.title, undefined, true)} {this.templateManager.conditionalFieldLogic[field.title]?.map(condition => conditionForm(condition.field, condition))} </div> </> @@ -1053,6 +1068,8 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps> @computed get editingView() { return <TemplateEditingWindow template={this._currEditingTemplate as Template} menu={this} /> } + private optionsButtonOpts: [IconProp, () => any] = ['gear', () => (this._menuContent = 'dashboard')]; + get renderSelectedViewType() { switch (this._menuContent) { case 'templates': @@ -1063,7 +1080,7 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps> title={'Suggested Templates'} menu={this} loading={this._GPTLoading} - optionsButtonOpts={['gear', () => (this._menuContent = 'dashboard')]} + optionsButtonOpts={this.optionsButtonOpts} templates={this._suggestedTemplates} /> <div className="docCreatorMenu-GPT-options"> diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/ConditionalsTextarea.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/ConditionalsTextarea.tsx new file mode 100644 index 000000000..2ca0bde3f --- /dev/null +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/ConditionalsTextarea.tsx @@ -0,0 +1,65 @@ +import { observer } from "mobx-react"; +import { ObservableReactComponent } from "../../../../ObservableReactComponent"; +import { Conditional } from "../Backend/TemplateManager"; +import { action, makeObservable, observable, runInAction } from "mobx"; +import React from "react"; + +interface ConditionalsTextAreaProps { + conditional: Conditional; + property: keyof Conditional; +} + +@observer +export class ConditionalsTextArea extends ObservableReactComponent<ConditionalsTextAreaProps> { + + private mirrorRef: HTMLSpanElement | null = null; + + @observable private inputWidth: string = '60px'; + + constructor(props: ConditionalsTextAreaProps) { + super(props); + makeObservable(this); + } + + setMirrorRef: React.LegacyRef<HTMLSpanElement> = (node) => { this.mirrorRef = node } + + @action updateInputWidth() { + const mirror = this.mirrorRef; + if (mirror) { + const width = mirror.offsetWidth; + if ( width + 8 > 60) this.inputWidth = `${width + 8}px`; + } + } + + render() { + return ( + <div style={{ display: 'inline-block', position: 'relative' }}> + <span + ref={this.setMirrorRef} + style={{ + position: 'absolute', + visibility: 'hidden', + whiteSpace: 'pre', + font: 'inherit', + padding: 0, + }} + > + {this._props.conditional[this._props.property] || ' '} + </span> + <input + className="form-row-input" + value={this.props.conditional[this.props.property] ?? ''} + onChange={e => { + runInAction(() => { + this.props.conditional[this.props.property] = e.target.value as any; + }); + this.updateInputWidth(); + }} + style={{ width: this.inputWidth }} + placeholder={this.props.property} + /> + </div> + ); + } + +}
\ No newline at end of file diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateEditingWindow.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateEditingWindow.tsx index e1d8ea8a5..cb87e9b47 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateEditingWindow.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/Menu/TemplateEditingWindow.tsx @@ -17,6 +17,8 @@ import { IDisposer } from "mobx-utils"; import { ImageField } from "../../../../../../fields/URLField"; import { DocCreatorMenuButton } from "./DocCreatorMenuButton"; import { TbHistory } from "react-icons/tb"; +import { IconProp } from "@fortawesome/fontawesome-svg-core"; +import { docStyle } from "pdfjs-dist/types/web/ui_utils"; export type FireflyStructureOptions = { numVariations: number; @@ -50,7 +52,9 @@ export class FireflyVariationsTab extends ObservableReactComponent<FireflyVariat generateVariations = async () => { this._props.menu._variations = []; this._loading = true; - const doc: Doc = this._props.template.clone(false).getRenderedDoc()!; + 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(url => { const newTemplate: Template = this._props.template.clone(true); @@ -68,6 +72,9 @@ export class FireflyVariationsTab extends ObservableReactComponent<FireflyVariat this.promptInput = node; } + private optionsButtonOpts: [IconProp, () => any] = ['gear', () => {}]; + private previewBoxRightButtonOpts: [IconProp, () => any] = ['gear', () => this.forceUpdate()]; + render() { return ( <div className='docCreatorMenu-editing-firefly-section'> @@ -78,8 +85,8 @@ export class FireflyVariationsTab extends ObservableReactComponent<FireflyVariat loading={this._loading} styles={'scrolling'} templates={this._props.menu._variations} - optionsButtonOpts={['gear', () => {}]} - previewBoxRightButtonOpts={['gear', (template: Template) => {this.forceUpdate();}]} + optionsButtonOpts={this.optionsButtonOpts} + previewBoxRightButtonOpts={this.previewBoxRightButtonOpts} /> <div className="docCreatorMenu-firefly-options"> <div className="docCreatorMenu-variation-prompt-row"> @@ -226,7 +233,7 @@ export class TemplateEditingWindow extends ObservableReactComponent<TemplateEdit this._props.menu.setExpandedView(undefined); }}/> <DocCreatorMenuButton icon={'lightbulb'} function={() => this.setVariationTab(!this._variationsTabOpen)}/> - <DocCreatorMenuButton icon={'arrow-rotate-backward'} function={() => { this._props.menu.setExpandedView(this._props.template); this.forceUpdate(); }}/> + <DocCreatorMenuButton icon={'arrow-rotate-backward'} function={() => { this._props.menu.editLastTemplate(); this.forceUpdate(); }}/> </div> </div> </div> diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/Template.ts b/src/client/views/nodes/DataVizBox/DocCreatorMenu/Template.ts index 1889e4984..232a9cf67 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/Template.ts +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/Template.ts @@ -137,7 +137,34 @@ export class Template { }); } - this._mainField.makeBackgroundField(field) + this._mainField.makeBackgroundField(field); + } + + /** + * This function is just a hack for now to get around weird document icon stuff (specifically it misses the background) + */ + setMatteBackground(makeTransparent: boolean = false) { + if (this._mainField.hasBackground) { + return; + } + + const fieldSettings: FieldSettings = { + tl: [-1, -1], + br: [1, 1], + opts: {backgroundColor: String(this._mainField.renderedDoc!.backgroundColor)}, + viewType: ViewType.TEXT, + } + + const field: TemplateField = TemplateField.CreateField(fieldSettings, Math.random() * 100 + 100, this._mainField); + + if (makeTransparent) { + this.allFields.forEach(field => { + field.updateDocSetting('backgroundColor', 'transparent'); + field.updateDocSetting('borderWidth', '0'); + }); + } + + this._mainField.makeBackgroundField(field); } getMatches = (cols: Col[]): number[][] => { diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateFieldTypes/DynamicField.ts b/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateFieldTypes/DynamicField.ts index fc520ba47..1576dd240 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateFieldTypes/DynamicField.ts +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateFieldTypes/DynamicField.ts @@ -20,6 +20,10 @@ export class DynamicField extends TemplateField { return this.getSubfields.flatMap(field => [field, ...((field as DynamicField).getAllSubfields ?? [])]); } + get hasBackground() { + return this.backgroundField !== undefined; + } + handleFieldUpdate = (newDocsList: Doc[]) => { const currRenderedDocs = new Set(this.getSubfields.filter(field => field.renderedDoc).map(field => field.renderedDoc!)); newDocsList.forEach(doc => !currRenderedDocs.has(doc) && this.addFieldFromDoc(doc)); @@ -44,7 +48,10 @@ export class DynamicField extends TemplateField { addField = (field: TemplateField, layer: number = 0) => { if (!this._subfields.includes(field)) { + console.log('success') + console.log('subs: ', this._subfields) this._subfields.splice(layer, 0, field); + console.log('subffelds: ', this._subfields) } }; @@ -91,6 +98,7 @@ export class DynamicField extends TemplateField { const dynClone = super.makeClone(parent) as DynamicField; dynClone._subfields = this.getSubfields.map(field => { if (field === this.backgroundField) { + console.log('background found') const backgroundField: TemplateField = field.makeClone(dynClone, true); dynClone.makeBackgroundField(backgroundField); return backgroundField; diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateFieldTypes/TemplateField.ts b/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateFieldTypes/TemplateField.ts index 2c304247d..a1107caf3 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateFieldTypes/TemplateField.ts +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateFieldTypes/TemplateField.ts @@ -81,6 +81,11 @@ export abstract class TemplateField { makeClone(parent?: TemplateField, withContent: boolean = false) { const settings: FieldSettings = structuredClone(this._settings); const cloned = TemplateField.CreateField(settings, this._id, parent, true); // create a value for this.Document/subfields that we want to ignore + cloned.renderedDoc!.width = this.renderedDoc!.width; + cloned.renderedDoc!.height = this.renderedDoc!.height; + cloned.renderedDoc!.x = this.renderedDoc!.x; + cloned.renderedDoc!.y = this.renderedDoc!.y; + cloned.renderedDoc!.backgroundColor = this.renderedDoc!.backgroundColor; cloned.setTitle(this._title); cloned._dimensions = this._dimensions; withContent && cloned.setContent(this.getContent()); @@ -134,6 +139,7 @@ export abstract class TemplateField { opts._nativeWidth ??= dimensions.width; opts._nativeHeight ??= dimensions.height; opts._layout_nativeDimEditable ??= true; + opts.layout_boxShadow = 'none'; }; } diff --git a/src/client/views/smartdraw/DrawingFillHandler.tsx b/src/client/views/smartdraw/DrawingFillHandler.tsx index 73a47681a..8918d1b0e 100644 --- a/src/client/views/smartdraw/DrawingFillHandler.tsx +++ b/src/client/views/smartdraw/DrawingFillHandler.tsx @@ -26,11 +26,11 @@ export class DrawingFillHandler { : Doc.Links(drawing) .map(link => Doc.getOppositeAnchor(link, drawing)) .map(anchor => anchor && DocCast(anchor.embedContainer)); - const styyleUrl = await DocumentView.GetDocImage(styleDocs.lastElement())?.then(styleImg => { + const styleUrl = await DocumentView.GetDocImage(styleDocs.lastElement())?.then(styleImg => { const hrefParts = ImageCast(styleImg).url.href.split('.'); return `${hrefParts.slice(0, -1).join('.')}_o.${hrefParts.lastElement()}`; }); - return DocumentView.GetDocImage(drawing)?.then(imageField => { + return DocumentView.GetDocImage(drawing)?.then((imageField) => { if (imageField) { const aspectRatio = (drawing.width as number) / (drawing.height as number); const dims = (() => { @@ -42,7 +42,7 @@ export class DrawingFillHandler { const { href } = ImageCast(imageField).url; const hrefParts = href.split('.'); const structureUrl = `${hrefParts.slice(0, -1).join('.')}_o.${hrefParts.lastElement()}`; - const styleUrl = styleDoc ? `${hrefParts.slice(0, -1).join('.')}_o.${hrefParts.lastElement()}` : undefined; + const styleUrl = `${hrefParts.slice(0, -1).join('.')}_o.${hrefParts.lastElement()}`; return imageUrlToBase64(structureUrl) .then(gptDescribeImage) .then((prompt, newPrompt = user_prompt || prompt) => |