Webhook details imoprovements (#3229)

* partial regex for custom headers
* disabled attribute for `Add custom request header` button
* align styles for new macaw ui
* add `Webhook events` header text
* add a pointer to objects & events lists
* sort webhook events & objects
This commit is contained in:
Bartłomiej Wiaduch 2023-03-03 09:53:13 +01:00 committed by GitHub
parent 12706a86e0
commit e7ce3000f3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 33 additions and 5 deletions

View file

@ -3683,6 +3683,10 @@
"context": "caption", "context": "caption",
"string": "If enabled, youll be able to use this attribute to filter products in product list." "string": "If enabled, youll be able to use this attribute to filter products in product list."
}, },
"QAisk4": {
"context": "Webhook events header",
"string": "Webhook events"
},
"QBxN6z": { "QBxN6z": {
"context": "is filter range or value", "context": "is filter range or value",
"string": "between" "string": "between"

View file

@ -124,13 +124,16 @@ const WebhookDetailsPage: React.FC<WebhookDetailsPageProps> = ({
errors={errors} errors={errors}
onChange={change} onChange={change}
/> />
</Box>
<FormSpacer /> <FormSpacer />
<Box>
<WebhookEvents <WebhookEvents
data={data} data={data}
setQuery={setQuery} setQuery={setQuery}
onSyncEventChange={handleSyncEventsSelect} onSyncEventChange={handleSyncEventsSelect}
onAsyncEventChange={handleAsyncEventsSelect} onAsyncEventChange={handleAsyncEventsSelect}
/> />
<WebhookSubscriptionQuery <WebhookSubscriptionQuery
query={query} query={query}
setQuery={setQuery} setQuery={setQuery}

View file

@ -1,3 +1,4 @@
import CardTitle from "@dashboard/components/CardTitle";
import Grid from "@dashboard/components/Grid"; import Grid from "@dashboard/components/Grid";
import Hr from "@dashboard/components/Hr"; import Hr from "@dashboard/components/Hr";
import { import {
@ -80,7 +81,8 @@ const WebhookEvents: React.FC<WebhookEventsProps> = ({
return ( return (
<> <>
<Card> <Card>
<CardContent className={classes.card}> <CardTitle title={intl.formatMessage(messages.webhookEvents)} />
<CardContent className={classes.cardHeader}>
<PageTabs value={tab} onChange={handleTabChange}> <PageTabs value={tab} onChange={handleTabChange}>
<PageTab <PageTab
label={intl.formatMessage(messages.asynchronous)} label={intl.formatMessage(messages.asynchronous)}
@ -179,6 +181,7 @@ const WebhookEvents: React.FC<WebhookEventsProps> = ({
</List> </List>
</div> </div>
</Grid> </Grid>
<Hr />
</Card> </Card>
</> </>
); );

View file

@ -33,4 +33,9 @@ export const messages = defineMessages({
id: "F6LHyk", id: "F6LHyk",
description: "Webhook details objects", description: "Webhook details objects",
}, },
webhookEvents: {
id: "QAisk4",
defaultMessage: "Webhook events",
description: "Webhook events header",
},
}); });

View file

@ -25,6 +25,7 @@ export const useStyles = makeStyles(
minHeight: 0, minHeight: 0,
gap: 0, gap: 0,
padding: theme.spacing(1), padding: theme.spacing(1),
cursor: "pointer",
}, },
listItemCell: { listItemCell: {
paddingLeft: "0 !important", paddingLeft: "0 !important",
@ -36,6 +37,9 @@ export const useStyles = makeStyles(
card: { card: {
paddingLeft: 0, paddingLeft: 0,
}, },
cardHeader: {
padding: "2.4rem 3.2rem",
},
}), }),
{ name: "WebhookEvents" }, { name: "WebhookEvents" },
); );

View file

@ -8,7 +8,7 @@ type Actions = string[];
export const getWebhookTypes = (webhookEvents: string[]) => { export const getWebhookTypes = (webhookEvents: string[]) => {
const multiWords = ["DRAFT_ORDER", "GIFT_CARD", "ANY_EVENTS"]; const multiWords = ["DRAFT_ORDER", "GIFT_CARD", "ANY_EVENTS"];
return webhookEvents.reduce<Record<string, Actions>>((acc, key) => { return webhookEvents.sort().reduce<Record<string, Actions>>((acc, key) => {
const keywords = key.split("_"); const keywords = key.split("_");
const multiKeyword = keywords.slice(0, 2).join("_"); const multiKeyword = keywords.slice(0, 2).join("_");

View file

@ -20,7 +20,7 @@ import { FormattedMessage, useIntl } from "react-intl";
import { WebhookFormData } from "../WebhookDetailsPage"; import { WebhookFormData } from "../WebhookDetailsPage";
import { messages } from "./messages"; import { messages } from "./messages";
import useStyles from "./styles"; import useStyles from "./styles";
import { mapHeaders, stringifyHeaders } from "./utils"; import { hasEmptyHeader, mapHeaders, stringifyHeaders } from "./utils";
import WebhookHeadersTableBody from "./WebhookHeadersTableBody"; import WebhookHeadersTableBody from "./WebhookHeadersTableBody";
export interface WebhookHeadersProps { export interface WebhookHeadersProps {
@ -143,6 +143,7 @@ const WebhookHeaders: React.FC<WebhookHeadersProps> = ({
variant="secondary" variant="secondary"
data-test-id="add-header" data-test-id="add-header"
onClick={add} onClick={add}
disabled={hasEmptyHeader(headers)}
> >
<FormattedMessage {...messages.add} /> <FormattedMessage {...messages.add} />
</Button> </Button>

View file

@ -46,6 +46,7 @@ const useStyles = makeStyles(
"&&": { "&&": {
paddingBottom: theme.spacing(2), paddingBottom: theme.spacing(2),
paddingTop: theme.spacing(2), paddingTop: theme.spacing(2),
paddingLeft: theme.spacing(4),
}, },
}, },
content: { content: {

View file

@ -12,7 +12,11 @@ export const stringifyHeaders = (headers: Header[]): string =>
const validateName = (name: string) => { const validateName = (name: string) => {
if ( if (
name.toLowerCase().match("(^x$)|(^x-)|(^authorization$)|(^authorization-)") name
.toLowerCase()
.match(
"(^x$)|(^x-)|^(a|$)(u|$)(t|$)(h|$)(o|$)(r|$)(i|$)(z|$)(a|$)(t|$)(i|$)(o|$)(n|$)(-|$)",
)
) { ) {
return false; return false;
} }
@ -33,3 +37,6 @@ export const mapHeaders = (customHeaders: string): Header[] => {
error: validateName(key), error: validateName(key),
})); }));
}; };
export const hasEmptyHeader = (customHeaders: Header[]): boolean =>
customHeaders.filter(header => header.name.length === 0).length > 0;