aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/apis/gpt/GPT.ts44
-rw-r--r--src/client/views/PropertiesView.tsx2
-rw-r--r--src/client/views/nodes/trails/PresBox.scss24
-rw-r--r--src/client/views/nodes/trails/PresBox.tsx63
-rw-r--r--src/client/views/nodes/trails/PresElementBox.tsx35
-rw-r--r--src/client/views/pdf/GPTPopup/GPTPopup.scss4
6 files changed, 157 insertions, 15 deletions
diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts
index 6bde7989b..d7e7f07fa 100644
--- a/src/client/apis/gpt/GPT.ts
+++ b/src/client/apis/gpt/GPT.ts
@@ -19,6 +19,32 @@ const callTypeMap: { [type: string]: GPTCallOpts } = {
completion: { model: 'text-davinci-003', maxTokens: 256, temp: 0.5, prompt: '' },
};
+const configuration = new Configuration({
+ apiKey: process.env.OPENAI_KEY,
+});
+const openai = new OpenAIApi(configuration);
+
+const gptTrailSlideCustomization = async (inputText: string) => {
+ const prompt =
+ 'We are adding customization to a slide in a presentation. Given a natural language input, translate it into a json with the required fields: [title, presentation_transition, presentation_effect, and config_zoom]. title is the title/name of the slide. presentation_transition is a number in milliseconds for how long it should take to transition to a slide. presentation_effect is an effect applied to the slide when we transition to it. Its only possible values are: [None, Fade in, Flip, Rotate, Bounce, Roll]. config zoom is a number from 0 to 1.0 indicating the percentage we should be zooming into the slide.If the input does not contain info a specific key, please set their value to null. Please only return the json with these keys and their values.';
+
+ try {
+ const response = await openai.createChatCompletion({
+ model: 'gpt-3.5-turbo',
+ messages: [
+ { role: 'system', content: prompt },
+ { role: 'user', content: inputText },
+ ],
+ temperature: 0.1,
+ max_tokens: 1000,
+ });
+ return response.data.choices[0].message?.content;
+ } catch (err) {
+ console.log(err);
+ return 'Error connecting with API.';
+ }
+};
+
/**
* Calls the OpenAI API.
*
@@ -29,10 +55,10 @@ const gptAPICall = async (inputText: string, callType: GPTCallType) => {
if (callType === GPTCallType.SUMMARY) inputText += '.';
const opts: GPTCallOpts = callTypeMap[callType];
try {
- const configuration = new Configuration({
- apiKey: process.env.OPENAI_KEY,
- });
- const openai = new OpenAIApi(configuration);
+ // const configuration = new Configuration({
+ // apiKey: process.env.OPENAI_KEY,
+ // });
+ // const openai = new OpenAIApi(configuration);
const response = await openai.createCompletion({
model: opts.model,
max_tokens: opts.maxTokens,
@@ -48,10 +74,10 @@ const gptAPICall = async (inputText: string, callType: GPTCallType) => {
const gptImageCall = async (prompt: string, n?: number) => {
try {
- const configuration = new Configuration({
- apiKey: process.env.OPENAI_KEY,
- });
- const openai = new OpenAIApi(configuration);
+ // const configuration = new Configuration({
+ // apiKey: process.env.OPENAI_KEY,
+ // });
+ // const openai = new OpenAIApi(configuration);
const response = await openai.createImage({
prompt: prompt,
n: n ?? 1,
@@ -65,4 +91,4 @@ const gptImageCall = async (prompt: string, n?: number) => {
}
};
-export { gptAPICall, gptImageCall, GPTCallType };
+export { gptAPICall, gptImageCall, gptTrailSlideCustomization, GPTCallType };
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index cb45ece42..984906ed0 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -1266,7 +1266,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
Doc.GetProto(LinkManager.currentLink).link_description = value;
if (LinkManager.currentLink.show_description === undefined) {
- LinkManager.currentLink['show_description'] = !LinkManager.currentLink['show_description'];
+ LinkManager.currentLink.show_description = !LinkManager.currentLink.show_description;
}
}
});
diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss
index 0b51813a5..ac0d58368 100644
--- a/src/client/views/nodes/trails/PresBox.scss
+++ b/src/client/views/nodes/trails/PresBox.scss
@@ -15,6 +15,30 @@
//overflow: hidden;
transition: 0.7s opacity ease;
+ .presBox-chatbox {
+ position: fixed;
+ bottom: 8px;
+ right: 8px;
+ width: 300px;
+ min-height: 100px;
+ border-radius: 16px;
+ padding: 16px;
+ gap: 8px;
+ z-index: 999;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ background-color: #ffffff;
+ box-shadow: 0 2px 5px #7474748d;
+
+ input {
+ resize: vertical;
+ // min-height: 125px;
+ border: none;
+ outline: none;
+ }
+ }
+
.presBox-listCont {
position: relative;
height: calc(100% - 67px);
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 383b400c8..ebf9c211c 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -37,7 +37,9 @@ import { FieldView, FieldViewProps } from '../FieldView';
import { ScriptingBox } from '../ScriptingBox';
import './PresBox.scss';
import { PresEffect, PresEffectDirection, PresMovement, PresStatus } from './PresEnums';
-const { Howl } = require('howler');
+import { IconButton, Type } from 'browndash-components';
+import { AiOutlineSend } from 'react-icons/ai';
+import { gptTrailSlideCustomization } from '../../../apis/gpt/GPT';
export interface pinDataTypes {
scrollable?: boolean;
@@ -105,7 +107,24 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
@observable _treeViewMap: Map<Doc, number> = new Map();
@observable _presKeyEvents: boolean = false;
@observable _forceKeyEvents: boolean = false;
- @computed get isTreeOrStack() {
+
+ // GPT
+ @observable chatActive: boolean = false;
+ @observable chatInput: string = '';
+ public slideToModify: Doc | null = null;
+
+ @action
+ setChatInput = (input: string) => {
+ this.chatInput = input;
+ };
+
+ @action
+ public setChatActive = (active: boolean) => {
+ this.chatActive = active;
+ };
+
+ @computed
+ get isTreeOrStack() {
return [CollectionViewType.Tree, CollectionViewType.Stacking].includes(StrCast(this.layoutDoc._type_collection) as any);
}
@computed get isTree() {
@@ -241,6 +260,28 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
};
+ @action
+ customizeWithGPT = async (input: string) => {
+ // const testInput = 'change title to Customized Slide, transition for 2.3s with fade in effect';
+ if (!this.slideToModify) return;
+
+ try {
+ const res = await gptTrailSlideCustomization(input);
+ if (typeof res === 'string') {
+ const resObj = JSON.parse(res);
+ console.log('Result ', resObj);
+ // this.activeItem
+ for (let key in resObj) {
+ if (resObj[key]) {
+ this.slideToModify[key] = resObj[key];
+ }
+ }
+ }
+ } catch (err) {
+ console.error(err);
+ }
+ };
+
//TODO: al: it seems currently that tempMedia doesn't stop onslidechange after clicking the button; the time the tempmedia stop depends on the start & end time
// TODO: to handle child slides (entering into subtrail and exiting), also the next() and back() functions
// No more frames in current doc and next slide is defined, therefore move to next slide
@@ -2661,7 +2702,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
/>
) : null}
</div>
-
{/* {
// if the document type is a presentation, then the collection stacking view has a "+ new slide" button at the bottom of the stack
<Tooltip title={<div className="dash-tooltip">{'Click on document to pin to presentaiton or make a marquee selection to pin your desired view'}</div>}>
@@ -2671,6 +2711,23 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
</Tooltip>
} */}
</div>
+ {/* presbox chatbox */}
+ {this.chatActive && (
+ <div className="presBox-chatbox">
+ <input placeholder="Customize..." value={this.chatInput} onChange={e => this.setChatInput(e.target.value)} />
+ <div style={{ alignSelf: 'flex-end' }}>
+ <IconButton
+ type={Type.TERT}
+ color={StrCast(Doc.UserDoc().userVariantColor)}
+ tooltip="Send"
+ icon={<AiOutlineSend size={'16px'} />}
+ onClick={() => {
+ this.customizeWithGPT(this.chatInput);
+ }}
+ />
+ </div>
+ </div>
+ )}
</div>
);
}
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
index 82ed9e8d5..534a0f2aa 100644
--- a/src/client/views/nodes/trails/PresElementBox.tsx
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -28,6 +28,7 @@ import React = require('react');
import { TreeView } from '../../collections/TreeView';
import { BranchingTrailManager } from '../../../util/BranchingTrailManager';
import { MultiToggle, Type } from 'browndash-components';
+import { gptTrailSlideCustomization } from '../../../apis/gpt/GPT';
/**
* This class models the view a document added to presentation will have in the presentation.
* It involves some functionality for its buttons and options.
@@ -434,6 +435,27 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
return width;
}
+ // GPT
+
+ @action
+ customizeWithGPT = async (input: string) => {
+ const testInput = 'change title to Customized Slide, transition for 2.3s with fade in effect';
+
+ try {
+ const res = await gptTrailSlideCustomization(testInput);
+ if (typeof res === 'string') {
+ const resObj = JSON.parse(res);
+ console.log('Result ', resObj);
+
+ for (let key in resObj) {
+ this.rootDoc[key] = resObj[key];
+ }
+ }
+ } catch (err) {
+ console.error(err);
+ }
+ };
+
@computed get presButtons() {
const presBox = this.presBox;
const presBoxColor = StrCast(presBox?._backgroundColor);
@@ -537,6 +559,19 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
</div>
</Tooltip>
);
+ items.push(
+ <Tooltip key="customize" title={<div className="dash-tooltip">Customize</div>}>
+ <div
+ className={'slideButton'}
+ onClick={() => {
+ PresBox.Instance.setChatActive(true);
+ PresBox.Instance.slideToModify = this.rootDoc;
+ // this.customizeWithGPT('');
+ }}>
+ <FontAwesomeIcon icon={'message'} onPointerDown={e => e.stopPropagation()} />
+ </div>
+ </Tooltip>
+ );
return items;
}
diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.scss b/src/client/views/pdf/GPTPopup/GPTPopup.scss
index 5d966395c..48659d0e7 100644
--- a/src/client/views/pdf/GPTPopup/GPTPopup.scss
+++ b/src/client/views/pdf/GPTPopup/GPTPopup.scss
@@ -11,8 +11,8 @@ $highlightedText: #82e0ff;
right: 10px;
width: 250px;
min-height: 200px;
- border-radius: 15px;
- padding: 15px;
+ border-radius: 16px;
+ padding: 16px;
padding-bottom: 0;
z-index: 999;
display: flex;