Add webhook components
This commit is contained in:
parent
2637ec3fdf
commit
4021b8ec62
20 changed files with 869 additions and 0 deletions
|
@ -202,6 +202,10 @@ export const sectionNames = defineMessages({
|
|||
vouchers: {
|
||||
defaultMessage: "Vouchers",
|
||||
description: "vouchers section name"
|
||||
},
|
||||
webhooks: {
|
||||
defaultMessage: "Webhooks",
|
||||
description: "webhooks section name"
|
||||
}
|
||||
});
|
||||
|
||||
|
|
57
src/webhooks/components/WebhookEvents/WebhookEvents.tsx
Normal file
57
src/webhooks/components/WebhookEvents/WebhookEvents.tsx
Normal file
|
@ -0,0 +1,57 @@
|
|||
import Card from "@material-ui/core/Card";
|
||||
import CardContent from "@material-ui/core/CardContent";
|
||||
import TextField from "@material-ui/core/TextField";
|
||||
import makeStyles from "@material-ui/styles/makeStyles";
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import ControlledCheckbox from "@saleor/components/ControlledCheckbox";
|
||||
import { FormErrors } from "@saleor/types";
|
||||
import { ConfigurationTypeFieldEnum } from "@saleor/types/globalTypes";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import { FormData } from "../WebhookDetailsPage";
|
||||
|
||||
interface WebhookEventsProps {
|
||||
data: FormData;
|
||||
errors: FormErrors<"name" | "configuration">;
|
||||
disabled: boolean;
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
fields: Array<{
|
||||
name: string;
|
||||
type: ConfigurationTypeFieldEnum | null;
|
||||
value: string;
|
||||
helpText: string | null;
|
||||
label: string | null;
|
||||
}>;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
item: {
|
||||
paddingBottom: 10,
|
||||
paddingTop: 10
|
||||
}
|
||||
}));
|
||||
|
||||
const WebhookEvents: React.StatelessComponent<WebhookEventsProps> = ({
|
||||
data,
|
||||
disabled,
|
||||
errors,
|
||||
onChange,
|
||||
fields
|
||||
}) => {
|
||||
const classes = useStyles({});
|
||||
const intl = useIntl();
|
||||
return (
|
||||
<Card>
|
||||
<CardTitle
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Events",
|
||||
description: "section header"
|
||||
})}
|
||||
/>
|
||||
<CardContent></CardContent>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
WebhookEvents.displayName = "WebhookEvents";
|
||||
export default WebhookEvents;
|
2
src/webhooks/components/WebhookEvents/index.ts
Normal file
2
src/webhooks/components/WebhookEvents/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
export { default } from "./WebhookEvents;
|
||||
export * from "./WebhookEvents;
|
53
src/webhooks/components/WebhookInfo/WebhookInfo.tsx
Normal file
53
src/webhooks/components/WebhookInfo/WebhookInfo.tsx
Normal file
|
@ -0,0 +1,53 @@
|
|||
import Card from "@material-ui/core/Card";
|
||||
import CardContent from "@material-ui/core/CardContent";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import makeStyles from "@material-ui/styles/makeStyles";
|
||||
import React from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import ControlledCheckbox from "@saleor/components/ControlledCheckbox";
|
||||
import FormSpacer from "@saleor/components/FormSpacer";
|
||||
import Hr from "@saleor/components/Hr";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { FormData } from "../WebhooksDetailsPage";
|
||||
|
||||
interface WebhookInfoProps {
|
||||
data: FormData;
|
||||
description: string;
|
||||
name: string;
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
status: {
|
||||
paddingTop: 20
|
||||
},
|
||||
title: {
|
||||
fontSize: 14,
|
||||
paddingTop: 10
|
||||
}
|
||||
}));
|
||||
|
||||
const WebhookInfo: React.StatelessComponent<WebhookInfoProps> = ({
|
||||
data,
|
||||
description,
|
||||
name,
|
||||
onChange
|
||||
}) => {
|
||||
const classes = useStyles({});
|
||||
const intl = useIntl();
|
||||
return (
|
||||
<Card>
|
||||
<CardTitle
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Plugin Information and Status",
|
||||
description: "section header"
|
||||
})}
|
||||
/>
|
||||
<CardContent></CardContent>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
WebhookInfo.displayName = "WebhookInfo";
|
||||
export default WebhookInfo;
|
2
src/webhooks/components/WebhookInfo/index.ts
Normal file
2
src/webhooks/components/WebhookInfo/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
export { default } from "./WebhookInfoo";
|
||||
export * from "./WebhookInfoo";
|
57
src/webhooks/components/WebhookStatus/WebhookStatus.tsx
Normal file
57
src/webhooks/components/WebhookStatus/WebhookStatus.tsx
Normal file
|
@ -0,0 +1,57 @@
|
|||
import Card from "@material-ui/core/Card";
|
||||
import CardContent from "@material-ui/core/CardContent";
|
||||
import TextField from "@material-ui/core/TextField";
|
||||
import makeStyles from "@material-ui/styles/makeStyles";
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import ControlledCheckbox from "@saleor/components/ControlledCheckbox";
|
||||
import { FormErrors } from "@saleor/types";
|
||||
import { ConfigurationTypeFieldEnum } from "@saleor/types/globalTypes";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import { FormData } from "../WebhooksDetailsPage";
|
||||
|
||||
interface WebhookStatusProps {
|
||||
data: FormData;
|
||||
errors: FormErrors<"name" | "configuration">;
|
||||
disabled: boolean;
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
fields: Array<{
|
||||
name: string;
|
||||
type: ConfigurationTypeFieldEnum | null;
|
||||
value: string;
|
||||
helpText: string | null;
|
||||
label: string | null;
|
||||
}>;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
item: {
|
||||
paddingBottom: 10,
|
||||
paddingTop: 10
|
||||
}
|
||||
}));
|
||||
|
||||
const WebhookStatus: React.StatelessComponent<WebhookStatusProps> = ({
|
||||
data,
|
||||
disabled,
|
||||
errors,
|
||||
onChange,
|
||||
fields
|
||||
}) => {
|
||||
const classes = useStyles({});
|
||||
const intl = useIntl();
|
||||
return (
|
||||
<Card>
|
||||
<CardTitle
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Webhook Status",
|
||||
description: "section header"
|
||||
})}
|
||||
/>
|
||||
<CardContent></CardContent>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
WebhookStatus.displayName = "WebhookStatus";
|
||||
export default WebhookStatus;
|
2
src/webhooks/components/WebhookStatus/index.ts
Normal file
2
src/webhooks/components/WebhookStatus/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
export { default } from "./WebhookStatus;
|
||||
export * from "./WebhookStatus;
|
|
@ -0,0 +1,78 @@
|
|||
import Typography from "@material-ui/core/Typography";
|
||||
import AppHeader from "@saleor/components/AppHeader";
|
||||
import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton";
|
||||
import Container from "@saleor/components/Container";
|
||||
import Form from "@saleor/components/Form";
|
||||
import Grid from "@saleor/components/Grid";
|
||||
import PageHeader from "@saleor/components/PageHeader";
|
||||
import SaveButtonBar from "@saleor/components/SaveButtonBar";
|
||||
import { sectionNames } from "@saleor/intl";
|
||||
import { maybe } from "@saleor/misc";
|
||||
import { UserError } from "@saleor/types";
|
||||
import { ConfigurationItemInput } from "@saleor/types/globalTypes";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import { Plugin_plugin } from "../../types/Plugin";
|
||||
import WebhookInfo from "../WebhookInfo";
|
||||
import WebhookEvents from "../WebhookEvents";
|
||||
|
||||
export interface FormData {
|
||||
active: boolean;
|
||||
configuration: ConfigurationItemInput[];
|
||||
}
|
||||
|
||||
export interface WebhooksDetailsPageProps {
|
||||
disabled: boolean;
|
||||
errors: UserError[];
|
||||
plugin: Plugin_plugin;
|
||||
saveButtonBarState: ConfirmButtonTransitionState;
|
||||
onBack: () => void;
|
||||
onSubmit: (data: FormData) => void;
|
||||
}
|
||||
|
||||
const WebhooksDetailsPage: React.StatelessComponent<
|
||||
WebhooksDetailsPageProps
|
||||
> = ({ disabled, errors, plugin, saveButtonBarState, onBack, onSubmit }) => {
|
||||
const intl = useIntl();
|
||||
const initialForm: FormData = {
|
||||
active: maybe(() => plugin.active, false),
|
||||
configuration: maybe(() => plugin.configuration, [])
|
||||
};
|
||||
|
||||
return (
|
||||
<Form errors={errors} initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ data, errors, hasChanged, submit, set, triggerChange }) => {
|
||||
return (
|
||||
<Container>
|
||||
<AppHeader onBack={onBack}>
|
||||
{intl.formatMessage(sectionNames.plugins)}
|
||||
</AppHeader>
|
||||
<PageHeader
|
||||
title={intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "{pluginName} Details",
|
||||
description: "header"
|
||||
},
|
||||
{
|
||||
pluginName: maybe(() => plugin.name, "...")
|
||||
}
|
||||
)}
|
||||
/>
|
||||
<Grid variant="inverted">
|
||||
<div></div>
|
||||
</Grid>
|
||||
<SaveButtonBar
|
||||
disabled={disabled || !hasChanged}
|
||||
state={saveButtonBarState}
|
||||
onCancel={onBack}
|
||||
onSave={submit}
|
||||
/>
|
||||
</Container>
|
||||
);
|
||||
}}
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
WebhooksDetailsPage.displayName = "WebhooksDetailsPage";
|
||||
export default WebhooksDetailsPage;
|
2
src/webhooks/components/WebhooksDetailsPage/index.ts
Normal file
2
src/webhooks/components/WebhooksDetailsPage/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
export { default } from "./WebhooksDetailsPage";
|
||||
export * from "./WebhooksDetailsPage";
|
155
src/webhooks/components/WebhooksList/WebhooksList.tsx
Normal file
155
src/webhooks/components/WebhooksList/WebhooksList.tsx
Normal file
|
@ -0,0 +1,155 @@
|
|||
import Card from "@material-ui/core/Card";
|
||||
import {
|
||||
createStyles,
|
||||
Theme,
|
||||
withStyles,
|
||||
WithStyles
|
||||
} from "@material-ui/core/styles";
|
||||
import Table from "@material-ui/core/Table";
|
||||
import TableBody from "@material-ui/core/TableBody";
|
||||
import TableCell from "@material-ui/core/TableCell";
|
||||
import TableFooter from "@material-ui/core/TableFooter";
|
||||
import TableHead from "@material-ui/core/TableHead";
|
||||
import TableRow from "@material-ui/core/TableRow";
|
||||
import EditIcon from "@material-ui/icons/Edit";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import Skeleton from "@saleor/components/Skeleton";
|
||||
import StatusLabel from "@saleor/components/StatusLabel";
|
||||
import TablePagination from "@saleor/components/TablePagination";
|
||||
import { translateBoolean } from "@saleor/intl";
|
||||
import { maybe, renderCollection } from "@saleor/misc";
|
||||
import { ListProps } from "@saleor/types";
|
||||
import { Plugins_plugins_edges_node } from "../../types/Plugins";
|
||||
|
||||
export interface WebhooksListProps extends ListProps {
|
||||
webhooks: Plugins_plugins_edges_node[];
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
[theme.breakpoints.up("lg")]: {
|
||||
colAction: {
|
||||
"& svg": {
|
||||
color: theme.palette.primary.main
|
||||
},
|
||||
textAlign: "right"
|
||||
},
|
||||
colActive: {},
|
||||
colName: {}
|
||||
},
|
||||
colAction: {},
|
||||
colActive: {},
|
||||
colName: {},
|
||||
link: {
|
||||
cursor: "pointer"
|
||||
}
|
||||
});
|
||||
|
||||
const numberOfColumns = 4;
|
||||
|
||||
const WebhooksList = withStyles(styles, { name: "PluginList" })(
|
||||
({
|
||||
classes,
|
||||
settings,
|
||||
webhooks,
|
||||
disabled,
|
||||
onNextPage,
|
||||
pageInfo,
|
||||
onRowClick,
|
||||
onUpdateListSettings,
|
||||
onPreviousPage
|
||||
}: WebhooksListProps & WithStyles<typeof styles>) => {
|
||||
const intl = useIntl();
|
||||
return (
|
||||
<Card>
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableCell className={classes.colName} padding="dense">
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Name",
|
||||
description: "webhook name"
|
||||
})}
|
||||
</TableCell>
|
||||
<TableCell className={classes.colActive} padding="dense">
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Service Account",
|
||||
description: "webhook service account"
|
||||
})}
|
||||
</TableCell>
|
||||
<TableCell className={classes.colAction} padding="dense">
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Action",
|
||||
description: "user action bar"
|
||||
})}
|
||||
</TableCell>
|
||||
</TableHead>
|
||||
<TableFooter>
|
||||
<TableRow>
|
||||
<TablePagination
|
||||
colSpan={numberOfColumns}
|
||||
settings={settings}
|
||||
hasNextPage={
|
||||
pageInfo && !disabled ? pageInfo.hasNextPage : false
|
||||
}
|
||||
onNextPage={onNextPage}
|
||||
onUpdateListSettings={onUpdateListSettings}
|
||||
hasPreviousPage={
|
||||
pageInfo && !disabled ? pageInfo.hasPreviousPage : false
|
||||
}
|
||||
onPreviousPage={onPreviousPage}
|
||||
/>
|
||||
</TableRow>
|
||||
</TableFooter>
|
||||
<TableBody>
|
||||
{renderCollection(
|
||||
webhooks,
|
||||
webhook => {
|
||||
return (
|
||||
// <TableRow
|
||||
// hover={!!plugin}
|
||||
// className={!!plugin ? classes.link : undefined}
|
||||
// onClick={plugin ? onRowClick(plugin.id) : undefined}
|
||||
// key={plugin ? plugin.id : "skeleton"}
|
||||
// >
|
||||
// <TableCell className={classes.colName}>
|
||||
// {maybe<React.ReactNode>(() => plugin.name, <Skeleton />)}
|
||||
// </TableCell>
|
||||
// <TableCell className={classes.colActive}>
|
||||
// {maybe<React.ReactNode>(
|
||||
// () => (
|
||||
// <StatusLabel
|
||||
// label={translateBoolean(plugin.active, intl)}
|
||||
// status={plugin.active ? "success" : "error"}
|
||||
// />
|
||||
// ),
|
||||
// <Skeleton />
|
||||
// )}
|
||||
// </TableCell>
|
||||
// <TableCell className={classes.colAction}>
|
||||
// <div onClick={plugin ? onRowClick(plugin.id) : undefined}>
|
||||
// <EditIcon />
|
||||
// </div>
|
||||
// </TableCell>
|
||||
// </TableRow>
|
||||
);
|
||||
},
|
||||
() => (
|
||||
<TableRow>
|
||||
<TableCell colSpan={numberOfColumns}>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "No plugins found"
|
||||
})}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
);
|
||||
WebhooksList.displayName = "WebhooksList";
|
||||
export default WebhooksList;
|
2
src/webhooks/components/WebhooksList/index.ts
Normal file
2
src/webhooks/components/WebhooksList/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
export { default } from "./WebhooksListt";
|
||||
export * from "./WebhooksListt";
|
|
@ -0,0 +1,49 @@
|
|||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import AppHeader from "@saleor/components/AppHeader";
|
||||
import Container from "@saleor/components/Container";
|
||||
import PageHeader from "@saleor/components/PageHeader";
|
||||
import { sectionNames } from "@saleor/intl";
|
||||
import { PageListProps } from "@saleor/types";
|
||||
import { Plugins_plugins_edges_node } from "../../types/Plugins";
|
||||
import WebhooksList from "../WebhooksList/WebhooksList";
|
||||
|
||||
export interface WebhooksListPageProps extends PageListProps {
|
||||
plugins: Plugins_plugins_edges_node[];
|
||||
onBack: () => void;
|
||||
}
|
||||
|
||||
const WebhooksListPage: React.StatelessComponent<WebhooksListPageProps> = ({
|
||||
disabled,
|
||||
settings,
|
||||
onBack,
|
||||
onNextPage,
|
||||
onPreviousPage,
|
||||
onRowClick,
|
||||
onUpdateListSettings,
|
||||
pageInfo,
|
||||
webhooks
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
return (
|
||||
<Container>
|
||||
<AppHeader onBack={onBack}>
|
||||
{intl.formatMessage(sectionNames.configuration)}
|
||||
</AppHeader>
|
||||
<PageHeader title={intl.formatMessage(sectionNames.webhooks)} />
|
||||
<WebhooksList
|
||||
disabled={disabled}
|
||||
settings={settings}
|
||||
webhooks={webhooks}
|
||||
onNextPage={onNextPage}
|
||||
onPreviousPage={onPreviousPage}
|
||||
onUpdateListSettings={onUpdateListSettings}
|
||||
onRowClick={onRowClick}
|
||||
pageInfo={pageInfo}
|
||||
/>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
WebhooksListPage.displayName = "WebhooksListPage";
|
||||
export default WebhooksListPage;
|
2
src/webhooks/components/WebhooksListPage/index.ts
Normal file
2
src/webhooks/components/WebhooksListPage/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
export { default } from "./WebhooksListPage";
|
||||
export * from "./WebhooksListPage";
|
57
src/webhooks/fixtures.ts
Normal file
57
src/webhooks/fixtures.ts
Normal file
|
@ -0,0 +1,57 @@
|
|||
import { ConfigurationTypeFieldEnum } from "@saleor/types/globalTypes";
|
||||
import { Plugin_plugin } from "./types/Plugin";
|
||||
import { Plugins_plugins_edges_node } from "./types/Plugins";
|
||||
|
||||
export const pluginList: Plugins_plugins_edges_node[] = [
|
||||
{
|
||||
__typename: "Plugin",
|
||||
active: true,
|
||||
description:
|
||||
"Lorem ipsum dolor sit amet enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis. Maecenas malesuada elit lectus felis, malesuada ultricies. Curabitur et ligula. Ut molestie a, ultricies porta urna. Vestibulum commodo volutpat a, convallis ac, laoreet enim. Phasellus fermentum in, dolor. Pellentesque facilisis. Nulla imperdiet sit amet magna.",
|
||||
id: "Jzx123sEt==",
|
||||
name: "Avalara"
|
||||
},
|
||||
{
|
||||
__typename: "Plugin",
|
||||
active: false,
|
||||
description:
|
||||
"Lorem ipsum dolor sit amet enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis. Maecenas malesuada elit lectus felis, malesuada ultricies. Curabitur et ligula. Ut molestie a, ultricies porta urna. Vestibulum commodo volutpat a, convallis ac, laoreet enim. Phasellus fermentum in, dolor. Pellentesque facilisis. Nulla imperdiet sit amet magna.",
|
||||
id: "Jzx123sEt==",
|
||||
name: "VatLayer"
|
||||
}
|
||||
];
|
||||
export const plugin: Plugin_plugin = {
|
||||
__typename: "Plugin",
|
||||
active: true,
|
||||
configuration: [
|
||||
{
|
||||
__typename: "ConfigurationItem",
|
||||
helpText: "Provide user or account details",
|
||||
label: "Username or account",
|
||||
name: "Username or account",
|
||||
type: ConfigurationTypeFieldEnum.STRING,
|
||||
value: ""
|
||||
},
|
||||
{
|
||||
__typename: "ConfigurationItem",
|
||||
helpText: "Provide password or license details",
|
||||
label: "Password or license",
|
||||
name: "Password or license",
|
||||
type: ConfigurationTypeFieldEnum.STRING,
|
||||
value: ""
|
||||
},
|
||||
{
|
||||
__typename: "ConfigurationItem",
|
||||
helpText: "Determines if Saleor should use Avatax sandbox API.",
|
||||
label: "Use sandbox",
|
||||
name: "Use sandbox",
|
||||
type: ConfigurationTypeFieldEnum.BOOLEAN,
|
||||
value: "true"
|
||||
}
|
||||
],
|
||||
description:
|
||||
"Lorem ipsum dolor sit amet enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis. Maecenas malesuada elit lectus felis, malesuada ultricies. Curabitur et ligula. Ut molestie a, ultricies porta urna. Vestibulum commodo volutpat a, convallis ac, laoreet enim. Phasellus fermentum in, dolor. Pellentesque facilisis. Nulla imperdiet sit amet magna.",
|
||||
|
||||
id: "UGx1Z2luQ29uZmlndXJhdGlvbjoy",
|
||||
name: "Username or account"
|
||||
};
|
51
src/webhooks/index.tsx
Normal file
51
src/webhooks/index.tsx
Normal file
|
@ -0,0 +1,51 @@
|
|||
import { parse as parseQs } from "qs";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
import { Route, RouteComponentProps, Switch } from "react-router-dom";
|
||||
|
||||
import { sectionNames } from "@saleor/intl";
|
||||
import { WindowTitle } from "../components/WindowTitle";
|
||||
import {
|
||||
webhooksListPath,
|
||||
WebhooksListUrlQueryParams,
|
||||
webhooksPath
|
||||
} from "./urls";
|
||||
import PluginsDetailsComponent from "./views/WebhooksDetails";
|
||||
import PluginsListComponent from "./views/WebhooksList";
|
||||
|
||||
const PluginList: React.StatelessComponent<RouteComponentProps<any>> = ({
|
||||
location
|
||||
}) => {
|
||||
const qs = parseQs(location.search.substr(1));
|
||||
const params: WebhooksListUrlQueryParams = qs;
|
||||
return <PluginsListComponent params={params} />;
|
||||
};
|
||||
|
||||
const PageDetails: React.StatelessComponent<RouteComponentProps<any>> = ({
|
||||
match
|
||||
}) => {
|
||||
const qs = parseQs(location.search.substr(1));
|
||||
const params: WebhooksListUrlQueryParams = qs;
|
||||
|
||||
return (
|
||||
<PluginsDetailsComponent
|
||||
id={decodeURIComponent(match.params.id)}
|
||||
params={params}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const Component = () => {
|
||||
const intl = useIntl();
|
||||
return (
|
||||
<>
|
||||
<WindowTitle title={intl.formatMessage(sectionNames.plugins)} />
|
||||
<Switch>
|
||||
<Route exact path={webhooksListPath} component={PluginList} />
|
||||
<Route path={webhooksPath(":id")} component={PageDetails} />
|
||||
</Switch>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Component;
|
60
src/webhooks/mutations.ts
Normal file
60
src/webhooks/mutations.ts
Normal file
|
@ -0,0 +1,60 @@
|
|||
import gql from "graphql-tag";
|
||||
|
||||
import { TypedMutation } from "../mutations";
|
||||
import { webhooksDetailsFragment } from "./queries";
|
||||
import { WebhookCreate, WebhookCreateVariables } from "./types/WebhookCreate";
|
||||
import { WebhookDelete, WebhookDeleteVariables } from "./types/WebhookDelete";
|
||||
import { WebhookUpdate, WebhookUpdateVariables } from "./types/WebhookUpdate";
|
||||
|
||||
const webhookCreate = gql`
|
||||
${webhooksDetailsFragment}
|
||||
mutation WebhookCreate($input: WebhookCreateInput!) {
|
||||
WebhookCreate(input: $input) {
|
||||
errors {
|
||||
field
|
||||
message
|
||||
}
|
||||
webhook {
|
||||
...WebhooksDetailsFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const TypedWebhookCreate = TypedMutation<
|
||||
WebhookCreate,
|
||||
WebhookCreateVariables
|
||||
>(webhookCreate);
|
||||
|
||||
const webhookUpdate = gql`
|
||||
${webhooksDetailsFragment}
|
||||
mutation WebhookUpdate($id: ID!, $input: WebhookUpdateInput!) {
|
||||
WebhookUpdate(id: $id, input: $input) {
|
||||
errors {
|
||||
field
|
||||
message
|
||||
}
|
||||
webhook {
|
||||
...WebhooksDetailsFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const TypedWebhookUpdate = TypedMutation<
|
||||
WebhookUpdate,
|
||||
WebhookUpdateVariables
|
||||
>(webhookUpdate);
|
||||
|
||||
const WebhookDelete = gql`
|
||||
mutation WebhookDelete($id: ID!) {
|
||||
WebhookDelete(id: $id) {
|
||||
errors {
|
||||
field
|
||||
message
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const TypedWebhookDelete = TypedMutation<
|
||||
WebhookDelete,
|
||||
WebhookDeleteVariables
|
||||
>(WebhookDelete);
|
62
src/webhooks/queries.ts
Normal file
62
src/webhooks/queries.ts
Normal file
|
@ -0,0 +1,62 @@
|
|||
import gql from "graphql-tag";
|
||||
|
||||
import { TypedQuery } from "../queries";
|
||||
import { Webhook, WebhookVariables } from "./types/Webhook";
|
||||
import { Webhooks, WebhooksVariables } from "./types/Webhooks";
|
||||
|
||||
export const webhooksFragment = gql`
|
||||
fragment WebhookFragment on Webhook {
|
||||
id
|
||||
events {
|
||||
eventType
|
||||
}
|
||||
isActive
|
||||
secretKey
|
||||
targetUrl
|
||||
serviceAccount {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const webhooksDetailsFragment = gql`
|
||||
${webhooksFragment}
|
||||
fragment WebhooksDetailsFragment on Webhook {
|
||||
...WebhooksFragment
|
||||
}
|
||||
`;
|
||||
|
||||
const webhooksList = gql`
|
||||
${webhooksFragment}
|
||||
query Webhooks($first: Int, $after: String, $last: Int, $before: String) {
|
||||
webhooks(before: $before, after: $after, first: $first, last: $last) {
|
||||
edges {
|
||||
node {
|
||||
...WebhooksFragment
|
||||
}
|
||||
}
|
||||
pageInfo {
|
||||
hasPreviousPage
|
||||
hasNextPage
|
||||
startCursor
|
||||
endCursor
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const TypedWebhooksListQuery = TypedQuery<Webhooks, WebhooksVariables>(
|
||||
webhooksList
|
||||
);
|
||||
|
||||
const webhooksDetails = gql`
|
||||
${webhooksFragment}
|
||||
query Webhook($id: ID!) {
|
||||
webhook(id: $id) {
|
||||
...WebhooksFragment
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const TypedWebhooksDetailsQuery = TypedQuery<Webhook, WebhookVariables>(
|
||||
webhooksDetails
|
||||
);
|
16
src/webhooks/urls.ts
Normal file
16
src/webhooks/urls.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
import { stringify as stringifyQs } from "qs";
|
||||
import urlJoin from "url-join";
|
||||
|
||||
import { Pagination, SingleAction } from "../types";
|
||||
|
||||
export const webhooksSection = "/webhooks/";
|
||||
|
||||
export const webhooksListPath = webhooksSection;
|
||||
export type WebhooksListUrlQueryParams = Pagination & SingleAction;
|
||||
export const webhooksListUrl = (params?: WebhooksListUrlQueryParams) =>
|
||||
webhooksPath + "?" + stringifyQs(params);
|
||||
|
||||
export const webhooksPath = (id: string) => urlJoin(webhooksSection, id);
|
||||
export type WebhooksUrlQueryParams = SingleAction;
|
||||
export const webhooksUrl = (id: string, params?: WebhooksUrlQueryParams) =>
|
||||
webhooksPath(encodeURIComponent(id)) + "?" + stringifyQs(params);
|
100
src/webhooks/views/WebhooksDetails.tsx
Normal file
100
src/webhooks/views/WebhooksDetails.tsx
Normal file
|
@ -0,0 +1,100 @@
|
|||
import { WindowTitle } from "@saleor/components/WindowTitle";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import { getMutationState, maybe } from "../../misc";
|
||||
import WebhooksDetailsPage from "../components/WebhooksDetailsPage";
|
||||
import { TypedPluginUpdate } from "../mutations";
|
||||
import { TypedPluginsDetailsQuery } from "../queries";
|
||||
import { pluginsListUrl, PluginsListUrlQueryParams } from "../urls";
|
||||
|
||||
export interface PluginsDetailsProps {
|
||||
id: string;
|
||||
params: PluginsListUrlQueryParams;
|
||||
}
|
||||
|
||||
export const PluginsDetails: React.StatelessComponent<PluginsDetailsProps> = ({
|
||||
id
|
||||
}) => {
|
||||
const navigate = useNavigator();
|
||||
const notify = useNotifier();
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<TypedPluginUpdate>
|
||||
{(pluginUpdate, pluginUpdateOpts) => (
|
||||
<TypedPluginsDetailsQuery variables={{ id }}>
|
||||
{PluginDetails => {
|
||||
const formTransitionState = getMutationState(
|
||||
pluginUpdateOpts.called,
|
||||
pluginUpdateOpts.loading,
|
||||
maybe(() => pluginUpdateOpts.data.pluginUpdate.errors)
|
||||
);
|
||||
|
||||
const formErrors = maybe(
|
||||
() => pluginUpdateOpts.data.pluginUpdate.errors,
|
||||
[]
|
||||
);
|
||||
|
||||
if (formErrors.length) {
|
||||
formErrors.map(error => {
|
||||
notify({
|
||||
text: error.message
|
||||
});
|
||||
});
|
||||
} else {
|
||||
if (pluginUpdateOpts.data) {
|
||||
notify({
|
||||
text: intl.formatMessage({
|
||||
defaultMessage: "Succesfully updated plugin settings",
|
||||
description: "plugin success message"
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<WindowTitle
|
||||
title={maybe(() => PluginDetails.data.plugin.name)}
|
||||
/>
|
||||
<WebhooksDetailsPage
|
||||
disabled={PluginDetails.loading}
|
||||
errors={formErrors}
|
||||
saveButtonBarState={formTransitionState}
|
||||
plugin={maybe(() => PluginDetails.data.plugin)}
|
||||
onBack={() => navigate(pluginsListUrl())}
|
||||
onSubmit={formData => {
|
||||
const configurationInput =
|
||||
formData.configuration &&
|
||||
formData.configuration.map(item => {
|
||||
return {
|
||||
name: item.name,
|
||||
value: item.value.toString()
|
||||
};
|
||||
});
|
||||
pluginUpdate({
|
||||
variables: {
|
||||
id,
|
||||
input: {
|
||||
active: formData.active,
|
||||
configuration: configurationInput
|
||||
? configurationInput
|
||||
: null
|
||||
}
|
||||
}
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</TypedPluginsDetailsQuery>
|
||||
)}
|
||||
</TypedPluginUpdate>
|
||||
);
|
||||
};
|
||||
PluginsDetails.displayName = "PluginsDetails";
|
||||
export default PluginsDetails;
|
58
src/webhooks/views/WebhooksList.tsx
Normal file
58
src/webhooks/views/WebhooksList.tsx
Normal file
|
@ -0,0 +1,58 @@
|
|||
import { configurationMenuUrl } from "@saleor/configuration";
|
||||
import useListSettings from "@saleor/hooks/useListSettings";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import usePaginator, {
|
||||
createPaginationState
|
||||
} from "@saleor/hooks/usePaginator";
|
||||
import { maybe } from "@saleor/misc";
|
||||
import { ListViews } from "@saleor/types";
|
||||
import React from "react";
|
||||
|
||||
import WebhooksListPage from "../components/WebhooksListPage/PluginsListPage";
|
||||
import { TypedWebhooksListQuery } from "../queries";
|
||||
import { WebhooksListUrlQueryParams, webhooksUrl } from "../urls";
|
||||
|
||||
interface PluginsListProps {
|
||||
params: WebhooksListUrlQueryParams;
|
||||
}
|
||||
|
||||
export const PluginsList: React.StatelessComponent<PluginsListProps> = ({
|
||||
params
|
||||
}) => {
|
||||
const navigate = useNavigator();
|
||||
const paginate = usePaginator();
|
||||
const { updateListSettings, settings } = useListSettings(
|
||||
ListViews.PLUGINS_LIST
|
||||
);
|
||||
const paginationState = createPaginationState(settings.rowNumber, params);
|
||||
|
||||
return (
|
||||
<TypedWebhooksListQuery displayLoader variables={paginationState}>
|
||||
{({ data, loading }) => {
|
||||
const { loadNextPage, loadPreviousPage, pageInfo } = paginate(
|
||||
maybe(() => data.plugins.pageInfo),
|
||||
paginationState,
|
||||
params
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<WebhooksListPage
|
||||
disabled={loading}
|
||||
settings={settings}
|
||||
webhooks={maybe(() => data.plugins.edges.map(edge => edge.node))}
|
||||
pageInfo={pageInfo}
|
||||
onAdd={() => navigate(configurationMenuUrl)}
|
||||
onBack={() => navigate(configurationMenuUrl)}
|
||||
onNextPage={loadNextPage}
|
||||
onPreviousPage={loadPreviousPage}
|
||||
onUpdateListSettings={updateListSettings}
|
||||
onRowClick={id => () => navigate(webhooksUrl(id))}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</TypedWebhooksListQuery>
|
||||
);
|
||||
};
|
||||
|
||||
export default PluginsList;
|
Loading…
Reference in a new issue