Skip to content

Commit

Permalink
Use new datatable column handling description for software
Browse files Browse the repository at this point in the history
  • Loading branch information
UpstreamData authored and b-rowan committed Dec 3, 2024
1 parent 3257fae commit 7acae19
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 131 deletions.
8 changes: 8 additions & 0 deletions goosebit/ui/bff/common/columns.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,11 @@ class RolloutColumns:
paused = DTColumnDescription(title="Paused", name="paused", data="paused")
success_count = DTColumnDescription(title="Success Count", data="success_count", name="success_count")
failure_count = DTColumnDescription(title="Failure Count", data="failure_count", name="failure_count")


class SoftwareColumns:
id = DTColumnDescription(title="ID", data="id", visible=False)
name = DTColumnDescription(title="Name", data="name", name="name")
version = DTColumnDescription(title="Version", data="version", name="version", searchable=True, orderable=True)
compatibility = DTColumnDescription(title="Compatibility", name="compatibility", data="compatibility")
size = DTColumnDescription(title="Size", name="size", data="size")
23 changes: 23 additions & 0 deletions goosebit/ui/bff/software/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
from goosebit.ui.bff.common.util import parse_datatables_query
from goosebit.updates import create_software_update

from ..common.columns import SoftwareColumns
from ..common.responses import DTColumns
from .responses import BFFSoftwareResponse

