* Refactor workspace sidebar component styles (#2380) rely on css for conditional styles * New sidebar colors (#2381) new sidebar colors * Main container color update (#2382) * Dark mode setup themes (#2411) * setup generic tailwind theme + ability to add new themes * add theme context * use correct colors from design for sidebar + fix padding * Settings sidebar UI updates (#2416) settings sidebar ui updates * fix sidebar resizing/truncate issue on hover * Dark mode chat window (#2443) * Support XLSX files (#2403) * support xlsx files * lint * create seperate docs for each xlsx sheet * lint * use node-xlsx pkg for parsing xslx files * lint * update error handling --------- Co-authored-by: timothycarambat <rambat1010@gmail.com> * wip chat window * ux+ux improvements and update new colors * chat window dark mode * remove comment --------- Co-authored-by: timothycarambat <rambat1010@gmail.com> * Dark mode welcome page (#2444) * dark mode welcome page styles + refactor * remove AI_BACKGROUND_COLOR and USER_BACKGROUND_COLOR constants * Dark mode UI for admin and tools pages + mobile view improvements (#2454) * dark mode ui for admin and tools pages + mobile view improvements * lint * ai provider pages + options darkmode ui * placeholder generic class * appearance settings styles * ai providers mobile margin * dark mode styles for agent skills + experimental features * mobile styles on security settings * fine tune flow ui dark mode * workspace settings page * lint * Dark mode onboarding (#2461) dark mode onboarding * update all modals + normalize styles (#2471) * lint * Dark mode privacy & experimental pages (#2479) * document watch + privacy pages ui + mobile modal darkmode * lint * Dark mode login screens (#2483) * multi-user auth screen ui update * dark mode login screen + recovery key modals * remove unneeded import * Workspace preset commands modals dark mode (#2484) update workspace preset dark mode modal * Document pinning modal ui update (#2490) document pinning modal ui update * Experimental agreement modal dark mode (#2491) experimental agreement modal dark mode * Serp options dark mode (#2492) serp options dark mode * field fixes * attempt light mode wip * setting sidebar * Toasts and threads * main page content and privacy page * force rewrite for light * add border for light mode rightside content * more fixes * wip * wip * wip light mode implementation * wip dark light mode file picker * document picker light mode ui * slight ui tweaks * light mode fine tuning flow * light mode tweaks + qa fixes * fix md rendering of light mode + tooltip fixes * lint * qa bug fixes * Add developer hook for theme move provider to outmost layer * qa light mode bug fixes * Linting and hotfixes for UI * Light mode to dev * accept invite light mode ui fix * Fix onboarding inputs in dark mode * fix close icons last minute items * patch z-index on tooltips * patch light mode citations --------- Co-authored-by: timothycarambat <rambat1010@gmail.com>
107 lines
3.6 KiB
JavaScript
107 lines
3.6 KiB
JavaScript
import React, { useEffect, useState } from "react";
|
|
import Workspace from "@/models/workspace";
|
|
import LoadingChat from "./LoadingChat";
|
|
import ChatContainer from "./ChatContainer";
|
|
import paths from "@/utils/paths";
|
|
import ModalWrapper from "../ModalWrapper";
|
|
import { useParams } from "react-router-dom";
|
|
import { DnDFileUploaderProvider } from "./ChatContainer/DnDWrapper";
|
|
|
|
export default function WorkspaceChat({ loading, workspace }) {
|
|
const { threadSlug = null } = useParams();
|
|
const [history, setHistory] = useState([]);
|
|
const [loadingHistory, setLoadingHistory] = useState(true);
|
|
|
|
useEffect(() => {
|
|
async function getHistory() {
|
|
if (loading) return;
|
|
if (!workspace?.slug) {
|
|
setLoadingHistory(false);
|
|
return false;
|
|
}
|
|
|
|
const chatHistory = threadSlug
|
|
? await Workspace.threads.chatHistory(workspace.slug, threadSlug)
|
|
: await Workspace.chatHistory(workspace.slug);
|
|
|
|
setHistory(chatHistory);
|
|
setLoadingHistory(false);
|
|
}
|
|
getHistory();
|
|
}, [workspace, loading]);
|
|
|
|
if (loadingHistory) return <LoadingChat />;
|
|
if (!loading && !loadingHistory && !workspace) {
|
|
return (
|
|
<>
|
|
{loading === false && !workspace && (
|
|
<ModalWrapper isOpen={true}>
|
|
<div className="relative w-full max-w-2xl bg-theme-bg-secondary rounded-lg shadow border-2 border-theme-modal-border">
|
|
<div className="flex flex-col gap-y-4 w-full p-6 text-center">
|
|
<p className="font-semibold text-red-500 text-xl">
|
|
Workspace not found!
|
|
</p>
|
|
<p className="text-sm mt-4 text-white">
|
|
It looks like a workspace by this name is not available.
|
|
</p>
|
|
|
|
<div className="flex w-full justify-center items-center mt-4">
|
|
<a
|
|
href={paths.home()}
|
|
className="transition-all duration-300 bg-white text-black hover:opacity-60 px-4 py-2 rounded-lg text-sm flex items-center gap-x-2"
|
|
>
|
|
Go back to homepage
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</ModalWrapper>
|
|
)}
|
|
<LoadingChat />
|
|
</>
|
|
);
|
|
}
|
|
|
|
setEventDelegatorForCodeSnippets();
|
|
return (
|
|
<DnDFileUploaderProvider workspace={workspace}>
|
|
<ChatContainer workspace={workspace} knownHistory={history} />
|
|
</DnDFileUploaderProvider>
|
|
);
|
|
}
|
|
|
|
// Enables us to safely markdown and sanitize all responses without risk of injection
|
|
// but still be able to attach a handler to copy code snippets on all elements
|
|
// that are code snippets.
|
|
function copyCodeSnippet(uuid) {
|
|
const target = document.querySelector(`[data-code="${uuid}"]`);
|
|
if (!target) return false;
|
|
const markdown =
|
|
target.parentElement?.parentElement?.querySelector(
|
|
"pre:first-of-type"
|
|
)?.innerText;
|
|
if (!markdown) return false;
|
|
|
|
window.navigator.clipboard.writeText(markdown);
|
|
target.classList.add("text-green-500");
|
|
const originalText = target.innerHTML;
|
|
target.innerText = "Copied!";
|
|
target.setAttribute("disabled", true);
|
|
|
|
setTimeout(() => {
|
|
target.classList.remove("text-green-500");
|
|
target.innerHTML = originalText;
|
|
target.removeAttribute("disabled");
|
|
}, 2500);
|
|
}
|
|
|
|
// Listens and hunts for all data-code-snippet clicks.
|
|
function setEventDelegatorForCodeSnippets() {
|
|
document?.addEventListener("click", function (e) {
|
|
const target = e.target.closest("[data-code-snippet]");
|
|
const uuidCode = target?.dataset?.code;
|
|
if (!uuidCode) return false;
|
|
copyCodeSnippet(uuidCode);
|
|
});
|
|
}
|