Lieferanten-/IT-Service-Cockpit direkt auf der Asset-Seite öffnen
Statt beim Klick auf ein Lieferanten-/IT-Service-Asset zur Lieferanten-Seite zu wechseln, wird das Fach-Cockpit jetzt als Popup auf /assets gerendert; Schließen, Bearbeiten, Speichern und Löschen bleiben auf der Asset-Seite. - backHref-Prop an SupplierDetail/Edit- und ServiceDetail/Edit-Modal: alle Schließen-/Bearbeiten-/Abbrechen-Links leiten sich davon ab (Default /suppliers) - withQuery-Helper (lib/supplier) für korrekte ?/&-Verkettung - updateSupplier/updateService lesen returnTo (verstecktes Feld) und leiten dorthin zurück; deleteSupplier/deleteService bekommen returnTo-Parameter - Kind-Actions revalidieren zusätzlich /assets, damit das Popup dort aktuell bleibt - SUPPLIER_INCLUDE/SERVICE_INCLUDE in lib/supplier-include ausgelagert und von beiden Seiten genutzt - assets/page.tsx bestimmt die Popup-Art vorab (supplier/service/asset) und rendert das passende Cockpit mit backHref="/assets"; profillose Alt-Assets bleiben Assets Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -17,7 +17,7 @@ import { Textarea } from "@/components/ui/textarea";
|
||||
import { Modal } from "@/components/modal";
|
||||
import { SegmentedRating } from "@/components/segmented-rating";
|
||||
import { CiaBadge, CiaLegend, CriticalityPill, Pill, Tag } from "@/components/mockup-ui";
|
||||
import { serviceRef } from "@/lib/supplier";
|
||||
import { serviceRef, withQuery } from "@/lib/supplier";
|
||||
import { riskLevel, riskRef, RISK_PILL_TONE } from "@/lib/risk";
|
||||
import { ISA_CONTROLS } from "@/lib/isa-controls";
|
||||
|
||||
@@ -37,7 +37,7 @@ const RACI_TONE = { PROVIDER: "info", US: "violet", SHARED: "warn" } as const;
|
||||
|
||||
/* ─────────────────────── Detail-Cockpit ─────────────────────── */
|
||||
|
||||
export async function ServiceDetailModal({ service, canWrite }: { service: ServiceAssetDetail; canWrite: boolean }) {
|
||||
export async function ServiceDetailModal({ service, canWrite, backHref = "/suppliers?tab=services" }: { service: ServiceAssetDetail; canWrite: boolean; backHref?: string }) {
|
||||
const t = await getTranslations("services");
|
||||
const ta = await getTranslations("assets");
|
||||
const tParty = await getTranslations("raciParty");
|
||||
@@ -60,16 +60,16 @@ export async function ServiceDetailModal({ service, canWrite }: { service: Servi
|
||||
<CriticalityPill level={p.criticality} label={tCrit(String(p.criticality))} />
|
||||
</span>
|
||||
}
|
||||
closeHref="/suppliers?tab=services"
|
||||
closeHref={backHref}
|
||||
closeLabel={tp("close")}
|
||||
footer={
|
||||
<>
|
||||
{canWrite && (
|
||||
<Button variant="outline" nativeButton={false} render={<Link href={`/suppliers?tab=services&edit=${service.id}`} />}>
|
||||
<Button variant="outline" nativeButton={false} render={<Link href={withQuery(backHref, "edit", service.id)} />}>
|
||||
<Pencil className="size-4" /> {tc("edit")}
|
||||
</Button>
|
||||
)}
|
||||
<Button nativeButton={false} render={<Link href="/suppliers?tab=services" />}>{tp("close")}</Button>
|
||||
<Button nativeButton={false} render={<Link href={backHref} />}>{tp("close")}</Button>
|
||||
</>
|
||||
}
|
||||
>
|
||||
@@ -334,10 +334,11 @@ export async function ServiceCreateModal({ providers }: { providers: { id: strin
|
||||
);
|
||||
}
|
||||
|
||||
export async function ServiceEditModal({ service, providers }: { service: ServiceAssetDetail; providers: { id: string; name: string }[] }) {
|
||||
export async function ServiceEditModal({ service, providers, backHref = "/suppliers?tab=services" }: { service: ServiceAssetDetail; providers: { id: string; name: string }[]; backHref?: string }) {
|
||||
const t = await getTranslations("services");
|
||||
const tc = await getTranslations("common");
|
||||
const FORM = "service-edit";
|
||||
const detailHref = withQuery(backHref, "detail", service.id);
|
||||
return (
|
||||
<Modal
|
||||
title={t("editTitle")}
|
||||
@@ -346,22 +347,24 @@ export async function ServiceEditModal({ service, providers }: { service: Servic
|
||||
<details className="relative">
|
||||
<summary className="grid size-8 cursor-pointer list-none place-items-center rounded-md text-muted-foreground hover:bg-muted [&::-webkit-details-marker]:hidden"><Trash2 className="size-4" /></summary>
|
||||
<div className="shadow-card absolute right-0 z-20 mt-1 w-48 rounded-xl border bg-card p-1.5">
|
||||
<form action={deleteService.bind(null, service.id)}>
|
||||
<form action={deleteService.bind(null, service.id, backHref)}>
|
||||
<button type="submit" className="flex w-full items-center gap-2 rounded-lg px-2.5 py-2 text-left text-sm text-destructive hover:bg-destructive/10"><Trash2 className="size-4" /> {tc("delete")}</button>
|
||||
</form>
|
||||
</div>
|
||||
</details>
|
||||
}
|
||||
closeHref={`/suppliers?tab=services&detail=${service.id}`}
|
||||
closeHref={detailHref}
|
||||
closeLabel={t("close")}
|
||||
footer={
|
||||
<>
|
||||
<Button variant="outline" nativeButton={false} render={<Link href={`/suppliers?tab=services&detail=${service.id}`} />}>{tc("cancel")}</Button>
|
||||
<Button variant="outline" nativeButton={false} render={<Link href={detailHref} />}>{tc("cancel")}</Button>
|
||||
<Button type="submit" form={FORM}>{tc("save")}</Button>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<form id={FORM} action={updateService.bind(null, service.id)} className="hidden" />
|
||||
<form id={FORM} action={updateService.bind(null, service.id)} className="hidden">
|
||||
<input type="hidden" name="returnTo" value={backHref} />
|
||||
</form>
|
||||
<div className="p-5">
|
||||
<ServiceFields service={service} providers={providers} formId={FORM} />
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user