diff --git a/website/css/style.css b/website/css/style.css
index 23ea546..9ea1452 100644
--- a/website/css/style.css
+++ b/website/css/style.css
@@ -31,8 +31,6 @@
--font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
--table-header-bg: #1e2430;
--row-hover-bg: #252c3a;
- --test-row-bg: #2a2618;
- --test-row-hover-bg: #3a321f;
--sticky-shadow: rgba(0, 0, 0, 0.35);
/* Incomplete translation highlight */
--trans-missing-bg: #1c222d;
@@ -686,18 +684,6 @@ table.data-table th {
table.data-table tr:hover td {
background: var(--row-hover-bg);
}
-table.data-table tbody tr.row-test-data td {
- background: var(--test-row-bg);
-}
-table.data-table tbody tr.row-test-data:hover td {
- background: var(--test-row-hover-bg);
-}
-#qdb-table tbody tr.row-test-data td {
- background: var(--test-row-bg);
-}
-#qdb-table tbody tr.row-test-data:hover td {
- background: var(--test-row-hover-bg);
-}
table.data-table .sticky-col {
position: sticky;
left: 0;
@@ -710,12 +696,6 @@ table.data-table thead th.sticky-col {
top: 0;
background: var(--table-header-bg);
}
-table.data-table tbody tr.row-test-data td.sticky-col {
- background: var(--test-row-bg);
-}
-table.data-table tbody tr.row-test-data:hover td.sticky-col {
- background: var(--test-row-hover-bg);
-}
th.sortable { cursor: pointer; user-select: none; }
th.sortable::after { content: ' \2195'; opacity: .4; }
th.sort-asc::after { content: ' \2191'; opacity: 1; }
@@ -1250,18 +1230,6 @@ table.data-table tbody tr.row-orphan-category td {
border-color: var(--primary);
}
-.coach-list-item.row-test-data {
- background: var(--test-row-bg);
-}
-
-.coach-list-item.row-test-data:hover {
- background: var(--test-row-hover-bg);
-}
-
-.coach-list-item.row-test-data.active {
- background: var(--primary-subtle);
-}
-
.coach-list-empty {
padding: 20px 12px;
text-align: center;
@@ -3034,19 +3002,133 @@ select:disabled {
letter-spacing: .04em;
color: #ca8a04;
}
-.client-coach-band-select {
- min-width: 6.5rem;
+
+/* Coach category picker (clients list) */
+.coach-band-picker {
+ position: relative;
+ display: inline-flex;
max-width: 100%;
- padding: 2px 6px;
- font-size: .75rem;
- border-radius: 6px;
- border: 1px solid var(--border);
- background: var(--surface, #fff);
- color: var(--text);
}
-.client-coach-band-select:disabled {
- opacity: 0.65;
- cursor: wait;
+.coach-band-trigger {
+ display: inline-flex;
+ align-items: center;
+ gap: 4px;
+ padding: 2px 6px 2px 4px;
+ border: 1px solid var(--border);
+ border-radius: 999px;
+ background: var(--surface);
+ color: inherit;
+ cursor: pointer;
+ transition: border-color 0.15s, background 0.15s, box-shadow 0.15s;
+ max-width: 100%;
+}
+.coach-band-trigger:hover {
+ border-color: color-mix(in srgb, var(--primary) 45%, var(--border));
+ background: var(--surface-hover, rgba(0, 0, 0, 0.03));
+}
+.coach-band-picker.is-open .coach-band-trigger,
+.coach-band-trigger:focus-visible {
+ outline: none;
+ border-color: var(--primary);
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary) 22%, transparent);
+}
+.coach-band-trigger-badge .band-badge {
+ margin: 0;
+}
+.coach-band-trigger-caret {
+ font-size: .65rem;
+ color: var(--text-secondary);
+ line-height: 1;
+ flex-shrink: 0;
+}
+.coach-band-picker.is-saving .coach-band-trigger {
+ opacity: 0.6;
+ pointer-events: none;
+}
+.coach-band-menu {
+ min-width: 11.5rem;
+ padding: 10px;
+ border-radius: 10px;
+ border: 1px solid var(--border);
+ background: var(--surface);
+ box-shadow: var(--shadow-lg);
+}
+.coach-band-menu-label {
+ margin: 0 0 8px;
+ font-size: .7rem;
+ font-weight: 600;
+ text-transform: uppercase;
+ letter-spacing: .04em;
+ color: var(--text-secondary);
+}
+.coach-band-menu-options {
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+}
+.coach-band-option {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 8px;
+ width: 100%;
+ padding: 8px 10px;
+ border: 1px solid transparent;
+ border-radius: 8px;
+ background: transparent;
+ color: inherit;
+ cursor: pointer;
+ text-align: left;
+ transition: background 0.12s, border-color 0.12s;
+}
+.coach-band-option:hover {
+ background: var(--surface-hover, rgba(0, 0, 0, 0.04));
+}
+.coach-band-option.is-selected {
+ border-color: color-mix(in srgb, var(--primary) 35%, var(--border));
+ background: color-mix(in srgb, var(--primary) 8%, var(--surface));
+}
+.coach-band-option-agree {
+ margin-top: 6px;
+ padding-top: 10px;
+ border-top: 1px solid var(--border);
+ border-radius: 0 0 8px 8px;
+}
+.coach-band-option-agree-label {
+ font-size: .75rem;
+ font-weight: 600;
+ color: var(--text-secondary);
+}
+.coach-band-confirm-compare {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-wrap: wrap;
+ gap: 12px 16px;
+ margin: 8px 0 4px;
+ padding: 16px;
+ border-radius: 10px;
+ border: 1px solid var(--border);
+ background: var(--surface-elevated, rgba(0, 0, 0, 0.02));
+}
+.coach-band-confirm-col {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 8px;
+ min-width: 5.5rem;
+}
+.coach-band-confirm-label {
+ font-size: .7rem;
+ font-weight: 600;
+ text-transform: uppercase;
+ letter-spacing: .04em;
+ color: var(--text-secondary);
+}
+.coach-band-confirm-arrow {
+ font-size: 1.25rem;
+ color: var(--text-secondary);
+ line-height: 1;
}
.client-profile-score-hint,
.client-profile-score-meta {
diff --git a/website/js/pages/assignments.js b/website/js/pages/assignments.js
index 0aa114e..fe8e4ca 100644
--- a/website/js/pages/assignments.js
+++ b/website/js/pages/assignments.js
@@ -1,6 +1,5 @@
import { apiGet, apiPost } from '../api.js';
import { pageHeaderHTML, showToast } from '../app.js';
-import { isDevTestClientCode, isDevTestUsername, testDataRowClassForClient } from '../test-data.js';
const CLIENT_PAGE_SIZE = 50;
@@ -100,11 +99,6 @@ function renderAssignments() {
-
@@ -178,10 +172,6 @@ function renderAssignments() {
clientPage = 0;
renderClientRows();
});
- document.getElementById('clientTestFilter').addEventListener('change', () => {
- clientPage = 0;
- renderClientRows();
- });
document.getElementById('selectAllBtn').addEventListener('click', () => {
document.querySelectorAll('#clientTableBody .client-cb').forEach(cb => {
@@ -313,10 +303,9 @@ function renderCoachList() {
function coachListItemHTML(c) {
const count = (clientsByCoach[c.coachID] || []).length;
- const coachTest = isDevTestUsername(c.username) ? ' row-test-data' : '';
const active = selectedCoachID === c.coachID ? ' active' : '';
return `
-
+
${esc(c.username)}
${c.supervisorUsername
? `${esc(c.supervisorUsername)}
`
@@ -336,8 +325,6 @@ function highlightCoachInList(coachID) {
function getVisibleClients() {
const coachFilter = document.getElementById('filterByCoach')?.value ?? '';
const search = document.getElementById('clientSearch')?.value.trim().toLowerCase() ?? '';
- const testMode = document.getElementById('clientTestFilter')?.value || '';
-
let visible = clients;
if (coachFilter === '__unassigned__') {
visible = clients.filter(c => !c.coachID);
@@ -350,11 +337,6 @@ function getVisibleClients() {
return hay.includes(search);
});
}
- if (testMode === 'test') {
- visible = visible.filter(c => isDevTestClientCode(c.clientCode));
- } else if (testMode === 'hide-test') {
- visible = visible.filter(c => !isDevTestClientCode(c.clientCode));
- }
return visible;
}
@@ -363,8 +345,7 @@ function updateClientSummary(filteredCount, pageSlice) {
if (!el) return;
const search = document.getElementById('clientSearch')?.value.trim() ?? '';
const coachFilter = document.getElementById('filterByCoach')?.value ?? '';
- const testFilter = document.getElementById('clientTestFilter')?.value;
- const hasFilter = search || coachFilter || testFilter;
+ const hasFilter = search || coachFilter;
const parts = [];
if (hasFilter && filteredCount !== clients.length) {
parts.push(`${filteredCount} of ${clients.length} match`);
@@ -453,7 +434,7 @@ function renderClientRows() {
body.innerHTML = slice.map(c => {
const checked = selectedClientCodes.has(c.clientCode) ? ' checked' : '';
return `
-
+
|
|
diff --git a/website/js/pages/clients.js b/website/js/pages/clients.js
index a2f7bbd..e966c0e 100644
--- a/website/js/pages/clients.js
+++ b/website/js/pages/clients.js
@@ -1,6 +1,5 @@
import { apiGet, apiPost, apiPut, apiDelete } from '../api.js';
import { pageHeaderHTML, showToast } from '../app.js';
-import { isDevTestClientCode, testDataRowClassForClient } from '../test-data.js';
const PAGE_SIZE = 50;
@@ -8,7 +7,6 @@ let clientsList = [];
let coachesList = [];
let scoringProfileCatalog = [];
let filterSearch = '';
-let filterTestData = '';
let page = 0;
let expandedClientCode = null;
let expandedQnKey = null;
@@ -74,11 +72,6 @@ function renderClients() {
-
${profileLegend}
@@ -107,13 +100,7 @@ function renderClients() {
clearExpandIfHidden();
renderClientTableBody();
});
- document.getElementById('clientTestFilter').addEventListener('change', (e) => {
- filterTestData = e.target.value;
- page = 0;
- clearExpandIfHidden();
- renderClientTableBody();
- });
-
+ ensureCoachBandGlobalClick();
renderClientTableBody();
}
@@ -126,11 +113,6 @@ function getFilteredClientsList() {
return hay.includes(q);
});
}
- if (filterTestData === 'test') {
- list = list.filter(c => isDevTestClientCode(c.clientCode));
- } else if (filterTestData === 'hide-test') {
- list = list.filter(c => !isDevTestClientCode(c.clientCode));
- }
return list;
}
@@ -167,12 +149,7 @@ function renderClientTableBody() {
body.querySelectorAll('.delete-client-btn').forEach(btn => {
btn.addEventListener('click', () => deleteClient(btn.dataset.code));
});
- body.querySelectorAll('.client-coach-band-select').forEach(select => {
- select.addEventListener('focus', () => {
- select.dataset.prev = select.value;
- });
- select.addEventListener('change', () => onCoachBandChange(select));
- });
+ bindCoachBandPickerEvents(body);
}
const pag = document.getElementById('clientsPagination');
@@ -309,29 +286,47 @@ function bandLabel(band) {
return band.charAt(0).toUpperCase() + band.slice(1);
}
-function coachBandSelectHTML(p, clientCode) {
+function coachBandPickerHTML(p, clientCode) {
const calcBand = p.calculatedBand || p.band;
if (!calcBand || !clientCode || !p.profileID) {
return '';
}
const current = p.coachBand || '';
const coachPending = p.pendingReview !== false && !current;
- const placeholder = coachPending
- ? '
'
- : '';
- const options = COACH_BANDS.map(b => {
- const selected = current === b ? ' selected' : '';
- return `
`;
- }).join('');
+ const triggerBadge = coachPending
+ ? bandBadgeHTML(null, { pending: true })
+ : bandBadgeHTML(current);
+ const showAgree = coachPending || (current && current !== calcBand);
+ const options = COACH_BANDS.map(b => `
+
`).join('');
+ const agreeBtn = showAgree ? `
+
` : '';
return `
-
`;
+ data-coach="${esc(current)}">
+
+
+
Coach category
+
${options}
+ ${agreeBtn}
+
+
`;
}
function profileScoreBlockHTML(p, clientCode = '') {
@@ -346,7 +341,7 @@ function profileScoreBlockHTML(p, clientCode = '') {
const coachPending = p.pendingReview !== false && !p.coachBand;
const coachDiffers = p.coachBand && p.coachBand !== calcBand;
const coachControl = clientCode
- ? coachBandSelectHTML(p, clientCode)
+ ? coachBandPickerHTML(p, clientCode)
: (coachPending ? bandBadgeHTML(null, { pending: true }) : bandBadgeHTML(p.coachBand));
return `
@@ -484,31 +479,130 @@ function patchClientScoringBand(clientCode, profileID, coachBand) {
}
}
-async function onCoachBandChange(select) {
- const clientCode = select.dataset.client;
- const profileID = select.dataset.profile;
- const profileName = select.dataset.profileName || profileID;
- const calculatedBand = select.dataset.calculated;
- const weightedRaw = select.dataset.weighted;
+function resetCoachBandMenuPosition(menu) {
+ if (!menu) return;
+ menu.style.position = '';
+ menu.style.left = '';
+ menu.style.top = '';
+ menu.style.minWidth = '';
+ menu.style.zIndex = '';
+ menu.style.visibility = '';
+}
+
+function positionCoachBandMenu(picker) {
+ const trigger = picker.querySelector('.coach-band-trigger');
+ const menu = picker.querySelector('.coach-band-menu');
+ if (!trigger || !menu) return;
+ menu.hidden = false;
+ menu.style.visibility = 'hidden';
+ const rect = trigger.getBoundingClientRect();
+ const menuWidth = Math.max(rect.width, 184);
+ const left = Math.min(rect.left, window.innerWidth - menuWidth - 8);
+ menu.style.position = 'fixed';
+ menu.style.left = `${Math.max(8, left)}px`;
+ menu.style.minWidth = `${menuWidth}px`;
+ menu.style.zIndex = '10001';
+ const menuHeight = menu.offsetHeight;
+ let top = rect.bottom + 6;
+ if (top + menuHeight > window.innerHeight - 8) {
+ top = rect.top - menuHeight - 6;
+ }
+ menu.style.top = `${Math.max(8, top)}px`;
+ menu.style.visibility = '';
+}
+
+function closeAllCoachBandMenus() {
+ document.querySelectorAll('.coach-band-picker.is-open').forEach(picker => {
+ picker.classList.remove('is-open');
+ const menu = picker.querySelector('.coach-band-menu');
+ const trigger = picker.querySelector('.coach-band-trigger');
+ resetCoachBandMenuPosition(menu);
+ if (menu) menu.hidden = true;
+ if (trigger) trigger.setAttribute('aria-expanded', 'false');
+ });
+}
+
+function toggleCoachBandMenu(picker) {
+ const isOpen = picker.classList.contains('is-open');
+ closeAllCoachBandMenus();
+ if (isOpen) return;
+ picker.classList.add('is-open');
+ const trigger = picker.querySelector('.coach-band-trigger');
+ positionCoachBandMenu(picker);
+ if (trigger) trigger.setAttribute('aria-expanded', 'true');
+}
+
+function openCoachBandConfirmModal({ clientCode, profileName, calculatedBand, coachBand }) {
+ return new Promise(resolve => {
+ const overlay = document.createElement('div');
+ overlay.className = 'modal-overlay coach-band-confirm-modal';
+ overlay.setAttribute('role', 'dialog');
+ overlay.setAttribute('aria-modal', 'true');
+ overlay.innerHTML = `
+
+
Set coach category
+
+ ${esc(profileName)} · ${esc(clientCode)}
+
+
+
+ Calculated
+ ${bandBadgeHTML(calculatedBand, { label: bandLabel(calculatedBand) })}
+
+
→
+
+ Coach
+ ${bandBadgeHTML(coachBand, { label: bandLabel(coachBand) })}
+
+
+
This overrides the coach category for this client and profile.
+
+
+
+
+
`;
+ document.body.appendChild(overlay);
+ document.body.classList.add('modal-open');
+
+ const close = (confirmed) => {
+ overlay.remove();
+ document.body.classList.remove('modal-open');
+ resolve(confirmed);
+ };
+ overlay.querySelector('[data-coach-cancel]').addEventListener('click', () => close(false));
+ overlay.querySelector('[data-coach-confirm]').addEventListener('click', () => close(true));
+ overlay.addEventListener('click', (e) => {
+ if (e.target === overlay) close(false);
+ });
+ overlay.querySelector('.modal-dialog').addEventListener('click', (e) => e.stopPropagation());
+ const onKey = (e) => {
+ if (e.key === 'Escape') close(false);
+ };
+ document.addEventListener('keydown', onKey, { once: true });
+ overlay.querySelector('[data-coach-confirm]').focus();
+ });
+}
+
+async function promptCoachBandSave(picker, coachBand) {
+ const clientCode = picker.dataset.client;
+ const profileID = picker.dataset.profile;
+ const profileName = picker.dataset.profileName || profileID;
+ const calculatedBand = picker.dataset.calculated;
+ const current = picker.dataset.coach || '';
+
+ if (!coachBand || coachBand === current) return;
+
+ const confirmed = await openCoachBandConfirmModal({
+ clientCode,
+ profileName,
+ calculatedBand,
+ coachBand,
+ });
+ if (!confirmed) return;
+
+ const weightedRaw = picker.dataset.weighted;
const weightedTotal = weightedRaw !== '' ? Number(weightedRaw) : null;
- const prev = select.dataset.prev || '';
- const coachBand = select.value;
-
- if (!coachBand) {
- select.value = prev;
- return;
- }
- if (coachBand === prev) {
- return;
- }
-
- const msg = `Set coach category to "${bandLabel(coachBand)}" for ${profileName} (${clientCode})?\n\nCalculated category: ${bandLabel(calculatedBand)}.`;
- if (!confirm(msg)) {
- select.value = prev || '';
- return;
- }
-
- select.disabled = true;
+ picker.classList.add('is-saving');
try {
await apiPut('clients.php', {
clientCode,
@@ -518,17 +612,42 @@ async function onCoachBandChange(select) {
weightedTotal,
});
patchClientScoringBand(clientCode, profileID, coachBand);
- select.dataset.prev = coachBand;
showToast(`Coach category saved for ${profileName}`, 'success');
renderClientTableBody();
} catch (e) {
- select.value = prev || '';
showToast(e.message, 'error');
} finally {
- select.disabled = false;
+ picker.classList.remove('is-saving');
}
}
+function bindCoachBandPickerEvents(root = document) {
+ root.querySelectorAll('.coach-band-trigger').forEach(btn => {
+ btn.addEventListener('click', (e) => {
+ e.stopPropagation();
+ toggleCoachBandMenu(btn.closest('.coach-band-picker'));
+ });
+ });
+ root.querySelectorAll('.coach-band-option').forEach(btn => {
+ btn.addEventListener('click', (e) => {
+ e.stopPropagation();
+ const picker = btn.closest('.coach-band-picker');
+ closeAllCoachBandMenus();
+ promptCoachBandSave(picker, btn.dataset.band);
+ });
+ });
+}
+
+let coachBandGlobalClickBound = false;
+function ensureCoachBandGlobalClick() {
+ if (coachBandGlobalClickBound) return;
+ coachBandGlobalClickBound = true;
+ document.addEventListener('click', () => closeAllCoachBandMenus());
+ document.addEventListener('keydown', (e) => {
+ if (e.key === 'Escape') closeAllCoachBandMenus();
+ });
+}
+
function clientHasResponseData(c) {
return Number(c.hasResponseData) === 1;
}
@@ -548,7 +667,7 @@ function clientRowHTML(c) {
const colCount = scoringProfileCatalog.length > 0 ? 4 : 3;
return `
-
+
|
${expandControl}${esc(c.clientCode)}
|
diff --git a/website/js/pages/results.js b/website/js/pages/results.js
index b7f4983..b972a40 100644
--- a/website/js/pages/results.js
+++ b/website/js/pages/results.js
@@ -1,11 +1,6 @@
import { apiGet } from '../api.js';
import { homeNavButton, showToast } from '../app.js';
-import {
- buildResultColumns,
- isDevTestClientCode,
- resultColumnCellValue,
- testDataRowClassForClient,
-} from '../test-data.js';
+import { buildResultColumns, resultColumnCellValue } from '../test-data.js';
const PAGE_SIZE = 50;
@@ -21,7 +16,6 @@ let filterStatus = '';
let filterDateFrom = '';
let filterDateTo = '';
let filterSearch = '';
-let filterTestData = '';
let filterQuestion = '';
let page = 0;
@@ -35,7 +29,6 @@ export async function resultsPage(params) {
filterDateFrom = '';
filterDateTo = '';
filterSearch = '';
- filterTestData = '';
filterQuestion = '';
page = 0;
@@ -102,11 +95,6 @@ function renderResults() {
-
@@ -114,7 +102,7 @@ function renderResults() {
Export CSV
- Each question has its own column; glass-scale symptoms are separate columns. Hover headers for context. Test rows (DEV-CL-*) are highlighted.
+ Each question has its own column; glass-scale symptoms are separate columns. Hover headers for context.
@@ -162,11 +150,6 @@ function renderResults() {
page = 0;
renderTableRows();
});
- document.getElementById('filterTestData').addEventListener('change', (e) => {
- filterTestData = e.target.value;
- page = 0;
- renderTableRows();
- });
document.getElementById('gotoQuestionBtn').addEventListener('click', () => {
filterQuestion = document.getElementById('filterQuestion').value.trim();
scrollToQuestionColumn(filterQuestion);
@@ -185,7 +168,6 @@ function renderResults() {
filterDateFrom = '';
filterDateTo = '';
filterSearch = '';
- filterTestData = '';
filterQuestion = '';
page = 0;
renderResults();
@@ -304,11 +286,6 @@ function getFilteredClients() {
return hay.includes(q);
});
}
- if (filterTestData === 'test') {
- clients = clients.filter(c => isDevTestClientCode(c.clientCode));
- } else if (filterTestData === 'hide-test') {
- clients = clients.filter(c => !isDevTestClientCode(c.clientCode));
- }
return clients;
}
@@ -404,7 +381,7 @@ function renderTableRows() {
return `
${esc(String(val))} | `;
}).join('');
- return `
+ return `
| ${esc(c.clientCode)} |
${esc(coachDisplayName(c))} |
${esc(supervisorDisplayName(c))} |
diff --git a/website/js/pages/users.js b/website/js/pages/users.js
index ecbe5e8..d35bf27 100644
--- a/website/js/pages/users.js
+++ b/website/js/pages/users.js
@@ -1,7 +1,6 @@
import { apiGet, apiPost, apiPut, apiDelete } from '../api.js';
import { getRole, getUser, pageHeaderHTML, showToast } from '../app.js';
import { openAdminResetPasswordModal } from '../password-modal.js';
-import { isDevTestUsername, testDataRowClassForUser } from '../test-data.js';
// Roles an admin can create; supervisors can only create coaches
const CREATEABLE_ROLES = {
@@ -14,7 +13,6 @@ let supervisorsList = [];
let callerRole = '';
/** @type {Record} */
let filterSearchByRole = { admin: '', supervisor: '', coach: '' };
-let filterTestData = '';
function roleGroupsForCaller() {
return callerRole === 'supervisor'
@@ -112,19 +110,7 @@ function renderUsers() {
const byRole = usersByRoleMap();
const groups = roleGroupsForCaller();
- const testFilterCard = `
-
-
-
-
-
-
`;
-
- container.innerHTML = testFilterCard + groups.map(group => {
+ container.innerHTML = groups.map(group => {
const allInRole = byRole[group.key] || [];
if (!allInRole.length) return '';
return `
@@ -154,11 +140,6 @@ function renderUsers() {
`;
}).join('');
- document.getElementById('userTestFilter')?.addEventListener('change', (e) => {
- filterTestData = e.target.value;
- renderUsers();
- });
-
container.addEventListener('input', (e) => {
const input = e.target.closest('.user-role-search');
if (!input) return;
@@ -184,11 +165,6 @@ function filterUsers(users, roleKey) {
return hay.includes(q);
});
}
- if (filterTestData === 'test') {
- list = list.filter(u => isDevTestUsername(u.username));
- } else if (filterTestData === 'hide-test') {
- list = list.filter(u => !isDevTestUsername(u.username));
- }
return list;
}
@@ -302,7 +278,7 @@ function userRowHTML(u, myUsername) {
}
return `
-
+
|
${esc(u.username)}
${isSelf ? 'You' : ''}
diff --git a/website/js/test-data.js b/website/js/test-data.js
index 3e03823..d7a7111 100644
--- a/website/js/test-data.js
+++ b/website/js/test-data.js
@@ -1,21 +1,3 @@
-/** Dev fixture prefixes (import script / dev_fixture.php). */
-export function isDevTestClientCode(code) {
- const c = String(code ?? '').trim();
- return c.toUpperCase().startsWith('DEV-CL-');
-}
-
-export function isDevTestUsername(username) {
- return String(username ?? '').trim().toLowerCase().startsWith('dev_');
-}
-
-export function testDataRowClassForClient(clientCode) {
- return isDevTestClientCode(clientCode) ? ' row-test-data' : '';
-}
-
-export function testDataRowClassForUser(username) {
- return isDevTestUsername(username) ? ' row-test-data' : '';
-}
-
const STABLE_KEY_RE = /^[a-zA-Z][a-zA-Z0-9_]*$/;
/** Local question id from full questionID (hash__q5 → q5). */
|