-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: allow use of existing creatives
- Loading branch information
1 parent
c186788
commit a2bc86e
Showing
20 changed files
with
1,013 additions
and
129 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { | ||
FormControl, | ||
Box, | ||
FormLabel, | ||
FormControlLabel, | ||
Radio, | ||
} from "@mui/material"; | ||
import { useFormikContext } from "formik"; | ||
import { CreativeInput } from "graphql/types"; | ||
import { NotificationFields } from "./NotificationFields"; | ||
import { FormikRadioGroup, FormikTextField } from "form/FormikHelpers"; | ||
|
||
interface Props { | ||
allowTypeChange: boolean; | ||
} | ||
|
||
export function CreativeFields({ allowTypeChange }: Props) { | ||
const formik = useFormikContext<CreativeInput>(); | ||
const creativeType = formik.values.type?.code; | ||
|
||
return ( | ||
<> | ||
<FormikTextField name="name" label="Creative Name" /> | ||
|
||
<Box> | ||
<FormControl | ||
component="fieldset" | ||
margin="normal" | ||
disabled={!allowTypeChange} | ||
> | ||
<FormLabel component="legend" color="secondary"> | ||
Creative Type | ||
</FormLabel> | ||
<FormikRadioGroup row name="type.code"> | ||
<FormControlLabel | ||
value="notification_all_v1" | ||
control={<Radio />} | ||
label="Push Notification" | ||
/> | ||
</FormikRadioGroup> | ||
</FormControl> | ||
</Box> | ||
|
||
<CreativeTypeSpecificFields creativeType={creativeType} /> | ||
</> | ||
); | ||
} | ||
|
||
const CreativeTypeSpecificFields = ({ | ||
creativeType, | ||
}: { | ||
creativeType?: string; | ||
}) => { | ||
if (creativeType === "notification_all_v1") return <NotificationFields />; | ||
|
||
return null; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import { EnhancedTable, StandardRenderers } from "components/EnhancedTable"; | ||
import { useAdvertiserCreativesQuery } from "graphql/creative.generated"; | ||
import { uiTextForCreativeTypeCode } from "user/library"; | ||
import { CardContainer } from "components/Card/CardContainer"; | ||
import { useAdvertiser } from "auth/hooks/queries/useAdvertiser"; | ||
import { ErrorDetail } from "components/Error/ErrorDetail"; | ||
import MiniSideBar from "components/Drawer/MiniSideBar"; | ||
|
||
export function CreativeList() { | ||
const { advertiser } = useAdvertiser(); | ||
const { data, error } = useAdvertiserCreativesQuery({ | ||
variables: { | ||
advertiserId: advertiser.id, | ||
}, | ||
}); | ||
|
||
if (error) | ||
return ( | ||
<ErrorDetail error={error} additionalDetails="Unable to get creatives" /> | ||
); | ||
|
||
return ( | ||
<MiniSideBar> | ||
<CardContainer | ||
header="Creatives" | ||
sx={{ | ||
flexGrow: 1, | ||
mr: 2, | ||
}} | ||
> | ||
<EnhancedTable | ||
rows={data?.advertiser?.creatives ?? []} | ||
initialSortColumn={0} | ||
initialSortDirection="desc" | ||
initialRowsPerPage={25} | ||
columns={[ | ||
{ | ||
title: "Created", | ||
value: (c) => c.modifiedAt, | ||
renderer: StandardRenderers.date, | ||
}, | ||
{ | ||
title: "Name", | ||
value: (c) => c.name, | ||
}, | ||
{ | ||
title: "Type", | ||
value: (c) => uiTextForCreativeTypeCode(c.type), | ||
}, | ||
{ | ||
title: "Title", | ||
value: (c) => | ||
c.payloadInlineContent?.title ?? | ||
c.payloadNotification?.title ?? | ||
c.payloadSearch?.title ?? | ||
c.payloadSearchHomepage?.title, | ||
}, | ||
{ | ||
title: "Body", | ||
value: (c) => | ||
c.payloadInlineContent?.ctaText ?? | ||
c.payloadNotification?.body ?? | ||
c.payloadSearch?.body ?? | ||
c.payloadSearchHomepage?.body, | ||
}, | ||
]} | ||
/> | ||
</CardContainer> | ||
</MiniSideBar> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
import { Box, Snackbar } from "@mui/material"; | ||
import { Form, Formik } from "formik"; | ||
import { useHistory, useLocation, useParams } from "react-router-dom"; | ||
import { CreativeInput } from "graphql/types"; | ||
import { CreativeFields } from "./CreativeFields"; | ||
import { | ||
AdvertiserCreativesDocument, | ||
useCreateCreativeMutation, | ||
} from "graphql/creative.generated"; | ||
import { useState } from "react"; | ||
import { CardContainer } from "components/Card/CardContainer"; | ||
import { ErrorDetail } from "components/Error/ErrorDetail"; | ||
import { FormikSubmitButton } from "form/FormikHelpers"; | ||
import { CreativeSchema } from "validation/CreativeSchema"; | ||
|
||
interface Params { | ||
advertiserId: string; | ||
} | ||
|
||
function wait(ms: number) { | ||
return new Promise((resolve) => window.setTimeout(resolve, ms)); | ||
} | ||
|
||
export const NewCreative: React.FC = () => { | ||
const params = useParams<Params>(); | ||
const history = useHistory(); | ||
const location = useLocation<CreativeInput>(); | ||
|
||
const defaultValue: CreativeInput & { targetUrlValid: boolean } = { | ||
advertiserId: params.advertiserId, | ||
state: "active", | ||
name: "", | ||
type: { | ||
code: "", | ||
name: "", | ||
}, | ||
targetUrlValid: false, | ||
payloadNotification: { | ||
body: "", | ||
targetUrl: "", | ||
title: "", | ||
}, | ||
startAt: null, | ||
endAt: null, | ||
}; | ||
|
||
const initialValue = location.state ?? defaultValue; | ||
|
||
const [createCreativeMutation, { error }] = useCreateCreativeMutation({ | ||
refetchQueries: [ | ||
{ | ||
query: AdvertiserCreativesDocument, | ||
variables: { advertiserId: params.advertiserId }, | ||
}, | ||
], | ||
}); | ||
|
||
const [id, setId] = useState(""); | ||
|
||
const doSubmit = async (values: CreativeInput) => { | ||
const input: CreativeInput = { | ||
advertiserId: values.advertiserId, | ||
name: values.name, | ||
payloadNotification: values.payloadNotification, | ||
startAt: values.startAt, | ||
endAt: values.endAt, | ||
state: values.state, | ||
type: values.type, | ||
}; | ||
|
||
const response = await createCreativeMutation({ | ||
variables: { input }, | ||
}); | ||
const id = response.data?.createCreative.id; | ||
if (id) { | ||
setId(id); | ||
await wait(2000); | ||
history.replace(id); | ||
} | ||
}; | ||
|
||
return ( | ||
<Box> | ||
<CardContainer header="New creative"> | ||
<Formik | ||
initialValues={initialValue} | ||
onSubmit={doSubmit} | ||
validationSchema={CreativeSchema} | ||
> | ||
<Form> | ||
<CreativeFields allowTypeChange={true} /> | ||
|
||
<ErrorDetail | ||
error={error} | ||
additionalDetails="Unable to create creative" | ||
/> | ||
|
||
<Box | ||
mt={1} | ||
display="flex" | ||
justifyContent="flex-end" | ||
alignItems="baseline" | ||
> | ||
<FormikSubmitButton isCreate={true} allowNavigation={!!id} /> | ||
</Box> | ||
</Form> | ||
</Formik> | ||
|
||
<Snackbar | ||
message={`Creative ${id} successfully created`} | ||
open={!!id} | ||
autoHideDuration={5000} | ||
/> | ||
</CardContainer> | ||
</Box> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { FormikTextField } from "form/FormikHelpers"; | ||
import { UrlResolver } from "components/Url/UrlResolver"; | ||
|
||
export function NotificationFields() { | ||
return ( | ||
<> | ||
<FormikTextField | ||
name="payloadNotification.title" | ||
label="Title" | ||
maxLengthInstantFeedback={30} | ||
/> | ||
<FormikTextField | ||
name="payloadNotification.body" | ||
label="Body" | ||
maxLengthInstantFeedback={60} | ||
/> | ||
|
||
<UrlResolver | ||
name="payloadNotification.targetUrl" | ||
validator="targetUrlValid" | ||
label="Ad Target URL" | ||
helperText="Example - https://brave.com/brave-rewards/" | ||
/> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.