import { t } from "@lingui/core/macro"; import { Trans, useLingui } from "@lingui/react/macro"; import type { ActionApprovalRule, ActionAutoReviewSettings } from "@rakazo/contracts"; import { Button, Label, Switch } from "@rakazo/ui-web"; import { useEffect, useId, useState } from "react"; import { rpc } from "../lib/rpc"; function describeRule(rule: ActionApprovalRule): string { if (rule.effect === "require_approval") { if (rule.matchKind === "category") { if (rule.matchValue === "email") return t`Ask before email actions`; if (rule.matchValue === "purchase") return t`Ask before purchase actions`; return t`Ask before ${rule.matchValue} actions`; } if (rule.matchKind === "connector") return t`Ask before ${rule.matchValue} connector`; return t`Ask before ${rule.matchValue}`; } if (rule.matchKind === "category") { if (rule.matchValue === "email") return t`Allow email actions without asking`; if (rule.matchValue === "purchase") return t`Allow purchase actions without asking`; return t`Allow ${rule.matchValue} actions without asking`; } if (rule.matchKind === "connector") return t`Allow ${rule.matchValue} connector without asking`; return t`Allow ${rule.matchValue} without asking`; } export function ApprovalRulesSettings() { const { t } = useLingui(); const autoReviewId = useId(); const [rules, setRules] = useState([]); const [autoReview, setAutoReview] = useState(null); const [loading, setLoading] = useState(true); const [savingPreset, setSavingPreset] = useState<"email" | "purchase" | null>(null); const [savingAutoReview, setSavingAutoReview] = useState(false); const [error, setError] = useState(null); async function refresh() { setLoading(true); setError(null); try { const [nextRules, nextAutoReview] = await Promise.all([ rpc.approvalRules.list(), rpc.autoReview.get(), ]); setRules(nextRules); setAutoReview(nextAutoReview); } catch (err) { setError(err instanceof Error ? err.message : t`Could not load approval rules`); } finally { setLoading(false); } } useEffect(() => { void refresh(); }, []); async function setPreset(matchValue: "email" | "purchase") { if (loading || savingPreset) return; if ( rules.some( (rule) => rule.effect === "require_approval" && rule.matchKind === "category" && rule.matchValue === matchValue, ) ) { return; } setSavingPreset(matchValue); setError(null); try { const saved = await rpc.approvalRules.set({ effect: "require_approval", matchKind: "category", matchValue, }); setRules((current) => [...current, saved]); } catch (err) { setError(err instanceof Error ? err.message : t`Could not save rule`); } finally { setSavingPreset(null); } } async function removeRule(id: string) { setError(null); try { await rpc.approvalRules.remove({ id }); setRules((current) => current.filter((rule) => rule.id !== id)); } catch (err) { setError(err instanceof Error ? err.message : t`Could not remove rule`); } } async function toggleAutoReview(enabled: boolean) { if (loading || savingAutoReview) return; setSavingAutoReview(true); setError(null); try { setAutoReview(await rpc.autoReview.set({ enabled })); } catch (err) { setError(err instanceof Error ? err.message : t`Could not save Auto Review`); } finally { setSavingAutoReview(false); } } return (

Action confirmations

Bots act without asking by default. Add an exception only when you want to review a type of action first.

void toggleAutoReview(checked)} />
{autoReview?.enabled && !autoReview.checkerAvailable ? (

Add a model in Settings to use this.

) : null}
{error ?

{error}

: null} {loading ? (

Loading rules…

) : rules.length === 0 ? (

No exceptions. Actions run automatically.

) : (
    {rules.map((rule) => (
  • {describeRule(rule)}
  • ))}
)}
); }