Add workflow menu button to thread lists

Bug: twpowertools:74
Change-Id: I703950394d674c2084278bf9e876014d08fa5cfb
diff --git a/src/contentScripts/communityConsole/workflows/components/Overlay.vue b/src/contentScripts/communityConsole/workflows/components/Overlay.vue
new file mode 100644
index 0000000..304b362
--- /dev/null
+++ b/src/contentScripts/communityConsole/workflows/components/Overlay.vue
@@ -0,0 +1,29 @@
+<script>
+import WfMenu from './WfMenu.vue';
+
+export default {
+  components: {
+    WfMenu,
+  },
+  data() {
+    return {
+      shown: false,
+      position: [0, 0],
+      // TODO: Get real data.
+      workflows: [
+        {name: 'Move to accounts'},
+        {name: 'Mark as spam w/ message'},
+      ],
+    };
+  },
+  methods: {
+    startWorkflow(e) {
+      console.log(e);
+    }
+  },
+}
+</script>
+
+<template>
+  <wf-menu v-model="shown" :position="position" :workflows="workflows" @select="startWorkflow" />
+</template>
diff --git a/src/contentScripts/communityConsole/workflows/components/WfMenu.vue b/src/contentScripts/communityConsole/workflows/components/WfMenu.vue
new file mode 100644
index 0000000..88528ea
--- /dev/null
+++ b/src/contentScripts/communityConsole/workflows/components/WfMenu.vue
@@ -0,0 +1,39 @@
+<script>
+import {Corner} from '@material/menu-surface/constants.js';
+
+export default {
+  components: {},
+  props: {
+    modelValue: Boolean,
+    position: Array,
+    workflows: Array,
+  },
+  data() {
+    return {
+      corner: Corner.TOP_RIGHT,
+    };
+  },
+  emits: [
+    'update:modelValue',
+    'select',
+  ],
+}
+</script>
+
+<template>
+  <mcw-menu :model-value="modelValue" fixed :anchor-corner="corner"
+      :style="{ left: 'unset', right: 'calc(100% - ' + position[0] + 'px)', top: position[1] + 'px' }"
+      @update:model-value="$emit('update:modelValue', $event)" @select="$emit('select', $event)">
+    <mcw-list-item v-for="wf in workflows">{{ wf.name }}</mcw-list-item>
+  </mcw-menu>
+</template>
+
+<style scoped>
+.mdc-list-item {
+  /* These styles mimic the Community Console style. */
+  font-family: 'Google Sans Text', 'Noto', sans-serif;
+  font-size: 14px;
+  font-weight: 400;
+  height: 40px!important;
+}
+</style>
diff --git a/src/contentScripts/communityConsole/workflows/vma.js b/src/contentScripts/communityConsole/workflows/vma.js
new file mode 100644
index 0000000..89d291c
--- /dev/null
+++ b/src/contentScripts/communityConsole/workflows/vma.js
@@ -0,0 +1,9 @@
+// We just import the components needed.
+import {list, menu} from 'vue-material-adapter';
+
+export default {
+  install(vm) {
+    vm.use(list);
+    vm.use(menu);
+  },
+}
diff --git a/src/contentScripts/communityConsole/workflows/workflows.js b/src/contentScripts/communityConsole/workflows/workflows.js
new file mode 100644
index 0000000..dc542fa
--- /dev/null
+++ b/src/contentScripts/communityConsole/workflows/workflows.js
@@ -0,0 +1,53 @@
+import {createApp} from 'vue';
+
+import {isOptionEnabled} from '../../../common/optionsUtils.js';
+
+import {addButtonToThreadListActions, shouldAddBtnToActionBar} from './../utils/common.js';
+import Overlay from './components/Overlay.vue';
+import VueMaterialAdapter from './vma.js';
+
+const wfDebugId = 'twpt-workflows';
+
+export default class Workflows {
+  constructor() {
+    this.overlayApp = null;
+    this.overlayVm = null;
+  }
+
+  createOverlay() {
+    let menuEl = document.createElement('div');
+    document.body.appendChild(menuEl);
+
+    this.overlayApp = createApp(Overlay);
+    this.overlayApp.use(VueMaterialAdapter);
+    this.overlayVm = this.overlayApp.mount(menuEl);
+  }
+
+  switchMenu(menuBtn) {
+    if (this.overlayApp === null) this.createOverlay();
+    if (!this.overlayVm.shown) {
+      let rect = menuBtn.getBoundingClientRect();
+      this.overlayVm.position = [rect.left + rect.width, rect.bottom];
+      this.overlayVm.shown = true;
+    } else {
+      this.overlayVm.shown = false;
+    }
+  }
+
+  addThreadListBtnIfEnabled(readToggle) {
+    isOptionEnabled('workflows').then(isEnabled => {
+      if (isEnabled) {
+        let tooltip = chrome.i18n.getMessage('inject_workflows_menubtn');
+        let btn = addButtonToThreadListActions(
+            readToggle, 'more_vert', wfDebugId, tooltip);
+        btn.addEventListener('click', () => {
+          this.switchMenu(btn);
+        });
+      }
+    });
+  }
+
+  shouldAddThreadListBtn(node) {
+    return shouldAddBtnToActionBar(wfDebugId, node);
+  }
+};