feat(settings): wire frontend to Coolify SoT response shape
- McpEnvVar: infisical_value → coolify_value + has_duplicates - McpEnvResponse: drop Infisical metadata fields - EnvVarRow: 'Coolify:' label, 'ערוך ב-Coolify' external link - DriftBadge: infisicalAvailable → coolifyAvailable - EnvironmentTab: Coolify app badge, duplicates count
This commit is contained in:
@@ -5,17 +5,17 @@ import { Badge } from "@/components/ui/badge";
|
||||
|
||||
type Props = {
|
||||
drift: boolean;
|
||||
// When false, Infisical was unreachable: drift state is unknown, not "synced".
|
||||
infisicalAvailable?: boolean;
|
||||
// When false, Coolify was unreachable: drift state is unknown, not "synced".
|
||||
coolifyAvailable?: boolean;
|
||||
};
|
||||
|
||||
export function DriftBadge({ drift, infisicalAvailable = true }: Props) {
|
||||
if (!infisicalAvailable) {
|
||||
export function DriftBadge({ drift, coolifyAvailable = true }: Props) {
|
||||
if (!coolifyAvailable) {
|
||||
return (
|
||||
<Badge
|
||||
variant="outline"
|
||||
className="text-ink-muted border-rule gap-1"
|
||||
title="Infisical לא זמין — מצב ה-drift לא ידוע"
|
||||
title="Coolify לא זמין — מצב ה-drift לא ידוע"
|
||||
>
|
||||
<HelpCircle className="w-3 h-3" />
|
||||
Unknown
|
||||
|
||||
@@ -12,22 +12,20 @@ import { EnvVarEditor } from "./env-var-editor";
|
||||
|
||||
type Props = {
|
||||
spec: McpEnvVar;
|
||||
infisicalProjectId: string;
|
||||
infisicalEnv: string;
|
||||
infisicalAvailable: boolean;
|
||||
coolifyAppUuid: string;
|
||||
coolifyAvailable: boolean;
|
||||
onPendingRedeploy: () => void;
|
||||
};
|
||||
|
||||
export function EnvVarRow({
|
||||
spec,
|
||||
infisicalProjectId,
|
||||
infisicalEnv,
|
||||
infisicalAvailable,
|
||||
coolifyAppUuid,
|
||||
coolifyAvailable,
|
||||
onPendingRedeploy,
|
||||
}: Props) {
|
||||
const [draft, setDraft] = useState<string>(spec.infisical_value ?? "");
|
||||
const [draft, setDraft] = useState<string>(spec.coolify_value ?? "");
|
||||
const update = useUpdateMcpEnv();
|
||||
const dirty = draft !== (spec.infisical_value ?? "");
|
||||
const dirty = draft !== (spec.coolify_value ?? "");
|
||||
|
||||
function handleSave() {
|
||||
update.mutate(
|
||||
@@ -42,8 +40,8 @@ export function EnvVarRow({
|
||||
);
|
||||
}
|
||||
|
||||
const infisicalUrl =
|
||||
`https://secret.dev.marcus-law.co.il/project/${infisicalProjectId}/secrets/overview?env=${infisicalEnv}`;
|
||||
const coolifyEnvUrl =
|
||||
`https://coolify.nautilus.marcusgroup.org/project/applications/${coolifyAppUuid}/environment-variables`;
|
||||
|
||||
return (
|
||||
<div className="rounded-md border border-rule p-4 bg-rule-soft/20 hover:bg-rule-soft/40 transition-colors">
|
||||
@@ -62,7 +60,12 @@ export function EnvVarRow({
|
||||
secret
|
||||
</Badge>
|
||||
)}
|
||||
<DriftBadge drift={spec.drift} infisicalAvailable={infisicalAvailable} />
|
||||
<DriftBadge drift={spec.drift} coolifyAvailable={coolifyAvailable} />
|
||||
{spec.has_duplicates && (
|
||||
<Badge variant="outline" className="text-[0.7rem] text-warn border-warn/40">
|
||||
duplicates
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-sm text-ink-muted mt-1">{spec.description}</p>
|
||||
</div>
|
||||
@@ -70,7 +73,7 @@ export function EnvVarRow({
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-3 text-sm">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-[0.72rem] text-ink-muted w-20">Infisical:</span>
|
||||
<span className="text-[0.72rem] text-ink-muted w-20">Coolify:</span>
|
||||
{spec.is_editable ? (
|
||||
<EnvVarEditor
|
||||
spec={spec}
|
||||
@@ -80,7 +83,7 @@ export function EnvVarRow({
|
||||
/>
|
||||
) : (
|
||||
<span className="font-mono text-ink" dir="ltr">
|
||||
{spec.infisical_value ?? <em className="text-ink-muted">— לא מוגדר —</em>}
|
||||
{spec.coolify_value ?? <em className="text-ink-muted">— לא מוגדר —</em>}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
@@ -95,12 +98,12 @@ export function EnvVarRow({
|
||||
<div className="flex items-center justify-end gap-2 mt-3">
|
||||
{!spec.is_editable && (
|
||||
<a
|
||||
href={infisicalUrl}
|
||||
href={coolifyEnvUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-[0.78rem] text-gold-deep hover:underline flex items-center gap-1"
|
||||
>
|
||||
ערוך ב-Infisical
|
||||
ערוך ב-Coolify
|
||||
<ExternalLink className="w-3 h-3" />
|
||||
</a>
|
||||
)}
|
||||
|
||||
@@ -67,8 +67,9 @@ export function EnvironmentTab() {
|
||||
}
|
||||
if (!data) return null;
|
||||
|
||||
const infisicalAvailable = data.errors.length === 0;
|
||||
const coolifyAvailable = data.errors.length === 0;
|
||||
const driftCount = data.vars.filter((v) => v.drift).length;
|
||||
const duplicatesCount = data.vars.filter((v) => v.has_duplicates).length;
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
@@ -76,16 +77,18 @@ export function EnvironmentTab() {
|
||||
<CardContent className="px-6 py-4 flex items-center justify-between gap-4 flex-wrap">
|
||||
<div className="flex items-center gap-3 flex-wrap text-sm">
|
||||
<Badge variant="outline">
|
||||
Infisical: <code dir="ltr" className="ms-1">{data.infisical_environment}</code>
|
||||
</Badge>
|
||||
<Badge variant="outline">
|
||||
Path: <code dir="ltr" className="ms-1">{data.infisical_path}</code>
|
||||
Coolify app: <code dir="ltr" className="ms-1">{data.coolify_app_uuid.slice(0, 8)}…</code>
|
||||
</Badge>
|
||||
{driftCount > 0 && (
|
||||
<Badge variant="outline" className="text-warn border-warn/40">
|
||||
{driftCount} drift
|
||||
</Badge>
|
||||
)}
|
||||
{duplicatesCount > 0 && (
|
||||
<Badge variant="outline" className="text-warn border-warn/40">
|
||||
{duplicatesCount} duplicates
|
||||
</Badge>
|
||||
)}
|
||||
{data.errors.length > 0 && (
|
||||
<Badge variant="outline" className="text-danger border-danger/40">
|
||||
{data.errors.join(", ")}
|
||||
@@ -121,9 +124,8 @@ export function EnvironmentTab() {
|
||||
<EnvVarRow
|
||||
key={v.key}
|
||||
spec={v}
|
||||
infisicalProjectId={data.infisical_project_id}
|
||||
infisicalEnv={data.infisical_environment}
|
||||
infisicalAvailable={infisicalAvailable}
|
||||
coolifyAppUuid={data.coolify_app_uuid}
|
||||
coolifyAvailable={coolifyAvailable}
|
||||
onPendingRedeploy={() => setPendingRedeploy(true)}
|
||||
/>
|
||||
))}
|
||||
|
||||
@@ -79,16 +79,14 @@ export type McpEnvVar = {
|
||||
min: number | null;
|
||||
max: number | null;
|
||||
enum_values: string[] | null;
|
||||
infisical_value: string | null;
|
||||
coolify_value: string | null;
|
||||
container_value: string | null;
|
||||
drift: boolean;
|
||||
has_duplicates: boolean;
|
||||
};
|
||||
|
||||
export type McpEnvResponse = {
|
||||
vars: McpEnvVar[];
|
||||
infisical_environment: string;
|
||||
infisical_project_id: string;
|
||||
infisical_path: string;
|
||||
coolify_app_uuid: string;
|
||||
errors: string[];
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user