Browse Source

feat(newtab): add workflow state in dashboard

Ahmad Kholid 3 years ago
parent
commit
76b0f844ab

+ 4 - 4
src/background/index.js

@@ -74,11 +74,11 @@ browser.runtime.onInstalled.addListener((details) => {
 const message = new MessageListener('background');
 
 message.on('workflow:execute', (workflow) => executeWorkflow(workflow));
-message.on('workflow:stop', (item) => {
-  const workflow = runningWorkflows[item.id];
-  console.log(workflow, item, 'stop workflow');
+message.on('workflow:stop', (id) => {
+  const workflow = runningWorkflows[id];
+  console.log(runningWorkflows, id);
   if (!workflow) {
-    workflowState.delete(item.id);
+    workflowState.delete(id);
     return;
   }
 

+ 1 - 0
src/background/workflow-engine.js

@@ -219,6 +219,7 @@ class WorkflowEngine {
     }, {});
 
     state.name = this.workflow.name;
+    state.icon = this.workflow.icon;
 
     return state;
   }

+ 1 - 1
src/background/workflow-state.js

@@ -60,7 +60,7 @@ class WorkflowState {
     return updater.call(
       this,
       (items, index) => {
-        console.log('state index', index, id);
+        console.log('state index', index, id, items);
         if (index !== -1) items.splice(index, 1);
 
         return items;

+ 0 - 0
src/components/newtab/LogsTable.vue → src/components/newtab/shared/SharedLogsTable.vue


+ 73 - 0
src/components/newtab/shared/SharedWorkflowState.vue

@@ -0,0 +1,73 @@
+<template>
+  <ui-card>
+    <div class="flex items-center mb-4">
+      <div class="flex-1 text-overflow mr-4">
+        <p class="w-full mr-2 text-overflow">{{ state.name }}</p>
+        <p
+          class="w-full mr-2 text-gray-600 leading-tight text-overflow"
+          :title="`Started at: ${formatDate(
+            state.startedTimestamp,
+            'DD MMM, hh:mm A'
+          )}`"
+        >
+          {{ formatDate(state.startedTimestamp, 'relative') }}
+        </p>
+      </div>
+      <ui-button
+        v-if="state.tabId"
+        icon
+        class="mr-2"
+        title="Open tab"
+        @click="openTab"
+      >
+        <v-remixicon name="riExternalLinkLine" />
+      </ui-button>
+      <ui-button variant="accent" @click="stopWorkflow(item)">
+        <v-remixicon name="riStopLine" class="mr-2 -ml-1" />
+        <span>Stop</span>
+      </ui-button>
+    </div>
+    <div class="flex items-center bg-box-transparent px-4 py-2 rounded-lg">
+      <template v-if="state.currentBlock">
+        <v-remixicon :name="getBlock().icon" />
+        <p class="flex-1 ml-2 mr-4">{{ getBlock().name }}</p>
+        <ui-spinner color="text-accnet" size="20" />
+      </template>
+      <p v-else>No block</p>
+    </div>
+  </ui-card>
+</template>
+<script setup>
+import browser from 'webextension-polyfill';
+import { sendMessage } from '@/utils/message';
+import { tasks } from '@/utils/shared';
+import dayjs from '@/lib/dayjs';
+
+const props = defineProps({
+  id: {
+    type: String,
+    default: '',
+  },
+  state: {
+    type: Object,
+    default: () => ({}),
+  },
+});
+
+function getBlock() {
+  if (!props.state.currentBlock) return {};
+
+  return tasks[props.state.currentBlock.name];
+}
+function formatDate(date, format) {
+  if (format === 'relative') return dayjs(date).fromNow();
+
+  return dayjs(date).format(format);
+}
+function openTab() {
+  browser.tabs.update(props.state.tabId, { active: true });
+}
+function stopWorkflow() {
+  sendMessage('workflow:stop', props.id, 'background');
+}
+</script>

+ 6 - 3
src/components/popup/home/HomeWorkflowCard.vue

@@ -2,12 +2,16 @@
   <ui-card
     class="w-full flex items-center space-x-2 hover:ring-2 hover:ring-gray-900"
   >
-    <router-link to="/workflow/anu/edit" class="flex-1">
+    <div
+      to="/workflow/anu/edit"
+      class="flex-1 cursor-pointer"
+      @click="$emit('details', workflow)"
+    >
       <p class="leading-tight">{{ workflow.name }}</p>
       <p class="leading-none text-gray-500">
         {{ dayjs(workflow.createdAt).fromNow() }}
       </p>
-    </router-link>
+    </div>
     <button title="Execute" @click="$emit('execute', workflow)">
       <v-remixicon name="riPlayLine" />
     </button>
@@ -44,7 +48,6 @@ defineProps({
 defineEmits(['execute', 'rename', 'details', 'delete']);
 
 const menu = [
-  { name: 'details', icon: 'riExternalLinkLine' },
   { name: 'rename', icon: 'riPencilLine' },
   { name: 'delete', icon: 'riDeleteBin7Line' },
 ];

+ 24 - 30
src/newtab/pages/Home.vue

@@ -2,13 +2,14 @@
   <div class="container pt-8 pb-4">
     <h1 class="text-2xl font-semibold mb-8">Dashboard</h1>
     <div class="flex items-start">
-      <div class="w-7/12 mr-8">
+      <div class="w-8/12 mr-8">
         <div class="grid gap-4 mb-8 grid-cols-3">
           <workflow-card
             v-for="workflow in workflows"
-            :key="workflow.id"
             v-bind="{ workflow }"
+            :key="workflow.id"
             :show-details="false"
+            @execute="executeWorkflow"
           />
         </div>
         <div>
@@ -21,44 +22,32 @@
               View all
             </router-link>
           </div>
-          <logs-table :logs="logs" class="w-full" />
+          <shared-logs-table :logs="logs" class="w-full" />
         </div>
       </div>
-      <ui-card class="flex-1">
-        <!-- <p class="mb-4">Running workflow</p> -->
-        <div class="flex items-center mb-4">
-          <span class="p-2 rounded-full bg-accent text-white inline-block">
-            <v-remixicon name="riGlobalLine" />
-          </span>
-          <div class="flex-grow"></div>
-          <ui-button class="mr-3">
-            <v-remixicon class="-ml-1 mr-1" name="riPauseLine" />
-            <span>Pause</span>
-          </ui-button>
-          <ui-button variant="accent">
-            <v-remixicon class="-ml-1 mr-1" name="riStopLine" />
-            <span>Stop</span>
-          </ui-button>
-        </div>
-        <p class="mb-2 text-lg font-semibold">Workflow name</p>
-        <shared-task-list class="bg-gray-100 rounded-lg p-2" :tasks="tasks" />
-      </ui-card>
+      <div class="w-4/12 space-y-4">
+        <shared-workflow-state
+          v-for="item in workflowState"
+          :id="item.id"
+          :key="item.id"
+          :state="item.state"
+          class="w-full"
+        />
+      </div>
     </div>
   </div>
 </template>
 <script setup>
 import { computed } from 'vue';
-import Workflow from '@/models/workflow';
+import { useStore } from 'vuex';
+import { sendMessage } from '@/utils/message';
 import Log from '@/models/log';
-import LogsTable from '@/components/newtab/LogsTable.vue';
-import SharedTaskList from '@/components/shared/SharedTaskList.vue';
+import Workflow from '@/models/workflow';
 import WorkflowCard from '@/components/newtab/workflow/WorkflowCard.vue';
+import SharedLogsTable from '@/components/newtab/shared/SharedLogsTable.vue';
+import SharedWorkflowState from '@/components/newtab/shared/SharedWorkflowState.vue';
 
-const tasks = [
-  { name: 'Open website', status: 'success' },
-  { name: 'Get data', status: 'success' },
-  { name: 'Close web', status: 'running' },
-];
+const store = useStore();
 
 const workflows = computed(() =>
   Workflow.query().orderBy('createdAt', 'desc').limit(3).get()
@@ -66,4 +55,9 @@ const workflows = computed(() =>
 const logs = computed(() =>
   Log.query().orderBy('startedAt', 'desc').limit(10).get()
 );
+const workflowState = computed(() => store.state.workflowState);
+
+function executeWorkflow(workflow) {
+  sendMessage('workflow:execute', workflow, 'background');
+}
 </script>

+ 3 - 3
src/newtab/pages/logs.vue

@@ -7,7 +7,7 @@
       @updateSorts="sortsBuilder[$event.key] = $event.value"
       @updateFilters="filtersBuilder[$event.key] = $event.value"
     />
-    <logs-table :logs="logs" class="w-full">
+    <shared-logs-table :logs="logs" class="w-full">
       <template #item-prepend="{ log }">
         <td class="w-8">
           <ui-checkbox
@@ -38,7 +38,7 @@
           </div>
         </td>
       </template>
-    </logs-table>
+    </shared-logs-table>
     <ui-card
       v-if="selectedLogs.length !== 0"
       class="fixed right-0 bottom-0 m-5 shadow-xl space-x-2"
@@ -65,9 +65,9 @@ import { shallowReactive, ref, computed } from 'vue';
 import { useStore } from 'vuex';
 import { useDialog } from '@/composable/dialog';
 import Log from '@/models/log';
-import LogsTable from '@/components/newtab/LogsTable.vue';
 import LogsFilters from '@/components/newtab/logs/LogsFilters.vue';
 import LogsDataViewer from '@/components/newtab/logs/LogsDataViewer.vue';
+import SharedLogsTable from '@/components/newtab/shared/SharedLogsTable.vue';
 
 const store = useStore();
 const dialog = useDialog();

+ 14 - 6
src/newtab/pages/workflows/[id].vue

@@ -56,11 +56,19 @@
         @deleteBlock="deleteBlock"
       />
       <div v-else class="container pb-4 mt-24 px-4">
-        <logs-table v-if="activeTab === 'logs'" :logs="logs" class="w-full" />
-        <workflow-running
-          v-else-if="activeTab === 'running'"
-          :data="workflowState"
+        <shared-logs-table
+          v-if="activeTab === 'logs'"
+          :logs="logs"
+          class="w-full"
         />
+        <div v-else-if="activeTab === 'running'" class="grid grid-cols-2 gap-4">
+          <shared-workflow-state
+            v-for="item in workflowState"
+            :id="item.id"
+            :key="item.id"
+            :state="item.state"
+          />
+        </div>
       </div>
     </div>
   </div>
@@ -96,13 +104,13 @@ import { debounce } from '@/utils/helper';
 import { useDialog } from '@/composable/dialog';
 import Log from '@/models/log';
 import Workflow from '@/models/workflow';
-import WorkflowRunning from '@/components/newtab/workflow/WorkflowRunning.vue';
 import WorkflowBuilder from '@/components/newtab/workflow/WorkflowBuilder.vue';
 import WorkflowSettings from '@/components/newtab/workflow/WorkflowSettings.vue';
 import WorkflowEditBlock from '@/components/newtab/workflow/WorkflowEditBlock.vue';
 import WorkflowDetailsCard from '@/components/newtab/workflow/WorkflowDetailsCard.vue';
 import WorkflowDataColumns from '@/components/newtab/workflow/WorkflowDataColumns.vue';
-import LogsTable from '@/components/newtab/LogsTable.vue';
+import SharedLogsTable from '@/components/newtab/shared/SharedLogsTable.vue';
+import SharedWorkflowState from '@/components/newtab/shared/SharedWorkflowState.vue';
 
 const store = useStore();
 const route = useRoute();