WorkflowEditor.vue 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. <template>
  2. <workflow-list
  3. v-if="!activeWorkflow"
  4. :workflows="state.workflows"
  5. @select="state.activeWorkflow = $event"
  6. />
  7. <div v-else class="mt-4 px-4 pb-4">
  8. <div class="flex items-center">
  9. <button class="group" @click="state.activeWorkflow = ''">
  10. <v-remixicon
  11. name="riArrowLeftLine"
  12. class="group-hover:-translate-x-1 -ml-1 transition-transform align-bottom inline-block"
  13. />
  14. </button>
  15. <p class="flex-1 text-overflow font-semibold ml-1">
  16. {{ activeWorkflow.name }}
  17. </p>
  18. </div>
  19. <p class="mt-2">Select a block output to start</p>
  20. <div
  21. ref="editorContainer"
  22. class="parent-drawflow h-40 min-h w-full rounded-lg bg-box-transparent"
  23. ></div>
  24. <workflow-add-block v-if="activeBlock" />
  25. </div>
  26. </template>
  27. <script setup>
  28. import {
  29. shallowReactive,
  30. computed,
  31. watch,
  32. ref,
  33. getCurrentInstance,
  34. shallowRef,
  35. inject,
  36. } from 'vue';
  37. import browser from 'webextension-polyfill';
  38. import { findTriggerBlock } from '@/utils/helper';
  39. import drawflow from '@/lib/drawflow';
  40. import WorkflowList from './WorkflowList.vue';
  41. import WorkflowAddBlock from './WorkflowAddBlock.vue';
  42. const rootElement = inject('rootElement');
  43. const context = getCurrentInstance().appContext.app._context;
  44. const editor = shallowRef(null);
  45. const editorContainer = ref(null);
  46. const activeBlock = shallowRef(null);
  47. const state = shallowReactive({
  48. workflows: [],
  49. activeWorkflow: '',
  50. blockOutput: 'output_1',
  51. });
  52. const activeWorkflow = computed(() =>
  53. state.workflows.find(({ id }) => id === state.activeWorkflow)
  54. );
  55. function onEditorClick(event) {
  56. const [target] = event.composedPath();
  57. const nodeEl = target.closest('.drawflow-node');
  58. if (nodeEl) {
  59. const prevActiveEl = editorContainer.value.querySelector(
  60. '.drawflow-node.selected'
  61. );
  62. if (prevActiveEl) {
  63. prevActiveEl.classList.remove('selected');
  64. const outputEl = prevActiveEl.querySelector('.output.active');
  65. outputEl.classList.remove('active');
  66. }
  67. const nodeId = nodeEl.id.slice(5);
  68. const node = editor.value.getNodeFromId(nodeId);
  69. let outputEl = target.closest('.output');
  70. if (outputEl) {
  71. /* eslint-disable-next-line */
  72. state.blockOutput = outputEl.classList[1];
  73. outputEl.classList.add('active');
  74. } else {
  75. const firstOutput = Object.keys(node.outputs)[0];
  76. state.blockOutput = firstOutput || '';
  77. outputEl = nodeEl.querySelector(`.${firstOutput}`);
  78. }
  79. console.log(outputEl);
  80. if (outputEl) outputEl.classList.add('active');
  81. nodeEl.classList.add('selected');
  82. activeBlock.value = node;
  83. console.log(activeBlock.value);
  84. }
  85. }
  86. watch(editorContainer, (element) => {
  87. if (!activeWorkflow.value) return;
  88. const flowData = activeWorkflow.value.drawflow;
  89. const flow = typeof flowData === 'string' ? JSON.parse(flowData) : flowData;
  90. const triggerBlock = findTriggerBlock(flow);
  91. const editorInstance = drawflow(element, {
  92. context,
  93. options: {
  94. zoom: 0.5,
  95. zoom_min: 0.1,
  96. zoom_max: 0.8,
  97. minimap: true,
  98. editor_mode: 'fixed',
  99. rootElement: rootElement.shadowRoot,
  100. },
  101. });
  102. editorInstance.start();
  103. editorInstance.import(flow);
  104. if (triggerBlock) {
  105. const getCoordinate = (pos) => {
  106. const num = Math.abs(pos);
  107. if (pos > 0) return -num;
  108. return num;
  109. };
  110. editorInstance.translate_to(
  111. getCoordinate(triggerBlock.pos_x),
  112. getCoordinate(triggerBlock.pos_y)
  113. );
  114. }
  115. editor.value = editorInstance;
  116. element.addEventListener('click', onEditorClick);
  117. });
  118. (async () => {
  119. const { workflows } = await browser.storage.local.get('workflows');
  120. state.workflows = (workflows || []).reverse();
  121. })();
  122. </script>
  123. <style>
  124. .output.active {
  125. @apply ring-4;
  126. }
  127. </style>