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