mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-02-26 04:14:10 +01:00
90 lines
3.2 KiB
TypeScript
90 lines
3.2 KiB
TypeScript
|
|
import React from 'react';
|
||
|
|
import { format } from 'date-fns';
|
||
|
|
import { Layers3 } from 'lucide-react';
|
||
|
|
import type { TPrompt, TPromptGroup } from 'librechat-data-provider';
|
||
|
|
import { useLocalize } from '~/hooks';
|
||
|
|
import { Tag } from '~/components/ui';
|
||
|
|
import { cn } from '~/utils';
|
||
|
|
|
||
|
|
const PromptVersions = ({
|
||
|
|
prompts,
|
||
|
|
group,
|
||
|
|
selectionIndex,
|
||
|
|
setSelectionIndex,
|
||
|
|
}: {
|
||
|
|
prompts: TPrompt[];
|
||
|
|
group?: TPromptGroup;
|
||
|
|
selectionIndex: React.SetStateAction<number>;
|
||
|
|
setSelectionIndex: React.Dispatch<React.SetStateAction<number>>;
|
||
|
|
}) => {
|
||
|
|
const localize = useLocalize();
|
||
|
|
return (
|
||
|
|
<>
|
||
|
|
<h2 className="mb-4 flex gap-2 text-base font-semibold dark:text-gray-200">
|
||
|
|
<Layers3 className="icon-lg text-green-500" />
|
||
|
|
{localize('com_ui_versions')}
|
||
|
|
</h2>
|
||
|
|
<ul className="flex flex-col gap-3">
|
||
|
|
{prompts.map((prompt: TPrompt, index: number) => {
|
||
|
|
const tags: string[] = [];
|
||
|
|
if (index === 0) {
|
||
|
|
tags.push('latest');
|
||
|
|
}
|
||
|
|
|
||
|
|
if (prompt._id === group?.productionId) {
|
||
|
|
tags.push('production');
|
||
|
|
}
|
||
|
|
|
||
|
|
return (
|
||
|
|
<li
|
||
|
|
key={index}
|
||
|
|
className={cn(
|
||
|
|
'relative cursor-pointer rounded-lg border p-4 dark:border-gray-600 dark:bg-transparent',
|
||
|
|
index === selectionIndex ? 'bg-gray-100 dark:bg-gray-700' : 'bg-white',
|
||
|
|
)}
|
||
|
|
onClick={() => setSelectionIndex(index)}
|
||
|
|
>
|
||
|
|
<p className="font-bold dark:text-gray-200">
|
||
|
|
{localize('com_ui_version_var', `${prompts.length - index}`)}
|
||
|
|
</p>
|
||
|
|
<p className="absolute right-4 top-5 whitespace-nowrap text-xs text-gray-600 dark:text-gray-400">
|
||
|
|
{format(new Date(prompt.createdAt), 'yyyy-MM-dd HH:mm')}
|
||
|
|
</p>
|
||
|
|
{tags.length > 0 && (
|
||
|
|
<span className="flex flex-wrap gap-1 text-sm">
|
||
|
|
{tags.map((tag, i) => {
|
||
|
|
return (
|
||
|
|
<Tag
|
||
|
|
key={`${tag}-${i}`}
|
||
|
|
label={tag}
|
||
|
|
className={cn(
|
||
|
|
'w-fit border border-transparent bg-blue-100 text-blue-500 dark:border-blue-500 dark:bg-transparent dark:text-blue-500',
|
||
|
|
tag === 'production' &&
|
||
|
|
'bg-green-100 text-green-500 dark:border-green-500 dark:bg-transparent dark:text-green-500',
|
||
|
|
)}
|
||
|
|
labelClassName="flex m-0 justify-center gap-1"
|
||
|
|
LabelNode={
|
||
|
|
tag === 'production' ? (
|
||
|
|
<div className="flex items-center ">
|
||
|
|
<span className="slow-pulse h-[0.4rem] w-[0.4rem] rounded-full bg-green-400" />
|
||
|
|
</div>
|
||
|
|
) : null
|
||
|
|
}
|
||
|
|
/>
|
||
|
|
);
|
||
|
|
})}
|
||
|
|
</span>
|
||
|
|
)}
|
||
|
|
{group?.authorName && (
|
||
|
|
<p className="text-xs text-gray-600 dark:text-gray-400">by {group.authorName}</p>
|
||
|
|
)}
|
||
|
|
</li>
|
||
|
|
);
|
||
|
|
})}
|
||
|
|
</ul>
|
||
|
|
</>
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
export default PromptVersions;
|