Display spinner animation during loading

This commit is contained in:
Zaid Abdulla committed 2021-02-16 00:09:24 -08:00
1 parent 4871613c67
commit 688811317c
23 files changed
+447 -307

No files matched your search

+21 -17
View File
@@ -171,25 +171,29 @@ const component: ClosureComponent = (): Component => {
});
return m(
".all-parameters",
"loading",
{ queries: [vnode.attrs["deviceQuery"]] },
m(
"a.download-csv",
{
href: `api/devices/${encodeURIComponent(
device["DeviceID.ID"].value[0]
)}.csv`,
download: "",
style: "float: right;",
},
"Download"
),
search,
m(
".parameter-list",
m("table", m("tbody", rows)),
".all-parameters",
m(
"m",
`Displaying ${filteredKeys.length} out of ${count} parameters.`
"a.download-csv",
{
href: `api/devices/${encodeURIComponent(
device["DeviceID.ID"].value[0]
)}.csv`,
download: "",
style: "float: right;",
},
"Download"
),
search,
m(
".parameter-list",
m("table", m("tbody", rows)),
m(
"m",
`Displaying ${filteredKeys.length} out of ${count} parameters.`
)
)
)
);
+7 -3
View File
@@ -67,12 +67,12 @@ const component: ClosureComponent = (): Component => {
.deleteResource("faults", f["_id"])
.then(() => {
notifications.push("success", "Fault deleted");
store.fulfill(Date.now(), Date.now());
store.setTimestamp(Date.now());
m.redraw();
})
.catch((err) => {
notifications.push("error", err.message);
store.fulfill(Date.now(), Date.now());
store.setTimestamp(Date.now());
});
},
},
@@ -95,7 +95,11 @@ const component: ClosureComponent = (): Component => {
);
}
return m("table.table", thead, tbody);
return m(
"loading",
{ queries: [faults] },
m("table.table", thead, tbody)
);
},
};
};
+80
View File
@@ -0,0 +1,80 @@
/**
* Copyright 2013-2021 GenieACS Inc.
*
* This file is part of GenieACS.
*
* GenieACS is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* GenieACS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with GenieACS. If not, see <http://www.gnu.org/licenses/>.
*/
import { VnodeDOM, ClosureComponent, Component } from "mithril";
const component: ClosureComponent = (): Component => {
let overlay: HTMLElement;
let dom: Element;
let loading = false;
function apply(vnode: VnodeDOM): void {
if (!loading) {
if (overlay) overlay.parentElement.remove();
if (dom) dom.classList.remove("loading");
overlay = null;
dom = null;
return;
}
if (dom && dom !== vnode.dom) dom.classList.remove("loading");
dom = vnode.dom;
dom.classList.add("loading");
if (!overlay) {
const wrapper = document.createElement("div");
wrapper.style.position = "relative";
wrapper.style.pointerEvents = "none";
overlay = document.createElement("div");
overlay.classList.add("loading-overlay");
overlay.style.position = "absolute";
wrapper.appendChild(overlay);
}
const wrapper = overlay.parentElement;
if (wrapper.parentElement !== dom.parentElement)
dom.parentNode.appendChild(wrapper);
const wrapperRect = wrapper.getBoundingClientRect();
const domRect = dom.getBoundingClientRect();
overlay.style.width = `${dom.scrollWidth}px`;
overlay.style.height = `${dom.scrollHeight}px`;
overlay.style.left = `${domRect.left - wrapperRect.left}px`;
overlay.style.top = `${domRect.top - wrapperRect.top}px`;
}
return {
view: (vnode) => {
const queries = vnode.attrs["queries"];
loading = queries.some((q) => q.fulfilling);
return vnode.children;
},
oncreate: apply,
onupdate: apply,
onremove: () => {
if (overlay) overlay.parentElement.remove();
if (dom) dom.classList.remove("loading");
overlay = null;
dom = null;
},
};
};
export default component;
+10 -1
View File
@@ -38,6 +38,11 @@ const component: ClosureComponent = (): Component => {
return m(
"tr",
{
oncreate: (vn) => {
(vn.dom as HTMLElement).style.display = (p as VnodeDOM).dom
? ""
: "none";
},
onupdate: (vn) => {
(vn.dom as HTMLElement).style.display = (p as VnodeDOM).dom
? ""
@@ -49,7 +54,11 @@ const component: ClosureComponent = (): Component => {
);
});
return m("table.parameter-list", rows);
return m(
"loading",
{ queries: [vnode.attrs["deviceQuery"]] },
m("table.parameter-list", rows)
);
},
};
};
+8 -1
View File
@@ -149,7 +149,14 @@ const component: ClosureComponent = (): Component => {
let label;
if (vnode.attrs["label"]) label = m("h2", vnode.attrs["label"]);
return [label, m("table.table", thead, m("tbody", rows))];
return [
label,
m(
"loading",
{ queries: [vnode.attrs["deviceQuery"]] },
m("table.table", thead, m("tbody", rows))
),
];
},
};
};
+1 -1
View File
@@ -78,7 +78,7 @@ const component: ClosureComponent = (): Component => {
)
.then(() => {
e.target.disabled = false;
store.fulfill(0, Date.now());
store.setTimestamp(Date.now());
})
.catch((err) => {
e.target.disabled = false;
+2 -2
View File
@@ -64,7 +64,7 @@ const component: ClosureComponent = (): Component => {
"success",
`${deviceId}: Tags updated`
);
store.fulfill(0, Date.now());
store.setTimestamp(Date.now());
})
.catch((err) => {
e.target.disabled = false;
@@ -99,7 +99,7 @@ const component: ClosureComponent = (): Component => {
.then(() => {
e.target.disabled = false;
notifications.push("success", `${deviceId}: Tags updated`);
store.fulfill(0, Date.now());
store.setTimestamp(Date.now());
})
.catch((err) => {
e.target.disabled = false;