aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/group-settings.js
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/group-settings.js')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/group-settings.js31
1 files changed, 27 insertions, 4 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/group-settings.js b/packages/meshbay-hub/src/meshbay_hub/static/group-settings.js
index 1a367be..a666c29 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/group-settings.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/group-settings.js
@@ -55,8 +55,9 @@ async function readLocalNode(node, groupId, attempts = NODE_CHECK_ATTEMPTS,
* mode="live" — a hosted group. What widens the node's sharing — adding
* a directory, its `writable` and `removable` switches — goes
* through the loopback API only, so only on the node's own
- * machine. Removing, ejecting and plugging are signed ops
- * over MNP, or the loopback API when there is no connection.
+ * machine. Removing, ejecting, plugging, pausing and
+ * resuming are signed ops over MNP, or the loopback API when
+ * there is no connection.
* mode="local" — the wizard, before the group exists. Changes are held in
* an array the caller owns; nothing is persisted until the
* group is attached.
@@ -72,7 +73,7 @@ async function readLocalNode(node, groupId, attempts = NODE_CHECK_ATTEMPTS,
*
* Props:
* roots — the node's current roots: { name, path, writable,
- * removable, ejected, available, kind }
+ * removable, ejected, paused, available, kind }
* groupId — the group id
* transport — MeshBayTransport instance, or null when not connected
* signFn — signing function for admin ops
@@ -153,7 +154,7 @@ function SharedDirectoriesTable({ roots, groupId, transport, signFn,
// signature proves that the operator's key signed, not that the operator
// meant it: in a browser that key is driven by code the hub serves.
//
- // Narrowing — remove, eject, plug — MNP first, then loopback.
+ // Narrowing — remove, eject, plug, pause, resume — MNP first, then loopback.
const overMnp = !isLocal && transport && transport.connected;
const overLoopback = !isLocal && !overMnp && nodeAvail;
const onNodeMachine = !isLocal && nodeAvail;
@@ -220,6 +221,18 @@ function SharedDirectoriesTable({ roots, groupId, transport, signFn,
else throw new Error(t('node.root_no_route'));
}), [overMnp, overLoopback, transport, groupId, signFn, run]);
+ const doPauseRoot = useCallback((rootName) => run(async () => {
+ if (overMnp) await transport.pauseRoot(groupId, rootName, signFn);
+ else if (overLoopback) await platform.node.op('pauseRoot', { groupId, rootName });
+ else throw new Error(t('node.root_no_route'));
+ }), [overMnp, overLoopback, transport, groupId, signFn, run]);
+
+ const doResumeRoot = useCallback((rootName) => run(async () => {
+ if (overMnp) await transport.resumeRoot(groupId, rootName, signFn);
+ else if (overLoopback) await platform.node.op('resumeRoot', { groupId, rootName });
+ else throw new Error(t('node.root_no_route'));
+ }), [overMnp, overLoopback, transport, groupId, signFn, run]);
+
const doRemoveRoot = useCallback(async (rootName) => {
if (isLocal) {
if (onLocalRootsChange) {
@@ -321,6 +334,8 @@ function SharedDirectoriesTable({ roots, groupId, transport, signFn,
<span class="node-root-badge node-root-badge-warn">${t('group.root_ejected')}</span>`}
${!isLocal && r.available === false && !r.ejected && html`
<span class="node-root-badge node-root-badge-warn">${t('node.unavailable')}</span>`}
+ ${!isLocal && r.paused && html`
+ <span class="node-root-badge">${t('node.root_paused')}</span>`}
</td>
${hasPaths && html`
<td class="sdt-col-path" title=${r.path || ''}>${r.path || ''}</td>`}
@@ -347,6 +362,14 @@ function SharedDirectoriesTable({ roots, groupId, transport, signFn,
`}
<td class="sdt-col-actions">
${canEdit && !isLocal && html`
+ <button class="sdt-action-btn" disabled=${busy || !!r.ejected}
+ title=${r.paused ? t('node.root_resume') : t('node.root_pause')}
+ aria-label=${r.paused ? t('node.root_resume') : t('node.root_pause')}
+ onClick=${() => r.paused ? doResumeRoot(r.name) : doPauseRoot(r.name)}>
+ <${Icon} name=${r.paused ? 'play' : 'pause'} />
+ </button>
+ `}
+ ${canEdit && !isLocal && html`
<button class="sdt-action-btn" disabled=${busy || !r.removable}
title=${r.ejected ? t('group.root_plug') : t('group.root_eject')}
onClick=${() => r.ejected ? doPlugRoot(r.name) : doEjectRoot(r.name)}>