From f72cb1cfc2e84d83d8635b4c4f4f92b07fdb5830 Mon Sep 17 00:00:00 2001
From: Ian Krieger <48930920+IanKrieger@users.noreply.github.com>
Date: Tue, 29 Aug 2023 14:42:52 -0400
Subject: [PATCH 1/4] chore: generalize how ads are created (#863)
* feat: allow use of existing creatives
* fix: tests
* feat: add new creative form
* feat: add existing creative modals to campaign create
* fix: remove in sync
* chore: move away from notification specific code
* chore: prepare for non-specific creative types
* chore: be more deliberate about populating form values
* fix: pick another field
* fix: better convert fragments
* fix: reduce changes
* fix: merge conflict
* fix: remove changes around edit
* fix: make sure edit knows they will lose changes
* fix: dont prop-drill loading
* fix: return component
* fix: bring back externalId
* fix: keep a copy of the existing ad set creatives
* fix: move creatives into one form backing object
* fix: edit values
* fix: working index means no id necessary
* fix: add tests and adjust padding
---
src/components/Box/BoxContainer.tsx | 21 +-
src/components/Campaigns/Status.tsx | 5 +-
.../Creatives/CreateCreativeButton.tsx | 67 +++
.../Creatives/CreativeSpecificFields.tsx | 13 +
.../Creatives/CreativeSpecificPreview.tsx | 65 +++
.../Creatives}/NotificationPreview.tsx | 21 +-
.../Creatives/NotificationSelect.tsx | 111 +++++
.../Creatives/SelectCreativeHeader.tsx | 47 ++
src/components/Navigation/Navbar.tsx | 1 -
.../Navigation/NewCampaignButton.tsx | 31 ++
src/graphql/ad-set.generated.tsx | 124 +++++
src/graphql/campaign.generated.tsx | 132 +++++
src/graphql/creative.generated.tsx | 259 ++++++----
src/graphql/creative.graphql | 58 ++-
src/state/context.ts | 5 +
src/user/ads/AdsExistingAd.tsx | 144 ++++++
src/user/ads/NewAd.tsx | 73 +--
src/user/ads/NotificationAd.tsx | 74 +--
src/user/hooks/useAdvertiserCreatives.ts | 40 +-
src/user/library/index.test.ts | 455 +++++++++++++++++-
src/user/library/index.ts | 172 ++++---
src/user/views/adsManager/types/index.ts | 43 +-
.../advanced/components/adSet/NewAdSet.tsx | 9 +-
.../components/adSet/fields/AdSetAds.tsx | 57 +--
.../advanced/components/form/EditCampaign.tsx | 7 +-
.../components/form/components/BaseForm.tsx | 43 +-
.../form/components/PaymentButton.tsx | 9 +-
.../advanced/components/review/Review.tsx | 4 +-
.../components/review/components/AdReview.tsx | 29 --
.../review/components/AdSetReview.tsx | 12 +-
src/validation/CampaignSchema.tsx | 41 +-
src/validation/CreativeSchema.test.ts | 65 +++
src/validation/CreativeSchema.tsx | 48 ++
src/validation/regex.ts | 4 +
34 files changed, 1805 insertions(+), 484 deletions(-)
create mode 100644 src/components/Creatives/CreateCreativeButton.tsx
create mode 100644 src/components/Creatives/CreativeSpecificFields.tsx
create mode 100644 src/components/Creatives/CreativeSpecificPreview.tsx
rename src/{user/ads => components/Creatives}/NotificationPreview.tsx (66%)
create mode 100644 src/components/Creatives/NotificationSelect.tsx
create mode 100644 src/components/Creatives/SelectCreativeHeader.tsx
create mode 100644 src/components/Navigation/NewCampaignButton.tsx
create mode 100644 src/user/ads/AdsExistingAd.tsx
delete mode 100644 src/user/views/adsManager/views/advanced/components/review/components/AdReview.tsx
create mode 100644 src/validation/CreativeSchema.test.ts
create mode 100644 src/validation/CreativeSchema.tsx
create mode 100644 src/validation/regex.ts
diff --git a/src/components/Box/BoxContainer.tsx b/src/components/Box/BoxContainer.tsx
index 4b152a48..d03c2c29 100644
--- a/src/components/Box/BoxContainer.tsx
+++ b/src/components/Box/BoxContainer.tsx
@@ -2,16 +2,23 @@ import { PropsWithChildren, ReactNode } from "react";
import { Box, Typography } from "@mui/material";
export function BoxContainer(
- props: { header?: ReactNode } & PropsWithChildren,
+ props: { useTypography?: boolean; header?: ReactNode } & PropsWithChildren,
) {
+ let header;
+ if (props.header) {
+ header = props.useTypography ? (
+
+ {props.header}
+
+ ) : (
+ props.header
+ );
+ }
+
return (
- {props.header && (
-
- {props.header}
-
- )}
-
+ {header}
+
{props.children}
diff --git a/src/components/Campaigns/Status.tsx b/src/components/Campaigns/Status.tsx
index c8dd1065..337a4892 100644
--- a/src/components/Campaigns/Status.tsx
+++ b/src/components/Campaigns/Status.tsx
@@ -7,11 +7,11 @@ interface Props {
state: string;
start?: string;
end?: string;
+ opaque?: boolean;
}
-export const Status = ({ state, start, end }: Props) => {
+export const Status = ({ state, start, end, opaque }: Props) => {
let color = calcColorForState(state);
-
let label = _.startCase(state);
if (start) {
@@ -36,6 +36,7 @@ export const Status = ({ state, start, end }: Props) => {
sx={{
backgroundColor: color,
fontSize: "0.7rem",
+ opacity: opaque === false ? "0.3" : 1,
}}
/>
diff --git a/src/components/Creatives/CreateCreativeButton.tsx b/src/components/Creatives/CreateCreativeButton.tsx
new file mode 100644
index 00000000..79e59561
--- /dev/null
+++ b/src/components/Creatives/CreateCreativeButton.tsx
@@ -0,0 +1,67 @@
+import SaveIcon from "@mui/icons-material/Save";
+import {
+ CampaignForm,
+ Creative,
+ initialCreative,
+} from "user/views/adsManager/types";
+import _ from "lodash";
+import {
+ refetchAdvertiserCreativesQuery,
+ useCreateCreativeMutation,
+} from "graphql/creative.generated";
+import { useField, useFormikContext } from "formik";
+import { useAdvertiser } from "auth/hooks/queries/useAdvertiser";
+import { LoadingButton } from "@mui/lab";
+import { validCreativeFields } from "user/library";
+
+export function CreateCreativeButton() {
+ const { values, setFieldValue } = useFormikContext();
+ const [, , isCreating] = useField("isCreating");
+ const [, newMeta, newHelper] = useField("newCreative");
+ const { advertiser } = useAdvertiser();
+
+ const [create, { loading }] = useCreateCreativeMutation({
+ async onCompleted(data) {
+ newHelper.setValue(initialCreative);
+ newHelper.setTouched(false);
+ values.adSets.forEach((adSet, idx) => {
+ void setFieldValue(`adSets.${idx}.creatives`, [
+ ...adSet.creatives,
+ validCreativeFields(data.createCreative, advertiser.id),
+ ]);
+ });
+ isCreating.setValue(false);
+ },
+ refetchQueries: [
+ {
+ ...refetchAdvertiserCreativesQuery({ advertiserId: advertiser.id }),
+ },
+ ],
+ });
+
+ return (
+ }
+ onClick={(e) => {
+ e.preventDefault();
+ create({
+ variables: {
+ input: {
+ ..._.omit(newMeta.value, "included"),
+ advertiserId: advertiser.id,
+ },
+ },
+ });
+ }}
+ disabled={
+ newMeta.value?.targetUrlValid !== undefined ||
+ !_.isEmpty(newMeta.error) ||
+ loading
+ }
+ loading={loading}
+ >
+ Add
+
+ );
+}
diff --git a/src/components/Creatives/CreativeSpecificFields.tsx b/src/components/Creatives/CreativeSpecificFields.tsx
new file mode 100644
index 00000000..f6463db6
--- /dev/null
+++ b/src/components/Creatives/CreativeSpecificFields.tsx
@@ -0,0 +1,13 @@
+import { useFormikContext } from "formik";
+import { CampaignForm } from "user/views/adsManager/types";
+import { CampaignFormat } from "graphql/types";
+import { NotificationAd } from "user/ads/NotificationAd";
+
+export const CreativeSpecificFields = () => {
+ const { values } = useFormikContext();
+
+ if (values.format === CampaignFormat.PushNotification)
+ return ;
+
+ return null;
+};
diff --git a/src/components/Creatives/CreativeSpecificPreview.tsx b/src/components/Creatives/CreativeSpecificPreview.tsx
new file mode 100644
index 00000000..f094e8bd
--- /dev/null
+++ b/src/components/Creatives/CreativeSpecificPreview.tsx
@@ -0,0 +1,65 @@
+import { CampaignFormat } from "graphql/types";
+import { BoxContainer } from "components/Box/BoxContainer";
+import { NotificationPreview } from "components/Creatives/NotificationPreview";
+import { Stack, Typography } from "@mui/material";
+import { PropsWithChildren } from "react";
+import { useField } from "formik";
+import { Creative } from "user/views/adsManager/types";
+import { DisplayError } from "user/views/adsManager/views/advanced/components/review/components/ReviewField";
+
+interface Props extends PropsWithChildren {
+ options: Creative[];
+ useSimpleHeader?: boolean;
+ error?: string;
+}
+
+export function CreativeSpecificPreview({
+ options,
+ useSimpleHeader,
+ error,
+ children,
+}: Props) {
+ const [, format] = useField("format");
+
+ let component;
+ if (format.value === CampaignFormat.PushNotification) {
+ component = options.map((c, idx) => (
+
+
+
+ ));
+ }
+
+ if (error) {
+ return (
+ <>
+
+ Ads
+
+
+ >
+ );
+ }
+
+ return (
+ <>
+ {useSimpleHeader && (
+
+ Ads
+
+ )}
+
+ {component}
+ {children}
+
+ >
+ );
+}
diff --git a/src/user/ads/NotificationPreview.tsx b/src/components/Creatives/NotificationPreview.tsx
similarity index 66%
rename from src/user/ads/NotificationPreview.tsx
rename to src/components/Creatives/NotificationPreview.tsx
index 460d070e..0591dd26 100644
--- a/src/user/ads/NotificationPreview.tsx
+++ b/src/components/Creatives/NotificationPreview.tsx
@@ -1,10 +1,14 @@
-import { useField } from "formik";
-import { Creative } from "user/views/adsManager/types";
import { Box, Paper, Stack, Typography } from "@mui/material";
import logo from "../../../brave_logo_icon.png";
+import { useField } from "formik";
+import { CreativeInput } from "graphql/types";
-export function NotificationPreview(props: { title?: string; body?: string }) {
- const [, meta] = useField("newCreative");
+export function NotificationPreview(props: {
+ title?: string;
+ body?: string;
+ selected?: boolean;
+}) {
+ const [, meta, ,] = useField("newCreative");
return (
@@ -18,6 +22,7 @@ export function NotificationPreview(props: { title?: string; body?: string }) {
display: "flex",
justifyContent: "left",
flexDirection: "row",
+ opacity: props.selected === false ? 0.5 : 1,
}}
>
@@ -27,10 +32,14 @@ export function NotificationPreview(props: { title?: string; body?: string }) {
/>
- {props.title || meta.value.title || "Title Preview"}
+ {props.title ||
+ meta.value?.payloadNotification?.title ||
+ "Title Preview"}
- {props.body || meta.value.body || "Body Preview"}
+ {props.body ||
+ meta.value?.payloadNotification?.body ||
+ "Body Preview"}
diff --git a/src/components/Creatives/NotificationSelect.tsx b/src/components/Creatives/NotificationSelect.tsx
new file mode 100644
index 00000000..4b6d552d
--- /dev/null
+++ b/src/components/Creatives/NotificationSelect.tsx
@@ -0,0 +1,111 @@
+import { Box, Button, Stack, Typography } from "@mui/material";
+import { BoxContainer } from "components/Box/BoxContainer";
+import { NotificationPreview } from "components/Creatives/NotificationPreview";
+import moment from "moment";
+import { SelectCreativeHeader } from "components/Creatives/SelectCreativeHeader";
+import { CampaignForm, Creative } from "user/views/adsManager/types";
+import _ from "lodash";
+import { useContext, useState } from "react";
+import { FormContext } from "state/context";
+import { useFormikContext } from "formik";
+
+export function NotificationSelect(props: {
+ options: Creative[];
+ useSelectedAdStyle?: boolean;
+ showState?: boolean;
+ index?: number;
+ hideCreated?: boolean;
+}) {
+ const index = props.index;
+ const { values, setFieldValue } = useFormikContext();
+ const { setIsShowingAds } = useContext(FormContext);
+ const [curr, setCurr] = useState([]);
+
+ const onSelectCreative = (c: Creative, selected: boolean) => {
+ let value;
+ if (selected) {
+ value = [...curr, c];
+ } else {
+ value = _.filter(curr, (n) => n.id !== c.id);
+ }
+
+ if (index !== undefined) {
+ const foundIndex = values.adSets[index].creatives.findIndex(
+ (co) => c.id === co.id,
+ );
+ if (foundIndex !== undefined) {
+ void setFieldValue(
+ `adSets.${index}.creatives.${foundIndex}.included`,
+ selected,
+ );
+ }
+ }
+
+ setCurr(_.uniqBy(value, "id"));
+ };
+
+ const isSelected = (co: Creative) =>
+ props.useSelectedAdStyle === false || co.included;
+
+ return (
+
+ 3 ? "scroll" : "hidden" }}
+ >
+ {props.options.map((co, idx) => (
+
+ }
+ key={idx}
+ >
+
+ {!(props.hideCreated ?? false) && (
+
+ created {moment(co.createdAt).fromNow()}
+
+ )}
+
+ ))}
+
+ {props.index === undefined && (
+
+ )}
+
+ );
+}
diff --git a/src/components/Creatives/SelectCreativeHeader.tsx b/src/components/Creatives/SelectCreativeHeader.tsx
new file mode 100644
index 00000000..6dc151f9
--- /dev/null
+++ b/src/components/Creatives/SelectCreativeHeader.tsx
@@ -0,0 +1,47 @@
+import { Box, IconButton, Typography } from "@mui/material";
+import CheckBoxIcon from "@mui/icons-material/CheckBox";
+import CheckBoxOutlineBlankIcon from "@mui/icons-material/CheckBoxOutlineBlank";
+import { Creative } from "user/views/adsManager/types";
+import { Status } from "components/Campaigns/Status";
+import { useEffect, useState } from "react";
+
+export const SelectCreativeHeader = (props: {
+ creative: Creative;
+ onSelectCreative: (c: Creative, selected: boolean) => void;
+ showState?: boolean;
+}) => {
+ const [selected, setSelected] = useState();
+ useEffect(() => {
+ setSelected(props.creative.included);
+ }, [props.creative]);
+
+ return (
+
+ {
+ const s = !selected;
+ setSelected(s);
+ props.onSelectCreative(props.creative, s);
+ }}
+ sx={{ p: 0 }}
+ >
+ {selected ? (
+
+ ) : (
+
+ )}
+
+ {props.creative.name}
+
+ {props.showState !== false && (
+
+ )}
+
+ );
+};
diff --git a/src/components/Navigation/Navbar.tsx b/src/components/Navigation/Navbar.tsx
index b6172e7e..8e1bc60f 100644
--- a/src/components/Navigation/Navbar.tsx
+++ b/src/components/Navigation/Navbar.tsx
@@ -1,5 +1,4 @@
import { useRouteMatch, Link as RouterLink } from "react-router-dom";
-
import { AppBar, Button, Divider, Stack, Toolbar } from "@mui/material";
import { DraftMenu } from "components/Navigation/DraftMenu";
diff --git a/src/components/Navigation/NewCampaignButton.tsx b/src/components/Navigation/NewCampaignButton.tsx
new file mode 100644
index 00000000..93674608
--- /dev/null
+++ b/src/components/Navigation/NewCampaignButton.tsx
@@ -0,0 +1,31 @@
+import { useAdvertiser } from "auth/hooks/queries/useAdvertiser";
+import { Button } from "@mui/material";
+import moment from "moment/moment";
+import { Link as RouterLink, useRouteMatch } from "react-router-dom";
+
+export function NewCampaignButton() {
+ const { url } = useRouteMatch();
+ const { advertiser } = useAdvertiser();
+ const isCompletePage = url.includes("/user/main/complete/new");
+ const isNewCampaignPage = url.includes("/user/main/adsmanager/advanced");
+ const newUrl = `/user/main/adsmanager/advanced/new/${moment()
+ .utc()
+ .valueOf()}/settings`;
+
+ if (!advertiser.selfServiceCreate) {
+ return null;
+ }
+
+ return (
+
+ );
+}
diff --git a/src/graphql/ad-set.generated.tsx b/src/graphql/ad-set.generated.tsx
index 0adb3893..4b947c7e 100644
--- a/src/graphql/ad-set.generated.tsx
+++ b/src/graphql/ad-set.generated.tsx
@@ -42,6 +42,35 @@ export type AdSetFragment = {
title: string;
targetUrl: string;
} | null;
+ payloadNewTabPage?: {
+ logo?: {
+ imageUrl: string;
+ alt: string;
+ companyName: string;
+ destinationUrl: string;
+ } | null;
+ wallpapers?: Array<{
+ imageUrl: string;
+ focalPoint: { x: number; y: number };
+ }> | null;
+ } | null;
+ payloadInlineContent?: {
+ title: string;
+ ctaText: string;
+ imageUrl: string;
+ targetUrl: string;
+ dimensions: string;
+ description: string;
+ } | null;
+ payloadSearch?: { body: string; title: string; targetUrl: string } | null;
+ payloadSearchHomepage?: {
+ body: string;
+ imageUrl: string;
+ imageDarkModeUrl?: string | null;
+ targetUrl: string;
+ title: string;
+ ctaText: string;
+ } | null;
};
}> | null;
};
@@ -63,6 +92,35 @@ export type AdFragment = {
title: string;
targetUrl: string;
} | null;
+ payloadNewTabPage?: {
+ logo?: {
+ imageUrl: string;
+ alt: string;
+ companyName: string;
+ destinationUrl: string;
+ } | null;
+ wallpapers?: Array<{
+ imageUrl: string;
+ focalPoint: { x: number; y: number };
+ }> | null;
+ } | null;
+ payloadInlineContent?: {
+ title: string;
+ ctaText: string;
+ imageUrl: string;
+ targetUrl: string;
+ dimensions: string;
+ description: string;
+ } | null;
+ payloadSearch?: { body: string; title: string; targetUrl: string } | null;
+ payloadSearchHomepage?: {
+ body: string;
+ imageUrl: string;
+ imageDarkModeUrl?: string | null;
+ targetUrl: string;
+ title: string;
+ ctaText: string;
+ } | null;
};
};
@@ -109,6 +167,39 @@ export type CreateAdSetMutation = {
title: string;
targetUrl: string;
} | null;
+ payloadNewTabPage?: {
+ logo?: {
+ imageUrl: string;
+ alt: string;
+ companyName: string;
+ destinationUrl: string;
+ } | null;
+ wallpapers?: Array<{
+ imageUrl: string;
+ focalPoint: { x: number; y: number };
+ }> | null;
+ } | null;
+ payloadInlineContent?: {
+ title: string;
+ ctaText: string;
+ imageUrl: string;
+ targetUrl: string;
+ dimensions: string;
+ description: string;
+ } | null;
+ payloadSearch?: {
+ body: string;
+ title: string;
+ targetUrl: string;
+ } | null;
+ payloadSearchHomepage?: {
+ body: string;
+ imageUrl: string;
+ imageDarkModeUrl?: string | null;
+ targetUrl: string;
+ title: string;
+ ctaText: string;
+ } | null;
};
}> | null;
};
@@ -157,6 +248,39 @@ export type UpdateAdSetMutation = {
title: string;
targetUrl: string;
} | null;
+ payloadNewTabPage?: {
+ logo?: {
+ imageUrl: string;
+ alt: string;
+ companyName: string;
+ destinationUrl: string;
+ } | null;
+ wallpapers?: Array<{
+ imageUrl: string;
+ focalPoint: { x: number; y: number };
+ }> | null;
+ } | null;
+ payloadInlineContent?: {
+ title: string;
+ ctaText: string;
+ imageUrl: string;
+ targetUrl: string;
+ dimensions: string;
+ description: string;
+ } | null;
+ payloadSearch?: {
+ body: string;
+ title: string;
+ targetUrl: string;
+ } | null;
+ payloadSearchHomepage?: {
+ body: string;
+ imageUrl: string;
+ imageDarkModeUrl?: string | null;
+ targetUrl: string;
+ title: string;
+ ctaText: string;
+ } | null;
};
}> | null;
};
diff --git a/src/graphql/campaign.generated.tsx b/src/graphql/campaign.generated.tsx
index d0be5d05..ee73e9ab 100644
--- a/src/graphql/campaign.generated.tsx
+++ b/src/graphql/campaign.generated.tsx
@@ -72,6 +72,39 @@ export type CampaignFragment = {
title: string;
targetUrl: string;
} | null;
+ payloadNewTabPage?: {
+ logo?: {
+ imageUrl: string;
+ alt: string;
+ companyName: string;
+ destinationUrl: string;
+ } | null;
+ wallpapers?: Array<{
+ imageUrl: string;
+ focalPoint: { x: number; y: number };
+ }> | null;
+ } | null;
+ payloadInlineContent?: {
+ title: string;
+ ctaText: string;
+ imageUrl: string;
+ targetUrl: string;
+ dimensions: string;
+ description: string;
+ } | null;
+ payloadSearch?: {
+ body: string;
+ title: string;
+ targetUrl: string;
+ } | null;
+ payloadSearchHomepage?: {
+ body: string;
+ imageUrl: string;
+ imageDarkModeUrl?: string | null;
+ targetUrl: string;
+ title: string;
+ ctaText: string;
+ } | null;
};
}> | null;
}>;
@@ -150,6 +183,39 @@ export type CampaignAdsFragment = {
title: string;
targetUrl: string;
} | null;
+ payloadNewTabPage?: {
+ logo?: {
+ imageUrl: string;
+ alt: string;
+ companyName: string;
+ destinationUrl: string;
+ } | null;
+ wallpapers?: Array<{
+ imageUrl: string;
+ focalPoint: { x: number; y: number };
+ }> | null;
+ } | null;
+ payloadInlineContent?: {
+ title: string;
+ ctaText: string;
+ imageUrl: string;
+ targetUrl: string;
+ dimensions: string;
+ description: string;
+ } | null;
+ payloadSearch?: {
+ body: string;
+ title: string;
+ targetUrl: string;
+ } | null;
+ payloadSearchHomepage?: {
+ body: string;
+ imageUrl: string;
+ imageDarkModeUrl?: string | null;
+ targetUrl: string;
+ title: string;
+ ctaText: string;
+ } | null;
};
}> | null;
}>;
@@ -228,6 +294,39 @@ export type LoadCampaignQuery = {
title: string;
targetUrl: string;
} | null;
+ payloadNewTabPage?: {
+ logo?: {
+ imageUrl: string;
+ alt: string;
+ companyName: string;
+ destinationUrl: string;
+ } | null;
+ wallpapers?: Array<{
+ imageUrl: string;
+ focalPoint: { x: number; y: number };
+ }> | null;
+ } | null;
+ payloadInlineContent?: {
+ title: string;
+ ctaText: string;
+ imageUrl: string;
+ targetUrl: string;
+ dimensions: string;
+ description: string;
+ } | null;
+ payloadSearch?: {
+ body: string;
+ title: string;
+ targetUrl: string;
+ } | null;
+ payloadSearchHomepage?: {
+ body: string;
+ imageUrl: string;
+ imageDarkModeUrl?: string | null;
+ targetUrl: string;
+ title: string;
+ ctaText: string;
+ } | null;
};
}> | null;
}>;
@@ -288,6 +387,39 @@ export type LoadCampaignAdsQuery = {
title: string;
targetUrl: string;
} | null;
+ payloadNewTabPage?: {
+ logo?: {
+ imageUrl: string;
+ alt: string;
+ companyName: string;
+ destinationUrl: string;
+ } | null;
+ wallpapers?: Array<{
+ imageUrl: string;
+ focalPoint: { x: number; y: number };
+ }> | null;
+ } | null;
+ payloadInlineContent?: {
+ title: string;
+ ctaText: string;
+ imageUrl: string;
+ targetUrl: string;
+ dimensions: string;
+ description: string;
+ } | null;
+ payloadSearch?: {
+ body: string;
+ title: string;
+ targetUrl: string;
+ } | null;
+ payloadSearchHomepage?: {
+ body: string;
+ imageUrl: string;
+ imageDarkModeUrl?: string | null;
+ targetUrl: string;
+ title: string;
+ ctaText: string;
+ } | null;
};
}> | null;
}>;
diff --git a/src/graphql/creative.generated.tsx b/src/graphql/creative.generated.tsx
index b67e1f46..8f46b4d8 100644
--- a/src/graphql/creative.generated.tsx
+++ b/src/graphql/creative.generated.tsx
@@ -15,6 +15,35 @@ export type CreativeFragment = {
title: string;
targetUrl: string;
} | null;
+ payloadNewTabPage?: {
+ logo?: {
+ imageUrl: string;
+ alt: string;
+ companyName: string;
+ destinationUrl: string;
+ } | null;
+ wallpapers?: Array<{
+ imageUrl: string;
+ focalPoint: { x: number; y: number };
+ }> | null;
+ } | null;
+ payloadInlineContent?: {
+ title: string;
+ ctaText: string;
+ imageUrl: string;
+ targetUrl: string;
+ dimensions: string;
+ description: string;
+ } | null;
+ payloadSearch?: { body: string; title: string; targetUrl: string } | null;
+ payloadSearchHomepage?: {
+ body: string;
+ imageUrl: string;
+ imageDarkModeUrl?: string | null;
+ targetUrl: string;
+ title: string;
+ ctaText: string;
+ } | null;
};
export type AdvertiserCreativesQueryVariables = Types.Exact<{
@@ -36,33 +65,88 @@ export type AdvertiserCreativesQuery = {
title: string;
targetUrl: string;
} | null;
+ payloadNewTabPage?: {
+ logo?: {
+ imageUrl: string;
+ alt: string;
+ companyName: string;
+ destinationUrl: string;
+ } | null;
+ wallpapers?: Array<{
+ imageUrl: string;
+ focalPoint: { x: number; y: number };
+ }> | null;
+ } | null;
+ payloadInlineContent?: {
+ title: string;
+ ctaText: string;
+ imageUrl: string;
+ targetUrl: string;
+ dimensions: string;
+ description: string;
+ } | null;
+ payloadSearch?: { body: string; title: string; targetUrl: string } | null;
+ payloadSearchHomepage?: {
+ body: string;
+ imageUrl: string;
+ imageDarkModeUrl?: string | null;
+ targetUrl: string;
+ title: string;
+ ctaText: string;
+ } | null;
}>;
} | null;
};
-export type CreateNotificationCreativeMutationVariables = Types.Exact<{
- input: Types.CreateNotificationCreativeInput;
+export type CreateCreativeMutationVariables = Types.Exact<{
+ input: Types.CreativeInput;
}>;
-export type CreateNotificationCreativeMutation = {
- createNotificationCreative: {
+export type CreateCreativeMutation = {
+ createCreative: {
id: string;
+ createdAt: any;
+ modifiedAt: any;
+ name: string;
+ state: string;
+ type: { code: string };
payloadNotification?: {
body: string;
title: string;
targetUrl: string;
} | null;
+ payloadNewTabPage?: {
+ logo?: {
+ imageUrl: string;
+ alt: string;
+ companyName: string;
+ destinationUrl: string;
+ } | null;
+ wallpapers?: Array<{
+ imageUrl: string;
+ focalPoint: { x: number; y: number };
+ }> | null;
+ } | null;
+ payloadInlineContent?: {
+ title: string;
+ ctaText: string;
+ imageUrl: string;
+ targetUrl: string;
+ dimensions: string;
+ description: string;
+ } | null;
+ payloadSearch?: { body: string; title: string; targetUrl: string } | null;
+ payloadSearchHomepage?: {
+ body: string;
+ imageUrl: string;
+ imageDarkModeUrl?: string | null;
+ targetUrl: string;
+ title: string;
+ ctaText: string;
+ } | null;
};
};
-export type UpdateNotificationCreativeMutationVariables = Types.Exact<{
- input: Types.UpdateNotificationCreativeInput;
-}>;
-
-export type UpdateNotificationCreativeMutation = {
- updateNotificationCreative: { id: string };
-};
-
export const CreativeFragmentDoc = gql`
fragment Creative on Creative {
id
@@ -78,6 +162,47 @@ export const CreativeFragmentDoc = gql`
title
targetUrl
}
+ payloadNewTabPage {
+ logo {
+ imageUrl
+ alt
+ companyName
+ destinationUrl
+ }
+ wallpapers {
+ imageUrl
+ focalPoint {
+ x
+ y
+ }
+ }
+ }
+ payloadInlineContent {
+ title
+ ctaText
+ imageUrl
+ targetUrl
+ dimensions
+ description
+ }
+ payloadNotification {
+ body
+ title
+ targetUrl
+ }
+ payloadSearch {
+ body
+ title
+ targetUrl
+ }
+ payloadSearchHomepage {
+ body
+ imageUrl
+ imageDarkModeUrl
+ targetUrl
+ title
+ ctaText
+ }
}
`;
export const AdvertiserCreativesDocument = gql`
@@ -147,114 +272,54 @@ export function refetchAdvertiserCreativesQuery(
) {
return { query: AdvertiserCreativesDocument, variables: variables };
}
-export const CreateNotificationCreativeDocument = gql`
- mutation createNotificationCreative(
- $input: CreateNotificationCreativeInput!
- ) {
- createNotificationCreative(createNotificationCreativeInput: $input) {
- id
- payloadNotification {
- body
- title
- targetUrl
- }
+export const CreateCreativeDocument = gql`
+ mutation createCreative($input: CreativeInput!) {
+ createCreative(creative: $input) {
+ ...Creative
}
}
+ ${CreativeFragmentDoc}
`;
-export type CreateNotificationCreativeMutationFn = Apollo.MutationFunction<
- CreateNotificationCreativeMutation,
- CreateNotificationCreativeMutationVariables
+export type CreateCreativeMutationFn = Apollo.MutationFunction<
+ CreateCreativeMutation,
+ CreateCreativeMutationVariables
>;
/**
- * __useCreateNotificationCreativeMutation__
+ * __useCreateCreativeMutation__
*
- * To run a mutation, you first call `useCreateNotificationCreativeMutation` within a React component and pass it any options that fit your needs.
- * When your component renders, `useCreateNotificationCreativeMutation` returns a tuple that includes:
+ * To run a mutation, you first call `useCreateCreativeMutation` within a React component and pass it any options that fit your needs.
+ * When your component renders, `useCreateCreativeMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
- * const [createNotificationCreativeMutation, { data, loading, error }] = useCreateNotificationCreativeMutation({
+ * const [createCreativeMutation, { data, loading, error }] = useCreateCreativeMutation({
* variables: {
* input: // value for 'input'
* },
* });
*/
-export function useCreateNotificationCreativeMutation(
+export function useCreateCreativeMutation(
baseOptions?: Apollo.MutationHookOptions<
- CreateNotificationCreativeMutation,
- CreateNotificationCreativeMutationVariables
+ CreateCreativeMutation,
+ CreateCreativeMutationVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useMutation<
- CreateNotificationCreativeMutation,
- CreateNotificationCreativeMutationVariables
- >(CreateNotificationCreativeDocument, options);
+ CreateCreativeMutation,
+ CreateCreativeMutationVariables
+ >(CreateCreativeDocument, options);
}
-export type CreateNotificationCreativeMutationHookResult = ReturnType<
- typeof useCreateNotificationCreativeMutation
+export type CreateCreativeMutationHookResult = ReturnType<
+ typeof useCreateCreativeMutation
>;
-export type CreateNotificationCreativeMutationResult =
- Apollo.MutationResult;
-export type CreateNotificationCreativeMutationOptions =
- Apollo.BaseMutationOptions<
- CreateNotificationCreativeMutation,
- CreateNotificationCreativeMutationVariables
- >;
-export const UpdateNotificationCreativeDocument = gql`
- mutation updateNotificationCreative(
- $input: UpdateNotificationCreativeInput!
- ) {
- updateNotificationCreative(updateNotificationCreativeInput: $input) {
- id
- }
- }
-`;
-export type UpdateNotificationCreativeMutationFn = Apollo.MutationFunction<
- UpdateNotificationCreativeMutation,
- UpdateNotificationCreativeMutationVariables
->;
-
-/**
- * __useUpdateNotificationCreativeMutation__
- *
- * To run a mutation, you first call `useUpdateNotificationCreativeMutation` within a React component and pass it any options that fit your needs.
- * When your component renders, `useUpdateNotificationCreativeMutation` returns a tuple that includes:
- * - A mutate function that you can call at any time to execute the mutation
- * - An object with fields that represent the current status of the mutation's execution
- *
- * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
- *
- * @example
- * const [updateNotificationCreativeMutation, { data, loading, error }] = useUpdateNotificationCreativeMutation({
- * variables: {
- * input: // value for 'input'
- * },
- * });
- */
-export function useUpdateNotificationCreativeMutation(
- baseOptions?: Apollo.MutationHookOptions<
- UpdateNotificationCreativeMutation,
- UpdateNotificationCreativeMutationVariables
- >,
-) {
- const options = { ...defaultOptions, ...baseOptions };
- return Apollo.useMutation<
- UpdateNotificationCreativeMutation,
- UpdateNotificationCreativeMutationVariables
- >(UpdateNotificationCreativeDocument, options);
-}
-export type UpdateNotificationCreativeMutationHookResult = ReturnType<
- typeof useUpdateNotificationCreativeMutation
+export type CreateCreativeMutationResult =
+ Apollo.MutationResult;
+export type CreateCreativeMutationOptions = Apollo.BaseMutationOptions<
+ CreateCreativeMutation,
+ CreateCreativeMutationVariables
>;
-export type UpdateNotificationCreativeMutationResult =
- Apollo.MutationResult;
-export type UpdateNotificationCreativeMutationOptions =
- Apollo.BaseMutationOptions<
- UpdateNotificationCreativeMutation,
- UpdateNotificationCreativeMutationVariables
- >;
diff --git a/src/graphql/creative.graphql b/src/graphql/creative.graphql
index 80ad3102..a7b10adf 100644
--- a/src/graphql/creative.graphql
+++ b/src/graphql/creative.graphql
@@ -12,6 +12,47 @@ fragment Creative on Creative {
title
targetUrl
}
+ payloadNewTabPage {
+ logo {
+ imageUrl
+ alt
+ companyName
+ destinationUrl
+ }
+ wallpapers {
+ imageUrl
+ focalPoint {
+ x
+ y
+ }
+ }
+ }
+ payloadInlineContent {
+ title
+ ctaText
+ imageUrl
+ targetUrl
+ dimensions
+ description
+ }
+ payloadNotification {
+ body
+ title
+ targetUrl
+ }
+ payloadSearch {
+ body
+ title
+ targetUrl
+ }
+ payloadSearchHomepage {
+ body
+ imageUrl
+ imageDarkModeUrl
+ targetUrl
+ title
+ ctaText
+ }
}
query advertiserCreatives($advertiserId: String!) {
@@ -23,19 +64,8 @@ query advertiserCreatives($advertiserId: String!) {
}
}
-mutation createNotificationCreative($input: CreateNotificationCreativeInput!) {
- createNotificationCreative(createNotificationCreativeInput: $input) {
- id
- payloadNotification {
- body
- title
- targetUrl
- }
- }
-}
-
-mutation updateNotificationCreative($input: UpdateNotificationCreativeInput!) {
- updateNotificationCreative(updateNotificationCreativeInput: $input) {
- id
+mutation createCreative($input: CreativeInput!) {
+ createCreative(creative: $input) {
+ ...Creative
}
}
diff --git a/src/state/context.ts b/src/state/context.ts
index 0c7e0b58..e5bb4ae2 100644
--- a/src/state/context.ts
+++ b/src/state/context.ts
@@ -31,3 +31,8 @@ export const FilterContext = createContext({
fromDate: null as Date | null,
setFromDate: (_d: Date | null) => {},
});
+
+export const FormContext = createContext({
+ isShowingAds: false as boolean,
+ setIsShowingAds: (_b: boolean) => {},
+});
diff --git a/src/user/ads/AdsExistingAd.tsx b/src/user/ads/AdsExistingAd.tsx
new file mode 100644
index 00000000..4dc45a71
--- /dev/null
+++ b/src/user/ads/AdsExistingAd.tsx
@@ -0,0 +1,144 @@
+import {
+ Alert,
+ Box,
+ InputAdornment,
+ LinearProgress,
+ TextField,
+ Typography,
+} from "@mui/material";
+import { useFormikContext } from "formik";
+import { CampaignFormat } from "graphql/types";
+import _ from "lodash";
+import {
+ CreativeFragment,
+ useAdvertiserCreativesQuery,
+} from "graphql/creative.generated";
+import { isCreativeTypeApplicableToCampaignFormat } from "user/library";
+import { useAdvertiser } from "auth/hooks/queries/useAdvertiser";
+import { CampaignForm } from "user/views/adsManager/types";
+import { CardContainer } from "components/Card/CardContainer";
+import SearchIcon from "@mui/icons-material/Search";
+import { useContext, useRef, useState } from "react";
+import { NotificationSelect } from "components/Creatives/NotificationSelect";
+import { FormContext } from "state/context";
+import { useAdvertiserCreatives } from "user/hooks/useAdvertiserCreatives";
+
+function filterCreativesBasedOnCampaignFormat(
+ creatives: CreativeFragment[],
+ campaignFormat: CampaignFormat | null,
+): CreativeFragment[] {
+ if (!campaignFormat) return creatives;
+
+ return creatives.filter((c) =>
+ isCreativeTypeApplicableToCampaignFormat(c.type, campaignFormat),
+ );
+}
+
+export function AdsExistingAd() {
+ const { setIsShowingAds } = useContext(FormContext);
+ const { creatives } = useAdvertiserCreatives();
+ const { values } = useFormikContext();
+ const { advertiser } = useAdvertiser();
+ const original = useRef([]);
+ const [options, setOptions] = useState();
+ const { loading } = useAdvertiserCreativesQuery({
+ variables: { advertiserId: advertiser.id },
+ onCompleted(data) {
+ const creativeOptionList = _.orderBy(
+ filterCreativesBasedOnCampaignFormat(
+ data.advertiser?.creatives ?? [],
+ values.format,
+ ),
+ ["type.code", "createdAt"],
+ ["asc", "desc"],
+ ) as CreativeFragment[];
+
+ const filtered = creativeOptionList.filter((c) => c.state === "active");
+ const exludeExisting = filtered.filter((e) => {
+ const associatedOptions = creatives ?? [];
+ return associatedOptions.find((ao) => ao.id === e.id) === undefined;
+ });
+ original.current = exludeExisting;
+ setOptions(exludeExisting);
+ },
+ });
+
+ if (loading) {
+ return ;
+ }
+
+ if (options && options.length === 0) {
+ return (
+ setIsShowingAds(false)}>
+ No previous Ads available
+
+ );
+ }
+
+ return (
+
+
+ Add an existing Ad
+
+
+
+ Ads are modular building blocks that can be paired with ad sets to build
+ unique combinations. Your previously approved ads will show here. Select
+ by using the box next to the name. Use the "Complete
+ selection" button to finish.
+
+
+
+
+
+
+ ),
+ }}
+ onChange={(e) => {
+ const value = e.target.value.toLowerCase();
+ if (!value || value.trim() !== "") {
+ setOptions(
+ original.current.filter((co) =>
+ co.name.toLowerCase().includes(value),
+ ),
+ );
+ } else {
+ setOptions(original.current);
+ }
+ }}
+ />
+
+
+
+
+ );
+}
+
+const CreativeSpecificSelect = (props: {
+ format: CampaignFormat;
+ options: CreativeFragment[];
+}) => {
+ const { advertiser } = useAdvertiser();
+
+ if (props.format === CampaignFormat.PushNotification)
+ return (
+ ({
+ ...o,
+ advertiserId: advertiser.id,
+ included: false,
+ }))}
+ useSelectedAdStyle={false}
+ showState={false}
+ />
+ );
+
+ return null;
+};
diff --git a/src/user/ads/NewAd.tsx b/src/user/ads/NewAd.tsx
index 74aaa35f..4538b7f1 100644
--- a/src/user/ads/NewAd.tsx
+++ b/src/user/ads/NewAd.tsx
@@ -1,34 +1,38 @@
-import { useRecentlyCreatedAdvertiserCreatives } from "user/hooks/useAdvertiserCreatives";
import { CardContainer } from "components/Card/CardContainer";
-import { Box, Button, Stack } from "@mui/material";
-import { useState } from "react";
+import { Box, Button, Link } from "@mui/material";
+import { useContext, useEffect } from "react";
import { BoxContainer } from "components/Box/BoxContainer";
import AddCircleOutlineIcon from "@mui/icons-material/AddCircleOutline";
import RemoveCircleOutlineIcon from "@mui/icons-material/RemoveCircleOutline";
-import { NotificationPreview } from "user/ads/NotificationPreview";
-import { NotificationAd } from "user/ads/NotificationAd";
+import { CreativeSpecificFields } from "components/Creatives/CreativeSpecificFields";
import { useField } from "formik";
+import { Creative, initialCreative } from "user/views/adsManager/types";
+import { FormContext } from "state/context";
+import { AdsExistingAd } from "user/ads/AdsExistingAd";
+import { CreativeSpecificPreview } from "components/Creatives/CreativeSpecificPreview";
+import { useAdvertiserCreatives } from "user/hooks/useAdvertiserCreatives";
export function NewAd() {
+ const { creatives } = useAdvertiserCreatives();
+ const [, , newCreative] = useField("newCreative");
const [, meta, helper] = useField("isCreating");
- const [showForm, setShowForm] = useState(false);
- const creatives = useRecentlyCreatedAdvertiserCreatives();
+ const { isShowingAds, setIsShowingAds } = useContext(FormContext);
+
+ useEffect(() => {
+ if (!meta.value) {
+ newCreative.setValue(initialCreative);
+ newCreative.setTouched(false);
+ }
+ }, [meta.value]);
return (
<>
-
-
- {(creatives ?? []).map((c, idx) => (
-
-
-
- ))}
-
+
+
+
{
helper.setValue(!meta.value);
- setShowForm(!showForm);
+ setIsShowingAds(false);
}}
>
- {showForm ? (
+ {meta.value ? (
) : (
)}
-
+
+ {!isShowingAds && (
+ {
+ setIsShowingAds(true);
+ helper.setValue(false);
+ }}
+ >
+ Use previously created Ads
+
+ )}
- {showForm && (
- {
- helper.setValue(false);
- setShowForm(false);
- }}
- />
- )}
+ {isShowingAds && }
+ {meta.value && }
>
);
}
diff --git a/src/user/ads/NotificationAd.tsx b/src/user/ads/NotificationAd.tsx
index 58ac1735..f5d850fd 100644
--- a/src/user/ads/NotificationAd.tsx
+++ b/src/user/ads/NotificationAd.tsx
@@ -2,45 +2,17 @@ import { CardContainer } from "components/Card/CardContainer";
import { FormikTextField } from "form/FormikHelpers";
import { Stack } from "@mui/material";
import { UrlResolver } from "components/Url/UrlResolver";
-import { LoadingButton } from "@mui/lab";
-import SaveIcon from "@mui/icons-material/Save";
-import { creativeInput } from "user/library";
-import { CreateNotificationCreativeInput } from "graphql/types";
import { useField } from "formik";
-import { Creative, initialCreative } from "user/views/adsManager/types";
-import { useAdvertiser } from "auth/hooks/queries/useAdvertiser";
-import { useUser } from "auth/hooks/queries/useUser";
-import { NotificationPreview } from "user/ads/NotificationPreview";
-import {
- refetchAdvertiserCreativesQuery,
- useCreateNotificationCreativeMutation,
-} from "graphql/creative.generated";
+import { NotificationPreview } from "components/Creatives/NotificationPreview";
+import { CreateCreativeButton } from "components/Creatives/CreateCreativeButton";
+import { useEffect } from "react";
-interface Props {
- onCreate: () => void;
-}
+export function NotificationAd() {
+ const [, , code] = useField("newCreative.type.code");
-export function NotificationAd({ onCreate }: Props) {
- const [, meta, newCreativeHelper] = useField("newCreative");
- const [, creativesMeta, creativesHelper] = useField("creatives");
- const { advertiser } = useAdvertiser();
- const { userId } = useUser();
- const [create, { loading }] = useCreateNotificationCreativeMutation({
- async onCompleted(data) {
- newCreativeHelper.setValue(initialCreative);
- newCreativeHelper.setTouched(false);
- creativesHelper.setValue([
- ...(creativesMeta.value ?? []),
- data.createNotificationCreative.id,
- ]);
- onCreate();
- },
- refetchQueries: [
- {
- ...refetchAdvertiserCreativesQuery({ advertiserId: advertiser.id }),
- },
- ],
- });
+ useEffect(() => {
+ code.setValue("notification_all_v1");
+ }, []);
return (
@@ -48,14 +20,14 @@ export function NotificationAd({ onCreate }: Props) {
- }
- onClick={(e) => {
- e.preventDefault();
- const input = creativeInput(
- advertiser.id,
- meta.value,
- userId,
- ) as CreateNotificationCreativeInput;
- create({ variables: { input } });
- }}
- disabled={
- !!meta.error ||
- meta.value?.targetUrlValidationResult !== undefined ||
- loading
- }
- loading={loading}
- >
- Add
-
+
);
diff --git a/src/user/hooks/useAdvertiserCreatives.ts b/src/user/hooks/useAdvertiserCreatives.ts
index 3117fe85..451f7231 100644
--- a/src/user/hooks/useAdvertiserCreatives.ts
+++ b/src/user/hooks/useAdvertiserCreatives.ts
@@ -1,34 +1,20 @@
-import { useAdvertiserCreativesQuery } from "graphql/creative.generated";
-import { useAdvertiser } from "auth/hooks/queries/useAdvertiser";
import { useFormikContext } from "formik";
import { CampaignForm, Creative } from "user/views/adsManager/types";
import _ from "lodash";
-export function useAdvertiserCreatives(): Creative[] {
- const { advertiser } = useAdvertiser();
- const { data } = useAdvertiserCreativesQuery({
- variables: { advertiserId: advertiser.id },
- });
- return (data?.advertiser?.creatives ?? []).map((c) => ({
- id: c.id,
- name: c.name,
- title: c.payloadNotification?.title ?? "New Ad",
- body: c.payloadNotification?.body ?? "Body Preview",
- targetUrl: c.payloadNotification?.targetUrl ?? "",
- state: c.state,
- }));
-}
-
-export function useRecentlyCreatedAdvertiserCreatives() {
+export function useAdvertiserCreatives() {
const { values } = useFormikContext();
- const creatives = useAdvertiserCreatives();
- const inCampaign = creatives.filter((c) => {
- if (c.id) {
- return (values.creatives ?? []).includes(c.id);
- }
-
- return false;
- });
+ const inAdSet: Creative[] = _.flatMap(values.adSets, "creatives").map(
+ (c: Creative) => ({
+ type: c.type,
+ payloadNotification: c.payloadNotification,
+ id: c.id,
+ advertiserId: c.advertiserId,
+ name: c.name,
+ state: c.state,
+ included: false,
+ }),
+ );
- return _.uniqBy(inCampaign, "id");
+ return { creatives: _.uniqBy(inAdSet, "id") };
}
diff --git a/src/user/library/index.test.ts b/src/user/library/index.test.ts
index aad02ce5..bd92261f 100644
--- a/src/user/library/index.test.ts
+++ b/src/user/library/index.test.ts
@@ -1,6 +1,11 @@
import { CampaignFragment } from "graphql/campaign.generated";
import { describe, expect, it } from "vitest";
-import { editCampaignValues, transformCreative } from ".";
+import {
+ editCampaignValues,
+ transformCreative,
+ transformEditForm,
+ transformNewForm,
+} from ".";
import {
CampaignFormat,
CampaignPacingStrategies,
@@ -9,7 +14,10 @@ import {
PaymentType,
} from "graphql/types";
import { produce } from "immer";
-import { Creative } from "user/views/adsManager/types";
+import { AdSetForm, CampaignForm, Creative } from "user/views/adsManager/types";
+import _ from "lodash";
+import { AdFragment, AdSetFragment } from "graphql/ad-set.generated";
+import { CreativeFragment } from "graphql/creative.generated";
const BASE_CPM_CAMPAIGN_FRAGMENT: Readonly = {
id: "3495317a-bb47-4daf-8d3e-14cdc0e87457",
@@ -160,10 +168,16 @@ describe("pricing logic (read)", () => {
describe("pricing logic (write)", () => {
const creative: Creative = {
+ payloadNotification: {
+ title: "some title",
+ body: "body",
+ targetUrl: "some url",
+ },
+ advertiserId: "some id",
+ state: "draft",
+ type: { code: "notification_all_v1" },
name: "some name",
- title: "some title",
- body: "body",
- targetUrl: "https://some.example.org",
+ included: true,
};
it("should convert from CPM to per-impression values when populating a CPM creative", () => {
@@ -196,3 +210,434 @@ describe("pricing logic (write)", () => {
expect(inputObject.priceType).toEqual(ConfirmationType.Landed);
});
});
+
+describe("new form tests", () => {
+ const dateString = new Date().toLocaleString();
+
+ const creative: Creative = {
+ id: "11111",
+ advertiserId: "123456",
+ included: true,
+ name: "Test",
+ state: "draft",
+ type: { code: "test" },
+ };
+
+ const creative2: Creative = {
+ id: "33333",
+ advertiserId: "123456",
+ included: false,
+ name: "Dont include",
+ state: "draft",
+ type: { code: "test" },
+ };
+
+ const adSetForm: AdSetForm = {
+ conversions: [],
+ creatives: [creative, creative2],
+ isNotTargeting: false,
+ name: "",
+ oses: [{ name: "macos", code: "1234" }],
+ segments: [{ name: "test", code: "5678" }],
+ };
+
+ const form: CampaignForm = {
+ adSets: [adSetForm],
+ advertiserId: "12345",
+ billingType: "cpm",
+ budget: 1000,
+ currency: "USD",
+ dailyBudget: 10,
+ endAt: dateString,
+ format: CampaignFormat.PushNotification,
+ geoTargets: [{ code: "US", name: "United States" }],
+ isCreating: false,
+ name: "Test",
+ paymentType: PaymentType.Radom,
+ price: 6,
+ startAt: dateString,
+ state: "draft",
+ type: "paid",
+ validateStart: false,
+ };
+
+ it("should transform campaign form", () => {
+ const res = _.omit(transformNewForm(form, "me"), ["startAt", "endAt"]);
+ expect(res).toMatchInlineSnapshot(`
+ {
+ "adSets": [
+ {
+ "ads": [
+ {
+ "creativeId": "11111",
+ "price": "0.006",
+ "priceType": "VIEW",
+ },
+ ],
+ "billingType": "cpm",
+ "conversions": [],
+ "name": "",
+ "oses": [
+ {
+ "code": "1234",
+ "name": "macos",
+ },
+ ],
+ "perDay": 1,
+ "segments": [
+ {
+ "code": "5678",
+ "name": "test",
+ },
+ ],
+ "totalMax": 10,
+ },
+ ],
+ "advertiserId": "12345",
+ "budget": 1000,
+ "currency": "USD",
+ "dailyBudget": 10,
+ "dailyCap": 1,
+ "externalId": "",
+ "format": "PUSH_NOTIFICATION",
+ "geoTargets": [
+ {
+ "code": "US",
+ "name": "United States",
+ },
+ ],
+ "name": "Test",
+ "pacingStrategy": "MODEL_V1",
+ "paymentType": "RADOM",
+ "source": "self_serve",
+ "state": "draft",
+ "type": "paid",
+ "userId": "me",
+ }
+ `);
+ });
+
+ it("should transform a creative", () => {
+ creative.payloadNotification = {
+ title: "valid",
+ targetUrl: "valid",
+ body: "valid",
+ };
+
+ creative.payloadSearch = {
+ title: "invalid",
+ targetUrl: "invalid",
+ body: "invalid",
+ };
+
+ const res = transformCreative(creative, form);
+ expect(res).toMatchInlineSnapshot(`
+ {
+ "creativeId": "11111",
+ "price": "0.006",
+ "priceType": "VIEW",
+ }
+ `);
+ });
+});
+
+describe("edit form tests", () => {
+ const creative: CreativeFragment = {
+ createdAt: undefined,
+ id: "1234",
+ modifiedAt: undefined,
+ name: "a creative",
+ state: "active",
+ payloadNotification: {
+ targetUrl: "valid",
+ title: "valid",
+ body: "valid",
+ },
+ type: { code: "notification_v1_all" },
+ };
+
+ const ad: AdFragment = {
+ id: "1",
+ creative: creative,
+ state: "active",
+ price: "6",
+ priceType: ConfirmationType.View,
+ };
+
+ const ad2: AdFragment = {
+ id: "2",
+ creative: creative,
+ state: "deleted",
+ price: "6",
+ priceType: ConfirmationType.View,
+ };
+
+ const ad3: AdFragment = {
+ id: "3",
+ creative: {
+ ...creative,
+ id: "1235",
+ name: "a different creative",
+ },
+ state: "active",
+ price: "6",
+ priceType: ConfirmationType.View,
+ };
+
+ const adSet: AdSetFragment = {
+ ads: [ad, ad2],
+ billingType: "cpm",
+ conversions: [],
+ createdAt: undefined,
+ id: "11111",
+ perDay: 1,
+ oses: [{ name: "macos", code: "1234" }],
+ segments: [{ name: "test", code: "5678" }],
+ state: "active",
+ totalMax: 100,
+ };
+
+ const adSet2: AdSetFragment = {
+ ads: [ad, ad3],
+ billingType: "cpm",
+ conversions: [],
+ createdAt: undefined,
+ id: "22222",
+ perDay: 1,
+ oses: [{ name: "linux", code: "1234" }],
+ segments: [{ name: "help", code: "5678" }],
+ state: "active",
+ totalMax: 100,
+ };
+
+ const campaignFragment: CampaignFragment = {
+ adSets: [adSet, adSet2],
+ advertiser: { id: "12345" },
+ budget: 100,
+ createdAt: undefined,
+ currency: "USD",
+ dailyBudget: 0,
+ dailyCap: 0,
+ endAt: undefined,
+ externalId: "",
+ format: CampaignFormat.PushNotification,
+ id: "000001",
+ name: "My first campaign",
+ pacingOverride: false,
+ pacingStrategy: CampaignPacingStrategies.ModelV1,
+ passThroughRate: 0,
+ paymentType: PaymentType.Radom,
+ priority: 1,
+ source: CampaignSource.SelfServe,
+ spent: 0,
+ startAt: undefined,
+ state: "active",
+ type: "paid",
+ };
+
+ const editForm = editCampaignValues(
+ campaignFragment,
+ campaignFragment.advertiser.id,
+ );
+ it("should result in a valid campaign form", () => {
+ const omitted = _.omit(editForm, ["newCreative"]);
+ expect(omitted).toMatchInlineSnapshot(`
+ {
+ "adSets": [
+ {
+ "conversions": [],
+ "creatives": [
+ {
+ "advertiserId": "12345",
+ "id": "1234",
+ "included": true,
+ "name": "a creative",
+ "payloadNotification": {
+ "body": "valid",
+ "targetUrl": "valid",
+ "title": "valid",
+ },
+ "state": "active",
+ "targetUrlValid": "",
+ "type": {
+ "code": "notification_v1_all",
+ },
+ },
+ {
+ "advertiserId": "12345",
+ "id": "1235",
+ "included": false,
+ "name": "a different creative",
+ "payloadNotification": {
+ "body": "valid",
+ "targetUrl": "valid",
+ "title": "valid",
+ },
+ "state": "active",
+ "targetUrlValid": "",
+ "type": {
+ "code": "notification_v1_all",
+ },
+ },
+ ],
+ "id": "11111",
+ "isNotTargeting": false,
+ "name": "11111",
+ "oses": [
+ {
+ "code": "1234",
+ "name": "macos",
+ },
+ ],
+ "segments": [
+ {
+ "code": "5678",
+ "name": "test",
+ },
+ ],
+ },
+ {
+ "conversions": [],
+ "creatives": [
+ {
+ "advertiserId": "12345",
+ "id": "1234",
+ "included": true,
+ "name": "a creative",
+ "payloadNotification": {
+ "body": "valid",
+ "targetUrl": "valid",
+ "title": "valid",
+ },
+ "state": "active",
+ "targetUrlValid": "",
+ "type": {
+ "code": "notification_v1_all",
+ },
+ },
+ {
+ "advertiserId": "12345",
+ "id": "1235",
+ "included": true,
+ "name": "a different creative",
+ "payloadNotification": {
+ "body": "valid",
+ "targetUrl": "valid",
+ "title": "valid",
+ },
+ "state": "active",
+ "targetUrlValid": "",
+ "type": {
+ "code": "notification_v1_all",
+ },
+ },
+ ],
+ "id": "22222",
+ "isNotTargeting": false,
+ "name": "22222",
+ "oses": [
+ {
+ "code": "1234",
+ "name": "linux",
+ },
+ ],
+ "segments": [
+ {
+ "code": "5678",
+ "name": "help",
+ },
+ ],
+ },
+ ],
+ "advertiserId": "12345",
+ "billingType": "cpm",
+ "budget": 100,
+ "currency": "USD",
+ "dailyBudget": 0,
+ "endAt": undefined,
+ "format": "PUSH_NOTIFICATION",
+ "geoTargets": [],
+ "id": "000001",
+ "isCreating": false,
+ "name": "My first campaign",
+ "paymentType": "RADOM",
+ "price": 6000,
+ "startAt": undefined,
+ "state": "active",
+ "type": "paid",
+ "validateStart": false,
+ }
+ `);
+ });
+
+ it("should resolve to update input", () => {
+ const update = transformEditForm(editForm, editForm.id ?? "");
+ expect(update).toMatchInlineSnapshot(`
+ {
+ "adSets": [
+ {
+ "ads": [
+ {
+ "creativeId": "1234",
+ "creativeSetId": "11111",
+ "price": "6",
+ "priceType": "VIEW",
+ },
+ ],
+ "id": "11111",
+ "oses": [
+ {
+ "code": "1234",
+ "name": "macos",
+ },
+ ],
+ "segments": [
+ {
+ "code": "5678",
+ "name": "test",
+ },
+ ],
+ },
+ {
+ "ads": [
+ {
+ "creativeId": "1234",
+ "creativeSetId": "22222",
+ "price": "6",
+ "priceType": "VIEW",
+ },
+ {
+ "creativeId": "1235",
+ "creativeSetId": "22222",
+ "price": "6",
+ "priceType": "VIEW",
+ },
+ ],
+ "id": "22222",
+ "oses": [
+ {
+ "code": "1234",
+ "name": "linux",
+ },
+ ],
+ "segments": [
+ {
+ "code": "5678",
+ "name": "help",
+ },
+ ],
+ },
+ ],
+ "budget": 100,
+ "dailyBudget": 0,
+ "endAt": undefined,
+ "id": "000001",
+ "name": "My first campaign",
+ "paymentType": "RADOM",
+ "startAt": undefined,
+ "state": "active",
+ "type": "paid",
+ }
+ `);
+ });
+});
diff --git a/src/user/library/index.ts b/src/user/library/index.ts
index 3a7d3781..85be5261 100644
--- a/src/user/library/index.ts
+++ b/src/user/library/index.ts
@@ -1,26 +1,25 @@
import {
CampaignFormat,
+ CampaignPacingStrategies,
ConfirmationType,
CreateAdInput,
CreateCampaignInput,
- CreateNotificationCreativeInput,
- GeocodeInput,
UpdateCampaignInput,
- UpdateNotificationCreativeInput,
} from "graphql/types";
import { CampaignFragment } from "graphql/campaign.generated";
import { AdFragment } from "graphql/ad-set.generated";
import {
+ AdSetForm,
Billing,
CampaignForm,
Conversion,
Creative,
initialCreative,
- OS,
Segment,
} from "user/views/adsManager/types";
import _ from "lodash";
import BigNumber from "bignumber.js";
+import { CreativeFragment } from "graphql/creative.generated";
const TYPE_CODE_LOOKUP: Record = {
notification_all_v1: "Push Notification",
@@ -36,14 +35,14 @@ export function transformNewForm(
): CreateCampaignInput {
return {
currency: form.currency,
- dailyCap: form.dailyCap,
+ externalId: "",
+ dailyCap: 1,
dailyBudget: form.dailyBudget,
endAt: form.endAt,
- pacingStrategy: form.pacingStrategy,
+ pacingStrategy: CampaignPacingStrategies.ModelV1,
geoTargets: form.geoTargets.map((g) => ({ code: g.code, name: g.name })),
name: form.name,
advertiserId: form.advertiserId,
- externalId: "",
format: form.format,
userId: userId,
source: "self_serve",
@@ -54,13 +53,14 @@ export function transformNewForm(
adSets: form.adSets.map((adSet) => ({
name: adSet.name,
billingType: form.billingType,
- execution: "per_click",
perDay: 1,
segments: adSet.segments.map((s) => ({ code: s.code, name: s.name })),
oses: adSet.oses,
totalMax: 10,
conversions: transformConversion(adSet.conversions),
- ads: adSet.creatives.map((ad) => transformCreative(ad, form)),
+ ads: adSet.creatives
+ .filter((c) => c.included)
+ .map((ad) => transformCreative(ad, form)),
})),
paymentType: form.paymentType,
};
@@ -96,44 +96,14 @@ export function transformCreative(
priceType = ConfirmationType.Click;
}
- return {
- webhooks: [],
- creativeId: creative.id!,
+ const createInput: CreateAdInput = {
price: price.toString(),
priceType: priceType,
};
-}
-
-export function creativeInput(
- advertiserId: string,
- creative: Creative,
- userId?: string,
-): CreateNotificationCreativeInput | UpdateNotificationCreativeInput {
- const baseNotification = {
- advertiserId,
- userId,
- name: creative.name,
- payload: {
- title: creative.title,
- body: creative.body,
- targetUrl: creative.targetUrl,
- },
- state: creative.state,
- };
- if (creative.id) {
- return {
- ...baseNotification,
- creativeId: creative.id,
- };
- }
+ createInput.creativeId = creative.id;
- return {
- ...baseNotification,
- type: {
- code: "notification_all_v1",
- },
- };
+ return createInput;
}
export function editCampaignValues(
@@ -153,33 +123,39 @@ export function editCampaignValues(
const seg = adSet.segments ?? ([] as Segment[]);
return {
- ...adSet,
id: adSet.id,
- conversions: adSet.conversions ?? [],
- oses: adSet.oses ?? ([] as OS[]),
- segments: adSet.segments ?? ([] as Segment[]),
+ conversions: (adSet.conversions ?? []).map((c) => ({
+ id: c.id,
+ type: c.type,
+ observationWindow: c.observationWindow,
+ urlPattern: c.urlPattern,
+ })),
+ oses: (adSet.oses ?? []).map((o) => ({ name: o.name, code: o.code })),
+ segments: (adSet.segments ?? []).map((o) => ({
+ name: o.name,
+ code: o.code,
+ })),
isNotTargeting: seg.length === 1 && seg[0].code === "Svp7l-zGN",
name: adSet.name || adSet.id.split("-")[0],
- creatives: creativeList(adSet.ads),
- };
+ creatives: creativeList(advertiserId, adSet.ads, ads),
+ } as AdSetForm;
}),
+ isCreating: false,
advertiserId,
- hasPaymentIntent: campaign.hasPaymentIntent ?? false,
- creatives: creativeList(ads).map((a) => a.id!),
newCreative: initialCreative,
- isCreating: false,
+ currency: campaign.currency,
price: price.toNumber(),
billingType: billingType,
validateStart: false,
budget: campaign.budget,
- currency: campaign.currency,
dailyBudget: campaign.dailyBudget,
- dailyCap: campaign.dailyCap,
endAt: campaign.endAt,
format: campaign.format,
- geoTargets: campaign.geoTargets ?? ([] as GeocodeInput[]),
+ geoTargets: (campaign.geoTargets ?? []).map((g) => ({
+ code: g.code,
+ name: g.name,
+ })),
name: campaign.name,
- pacingStrategy: campaign.pacingStrategy,
startAt: campaign.startAt,
state: campaign.state,
type: "paid",
@@ -187,36 +163,58 @@ export function editCampaignValues(
};
}
-function creativeList(ads?: AdFragment[] | null): Creative[] {
- return _.uniqBy(
- (ads ?? [])
- .filter((ad) => ad.creative != null && ad.state !== "deleted")
+function creativeList(
+ advertiserId: string,
+ adSetAds?: AdFragment[] | null,
+ allAds?: AdFragment[] | null,
+): Creative[] {
+ const filterAds = (a?: AdFragment[] | null, included?: boolean) => {
+ return (a ?? [])
+ .filter((ad) => ad.creative !== null && ad.state !== "deleted")
.map((ad) => {
const c = ad.creative;
return {
- creativeInstanceId: ad.id,
- id: c.id,
- name: c.name,
- targetUrl: c.payloadNotification!.targetUrl,
- title: c.payloadNotification!.title,
- body: c.payloadNotification!.body,
- targetUrlValidationResult: "",
- state: c.state,
+ ...validCreativeFields(c, advertiserId, included),
};
- }),
+ });
+ };
+
+ return _.uniqBy(
+ [...filterAds(adSetAds, true), ...filterAds(allAds, false)],
"id",
);
}
+export function validCreativeFields(
+ c: CreativeFragment | Creative,
+ advertiserId: string,
+ included?: boolean,
+): Creative {
+ return {
+ advertiserId,
+ id: c.id,
+ included: included ?? false,
+ name: c.name,
+ targetUrlValid: "",
+ state: c.state,
+ type: { code: c.type.code },
+ payloadNotification: c.payloadNotification
+ ? {
+ title: c.payloadNotification.title,
+ body: c.payloadNotification.body,
+ targetUrl: c.payloadNotification.targetUrl,
+ }
+ : undefined,
+ };
+}
+
export function transformEditForm(
form: CampaignForm,
id: string,
): UpdateCampaignInput {
return {
budget: form.budget,
- currency: form.currency,
dailyBudget: form.dailyBudget,
- dailyCap: form.dailyCap,
endAt: form.endAt,
id,
name: form.name,
@@ -228,11 +226,12 @@ export function transformEditForm(
id: adSet.id,
segments: adSet.segments.map((v) => ({ code: v.code, name: v.name })),
oses: adSet.oses.map((v) => ({ code: v.code, name: v.name })),
- ads: adSet.creatives.map((ad) => ({
- ...transformCreative(ad, form),
- id: ad.creativeInstanceId,
- creativeSetId: adSet.id,
- })),
+ ads: adSet.creatives
+ .filter((c) => c.included)
+ .map((ad) => ({
+ ...transformCreative(ad, form),
+ creativeSetId: adSet.id,
+ })),
})),
};
}
@@ -258,3 +257,26 @@ export function uiTextForCreativeTypeCode(creativeTypeCode: {
}): string {
return uiTextForCreativeType(creativeTypeCode.code);
}
+
+export function isCreativeTypeApplicableToCampaignFormat(
+ creativeTypeCode: {
+ code: string;
+ },
+ format: CampaignFormat,
+): boolean {
+ const { code } = creativeTypeCode;
+ switch (code) {
+ case "notification_all_v1":
+ return format === CampaignFormat.PushNotification;
+ case "new_tab_page_all_v1":
+ return format === CampaignFormat.NtpSi;
+ case "inline_content_all_v1":
+ return format === CampaignFormat.NewsDisplayAd;
+ case "search_all_v1":
+ return format === CampaignFormat.Search;
+ case "search_homepage_all_v1":
+ return format === CampaignFormat.SearchHomepage;
+ default:
+ return false;
+ }
+}
diff --git a/src/user/views/adsManager/types/index.ts b/src/user/views/adsManager/types/index.ts
index ff5a0ebc..fef57b7d 100644
--- a/src/user/views/adsManager/types/index.ts
+++ b/src/user/views/adsManager/types/index.ts
@@ -1,8 +1,4 @@
-import {
- CampaignFormat,
- CampaignPacingStrategies,
- PaymentType,
-} from "graphql/types";
+import { CampaignFormat, CreativeInput, PaymentType } from "graphql/types";
import { defaultEndDate, defaultStartDate } from "form/DateFieldHelpers";
import { MIN_PER_CAMPAIGN } from "validation/CampaignSchema";
import { IAdvertiser } from "auth/context/auth.interface";
@@ -20,20 +16,16 @@ export type CampaignForm = {
isCreating: boolean;
currency: string;
dailyBudget: number;
- dailyCap: number;
geoTargets: GeoTarget[];
adSets: AdSetForm[];
format: CampaignFormat;
newCreative?: Creative;
- creatives?: string[];
name: string;
state: string;
type: "paid";
// this is per click for CPC campaigns, but per thousand views for CPM campaigns
price: number;
billingType: Billing;
- pacingStrategy: CampaignPacingStrategies;
- hasPaymentIntent: boolean;
paymentType: PaymentType;
};
@@ -68,15 +60,13 @@ export type Segment = {
name: string;
};
-export type Creative = {
+export type Creative = CreativeInput & {
id?: string;
- name: string;
- title: string;
- body: string;
- targetUrl: string;
- targetUrlValidationResult?: string;
+ targetUrlValid?: string;
state?: string;
- creativeInstanceId?: string;
+ createdAt?: string;
+ modifiedAt?: string;
+ included: boolean;
};
export const initialConversion: Conversion = {
@@ -87,10 +77,15 @@ export const initialConversion: Conversion = {
export const initialCreative: Creative = {
name: "",
- title: "",
- body: "",
- targetUrl: "",
+ advertiserId: "",
+ payloadNotification: {
+ title: "",
+ targetUrl: "",
+ body: "",
+ },
+ type: { code: "" },
state: "draft",
+ included: false,
};
export const initialAdSet: AdSetForm = {
@@ -104,18 +99,17 @@ export const initialAdSet: AdSetForm = {
export const initialCampaign = (advertiser: IAdvertiser): CampaignForm => {
return {
+ isCreating: false,
advertiserId: advertiser.id,
startAt: defaultStartDate(),
endAt: defaultEndDate(),
validateStart: true,
- isCreating: false,
budget: MIN_PER_CAMPAIGN,
- hasPaymentIntent: false,
- currency: "USD",
dailyBudget: MIN_PER_CAMPAIGN,
- dailyCap: 1,
geoTargets: [],
+ newCreative: initialCreative,
billingType: "cpm",
+ currency: "USD",
price: 6,
adSets: [
{
@@ -126,9 +120,6 @@ export const initialCampaign = (advertiser: IAdvertiser): CampaignForm => {
name: "",
state: "draft",
type: "paid",
- pacingStrategy: CampaignPacingStrategies.ModelV1,
paymentType: advertiser.selfServicePaymentType,
- newCreative: initialCreative,
- creatives: [],
};
};
diff --git a/src/user/views/adsManager/views/advanced/components/adSet/NewAdSet.tsx b/src/user/views/adsManager/views/advanced/components/adSet/NewAdSet.tsx
index 0847965e..f36d63ec 100644
--- a/src/user/views/adsManager/views/advanced/components/adSet/NewAdSet.tsx
+++ b/src/user/views/adsManager/views/advanced/components/adSet/NewAdSet.tsx
@@ -13,8 +13,10 @@ import { CampaignForm, initialAdSet } from "user/views/adsManager/types";
import { useRef } from "react";
import RemoveCircleOutlineIcon from "@mui/icons-material/RemoveCircleOutline";
import { useIsEdit } from "form/FormikHelpers";
+import { useAdvertiserCreatives } from "user/hooks/useAdvertiserCreatives";
export function NewAdSet() {
+ const { creatives } = useAdvertiserCreatives();
const { isEdit } = useIsEdit();
const history = useHistory();
const { values } = useFormikContext();
@@ -22,6 +24,11 @@ export function NewAdSet() {
const selected = useRef(0);
selected.current = Number(params.get("current") ?? 0);
+ const initial = {
+ ...initialAdSet,
+ creatives,
+ };
+
return (
<>
@@ -77,7 +84,7 @@ export function NewAdSet() {
pb={0}
pt={0}
component={Button}
- onClick={() => helper.push(initialAdSet)}
+ onClick={() => helper.push(initial)}
border="1px solid #ededed"
>
diff --git a/src/user/views/adsManager/views/advanced/components/adSet/fields/AdSetAds.tsx b/src/user/views/adsManager/views/advanced/components/adSet/fields/AdSetAds.tsx
index 1289451a..123e825f 100644
--- a/src/user/views/adsManager/views/advanced/components/adSet/fields/AdSetAds.tsx
+++ b/src/user/views/adsManager/views/advanced/components/adSet/fields/AdSetAds.tsx
@@ -1,54 +1,29 @@
import { CardContainer } from "components/Card/CardContainer";
-import { Autocomplete, Checkbox, TextField } from "@mui/material";
-import { useRecentlyCreatedAdvertiserCreatives } from "user/hooks/useAdvertiserCreatives";
-import CheckBoxOutlineBlankIcon from "@mui/icons-material/CheckBoxOutlineBlank";
-import CheckBoxIcon from "@mui/icons-material/CheckBox";
-import { useField } from "formik";
-import { Creative } from "user/views/adsManager/types";
-import _ from "lodash";
+import { Typography } from "@mui/material";
+import { CampaignForm } from "user/views/adsManager/types";
+import { useFormikContext } from "formik";
+import { CampaignFormat } from "graphql/types";
+import { NotificationSelect } from "components/Creatives/NotificationSelect";
interface Props {
index: number;
}
export function AdSetAds({ index }: Props) {
- const creatives = useRecentlyCreatedAdvertiserCreatives();
- const [, meta, helper] = useField(`adSets.${index}.creatives`);
+ const { values } = useFormikContext();
return (
- option.name}
- renderOption={(props, option, { selected }) => (
-
- }
- checkedIcon={}
- style={{ marginRight: 8 }}
- checked={selected}
- />
- {option.name}
-
- )}
- renderInput={(params) => (
-
- )}
- isOptionEqualToValue={(option, value) => option.id === value.id}
- value={meta.value}
- onChange={(_ev, value) => {
- helper.setValue(_.sortBy(value, "name"));
- }}
- onBlur={() => helper.setTouched(true)}
- />
+
+ Select the Ads you would like to include in this ad set.
+
+
+ {values.format === CampaignFormat.PushNotification && (
+
+ )}
);
}
diff --git a/src/user/views/adsManager/views/advanced/components/form/EditCampaign.tsx b/src/user/views/adsManager/views/advanced/components/form/EditCampaign.tsx
index a5bdadd0..a9e259ae 100644
--- a/src/user/views/adsManager/views/advanced/components/form/EditCampaign.tsx
+++ b/src/user/views/adsManager/views/advanced/components/form/EditCampaign.tsx
@@ -36,14 +36,15 @@ export function EditCampaign() {
fetchPolicy: "cache-and-network",
});
+ const hasPaymentIntent = initialData?.campaign?.hasPaymentIntent;
const [mutation] = useUpdateCampaignMutation({
onCompleted(data) {
- if (initialData?.campaign?.hasPaymentIntent) {
+ if (hasPaymentIntent) {
history.push(
`/user/main/complete/edit?referenceId=${data.updateCampaign.id}`,
);
} else {
- createPaymentSession(data.updateCampaign.id);
+ void createPaymentSession(data.updateCampaign.id);
}
},
onError() {
@@ -85,7 +86,7 @@ export function EditCampaign() {
}}
validationSchema={CampaignSchema}
>
-
+
);
diff --git a/src/user/views/adsManager/views/advanced/components/form/components/BaseForm.tsx b/src/user/views/adsManager/views/advanced/components/form/components/BaseForm.tsx
index a2240756..bf964cb2 100644
--- a/src/user/views/adsManager/views/advanced/components/form/components/BaseForm.tsx
+++ b/src/user/views/adsManager/views/advanced/components/form/components/BaseForm.tsx
@@ -8,9 +8,16 @@ import { AdSetFields } from "user/views/adsManager/views/advanced/components/adS
import { NewAdSet } from "user/views/adsManager/views/advanced/components/adSet/NewAdSet";
import { Route, Switch, useRouteMatch } from "react-router-dom";
import { BudgetSettings } from "user/views/adsManager/views/advanced/components/campaign/BudgetSettings";
+import { FormContext } from "state/context";
+import { useState } from "react";
-export function BaseForm() {
+interface Props {
+ hasPaymentIntent?: boolean | null;
+}
+
+export function BaseForm({ hasPaymentIntent }: Props) {
const { url } = useRouteMatch();
+ const [isShowingAds, setIsShowingAds] = useState(false);
const steps = [
{
@@ -43,16 +50,28 @@ export function BaseForm() {
];
return (
-
+
+
+
);
}
diff --git a/src/user/views/adsManager/views/advanced/components/form/components/PaymentButton.tsx b/src/user/views/adsManager/views/advanced/components/form/components/PaymentButton.tsx
index 665b3d16..aa9c8fb1 100644
--- a/src/user/views/adsManager/views/advanced/components/form/components/PaymentButton.tsx
+++ b/src/user/views/adsManager/views/advanced/components/form/components/PaymentButton.tsx
@@ -1,17 +1,14 @@
import { FormikSubmitButton, useIsEdit } from "form/FormikHelpers";
-import { useFormikContext } from "formik";
-import { CampaignForm } from "user/views/adsManager/types";
-export function PaymentButton() {
+export function PaymentButton(props: { hasPaymentIntent: boolean }) {
const { isEdit } = useIsEdit();
- const { values } = useFormikContext();
const paymentText = "Make payment & submit for approval";
return (
();
@@ -20,13 +19,12 @@ export function Review() {
-
-
{values.adSets.map((adSet, adSetIdx) => (
))}
diff --git a/src/user/views/adsManager/views/advanced/components/review/components/AdReview.tsx b/src/user/views/adsManager/views/advanced/components/review/components/AdReview.tsx
deleted file mode 100644
index ce40d382..00000000
--- a/src/user/views/adsManager/views/advanced/components/review/components/AdReview.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import { Stack, Typography } from "@mui/material";
-import { useRecentlyCreatedAdvertiserCreatives } from "user/hooks/useAdvertiserCreatives";
-import { BoxContainer } from "components/Box/BoxContainer";
-import { NotificationPreview } from "user/ads/NotificationPreview";
-import { ReviewContainer } from "user/views/adsManager/views/advanced/components/review/components/ReviewContainer";
-
-export function AdReview() {
- const creatives = useRecentlyCreatedAdvertiserCreatives();
-
- return (
-
- {creatives.length === 0 && (
- No Recently Created Ads
- )}
-
- {creatives.map((c) => (
-
-
-
- ))}
-
-
- );
-}
diff --git a/src/user/views/adsManager/views/advanced/components/review/components/AdSetReview.tsx b/src/user/views/adsManager/views/advanced/components/review/components/AdSetReview.tsx
index c988b55c..1917ae07 100644
--- a/src/user/views/adsManager/views/advanced/components/review/components/AdSetReview.tsx
+++ b/src/user/views/adsManager/views/advanced/components/review/components/AdSetReview.tsx
@@ -3,19 +3,23 @@ import { FormikErrors } from "formik";
import { ConversionDisplay } from "components/Conversion/ConversionDisplay";
import { ReviewField } from "./ReviewField";
import { ReviewContainer } from "user/views/adsManager/views/advanced/components/review/components/ReviewContainer";
+import { CampaignFormat } from "graphql/types";
+import { CreativeSpecificPreview } from "components/Creatives/CreativeSpecificPreview";
interface Props {
idx: number;
adSet: AdSetForm;
+ format: CampaignFormat;
errors?: string | FormikErrors;
}
export function AdSetReview({ adSet, idx, errors }: Props) {
+ const included = adSet.creatives.filter((c) => c.included);
+ const hasErrors = !!errors;
if (typeof errors === "string") {
return <>{errors}>;
}
- const hasErrors = !!errors;
const adSetError = errors;
const mapToString = (arr: Segment[] | OS[] | Creative[]) => {
@@ -47,9 +51,9 @@ export function AdSetReview({ adSet, idx, errors }: Props) {
conversions={adSet.conversions}
convErrors={adSetError?.conversions}
/>
-
diff --git a/src/validation/CampaignSchema.tsx b/src/validation/CampaignSchema.tsx
index 33f2fbb4..a1b9efa8 100644
--- a/src/validation/CampaignSchema.tsx
+++ b/src/validation/CampaignSchema.tsx
@@ -1,12 +1,8 @@
import { array, boolean, date, number, object, ref, string } from "yup";
import { startOfDay } from "date-fns";
import { twoDaysOut } from "form/DateFieldHelpers";
-import _ from "lodash";
-
-export const SimpleUrlRegexp = /https:\/\/.+\.[a-zA-Z]{2,}\/?.*/g;
-const NoSpacesRegex = /^\S*$/;
-const TrailingAsteriskRegex = /.*\*$/;
-const HttpsRegex = /^https:\/\//;
+import { TrailingAsteriskRegex } from "validation/regex";
+import { CreativeSchema } from "validation/CreativeSchema";
export const MIN_PER_DAY = 33;
export const MIN_PER_CAMPAIGN = 100;
@@ -20,34 +16,9 @@ export const CampaignSchema = object().shape({
MIN_PER_CAMPAIGN,
`Lifetime budget must be $${MIN_PER_CAMPAIGN} or more`,
),
- isCreating: boolean().default(false),
newCreative: object().when("isCreating", {
is: true,
- then: (schema) =>
- schema.shape({
- name: string().label("Creative Name").required("Ad Name is required"),
- title: string()
- .label("Title")
- .max(30, "Maximum 30 Characters")
- .required("Ad Title is required"),
- body: string()
- .label("Body")
- .max(60, "Maximum 60 Characters")
- .required("Ad Body is required"),
- targetUrlValidationResult: string().test({
- test: (value) => _.isEmpty(value),
- message: ({ value }) => value,
- }),
- targetUrl: string()
- .label("Target Url")
- .required("Ad URL is required")
- .matches(NoSpacesRegex, `Ad URL must not contain any whitespace`)
- .matches(HttpsRegex, `URL must start with https://`)
- .matches(
- SimpleUrlRegexp,
- `Please enter a valid Ad URL, for example https://brave.com`,
- ),
- }),
+ then: () => CreativeSchema,
}),
validateStart: boolean(),
dailyBudget: number()
@@ -148,7 +119,11 @@ export const CampaignSchema = object().shape({
.required("Conversion Type required."),
}),
),
- creatives: array().min(1, "Ad Sets must have at least one Ad"),
+ creatives: array().test(
+ "min-length",
+ "Ad Sets must have at least one Ad",
+ (value) => (value ?? []).filter((c) => c.included).length > 0,
+ ),
}),
),
});
diff --git a/src/validation/CreativeSchema.test.ts b/src/validation/CreativeSchema.test.ts
new file mode 100644
index 00000000..a5242735
--- /dev/null
+++ b/src/validation/CreativeSchema.test.ts
@@ -0,0 +1,65 @@
+import { CreativeSchema } from "./CreativeSchema";
+import { produce } from "immer";
+
+const validPushCreative = {
+ name: "some creative",
+ type: { code: "notification_all_v1", name: "" },
+ state: "under_review",
+ payloadNotification: {
+ body: "abc",
+ title: "xyz",
+ targetUrl: "https://hello.com",
+ },
+};
+
+it("should pass on a valid object", () => {
+ CreativeSchema.validateSync(validPushCreative);
+});
+
+it.each([
+ "https://example.com",
+ "https://www.secure2.sophos.com/en-us/security-news-trends/whitepapers/gated-wp/endpoint-buyers-guide.aspx?cmp=134766&utm_source=Brave&utm_campaign=ASEAN%7CBrave%7CEndpointBuyer%27sGuide%7CITFocus&utm_medium=cpc&utm_content=SM116529",
+ "https://test.io?bar=baz#foo",
+])("should pass if push notification is selected for %s", (value) => {
+ const c = produce(validPushCreative, (draft) => {
+ draft.payloadNotification.targetUrl = value;
+ });
+
+ expect(() => CreativeSchema.validateSync(c));
+});
+
+it.each(["notAUrl", "gopher://blah.com", "httpx://balh.com"])(
+ "should reject as invalid url if push notification is selected for %s",
+ (value) => {
+ const c = produce(validPushCreative, (draft) => {
+ draft.payloadNotification.targetUrl = value;
+ });
+ expect(() => CreativeSchema.validateSync(c)).toThrowError(
+ "URL must start with https://",
+ );
+ },
+);
+
+it.each(["https://with a space"])(
+ "should reject as invalid input if push notification is selected for %s",
+ (value) => {
+ const c = produce(validPushCreative, (draft) => {
+ draft.payloadNotification.targetUrl = value;
+ });
+ expect(() => CreativeSchema.validateSync(c)).toThrowError(
+ "URL must not contain any whitespace",
+ );
+ },
+);
+
+it.each(["http://example.com"])(
+ "should reject as not secure if push notification is selected for %s",
+ (value) => {
+ const c = produce(validPushCreative, (draft) => {
+ draft.payloadNotification.targetUrl = value;
+ });
+ expect(() => CreativeSchema.validateSync(c)).toThrowError(
+ "URL must start with https://",
+ );
+ },
+);
diff --git a/src/validation/CreativeSchema.tsx b/src/validation/CreativeSchema.tsx
new file mode 100644
index 00000000..1abbbc11
--- /dev/null
+++ b/src/validation/CreativeSchema.tsx
@@ -0,0 +1,48 @@
+import { object, string } from "yup";
+import { HttpsRegex, NoSpacesRegex, SimpleUrlRegexp } from "validation/regex";
+import _ from "lodash";
+
+export const CreativeSchema = object().shape({
+ name: string().label("Creative Name").required(),
+ type: object().shape({
+ code: string()
+ .oneOf([
+ "notification_all_v1",
+ "new_tab_page_all_v1",
+ "inline_content_all_v1",
+ "search_all_v1",
+ "search_homepage_all_v1",
+ ])
+ .label("Creative Type")
+ .required("Creative Type is required"),
+ name: string(),
+ }),
+ state: string()
+ .oneOf(["draft", "under_review"])
+ .label("State")
+ .required()
+ .default("draft"),
+ targetUrlValid: string().test({
+ test: (value) => _.isEmpty(value),
+ message: ({ value }) => value,
+ }),
+ payloadNotification: object()
+ .nullable()
+ .when("type.code", {
+ is: "notification_all_v1",
+ then: (schema) =>
+ schema.required().shape({
+ body: string().label("Body").required().max(60),
+ targetUrl: string()
+ .label("Target Url")
+ .required("URL is required")
+ .matches(NoSpacesRegex, `URL must not contain any whitespace`)
+ .matches(HttpsRegex, `URL must start with https://`)
+ .matches(
+ SimpleUrlRegexp,
+ `Please enter a valid Ad URL, for example https://brave.com`,
+ ),
+ title: string().label("Title").required().max(30),
+ }),
+ }),
+});
diff --git a/src/validation/regex.ts b/src/validation/regex.ts
new file mode 100644
index 00000000..4d171332
--- /dev/null
+++ b/src/validation/regex.ts
@@ -0,0 +1,4 @@
+export const SimpleUrlRegexp = /https:\/\/.+\.[a-zA-Z]{2,}\/?.*/g;
+export const NoSpacesRegex = /^\S*$/;
+export const TrailingAsteriskRegex = /.*\*$/;
+export const HttpsRegex = /^https:\/\//;
From 1b9955e4e6afdb51b587086c6edc9db26a685dac Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 1 Sep 2023 09:59:24 -0400
Subject: [PATCH 2/4] fix(deps): update all non-major dependencies (#844)
* fix(deps): update all non-major dependencies
* fix: switch adapters
* fix: re-rerun install
---------
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Ian Krieger
---
package-lock.json | 825 +++++++++++++-------
package.json | 50 +-
src/auth/views/components/AuthContainer.tsx | 7 +-
src/components/Date/DateRangePicker.tsx | 4 +-
4 files changed, 561 insertions(+), 325 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index aa3f4d8c..82fe9fc4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,23 +8,23 @@
"name": "ads-ui",
"version": "0.1.0",
"dependencies": {
- "@apollo/client": "3.7.17",
- "@date-io/moment": "2.16.1",
+ "@apollo/client": "3.8.1",
+ "@date-io/moment": "2.17.0",
"@emotion/react": "11.11.1",
"@emotion/styled": "11.11.0",
- "@fontsource/mulish": "5.0.5",
- "@fontsource/poppins": "5.0.5",
- "@mui/icons-material": "5.14.0",
- "@mui/lab": "5.0.0-alpha.136",
- "@mui/material": "5.14.0",
+ "@fontsource/mulish": "5.0.8",
+ "@fontsource/poppins": "5.0.8",
+ "@mui/icons-material": "5.14.6",
+ "@mui/lab": "5.0.0-alpha.141",
+ "@mui/material": "5.14.6",
"@mui/x-date-pickers": "5.0.20",
- "axios": "1.4.0",
+ "axios": "1.5.0",
"base64url": "3.0.1",
- "bignumber.js": "9.1.1",
+ "bignumber.js": "9.1.2",
"date-fns": "2.30.0",
"date-fns-tz": "2.0.0",
- "formik": "2.4.2",
- "graphql": "16.7.1",
+ "formik": "2.4.3",
+ "graphql": "16.8.0",
"highcharts": "11.1.0",
"highcharts-react-official": "3.2.0",
"immer": "10.0.2",
@@ -49,26 +49,26 @@
"@graphql-codegen/visitor-plugin-common": "2.13.8",
"@types/chart.js": "2.9.37",
"@types/classnames": "2.3.0",
- "@types/jest": "29.5.3",
+ "@types/jest": "29.5.4",
"@types/jwt-decode": "2.2.1",
- "@types/lodash": "4.14.195",
- "@types/react": "18.2.15",
+ "@types/lodash": "4.14.197",
+ "@types/react": "18.2.21",
"@types/react-dom": "18.2.7",
"@types/react-router-dom": "5.3.3",
- "@typescript-eslint/eslint-plugin": "6.3.0",
- "@typescript-eslint/parser": "6.3.0",
+ "@typescript-eslint/eslint-plugin": "6.4.1",
+ "@typescript-eslint/parser": "6.4.1",
"@vitejs/plugin-basic-ssl": "1.0.1",
- "@vitejs/plugin-react": "4.0.3",
- "eslint": "8.46.0",
+ "@vitejs/plugin-react": "4.0.4",
+ "eslint": "8.48.0",
"eslint-config-prettier": "9.0.0",
- "eslint-plugin-react": "7.33.1",
+ "eslint-plugin-react": "7.33.2",
"husky": "8.0.3",
- "prettier": "3.0.0",
- "typescript": "5.1.6",
- "vite": "4.4.4",
- "vite-plugin-checker": "0.6.1",
+ "prettier": "3.0.2",
+ "typescript": "5.2.2",
+ "vite": "4.4.9",
+ "vite-plugin-checker": "0.6.2",
"vite-tsconfig-paths": "4.2.0",
- "vitest": "0.33.0"
+ "vitest": "0.34.3"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
@@ -107,17 +107,17 @@
}
},
"node_modules/@apollo/client": {
- "version": "3.7.17",
- "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.7.17.tgz",
- "integrity": "sha512-0EErSHEtKPNl5wgWikHJbKFAzJ/k11O0WO2QyqZSHpdxdAnw7UWHY4YiLbHCFG7lhrD+NTQ3Z/H9Jn4rcikoJA==",
+ "version": "3.8.1",
+ "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.8.1.tgz",
+ "integrity": "sha512-JGGj/9bdoLEqzatRikDeN8etseY5qeFAY0vSAx/Pd0ePNsaflKzHx6V2NZ0NsGkInq+9IXXX3RLVDf0EotizMA==",
"dependencies": {
"@graphql-typed-document-node/core": "^3.1.1",
- "@wry/context": "^0.7.0",
- "@wry/equality": "^0.5.0",
- "@wry/trie": "^0.4.0",
+ "@wry/context": "^0.7.3",
+ "@wry/equality": "^0.5.6",
+ "@wry/trie": "^0.4.3",
"graphql-tag": "^2.12.6",
"hoist-non-react-statics": "^3.3.2",
- "optimism": "^0.16.2",
+ "optimism": "^0.17.5",
"prop-types": "^15.7.2",
"response-iterator": "^0.2.6",
"symbol-observable": "^4.0.0",
@@ -147,17 +147,6 @@
}
}
},
- "node_modules/@apollo/client/node_modules/@wry/trie": {
- "version": "0.4.3",
- "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.4.3.tgz",
- "integrity": "sha512-I6bHwH0fSf6RqQcnnXLJKhkSXG45MFral3GxPaY4uAl0LYDZM+YDVDAiU9bYwjTuysy1S0IeecWtmq1SZA3M1w==",
- "dependencies": {
- "tslib": "^2.3.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/@ardatan/relay-compiler": {
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/@ardatan/relay-compiler/-/relay-compiler-12.0.0.tgz",
@@ -1180,11 +1169,11 @@
}
},
"node_modules/@babel/runtime": {
- "version": "7.22.6",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz",
- "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==",
+ "version": "7.22.11",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.11.tgz",
+ "integrity": "sha512-ee7jVNlWN09+KftVOu9n7S8gQzD/Z6hN/I8VBRXW4P1+Xe7kJGXMwu8vds4aGIMHZnNbdpSWCfZZtinytpcAvA==",
"dependencies": {
- "regenerator-runtime": "^0.13.11"
+ "regenerator-runtime": "^0.14.0"
},
"engines": {
"node": ">=6.9.0"
@@ -1261,9 +1250,9 @@
}
},
"node_modules/@date-io/core": {
- "version": "2.16.0",
- "resolved": "https://registry.npmjs.org/@date-io/core/-/core-2.16.0.tgz",
- "integrity": "sha512-DYmSzkr+jToahwWrsiRA2/pzMEtz9Bq1euJwoOuYwuwIYXnZFtHajY2E6a1VNVDc9jP8YUXK1BvnZH9mmT19Zg=="
+ "version": "2.17.0",
+ "resolved": "https://registry.npmjs.org/@date-io/core/-/core-2.17.0.tgz",
+ "integrity": "sha512-+EQE8xZhRM/hsY0CDTVyayMDDY5ihc4MqXCrPxooKw19yAzUIC6uUqsZeaOFNL9YKTNxYKrJP5DFgE8o5xRCOw=="
},
"node_modules/@date-io/date-fns": {
"version": "2.16.0",
@@ -1314,11 +1303,11 @@
}
},
"node_modules/@date-io/moment": {
- "version": "2.16.1",
- "resolved": "https://registry.npmjs.org/@date-io/moment/-/moment-2.16.1.tgz",
- "integrity": "sha512-JkxldQxUqZBfZtsaCcCMkm/dmytdyq5pS1RxshCQ4fHhsvP5A7gSqPD22QbVXMcJydi3d3v1Y8BQdUKEuGACZQ==",
+ "version": "2.17.0",
+ "resolved": "https://registry.npmjs.org/@date-io/moment/-/moment-2.17.0.tgz",
+ "integrity": "sha512-e4nb4CDZU4k0WRVhz1Wvl7d+hFsedObSauDHKtZwU9kt7gdYEAzKgnrSCTHsEaXrDumdrkCYTeZ0Tmyk7uV4tw==",
"dependencies": {
- "@date-io/core": "^2.16.0"
+ "@date-io/core": "^2.17.0"
},
"peerDependencies": {
"moment": "^2.24.0"
@@ -1858,9 +1847,9 @@
}
},
"node_modules/@eslint/eslintrc": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.1.tgz",
- "integrity": "sha512-9t7ZA7NGGK8ckelF0PQCfcxIUzs1Md5rrO6U/c+FIQNanea5UZC0wqKXH4vHBccmu4ZJgZ2idtPeW7+Q2npOEA==",
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz",
+ "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==",
"dev": true,
"dependencies": {
"ajv": "^6.12.4",
@@ -1908,23 +1897,57 @@
}
},
"node_modules/@eslint/js": {
- "version": "8.46.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.46.0.tgz",
- "integrity": "sha512-a8TLtmPi8xzPkCbp/OGFUo5yhRkHM2Ko9kOWP4znJr0WAhWyThaw3PnwX4vOTWOAMsV2uRt32PPDcEz63esSaA==",
+ "version": "8.48.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.48.0.tgz",
+ "integrity": "sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
+ "node_modules/@floating-ui/core": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.4.1.tgz",
+ "integrity": "sha512-jk3WqquEJRlcyu7997NtR5PibI+y5bi+LS3hPmguVClypenMsCY3CBa3LAQnozRCtCrYWSEtAdiskpamuJRFOQ==",
+ "dependencies": {
+ "@floating-ui/utils": "^0.1.1"
+ }
+ },
+ "node_modules/@floating-ui/dom": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.1.tgz",
+ "integrity": "sha512-KwvVcPSXg6mQygvA1TjbN/gh///36kKtllIF8SUm0qpFj8+rvYrpvlYdL1JoA71SHpDqgSSdGOSoQ0Mp3uY5aw==",
+ "dependencies": {
+ "@floating-ui/core": "^1.4.1",
+ "@floating-ui/utils": "^0.1.1"
+ }
+ },
+ "node_modules/@floating-ui/react-dom": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.2.tgz",
+ "integrity": "sha512-5qhlDvjaLmAst/rKb3VdlCinwTF4EYMiVxuuc/HVUjs46W0zgtbMmAZ1UTsDrRTxRmUEzl92mOtWbeeXL26lSQ==",
+ "dependencies": {
+ "@floating-ui/dom": "^1.5.1"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@floating-ui/utils": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.1.tgz",
+ "integrity": "sha512-m0G6wlnhm/AX0H12IOWtK8gASEMffnX08RtKkCgTdHb9JpHKGloI7icFfLg9ZmQeavcvR0PKmzxClyuFPSjKWw=="
+ },
"node_modules/@fontsource/mulish": {
- "version": "5.0.5",
- "resolved": "https://registry.npmjs.org/@fontsource/mulish/-/mulish-5.0.5.tgz",
- "integrity": "sha512-C2eHZ11poELitOhh/73s+NI7PyAAbLMm0FVgnnAesI51ntpDX6bnK4nU+2j/xrajGmSjeKtqFKWjbAVsKkfPzA=="
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/@fontsource/mulish/-/mulish-5.0.8.tgz",
+ "integrity": "sha512-3XWTEYs9FYAL5mgF60NCo9b8+D1OgURPMcmQYkEZt7BEGlRveTwSIRvTcqRjD0UEM9Vzv1MkeolsBytvveL4GA=="
},
"node_modules/@fontsource/poppins": {
- "version": "5.0.5",
- "resolved": "https://registry.npmjs.org/@fontsource/poppins/-/poppins-5.0.5.tgz",
- "integrity": "sha512-Y/AGmD6iavfobRb7f2l49q0dQSyisvRrUfJ7F0AWOlTNFty8bbnPBbg+5Qsq5EN6xWaIAn++50aLfOCEe7zu3w=="
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/@fontsource/poppins/-/poppins-5.0.8.tgz",
+ "integrity": "sha512-P8owfYWluoUY5Nyzk4gT/L6LmLmseP6ezFWhj6VBUa5pRIdnCvNJpoQ6i/vhekjtJOfqX6nKlB+LCttoUl2GQQ=="
},
"node_modules/@graphql-codegen/add": {
"version": "3.2.3",
@@ -2841,19 +2864,19 @@
}
},
"node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.4.14",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
- "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
+ "version": "1.4.15",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
"dev": true
},
"node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.18",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz",
- "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==",
+ "version": "0.3.19",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz",
+ "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==",
"dev": true,
"dependencies": {
- "@jridgewell/resolve-uri": "3.1.0",
- "@jridgewell/sourcemap-codec": "1.4.14"
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@korzio/djv-draft-04": {
@@ -2863,16 +2886,17 @@
"optional": true
},
"node_modules/@mui/base": {
- "version": "5.0.0-beta.7",
- "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.7.tgz",
- "integrity": "sha512-Pjbwm6gjiS96kOMF7E5fjEJsenc0tZBesrLQ4rrdi3eT/c/yhSWnPbCUkHSz8bnS0l3/VQ8bA+oERSGSV2PK6A==",
+ "version": "5.0.0-beta.12",
+ "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.12.tgz",
+ "integrity": "sha512-tZjjXNAyUpwSDT1uRliZMhRQkWYzELJ8Qi61EuOMRpi36HIwnK2T7Nr4RI423Sv8G2EEikDAZj7je33eNd73NQ==",
"dependencies": {
- "@babel/runtime": "^7.22.5",
+ "@babel/runtime": "^7.22.10",
"@emotion/is-prop-valid": "^1.2.1",
+ "@floating-ui/react-dom": "^2.0.1",
"@mui/types": "^7.2.4",
- "@mui/utils": "^5.13.7",
+ "@mui/utils": "^5.14.6",
"@popperjs/core": "^2.11.8",
- "clsx": "^1.2.1",
+ "clsx": "^2.0.0",
"prop-types": "^15.8.1",
"react-is": "^18.2.0"
},
@@ -2894,21 +2918,29 @@
}
}
},
+ "node_modules/@mui/base/node_modules/clsx": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz",
+ "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/@mui/core-downloads-tracker": {
- "version": "5.14.1",
- "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.1.tgz",
- "integrity": "sha512-mIa1WmDmNr1LoupV1Rbxt9bTFKMbIn10RHG1bnZ/FJCkAYpuU/D4n+R+ttiycgcZNngU++zyh/OQeJblzbQPzg==",
+ "version": "5.14.7",
+ "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.7.tgz",
+ "integrity": "sha512-sCWTUNElBPgB30iLvWe3PU7SIlTKZNf6/E/sko85iHVeHCM6WPkDw+y89CrZYjhFNmPqt2fIQM/pZu+rP2lFLA==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mui"
}
},
"node_modules/@mui/icons-material": {
- "version": "5.14.0",
- "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.14.0.tgz",
- "integrity": "sha512-z7lYNteDi1GMkF9JP/m2RWuCYK1M/FlaeBSUK7/IhIYzIXNhAVjfD8jRq5vFBV31qkEi2aGBS2z5SfLXwH6U0A==",
+ "version": "5.14.6",
+ "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.14.6.tgz",
+ "integrity": "sha512-7Cujy7lRGTj2T3SvY9C9ZOTFDtrXJogeNnRcU/ODyNoxwskMNPFOcc15F+98MAdJenBVLJPYu+vPP6DUvEpNrA==",
"dependencies": {
- "@babel/runtime": "^7.22.5"
+ "@babel/runtime": "^7.22.10"
},
"engines": {
"node": ">=12.0.0"
@@ -2929,16 +2961,16 @@
}
},
"node_modules/@mui/lab": {
- "version": "5.0.0-alpha.136",
- "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.136.tgz",
- "integrity": "sha512-ai6LspCkyKRD8rL2HEtaTPBbeYkARNNKvSbjOLVJtro9bIFpZ0noH21Pp7t50Y2eFemuYeC+D5Tto3OvGKrhnQ==",
+ "version": "5.0.0-alpha.141",
+ "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.141.tgz",
+ "integrity": "sha512-PsW55xX2ieNLldca2hLxL1SYtZgRQv++lj1W/Jyi5Z2MHuFDcdqI7yKGrOzyIWw7ctQrmHa1FTShBiCa2wkEoQ==",
"dependencies": {
- "@babel/runtime": "^7.22.5",
- "@mui/base": "5.0.0-beta.7",
- "@mui/system": "^5.14.0",
+ "@babel/runtime": "^7.22.10",
+ "@mui/base": "5.0.0-beta.12",
+ "@mui/system": "^5.14.6",
"@mui/types": "^7.2.4",
- "@mui/utils": "^5.13.7",
- "clsx": "^1.2.1",
+ "@mui/utils": "^5.14.6",
+ "clsx": "^2.0.0",
"prop-types": "^15.8.1",
"react-is": "^18.2.0"
},
@@ -2969,19 +3001,27 @@
}
}
},
+ "node_modules/@mui/lab/node_modules/clsx": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz",
+ "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/@mui/material": {
- "version": "5.14.0",
- "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.14.0.tgz",
- "integrity": "sha512-HP7CP71NhMkui2HUIEKl2/JfuHMuoarSUWAKlNw6s17bl/Num9rN61EM6uUzc2A2zHjj/00A66GnvDnmixEJEw==",
- "dependencies": {
- "@babel/runtime": "^7.22.5",
- "@mui/base": "5.0.0-beta.7",
- "@mui/core-downloads-tracker": "^5.14.0",
- "@mui/system": "^5.14.0",
+ "version": "5.14.6",
+ "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.14.6.tgz",
+ "integrity": "sha512-C3UgGrmtvcGkQkm0ONBU7bTdapTjQc2Se3b2354xMmU7lgSgW7VM6EP9wIH5XqqoJ60m9l/s9kbTWX0Y+EaWvA==",
+ "dependencies": {
+ "@babel/runtime": "^7.22.10",
+ "@mui/base": "5.0.0-beta.12",
+ "@mui/core-downloads-tracker": "^5.14.6",
+ "@mui/system": "^5.14.6",
"@mui/types": "^7.2.4",
- "@mui/utils": "^5.13.7",
+ "@mui/utils": "^5.14.6",
"@types/react-transition-group": "^4.4.6",
- "clsx": "^1.2.1",
+ "clsx": "^2.0.0",
"csstype": "^3.1.2",
"prop-types": "^15.8.1",
"react-is": "^18.2.0",
@@ -3013,13 +3053,21 @@
}
}
},
+ "node_modules/@mui/material/node_modules/clsx": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz",
+ "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/@mui/private-theming": {
- "version": "5.13.7",
- "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.13.7.tgz",
- "integrity": "sha512-qbSr+udcij5F9dKhGX7fEdx2drXchq7htLNr2Qg2Ma+WJ6q0ERlEqGSBiPiVDJkptcjeVL4DGmcf1wl5+vD4EA==",
+ "version": "5.14.7",
+ "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.14.7.tgz",
+ "integrity": "sha512-Y86+hmDnJab2Ka42PgxKpK3oL7EiacbeeX3X/lG9LGO0wSc45wZjHeTfIlVSkkUCkexiMKEJp5NlSjZhr27NRQ==",
"dependencies": {
- "@babel/runtime": "^7.22.5",
- "@mui/utils": "^5.13.7",
+ "@babel/runtime": "^7.22.10",
+ "@mui/utils": "^5.14.7",
"prop-types": "^15.8.1"
},
"engines": {
@@ -3040,11 +3088,11 @@
}
},
"node_modules/@mui/styled-engine": {
- "version": "5.13.2",
- "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.13.2.tgz",
- "integrity": "sha512-VCYCU6xVtXOrIN8lcbuPmoG+u7FYuOERG++fpY74hPpEWkyFQG97F+/XfTQVYzlR2m7nPjnwVUgATcTCMEaMvw==",
+ "version": "5.14.7",
+ "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.14.7.tgz",
+ "integrity": "sha512-hKBETEDsIAkL8/mBwPiQj/vw28OeIhMXC3Tvj4J2bb9snxAKpiZioR1PwqP+6P41twsC/GKBd0Vr9oaWYaHuMg==",
"dependencies": {
- "@babel/runtime": "^7.21.0",
+ "@babel/runtime": "^7.22.10",
"@emotion/cache": "^11.11.0",
"csstype": "^3.1.2",
"prop-types": "^15.8.1"
@@ -3071,16 +3119,16 @@
}
},
"node_modules/@mui/system": {
- "version": "5.14.1",
- "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.14.1.tgz",
- "integrity": "sha512-u+xlsU34Jdkgx1CxmBnIC4Y08uPdVX5iEd3S/1dggDFtOGp+Lj8xmKRJAQ8PJOOJLOh8pDwaZx4AwXikL4l1QA==",
+ "version": "5.14.7",
+ "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.14.7.tgz",
+ "integrity": "sha512-jeZtHglc+Pi6qjGoopT6O4RqYXVBMqHVOsjMGP0hxGSSPm1T4gsAu7jU8eqGx9YwwjvvJ0eotTjFqw7iJ6qE2Q==",
"dependencies": {
- "@babel/runtime": "^7.22.6",
- "@mui/private-theming": "^5.13.7",
- "@mui/styled-engine": "^5.13.2",
+ "@babel/runtime": "^7.22.10",
+ "@mui/private-theming": "^5.14.7",
+ "@mui/styled-engine": "^5.14.7",
"@mui/types": "^7.2.4",
- "@mui/utils": "^5.14.1",
- "clsx": "^1.2.1",
+ "@mui/utils": "^5.14.7",
+ "clsx": "^2.0.0",
"csstype": "^3.1.2",
"prop-types": "^15.8.1"
},
@@ -3109,6 +3157,14 @@
}
}
},
+ "node_modules/@mui/system/node_modules/clsx": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz",
+ "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/@mui/types": {
"version": "7.2.4",
"resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.4.tgz",
@@ -3123,11 +3179,11 @@
}
},
"node_modules/@mui/utils": {
- "version": "5.14.1",
- "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.14.1.tgz",
- "integrity": "sha512-39KHKK2JeqRmuUcLDLwM+c2XfVC136C5/yUyQXmO2PVbOb2Bol4KxtkssEqCbTwg87PSCG3f1Tb0keRsK7cVGw==",
+ "version": "5.14.7",
+ "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.14.7.tgz",
+ "integrity": "sha512-RtheP/aBoPogVdi8vj8Vo2IFnRa4mZVmnD0RGlVZ49yF60rZs+xP4/KbpIrTr83xVs34QmHQ2aQ+IX7I0a0dDw==",
"dependencies": {
- "@babel/runtime": "^7.22.6",
+ "@babel/runtime": "^7.22.10",
"@types/prop-types": "^15.7.5",
"@types/react-is": "^18.2.1",
"prop-types": "^15.8.1",
@@ -3403,9 +3459,9 @@
}
},
"node_modules/@types/jest": {
- "version": "29.5.3",
- "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.3.tgz",
- "integrity": "sha512-1Nq7YrO/vJE/FYnqYyw0FS8LdrjExSgIiHyKg7xPpn+yi8Q4huZryKnkJatN1ZRH89Kw2v33/8ZMB7DuZeSLlA==",
+ "version": "29.5.4",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.4.tgz",
+ "integrity": "sha512-PhglGmhWeD46FYOVLt3X7TiWjzwuVGW9wG/4qocPevXMjCmrIc5b6db9WjeGE4QYVpUAWMDv3v0IiBwObY289A==",
"dev": true,
"dependencies": {
"expect": "^29.0.0",
@@ -3446,9 +3502,9 @@
"dev": true
},
"node_modules/@types/lodash": {
- "version": "4.14.195",
- "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.195.tgz",
- "integrity": "sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg==",
+ "version": "4.14.197",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.197.tgz",
+ "integrity": "sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g==",
"dev": true
},
"node_modules/@types/node": {
@@ -3468,9 +3524,9 @@
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
},
"node_modules/@types/react": {
- "version": "18.2.15",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.15.tgz",
- "integrity": "sha512-oEjE7TQt1fFTFSbf8kkNuc798ahTUzn3Le67/PWjE8MAfYAD/qB7O8hSTcromLFqHCt9bcdOg5GXMokzTjJ5SA==",
+ "version": "18.2.21",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.21.tgz",
+ "integrity": "sha512-neFKG/sBAwGxHgXiIxnbm3/AAVQ/cMRS93hvBpg8xYRbeQSPVABp9U2bRnPf0iI4+Ucdv3plSxKK+3CW2ENJxA==",
"dependencies": {
"@types/prop-types": "*",
"@types/scheduler": "*",
@@ -3529,9 +3585,9 @@
"integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="
},
"node_modules/@types/semver": {
- "version": "7.5.0",
- "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz",
- "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==",
+ "version": "7.5.1",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.1.tgz",
+ "integrity": "sha512-cJRQXpObxfNKkFAZbJl2yjWtJCqELQIdShsogr1d2MilP8dKD9TE/nEKHkJgUNHdGKCQaf9HbIynuV2csLGVLg==",
"dev": true
},
"node_modules/@types/stack-utils": {
@@ -3565,21 +3621,20 @@
"dev": true
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.3.0.tgz",
- "integrity": "sha512-IZYjYZ0ifGSLZbwMqIip/nOamFiWJ9AH+T/GYNZBWkVcyNQOFGtSMoWV7RvY4poYCMZ/4lHzNl796WOSNxmk8A==",
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.4.1.tgz",
+ "integrity": "sha512-3F5PtBzUW0dYlq77Lcqo13fv+58KDwUib3BddilE8ajPJT+faGgxmI9Sw+I8ZS22BYwoir9ZhNXcLi+S+I2bkw==",
"dev": true,
"dependencies": {
"@eslint-community/regexpp": "^4.5.1",
- "@typescript-eslint/scope-manager": "6.3.0",
- "@typescript-eslint/type-utils": "6.3.0",
- "@typescript-eslint/utils": "6.3.0",
- "@typescript-eslint/visitor-keys": "6.3.0",
+ "@typescript-eslint/scope-manager": "6.4.1",
+ "@typescript-eslint/type-utils": "6.4.1",
+ "@typescript-eslint/utils": "6.4.1",
+ "@typescript-eslint/visitor-keys": "6.4.1",
"debug": "^4.3.4",
"graphemer": "^1.4.0",
"ignore": "^5.2.4",
"natural-compare": "^1.4.0",
- "natural-compare-lite": "^1.4.0",
"semver": "^7.5.4",
"ts-api-utils": "^1.0.1"
},
@@ -3601,15 +3656,15 @@
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.3.0.tgz",
- "integrity": "sha512-ibP+y2Gr6p0qsUkhs7InMdXrwldjxZw66wpcQq9/PzAroM45wdwyu81T+7RibNCh8oc0AgrsyCwJByncY0Ongg==",
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.4.1.tgz",
+ "integrity": "sha512-610G6KHymg9V7EqOaNBMtD1GgpAmGROsmfHJPXNLCU9bfIuLrkdOygltK784F6Crboyd5tBFayPB7Sf0McrQwg==",
"dev": true,
"dependencies": {
- "@typescript-eslint/scope-manager": "6.3.0",
- "@typescript-eslint/types": "6.3.0",
- "@typescript-eslint/typescript-estree": "6.3.0",
- "@typescript-eslint/visitor-keys": "6.3.0",
+ "@typescript-eslint/scope-manager": "6.4.1",
+ "@typescript-eslint/types": "6.4.1",
+ "@typescript-eslint/typescript-estree": "6.4.1",
+ "@typescript-eslint/visitor-keys": "6.4.1",
"debug": "^4.3.4"
},
"engines": {
@@ -3629,13 +3684,13 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.3.0.tgz",
- "integrity": "sha512-WlNFgBEuGu74ahrXzgefiz/QlVb+qg8KDTpknKwR7hMH+lQygWyx0CQFoUmMn1zDkQjTBBIn75IxtWss77iBIQ==",
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz",
+ "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "6.3.0",
- "@typescript-eslint/visitor-keys": "6.3.0"
+ "@typescript-eslint/types": "6.4.1",
+ "@typescript-eslint/visitor-keys": "6.4.1"
},
"engines": {
"node": "^16.0.0 || >=18.0.0"
@@ -3646,13 +3701,13 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.3.0.tgz",
- "integrity": "sha512-7Oj+1ox1T2Yc8PKpBvOKWhoI/4rWFd1j7FA/rPE0lbBPXTKjdbtC+7Ev0SeBjEKkIhKWVeZSP+mR7y1Db1CdfQ==",
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.4.1.tgz",
+ "integrity": "sha512-7ON8M8NXh73SGZ5XvIqWHjgX2f+vvaOarNliGhjrJnv1vdjG0LVIz+ToYfPirOoBi56jxAKLfsLm40+RvxVVXA==",
"dev": true,
"dependencies": {
- "@typescript-eslint/typescript-estree": "6.3.0",
- "@typescript-eslint/utils": "6.3.0",
+ "@typescript-eslint/typescript-estree": "6.4.1",
+ "@typescript-eslint/utils": "6.4.1",
"debug": "^4.3.4",
"ts-api-utils": "^1.0.1"
},
@@ -3673,9 +3728,9 @@
}
},
"node_modules/@typescript-eslint/types": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.3.0.tgz",
- "integrity": "sha512-K6TZOvfVyc7MO9j60MkRNWyFSf86IbOatTKGrpTQnzarDZPYPVy0oe3myTMq7VjhfsUAbNUW8I5s+2lZvtx1gg==",
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz",
+ "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==",
"dev": true,
"engines": {
"node": "^16.0.0 || >=18.0.0"
@@ -3686,13 +3741,13 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.3.0.tgz",
- "integrity": "sha512-Xh4NVDaC4eYKY4O3QGPuQNp5NxBAlEvNQYOqJquR2MePNxO11E5K3t5x4M4Mx53IZvtpW+mBxIT0s274fLUocg==",
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz",
+ "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "6.3.0",
- "@typescript-eslint/visitor-keys": "6.3.0",
+ "@typescript-eslint/types": "6.4.1",
+ "@typescript-eslint/visitor-keys": "6.4.1",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
@@ -3713,17 +3768,17 @@
}
},
"node_modules/@typescript-eslint/utils": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.3.0.tgz",
- "integrity": "sha512-hLLg3BZE07XHnpzglNBG8P/IXq/ZVXraEbgY7FM0Cnc1ehM8RMdn9mat3LubJ3KBeYXXPxV1nugWbQPjGeJk6Q==",
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.4.1.tgz",
+ "integrity": "sha512-F/6r2RieNeorU0zhqZNv89s9bDZSovv3bZQpUNOmmQK1L80/cV4KEu95YUJWi75u5PhboFoKUJBnZ4FQcoqhDw==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
"@types/json-schema": "^7.0.12",
"@types/semver": "^7.5.0",
- "@typescript-eslint/scope-manager": "6.3.0",
- "@typescript-eslint/types": "6.3.0",
- "@typescript-eslint/typescript-estree": "6.3.0",
+ "@typescript-eslint/scope-manager": "6.4.1",
+ "@typescript-eslint/types": "6.4.1",
+ "@typescript-eslint/typescript-estree": "6.4.1",
"semver": "^7.5.4"
},
"engines": {
@@ -3738,12 +3793,12 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.3.0.tgz",
- "integrity": "sha512-kEhRRj7HnvaSjux1J9+7dBen15CdWmDnwrpyiHsFX6Qx2iW5LOBUgNefOFeh2PjWPlNwN8TOn6+4eBU3J/gupw==",
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz",
+ "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "6.3.0",
+ "@typescript-eslint/types": "6.4.1",
"eslint-visitor-keys": "^3.4.1"
},
"engines": {
@@ -3767,12 +3822,12 @@
}
},
"node_modules/@vitejs/plugin-react": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.0.3.tgz",
- "integrity": "sha512-pwXDog5nwwvSIzwrvYYmA2Ljcd/ZNlcsSG2Q9CNDBwnsd55UGAyr2doXtB5j+2uymRCnCfExlznzzSFbBRcoCg==",
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.0.4.tgz",
+ "integrity": "sha512-7wU921ABnNYkETiMaZy7XqpueMnpu5VxvVps13MjmCo+utBdD79sZzrApHawHtVX66cCJQQTXFcjH0y9dSUK8g==",
"dev": true,
"dependencies": {
- "@babel/core": "^7.22.5",
+ "@babel/core": "^7.22.9",
"@babel/plugin-transform-react-jsx-self": "^7.22.5",
"@babel/plugin-transform-react-jsx-source": "^7.22.5",
"react-refresh": "^0.14.0"
@@ -3785,13 +3840,13 @@
}
},
"node_modules/@vitest/expect": {
- "version": "0.33.0",
- "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.33.0.tgz",
- "integrity": "sha512-sVNf+Gla3mhTCxNJx+wJLDPp/WcstOe0Ksqz4Vec51MmgMth/ia0MGFEkIZmVGeTL5HtjYR4Wl/ZxBxBXZJTzQ==",
+ "version": "0.34.3",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.3.tgz",
+ "integrity": "sha512-F8MTXZUYRBVsYL1uoIft1HHWhwDbSzwAU9Zgh8S6WFC3YgVb4AnFV2GXO3P5Em8FjEYaZtTnQYoNwwBrlOMXgg==",
"dev": true,
"dependencies": {
- "@vitest/spy": "0.33.0",
- "@vitest/utils": "0.33.0",
+ "@vitest/spy": "0.34.3",
+ "@vitest/utils": "0.34.3",
"chai": "^4.3.7"
},
"funding": {
@@ -3799,12 +3854,12 @@
}
},
"node_modules/@vitest/runner": {
- "version": "0.33.0",
- "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.33.0.tgz",
- "integrity": "sha512-UPfACnmCB6HKRHTlcgCoBh6ppl6fDn+J/xR8dTufWiKt/74Y9bHci5CKB8tESSV82zKYtkBJo9whU3mNvfaisg==",
+ "version": "0.34.3",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.3.tgz",
+ "integrity": "sha512-lYNq7N3vR57VMKMPLVvmJoiN4bqwzZ1euTW+XXYH5kzr3W/+xQG3b41xJn9ChJ3AhYOSoweu974S1V3qDcFESA==",
"dev": true,
"dependencies": {
- "@vitest/utils": "0.33.0",
+ "@vitest/utils": "0.34.3",
"p-limit": "^4.0.0",
"pathe": "^1.1.1"
},
@@ -3840,9 +3895,9 @@
}
},
"node_modules/@vitest/snapshot": {
- "version": "0.33.0",
- "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.33.0.tgz",
- "integrity": "sha512-tJjrl//qAHbyHajpFvr8Wsk8DIOODEebTu7pgBrP07iOepR5jYkLFiqLq2Ltxv+r0uptUb4izv1J8XBOwKkVYA==",
+ "version": "0.34.3",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.3.tgz",
+ "integrity": "sha512-QyPaE15DQwbnIBp/yNJ8lbvXTZxS00kRly0kfFgAD5EYmCbYcA+1EEyRalc93M0gosL/xHeg3lKAClIXYpmUiQ==",
"dev": true,
"dependencies": {
"magic-string": "^0.30.1",
@@ -3854,9 +3909,9 @@
}
},
"node_modules/@vitest/spy": {
- "version": "0.33.0",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.33.0.tgz",
- "integrity": "sha512-Kv+yZ4hnH1WdiAkPUQTpRxW8kGtH8VRTnus7ZTGovFYM1ZezJpvGtb9nPIjPnptHbsyIAxYZsEpVPYgtpjGnrg==",
+ "version": "0.34.3",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.3.tgz",
+ "integrity": "sha512-N1V0RFQ6AI7CPgzBq9kzjRdPIgThC340DGjdKdPSE8r86aUSmeliTUgkTqLSgtEwWWsGfBQ+UetZWhK0BgJmkQ==",
"dev": true,
"dependencies": {
"tinyspy": "^2.1.1"
@@ -3866,9 +3921,9 @@
}
},
"node_modules/@vitest/utils": {
- "version": "0.33.0",
- "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.33.0.tgz",
- "integrity": "sha512-pF1w22ic965sv+EN6uoePkAOTkAPWM03Ri/jXNyMIKBb/XHLDPfhLvf/Fa9g0YECevAIz56oVYXhodLvLQ/awA==",
+ "version": "0.34.3",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.3.tgz",
+ "integrity": "sha512-kiSnzLG6m/tiT0XEl4U2H8JDBjFtwVlaE8I3QfGiMFR0QvnRDfYfdP3YvTBWM/6iJDAyaPY6yVQiCTUc7ZzTHA==",
"dev": true,
"dependencies": {
"diff-sequences": "^29.4.3",
@@ -3913,9 +3968,9 @@
}
},
"node_modules/@wry/context": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.7.0.tgz",
- "integrity": "sha512-LcDAiYWRtwAoSOArfk7cuYvFXytxfVrdX7yxoUmK7pPITLk5jYh2F8knCwS7LjgYL8u1eidPlKKV6Ikqq0ODqQ==",
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.7.3.tgz",
+ "integrity": "sha512-Nl8WTesHp89RF803Se9X3IiHjdmLBrIvPMaJkl+rKVJAYyPsz1TEUbu89943HpvujtSJgDUx9W4vZw3K1Mr3sA==",
"dependencies": {
"tslib": "^2.3.0"
},
@@ -3924,9 +3979,9 @@
}
},
"node_modules/@wry/equality": {
- "version": "0.5.3",
- "resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.5.3.tgz",
- "integrity": "sha512-avR+UXdSrsF2v8vIqIgmeTY0UR91UT+IyablCyKe/uk22uOJ8fusKZnH9JH9e1/EtLeNJBtagNmL3eJdnOV53g==",
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.5.6.tgz",
+ "integrity": "sha512-D46sfMTngaYlrH+OspKf8mIJETntFnf6Hsjb0V41jAXJ7Bx2kB8Rv8RCUujuVWYttFtHkUNp7g+FwxNQAr6mXA==",
"dependencies": {
"tslib": "^2.3.0"
},
@@ -3935,9 +3990,9 @@
}
},
"node_modules/@wry/trie": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.3.2.tgz",
- "integrity": "sha512-yRTyhWSls2OY/pYLfwff867r8ekooZ4UI+/gxot5Wj8EFwSf2rG+n+Mo/6LoLQm1TKA4GRj2+LCpbfS937dClQ==",
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.4.3.tgz",
+ "integrity": "sha512-I6bHwH0fSf6RqQcnnXLJKhkSXG45MFral3GxPaY4uAl0LYDZM+YDVDAiU9bYwjTuysy1S0IeecWtmq1SZA3M1w==",
"dependencies": {
"tslib": "^2.3.0"
},
@@ -4257,6 +4312,15 @@
"node": ">=8"
}
},
+ "node_modules/asynciterator.prototype": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz",
+ "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ }
+ },
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -4297,9 +4361,9 @@
}
},
"node_modules/axios": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz",
- "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==",
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.0.tgz",
+ "integrity": "sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==",
"dependencies": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
@@ -4399,9 +4463,9 @@
}
},
"node_modules/bignumber.js": {
- "version": "9.1.1",
- "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.1.tgz",
- "integrity": "sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig==",
+ "version": "9.1.2",
+ "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz",
+ "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==",
"engines": {
"node": "*"
}
@@ -5421,6 +5485,28 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/es-iterator-helpers": {
+ "version": "1.0.14",
+ "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.14.tgz",
+ "integrity": "sha512-JgtVnwiuoRuzLvqelrvN3Xu7H9bu2ap/kQ2CrM62iidP8SKuD99rWU3CJy++s7IVL2qb/AjXPGR/E7i9ngd/Cw==",
+ "dev": true,
+ "dependencies": {
+ "asynciterator.prototype": "^1.0.0",
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-set-tostringtag": "^2.0.1",
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.2.1",
+ "globalthis": "^1.0.3",
+ "has-property-descriptors": "^1.0.0",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.5",
+ "iterator.prototype": "^1.1.0",
+ "safe-array-concat": "^1.0.0"
+ }
+ },
"node_modules/es-set-tostringtag": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz",
@@ -5540,15 +5626,15 @@
}
},
"node_modules/eslint": {
- "version": "8.46.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.46.0.tgz",
- "integrity": "sha512-cIO74PvbW0qU8e0mIvk5IV3ToWdCq5FYG6gWPHHkx6gNdjlbAYvtfHmlCMXxjcoVaIdwy/IAt3+mDkZkfvb2Dg==",
+ "version": "8.48.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.48.0.tgz",
+ "integrity": "sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1",
- "@eslint/eslintrc": "^2.1.1",
- "@eslint/js": "^8.46.0",
+ "@eslint/eslintrc": "^2.1.2",
+ "@eslint/js": "8.48.0",
"@humanwhocodes/config-array": "^0.11.10",
"@humanwhocodes/module-importer": "^1.0.1",
"@nodelib/fs.walk": "^1.2.8",
@@ -5559,7 +5645,7 @@
"doctrine": "^3.0.0",
"escape-string-regexp": "^4.0.0",
"eslint-scope": "^7.2.2",
- "eslint-visitor-keys": "^3.4.2",
+ "eslint-visitor-keys": "^3.4.3",
"espree": "^9.6.1",
"esquery": "^1.4.2",
"esutils": "^2.0.2",
@@ -5606,15 +5692,16 @@
}
},
"node_modules/eslint-plugin-react": {
- "version": "7.33.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.1.tgz",
- "integrity": "sha512-L093k0WAMvr6VhNwReB8VgOq5s2LesZmrpPdKz/kZElQDzqS7G7+DnKoqT+w4JwuiGeAhAvHO0fvy0Eyk4ejDA==",
+ "version": "7.33.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz",
+ "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==",
"dev": true,
"dependencies": {
"array-includes": "^3.1.6",
"array.prototype.flatmap": "^1.3.1",
"array.prototype.tosorted": "^1.1.1",
"doctrine": "^2.1.0",
+ "es-iterator-helpers": "^1.0.12",
"estraverse": "^5.3.0",
"jsx-ast-utils": "^2.4.1 || ^3.0.0",
"minimatch": "^3.1.2",
@@ -5680,9 +5767,9 @@
}
},
"node_modules/eslint-visitor-keys": {
- "version": "3.4.2",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.2.tgz",
- "integrity": "sha512-8drBzUEyZ2llkpCA67iYrgEssKDUu68V8ChqqOfFupIaG/LCVPUT+CoGJpT77zJprs4T/W7p07LP7zAIMuweVw==",
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -5716,9 +5803,9 @@
}
},
"node_modules/eslint/node_modules/globals": {
- "version": "13.20.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
- "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
+ "version": "13.21.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz",
+ "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==",
"dev": true,
"dependencies": {
"type-fest": "^0.20.2"
@@ -6060,9 +6147,9 @@
}
},
"node_modules/formik": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/formik/-/formik-2.4.2.tgz",
- "integrity": "sha512-C6nx0hifW2uENP3M6HpPmnAE6HFWCcd8/sqBZEOHZY6lpHJ5qehsfAy43ktpFLEmkBmhiZDei726utcUB9leqg==",
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/formik/-/formik-2.4.3.tgz",
+ "integrity": "sha512-2Dy79Szw3zlXmZiokUdKsn+n1ow4G8hRrC/n92cOWHNTWXCRpQXlyvz6HcjW7aSQZrldytvDOavYjhfmDnUq8Q==",
"funding": [
{
"type": "individual",
@@ -6313,9 +6400,9 @@
"dev": true
},
"node_modules/graphql": {
- "version": "16.7.1",
- "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.7.1.tgz",
- "integrity": "sha512-DRYR9tf+UGU0KOsMcKAlXeFfX89UiiIZ0dRU3mR0yJfu6OjZqUcp68NnFLnqQU5RexygFoDy1EW+ccOYcPfmHg==",
+ "version": "16.8.0",
+ "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.0.tgz",
+ "integrity": "sha512-0oKGaR+y3qcS5mCu1vb7KG+a89vjn06C7Ihq/dDl3jA+A8B3TKomvi3CiEcVLJQGalbu8F52LxkOym7U5sSfbg==",
"engines": {
"node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
}
@@ -6832,6 +6919,21 @@
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
},
+ "node_modules/is-async-function": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz",
+ "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-bigint": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
@@ -6885,9 +6987,9 @@
}
},
"node_modules/is-core-module": {
- "version": "2.12.1",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz",
- "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==",
+ "version": "2.13.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz",
+ "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==",
"dependencies": {
"has": "^1.0.3"
},
@@ -6919,6 +7021,18 @@
"node": ">=0.10.0"
}
},
+ "node_modules/is-finalizationregistry": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz",
+ "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
@@ -6928,6 +7042,21 @@
"node": ">=8"
}
},
+ "node_modules/is-generator-function": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
+ "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
@@ -6958,6 +7087,15 @@
"tslib": "^2.0.3"
}
},
+ "node_modules/is-map": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
+ "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-negative-zero": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
@@ -7047,6 +7185,15 @@
"node": ">=0.10.0"
}
},
+ "node_modules/is-set": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz",
+ "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-shared-array-buffer": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
@@ -7137,6 +7284,15 @@
"tslib": "^2.0.3"
}
},
+ "node_modules/is-weakmap": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
+ "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-weakref": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
@@ -7149,6 +7305,19 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-weakset": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz",
+ "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-windows": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
@@ -7189,6 +7358,18 @@
"ws": "*"
}
},
+ "node_modules/iterator.prototype": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.1.tgz",
+ "integrity": "sha512-9E+nePc8C9cnQldmNl6bgpTY6zI4OPRZd97fhJ/iVZ1GifIUDVV5F6x1nEDqpe8KaMEZGT4xgrwKQDxXnjOIZQ==",
+ "dev": true,
+ "dependencies": {
+ "define-properties": "^1.2.0",
+ "get-intrinsic": "^1.2.1",
+ "has-symbols": "^1.0.3",
+ "reflect.getprototypeof": "^1.0.3"
+ }
+ },
"node_modules/jest-diff": {
"version": "29.5.0",
"resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz",
@@ -7805,12 +7986,6 @@
"node": ">=12"
}
},
- "node_modules/magic-string/node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.4.15",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
- "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
- "dev": true
- },
"node_modules/make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
@@ -7971,12 +8146,6 @@
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
"dev": true
},
- "node_modules/natural-compare-lite": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
- "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
- "dev": true
- },
"node_modules/no-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
@@ -8205,12 +8374,13 @@
}
},
"node_modules/optimism": {
- "version": "0.16.2",
- "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.16.2.tgz",
- "integrity": "sha512-zWNbgWj+3vLEjZNIh/okkY2EUfX+vB9TJopzIZwT1xxaMqC5hRLLraePod4c5n4He08xuXNH+zhKFFCu390wiQ==",
+ "version": "0.17.5",
+ "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.17.5.tgz",
+ "integrity": "sha512-TEcp8ZwK1RczmvMnvktxHSF2tKgMWjJ71xEFGX5ApLh67VsMSTy1ZUlipJw8W+KaqgOmQ+4pqwkeivY89j+4Vw==",
"dependencies": {
"@wry/context": "^0.7.0",
- "@wry/trie": "^0.3.0"
+ "@wry/trie": "^0.4.3",
+ "tslib": "^2.3.0"
}
},
"node_modules/optionator": {
@@ -8539,9 +8709,9 @@
}
},
"node_modules/prettier": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.0.tgz",
- "integrity": "sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==",
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.2.tgz",
+ "integrity": "sha512-o2YR9qtniXvwEZlOKbveKfDQVyqxbEIWn48Z8m3ZJjBjcCmUy3xZGIv+7AkaeuaTr6yPXJjwv07ZWlsWbEy1rQ==",
"dev": true,
"bin": {
"prettier": "bin/prettier.cjs"
@@ -8843,10 +9013,30 @@
"node": ">=8.10.0"
}
},
+ "node_modules/reflect.getprototypeof": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz",
+ "integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "get-intrinsic": "^1.2.1",
+ "globalthis": "^1.0.3",
+ "which-builtin-type": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/regenerator-runtime": {
- "version": "0.13.11",
- "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
- "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
+ "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA=="
},
"node_modules/regexp.prototype.flags": {
"version": "1.5.0",
@@ -8921,11 +9111,11 @@
"peer": true
},
"node_modules/resolve": {
- "version": "1.22.2",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
- "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==",
+ "version": "1.22.4",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz",
+ "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==",
"dependencies": {
- "is-core-module": "^2.11.0",
+ "is-core-module": "^2.13.0",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
},
@@ -9011,9 +9201,9 @@
}
},
"node_modules/rollup": {
- "version": "3.26.3",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.26.3.tgz",
- "integrity": "sha512-7Tin0C8l86TkpcMtXvQu6saWH93nhG3dGQ1/+l5V2TDMceTxO7kDiK6GzbfLWNNxqJXm591PcEZUozZm51ogwQ==",
+ "version": "3.28.1",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.28.1.tgz",
+ "integrity": "sha512-R9OMQmIHJm9znrU3m3cpE8uhN0fGdXiawME7aZIpQqvpS/85+Vt1Hq1/yVIcYfOmaQiHjvXkQAoJukvLpau6Yw==",
"dev": true,
"bin": {
"rollup": "dist/bin/rollup"
@@ -9666,9 +9856,9 @@
"dev": true
},
"node_modules/tinypool": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.6.0.tgz",
- "integrity": "sha512-FdswUUo5SxRizcBc6b1GSuLpLjisa8N8qMyYoP3rl+bym+QauhtJP5bvZY1ytt8krKGmMLYIRl36HBZfeAoqhQ==",
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.7.0.tgz",
+ "integrity": "sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==",
"dev": true,
"engines": {
"node": ">=14.0.0"
@@ -9984,9 +10174,9 @@
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
},
"node_modules/typescript": {
- "version": "5.1.6",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz",
- "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==",
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
+ "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
@@ -10182,14 +10372,14 @@
}
},
"node_modules/vite": {
- "version": "4.4.4",
- "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.4.tgz",
- "integrity": "sha512-4mvsTxjkveWrKDJI70QmelfVqTm+ihFAb6+xf4sjEU2TmUCTlVX87tmg/QooPEMQb/lM9qGHT99ebqPziEd3wg==",
+ "version": "4.4.9",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz",
+ "integrity": "sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==",
"dev": true,
"dependencies": {
"esbuild": "^0.18.10",
- "postcss": "^8.4.25",
- "rollup": "^3.25.2"
+ "postcss": "^8.4.27",
+ "rollup": "^3.27.1"
},
"bin": {
"vite": "bin/vite.js"
@@ -10237,9 +10427,9 @@
}
},
"node_modules/vite-node": {
- "version": "0.33.0",
- "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.33.0.tgz",
- "integrity": "sha512-19FpHYbwWWxDr73ruNahC+vtEdza52kA90Qb3La98yZ0xULqV8A5JLNPUff0f5zID4984tW7l3DH2przTJUZSw==",
+ "version": "0.34.3",
+ "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.34.3.tgz",
+ "integrity": "sha512-+0TzJf1g0tYXj6tR2vEyiA42OPq68QkRZCu/ERSo2PtsDJfBpDyEfuKbRvLmZqi/CgC7SCBtyC+WjTGNMRIaig==",
"dev": true,
"dependencies": {
"cac": "^6.7.14",
@@ -10260,9 +10450,9 @@
}
},
"node_modules/vite-plugin-checker": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/vite-plugin-checker/-/vite-plugin-checker-0.6.1.tgz",
- "integrity": "sha512-4fAiu3W/IwRJuJkkUZlWbLunSzsvijDf0eDN6g/MGh6BUK4SMclOTGbLJCPvdAcMOQvVmm8JyJeYLYd4//8CkA==",
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/vite-plugin-checker/-/vite-plugin-checker-0.6.2.tgz",
+ "integrity": "sha512-YvvvQ+IjY09BX7Ab+1pjxkELQsBd4rPhWNw8WLBeFVxu/E7O+n6VYAqNsKdK/a2luFlX/sMpoWdGFfg4HvwdJQ==",
"dev": true,
"dependencies": {
"@babel/code-frame": "^7.12.13",
@@ -10344,19 +10534,19 @@
}
},
"node_modules/vitest": {
- "version": "0.33.0",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.33.0.tgz",
- "integrity": "sha512-1CxaugJ50xskkQ0e969R/hW47za4YXDUfWJDxip1hwbnhUjYolpfUn2AMOulqG/Dtd9WYAtkHmM/m3yKVrEejQ==",
+ "version": "0.34.3",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.34.3.tgz",
+ "integrity": "sha512-7+VA5Iw4S3USYk+qwPxHl8plCMhA5rtfwMjgoQXMT7rO5ldWcdsdo3U1QD289JgglGK4WeOzgoLTsGFu6VISyQ==",
"dev": true,
"dependencies": {
"@types/chai": "^4.3.5",
"@types/chai-subset": "^1.3.3",
"@types/node": "*",
- "@vitest/expect": "0.33.0",
- "@vitest/runner": "0.33.0",
- "@vitest/snapshot": "0.33.0",
- "@vitest/spy": "0.33.0",
- "@vitest/utils": "0.33.0",
+ "@vitest/expect": "0.34.3",
+ "@vitest/runner": "0.34.3",
+ "@vitest/snapshot": "0.34.3",
+ "@vitest/spy": "0.34.3",
+ "@vitest/utils": "0.34.3",
"acorn": "^8.9.0",
"acorn-walk": "^8.2.0",
"cac": "^6.7.14",
@@ -10369,9 +10559,9 @@
"std-env": "^3.3.3",
"strip-literal": "^1.0.1",
"tinybench": "^2.5.0",
- "tinypool": "^0.6.0",
+ "tinypool": "^0.7.0",
"vite": "^3.0.0 || ^4.0.0",
- "vite-node": "0.33.0",
+ "vite-node": "0.34.3",
"why-is-node-running": "^2.2.2"
},
"bin": {
@@ -10632,6 +10822,47 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/which-builtin-type": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz",
+ "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==",
+ "dev": true,
+ "dependencies": {
+ "function.prototype.name": "^1.1.5",
+ "has-tostringtag": "^1.0.0",
+ "is-async-function": "^2.0.0",
+ "is-date-object": "^1.0.5",
+ "is-finalizationregistry": "^1.0.2",
+ "is-generator-function": "^1.0.10",
+ "is-regex": "^1.1.4",
+ "is-weakref": "^1.0.2",
+ "isarray": "^2.0.5",
+ "which-boxed-primitive": "^1.0.2",
+ "which-collection": "^1.0.1",
+ "which-typed-array": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-collection": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz",
+ "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==",
+ "dev": true,
+ "dependencies": {
+ "is-map": "^2.0.1",
+ "is-set": "^2.0.1",
+ "is-weakmap": "^2.0.1",
+ "is-weakset": "^2.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/which-module": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
diff --git a/package.json b/package.json
index 8d18baa1..5af766de 100644
--- a/package.json
+++ b/package.json
@@ -3,23 +3,23 @@
"version": "0.1.0",
"private": true,
"dependencies": {
- "@apollo/client": "3.7.17",
- "@date-io/moment": "2.16.1",
+ "@apollo/client": "3.8.1",
+ "@date-io/moment": "2.17.0",
"@emotion/react": "11.11.1",
"@emotion/styled": "11.11.0",
- "@fontsource/mulish": "5.0.5",
- "@fontsource/poppins": "5.0.5",
- "@mui/icons-material": "5.14.0",
- "@mui/lab": "5.0.0-alpha.136",
- "@mui/material": "5.14.0",
+ "@fontsource/mulish": "5.0.8",
+ "@fontsource/poppins": "5.0.8",
+ "@mui/icons-material": "5.14.6",
+ "@mui/lab": "5.0.0-alpha.141",
+ "@mui/material": "5.14.6",
"@mui/x-date-pickers": "5.0.20",
- "axios": "1.4.0",
+ "axios": "1.5.0",
"base64url": "3.0.1",
- "bignumber.js": "9.1.1",
+ "bignumber.js": "9.1.2",
"date-fns": "2.30.0",
"date-fns-tz": "2.0.0",
- "formik": "2.4.2",
- "graphql": "16.7.1",
+ "formik": "2.4.3",
+ "graphql": "16.8.0",
"highcharts": "11.1.0",
"highcharts-react-official": "3.2.0",
"immer": "10.0.2",
@@ -58,26 +58,26 @@
"@graphql-codegen/visitor-plugin-common": "2.13.8",
"@types/chart.js": "2.9.37",
"@types/classnames": "2.3.0",
- "@types/jest": "29.5.3",
+ "@types/jest": "29.5.4",
"@types/jwt-decode": "2.2.1",
- "@types/lodash": "4.14.195",
- "@types/react": "18.2.15",
+ "@types/lodash": "4.14.197",
+ "@types/react": "18.2.21",
"@types/react-dom": "18.2.7",
"@types/react-router-dom": "5.3.3",
- "@typescript-eslint/eslint-plugin": "6.3.0",
- "@typescript-eslint/parser": "6.3.0",
+ "@typescript-eslint/eslint-plugin": "6.4.1",
+ "@typescript-eslint/parser": "6.4.1",
"@vitejs/plugin-basic-ssl": "1.0.1",
- "@vitejs/plugin-react": "4.0.3",
+ "@vitejs/plugin-react": "4.0.4",
+ "eslint": "8.48.0",
+ "eslint-config-prettier": "9.0.0",
+ "eslint-plugin-react": "7.33.2",
"husky": "8.0.3",
- "prettier": "3.0.0",
- "typescript": "5.1.6",
- "vite": "4.4.4",
- "vite-plugin-checker": "0.6.1",
+ "prettier": "3.0.2",
+ "typescript": "5.2.2",
+ "vite": "4.4.9",
+ "vite-plugin-checker": "0.6.2",
"vite-tsconfig-paths": "4.2.0",
- "vitest": "0.33.0",
- "eslint": "8.46.0",
- "eslint-config-prettier": "9.0.0",
- "eslint-plugin-react": "7.33.1"
+ "vitest": "0.34.3"
},
"overrides": {
"semver": "7.5.4",
diff --git a/src/auth/views/components/AuthContainer.tsx b/src/auth/views/components/AuthContainer.tsx
index e865e50d..bf621812 100644
--- a/src/auth/views/components/AuthContainer.tsx
+++ b/src/auth/views/components/AuthContainer.tsx
@@ -14,7 +14,12 @@ export function AuthContainer({ children, belowCard, aboveCard }: Props) {
return (
-
+
{aboveCard}
{children}
{belowCard}
diff --git a/src/components/Date/DateRangePicker.tsx b/src/components/Date/DateRangePicker.tsx
index 37a19a0d..cd278c69 100644
--- a/src/components/Date/DateRangePicker.tsx
+++ b/src/components/Date/DateRangePicker.tsx
@@ -1,7 +1,7 @@
import { Stack, TextField } from "@mui/material";
import { Dispatch } from "react";
-import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFns";
import { DatePicker, LocalizationProvider } from "@mui/x-date-pickers";
+import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment";
interface Props {
from: Date;
@@ -17,7 +17,7 @@ export const DateRangePicker = ({
onToChange,
}: Props) => {
return (
-
+
Date: Tue, 5 Sep 2023 09:26:25 -0400
Subject: [PATCH 3/4] chore(deps): update actions/checkout action to v4 (#879)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
.github/workflows/codeql-analysis.yml | 2 +-
.github/workflows/deploy-to-production.yml | 2 +-
.github/workflows/deploy-to-staging.yml | 2 +-
.github/workflows/sanity-check.yml | 2 +-
.github/workflows/semgrep.yml | 2 +-
5 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 9f3a1d72..f9f23f49 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
diff --git a/.github/workflows/deploy-to-production.yml b/.github/workflows/deploy-to-production.yml
index a434a89e..433ed5e3 100644
--- a/.github/workflows/deploy-to-production.yml
+++ b/.github/workflows/deploy-to-production.yml
@@ -12,7 +12,7 @@ jobs:
url: https://ads.brave.com
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4
- name: Use Node.js
uses: actions/setup-node@v3
with:
diff --git a/.github/workflows/deploy-to-staging.yml b/.github/workflows/deploy-to-staging.yml
index e13913cd..2af967aa 100644
--- a/.github/workflows/deploy-to-staging.yml
+++ b/.github/workflows/deploy-to-staging.yml
@@ -12,7 +12,7 @@ jobs:
url: https://ads.bravesoftware.com
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4
- name: Use Node.js
uses: actions/setup-node@v3
with:
diff --git a/.github/workflows/sanity-check.yml b/.github/workflows/sanity-check.yml
index 3ac332f1..c2f69967 100644
--- a/.github/workflows/sanity-check.yml
+++ b/.github/workflows/sanity-check.yml
@@ -12,7 +12,7 @@ jobs:
check:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4
- name: Use Node.js
uses: actions/setup-node@v3
with:
diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml
index 9afe8a34..008c81b8 100644
--- a/.github/workflows/semgrep.yml
+++ b/.github/workflows/semgrep.yml
@@ -19,7 +19,7 @@ jobs:
steps:
# Fetch project source
- - uses: actions/checkout@v3
+ - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4
- uses: returntocorp/semgrep-action@v1
with:
publishToken: ${{ secrets.SEMGREP_APP_TOKEN }}
From 25eb1dac6f4e76ea0f58602725dbe08b448b964c Mon Sep 17 00:00:00 2001
From: Ian Krieger <48930920+IanKrieger@users.noreply.github.com>
Date: Tue, 5 Sep 2023 14:02:26 -0400
Subject: [PATCH 4/4] fix: correctly include createdAt (#880)
* fix: correctly include createdAt
* fix: update test
---
src/user/hooks/useAdvertiserCreatives.ts | 1 +
src/user/library/index.test.ts | 4 ++++
src/user/library/index.ts | 1 +
3 files changed, 6 insertions(+)
diff --git a/src/user/hooks/useAdvertiserCreatives.ts b/src/user/hooks/useAdvertiserCreatives.ts
index 451f7231..93d9c33b 100644
--- a/src/user/hooks/useAdvertiserCreatives.ts
+++ b/src/user/hooks/useAdvertiserCreatives.ts
@@ -12,6 +12,7 @@ export function useAdvertiserCreatives() {
advertiserId: c.advertiserId,
name: c.name,
state: c.state,
+ createdAt: c.createdAt,
included: false,
}),
);
diff --git a/src/user/library/index.test.ts b/src/user/library/index.test.ts
index bd92261f..65240186 100644
--- a/src/user/library/index.test.ts
+++ b/src/user/library/index.test.ts
@@ -449,6 +449,7 @@ describe("edit form tests", () => {
"creatives": [
{
"advertiserId": "12345",
+ "createdAt": undefined,
"id": "1234",
"included": true,
"name": "a creative",
@@ -465,6 +466,7 @@ describe("edit form tests", () => {
},
{
"advertiserId": "12345",
+ "createdAt": undefined,
"id": "1235",
"included": false,
"name": "a different creative",
@@ -501,6 +503,7 @@ describe("edit form tests", () => {
"creatives": [
{
"advertiserId": "12345",
+ "createdAt": undefined,
"id": "1234",
"included": true,
"name": "a creative",
@@ -517,6 +520,7 @@ describe("edit form tests", () => {
},
{
"advertiserId": "12345",
+ "createdAt": undefined,
"id": "1235",
"included": true,
"name": "a different creative",
diff --git a/src/user/library/index.ts b/src/user/library/index.ts
index 85be5261..00a19678 100644
--- a/src/user/library/index.ts
+++ b/src/user/library/index.ts
@@ -175,6 +175,7 @@ function creativeList(
const c = ad.creative;
return {
...validCreativeFields(c, advertiserId, included),
+ createdAt: c.createdAt,
};
});
};