From d22e3869a33f5582c2d89fdce715b8f285558eb1 Mon Sep 17 00:00:00 2001 From: KShervington Date: Sat, 4 May 2024 17:05:03 -0400 Subject: [PATCH 1/5] prep for personal windows env --- .gitignore | 1 + src/AdHere.py | 2 +- src/frontend/package.json | 4 ++-- .../src/components/ViolatingSiteTableRow.tsx | 12 +++++------- src/frontend/src/components/ViolatingSitesTable.tsx | 2 +- src/server.py | 2 +- 6 files changed, 11 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 11ae0e2..124c14b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ src/google.py src/chromedriver +src/chromedriver.exe src/violations.txt # --- Frontend diff --git a/src/AdHere.py b/src/AdHere.py index 122ec5a..2231a70 100644 --- a/src/AdHere.py +++ b/src/AdHere.py @@ -30,7 +30,7 @@ ######################################################## # Please fill this variable before running this script. # Input the user profile location of Google Chrome between the quotation marks. -USRPROFILE = '' +USRPROFILE = 'C:\\Users\\kyles\\AppData\\Local\\Google\\Chrome\\User Data' ######################################################## # Official ABP plugin, only works under headless mode diff --git a/src/frontend/package.json b/src/frontend/package.json index 7585884..fd287f5 100644 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -1,7 +1,7 @@ { "name": "frontend", "version": "0.1.0", - "proxy": "http://localhost:8080", + "proxy": "http://localhost:5000", "private": true, "dependencies": { "@types/node": "^16.18.93", @@ -41,4 +41,4 @@ "devDependencies": { "tailwindcss": "^3.4.3" } -} +} \ No newline at end of file diff --git a/src/frontend/src/components/ViolatingSiteTableRow.tsx b/src/frontend/src/components/ViolatingSiteTableRow.tsx index 984875f..ed623bf 100644 --- a/src/frontend/src/components/ViolatingSiteTableRow.tsx +++ b/src/frontend/src/components/ViolatingSiteTableRow.tsx @@ -19,7 +19,7 @@ export default function ViolatingSiteTableRow(props: RowProps) { const response = await fetch( // If 'options object' issues are encountered then delete the following line from package.json // "proxy": "http://localhost:8080", - `http://localhost:8080/find-violations?url=${encodeURIComponent(site)}`, + `http://localhost:5000/find-violations?url=${encodeURIComponent(site)}`, { method: "GET", } @@ -41,17 +41,15 @@ export default function ViolatingSiteTableRow(props: RowProps) { return (
{/* Site url */}

{props.url}

