-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #665 from opensafely-core/datatable-csv
Create a custom datatable component for Airlock
- Loading branch information
Showing
19 changed files
with
391 additions
and
259 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,11 @@ | ||
// ensure datatable is initialised when loading over HTMX | ||
window.initCustomTable ? window.initCustomTable() : null; | ||
|
||
// implement select all checkbox | ||
function toggleSelectAll(elem, event) { | ||
function toggleSelectAll(elem) { | ||
const form = document.querySelector("#multiselect_form"); | ||
|
||
const checkboxes = form.querySelectorAll('input[type="checkbox"]'); | ||
/** @type {NodeListOf<HTMLInputElement>|undefined} */ | ||
const checkboxes = form?.querySelectorAll('input[type="checkbox"]'); | ||
|
||
checkboxes.forEach(function(checkbox) { | ||
checkboxes?.forEach(function(checkbox) { | ||
checkbox.checked = elem.checked; | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<div class="table-container"> | ||
<p class="spinner p-4" data-datatable-spinner>Loading table data...</p> | ||
<table | ||
class="{{ class }} hidden" | ||
data-datatable | ||
{% if per_page %} | ||
data-per-page="{{ per_page }}" | ||
{% endif %} | ||
{% attrs id data-column-filter=column_filter data-sortable=sortable data-searchable=searchable %} | ||
> | ||
{{ children }} | ||
</table> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,88 +1,68 @@ | ||
{% load airlock %} | ||
{% load django_vite %} | ||
{% load static %} | ||
|
||
<link rel="stylesheet" href="{% static 'assets/datatable.css' %}"> | ||
|
||
{% #card title="Recent activity" %} | ||
{% #card title="Recent activity" class="mt-5" %} | ||
{% if activity %} | ||
<div id="airlock-table"> | ||
<p class="spinner">Loading table data...</p> | ||
<table class="datatable hidden" id="customTable"> | ||
<thead> | ||
{% #datatable per_page="10" column_filter searchable sortable %} | ||
<thead> | ||
<tr> | ||
<th> | ||
<div class="flex flex-row gap-2 items-center"> | ||
Time | ||
<span class="sort-icon h-4 w-4 [&_img]:h-4 [&_img]:w-4"> | ||
{% datatable_sort_icon %} | ||
</span> | ||
</div> | ||
</th> | ||
<th> | ||
<div class="flex flex-row gap-2 items-center"> | ||
User | ||
<span class="sort-icon h-4 w-4 [&_img]:h-4 [&_img]:w-4"> | ||
{% datatable_sort_icon %} | ||
</span> | ||
</div> | ||
</th> | ||
<th> | ||
<div class="flex flex-row gap-2 items-center"> | ||
Action | ||
<span class="sort-icon h-4 w-4 [&_img]:h-4 [&_img]:w-4"> | ||
{% datatable_sort_icon %} | ||
</span> | ||
</div> | ||
</th> | ||
<th> | ||
<div class="flex flex-row gap-2 items-center"> | ||
Details | ||
<span class="sort-icon h-4 w-4 [&_img]:h-4 [&_img]:w-4"> | ||
{% datatable_sort_icon %} | ||
</span> | ||
</div> | ||
</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{% for log in activity %} | ||
<tr> | ||
<th><div class="flex flex-row gap-2">Time{% datatable_sort_icon %}</div></th> | ||
<th><div class="flex flex-row gap-2">User{% datatable_sort_icon %}</div></th> | ||
<th><div class="flex flex-row gap-2">Action{% datatable_sort_icon %}</div></th> | ||
<th><div class="flex flex-row gap-2">Details{% datatable_sort_icon %}</div></th> | ||
<td>{{ log.created_at|date:'Y-m-d H:i' }}</td> | ||
<td>{{ log.user }}</td> | ||
<td>{{ log.description }}</td> | ||
<td> | ||
<ul> | ||
{% if log.path %}<li><b>path:</b> {{ log.path }}</li>{% endif %} | ||
{% for k,v in log.extra.items %} | ||
<li><b>{{ k }}:</b> {{ v }}</li> | ||
{% endfor %} | ||
</ul> | ||
</td> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{% for log in activity %} | ||
<tr> | ||
<td>{{ log.created_at|date:'Y-m-d H:i' }}</td> | ||
<td>{{ log.user }}</td> | ||
<td>{{ log.description }}</td> | ||
<td> | ||
<ul> | ||
{% if log.path %}<li><b>path:</b> {{ log.path }}</li>{% endif %} | ||
{% for k,v in log.extra.items %} | ||
<li><b>{{ k }}:</b> {{ v }}</li> | ||
{% endfor %} | ||
</ul> | ||
</td> | ||
</tr> | ||
{% endfor %} | ||
</tbody> | ||
</table> | ||
</table> | ||
|
||
<nav id="pagination-nav" class="hidden flex items-center justify-between border-t border-gray-200 bg-white px-4 py-3" aria-label="Pagination"> | ||
<div class="sm:block"> | ||
<p class="text-sm text-gray-700"> | ||
Page | ||
<strong data-table-pagination="page-number">#</strong> | ||
of | ||
<strong data-table-pagination="total-pages">#</strong> | ||
</p> | ||
</div> | ||
<div class="flex flex-1 justify-between gap-4 sm:justify-end"> | ||
<button | ||
data-table-pagination="previous-page" | ||
class=" | ||
px-4 py-2 text-sm font-medium | ||
inline-flex items-center justify-center border rounded-md shadow-sm transition-buttons duration-200 | ||
border border-slate-400/75 text-slate-700 !shadow-none | ||
hover:bg-slate-200 | ||
focus:bg-slate-200 focus:ring-slate-500 focus:ring-offset-white | ||
hover:shadow-lg | ||
focus:outline-none focus:ring-2 focus:ring-offset-2" | ||
> | ||
Previous | ||
</button> | ||
<button | ||
data-table-pagination="next-page" | ||
class=" | ||
px-4 py-2 text-sm font-medium | ||
inline-flex items-center justify-center border rounded-md shadow-sm transition-buttons duration-200 | ||
border border-slate-400/75 text-slate-700 !shadow-none | ||
hover:bg-slate-200 | ||
focus:bg-slate-200 focus:ring-slate-500 focus:ring-offset-white | ||
hover:shadow-lg | ||
focus:outline-none focus:ring-2 focus:ring-offset-2" | ||
> | ||
Next | ||
</button> | ||
</div> | ||
</nav> | ||
</div> | ||
{% endfor %} | ||
</tbody> | ||
{% /datatable %} | ||
{% else %} | ||
{% #list_group %} | ||
{% list_group_empty title="No activity" description="There has been no recent activity on this workspace" %} | ||
{% /list_group %} | ||
{% endif %} | ||
{% /card %} | ||
|
||
{% vite_asset "assets/src/scripts/components.js" app="job_server" %} | ||
<script defer src="{% static 'assets/activity.js' %}"></script> | ||
<script defer src="{% static 'assets/datatable-loader.js' %}"></script> | ||
{% vite_asset "assets/src/scripts/datatable.js" %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.