Skip to content

Commit ddc1734

Browse files
committed
WIP
1 parent 1268ead commit ddc1734

File tree

1 file changed

+146
-47
lines changed

1 file changed

+146
-47
lines changed

templates/opencodelists/this_user.html

Lines changed: 146 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
{% block title_extra %}{{ user.name }}{% endblock %}
66

77
{% block content %}
8-
<header class="grid gap-y-4 mb-4 mt-6 py-4 border-b border-b-slate-300">
8+
<header class="grid gap-y-4 mb-4 mt-6 py-8 border-b border-b-slate-300">
99
<h1 class="text-2xl max-w-prose tracking-tight wrap-break-word md:text-4xl font-bold text-slate-900">
1010
Hello, {{ user.name }}
1111
</h1>
@@ -18,30 +18,52 @@ <h1 class="text-2xl max-w-prose tracking-tight wrap-break-word md:text-4xl font-
1818

1919
{% block full_width_content %}
2020
<div class="px-4 sm:px-6 lg:px-8 pt-6 pb-24">
21-
<h2 class="text-2xl/tight font-bold text-slate-900">Your codelists</h2>
22-
<p class="mt-2 text-base/snug text-slate-700">A list of all the the codelists you have access to edit, update, and publish.</p>
21+
<div class="container">
22+
<h2 class="text-2xl/tight font-bold text-slate-900">Your codelists</h2>
23+
<p class="mt-2 text-base/snug text-slate-700">A list of all the the codelists you have access to edit, update, and publish.</p>
24+
</div>
2325
<div class="mt-8 flow-root">
2426
<div class="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
2527
<div class="inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8">
2628
<div class="overflow-hidden shadow-sm outline-1 outline-black/5 sm:rounded-lg dark:shadow-none dark:-outline-offset-1 dark:outline-white/10">
2729
<table class="relative min-w-full divide-y divide-slate-200">
2830
<thead class="bg-slate-100 text-left text-sm font-semibold text-slate-900 border-b-slate-300">
2931
<tr class="align-bottom">
30-
<th class="py-3.5 pr-3 pl-4 whitespace-nowrap sm:pl-6" rowspan="2">
31-
<div class="inline-flex items-center gap-x-1">
32-
Name
33-
<button
34-
id="sort-codelists-by-name"
35-
type="button"
36-
aria-label="Sort codelists by name"
37-
aria-pressed="false"
38-
class="ml-2 flex-none cursor-pointer rounded-sm bg-gray-200 text-gray-900 transition-colors hover:bg-gray-300"
32+
<th id="name-column-heading" class="py-3.5 pr-3 pl-4 whitespace-nowrap sm:pl-6" rowspan="2">
33+
<button
34+
id="sort-codelists-by-name"
35+
type="button"
36+
aria-label="Sort codelists by name"
37+
aria-pressed="false"
38+
class="group inline-flex items-center gap-x-1 cursor-pointer rounded-sm focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-slate-400"
39+
>
40+
<span>Name</span>
41+
<svg
42+
viewBox="0 0 24 24"
43+
fill="none"
44+
stroke="currentColor"
45+
stroke-width="1.5"
46+
aria-hidden="true"
47+
data-sort-icon="unsorted"
48+
class="size-5 text-gray-400"
49+
>
50+
<path
51+
stroke-linecap="round"
52+
stroke-linejoin="round"
53+
d="M3 7.5 7.5 3m0 0L12 7.5M7.5 3v13.5m13.5 0L16.5 21m0 0L12 16.5m4.5 4.5V7.5"
54+
/>
55+
</svg>
56+
<svg
57+
viewBox="0 0 20 20"
58+
fill="currentColor"
59+
data-slot="icon"
60+
aria-hidden="true"
61+
data-sort-icon="direction"
62+
class="hidden size-5 rounded-sm transition-transform"
3963
>
40-
<svg viewBox="0 0 20 20" fill="currentColor" data-slot="icon" aria-hidden="true" class="size-5">
41-
<path d="M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" fill-rule="evenodd" />
42-
</svg>
43-
</button>
44-
</div>
64+
<path d="M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" fill-rule="evenodd" />
65+
</svg>
66+
</button>
4567
</th>
4668
<th class="px-3 py-3.5 whitespace-nowrap" rowspan="2">Owner</th>
4769
<th class="px-3 py-3.5 whitespace-nowrap" rowspan="2">Coding system</th>
@@ -51,38 +73,58 @@ <h2 class="text-2xl/tight font-bold text-slate-900">Your codelists</h2>
5173
<th class="px-3 py-3.5 whitespace-nowrap">Version ID</th>
5274
<th class="px-3 py-3.5 whitespace-nowrap">Status</th>
5375
<th class="px-3 py-3.5 whitespace-nowrap">Number of codes</th>
54-
<th class="px-3 py-3.5 whitespace-nowrap pl-3 sm:pr-3">
55-
<div class="inline-flex items-center gap-x-1">
56-
Last updated
57-
<button
58-
id="sort-codelists-by-date"
59-
type="button"
60-
aria-label="Sort codelists by date"
61-
aria-pressed="false"
62-
class="ml-2 flex-none cursor-pointer rounded-sm bg-gray-200 text-gray-900 transition-colors hover:bg-gray-300"
76+
<th id="date-column-heading" class="px-3 py-3.5 whitespace-nowrap pl-3 sm:pr-3">
77+
<button
78+
id="sort-codelists-by-date"
79+
type="button"
80+
aria-label="Sort codelists by date"
81+
aria-pressed="false"
82+
class="group inline-flex items-center gap-x-1 cursor-pointer rounded-sm focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-slate-400"
83+
>
84+
<span>Last updated</span>
85+
<svg
86+
viewBox="0 0 24 24"
87+
fill="none"
88+
stroke="currentColor"
89+
stroke-width="1.5"
90+
aria-hidden="true"
91+
data-sort-icon="unsorted"
92+
class="size-5 text-gray-400"
93+
>
94+
<path
95+
stroke-linecap="round"
96+
stroke-linejoin="round"
97+
d="M3 7.5 7.5 3m0 0L12 7.5M7.5 3v13.5m13.5 0L16.5 21m0 0L12 16.5m4.5 4.5V7.5"
98+
/>
99+
</svg>
100+
<svg
101+
viewBox="0 0 20 20"
102+
fill="currentColor"
103+
data-slot="icon"
104+
aria-hidden="true"
105+
data-sort-icon="direction"
106+
class="hidden size-5 rounded-sm transition-transform"
63107
>
64-
<svg viewBox="0 0 20 20" fill="currentColor" data-slot="icon" aria-hidden="true" class="size-5">
65-
<path d="M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" fill-rule="evenodd" />
66-
</svg>
67-
</button>
68-
</div>
108+
<path d="M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" fill-rule="evenodd" />
109+
</svg>
110+
</button>
69111
</th>
70112
</tr>
71113
</thead>
72114
{% for item in all_codelists %}
73115
{% if item.versions|length == 1 %}
74-
<tbody class="bg-white even:bg-slate-50 hover:bg-yellow-50">
116+
<tbody class="bg-white even:bg-slate-50 group">
75117
{% with version=item.versions.0 %}
76118
<tr class="text-sm text-slate-900">
77-
<td class="py-4 pr-3 pl-4 text-base/snug font-semibold sm:pl-6">{{ item.codelist.name }}</td>
78-
<td class="px-3 py-4">{{ item.codelist.owner }}</td>
79-
<td class="px-3 py-4 whitespace-nowrap">{{ item.codelist.coding_system_short_name }}</td>
80-
<td class="px-3 py-4">
119+
<td class="name-sort-column py-4 pr-3 group-hover:bg-yellow-50 pl-4 text-base/snug font-semibold sm:pl-6">{{ item.codelist.name }}</td>
120+
<td class="px-3 py-4 group-hover:bg-yellow-50">{{ item.codelist.owner }}</td>
121+
<td class="px-3 py-4 group-hover:bg-yellow-50 whitespace-nowrap">{{ item.codelist.coding_system_short_name }}</td>
122+
<td class="px-3 py-4 group-hover:bg-yellow-50">
81123
<a class="link whitespace-nowrap" href="{{ version.get_absolute_url }}">
82124
{{ version.tag_or_hash }}
83125
</a>
84126
</td>
85-
<td class="px-3">
127+
<td class="px-3 group-hover:bg-yellow-50">
86128
{% if version.is_under_review %}
87129
<span class="inline-flex rounded-full px-2 py-0.5 text-sm/tight font-semibold border bg-blue-200 text-blue-900 border-blue-200 whitespace-nowrap">Under review</span>
88130
{% elif version.is_draft %}
@@ -91,8 +133,8 @@ <h2 class="text-2xl/tight font-bold text-slate-900">Your codelists</h2>
91133
<span class="inline-flex rounded-full px-2 py-0.5 text-sm/tight font-semibold border bg-green-200 text-green-900 border-green-200 whitespace-nowrap">Published</span>
92134
{% endif %}
93135
</td>
94-
<td class="px-3 py-4 whitespace-nowrap">{{ version.codes|length }} code{{ version.codes|pluralize}}</td>
95-
<td class="px-3 py-4 pl-3 sm:pr-3">
136+
<td class="px-3 py-4 group-hover:bg-yellow-50 whitespace-nowrap">{{ version.codes|length }} code{{ version.codes|pluralize}}</td>
137+
<td class="date-sort-column px-3 py-4 group-hover:bg-yellow-50 pl-3 sm:pr-3">
96138
<time class="whitespace-nowrap" datetime="{{ version.updated_at|date:"c" }}">
97139
{{ version.updated_at|date:'d M Y' }} at {{ version.updated_at|date:'H:i' }}
98140
</time>
@@ -103,22 +145,22 @@ <h2 class="text-2xl/tight font-bold text-slate-900">Your codelists</h2>
103145
{% else %}
104146
<tbody class="group bg-white even:bg-slate-50">
105147
{% for version in item.versions %}
106-
<tr class="text-sm text-slate-900 group-hover:bg-yellow-50">
107-
<td class="py-2 pr-3 pl-4 font-semibold sm:pl-6 text-base/snug">
148+
<tr class="text-sm text-slate-900">
149+
<td class="name-sort-column py-2 pr-3 pl-4 font-semibold sm:pl-6 text-base/snug group-hover:bg-yellow-50">
108150
<span class="{% if not forloop.first %}sr-only{% endif %}">{{ item.codelist.name }}</span>
109151
</td>
110-
<td class="px-3 py-2 min-w-[20ch] ">
152+
<td class="px-3 py-2 min-w-[20ch] group-hover:bg-yellow-50">
111153
<span class="{% if not forloop.first %}sr-only{% endif %}">{{ item.codelist.owner }}</span>
112154
</td>
113-
<td class="px-3 py-2 whitespace-nowrap ">
155+
<td class="px-3 py-2 whitespace-nowrap group-hover:bg-yellow-50">
114156
<span class="{% if not forloop.first %}sr-only{% endif %}">{{ item.codelist.coding_system_short_name }}</span>
115157
</td>
116-
<td class="px-3 py-2 ">
158+
<td class="px-3 py-2 group-hover:bg-yellow-50">
117159
<a class="link whitespace-nowrap" href="{{ version.get_absolute_url }}">
118160
{{ version.tag_or_hash }}
119161
</a>
120162
</td>
121-
<td class="px-3">
163+
<td class="px-3 group-hover:bg-yellow-50">
122164
{% if version.is_under_review %}
123165
<span class="inline-flex rounded-full px-2 py-0.5 text-sm/tight font-semibold border bg-blue-200 text-blue-900 border-blue-200 whitespace-nowrap">Under review</span>
124166
{% elif version.is_draft %}
@@ -127,8 +169,8 @@ <h2 class="text-2xl/tight font-bold text-slate-900">Your codelists</h2>
127169
<span class="inline-flex rounded-full px-2 py-0.5 text-sm/tight font-semibold border bg-green-200 text-green-900 border-green-200 whitespace-nowrap">Published</span>
128170
{% endif %}
129171
</td>
130-
<td class="px-3 py-2 whitespace-nowrap ">{{ version.codes|length }} code{{ version.codes|pluralize}}</td>
131-
<td class="px-3 py-2 pl-3 sm:pr-3">
172+
<td class="px-3 py-2 whitespace-nowrap group-hover:bg-yellow-50">{{ version.codes|length }} code{{ version.codes|pluralize}}</td>
173+
<td class="date-sort-column px-3 py-2 pl-3 sm:pr-3 group-hover:bg-yellow-50">
132174
<time class="whitespace-nowrap" datetime="{{ version.updated_at|date:"c" }}">
133175
{{ version.updated_at|date:'d M Y' }} at {{ version.updated_at|date:'H:i' }}
134176
</time>
@@ -150,9 +192,15 @@ <h2 class="text-2xl/tight font-bold text-slate-900">Your codelists</h2>
150192
<script nonce="{{ request.csp_nonce }}">
151193
const nameSortButton = document.getElementById("sort-codelists-by-name");
152194
const dateSortButton = document.getElementById("sort-codelists-by-date");
195+
const nameSortIcon = nameSortButton?.querySelector('[data-sort-icon="direction"]');
196+
const dateSortIcon = dateSortButton?.querySelector('[data-sort-icon="direction"]');
197+
const nameUnsortedIcon = nameSortButton?.querySelector('[data-sort-icon="unsorted"]');
198+
const dateUnsortedIcon = dateSortButton?.querySelector('[data-sort-icon="unsorted"]');
153199
const codelistsTable = nameSortButton?.closest("table");
154200
let isNameDescending = false;
155201
let isDateDescending = false;
202+
const activeIconClasses = ["bg-gray-200", "text-gray-900", "group-hover:bg-gray-300"];
203+
const sortedColumnClass = "bg-transparent";
156204