router = APIRouter(prefix="/software")
Expand Down Expand Up @@ -94,3 +96,24 @@ async def post_update(
await create_software_update(absolute.as_uri(), temp_file)
finally:
await temp_file.unlink(missing_ok=True)


@router.get(
"/columns",
dependencies=[Security(validate_user_permissions, scopes=["software.read"])],
response_model_exclude_none=True,
)
async def devices_get_columns() -> DTColumns:
columns = list(
filter(
None,
[
SoftwareColumns.id,
SoftwareColumns.name,
SoftwareColumns.version,
SoftwareColumns.compatibility,
SoftwareColumns.size,
],
)
)
return DTColumns(columns=columns)
242 changes: 122 additions & 120 deletions goosebit/ui/static/js/software.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,128 @@ const uploadProgressBar = document.getElementById("upload-progress");

let dataTable;

const renderFunctions = {
compatibility: (data, type) => {
const result = data.reduce((acc, { model, revision }) => {
if (!acc[model]) {
acc[model] = [];
}
acc[model].push(revision);
return acc;
}, {});

return Object.entries(result)
.map(([model, revision]) => `${model} - ${revision.join(", ")}`)
.join("\n");
},
size: (data, type) => {
if (type === "display" || type === "filter") {
return `${(data / 1024 / 1024).toFixed(2)}MB`;
}
return data;
},
};

document.addEventListener("DOMContentLoaded", async () => {
const columnConfig = await get_request("/ui/bff/software/columns");
for (const col in columnConfig.columns) {
const colDesc = columnConfig.columns[col];
const colName = colDesc.data;
if (renderFunctions[colName]) {
columnConfig.columns[col].render = renderFunctions[colName];
}
}

const buttons = [
{
text: '<i class="bi bi-cloud-download" ></i>',
action: (e, dt) => {
const selectedSoftware = dt
.rows({ selected: true })
.data()
.toArray()
.map((d) => d.id);
downloadSoftware(selectedSoftware[0]);
},
className: "buttons-download",
titleAttr: "Download Software",
},
{
text: '<i class="bi bi-trash" ></i>',
action: async (e, dt) => {
const selectedSoftware = dt
.rows({ selected: true })
.data()
.toArray()
.map((d) => d.id);
await deleteSoftware(selectedSoftware);
},
className: "buttons-delete",
titleAttr: "Delete Software",
},
];

// add create button at the beginning if upload modal exists
if ($("#upload-modal").length > 0) {
buttons.unshift({
text: '<i class="bi bi-plus" ></i>',
action: () => {
new bootstrap.Modal("#upload-modal").show();
},
className: "buttons-create",
titleAttr: "Add Software",
});
}

dataTable = new DataTable("#software-table", {
responsive: true,
paging: true,
processing: false,
serverSide: true,
scrollCollapse: true,
scroller: true,
scrollY: "60vh",
stateSave: true,
ajax: {
url: "/ui/bff/software",
data: (data) => {
// biome-ignore lint/performance/noDelete: really has to be deleted
delete data.columns;
},
contentType: "application/json",
},
initComplete: () => {
updateBtnState();
},
columnDefs: [
{
targets: "_all",
searchable: false,
orderable: false,
render: (data) => data || "-",
},
],
columns: columnConfig.columns,
select: true,
rowId: "id",
layout: {
bottom1Start: {
buttons,
},
},
});

dataTable
.on("select", () => {
updateBtnState();
})
.on("deselect", () => {
updateBtnState();
});

updateSoftwareList();
});

uploadForm.addEventListener("submit", async (e) => {
e.preventDefault();
await sendFileChunks(uploadFileInput.files[0]);
Expand Down Expand Up @@ -125,126 +247,6 @@ function resetProgress() {
updateSoftwareList();
}

document.addEventListener("DOMContentLoaded", () => {
const buttons = [
{
text: '<i class="bi bi-cloud-download" ></i>',
action: (e, dt) => {
const selectedSoftware = dt
.rows({ selected: true })
.data()
.toArray()
.map((d) => d.id);
downloadSoftware(selectedSoftware[0]);
},
className: "buttons-download",
titleAttr: "Download Software",
},
{
text: '<i class="bi bi-trash" ></i>',
action: async (e, dt) => {
const selectedSoftware = dt
.rows({ selected: true })
.data()
.toArray()
.map((d) => d.id);
await deleteSoftware(selectedSoftware);
},
className: "buttons-delete",
titleAttr: "Delete Software",
},
];

// add create button at the beginning if upload modal exists
if ($("#upload-modal").length > 0) {
buttons.unshift({
text: '<i class="bi bi-plus" ></i>',
action: () => {
new bootstrap.Modal("#upload-modal").show();
},
className: "buttons-create",
titleAttr: "Add Software",
});
}

dataTable = new DataTable("#software-table", {
responsive: true,
paging: true,
processing: false,
serverSide: true,
scrollCollapse: true,
scroller: true,
scrollY: "60vh",
stateSave: true,
ajax: {
url: "/ui/bff/software",
data: (data) => {
// biome-ignore lint/performance/noDelete: really has to be deleted
delete data.columns;
},
contentType: "application/json",
},
initComplete: () => {
updateBtnState();
},
columnDefs: [
{
targets: "_all",
searchable: false,
orderable: false,
render: (data) => data || "-",
},
],
columns: [
{ data: "id", visible: false },
{ data: "name" },
{ data: "version", name: "version", searchable: true, orderable: true },
{
data: "compatibility",
render: (data) => {
const result = data.reduce((acc, { model, revision }) => {
if (!acc[model]) {
acc[model] = [];
}
acc[model].push(revision);
return acc;
}, {});

return Object.entries(result)
.map(([model, revision]) => `${model} - ${revision.join(", ")}`)
.join("\n");
},
},
{
data: "size",
render: (data, type) => {
if (type === "display" || type === "filter") {
return `${(data / 1024 / 1024).toFixed(2)}MB`;
}
return data;
},
},
],
select: true,
rowId: "id",
layout: {
bottom1Start: {
buttons,
},
},
});

dataTable
.on("select", () => {
updateBtnState();
})
.on("deselect", () => {
updateBtnState();
});

updateSoftwareList();
});

function updateBtnState() {
if (dataTable.rows({ selected: true }).any()) {
document.querySelector("button.buttons-delete").classList.remove("disabled");
Expand Down
11 changes: 0 additions & 11 deletions goosebit/ui/templates/software.html.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,6 @@
<div class="row p-2 pt-4 g-4 d-flex justify-content-center">
<div class="col">
<table id="software-table" class="table table-hover">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Version</th>
<th>Compatibility</th>
<th>Size</th>
</tr>
</thead>
<tbody id="software-list">
</tbody>
</table>
</div>
</div>
Expand Down

0 comments on commit 7acae19

Please sign in to comment.