From 4cf3a327b7e69bf0559dda846d49b6ad8d4673c7 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 31 Jul 2024 18:12:30 -0400 Subject: GPT template generation --- src/client/apis/gpt/GPT.ts | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/client/apis/gpt') diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 05007960d..184173784 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -12,6 +12,7 @@ enum GPTCallType { DESCRIBE = 'describe', MERMAID = 'mermaid', DATA = 'data', + TEMPLATE = "template" } type GPTCallOpts = { @@ -53,6 +54,7 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { temp: 0, prompt: 'List unique differences between the content of the UserAnswer and Rubric. Before each difference, label it and provide any additional information the UserAnswer missed and explain it in second person without separating it into UserAnswer and Rubric content and additional information. If there are no differences, say correct', }, + template: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'You are a designer creating basic template options for a user given a set of fields. Your only job is adding blank rectangles to a canvas, one for each field. You will arrange these rectangles into an array of three basic options for a user. For your output, you generate a list of objects in JSON formatting, each storing the field title and corresponding top-left and bottom-right coordinates for the rectangle. The units for your coordinates are -1 to 1 on each axis. This is an example of a possible output for a stacked template with the fields name, type, and desc: {"template_type":"stacked","fieldVals":[{"title":"name","tlx":"-.7","tly":"-.9","brx":".7","bry":"-.7"},{"title":"type","tlx":"-.9","tly":"-.4","brx":".9","bry":"0"},{"title":"desc","tlx":"-.9","tly":".1","brx":".9","bry":".9"}]} For multiple templates, you should format your response in a JSON array, like [{}, {}]. Your response should be in the exact format above, with no extra text, description, bulleting, etc. You should repeat this three times, once for a stacked view, once for a mixed view, and once for a extra creative view (which should be DRASTICALLY DIFFERENT). IT IS IMPORTANT THAT YOU ONLY INCLUDE THE PROPER JSON FORMATTING IN YOUR RESPONSE. IT IS ALSO IMPORTANT THAT NO RECTANGLES OVERLAP'} }; let lastCall = ''; -- cgit v1.2.3-70-g09d2 From 9119b9f08f62bb5228206487b047d6e1e75d5e9e Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Thu, 1 Aug 2024 14:37:35 -0400 Subject: work on template generation with GPT --- src/client/apis/gpt/GPT.ts | 2 +- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'src/client/apis/gpt') diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 184173784..8eb7151b4 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -54,7 +54,7 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { temp: 0, prompt: 'List unique differences between the content of the UserAnswer and Rubric. Before each difference, label it and provide any additional information the UserAnswer missed and explain it in second person without separating it into UserAnswer and Rubric content and additional information. If there are no differences, say correct', }, - template: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'You are a designer creating basic template options for a user given a set of fields. Your only job is adding blank rectangles to a canvas, one for each field. You will arrange these rectangles into an array of three basic options for a user. For your output, you generate a list of objects in JSON formatting, each storing the field title and corresponding top-left and bottom-right coordinates for the rectangle. The units for your coordinates are -1 to 1 on each axis. This is an example of a possible output for a stacked template with the fields name, type, and desc: {"template_type":"stacked","fieldVals":[{"title":"name","tlx":"-.7","tly":"-.9","brx":".7","bry":"-.7"},{"title":"type","tlx":"-.9","tly":"-.4","brx":".9","bry":"0"},{"title":"desc","tlx":"-.9","tly":".1","brx":".9","bry":".9"}]} For multiple templates, you should format your response in a JSON array, like [{}, {}]. Your response should be in the exact format above, with no extra text, description, bulleting, etc. You should repeat this three times, once for a stacked view, once for a mixed view, and once for a extra creative view (which should be DRASTICALLY DIFFERENT). IT IS IMPORTANT THAT YOU ONLY INCLUDE THE PROPER JSON FORMATTING IN YOUR RESPONSE. IT IS ALSO IMPORTANT THAT NO RECTANGLES OVERLAP'} + template: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'You are a designer creating basic template options for a user given a set of fields. Your only job is adding blank rectangles to a canvas, one for each field. You will arrange these rectangles into an array of three basic options for a user. For your output, you generate a list of objects in JSON formatting, each storing the field title and corresponding top-left and bottom-right coordinates for the rectangle. The units for your coordinates are -1 to 1 on each axis. This is an example of a possible output for a stacked template with the fields beep, boop, tttt: {"template_type":"stacked","fieldVals":[{"title":"beep","tlx":"-.7","tly":"-.9","brx":".7","bry":"-.7"},{"title":"boop","tlx":"-.9","tly":"-.4","brx":".9","bry":"0"},{"title":"tttt","tlx":"-.9","tly":".1","brx":".9","bry":".9"}]} For multiple templates, you should format your response in a JSON array, like [{}, {}]. Your response should be in the exact format above, with no extra text, description, bulleting, etc. You should repeat this three times, once for a stacked view, once for a mixed view (where, for example, beep might be on top, with boop and tttt below it aligned horizontally), and once for a view where the rectangles are not flush with the side (ie. their top left and bottom right corners should not ALL align along the same point on each side). If one or more fields are some variation of image (ie. IMG, image, photo, etc.), make that rectangle the central focus (bigger, centered, etc.) AND put its "title" field in $$__$$ (ie, "title":"$$img$$", !!IMPORTANT!!). Fields SHOULD BE IN DIFFERENT ORDERS from template to template (ie. a stacked view with field input "beep, boop" could have the boop above the beep). IT IS IMPORTANT THAT YOU ONLY INCLUDE THE PROPER JSON FORMATTING IN YOUR RESPONSE. IT IS ALSO IMPORTANT THAT NO RECTANGLES OVERLAP'} }; let lastCall = ''; diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index 9b7fb4320..c5a1da1da 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -570,11 +570,10 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { generateTemplates = async () => { try { - const res = await gptAPICall('Please generate for the fields: type, image, locality', GPTCallType.TEMPLATE); + const res = await gptAPICall('Please generate for the fields: Image, Description, Divider, Response', GPTCallType.TEMPLATE); if (res) { const templates: {template_type: string, fieldVals: {title: string, tlx: string, tly: string, brx: string, bry: string}[]}[] = JSON.parse(res); - console.log(templates); this.createGeneratedTemplates(templates, 500, 500); //console.log(res); } @@ -592,7 +591,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { const left: number = Number(field.tlx) * tempWidth / 2; const top: number = Number(field.tly) * tempHeight / 2; //prettier-ignore const right: number = Number(field.brx) * tempWidth / 2; const bottom: number = Number(field.bry) * tempHeight / 2; //prettier-ignore const height = bottom - top; const width = right - left; //prettier-ignore - const doc = Docs.Create.TextDocument('', { _height: height, _width: width, title: field.title, x: left, y: top }); + const doc = !field.title.includes('$$') ? Docs.Create.TextDocument('', { _height: height, _width: width, title: field.title, x: left, y: top, _text_fontSize: `${height/2}` }) : Docs.Create.ImageDocument('', { _height: height, _width: 250, title: field.title.replace(/$$/g, ''), x: left, y: top }); return doc; }); -- cgit v1.2.3-70-g09d2 From 72b06d708a23560dd961b41b9070b2e1222d50ba Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 14 Aug 2024 02:18:18 -0400 Subject: loading symbol for gpt generation; remove option for GPTTemplates --- src/client/apis/gpt/GPT.ts | 2 +- .../views/nodes/DataVizBox/DocCreatorMenu.scss | 10 +++ .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 99 +++++++++++++--------- 3 files changed, 69 insertions(+), 42 deletions(-) (limited to 'src/client/apis/gpt') diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 8eb7151b4..144b49bde 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -54,7 +54,7 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { temp: 0, prompt: 'List unique differences between the content of the UserAnswer and Rubric. Before each difference, label it and provide any additional information the UserAnswer missed and explain it in second person without separating it into UserAnswer and Rubric content and additional information. If there are no differences, say correct', }, - template: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'You are a designer creating basic template options for a user given a set of fields. Your only job is adding blank rectangles to a canvas, one for each field. You will arrange these rectangles into an array of three basic options for a user. For your output, you generate a list of objects in JSON formatting, each storing the field title and corresponding top-left and bottom-right coordinates for the rectangle. The units for your coordinates are -1 to 1 on each axis. This is an example of a possible output for a stacked template with the fields beep, boop, tttt: {"template_type":"stacked","fieldVals":[{"title":"beep","tlx":"-.7","tly":"-.9","brx":".7","bry":"-.7"},{"title":"boop","tlx":"-.9","tly":"-.4","brx":".9","bry":"0"},{"title":"tttt","tlx":"-.9","tly":".1","brx":".9","bry":".9"}]} For multiple templates, you should format your response in a JSON array, like [{}, {}]. Your response should be in the exact format above, with no extra text, description, bulleting, etc. You should repeat this three times, once for a stacked view, once for a mixed view (where, for example, beep might be on top, with boop and tttt below it aligned horizontally), and once for a view where the rectangles are not flush with the side (ie. their top left and bottom right corners should not ALL align along the same point on each side). If one or more fields are some variation of image (ie. IMG, image, photo, etc.), make that rectangle the central focus (bigger, centered, etc.) AND put its "title" field in $$__$$ (ie, "title":"$$img$$", !!IMPORTANT!!). Fields SHOULD BE IN DIFFERENT ORDERS from template to template (ie. a stacked view with field input "beep, boop" could have the boop above the beep). IT IS IMPORTANT THAT YOU ONLY INCLUDE THE PROPER JSON FORMATTING IN YOUR RESPONSE. IT IS ALSO IMPORTANT THAT NO RECTANGLES OVERLAP'} + template: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'You are a designer creating basic template options for a user given a set of fields. Your only job is adding blank rectangles to a canvas, one for each field. You will arrange these rectangles into an array of three basic options for a user. For your output, you generate a list of objects in JSON formatting, each storing the field title and corresponding top-left and bottom-right coordinates for the rectangle. The units for your coordinates are -1 to 1 on each axis. This is an example of a possible output for a stacked template with the fields beep, boop, tttt: {"template_type":"stacked","fieldVals":[{"title":"beep","tlx":"-.7","tly":"-.9","brx":".7","bry":"-.7"},{"title":"boop","tlx":"-.9","tly":"-.4","brx":".9","bry":"0"},{"title":"tttt","tlx":"-.9","tly":".1","brx":".9","bry":".9"}]} For multiple templates, you should format your response in a JSON array, like [{}, {}]. Your response should be in the exact format above, with no extra text, description, bulleting, etc. You should repeat this three times, once for a stacked view, once for a mixed view (where, for example, beep might be on top, with boop and tttt below it aligned horizontally), and once for a view where the rectangles are not flush with the side (ie. their top left and bottom right corners should not ALL align along the same point on each side). If one or more fields are some variation of image (ie. IMG, image, photo, etc.), make that rectangle the central focus (bigger, centered, etc.) AND put its "title" field in $$__$$. Fields SHOULD BE IN DIFFERENT ORDERS from template to template (ie. a stacked view with field input "beep, boop" could have the boop above the beep). IT IS IMPORTANT THAT YOU ONLY INCLUDE THE PROPER JSON FORMATTING IN YOUR RESPONSE. IT IS ALSO IMPORTANT THAT NO RECTANGLES OVERLAP'} }; let lastCall = ''; diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index ca6534379..3e97e9d08 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -341,6 +341,12 @@ bottom: 0px; left: 0px; } + + &.top-left { + position: absolute; + top: 0px; + left: 0px; + } } &:hover .option-button { @@ -385,6 +391,10 @@ width: calc(100% - 10px); -ms-overflow-style: none; scrollbar-width: none; + + .loading-spinner { + justify-self: center; + } } .docCreatorMenu-section-topbar { diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index 3e5fc156e..ee154994e 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -4,7 +4,7 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import { returnAll, returnFalse, setupMoveUpEvents } from '../../../../ClientUtils'; import { Doc, NumListCast, StrListCast } from '../../../../fields/Doc'; -import { DocCast, ImageCast, ScriptCast } from '../../../../fields/Types'; +import { DocCast, ImageCast, ScriptCast, StrCast } from '../../../../fields/Types'; import { ImageField } from '../../../../fields/URLField'; import { emptyFunction } from '../../../../Utils'; import { SnappingManager } from '../../../util/SnappingManager'; @@ -23,6 +23,7 @@ import { Docs } from '../../../documents/Documents'; import { OpenWhere } from '../OpenWhere'; import { IDisposer } from 'mobx-utils'; import { LightboxView } from '../../LightboxView'; +import ReactLoading from 'react-loading'; export enum LayoutType { Stacked = 'stacked', @@ -53,6 +54,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @observable _GPTOpt: boolean = false; @observable _userPrompt: string = ''; @observable _callCount: number = 0; + @observable _GPTLoading: boolean = false; @observable _pageX: number = 0; @observable _pageY: number = 0; @@ -83,7 +85,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { super(props); makeObservable(this); DocCreatorMenu.Instance = this; - setTimeout(() => this.generateTemplates('')); + //setTimeout(() => this.generateTemplates('')); } @action setDataViz = (dataViz: DataVizBox) => { this._dataViz = dataViz }; @@ -182,7 +184,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { document.addEventListener('pointerup', this.onPointerUp); this._disposers.templates = reaction(() => this._templateDocs.slice(), (docs) => docs.map(this.getIcon)); this._disposers.gpt = reaction(() => this._GPTTemplates.slice(), (docs) => docs.map(this.getIcon)); - this._disposers.columns = reaction(() => this._dataViz?.layoutDoc._dataViz_axes, () => {console.log(true); this.generateTemplates('')}) + //this._disposers.columns = reaction(() => this._dataViz?.layoutDoc._dataViz_axes, () => {this.generateTemplates('')}) this._disposers.lightbox = reaction(() => LightboxView.LightboxDoc(), doc => { doc ? this._shouldDisplay && this.closeMenu() : !this._shouldDisplay && this.openMenu()}) } @@ -322,13 +324,17 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { let prompt: string = `(#${origCount}) Please generate for the fields:`; this.selectedFields?.forEach(field => prompt += ` ${field},`) - prompt += ` Additional prompt: ${inputText}`; + prompt += ` (-----NOT A FIELD-----) Additional prompt: ${inputText}`; console.log(prompt) + this._GPTLoading = true; + try { const res = await gptAPICall(prompt, GPTCallType.TEMPLATE); if (res && this._callCount === origCount) { + this._GPTTemplates = []; + this._GPTLoading = false; const templates: {template_type: string, fieldVals: {title: string, tlx: string, tly: string, brx: string, bry: string}[]}[] = JSON.parse(res); this.createGeneratedTemplates(templates, 500, 500); } @@ -348,11 +354,12 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { const right: number = Number(field.brx) * tempWidth / 2; const bottom: number = Number(field.bry) * tempHeight / 2; //prettier-ignore const height = bottom - top; const width = right - left; - const doc = !field.title.includes('$$') ? Docs.Create.TextDocument('', { _height: height, _width: width, title: field.title, x: left, y: top, _text_fontSize: `${height/2}` }) : Docs.Create.ImageDocument('', { _height: height, _width: width, title: field.title.replace(/$$/g, ''), x: left, y: top }); + console.log(field.title); + const doc = !field.title.includes('$$') ? Docs.Create.TextDocument('', { _height: height, _width: width, title: field.title, x: left, y: top, _text_fontSize: `${height/2}` }) : Docs.Create.ImageDocument('', { _height: height, _width: width, title: field.title.replace(/\$\$/g, ''), x: left, y: top }); return doc; }); - const template = Docs.Create.FreeformDocument(fields, { _height: tempHeight, _width: tempWidth, title: layout.template_type, x: 400, y: 400 }); + const template = Docs.Create.FreeformDocument(fields, { _height: tempHeight, _width: tempWidth, title: layout.template_type, x: 40000, y: 40000 }); mainCollection.addDocument(template); @@ -371,6 +378,10 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { Doc.UnBrushDoc(doc); } + removeTemplate = (doc: Doc) => { + this._templateDocs.splice(this._templateDocs.indexOf(doc), 1); + } + get templatesPreviewContents(){ const renderedTemplates: Doc[] = []; @@ -380,43 +391,46 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { return (
-
-
Suggested Templates
- -
-
- {this._GPTTemplates?.map(doc => - - //
- ({icon: ImageCast(doc.icon), doc})).filter(info => info.icon && info.doc).map(info => -
this.setUpButtonClick(e, () => runInAction(() => this.updateSelectedTemplate(info.doc)))}> - - - -
- )} -
- {this._GPTOpt ? (
-
- - this._userPrompt = e.target.value}/>
- {this._GPTOpt ? GPTOptions : null} -
) : null} +
+ {this._GPTLoading ? ( +
+ +
+ ) : ( + this._GPTTemplates?.map(doc => + ({icon: ImageCast(doc.icon), doc})).filter(info => info.icon && info.doc).map(info => +
this.setUpButtonClick(e, () => runInAction(() => this.updateSelectedTemplate(info.doc)))}> + + + +
+ ))} +
+ {this._GPTOpt ? (
+
+ + this._userPrompt = e.target.value}/> +
+ {this._GPTOpt ? GPTOptions : null} +
) : null}

