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/components/ModelCard.tsx | 122 +++++++++++++++++++++++
 1 file changed, 122 insertions(+)
 create mode 100644 extension/react-app/src/components/ModelCard.tsx

(limited to 'extension/react-app/src/components/ModelCard.tsx')

diff --git a/extension/react-app/src/components/ModelCard.tsx b/extension/react-app/src/components/ModelCard.tsx
new file mode 100644
index 00000000..a537c5f4
--- /dev/null
+++ b/extension/react-app/src/components/ModelCard.tsx
@@ -0,0 +1,122 @@
+import React, { useContext } from "react";
+import styled from "styled-components";
+import { buttonColor, defaultBorderRadius, lightGray, vscForeground } from ".";
+import { setShowDialog } from "../redux/slices/uiStateSlice";
+import { GUIClientContext } from "../App";
+import { useDispatch, useSelector } from "react-redux";
+import { useNavigate } from "react-router-dom";
+import { RootStore } from "../redux/store";
+import { BookOpenIcon } from "@heroicons/react/24/outline";
+import HeaderButtonWithText from "./HeaderButtonWithText";
+import ReactDOM from "react-dom";
+
+export enum ModelTag {
+  "Requires API Key" = "Requires API Key",
+  "Local" = "Local",
+  "Free" = "Free",
+  "Open-Source" = "Open-Source",
+}
+
+const MODEL_TAG_COLORS: any = {};
+MODEL_TAG_COLORS[ModelTag["Requires API Key"]] = "#FF0000";
+MODEL_TAG_COLORS[ModelTag["Local"]] = "#00bb00";
+MODEL_TAG_COLORS[ModelTag["Open-Source"]] = "#0033FF";
+MODEL_TAG_COLORS[ModelTag["Free"]] = "#ffff00";
+
+export interface ModelInfo {
+  title: string;
+  class: string;
+  args: any;
+  description: string;
+  icon?: string;
+  tags?: ModelTag[];
+}
+
+const Div = styled.div<{ color: string }>`
+  border: 1px solid ${lightGray};
+  border-radius: ${defaultBorderRadius};
+  cursor: pointer;
+  padding: 4px 8px;
+  position: relative;
+  width: 100%;
+  transition: all 0.5s;
+
+  &:hover {
+    border: 1px solid ${(props) => props.color};
+    background-color: ${(props) => props.color}22;
+  }
+`;
+
+interface ModelCardProps {
+  modelInfo: ModelInfo;
+}
+
+function ModelCard(props: ModelCardProps) {
+  const client = useContext(GUIClientContext);
+  const dispatch = useDispatch();
+  const navigate = useNavigate();
+  const vscMediaUrl = useSelector(
+    (state: RootStore) => state.config.vscMediaUrl
+  );
+
+  return (
+    <Div
+      color={buttonColor}
+      onClick={(e) => {
+        if ((e.target as any).closest("a")) {
+          return;
+        }
+        client?.addModelForRole(
+          "*",
+          props.modelInfo.class,
+          props.modelInfo.args
+        );
+        dispatch(setShowDialog(false));
+        navigate("/");
+      }}
+    >
+      <div style={{ display: "flex", alignItems: "center" }}>
+        {vscMediaUrl && (
+          <img
+            src={`${vscMediaUrl}/logos/${props.modelInfo.icon}`}
+            height="24px"
+            style={{ marginRight: "10px" }}
+          />
+        )}
+        <h3>{props.modelInfo.title}</h3>
+      </div>
+      {props.modelInfo.tags?.map((tag) => {
+        return (
+          <span
+            style={{
+              backgroundColor: `${MODEL_TAG_COLORS[tag]}55`,
+              color: "white",
+              padding: "2px 4px",
+              borderRadius: defaultBorderRadius,
+              marginRight: "4px",
+            }}
+          >
+            {tag}
+          </span>
+        );
+      })}
+      <p>{props.modelInfo.description}</p>
+
+      <a
+        style={{
+          position: "absolute",
+          right: "8px",
+          top: "8px",
+        }}
+        href={`https://continue.dev/docs/reference/Models/${props.modelInfo.class.toLowerCase()}`}
+        target="_blank"
+      >
+        <HeaderButtonWithText text="Read the docs">
+          <BookOpenIcon width="1.6em" height="1.6em" />
+        </HeaderButtonWithText>
+      </a>
+    </Div>
+  );
+}
+
+export default ModelCard;
-- 
cgit v1.2.3-70-g09d2

