auth-yes/replace_roles_form.py
google-labs-jules[bot] 4c7d8d4af7 feat(ui): decompose admin pages into reusable AdminTable and AdminModal components
Refactored AdminInvitesPage, AdminUserDetailsPage, AdminRolesPage, and AdminAppsPage to use the new pure Hono SSR JSX stateless components.
Fixed missing import definitions in AdminRolesPage.
Moved task file to complete state.

Co-authored-by: mrteye <1945243+mrteye@users.noreply.github.com>
2026-08-26 00:34:29 +00:00

205 lines
7.2 KiB
Python

import re
with open('ui/components/AdminRolesPage.tsx', 'r') as f:
content = f.read()
role_form = """ <div
id="roleFormCard"
class="card"
style="display: none; border-left: 4px solid var(--primary); margin-bottom: 1.5rem;"
>
<h3
id="roleFormTitle"
style="margin: 0 0 0.5rem 0; color: var(--text-primary);"
>
Create New Role
</h3>
<p style="color: var(--text-secondary); font-size: 0.9rem; margin: 0 0 1.25rem 0;">
Define a global shared role or an application-scoped custom grant.
</p>
<form id="roleForm" onsubmit="handleSaveRole(event)">
<input type="hidden" id="editRoleId" value="" />
<div
id="scopeSelectContainer"
style="display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1rem; margin-bottom: 1rem;"
>
<div>
<label style="display: block; font-weight: 600; margin-bottom: 0.35rem; font-size: 0.85rem; color: var(--text-secondary);">
Scope (Applicability) *
</label>
<select
id="roleScope"
onchange="handleScopeChange()"
style="width: 100%;"
>
<option value="global">
Global (Shared across ALL applications)
</option>
<option value="app_specific">
Application-Specific (Scoped to single app)
</option>
</select>
</div>
<div id="appSelectContainer" style="display: none;">
<label style="display: block; font-weight: 600; margin-bottom: 0.35rem; font-size: 0.85rem; color: var(--text-secondary);">
Target Application *
</label>
<select
id="roleAppId"
style="width: 100%;"
>
{apps.map((app) => (
<option value={app.id}>
{app.name} ({app.spiffe_id})
</option>
))}
</select>
</div>
</div>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1rem; margin-bottom: 1.25rem;">
<div>
<label style="display: block; font-weight: 600; margin-bottom: 0.35rem; font-size: 0.85rem; color: var(--text-secondary);">
Role Identifier *
</label>
<input
type="text"
id="roleName"
placeholder="e.g. navigator, copilot, auditor"
required
style="width: 100%;"
/>
</div>
<div>
<label style="display: block; font-weight: 600; margin-bottom: 0.35rem; font-size: 0.85rem; color: var(--text-secondary);">
Description / Purpose
</label>
<input
type="text"
id="roleDescription"
placeholder="e.g. Flight routing and navigational telemetry access"
style="width: 100%;"
/>
</div>
</div>
<div style="display: flex; gap: 0.75rem;">
<button type="submit" class="btn-primary" style="min-height: 42px;">
Save Role
</button>
<button
type="button"
class="btn-outline"
onclick="closeRoleDrawer()"
style="min-height: 42px;"
>
Cancel
</button>
</div>
</form>
</div>"""
role_form_replacement = """ <AdminModal
id="roleFormModal"
title="Create New Role"
onClose="closeRoleDrawer()"
>
<p style="color: var(--text-secondary); font-size: 0.9rem; margin: 0 0 1.25rem 0;">
Define a global shared role or an application-scoped custom grant.
</p>
<form id="roleForm" onsubmit="handleSaveRole(event)">
<input type="hidden" id="editRoleId" value="" />
<div
id="scopeSelectContainer"
style="display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1rem; margin-bottom: 1rem;"
>
<div>
<label style="display: block; font-weight: 600; margin-bottom: 0.35rem; font-size: 0.85rem; color: var(--text-secondary);">
Scope (Applicability) *
</label>
<select
id="roleScope"
onchange="handleScopeChange()"
style="width: 100%;"
>
<option value="global">
Global (Shared across ALL applications)
</option>
<option value="app_specific">
Application-Specific (Scoped to single app)
</option>
</select>
</div>
<div id="appSelectContainer" style="display: none;">
<label style="display: block; font-weight: 600; margin-bottom: 0.35rem; font-size: 0.85rem; color: var(--text-secondary);">
Target Application *
</label>
<select
id="roleAppId"
style="width: 100%;"
>
{apps.map((app) => (
<option value={app.id}>
{app.name} ({app.spiffe_id})
</option>
))}
</select>
</div>
</div>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1rem; margin-bottom: 1.25rem;">
<div>
<label style="display: block; font-weight: 600; margin-bottom: 0.35rem; font-size: 0.85rem; color: var(--text-secondary);">
Role Identifier *
</label>
<input
type="text"
id="roleName"
placeholder="e.g. navigator, copilot, auditor"
required
style="width: 100%;"
/>
</div>
<div>
<label style="display: block; font-weight: 600; margin-bottom: 0.35rem; font-size: 0.85rem; color: var(--text-secondary);">
Description / Purpose
</label>
<input
type="text"
id="roleDescription"
placeholder="e.g. Flight routing and navigational telemetry access"
style="width: 100%;"
/>
</div>
</div>
<div style="display: flex; gap: 0.75rem;">
<button type="submit" class="btn-primary" style="min-height: 42px;">
Save Role
</button>
<button
type="button"
class="btn-outline"
onclick="closeRoleDrawer()"
style="min-height: 42px;"
>
Cancel
</button>
</div>
</form>
</AdminModal>"""
content = content.replace(role_form, role_form_replacement)
with open('ui/components/AdminRolesPage.tsx', 'w') as f:
f.write(content)
print("Replaced Roles Form!")