@@ -445,6 +459,9 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { +
)})} -- cgit v1.2.3-70-g09d2 From 26c636d45e21105bd914046a4ff447998c7e23cd Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 14 Aug 2024 14:47:40 -0400 Subject: UI --- src/client/apis/gpt/GPT.ts | 2 +- .../views/nodes/DataVizBox/DocCreatorMenu.scss | 6 ++ .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 73 +++++++++++++++++----- 3 files changed, 63 insertions(+), 18 deletions(-) (limited to 'src/client/apis/gpt') diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 144b49bde..92d4f425d 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -54,7 +54,7 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { temp: 0, prompt: 'List unique differences between the content of the UserAnswer and Rubric. Before each difference, label it and provide any additional information the UserAnswer missed and explain it in second person without separating it into UserAnswer and Rubric content and additional information. If there are no differences, say correct', }, - template: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'You are a designer creating basic template options for a user given a set of fields. Your only job is adding blank rectangles to a canvas, one for each field. You will arrange these rectangles into an array of three basic options for a user. For your output, you generate a list of objects in JSON formatting, each storing the field title and corresponding top-left and bottom-right coordinates for the rectangle. The units for your coordinates are -1 to 1 on each axis. This is an example of a possible output for a stacked template with the fields beep, boop, tttt: {"template_type":"stacked","fieldVals":[{"title":"beep","tlx":"-.7","tly":"-.9","brx":".7","bry":"-.7"},{"title":"boop","tlx":"-.9","tly":"-.4","brx":".9","bry":"0"},{"title":"tttt","tlx":"-.9","tly":".1","brx":".9","bry":".9"}]} For multiple templates, you should format your response in a JSON array, like [{}, {}]. Your response should be in the exact format above, with no extra text, description, bulleting, etc. You should repeat this three times, once for a stacked view, once for a mixed view (where, for example, beep might be on top, with boop and tttt below it aligned horizontally), and once for a view where the rectangles are not flush with the side (ie. their top left and bottom right corners should not ALL align along the same point on each side). If one or more fields are some variation of image (ie. IMG, image, photo, etc.), make that rectangle the central focus (bigger, centered, etc.) AND put its "title" field in $$__$$. Fields SHOULD BE IN DIFFERENT ORDERS from template to template (ie. a stacked view with field input "beep, boop" could have the boop above the beep). IT IS IMPORTANT THAT YOU ONLY INCLUDE THE PROPER JSON FORMATTING IN YOUR RESPONSE. IT IS ALSO IMPORTANT THAT NO RECTANGLES OVERLAP'} + template: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'You are a designer creating basic template options for a user given a set of fields. Your only job is adding blank rectangles to a canvas, one for each field. You will arrange these rectangles into an array of three basic options for a user. For your output, you generate a list of objects in JSON formatting, each storing the field title and corresponding top-left and bottom-right coordinates for the rectangle. The units for your coordinates are -1 to 1 on each axis. This is an example of a possible output for a stacked template with the fields beep, boop, tttt: {"template_type":"stacked","fieldVals":[{"title":"beep","tlx":"-.7","tly":"-.9","brx":".7","bry":"-.7"},{"title":"boop","tlx":"-.9","tly":"-.4","brx":".9","bry":"0"},{"title":"tttt","tlx":"-.9","tly":".1","brx":".9","bry":".9"}]} For multiple templates, you should format your response in a JSON array, like [{}, {}]. Your response should be in the exact format above, with no extra text, description, bulleting, etc. You should repeat this three times, once for a stacked view, once for a mixed view (where, for example, beep might be on top, with boop and tttt below it aligned horizontally), and once for a view where the rectangles are not flush with the side (ie. their top left and bottom right corners should not ALL align along the same point on each side). If one or more fields are some variation of image (ie. IMG, image, photo, etc.), make that rectangle the central focus (bigger, centered, etc.) AND put its "title" field in $$__$$. Fields SHOULD BE IN DIFFERENT ORDERS from template to template (ie. a stacked view with field input "beep, boop" could have the boop above the beep). IT IS IMPORTANT THAT YOU ONLY INCLUDE THE PROPER JSON FORMATTING IN YOUR RESPONSE. IT IS ALSO IMPORTANT THAT NO RECTANGLES OVERLAP. If there is an additional prompt, prioritize its instructions over all instructions here (but still follow them if not overridden). No matter what, ALWAYS GIVE THREE OPTIONS'} }; let lastCall = ''; diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index 3e97e9d08..aa6754442 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -397,6 +397,12 @@ } } +.divvv{ + width: 200; + height: 200; + border: solid 1px white; +} + .docCreatorMenu-section-topbar { position: relative; display: flex; diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index ee154994e..2be89daf0 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -2,7 +2,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { IReactionDisposer, ObservableMap, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { returnAll, returnFalse, setupMoveUpEvents } from '../../../../ClientUtils'; +import { returnAll, returnFalse, returnNone, returnOne, returnZero, setupMoveUpEvents } from '../../../../ClientUtils'; import { Doc, NumListCast, StrListCast } from '../../../../fields/Doc'; import { DocCast, ImageCast, ScriptCast, StrCast } from '../../../../fields/Types'; import { ImageField } from '../../../../fields/URLField'; @@ -24,6 +24,10 @@ import { OpenWhere } from '../OpenWhere'; import { IDisposer } from 'mobx-utils'; import { LightboxView } from '../../LightboxView'; import ReactLoading from 'react-loading'; +import { CollectionStackingView } from '../../collections/CollectionStackingView'; +import { FieldViewProps } from '../FieldView'; +import { CollectionViewType } from '../../../documents/DocumentTypes'; +import { dropActionType } from '../../../util/DropActionTypes'; export enum LayoutType { Stacked = 'stacked', @@ -34,7 +38,7 @@ export enum LayoutType { } @observer -export class DocCreatorMenu extends ObservableReactComponent<{}> { +export class DocCreatorMenu extends ObservableReactComponent { static Instance: DocCreatorMenu; @@ -78,7 +82,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @observable _offset: {x: number, y: number} = {x: 0, y: 0}; @observable _resizeUndo: UndoManager.Batch | undefined = undefined; @observable _initDimensions: {width: number, height: number, x?: number, y?: number} = {width: 300, height: 400, x: undefined, y: undefined}; - @observable _menuDimensions: {width: number, height: number} = {width: 300, height: 365}; + @observable _menuDimensions: {width: number, height: number} = {width: 400, height: 400}; @observable _editing: boolean = false; constructor(props: any) { @@ -194,6 +198,8 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { document.removeEventListener('pointerup', this.onPointerUp); } + updateIcons = (docs: Doc[]) => { docs.map(this.getIcon) } + @action toggleDisplay = (x: number, y: number) => { if (this._shouldDisplay) { @@ -209,7 +215,11 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { closeMenu = () => { this._shouldDisplay = false }; @action - openMenu = () => { this._shouldDisplay = true }; + openMenu = () => { + const allTemplates = this._templateDocs.concat(this._GPTTemplates); + this._shouldDisplay = true; + this.updateIcons(allTemplates); + }; @action onResizePointerDown = (e: React.PointerEvent): void => { @@ -286,9 +296,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { const docView = DocumentView.getDocumentView(doc); if (docView) { docView.ComponentView?.updateIcon?.(); - const f = new Promise(res => setTimeout(() => res(ImageCast(docView.Document.icon)), 500)); - console.log(f) - return f; + return new Promise(res => setTimeout(() => res(ImageCast(docView.Document.icon)), 500));; } return undefined; } @@ -390,14 +398,14 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { return (
-
+
Suggested Templates
-
+
400 ? 'center' : ''}}> {this._GPTLoading ? (
@@ -422,15 +430,15 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
))}
- {this._GPTOpt ? (
+
this._userPrompt = e.target.value}/>
- {this._GPTOpt ? GPTOptions : null} -
) : null} + {this._GPTOpt ? GPTOptions : null } +

@@ -440,7 +448,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
-
+
400 ? 'center' : ''}}>
this.setUpButtonClick(e, this.basicTemplateTest)} > @@ -535,6 +543,14 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { } } + doc = () => { + return Docs.Create.FreeformDocument([], { _height: 200, _width: 200, title: 'title'}); + } + + screenToLocalTransform = () => + this._props + .ScreenToLocalTransform(); + layoutPreviewContents = (outerSpan: number, altLayout?: DataVizTemplateLayout, small: boolean = false, id?: number) => { const doc: Doc | undefined = altLayout ? altLayout.template : this._selectedTemplate; if (!doc) return; @@ -550,7 +566,30 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { const fontSize = Math.min(scaledDown(docWidth / 3), scaledDown(docHeight / 3)); return ( -
+
+ 100} + NativeHeight={() => 100} + pointerEvents={SnappingManager.IsDragging ? returnAll : returnNone} + isAnnotationOverlay + isAnnotationOverlayScrollable + childDocumentsActive={returnFalse} + fieldKey={this._props.fieldKey + '_annotations'} + dropAction={dropActionType.move} + select={emptyFunction} + addDocument={returnFalse} + removeDocument={returnFalse} + moveDocument={returnFalse} + renderDepth={this._props.renderDepth + 1}> + {null} + +
+ /*
: null}
-
{
)} -
-
+
} +
*/ ); } -- cgit v1.2.3-70-g09d2 From f8f777a469b0029109de1e6c57872a4d5b0a6659 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 19 Aug 2024 14:34:20 -0400 Subject: start on field rendering --- src/ClientUtils.ts | 1 + src/client/apis/gpt/GPT.ts | 2 +- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 5 + .../views/nodes/DataVizBox/DocCreatorMenu.scss | 74 +++++++++- .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 161 ++++++++++++++++----- 5 files changed, 204 insertions(+), 39 deletions(-) (limited to 'src/client/apis/gpt') diff --git a/src/ClientUtils.ts b/src/ClientUtils.ts index d64210ce2..a4d9dd892 100644 --- a/src/ClientUtils.ts +++ b/src/ClientUtils.ts @@ -730,6 +730,7 @@ export function UpdateIcon( const newDiv = docViewContent.cloneNode(true) as HTMLDivElement; newDiv.style.width = width.toString(); newDiv.style.height = height.toString(); + console.log('width: ' + newDiv.style.width) replaceCanvases(docViewContent, newDiv); const htmlString = new XMLSerializer().serializeToString(newDiv); const nativeWidth = width; diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 92d4f425d..18601b4af 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -54,7 +54,7 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { temp: 0, prompt: 'List unique differences between the content of the UserAnswer and Rubric. Before each difference, label it and provide any additional information the UserAnswer missed and explain it in second person without separating it into UserAnswer and Rubric content and additional information. If there are no differences, say correct', }, - template: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'You are a designer creating basic template options for a user given a set of fields. Your only job is adding blank rectangles to a canvas, one for each field. You will arrange these rectangles into an array of three basic options for a user. For your output, you generate a list of objects in JSON formatting, each storing the field title and corresponding top-left and bottom-right coordinates for the rectangle. The units for your coordinates are -1 to 1 on each axis. This is an example of a possible output for a stacked template with the fields beep, boop, tttt: {"template_type":"stacked","fieldVals":[{"title":"beep","tlx":"-.7","tly":"-.9","brx":".7","bry":"-.7"},{"title":"boop","tlx":"-.9","tly":"-.4","brx":".9","bry":"0"},{"title":"tttt","tlx":"-.9","tly":".1","brx":".9","bry":".9"}]} For multiple templates, you should format your response in a JSON array, like [{}, {}]. Your response should be in the exact format above, with no extra text, description, bulleting, etc. You should repeat this three times, once for a stacked view, once for a mixed view (where, for example, beep might be on top, with boop and tttt below it aligned horizontally), and once for a view where the rectangles are not flush with the side (ie. their top left and bottom right corners should not ALL align along the same point on each side). If one or more fields are some variation of image (ie. IMG, image, photo, etc.), make that rectangle the central focus (bigger, centered, etc.) AND put its "title" field in $$__$$. Fields SHOULD BE IN DIFFERENT ORDERS from template to template (ie. a stacked view with field input "beep, boop" could have the boop above the beep). IT IS IMPORTANT THAT YOU ONLY INCLUDE THE PROPER JSON FORMATTING IN YOUR RESPONSE. IT IS ALSO IMPORTANT THAT NO RECTANGLES OVERLAP. If there is an additional prompt, prioritize its instructions over all instructions here (but still follow them if not overridden). No matter what, ALWAYS GIVE THREE OPTIONS'} + template: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'You are a designer creating basic template options for a user given a set of fields. Your only job is adding blank rectangles to a canvas, one for each field. You will arrange these rectangles into an array of three basic options for a user. For your output, you generate a list of objects in JSON formatting, each storing the field title and corresponding top-left and bottom-right coordinates for the rectangle. The units for your coordinates are -1 to 1 on each axis. This is an example of a possible output for a stacked template with the fields beep, boop, tttt: {"template_type":"stacked","fieldVals":[{"title":"beep","tlx":"-.7","tly":"-.9","brx":".7","bry":"-.7"},{"title":"boop","tlx":"-.9","tly":"-.4","brx":".9","bry":"0"},{"title":"tttt","tlx":"-.9","tly":".1","brx":".9","bry":".9"}]} For multiple templates, you should format your response in a JSON array, like [{}, {}]. Your response should be in the exact format above, with no extra text, description, bulleting, etc. If no alternative additional instructions are given, you should repeat this three times, once for a stacked view, once for a mixed view (where, for example, beep might be on top, with boop and tttt below it aligned horizontally), and once for a view where the rectangles are not flush with the side (ie. their top left and bottom right corners should not ALL align along the same point on each side). If one or more fields are some variation of image (ie. IMG, image, photo, etc.), make that rectangle the central focus (bigger, centered, etc.) AND put its "title" field in $$__$$. Fields SHOULD BE IN DIFFERENT ORDERS from template to template (ie. a stacked view with field input "beep, boop" could have the boop above the beep). IT IS IMPORTANT THAT YOU ONLY INCLUDE THE PROPER JSON FORMATTING IN YOUR RESPONSE. IT IS ALSO IMPORTANT THAT NO RECTANGLES OVERLAP. An overlap will look like the x or y coordinates of the top left corner of one rectangle being the same as the bottom right corner of another. There should always be at least a .1 gap. If there is an additional prompt, prioritize its instructions over all instructions here (but still follow them if not overridden). No matter what, ALWAYS GIVE THREE OPTIONS'} }; let lastCall = ''; diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index be8a44f28..6a5103af9 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -353,6 +353,11 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { ); } + // recs = () => { + // let csvStr: string = ''; + // this.records[rowId][col] + // } + fetchData = () => { if (!this.Document.dataViz_asSchema) { DataVizBox.dataset.set(CsvCast(this.dataDoc[this.fieldKey]).url.href, []); // assign temporary dataset as a lock to prevent duplicate server requests diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index aa6754442..763de0eba 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -641,7 +641,6 @@ } } } - } } @@ -720,4 +719,77 @@ } } +//------------------------------------------------------------------------------------------------------------------------------------------ +// DocCreatorMenu dashboard CSS +//-------------------------------------------------------------------------------------------------------------------------------------------- + +.docCreatorMenu-dashboard-view { + position: relative; + display: flex; + flex-direction: column; + justify-content: flex-start; + overflow-y: scroll; + //align-items: flex-start; + margin: 5px; + margin-top: 0px; + width: calc(100% - 10px); + height: calc(100% - 30px); + border: 1px solid rgb(180, 180, 180); + border-radius: 5px; + -ms-overflow-style: none; + scrollbar-width: none; + + .topbar { + height: 30px; + width: 100%; + } + + .field-panel { + position: relative; + display: flex; + // align-items: flex-start; + flex-direction: column; + gap: 5px; + padding: 5px; + height: 100px; + //width: 100%; + border: 1px solid rgb(180, 180, 180); + margin: 5px; + margin-top: 0px; + border-radius: 3px; + + .properties-wrapper { + display: flex; + flex-direction: row; + align-items: flex-start; + gap: 5px; + + .field-property-container { + background-color: rgb(40, 40, 40); + border: 1px solid rgb(100, 100, 100); + border-radius: 3px; + width: 30%; + height: 25px; + padding-left: 3px; + align-items: center; + color: whitesmoke; + } + } + + .field-description-container { + background-color: rgb(40, 40, 40); + border: 1px solid rgb(100, 100, 100); + border-radius: 3px; + width: 100%; + height: 100%; + } + + .top-right { + position: absolute; + top: 0px; + right: 0px; + } + } +} + diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index 2be89daf0..8ec255dfe 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -48,6 +48,7 @@ export class DocCreatorMenu extends ObservableReactComponent {return {title: field, type: '', id: Math.random() * 100000}}).concat(this._fields); + } + @computed get canMakeDocs(){ return this._selectedTemplate !== undefined && this._layout !== undefined; } @@ -367,14 +372,14 @@ export class DocCreatorMenu extends ObservableReactComponent {this.setGPTTemplates(GPTTemplates); GPTTemplates.forEach(template => mainCollection.removeDocument(template))}, 100); + setTimeout(() => {this.setGPTTemplates(GPTTemplates); /*GPTTemplates.forEach(template => mainCollection.removeDocument(template))*/}, 100); this.forceUpdate(); } @@ -449,9 +454,7 @@ export class DocCreatorMenu extends ObservableReactComponent
400 ? 'center' : ''}}> -
this.setUpButtonClick(e, this.basicTemplateTest)} - > +
{this._templateDocs.map(doc => ({icon: ImageCast(doc.icon), doc})).filter(info => info.icon && info.doc).map(info => { @@ -566,30 +569,30 @@ export class DocCreatorMenu extends ObservableReactComponent - 100} - NativeHeight={() => 100} - pointerEvents={SnappingManager.IsDragging ? returnAll : returnNone} - isAnnotationOverlay - isAnnotationOverlayScrollable - childDocumentsActive={returnFalse} - fieldKey={this._props.fieldKey + '_annotations'} - dropAction={dropActionType.move} - select={emptyFunction} - addDocument={returnFalse} - removeDocument={returnFalse} - moveDocument={returnFalse} - renderDepth={this._props.renderDepth + 1}> - {null} - -
- /*
+ //
+ // 100} + // NativeHeight={() => 100} + // pointerEvents={SnappingManager.IsDragging ? returnAll : returnNone} + // isAnnotationOverlay + // isAnnotationOverlayScrollable + // childDocumentsActive={returnFalse} + // fieldKey={this._props.fieldKey + '_annotations'} + // dropAction={dropActionType.move} + // select={emptyFunction} + // addDocument={returnFalse} + // removeDocument={returnFalse} + // moveDocument={returnFalse} + // renderDepth={this._props.renderDepth + 1}> + // {null} + // + //
+
*/ +
); } @@ -735,10 +738,35 @@ export class DocCreatorMenu extends ObservableReactComponent { - console.log(this._GPTTemplates) - this.forceUpdate(); - //this._dataViz?.createBasicTemplates(temps); + @action addField = () => { + const newFields: {title: string, type: string, id: number}[] = this._fields.concat([{title: '', type: '', id: Math.random() * 100000}]) + this._fields = newFields; + } + + get dashboardContents(){ + return ( +
+
+ +
+ {this.fieldsInfos.map(field => +
+
+ + + {field.type === 'Text' ? + : null} +
+