mirror of
https://github.com/okieselbach/AutopilotMonitor.git
synced 2026-10-24 12:42:38 +00:00
refactor(web): rename Tenant Templates -> Tenant Groups in the UI
User-facing label is clearer as a 'group of tenants' than 'template'. Renames the menu label, page header, copy and the frontend route slug (/admin/settings/tenant-templates -> /admin/settings/tenant-groups). Backend (tables, classes, /api/global/tenant-templates routes) intentionally unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -17,7 +17,7 @@ const SECTION_COMPONENTS: Record<SettingsSectionId, React.ComponentType> = {
|
||||
"diagnostics-log-paths": SectionDiagnosticsLogPaths,
|
||||
"mcp-users": SectionMcpUsers,
|
||||
"delegated-admins": SectionDelegatedAdmins,
|
||||
"tenant-templates": SectionTenantTemplates,
|
||||
"tenant-groups": SectionTenantTemplates,
|
||||
"config-reseed": SectionConfigReseed,
|
||||
"usage-plans": SectionUsagePlans,
|
||||
"alerts": SectionAlerts,
|
||||
|
||||
+11
-11
@@ -77,11 +77,11 @@ export function SectionTenantTemplates() {
|
||||
try {
|
||||
setLoading(true);
|
||||
const response = await authenticatedFetch(api.tenantTemplates.list(), getAccessToken);
|
||||
if (!response.ok) throw new Error(`Failed to load templates: ${response.statusText}`);
|
||||
if (!response.ok) throw new Error(`Failed to load groups: ${response.statusText}`);
|
||||
const data = await response.json();
|
||||
setTemplates(data.templates ?? []);
|
||||
} catch (err) {
|
||||
handleError(err, "Failed to load templates");
|
||||
handleError(err, "Failed to load groups");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
@@ -126,14 +126,14 @@ export function SectionTenantTemplates() {
|
||||
const name = newName.trim();
|
||||
if (!name) return;
|
||||
setCreating(true);
|
||||
const ok = await mutate("create", api.tenantTemplates.create(), "POST", { name }, `Created template "${name}".`);
|
||||
const ok = await mutate("create", api.tenantTemplates.create(), "POST", { name }, `Created group "${name}".`);
|
||||
setCreating(false);
|
||||
if (ok) setNewName("");
|
||||
}, [newName, mutate]);
|
||||
|
||||
const handleRename = useCallback(
|
||||
async (t: TenantTemplate) => {
|
||||
const name = prompt("Rename template:", t.name)?.trim();
|
||||
const name = prompt("Rename group:", t.name)?.trim();
|
||||
if (!name || name === t.name) return;
|
||||
await mutate(`rename:${t.templateId}`, api.tenantTemplates.rename(t.templateId), "PATCH", { name }, `Renamed to "${name}".`);
|
||||
},
|
||||
@@ -143,7 +143,7 @@ export function SectionTenantTemplates() {
|
||||
const handleDeleteTemplate = useCallback(
|
||||
async (t: TenantTemplate) => {
|
||||
const extra = t.assigneeCount > 0 ? ` ${t.assigneeCount} assignee(s) will lose this access.` : "";
|
||||
if (!confirm(`Delete template "${t.name}"?${extra}`)) return;
|
||||
if (!confirm(`Delete group "${t.name}"?${extra}`)) return;
|
||||
await mutate(`delete:${t.templateId}`, api.tenantTemplates.remove(t.templateId), "DELETE", undefined, `Deleted "${t.name}".`);
|
||||
},
|
||||
[mutate],
|
||||
@@ -199,7 +199,7 @@ export function SectionTenantTemplates() {
|
||||
|
||||
const handleUnassign = useCallback(
|
||||
async (t: TenantTemplate, upn: string) => {
|
||||
if (!confirm(`Remove ${upn} from "${t.name}"? They lose access to all tenants in this template.`)) return;
|
||||
if (!confirm(`Remove ${upn} from "${t.name}"? They lose access to all tenants in this group.`)) return;
|
||||
await mutate(
|
||||
`unassign:${t.templateId}:${upn}`,
|
||||
api.tenantTemplates.unassign(t.templateId, upn),
|
||||
@@ -225,10 +225,10 @@ export function SectionTenantTemplates() {
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
|
||||
d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
|
||||
</svg>
|
||||
<h2 className="text-lg font-semibold text-gray-900">Tenant Templates (MSP Mode)</h2>
|
||||
<h2 className="text-lg font-semibold text-gray-900">Tenant Groups (MSP Mode)</h2>
|
||||
</div>
|
||||
<p className="mt-1 text-sm text-gray-600">
|
||||
Bundle tenants into a named template, then assign people to the template instead of to each tenant.
|
||||
Bundle tenants into a named group, then assign people to the group instead of to each tenant.
|
||||
Add a tenant once and every assignee gets it; manage your managed-service team by who is assigned here.
|
||||
</p>
|
||||
</div>
|
||||
@@ -254,7 +254,7 @@ export function SectionTenantTemplates() {
|
||||
|
||||
{/* Create form */}
|
||||
<div className="bg-sky-50 border border-sky-200 rounded-lg p-4 space-y-3">
|
||||
<p className="text-sm font-medium text-sky-800">New template</p>
|
||||
<p className="text-sm font-medium text-sky-800">New group</p>
|
||||
<div className="flex flex-col gap-2 sm:flex-row">
|
||||
<input
|
||||
type="text"
|
||||
@@ -291,14 +291,14 @@ export function SectionTenantTemplates() {
|
||||
{loading && (
|
||||
<div className="flex items-center justify-center py-8">
|
||||
<div className="animate-spin rounded-full h-6 w-6 border-b-2 border-sky-600" />
|
||||
<span className="ml-3 text-sm text-gray-500">Loading templates…</span>
|
||||
<span className="ml-3 text-sm text-gray-500">Loading groups…</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Empty */}
|
||||
{!loading && sorted.length === 0 && (
|
||||
<p className="text-sm text-gray-500 py-4 text-center">
|
||||
No templates yet. Create one above, add tenants to it, then assign your team.
|
||||
No groups yet. Create one above, add tenants to it, then assign your team.
|
||||
</p>
|
||||
)}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ export const SETTINGS_NAV_SECTIONS = [
|
||||
{ id: "diagnostics-log-paths", label: "Diagnostics Log Paths", description: "Global diagnostics log path configuration" },
|
||||
{ id: "mcp-users", label: "MCP Users", description: "Manage AI agent access via MCP" },
|
||||
{ id: "delegated-admins", label: "Delegated Admins", description: "Grant cross-tenant read access (MSP mode)" },
|
||||
{ id: "tenant-templates", label: "Tenant Templates", description: "Bundle tenants and assign delegated admins (MSP mode)" },
|
||||
{ id: "tenant-groups", label: "Tenant Groups", description: "Group tenants and assign delegated admins (MSP mode)" },
|
||||
{ id: "config-reseed", label: "Config Reseed", description: "Fetch and reseed rules from GitHub" },
|
||||
{ id: "usage-plans", label: "Usage Plans", description: "Define MCP usage plan tiers and limits" },
|
||||
{ id: "alerts", label: "Alerts", description: "Configure ops event alert rules and notification providers" },
|
||||
|
||||
@@ -283,7 +283,7 @@ export const EXPANDABLE_NAV_GROUPS: ExpandableNavGroup[] = [
|
||||
{ id: "ga-diag-paths", label: "Diagnostics Log Paths", href: "/admin/settings/diagnostics-log-paths" },
|
||||
{ id: "ga-mcp-users", label: "MCP Users", href: "/admin/settings/mcp-users" },
|
||||
{ id: "ga-delegated-admins", label: "Delegated Admins", href: "/admin/settings/delegated-admins" },
|
||||
{ id: "ga-tenant-templates", label: "Tenant Templates", href: "/admin/settings/tenant-templates" },
|
||||
{ id: "ga-tenant-groups", label: "Tenant Groups", href: "/admin/settings/tenant-groups" },
|
||||
{ id: "ga-config-reseed", label: "Config Reseed", href: "/admin/settings/config-reseed" },
|
||||
{ id: "ga-usage-plans", label: "Usage Plans", href: "/admin/settings/usage-plans" },
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user