157205
const getCodelistName = (tbody) => {
158206
const nameCell = tbody.querySelector("tr td");
@@ -188,6 +236,49 @@ <h2 class="text-2xl/tight font-bold text-slate-900">Your codelists</h2>
188236
: Math.min(...timestamps);
189237
};
190238

239+
const updateSortIcon = (icon, isActive, isDescending) => {
240+
if (!icon) {
241+
return;
242+
}
243+
244+
icon.classList.remove(...activeIconClasses, "rotate-180", "hidden");
245+
246+
if (isActive) {
247+
icon.classList.add(...activeIconClasses);
248+
if (!isDescending) {
249+
icon.classList.add("rotate-180");
250+
}
251+
} else {
252+
icon.classList.add("hidden");
253+
}
254+
};
255+
256+
const updateUnsortedIcon = (icon, shouldShow) => {
257+
if (!icon) {
258+
return;
259+
}
260+
261+
icon.classList.toggle("hidden", !shouldShow);
262+
};
263+
264+
const highlightSortedColumn = (columnName) => {
265+
document.querySelectorAll(".name-sort-column, .date-sort-column").forEach((cell) => {
266+
cell.classList.remove(sortedColumnClass);
267+
});
268+
269+
if (columnName === "name") {
270+
document.querySelectorAll(".name-sort-column").forEach((cell) => {
271+
cell.classList.add(sortedColumnClass);
272+
});
273+
}
274+
275+
if (columnName === "date") {
276+
document.querySelectorAll(".date-sort-column").forEach((cell) => {
277+
cell.classList.add(sortedColumnClass);
278+
});
279+
}
280+
};
281+
191282
const setSortState = (activeButton) => {
192283
[nameSortButton, dateSortButton].forEach((button) => {
193284
if (!button) {
@@ -196,10 +287,18 @@ <h2 class="text-2xl/tight font-bold text-slate-900">Your codelists</h2>
196287

197288
button.setAttribute("aria-pressed", String(button === activeButton));
198289
});
290+
291+
updateSortIcon(nameSortIcon, activeButton === nameSortButton, isNameDescending);
292+
updateSortIcon(dateSortIcon, activeButton === dateSortButton, isDateDescending);
293+
updateUnsortedIcon(nameUnsortedIcon, activeButton !== nameSortButton);
294+
updateUnsortedIcon(dateUnsortedIcon, activeButton !== dateSortButton);
295+
highlightSortedColumn(activeButton === nameSortButton ? "name" : "date");
199296
};
200297

201298
const sortTableBodiesByName = () => {
202299
const tableBodies = getTableBodies();
300+
tableBodies.forEach((tbody) => sortRowsByDate(tbody, true));
301+
203302
tableBodies
204303
.sort((leftBody, rightBody) => {
205304
const leftName = getCodelistName(leftBody);

0 commit comments

Comments
 (0)