Layout/style tweaks, remove text file prompts, integrate system prompt into database/settings
This commit is contained in:
@@ -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"}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user