Browse Source

feat: add "log data" block

Ahmad Kholid 3 years ago
parent
commit
d4625d3926

+ 35 - 0
src/background/workflowEngine/blocksHandler/handlerLogData.js

@@ -0,0 +1,35 @@
+import dbLogs from '@/db/logs';
+
+export async function logData({ id, data }) {
+  if (!data.workflowId) {
+    console.log(data);
+    throw new Error('No workflow is selected');
+  }
+
+  const [workflowLog] = await dbLogs.items
+    .where('workflowId')
+    .equals(data.workflowId)
+    .reverse()
+    .sortBy('endedAt');
+  let workflowLogData = null;
+
+  if (workflowLog) {
+    workflowLogData = (
+      await dbLogs.logsData.where('logId').equals(workflowLog.id).first()
+    ).data;
+
+    if (data.assignVariable) {
+      this.setVariable(data.variableName, workflowLogData);
+    }
+    if (data.saveData) {
+      this.addDataToColumn(data.dataColumn, workflowLogData);
+    }
+  }
+
+  return {
+    data: workflowLogData,
+    nextBlockId: this.getBlockConnections(id),
+  };
+}
+
+export default logData;

+ 5 - 0
src/components/newtab/workflow/WorkflowEditor.vue

@@ -140,6 +140,11 @@ editor.onConnect((params) => {
   editor.addEdges([params]);
 });
 editor.onEdgeUpdate(({ edge, connection }) => {
+  const isBothOutput =
+    connection.sourceHandle.includes('output') &&
+    connection.targetHandle.includes('output');
+  if (isBothOutput) return;
+
   Object.assign(edge, connection);
 });
 

+ 2 - 2
src/components/newtab/workflow/edit/EditBlockSettings.vue

@@ -12,7 +12,7 @@
     <ui-modal
       v-model="state.showModal"
       :title="t('workflow.blocks.base.settings.title')"
-      content-class="max-w-xl block-settings"
+      content-class="max-w-xl modal-block-settings"
     >
       <ui-tabs v-model="state.activeTab" class="-mt-2">
         <ui-tab v-for="tab in tabs" :key="tab.id" :value="tab.id">
@@ -125,7 +125,7 @@ onMounted(() => {
 });
 </script>
 <style>
