Layout/style tweaks, remove text file prompts, integrate system prompt into database/settings

This commit is contained in:
2025-03-24 12:26:21 -04:00
parent dd4b3f7145
commit 228ae8b2a9
7 changed files with 232 additions and 315 deletions

View File

@@ -252,39 +252,26 @@ export const AiValidationDialogs: React.FC<AiValidationDialogsProps> = ({
{/* Prompt Sources Section */}
{currentPrompt.debugData?.promptSources && (
<Card className="mb-4">
<Card className="py-2">
<CardHeader className="py-2">
<CardTitle className="text-base">
Prompt Sources
{hasCompanyPrompts && (
<Badge className="ml-2 bg-blue-500" variant="secondary">
{currentPrompt.debugData.promptSources.companyPrompts?.length} Company-Specific
</Badge>
)}
</CardTitle>
</CardHeader>
<CardContent className="py-2">
<div className="text-sm">
<p className="mb-2">
<Badge variant="outline" className="mr-2">
General
</Badge>
Base prompt for all products
</p>
<div className="flex flex-wrap gap-2">
<Badge variant="outline" className="bg-purple-50">
System
</Badge>
<Badge variant="outline" className="bg-green-50">
General
</Badge>
{hasCompanyPrompts && (
<div className="mt-2">
<p className="font-medium mb-1">Company Specific:</p>
<ul className="list-disc pl-5 space-y-1">
{currentPrompt.debugData.promptSources.companyPrompts?.map((prompt, idx) => (
<li key={idx}>
<span className="font-semibold">{prompt.companyName}</span>
<span className="text-xs text-muted-foreground ml-1">(ID: {prompt.company})</span>
</li>
))}
</ul>
</div>
)}
{currentPrompt.debugData.promptSources.companyPrompts?.map((prompt, idx) => (
<Badge key={idx} variant="outline" className="bg-blue-50">
{prompt.companyName}
</Badge>
))}
</div>
</CardContent>
</Card>
@@ -306,10 +293,11 @@ export const AiValidationDialogs: React.FC<AiValidationDialogsProps> = ({
defaultValue="full"
value={activeTab}
onValueChange={setActiveTab}
className="w-full h-full flex flex-col"
className="h-full flex flex-col"
>
<TabsList className="mb-2 flex-shrink-0">
<TabsList className="mb-2 w-fit">
<TabsTrigger value="full">Full Prompt</TabsTrigger>
<TabsTrigger value="system">System</TabsTrigger>
<TabsTrigger value="general">General Prompt</TabsTrigger>
{hasCompanyPrompts && (
<TabsTrigger value="company">Company Prompts</TabsTrigger>
@@ -324,6 +312,12 @@ export const AiValidationDialogs: React.FC<AiValidationDialogsProps> = ({
</Code>
</TabsContent>
<TabsContent value="system" className="m-0 p-0 h-full">
<Code className="whitespace-pre-wrap p-4 break-normal max-w-full">
{currentPrompt.debugData.promptSources.systemPrompt?.prompt_text || "No system prompt available"}
</Code>
</TabsContent>
<TabsContent value="general" className="m-0 p-0 h-full">
<Code className="whitespace-pre-wrap p-4 break-normal max-w-full">
{currentPrompt.debugData.promptSources.generalPrompt?.prompt_text || "No general prompt available"}

View File

@@ -57,6 +57,7 @@ export interface CurrentPrompt {
sampleFullPrompt: string;
promptLength: number;
promptSources?: {
systemPrompt?: { id: number; prompt_text: string };
generalPrompt?: { id: number; prompt_text: string };
companyPrompts?: Array<{
id: number;

View File

@@ -30,16 +30,7 @@ import {
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import {
AlertDialog,
AlertDialogAction,
@@ -60,14 +51,14 @@ interface FieldOption {
interface PromptFormData {
id?: number;
prompt_text: string;
prompt_type: 'general' | 'company_specific';
prompt_type: 'general' | 'company_specific' | 'system';
company: string | null;
}
interface AiPrompt {
id: number;
prompt_text: string;
prompt_type: 'general' | 'company_specific';
prompt_type: 'general' | 'company_specific' | 'system';
company: string | null;
created_at: string;
updated_at: string;
@@ -82,7 +73,10 @@ export function PromptManagement() {
const [isDeleteOpen, setIsDeleteOpen] = useState(false);
const [promptToDelete, setPromptToDelete] = useState<AiPrompt | null>(null);
const [editingPrompt, setEditingPrompt] = useState<AiPrompt | null>(null);
const [sorting, setSorting] = useState<SortingState>([]);
const [sorting, setSorting] = useState<SortingState>([
{ id: "prompt_type", desc: true },
{ id: "company", desc: false }
]);
const [searchQuery, setSearchQuery] = useState("");
const [formData, setFormData] = useState<PromptFormData>({
prompt_text: "",
@@ -114,10 +108,14 @@ export function PromptManagement() {
},
});
// Check if a general prompt already exists
// Check if general and system prompts already exist
const generalPromptExists = useMemo(() => {
return prompts?.some(prompt => prompt.prompt_type === 'general');
}, [prompts]);
const systemPromptExists = useMemo(() => {
return prompts?.some(prompt => prompt.prompt_type === 'system');
}, [prompts]);
const createMutation = useMutation({
mutationFn: async (data: PromptFormData) => {
@@ -220,10 +218,10 @@ export function PromptManagement() {
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
// If prompt_type is general, ensure company is null
// If prompt_type is general or system, ensure company is null
const submitData = {
...formData,
company: formData.prompt_type === 'general' ? null : formData.company,
company: formData.prompt_type === 'company_specific' ? formData.company : null,
};
if (editingPrompt) {
@@ -246,12 +244,24 @@ export function PromptManagement() {
const handleCreateClick = () => {
resetForm();
// If general prompt exists, default to company-specific
if (generalPromptExists) {
// If general prompt and system prompt exist, default to company-specific
if (generalPromptExists && systemPromptExists) {
setFormData(prev => ({
...prev,
prompt_type: 'company_specific'
}));
} else if (generalPromptExists && !systemPromptExists) {
// If general exists but system doesn't, suggest system prompt
setFormData(prev => ({
...prev,
prompt_type: 'system'
}));
} else if (!generalPromptExists) {
// If no general prompt, suggest that first
setFormData(prev => ({
...prev,
prompt_type: 'general'
}));
}
setIsFormOpen(true);
@@ -271,7 +281,26 @@ export function PromptManagement() {
),
cell: ({ row }) => {
const type = row.getValue("prompt_type") as string;
return type === 'general' ? 'General' : 'Company Specific';
if (type === 'general') return 'General';
if (type === 'system') return 'System';
return 'Company Specific';
},
},
{
accessorFn: (row) => row.prompt_text.length,
id: "length",
header: ({ column }) => (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Length
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
),
cell: ({ getValue }) => {
const length = getValue() as number;
return <span>{length.toLocaleString()}</span>;
},
},
{
@@ -431,24 +460,44 @@ export function PromptManagement() {
<Label htmlFor="prompt_type">Prompt Type</Label>
<Select
value={formData.prompt_type}
onValueChange={(value: 'general' | 'company_specific') =>
onValueChange={(value: 'general' | 'company_specific' | 'system') =>
setFormData({ ...formData, prompt_type: value })
}
disabled={generalPromptExists && formData.prompt_type !== 'general' && !editingPrompt?.id}
disabled={(generalPromptExists && formData.prompt_type !== 'general' && !editingPrompt?.id) ||
(systemPromptExists && formData.prompt_type !== 'system' && !editingPrompt?.id)}
>
<SelectTrigger>
<SelectValue placeholder="Select prompt type" />
</SelectTrigger>
<SelectContent>
<SelectItem value="general" disabled={generalPromptExists && !editingPrompt?.prompt_type?.includes('general')}>
<SelectItem
value="general"
disabled={generalPromptExists && !editingPrompt?.prompt_type?.includes('general')}
>
General
</SelectItem>
<SelectItem
value="system"
disabled={systemPromptExists && !editingPrompt?.prompt_type?.includes('system')}
>
System
</SelectItem>
<SelectItem value="company_specific">Company Specific</SelectItem>
</SelectContent>
</Select>
{generalPromptExists && formData.prompt_type !== 'general' && !editingPrompt?.id && (
{generalPromptExists && formData.prompt_type !== 'general' && !editingPrompt?.id && systemPromptExists && formData.prompt_type !== 'system' && (
<p className="text-xs text-muted-foreground">
A general prompt already exists. You can only create company-specific prompts.
General and system prompts already exist. You can only create company-specific prompts.
</p>
)}
{generalPromptExists && !systemPromptExists && formData.prompt_type !== 'general' && !editingPrompt?.id && (
<p className="text-xs text-muted-foreground">
A general prompt already exists. You can create a system prompt or company-specific prompts.
</p>
)}
{systemPromptExists && !generalPromptExists && formData.prompt_type !== 'system' && !editingPrompt?.id && (
<p className="text-xs text-muted-foreground">
A system prompt already exists. You can create a general prompt or company-specific prompts.
</p>
)}
</div>
@@ -481,10 +530,15 @@ export function PromptManagement() {
id="prompt_text"
value={formData.prompt_text}
onChange={(e) => setFormData({ ...formData, prompt_text: e.target.value })}
placeholder="Enter your validation prompt text..."
placeholder={`Enter your ${formData.prompt_type === 'system' ? 'system instructions' : 'validation prompt'} text...`}
className="h-80 font-mono text-sm"
required
/>
{formData.prompt_type === 'system' && (
<p className="text-xs text-muted-foreground mt-1">
System prompts provide the initial instructions to the AI. This sets the tone and approach for all validations.
</p>
)}
</div>
</div>