diff --git a/src/frontend/src/components/ViolatingSitesTable.tsx b/src/frontend/src/components/ViolatingSitesTable.tsx index 5cae20f..6c482c9 100644 --- a/src/frontend/src/components/ViolatingSitesTable.tsx +++ b/src/frontend/src/components/ViolatingSitesTable.tsx @@ -34,7 +34,7 @@ export default function ViolatingSitesTable() { const site = data.violatingSites[violatingSitesIndex++].reviewedSite; // Calls Flask server endpoint which returns true or false depending on whether or not the site exists await fetch( - `http://localhost:8080/url-check?url=${encodeURIComponent(site)}` + `http://localhost:5000/url-check?url=${encodeURIComponent(site)}` ) .then((response) => response.json()) .then((data) => { diff --git a/src/server.py b/src/server.py index c29f7bf..5f0a7ce 100644 --- a/src/server.py +++ b/src/server.py @@ -48,4 +48,4 @@ def get_violations(): # Port 8080 to not conflict with frontend on 3000 if __name__ == '__main__': - app.run(port=8080, debug=True) + app.run(port=5000, debug=True) From 6c99c150bda593241a8eb6a367af8b5a27caf2f8 Mon Sep 17 00:00:00 2001 From: KShervington Date: Sat, 4 May 2024 17:36:45 -0400 Subject: [PATCH 2/5] do not filter nonexistent sites by default --- src/frontend/README.md | 14 +++++-- .../src/components/ViolatingSitesTable.tsx | 40 +++++++++++-------- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/src/frontend/README.md b/src/frontend/README.md index 805300b..fb10e1c 100644 --- a/src/frontend/README.md +++ b/src/frontend/README.md @@ -18,10 +18,16 @@ The `ViolatingSitesTable.tsx` component requires an active API Key to retrieve a 8. Copy the newly created API key 9. Create a **_.env_** at **_./src/frontend/_** in your project - The file should have the following contents: - ```bash - REACT_APP_AD_EXPERIENCE_API_KEY="[API_KEY]" - ``` - > Replace `[API_KEY]` with the key you copied at step 8 + ```bash + REACT_APP_AD_EXPERIENCE_API_KEY="[API_KEY]" + ``` + > Replace `[API_KEY]` with the key you copied in the previous step + +## Controlling Site Filtering +By default, when you run the frontend, the sites that populate the main table of violating sites are the first 10 sites in the response received from Google's Ad Experience Report API.
+ +However, there is the option to filter out sites that do not exist. To do so, change the `FILTER_SITES` constant in **_.\src\frontend\src\components\ViolatingSitesTable.tsx_** from `false` to `true`. +> **NOTE**: Filtering out sites can take a long time (anywhere from a few minutes to tens of minutes, depending on network speed). This will impact the time it takes to populate the table of violating sites, both on initial page load, and every time a new list is requested. ## Documentation Reference diff --git a/src/frontend/src/components/ViolatingSitesTable.tsx b/src/frontend/src/components/ViolatingSitesTable.tsx index 6c482c9..c2b25a5 100644 --- a/src/frontend/src/components/ViolatingSitesTable.tsx +++ b/src/frontend/src/components/ViolatingSitesTable.tsx @@ -2,6 +2,7 @@ import { useEffect, useState } from "react"; import ViolatingSiteTableRow from "./ViolatingSiteTableRow"; export default function ViolatingSitesTable() { + const FILTER_SITES = false; const [loading, setLoading] = useState(false); const [violatingSites, setViolatingSites] = useState([]); @@ -32,22 +33,29 @@ export default function ViolatingSitesTable() { violatingSitesIndex < data.violatingSites.length ) { const site = data.violatingSites[violatingSitesIndex++].reviewedSite; - // Calls Flask server endpoint which returns true or false depending on whether or not the site exists - await fetch( - `http://localhost:5000/url-check?url=${encodeURIComponent(site)}` - ) - .then((response) => response.json()) - .then((data) => { - if ( - data.does_url_exist && - filteredSites.length !== numSitesToShow - ) { - filteredSites.push(site); - } - }) - .catch((error) => { - console.error("Error:", error); - }); + + if (FILTER_SITES) { + // Calls Flask server endpoint which returns true or false depending on whether or not the site exists + await fetch( + `http://localhost:5000/url-check?url=${encodeURIComponent(site)}` + ) + .then((response) => response.json()) + .then((data) => { + if ( + data.does_url_exist && + filteredSites.length !== numSitesToShow + ) { + filteredSites.push(site); + } + }) + .catch((error) => { + console.error("Error:", error); + }); + } + else { + // If we're not filtering sites, just add them to the list + filteredSites.push(site); + } } // Update state with the new sites From 2776dd40cd127d6d6004eccd134f1f1f45c92b36 Mon Sep 17 00:00:00 2001 From: KShervington Date: Sun, 5 May 2024 12:14:10 -0400 Subject: [PATCH 3/5] added component to run AdHere on custom url and fixed spacing issues --- src/frontend/README.md | 2 +- src/frontend/src/App.tsx | 2 +- .../src/components/CustomURLTableRow.tsx | 83 +++++++++++++++++++ src/frontend/src/components/FixSuggestion.tsx | 3 +- .../src/components/ViolatingSiteTableRow.tsx | 8 +- .../src/components/ViolatingSitesTable.tsx | 17 ++-- 6 files changed, 102 insertions(+), 13 deletions(-) create mode 100644 src/frontend/src/components/CustomURLTableRow.tsx diff --git a/src/frontend/README.md b/src/frontend/README.md index fb10e1c..22445a5 100644 --- a/src/frontend/README.md +++ b/src/frontend/README.md @@ -24,7 +24,7 @@ The `ViolatingSitesTable.tsx` component requires an active API Key to retrieve a > Replace `[API_KEY]` with the key you copied in the previous step ## Controlling Site Filtering -By default, when you run the frontend, the sites that populate the main table of violating sites are the first 10 sites in the response received from Google's Ad Experience Report API.
+By default, when you run the frontend, the sites that populate the main table of violating sites are the first 9 sites in the response received from Google's Ad Experience Report API.
However, there is the option to filter out sites that do not exist. To do so, change the `FILTER_SITES` constant in **_.\src\frontend\src\components\ViolatingSitesTable.tsx_** from `false` to `true`. > **NOTE**: Filtering out sites can take a long time (anywhere from a few minutes to tens of minutes, depending on network speed). This will impact the time it takes to populate the table of violating sites, both on initial page load, and every time a new list is requested. diff --git a/src/frontend/src/App.tsx b/src/frontend/src/App.tsx index 4da42a3..890fb98 100644 --- a/src/frontend/src/App.tsx +++ b/src/frontend/src/App.tsx @@ -12,7 +12,7 @@ function App(): JSX.Element {
diff --git a/src/frontend/src/components/CustomURLTableRow.tsx b/src/frontend/src/components/CustomURLTableRow.tsx new file mode 100644 index 0000000..bc0ec4a --- /dev/null +++ b/src/frontend/src/components/CustomURLTableRow.tsx @@ -0,0 +1,83 @@ +import { useState } from "react"; +import FixSuggestions from "./FixSuggestion"; + +export default function ViolatingSiteTableRow() { + const [loading, setLoading] = useState(false); // State to show/hide loading spinner + const [showViolations, setShowViolations] = useState(false); // State to show/hide violations + const [url, setUrl] = useState(""); // State to store the URL entered by the user + + // Run AdHere.py against the url in this table row + const findViolations = async (site: string) => { + try { + setLoading(true); + + // Pass url to endpoint that runs AdHere + const response = await fetch( + // If 'options object' issues are encountered then delete the following line from package.json + // "proxy": "http://localhost:8080", + `http://localhost:5000/find-violations?url=${encodeURIComponent(site)}`, + { + method: "GET", + } + ); + + // AdHere.py execution complete + if (!response.ok) { + throw new Error("Failed to fetch data"); + } else { + setShowViolations(true); // Trigger component to show violations + } + } catch (error) { + console.error("Error running AdHere on custom url ", site, " : ", error); + } finally { + setLoading(false); + } + }; + + return ( +
+ {/* Text box */} + setUrl(e.target.value.trim())}> + + + {/* Row Button */} + {/* Default: Run AdHere || Waiting on AdHere execution: circle_spin || Showing violations: Close */} + {!showViolations ? ( + loading ? ( +
+ loading spinner +
+ ) : ( + + ) + ) : ( + + )} + + {/* Render component to show violations only when AdHere completes execution */} + {showViolations && } +
+ ); +} diff --git a/src/frontend/src/components/FixSuggestion.tsx b/src/frontend/src/components/FixSuggestion.tsx index 9059f8d..02c3340 100644 --- a/src/frontend/src/components/FixSuggestion.tsx +++ b/src/frontend/src/components/FixSuggestion.tsx @@ -26,7 +26,8 @@ export default function FixSuggestions() { language="js" data-color-mode={localStorage.theme} style={{ - overflow: "scroll", + overflowY: "scroll", + overflowX: "hidden", height: "20rem", fontSize: "1rem", }} diff --git a/src/frontend/src/components/ViolatingSiteTableRow.tsx b/src/frontend/src/components/ViolatingSiteTableRow.tsx index ed623bf..56ccfd5 100644 --- a/src/frontend/src/components/ViolatingSiteTableRow.tsx +++ b/src/frontend/src/components/ViolatingSiteTableRow.tsx @@ -7,8 +7,8 @@ interface RowProps { } export default function ViolatingSiteTableRow(props: RowProps) { - const [loading, setLoading] = useState(false); - const [showViolations, setShowViolations] = useState(false); + const [loading, setLoading] = useState(false); // State to show/hide loading spinner + const [showViolations, setShowViolations] = useState(false); // State to show/hide violations // Run AdHere.py against the url in this table row const findViolations = async (site: string, index: number) => { @@ -47,8 +47,8 @@ export default function ViolatingSiteTableRow(props: RowProps) { {/* Site url */}

{props.url} diff --git a/src/frontend/src/components/ViolatingSitesTable.tsx b/src/frontend/src/components/ViolatingSitesTable.tsx index c2b25a5..3106114 100644 --- a/src/frontend/src/components/ViolatingSitesTable.tsx +++ b/src/frontend/src/components/ViolatingSitesTable.tsx @@ -1,12 +1,13 @@ import { useEffect, useState } from "react"; import ViolatingSiteTableRow from "./ViolatingSiteTableRow"; +import CustomURLTableRow from "./CustomURLTableRow"; export default function ViolatingSitesTable() { const FILTER_SITES = false; const [loading, setLoading] = useState(false); const [violatingSites, setViolatingSites] = useState([]); - const numSitesToShow = 10; + const numSitesToShow = 9; // Get list of violating sites const getNewSites = async () => { @@ -73,7 +74,7 @@ export default function ViolatingSitesTable() { }, []); return ( -

+
{/* Row plus button for getting new sites */}
) : ( - // Map over sites and display them - violatingSites.map((site, index) => ( - - )) +
+ + {// Map over sites and display them + violatingSites.map((site, index) => ( + + ))} + +
)}
); From d692634d685d3c609b545616cabf64e162049609 Mon Sep 17 00:00:00 2001 From: KShervington Date: Sun, 5 May 2024 14:37:50 -0400 Subject: [PATCH 4/5] made it easier to change the backend port used by frontend + misc --- src/frontend/README.md | 20 ++++++++++++++++++- src/frontend/package.json | 1 - src/frontend/src/App.tsx | 4 ++-- .../src/components/CustomURLTableRow.tsx | 3 ++- src/frontend/src/components/FixSuggestion.tsx | 4 +++- src/frontend/src/components/Header.tsx | 6 +++--- .../src/components/ViolatingSiteTableRow.tsx | 11 +++++----- .../src/components/ViolatingSitesTable.tsx | 3 ++- 8 files changed, 37 insertions(+), 15 deletions(-) diff --git a/src/frontend/README.md b/src/frontend/README.md index 22445a5..a620606 100644 --- a/src/frontend/README.md +++ b/src/frontend/README.md @@ -19,7 +19,7 @@ The `ViolatingSitesTable.tsx` component requires an active API Key to retrieve a 9. Create a **_.env_** at **_./src/frontend/_** in your project - The file should have the following contents: ```bash - REACT_APP_AD_EXPERIENCE_API_KEY="[API_KEY]" + REACT_APP_AD_EXPERIENCE_API_KEY=[API_KEY] ``` > Replace `[API_KEY]` with the key you copied in the previous step @@ -29,6 +29,24 @@ By default, when you run the frontend, the sites that populate the main table of However, there is the option to filter out sites that do not exist. To do so, change the `FILTER_SITES` constant in **_.\src\frontend\src\components\ViolatingSitesTable.tsx_** from `false` to `true`. > **NOTE**: Filtering out sites can take a long time (anywhere from a few minutes to tens of minutes, depending on network speed). This will impact the time it takes to populate the table of violating sites, both on initial page load, and every time a new list is requested. +## Controlling Port for the Backend +By default, port 8080 is used to run the Flask server. However, some situations may arise where you have to use a different port. The purpose of changing the port is to ensure the Flask server does not conflict with other applications/services and to ensure the frontend is using the correct port to communicate with the server. To change the port, follow these steps: +1. Change the port argument in the main function of **_./src/server.py_** + ```python + # BEFORE + if __name__ == '__main__': + app.run(port=8080, debug=True) + ``` + ```python + # AFTER + if __name__ == '__main__': + app.run(port=5000, debug=True) + ``` +2. Add a new environment variable to the **_./src/frontend/.env_** file. The variable will have your desired port number, like so: + ```bash + REACT_APP_BACKEND_PORT=5000 + ``` + ## Documentation Reference - [React](https://react.dev/) diff --git a/src/frontend/package.json b/src/frontend/package.json index fd287f5..fa3bcd9 100644 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -1,7 +1,6 @@ { "name": "frontend", "version": "0.1.0", - "proxy": "http://localhost:5000", "private": true, "dependencies": { "@types/node": "^16.18.93", diff --git a/src/frontend/src/App.tsx b/src/frontend/src/App.tsx index 890fb98..959c98a 100644 --- a/src/frontend/src/App.tsx +++ b/src/frontend/src/App.tsx @@ -6,13 +6,13 @@ function App(): JSX.Element { return (
diff --git a/src/frontend/src/components/CustomURLTableRow.tsx b/src/frontend/src/components/CustomURLTableRow.tsx index bc0ec4a..76d09e4 100644 --- a/src/frontend/src/components/CustomURLTableRow.tsx +++ b/src/frontend/src/components/CustomURLTableRow.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import FixSuggestions from "./FixSuggestion"; export default function ViolatingSiteTableRow() { + const BACKEND_PORT = process.env.REACT_APP_BACKEND_PORT || 8080; // Port where the backend server is running const [loading, setLoading] = useState(false); // State to show/hide loading spinner const [showViolations, setShowViolations] = useState(false); // State to show/hide violations const [url, setUrl] = useState(""); // State to store the URL entered by the user @@ -15,7 +16,7 @@ export default function ViolatingSiteTableRow() { const response = await fetch( // If 'options object' issues are encountered then delete the following line from package.json // "proxy": "http://localhost:8080", - `http://localhost:5000/find-violations?url=${encodeURIComponent(site)}`, + `http://localhost:${BACKEND_PORT}/find-violations?url=${encodeURIComponent(site)}`, { method: "GET", } diff --git a/src/frontend/src/components/FixSuggestion.tsx b/src/frontend/src/components/FixSuggestion.tsx index 02c3340..a0b31a8 100644 --- a/src/frontend/src/components/FixSuggestion.tsx +++ b/src/frontend/src/components/FixSuggestion.tsx @@ -3,11 +3,13 @@ import CodeEditor from "@uiw/react-textarea-code-editor"; export default function FixSuggestions() { const [fixText, setFixText] = useState(""); + const BACKEND_PORT = process.env.REACT_APP_BACKEND_PORT || 8080; // Port where the backend server is running useEffect(() => { + // Fetch the fix suggestions from the Flask server const fetchData = async () => { try { - const response = await fetch("/get-violations"); + const response = await fetch(`http://localhost:${BACKEND_PORT}/get-violations`); const data = await response.text(); setFixText(data); } catch (error) { diff --git a/src/frontend/src/components/Header.tsx b/src/frontend/src/components/Header.tsx index f6b56de..64fd3a8 100644 --- a/src/frontend/src/components/Header.tsx +++ b/src/frontend/src/components/Header.tsx @@ -6,7 +6,7 @@ export default function Header() { const [pageTheme, setPageTheme] = useState("dark"); // Element where 'dark' class will be applied - const app = document.documentElement.getElementsByTagName("div"); + const divs = document.documentElement.getElementsByTagName("div"); const iconStyling = "text-zinc-700 dark:text-white hover:text-slate-400 cursor-pointer"; @@ -26,10 +26,10 @@ export default function Header() { // toggle between dark and light theme useEffect(() => { if (pageTheme === "dark") { - app[0].classList.add("dark"); + divs[0].classList.add("dark"); localStorage.theme = "dark"; } else { - app[0].classList.remove("dark"); + divs[0].classList.remove("dark"); localStorage.theme = "light"; } // eslint-disable-next-line react-hooks/exhaustive-deps diff --git a/src/frontend/src/components/ViolatingSiteTableRow.tsx b/src/frontend/src/components/ViolatingSiteTableRow.tsx index 56ccfd5..2ca508e 100644 --- a/src/frontend/src/components/ViolatingSiteTableRow.tsx +++ b/src/frontend/src/components/ViolatingSiteTableRow.tsx @@ -7,11 +7,12 @@ interface RowProps { } export default function ViolatingSiteTableRow(props: RowProps) { + const BACKEND_PORT = process.env.REACT_APP_BACKEND_PORT || 8080; // Port where the backend server is running const [loading, setLoading] = useState(false); // State to show/hide loading spinner const [showViolations, setShowViolations] = useState(false); // State to show/hide violations // Run AdHere.py against the url in this table row - const findViolations = async (site: string, index: number) => { + const findViolations = async (site: string) => { try { setLoading(true); @@ -19,7 +20,7 @@ export default function ViolatingSiteTableRow(props: RowProps) { const response = await fetch( // If 'options object' issues are encountered then delete the following line from package.json // "proxy": "http://localhost:8080", - `http://localhost:5000/find-violations?url=${encodeURIComponent(site)}`, + `http://localhost:${BACKEND_PORT}/find-violations?url=${encodeURIComponent(site)}`, { method: "GET", } @@ -29,7 +30,7 @@ export default function ViolatingSiteTableRow(props: RowProps) { if (!response.ok) { throw new Error("Failed to fetch data"); } else { - setShowViolations(true); // Trigger component @1 + setShowViolations(true); // Trigger component to show violations } } catch (error) { console.error("Error running AdHere on ", site, ": ", error); @@ -68,7 +69,7 @@ export default function ViolatingSiteTableRow(props: RowProps) {
) : ( )} - {/* @1 Render component to show violations only when AdHere completes execution */} + {/* Render component to show violations only when AdHere completes execution */} {showViolations && }
); diff --git a/src/frontend/src/components/ViolatingSitesTable.tsx b/src/frontend/src/components/ViolatingSitesTable.tsx index 3106114..c5e4854 100644 --- a/src/frontend/src/components/ViolatingSitesTable.tsx +++ b/src/frontend/src/components/ViolatingSitesTable.tsx @@ -4,6 +4,7 @@ import CustomURLTableRow from "./CustomURLTableRow"; export default function ViolatingSitesTable() { const FILTER_SITES = false; + const BACKEND_PORT = process.env.REACT_APP_BACKEND_PORT || 8080; // Port where the backend server is running const [loading, setLoading] = useState(false); const [violatingSites, setViolatingSites] = useState([]); @@ -38,7 +39,7 @@ export default function ViolatingSitesTable() { if (FILTER_SITES) { // Calls Flask server endpoint which returns true or false depending on whether or not the site exists await fetch( - `http://localhost:5000/url-check?url=${encodeURIComponent(site)}` + `http://localhost:${BACKEND_PORT}/url-check?url=${encodeURIComponent(site)}` ) .then((response) => response.json()) .then((data) => { From 5ee752a356bcbc01c21c1ef156ef97b9d538c4cf Mon Sep 17 00:00:00 2001 From: KShervington Date: Sun, 5 May 2024 14:40:13 -0400 Subject: [PATCH 5/5] prep for PR --- src/AdHere.py | 2 +- src/server.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AdHere.py b/src/AdHere.py index 2231a70..122ec5a 100644 --- a/src/AdHere.py +++ b/src/AdHere.py @@ -30,7 +30,7 @@ ######################################################## # Please fill this variable before running this script. # Input the user profile location of Google Chrome between the quotation marks. -USRPROFILE = 'C:\\Users\\kyles\\AppData\\Local\\Google\\Chrome\\User Data' +USRPROFILE = '' ######################################################## # Official ABP plugin, only works under headless mode diff --git a/src/server.py b/src/server.py index 5f0a7ce..c29f7bf 100644 --- a/src/server.py +++ b/src/server.py @@ -48,4 +48,4 @@ def get_violations(): # Port 8080 to not conflict with frontend on 3000 if __name__ == '__main__': - app.run(port=5000, debug=True) + app.run(port=8080, debug=True)