feat: Enhance Domains, Environments, Services, and Templates management

- Implemented dialog-based forms for adding and editing Domains and Environments.
- Added delete functionality for Domains and Environments with confirmation prompts.
- Introduced EnvironmentDetailsPage to display details of selected environments and their linked domains.
- Created EnvironmentDomainsPage for linking domains to environments.
- Enhanced ServicesPage with dialog support for adding, editing, and viewing service details.
- Updated TemplatesPage to manage templates with comprehensive form fields and validation.
- Improved type definitions in portal.ts to support new features and ensure type safety.
This commit is contained in:
Torsten Brendgen
2026-05-15 00:05:09 +02:00
parent fdf294cac0
commit 7080d659ef
13 changed files with 1283 additions and 86 deletions

View File

@@ -0,0 +1,129 @@
import { useQuery } from "@tanstack/react-query";
import {
Badge,
Button,
makeStyles,
MessageBar,
MessageBarBody,
shorthands,
Table,
TableBody,
TableCell,
TableHeader,
TableHeaderCell,
TableRow,
Text,
Title3,
tokens,
} from "@fluentui/react-components";
import { ArrowLeftRegular } from "@fluentui/react-icons";
import { Link, useParams } from "react-router-dom";
import { portalApi } from "../api/portalApi";
import { DataState } from "../components/DataState";
import { PageHeader } from "../components/PageHeader";
const useStyles = makeStyles({
backLink: {
display: "inline-flex",
marginBottom: "18px",
textDecorationLine: "none",
},
details: {
display: "grid",
gap: "14px",
gridTemplateColumns: "repeat(2, minmax(180px, 1fr))",
marginBottom: "24px",
maxWidth: "720px",
...shorthands.border("1px", "solid", tokens.colorNeutralStroke2),
...shorthands.borderRadius("8px"),
...shorthands.padding("18px"),
},
field: {
display: "grid",
gap: "4px",
minWidth: 0,
},
value: {
overflowWrap: "anywhere",
},
sectionTitle: {
marginBottom: "12px",
},
});
export function EnvironmentDetailsPage() {
const styles = useStyles();
const { id } = useParams();
const { data, error, isLoading } = useQuery({
enabled: Boolean(id),
queryKey: ["environment", id, "domains"],
queryFn: ({ signal }) => portalApi.getEnvironmentDomains(id!, signal),
});
const links = data?.environmentDomains?.filter((link) => link.domain) ?? [];
return (
<>
<Link className={styles.backLink} to="/environments">
<Button appearance="subtle" icon={<ArrowLeftRegular />}>
Environments
</Button>
</Link>
<PageHeader title={data?.name ?? "Environment"} description="Details und verknuepfte Domains." />
<DataState isLoading={isLoading} error={error} />
{data && (
<>
<section className={styles.details} aria-label="Environment details">
<div className={styles.field}>
<Text size={200}>Name</Text>
<Text className={styles.value} weight="semibold">
{data.name}
</Text>
</div>
<div className={styles.field}>
<Text size={200}>Id</Text>
<Text className={styles.value} weight="semibold">
{data.id}
</Text>
</div>
</section>
<Title3 className={styles.sectionTitle}>Linked Domains</Title3>
{links.length === 0 ? (
<MessageBar>
<MessageBarBody>Dieses Environment ist noch mit keiner Domain verknuepft.</MessageBarBody>
</MessageBar>
) : (
<Table aria-label="Linked domains">
<TableHeader>
<TableRow>
<TableHeaderCell>Name</TableHeaderCell>
<TableHeaderCell>FQDN</TableHeaderCell>
<TableHeaderCell>NetBIOS</TableHeaderCell>
<TableHeaderCell>Status</TableHeaderCell>
<TableHeaderCell>Details</TableHeaderCell>
</TableRow>
</TableHeader>
<TableBody>
{links.map((link) => (
<TableRow key={link.domain!.id}>
<TableCell>{link.domain!.name}</TableCell>
<TableCell>{link.domain!.fqdn}</TableCell>
<TableCell>{link.domain!.netBIOS}</TableCell>
<TableCell>
<Badge appearance="filled" color="success">
Linked
</Badge>
</TableCell>
<TableCell>
<Link to={`/domains/${link.domain!.id}`}>Oeffnen</Link>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
)}
</>
)}
</>
);
}