Browse Source

feat: add workflow history data snapshot

Ahmad Kholid 2 years ago
parent
commit
5f4070bdfd

+ 50 - 26
src/components/newtab/logs/LogsHistory.vue

@@ -262,27 +262,25 @@
           </tbody>
         </table>
       </div>
-      <template v-if="ctxData[state.itemId]">
-        <div class="px-4 pb-4 flex items-center">
-          <p>Log data</p>
-          <div class="flex-grow" />
-          <ui-select v-model="state.activeTab">
-            <option v-for="option in tabs" :key="option.id" :value="option.id">
-              {{ option.name }}
-            </option>
-          </ui-select>
-        </div>
-        <div class="pb-4 px-2 log-data-prev">
-          <shared-codemirror
-            :model-value="logCtxData"
-            readonly
-            hide-lang
-            lang="json"
-            style="max-height: 460px"
-            class="scroll"
-          />
-        </div>
-      </template>
+      <div class="px-4 pb-4 flex items-center">
+        <p>Log data</p>
+        <div class="flex-grow" />
+        <ui-select v-model="state.activeTab">
+          <option v-for="option in tabs" :key="option.id" :value="option.id">
+            {{ option.name }}
+          </option>
+        </ui-select>
+      </div>
+      <div class="pb-4 px-2 log-data-prev">
+        <shared-codemirror
+          :model-value="logCtxData"
+          readonly
+          hide-lang
+          lang="json"
+          style="max-height: 460px"
+          class="scroll"
+        />
+      </div>
     </div>
   </div>
 </template>
@@ -423,15 +421,35 @@ const errorBlock = computed(() => {
   };
 });
 const logCtxData = computed(() => {
-  if (!state.itemId || !props.ctxData[state.itemId]) return '';
+  let logData = props.ctxData;
+  if (logData.ctxData) logData = logData.ctxData;
+
+  if (!state.itemId || !logData[state.itemId]) return '';
 
-  const data = props.ctxData[state.itemId];
-  const logData =
+  const data = logData[state.itemId];
+  const itemLogData =
     state.activeTab === 'all' ? data : objectPath.get(data, state.activeTab);
 
-  return JSON.stringify(logData, null, 2);
+  /* eslint-disable-next-line */
+  getDataSnapshot(itemLogData.referenceData);
+
+  return JSON.stringify(itemLogData, null, 2);
 });
 
