import { action, makeAutoObservable } from 'mobx'; import { Col } from '../DocCreatorMenu'; import { FieldSettings, TemplateField } from '../TemplateFieldTypes/TemplateField'; import { Template } from '../Template'; import { NumListCast } from '../../../../../../fields/Doc'; import { DataVizBox } from '../../DataVizBox'; import { TemplateFieldType } from '../TemplateBackend'; import { TemplateMenuAIUtils } from './TemplateMenuAIUtils'; export type Conditional = { field: string; operator: '=' | '>' | '<' | 'contains'; condition: string; target: string; attribute: string; value: string; }; export class TemplateManager { _templates: Template[] = []; _conditionalFieldLogic: Record = {}; constructor(templateSettings: FieldSettings[]) { makeAutoObservable(this); this._templates = templateSettings.map(settings => new Template(settings)); } getValidTemplates = (cols: Col[]) => this._templates.filter(template => template.isValidTemplate(cols)); addTemplate = (newTemplate: Template) => this._templates.push(newTemplate); removeTemplate = (template: Template) => { if (this._templates.includes(template)) { this._templates.splice(this._templates.indexOf(template), 1); } template.cleanup(); }; addFieldCondition = (fieldTitle: string, condition: Conditional) => { if (this._conditionalFieldLogic[fieldTitle] === undefined) { this._conditionalFieldLogic[fieldTitle] = [condition]; } else { this._conditionalFieldLogic[fieldTitle].push(condition); } }; removeFieldCondition = (fieldTitle: string, condition: Conditional) => (this._conditionalFieldLogic[fieldTitle] = this._conditionalFieldLogic[fieldTitle]?.filter(cond => cond !== condition)); 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 csvFields = Array.from(Object.keys(dv.records[0])); const processContent = (content: { [title: string]: string }) => { const templateCopy = template.clone(); csvFields .filter(title => title) .forEach(title => { const field = templateCopy.getFieldByTitle(title); field?.setContent(content[title], field.viewType); }); const gptFunc = (type: TemplateFieldType) => (type === TemplateFieldType.VISUAL ? TemplateMenuAIUtils.renderGPTImageCall : TemplateMenuAIUtils.renderGPTTextCall); const generateGptContent = cols .map(field => ({ field, templateField: field?.AIGenerated && templateCopy.getFieldByTitle(field.title) })) .filter(({ templateField }) => templateField instanceof TemplateField) .map(({ field, templateField }) => gptFunc(field.type)(templateCopy, field, (templateField as TemplateField).getID)); return Promise.all(generateGptContent).then(() => templateCopy.applyConditionalLogic(this._conditionalFieldLogic)); }; const rowContents = debug ? [{}, {}, {}, {}] : NumListCast(dv.layoutDoc.dataViz_selectedRows).map(row => csvFields.reduce( (values, col) => { values[col] = dv.records[row][col]; return values; }, {} as { [title: string]: string } ) ); return Promise.all(rowContents.map(processContent)); }); }