From d42b934d049396d1d449e3881df1536920ea19e7 Mon Sep 17 00:00:00 2001 From: Kaitlyn Andres Date: Mon, 24 Feb 2025 09:00:57 -0500 Subject: [PATCH] MNTOR-3893 - Fix qa custom broker tool (#5647) * add new custom broker with the same type as real data * update type * add flag for mocked scan results * add dashboard state * lint * add feature flag blocker * fix post req * remove changes to pageloadevent * remove mocked brokers addition to util func * fixes * more fixes * fix build --- .../feature-flags/components/FlagEditor.tsx | 16 +- .../admin/feature-flags/page.tsx | 14 +- .../admin/qa-customs/onerepConfig.tsx | 271 +++++++++--------- .../dashboard/[[...slug]]/page.tsx | 23 +- .../removal-under-maintenance/page.tsx | 27 +- .../dashboard/getUserDashboardState.tsx | 21 +- .../api/v1/admin/qa-customs/onerep/route.ts | 39 +-- src/app/components/client/PageLoadEvent.tsx | 1 - src/db/tables/featureFlags.ts | 11 + src/db/tables/onerep_scans.ts | 43 ++- src/db/tables/qa_customs.ts | 47 +-- 11 files changed, 311 insertions(+), 202 deletions(-) diff --git a/src/app/(proper_react)/(redesign)/(authenticated)/admin/feature-flags/components/FlagEditor.tsx b/src/app/(proper_react)/(redesign)/(authenticated)/admin/feature-flags/components/FlagEditor.tsx index c5c5554f06a..6571fe006a0 100644 --- a/src/app/(proper_react)/(redesign)/(authenticated)/admin/feature-flags/components/FlagEditor.tsx +++ b/src/app/(proper_react)/(redesign)/(authenticated)/admin/feature-flags/components/FlagEditor.tsx @@ -16,9 +16,13 @@ import { Button } from "../../../../../../components/client/Button"; import { CreateFeatureFlagRequestBody } from "../../../../../../api/v1/admin/feature-flags/route"; import { FeatureFlagName } from "../../../../../../../db/tables/featureFlags"; -export const NewFlagEditor = (props: { flagName: FeatureFlagName }) => { +export const NewFlagEditor = (props: { + flagName: FeatureFlagName; + adminOnly: boolean; +}) => { return ( { @@ -45,9 +49,13 @@ export const NewFlagEditor = (props: { flagName: FeatureFlagName }) => { ); }; -export const ExistingFlagEditor = (props: { flag: FeatureFlagRow }) => { +export const ExistingFlagEditor = (props: { + flag: FeatureFlagRow; + adminOnly: boolean; +}) => { return ( { @@ -82,6 +90,7 @@ type Props = { isEnabled: boolean; onToggleEnable: (isEnabled: boolean) => Promise; allowList: string[]; + adminOnly: boolean; onUpdateAllowlist: (allowList: string[]) => Promise; }; const FlagEditor = (props: Props) => { @@ -114,8 +123,9 @@ const FlagEditor = (props: Props) => { variant="secondary" onPress={() => void setIsEnabled(true)} small + disabled={props.adminOnly} > - Enable for everyone + {props.adminOnly ? "Allow list only" : "Enable for everyone"} )} diff --git a/src/app/(proper_react)/(redesign)/(authenticated)/admin/feature-flags/page.tsx b/src/app/(proper_react)/(redesign)/(authenticated)/admin/feature-flags/page.tsx index 04655553254..c9eb12be7ac 100644 --- a/src/app/(proper_react)/(redesign)/(authenticated)/admin/feature-flags/page.tsx +++ b/src/app/(proper_react)/(redesign)/(authenticated)/admin/feature-flags/page.tsx @@ -8,6 +8,7 @@ import { FeatureFlagName, featureFlagNames, getAllFeatureFlags, + isFeatureFlagAdminOnly, } from "../../../../../../db/tables/featureFlags"; import { isAdmin } from "../../../../../api/utils/auth"; import { Toolbar } from "../../../../../components/client/toolbar/Toolbar"; @@ -77,11 +78,16 @@ export default async function FeatureFlagPage() {
{disabledFlags.map((flagOrFlagName) => { return typeof flagOrFlagName === "string" ? ( - + ) : ( ); })} @@ -95,7 +101,11 @@ export default async function FeatureFlagPage() { featureFlagNames.includes(flag.name as FeatureFlagName), ) .map((flag) => ( - + ))}
diff --git a/src/app/(proper_react)/(redesign)/(authenticated)/admin/qa-customs/onerepConfig.tsx b/src/app/(proper_react)/(redesign)/(authenticated)/admin/qa-customs/onerepConfig.tsx index 7a2e1dd6edc..0beac86d2dc 100644 --- a/src/app/(proper_react)/(redesign)/(authenticated)/admin/qa-customs/onerepConfig.tsx +++ b/src/app/(proper_react)/(redesign)/(authenticated)/admin/qa-customs/onerepConfig.tsx @@ -6,28 +6,8 @@ import React, { useState, useEffect } from "react"; import styles from "./ConfigPage.module.scss"; - -interface QaBrokerDataCounts { - onerep_scan_result_id?: number; - onerep_profile_id: number; - link: string; - age: number | null | undefined; - data_broker: string; - emails: number; - phones: number; - addresses: number; - relatives: number; - first_name: string; - middle_name: string | null | undefined; - last_name: string; - status: string; - manually_resolved: string; - optout_attempts?: number; - last_optout_at?: string; -} - -const endpointBase = "/api/v1/admin/qa-customs/onerep"; -const endpointToggleBase = "/api/v1/admin/qa-customs"; +import { OnerepScanResultDataBrokerRow } from "knex/types/tables"; +import { StateAbbr } from "../../../../../../utils/states"; interface Props { onerepProfileId: number; @@ -37,43 +17,49 @@ interface Props { showQaParamEnum: string; } -const OnerepConfigPage = (props: Props) => { - const profileId = props.onerepProfileId; - const [brokersFetchHappened, setBrokersFetchHappened] = - useState(false); - const [brokers, setBrokers] = useState([]); - const [errors, setErrors] = useState({ - profile_id: false, - data_broker: false, - link: false, - }); - - // Initialize a base broker template to reset form fields +const endpointBase = "/api/v1/admin/qa-customs/onerep"; +const endpointToggleBase = "/api/v1/admin/qa-customs"; - const baseBroker: QaBrokerDataCounts = { - onerep_profile_id: -1, +const OnerepConfigPage = ({ + onerepProfileId, + showApiBrokers, + showQaBrokers, + showApiParamEnum, + showQaParamEnum, +}: Props) => { + const [brokers, setBrokers] = useState([]); + const [newBroker, setNewBroker] = useState({ link: "", - age: null, + age: 30, data_broker: "", - emails: 0, - phones: 0, - addresses: 0, - relatives: 0, + emails: [], + phones: [], + addresses: [], + relatives: [], first_name: "", - middle_name: null, + middle_name: "", last_name: "", status: "new", - manually_resolved: "false", - }; + manually_resolved: false, + scan_result_status: "new", + broker_status: "removal_under_maintenance", + url: "", + id: 0, + onerep_scan_result_id: Math.floor(Math.random() * 2147483647), + onerep_scan_id: 0, + data_broker_id: 0, + created_at: new Date(), + updated_at: new Date(), + }); + const [errors, setErrors] = useState({ + profile_id: false, + data_broker: false, + link: false, + }); - // Temporary state to hold form input for a new broker - const [newBroker, setNewBroker] = useState(baseBroker); - const [showQaBrokers, setShowQaBrokers] = useState( - props.showQaBrokers, - ); - const [showApiBrokers, setShowApiBrokers] = useState( - props.showApiBrokers, - ); + const [brokersFetchHappened, setBrokersFetchHappened] = useState(false); + const [showQaBrokersState, setShowQaBrokers] = useState(showQaBrokers); + const [showApiBrokersState, setShowApiBrokers] = useState(showApiBrokers); useEffect(() => { void fetchBrokers(); @@ -84,7 +70,7 @@ const OnerepConfigPage = (props: Props) => { setBrokersFetchHappened(false); try { const response = await fetch( - `${endpointBase}?onerep_profile_id=${props.onerepProfileId}`, + `${endpointBase}?onerep_scan_result_id=${onerepProfileId}`, ); const data = await response.json(); setBrokers(data); @@ -99,77 +85,64 @@ const OnerepConfigPage = (props: Props) => { | React.ChangeEvent | React.ChangeEvent, ) => { - setNewBroker({ ...newBroker, [e.target.name]: e.target.value }); + const { name, value } = e.target; + setNewBroker({ + ...newBroker, + [name]: name === "manually_resolved" ? value === "true" : value, + }); }; - const handleAddBroker = async (event: React.FormEvent) => { - event.preventDefault(); + const handleAddBroker = async (e: React.FormEvent) => { + e.preventDefault(); let hasError = false; - if (profileId < 0) { + if (onerepProfileId < 0) { setErrors({ ...errors, profile_id: true }); hasError = true; } else { setErrors({ ...errors, profile_id: false }); } - let linkString = ""; - try { - if (newBroker.link.length !== 0) { - const urlObj = new URL(newBroker.link); - linkString = urlObj.href; - } - setErrors({ ...errors, link: false }); - } catch { - setErrors({ ...errors, link: true }); - hasError = true; - } - if (hasError) return; - newBroker.onerep_profile_id = profileId; try { - const req = fetch(endpointBase, { + const response = await fetch(endpointBase, { method: "POST", - headers: { - "Content-Type": "application/json", - }, + headers: { "Content-Type": "application/json" }, body: JSON.stringify({ ...newBroker, - link: linkString, - manually_resolved: - newBroker.manually_resolved === "false" ? false : true, + manually_resolved: newBroker.manually_resolved, }), }); - alert("Request made successfully"); - - const response = await req; - if (response.ok) { - await fetchBrokers(); // Refresh the brokers list - setNewBroker(baseBroker); // Reset form fields + alert("Request made successfully"); + await fetchBrokers(); + setNewBroker({ + ...newBroker, + link: "", + age: 30, + data_broker: "", + emails: [], + phones: [], + relatives: [], + }); } else { - console.error("Error adding broker:", await response.json()); + alert(`Error adding broker: ${await response.json()}`); } } catch (error) { - console.error("Error adding broker:", error); + alert("Error adding broker: " + error); } }; const handleDeleteBroker = async (onerep_scan_result_id: number) => { try { - const req = fetch( + const response = await fetch( `${endpointBase}?onerep_scan_result_id=${onerep_scan_result_id}`, - { - method: "DELETE", - }, + { method: "DELETE" }, ); - alert("Deletion request made successfully!"); - const response = await req; - if (response.ok) { - await fetchBrokers(); // Refresh the brokers list + await fetchBrokers(); } else { console.error("Error deleting broker:", await response.json()); } @@ -178,40 +151,48 @@ const OnerepConfigPage = (props: Props) => { } }; - const toggleQaBrokers = () => { - void fetch( - endpointToggleBase + - `?columnName=${props.showQaParamEnum}&isVisible=${!showQaBrokers}`, - { - method: "PUT", - }, + const toggleQaBrokersVisibility = () => { + fetch( + `${endpointToggleBase}?columnName=${showQaParamEnum}&isVisible=${!showQaBrokersState}`, + { method: "PUT" }, ).then((res) => { if (res.ok) { - setShowQaBrokers(!showQaBrokers); - return; + setShowQaBrokers(!showQaBrokersState); + } else { + alert("Something went wrong during the QA brokers toggle..."); } - alert("Something went wrong during the QA brokers toggle..."); }); - alert("Request made successfully!"); }; - const toggleApiBrokers = () => { - void fetch( - endpointToggleBase + - `?columnName=${props.showApiParamEnum}&isVisible=${!showApiBrokers}`, - { - method: "PUT", - }, + const toggleApiBrokersVisibility = () => { + fetch( + `${endpointToggleBase}?columnName=${showApiParamEnum}&isVisible=${!showApiBrokersState}`, + { method: "PUT" }, ).then((res) => { if (res.ok) { - setShowApiBrokers(!showApiBrokers); - return; + setShowApiBrokers(!showApiBrokersState); + } else { + alert("Something went wrong during the API brokers toggle..."); } - alert("Something went wrong during the API brokers toggle..."); }); - alert("Request made successfully!"); }; + const [numAddresses, setNumAddresses] = useState(1); + + const handleNumAddressesChange = (e: React.ChangeEvent) => { + const count = Math.max(1, parseInt(e.target.value, 10) || 1); + setNumAddresses(count); + + setNewBroker({ + ...newBroker, + addresses: Array.from({ length: count }, () => ({ + zip: "93386", + city: "Berkeley", + state: "CA" as StateAbbr, + street: "Von Meadows", + })), + }); + }; return (
@@ -221,11 +202,11 @@ const OnerepConfigPage = (props: Props) => {
- -
@@ -300,26 +281,25 @@ const OnerepConfigPage = (props: Props) => { @@ -359,11 +339,11 @@ const OnerepConfigPage = (props: Props) => { /> -