From e976d60974a7837967d03807605cbf2e7b4f3f9a Mon Sep 17 00:00:00 2001
From: Nate Sesti <33237525+sestinj@users.noreply.github.com>
Date: Sat, 23 Sep 2023 13:06:00 -0700
Subject: UI Redesign and fixing many details (#496)

* feat: :lipstick: start of major design upgrade

* feat: :lipstick: model selection page

* feat: :lipstick: use shortcut to add highlighted code as ctx

* feat: :lipstick: better display of errors

* feat: :lipstick: ui for learning keyboard shortcuts, more details

* refactor: :construction: testing slash commands ui

* Truncate continue.log

* refactor: :construction: refactoring client_session, ui, more

* feat: :bug: layout fixes

* refactor: :lipstick: ui to enter OpenAI Key

* refactor: :truck: rename MaybeProxyOpenAI -> OpenAIFreeTrial

* starting help center

* removing old shortcut docs

* fix: :bug: fix model setting logic to avoid overwrites

* feat: :lipstick: tutorial and model descriptions

* refactor: :truck: rename unused -> saved

* refactor: :truck: rename model roles

* feat: :lipstick: edit indicator

* refactor: :lipstick: move +, folder icons

* feat: :lipstick: tab to clear all context

* fix: :bug: context providers ui fixes

* fix: :bug: fix lag when stopping step

* fix: :bug: don't override system message for models

* fix: :bug: fix continue button cursor

* feat: :lipstick: title bar

* fix: :bug: updates to code highlighting logic and more

* fix: :bug: fix renaming of summarize model role

* feat: :lipstick: help page and better session title

* feat: :lipstick: more help page / ui improvements

* feat: :lipstick: set session title

* fix: :bug: small fixes for changing sessions

* fix: :bug: perfecting the highlighting code and ctx interactions

* style: :lipstick: sticky headers for scroll, ollama warming

* fix: :bug: fix toggle bug

---------

Co-authored-by: Ty Dunn <ty@tydunn.com>
---
 extension/react-app/src/pages/history.tsx | 172 ++++++++++++++++++------------
 1 file changed, 101 insertions(+), 71 deletions(-)

(limited to 'extension/react-app/src/pages/history.tsx')

diff --git a/extension/react-app/src/pages/history.tsx b/extension/react-app/src/pages/history.tsx
index b901dd55..b6de0520 100644
--- a/extension/react-app/src/pages/history.tsx
+++ b/extension/react-app/src/pages/history.tsx
@@ -1,13 +1,14 @@
 import React, { useContext, useEffect, useState } from "react";
 import { SessionInfo } from "../../../schema/SessionInfo";
 import { GUIClientContext } from "../App";
-import { useSelector } from "react-redux";
+import { useDispatch, useSelector } from "react-redux";
 import { RootStore } from "../redux/store";
 import { useNavigate } from "react-router-dom";
-import { secondaryDark, vscBackground } from "../components";
+import { lightGray, secondaryDark, vscBackground } from "../components";
 import styled from "styled-components";
 import { ArrowLeftIcon } from "@heroicons/react/24/outline";
 import CheckDiv from "../components/CheckDiv";
+import { temporarilyClearSession } from "../redux/slices/serverStateReducer";
 
 const Tr = styled.tr`
   &:hover {
@@ -41,6 +42,7 @@ function lastPartOfPath(path: string): string {
 
 function History() {
   const navigate = useNavigate();
+  const dispatch = useDispatch();
   const [sessions, setSessions] = useState<SessionInfo[]>([]);
   const client = useContext(GUIClientContext);
   const apiUrl = useSelector((state: RootStore) => state.config.apiUrl);
@@ -67,78 +69,106 @@ function History() {
     fetchSessions();
   }, [client]);
 
-  console.log(sessions.map((session) => session.date_created));
-
   return (
-    <div className="w-full">
-      <div className="items-center flex">
-        <ArrowLeftIcon
-          width="1.4em"
-          height="1.4em"
-          onClick={() => navigate("/")}
-          className="inline-block ml-4 cursor-pointer"
-        />
-        <h1 className="text-xl font-bold m-4 inline-block">History</h1>
+    <div className="overflow-y-scroll">
+      <div className="sticky top-0" style={{ backgroundColor: vscBackground }}>
+        <div
+          className="items-center flex m-0 p-0"
+          style={{
+            borderBottom: `0.5px solid ${lightGray}`,
+          }}
+        >
+          <ArrowLeftIcon
+            width="1.2em"
+            height="1.2em"
+            onClick={() => navigate("/")}
+            className="inline-block ml-4 cursor-pointer"
+          />
+          <h3 className="text-lg font-bold m-2 inline-block">History</h3>
+        </div>
+        {workspacePaths && workspacePaths.length > 0 && (
+          <CheckDiv
+            checked={filteringByWorkspace}
+            onClick={() => setFilteringByWorkspace((prev) => !prev)}
+            title={`Show only sessions from ${lastPartOfPath(
+              workspacePaths[workspacePaths.length - 1]
+            )}/`}
+          />
+        )}
       </div>
-      {workspacePaths && workspacePaths.length > 0 && (
-        <CheckDiv
-          checked={filteringByWorkspace}
-          onClick={() => setFilteringByWorkspace((prev) => !prev)}
-          title={`Show only sessions from ${lastPartOfPath(
-            workspacePaths[workspacePaths.length - 1]
-          )}/`}
-        />
+
+      {sessions.filter((session) => {
+        if (
+          !filteringByWorkspace ||
+          typeof workspacePaths === "undefined" ||
+          typeof session.workspace_directory === "undefined"
+        ) {
+          return true;
+        }
+        return workspacePaths.includes(session.workspace_directory);
+      }).length === 0 && (
+        <div className="text-center my-4">
+          No past sessions found. To start a new session, either click the "+"
+          button or use the keyboard shortcut: <b>Option + Command + N</b>
+        </div>
       )}
-      <table className="w-full">
-        <tbody>
-          {sessions
-            .filter((session) => {
-              if (
-                !filteringByWorkspace ||
-                typeof workspacePaths === "undefined" ||
-                typeof session.workspace_directory === "undefined"
-              ) {
-                return true;
-              }
-              return workspacePaths.includes(session.workspace_directory);
-            })
-            .sort(
-              (a, b) =>
-                parseDate(b.date_created).getTime() -
-                parseDate(a.date_created).getTime()
-            )
-            .map((session, index) => (
-              <Tr key={index}>
-                <td>
-                  <TdDiv
-                    onClick={() => {
-                      client?.loadSession(session.session_id);
-                      navigate("/");
-                    }}
-                  >
-                    <div className="text-md">{session.title}</div>
-                    <div className="text-gray-400">
-                      {parseDate(session.date_created).toLocaleString("en-US", {
-                        weekday: "short",
-                        year: "numeric",
-                        month: "long",
-                        day: "numeric",
-                        hour: "numeric",
-                        minute: "numeric",
-                      })}
-                      {" | "}
-                      {lastPartOfPath(session.workspace_directory || "")}/
-                    </div>
-                  </TdDiv>
-                </td>
-              </Tr>
-            ))}
-        </tbody>
-      </table>
-      <br />
-      <i className="text-sm ml-4">
-        All session data is saved in ~/.continue/sessions
-      </i>
+
+      <div>
+        <table className="w-full">
+          <tbody>
+            {sessions
+              .filter((session) => {
+                if (
+                  !filteringByWorkspace ||
+                  typeof workspacePaths === "undefined" ||
+                  typeof session.workspace_directory === "undefined"
+                ) {
+                  return true;
+                }
+                return workspacePaths.includes(session.workspace_directory);
+              })
+              .sort(
+                (a, b) =>
+                  parseDate(b.date_created).getTime() -
+                  parseDate(a.date_created).getTime()
+              )
+              .map((session, index) => (
+                <Tr key={index}>
+                  <td>
+                    <TdDiv
+                      onClick={() => {
+                        client?.loadSession(session.session_id);
+                        dispatch(temporarilyClearSession());
+                        navigate("/");
+                      }}
+                    >
+                      <div className="text-md">{session.title}</div>
+                      <div className="text-gray-400">
+                        {parseDate(session.date_created).toLocaleString(
+                          "en-US",
+                          {
+                            year: "2-digit",
+                            month: "2-digit",
+                            day: "2-digit",
+                            hour: "numeric",
+                            minute: "2-digit",
+                            hour12: true,
+                          }
+                        )}
+                        {" | "}
+                        {lastPartOfPath(session.workspace_directory || "")}/
+                      </div>
+                    </TdDiv>
+                  </td>
+                </Tr>
+              ))}
+          </tbody>
+        </table>
+        <br />
+        <i className="text-sm ml-4">
+          All session data is saved in ~/.continue/sessions
+        </i>
+      </div>
     </div>
   );
 }
-- 
cgit v1.2.3-70-g09d2

