diff options
Diffstat (limited to 'src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx')
-rw-r--r-- | src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx | 190 |
1 files changed, 146 insertions, 44 deletions
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index 191b387c4..33d9a8827 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -31,6 +31,7 @@ import { dropActionType } from '../../../util/DropActionTypes'; import { ImageBox } from '../ImageBox'; import { a } from '@react-spring/web'; import { RichTextMenu } from '../formattedText/RichTextMenu'; +import e from 'cors'; export enum LayoutType { Stacked = 'stacked', @@ -137,8 +138,22 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { @computed get fieldsInfos(): Col[] { const colInfo = this._dataViz?.colsInfo; - return this.selectedFields.map(field => {return {title: field, type: colInfo?.get(field)?.type ?? TemplateFieldType.UNSET, desc: colInfo?.get(field)?.desc ?? '', size: colInfo?.get(field)?.size ?? TemplateFieldSize.MEDIUM, defaultContent: colInfo?.get(field)?.defaultContent ?? ''}}); - //.concat(this._columns) + return this.selectedFields.map(field => { + const fieldInfo = colInfo?.get(field); + + const col: Col = { + title: field, + type: fieldInfo?.type ?? TemplateFieldType.UNSET, + desc: fieldInfo?.desc ?? '', + size: fieldInfo?.size ?? TemplateFieldSize.MEDIUM + }; + + if (fieldInfo?.defaultContent !== undefined) { + col.defaultContent = fieldInfo.defaultContent; + } + + return col; + }).concat(this._columns); } @computed get canMakeDocs(){ @@ -463,7 +478,7 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { } }; - setFieldType = (column: Col, type: TemplateFieldType) => { + setColType = (column: Col, type: TemplateFieldType) => { if (this.selectedFields.includes(column.title)) { this._dataViz?.setColumnType(column.title, type); } else { @@ -472,7 +487,7 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { this.forceUpdate(); }; - setFieldSize = (column: Col, size: TemplateFieldSize) => { + setColSize = (column: Col, size: TemplateFieldSize) => { if (this.selectedFields.includes(column.title)) { this._dataViz?.setColumnSize(column.title, size); } else { @@ -481,11 +496,12 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { this.forceUpdate(); }; - setFieldDesc = (column: Col, desc: string) => { + setColDesc = (column: Col, desc: string) => { if (this.selectedFields.includes(column.title)) { this._dataViz?.setColumnDesc(column.title, desc); } else { column.desc = desc; + console.log(column, column.desc) } this.forceUpdate(); }; @@ -578,11 +594,45 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { // return new Doc; // } - createEmptyTemplate = (template: TemplateDocInfos, assignments: {[field: string]: Col}): Doc => { + fillPresetTemplate = async(template: TemplateDocInfos, assignments: {[field: string]: Col}): Promise<Doc> => { + const wordLimit = (size: TemplateFieldSize) => { + switch (size) { + case TemplateFieldSize.TINY: + return 2; + case TemplateFieldSize.SMALL: + return 5; + case TemplateFieldSize.MEDIUM: + return 20; + case TemplateFieldSize.LARGE: + return 50; + case TemplateFieldSize.HUGE: + return 100; + default: + return 10; + } + } + const fields: Doc[] = []; - Object.entries(assignments).forEach(([f, col]) => { + const GPTAssignments = Object.entries(assignments).filter(([f, col]) => this._columns.includes(col)); + const nonGPTAssignments: [string, Col][] = Object.entries(assignments).filter(a => !GPTAssignments.includes(a)); + + const stringifyGPTInfo = (): string => { + let string: string = '*** COLUMN INFO:'; + GPTAssignments.forEach(([fieldNum, col]) => { + `--- title: ${col.title}, prompt: ${col.desc}, word limit: ${wordLimit(col.size)} words, assigned field: ${fieldNum} ---` + }); + return string += ' ***'; + }; + + const GPTAssignmentString = stringifyGPTInfo(); + console.log('assignment string', GPTAssignmentString); + + let fieldContent: string = ''; + + Object.entries(nonGPTAssignments).forEach(([f, strCol]) => { const field: Field = template.fields[Number(f)]; + const col = strCol[1]; const doc = (col.type === TemplateFieldType.VISUAL ? FieldFuncs.ImageField : FieldFuncs.TextField)({ tl: field.tl, @@ -594,6 +644,8 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { field.opts ); + fieldContent += `--- Field #${f} (title: ${col.title}): ${col.defaultContent ?? ''} ---` + fields.push(doc); }); @@ -611,21 +663,67 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { fields.push(doc); }); - const renderedTemplate = Docs.Create.FreeformDocument(fields, { - _height: template.height, - _width: template.width, - title: template.title, - backgroundColor: template.opts.backgroundColor, - _layout_borderRounding: `${template.opts.cornerRounding}px` ?? '0px', - borderWidth: template.opts.borderWidth, - borderColor: template.opts.borderColor, - x: 400, - y: 400, - }); + const createMainDoc = (): Doc => { + const main = Docs.Create.FreeformDocument(fields, { + _height: template.height, + _width: template.width, + title: template.title, + backgroundColor: template.opts.backgroundColor, + _layout_borderRounding: `${template.opts.cornerRounding}px` ?? '0px', + borderWidth: template.opts.borderWidth, + borderColor: template.opts.borderColor, + x: 400, + y: 400, + }); - const mainCollection = this._dataViz?.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView; - mainCollection.addDocument(renderedTemplate); - return renderedTemplate; + const mainCollection = this._dataViz?.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView; + mainCollection.addDocument(main); + + return main; + } + + console.log('field content', fieldContent) + + if (GPTAssignments.length) { + + try { + const prompt = fieldContent + GPTAssignmentString; + + const res = await gptAPICall(prompt, GPTCallType.FILL); + + if (res){ + console.log('response', res); + + const assignments: {[title: string]: {number: string, content: string}} = JSON.parse(res); + console.log('assignments', assignments); + Object.entries(assignments).forEach(([title, info]) => { + const field: Field = template.fields[Number(info.number)]; + const col = this.getColByTitle(title); + + const doc = (col.type === TemplateFieldType.VISUAL ? FieldFuncs.ImageField : FieldFuncs.TextField)({ + tl: field.tl, + br: field.br }, + template.height, + template.width, + col.title, + info.content ?? '', + field.opts + ); + + fields.push(doc); + }); + + return createMainDoc(); + } + } catch(err) { + console.log(err); + } + + } else { + return createMainDoc(); + } + + return new Doc; }; compileFieldDescriptions = (templates: TemplateDocInfos[]): string => { @@ -693,17 +791,21 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { return []; }; - generatePresetTemplates = async() => { + generatePresetTemplates = async () => { const cols = this.fieldsInfos; const templates = this.findValidTemplates(cols, TemplateLayouts.allTemplates); - const assignments: [TemplateDocInfos, {[field: number]: Col}][] = await this.assignColsToFields(templates, cols); - const renderedTemplates: Doc[] = []; - assignments.forEach(([template, assignments]) => { - renderedTemplates.push(this.createEmptyTemplate(template, assignments)); - }); - - setTimeout(() => {this.setGSuggestedTemplates(renderedTemplates)}); - } + + const assignments: [TemplateDocInfos, { [field: number]: Col }][] = await this.assignColsToFields(templates, cols); + + const renderedTemplatePromises: Promise<Doc>[] = assignments.map(([template, assignments]) => + this.fillPresetTemplate(template, assignments) + ); + + const renderedTemplates: Doc[] = await Promise.all(renderedTemplatePromises); + + setTimeout(() => { this.setGSuggestedTemplates(renderedTemplates) }); + }; + get templatesPreviewContents(){ const renderedTemplates: Doc[] = []; @@ -1067,15 +1169,15 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { {field.type === TemplateFieldType.UNSET ? <span className='placeholder'>Select media type</span> : null} <span className='type-display'>{field.type === TemplateFieldType.TEXT ? 'Text Field' : field.type === TemplateFieldType.VISUAL ? 'File Field' : ''}</span> <div className='bubbles'> - <input className='bubble' type="radio" name="type" onClick={() => {this.setFieldType(field, TemplateFieldType.TEXT)}}/> + <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.setFieldType(field, TemplateFieldType.VISUAL)}}/> + <input className='bubble' type="radio" name="type" onClick={() => {this.setColType(field, TemplateFieldType.VISUAL)}}/> <div className='text'>File</div> </div> </div> <input className='field-property-container' id={`${Math.random() * 100}`} placeholder={this._dataViz?.GPTSummary?.get(field.title)?.size} style={{width: field.title === '' ? '30%' : ''}}/> </div> - <textarea className='field-description-container' onChange={(e) => this._dataViz?.setColumnDesc(field.title, 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 to help with template generation.'} /> + <textarea className='field-description-container' 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 to help with template generation.'} /> <div> <button className='docCreatorMenu-menu-button section-reveal-options top-right' onPointerDown={e => this.setUpButtonClick(e, () => this.removeField(field))}> <FontAwesomeIcon icon='trash'/> @@ -1821,37 +1923,37 @@ export class TemplateLayouts { backgroundColor: '#9E9C95' }, fields: [{ - tl: [-.95, .8], - br: [-.1, .95], + tl: [-.875, -.9], + br: [.875, .7], types: [TemplateFieldType.VISUAL], sizes: [TemplateFieldSize.MEDIUM, TemplateFieldSize.LARGE, TemplateFieldSize.HUGE], - description: '', + description: 'A medium to large visual field for the main content of the template', opts: { - backgroundColor: 'transparent', - color: 'white', - contentXCentering: 'h-right', + borderWidth: '15', + borderColor: '#E0E0DA', } }, { - tl: [.1, .8], - br: [.95, .95], + tl: [.1, .775], + br: [.95, .975], types: [TemplateFieldType.TEXT], sizes: [TemplateFieldSize.TINY, TemplateFieldSize.SMALL], description: 'A very small text field for one to a few words. The content should represent a general categorization of the image.', opts: { backgroundColor: 'transparent', - color: 'red', + color: '#AF0D0D', fontTransform: 'uppercase', fontBold: true, contentXCentering: 'h-left' } }, { - tl: [0, -.9], - br: [.85, -.66], + tl: [-.95, .775], + br: [-.1, .975], types: [TemplateFieldType.TEXT], sizes: [TemplateFieldSize.TINY, TemplateFieldSize.SMALL], description: 'A very small text field for one to a few words. The content should contextualize field 2.', opts: { backgroundColor: 'transparent', + color: 'black', contentXCentering: 'h-right' } }], |