Selaa lähdekoodia

feat: add copy paste blocks

Ahmad Kholid 2 vuotta sitten
vanhempi
commit
f3add4740a
4 muutettua tiedostoa jossa 112 lisäystä ja 26 poistoa
  1. 1 1
      package.json
  2. 79 2
      src/newtab/pages/workflows/[id].vue
  3. 4 1
      src/stores/main.js
  4. 28 22
      yarn.lock

+ 1 - 1
package.json

@@ -30,7 +30,7 @@
     "*.{js,ts,vue}": "eslint --fix"
   },
   "dependencies": {
-    "@braks/vue-flow": "^0.4.23",
+    "@braks/vue-flow": "^0.4.24",
     "@codemirror/lang-javascript": "^6.0.0",
     "@codemirror/lang-json": "^6.0.0",
     "@codemirror/language": "^6.0.0",

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

@@ -127,6 +127,7 @@ import {
 import { useI18n } from 'vue-i18n';
 import { useRoute, useRouter, onBeforeRouteLeave } from 'vue-router';
 import { customAlphabet } from 'nanoid';
+import { useStore } from '@/stores/main';
 import { useUserStore } from '@/stores/user';
 import { useWorkflowStore } from '@/stores/workflow';
 import { useShortcut } from '@/composable/shortcut';
@@ -148,6 +149,7 @@ import EditorLocalActions from '@/components/newtab/workflow/editor/EditorLocalA
 const nanoid = customAlphabet('1234567890abcdef', 7);
 
 const { t } = useI18n();
+const store = useStore();
 const route = useRoute();
 const router = useRouter();
 const userStore = useUserStore();
@@ -346,8 +348,15 @@ function updateWorkflow(data) {
 function onEditorInit(instance) {
   editor.value = instance;
   // listen to change event
-  instance.onEdgesChange(() => {
-    state.dataChanged = true;
+  instance.onEdgesChange((changes) => {
+    changes.forEach(({ type }) => {
+      if (state.dataChanged) return;
+
+      state.dataChanged = type !== 'select';
+    });
+  });
+  instance.onEdgeDoubleClick(({ edge }) => {
+    instance.removeEdges([edge]);
   });
 }
 function clearHighlightedElements() {
@@ -438,6 +447,72 @@ function onDropInEditor({ dataTransfer, clientX, clientY, target }) {
 
   state.dataChanged = true;
 }
+function copySelectedElements() {
+  const newIds = new Map();
+
+  const nodes = editor.value.getSelectedNodes.value.map(
+    ({ id, label, position, data, type }) => {
+      const newNodeId = nanoid();
+
+      newIds.set(id, newNodeId);
+
+      return {
+        type,
+        data,
+        label,
+        position: {
+          z: position.z,
+          y: position.y + 50,
+          x: position.x + 50,
+        },
+        id: newNodeId,
+        selected: true,
+      };
+    }
+  );
+  const edges = editor.value.getSelectedEdges.value.reduce(
+    (acc, { target, targetHandle, source, sourceHandle }) => {
+      const targetId = newIds.get(target);
+      const sourceId = newIds.get(source);
+
+      if (!targetId || !sourceId) return acc;
+
+      acc.push({
+        selected: true,
+        target: targetId,
+        source: sourceId,
+        id: `edge-${nanoid()}`,
+        targetHandle: targetHandle.replace(target, targetId),
+        sourceHandle: sourceHandle.replace(source, sourceId),
+      });
+
+      return acc;
+    },
+    []
+  );
+
+  store.copiedEls.edges = edges;
+  store.copiedEls.nodes = nodes;
+}
+function pasteCopiedElements() {
+  editor.value.removeSelectedNodes(editor.value.getSelectedNodes.value);
+  editor.value.removeSelectedEdges(editor.value.getSelectedEdges.value);
+
+  const { nodes, edges } = store.copiedEls;
+  editor.value.addNodes(nodes);
+  editor.value.addEdges(edges);
+}
+function onKeydown({ ctrlKey, metaKey, key }) {
+  const command = (keyName) => (ctrlKey || metaKey) && keyName === key;
+
+  if (command('c')) {
+    copySelectedElements();
+    console.log(store.copiedEls);
+  } else if (command('v')) {
+    pasteCopiedElements();
+  }
+}
+
 /* eslint-disable consistent-return */
 onBeforeRouteLeave(() => {
   updateHostedWorkflow();
@@ -469,9 +544,11 @@ onMounted(() => {
     }
     return true;
   };
+  window.addEventListener('keydown', onKeydown);
 });
 onBeforeUnmount(() => {
   window.onbeforeunload = null;
+  window.removeEventListener('keydown', onKeydown);
 });
 </script>
 <style>

+ 4 - 1
src/stores/main.js

@@ -4,7 +4,10 @@ import browser from 'webextension-polyfill';
 
 export const useStore = defineStore('main', {
   state: () => ({
-    user: null,
+    copiedEls: {
+      edges: [],
+      nodes: [],
+    },
     settings: {
       locale: 'en',
       deleteLogAfter: 30,

+ 28 - 22
yarn.lock

@@ -912,13 +912,13 @@
     "@babel/helper-validator-identifier" "^7.16.7"
     to-fast-properties "^2.0.0"
 
-"@braks/vue-flow@^0.4.23":
-  version "0.4.23"
-  resolved "https://registry.yarnpkg.com/@braks/vue-flow/-/vue-flow-0.4.23.tgz#a6cf2087edd78d9aec70b544c067972ce26abce9"
-  integrity sha512-+BmeM1WareYWRAqcLeSSmLqJUOCoO9dvjiQslnzn4cM7DkqjjXaZnk59lB1Wki/5eEXeGMBTWOKciHUxq/i/oA==
+"@braks/vue-flow@^0.4.24":
+  version "0.4.24"
+  resolved "https://registry.yarnpkg.com/@braks/vue-flow/-/vue-flow-0.4.24.tgz#126f6f96dc8e0fc727e81eeb8d3d1f53bfca7468"
+  integrity sha512-9yRLeQGGnTgBSdBt1euqRWeEYjnmX2gdyhfZqgizUVHLdB90cfLltScLp3C7SXBAX3cbG1HCpS22oB7+OsXTPw==
   dependencies:
     "@types/d3" "^7.4.0"
-    "@vueuse/core" "^8.6.0"
+    "@vueuse/core" "^8.7.5"
     d3 "^7.4.4"
     d3-drag "^3.0.0"
     d3-selection "^3.0.0"
@@ -1839,6 +1839,11 @@
   dependencies:
     "@types/node" "*"
 
+"@types/web-bluetooth@^0.0.14":
+  version "0.0.14"
+  resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.14.tgz#94e175b53623384bff1f354cdb3197a8d63cdbe5"
+  integrity sha512-5d2RhCard1nQUC3aHcq/gHzWYO6K0WJmAbjO7mQJgCQKtZpgXxv1rOM6O/dBDhDYYVutk1sciOgNSe+5YyfM8A==
+
 "@types/ws@^8.5.1":
   version "8.5.3"
   resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d"
@@ -1946,19 +1951,20 @@
   resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.37.tgz#8e6adc3f2759af52f0e85863dfb0b711ecc5c702"
   integrity sha512-4rSJemR2NQIo9Klm1vabqWjD8rs/ZaJSzMxkMNeJS6lHiUjjUeYFbooN19NgFjztubEKh3WlZUeOLVdbbUWHsw==
 
-"@vueuse/core@^8.6.0":
-  version "8.7.3"
-  resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-8.7.3.tgz#50d4e40417f10d9b3ccf801cee9b1bf913f0a1da"
-  integrity sha512-jpBnyG9b4wXgk0Dz3I71lfhD0o53t1tZR+NoAQ+17zJy7MP/VDfGIkq8GcqpDwmptLCmGiGVipkPbWmDGMic8Q==
+"@vueuse/core@^8.7.5":
+  version "8.7.5"
+  resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-8.7.5.tgz#e74a888251ea11a9d432068ce18cbdfc4f810251"
+  integrity sha512-tqgzeZGoZcXzoit4kOGLWJibDMLp0vdm6ZO41SSUQhkhtrPhAg6dbIEPiahhUu6sZAmSYvVrZgEr5aKD51nrLA==
   dependencies:
-    "@vueuse/metadata" "8.7.3"
-    "@vueuse/shared" "8.7.3"
+    "@types/web-bluetooth" "^0.0.14"
+    "@vueuse/metadata" "8.7.5"
+    "@vueuse/shared" "8.7.5"
     vue-demi "*"
 
-"@vueuse/metadata@8.7.3":
-  version "8.7.3"
-  resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-8.7.3.tgz#6db0d064ed4ece3854be63a43a829ed6395d6844"
-  integrity sha512-spf9kgCsBEFbQb90I6SIqAWh1yP5T1JoJGj+/04+VTMIHXKzn3iecmHUalg8QEOCPNtnFQGNEw5OLg0L39eizg==
+"@vueuse/metadata@8.7.5":
+  version "8.7.5"
+  resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-8.7.5.tgz#c7f2b21d873d1604a8860ed9c5728d8f3295f00a"
+  integrity sha512-emJZKRQSaEnVqmlu39NpNp8iaW+bPC2kWykWoWOZMSlO/0QVEmO/rt8A5VhOEJTKLX3vwTevqbiRy9WJRwVOQg==
 
 "@vueuse/rxjs@^8.7.4":
   version "8.7.4"
@@ -1968,13 +1974,6 @@
     "@vueuse/shared" "8.7.4"
     vue-demi "*"
 
-"@vueuse/shared@8.7.3":
-  version "8.7.3"
-  resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-8.7.3.tgz#64b394c24a68fcf105c6bfe98954df11642bc111"
-  integrity sha512-PMc/h6cEakJ4+5VuNUGi7RnbA6CkLvtG2230x8w3zYJpW1P6Qphh9+dFFvHn7TX+RlaicF5ND0RX1NxWmAoW7w==
-  dependencies:
-    vue-demi "*"
-
 "@vueuse/shared@8.7.4":
   version "8.7.4"
   resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-8.7.4.tgz#c9ddff6515c0898bb28d00a38dccc62d9be35887"
@@ -1982,6 +1981,13 @@
   dependencies:
     vue-demi "*"
 
+"@vueuse/shared@8.7.5":
+  version "8.7.5"
+  resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-8.7.5.tgz#06fb08f6f8fc9e90be9d1e033fa443de927172b0"
+  integrity sha512-THXPvMBFmg6Gf6AwRn/EdTh2mhqwjGsB2Yfp374LNQSQVKRHtnJ0I42bsZTn7nuEliBxqUrGQm/lN6qUHmhJLw==
+  dependencies:
+    vue-demi "*"
+
 "@vuex-orm/core@^0.36.4":
   version "0.36.4"
   resolved "https://registry.yarnpkg.com/@vuex-orm/core/-/core-0.36.4.tgz#9e2b1b8dfd74c2a508f1862ffa3e4a2c1e4cc60c"