Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 97 additions & 1 deletion src/js/techreport/tableLinked.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class TableLinked {

this.updateContent();
this.updateSelectionText(DataUtils.getTechsFromURL());
this.initSortHeaders();

const rowCount = document.getElementById('rowsPerPage');
rowCount?.addEventListener('change', (e) => this.updateRowsPerPage(e));
Expand Down Expand Up @@ -61,9 +62,16 @@ class TableLinked {
const sortEndpoint = component.dataset.sortEndpoint;
const sortMetric = component.dataset.sortMetric;
const sortKey = component.dataset.sortKey;
const sortOrder = component.dataset.sortOrder || 'desc';
const client = component.dataset.client;

if(sortMetric) {
if(sortMetric === 'technology') {
this.dataArray = this.dataArray.sort((techA, techB) => {
const aName = techA[0]?.technology || '';
const bName = techB[0]?.technology || '';
return sortOrder === 'asc' ? aName.localeCompare(bName) : bName.localeCompare(aName);
});
} else if(sortMetric) {
this.dataArray = this.dataArray.sort((techA, techB) => {
// Sort techs by date to get the latest
const aSortedDate = techA.sort((a, b) => new Date(b.date) - new Date(a.date));
Expand All @@ -78,6 +86,9 @@ class TableLinked {
const aValue = aMetric?.[client]?.[sortKey];
const bValue = bMetric?.[client]?.[sortKey];

if (sortOrder === 'asc') {
return aValue - bValue > 0 ? 1 : -1;
}
return bValue - aValue > 0 ? 1 : -1;
});
}
Expand Down Expand Up @@ -326,6 +337,91 @@ class TableLinked {
const rowsAnnouncement = document.getElementById('rows-announcement');
rowsAnnouncement.innerText = `Showing ${this.rows} rows.`;
}

initSortHeaders() {
const component = document.getElementById(`table-${this.id}`);
const headers = component.querySelectorAll('thead th');

headers.forEach(th => {
const endpoint = th.dataset.endpoint;
const metric = th.dataset.metric;
const key = th.dataset.key;

const isSortable = (key === 'technology') || (endpoint && metric);
if (!isSortable) return;

const btn = document.createElement('button');
btn.className = 'sort-btn';
btn.setAttribute('type', 'button');
while (th.firstChild) {
btn.appendChild(th.firstChild);
}
th.appendChild(btn);
btn.addEventListener('click', () => this.onSortClick(th));
});

this.updateSortIndicators();
}

onSortClick(th) {
const component = document.getElementById(`table-${this.id}`);
const endpoint = th.dataset.endpoint || '';
const subcategory = th.dataset.subcategory || '';
const metric = th.dataset.metric || '';
const key = th.dataset.key;

const isTechColumn = key === 'technology';
const currentOrder = component.dataset.sortOrder || 'desc';

const isCurrentCol = isTechColumn
? component.dataset.sortMetric === 'technology'
: (component.dataset.sortEndpoint === endpoint &&
component.dataset.sortMetric === subcategory &&
component.dataset.sortKey === metric);

const newOrder = isCurrentCol && currentOrder === 'desc' ? 'asc' : 'desc';

if (isTechColumn) {
component.dataset.sortEndpoint = '';
component.dataset.sortMetric = 'technology';
component.dataset.sortKey = 'technology';
} else {
component.dataset.sortEndpoint = endpoint;
component.dataset.sortMetric = subcategory;
component.dataset.sortKey = metric;
}
component.dataset.sortOrder = newOrder;

this.updateContent();
this.updateSortIndicators();
}

updateSortIndicators() {
const component = document.getElementById(`table-${this.id}`);
const headers = component.querySelectorAll('thead th');
const sortMetric = component.dataset.sortMetric;
const sortEndpoint = component.dataset.sortEndpoint || '';
const sortKey = component.dataset.sortKey || '';
const sortOrder = component.dataset.sortOrder || 'desc';

headers.forEach(th => {
const endpoint = th.dataset.endpoint || '';
const subcategory = th.dataset.subcategory || '';
const metric = th.dataset.metric || '';
const key = th.dataset.key;

const isTechColumn = key === 'technology';
const isActive = isTechColumn
? sortMetric === 'technology'
: (endpoint && endpoint === sortEndpoint && subcategory === sortMetric && metric === sortKey);

if (isActive) {
th.setAttribute('aria-sort', sortOrder === 'asc' ? 'ascending' : 'descending');
} else {
th.removeAttribute('aria-sort');
}
});
}
}

export default TableLinked;
26 changes: 26 additions & 0 deletions static/css/techreport/techreport.css
Original file line number Diff line number Diff line change
Expand Up @@ -1249,6 +1249,32 @@ select {
border-bottom: 1px solid var(--color-text);
}

.table-ui thead th .sort-btn {
background: none;
border: none;
padding: 0;
font: inherit;
cursor: pointer;
color: inherit;
text-align: left;
}

.table-ui thead th .sort-btn::after {
content: ' ↕';
opacity: 0.4;
font-size: 0.75em;
}

.table-ui thead th[aria-sort="ascending"] .sort-btn::after {
content: ' ↑';
opacity: 1;
}

.table-ui thead th[aria-sort="descending"] .sort-btn::after {
content: ' ↓';
opacity: 1;
}

.table-ui :is(td, th) {
min-width: 5rem;
text-align: left;
Expand Down
2 changes: 2 additions & 0 deletions templates/techreport/components/table_linked.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
data-key="{{ column.key }}"
data-metric="{{ column.metric }}"
data-endpoint="{{ column.endpoint }}"
data-subcategory="{{ column.subcategory or '' }}"
class="{{ column.className }}"
scope="col"
>
{% if column.hiddenName %}
<span class="sr-only">{{ column.name }}</span>
Expand Down
Loading