further extensions to display page
Some checks failed
PHPUnit / test (push) Has been cancelled

This commit is contained in:
2026-07-01 09:29:31 +02:00
parent 223f38a11f
commit bbf10fe866

View File

@ -130,8 +130,8 @@ function renderResults() {
</div> </div>
<p class="data-toolbar-hint" style="margin-top:8px"> <p class="data-toolbar-hint" style="margin-top:8px">
${showAllVersions ${showAllVersions
? `Each row is one uploaded version, sorted by client then version.${showMetadata ? ' Cycle, session, and timestamps are shown per submission.' : ' Turn on metadata to see version, cycle, session, and timestamps.'}` ? `Each row is one uploaded version, sorted by client then version.${showMetadata ? ' Metadata includes version, cycle, session, start/end/upload times, and submission details.' : ' Turn on metadata to see version, cycle, session, and timestamps.'}`
: `Latest response per client.${showMetadata ? ' Cycle, session, and completion times are shown.' : ' Turn on metadata to see cycle, session, and timestamps.'} Each question has its own column.`} : `Latest response per client.${showMetadata ? ' Metadata includes cycle, session, and start/end times.' : ' Turn on metadata to see cycle, session, and timestamps.'} Each question has its own column.`}
</p> </p>
</div> </div>
<div class="card"> <div class="card">
@ -223,8 +223,8 @@ function renderResults() {
const hint = document.querySelector('#resultsContent .data-toolbar-hint'); const hint = document.querySelector('#resultsContent .data-toolbar-hint');
if (hint) { if (hint) {
hint.textContent = showAllVersions hint.textContent = showAllVersions
? `Each row is one uploaded version, sorted by client then version.${showMetadata ? ' Cycle, session, and timestamps are shown per submission.' : ' Turn on metadata to see version, cycle, session, and timestamps.'}` ? `Each row is one uploaded version, sorted by client then version.${showMetadata ? ' Metadata includes version, cycle, session, start/end/upload times, and submission details.' : ' Turn on metadata to see version, cycle, session, and timestamps.'}`
: `Latest response per client.${showMetadata ? ' Cycle, session, and completion times are shown.' : ' Turn on metadata to see cycle, session, and timestamps.'} Each question has its own column.`; : `Latest response per client.${showMetadata ? ' Metadata includes cycle, session, and start/end times.' : ' Turn on metadata to see cycle, session, and timestamps.'} Each question has its own column.`;
} }
}); });
document.getElementById('exportCsvLink').addEventListener('click', (e) => { document.getElementById('exportCsvLink').addEventListener('click', (e) => {
@ -244,41 +244,52 @@ const META_COL_KEYS = new Set([
'version', 'version',
'programCycleNumber', 'programCycleNumber',
'programSessionNumber', 'programSessionNumber',
'programSessionID',
'startedAt', 'startedAt',
'completedAt', 'completedAt',
'submittedAt', 'submittedAt',
'submissionID',
'structureRevision',
'submittedByRole',
'submittedBy',
]); ]);
const ALL_VERSIONS_FIXED_COLUMNS = [ const IDENTITY_FIXED_COLUMNS = [
{ key: 'clientCode', label: 'Client' }, { key: 'coachUsername', label: 'Counselor' },
{ key: 'supervisorUsername', label: 'Supervisor' },
{ key: 'status', label: 'Status' },
{ key: 'sumPoints', label: 'Score' },
];
const META_COLUMNS_ALL_VERSIONS = [
{ key: 'version', label: 'Version' }, { key: 'version', label: 'Version' },
{ key: 'programCycleNumber', label: 'Cycle' }, { key: 'programCycleNumber', label: 'Cycle' },
{ key: 'programSessionNumber', label: 'Session' }, { key: 'programSessionNumber', label: 'Session' },
{ key: 'coachUsername', label: 'Counselor' }, { key: 'programSessionID', label: 'Session ID' },
{ key: 'supervisorUsername', label: 'Supervisor' },
{ key: 'status', label: 'Status' },
{ key: 'sumPoints', label: 'Score' },
{ key: 'startedAt', label: 'Started' }, { key: 'startedAt', label: 'Started' },
{ key: 'completedAt', label: 'Completed' }, { key: 'completedAt', label: 'Completed' },
{ key: 'submittedAt', label: 'Uploaded' }, { key: 'submittedAt', label: 'Uploaded' },
{ key: 'submissionID', label: 'Submission ID' },
{ key: 'structureRevision', label: 'Structure rev.' },
{ key: 'submittedByRole', label: 'Submitted by role' },
{ key: 'submittedBy', label: 'Submitted by' },
]; ];
const CURRENT_FIXED_COLUMNS = [ const META_COLUMNS_CURRENT = [
{ key: 'clientCode', label: 'Client' },
{ key: 'coachUsername', label: 'Counselor' },
{ key: 'supervisorUsername', label: 'Supervisor' },
{ key: 'status', label: 'Status' },
{ key: 'sumPoints', label: 'Score' },
{ key: 'programCycleNumber', label: 'Cycle' }, { key: 'programCycleNumber', label: 'Cycle' },
{ key: 'programSessionNumber', label: 'Session' }, { key: 'programSessionNumber', label: 'Session' },
{ key: 'programSessionID', label: 'Session ID' },
{ key: 'startedAt', label: 'Started' }, { key: 'startedAt', label: 'Started' },
{ key: 'completedAt', label: 'Completed' }, { key: 'completedAt', label: 'Completed' },
]; ];
function getTableFixedColumns() { function getTableFixedColumns() {
const full = showAllVersions ? ALL_VERSIONS_FIXED_COLUMNS : CURRENT_FIXED_COLUMNS; const clientCol = [{ key: 'clientCode', label: 'Client' }];
if (showMetadata) return full; if (!showMetadata) {
return full.filter(col => !META_COL_KEYS.has(col.key)); return [...clientCol, ...IDENTITY_FIXED_COLUMNS];
}
const meta = showAllVersions ? META_COLUMNS_ALL_VERSIONS : META_COLUMNS_CURRENT;
return [...clientCol, ...meta, ...IDENTITY_FIXED_COLUMNS];
} }
function renderTableHead() { function renderTableHead() {
@ -434,8 +445,15 @@ function dateInputToUnixEnd(yyyyMmDd) {
return Math.floor(new Date(y, m - 1, d, 23, 59, 59, 999).getTime() / 1000); return Math.floor(new Date(y, m - 1, d, 23, 59, 59, 999).getTime() / 1000);
} }
function formatUnixDate(ts) { function formatUnixDateTime(ts) {
return ts ? new Date(ts * 1000).toLocaleDateString() : '—'; if (!ts) return '—';
return new Date(ts * 1000).toLocaleString(undefined, {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
});
} }
function fixedColumnCellHtml(c, col, { groupStart = false } = {}) { function fixedColumnCellHtml(c, col, { groupStart = false } = {}) {
@ -448,6 +466,8 @@ function fixedColumnCellHtml(c, col, { groupStart = false } = {}) {
return `<td>${c.programCycleNumber ?? '—'}</td>`; return `<td>${c.programCycleNumber ?? '—'}</td>`;
case 'programSessionNumber': case 'programSessionNumber':
return `<td>${c.programSessionNumber ?? '—'}</td>`; return `<td>${c.programSessionNumber ?? '—'}</td>`;
case 'programSessionID':
return `<td>${c.programSessionID ? esc(c.programSessionID) : '—'}</td>`;
case 'coachUsername': case 'coachUsername':
return `<td>${esc(coachDisplayName(c))}</td>`; return `<td>${esc(coachDisplayName(c))}</td>`;
case 'supervisorUsername': case 'supervisorUsername':
@ -461,11 +481,19 @@ function fixedColumnCellHtml(c, col, { groupStart = false } = {}) {
case 'sumPoints': case 'sumPoints':
return `<td>${c.sumPoints !== null && c.sumPoints !== undefined ? c.sumPoints : '—'}</td>`; return `<td>${c.sumPoints !== null && c.sumPoints !== undefined ? c.sumPoints : '—'}</td>`;
case 'startedAt': case 'startedAt':
return `<td>${formatUnixDate(c.startedAt)}</td>`; return `<td>${formatUnixDateTime(c.startedAt)}</td>`;
case 'completedAt': case 'completedAt':
return `<td>${formatUnixDate(c.completedAt)}</td>`; return `<td>${formatUnixDateTime(c.completedAt)}</td>`;
case 'submittedAt': case 'submittedAt':
return `<td>${formatUnixDate(c.submittedAt)}</td>`; return `<td>${formatUnixDateTime(c.submittedAt)}</td>`;
case 'submissionID':
return `<td>${c.submissionID ? esc(c.submissionID) : '—'}</td>`;
case 'structureRevision':
return `<td>${c.structureRevision ?? '—'}</td>`;
case 'submittedByRole':
return `<td>${c.submittedByRole ? esc(c.submittedByRole) : '—'}</td>`;
case 'submittedBy':
return `<td>${c.submittedBy ? esc(c.submittedBy) : '—'}</td>`;
default: default:
return '<td>—</td>'; return '<td>—</td>';
} }
@ -539,9 +567,14 @@ function getCellValue(client, key) {
if (key === 'sumPoints') return client.sumPoints; if (key === 'sumPoints') return client.sumPoints;
if (key === 'programCycleNumber') return client.programCycleNumber; if (key === 'programCycleNumber') return client.programCycleNumber;
if (key === 'programSessionNumber') return client.programSessionNumber; if (key === 'programSessionNumber') return client.programSessionNumber;
if (key === 'programSessionID') return client.programSessionID;
if (key === 'startedAt') return client.startedAt; if (key === 'startedAt') return client.startedAt;
if (key === 'completedAt') return client.completedAt; if (key === 'completedAt') return client.completedAt;
if (key === 'submittedAt') return client.submittedAt; if (key === 'submittedAt') return client.submittedAt;
if (key === 'submissionID') return client.submissionID;
if (key === 'structureRevision') return client.structureRevision;
if (key === 'submittedByRole') return client.submittedByRole;
if (key === 'submittedBy') return client.submittedBy;
const col = resultColumns.find(c => c.key === key); const col = resultColumns.find(c => c.key === key);
if (col) { if (col) {
const ans = client.answers && client.answers[col.questionID]; const ans = client.answers && client.answers[col.questionID];