- delete public/js/notifications.js (521 LOC) - remove notifications/patterns/surge/chat/priority/bosscord/accountinfo/threads UI sections - remove 3 /api/notifications/* proxy routes from server.js - untrack settings-site backup files from git - ~926 LOC removed from settings-site
269 lines
21 KiB
HTML
269 lines
21 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Broccolini Settings</title>
|
|
<link rel="stylesheet" href="/css/main.css">
|
|
</head>
|
|
<body>
|
|
<div id="loading" class="loading"><div class="spinner"></div></div>
|
|
<div id="toast-container"></div>
|
|
|
|
<!-- Sidebar -->
|
|
<div class="sidebar-backdrop" id="sidebar-backdrop" aria-hidden="true"></div>
|
|
<nav class="sidebar" id="sidebar">
|
|
<div class="logo">Broccolini Settings</div>
|
|
<a href="/" class="active">Home</a>
|
|
<a href="/core">Core</a>
|
|
<a href="/channels">Channels</a>
|
|
<a href="/categories">Categories</a>
|
|
<a href="/gmail">Gmail</a>
|
|
<a href="/behavior">Ticket Behavior</a>
|
|
<a href="/threads">Staff Threads</a>
|
|
<a href="/pins">Pin Messages</a>
|
|
<a href="/logging">Logging</a>
|
|
<a href="/automation">Automation</a>
|
|
<a href="/appearance">Appearance</a>
|
|
<a href="/staff">Staff</a>
|
|
<a href="/advanced">Advanced</a>
|
|
</nav>
|
|
|
|
<!-- Top bar -->
|
|
<div class="topbar">
|
|
<button type="button" class="menu-toggle" id="menu-toggle" aria-label="Toggle navigation" aria-expanded="false" aria-controls="sidebar">
|
|
<span class="menu-toggle-bars" aria-hidden="true"></span>
|
|
</button>
|
|
<h1>Settings</h1>
|
|
<div class="status">
|
|
<span class="dot" id="bot-status-dot"></span>
|
|
<span id="bot-status-text">Checking...</span>
|
|
</div>
|
|
<div class="actions">
|
|
<button type="button" id="logout-btn">Logout</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Main content -->
|
|
<div class="main">
|
|
|
|
<!-- 0. Landing -->
|
|
<div class="section landing-section" id="s-landing">
|
|
<div class="landing-grid">
|
|
<a class="landing-card" href="/core"><div class="landing-card-body"><h3>Core</h3><p>Discord credentials and guild</p></div><span class="chevron">›</span></a>
|
|
<a class="landing-card" href="/channels"><div class="landing-card-body"><h3>Channels</h3><p>Log, transcript, and alert channels</p></div><span class="chevron">›</span></a>
|
|
<a class="landing-card" href="/categories"><div class="landing-card-body"><h3>Categories</h3><p>Ticket categories and escalation</p></div><span class="chevron">›</span></a>
|
|
<a class="landing-card" href="/gmail"><div class="landing-card-body"><h3>Gmail</h3><p>Google OAuth and email settings</p></div><span class="chevron">›</span></a>
|
|
<a class="landing-card" href="/behavior"><div class="landing-card-body"><h3>Ticket Behavior</h3><p>Automation, limits, and messages</p></div><span class="chevron">›</span></a>
|
|
<a class="landing-card" href="/threads"><div class="landing-card-body"><h3>Staff Threads</h3><p>Private staff discussion threads</p></div><span class="chevron">›</span></a>
|
|
<a class="landing-card" href="/pins"><div class="landing-card-body"><h3>Pin Messages</h3><p>Auto-pin welcome and escalations</p></div><span class="chevron">›</span></a>
|
|
<a class="landing-card" href="/logging"><div class="landing-card-body"><h3>Logging</h3><p>Log channel configuration</p></div><span class="chevron">›</span></a>
|
|
<a class="landing-card" href="/automation"><div class="landing-card-body"><h3>Automation</h3><p>Polling intervals and timers</p></div><span class="chevron">›</span></a>
|
|
<a class="landing-card" href="/appearance"><div class="landing-card-body"><h3>Appearance</h3><p>Colors, labels, emojis</p></div><span class="chevron">›</span></a>
|
|
<a class="landing-card" href="/staff"><div class="landing-card-body"><h3>Staff</h3><p>Staff IDs, emojis, admin</p></div><span class="chevron">›</span></a>
|
|
<a class="landing-card" href="/advanced"><div class="landing-card-body"><h3>Advanced</h3><p>Ports, URLs, game list, branding</p></div><span class="chevron">›</span></a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 1. Core -->
|
|
<div class="section" id="s-core">
|
|
<div class="section-header"><h2>Core</h2><p>Discord bot credentials and guild</p><span class="chevron">▼</span></div>
|
|
<div class="section-body"><div class="field-grid">
|
|
<div class="field"><label>Discord Token</label><input type="password" data-key="DISCORD_TOKEN" placeholder="Bot token"></div>
|
|
<div class="field"><label>Application ID</label><input type="text" data-key="DISCORD_APPLICATION_ID"></div>
|
|
<div class="field"><label>Guild ID</label><input type="text" data-key="DISCORD_GUILD_ID"></div>
|
|
</div></div>
|
|
</div>
|
|
|
|
<!-- 2. Channels -->
|
|
<div class="section" id="s-channels">
|
|
<div class="section-header"><h2>Channels</h2><p>Channel assignments for logging, transcripts, and alerts</p><span class="chevron">▼</span></div>
|
|
<div class="section-body"><div class="field-grid">
|
|
<div class="field"><label>Transcript Channel</label><input type="text" data-key="TRANSCRIPT_CHANNEL_ID" data-smart="channel"></div>
|
|
<div class="field"><label>Logging Channel</label><input type="text" data-key="LOGGING_CHANNEL_ID" data-smart="channel"></div>
|
|
<div class="field"><label>Debugging Channel</label><input type="text" data-key="DEBUGGING_CHANNEL_ID" data-smart="channel"></div>
|
|
<div class="field"><label>Gmail Log Channel</label><input type="text" data-key="GMAIL_LOG_CHANNEL_ID" data-smart="channel"></div>
|
|
<div class="field"><label>Automation Log Channel</label><input type="text" data-key="AUTOMATION_LOG_CHANNEL_ID" data-smart="channel"></div>
|
|
<div class="field"><label>Rename Log Channel</label><input type="text" data-key="RENAME_LOG_CHANNEL_ID" data-smart="channel"></div>
|
|
<div class="field"><label>Security Log Channel</label><input type="text" data-key="SECURITY_LOG_CHANNEL_ID" data-smart="channel"></div>
|
|
<div class="field"><label>System Log Channel</label><input type="text" data-key="SYSTEM_LOG_CHANNEL_ID" data-smart="channel"></div>
|
|
</div></div>
|
|
</div>
|
|
|
|
<!-- 3. Categories -->
|
|
<div class="section" id="s-categories">
|
|
<div class="section-header"><h2>Categories</h2><p>Ticket category assignments and escalation targets</p><span class="chevron">▼</span></div>
|
|
<div class="section-body"><div class="field-grid">
|
|
<div class="field"><label>Email Ticket Category</label><input type="text" data-key="TICKET_CATEGORY_ID" data-smart="category"></div>
|
|
<div class="field"><label>Discord Ticket Category</label><input type="text" data-key="DISCORD_TICKET_CATEGORY_ID" data-smart="category"></div>
|
|
<div class="field"><label>Email T2 Category</label><input type="text" data-key="EMAIL_ESCALATED2_CHANNEL_ID" data-smart="category"></div>
|
|
<div class="field"><label>Discord T2 Category</label><input type="text" data-key="DISCORD_ESCALATED2_CHANNEL_ID" data-smart="category"></div>
|
|
<div class="field"><label>Email T3 Category</label><input type="text" data-key="EMAIL_ESCALATED3_CHANNEL_ID" data-smart="category"></div>
|
|
<div class="field"><label>Discord T3 Category</label><input type="text" data-key="DISCORD_ESCALATED3_CHANNEL_ID" data-smart="category"></div>
|
|
<div class="field"><label>Category Name</label><input type="text" data-key="TICKET_CATEGORY_NAME"></div>
|
|
<div class="field"><label>T2 Category Name</label><input type="text" data-key="TICKET_T2_CATEGORY_NAME"></div>
|
|
<div class="field"><label>T3 Category Name</label><input type="text" data-key="TICKET_T3_CATEGORY_NAME"></div>
|
|
</div></div>
|
|
</div>
|
|
|
|
<!-- 4. Gmail -->
|
|
<div class="section" id="s-gmail">
|
|
<div class="section-header"><h2>Gmail</h2><p>Google OAuth credentials and email settings</p><span class="chevron">▼</span></div>
|
|
<div class="section-body"><div class="field-grid">
|
|
<div class="field"><label>Google Client ID</label><input type="text" data-key="GOOGLE_CLIENT_ID"></div>
|
|
<div class="field"><label>Google Client Secret</label><input type="password" data-key="GOOGLE_CLIENT_SECRET"></div>
|
|
<div class="field"><label>Refresh Token</label><input type="password" data-key="REFRESH_TOKEN"></div>
|
|
<div class="field"><label>Support Email</label><input type="email" data-key="MY_EMAIL"></div>
|
|
</div></div>
|
|
</div>
|
|
|
|
<!-- 5. Ticket Behavior -->
|
|
<div class="section" id="s-behavior">
|
|
<div class="section-header"><h2>Ticket Behavior</h2><p>Automation, limits, and messages</p><span class="chevron">▼</span></div>
|
|
<div class="section-body"><div class="field-grid">
|
|
<div class="field"><label>Auto-Close</label><div class="toggle-wrap"><label class="toggle"><input type="checkbox" data-key="AUTO_CLOSE_ENABLED"><span class="slider"></span></label><span>Enabled</span></div></div>
|
|
<div class="field"><label>Auto-Close Hours</label><input type="number" data-key="AUTO_CLOSE_AFTER_HOURS"></div>
|
|
<div class="field"><label>Reminders</label><div class="toggle-wrap"><label class="toggle"><input type="checkbox" data-key="REMINDER_ENABLED"><span class="slider"></span></label><span>Enabled</span></div></div>
|
|
<div class="field"><label>Reminder Hours</label><input type="number" data-key="REMINDER_AFTER_HOURS"></div>
|
|
<div class="field"><label>Auto-Unclaim</label><div class="toggle-wrap"><label class="toggle"><input type="checkbox" data-key="AUTO_UNCLAIM_ENABLED"><span class="slider"></span></label><span>Enabled</span></div></div>
|
|
<div class="field"><label>Auto-Unclaim Hours</label><input type="number" data-key="AUTO_UNCLAIM_AFTER_HOURS"></div>
|
|
<div class="field"><label>Allow Claim Overwrite</label><div class="toggle-wrap"><label class="toggle"><input type="checkbox" data-key="ALLOW_CLAIM_OVERWRITE"><span class="slider"></span></label><span>Enabled</span></div></div>
|
|
<div class="field"><label>Global Ticket Limit</label><input type="number" data-key="GLOBAL_TICKET_LIMIT"></div>
|
|
<div class="field"><label>Rate Limit (per user)</label><input type="number" data-key="RATE_LIMIT_TICKETS_PER_USER"></div>
|
|
<div class="field"><label>Rate Limit Window (min)</label><input type="number" data-key="RATE_LIMIT_WINDOW_MINUTES"></div>
|
|
<div class="field"><label>Role to Ping</label><input type="text" data-key="ROLE_ID_TO_PING" data-smart="role"></div>
|
|
<div class="field full-width"><label>Welcome Message</label><textarea data-key="TICKET_WELCOME_MESSAGE" rows="3"></textarea></div>
|
|
<div class="field full-width"><label>Claimed Message</label><textarea data-key="TICKET_CLAIMED_MESSAGE" rows="2"></textarea><div class="hint">Variables: {staff_mention}, {staff_name}</div></div>
|
|
<div class="field full-width"><label>Unclaimed Message</label><textarea data-key="TICKET_UNCLAIMED_MESSAGE" rows="2"></textarea></div>
|
|
<div class="field full-width"><label>Escalation Message</label><textarea data-key="ESCALATION_MESSAGE" rows="3"></textarea><div class="hint">Variables: {support_name}</div></div>
|
|
<div class="field full-width"><label>Reminder Message</label><textarea data-key="REMINDER_MESSAGE" rows="2"></textarea><div class="hint">Variables: {ping}, {hours}</div></div>
|
|
</div></div>
|
|
</div>
|
|
|
|
<!-- 6. Staff Threads -->
|
|
<div class="section" id="s-threads">
|
|
<div class="section-header"><h2>Staff Threads</h2><p>Private staff discussion threads on ticket channels</p><span class="chevron">▼</span></div>
|
|
<div class="section-body"><div class="field-grid">
|
|
<div class="field"><label>Enabled</label><div class="toggle-wrap"><label class="toggle"><input type="checkbox" data-key="STAFF_THREAD_ENABLED"><span class="slider"></span></label><span>Enabled</span></div></div>
|
|
<div class="field"><label>Thread Name</label><input type="text" data-key="STAFF_THREAD_NAME"></div>
|
|
<div class="field"><label>Auto-Add Role</label><div class="toggle-wrap"><label class="toggle"><input type="checkbox" data-key="STAFF_THREAD_AUTO_ADD_ROLE"><span class="slider"></span></label><span>Enabled</span></div></div>
|
|
<div class="field"><label>Staff Thread Role</label><input type="text" data-key="STAFF_THREAD_ROLE_ID" data-smart="role"></div>
|
|
</div></div>
|
|
</div>
|
|
|
|
<!-- 7. Pin Messages -->
|
|
<div class="section" id="s-pins">
|
|
<div class="section-header"><h2>Pin Messages</h2><p>Auto-pin welcome and escalation messages</p><span class="chevron">▼</span></div>
|
|
<div class="section-body"><div class="field-grid">
|
|
<div class="field"><label>Pin Initial Message</label><div class="toggle-wrap"><label class="toggle"><input type="checkbox" data-key="PIN_INITIAL_MESSAGE_ENABLED"><span class="slider"></span></label><span>Enabled</span></div></div>
|
|
<div class="field"><label>Pin Escalation Message</label><div class="toggle-wrap"><label class="toggle"><input type="checkbox" data-key="PIN_ESCALATION_MESSAGE_ENABLED"><span class="slider"></span></label><span>Enabled</span></div></div>
|
|
<div class="field"><label>Suppress Pin Notice</label><div class="toggle-wrap"><label class="toggle"><input type="checkbox" data-key="PIN_SUPPRESS_SYSTEM_MESSAGE"><span class="slider"></span></label><span>Enabled</span></div></div>
|
|
</div></div>
|
|
</div>
|
|
|
|
<!-- 10. Logging -->
|
|
<div class="section" id="s-logging">
|
|
<div class="section-header"><h2>Logging</h2><p>Log channel configuration (channels set in Channels section)</p><span class="chevron">▼</span></div>
|
|
<div class="section-body"><div class="field-grid">
|
|
<div class="field full-width"><p class="logging-hint">Log channels are configured in the <a href="/channels">Channels</a> section. This section shows which logs are active based on configured channels.</p></div>
|
|
</div></div>
|
|
</div>
|
|
|
|
<!-- 11. Automation -->
|
|
<div class="section" id="s-automation">
|
|
<div class="section-header"><h2>Automation</h2><p>Polling intervals and timer durations</p><span class="chevron">▼</span></div>
|
|
<div class="section-body"><div class="field-grid">
|
|
<div class="field"><label>Gmail Poll Interval (sec)</label><select data-key="GMAIL_POLL_INTERVAL_SECONDS">
|
|
<option value="5">5s</option><option value="10">10s</option><option value="30">30s</option><option value="45">45s</option>
|
|
<option value="60">1m</option><option value="120">2m</option><option value="180">3m</option><option value="240">4m</option>
|
|
<option value="300">5m</option><option value="600">10m</option>
|
|
</select></div>
|
|
<div class="field"><label>Force-Close Timer (sec)</label><select data-key="FORCE_CLOSE_TIMER_SECONDS">
|
|
<option value="5">5s</option><option value="10">10s</option><option value="30">30s</option><option value="45">45s</option>
|
|
<option value="60">1m</option><option value="120">2m</option><option value="180">3m</option><option value="240">4m</option>
|
|
<option value="300">5m</option><option value="600">10m</option>
|
|
</select></div>
|
|
</div></div>
|
|
</div>
|
|
|
|
<!-- 12. Appearance -->
|
|
<div class="section" id="s-appearance">
|
|
<div class="section-header"><h2>Appearance</h2><p>Embed colors, button labels, and emojis</p><span class="chevron">▼</span></div>
|
|
<div class="section-body"><div class="field-grid">
|
|
<div class="field"><label>Open Color</label><div class="color-field"><input type="color" data-key="EMBED_COLOR_OPEN"><span>Open tickets</span></div></div>
|
|
<div class="field"><label>Closed Color</label><div class="color-field"><input type="color" data-key="EMBED_COLOR_CLOSED"><span>Closed tickets</span></div></div>
|
|
<div class="field"><label>Claimed Color</label><div class="color-field"><input type="color" data-key="EMBED_COLOR_CLAIMED"><span>Claimed tickets</span></div></div>
|
|
<div class="field"><label>Escalated Color</label><div class="color-field"><input type="color" data-key="EMBED_COLOR_ESCALATED"><span>Escalated tickets</span></div></div>
|
|
<div class="field"><label>Info Color</label><div class="color-field"><input type="color" data-key="EMBED_COLOR_INFO"><span>Info embeds</span></div></div>
|
|
<div class="field"><label>Close Button Label</label><input type="text" data-key="BUTTON_LABEL_CLOSE"></div>
|
|
<div class="field"><label>Claim Button Label</label><input type="text" data-key="BUTTON_LABEL_CLAIM"></div>
|
|
<div class="field"><label>Unclaim Button Label</label><input type="text" data-key="BUTTON_LABEL_UNCLAIM"></div>
|
|
<div class="field"><label>Close Emoji</label><input type="text" data-key="BUTTON_EMOJI_CLOSE"></div>
|
|
<div class="field"><label>Claim Emoji</label><input type="text" data-key="BUTTON_EMOJI_CLAIM"></div>
|
|
<div class="field"><label>Unclaim Emoji</label><input type="text" data-key="BUTTON_EMOJI_UNCLAIM"></div>
|
|
</div></div>
|
|
</div>
|
|
|
|
<!-- 13. Staff -->
|
|
<div class="section" id="s-staff">
|
|
<div class="section-header"><h2>Staff</h2><p>Admin and staff role settings</p><span class="chevron">▼</span></div>
|
|
<div class="section-body"><div class="field-grid">
|
|
<div class="field"><label>Admin ID</label><input type="text" data-key="ADMIN_ID" data-smart="member"></div>
|
|
<div class="field full-width"><label>Additional Staff Roles (comma-separated)</label><input type="text" data-key="ADDITIONAL_STAFF_ROLES"><div class="hint">Role IDs with staff permissions</div></div>
|
|
<div class="field full-width"><label>Blacklisted Roles (comma-separated)</label><input type="text" data-key="BLACKLISTED_ROLES"><div class="hint">Role IDs that cannot open tickets</div></div>
|
|
</div></div>
|
|
</div>
|
|
|
|
<!-- 14. Advanced -->
|
|
<div class="section" id="s-advanced">
|
|
<div class="section-header"><h2>Advanced</h2><p>Ports, URLs, game list, branding</p><span class="chevron">▼</span></div>
|
|
<div class="section-body"><div class="field-grid">
|
|
<div class="field"><label>Bot Port</label><input type="number" data-key="DISCORD_ONLY_PORT"></div>
|
|
<div class="field"><label>Healthcheck Host</label><input type="text" data-key="HEALTHCHECK_HOST" placeholder="leave empty for all interfaces"></div>
|
|
<div class="field"><label>Settings Port</label><input type="number" data-key="SETTINGS_PORT"></div>
|
|
<div class="field"><label>Settings Domain</label><input type="text" data-key="SETTINGS_DOMAIN"></div>
|
|
<div class="field"><label>Internal API Port</label><input type="number" data-key="INTERNAL_API_PORT"></div>
|
|
<div class="field"><label>Support Name</label><input type="text" data-key="SUPPORT_NAME"></div>
|
|
<div class="field"><label>Logo URL</label><input type="text" data-key="LOGO_URL"></div>
|
|
<div class="field full-width"><label>Game List (comma-separated)</label><textarea data-key="GAME_LIST" rows="3"></textarea></div>
|
|
<div class="field full-width"><label>Email Signature (HTML, use \n for breaks)</label><textarea data-key="EMAIL_SIGNATURE" rows="3"></textarea></div>
|
|
<div class="field full-width"><label>Close Subject Prefix</label><input type="text" data-key="TICKET_CLOSE_SUBJECT_PREFIX"></div>
|
|
<div class="field full-width"><label>Close Message (email body)</label><textarea data-key="TICKET_CLOSE_MESSAGE" rows="2"></textarea></div>
|
|
<div class="field full-width"><label>Discord Close Message</label><textarea data-key="DISCORD_CLOSE_MESSAGE" rows="2"></textarea></div>
|
|
<div class="field full-width"><label>Transcript Message</label><textarea data-key="DISCORD_TRANSCRIPT_MESSAGE" rows="2"></textarea><div class="hint">Variables: {channel_name}, {email}, {date_opened}, {date_closed}</div></div>
|
|
<div class="field full-width"><label>Auto-Close Message</label><textarea data-key="DISCORD_AUTO_CLOSE_MESSAGE" rows="2"></textarea></div>
|
|
</div></div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- Save bar -->
|
|
<div id="save-bar" class="save-bar">
|
|
<span id="change-count">0 unsaved changes</span>
|
|
<div class="save-actions">
|
|
<button type="button" id="save-btn">Save</button>
|
|
<button type="button" id="save-restart-btn" class="danger">Save & Restart Now</button>
|
|
<button type="button" id="schedule-restart-btn" class="secondary">Schedule restart...</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Schedule modal -->
|
|
<div id="schedule-modal" class="modal hidden" role="dialog" aria-modal="true" aria-labelledby="schedule-modal-title">
|
|
<div class="modal-card">
|
|
<h3 id="schedule-modal-title">Schedule restart</h3>
|
|
<input type="datetime-local" id="schedule-datetime" aria-label="Restart date and time">
|
|
<div class="modal-actions">
|
|
<button type="button" id="schedule-confirm-btn">Schedule</button>
|
|
<button type="button" id="schedule-cancel-btn" class="secondary">Cancel</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script defer src="/js/util.js"></script>
|
|
<script defer src="/js/router.js"></script>
|
|
<script defer src="/js/fields.js"></script>
|
|
<script defer src="/js/discord.js"></script>
|
|
<script defer src="/js/app.js"></script>
|
|
</body>
|
|
</html>
|