Преглед изворни кода

feat: add options tab in element selector

Ahmad Kholid пре 3 година
родитељ
комит
46acfb30ae

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "automa",
-  "version": "0.17.0",
+  "version": "0.17.2",
   "description": "An extension for automating your browser by connecting blocks",
   "license": "MIT",
   "repository": {

+ 5 - 2
src/components/newtab/logs/LogsDataViewer.vue

@@ -35,11 +35,14 @@
   />
 </template>
 <script setup>
-import { ref, computed } from 'vue';
+import { ref, computed, defineAsyncComponent } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { dataExportTypes } from '@/utils/shared';
 import dataExporter, { generateJSON } from '@/utils/data-exporter';
-import SharedCodemirror from '@/components/newtab/shared/SharedCodemirror.vue';
+
+const SharedCodemirror = defineAsyncComponent(() =>
+  import('@/components/newtab/shared/SharedCodemirror.vue')
+);
 
 const props = defineProps({
   log: {

+ 5 - 2
src/components/newtab/workflow/WorkflowGlobalData.vue

@@ -19,10 +19,13 @@
   </div>
 </template>
 <script setup>
-import { ref, watch } from 'vue';
+import { ref, watch, defineAsyncComponent } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { debounce } from '@/utils/helper';
-import SharedCodemirror from '@/components/newtab/shared/SharedCodemirror.vue';
+
+const SharedCodemirror = defineAsyncComponent(() =>
+  import('@/components/newtab/shared/SharedCodemirror.vue')
+);
 
 const props = defineProps({
   workflow: {

+ 5 - 2
src/components/newtab/workflow/edit/EditExecuteWorkflow.vue

@@ -45,11 +45,14 @@
   </div>
 </template>
 <script setup>
-import { computed, shallowReactive } from 'vue';
+import { computed, shallowReactive, defineAsyncComponent } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useRoute } from 'vue-router';
 import Workflow from '@/models/workflow';
-import SharedCodemirror from '@/components/newtab/shared/SharedCodemirror.vue';
+
+const SharedCodemirror = defineAsyncComponent(() =>
+  import('@/components/newtab/shared/SharedCodemirror.vue')
+);
 
 const props = defineProps({
   data: {

+ 5 - 2
src/components/newtab/workflow/edit/EditGoogleSheets.vue

@@ -153,11 +153,14 @@
   </div>
 </template>
 <script setup>
-import { shallowReactive } from 'vue';
+import { shallowReactive, defineAsyncComponent } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { googleSheets } from '@/utils/api';
 import { convert2DArrayToArrayObj } from '@/utils/helper';
-import SharedCodemirror from '@/components/newtab/shared/SharedCodemirror.vue';
+
+const SharedCodemirror = defineAsyncComponent(() =>
+  import('@/components/newtab/shared/SharedCodemirror.vue')
+);
 
 const props = defineProps({
   data: {

+ 5 - 2
src/components/newtab/workflow/edit/EditJavascriptCode.vue

@@ -91,11 +91,14 @@
   </div>
 </template>
 <script setup>
-import { watch, reactive } from 'vue';
+import { watch, reactive, defineAsyncComponent } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { syntaxTree } from '@codemirror/language';
 import { autocompletion, snippet } from '@codemirror/autocomplete';
-import SharedCodemirror from '@/components/newtab/shared/SharedCodemirror.vue';
+
+const SharedCodemirror = defineAsyncComponent(() =>
+  import('@/components/newtab/shared/SharedCodemirror.vue')
+);
 
 const props = defineProps({
   data: {

+ 5 - 2
src/components/newtab/workflow/edit/EditLoopData.vue

@@ -119,13 +119,16 @@
   </div>
 </template>
 <script setup>
-import { onMounted, shallowReactive } from 'vue';
+import { onMounted, shallowReactive, defineAsyncComponent } from 'vue';
 import { nanoid } from 'nanoid';
 import { useI18n } from 'vue-i18n';
 import { useToast } from 'vue-toastification';
 import Papa from 'papaparse';
 import { openFilePicker } from '@/utils/helper';
-import SharedCodemirror from '@/components/newtab/shared/SharedCodemirror.vue';
+
+const SharedCodemirror = defineAsyncComponent(() =>
+  import('@/components/newtab/shared/SharedCodemirror.vue')
+);
 
 const props = defineProps({
   blockId: {

+ 5 - 2
src/components/newtab/workflow/edit/EditWebhook.vue

@@ -107,10 +107,13 @@
   </div>
 </template>
 <script setup>
-import { ref, watch } from 'vue';
+import { ref, watch, defineAsyncComponent } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { contentTypes } from '@/utils/shared';
-import SharedCodemirror from '@/components/newtab/shared/SharedCodemirror.vue';
+
+const SharedCodemirror = defineAsyncComponent(() =>
+  import('@/components/newtab/shared/SharedCodemirror.vue')
+);
 
 const props = defineProps({
   data: {

+ 79 - 8
src/content/element-selector/App.vue

@@ -42,6 +42,9 @@
       <template v-if="!state.hide && state.selectedElements.length > 0">
         <ui-tabs v-model="state.activeTab" class="mt-2" fill>
           <ui-tab value="attributes"> Attributes </ui-tab>
+          <ui-tab v-if="state.selectElements.length > 0" value="options">
+            Options
+          </ui-tab>
           <ui-tab value="blocks"> Blocks </ui-tab>
         </ui-tabs>
         <ui-tab-panels
@@ -50,13 +53,62 @@
           style="max-height: calc(100vh - 15rem)"
         >
           <ui-tab-panel value="attributes">
-            <app-element-attributes
+            <app-element-list
               :elements="state.selectedElements"
+              @highlight="toggleHighlightElement"
+            >
+              <template #item="{ element }">
+                <div
+                  v-for="attribute in element.attributes"
+                  :key="attribute.name"
+                  class="bg-box-transparent mb-1 rounded-lg py-2 px-3"
+                >
+                  <p
+                    class="text-sm text-overflow leading-tight text-gray-600"
+                    title="Attribute name"
+                  >
+                    {{ attribute.name }}
+                  </p>
+                  <p title="Attribute value" class="text-overflow">
+                    {{ attribute.value }}
+                  </p>
+                </div>
+              </template>
+            </app-element-list>
+          </ui-tab-panel>
+          <ui-tab-panel value="options">
+            <app-element-list
+              :elements="state.selectElements"
+              element-name="Select element options"
               @highlight="
-                state.selectedElements[$event.index].highlight =
-                  $event.highlight
+                toggleHighlightElement({
+                  index: $event.element.index,
+                  highlight: $event.highlight,
+                })
               "
-            />
+            >
+              <template #item="{ element }">
+                <div
+                  v-for="option in element.options"
+                  :key="option.name"
+                  class="bg-box-transparent mb-1 rounded-lg py-2 px-3"
+                >
+                  <p
+                    class="text-sm text-overflow leading-tight text-gray-600"
+                    title="Option name"
+                  >
+                    {{ option.name }}
+                  </p>
+                  <input
+                    :value="option.value"
+                    title="Option value"
+                    class="text-overflow focus:ring-0 w-full bg-transparent"
+                    readonly
+                    @click="$event.target.select()"
+                  />
+                </div>
+              </template>
+            </app-element-list>
           </ui-tab-panel>
           <ui-tab-panel value="blocks">
             <app-blocks
@@ -98,7 +150,7 @@ import { finder } from '@medv/finder';
 import { debounce } from '@/utils/helper';
 import AppBlocks from './AppBlocks.vue';
 import AppSelector from './AppSelector.vue';
-import AppElementAttributes from './AppElementAttributes.vue';
+import AppElementList from './AppElementList.vue';
 
 const selectedElement = {
   path: [],
@@ -115,6 +167,7 @@ const state = reactive({
   elSelector: '',
   isDragging: false,
   isExecuting: false,
+  selectElements: [],
   selectedElements: [],
   hide: window.self !== window.top,
 });
@@ -131,6 +184,9 @@ const cardRect = reactive({
   width: 0,
 });
 
+function toggleHighlightElement({ index, highlight }) {
+  state.selectedElements[index].highlight = highlight;
+}
 function getElementRect(target) {
   if (!target) return {};
 
@@ -148,20 +204,35 @@ function updateSelectedElements(selector) {
 
   try {
     const elements = document.querySelectorAll(selector);
+    const selectElements = [];
 
-    state.selectedElements = Array.from(elements).map((element) => {
+    state.selectedElements = Array.from(elements).map((element, index) => {
       const attributes = Array.from(element.attributes).map(
         ({ name, value }) => ({ name, value })
       );
-
-      return {
+      const elementProps = {
         element,
         attributes,
         highlight: false,
         ...getElementRect(element),
       };
+
+      if (element.tagName === 'SELECT') {
+        const options = Array.from(element.querySelectorAll('option')).map(
+          (option) => ({
+            name: option.innerText,
+            value: option.value,
+          })
+        );
+
+        selectElements.push({ ...elementProps, options, index });
+      }
+
+      return elementProps;
     });
+    state.selectElements = selectElements;
   } catch (error) {
+    state.selectElements = [];
     state.selectedElements = [];
   }
 }

+ 1 - 1
src/content/element-selector/AppBlocks.vue

@@ -28,7 +28,7 @@
     />
     <pre
       v-if="state.blockResult"
-      class="p-2 rounded-lg text-gray-100 bg-accent h-full mt-2 overflow-auto"
+      class="p-2 rounded-lg text-gray-100 bg-accent h-full mt-2 overflow-auto text-sm"
       >{{ state.blockResult }}</pre
     >
   </div>

+ 0 - 39
src/content/element-selector/AppElementAttributes.vue

@@ -1,39 +0,0 @@
-<template>
-  <ul class="space-y-4 mt-2">
-    <li
-      v-for="(element, index) in elements"
-      :key="index"
-      @mouseenter="$emit('highlight', { highlight: true, index })"
-      @mouseleave="$emit('highlight', { highlight: false, index })"
-    >
-      <p
-        class="mb-1 cursor-pointer"
-        title="Scroll into view"
-        @click="
-          element.element.scrollIntoView({ block: 'center', inline: 'center' })
-        "
-      >
-        #{{ index + 1 }} Element
-      </p>
-      <div
-        v-for="attribute in element.attributes"
-        :key="attribute.name"
-        class="bg-box-transparent mb-1 rounded-lg py-2 px-3"
-      >
-        <p class="text-sm text-overflow leading-tight text-gray-600">
-          {{ attribute.name }}
-        </p>
-        <p class="text-overflow">{{ attribute.value }}</p>
-      </div>
-    </li>
-  </ul>
-</template>
-<script setup>
-defineProps({
-  elements: {
-    type: Array,
-    default: () => [],
-  },
-});
-defineEmits(['highlight']);
-</script>

+ 34 - 0
src/content/element-selector/AppElementList.vue

@@ -0,0 +1,34 @@
+<template>
+  <ul class="space-y-4 mt-2">
+    <li
+      v-for="(element, index) in elements"
+      :key="index"
+      @mouseenter="$emit('highlight', { highlight: true, index, element })"
+      @mouseleave="$emit('highlight', { highlight: false, index, element })"
+    >
+      <p
+        class="mb-1 cursor-pointer"
+        title="Scroll into view"
+        @click="
+          element.element.scrollIntoView({ block: 'center', inline: 'center' })
+        "
+      >
+        #{{ index + 1 }} {{ elementName }}
+      </p>
+      <slot name="item" v-bind="{ element }" />
+    </li>
+  </ul>
+</template>
+<script setup>
+defineProps({
+  elements: {
+    type: Array,
+    default: () => [],
+  },
+  elementName: {
+    type: String,
+    default: 'Element',
+  },
+});
+defineEmits(['highlight']);
+</script>

+ 11 - 2
src/newtab/pages/collections/[id].vue

@@ -194,7 +194,13 @@
   </ui-modal>
 </template>
 <script setup>
-import { computed, shallowReactive, onMounted, watch } from 'vue';
+import {
+  computed,
+  shallowReactive,
+  onMounted,
+  watch,
+  defineAsyncComponent,
+} from 'vue';
 import { nanoid } from 'nanoid';
 import { useStore } from 'vuex';
 import { useRoute, useRouter } from 'vue-router';
@@ -206,9 +212,12 @@ import Log from '@/models/log';
 import Workflow from '@/models/workflow';
 import Collection from '@/models/collection';
 import SharedLogsTable from '@/components/newtab/shared/SharedLogsTable.vue';
-import SharedCodemirror from '@/components/newtab/shared/SharedCodemirror.vue';
 import SharedWorkflowState from '@/components/newtab/shared/SharedWorkflowState.vue';
 
+const SharedCodemirror = defineAsyncComponent(() =>
+  import('@/components/newtab/shared/SharedCodemirror.vue')
+);
+
 const { t } = useI18n();
 const store = useStore();
 const route = useRoute();