diff --git a/src/features/PageTemplate.tsx b/src/features/PageTemplate.tsx new file mode 100644 index 00000000..69f87ff3 --- /dev/null +++ b/src/features/PageTemplate.tsx @@ -0,0 +1,25 @@ +import React from "react"; +import SentryWrapper from "./SentryWrapper"; +import { useGetUsersMeQuery } from "src/services/tryberApi"; +import TagManager from "react-gtm-module"; + +export const PageTemplate = ({ children }: { children: React.ReactNode }) => { + const { error, isLoading } = useGetUsersMeQuery({}); + if (isLoading) { + return
Loading...
; + } + TagManager.dataLayer({ + dataLayer: { + event: "ApiLoaded", + }, + }); + if (error) { + if ("status" in error && error.status === 403) { + return
You are not logged in. Please log in to continue.
; + } else { + if ("message" in error) alert(error.message); + } + return null; + } + return {children}; +}; diff --git a/src/features/SentryWrapper.tsx b/src/features/SentryWrapper.tsx new file mode 100644 index 00000000..ec701f37 --- /dev/null +++ b/src/features/SentryWrapper.tsx @@ -0,0 +1,16 @@ +import { useGetUsersMeQuery } from "src/services/tryberApi"; +import * as Sentry from "@sentry/react"; + +const SentryWrapper = ({ children }: { children: React.ReactNode }) => { + const { data: user } = useGetUsersMeQuery({}); + + Sentry.setUser({ + role: user?.role ?? "unknown", + wp_user_id: user?.wp_user_id ?? 0, + tester_id: user?.id ?? 0, + }); + + return <>{children}; +}; + +export default SentryWrapper; diff --git a/src/pages/BugsList/index.tsx b/src/pages/BugsList/index.tsx index 360285f5..80c75d96 100644 --- a/src/pages/BugsList/index.tsx +++ b/src/pages/BugsList/index.tsx @@ -12,6 +12,7 @@ import Filters from "./Filters"; import TagsFilter from "./Filters/TagsFilter"; import Stats from "./Stats"; import Table from "./Table"; +import { PageTemplate } from "src/features/PageTemplate"; const FluidContainer = styled.div` max-width: 90%; @@ -28,41 +29,43 @@ const BugsList = () => { const [isStatsModalOpen, setIsStatsModalOpen] = useState(false); return ( - - Bug List - CP-{id} - - - {"<"} To Campaign List - - - {"<"} To Dashboard - - setIsStatsModalOpen(true)}> - Stats - - -
- -
-
- -
- - - - - - - + + + Bug List - CP-{id} + + + {"<"} To Campaign List + + + {"<"} To Dashboard + + setIsStatsModalOpen(true)}> + Stats + + +
+ +
+
+ +
+ + +
+ + + + + ); }; diff --git a/src/pages/Jotform/index.tsx b/src/pages/Jotform/index.tsx index 37c9d169..1f0aea4b 100644 --- a/src/pages/Jotform/index.tsx +++ b/src/pages/Jotform/index.tsx @@ -5,6 +5,7 @@ import { CufListCard } from "./CufListCard"; import { useAppSelector } from "src/store"; import { JotformSuccessCard } from "src/pages/Jotform/JotformSuccessCard"; import { OpsUserContainer } from "src/features/AuthorizedOnlyContainer"; +import { PageTemplate } from "src/features/PageTemplate"; const StickyContainer = styled.div` @media (min-width: ${(p) => p.theme.grid.breakpoints.lg}) { @@ -16,28 +17,30 @@ const StickyContainer = styled.div` export default function Jotform() { const { url } = useAppSelector((state) => state.jotform); return ( - - - {url ? ( - <> - - - - - - ) : ( - <> - - - - - - - - - - )} - - + + + + {url ? ( + <> + + + + + + ) : ( + <> + + + + + + + + + + )} + + + ); } diff --git a/src/pages/Payments/index.tsx b/src/pages/Payments/index.tsx index 74187d2c..c29d2179 100644 --- a/src/pages/Payments/index.tsx +++ b/src/pages/Payments/index.tsx @@ -15,6 +15,7 @@ import { MakePaymentModal } from "src/pages/Payments/MakePaymentModal"; import { PendingReqFilters } from "src/pages/Payments/pending/PendingReqFilters"; import { RetryPaymentModal } from "./RetryPaymentModal"; import { DeletePaymentModal } from "./DeletePaymentModal"; +import { PageTemplate } from "src/features/PageTemplate"; const StyledTabs = styled.div` .cell { @@ -31,44 +32,46 @@ export default function AdminPayments() { ); return ( - - - - - - - - - - Pending} + + + + + + + + + + - - - - Failed - {total > 0 ? ` (${total})` : null} - - } - > - - - - - - - - {activeTab === "pending" && } - - - + Pending} + > + + + + Failed + {total > 0 ? ` (${total})` : null} + + } + > + + + + + + + + {activeTab === "pending" && } + + + + ); } diff --git a/src/pages/Popups/Create/index.tsx b/src/pages/Popups/Create/index.tsx index e361733b..119ed5ec 100644 --- a/src/pages/Popups/Create/index.tsx +++ b/src/pages/Popups/Create/index.tsx @@ -8,58 +8,61 @@ import { import { useHistory } from "react-router-dom"; import createPopup from "src/api/createPopup"; import Editor from "src/features/Editor"; +import { PageTemplate } from "src/features/PageTemplate"; const usePopupsCreate = () => { let history = useHistory(); return ( -
- { - if (!data.title) { - alert("Please specify a title for the popup"); - return; - } - createPopup(data) - .then((data) => { - alert("Saved!"); - history.push(`/backoffice/${data.id}`); - }) - .catch((e) => { - alert("Error!"); - console.error(e.message); - }); - }} - > - +
+ { + if (!data.title) { + alert("Please specify a title for the popup"); + return; + } + createPopup(data) + .then((data) => { + alert("Saved!"); + history.push(`/backoffice/${data.id}`); + }) + .catch((e) => { + alert("Error!"); + console.error(e.message); + }); + }} > - - -
+
+
+ ); }; diff --git a/src/pages/Popups/List/index.tsx b/src/pages/Popups/List/index.tsx index 9a104a79..ca5fb582 100644 --- a/src/pages/Popups/List/index.tsx +++ b/src/pages/Popups/List/index.tsx @@ -8,6 +8,7 @@ import { import { useEffect, useState } from "react"; import { Link } from "react-router-dom"; import getAllPopups from "src/api/getAllPopups"; +import { PageTemplate } from "src/features/PageTemplate"; const usePopupsList = () => { const [data, setData] = useState([]); @@ -54,29 +55,31 @@ const usePopupsList = () => { }, ]; return ( -
-
- - - - - - - - -
- - - + +
+
+ + + + + + + + +
+ + + + - + ); }; diff --git a/src/pages/Popups/Update/index.tsx b/src/pages/Popups/Update/index.tsx index 239f3ee2..53729610 100644 --- a/src/pages/Popups/Update/index.tsx +++ b/src/pages/Popups/Update/index.tsx @@ -4,6 +4,7 @@ import { useHistory, useParams } from "react-router-dom"; import getOnePopup from "src/api/getOnePopup"; import updatePopup from "src/api/updatePopup"; import Editor from "src/features/Editor"; +import { PageTemplate } from "src/features/PageTemplate"; const usePopupsUpdate = () => { let { id } = useParams<{ id: string }>(); @@ -40,30 +41,32 @@ const usePopupsUpdate = () => { return

Loading

; } return ( -
- { - if (!data.title) { - alert("Please specify a title for the popup"); - return; - } - updatePopup(data, id) - .then((data) => { - alert("Saved!"); - }) - .catch((e) => { - alert("Error!"); - console.error(e.message); - }); - }} - data={{ - title, - targets, - once, - }} - json={json} - /> -
+ +
+ { + if (!data.title) { + alert("Please specify a title for the popup"); + return; + } + updatePopup(data, id) + .then((data) => { + alert("Saved!"); + }) + .catch((e) => { + alert("Error!"); + console.error(e.message); + }); + }} + data={{ + title, + targets, + once, + }} + json={json} + /> +
+
); }; diff --git a/src/pages/Prospect/index.tsx b/src/pages/Prospect/index.tsx index 88e8d646..66f96ed6 100644 --- a/src/pages/Prospect/index.tsx +++ b/src/pages/Prospect/index.tsx @@ -5,6 +5,7 @@ import { useContainerDimensions } from "src/hooks/useContainerDimensions"; import { useGetCampaignsByCampaignQuery } from "src/services/tryberApi"; import styled from "styled-components"; import Table from "./Table"; +import { PageTemplate } from "src/features/PageTemplate"; const FluidContainer = styled.div` max-width: 90%; @@ -23,35 +24,37 @@ const Prospect = () => { campaign: id, }); return ( - - Prospect - - {"<"} Go to old Prospect - - - Pay Assistants - - - Go to Add Booty - - - CP{id} {data?.title ? `- ${data.title}` : ""} - -
- + + + Prospect + + {"<"} Go to old Prospect + + + Pay Assistants + + + Go to Add Booty + + + CP{id} {data?.title ? `- ${data.title}` : ""} + +
+ + ); }; diff --git a/src/pages/UxDashboard/index.tsx b/src/pages/UxDashboard/index.tsx index 1efffa3d..d88e44d6 100644 --- a/src/pages/UxDashboard/index.tsx +++ b/src/pages/UxDashboard/index.tsx @@ -18,6 +18,7 @@ import FormProvider from "./UxForm/FormProvider"; import ResultsPage from "./ResultsPage"; import { useAppSelector } from "src/store"; import styled from "styled-components"; +import { PageTemplate } from "src/features/PageTemplate"; const StyledSteps = styled(Steps)` .step-status-icon { @@ -58,46 +59,48 @@ const UxDashboard = () => { if (permissions?.appq_campaign === true) { // todo: discuss about appq_video_dashboard permission (change tests) return ( - - - - Tool di compilazione - - - - - - - - - 0} - title={"Preview"} - /> - 1} - title={"Publish"} - /> - - {currentStep === 0 && } - {currentStep === 1 && } - {currentStep === 2 && } - - - - + + + + + Tool di compilazione + + + + + + + + + 0} + title={"Preview"} + /> + 1} + title={"Publish"} + /> + + {currentStep === 0 && } + {currentStep === 1 && } + {currentStep === 2 && } + + + + + ); } diff --git a/src/pages/agreements/list/index.tsx b/src/pages/agreements/list/index.tsx index 4deefa8e..ef55c0e1 100644 --- a/src/pages/agreements/list/index.tsx +++ b/src/pages/agreements/list/index.tsx @@ -13,6 +13,7 @@ import { Agreements } from "./Agreements"; import { ReactNode } from "react"; import { useGetAgreementsQuery } from "src/services/tryberApi"; import ErrorUnauthorized from "src/features/ErrorUnauthorized/ErrorUnauthorized"; +import { PageTemplate } from "src/features/PageTemplate"; const FluidContainer = styled.div` padding: 2rem; @@ -54,39 +55,41 @@ const AgreementsListPageContent = ({ children }: { children: ReactNode }) => { }; const AgreementsListPage = () => ( - - - - Agreements List - - + Add New - - - - -
+ + + + Agreements List + - -
- - - - - -
-
-
-
+ + Add New + + + + +
+ +
+ + + + + +
+
+ + + ); export default AgreementsListPage; diff --git a/src/pages/agreements/new/index.tsx b/src/pages/agreements/new/index.tsx index 03b23bfb..adaa1bee 100644 --- a/src/pages/agreements/new/index.tsx +++ b/src/pages/agreements/new/index.tsx @@ -9,6 +9,7 @@ import { FormikHelpers } from "formik"; import { useHistory } from "react-router-dom"; import siteWideMessageStore from "src/redux/siteWideMessages"; import { formatDateforAPI } from "../utils"; +import { PageTemplate } from "src/features/PageTemplate"; const NewAgreementPage = () => { const [newAgreement] = usePostAgreementsMutation(); @@ -43,16 +44,18 @@ const NewAgreementPage = () => { return; }; return ( - - - New Agreement - - - - - + + + + New Agreement + + + + + + ); }; diff --git a/src/pages/agreements/view-edit/index.tsx b/src/pages/agreements/view-edit/index.tsx index 2ca60185..41c935e4 100644 --- a/src/pages/agreements/view-edit/index.tsx +++ b/src/pages/agreements/view-edit/index.tsx @@ -12,6 +12,7 @@ import { import { useHistory, useParams } from "react-router-dom"; import siteWideMessageStore from "src/redux/siteWideMessages"; import { formatDateforAPI } from "../utils"; +import { PageTemplate } from "src/features/PageTemplate"; const EditAgreementPage = () => { const { id } = useParams<{ id: string }>(); @@ -60,17 +61,19 @@ const EditAgreementPage = () => { }; return ( - - - Edit Agreement: {currentData?.title} - - - - - + + + + Edit Agreement: {currentData?.title} + + + + + + ); }; diff --git a/src/pages/campaigns/preselectionForm/index.tsx b/src/pages/campaigns/preselectionForm/index.tsx index 9a5bb749..aae23036 100644 --- a/src/pages/campaigns/preselectionForm/index.tsx +++ b/src/pages/campaigns/preselectionForm/index.tsx @@ -30,6 +30,7 @@ import { v4 as uuidv4 } from "uuid"; import { getCustomQuestionTypeLabel } from "./getCustomQuestionTypeLabel"; import { CopyLinkButton } from "src/pages/campaigns/preselectionFormList/CopyLinkButton"; import { getProfileTypeLabel } from "./getProfileTypeLabel"; +import { PageTemplate } from "src/features/PageTemplate"; const PreselectionForm = () => { const history = useHistory(); @@ -160,164 +161,166 @@ const PreselectionForm = () => { } }, [savedData]); return ( - - - {id ? "Edit Preselection Form" : "New Preselection Form"} - - - { - const fieldsToSend = values.fields.map((field) => { - const newField: PreselectionFormQuestion & { id?: number } = { - ...(field.questionId ? { id: field.questionId } : {}), - question: field.question, - short_name: field.shortTitle, - type: field.type, - }; - if (field.options) { - // @ts-ignore - newField.options = field.options; - } - if ("selectedOptions" in field && field.selectedOptions) { - if (field.selectedOptions[0]?.value === "-1") { - getAllOptions(field.cufId).then((res) => { - newField.options = res; - }); - } else { - newField.options = field.selectedOptions.map((o) => - parseInt(o.value) - ); - } - } - return newField; - }); - if (id) { - setSaveEdit(true); - const args: PutCampaignsFormsByFormIdApiArg = { - formId: id, - body: { - name: values.formTitle, + + + + {id ? "Edit Preselection Form" : "New Preselection Form"} + + + { + const fieldsToSend = values.fields.map((field) => { + const newField: PreselectionFormQuestion & { id?: number } = { + ...(field.questionId ? { id: field.questionId } : {}), + question: field.question, + short_name: field.shortTitle, + type: field.type, + }; + if (field.options) { // @ts-ignore - fields: fieldsToSend, - }, - }; - if (values.campaign?.value) - args.body.campaign = parseInt(values.campaign?.value); - const res = await editForm(args); - if (res && "data" in res) { - history.push( - `/backoffice/campaigns/preselection-forms/${res.data.id}` - ); - add({ type: "success", message: "Form saved" }); - } else { - const errorCode = - "error" in res && "data" in res.error - ? (res.error.data as { code: string }).code - : false; - switch (errorCode) { - case "CAMPAIGN_ID_ALREADY_ASSIGNED": - add({ - type: "danger", - message: "This campaign already has a form assigned", - }); - break; - case "NO_ACCESS_TO_CAMPAIGN": - add({ - type: "danger", - message: - "You can't assign a form to a campaign you don't own", - }); - break; - default: - add({ - type: "danger", - message: "There was an error", + newField.options = field.options; + } + if ("selectedOptions" in field && field.selectedOptions) { + if (field.selectedOptions[0]?.value === "-1") { + getAllOptions(field.cufId).then((res) => { + newField.options = res; }); - break; + } else { + newField.options = field.selectedOptions.map((o) => + parseInt(o.value) + ); + } + } + return newField; + }); + if (id) { + setSaveEdit(true); + const args: PutCampaignsFormsByFormIdApiArg = { + formId: id, + body: { + name: values.formTitle, + // @ts-ignore + fields: fieldsToSend, + }, + }; + if (values.campaign?.value) + args.body.campaign = parseInt(values.campaign?.value); + const res = await editForm(args); + if (res && "data" in res) { + history.push( + `/backoffice/campaigns/preselection-forms/${res.data.id}` + ); + add({ type: "success", message: "Form saved" }); + } else { + const errorCode = + "error" in res && "data" in res.error + ? (res.error.data as { code: string }).code + : false; + switch (errorCode) { + case "CAMPAIGN_ID_ALREADY_ASSIGNED": + add({ + type: "danger", + message: "This campaign already has a form assigned", + }); + break; + case "NO_ACCESS_TO_CAMPAIGN": + add({ + type: "danger", + message: + "You can't assign a form to a campaign you don't own", + }); + break; + default: + add({ + type: "danger", + message: "There was an error", + }); + break; + } } - } - } else { - const args: PostCampaignsFormsApiArg = { - body: { - name: values.formTitle, - // @ts-ignore - fields: fieldsToSend, - }, - }; - if (values.campaign?.value) - args.body.campaign = parseInt(values.campaign?.value); - const res = await createForm(args); - if (res && "data" in res) { - history.push( - `/backoffice/campaigns/preselection-forms/${res.data.id}` - ); - add({ type: "success", message: "Form saved" }); } else { - const errorCode = - "error" in res && "data" in res.error - ? (res.error.data as { code: string }).code - : false; - switch (errorCode) { - case "CAMPAIGN_ID_ALREADY_ASSIGNED": - add({ - type: "danger", - message: "This campaign already has a form assigned", - }); - break; - case "NO_ACCESS_TO_CAMPAIGN": - add({ - type: "danger", - message: - "You can't assign a form to a campaign you don't own", - }); - break; - default: - add({ - type: "danger", - message: "There was an error", - }); - break; + const args: PostCampaignsFormsApiArg = { + body: { + name: values.formTitle, + // @ts-ignore + fields: fieldsToSend, + }, + }; + if (values.campaign?.value) + args.body.campaign = parseInt(values.campaign?.value); + const res = await createForm(args); + if (res && "data" in res) { + history.push( + `/backoffice/campaigns/preselection-forms/${res.data.id}` + ); + add({ type: "success", message: "Form saved" }); + } else { + const errorCode = + "error" in res && "data" in res.error + ? (res.error.data as { code: string }).code + : false; + switch (errorCode) { + case "CAMPAIGN_ID_ALREADY_ASSIGNED": + add({ + type: "danger", + message: "This campaign already has a form assigned", + }); + break; + case "NO_ACCESS_TO_CAMPAIGN": + add({ + type: "danger", + message: + "You can't assign a form to a campaign you don't own", + }); + break; + default: + add({ + type: "danger", + message: "There was an error", + }); + break; + } } } - } - // scroll to form title - const selector = `[id="formTitle"]`; - const formTitleElement = document.querySelector( - selector - ) as HTMLElement; - formTitleElement?.scrollIntoView({ - behavior: "smooth", - block: "center", - }); - }} - > -
- - - - - - {savedData.isLoading || savedData.isFetching ? ( - ...loading - ) : savedData.error || (id && !savedData.data) ? ( - ...error retrieving form - ) : ( - - )} - - - -
-
+ // scroll to form title + const selector = `[id="formTitle"]`; + const formTitleElement = document.querySelector( + selector + ) as HTMLElement; + formTitleElement?.scrollIntoView({ + behavior: "smooth", + block: "center", + }); + }} + > +
+ + + + + + {savedData.isLoading || savedData.isFetching ? ( + ...loading + ) : savedData.error || (id && !savedData.data) ? ( + ...error retrieving form + ) : ( + + )} + + + +
+
+ ); }; diff --git a/src/pages/campaigns/preselectionFormList/index.tsx b/src/pages/campaigns/preselectionFormList/index.tsx index fa5531ce..0e95de9d 100644 --- a/src/pages/campaigns/preselectionFormList/index.tsx +++ b/src/pages/campaigns/preselectionFormList/index.tsx @@ -2,24 +2,27 @@ import { BSCol, BSGrid, Button } from "@appquality/appquality-design-system"; import { OpsUserContainer } from "../../../features/AuthorizedOnlyContainer"; import { FormTableCard } from "./formTableCard"; import { PageTitle } from "@appquality/appquality-design-system"; +import { PageTemplate } from "src/features/PageTemplate"; const PreselectionFormList = () => { return ( - - -
- Preselection Form List - -
-
- - - - - -
+ + + +
+ Preselection Form List + +
+
+ + + + + +
+
); }; diff --git a/src/pages/campaigns/selection/index.tsx b/src/pages/campaigns/selection/index.tsx index af6c93bf..1083e834 100644 --- a/src/pages/campaigns/selection/index.tsx +++ b/src/pages/campaigns/selection/index.tsx @@ -13,6 +13,7 @@ import { useParams } from "react-router-dom"; import ConfirmButton from "src/pages/campaigns/selection/confirmButton/ConfirmButton"; import ConfirmModal from "src/pages/campaigns/selection/confirmModal/ConfirmModal"; import styled from "styled-components"; +import { PageTemplate } from "src/features/PageTemplate"; const StickyToBottomContainer = styled.div` position: sticky; @@ -22,33 +23,35 @@ const StickyToBottomContainer = styled.div` const SelectionPage = () => { const { id } = useParams<{ id: string }>(); return ( -
- - - Tester selection panel - - - - - - - - - - - - - - - - - + +
+ + + Tester selection panel + + + + - - - - -
+
+ + + + + + + + + + + + + + +
+
+
+ ); }; export default SelectionPage;