Files

408 lines
15 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#302224" />
<title>Overview · The Steward</title>
<link rel="icon" href="mark.svg" type="image/svg+xml" />
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<a class="skip-link" href="#mainContent">Skip to content</a>
<div class="app-shell">
<aside class="sidebar" aria-label="Dashboard navigation">
<a class="brand" href="/" aria-label="The Steward home">
<img src="mark.svg" alt="" />
<span
><small>THE</small>Steward<span class="brand-period">.</span></span
>
</a>
<nav class="tabs" aria-label="Server management">
<button class="tab active" data-tab="settings" aria-current="page">
<svg><use href="icons.svg#grid" /></svg>Overview
</button>
<button class="tab" data-tab="permissions">
<svg><use href="icons.svg#key" /></svg>Permissions
<span class="nav-count" id="navCommandCount">–</span>
</button>
<button class="tab" data-tab="warnings">
<svg><use href="icons.svg#shield" /></svg>Warnings
</button>
</nav>
<div class="sidebar__section-label server-label">
SERVERS <span id="guildCount">–</span>
</div>
<div class="search-field sidebar-search">
<svg><use href="icons.svg#search" /></svg>
<input
type="search"
id="guildSearch"
aria-label="Search servers"
placeholder="Search servers"
/>
</div>
<div class="guild-list" id="guildList"></div>
<div class="skeleton-list" id="guildListSkeleton" hidden>
<div class="skeleton-line"></div>
<div class="skeleton-line"></div>
<div class="skeleton-line"></div>
</div>
<div class="empty-state" id="guildEmpty" hidden>
No servers available.
</div>
<div class="sidebar-bottom">
<div class="profile">
<div class="profile-avatar" id="userInitial">S</div>
<div class="profile__text">
<strong id="userDisplay">Loading…</strong
><span id="sessionExpiry">Discord account</span>
</div>
<button
class="icon-button"
id="logoutButton"
aria-label="Log out"
title="Log out"
>
<svg><use href="icons.svg#logout" /></svg>
</button>
</div>
</div>
</aside>
<div class="workspace">
<header class="topbar">
<div class="breadcrumb">
Dashboard <span>/</span><strong id="currentPage">Overview</strong>
</div>
<a class="icon-button" href="/" aria-label="Home" title="Home"
><svg><use href="icons.svg#home" /></svg
></a>
</header>
<main class="content" id="mainContent" tabindex="-1">
<div class="error-banner" id="errorBanner" role="alert" hidden>
<p data-role="error-message"></p>
<button class="button button--ghost" data-role="error-copy">
Copy details
</button>
</div>
<section class="page-heading">
<h1 id="pageTitle">Overview</h1>
<div class="guild-header">
<span class="guild-avatar" id="guildHeaderFallback">S</span
><img id="guildHeaderIcon" alt="" hidden /><strong
id="guildHeaderName"
>Select a server</strong
>
</div>
</section>
<section
class="overview-stats"
id="overviewStats"
aria-label="Server summary"
>
<article class="overview-stat">
<div class="stat-heading">
<span>Bot status</span
><button
class="icon-button"
id="refreshBotButton"
aria-label="Refresh bot status"
title="Refresh bot status"
hidden
>
↻
</button>
</div>
<strong
class="stat-value stat-value--status"
id="overviewBotStatus"
>–</strong
>
</article>
<article class="overview-stat">
<div class="stat-heading">
<button class="text-link" data-open-tab="permissions">
Commands ↗</button
><svg><use href="icons.svg#terminal" /></svg>
</div>
<strong class="stat-value" id="overviewCommandCount">–</strong>
</article>
<article class="overview-stat">
<div class="stat-heading">
<span>Admin roles</span
><svg><use href="icons.svg#users" /></svg>
</div>
<strong class="stat-value" id="overviewRoleCount">–</strong>
</article>
<article class="overview-stat">
<div class="stat-heading">
<span>Restricted commands</span
><svg><use href="icons.svg#key" /></svg>
</div>
<strong class="stat-value" id="overviewRestrictedCount">–</strong>
</article>
</section>
<div class="callout" id="botInactiveCallout" hidden>
<svg><use href="icons.svg#info" /></svg>
<p>Invite the bot to edit settings.</p>
<button class="button button--primary" id="inviteButton" hidden>
Invite bot ↗
</button>
</div>
<div class="empty-state panel" id="workspaceEmpty" hidden>
Select a server to get started.
</div>
<section
class="settings-layout"
id="settingsPanel"
aria-labelledby="adminTitle"
hidden
>
<div class="panel admin-panel">
<div class="panel__header">
<div class="section-title">
<span class="section-icon"
><svg><use href="icons.svg#users" /></svg
></span>
<h2 id="adminTitle">Admin access</h2>
</div>
</div>
<div class="admin-fields">
<div class="field">
<span id="adminRolesLabel">Roles</span>
<div id="adminRolesPicker"></div>
</div>
<div class="field">
<label for="adminUserInput">Members</label>
<div class="input-row">
<input
type="text"
id="adminUserInput"
placeholder="Discord user IDs, comma-separated"
/><button
class="button button--soft"
id="addAdminUserButton"
>
Add
</button>
</div>
<div class="chip-list" id="adminUserChips"></div>
</div>
</div>
<div class="panel-footnote">
<svg><use href="icons.svg#info" /></svg>Admins bypass command
restrictions.
</div>
</div>
</section>
<section
class="panel"
id="permissionsPanel"
aria-labelledby="permissionsTitle"
hidden
>
<div class="panel__header panel__header--split">
<h2 id="permissionsTitle">Commands</h2>
<div class="button-row">
<button class="button button--ghost" id="clearAllCommands">
Reset restrictions</button
><button class="button" id="copyFromGuild">
<svg><use href="icons.svg#copy" /></svg>Copy from server
</button>
</div>
</div>
<div class="stats-grid">
<article class="stat-card">
<span>Total</span><strong id="permissionTotalCount">0</strong>
</article>
<article class="stat-card">
<span>Restricted</span
><strong id="permissionRestrictedCount">0</strong>
</article>
<article class="stat-card">
<span>Default access</span
><strong id="permissionOpenCount">0</strong>
</article>
<article class="stat-card">
<span>Unsaved</span
><strong id="permissionChangedCount">0</strong>
</article>
</div>
<div class="toolbar">
<div class="search-field">
<svg><use href="icons.svg#search" /></svg
><input
type="search"
id="commandSearch"
aria-label="Search commands"
placeholder="Search commands"
/>
</div>
<select id="commandFilter" aria-label="Filter commands">
<option value="all">All commands</option>
<option value="restricted">Restricted</option>
<option value="open">Default access</option>
<option value="changed">Unsaved</option>
</select>
</div>
<p class="field-hint">Discord permissions still apply.</p>
<div class="command-list" id="commandsList"></div>
<div class="empty-state" id="commandsEmpty" hidden>
No matching commands.
</div>
<div class="custom-command">
<label for="newCommandInput">Custom command</label>
<div class="input-row">
<input
type="text"
id="newCommandInput"
placeholder="command-name"
maxlength="32"
/><button class="button" id="addCommandButton">Add</button>
</div>
</div>
</section>
<section
class="warnings-layout"
id="warningsPanel"
aria-label="Member warnings"
hidden
>
<div class="panel warnings-pane">
<div class="panel__header"><h2>Member</h2></div>
<div class="field">
<label for="warningsUserSearch">Search</label>
<div class="search-field">
<svg><use href="icons.svg#search" /></svg
><input
type="search"
id="warningsUserSearch"
placeholder="Member name"
maxlength="64"
/>
</div>
<span
class="field-hint"
id="warningsSearchStatus"
role="status"
></span>
</div>
<div class="member-list" id="warningsUserResults"></div>
<div class="field">
<label for="warningsUserInput">Or enter a user ID</label
><input
type="text"
id="warningsUserInput"
placeholder="123456789012345678"
inputmode="numeric"
/>
</div>
<div class="selected-user-card" id="warningsSelectedCard" hidden>
<strong id="warningsSelectedUser"></strong
><span class="field-hint" id="warningsSelectedHint"></span>
</div>
<div class="button-row warning-actions">
<button class="button button--dark" id="fetchWarningsButton">
Load history</button
><button class="button button--danger" id="clearWarningsButton">
Clear warnings
</button>
</div>
<div
class="spinner"
id="warningsSpinner"
aria-label="Loading warnings"
hidden
></div>
</div>
<div class="panel warnings-pane">
<div class="panel__header"><h2>History</h2></div>
<div class="stats-grid stats-grid--compact">
<article class="stat-card">
<span>Warnings</span
><strong id="warningsTotalCount">–</strong>
</article>
<article class="stat-card">
<span>Latest</span
><strong class="stat-value--small" id="warningsLatestDate"
>–</strong
>
</article>
</div>
<div class="empty-state" id="warningsEmpty">
Select a member to view warnings.
</div>
<ul id="warningsList"></ul>
<div class="divider"></div>
<div class="field">
<label for="warningReasonInput">Reason</label
><textarea
id="warningReasonInput"
placeholder="Reason for warning"
maxlength="500"
rows="4"
></textarea>
<div class="field__meta">
<span id="warningStatus" role="status"></span
><span class="field-hint" id="warningCharCount">0/500</span>
</div>
</div>
<button class="button button--primary" id="addWarningButton">
Add warning
</button>
</div>
</section>
<div class="save-bar" id="saveBar" role="status" hidden>
<div>
<span class="save-dot"></span><strong>Unsaved changes</strong>
</div>
<div class="button-row">
<button class="button button--ghost" id="discardChangesButton">
Discard</button
><button
class="button button--primary"
id="savePermissionsButton"
>
Save changes <svg><use href="icons.svg#check" /></svg>
</button>
</div>
</div>
<div
class="panel skeleton-panel"
id="contentSkeleton"
aria-label="Loading server"
hidden
>
<div class="skeleton-line"></div>
<div class="skeleton-line"></div>
<div class="skeleton-line"></div>
</div>
</main>
</div>
</div>
<div
class="toast-container"
id="toastContainer"
role="status"
aria-live="polite"
></div>
<dialog class="modal" id="copyModal" aria-labelledby="copyTitle">
<div class="modal__content">
<h2 id="copyTitle">Copy permissions</h2>
<label for="copyGuildSelect">From server</label
><select id="copyGuildSelect"></select>
<p class="field-hint">Replace unavailable roles before saving.</p>
<div class="button-row">
<button class="button button--ghost" id="cancelCopyButton">
Cancel</button
><button class="button button--primary" id="confirmCopyButton">
Copy
</button>
</div>
</div>
</dialog>
<script src="app.js"></script>
<script src="dashboard.js"></script>
</body>
</html>