-.block-settings {
+.modal-block-settings {
   min-height: 500px;
 }
 </style>

+ 61 - 0
src/components/newtab/workflow/edit/EditLogData.vue

@@ -0,0 +1,61 @@
+<template>
+  <div>
+    <ui-textarea
+      :model-value="data.description"
+      :placeholder="t('common.description')"
+      class="w-full"
+      @change="updateData({ description: $event })"
+    />
+    <ui-select
+      :model-value="data.workflowId"
+      :placeholder="t('workflow.blocks.execute-workflow.select')"
+      class="mt-4"
+      @change="updateData({ workflowId: $event })"
+    >
+      <option
+        v-for="workflow in workflows"
+        :key="workflow.id"
+        :value="workflow.id"
+      >
+        {{ workflow.name }}
+      </option>
+    </ui-select>
+    <div class="mb-8 log-data">
+      <template v-if="data.workflowId">
+        <p class="mt-4 mb-2">
+          {{ t('workflow.blocks.log-data.data') }}
+        </p>
+        <insert-workflow-data :data="data" variables @update="updateData" />
+      </template>
+    </div>
+  </div>
+</template>
+<script setup>
+import { useI18n } from 'vue-i18n';
+import { useWorkflowStore } from '@/stores/workflow';
+import InsertWorkflowData from './InsertWorkflowData.vue';
+
+const props = defineProps({
+  data: {
+    type: Object,
+    default: () => ({}),
+  },
+});
+const emit = defineEmits(['update:data']);
+
+const { t } = useI18n();
+const workflowStore = useWorkflowStore();
+
+const workflows = workflowStore.getWorkflows.sort((a, b) =>
+  a.name > b.name ? 1 : -1
+);
+
+function updateData(value) {
+  emit('update:data', { ...props.data, ...value });
+}
+</script>
+<style>
+.log-data .block-variable {
+  margin-top: 4px;
+}
+</style>

+ 1 - 1
src/components/newtab/workflow/edit/InsertWorkflowData.vue

@@ -3,7 +3,7 @@
     <ui-checkbox
       :model-value="data.assignVariable"
       block
-      class="mt-4"
+      class="mt-4 block-variable"
       @change="updateData({ assignVariable: $event })"
     >
       {{ t('workflow.variables.assign') }}

+ 2 - 0
src/lib/vRemixicon.js

@@ -97,6 +97,7 @@ import {
   riFlashlightLine,
   riTimerFlashLine,
   riBaseStationLine,
+  riFileHistoryLine,
   riInformationLine,
   riArrowUpDownLine,
   riArrowGoBackLine,
@@ -214,6 +215,7 @@ export const icons = {
   riFlashlightLine,
   riTimerFlashLine,
   riBaseStationLine,
+  riFileHistoryLine,
   riInformationLine,
   riArrowUpDownLine,
   riArrowGoBackLine,

+ 5 - 0
src/locales/en/blocks.json

@@ -109,6 +109,11 @@
         "from": "Data from",
         "allColumns": "[All columns]"
       },
+      "log-data": {
+        "name": "Get log data",
+        "description": "Get the latest log data of a workflow",
+        "data": "Log data"
+      },
       "reload-tab": {
         "name": "Reload tab",
         "description": "Reload the active tab"

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

@@ -157,7 +157,7 @@ import { tasks } from '@/utils/shared';
 import { debounce, parseJSON, throttle } from '@/utils/helper';
 import { fetchApi } from '@/utils/api';
 import browser from 'webextension-polyfill';
-import EditorUtils from '@/utils/EditorUtils';
+import DroppedNode from '@/utils/editor/DroppedNode';
 import convertWorkflowData from '@/utils/convertWorkflowData';
 import WorkflowShare from '@/components/newtab/workflow/WorkflowShare.vue';
 import WorkflowEditor from '@/components/newtab/workflow/WorkflowEditor.vue';
@@ -533,9 +533,9 @@ function onDropInEditor({ dataTransfer, clientX, clientY, target }) {
 
   clearHighlightedElements();
 
-  const nodeEl = EditorUtils.isNode(target);
+  const nodeEl = DroppedNode.isNode(target);
   if (nodeEl) {
-    EditorUtils.replaceNode(editor.value, { block, target: nodeEl });
+    DroppedNode.replaceNode(editor.value, { block, target: nodeEl });
     return;
   }
 
@@ -554,16 +554,16 @@ function onDropInEditor({ dataTransfer, clientX, clientY, target }) {
   };
   editor.value.addNodes([newNode]);
 
-  const edgeEl = EditorUtils.isEdge(target);
-  const handleEl = EditorUtils.isHandle(target);
+  const edgeEl = DroppedNode.isEdge(target);
+  const handleEl = DroppedNode.isHandle(target);
 
   if (handleEl) {
-    EditorUtils.appendNode(editor.value, {
+    DroppedNode.appendNode(editor.value, {
       target: handleEl,
       nodeId: newNode.id,
     });
   } else if (edgeEl) {
-    EditorUtils.insertBetweenNode(editor.value, {
+    DroppedNode.insertBetweenNode(editor.value, {
       target: edgeEl,
       nodeId: newNode.id,
       outputs: block.outputs,

+ 4 - 4
src/utils/EditorUtils.js → src/utils/editor/DroppedNode.js

@@ -1,9 +1,9 @@
 import { customAlphabet } from 'nanoid';
-import { tasks, excludeOnError } from './shared';
+import { tasks, excludeOnError } from '../shared';
 
-const nanoid = customAlphabet('1234567890abcdef', 7);
+const nanoid = customAlphabet('1234567890abcdefghijklmnopqrstuvwxyz', 7);
 
-class EditorUtils {
+class DroppedNode {
   static isNode(target) {
     if (target.closest('.vue-flow__handle')) return null;
 
@@ -162,4 +162,4 @@ class EditorUtils {
   }
 }
 
-export default EditorUtils;
+export default DroppedNode;

+ 27 - 0
src/utils/shared.js

@@ -1003,6 +1003,28 @@ export const tasks = {
       title: 'Hello world!',
     },
   },
+  'log-data': {
+    name: 'Get log data',
+    description: 'Get the latest log data of a workflow',
+    icon: 'riFileHistoryLine',
+    editComponent: 'EditLogData',
+    component: 'BlockBasic',
+    category: 'data',
+    inputs: 1,
+    outputs: 1,
+    allowedInputs: true,
+    maxConnection: 1,
+    refDataKeys: ['message', 'title', 'iconUrl', 'imageUrl'],
+    data: {
+      disableBlock: false,
+      description: '',
+      workflowId: '',
+      dataColumn: '',
+      saveData: true,
+      assignVariable: false,
+      variableName: '',
+    },
+  },
 };
 
 export const categories = {
@@ -1028,6 +1050,11 @@ export const categories = {
     border: 'border-red-200 dark:border-red-300',
     color: 'bg-red-200 dark:bg-red-300 fill-red-200 dark:fill-red-300',
   },
+  data: {
+    name: 'Data',
+    border: 'border-lime-200 dark:border-lime-300',
+    color: 'bg-lime-200 dark:bg-lime-300 fill-lime-200 dark:fill-lime-300',
+  },
   conditions: {
     name: 'Conditions',
     border: 'border-blue-200 dark:border-blue-300',