import { useEffect, useState } from "preact/hooks";
import { t } from "../../i18n";
import { api, apiErrorText } from "../../features/customize/api";
import { custTab } from "../../features/customize/actions";
import { confirmAction, hint } from "../../features/customize/host";
import { currentId } from "../../stores/session";
import { useAlive } from "./use-timer-lease";
import { markCustomizeFailed, markCustomizeLoaded } from "../../features/customize/load";
import { Hdr, IconGhost, Note } from "./ui";
type ScopeMeta = { scope: string; scope_id: string; label: string };
type Rule = { rule_id: string; tool: string; pattern: string; decision: string };
function DecSelect({
value,
onChange,
}: {
value: string;
onChange: (v: string) => void;
}) {
return (
);
}
function ResetRow() {
return (
{t("cust.perm.resetName")}
{t("cust.perm.resetDesc")}
);
}
function AddRow({ g }: { g: ScopeMeta }) {
const [tool, setTool] = useState("");
const [pat, setPat] = useState("*");
const [dec, setDec] = useState("ask");
return (
setTool((e.target as HTMLInputElement).value)}
/>
setPat((e.target as HTMLInputElement).value)}
/>
);
}
export function PermissionsTab() {
const alive = useAlive();
const [note, setNote] = useState(null);
const [data, setData] = useState | null>(null);
useEffect(() => {
if (!currentId.value) {
setNote(t("cust.perm.noSessionNote"));
markCustomizeLoaded();
return;
}
void (async () => {
try {
const next = await api(`/frames/${currentId.value}/permissions`);
if (!alive()) return;
setData(next);
markCustomizeLoaded();
} catch (e) {
if (!alive()) return;
const message = t("versions.load.err", (e as Error).message);
setNote(message);
markCustomizeFailed(message);
}
})();
}, [alive]);
const meta: Record | null = data
? {
global: { scope: "global", scope_id: "", label: t("cust.perm.scope.global") },
project: {
scope: "project",
scope_id: String(data.project_id || ""),
label: t("cust.perm.scope.project"),
},
conversation: {
scope: "conversation",
scope_id: String(data.root_frame_id || ""),
label: t("cust.perm.scope.conversation"),
},
}
: null;
return (
{note ?
{note} : null}
{meta
? (["conversation", "project", "global"] as const).map((k) => {
const g = meta[k]!;
const rules = ((data!.rules as Record
| undefined) || {})[
k
] || [];
return (
{g.label}
{!rules.length ?
{t("cust.perm.noRules")} : null}
{rules.map((r) => (
{r.tool}
{r.pattern}
{
try {
await api("/permissions", {
method: "POST",
body: JSON.stringify({
scope: g.scope,
scope_id: g.scope_id,
tool: r.tool,
pattern: r.pattern,
decision: v,
}),
});
hint(t("toast.perm.ruleUpdated"));
} catch (e) {
hint(t("toast.perm.updateFailed", apiErrorText(e)), true);
}
}}
/>
{
try {
await api(`/permissions/${r.rule_id}`, { method: "DELETE" });
custTab("permissions");
} catch (e) {
hint(t("toast.deleteFailed", apiErrorText(e)), true);
}
}}
/>
))}
);
})
: null}
);
}