-
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: creative management screen (#928)
* wip: add creative management screen * wip: add creative management screen * feat: create and edit view, change verbiage, introduce floating button * fix: schema * feat: fix dirty submit * fix: validation for inline creative * fix: submit from dialog * fix: make state rules more clear * fix: submit process * fix: spelling * fix: grammar
- Loading branch information
1 parent
57f947b
commit 1e542ed
Showing
36 changed files
with
1,474 additions
and
150 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { IconButton } from "@mui/material"; | ||
import HelpIcon from "@mui/icons-material/Help"; | ||
|
||
export function FormatHelp() { | ||
return ( | ||
<IconButton | ||
size="small" | ||
onClick={() => | ||
window.open( | ||
"https://brave.com/brave-ads/ad-formats/", | ||
"__blank", | ||
"noopener", | ||
) | ||
} | ||
> | ||
<HelpIcon fontSize="small" /> | ||
</IconButton> | ||
); | ||
} |
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,88 @@ | ||
import { Box, Link, Paper, Slide } from "@mui/material"; | ||
import { PropsWithChildren, ReactNode, useState } from "react"; | ||
import { useFormikContext } from "formik"; | ||
import { | ||
extractErrors, | ||
FormikDialogButton, | ||
FormikSubmitButton, | ||
} from "form/FormikButton"; | ||
|
||
function StatusMessage({ | ||
errors, | ||
isDirty, | ||
}: { | ||
errors: string[]; | ||
isDirty: boolean; | ||
}): ReactNode { | ||
const [showErrors, setShowErrors] = useState(false); | ||
|
||
if (errors.length === 0) { | ||
return isDirty ? "You have unsaved changes" : null; | ||
} | ||
|
||
if (errors.length === 1) { | ||
return errors[0]; | ||
} | ||
|
||
return ( | ||
<Box> | ||
<Link underline="hover" onClick={() => setShowErrors((state) => !state)}> | ||
You have {errors.length} errors that must be fixed before submitting. | ||
</Link> | ||
{showErrors && ( | ||
<ul> | ||
{errors.map((v, idx) => ( | ||
<li key={idx}>{`${v}`}</li> | ||
))} | ||
</ul> | ||
)} | ||
</Box> | ||
); | ||
} | ||
|
||
interface Props { | ||
isCreate: boolean; | ||
hasDialog?: boolean; | ||
dialogTitle?: string; | ||
dialogMessage?: string; | ||
} | ||
|
||
export function SubmitPanel(props: PropsWithChildren<Props>) { | ||
const { dirty, errors, submitCount } = useFormikContext(); | ||
// when creating a new item, we don't want to bombard with a whole load | ||
// of validation errors. So wait until it's been submitted at least once | ||
// before dumping the set of things that need to be completed. | ||
const errorStrings = | ||
props.isCreate && submitCount < 1 ? [] : extractErrors(errors); | ||
|
||
return ( | ||
<Slide in={true} direction="up"> | ||
<Paper | ||
elevation={8} | ||
sx={{ | ||
p: 2, | ||
backgroundColor: "#eeeeee", | ||
position: "sticky", | ||
bottom: 0, | ||
zIndex: 9999, | ||
borderRadius: "16px", | ||
}} | ||
> | ||
<Box display="flex" justifyContent="flex-end" alignItems="end" gap={2}> | ||
<Box flex={1} alignSelf="center"> | ||
<StatusMessage errors={errorStrings} isDirty={dirty} /> | ||
</Box> | ||
|
||
{props.hasDialog && props.dialogTitle && props.dialogMessage && ( | ||
<FormikDialogButton | ||
{...props} | ||
dialogMessage={props.dialogMessage} | ||
dialogTitle={props.dialogTitle} | ||
/> | ||
)} | ||
{!props.hasDialog && <FormikSubmitButton {...props} />} | ||
</Box> | ||
</Paper> | ||
</Slide> | ||
); | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { CampaignsForCreativeQuery } from "graphql/creative.generated"; | ||
import { Link as RouterLink } from "react-router-dom"; | ||
import { | ||
Link, | ||
Table, | ||
TableBody, | ||
TableCell, | ||
TableHead, | ||
TableRow, | ||
} from "@mui/material"; | ||
import { ErrorDetail } from "components/Error/ErrorDetail"; | ||
import { CardContainer } from "components/Card/CardContainer"; | ||
import _ from "lodash"; | ||
import { Status } from "components/Campaigns/Status"; | ||
import { ApolloError } from "@apollo/client"; | ||
|
||
interface Props { | ||
data?: CampaignsForCreativeQuery; | ||
error?: ApolloError; | ||
loading: boolean; | ||
} | ||
|
||
export default function CreativeCampaigns({ data, error, loading }: Props) { | ||
if (loading || !data || !data.creativeCampaigns) { | ||
return null; | ||
} | ||
|
||
if (error) { | ||
return ( | ||
<ErrorDetail | ||
error={error} | ||
additionalDetails="Unable to get campaign information for creative" | ||
/> | ||
); | ||
} | ||
|
||
const campaigns = _.uniqBy(data.creativeCampaigns, "id"); | ||
return ( | ||
<CardContainer header="Campaigns"> | ||
<Table> | ||
<TableHead> | ||
<TableRow> | ||
<TableCell>Name</TableCell> | ||
<TableCell>Status</TableCell> | ||
</TableRow> | ||
</TableHead> | ||
<TableBody> | ||
{campaigns.map((c) => ( | ||
<TableRow key={c.id}> | ||
<TableCell> | ||
<Link | ||
component={RouterLink} | ||
to={`/user/main/campaign/${c.id}`} | ||
underline="none" | ||
color="secondary" | ||
> | ||
{c.name} | ||
</Link> | ||
</TableCell> | ||
<TableCell> | ||
<Status state={c.state} /> | ||
</TableCell> | ||
</TableRow> | ||
))} | ||
</TableBody> | ||
</Table> | ||
</CardContainer> | ||
); | ||
} |
Oops, something went wrong.