diff --git a/lib/common/debounce.ts b/lib/common/debounce.ts new file mode 100644 index 0000000..e842320 --- /dev/null +++ b/lib/common/debounce.ts @@ -0,0 +1,16 @@ +export default function debounce( + func: (args: T[]) => void, + timeout: number +): (arg: T) => void { + let timer: ReturnType; + let args: T[] = []; + return (arg: T) => { + args.push(arg); + clearTimeout(timer); + timer = setTimeout(() => { + const argscopy = args; + args = []; + func(argscopy); + }, timeout); + }; +} diff --git a/ui/devices-page.ts b/ui/devices-page.ts index d245a5c..7e3f236 100644 --- a/ui/devices-page.ts +++ b/ui/devices-page.ts @@ -268,18 +268,14 @@ export const component: ClosureComponent = (): Component => { } function onSortChange(sortedAttrs): void { - let _sort = Object.assign({}, sort); - for (const [index, direction] of Object.entries(sortedAttrs)) { - const param = memoizedGetSortable(attributes[index].parameter); - if (param) { - // Changing the priority of columns - delete _sort[param]; - if (direction) _sort = Object.assign({ [param]: direction }, _sort); - } + const _sort = {}; + for (const index of sortedAttrs) { + const param = memoizedGetSortable( + attributes[Math.abs(index) - 1].parameter + ); + _sort[param] = Math.sign(index); } - - const ops = {}; - if (Object.keys(_sort).length) ops["sort"] = JSON.stringify(_sort); + const ops = { sort: JSON.stringify(_sort) }; if (vnode.attrs["filter"]) ops["filter"] = vnode.attrs["filter"]; m.route.set("/devices", ops); } diff --git a/ui/faults-page.ts b/ui/faults-page.ts index 5bc58cb..fe51966 100644 --- a/ui/faults-page.ts +++ b/ui/faults-page.ts @@ -107,16 +107,10 @@ export const component: ClosureComponent = (): Component => { } function onSortChange(sortAttrs): void { - let _sort = Object.assign({}, sort); - for (const [index, direction] of Object.entries(sortAttrs)) { - // Changing the priority of columns - delete _sort[attributes[index].id]; - if (direction) - _sort = Object.assign({ [attributes[index].id]: direction }, _sort); - } - - const ops = {}; - if (Object.keys(_sort).length) ops["sort"] = JSON.stringify(_sort); + const _sort = {}; + for (const index of sortAttrs) + _sort[attributes[Math.abs(index) - 1].id] = Math.sign(index); + const ops = { sort: JSON.stringify(_sort) }; if (vnode.attrs["filter"]) ops["filter"] = vnode.attrs["filter"]; m.route.set("/faults", ops); } diff --git a/ui/files-page.ts b/ui/files-page.ts index 3c85528..bf30cca 100644 --- a/ui/files-page.ts +++ b/ui/files-page.ts @@ -151,16 +151,10 @@ export const component: ClosureComponent = (): Component => { sortAttributes[i] = sort[attributes[i].id] || 0; function onSortChange(sortAttrs): void { - let _sort = Object.assign({}, sort); - for (const [index, direction] of Object.entries(sortAttrs)) { - // Changing the priority of columns - delete _sort[attributes[index].id]; - if (direction) - _sort = Object.assign({ [attributes[index].id]: direction }, _sort); - } - - const ops = {}; - if (Object.keys(_sort).length) ops["sort"] = JSON.stringify(_sort); + const _sort = {}; + for (const index of sortAttrs) + _sort[attributes[Math.abs(index) - 1].id] = Math.sign(index); + const ops = { sort: JSON.stringify(_sort) }; if (vnode.attrs["filter"]) ops["filter"] = vnode.attrs["filter"]; m.route.set("/admin/files", ops); } diff --git a/ui/index-table-component.ts b/ui/index-table-component.ts index dcf9eac..d28bb95 100644 --- a/ui/index-table-component.ts +++ b/ui/index-table-component.ts @@ -20,6 +20,7 @@ import { ClosureComponent, Component, Children } from "mithril"; import { m } from "./components"; import { getIcon } from "./icons"; +import debounce from "../lib/common/debounce"; interface Attribute { id?: string; @@ -36,7 +37,7 @@ function renderTable( showMoreCallback: () => void, selected: Set, sortAttributes: Record, - onSortChange: (obj: Record) => void, + onSort: (i: number) => void, downloadUrl?: string, valueCallback?: (attr: Attribute, record: Record) => Children, actionsCallback?: Children | ((sel: Set) => Children), @@ -86,9 +87,9 @@ function renderTable( const sortable = m( "button", { - onclick: () => { - const direction = ((sortAttributes[i] + 2) % 3) - 1; - return onSortChange({ [i]: direction }); + onclick: (e) => { + e.redraw = false; + onSort(i); }, }, symbol @@ -213,7 +214,10 @@ function renderTable( const component: ClosureComponent = (): Component => { let selected = new Set(); - + let sortingfunction: (events: number[]) => void; + const onSort = debounce((events: number[]) => { + sortingfunction(events); + }, 500); return { view: (vnode) => { const attributes = vnode.attrs["attributes"]; @@ -232,6 +236,20 @@ const component: ClosureComponent = (): Component => { const id = record["_id"] || record["DeviceID.ID"].value[0]; if (selected.has(id)) _selected.add(id); } + + sortingfunction = (events) => { + const sortArray = new Set( + Object.keys(sortAttributes) + .map((x) => (parseInt(x) + 1) * sortAttributes[x]) + .filter((x) => x) + ); + for (const num of events) { + if (sortArray.delete(num + 1)) sortArray.add(-(num + 1)); + else if (!sortArray.delete((num + 1) * -1)) sortArray.add(num + 1); + } + onSortChange(Array.from(sortArray).reverse()); + }; + selected = _selected; return renderTable( @@ -241,7 +259,7 @@ const component: ClosureComponent = (): Component => { showMoreCallback, selected, sortAttributes, - onSortChange, + onSort, downloadUrl, valueCallback, actionsCallback, diff --git a/ui/permissions-page.ts b/ui/permissions-page.ts index 988a3b3..bb8333b 100644 --- a/ui/permissions-page.ts +++ b/ui/permissions-page.ts @@ -205,16 +205,10 @@ export const component: ClosureComponent = (): Component => { } function onSortChange(sortAttrs): void { - let _sort = Object.assign({}, sort); - for (const [index, direction] of Object.entries(sortAttrs)) { - // Changing the priority of columns - delete _sort[attributes[index].id]; - if (direction) - _sort = Object.assign({ [attributes[index].id]: direction }, _sort); - } - - const ops = {}; - if (Object.keys(_sort).length) ops["sort"] = JSON.stringify(_sort); + const _sort = {}; + for (const index of sortAttrs) + _sort[attributes[Math.abs(index) - 1].id] = Math.sign(index); + const ops = { sort: JSON.stringify(_sort) }; if (vnode.attrs["filter"]) ops["filter"] = vnode.attrs["filter"]; m.route.set("/admin/permissions", ops); } diff --git a/ui/presets-page.ts b/ui/presets-page.ts index 2b9cc7a..528df89 100644 --- a/ui/presets-page.ts +++ b/ui/presets-page.ts @@ -190,16 +190,10 @@ export const component: ClosureComponent = (): Component => { } function onSortChange(sortAttrs): void { - let _sort = Object.assign({}, sort); - for (const [index, direction] of Object.entries(sortAttrs)) { - // Changing the priority of columns - delete _sort[attributes[index].id]; - if (direction) - _sort = Object.assign({ [attributes[index].id]: direction }, _sort); - } - - const ops = {}; - if (Object.keys(_sort).length) ops["sort"] = JSON.stringify(_sort); + const _sort = {}; + for (const index of sortAttrs) + _sort[attributes[Math.abs(index) - 1].id] = Math.sign(index); + const ops = { sort: JSON.stringify(_sort) }; if (vnode.attrs["filter"]) ops["filter"] = vnode.attrs["filter"]; m.route.set("/admin/presets", ops); } diff --git a/ui/provisions-page.ts b/ui/provisions-page.ts index f4ff23e..a797831 100644 --- a/ui/provisions-page.ts +++ b/ui/provisions-page.ts @@ -173,16 +173,10 @@ export const component: ClosureComponent = (): Component => { sortAttributes[i] = sort[attributes[i].id] || 0; function onSortChange(sortAttrs): void { - let _sort = Object.assign({}, sort); - for (const [index, direction] of Object.entries(sortAttrs)) { - // Changing the priority of columns - delete _sort[attributes[index].id]; - if (direction) - _sort = Object.assign({ [attributes[index].id]: direction }, _sort); - } - - const ops = {}; - if (Object.keys(_sort).length) ops["sort"] = JSON.stringify(_sort); + const _sort = {}; + for (const index of sortAttrs) + _sort[attributes[Math.abs(index) - 1].id] = Math.sign(index); + const ops = { sort: JSON.stringify(_sort) }; if (vnode.attrs["filter"]) ops["filter"] = vnode.attrs["filter"]; m.route.set("/admin/provisions", ops); } diff --git a/ui/users-page.ts b/ui/users-page.ts index 076e64c..ee8abaf 100644 --- a/ui/users-page.ts +++ b/ui/users-page.ts @@ -186,16 +186,10 @@ export const component: ClosureComponent = (): Component => { } function onSortChange(sortAttrs): void { - let _sort = Object.assign({}, sort); - for (const [index, direction] of Object.entries(sortAttrs)) { - // Changing the priority of columns - delete _sort[attributes[index].id]; - if (direction) - _sort = Object.assign({ [attributes[index].id]: direction }, _sort); - } - - const ops = {}; - if (Object.keys(_sort).length) ops["sort"] = JSON.stringify(_sort); + const _sort = {}; + for (const index of sortAttrs) + _sort[attributes[Math.abs(index) - 1].id] = Math.sign(index); + const ops = { sort: JSON.stringify(_sort) }; if (vnode.attrs["filter"]) ops["filter"] = vnode.attrs["filter"]; m.route.set("/admin/users", ops); } diff --git a/ui/virtual-parameters-page.ts b/ui/virtual-parameters-page.ts index e6d45dd..f728ed4 100644 --- a/ui/virtual-parameters-page.ts +++ b/ui/virtual-parameters-page.ts @@ -173,16 +173,10 @@ export const component: ClosureComponent = (): Component => { sortAttributes[i] = sort[attributes[i].id] || 0; function onSortChange(sortAttrs): void { - let _sort = Object.assign({}, sort); - for (const [index, direction] of Object.entries(sortAttrs)) { - // Changing the priority of columns - delete _sort[attributes[index].id]; - if (direction) - _sort = Object.assign({ [attributes[index].id]: direction }, _sort); - } - - const ops = {}; - if (Object.keys(_sort).length) ops["sort"] = JSON.stringify(_sort); + const _sort = {}; + for (const index of sortAttrs) + _sort[attributes[Math.abs(index) - 1].id] = Math.sign(index); + const ops = { sort: JSON.stringify(_sort) }; if (vnode.attrs["filter"]) ops["filter"] = vnode.attrs["filter"]; m.route.set("/admin/virtualParameters", ops); }