mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-05-31 19:15:17 +02:00
Add feature flags for use multiple projects and display project page accordingly
Update project new page style
This commit is contained in:
parent
50ac0ebec7
commit
01f16a11d3
4 changed files with 143 additions and 102 deletions
|
|
@ -3,3 +3,9 @@ export const USE_RAG_UPLOADS = process.env.USE_RAG_UPLOADS === 'true';
|
||||||
export const USE_RAG_SCRAPING = process.env.USE_RAG_SCRAPING === 'true';
|
export const USE_RAG_SCRAPING = process.env.USE_RAG_SCRAPING === 'true';
|
||||||
export const USE_CHAT_WIDGET = process.env.USE_CHAT_WIDGET === 'true';
|
export const USE_CHAT_WIDGET = process.env.USE_CHAT_WIDGET === 'true';
|
||||||
export const USE_AUTH = process.env.USE_AUTH === 'true';
|
export const USE_AUTH = process.env.USE_AUTH === 'true';
|
||||||
|
|
||||||
|
// export const USE_MULTIPLE_PROJECTS = true;
|
||||||
|
export const USE_MULTIPLE_PROJECTS = false;
|
||||||
|
|
||||||
|
export const USE_TESTING_FEATURE = false;
|
||||||
|
export const USE_VOICE_FEATURE = false;
|
||||||
|
|
@ -11,6 +11,7 @@ import { TestProfile } from "@/app/lib/types/testing_types";
|
||||||
import { WithStringId } from "@/app/lib/types/types";
|
import { WithStringId } from "@/app/lib/types/types";
|
||||||
import { ProfileSelector } from "@/app/projects/[projectId]/test/[[...slug]]/components/selectors/profile-selector";
|
import { ProfileSelector } from "@/app/projects/[projectId]/test/[[...slug]]/components/selectors/profile-selector";
|
||||||
import { CheckIcon, CopyIcon, PlusIcon, UserIcon } from "lucide-react";
|
import { CheckIcon, CopyIcon, PlusIcon, UserIcon } from "lucide-react";
|
||||||
|
import { USE_TESTING_FEATURE } from "@/app/lib/feature_flags";
|
||||||
|
|
||||||
const defaultSystemMessage = '';
|
const defaultSystemMessage = '';
|
||||||
|
|
||||||
|
|
@ -103,6 +104,7 @@ export function App({
|
||||||
}
|
}
|
||||||
rightActions={
|
rightActions={
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
|
{USE_TESTING_FEATURE && (
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
|
@ -112,6 +114,7 @@ export function App({
|
||||||
>
|
>
|
||||||
<UserIcon className="w-4 h-4" />
|
<UserIcon className="w-4 h-4" />
|
||||||
</Button>
|
</Button>
|
||||||
|
)}
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
|
@ -128,6 +131,7 @@ export function App({
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
{USE_TESTING_FEATURE && (
|
||||||
<ProfileSelector
|
<ProfileSelector
|
||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
isOpen={isProfileSelectorOpen}
|
isOpen={isProfileSelectorOpen}
|
||||||
|
|
@ -135,6 +139,7 @@ export function App({
|
||||||
onSelect={handleTestProfileChange}
|
onSelect={handleTestProfileChange}
|
||||||
selectedProfileId={testProfile?._id}
|
selectedProfileId={testProfile?._id}
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
<div className="h-full overflow-auto px-4 py-4">
|
<div className="h-full overflow-auto px-4 py-4">
|
||||||
<Chat
|
<Chat
|
||||||
key={`chat-${counter}`}
|
key={`chat-${counter}`}
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,18 @@ import { SearchProjects } from "./components/search-projects";
|
||||||
import { CustomPromptCard } from "./components/custom-prompt-card";
|
import { CustomPromptCard } from "./components/custom-prompt-card";
|
||||||
import { Submit } from "./components/submit-button";
|
import { Submit } from "./components/submit-button";
|
||||||
import { PageHeading } from "@/components/ui/page-heading";
|
import { PageHeading } from "@/components/ui/page-heading";
|
||||||
|
import { USE_MULTIPLE_PROJECTS } from "@/app/lib/feature_flags";
|
||||||
|
|
||||||
const sectionHeaderStyles = clsx(
|
const sectionHeaderStyles = clsx(
|
||||||
"text-sm font-medium",
|
"text-sm font-medium",
|
||||||
"text-gray-900 dark:text-gray-100"
|
"text-gray-900 dark:text-gray-100"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const largeSectionHeaderStyles = clsx(
|
||||||
|
"text-lg font-medium",
|
||||||
|
"text-gray-900 dark:text-gray-100"
|
||||||
|
);
|
||||||
|
|
||||||
const textareaStyles = clsx(
|
const textareaStyles = clsx(
|
||||||
"w-full",
|
"w-full",
|
||||||
"rounded-lg p-3",
|
"rounded-lg p-3",
|
||||||
|
|
@ -34,12 +41,12 @@ export default function App() {
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
|
||||||
const [selectedCard, setSelectedCard] = useState<'custom' | any>('custom');
|
const [selectedCard, setSelectedCard] = useState<'custom' | any>('custom');
|
||||||
const [customPrompt, setCustomPrompt] = useState("Create a customer support assistant with one example agent");
|
const [customPrompt, setCustomPrompt] = useState("");
|
||||||
const [name, setName] = useState("");
|
const [name, setName] = useState("");
|
||||||
const [defaultName, setDefaultName] = useState('Assistant 1');
|
const [defaultName, setDefaultName] = useState('Assistant 1');
|
||||||
const [isExamplesExpanded, setIsExamplesExpanded] = useState(false);
|
const [isExamplesExpanded, setIsExamplesExpanded] = useState(false);
|
||||||
const [selectedTemplate, setSelectedTemplate] = useState<string>('blank');
|
const [selectedTemplate, setSelectedTemplate] = useState<string>('custom');
|
||||||
const [showCustomPrompt, setShowCustomPrompt] = useState(false);
|
const [showCustomPrompt, setShowCustomPrompt] = useState(true);
|
||||||
const [promptError, setPromptError] = useState<string | null>(null);
|
const [promptError, setPromptError] = useState<string | null>(null);
|
||||||
const [hasEditedPrompt, setHasEditedPrompt] = useState(false);
|
const [hasEditedPrompt, setHasEditedPrompt] = useState(false);
|
||||||
|
|
||||||
|
|
@ -88,7 +95,7 @@ export default function App() {
|
||||||
setSelectedCard(card);
|
setSelectedCard(card);
|
||||||
|
|
||||||
if (card === 'custom') {
|
if (card === 'custom') {
|
||||||
setCustomPrompt("Create a customer support assistant with one example agent");
|
setCustomPrompt("");
|
||||||
} else {
|
} else {
|
||||||
setCustomPrompt(card.prompt || card.description);
|
setCustomPrompt(card.prompt || card.description);
|
||||||
}
|
}
|
||||||
|
|
@ -178,12 +185,20 @@ export default function App() {
|
||||||
"flex-1 px-12 pt-4 pb-32"
|
"flex-1 px-12 pt-4 pb-32"
|
||||||
)}>
|
)}>
|
||||||
<PageHeading
|
<PageHeading
|
||||||
title="Projects"
|
title={USE_MULTIPLE_PROJECTS ? "Projects" : "Let's get started"}
|
||||||
description="Select an existing project or create a new one"
|
description={USE_MULTIPLE_PROJECTS
|
||||||
|
? "Select an existing project or create a new one"
|
||||||
|
: "Create a multi-agent assistant in minutes"
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-[1fr,2fr] gap-8 mt-8">
|
<div className={clsx(
|
||||||
|
USE_MULTIPLE_PROJECTS
|
||||||
|
? "grid grid-cols-1 lg:grid-cols-[1fr,2fr] gap-8 mt-8"
|
||||||
|
: "mt-8 -mx-12"
|
||||||
|
)}>
|
||||||
{/* Left side: Project Selection */}
|
{/* Left side: Project Selection */}
|
||||||
|
{USE_MULTIPLE_PROJECTS && (
|
||||||
<div className="overflow-auto">
|
<div className="overflow-auto">
|
||||||
<SearchProjects
|
<SearchProjects
|
||||||
projects={projects}
|
projects={projects}
|
||||||
|
|
@ -193,26 +208,37 @@ export default function App() {
|
||||||
className="h-full"
|
className="h-full"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Right side: Project Creation */}
|
{/* Right side: Project Creation */}
|
||||||
<div className="overflow-auto">
|
<div className={clsx(
|
||||||
<section className="card h-full">
|
"overflow-auto",
|
||||||
<div className="px-4 pt-4">
|
!USE_MULTIPLE_PROJECTS && "max-w-none px-12 py-12"
|
||||||
|
)}>
|
||||||
|
<section className={clsx(
|
||||||
|
"card h-full",
|
||||||
|
!USE_MULTIPLE_PROJECTS && "px-24",
|
||||||
|
USE_MULTIPLE_PROJECTS && "px-8"
|
||||||
|
)}>
|
||||||
|
{USE_MULTIPLE_PROJECTS && (
|
||||||
|
<div className="pt-12">
|
||||||
<SectionHeading subheading="Set up a new AI assistant">
|
<SectionHeading subheading="Set up a new AI assistant">
|
||||||
Create a new project
|
Create a new project
|
||||||
</SectionHeading>
|
</SectionHeading>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<form
|
<form
|
||||||
id="create-project-form"
|
id="create-project-form"
|
||||||
action={handleSubmit}
|
action={handleSubmit}
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
className="px-4 pt-4 pb-8 space-y-8"
|
className="pt-12 pb-16 space-y-12"
|
||||||
>
|
>
|
||||||
{/* Name Section */}
|
{/* Name Section */}
|
||||||
|
{USE_MULTIPLE_PROJECTS && (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-4">
|
||||||
<label className={sectionHeaderStyles}>
|
<label className={largeSectionHeaderStyles}>
|
||||||
Name
|
Name
|
||||||
</label>
|
</label>
|
||||||
<Textarea
|
<Textarea
|
||||||
|
|
@ -230,12 +256,50 @@ export default function App() {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Custom Prompt Section - Only show when needed */}
|
||||||
|
{showCustomPrompt && (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<label className={largeSectionHeaderStyles}>
|
||||||
|
{selectedTemplate === 'custom' ? 'What do you want to build?' : 'Customize the description'}
|
||||||
|
</label>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Textarea
|
||||||
|
value={customPrompt}
|
||||||
|
onChange={(e) => {
|
||||||
|
setCustomPrompt(e.target.value);
|
||||||
|
setPromptError(null);
|
||||||
|
}}
|
||||||
|
placeholder="Example: Create a customer support assistant that can handle product inquiries and returns"
|
||||||
|
className={clsx(
|
||||||
|
textareaStyles,
|
||||||
|
"text-base",
|
||||||
|
"text-gray-900 dark:text-gray-100",
|
||||||
|
promptError && "border-red-500 focus:ring-red-500/20"
|
||||||
|
)}
|
||||||
|
style={{ minHeight: "120px" }}
|
||||||
|
autoFocus
|
||||||
|
autoResize
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
{promptError && (
|
||||||
|
<p className="text-sm text-red-500">
|
||||||
|
{promptError}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
|
||||||
{/* Template Selection Section */}
|
{/* Template Selection Section */}
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-4">
|
||||||
<label className={sectionHeaderStyles}>
|
<label className={largeSectionHeaderStyles}>
|
||||||
Choose how to start
|
How do you want to start?
|
||||||
</label>
|
</label>
|
||||||
<select
|
<select
|
||||||
value={selectedTemplate}
|
value={selectedTemplate}
|
||||||
|
|
@ -259,9 +323,9 @@ export default function App() {
|
||||||
"dark:bg-[url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23ffffff%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E')]"
|
"dark:bg-[url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23ffffff%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E')]"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<option value="blank">Start with a blank template</option>
|
<option value="custom">Tell us what you want to build</option>
|
||||||
<option value="custom">Write your own starting prompt</option>
|
<option value="blank">I'll provide a description later</option>
|
||||||
<optgroup label="Example Prompts">
|
<optgroup label="Customizable Examples">
|
||||||
{starting_copilot_prompts &&
|
{starting_copilot_prompts &&
|
||||||
Object.entries(starting_copilot_prompts)
|
Object.entries(starting_copilot_prompts)
|
||||||
.filter(([name]) => name !== 'Blank Template')
|
.filter(([name]) => name !== 'Blank Template')
|
||||||
|
|
@ -276,40 +340,6 @@ export default function App() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Custom Prompt Section - Only show when needed */}
|
|
||||||
{showCustomPrompt && (
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div className="flex flex-col gap-2">
|
|
||||||
<label className={sectionHeaderStyles}>
|
|
||||||
{selectedTemplate === 'custom' ? 'Write your prompt' : 'Customize the prompt'}
|
|
||||||
</label>
|
|
||||||
<div className="space-y-2">
|
|
||||||
<Textarea
|
|
||||||
value={customPrompt}
|
|
||||||
onChange={(e) => {
|
|
||||||
setCustomPrompt(e.target.value);
|
|
||||||
setPromptError(null);
|
|
||||||
}}
|
|
||||||
placeholder="Example: Create a customer support assistant that can handle product inquiries and returns"
|
|
||||||
className={clsx(
|
|
||||||
textareaStyles,
|
|
||||||
"min-h-[100px]",
|
|
||||||
"text-base",
|
|
||||||
"text-gray-900 dark:text-gray-100",
|
|
||||||
promptError && "border-red-500 focus:ring-red-500/20"
|
|
||||||
)}
|
|
||||||
autoResize
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
{promptError && (
|
|
||||||
<p className="text-sm text-red-500">
|
|
||||||
{promptError}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Submit Button */}
|
{/* Submit Button */}
|
||||||
<div className="pt-6 w-full">
|
<div className="pt-6 w-full">
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ export function Submit() {
|
||||||
isLoading={pending}
|
isLoading={pending}
|
||||||
startContent={<PlusIcon size={16} />}
|
startContent={<PlusIcon size={16} />}
|
||||||
>
|
>
|
||||||
Create project
|
Create assistant
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue