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.tsx172
1 files changed, 96 insertions, 76 deletions
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx
index 379a33a99..ea38430ca 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx
@@ -61,7 +61,7 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> {
@observable _selectedTemplate: Template | undefined = undefined;
@observable _currEditingTemplate: Template | undefined = undefined;
- @observable _userCreatedColumns: Col[] = [];
+ @observable _userCreatedFields: Col[] = [];
@observable _selectedCols: { title: string; type: string; desc: string }[] | undefined = [];
@observable _layout: { type: LayoutType; yMargin: number; xMargin: number; columns?: number; repeat: number } = { type: LayoutType.FREEFORM, yMargin: 10, xMargin: 10, columns: 3, repeat: 0 };
@@ -175,7 +175,7 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> {
return col;
})
- .concat(this._userCreatedColumns);
+ .concat(this._userCreatedFields);
}
@computed get canMakeDocs() {
@@ -360,14 +360,14 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> {
return undefined;
}
- @action updateSelectedTemplate = (template: Template) => {
+ @action updateSelectedTemplate = async (template: Template) => {
if (this._selectedTemplate === template) {
this._selectedTemplate = undefined;
return;
} else {
this._selectedTemplate = template;
template.renderUpdates();
- this._fullyRenderedDocs = this.createDocsFromTemplate(template) ?? [];
+ this._fullyRenderedDocs = await this.createDocsFromTemplate(template) ?? [];
this.updateRenderedDocCollection();
}
};
@@ -410,15 +410,15 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> {
};
@action addField = () => {
- const newFields: Col[] = this._userCreatedColumns.concat([{ title: '', type: TemplateFieldType.UNSET, desc: '', sizes: [] }]);
- this._userCreatedColumns = newFields;
+ const newFields: Col[] = this._userCreatedFields.concat([{ title: '', type: TemplateFieldType.UNSET, desc: '', sizes: [] }]);
+ this._userCreatedFields = newFields;
};
@action removeField = (field: { title: string; type: string; desc: string }) => {
if (this._dataViz?.axes.includes(field.title)) {
this._dataViz.selectAxes(this._dataViz.axes.filter(col => col !== field.title));
} else {
- const toRemove = this._userCreatedColumns.filter(f => f === field);
+ const toRemove = this._userCreatedFields.filter(f => f === field);
if (!toRemove) return;
if (toRemove.length > 1) {
@@ -427,10 +427,10 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> {
}
}
- if (this._userCreatedColumns.length === 1) {
- this._userCreatedColumns = [];
+ if (this._userCreatedFields.length === 1) {
+ this._userCreatedFields = [];
} else {
- this._userCreatedColumns.splice(this._userCreatedColumns.indexOf(toRemove[0]), 1);
+ this._userCreatedFields.splice(this._userCreatedFields.indexOf(toRemove[0]), 1);
}
}
};
@@ -498,22 +498,6 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> {
* @returns a doc containing the fully rendered template
*/
applyGPTContentToTemplate = async (template: Template, assignments: { [field: string]: Col }): Promise<Template | undefined> => {
- 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 generateAndLoadImage = async (fieldNum: string, col: Col, prompt: string) => {
const url = await this.generateGPTImage(prompt);
@@ -523,44 +507,17 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> {
field.setTitle(col.title);
};
- const GPTTextCalls = Object.entries(assignments).filter(([str, col]) => col.type === TemplateFieldType.TEXT);
- const GPTIMGCalls = Object.entries(assignments).filter(([str, col]) => col.type === TemplateFieldType.VISUAL);
-
- if (!GPTTextCalls && !GPTIMGCalls) return;
-
- const stringifyGPTInfo = (calls: [string, Col][]): string => {
- let string: string = '*** COLUMN INFO:';
- calls.forEach(([fieldNum, col]) => {
- string += `--- title: ${col.title}, prompt: ${col.desc}, word limit: ${wordLimit(col.sizes[0])} words, assigned field: ${fieldNum} ---`;
- });
- return (string += ' ***');
- };
-
- const GPTTextAssignment = stringifyGPTInfo(GPTTextCalls);
-
+ const GPTTextCalls = Object.entries(assignments).filter(([str, col]) => col.type === TemplateFieldType.TEXT && this._userCreatedFields.includes(col));
+ const GPTIMGCalls = Object.entries(assignments).filter(([str, col]) => col.type === TemplateFieldType.VISUAL && this._userCreatedFields.includes(col));
let fieldContent: string = template.compiledContent;
if (GPTTextCalls.length) {
- try {
- const prompt = fieldContent + GPTTextAssignment;
-
- const res = await gptAPICall(`${++this._callCount}: ${prompt}`, GPTCallType.FILL);
-
- if (res) {
- const assignments: { [title: string]: { number: string; content: string } } = JSON.parse(res);
- //console.log('assignments', GPTAssignments, 'assignment string', GPTAssignmentString, 'field content', fieldContent, 'response', res, 'assignments', assignments);
- Object.entries(assignments).forEach(([title, info]) => {
- const field: Field = template.getFieldByID(Number(info.number));
- const col = this.getColByTitle(title);
+ const promises = GPTTextCalls.map(([str, col]) => {
+ return this.renderGPTTextCall(template, col, Number(str));
+ });
- field.setContent(info.content ?? '', FieldContentType.STRING);
- field.setTitle(col.title);
- });
- }
- } catch (err) {
- console.log(err);
- }
+ await Promise.all(promises);
}
if (GPTIMGCalls.length) {
@@ -634,7 +591,7 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> {
const toObj = Object.entries(assignment).reduce(
(a, [fieldID, colTitle]) => {
const col = this.getColByTitle(colTitle);
- if (!this._userCreatedColumns.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 fields
+ 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 fields
const field = template.getFieldByID(Number(fieldID));
//console.log(field);
field.setContent(col.defaultContent ?? '', col.type === TemplateFieldType.VISUAL ? FieldContentType.IMAGE : FieldContentType.STRING);
@@ -676,38 +633,101 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> {
});
};
- createDocsFromTemplate = (template: Template) => {
+ renderGPTTextCall = async (template: Template, col: Col, fieldNum: number): Promise<boolean> => {
+ 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 textAssignment = `--- title: ${col.title}, prompt: ${col.desc}, word limit: ${wordLimit(col.sizes[0])} words, assigned field: ${fieldNum} ---`;
+
+ let fieldContent: string = template.compiledContent;
+
+ try {
+ const prompt = fieldContent + textAssignment;
+
+ const res = await gptAPICall(`${++this._callCount}: ${prompt}`, GPTCallType.FILL);
+
+ console.log('prompt: ', prompt, ' response: ', res);
+
+ if (res) {
+ const assignments: { [title: string]: { number: string; content: string } } = JSON.parse(res);
+ Object.entries(assignments).forEach(([title, info]) => {
+ const field: Field = template.getFieldByID(Number(info.number));
+ const col = this.getColByTitle(title);
+
+ field.setContent(info.content ?? '', FieldContentType.STRING);
+ field.setTitle(col.title);
+ });
+ }
+ } catch (err) {
+ console.log(err);
+ }
+
+ return true;
+ }
+
+ createDocsFromTemplate = async (template: Template) => {
const dv = this._dataViz;
if (!dv) return;
const fields: string[] = Array.from(Object.keys(dv.records[0]));
const selectedRows = NumListCast(dv.layoutDoc.dataViz_selectedRows);
-
- const fieldContents: {[title: string]: string}[] = selectedRows.map(row => {
- let values: {[title: string]: string} = {};
+
+ const rowContents: { [title: string]: string }[] = selectedRows.map(row => {
+ let values: { [title: string]: string } = {};
fields.forEach(col => {
values[col] = dv.records[row][col];
});
-
+
return values;
});
+
+ const processContent = async (content: {[title: string]: string}) => {
+ const templateCopy = template.cloneBase();
+
+ console.log('rows: ', content, '---------------- fields: ', fields)
-
- const renderedDocs: Doc[] = [];
-
- fieldContents.forEach(content => {
fields.filter(title => title).forEach(title => {
- const field = template.getFieldByTitle(title);
- if (field === undefined){
- return;
- }
+ const field = templateCopy.getFieldByTitle(title);
+ console.log('field: ', field);
+ if (field === undefined) { return };
field.setContent(content[title]);
});
-
- renderedDocs.push(template.mainField.renderedDoc());
- });
+
+ const gptPromises = this._userCreatedFields.map(field => {
+ const title = field.title;
+ const templateField = templateCopy.getFieldByTitle(title);
+ if (templateField === undefined) { return };
+ const templatefieldID = templateField.getID;
+
+ return this.renderGPTTextCall(templateCopy, field, templatefieldID);
+ });
+
+ await Promise.all(gptPromises);
+
+ console.log(templateCopy);
+ return templateCopy.mainField.renderedDoc();
+ };
+
+ const promises = rowContents.map(content => processContent(content));
+
+ const renderedDocs = await Promise.all(promises);
return renderedDocs;
}
+
addRenderedCollectionToMainview = () => {
const collection = this._renderedDocCollection;