158 lines
4.5 KiB
TypeScript
158 lines
4.5 KiB
TypeScript
import { useState, useEffect } from 'react';
|
|
import { Plus, Minus } from 'lucide-react';
|
|
import { Button, Select, Card, CardBody } from '../../components/ui';
|
|
import { Env, AddEvent, RemoveEvent, UpdateEvent } from '../../models/Env';
|
|
import { EnvParam } from '../../models/EnvParam';
|
|
import { EnvironmentParam } from './EnvironmentParam';
|
|
|
|
interface EnvironmentProps {
|
|
envs: Env[];
|
|
onChanged: (env: Env) => void;
|
|
onSelected: (envId: number) => void;
|
|
onAdd: (env: Env) => number;
|
|
onRemove: (envId: number) => void;
|
|
}
|
|
|
|
export function Environment({ envs, onChanged, onSelected, onAdd, onRemove }: EnvironmentProps) {
|
|
const [currEnvId, setCurrEnvId] = useState<number>(envs[0]?.id ?? 0);
|
|
|
|
// Sync currEnvId when envs changes
|
|
useEffect(() => {
|
|
if (!envs.find(e => e.id === currEnvId)) {
|
|
setCurrEnvId(envs[0]?.id ?? 0);
|
|
}
|
|
}, [envs, currEnvId]);
|
|
|
|
const currEnv = envs.find(e => e.id === currEnvId) ?? envs[0];
|
|
|
|
function handleParamChanged(event: AddEvent<EnvParam> | RemoveEvent<EnvParam> | UpdateEvent<EnvParam>) {
|
|
let newEnv: Env = currEnv;
|
|
let isChanged = false;
|
|
|
|
if (event instanceof RemoveEvent) {
|
|
newEnv = currEnv.delParam(event.payload);
|
|
isChanged = true;
|
|
} else if (event instanceof AddEvent) {
|
|
newEnv = currEnv.addParams(event.payload);
|
|
isChanged = true;
|
|
} else if (event instanceof UpdateEvent) {
|
|
newEnv = currEnv.updateParams(event.payload);
|
|
isChanged = true;
|
|
}
|
|
|
|
if (isChanged) {
|
|
onChanged(newEnv);
|
|
setCurrEnvId(newEnv.id ?? 0);
|
|
}
|
|
}
|
|
|
|
function handleAddEnv() {
|
|
const name = prompt('Enter new environment name:');
|
|
if (!name || name.trim() === '') return;
|
|
|
|
// Calculate next integer ID based on max existing ID
|
|
const maxId = envs.reduce((max, e) => Math.max(max, e.id ?? 0), -1);
|
|
const newId = maxId + 1;
|
|
|
|
const newEnv = new Env(newId, name.trim(), [...currEnv.params]);
|
|
const newIdx = onAdd(newEnv);
|
|
setCurrEnvId(newEnv.id ?? 0);
|
|
onSelected(newIdx);
|
|
}
|
|
|
|
function handleRemoveEnv() {
|
|
if (currEnv.isDefault()) {
|
|
alert('Cannot remove DEFAULT environment');
|
|
return;
|
|
}
|
|
if (!confirm(`Remove environment "${currEnv.name}"?`)) return;
|
|
|
|
const idx = envs.findIndex(x => x.id === currEnv.id);
|
|
if (idx > -1 && currEnv.id !== undefined) {
|
|
onRemove(currEnv.id);
|
|
const newIdx = Math.max(0, idx - 1);
|
|
const newEnv = envs[newIdx];
|
|
if (newEnv?.id !== undefined) {
|
|
setCurrEnvId(newEnv.id);
|
|
}
|
|
onSelected(newIdx);
|
|
}
|
|
}
|
|
|
|
const selectOptions = envs.map((x) => ({
|
|
value: x.id ?? 0,
|
|
label: x.name ?? 'Unknown',
|
|
}));
|
|
|
|
const paramCtrls = currEnv.params.map((x) => (
|
|
<EnvironmentParam
|
|
key={`${currEnv.id}-${x.id}`}
|
|
param={new EnvParam(x.id, x.name, x.value)}
|
|
onChanged={handleParamChanged}
|
|
isNew={false}
|
|
/>
|
|
));
|
|
|
|
return (
|
|
<Card variant="bordered" padding="none" className="h-full">
|
|
<CardBody className="space-y-1">
|
|
{/* Environment Selector */}
|
|
<div className="flex gap-2">
|
|
<div className="flex-1">
|
|
<Select
|
|
label="Environment"
|
|
value={currEnvId}
|
|
options={selectOptions}
|
|
onChange={(e) => {
|
|
const id = Number.parseInt(e.target.value);
|
|
setCurrEnvId(id);
|
|
onSelected(id);
|
|
}}
|
|
id="environments"
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex flex-col justify-center gap-2 pt-6">
|
|
<div className="flex gap-2">
|
|
<Button
|
|
variant="success"
|
|
size="sm"
|
|
onClick={handleAddEnv}
|
|
title="Add environment"
|
|
icon={Plus}
|
|
/>
|
|
|
|
<Button
|
|
variant="danger"
|
|
size="sm"
|
|
onClick={handleRemoveEnv}
|
|
title="Remove environment"
|
|
icon={Minus}
|
|
disabled={currEnv.isDefault()}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Parameters Section */}
|
|
<div>
|
|
<h3 className="text-sm font-semibold text-slate-700 mb-1 uppercase tracking-wide">
|
|
Parameters
|
|
</h3>
|
|
|
|
<div className="space-y-0">
|
|
{paramCtrls}
|
|
|
|
<EnvironmentParam
|
|
key={`${currEnv.id}-new`}
|
|
param={new EnvParam(-1, '', '')}
|
|
onChanged={handleParamChanged}
|
|
isNew={true}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</CardBody>
|
|
</Card>
|
|
);
|
|
}
|