feat(workflows): add reorder buttons to the workflow manager
This change allows users to reorder workflows in the workflow manager by
exposing move up/down buttons next to each workflow.
Fixed: twpowertools:152
Change-Id: I4298344ec7a296f125c30ba5762fb5f0c8e632a0
diff --git a/src/features/workflows/core/manager/components/List.js b/src/features/workflows/core/manager/components/List.js
index 9f7ed5f..4621a8e 100644
--- a/src/features/workflows/core/manager/components/List.js
+++ b/src/features/workflows/core/manager/components/List.js
@@ -36,13 +36,26 @@
dialogRef = createRef();
renderListItems() {
- return map(this.workflows, w => html`
+ return map(this.workflows, (w, index) => html`
<md-list-item
type="button"
@click=${() => this._show(w)}>
<div slot="headline">${w.proto?.getName?.()}</div>
<div slot="end" class="end">
<md-icon-button
+ aria-label="Move up"
+ ?soft-disabled=${index === 0}
+ @click=${e => this._moveUp(w.uuid, e)}>
+ <md-icon>arrow_upward</md-icon>
+ </md-icon-button>
+ <md-icon-button
+ aria-label="Move down"
+ ?soft-disabled=${index === this.workflows.length - 1}
+ @click=${e => this._moveDown(w.uuid, e)}>
+ <md-icon>arrow_downward</md-icon>
+ </md-icon-button>
+ <md-icon-button
+ aria-label="Delete"
@click=${e => this._showDelete(w.uuid, e)}>
<md-icon>delete</md-icon>
</md-icon-button>
@@ -87,6 +100,16 @@
this.dialogRef.value.open = true;
}
+ _moveUp(uuid, e) {
+ e.stopPropagation();
+ WorkflowsStorage.moveUp(uuid);
+ }
+
+ _moveDown(uuid, e) {
+ e.stopPropagation();
+ WorkflowsStorage.moveDown(uuid);
+ }
+
_showDelete(uuid, e) {
e.stopPropagation();
const proceed = window.confirm(
diff --git a/src/features/workflows/core/workflowsStorage.js b/src/features/workflows/core/workflowsStorage.js
index 3fc6f95..43ffd2b 100644
--- a/src/features/workflows/core/workflowsStorage.js
+++ b/src/features/workflows/core/workflowsStorage.js
@@ -97,6 +97,38 @@
});
}
+ static async moveUp(uuid) {
+ await this.moveToRelativePosition(uuid, -1);
+ }
+
+ static async moveDown(uuid) {
+ await this.moveToRelativePosition(uuid, 1);
+ }
+
+ /**
+ * Swaps the workflow with the one saved in the specified position relative to
+ * the workflow's position. Example: position = 1 swaps the workflow with the
+ * next workflow, so it appears afterwards.
+ */
+ static async moveToRelativePosition(uuid, relativePosition) {
+ const workflows = await this.getAll();
+ const index = workflows.findIndex((workflow) => workflow.uuid === uuid);
+ if (index === -1) {
+ throw new Error(
+ 'Couldn\'t move the workflow because it couldn\'t be found.',
+ );
+ }
+ if (workflows[index + relativePosition] === undefined) {
+ throw new Error(
+ 'Couldn\'t move the workflow because the specified relative position is out of bounds.',
+ );
+ }
+ [workflows[index], workflows[index + relativePosition]] =
+ [workflows[index + relativePosition], workflows[index]];
+ const items = {[kWorkflowsDataKey]: workflows};
+ await chrome.storage.local.set(items);
+ }
+
static _proto2Base64(workflow) {
const binaryWorkflow = workflow.serializeBinary();
return arrayBufferToBase64(binaryWorkflow);