feat: new importer (#214)

This commit is contained in:
Carl-Gerhard Lindesvärd
2025-11-05 09:49:36 +01:00
committed by GitHub
parent b51bc8f3f6
commit 212254d31a
80 changed files with 4884 additions and 842 deletions

View File

@@ -50,12 +50,15 @@ export function IntegrationCardHeaderButtons({
export function IntegrationCardLogoImage({
src,
backgroundColor,
className,
}: {
src: string;
backgroundColor: string;
className?: string;
}) {
return (
<IntegrationCardLogo
className={className}
style={{
backgroundColor,
}}

View File

@@ -0,0 +1,116 @@
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
import type { IServiceProject } from '@openpanel/db';
import { PlusIcon, XIcon } from 'lucide-react';
import type {
Control,
FieldArrayWithId,
UseFieldArrayAppend,
UseFieldArrayRemove,
UseFormRegister,
UseFormSetValue,
UseFormWatch,
} from 'react-hook-form';
interface ProjectMapperProps {
fields: FieldArrayWithId<any, 'projectMapper', 'id'>[];
append: UseFieldArrayAppend<any, 'projectMapper'>;
remove: UseFieldArrayRemove;
projects: IServiceProject[];
register: UseFormRegister<any>;
watch: UseFormWatch<any>;
setValue: UseFormSetValue<any>;
}
export function ProjectMapper({
fields,
append,
remove,
projects,
register,
watch,
setValue,
}: ProjectMapperProps) {
return (
<div className="space-y-2">
<div className="flex items-center justify-between">
<Label className="mb-0">Project Mapper (Optional)</Label>
<Button
type="button"
variant="outline"
size="sm"
onClick={() => append({ from: '', to: '' })}
>
<PlusIcon className="mr-1 h-4 w-4" />
Add Mapping
</Button>
</div>
{fields.length === 0 && (
<p className="text-sm text-muted-foreground leading-normal">
Map source project IDs to your OpenPanel projects. If you skip mapping
all data will be imported to your current project.
</p>
)}
{fields.length > 0 && (
<div className="space-y-2">
{fields.map((field, index) => (
<div key={field.id} className="gap-2 rounded-md border p-3 row">
<div className="grid grid-cols-2 gap-2">
<div className="flex-1">
<Label className="text-xs text-muted-foreground">
From (Source Project ID)
</Label>
<Input
placeholder="e.g., abc123"
{...register(`projectMapper.${index}.from`)}
className="mt-1"
/>
</div>
<div className="flex-1">
<Label className="text-xs text-muted-foreground">
To (OpenPanel Project)
</Label>
<Select
value={watch(`projectMapper.${index}.to`)}
onValueChange={(value) =>
setValue(`projectMapper.${index}.to`, value)
}
>
<SelectTrigger className="mt-1 w-full" size="sm">
<SelectValue placeholder="Select project" />
</SelectTrigger>
<SelectContent>
{projects.slice(0, 10).map((project) => (
<SelectItem key={project.id} value={project.id}>
{project.name}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
</div>
<Button
type="button"
variant="ghost"
size="icon"
onClick={() => remove(index)}
className="mt-5"
>
<XIcon className="h-4 w-4" />
</Button>
</div>
))}
</div>
)}
</div>
);
}

View File

@@ -9,6 +9,11 @@ const badgeVariants = cva(
{
variants: {
variant: {
success:
'border-transparent bg-emerald-700 text-white [a&]:hover:bg-emerald-700/90',
warning:
'border-transparent bg-yellow-500 text-white [a&]:hover:bg-yellow-500/90',
info: 'border-transparent bg-blue-500 text-white [a&]:hover:bg-blue-500/90',
default:
'border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90',
secondary: