diff --git a/manifest.json b/manifest.json index 608bd45..6c26328 100644 --- a/manifest.json +++ b/manifest.json @@ -3,7 +3,7 @@ "name": "JDN", "description": "", "devtools_page": "index.html", - "version": "3.0.44", + "version": "3.0.45", "permissions": [ "activeTab", "tabs", diff --git a/package-lock.json b/package-lock.json index 9aa708e..2aa0d87 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "jdi-react-extension", - "version": "3.0.42", + "version": "3.0.44", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index d6892d2..33a0a3f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jdi-react-extension", - "version": "3.0.44", + "version": "3.0.45", "description": "jdi react extension", "scripts": { "start": "npm run webpack", diff --git a/src/css/main.less b/src/css/main.less index 64bffcc..5907392 100644 --- a/src/css/main.less +++ b/src/css/main.less @@ -9,14 +9,14 @@ ul { list-style: nont; } -.urls-list { - margin: 0 0 0 10px; -} - #chromeExtensionReactApp { - overflow-x: hidden; + height: 100%; + font-family: 'Noto Sans', sans-serif; + background-color: #f7faff; } +.ant-layout { background-color: inherit; } + .ant-select-selection-item { color: #008ace; font-size: 13px; @@ -104,10 +104,10 @@ button svg { cursor: pointer; } -.ant-btn-primary { - color: #fff; - border: none; -} +// .ant-btn-primary { +// color: #fff; +// border: none; +// } .ant-btn-sm { font-size: 12px; diff --git a/src/icons/clear-all.svg b/src/icons/clear-all.svg new file mode 100644 index 0000000..0ae079f --- /dev/null +++ b/src/icons/clear-all.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/icons/download.svg b/src/icons/download.svg new file mode 100644 index 0000000..6e17202 --- /dev/null +++ b/src/icons/download.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/icons/index.js b/src/icons/index.js index 2caf5bb..4981ff8 100644 --- a/src/icons/index.js +++ b/src/icons/index.js @@ -8,6 +8,7 @@ const arrowDown = require("./arrow-down.png"); const errorIcon = require("./error.png"); const successIcon = require("./success.png"); const warningIcon = require("./warning.png"); +const questionFilled = require("./question-filled.svg"); export { settings, @@ -20,4 +21,5 @@ export { errorIcon, successIcon, warningIcon, + questionFilled, }; diff --git a/src/icons/question-filled.svg b/src/icons/question-filled.svg new file mode 100644 index 0000000..c2ccae2 --- /dev/null +++ b/src/icons/question-filled.svg @@ -0,0 +1,4 @@ + +​​​​​​​ + + \ No newline at end of file diff --git a/src/index.html b/src/index.html index dcc809a..176d780 100644 --- a/src/index.html +++ b/src/index.html @@ -5,6 +5,9 @@ + + + diff --git a/src/js/blocks/autoFind/AutoFind.jsx b/src/js/blocks/autoFind/AutoFind.jsx deleted file mode 100644 index 58bfbc4..0000000 --- a/src/js/blocks/autoFind/AutoFind.jsx +++ /dev/null @@ -1,132 +0,0 @@ -import React, { useEffect, useState } from "react"; -import injectSheet from "react-jss"; -import { Slider, Row, Alert } from "antd"; -import { useAutoFind, xpathGenerationStatus } from "./autoFindProvider/AutoFindProvider"; - -import "./slider.less"; -import Layout, { Content, Footer } from "antd/lib/layout/layout"; -import { styles } from "./styles"; -import { XPathSettings } from "./xPathSettings/XPathSettings"; - -let sliderTimer; -const AutoFind = ({ classes }) => { - const [perceptionOutput, setPerceptionOutput] = useState(0.5); - const [backendVer, setBackendVer] = useState(""); - const [ - { - status, - predictedElements, - pageElements, - allowIdentifyElements, - allowRemoveElements, - perception, - unreachableNodes, - availableForGeneration, - xpathStatus, - unactualPrediction, - }, - { identifyElements, removeHighlighs, generateAndDownload, onChangePerception, reportProblem }, - ] = useAutoFind(); - - useEffect(() => { - const fetchData = async () => { - const result = await fetch("http:localhost:5000/build", { - method: "GET", - }); - const r = await result.json(); - setBackendVer(r); - }; - - fetchData(); - }, []); - - const handleGetElements = () => { - identifyElements(); - }; - - const handleRemove = () => { - removeHighlighs(); - }; - - const handleGenerate = () => { - generateAndDownload(perception); - }; - - const handlePerceptionChange = (value) => { - setPerceptionOutput(value); - if (sliderTimer) clearTimeout(sliderTimer); - sliderTimer = setTimeout(() => { - onChangePerception(value); - }, 300); - }; - - const getPredictedElements = () => { - return predictedElements && allowRemoveElements ? predictedElements.length : 0; - }; - - const handleReportProblem = () => { - reportProblem(predictedElements); - }; - - return ( - - - - - - - - - - - - - - -
{status}
-
{pageElements || 0} found on page.
-
{getPredictedElements()} predicted.
-
{availableForGeneration.length} available for generation.
-
{xpathStatus}
- {unreachableNodes && unreachableNodes.length ? ( - - ) : null} - {unactualPrediction ? ( - - ) : null} -
- -
- ); -}; - -const AutoFindWrapper = injectSheet(styles)(AutoFind); -export default AutoFindWrapper; diff --git a/src/js/blocks/autoFind/autoFindProvider/AutoFindProvider.jsx b/src/js/blocks/autoFind/autoFindProvider/AutoFindProvider.jsx index 959c115..a101e4c 100644 --- a/src/js/blocks/autoFind/autoFindProvider/AutoFindProvider.jsx +++ b/src/js/blocks/autoFind/autoFindProvider/AutoFindProvider.jsx @@ -1,5 +1,5 @@ /* eslint-disable indent */ -import _ from "lodash"; +import _, { sortBy } from "lodash"; import React, { useState, useEffect } from "react"; import { inject, observer } from "mobx-react"; import { useContext } from "react"; @@ -9,12 +9,9 @@ import { runDocumentListeners, generatePageObject, requestGenerationData, -} from "./pageDataHandlers"; -import { reportProblemPopup } from "./contentScripts/reportProblemPopup/reportProblemPopup"; -import { JDIclasses, getJdiClassName } from "./generationClassesMap"; -import { connector, sendMessage } from "./connector"; - -/* global chrome */ +} from "./../utils/pageDataHandlers"; +import { JDIclasses, getJdiClassName } from "./../utils/generationClassesMap"; +import { connector, sendMessage } from "../utils/connector"; export const autoFindStatus = { noStatus: "", @@ -22,7 +19,7 @@ export const autoFindStatus = { success: "Successful!", removed: "Removed", error: "An error occured", - blocked: "Script is blocked. Close all popups" + blocked: "Script is blocked. Close all popups", }; export const xpathGenerationStatus = { @@ -43,15 +40,13 @@ const AutoFindProvider = inject("mainModel")( const [perception, setPerception] = useState(0.5); const [unreachableNodes, setUnreachableNodes] = useState([]); const [availableForGeneration, setAvailableForGeneration] = useState([]); - const [xpathStatus, setXpathStatus] = useState( - xpathGenerationStatus.noStatus - ); + const [xpathStatus, setXpathStatus] = useState(xpathGenerationStatus.noStatus); const [unactualPrediction, setUnactualPrediction] = useState(false); const [xpathConfig, setXpathConfig] = useState({ - "maximum_generation_time": 10, - "allow_indexes_at_the_beginning": false, - "allow_indexes_in_the_middle": false, - "allow_indexes_at_the_end": true + maximum_generation_time: 10, + allow_indexes_at_the_beginning: false, + allow_indexes_in_the_middle: false, + allow_indexes_at_the_end: true, }); connector.onerror = () => { @@ -123,13 +118,6 @@ const AutoFindProvider = inject("mainModel")( }); }; - const reportProblem = (predictedElements) => { - chrome.storage.sync.set( - { predictedElements }, - connector.attachContentScript(reportProblemPopup) - ); - }; - const updateElements = ([predicted, page]) => { const rounded = predicted.map((el) => ({ ...el, @@ -168,7 +156,12 @@ const AutoFindProvider = inject("mainModel")( const element = predictedElements.find((e) => e.element_id === id); sendMessage.elementData({ element, - types: Object.keys(JDIclasses).map(getJdiClassName), + types: sortBy( + Object.keys(JDIclasses).map((label) => { + return { label, jdi: getJdiClassName(label) }; + }), + ["jdi"] + ), }); }; @@ -198,15 +191,12 @@ const AutoFindProvider = inject("mainModel")( !e.skipGeneration && !e.hidden && !unreachableNodes.includes(e.element_id) - ).value() + ) + .value() ); }; - highlightElements( - predictedElements, - onHighlighted, - perception - ); + highlightElements(predictedElements, onHighlighted, perception); } }, [predictedElements, perception]); @@ -218,16 +208,14 @@ const AutoFindProvider = inject("mainModel")( useEffect(() => { if (!availableForGeneration) return; - const noXpath = availableForGeneration.filter( - (element) => !element.xpath - ); + const noXpath = availableForGeneration.filter((element) => !element.xpath); if (!noXpath.length) return; setXpathStatus(xpathGenerationStatus.started); requestGenerationData(noXpath, xpathConfig, ({ generationData, unreachableNodes }) => { setAvailableForGeneration( _.chain(availableForGeneration) .map((el) => _.chain(generationData).find({ element_id: el.element_id }).merge(el).value()) - .differenceBy(unreachableNodes, 'element_id') + .differenceBy(unreachableNodes, "element_id") .value() ); setUnreachableNodes(unreachableNodes); @@ -259,16 +247,11 @@ const AutoFindProvider = inject("mainModel")( removeHighlighs, generateAndDownload, onChangePerception, - reportProblem, setXpathConfig, }, ]; - return ( - - {children} - - ); + return {children}; }) ); diff --git a/src/js/blocks/autoFind/autoFindProvider/contentScripts/reportProblemPopup/reportProblemPopup.css b/src/js/blocks/autoFind/autoFindProvider/contentScripts/reportProblemPopup/reportProblemPopup.css deleted file mode 100644 index 29999ef..0000000 --- a/src/js/blocks/autoFind/autoFindProvider/contentScripts/reportProblemPopup/reportProblemPopup.css +++ /dev/null @@ -1,26 +0,0 @@ -.jdn-report-problem-popup__background { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 6000; - height: 100%; - background-color: #00000073; -} -.jdn-report-problem-popup__modal { - padding: 16px 24px; - max-width: 500px; - margin: 200px auto; - position: relative; - display: block; - width: 500px; - background-color: #fff; - border: 1px solid rgba(0,0,0,.2); - border-radius: .3rem; -} - -.jdn-report-problem-popup__button { - margin: 0 15px 0 0; - padding: 5px 10px; -} \ No newline at end of file diff --git a/src/js/blocks/autoFind/autoFindProvider/contentScripts/reportProblemPopup/reportProblemPopup.js b/src/js/blocks/autoFind/autoFindProvider/contentScripts/reportProblemPopup/reportProblemPopup.js deleted file mode 100644 index ba97fbc..0000000 --- a/src/js/blocks/autoFind/autoFindProvider/contentScripts/reportProblemPopup/reportProblemPopup.js +++ /dev/null @@ -1,106 +0,0 @@ -export const reportProblemPopup = () => { - - function removePopup() { - backgroundModal.remove(); - modal.remove(); - } - - function mailTo() { - let mailToLink = document.createElement("a"); - mailToLink.target = "_blank"; - mailToLink.href = `mailto:JDI-support+JDN@epam.com?subject=Some%20elements%20were%20not%20identified%20on%20page%3A%20${window.location.href}&body=Hi%2C%0D%0ASome%20elements%20were%20not%20identified%20on%20the%20page%2C%20please%20have%20a%20look.%0D%0A%3CPlease%20save%20provided%20archive%20to%20disk%20and%20attach%20it%20to%20this%20email%3E%0D%0A%3CPROVIDE%20ADDITIONAL%20DETAILS%20IF%20NEEDED%3E`; - mailToLink.click(); - } - - function saveImage(frame) { - let imageLink = document.createElement('a'); - imageLink.href = frame; - imageLink.download = 'screenshot.jpg'; - imageLink.click(); - } - - saveJson = (content) => { - let a = document.createElement("a"); - let file = new Blob([content], {type: 'text/plain'}); - a.href = URL.createObjectURL(file); - a.download = 'json.txt'; - a.click(); - } - - const backgroundModal = document.createElement('div'); - backgroundModal.classList.add('jdn-report-problem-popup__background'); - - const modal = document.createElement('div'); - modal.classList.add('jdn-report-problem-popup__modal'); - - const title = document.createElement('h4'); - title.innerText = 'Report Problem'; - - const descriptionText = document.createElement('p'); - descriptionText.innerHTML = ` - To find the real problem, we need to get the txt-file (json.txt) and a screenshot of the site with the identified elements on it (screenshot.jpg).

- - To take a screenshot and get the json file, you need:
- - press the OK button in this window
- - select the 'Chrome tab' tab in the newly appeared window
- - select the ${document.title}
- - click the 'Share' button

- - After that, send a letter in which you describe the problem and attach the downloaded files. - `; - - const buttonOk = document.createElement('button'); - buttonOk.classList.add('jdn-report-problem-popup__button'); - buttonOk.innerText = 'Ok'; - - buttonOk.addEventListener('click', () => { - - removePopup(); - - const capture = async () => { - const canvas = document.createElement("canvas"); - const context = canvas.getContext("2d"); - const video = document.createElement("video"); - - video.width = window.outerWidth; - video.height = window.outerHeight; - - canvas.width = window.outerWidth; - canvas.height = window.outerHeight; - - const captureStream = await navigator.mediaDevices.getDisplayMedia(); - video.srcObject = captureStream; - - video.onloadedmetadata = () => { - video.play(); - context.drawImage(video, 0, 0, window.outerWidth, window.outerHeight); - const frame = canvas.toDataURL("image/png"); - captureStream.getTracks().forEach(track => track.stop()); - - chrome.storage.sync.get(["predictedElements"], ({predictedElements}) => { - saveJson(JSON.stringify(predictedElements)); - saveImage(frame); - mailTo(); - }); - } - }; - - capture(); - }); - - const buttonCancel = document.createElement('button'); - buttonCancel.classList.add('jdn-report-problem-popup__button'); - buttonCancel.innerText = 'Cancel'; - - buttonCancel.addEventListener('click', () => removePopup()); - - modal.append(title); - modal.append(descriptionText); - modal.append(buttonOk); - modal.append(buttonCancel); - - backgroundModal.append(modal); - - document.body.append(backgroundModal); - -}; \ No newline at end of file diff --git a/src/js/blocks/autoFind/components/ControlBar.jsx b/src/js/blocks/autoFind/components/ControlBar.jsx new file mode 100644 index 0000000..2161e5b --- /dev/null +++ b/src/js/blocks/autoFind/components/ControlBar.jsx @@ -0,0 +1,58 @@ +import { Divider, Space } from "antd"; +import React, { useState, useEffect } from "react"; +import { useAutoFind } from "../autoFindProvider/AutoFindProvider"; +import { reportProblem } from "../utils/pageDataHandlers"; + +export const ControlBar = () => { + const [backendVer, setBackendVer] = useState(""); + const [pluginVer, setPluginVer] = useState(""); + const [{ predictedElements, allowRemoveElements }] = useAutoFind(); + + useEffect(() => { + const fetchData = async () => { + const result = await fetch("http:localhost:5000/build", { + method: "GET", + }); + const r = await result.json(); + setBackendVer(r); + }; + + fetchData(); + + const manifest = chrome.runtime.getManifest(); + setPluginVer(manifest.version); + }, []); + + const handleReportProblem = () => { + reportProblem(predictedElements); + }; + + return ( + +
+

JDN

+
+ } + > + version {pluginVer} + backend {backendVer} + +
+
+ + + + Readme + + + Upgrade + + +
+ ); +}; diff --git a/src/js/blocks/autoFind/components/GenerationButtons.jsx b/src/js/blocks/autoFind/components/GenerationButtons.jsx new file mode 100644 index 0000000..2a1ba0e --- /dev/null +++ b/src/js/blocks/autoFind/components/GenerationButtons.jsx @@ -0,0 +1,40 @@ +import Icon, { SearchOutlined } from "@ant-design/icons"; +import { Button, Space } from "antd"; +import React from "react"; +import { autoFindStatus, useAutoFind, xpathGenerationStatus } from "../autoFindProvider/AutoFindProvider"; + +// import "./GenerationButtons.less"; +import ClearAllSvg from "../../../../icons/clear-all.svg"; +import DownloadSvg from "../../../../icons/download.svg"; +import { Content } from "antd/lib/layout/layout"; + +export const GenerationButtons = () => { + const [ + { status, allowIdentifyElements, allowRemoveElements, xpathStatus }, + { identifyElements, removeHighlighs, generateAndDownload }, + ] = useAutoFind(); + + return ( + + + + + + + + ); +}; diff --git a/src/js/blocks/autoFind/components/PerceptionTreshold.jsx b/src/js/blocks/autoFind/components/PerceptionTreshold.jsx new file mode 100644 index 0000000..582ea7a --- /dev/null +++ b/src/js/blocks/autoFind/components/PerceptionTreshold.jsx @@ -0,0 +1,50 @@ +import React from "react"; +import Text from "antd/lib/typography/Text"; +import { Col, Row, Slider, Tooltip } from "antd"; +import { useAutoFind } from "../autoFindProvider/AutoFindProvider"; +import { useState } from "react"; +import { Content } from "antd/lib/layout/layout"; +import Icon from "@ant-design/icons"; + +import QuestionFilled from "../../../../icons/question-filled.svg"; + +let sliderTimer; +export const PerceptionTreshold = () => { + const [{ perception }, { onChangePerception }] = useAutoFind(); + const [perceptionOutput, setPerceptionOutput] = useState(0.5); + + const handlePerceptionChange = (value) => { + setPerceptionOutput(value); + if (sliderTimer) clearTimeout(sliderTimer); + sliderTimer = setTimeout(() => { + onChangePerception(value); + }, 300); + }; + + return ( + + + Perception treshold: {perception} + + + + + + + 0.0 + + + + + + 1.0 + + + + ); +}; diff --git a/src/js/blocks/autoFind/components/Result.jsx b/src/js/blocks/autoFind/components/Result.jsx new file mode 100644 index 0000000..cf94ccb --- /dev/null +++ b/src/js/blocks/autoFind/components/Result.jsx @@ -0,0 +1,65 @@ +import { Space } from "antd"; +import { Content } from "antd/lib/layout/layout"; +import Text from "antd/lib/typography/Text"; +import React from "react"; +import { autoFindStatus, useAutoFind } from "../autoFindProvider/AutoFindProvider"; + +const hideStatus = [autoFindStatus.loading, autoFindStatus.removed]; + +export const Result = () => { + const [ + { + status, + predictedElements, + pageElements, + allowRemoveElements, + unreachableNodes, + availableForGeneration, + xpathStatus, + unactualPrediction, + }, + ] = useAutoFind(); + + const getPredictedElements = () => { + return predictedElements && allowRemoveElements ? predictedElements.length : 0; + }; + + const renderStatus = () => { + if (hideStatus.includes(status)) return null; + if (unactualPrediction) { + return ( + + Prediction is not actual anymore. Please, remove highlight and re-run identification. + + ); + } else if (unreachableNodes && unreachableNodes.length) { + return {`${unreachableNodes.length} controls are unreachable due to DOM updates.`}; + } else { + return {status}; + } + }; + + return ( + + ); +}; diff --git a/src/js/blocks/autoFind/xPathSettings/XPathSettings.jsx b/src/js/blocks/autoFind/components/XPathSettings.jsx similarity index 99% rename from src/js/blocks/autoFind/xPathSettings/XPathSettings.jsx rename to src/js/blocks/autoFind/components/XPathSettings.jsx index b396261..de01a9c 100644 --- a/src/js/blocks/autoFind/xPathSettings/XPathSettings.jsx +++ b/src/js/blocks/autoFind/components/XPathSettings.jsx @@ -1,10 +1,11 @@ import React from "react"; -import { useAutoFind } from "../autoFindProvider/AutoFindProvider"; import { Collapse, InputNumber } from "antd"; import CollapsePanel from "antd/lib/collapse/CollapsePanel"; import Checkbox from "antd/lib/checkbox/Checkbox"; +import { useAutoFind } from "../autoFindProvider/AutoFindProvider"; + export const XPathSettings = () => { const [{ xpathConfig }, { setXpathConfig }] = useAutoFind(); diff --git a/src/js/blocks/autoFind/components/autoFind.less b/src/js/blocks/autoFind/components/autoFind.less new file mode 100644 index 0000000..9ed5f2e --- /dev/null +++ b/src/js/blocks/autoFind/components/autoFind.less @@ -0,0 +1,172 @@ +@primary-color: #1582d8; +@primary-active-color: #0f73c1; +@disabled-color: #b2b5c2; + +.jdn__autofind { + min-width: 694px; + overflow-x: auto; + background-color: #f7faff; + + .ant-btn, + .ant-btn:focus, + .ant-btn:active { + height: 36px; + font-size: 14px; + font-weight: 700; + border: 1px solid @primary-color; + color: @primary-color; + background: transparent; + + .anticon { + vertical-align: baseline; + } + } + + .ant-btn:hover { + color: @primary-active-color; + border: 1px solid @primary-active-color; + background: transparent; + } + + .ant-btn-primary { + color: #fff; + background: @primary-color; + } + + .ant-btn-primary:hover { + color: #fff; + background-color: @primary-active-color; + } + + .ant-btn-primary[disabled], + .ant-btn-primary[disabled]:hover, + .ant-btn-primary[disabled]:focus, + .ant-btn-primary[disabled]:active { + background: @disabled-color; + border-color: @disabled-color; + } + + .ant-btn.ant-btn-loading::before { + display: none; + } + + .ant-space-vertical { + width: 100%; + } + + .ant-space-align-center { + align-items: flex-start; + } + + .ant-layout-content { + padding: 0 16px; + } + + .ant-typography-success { + color: @primary-color !important; + } + + .ant-typography-warning { + color: #d8a115; + } + + .ant-typography-danger { + color: #d82c15; + } + + .jdn { + /* + COMMON CLASSES + */ + &__hidden { + height: 0; + overflow: hidden; + } + + /* + HEADER + */ + &__header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px 30px; + background-color: #000; + } + + &__header-title { + flex-grow: 0.8; + font-size: 13px; + line-height: 1.3; + } + + &__header-text { + margin: 0; + padding: 0; + font-size: 13px; + color: #fff; + } + + &__header-version { + color: #fff; + } + + &__header-link { + font-size: 12px; + font-weight: 700; + color: #fff; + } + + &__content { + margin: 16px 0; + } + + &__divider { + margin: 16px 0; + background-color: #000; + opacity: 0.2; + } + + &__perception-treshold { + font-size: 13px; + line-height: 17.71px; + } + + /* + SLIDER + */ + &__slider { + display: flex; + + &__perception-min { + text-align: left; + } + + &__perception-max { + text-align: right; + } + } + + /* + RESULTS + */ + + &__result-status { + min-height: 25px; + font-size: 18px; + font-weight: 700; + color: @primary-color; + } + &__result-count { + display: block; + font-size: 36px; + } + + /* + URL LIST + */ + &__urls-list { + margin: 0 0 0 10px; + } + } +} diff --git a/src/js/blocks/autoFind/components/autoFind/AutoFind.jsx b/src/js/blocks/autoFind/components/autoFind/AutoFind.jsx new file mode 100644 index 0000000..e32431a --- /dev/null +++ b/src/js/blocks/autoFind/components/autoFind/AutoFind.jsx @@ -0,0 +1,35 @@ +import React from "react"; + +import "./slider.less"; +import "./../autoFind.less"; + +import Layout, { Header } from "antd/lib/layout/layout"; +import { GenerationButtons } from "../GenerationButtons"; +import { PerceptionTreshold } from "../PerceptionTreshold"; +import { Result } from "../Result"; +import { Divider, Space } from "antd"; +import { ControlBar } from "../ControlBar"; +import { XPathSettings } from "../XPathSettings"; + +const AutoFind = () => { + return ( + +
+ +
+ } + className="jdn__content" + > + + + + + +
+ ); +}; + +export default AutoFind; diff --git a/src/js/blocks/autoFind/components/autoFind/slider.less b/src/js/blocks/autoFind/components/autoFind/slider.less new file mode 100644 index 0000000..66f0148 --- /dev/null +++ b/src/js/blocks/autoFind/components/autoFind/slider.less @@ -0,0 +1,37 @@ +@import "../autoFind.less"; + +.ant-slider-track { + height: 2px; + background-color: #C4C4C4; +} + +.ant-slider-rail { + height: 2px; + background-color: @primary-color; +} + +.ant-slider { + padding: 0; +} + +.ant-slider:hover { + .ant-slider-track { + background-color: #C4C4C4; + } + .ant-slider-rail { + background-color: @primary-active-color; + } +} + +.ant-slider-handle { + width: 15px; + height: 15px; + margin: -6px 0 0; + border: none; + background-color: @primary-color; + box-shadow: none; +} + +.ant-slider-handle:focus { + background-color: @primary-active-color; +} diff --git a/src/js/blocks/autoFind/autoFindProvider/contentScripts/contextMenu/contextmenu.js b/src/js/blocks/autoFind/contentScripts/contextMenu/contextmenu.js similarity index 73% rename from src/js/blocks/autoFind/autoFindProvider/contentScripts/contextMenu/contextmenu.js rename to src/js/blocks/autoFind/contentScripts/contextMenu/contextmenu.js index a021cec..1c6bac1 100644 --- a/src/js/blocks/autoFind/autoFindProvider/contentScripts/contextMenu/contextmenu.js +++ b/src/js/blocks/autoFind/contentScripts/contextMenu/contextmenu.js @@ -5,8 +5,8 @@ export const runContextMenu = () => { */ function ContextMenu(menu, options) { - var self = this; - var num = ContextMenu.count++; + const self = this; + const num = ContextMenu.count++; this.menu = menu; this.contextTarget = null; @@ -31,7 +31,7 @@ export const runContextMenu = () => { window.addEventListener("resize", onResize); - this.setOptions = function (_options) { + this.setOptions = function(_options) { if (typeof _options === "object") { options = _options; } else { @@ -39,7 +39,7 @@ export const runContextMenu = () => { } }; - this.changeOption = function (option, value) { + this.changeOption = function(option, value) { if (typeof option === "string") { if (typeof value !== "undefined") { options[option] = value; @@ -51,71 +51,74 @@ export const runContextMenu = () => { } }; - this.getOptions = function () { + this.getOptions = function() { return options; }; - this.reload = function () { + this.reload = function() { if (document.getElementById("cm_" + num) == null) { - var cnt = document.createElement("div"); + const cnt = document.createElement("div"); cnt.className = "cm_container"; cnt.id = "cm_" + num; document.body.appendChild(cnt); } - var container = document.getElementById("cm_" + num); + const container = document.getElementById("cm_" + num); container.innerHTML = ""; container.appendChild(renderLevel(menu)); }; function renderLevel(level) { - var ul_outer = document.createElement("ul"); + const ul_outer = document.createElement("ul"); - level.forEach(function (item) { - var li = document.createElement("li"); + level.forEach(function(item) { + const li = document.createElement("li"); li.menu = self; if (typeof item.type === "undefined") { - var icon_span = document.createElement("span"); + const icon_span = document.createElement("span"); icon_span.className = "cm_icon_span"; if (ContextUtil.getProperty(item, "icon", "") != "") { icon_span.innerHTML = ContextUtil.getProperty(item, "icon", ""); } else { icon_span.innerHTML = ContextUtil.getProperty( - options, - "default_icon", - "" + options, + "default_icon", + "" ); } - var text_span = document.createElement("span"); + const text_span = document.createElement("span"); text_span.className = "cm_text"; if (ContextUtil.getProperty(item, "text", "") != "") { text_span.innerHTML = ContextUtil.getProperty(item, "text", ""); } else { text_span.innerHTML = ContextUtil.getProperty( - options, - "default_text", - "item" + options, + "default_text", + "item" ); } - var sub_span = document.createElement("span"); + const sub_span = document.createElement("span"); sub_span.className = "cm_sub_span"; if (typeof item.sub !== "undefined") { if (ContextUtil.getProperty(options, "sub_icon", "") != "") { sub_span.innerHTML = ContextUtil.getProperty( - options, - "sub_icon", - "" + options, + "sub_icon", + "" ); } else { - sub_span.innerHTML = "›"; + sub_span.innerHTML = ` + + + `; } } @@ -127,9 +130,9 @@ export const runContextMenu = () => { li.setAttribute("disabled", ""); } else { if (typeof item.events === "object") { - var keys = Object.keys(item.events); + const keys = Object.keys(item.events); - for (var i = 0; i < keys.length; i++) { + for (let i = 0; i < keys.length; i++) { li.addEventListener(keys[i], item.events[keys[i]]); } } @@ -150,27 +153,27 @@ export const runContextMenu = () => { return ul_outer; } - this.display = function (e, target) { + this.display = function(e, target) { if (typeof target !== "undefined") { self.contextTarget = target; } else { self.contextTarget = e.target; } - var menu = document.getElementById("cm_" + num); + const menu = document.getElementById("cm_" + num); - var clickCoords = { x: e.clientX, y: e.clientY }; - var clickCoordsX = clickCoords.x; - var clickCoordsY = clickCoords.y; + const clickCoords = { x: e.clientX, y: e.clientY }; + const clickCoordsX = clickCoords.x; + const clickCoordsY = clickCoords.y; - var menuWidth = menu.offsetWidth + 4; - var menuHeight = menu.offsetHeight + 4; + const menuWidth = menu.offsetWidth + 4; + const menuHeight = menu.offsetHeight + 4; - var windowWidth = window.innerWidth; - var windowHeight = window.innerHeight; + const windowWidth = window.innerWidth; + const windowHeight = window.innerHeight; - var mouseOffset = parseInt( - ContextUtil.getProperty(options, "mouse_offset", 2) + const mouseOffset = parseInt( + ContextUtil.getProperty(options, "mouse_offset", 2) ); if (windowWidth - clickCoordsX < menuWidth) { @@ -187,7 +190,7 @@ export const runContextMenu = () => { menu.style.position = "absolute"; - var sizes = ContextUtil.getSizes(menu); + const sizes = ContextUtil.getSizes(menu); if (windowWidth - clickCoordsX < sizes.width) { menu.classList.add("cm_border_right"); @@ -210,12 +213,12 @@ export const runContextMenu = () => { e.preventDefault(); }; - this.hide = function () { + this.hide = function() { document.getElementById("cm_" + num).classList.remove("display"); window.removeEventListener("click", documentClick); }; - this.remove = function () { + this.remove = function() { document.getElementById("cm_" + num).remove(); window.removeEventListener("click", documentClick); window.removeEventListener("resize", onResize); @@ -232,7 +235,7 @@ export const runContextMenu = () => { ContextMenu.DIVIDER = "cm_divider"; const ContextUtil = { - getProperty: function (options, opt, def) { + getProperty: function(options, opt, def) { if (typeof options[opt] !== "undefined") { return options[opt]; } else { @@ -240,11 +243,11 @@ export const runContextMenu = () => { } }, - getSizes: function (obj) { - var lis = obj.getElementsByTagName("li"); + getSizes: function(obj) { + const lis = obj.getElementsByTagName("li"); - var width_def = 0; - var height_def = 0; + let width_def = 0; + let height_def = 0; for (var i = 0; i < lis.length; i++) { var li = lis[i]; @@ -258,15 +261,15 @@ export const runContextMenu = () => { } } - var width = width_def; - var height = height_def; + let width = width_def; + let height = height_def; for (var i = 0; i < lis.length; i++) { var li = lis[i]; - var ul = li.getElementsByTagName("ul"); + const ul = li.getElementsByTagName("ul"); if (typeof ul[0] !== "undefined") { - var ul_size = ContextUtil.getSizes(ul[0]); + const ul_size = ContextUtil.getSizes(ul[0]); if (width_def + ul_size.width > width) { width = width_def + ul_size.width; @@ -286,7 +289,6 @@ export const runContextMenu = () => { }; const changeElementNameModal = (element_id, jdi_class_name) => { - // MODAL const modal = document.createElement('div'); modal.classList.add("jdn-change-element-name-modal"); @@ -302,7 +304,7 @@ export const runContextMenu = () => { modalTitle.innerText = "Change Name"; modalTitle.classList.add('jdn-change-element-name-modal__title'); modal.append(modalTitle); - + // MODAL FORM const form = document.createElement('form'); @@ -322,7 +324,7 @@ export const runContextMenu = () => { modal.append(form); document.body.appendChild(modal); formInput.focus(); - + // ACTION: CHANGE ELEMENT NAME formButton.addEventListener("click", (event) => { event.preventDefault(); @@ -347,18 +349,23 @@ export const runContextMenu = () => { // <----- - /*global chrome*/ + /* global chrome */ let elementMenu; let contextEvent; let predictedElement; const menuItems = ( - { jdi_class_name, jdi_custom_class_name = null, element_id, skipGeneration }, - types + { jdi_class_name, jdi_custom_class_name = null, element_id, skipGeneration }, + types ) => [ { - text: `Change name: ${jdi_custom_class_name ? jdi_custom_class_name : jdi_class_name} `, + text: `Change name: ${jdi_custom_class_name ? jdi_custom_class_name : jdi_class_name} + + + + + `, events: { click: () => changeElementNameModal(element_id, jdi_class_name), }, @@ -390,7 +397,7 @@ export const runContextMenu = () => { }, }, { - text: "Remove", + text: `Remove`, events: { click: () => chrome.runtime.sendMessage({ @@ -402,20 +409,24 @@ export const runContextMenu = () => { ]; const typesMenu = (types) => { - return types.map((type) => { - return { - text: type, - icon: - type === predictedElement.predicted_label ? "" : "", - events: { - click: () => - chrome.runtime.sendMessage({ - message: "CHANGE_TYPE", - param: { id: predictedElement.element_id, newType: type }, - }), - }, - }; - }); + return types + .map((type) => { + return { + text: type.jdi, + icon: + type.label === predictedElement.predicted_label ? ` + + + ` : "", + events: { + click: () => + chrome.runtime.sendMessage({ + message: "CHANGE_TYPE", + param: { id: predictedElement.element_id, newType: type.jdi }, + }), + }, + }; + }); }; const contextMenuListener = (event) => { @@ -441,7 +452,6 @@ export const runContextMenu = () => { const messageHandler = ({ message, param }, sender, sendResponse) => { if (message === "ELEMENT_DATA") { - // element can be undefined in case of outdated event listener (after refresh, for example). better solution is to kill listener, but I can't implement it for now if (!param.element) return; predictedElement = param.element; types = param.types; diff --git a/src/js/blocks/autoFind/autoFindProvider/contentScripts/generationData.js b/src/js/blocks/autoFind/contentScripts/generationData.js similarity index 100% rename from src/js/blocks/autoFind/autoFindProvider/contentScripts/generationData.js rename to src/js/blocks/autoFind/contentScripts/generationData.js diff --git a/src/js/blocks/autoFind/autoFindProvider/contentScripts/highlight.css b/src/js/blocks/autoFind/contentScripts/highlight.css similarity index 87% rename from src/js/blocks/autoFind/autoFindProvider/contentScripts/highlight.css rename to src/js/blocks/autoFind/contentScripts/highlight.css index d0de398..7b5290f 100644 --- a/src/js/blocks/autoFind/autoFindProvider/contentScripts/highlight.css +++ b/src/js/blocks/autoFind/contentScripts/highlight.css @@ -33,7 +33,7 @@ .cm_container li { padding: 10px 17px; - padding-right: 1.7em; + padding-right: 3em; cursor: pointer; white-space: nowrap; } @@ -43,19 +43,17 @@ color: #1582D8; } -.cm_container li:last-child { +.cm_container li .cm_container_warning-option { color: #D82C15; } .cm_container li .cm_icon_span { - width: 1.5em; - height: 1.2em; - vertical-align: bottom; + right: 12px; + top: 50%; + transform: translateY(-50%); + right: 6px; + position: absolute; display: inline-block; - border-right: 1px solid #aaa; - margin-right: 5px; - padding-right: 5px; - text-align: center; } .cm_container li .cm_text_icon { @@ -64,6 +62,11 @@ transform: scale(-1, 1); } +.cm_container li .cm_text .cm_text_edit_icon { + position: absolute; + right: -2.8em; +} + .cm_container li .cm_sub_span { width: 1em; display: inline-block; @@ -81,6 +84,23 @@ opacity: 0; transition: opacity 0.2s; visibility: hidden; + max-height: 190px; + overflow-y: auto; +} + +.cm_container li > ul::-webkit-scrollbar { + width: 4px; +} +.cm_container li > ul::-webkit-scrollbar-thumb { + background-color: rgba(102, 104, 118, 1); + border-radius: 10px; +} +.cm_container li > ul::-webkit-scrollbar-thumb:active { + background-color: rgb(157, 157, 163); + border-radius: 10px; +} +.cm_container li > ul::-webkit-scrollbar-track { + background-color: #000; } .cm_container li:hover > ul { diff --git a/src/js/blocks/autoFind/autoFindProvider/contentScripts/highlight.js b/src/js/blocks/autoFind/contentScripts/highlight.js similarity index 100% rename from src/js/blocks/autoFind/autoFindProvider/contentScripts/highlight.js rename to src/js/blocks/autoFind/contentScripts/highlight.js diff --git a/src/js/blocks/autoFind/autoFindProvider/contentScripts/highlightOrder.js b/src/js/blocks/autoFind/contentScripts/highlightOrder.js similarity index 100% rename from src/js/blocks/autoFind/autoFindProvider/contentScripts/highlightOrder.js rename to src/js/blocks/autoFind/contentScripts/highlightOrder.js diff --git a/src/js/blocks/autoFind/autoFindProvider/contentScripts/pageData.js b/src/js/blocks/autoFind/contentScripts/pageData.js similarity index 100% rename from src/js/blocks/autoFind/autoFindProvider/contentScripts/pageData.js rename to src/js/blocks/autoFind/contentScripts/pageData.js diff --git a/src/js/blocks/autoFind/contentScripts/reportProblemPopup/reportProblemPopup.css b/src/js/blocks/autoFind/contentScripts/reportProblemPopup/reportProblemPopup.css new file mode 100644 index 0000000..a7b7627 --- /dev/null +++ b/src/js/blocks/autoFind/contentScripts/reportProblemPopup/reportProblemPopup.css @@ -0,0 +1,42 @@ +.jdn-report-problem-popup__background { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 6000; + height: 100%; + background-color: #00000073; +} +.jdn-report-problem-popup__modal { + top: 50%; + transform: translateY(-50%); + margin: auto; + padding: 16px 24px; + width: 270px; + position: relative; + display: block; + color: #fff; + background-color: #000; + border: 1px solid rgba(0, 0, 0, 0.2); +} + +.jdn-report-problem-popup__button { + padding: 5px 10px; + background-color: #000; + border: none; +} + +.jdn-report-problem-popup__button--ok { + background-color: #1582d8; +} + +.jdn-report-problem-popup__button--ok:hover { + background-color: #0f73c1; +} + +.jdn-report-problem-popup__button-container { + display: flex; + justify-content: flex-end; + gap: 16px; +} diff --git a/src/js/blocks/autoFind/contentScripts/reportProblemPopup/reportProblemPopup.js b/src/js/blocks/autoFind/contentScripts/reportProblemPopup/reportProblemPopup.js new file mode 100644 index 0000000..12f03dd --- /dev/null +++ b/src/js/blocks/autoFind/contentScripts/reportProblemPopup/reportProblemPopup.js @@ -0,0 +1,108 @@ +export const reportProblemPopup = () => { + function removePopup() { + backgroundModal.remove(); + modal.remove(); + } + + function mailTo() { + const mailToLink = document.createElement("a"); + mailToLink.target = "_blank"; + mailToLink.href = `mailto:JDI-support+JDN@epam.com?subject=Some%20elements%20were%20not%20identified%20on%20page%3A%20${window.location.href}&body=Hi%2C%0D%0ASome%20elements%20were%20not%20identified%20on%20the%20page%2C%20please%20have%20a%20look.%0D%0A%3CPlease%20save%20provided%20archive%20to%20disk%20and%20attach%20it%20to%20this%20email%3E%0D%0A%3CPROVIDE%20ADDITIONAL%20DETAILS%20IF%20NEEDED%3E`; + mailToLink.click(); + } + + function saveImage(frame) { + const imageLink = document.createElement("a"); + imageLink.href = frame; + imageLink.download = "screenshot.jpg"; + imageLink.click(); + } + + saveJson = (content) => { + const a = document.createElement("a"); + const file = new Blob([content], { type: "text/plain" }); + a.href = URL.createObjectURL(file); + a.download = "json.txt"; + a.click(); + }; + + const backgroundModal = document.createElement("div"); + backgroundModal.classList.add("jdn-report-problem-popup__background"); + + const modal = document.createElement("div"); + modal.classList.add("jdn-report-problem-popup__modal"); + + const title = document.createElement("h4"); + title.innerText = "Report Problem"; + + const descriptionText = document.createElement("p"); + descriptionText.innerHTML = ` + To find the real problem, we need to get the txt-file (json.txt) and a screenshot of the site with the identified elements on it (screenshot.jpg).

+ + To take a screenshot and get the json file, you need:
+ - press the OK button in this window
+ - select the 'Chrome tab' tab in the newly appeared window
+ - select the ${document.title}
+ - click the 'Share' button

+ + After that, send a letter in which you describe the problem and attach the downloaded files. + `; + + const buttonOk = document.createElement("button"); + buttonOk.classList.add("jdn-report-problem-popup__button"); + buttonOk.classList.add("jdn-report-problem-popup__button--ok"); + buttonOk.innerText = "Ok"; + + buttonOk.addEventListener("click", () => { + removePopup(); + + const capture = async () => { + const canvas = document.createElement("canvas"); + const context = canvas.getContext("2d"); + const video = document.createElement("video"); + + video.width = window.outerWidth; + video.height = window.outerHeight; + + canvas.width = window.outerWidth; + canvas.height = window.outerHeight; + + const captureStream = await navigator.mediaDevices.getDisplayMedia(); + video.srcObject = captureStream; + + video.onloadedmetadata = () => { + video.play(); + context.drawImage(video, 0, 0, window.outerWidth, window.outerHeight); + const frame = canvas.toDataURL("image/png"); + captureStream.getTracks().forEach((track) => track.stop()); + + chrome.storage.sync.get(["predictedElements"], ({ predictedElements }) => { + saveJson(JSON.stringify(predictedElements)); + saveImage(frame); + mailTo(); + }); + }; + }; + + capture(); + }); + + const buttonCancel = document.createElement("button"); + buttonCancel.classList.add("jdn-report-problem-popup__button"); + buttonCancel.innerText = "Cancel"; + + buttonCancel.addEventListener("click", () => removePopup()); + + const buttonContainer = document.createElement("div"); + buttonContainer.classList.add("jdn-report-problem-popup__button-container"); + buttonContainer.append(buttonCancel); + buttonContainer.append(buttonOk); + + modal.append(title); + modal.append(descriptionText); + modal.append(buttonContainer); + + backgroundModal.append(modal); + + document.body.append(backgroundModal); +}; diff --git a/src/js/blocks/autoFind/autoFindProvider/contentScripts/urlListener.js b/src/js/blocks/autoFind/contentScripts/urlListener.js similarity index 100% rename from src/js/blocks/autoFind/autoFindProvider/contentScripts/urlListener.js rename to src/js/blocks/autoFind/contentScripts/urlListener.js diff --git a/src/js/blocks/autoFind/slider.less b/src/js/blocks/autoFind/slider.less deleted file mode 100644 index 0cf5660..0000000 --- a/src/js/blocks/autoFind/slider.less +++ /dev/null @@ -1,16 +0,0 @@ -.ant-slider-track { - background-color: #f5f5f5; -} - -.ant-slider-rail { - background-color: #76d7f5; -} - -.ant-slider:hover { - .ant-slider-track { - background-color: #e1e1e1; - } - .ant-slider-rail { - background-color: #4abee8; - } -} diff --git a/src/js/blocks/autoFind/styles.jsx b/src/js/blocks/autoFind/styles.jsx deleted file mode 100644 index 50d2a03..0000000 --- a/src/js/blocks/autoFind/styles.jsx +++ /dev/null @@ -1,11 +0,0 @@ -export const styles = { - content: { - backgroundColor: '#fff', - }, - footer: { - position: 'fixed', - right: 0, - bottom: 0, - backgroundColor: '#fff', - } -} \ No newline at end of file diff --git a/src/js/blocks/autoFind/tests/autoFind.test.js b/src/js/blocks/autoFind/tests/autoFind.test.js index 7d7c6ba..fde6965 100644 --- a/src/js/blocks/autoFind/tests/autoFind.test.js +++ b/src/js/blocks/autoFind/tests/autoFind.test.js @@ -1,9 +1,10 @@ import React from "react"; import { AutoFindProvider, autoFindStatus, useAutoFind } from "../autoFindProvider/AutoFindProvider"; -import { connector } from "../autoFindProvider/connector"; + import { act } from "react-dom/test-utils"; import { render, unmountComponentAtNode } from "react-dom"; -import * as pageDataHandlers from "../autoFindProvider/pageDataHandlers"; +import * as pageDataHandlers from "../utils/pageDataHandlers"; +import { connector } from "../utils/connector"; import { abovePerception, generationData, @@ -74,12 +75,6 @@ describe("AutoFind Identify functionality", () => { container = null; }); - test("changes status to Loading", () => { - const button = container.querySelector("#identify"); - button.dispatchEvent(new MouseEvent("click", { bubbles: true })); - expect(container.querySelector("#status").textContent).toBe(autoFindStatus.loading); - }); - test("predicted elements are received, updated properly and passed to component", async () => { const button = container.querySelector("#identify"); await act(async () => { diff --git a/src/js/blocks/autoFind/autoFindProvider/connector.js b/src/js/blocks/autoFind/utils/connector.js similarity index 100% rename from src/js/blocks/autoFind/autoFindProvider/connector.js rename to src/js/blocks/autoFind/utils/connector.js diff --git a/src/js/blocks/autoFind/autoFindProvider/generationClassesMap.js b/src/js/blocks/autoFind/utils/generationClassesMap.js similarity index 95% rename from src/js/blocks/autoFind/autoFindProvider/generationClassesMap.js rename to src/js/blocks/autoFind/utils/generationClassesMap.js index c5d970c..a7009cc 100644 --- a/src/js/blocks/autoFind/autoFindProvider/generationClassesMap.js +++ b/src/js/blocks/autoFind/utils/generationClassesMap.js @@ -17,7 +17,7 @@ export const JDIclasses = { progressbar: defaultClass, datetimeselector: defaultClass, numberselector: defaultClass, - dropdownselector: "Dropdown", + dropdownselector: "Dropdown selector", checklist: "CheckList", radiobutton: "RadioButtons", table: "Table", diff --git a/src/js/blocks/autoFind/autoFindProvider/pageDataHandlers.js b/src/js/blocks/autoFind/utils/pageDataHandlers.js similarity index 85% rename from src/js/blocks/autoFind/autoFindProvider/pageDataHandlers.js rename to src/js/blocks/autoFind/utils/pageDataHandlers.js index 077a351..5a14e06 100644 --- a/src/js/blocks/autoFind/autoFindProvider/pageDataHandlers.js +++ b/src/js/blocks/autoFind/utils/pageDataHandlers.js @@ -1,12 +1,13 @@ import { connector, sendMessage } from "./connector"; -import { runContextMenu } from "./contentScripts/contextMenu/contextmenu"; -import { getGenerationAttributes } from "./contentScripts/generationData"; -import { highlightOnPage } from "./contentScripts/highlight"; -import { getPageData } from "./contentScripts/pageData"; -import { urlListener } from "./contentScripts/urlListener"; +import { runContextMenu } from "./../contentScripts/contextMenu/contextmenu"; +import { getGenerationAttributes } from "./../contentScripts/generationData"; +import { highlightOnPage } from "./../contentScripts/highlight"; +import { getPageData } from "./../contentScripts/pageData"; +import { urlListener } from "./../contentScripts/urlListener"; import { getPage, predictedToConvert } from "./pageObject"; -import { autoFindStatus } from "./AutoFindProvider"; -import { highlightOrder } from "./contentScripts/highlightOrder"; +import { autoFindStatus } from "./../autoFindProvider/AutoFindProvider"; +import { highlightOrder } from "./../contentScripts/highlightOrder"; +import { reportProblemPopup } from "../contentScripts/reportProblemPopup/reportProblemPopup"; /* global chrome*/ let documentListenersStarted; @@ -61,7 +62,6 @@ export const getElements = (callback, setStatus) => { connector.updateMessageListener((payload) => { if (payload.message === "START_COLLECT_DATA") { clearTimeout(pageAccessTimeout); - setStatus(autoFindStatus.loading); overlayID = payload.param.overlayID; } }); @@ -166,3 +166,7 @@ export const generatePageObject = (elements, mainModel) => { mainModel.conversionModel.downloadPageCode(page, ".java"); }); }; + +export const reportProblem = (predictedElements) => { + chrome.storage.sync.set({ predictedElements }, connector.attachContentScript(reportProblemPopup)); +}; diff --git a/src/js/blocks/autoFind/autoFindProvider/pageObject.js b/src/js/blocks/autoFind/utils/pageObject.js similarity index 100% rename from src/js/blocks/autoFind/autoFindProvider/pageObject.js rename to src/js/blocks/autoFind/utils/pageObject.js diff --git a/src/js/blocks/generate/GenerateBlock.jsx b/src/js/blocks/generate/GenerateBlock.jsx index 1f92462..f350824 100644 --- a/src/js/blocks/generate/GenerateBlock.jsx +++ b/src/js/blocks/generate/GenerateBlock.jsx @@ -117,7 +117,7 @@ export default class GenerateBlock extends React.Component { Export URLs -