summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNate Sesti <sestinj@gmail.com>2023-06-13 22:56:29 -0700
committerNate Sesti <sestinj@gmail.com>2023-06-13 22:56:29 -0700
commit114015518f41ed4eb00308f4bf72b89133091b9f (patch)
tree800b623c0e338a8732fc6cd0988970cda83b0159
parentc047e251aa14a7f39105bd40210963879bf03895 (diff)
downloadsncontinue-114015518f41ed4eb00308f4bf72b89133091b9f.tar.gz
sncontinue-114015518f41ed4eb00308f4bf72b89133091b9f.tar.bz2
sncontinue-114015518f41ed4eb00308f4bf72b89133091b9f.zip
feedback dialog
-rw-r--r--extension/react-app/src/components/TextDialog.tsx56
-rw-r--r--extension/react-app/src/tabs/gui.tsx194
2 files changed, 168 insertions, 82 deletions
diff --git a/extension/react-app/src/components/TextDialog.tsx b/extension/react-app/src/components/TextDialog.tsx
new file mode 100644
index 00000000..6b335e00
--- /dev/null
+++ b/extension/react-app/src/components/TextDialog.tsx
@@ -0,0 +1,56 @@
+// Write a component that displays a dialog box with a text field and a button.
+import React, { useState } from "react";
+import styled from "styled-components";
+import { Button, buttonColor, secondaryDark, vscBackground } from ".";
+
+const DialogContainer = styled.div`
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+`;
+
+const Dialog = styled.div`
+ background-color: white;
+ border-radius: 8px;
+ padding: 8px;
+ display: flex;
+ flex-direction: column;
+ /* box-shadow: 0 0 10px 0 rgba(255, 255, 255, 0.5); */
+ border: 2px solid ${buttonColor};
+ width: fit-content;
+ margin: auto;
+`;
+
+const TextArea = styled.textarea`
+ border: 1px solid #ccc;
+ border-radius: 8px;
+ padding: 8px;
+ outline: 1px solid black;
+ font-family: Arial, Helvetica, sans-serif;
+`;
+
+const P = styled.p`
+ color: black;
+ margin: 8px auto;
+`;
+
+const TextDialog = (props: {
+ showDialog: boolean;
+ onEnter: (text: string) => void;
+}) => {
+ const [text, setText] = useState("");
+ const textAreaRef = React.createRef<HTMLTextAreaElement>();
+
+ return (
+ <DialogContainer hidden={!props.showDialog}>
+ <Dialog>
+ <P>Thanks for your feedback. We'll get back to you soon!</P>
+ <TextArea cols={50} rows={10} ref={textAreaRef}></TextArea>
+ <Button onClick={() => props.onEnter(text)}>Enter</Button>
+ </Dialog>
+ </DialogContainer>
+ );
+};
+
+export default TextDialog;
diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx
index bf6a9401..55c2b763 100644
--- a/extension/react-app/src/tabs/gui.tsx
+++ b/extension/react-app/src/tabs/gui.tsx
@@ -12,8 +12,15 @@ import { History } from "../../../schema/History";
import { HistoryNode } from "../../../schema/HistoryNode";
import StepContainer from "../components/StepContainer";
import useContinueGUIProtocol from "../hooks/useWebsocket";
-import { BookOpen, Trash } from "@styled-icons/heroicons-outline";
+import {
+ BookOpen,
+ ChatBubbleOvalLeft,
+ ChatBubbleOvalLeftEllipsis,
+ Trash,
+} from "@styled-icons/heroicons-outline";
import ComboBox from "../components/ComboBox";
+import TextDialog from "../components/TextDialog";
+
let TopGUIDiv = styled.div`
display: grid;
grid-template-columns: 1fr;
@@ -31,9 +38,11 @@ let UserInputQueueItem = styled.div`
const TopBar = styled.div`
display: flex;
flex-direction: row;
- justify-content: space-between;
+ gap: 8px;
+ justify-content: center;
padding: 8px;
align-items: center;
+ border-bottom: 0.1px solid gray;
`;
interface GUIProps {
@@ -170,6 +179,8 @@ function GUI(props: GUIProps) {
// current_index: 3,
// } as any);
+ const [showFeedbackDialog, setShowFeedbackDialog] = useState(false);
+
const topGuiDivRef = useRef<HTMLDivElement>(null);
const client = useContinueGUIProtocol();
@@ -275,91 +286,110 @@ function GUI(props: GUIProps) {
// const iterations = useSelector(selectIterations);
return (
- <TopGUIDiv
- ref={topGuiDivRef}
- onKeyDown={(e) => {
- if (e.key === "Enter" && e.ctrlKey) {
- onMainTextInput();
- }
- }}
- >
- <TopBar>
- <a href="https://continue.dev/docs" className="no-underline">
- <HeaderButton style={{ padding: "3px" }}>
- Continue Docs
- <BookOpen size="1.6em" />
- </HeaderButton>
- </a>
- <HeaderButton
- onClick={() => {
- client?.sendClear();
- }}
- style={{ padding: "3px" }}
- >
- Clear History
- <Trash size="1.6em" />
- </HeaderButton>
- </TopBar>
-
- {typeof client === "undefined" && (
- <>
- <Loader></Loader>
- <p style={{ textAlign: "center" }}>
- Trying to reconnect with server...
- </p>
- </>
- )}
- {history?.timeline.map((node: HistoryNode, index: number) => {
- return (
- <StepContainer
- key={index}
- onUserInput={(input: string) => {
- onStepUserInput(input, index);
- }}
- inFuture={index > history?.current_index}
- historyNode={node}
- onRefinement={(input: string) => {
- client?.sendRefinementInput(input, index);
- }}
- onReverse={() => {
- client?.reverseToIndex(index);
- }}
- onRetry={() => {
- client?.retryAtIndex(index);
- setWaitingForSteps(true);
+ <>
+ <TextDialog
+ showDialog={showFeedbackDialog}
+ onEnter={(text) => {
+ client?.sendMainInput(`/feedback ${text}`);
+ setShowFeedbackDialog(false);
+ }}
+ ></TextDialog>
+ <TopGUIDiv
+ ref={topGuiDivRef}
+ onKeyDown={(e) => {
+ if (e.key === "Enter" && e.ctrlKey) {
+ onMainTextInput();
+ }
+ }}
+ >
+ <TopBar>
+ <a href="https://continue.dev/docs" className="no-underline">
+ <HeaderButton style={{ padding: "3px" }}>
+ Continue Docs
+ <BookOpen size="1.6em" />
+ </HeaderButton>
+ </a>
+ <HeaderButton
+ style={{ padding: "3px" }}
+ onClick={() => {
+ // Set dialog open
+ setShowFeedbackDialog(true);
}}
- onDelete={() => {
- client?.deleteAtIndex(index);
+ >
+ Feedback
+ <ChatBubbleOvalLeftEllipsis size="1.6em" />
+ </HeaderButton>
+ <HeaderButton
+ onClick={() => {
+ client?.sendClear();
}}
- />
- );
- })}
- {waitingForSteps && <Loader></Loader>}
+ style={{ padding: "3px" }}
+ >
+ Clear History
+ <Trash size="1.6em" />
+ </HeaderButton>
+ </TopBar>
- <div>
- {userInputQueue.map((input) => {
- return <UserInputQueueItem>{input}</UserInputQueueItem>;
+ {typeof client === "undefined" && (
+ <>
+ <Loader></Loader>
+ <p style={{ textAlign: "center" }}>
+ Trying to reconnect with server...
+ </p>
+ </>
+ )}
+ {history?.timeline.map((node: HistoryNode, index: number) => {
+ return (
+ <StepContainer
+ key={index}
+ onUserInput={(input: string) => {
+ onStepUserInput(input, index);
+ }}
+ inFuture={index > history?.current_index}
+ historyNode={node}
+ onRefinement={(input: string) => {
+ client?.sendRefinementInput(input, index);
+ }}
+ onReverse={() => {
+ client?.reverseToIndex(index);
+ }}
+ onRetry={() => {
+ client?.retryAtIndex(index);
+ setWaitingForSteps(true);
+ }}
+ onDelete={() => {
+ client?.deleteAtIndex(index);
+ }}
+ />
+ );
})}
- </div>
+ {waitingForSteps && <Loader></Loader>}
- <ComboBox
- disabled={
- history?.timeline.length
- ? history.timeline[history.current_index].step.name ===
- "Waiting for user confirmation"
- : false
- }
- ref={mainTextInputRef}
- onEnter={(e) => {
- onMainTextInput();
- e.stopPropagation();
- e.preventDefault();
- }}
- onInputValueChange={() => {}}
- items={availableSlashCommands}
- />
- <ContinueButton onClick={onMainTextInput} />
- </TopGUIDiv>
+ <div>
+ {userInputQueue.map((input) => {
+ return <UserInputQueueItem>{input}</UserInputQueueItem>;
+ })}
+ </div>
+
+ <ComboBox
+ disabled={
+ history?.timeline.length
+ ? history.timeline[history.current_index].step.name ===
+ "Waiting for user confirmation"
+ : false
+ }
+ ref={mainTextInputRef}
+ onEnter={(e) => {
+ onMainTextInput();
+ e.stopPropagation();
+ e.preventDefault();
+ }}
+ onInputValueChange={() => {}}
+ items={availableSlashCommands}
+ />
+ <ContinueButton onClick={onMainTextInput} />
+ </TopGUIDiv>
+ </>
);
}