Bulk push file from device list page

This commit is contained in:
Zaid Abdulla committed 2020-09-27 11:20:30 -07:00
1 parent 82124d471e
commit f14e6ceb97
5 files changed
+110 -66

No files matched your search

+1 -1
View File
@@ -70,7 +70,7 @@ const component: ClosureComponent = (): Component => {
onclick: () => { onclick: () => {
taskQueue.stageDownload({ taskQueue.stageDownload({
name: "download", name: "download",
device: device["DeviceID.ID"].value[0], devices: [device["DeviceID.ID"].value[0]],
}); });
}, },
}, },
+1 -1
View File
@@ -90,7 +90,7 @@ const component: ClosureComponent = (): Component => {
onclick: () => { onclick: () => {
taskQueue.stageSpv({ taskQueue.stageSpv({
name: "setParameterValues", name: "setParameterValues",
device: device["DeviceID.ID"].value[0], devices: [device["DeviceID.ID"].value[0]],
parameterValues: [ parameterValues: [
[ [
parameter, parameter,
+17
View File
@@ -122,6 +122,23 @@ function renderActions(selected: Set<string>): Children {
) )
); );
buttons.push(
m(
"button.critical",
{
title: "Push a firmware or a config file",
disabled: !selected.size,
onclick: () => {
taskQueue.stageDownload({
name: "download",
devices: [...selected],
});
},
},
"Push file"
)
);
buttons.push( buttons.push(
m( m(
"button.primary", "button.primary",
+82 -57
View File
@@ -24,10 +24,21 @@ import m, {
Component, Component,
VnodeDOM, VnodeDOM,
} from "mithril"; } from "mithril";
import * as taskQueue from "./task-queue";
import * as store from "./store"; import * as store from "./store";
import * as notifications from "./notifications"; import * as notifications from "./notifications";
import { getIcon } from "./icons"; import { getIcon } from "./icons";
import {
clear,
commit,
deleteTask,
getQueue,
getStaging,
QueueTask,
queueTask,
StageTask,
} from "./task-queue";
const invalid: WeakSet<StageTask> = new WeakSet();
function mparam(param): Children { function mparam(param): Children {
return m("span.parameter", { title: param }, `${param}`); return m("span.parameter", { title: param }, `${param}`);
@@ -37,7 +48,7 @@ function mval(val): Children {
return m("span.value", { title: val }, `${val}`); return m("span.value", { title: val }, `${val}`);
} }
function renderStagingSpv(task, queueFunc, cancelFunc): Children { function renderStagingSpv(task: StageTask, queueFunc, cancelFunc): Children {
function keydown(e): void { function keydown(e): void {
if (e.keyCode === 13) queueFunc(); if (e.keyCode === 13) queueFunc();
else if (e.keyCode === 27) cancelFunc(); else if (e.keyCode === 27) cancelFunc();
@@ -90,13 +101,24 @@ function renderStagingSpv(task, queueFunc, cancelFunc): Children {
return [m("span", "Editing ", mparam(task.parameterValues[0][0])), input]; return [m("span", "Editing ", mparam(task.parameterValues[0][0])), input];
} }
function renderStagingDownload(task): Children { function renderStagingDownload(task: StageTask): Children {
task.invalid = !task.fileName || !task.fileType; if (!task.fileName || !task.fileType) invalid.add(task);
else invalid.delete(task);
const files = store.fetch("files", true); const files = store.fetch("files", true);
const idParts = task.device.split("-"); let oui = "";
const oui = decodeURIComponent(idParts[0]); let productClass = "";
const productClass = for (const d of task.devices) {
idParts.length === 3 ? decodeURIComponent(idParts[1]) : ""; const parts = d.split("-");
if (oui === "") oui = parts[0];
else if (oui !== parts[0]) oui = null;
if (parts.length === 3) {
if (productClass === "") productClass = parts[1];
else if (productClass !== parts[1]) productClass = null;
}
}
if (oui) oui = decodeURIComponent(oui);
if (productClass) productClass = decodeURIComponent(productClass);
const typesList = [ const typesList = [
"", "",
@@ -162,13 +184,17 @@ function renderStagingDownload(task): Children {
]; ];
} }
function renderStaging(staging): Child[] { function renderStaging(staging: Set<StageTask>): Child[] {
const elements: Child[] = []; const elements: Child[] = [];
for (const s of staging) { for (const s of staging) {
const queueFunc = (): void => { const queueFunc = (): void => {
staging.delete(s); staging.delete(s);
taskQueue.queueTask(s); for (const d of s.devices) {
const t = Object.assign({ device: d }, s);
delete t.devices;
queueTask(t);
}
}; };
const cancelFunc = (): void => { const cancelFunc = (): void => {
staging.delete(s); staging.delete(s);
@@ -181,7 +207,7 @@ function renderStaging(staging): Child[] {
const queue = m( const queue = m(
"button.primary", "button.primary",
{ title: "Queue task", onclick: queueFunc, disabled: s.invalid }, { title: "Queue task", onclick: queueFunc, disabled: invalid.has(s) },
"Queue" "Queue"
); );
const cancel = m( const cancel = m(
@@ -195,7 +221,7 @@ function renderStaging(staging): Child[] {
return elements; return elements;
} }
function renderQueue(queue): Child[] { function renderQueue(queue: Set<QueueTask>): Child[] {
const details: Child[] = []; const details: Child[] = [];
const devices: { [deviceId: string]: any[] } = {}; const devices: { [deviceId: string]: any[] } = {};
for (const t of queue) { for (const t of queue) {
@@ -215,7 +241,7 @@ function renderQueue(queue): Child[] {
{ {
title: "Retry this task", title: "Retry this task",
onclick: () => { onclick: () => {
taskQueue.queueTask(t); queueTask(t);
}, },
}, },
getIcon("retry") getIcon("retry")
@@ -229,7 +255,7 @@ function renderQueue(queue): Child[] {
{ {
title: "Remove this task", title: "Remove this task",
onclick: () => { onclick: () => {
taskQueue.deleteTask(t); deleteTask(t);
}, },
}, },
getIcon("remove") getIcon("remove")
@@ -347,8 +373,8 @@ function renderNotifications(notifs): Child[] {
const component: ClosureComponent = (): Component => { const component: ClosureComponent = (): Component => {
return { return {
view: (vnode) => { view: (vnode) => {
const queue = taskQueue.getQueue(); const queue = getQueue();
const staging = taskQueue.getStaging(); const staging = getStaging();
const notifs = notifications.getNotifications(); const notifs = notifications.getNotifications();
let drawerElement, statusElement; let drawerElement, statusElement;
@@ -394,51 +420,50 @@ const component: ClosureComponent = (): Component => {
title: "Commit queued tasks", title: "Commit queued tasks",
disabled: !statusCount.queued, disabled: !statusCount.queued,
onclick: () => { onclick: () => {
const tasks = Array.from(taskQueue.getQueue()).filter( const tasks = Array.from(getQueue()).filter(
(t) => t["status"] === "queued" (t) => t["status"] === "queued"
); );
taskQueue commit(
.commit( tasks,
tasks, (deviceId, err, connectionRequestStatus, tasks2) => {
(deviceId, err, connectionRequestStatus, tasks2) => { if (err) {
if (err) {
notifications.push(
"error",
`${deviceId}: ${err.message}`
);
return;
}
if (connectionRequestStatus !== "OK") {
notifications.push(
"error",
`${deviceId}: ${connectionRequestStatus}`
);
return;
}
for (const t of tasks2) {
if (t.status === "stale") {
notifications.push(
"error",
`${deviceId}: No contact from device`
);
return;
} else if (t.status === "fault") {
notifications.push(
"error",
`${deviceId}: Task(s) faulted`
);
return;
}
}
notifications.push( notifications.push(
"success", "error",
`${deviceId}: Task(s) committed` `${deviceId}: ${err.message}`
); );
return;
} }
)
if (connectionRequestStatus !== "OK") {
notifications.push(
"error",
`${deviceId}: ${connectionRequestStatus}`
);
return;
}
for (const t of tasks2) {
if (t.status === "stale") {
notifications.push(
"error",
`${deviceId}: No contact from device`
);
return;
} else if (t.status === "fault") {
notifications.push(
"error",
`${deviceId}: Task(s) faulted`
);
return;
}
}
notifications.push(
"success",
`${deviceId}: Task(s) committed`
);
}
)
.then(() => { .then(() => {
store.fulfill(0, Date.now()); store.fulfill(0, Date.now());
}) })
@@ -453,7 +478,7 @@ const component: ClosureComponent = (): Component => {
"button", "button",
{ {
title: "Clear tasks", title: "Clear tasks",
onclick: taskQueue.clear, onclick: clear,
disabled: !queueElements.length, disabled: !queueElements.length,
}, },
"Clear" "Clear"
+9 -7
View File
@@ -22,20 +22,22 @@ import { Task } from "../lib/types";
export interface QueueTask extends Task { export interface QueueTask extends Task {
status?: string; status?: string;
device?: string; device: string;
}
export interface StageTask extends Task {
devices: string[];
} }
const queue: Set<QueueTask> = new Set(); const queue: Set<QueueTask> = new Set();
const staging: Set<QueueTask> = new Set(); const staging: Set<StageTask> = new Set();
export function queueTask(task: QueueTask): void { export function queueTask(task: QueueTask): void {
staging.delete(task);
task.status = "queued"; task.status = "queued";
queue.add(task); queue.add(task);
} }
export function deleteTask(task: QueueTask): void { export function deleteTask(task: QueueTask): void {
staging.delete(task);
queue.delete(task); queue.delete(task);
} }
@@ -47,7 +49,7 @@ export function clear(): void {
queue.clear(); queue.clear();
} }
export function getStaging(): Set<QueueTask> { export function getStaging(): Set<StageTask> {
return staging; return staging;
} }
@@ -55,11 +57,11 @@ export function clearStaging(): void {
staging.clear(); staging.clear();
} }
export function stageSpv(task: QueueTask): void { export function stageSpv(task: StageTask): void {
staging.add(task); staging.add(task);
} }
export function stageDownload(task: QueueTask): void { export function stageDownload(task: StageTask): void {
staging.add(task); staging.add(task);
} }