feat(scenarios): link scenarios to a default environment
- add optional ManyToOne relation from scenario to environment entity - expose environmentId in create/update DTOs, service, and MCP tools - pre-select linked environment in run modals on detail and list pages - add environment selector to create/edit scenario forms - show linked environment as a navigable link on scenario detail page
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useState, SubmitEvent } from 'react';
|
||||
import { useEffect, useRef, useState, SubmitEvent } from 'react';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
@@ -68,6 +68,7 @@ export function ScenarioDetailPage() {
|
||||
const [saveSessionFlag, setSaveSessionFlag] = useState(false);
|
||||
const [envs, setEnvs] = useState<Environment[]>([]);
|
||||
const [selectedEnvId, setSelectedEnvId] = useState('');
|
||||
const envInitRef = useRef(false);
|
||||
const [pendingDelete, setPendingDelete] = useState<
|
||||
{ type: 'scenario' } | { type: 'step'; id: string } | { type: 'credential'; id: string } | null
|
||||
>(null);
|
||||
@@ -90,11 +91,19 @@ export function ScenarioDetailPage() {
|
||||
.list(1, 200)
|
||||
.then((r) => {
|
||||
setEnvs(r.data);
|
||||
setSelectedEnvId((prev) => prev || r.data[0]?.id || '');
|
||||
})
|
||||
.catch(() => {});
|
||||
}, [id]);
|
||||
|
||||
// Default selected env to scenario's linked environment (or first env) once both are loaded
|
||||
useEffect(() => {
|
||||
if (envInitRef.current || envs.length === 0) return;
|
||||
envInitRef.current = true;
|
||||
const preferred = scenario?.environmentId ?? null;
|
||||
const exists = preferred ? envs.some((e) => e.id === preferred) : false;
|
||||
setSelectedEnvId(exists ? preferred! : envs[0].id);
|
||||
}, [scenario, envs]);
|
||||
|
||||
const reloadScenario = async () => {
|
||||
if (!id) return;
|
||||
const s = await scenarios.get(id);
|
||||
@@ -389,6 +398,19 @@ export function ScenarioDetailPage() {
|
||||
items={[
|
||||
{ term: t('scenarios.field_id'), detail: <UuidBadge id={scenario.id} /> },
|
||||
{ term: t('scenarios.field_name'), detail: scenario.name },
|
||||
...(scenario.environment
|
||||
? [{
|
||||
term: t('scenarios.field_environment'),
|
||||
detail: (
|
||||
<a
|
||||
href={`/environments/${scenario.environment.id}`}
|
||||
onClick={(e) => { e.preventDefault(); navigate(`/environments/${scenario.environment!.id}`); }}
|
||||
>
|
||||
{scenario.environment.name}
|
||||
</a>
|
||||
),
|
||||
}]
|
||||
: []),
|
||||
{
|
||||
term: t('scenarios.field_created'),
|
||||
detail: <Timestamp value={scenario.createdAt} />,
|
||||
|
||||
Reference in New Issue
Block a user