Skip to content

Commit

Permalink
Initial WIP for CSV datatable component
Browse files Browse the repository at this point in the history
  • Loading branch information
tomodwyer committed Sep 10, 2024
1 parent 8160145 commit 31b0d26
Show file tree
Hide file tree
Showing 8 changed files with 299 additions and 37 deletions.
10 changes: 10 additions & 0 deletions airlock/templates/_components/datatable.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<table
class="{{ class }}"
data-datatable
{% if not paging and per_page %}
data-per-page="{{ per_page }}"
{% endif %}
{% attrs id data-column-filter=column_filter data-paging=paging data-per-page=per_page data-sortable=sortable data-searchable=searchable %}
>
{{ children }}
</table>
94 changes: 59 additions & 35 deletions airlock/templates/file_browser/file_content/csv.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,52 +3,76 @@
{% load static %}

<!DOCTYPE html>
<html lang="en">
<html lang="en" class="min-h-screen">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">

{% vite_hmr_client %}
{% vite_asset "assets/src/scripts/base.js" app="job_server" %}
{% vite_asset "assets/src/scripts/components.js" app="job_server" %}
<link rel="stylesheet" href="{% static 'assets/datatable.css' %}">
<link rel="stylesheet" href="{% static 'assets/icons.css' %}">
{% vite_asset "assets/src/scripts/main.js" %}
{% vite_asset "assets/src/datatable.js" %}
</head>

<body>

<div id="airlock-table">
{% if use_datatables %}
<p class="spinner">Loading table data...</p>
<table class="datatable hidden" id="customTable">
<p class="spinner p-4">Loading table data...</p>
{% #datatable class="hidden" column_filter searchable sortable %}
<thead>
<tr>
{% for header in headers %}
<th>
<div class="flex flex-row gap-2">
{{ header }}
{% if use_datatables %}
<span class="sort-icon">{% datatable_sort_icon %}</span>
{% endif %}
</dir>
</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for row in rows %}
<tr>
{% for cell in row %}
<td data-order="{{ cell }}">{{ cell }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
{% /datatable %}
{% else %}
<table>
{% endif %}
<thead>
<tr>
{% for header in headers %}
<th>
<div class="flex flex-row gap-2">
{{ header }}
{% if use_datatables %}
<span class="sort-icon">{% datatable_sort_icon %}</span>
{% endif %}
</dir>
</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for row in rows %}
<tr>
{% for cell in row %}
<td data-order="{{ cell }}">{{ cell }}</td>
<thead>
<tr>
{% for header in headers %}
<th>
<div class="flex flex-row gap-2">
{{ header }}
{% if use_datatables %}
<span class="sort-icon">{% datatable_sort_icon %}</span>
{% endif %}
</dir>
</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for row in rows %}
<tr>
{% for cell in row %}
<td data-order="{{ cell }}">{{ cell }}</td>
{% endfor %}
</tr>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>

</div>
</tbody>
</table>
{% endif %}

<script src="{% static 'assets/datatable-loader.js' %}"></script>
</body>
</div>
</body>

