Browse Source

feat: add verify selector

Ahmad Kholid 2 years ago
parent
commit
10ae54efa7

+ 2 - 2
src/components/content/shared/SharedElementHighlighter.vue

@@ -4,11 +4,11 @@
     v-bind="{
       x: getNumber(item?.x),
       y: getNumber(item?.y),
+      fill: getFillColor(item),
+      stroke: getStrokeColor(item),
       width: getNumber(item?.width),
       height: getNumber(item?.height),
       'stroke-dasharray': item?.outline ? '5,5' : null,
-      fill: getFillColor(item),
-      stroke: getStrokeColor(item),
     }"
     :key="index"
     stroke-width="2"

+ 21 - 1
src/components/newtab/workflow/edit/EditInteractionBase.vue

@@ -24,10 +24,19 @@
         <ui-button
           v-tooltip.group="t('workflow.blocks.base.element.select')"
           icon
+          class="mr-2"
           @click="selectElement"
         >
           <v-remixicon name="riFocus3Line" />
         </ui-button>
+        <ui-button
+          v-tooltip.group="t('workflow.blocks.base.element.verify')"
+          :disabled="!data.selector"
+          icon
+          @click="verifySelector"
+        >
+          <v-remixicon name="riCheckDoubleLine" />
+        </ui-button>
       </div>
       <edit-autocomplete v-if="!hideSelector" class="mb-1">
         <ui-input
@@ -96,6 +105,7 @@
 <script setup>
 import { onMounted } from 'vue';
 import { useI18n } from 'vue-i18n';
+import { useToast } from 'vue-toastification';
 import elementSelector from '@/newtab/utils/elementSelector';
 import EditAutocomplete from './EditAutocomplete.vue';
 
@@ -125,6 +135,7 @@ const props = defineProps({
 const emit = defineEmits(['update:data', 'change']);
 
 const { t } = useI18n();
+const toast = useToast();
 
 const selectorTypes = ['cssSelector', 'xpath'];
 
@@ -135,11 +146,20 @@ function updateData(value) {
   emit('change', payload);
 }
 function selectElement() {
-  /* eslint-disable-next-line */
   elementSelector.selectElement().then((selector) => {
     updateData({ selector });
   });
 }
+function verifySelector() {
+  const { selector, multiple, findBy } = props.data;
+  elementSelector
+    .verifySelector({ selector, multiple, findBy })
+    .then((result) => {
+      if (!result.notFound) return;
+
+      toast.error('Element not found');
+    });
+}
 
 onMounted(() => {
   if (!props.data.findBy) {

+ 59 - 0
src/content/blocksHandler/handlerVerifySelector.js

@@ -0,0 +1,59 @@
+import { sleep } from '@/utils/helper';
+import handleSelector from '../handleSelector';
+
+const SLEEP_TIME = 1700;
+
+async function verifySelector(block) {
+  let elements = await handleSelector(block);
+  if (!elements) {
+    await sleep(SLEEP_TIME);
+    return { notFound: true };
+  }
+
+  if (!block.data.multiple) {
+    elements.scrollIntoView({
+      block: 'center',
+      inline: 'center',
+      behavior: 'smooth',
+    });
+    elements = [elements];
+  }
+
+  const divEl = document.createElement('div');
+  divEl.style =
+    'height: 100%; width: 100%; top: 0; left: 0; background-color: rgb(0 0 0 / 0.3); pointer-events: none; position: fixed; z-index: 99999';
+
+  const svgEl = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
+  svgEl.style =
+    'height: 100%; width: 100%; top: 0; left: 0; pointer-events: none; position: relative;';
+
+  divEl.appendChild(svgEl);
+
+  elements.forEach((element) => {
+    const { left, top, width, height } = element.getBoundingClientRect();
+    const rectEl = document.createElementNS(
+      'http://www.w3.org/2000/svg',
+      'rect'
+    );
+
+    rectEl.setAttribute('y', top);
+    rectEl.setAttribute('x', left);
+    rectEl.setAttribute('width', width);
+    rectEl.setAttribute('height', height);
+    rectEl.setAttribute('stroke', '#2563EB');
+    rectEl.setAttribute('stroke-width', '2');
+    rectEl.setAttribute('fill', 'rgba(37, 99, 235, 0.4)');
+
+    svgEl.appendChild(rectEl);
+  });
+
+  document.body.appendChild(divEl);
+
+  await sleep(SLEEP_TIME);
+
+  divEl.remove();
+
+  return { notFound: false };
+}
+
+export default verifySelector;

+ 2 - 0
src/lib/vRemixicon.js

@@ -92,6 +92,7 @@ import {
   riFileListLine,
   riDragDropLine,
   riClipboardLine,
+  riCheckDoubleLine,
   riDoubleQuotesL,
   riLightbulbLine,
   riFolderZipLine,
@@ -225,6 +226,7 @@ export const icons = {
   riFileListLine,
   riDragDropLine,
   riClipboardLine,
+  riCheckDoubleLine,
   riDoubleQuotesL,
   riLightbulbLine,
   riFolderZipLine,

+ 1 - 1
src/locales/en/blocks.json

@@ -20,7 +20,7 @@
         "action": "Action",
         "element": {
           "select": "Select an element",
-          "verify": "Verify element"
+          "verify": "Verify selector"
         },
         "settings": {
           "title": "Block settings",

+ 42 - 13
src/newtab/utils/elementSelector.js

@@ -1,4 +1,24 @@
 import browser from 'webextension-polyfill';
+import { isXPath } from '@/utils/helper';
+
+async function getActiveTab() {
+  const [tab] = await browser.tabs.query({
+    active: true,
+    url: '*://*/*',
+  });
+  if (!tab) throw new Error('No active tab');
+
+  return tab;
+}
+async function makeDashboardFocus() {
+  const [currentTab] = await browser.tabs.query({
+    active: true,
+    currentWindow: true,
+  });
+  await browser.windows.update(currentTab.windowId, {
+    focused: true,
+  });
+}
 
 async function initElementSelector(tab = null) {
   let activeTab = tab;
@@ -29,14 +49,29 @@ async function initElementSelector(tab = null) {
   await browser.windows.update(activeTab.windowId, { focused: true });
 }
 
-export function verifySelector() {}
+async function verifySelector(data) {
+  const activeTab = await getActiveTab();
 
-export async function selectElement(name) {
-  const [tab] = await browser.tabs.query({
-    active: true,
-    url: '*://*/*',
+  if (!data.findBy) {
+    data.findBy = isXPath(data.selector) ? 'xpath' : 'cssSelector';
+  }
+
+  await browser.tabs.update(activeTab.id, { active: true });
+  await browser.windows.update(activeTab.windowId, { focused: true });
+
+  const result = await browser.tabs.sendMessage(activeTab.id, {
+    data,
+    isBlock: true,
+    label: 'verify-selector',
   });
-  if (!tab) throw new Error('No active tab');
+
+  await makeDashboardFocus();
+
+  return result;
+}
+
+async function selectElement(name) {
+  const tab = await getActiveTab();
 
   await initElementSelector(tab);
 
@@ -48,13 +83,7 @@ export async function selectElement(name) {
       });
       port.onMessage.addListener(async (message) => {
         try {
-          const [currentTab] = await browser.tabs.query({
-            active: true,
-            currentWindow: true,
-          });
-          await browser.windows.update(currentTab.windowId, {
-            focused: true,
-          });
+          makeDashboardFocus();
         } catch (error) {
           console.error(error);
         } finally {