Files
ds-chat/frontend/src/pages/AdminPage.css
T
ksmithandClaude Sonnet 5 66e9c80422 Add the ability to resend unaccepted invites (#60)
Previously the only way to resend was to re-invite the same email from
scratch, creating a whole new invite row. Adds a "Resend" action next
to Revoke on each pending invite -- rotates the token and refreshes the
7-day expiry on the same row (the old link stops working the moment
it's used, same instinct as a password-reset resend), then re-sends
the invite email.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-28 18:29:24 -06:00

331 lines
5.8 KiB
CSS

.admin-page {
/* Fills whatever's left in #root's flex column after UpdateBanner --
see tokens.css. height:100% resolved to the full viewport regardless
of the banner, causing the same off-screen-content bug ChatShellPage
had. */
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
background: var(--ds-void);
}
.admin-body {
flex: 1;
overflow-y: auto;
padding: var(--sp-6) var(--sp-8);
max-width: 960px;
width: 100%;
margin: 0 auto;
}
.admin-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: var(--sp-6);
}
.admin-header h1 {
font-size: 1.3rem;
margin: 0;
}
.admin-tabs {
display: flex;
gap: var(--sp-2);
border-bottom: 1px solid var(--ds-border);
margin-bottom: var(--sp-4);
}
.admin-tab {
background: transparent;
border: none;
color: var(--ds-muted);
font-size: 0.86rem;
font-weight: 700;
padding: 10px 4px;
cursor: pointer;
border-bottom: 2px solid transparent;
margin-bottom: -1px;
}
.admin-tab:hover {
color: var(--ds-text);
}
.admin-tab.active {
color: var(--ds-accent);
border-bottom-color: var(--ds-accent);
}
.admin-error {
color: var(--ds-danger);
font-size: 0.84rem;
margin: 0 0 var(--sp-4);
}
.admin-placeholder {
color: var(--ds-muted);
font-size: 0.9rem;
}
.admin-table {
width: 100%;
border-collapse: collapse;
font-size: 0.84rem;
}
.admin-table th {
text-align: left;
font-size: 0.7rem;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--ds-muted);
padding: 8px 10px;
border-bottom: 1px solid var(--ds-border);
}
.admin-table td {
padding: 10px;
border-bottom: 1px solid var(--ds-border);
vertical-align: middle;
}
.admin-table tbody tr:hover {
background: var(--ds-surface);
}
.status-badge {
display: inline-flex;
align-items: center;
border-radius: var(--radius-pill);
font-size: 0.68rem;
font-weight: 800;
padding: 2px 8px;
}
.status-badge.active {
border: 1px solid color-mix(in srgb, var(--ds-accent) 50%, transparent);
background: color-mix(in srgb, var(--ds-accent) 14%, transparent);
color: var(--ds-accent);
}
.status-badge.inactive {
border: 1px solid color-mix(in srgb, var(--ds-danger) 50%, transparent);
background: color-mix(in srgb, var(--ds-danger) 14%, transparent);
color: var(--ds-danger);
}
.admin-actions {
display: flex;
gap: 6px;
flex-wrap: wrap;
}
.admin-actions button {
background: transparent;
border: 1px solid var(--ds-border);
color: var(--ds-muted);
font-size: 0.72rem;
padding: 4px 8px;
border-radius: 6px;
cursor: pointer;
}
.admin-actions button:hover:not(:disabled) {
color: var(--ds-text);
border-color: var(--ds-accent);
}
.admin-actions button:disabled {
opacity: 0.4;
cursor: not-allowed;
}
.admin-load-more {
margin-top: var(--sp-4);
}
.admin-create-form {
display: flex;
gap: var(--sp-2);
margin-bottom: var(--sp-4);
}
.admin-create-form input {
flex: 1;
max-width: 280px;
background: var(--ds-surface-2);
border: 1px solid var(--ds-border);
border-radius: var(--radius);
padding: 7px 10px;
color: var(--ds-text);
font-size: 0.84rem;
}
.admin-bot-detail {
background: var(--ds-void-2);
}
.admin-invite-list {
background: var(--ds-void-2);
border: 1px solid var(--ds-border);
border-radius: var(--radius);
padding: var(--sp-3) var(--sp-4);
margin-bottom: var(--sp-6);
}
.admin-invite-list-label {
font-size: 0.7rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--ds-muted);
margin-bottom: var(--sp-2);
}
.admin-token-list {
display: flex;
flex-direction: column;
gap: 6px;
margin-bottom: var(--sp-3);
}
.admin-token-row {
display: flex;
align-items: center;
gap: var(--sp-3);
font-size: 0.8rem;
}
.admin-token-scopes {
font-family: var(--mono);
color: var(--ds-text);
}
.admin-token-meta {
color: var(--ds-muted);
flex: 1;
}
.admin-token-revoke {
background: transparent;
border: none;
color: var(--ds-danger);
font-size: 0.76rem;
cursor: pointer;
}
.admin-token-resend {
background: transparent;
border: none;
color: var(--ds-accent);
font-size: 0.76rem;
cursor: pointer;
}
.admin-issue-token {
display: flex;
align-items: center;
gap: var(--sp-3);
flex-wrap: wrap;
}
.admin-scope-checkbox {
display: flex;
align-items: center;
gap: 4px;
font-size: 0.78rem;
font-family: var(--mono);
color: var(--ds-muted);
}
.admin-new-token {
margin-top: var(--sp-3);
font-size: 0.8rem;
color: var(--ds-accent);
}
.admin-new-token code {
background: var(--ds-surface-2);
padding: 3px 8px;
border-radius: 6px;
word-break: break-all;
}
.admin-subheading {
font-size: 0.95rem;
margin: var(--sp-6) 0 var(--sp-3);
}
.admin-settings-form {
display: flex;
flex-direction: column;
gap: var(--sp-4);
max-width: 480px;
}
.admin-settings-row {
display: flex;
gap: var(--sp-3);
}
.admin-settings-field {
flex: 1;
display: flex;
flex-direction: column;
gap: 6px;
font-size: 0.78rem;
color: var(--ds-muted);
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.04em;
}
.admin-settings-field-narrow {
flex: 0 0 120px;
}
.admin-settings-field input {
background: var(--ds-surface-2);
border: 1px solid var(--ds-border);
border-radius: var(--radius);
padding: 9px 11px;
font-size: 0.9rem;
color: var(--ds-text);
text-transform: none;
letter-spacing: 0;
font-weight: 400;
}
.admin-settings-field input:focus {
border-color: var(--ds-accent);
outline: none;
}
.admin-settings-checkbox {
display: flex;
align-items: center;
gap: 8px;
font-size: 0.86rem;
color: var(--ds-text);
}
.admin-settings-actions {
display: flex;
gap: var(--sp-2);
}
.admin-settings-test-result {
font-size: 0.84rem;
color: var(--ds-muted);
margin: 0;
}
.admin-settings-hint {
font-size: 0.82rem;
color: var(--ds-muted);
margin: -4px 0 0;
}