</html>
1 change: 1 addition & 0 deletions airlock/templatetags/airlock_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"airlock_workspace_header": "_components/header/workspace/header.html",
"airlock_request_header": "_components/header/request/header.html",
"airlock_repo_header": "_components/header/repo/header.html",
"datatable": "_components/datatable.html",
},
register,
)
122 changes: 122 additions & 0 deletions assets/src/datatable.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
[data-datatable] {
@apply min-w-full divide-y divide-slate-300;

& thead {
@apply bg-slate-200;
}

& th {
color: var(--color-slate-900);
font-size: 0.875rem;
font-weight: 600;
line-height: 1.25rem;
text-align: left;
white-space: nowrap;
width: auto !important;

& button {
padding: 0.5rem;
position: relative;
text-align: left;
width: 100%;
}

&:has(input) {
padding: 0.5rem;
}

& input.datatable-input {
display: block;
width: 100%;
border-radius: 0.375rem;
border-color: var(--color-slate-300);
font-weight: 400;
box-shadow:
0 0 rgba(0, 0, 0, 0),
0 0 rgba(0, 0, 0, 0),
0 1px 2px 0 rgba(0, 0, 0, 0.05);

@media (min-width: 640px) {
font-size: 0.875rem;
line-height: 1.25rem;
}

&:focus {
border-color: var(--color-oxford-500);
outline-color: var(--color-oxford-500);
outline-offset: -1px;
}
}

& .datatable-icon--descending,
& .datatable-icon--ascending {
display: none;
}

& .datatable-icon--no-sort {
display: block;
}

&.datatable-ascending {
& .datatable-icon--no-sort,
& .datatable-icon--descending {
display: none;
}

& .datatable-icon--ascending {
display: block;
}
}

&.datatable-descending {
& .datatable-icon--no-sort,
& .datatable-icon--ascending {
display: none;
}

& .datatable-icon--descending {
display: block;
}
}
}

& tbody > tr ~ tr {
background-color: var(--color-white);
}

& tbody > tr ~ tr:not(:last-child) {
border-block: 1px solid var(--color-slate-200);
}

& tr:nth-child(even) {
background-color: var(--color-slate-50);
}

& td {
color: var(--color-slate-700);
font-size: 0.875rem;
line-height: 1.25rem;
padding: 0.5rem;
}

& a {
color: var(--color-oxford-600);
font-weight: 600;
text-decoration: underline #69afff;
text-underline-offset: 2px;
transition-duration: 200ms;
transition-property: color, background-color, border-color,
text-decoration-color;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);

&:hover,
&:focus {
color: var(--color-oxford-800);
text-decoration-color: transparent;
}

&:focus {
background-color: var(--color-bn-sun-300);
}
}
}
80 changes: 80 additions & 0 deletions assets/src/datatable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { DataTable } from "simple-datatables";
import "./datatable.css";

/**
* @param {string} value
*/
function hasOnlyDigits(value) {
return /^\d+$/.test(value);
}

/** @type {NodeListOf<HTMLTableElement> | null} */
const datatableEls = document.querySelectorAll("[data-datatable]");

datatableEls?.forEach((table) => {
const columnFilter = table.hasAttribute("data-column-filter");
const paging = table.hasAttribute("data-paging");
const searchable = table.hasAttribute("data-searchable");
const sortable = table.hasAttribute("data-sortable");

let perPage = undefined;
if (table.hasAttribute("data-per-page")) {
const dataPerPage = table.getAttribute("data-per-page");
if (dataPerPage !== null && hasOnlyDigits(dataPerPage)) {
perPage = parseInt(dataPerPage);
}
}

let dataTable = new DataTable(table, {
classes: {
table: "datatable-table min-w-full divide-y divide-slate-300",
top: "hidden",
},
paging,
perPage,
searchable,
sortable,
tableRender: columnFilter
? (_data, table) => {
const tHead = table.childNodes?.[0];
const filterHeaders = {
nodeName: "TR",
childNodes: tHead?.childNodes?.[0].childNodes?.map((_th, index) => {
const showSearch = _th.attributes["data-searchable"] !== "false";

return {
nodeName: "TH",
childNodes: showSearch
? [
{
nodeName: "INPUT",
attributes: {
class:
"datatable-input block w-full border-slate-300 font-normal shadow-sm rounded-md sm:text-sm sm:leading-5 focus:border-oxford-500 focus:outline-oxford-500 focus:-outline-offset-1",
"data-columns": `[${index}]`,
// @ts-ignore
placeholder: `Filter ${_data.headings[index].text
.trim()
.toLowerCase()}`,
type: "search",
},
},
]
: [],
};
}),
};
tHead?.childNodes?.push(filterHeaders);
return table;
}
: false,
});

dataTable.on("datatable.init", () => {
const spinner = document.querySelector("#airlock-table .spinner");
spinner?.classList.toggle("hidden");

const table = document.querySelector("#airlock-table [data-datatable]");
table?.classList.toggle("hidden");
});
});
25 changes: 24 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
},
"dependencies": {
"@fontsource-variable/public-sans": "^5.0.19",
"htmx.org": "^1.9.12"
"htmx.org": "^1.9.12",
"simple-datatables": "^9.1.0"
}
}
Loading

0 comments on commit 31b0d26

Please sign in to comment.