+function getDataSnapshot(refData) {
+  if (!props.ctxData?.dataSnapshot) return;
+
+  const data = props.ctxData.dataSnapshot;
+  const getData = (key) => {
+    const currentData = refData[key];
+    if (typeof currentData !== 'string') return currentData;
+
+    return data[currentData] ?? {};
+  };
+
+  refData.loopData = getData('loopData');
+  refData.variables = getData('variables');
+}
 function exportLogs(type) {
   let data = type === 'plain-text' ? '' : [];
   const getItemData = {
@@ -475,6 +493,12 @@ function exportLogs(type) {
     },
   };
   translatedLog.value.forEach((item, index) => {
+    let logData = props.ctxData;
+    if (logData.ctxData) logData = logData.ctxData;
+
+    const itemData = logData[item.id] || null;
+    if (itemData) getDataSnapshot(itemData.referenceData);
+
     getItemData[type](
       [
         dayjs(item.timestamp || Date.now()).format('DD-MM-YYYY, hh:mm:ss'),
@@ -482,7 +506,7 @@ function exportLogs(type) {
         item.name,
         item.description || 'NULL',
         item.message || 'NULL',
-        props.ctxData[item.id] || null,
+        itemData,
       ],
       index
     );

+ 0 - 1
src/content/index.js

@@ -263,7 +263,6 @@ function messageListener({ data, source }) {
               $ctxElSelector,
               $ctxTextSelection,
             });
-            console.log(cloneContextData);
 
             $ctxLink = '';
             $ctxMediaUrl = '';

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

@@ -587,7 +587,7 @@ const updateHostedWorkflow = throttle(async () => {
   if (!userStore.user || workflowPayload.isUpdating) return;
 
   const isHosted = userStore.hostedWorkflows[route.params.id];
-  const isBackup = userStore.backupIds.includes(route.params.id);
+  const isBackup = userStore.backupIds?.includes(route.params.id);
   const workflowExist = workflowStore.getById(route.params.id);
 
   if (

+ 37 - 11
src/workflowEngine/WorkflowEngine.js

@@ -27,7 +27,6 @@ class WorkflowEngine {
     this.extractedGroup = {};
     this.connectionsMap = {};
     this.waitConnections = {};
-    this.restartWorkersCount = {};
 
     this.isDestroyed = false;
     this.isUsingProxy = false;
@@ -65,6 +64,17 @@ class WorkflowEngine {
     }
     this.options = options;
 
+    this.refDataSnapshots = {};
+    this.refDataSnapshotsKeys = {
+      loopData: {
+        index: 0,
+        key: '##loopData0',
+      },
+      variables: {
+        index: 0,
+        key: '##variables0',
+      },
+    };
     this.referenceData = {
       variables,
       table: [],
@@ -121,6 +131,10 @@ class WorkflowEngine {
         return;
       }
 
+      if (!this.workflow.settings) {
+        this.workflow.settings = {};
+      }
+
       blocks = getBlocks();
 
       const checkParams = this.options?.checkParams ?? true;
@@ -144,7 +158,7 @@ class WorkflowEngine {
           browser.windows.create({
             type: 'popup',
             width: 480,
-            height: 650,
+            height: 700,
             url: browser.runtime.getURL(
               `/params.html?workflowId=${this.workflow.id}`
             ),
@@ -174,7 +188,8 @@ class WorkflowEngine {
         {}
       );
 
-      const workflowTable = this.workflow.table || this.workflow.dataColumns;
+      const workflowTable =
+        this.workflow.table || this.workflow.dataColumns || [];
       let columns = Array.isArray(workflowTable)
         ? workflowTable
         : Object.values(workflowTable);
@@ -259,6 +274,16 @@ class WorkflowEngine {
     }
   }
 
+  addRefDataSnapshot(key) {
+    this.refDataSnapshotsKeys[key].index += 1;
+    this.refDataSnapshotsKeys[
+      key
+    ].key = `##${key}${this.refDataSnapshotsKeys[key].index}`;
+
+    const keyName = this.refDataSnapshotsKeys[key].key;
+    this.refDataSnapshots[keyName] = cloneDeep(this.referenceData[key]);
+  }
+
   addWorker(detail) {
     this.workerId += 1;
 
@@ -272,7 +297,7 @@ class WorkflowEngine {
   addLogHistory(detail) {
     if (detail.name === 'blocks-group') return;
 
-    const isLimit = this.history?.length >= this.logsLimit;
+    const isLimit = this.history.length >= this.logsLimit;
     const notErrorLog = detail.type !== 'error';
 
     if ((isLimit || !this.saveLog) && notErrorLog) return;
@@ -286,15 +311,13 @@ class WorkflowEngine {
       detail.name === 'javascript-code' ||
       (blocks[detail.name]?.refDataKeys && this.saveLog)
     ) {
-      const { activeTabUrl, variables, loopData } = JSON.parse(
-        JSON.stringify(this.referenceData)
-      );
+      const { variables, loopData } = this.refDataSnapshotsKeys;
 
       this.historyCtxData[this.logHistoryId] = {
         referenceData: {
-          loopData,
-          variables,
-          activeTabUrl,
+          loopData: loopData.key,
+          variables: variables.key,
+          activeTabUrl: detail.activeTabUrl,
           prevBlockData: detail.prevBlockData || '',
         },
         replacedValue: cloneDeep(detail.replacedValue),
@@ -482,7 +505,10 @@ class WorkflowEngine {
           },
           ctxData: {
             logId: this.id,
-            data: this.historyCtxData,
+            data: {
+              ctxData: this.historyCtxData,
+              dataSnapshot: this.refDataSnapshots,
+            },
           },
           data: {
             logId: this.id,

+ 2 - 0
src/workflowEngine/WorkflowWorker.js

@@ -87,6 +87,7 @@ class WorkflowWorker {
 
   setVariable(name, value) {
     this.engine.referenceData.variables[name] = value;
+    this.engine.addRefDataSnapshot('variables');
   }
 
   getBlockConnections(blockId, outputIndex = 1) {
@@ -196,6 +197,7 @@ class WorkflowWorker {
         blockId: block.id,
         workerId: this.id,
         timestamp: startExecuteTime,
+        activeTabUrl: this.activeTab?.url,
         replacedValue: replacedBlock.replacedValue,
         duration: Math.round(Date.now() - startExecuteTime),
         ...obj,

+ 1 - 0
src/workflowEngine/blocksHandler/handlerLoopBreakpoint.js

@@ -70,6 +70,7 @@ async function loopBreakpoint(block, { prevBlockData }) {
 
   delete this.loopList[block.data.loopId];
   delete this.engine.referenceData.loopData[block.data.loopId];
+  this.engine.addRefDataSnapshot('loopData');
 
   return {
     data: prevBlockData,

+ 1 - 0
src/workflowEngine/blocksHandler/handlerLoopData.js

@@ -106,6 +106,7 @@ async function loopData({ data, id }, { refData }) {
             : currLoopData[index],
         $index: index,
       };
+      this.engine.addRefDataSnapshot('loopData');
     }
 
     if (this.engine.isPopup) {