From 4021b8ec62db16945b4e83c46ee61c8d059b5bf4 Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Wed, 9 Oct 2019 08:01:52 +0200 Subject: [PATCH 01/38] Add webhook components --- src/intl.ts | 4 + .../WebhookEvents/WebhookEvents.tsx | 57 +++++++ .../components/WebhookEvents/index.ts | 2 + .../components/WebhookInfo/WebhookInfo.tsx | 53 ++++++ src/webhooks/components/WebhookInfo/index.ts | 2 + .../WebhookStatus/WebhookStatus.tsx | 57 +++++++ .../components/WebhookStatus/index.ts | 2 + .../WebhooksDetailsPage.tsx | 78 +++++++++ .../components/WebhooksDetailsPage/index.ts | 2 + .../components/WebhooksList/WebhooksList.tsx | 155 ++++++++++++++++++ src/webhooks/components/WebhooksList/index.ts | 2 + .../WebhooksListPage/WebhooksListPage.tsx | 49 ++++++ .../components/WebhooksListPage/index.ts | 2 + src/webhooks/fixtures.ts | 57 +++++++ src/webhooks/index.tsx | 51 ++++++ src/webhooks/mutations.ts | 60 +++++++ src/webhooks/queries.ts | 62 +++++++ src/webhooks/urls.ts | 16 ++ src/webhooks/views/WebhooksDetails.tsx | 100 +++++++++++ src/webhooks/views/WebhooksList.tsx | 58 +++++++ 20 files changed, 869 insertions(+) create mode 100644 src/webhooks/components/WebhookEvents/WebhookEvents.tsx create mode 100644 src/webhooks/components/WebhookEvents/index.ts create mode 100644 src/webhooks/components/WebhookInfo/WebhookInfo.tsx create mode 100644 src/webhooks/components/WebhookInfo/index.ts create mode 100644 src/webhooks/components/WebhookStatus/WebhookStatus.tsx create mode 100644 src/webhooks/components/WebhookStatus/index.ts create mode 100644 src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx create mode 100644 src/webhooks/components/WebhooksDetailsPage/index.ts create mode 100644 src/webhooks/components/WebhooksList/WebhooksList.tsx create mode 100644 src/webhooks/components/WebhooksList/index.ts create mode 100644 src/webhooks/components/WebhooksListPage/WebhooksListPage.tsx create mode 100644 src/webhooks/components/WebhooksListPage/index.ts create mode 100644 src/webhooks/fixtures.ts create mode 100644 src/webhooks/index.tsx create mode 100644 src/webhooks/mutations.ts create mode 100644 src/webhooks/queries.ts create mode 100644 src/webhooks/urls.ts create mode 100644 src/webhooks/views/WebhooksDetails.tsx create mode 100644 src/webhooks/views/WebhooksList.tsx diff --git a/src/intl.ts b/src/intl.ts index a15b105a1..867bf279c 100644 --- a/src/intl.ts +++ b/src/intl.ts @@ -202,6 +202,10 @@ export const sectionNames = defineMessages({ vouchers: { defaultMessage: "Vouchers", description: "vouchers section name" + }, + webhooks: { + defaultMessage: "Webhooks", + description: "webhooks section name" } }); diff --git a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx new file mode 100644 index 000000000..cf2b168ef --- /dev/null +++ b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx @@ -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) => 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 = ({ + data, + disabled, + errors, + onChange, + fields +}) => { + const classes = useStyles({}); + const intl = useIntl(); + return ( + + + + + ); +}; +WebhookEvents.displayName = "WebhookEvents"; +export default WebhookEvents; diff --git a/src/webhooks/components/WebhookEvents/index.ts b/src/webhooks/components/WebhookEvents/index.ts new file mode 100644 index 000000000..a756533f2 --- /dev/null +++ b/src/webhooks/components/WebhookEvents/index.ts @@ -0,0 +1,2 @@ +export { default } from "./WebhookEvents; +export * from "./WebhookEvents; diff --git a/src/webhooks/components/WebhookInfo/WebhookInfo.tsx b/src/webhooks/components/WebhookInfo/WebhookInfo.tsx new file mode 100644 index 000000000..64ac09fda --- /dev/null +++ b/src/webhooks/components/WebhookInfo/WebhookInfo.tsx @@ -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) => void; +} + +const useStyles = makeStyles(() => ({ + status: { + paddingTop: 20 + }, + title: { + fontSize: 14, + paddingTop: 10 + } +})); + +const WebhookInfo: React.StatelessComponent = ({ + data, + description, + name, + onChange +}) => { + const classes = useStyles({}); + const intl = useIntl(); + return ( + + + + + ); +}; +WebhookInfo.displayName = "WebhookInfo"; +export default WebhookInfo; diff --git a/src/webhooks/components/WebhookInfo/index.ts b/src/webhooks/components/WebhookInfo/index.ts new file mode 100644 index 000000000..8c767a478 --- /dev/null +++ b/src/webhooks/components/WebhookInfo/index.ts @@ -0,0 +1,2 @@ +export { default } from "./WebhookInfoo"; +export * from "./WebhookInfoo"; diff --git a/src/webhooks/components/WebhookStatus/WebhookStatus.tsx b/src/webhooks/components/WebhookStatus/WebhookStatus.tsx new file mode 100644 index 000000000..f674f9539 --- /dev/null +++ b/src/webhooks/components/WebhookStatus/WebhookStatus.tsx @@ -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) => 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 = ({ + data, + disabled, + errors, + onChange, + fields +}) => { + const classes = useStyles({}); + const intl = useIntl(); + return ( + + + + + ); +}; +WebhookStatus.displayName = "WebhookStatus"; +export default WebhookStatus; diff --git a/src/webhooks/components/WebhookStatus/index.ts b/src/webhooks/components/WebhookStatus/index.ts new file mode 100644 index 000000000..87e64e1c3 --- /dev/null +++ b/src/webhooks/components/WebhookStatus/index.ts @@ -0,0 +1,2 @@ +export { default } from "./WebhookStatus; +export * from "./WebhookStatus; diff --git a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx new file mode 100644 index 000000000..0a9f722d0 --- /dev/null +++ b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx @@ -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 ( +
+ {({ data, errors, hasChanged, submit, set, triggerChange }) => { + return ( + + + {intl.formatMessage(sectionNames.plugins)} + + plugin.name, "...") + } + )} + /> + +
+
+ +
+ ); + }} +
+ ); +}; +WebhooksDetailsPage.displayName = "WebhooksDetailsPage"; +export default WebhooksDetailsPage; diff --git a/src/webhooks/components/WebhooksDetailsPage/index.ts b/src/webhooks/components/WebhooksDetailsPage/index.ts new file mode 100644 index 000000000..c09cb2fe6 --- /dev/null +++ b/src/webhooks/components/WebhooksDetailsPage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./WebhooksDetailsPage"; +export * from "./WebhooksDetailsPage"; diff --git a/src/webhooks/components/WebhooksList/WebhooksList.tsx b/src/webhooks/components/WebhooksList/WebhooksList.tsx new file mode 100644 index 000000000..19643d3e6 --- /dev/null +++ b/src/webhooks/components/WebhooksList/WebhooksList.tsx @@ -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) => { + const intl = useIntl(); + return ( + + + + + {intl.formatMessage({ + defaultMessage: "Name", + description: "webhook name" + })} + + + {intl.formatMessage({ + defaultMessage: "Service Account", + description: "webhook service account" + })} + + + {intl.formatMessage({ + defaultMessage: "Action", + description: "user action bar" + })} + + + + + + + + + {renderCollection( + webhooks, + webhook => { + return ( + // + // + // {maybe(() => plugin.name, )} + // + // + // {maybe( + // () => ( + // + // ), + // + // )} + // + // + //
+ // + //
+ //
+ //
+ ); + }, + () => ( + + + {intl.formatMessage({ + defaultMessage: "No plugins found" + })} + + + ) + )} +
+
+
+ ); + } +); +WebhooksList.displayName = "WebhooksList"; +export default WebhooksList; diff --git a/src/webhooks/components/WebhooksList/index.ts b/src/webhooks/components/WebhooksList/index.ts new file mode 100644 index 000000000..b3d7c9391 --- /dev/null +++ b/src/webhooks/components/WebhooksList/index.ts @@ -0,0 +1,2 @@ +export { default } from "./WebhooksListt"; +export * from "./WebhooksListt"; diff --git a/src/webhooks/components/WebhooksListPage/WebhooksListPage.tsx b/src/webhooks/components/WebhooksListPage/WebhooksListPage.tsx new file mode 100644 index 000000000..20ced1671 --- /dev/null +++ b/src/webhooks/components/WebhooksListPage/WebhooksListPage.tsx @@ -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 = ({ + disabled, + settings, + onBack, + onNextPage, + onPreviousPage, + onRowClick, + onUpdateListSettings, + pageInfo, + webhooks +}) => { + const intl = useIntl(); + return ( + + + {intl.formatMessage(sectionNames.configuration)} + + + + + ); +}; +WebhooksListPage.displayName = "WebhooksListPage"; +export default WebhooksListPage; diff --git a/src/webhooks/components/WebhooksListPage/index.ts b/src/webhooks/components/WebhooksListPage/index.ts new file mode 100644 index 000000000..68f52d520 --- /dev/null +++ b/src/webhooks/components/WebhooksListPage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./WebhooksListPage"; +export * from "./WebhooksListPage"; diff --git a/src/webhooks/fixtures.ts b/src/webhooks/fixtures.ts new file mode 100644 index 000000000..4da3ce27b --- /dev/null +++ b/src/webhooks/fixtures.ts @@ -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" +}; diff --git a/src/webhooks/index.tsx b/src/webhooks/index.tsx new file mode 100644 index 000000000..e6fe869ed --- /dev/null +++ b/src/webhooks/index.tsx @@ -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> = ({ + location +}) => { + const qs = parseQs(location.search.substr(1)); + const params: WebhooksListUrlQueryParams = qs; + return ; +}; + +const PageDetails: React.StatelessComponent> = ({ + match +}) => { + const qs = parseQs(location.search.substr(1)); + const params: WebhooksListUrlQueryParams = qs; + + return ( + + ); +}; + +const Component = () => { + const intl = useIntl(); + return ( + <> + + + + + + + ); +}; + +export default Component; diff --git a/src/webhooks/mutations.ts b/src/webhooks/mutations.ts new file mode 100644 index 000000000..e766cd8f4 --- /dev/null +++ b/src/webhooks/mutations.ts @@ -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); diff --git a/src/webhooks/queries.ts b/src/webhooks/queries.ts new file mode 100644 index 000000000..f24e185ee --- /dev/null +++ b/src/webhooks/queries.ts @@ -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( + webhooksList +); + +const webhooksDetails = gql` + ${webhooksFragment} + query Webhook($id: ID!) { + webhook(id: $id) { + ...WebhooksFragment + } + } +`; +export const TypedWebhooksDetailsQuery = TypedQuery( + webhooksDetails +); diff --git a/src/webhooks/urls.ts b/src/webhooks/urls.ts new file mode 100644 index 000000000..f12eae33a --- /dev/null +++ b/src/webhooks/urls.ts @@ -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); diff --git a/src/webhooks/views/WebhooksDetails.tsx b/src/webhooks/views/WebhooksDetails.tsx new file mode 100644 index 000000000..a6e8d6cd9 --- /dev/null +++ b/src/webhooks/views/WebhooksDetails.tsx @@ -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 = ({ + id +}) => { + const navigate = useNavigator(); + const notify = useNotifier(); + const intl = useIntl(); + + return ( + + {(pluginUpdate, pluginUpdateOpts) => ( + + {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 ( + <> + PluginDetails.data.plugin.name)} + /> + 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 + } + } + }); + }} + /> + + ); + }} + + )} + + ); +}; +PluginsDetails.displayName = "PluginsDetails"; +export default PluginsDetails; diff --git a/src/webhooks/views/WebhooksList.tsx b/src/webhooks/views/WebhooksList.tsx new file mode 100644 index 000000000..67d7793d7 --- /dev/null +++ b/src/webhooks/views/WebhooksList.tsx @@ -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 = ({ + params +}) => { + const navigate = useNavigator(); + const paginate = usePaginator(); + const { updateListSettings, settings } = useListSettings( + ListViews.PLUGINS_LIST + ); + const paginationState = createPaginationState(settings.rowNumber, params); + + return ( + + {({ data, loading }) => { + const { loadNextPage, loadPreviousPage, pageInfo } = paginate( + maybe(() => data.plugins.pageInfo), + paginationState, + params + ); + return ( + <> + 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))} + /> + + ); + }} + + ); +}; + +export default PluginsList; From be8095b22fa5497b9244803a1e0b6483b8730ecc Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Wed, 9 Oct 2019 08:56:46 +0200 Subject: [PATCH 02/38] Update types --- schema.graphql | 69 +++++++++++++++---- src/types.ts | 3 +- src/types/globalTypes.ts | 28 ++++++++ .../WebhooksDetailsPage.tsx | 54 ++++++++++++--- .../components/WebhooksList/WebhooksList.tsx | 4 +- src/webhooks/components/WebhooksList/index.ts | 4 +- .../WebhooksListPage/WebhooksListPage.tsx | 4 +- src/webhooks/mutations.ts | 6 +- src/webhooks/queries.ts | 7 +- src/webhooks/types/Webhook.ts | 37 ++++++++++ src/webhooks/types/WebhookCreate.ts | 51 ++++++++++++++ src/webhooks/types/WebhookDelete.ts | 26 +++++++ src/webhooks/types/WebhookFragment.ts | 29 ++++++++ src/webhooks/types/WebhookUpdate.ts | 52 ++++++++++++++ src/webhooks/types/Webhooks.ts | 59 ++++++++++++++++ src/webhooks/types/WebhooksDetailsFragment.ts | 29 ++++++++ src/webhooks/views/WebhooksDetails.tsx | 52 +++++++------- src/webhooks/views/WebhooksList.tsx | 14 ++-- 18 files changed, 457 insertions(+), 71 deletions(-) create mode 100644 src/webhooks/types/Webhook.ts create mode 100644 src/webhooks/types/WebhookCreate.ts create mode 100644 src/webhooks/types/WebhookDelete.ts create mode 100644 src/webhooks/types/WebhookFragment.ts create mode 100644 src/webhooks/types/WebhookUpdate.ts create mode 100644 src/webhooks/types/Webhooks.ts create mode 100644 src/webhooks/types/WebhooksDetailsFragment.ts diff --git a/schema.graphql b/schema.graphql index 2cac71003..eaa7a9b2a 100644 --- a/schema.graphql +++ b/schema.graphql @@ -604,7 +604,7 @@ type Checkout implements Node { privateMeta: [MetaStore]! meta: [MetaStore]! availableShippingMethods: [ShippingMethod]! - availablePaymentGateways: [String]! + availablePaymentGateways: [PaymentGateway]! email: String! isShippingRequired: Boolean! lines: [CheckoutLine] @@ -625,13 +625,13 @@ type CheckoutBillingAddressUpdate { checkoutErrors: [CheckoutError!] } -type CheckoutClearStoredMeta { +type CheckoutClearMeta { errors: [Error!] checkoutErrors: [CheckoutError!] checkout: Checkout } -type CheckoutClearStoredPrivateMeta { +type CheckoutClearPrivateMeta { errors: [Error!] checkoutErrors: [CheckoutError!] checkout: Checkout @@ -1610,6 +1610,11 @@ input FulfillmentUpdateTrackingInput { notifyCustomer: Boolean } +type GatewayConfigLine { + field: String! + value: String +} + scalar GenericScalar type Geolocalization { @@ -2107,12 +2112,16 @@ type Mutations { orderAddNote(order: ID!, input: OrderAddNoteInput!): OrderAddNote orderCancel(id: ID!, restock: Boolean!): OrderCancel orderCapture(amount: Decimal!, id: ID!): OrderCapture + orderClearPrivateMeta(id: ID!, input: MetaPath!): OrderClearPrivateMeta + orderClearMeta(id: ID!, input: MetaPath!): OrderClearMeta orderFulfillmentCancel(id: ID!, input: FulfillmentCancelInput!): FulfillmentCancel orderFulfillmentCreate(input: FulfillmentCreateInput!, order: ID): FulfillmentCreate orderFulfillmentUpdateTracking(id: ID!, input: FulfillmentUpdateTrackingInput!): FulfillmentUpdateTracking orderMarkAsPaid(id: ID!): OrderMarkAsPaid orderRefund(amount: Decimal!, id: ID!): OrderRefund orderUpdate(id: ID!, input: OrderUpdateInput!): OrderUpdate + orderUpdateMeta(id: ID!, input: MetaInput!): OrderUpdateMeta + orderUpdatePrivateMeta(id: ID!, input: MetaInput!): OrderUpdatePrivateMeta orderUpdateShipping(order: ID!, input: OrderUpdateShippingInput): OrderUpdateShipping orderVoid(id: ID!): OrderVoid orderBulkCancel(ids: [ID]!, restock: Boolean!): OrderBulkCancel @@ -2165,14 +2174,14 @@ type Mutations { checkoutShippingMethodUpdate(checkoutId: ID, shippingMethodId: ID!): CheckoutShippingMethodUpdate checkoutUpdateVoucher(checkoutId: ID!, voucherCode: String): CheckoutUpdateVoucher checkoutUpdateMetadata(id: ID!, input: MetaInput!): CheckoutUpdateMeta - checkoutClearMetadata(id: ID!, input: MetaPath!): CheckoutClearStoredMeta + checkoutClearMetadata(id: ID!, input: MetaPath!): CheckoutClearMeta checkoutUpdatePrivateMetadata(id: ID!, input: MetaInput!): CheckoutUpdatePrivateMeta - checkoutClearPrivateMetadata(id: ID!, input: MetaPath!): CheckoutClearStoredPrivateMeta + checkoutClearPrivateMetadata(id: ID!, input: MetaPath!): CheckoutClearPrivateMeta requestPasswordReset(email: String!, redirectUrl: String!): RequestPasswordReset setPassword(token: String!, email: String!, password: String!): SetPassword passwordChange(newPassword: String!, oldPassword: String!): PasswordChange userUpdateMetadata(id: ID!, input: MetaInput!): UserUpdateMeta - userClearStoredMetadata(id: ID!, input: MetaPath!): UserClearStoredMeta + userClearMetadata(id: ID!, input: MetaPath!): UserClearMeta accountAddressCreate(input: AddressInput!, type: AddressTypeEnum): AccountAddressCreate accountAddressUpdate(id: ID!, input: AddressInput!): AccountAddressUpdate accountAddressDelete(id: ID!): AccountAddressDelete @@ -2202,12 +2211,12 @@ type Mutations { userAvatarDelete: UserAvatarDelete userBulkSetActive(ids: [ID]!, isActive: Boolean!): UserBulkSetActive userUpdatePrivateMetadata(id: ID!, input: MetaInput!): UserUpdatePrivateMeta - userClearStoredPrivateMetadata(id: ID!, input: MetaPath!): UserClearStoredPrivateMeta + userClearPrivateMetadata(id: ID!, input: MetaPath!): UserClearPrivateMeta serviceAccountCreate(input: ServiceAccountInput!): ServiceAccountCreate serviceAccountUpdate(id: ID!, input: ServiceAccountInput!): ServiceAccountUpdate serviceAccountDelete(id: ID!): ServiceAccountDelete serviceAccountUpdatePrivateMetadata(id: ID!, input: MetaInput!): ServiceAccountUpdatePrivateMeta - serviceAccountClearStoredPrivateMetadata(id: ID!, input: MetaPath!): ServiceAccountClearStoredPrivateMeta + serviceAccountClearPrivateMetadata(id: ID!, input: MetaPath!): ServiceAccountClearPrivateMeta serviceAccountTokenCreate(input: ServiceAccountTokenInput!): ServiceAccountTokenCreate serviceAccountTokenDelete(id: ID!): ServiceAccountTokenDelete passwordReset(email: String!): PasswordReset @@ -2252,6 +2261,8 @@ type Order implements Node { displayGrossPrices: Boolean! customerNote: String! weight: Weight + privateMeta: [MetaStore]! + meta: [MetaStore]! fulfillments: [Fulfillment]! lines: [OrderLine]! actions: [OrderAction]! @@ -2310,6 +2321,16 @@ type OrderCapture { orderErrors: [OrderError!] } +type OrderClearMeta { + errors: [Error!] + order: Order +} + +type OrderClearPrivateMeta { + errors: [Error!] + order: Order +} + type OrderCountableConnection { pageInfo: PageInfo! edges: [OrderCountableEdge!]! @@ -2504,6 +2525,16 @@ input OrderUpdateInput { shippingAddress: AddressInput } +type OrderUpdateMeta { + errors: [Error!] + order: Order +} + +type OrderUpdatePrivateMeta { + errors: [Error!] + order: Order +} + type OrderUpdateShipping { errors: [Error!] order: Order @@ -2689,6 +2720,11 @@ enum PaymentErrorCode { UNIQUE } +type PaymentGateway { + name: String! + config: [GatewayConfigLine!]! +} + input PaymentInput { gateway: String! token: String! @@ -2800,11 +2836,11 @@ type Product implements Node { meta: [MetaStore]! url: String! thumbnail(size: Int): Image - availability: ProductPricingInfo @deprecated(reason: "DEPRECATED: Will be removed in Saleor 2.10, Has been renamed to 'pricing'.") + availability: ProductPricingInfo @deprecated(reason: "DEPRECATED: Will be removed in Saleor 2.10, Has been renamed to `pricing`.") pricing: ProductPricingInfo isAvailable: Boolean basePrice: Money - price: Money @deprecated(reason: "DEPRECATED: Will be removed in Saleor 2.10, has been replaced by 'basePrice'") + price: Money @deprecated(reason: "DEPRECATED: Will be removed in Saleor 2.10, has been replaced by `basePrice`") minimalVariantPrice: Money taxType: TaxType attributes: [SelectedAttribute!]! @@ -3168,7 +3204,7 @@ type ProductVariant implements Node { stockQuantity: Int! priceOverride: Money price: Money @deprecated(reason: "DEPRECATED: Will be removed in Saleor 2.10, has been replaced by 'pricing.priceUndiscounted'") - availability: VariantPricingInfo @deprecated(reason: "DEPRECATED: Will be removed in Saleor 2.10, has been renamed to 'pricing'.") + availability: VariantPricingInfo @deprecated(reason: "DEPRECATED: Will be removed in Saleor 2.10, has been renamed to `pricing`.") pricing: VariantPricingInfo isAvailable: Boolean attributes: [SelectedAttribute!]! @@ -3313,7 +3349,7 @@ type Query { reportProductSales(period: ReportingPeriod!, before: String, after: String, first: Int, last: Int): ProductVariantCountableConnection payment(id: ID!): Payment payments(before: String, after: String, first: Int, last: Int): PaymentCountableConnection - paymentClientToken(gateway: String!): String + paymentClientToken(gateway: String!): String @deprecated(reason: "DEPRECATED: Will be removed in Saleor 2.10, use payment gateway config instead in availablePaymentGateways.") page(id: ID, slug: String): Page pages(query: String, filter: PageFilterInput, before: String, after: String, first: Int, last: Int): PageCountableConnection homepageEvents(before: String, after: String, first: Int, last: Int): OrderEventCountableConnection @@ -3484,7 +3520,7 @@ type ServiceAccount implements Node { name: String } -type ServiceAccountClearStoredPrivateMeta { +type ServiceAccountClearPrivateMeta { errors: [Error!] accountErrors: [AccountError!] serviceAccount: ServiceAccount @@ -4026,13 +4062,13 @@ type UserBulkSetActive { accountErrors: [AccountError!] } -type UserClearStoredMeta { +type UserClearMeta { errors: [Error!] accountErrors: [AccountError!] user: User } -type UserClearStoredPrivateMeta { +type UserClearPrivateMeta { errors: [Error!] accountErrors: [AccountError!] user: User @@ -4223,6 +4259,7 @@ type VoucherUpdate { } type Webhook implements Node { + name: String serviceAccount: ServiceAccount! targetUrl: String! isActive: Boolean! @@ -4249,6 +4286,7 @@ type WebhookCreate { } input WebhookCreateInput { + name: String targetUrl: String events: [WebhookEventTypeEnum] serviceAccount: ID @@ -4297,6 +4335,7 @@ type WebhookUpdate { } input WebhookUpdateInput { + name: String targetUrl: String events: [WebhookEventTypeEnum] serviceAccount: ID diff --git a/src/types.ts b/src/types.ts index 77ffb5cbd..c466b2fe2 100644 --- a/src/types.ts +++ b/src/types.ts @@ -28,7 +28,8 @@ export enum ListViews { SALES_LIST = "SALES_LIST", SHIPPING_METHODS_LIST = "SHIPPING_METHODS_LIST", STAFF_MEMBERS_LIST = "STAFF_MEMBERS_LIST", - VOUCHER_LIST = "VOUCHER_LIST" + VOUCHER_LIST = "VOUCHER_LIST", + WEBHOOK_LIST = "WEBHOOK_LIST" } export interface ListProps { diff --git a/src/types/globalTypes.ts b/src/types/globalTypes.ts index 1e8cfaf3a..d3754b168 100644 --- a/src/types/globalTypes.ts +++ b/src/types/globalTypes.ts @@ -272,6 +272,16 @@ export enum VoucherTypeEnum { SPECIFIC_PRODUCT = "SPECIFIC_PRODUCT", } +export enum WebhookEventTypeEnum { + ALL_EVENTS = "ALL_EVENTS", + CUSTOMER_CREATED = "CUSTOMER_CREATED", + ORDER_CANCELLED = "ORDER_CANCELLED", + ORDER_CREATED = "ORDER_CREATED", + ORDER_FULLY_PAID = "ORDER_FULLY_PAID", + ORDER_UPDATED = "ORDER_UPDATED", + PRODUCT_CREATED = "PRODUCT_CREATED", +} + export enum WeightUnitsEnum { G = "G", KG = "KG", @@ -775,6 +785,24 @@ export interface VoucherInput { usageLimit?: number | null; } +export interface WebhookCreateInput { + name?: string | null; + targetUrl?: string | null; + events?: (WebhookEventTypeEnum | null)[] | null; + serviceAccount?: string | null; + isActive?: boolean | null; + secretKey?: string | null; +} + +export interface WebhookUpdateInput { + name?: string | null; + targetUrl?: string | null; + events?: (WebhookEventTypeEnum | null)[] | null; + serviceAccount?: string | null; + isActive?: boolean | null; + secretKey?: string | null; +} + //============================================================== // END Enums and Input Objects //============================================================== diff --git a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx index 0a9f722d0..94318ebfa 100644 --- a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx +++ b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx @@ -13,19 +13,28 @@ 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 { + Webhook_webhook, + Webhook_webhook_events, + Webhook_webhook_serviceAccount +} from "../../types/Webhook"; import WebhookEvents from "../WebhookEvents"; +import WebhookInfo from "../WebhookInfo"; +import WebhookStatus from "../WebhookStatus"; export interface FormData { - active: boolean; - configuration: ConfigurationItemInput[]; + id: string; + events: Webhook_webhook_events; + isActive: boolean; + secretKey: string | null; + targetUrl: string; + serviceAccount: Webhook_webhook_serviceAccount; } export interface WebhooksDetailsPageProps { disabled: boolean; errors: UserError[]; - plugin: Plugin_plugin; + webhook: Webhook_webhook; saveButtonBarState: ConfirmButtonTransitionState; onBack: () => void; onSubmit: (data: FormData) => void; @@ -33,16 +42,20 @@ export interface WebhooksDetailsPageProps { const WebhooksDetailsPage: React.StatelessComponent< WebhooksDetailsPageProps -> = ({ disabled, errors, plugin, saveButtonBarState, onBack, onSubmit }) => { +> = ({ disabled, errors, webhook, saveButtonBarState, onBack, onSubmit }) => { const intl = useIntl(); const initialForm: FormData = { - active: maybe(() => plugin.active, false), - configuration: maybe(() => plugin.configuration, []) + events: maybe(() => webhook.events, []), + id: maybe(() => webhook.id, null), + isActive: maybe(() => webhook.isActive, false), + secretKey: maybe(() => webhook.secretKey, ""), + serviceAccount: maybe(() => webhook.serviceAccount, []), + targetUrl: maybe(() => webhook.targetUrl, "") }; return (
- {({ data, errors, hasChanged, submit, set, triggerChange }) => { + {({ data, errors, hasChanged, submit, change }) => { return ( @@ -60,7 +73,28 @@ const WebhooksDetailsPage: React.StatelessComponent< )} /> -
+
+ plugin.description, "")} + errors={errors} + onChange={change} + /> +
+
+ plugin.name, "")} + onChange={change} + /> + plugin.name, "")} + onChange={change} + /> +
diff --git a/src/webhooks/components/WebhooksList/index.ts b/src/webhooks/components/WebhooksList/index.ts index b3d7c9391..a9be5a3b1 100644 --- a/src/webhooks/components/WebhooksList/index.ts +++ b/src/webhooks/components/WebhooksList/index.ts @@ -1,2 +1,2 @@ -export { default } from "./WebhooksListt"; -export * from "./WebhooksListt"; +export { default } from "./WebhooksList"; +export * from "./WebhooksList"; diff --git a/src/webhooks/components/WebhooksListPage/WebhooksListPage.tsx b/src/webhooks/components/WebhooksListPage/WebhooksListPage.tsx index 20ced1671..018577960 100644 --- a/src/webhooks/components/WebhooksListPage/WebhooksListPage.tsx +++ b/src/webhooks/components/WebhooksListPage/WebhooksListPage.tsx @@ -6,11 +6,11 @@ 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 { Webhooks_webhooks_edges_node } from "../../types/Webhooks"; import WebhooksList from "../WebhooksList/WebhooksList"; export interface WebhooksListPageProps extends PageListProps { - plugins: Plugins_plugins_edges_node[]; + webhooks: Webhooks_webhooks_edges_node[]; onBack: () => void; } diff --git a/src/webhooks/mutations.ts b/src/webhooks/mutations.ts index e766cd8f4..2b3b899f0 100644 --- a/src/webhooks/mutations.ts +++ b/src/webhooks/mutations.ts @@ -9,7 +9,7 @@ import { WebhookUpdate, WebhookUpdateVariables } from "./types/WebhookUpdate"; const webhookCreate = gql` ${webhooksDetailsFragment} mutation WebhookCreate($input: WebhookCreateInput!) { - WebhookCreate(input: $input) { + webhookCreate(input: $input) { errors { field message @@ -28,7 +28,7 @@ export const TypedWebhookCreate = TypedMutation< const webhookUpdate = gql` ${webhooksDetailsFragment} mutation WebhookUpdate($id: ID!, $input: WebhookUpdateInput!) { - WebhookUpdate(id: $id, input: $input) { + webhookUpdate(id: $id, input: $input) { errors { field message @@ -46,7 +46,7 @@ export const TypedWebhookUpdate = TypedMutation< const WebhookDelete = gql` mutation WebhookDelete($id: ID!) { - WebhookDelete(id: $id) { + webhookDelete(id: $id) { errors { field message diff --git a/src/webhooks/queries.ts b/src/webhooks/queries.ts index f24e185ee..76c1799b0 100644 --- a/src/webhooks/queries.ts +++ b/src/webhooks/queries.ts @@ -7,6 +7,7 @@ import { Webhooks, WebhooksVariables } from "./types/Webhooks"; export const webhooksFragment = gql` fragment WebhookFragment on Webhook { id + name events { eventType } @@ -23,7 +24,7 @@ export const webhooksFragment = gql` export const webhooksDetailsFragment = gql` ${webhooksFragment} fragment WebhooksDetailsFragment on Webhook { - ...WebhooksFragment + ...WebhookFragment } `; @@ -33,7 +34,7 @@ const webhooksList = gql` webhooks(before: $before, after: $after, first: $first, last: $last) { edges { node { - ...WebhooksFragment + ...WebhookFragment } } pageInfo { @@ -53,7 +54,7 @@ const webhooksDetails = gql` ${webhooksFragment} query Webhook($id: ID!) { webhook(id: $id) { - ...WebhooksFragment + ...WebhookFragment } } `; diff --git a/src/webhooks/types/Webhook.ts b/src/webhooks/types/Webhook.ts new file mode 100644 index 000000000..8286a50f2 --- /dev/null +++ b/src/webhooks/types/Webhook.ts @@ -0,0 +1,37 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: Webhook +// ==================================================== + +export interface Webhook_webhook_events { + __typename: "WebhookEvent"; + eventType: string | null; +} + +export interface Webhook_webhook_serviceAccount { + __typename: "ServiceAccount"; + id: string; + name: string | null; +} + +export interface Webhook_webhook { + __typename: "Webhook"; + id: string; + name: string | null; + events: (Webhook_webhook_events | null)[] | null; + isActive: boolean; + secretKey: string | null; + targetUrl: string; + serviceAccount: Webhook_webhook_serviceAccount; +} + +export interface Webhook { + webhook: Webhook_webhook | null; +} + +export interface WebhookVariables { + id: string; +} diff --git a/src/webhooks/types/WebhookCreate.ts b/src/webhooks/types/WebhookCreate.ts new file mode 100644 index 000000000..1e5fcac94 --- /dev/null +++ b/src/webhooks/types/WebhookCreate.ts @@ -0,0 +1,51 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { WebhookCreateInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: WebhookCreate +// ==================================================== + +export interface WebhookCreate_webhookCreate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface WebhookCreate_webhookCreate_webhook_events { + __typename: "WebhookEvent"; + eventType: string | null; +} + +export interface WebhookCreate_webhookCreate_webhook_serviceAccount { + __typename: "ServiceAccount"; + id: string; + name: string | null; +} + +export interface WebhookCreate_webhookCreate_webhook { + __typename: "Webhook"; + id: string; + name: string | null; + events: (WebhookCreate_webhookCreate_webhook_events | null)[] | null; + isActive: boolean; + secretKey: string | null; + targetUrl: string; + serviceAccount: WebhookCreate_webhookCreate_webhook_serviceAccount; +} + +export interface WebhookCreate_webhookCreate { + __typename: "WebhookCreate"; + errors: WebhookCreate_webhookCreate_errors[] | null; + webhook: WebhookCreate_webhookCreate_webhook | null; +} + +export interface WebhookCreate { + webhookCreate: WebhookCreate_webhookCreate | null; +} + +export interface WebhookCreateVariables { + input: WebhookCreateInput; +} diff --git a/src/webhooks/types/WebhookDelete.ts b/src/webhooks/types/WebhookDelete.ts new file mode 100644 index 000000000..7dcfe4301 --- /dev/null +++ b/src/webhooks/types/WebhookDelete.ts @@ -0,0 +1,26 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: WebhookDelete +// ==================================================== + +export interface WebhookDelete_webhookDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface WebhookDelete_webhookDelete { + __typename: "WebhookDelete"; + errors: WebhookDelete_webhookDelete_errors[] | null; +} + +export interface WebhookDelete { + webhookDelete: WebhookDelete_webhookDelete | null; +} + +export interface WebhookDeleteVariables { + id: string; +} diff --git a/src/webhooks/types/WebhookFragment.ts b/src/webhooks/types/WebhookFragment.ts new file mode 100644 index 000000000..04132dc9f --- /dev/null +++ b/src/webhooks/types/WebhookFragment.ts @@ -0,0 +1,29 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: WebhookFragment +// ==================================================== + +export interface WebhookFragment_events { + __typename: "WebhookEvent"; + eventType: string | null; +} + +export interface WebhookFragment_serviceAccount { + __typename: "ServiceAccount"; + id: string; + name: string | null; +} + +export interface WebhookFragment { + __typename: "Webhook"; + id: string; + name: string | null; + events: (WebhookFragment_events | null)[] | null; + isActive: boolean; + secretKey: string | null; + targetUrl: string; + serviceAccount: WebhookFragment_serviceAccount; +} diff --git a/src/webhooks/types/WebhookUpdate.ts b/src/webhooks/types/WebhookUpdate.ts new file mode 100644 index 000000000..d58000b70 --- /dev/null +++ b/src/webhooks/types/WebhookUpdate.ts @@ -0,0 +1,52 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { WebhookUpdateInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: WebhookUpdate +// ==================================================== + +export interface WebhookUpdate_webhookUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface WebhookUpdate_webhookUpdate_webhook_events { + __typename: "WebhookEvent"; + eventType: string | null; +} + +export interface WebhookUpdate_webhookUpdate_webhook_serviceAccount { + __typename: "ServiceAccount"; + id: string; + name: string | null; +} + +export interface WebhookUpdate_webhookUpdate_webhook { + __typename: "Webhook"; + id: string; + name: string | null; + events: (WebhookUpdate_webhookUpdate_webhook_events | null)[] | null; + isActive: boolean; + secretKey: string | null; + targetUrl: string; + serviceAccount: WebhookUpdate_webhookUpdate_webhook_serviceAccount; +} + +export interface WebhookUpdate_webhookUpdate { + __typename: "WebhookUpdate"; + errors: WebhookUpdate_webhookUpdate_errors[] | null; + webhook: WebhookUpdate_webhookUpdate_webhook | null; +} + +export interface WebhookUpdate { + webhookUpdate: WebhookUpdate_webhookUpdate | null; +} + +export interface WebhookUpdateVariables { + id: string; + input: WebhookUpdateInput; +} diff --git a/src/webhooks/types/Webhooks.ts b/src/webhooks/types/Webhooks.ts new file mode 100644 index 000000000..6b0801cda --- /dev/null +++ b/src/webhooks/types/Webhooks.ts @@ -0,0 +1,59 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: Webhooks +// ==================================================== + +export interface Webhooks_webhooks_edges_node_events { + __typename: "WebhookEvent"; + eventType: string | null; +} + +export interface Webhooks_webhooks_edges_node_serviceAccount { + __typename: "ServiceAccount"; + id: string; + name: string | null; +} + +export interface Webhooks_webhooks_edges_node { + __typename: "Webhook"; + id: string; + name: string | null; + events: (Webhooks_webhooks_edges_node_events | null)[] | null; + isActive: boolean; + secretKey: string | null; + targetUrl: string; + serviceAccount: Webhooks_webhooks_edges_node_serviceAccount; +} + +export interface Webhooks_webhooks_edges { + __typename: "WebhookCountableEdge"; + node: Webhooks_webhooks_edges_node; +} + +export interface Webhooks_webhooks_pageInfo { + __typename: "PageInfo"; + hasPreviousPage: boolean; + hasNextPage: boolean; + startCursor: string | null; + endCursor: string | null; +} + +export interface Webhooks_webhooks { + __typename: "WebhookCountableConnection"; + edges: Webhooks_webhooks_edges[]; + pageInfo: Webhooks_webhooks_pageInfo; +} + +export interface Webhooks { + webhooks: Webhooks_webhooks | null; +} + +export interface WebhooksVariables { + first?: number | null; + after?: string | null; + last?: number | null; + before?: string | null; +} diff --git a/src/webhooks/types/WebhooksDetailsFragment.ts b/src/webhooks/types/WebhooksDetailsFragment.ts new file mode 100644 index 000000000..b54fc69c0 --- /dev/null +++ b/src/webhooks/types/WebhooksDetailsFragment.ts @@ -0,0 +1,29 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: WebhooksDetailsFragment +// ==================================================== + +export interface WebhooksDetailsFragment_events { + __typename: "WebhookEvent"; + eventType: string | null; +} + +export interface WebhooksDetailsFragment_serviceAccount { + __typename: "ServiceAccount"; + id: string; + name: string | null; +} + +export interface WebhooksDetailsFragment { + __typename: "Webhook"; + id: string; + name: string | null; + events: (WebhooksDetailsFragment_events | null)[] | null; + isActive: boolean; + secretKey: string | null; + targetUrl: string; + serviceAccount: WebhooksDetailsFragment_serviceAccount; +} diff --git a/src/webhooks/views/WebhooksDetails.tsx b/src/webhooks/views/WebhooksDetails.tsx index a6e8d6cd9..858050ad3 100644 --- a/src/webhooks/views/WebhooksDetails.tsx +++ b/src/webhooks/views/WebhooksDetails.tsx @@ -6,35 +6,35 @@ 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"; +import { TypedWebhookUpdate } from "../mutations"; +import { TypedWebhooksDetailsQuery } from "../queries"; +import { webhooksListUrl, WebhooksListUrlQueryParams } from "../urls"; -export interface PluginsDetailsProps { +export interface WebhooksDetailsProps { id: string; - params: PluginsListUrlQueryParams; + params: WebhooksListUrlQueryParams; } -export const PluginsDetails: React.StatelessComponent = ({ - id -}) => { +export const WebhooksDetails: React.StatelessComponent< + WebhooksDetailsProps +> = ({ id }) => { const navigate = useNavigator(); const notify = useNotifier(); const intl = useIntl(); return ( - - {(pluginUpdate, pluginUpdateOpts) => ( - - {PluginDetails => { + + {(webhookUpdate, webhookUpdateOpts) => ( + + {WebhookDetails => { const formTransitionState = getMutationState( - pluginUpdateOpts.called, - pluginUpdateOpts.loading, - maybe(() => pluginUpdateOpts.data.pluginUpdate.errors) + webhookUpdateOpts.called, + webhookUpdateOpts.loading, + maybe(() => webhookUpdateOpts.data.webhookUpdate.errors) ); const formErrors = maybe( - () => pluginUpdateOpts.data.pluginUpdate.errors, + () => webhookUpdateOpts.data.webhookUpdate.errors, [] ); @@ -45,7 +45,7 @@ export const PluginsDetails: React.StatelessComponent = ({ }); }); } else { - if (pluginUpdateOpts.data) { + if (webhookUpdateOpts.data) { notify({ text: intl.formatMessage({ defaultMessage: "Succesfully updated plugin settings", @@ -58,14 +58,14 @@ export const PluginsDetails: React.StatelessComponent = ({ return ( <> PluginDetails.data.plugin.name)} + title={maybe(() => WebhookDetails.data.webhook.name)} /> PluginDetails.data.plugin)} - onBack={() => navigate(pluginsListUrl())} + webhook={maybe(() => WebhookDetails.data.webook)} + onBack={() => navigate(webhooksListUrl())} onSubmit={formData => { const configurationInput = formData.configuration && @@ -75,7 +75,7 @@ export const PluginsDetails: React.StatelessComponent = ({ value: item.value.toString() }; }); - pluginUpdate({ + webhookUpdate({ variables: { id, input: { @@ -91,10 +91,10 @@ export const PluginsDetails: React.StatelessComponent = ({ ); }} - + )} - + ); }; -PluginsDetails.displayName = "PluginsDetails"; -export default PluginsDetails; +WebhooksDetails.displayName = "WebhooksDetails"; +export default WebhooksDetails; diff --git a/src/webhooks/views/WebhooksList.tsx b/src/webhooks/views/WebhooksList.tsx index 67d7793d7..48ace5c7b 100644 --- a/src/webhooks/views/WebhooksList.tsx +++ b/src/webhooks/views/WebhooksList.tsx @@ -8,21 +8,21 @@ import { maybe } from "@saleor/misc"; import { ListViews } from "@saleor/types"; import React from "react"; -import WebhooksListPage from "../components/WebhooksListPage/PluginsListPage"; +import WebhooksListPage from "../components/WebhooksListPage/WebhooksListPage"; import { TypedWebhooksListQuery } from "../queries"; import { WebhooksListUrlQueryParams, webhooksUrl } from "../urls"; -interface PluginsListProps { +interface WebhooksListProps { params: WebhooksListUrlQueryParams; } -export const PluginsList: React.StatelessComponent = ({ +export const WebhooksList: React.StatelessComponent = ({ params }) => { const navigate = useNavigator(); const paginate = usePaginator(); const { updateListSettings, settings } = useListSettings( - ListViews.PLUGINS_LIST + ListViews.WEBHOOK_LIST ); const paginationState = createPaginationState(settings.rowNumber, params); @@ -30,7 +30,7 @@ export const PluginsList: React.StatelessComponent = ({ {({ data, loading }) => { const { loadNextPage, loadPreviousPage, pageInfo } = paginate( - maybe(() => data.plugins.pageInfo), + maybe(() => data.webhooks.pageInfo), paginationState, params ); @@ -39,7 +39,7 @@ export const PluginsList: React.StatelessComponent = ({ data.plugins.edges.map(edge => edge.node))} + webhooks={maybe(() => data.webhooks.edges.map(edge => edge.node))} pageInfo={pageInfo} onAdd={() => navigate(configurationMenuUrl)} onBack={() => navigate(configurationMenuUrl)} @@ -55,4 +55,4 @@ export const PluginsList: React.StatelessComponent = ({ ); }; -export default PluginsList; +export default WebhooksList; From 6b668937459b24cfd6d0a59355fdbae423f17cf9 Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Wed, 9 Oct 2019 09:31:00 +0200 Subject: [PATCH 03/38] Add webhooks section to configuration menu --- src/config.ts | 4 +++ src/configuration/index.tsx | 11 ++++++++ src/icons/Webhooks.tsx | 15 +++++++++++ src/index.tsx | 6 +++++ .../components/WebhookEvents/index.ts | 4 +-- src/webhooks/components/WebhookInfo/index.ts | 4 +-- .../components/WebhookStatus/index.ts | 4 +-- .../components/WebhooksList/WebhooksList.tsx | 27 +------------------ src/webhooks/index.tsx | 14 +++++----- src/webhooks/mutations.ts | 2 +- src/webhooks/urls.ts | 2 +- 11 files changed, 52 insertions(+), 41 deletions(-) create mode 100644 src/icons/Webhooks.tsx diff --git a/src/config.ts b/src/config.ts index 7737bfe0d..7bc422d3a 100644 --- a/src/config.ts +++ b/src/config.ts @@ -27,6 +27,7 @@ export interface AppListViewSettings { [ListViews.SHIPPING_METHODS_LIST]: ListSettings; [ListViews.STAFF_MEMBERS_LIST]: ListSettings; [ListViews.VOUCHER_LIST]: ListSettings; + [ListViews.WEBHOOK_LIST]: ListSettings; } export const defaultListSettings: AppListViewSettings = { [ListViews.CATEGORY_LIST]: { @@ -68,5 +69,8 @@ export const defaultListSettings: AppListViewSettings = { }, [ListViews.VOUCHER_LIST]: { rowNumber: PAGINATE_BY + }, + [ListViews.WEBHOOK_LIST]: { + rowNumber: PAGINATE_BY } }; diff --git a/src/configuration/index.tsx b/src/configuration/index.tsx index 8f70c5297..38af5d7d6 100644 --- a/src/configuration/index.tsx +++ b/src/configuration/index.tsx @@ -15,6 +15,7 @@ import ShippingMethods from "@saleor/icons/ShippingMethods"; import SiteSettings from "@saleor/icons/SiteSettings"; import StaffMembers from "@saleor/icons/StaffMembers"; import Taxes from "@saleor/icons/Taxes"; +import Webhooks from "@saleor/icons/Webhooks"; import { sectionNames } from "@saleor/intl"; import { maybe } from "@saleor/misc"; import { menuListUrl } from "@saleor/navigation/urls"; @@ -27,6 +28,7 @@ import { siteSettingsUrl } from "@saleor/siteSettings/urls"; import { staffListUrl } from "@saleor/staff/urls"; import { taxSection } from "@saleor/taxes/urls"; import { PermissionEnum } from "@saleor/types/globalTypes"; +import { webhooksListUrl } from "@saleor/webhooks/urls"; import ConfigurationPage, { MenuSection } from "./ConfigurationPage"; export function createConfigurationMenu(intl: IntlShape): MenuSection[] { @@ -161,6 +163,15 @@ export function createConfigurationMenu(intl: IntlShape): MenuSection[] { permission: PermissionEnum.MANAGE_SERVICE_ACCOUNTS, title: intl.formatMessage(sectionNames.serviceAccounts), url: serviceListUrl() + }, + { + description: intl.formatMessage({ + defaultMessage: "View and update your site settings" + }), + icon: , + permission: PermissionEnum.MANAGE_WEBHOOKS, + title: intl.formatMessage(sectionNames.webhooks), + url: webhooksListUrl() } ] } diff --git a/src/icons/Webhooks.tsx b/src/icons/Webhooks.tsx new file mode 100644 index 000000000..eaa17aae7 --- /dev/null +++ b/src/icons/Webhooks.tsx @@ -0,0 +1,15 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import React from "react"; + +export const Webhooks = createSvgIcon( + <> + + +); +Webhooks.displayName = "Webhooks"; +export default Webhooks; diff --git a/src/index.tsx b/src/index.tsx index 1cf61065b..5ac47a9c0 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -48,6 +48,7 @@ import SiteSettingsSection from "./siteSettings"; import StaffSection from "./staff"; import TaxesSection from "./taxes"; import TranslationsSection from "./translations"; +import WebhooksSection from "./webhooks"; import { PermissionEnum } from "./types/globalTypes"; interface ResponseError extends ErrorResponse { @@ -219,6 +220,11 @@ const Routes: React.FC = () => { path="/translations" component={TranslationsSection} /> + { return ( - // - // - // {maybe(() => plugin.name, )} - // - // - // {maybe( - // () => ( - // - // ), - // - // )} - // - // - //
- // - //
- //
- //
+
); }, () => ( diff --git a/src/webhooks/index.tsx b/src/webhooks/index.tsx index e6fe869ed..2088ff140 100644 --- a/src/webhooks/index.tsx +++ b/src/webhooks/index.tsx @@ -10,15 +10,15 @@ import { WebhooksListUrlQueryParams, webhooksPath } from "./urls"; -import PluginsDetailsComponent from "./views/WebhooksDetails"; -import PluginsListComponent from "./views/WebhooksList"; +import WebhooksDetails from "./views/WebhooksDetails"; +import WebhooksList from "./views/WebhooksList"; -const PluginList: React.StatelessComponent> = ({ +const WebhookList: React.StatelessComponent> = ({ location }) => { const qs = parseQs(location.search.substr(1)); const params: WebhooksListUrlQueryParams = qs; - return ; + return ; }; const PageDetails: React.StatelessComponent> = ({ @@ -28,7 +28,7 @@ const PageDetails: React.StatelessComponent> = ({ const params: WebhooksListUrlQueryParams = qs; return ( - @@ -41,8 +41,8 @@ const Component = () => { <> - - + + ); diff --git a/src/webhooks/mutations.ts b/src/webhooks/mutations.ts index 2b3b899f0..864e482b0 100644 --- a/src/webhooks/mutations.ts +++ b/src/webhooks/mutations.ts @@ -44,7 +44,7 @@ export const TypedWebhookUpdate = TypedMutation< WebhookUpdateVariables >(webhookUpdate); -const WebhookDelete = gql` +const webhookDelete = gql` mutation WebhookDelete($id: ID!) { webhookDelete(id: $id) { errors { diff --git a/src/webhooks/urls.ts b/src/webhooks/urls.ts index f12eae33a..94d423ee3 100644 --- a/src/webhooks/urls.ts +++ b/src/webhooks/urls.ts @@ -8,7 +8,7 @@ export const webhooksSection = "/webhooks/"; export const webhooksListPath = webhooksSection; export type WebhooksListUrlQueryParams = Pagination & SingleAction; export const webhooksListUrl = (params?: WebhooksListUrlQueryParams) => - webhooksPath + "?" + stringifyQs(params); +webhooksListPath + "?" + stringifyQs(params); export const webhooksPath = (id: string) => urlJoin(webhooksSection, id); export type WebhooksUrlQueryParams = SingleAction; From 2fd01ec3c5e2629a7822bd7b0370d46e9960ca92 Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Wed, 9 Oct 2019 22:50:03 +0200 Subject: [PATCH 04/38] Update components --- src/index.tsx | 2 +- .../WebhookCreatePage/WebhookCreatePage.tsx | 116 ++++++++++++++++++ .../components/WebhookCreatePage/index.ts | 2 + .../WebhookEvents/WebhookEvents.tsx | 62 +++++++--- .../components/WebhookInfo/WebhookInfo.tsx | 105 ++++++++++++++-- .../WebhookStatus/WebhookStatus.tsx | 44 ++++--- .../WebhooksDetailsPage.tsx | 46 ++++--- .../components/WebhooksList/WebhooksList.tsx | 28 ++++- .../WebhooksListPage/WebhooksListPage.tsx | 13 +- src/webhooks/index.tsx | 12 +- src/webhooks/queries.ts | 37 ++++++ src/webhooks/types/ServiceFragment.ts | 14 +++ src/webhooks/types/ServiceList.ts | 47 +++++++ src/webhooks/urls.ts | 5 +- src/webhooks/views/WebhooksCreate.tsx | 103 ++++++++++++++++ src/webhooks/views/WebhooksDetails.tsx | 69 ++++++----- src/webhooks/views/WebhooksList.tsx | 8 +- 17 files changed, 591 insertions(+), 122 deletions(-) create mode 100644 src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx create mode 100644 src/webhooks/components/WebhookCreatePage/index.ts create mode 100644 src/webhooks/types/ServiceFragment.ts create mode 100644 src/webhooks/types/ServiceList.ts create mode 100644 src/webhooks/views/WebhooksCreate.tsx diff --git a/src/index.tsx b/src/index.tsx index 5ac47a9c0..7c193a445 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -48,8 +48,8 @@ import SiteSettingsSection from "./siteSettings"; import StaffSection from "./staff"; import TaxesSection from "./taxes"; import TranslationsSection from "./translations"; -import WebhooksSection from "./webhooks"; import { PermissionEnum } from "./types/globalTypes"; +import WebhooksSection from "./webhooks"; interface ResponseError extends ErrorResponse { networkError?: Error & { diff --git a/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx b/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx new file mode 100644 index 000000000..496792fd2 --- /dev/null +++ b/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx @@ -0,0 +1,116 @@ +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 FormSpacer from "@saleor/components/FormSpacer"; +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 React from "react"; +import { useIntl } from "react-intl"; +import { ServiceList_serviceAccounts_edges_node } from "../../types/ServiceList"; +import { Webhook_webhook, Webhook_webhook_events } from "../../types/Webhook"; +import WebhookEvents from "../WebhookEvents"; +import WebhookInfo from "../WebhookInfo"; +import WebhookStatus from "../WebhookStatus"; + +export interface FormData { + id: string; + events: Webhook_webhook_events[]; + isActive: boolean; + name: string; + secretKey: string | null; + targetUrl: string; + serviceAccount: string; +} + +export interface WebhookCreatePageProps { + disabled: boolean; + errors: UserError[]; + webhook: Webhook_webhook; + services: ServiceList_serviceAccounts_edges_node[]; + saveButtonBarState: ConfirmButtonTransitionState; + onBack: () => void; + onSubmit: (data: FormData) => void; +} + +const WebhookCreatePage: React.StatelessComponent = ({ + disabled, + errors, + webhook, + saveButtonBarState, + services, + onBack, + onSubmit +}) => { + const intl = useIntl(); + const initialForm: FormData = { + events: maybe(() => webhook.events, []), + id: maybe(() => webhook.id, null), + isActive: maybe(() => webhook.isActive, false), + name: maybe(() => webhook.name, null), + secretKey: maybe(() => webhook.secretKey, ""), + serviceAccount: maybe(() => webhook.serviceAccount, ""), + targetUrl: maybe(() => webhook.targetUrl, "") + }; + + return ( + + {({ data, errors, hasChanged, submit, change }) => { + return ( + + + {intl.formatMessage(sectionNames.plugins)} + + webhook.name, "...") + } + )} + /> + +
+ services, [])} + errors={errors} + onChange={change} + /> +
+
+ + + +
+
+ +
+ ); + }} + + ); +}; +WebhookCreatePage.displayName = "WebhookCreatePage"; +export default WebhookCreatePage; diff --git a/src/webhooks/components/WebhookCreatePage/index.ts b/src/webhooks/components/WebhookCreatePage/index.ts new file mode 100644 index 000000000..a1632a319 --- /dev/null +++ b/src/webhooks/components/WebhookCreatePage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./WebhookCreatePage"; +export * from "./WebhookCreatePage"; diff --git a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx index cf2b168ef..b9e364b6b 100644 --- a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx +++ b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx @@ -1,28 +1,18 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; -import TextField from "@material-ui/core/TextField"; +import Typography from "@material-ui/core/Typography"; 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"; +import { WebhookEventTypeEnum } from "../../../types/globalTypes"; +import { FormData } from "../WebhooksDetailsPage"; interface WebhookEventsProps { data: FormData; - errors: FormErrors<"name" | "configuration">; disabled: boolean; onChange: (event: React.ChangeEvent) => void; - fields: Array<{ - name: string; - type: ConfigurationTypeFieldEnum | null; - value: string; - helpText: string | null; - label: string | null; - }>; } const useStyles = makeStyles(() => ({ @@ -35,12 +25,29 @@ const useStyles = makeStyles(() => ({ const WebhookEvents: React.StatelessComponent = ({ data, disabled, - errors, - onChange, - fields + onChange }) => { - const classes = useStyles({}); const intl = useIntl(); + const [events, setEvents] = React.useState(); + + const eventsEnum = Object.values(WebhookEventTypeEnum); + + const addOrRemove = (array, value) => { + const index = array.indexOf(value); + + if (index === -1) { + array.push(value); + } else { + array.splice(index, 1); + } + }; + + const eventsOnChange = event => { + const newData = [events]; + addOrRemove(newData, event.name); + setEvents(newData); + }; + return ( = ({ description: "section header" })} /> - + + + {intl.formatMessage({ + defaultMessage: + "Expand or restrict webhooks permissions to register certain events in Saleor system.", + description: "webhook events" + })} + + {eventsEnum.map((event, index) => ( +
+ +
+ ))} +
); }; diff --git a/src/webhooks/components/WebhookInfo/WebhookInfo.tsx b/src/webhooks/components/WebhookInfo/WebhookInfo.tsx index 64ac09fda..fcdb88ac5 100644 --- a/src/webhooks/components/WebhookInfo/WebhookInfo.tsx +++ b/src/webhooks/components/WebhookInfo/WebhookInfo.tsx @@ -1,21 +1,25 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; +import TextField from "@material-ui/core/TextField"; 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 { 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 SingleSelectField from "@saleor/components/SingleSelectField"; +import { FormErrors } from "@saleor/types"; import { FormData } from "../WebhooksDetailsPage"; +import { ServiceList_serviceAccounts_edges_node } from "../../types/ServiceList"; + interface WebhookInfoProps { data: FormData; - description: string; - name: string; + disabled: boolean; + services: ServiceList_serviceAccounts_edges_node[]; + errors: FormErrors<"name" | "targetUrl" | "secretKey">; onChange: (event: React.ChangeEvent) => void; } @@ -24,28 +28,107 @@ const useStyles = makeStyles(() => ({ paddingTop: 20 }, title: { - fontSize: 14, - paddingTop: 10 + fontSize: 16, + lineHeight: 1.9, + paddingBottom: 10 } })); const WebhookInfo: React.StatelessComponent = ({ data, - description, - name, + disabled, + services, + errors, onChange }) => { const classes = useStyles({}); const intl = useIntl(); + return ( - + + + {intl.formatMessage({ + defaultMessage: "General Information", + description: "webhook general information" + })} + + + +
+ + + {intl.formatMessage({ + defaultMessage: "Webhook specific information", + description: "webhook specific information" + })} + + ({ + label: service.name, + value: service.id + }))} + name="serviceAccount" + value={data.serviceAccount} + label={intl.formatMessage({ + defaultMessage: "Assign to Service Account" + })} + onChange={onChange} + /> + + + + +
); }; diff --git a/src/webhooks/components/WebhookStatus/WebhookStatus.tsx b/src/webhooks/components/WebhookStatus/WebhookStatus.tsx index f674f9539..d93f511e0 100644 --- a/src/webhooks/components/WebhookStatus/WebhookStatus.tsx +++ b/src/webhooks/components/WebhookStatus/WebhookStatus.tsx @@ -1,11 +1,9 @@ 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 Typography from "@material-ui/core/Typography"; 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"; @@ -13,33 +11,15 @@ import { FormData } from "../WebhooksDetailsPage"; interface WebhookStatusProps { data: FormData; - errors: FormErrors<"name" | "configuration">; disabled: boolean; onChange: (event: React.ChangeEvent) => 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 = ({ data, disabled, - errors, - onChange, - fields + onChange }) => { - const classes = useStyles({}); const intl = useIntl(); return ( @@ -49,7 +29,25 @@ const WebhookStatus: React.StatelessComponent = ({ description: "section header" })} /> - + + + {intl.formatMessage({ + defaultMessage: + "If you want to disable this webhook please uncheck the box below.", + description: "webhook active" + })} + + + ); }; diff --git a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx index 94318ebfa..e94a1ccfd 100644 --- a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx +++ b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx @@ -1,40 +1,38 @@ -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 FormSpacer from "@saleor/components/FormSpacer"; 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 { WebhookEventTypeEnum } from "@saleor/types/globalTypes"; import React from "react"; import { useIntl } from "react-intl"; - -import { - Webhook_webhook, - Webhook_webhook_events, - Webhook_webhook_serviceAccount -} from "../../types/Webhook"; +import { ServiceList_serviceAccounts_edges_node } from "../../types/ServiceList"; +import { Webhook_webhook, Webhook_webhook_events } from "../../types/Webhook"; import WebhookEvents from "../WebhookEvents"; import WebhookInfo from "../WebhookInfo"; import WebhookStatus from "../WebhookStatus"; export interface FormData { id: string; - events: Webhook_webhook_events; + events: Webhook_webhook_events[]; isActive: boolean; + name: string; secretKey: string | null; targetUrl: string; - serviceAccount: Webhook_webhook_serviceAccount; + serviceAccount: string; } export interface WebhooksDetailsPageProps { disabled: boolean; errors: UserError[]; webhook: Webhook_webhook; + services: ServiceList_serviceAccounts_edges_node[]; saveButtonBarState: ConfirmButtonTransitionState; onBack: () => void; onSubmit: (data: FormData) => void; @@ -42,17 +40,25 @@ export interface WebhooksDetailsPageProps { const WebhooksDetailsPage: React.StatelessComponent< WebhooksDetailsPageProps -> = ({ disabled, errors, webhook, saveButtonBarState, onBack, onSubmit }) => { +> = ({ + disabled, + errors, + webhook, + saveButtonBarState, + services, + onBack, + onSubmit +}) => { const intl = useIntl(); const initialForm: FormData = { events: maybe(() => webhook.events, []), id: maybe(() => webhook.id, null), isActive: maybe(() => webhook.isActive, false), + name: maybe(() => webhook.name, ""), secretKey: maybe(() => webhook.secretKey, ""), - serviceAccount: maybe(() => webhook.serviceAccount, []), + serviceAccount: maybe(() => webhook.serviceAccount.id, ""), targetUrl: maybe(() => webhook.targetUrl, "") }; - return (
{({ data, errors, hasChanged, submit, change }) => { @@ -68,15 +74,16 @@ const WebhooksDetailsPage: React.StatelessComponent< description: "header" }, { - pluginName: maybe(() => plugin.name, "...") + pluginName: maybe(() => webhook.name, "...") } )} /> - +
plugin.description, "")} + disabled={disabled} + services={maybe(() => services, [])} errors={errors} onChange={change} /> @@ -84,14 +91,13 @@ const WebhooksDetailsPage: React.StatelessComponent<
plugin.name, "")} + disabled={disabled} onChange={change} /> + plugin.name, "")} + disabled={disabled} onChange={change} />
diff --git a/src/webhooks/components/WebhooksList/WebhooksList.tsx b/src/webhooks/components/WebhooksList/WebhooksList.tsx index 2efe6c5f5..7c5cbe4ff 100644 --- a/src/webhooks/components/WebhooksList/WebhooksList.tsx +++ b/src/webhooks/components/WebhooksList/WebhooksList.tsx @@ -16,9 +16,7 @@ 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 { Webhooks_webhooks_edges_node } from "../../types/Webhooks"; @@ -107,14 +105,36 @@ const WebhooksList = withStyles(styles, { name: "PluginList" })( webhooks, webhook => { return ( -
+ + + {maybe(() => webhook.name, )} + + + {maybe( + () => webhook.serviceAccount.name, + + )} + + +
+ +
+
+
); }, () => ( {intl.formatMessage({ - defaultMessage: "No plugins found" + defaultMessage: "No webhooks found" })} diff --git a/src/webhooks/components/WebhooksListPage/WebhooksListPage.tsx b/src/webhooks/components/WebhooksListPage/WebhooksListPage.tsx index 018577960..2803f94db 100644 --- a/src/webhooks/components/WebhooksListPage/WebhooksListPage.tsx +++ b/src/webhooks/components/WebhooksListPage/WebhooksListPage.tsx @@ -1,5 +1,6 @@ +import Button from "@material-ui/core/Button"; import React from "react"; -import { useIntl } from "react-intl"; +import { FormattedMessage, useIntl } from "react-intl"; import AppHeader from "@saleor/components/AppHeader"; import Container from "@saleor/components/Container"; @@ -17,6 +18,7 @@ export interface WebhooksListPageProps extends PageListProps { const WebhooksListPage: React.StatelessComponent = ({ disabled, settings, + onAdd, onBack, onNextPage, onPreviousPage, @@ -31,7 +33,14 @@ const WebhooksListPage: React.StatelessComponent = ({ {intl.formatMessage(sectionNames.configuration)} - + + + > = ({ return ; }; -const PageDetails: React.StatelessComponent> = ({ +const WebhookDetails: React.StatelessComponent> = ({ match }) => { const qs = parseQs(location.search.substr(1)); const params: WebhooksListUrlQueryParams = qs; return ( - + ); }; @@ -42,7 +41,8 @@ const Component = () => { - + + ); diff --git a/src/webhooks/queries.ts b/src/webhooks/queries.ts index 76c1799b0..efdecc18f 100644 --- a/src/webhooks/queries.ts +++ b/src/webhooks/queries.ts @@ -1,9 +1,18 @@ import gql from "graphql-tag"; import { TypedQuery } from "../queries"; +import { ServiceList, ServiceListVariables } from "./types/ServiceList"; import { Webhook, WebhookVariables } from "./types/Webhook"; import { Webhooks, WebhooksVariables } from "./types/Webhooks"; +export const serviceFragment = gql` + fragment ServiceFragment on ServiceAccount { + id + name + isActive + } +`; + export const webhooksFragment = gql` fragment WebhookFragment on Webhook { id @@ -50,6 +59,34 @@ export const TypedWebhooksListQuery = TypedQuery( webhooksList ); +const serviceList = gql` + ${serviceFragment} + query ServiceList($first: Int, $after: String, $last: Int, $before: String) { + serviceAccounts( + first: $first + after: $after + before: $before + last: $last + ) { + edges { + node { + ...ServiceFragment + } + } + pageInfo { + hasPreviousPage + hasNextPage + startCursor + endCursor + } + } + } +`; +export const TypedServiceListQuery = TypedQuery< + ServiceList, + ServiceListVariables +>(serviceList); + const webhooksDetails = gql` ${webhooksFragment} query Webhook($id: ID!) { diff --git a/src/webhooks/types/ServiceFragment.ts b/src/webhooks/types/ServiceFragment.ts new file mode 100644 index 000000000..5c0e96fec --- /dev/null +++ b/src/webhooks/types/ServiceFragment.ts @@ -0,0 +1,14 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: ServiceFragment +// ==================================================== + +export interface ServiceFragment { + __typename: "ServiceAccount"; + id: string; + name: string | null; + isActive: boolean | null; +} diff --git a/src/webhooks/types/ServiceList.ts b/src/webhooks/types/ServiceList.ts new file mode 100644 index 000000000..0d1b614fe --- /dev/null +++ b/src/webhooks/types/ServiceList.ts @@ -0,0 +1,47 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { ServiceAccountFilterInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: ServiceList +// ==================================================== + +export interface ServiceList_serviceAccounts_edges_node { + __typename: "ServiceAccount"; + id: string; + name: string | null; + isActive: boolean | null; +} + +export interface ServiceList_serviceAccounts_edges { + __typename: "ServiceAccountCountableEdge"; + node: ServiceList_serviceAccounts_edges_node; +} + +export interface ServiceList_serviceAccounts_pageInfo { + __typename: "PageInfo"; + hasPreviousPage: boolean; + hasNextPage: boolean; + startCursor: string | null; + endCursor: string | null; +} + +export interface ServiceList_serviceAccounts { + __typename: "ServiceAccountCountableConnection"; + edges: ServiceList_serviceAccounts_edges[]; + pageInfo: ServiceList_serviceAccounts_pageInfo; +} + +export interface ServiceList { + serviceAccounts: ServiceList_serviceAccounts | null; +} + +export interface ServiceListVariables { + first?: number | null; + after?: string | null; + last?: number | null; + before?: string | null; + filter?: ServiceAccountFilterInput | null; +} diff --git a/src/webhooks/urls.ts b/src/webhooks/urls.ts index 94d423ee3..c8c410e1d 100644 --- a/src/webhooks/urls.ts +++ b/src/webhooks/urls.ts @@ -8,9 +8,12 @@ export const webhooksSection = "/webhooks/"; export const webhooksListPath = webhooksSection; export type WebhooksListUrlQueryParams = Pagination & SingleAction; export const webhooksListUrl = (params?: WebhooksListUrlQueryParams) => -webhooksListPath + "?" + stringifyQs(params); + webhooksListPath + "?" + 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); + +export const webhooksAddPath = urlJoin(webhooksSection, "add"); +export const webhooksAddUrl = webhooksAddPath; diff --git a/src/webhooks/views/WebhooksCreate.tsx b/src/webhooks/views/WebhooksCreate.tsx new file mode 100644 index 000000000..e28887453 --- /dev/null +++ b/src/webhooks/views/WebhooksCreate.tsx @@ -0,0 +1,103 @@ +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import useShop from "@saleor/hooks/useShop"; +import { commonMessages } from "@saleor/intl"; +import { WebhookCreate as WebhookCreateData } from "@saleor/webhooks/types/WebhookCreate"; +import React from "react"; +import { useIntl } from "react-intl"; + +import { getMutationState, maybe } from "../../misc"; +import WebhookCreatePage, { FormData } from "../components/WebhookCreatePage"; +import { TypedWebhookCreate } from "../mutations"; +import { TypedServiceListQuery } from "../queries"; +import { + webhooksListUrl, + WebhooksListUrlQueryParams, + webhooksUrl +} from "../urls"; + +export interface WebhooksCreateProps { + id: string; + params: WebhooksListUrlQueryParams; +} + +export const WebhooksCreate: React.StatelessComponent< + WebhooksCreateProps +> = () => { + const navigate = useNavigator(); + const notify = useNotifier(); + const intl = useIntl(); + const shop = useShop(); + + const onSubmit = (data: WebhookCreateData) => { + if (data.webhookCreate.errors.length === 0) { + notify({ + text: intl.formatMessage(commonMessages.savedChanges) + }); + navigate(webhooksUrl(data.webhookCreate.webhook.id)); + } + }; + + const handleBack = () => navigate(webhooksListUrl()); + + return ( + + {(WebhookCreate, webhookCreateOpts) => { + const handleSubmit = (data: FormData) => + WebhookCreate({ + variables: { + input: { + events: data.events, + isActive: data.isActive, + name: data.name, + secretKey: data.secretKey, + serviceAccount: data.serviceAccount, + targetUrl: data.targetUrl + } + } + }); + + const formTransitionState = getMutationState( + webhookCreateOpts.called, + webhookCreateOpts.loading, + maybe(() => webhookCreateOpts.data.webhookCreate.errors) + ); + + return ( + + {({ data, loading }) => { + return ( + <> + + webhookCreateOpts.data.webhookCreate.errors, + [] + )} + services={maybe(() => + data.serviceAccounts.edges.map(edge => edge.node) + )} + loading={loading} + onBack={handleBack} + onSubmit={handleSubmit} + permissions={maybe(() => shop.permissions)} + saveButtonBarState={formTransitionState} + /> + + ); + }} + + ); + }} + + ); +}; +WebhooksCreate.displayName = "WebhooksCreate"; +export default WebhooksCreate; diff --git a/src/webhooks/views/WebhooksDetails.tsx b/src/webhooks/views/WebhooksDetails.tsx index 858050ad3..2413b735f 100644 --- a/src/webhooks/views/WebhooksDetails.tsx +++ b/src/webhooks/views/WebhooksDetails.tsx @@ -7,7 +7,7 @@ import { useIntl } from "react-intl"; import { getMutationState, maybe } from "../../misc"; import WebhooksDetailsPage from "../components/WebhooksDetailsPage"; import { TypedWebhookUpdate } from "../mutations"; -import { TypedWebhooksDetailsQuery } from "../queries"; +import { TypedServiceListQuery, TypedWebhooksDetailsQuery } from "../queries"; import { webhooksListUrl, WebhooksListUrlQueryParams } from "../urls"; export interface WebhooksDetailsProps { @@ -56,39 +56,40 @@ export const WebhooksDetails: React.StatelessComponent< } return ( - <> - WebhookDetails.data.webhook.name)} - /> - WebhookDetails.data.webook)} - onBack={() => navigate(webhooksListUrl())} - onSubmit={formData => { - const configurationInput = - formData.configuration && - formData.configuration.map(item => { - return { - name: item.name, - value: item.value.toString() - }; - }); - webhookUpdate({ - variables: { - id, - input: { - active: formData.active, - configuration: configurationInput - ? configurationInput - : null - } - } - }); - }} - /> - + + {({ data }) => ( + <> + WebhookDetails.data.webhook.name)} + /> + WebhookDetails.data.webhook)} + services={maybe(() => + data.serviceAccounts.edges.map(edge => edge.node) + )} + onBack={() => navigate(webhooksListUrl())} + onSubmit={data => { + webhookUpdate({ + variables: { + id, + input: { + events: data.events, + isActive: data.isActive, + name: data.name, + secretKey: data.secretKey, + serviceAccount: data.serviceAccount, + targetUrl: data.targetUrl + } + } + }); + }} + /> + + )} + ); }} diff --git a/src/webhooks/views/WebhooksList.tsx b/src/webhooks/views/WebhooksList.tsx index 48ace5c7b..1f0e378c8 100644 --- a/src/webhooks/views/WebhooksList.tsx +++ b/src/webhooks/views/WebhooksList.tsx @@ -10,7 +10,11 @@ import React from "react"; import WebhooksListPage from "../components/WebhooksListPage/WebhooksListPage"; import { TypedWebhooksListQuery } from "../queries"; -import { WebhooksListUrlQueryParams, webhooksUrl } from "../urls"; +import { + webhooksAddUrl, + WebhooksListUrlQueryParams, + webhooksUrl +} from "../urls"; interface WebhooksListProps { params: WebhooksListUrlQueryParams; @@ -41,7 +45,7 @@ export const WebhooksList: React.StatelessComponent = ({ settings={settings} webhooks={maybe(() => data.webhooks.edges.map(edge => edge.node))} pageInfo={pageInfo} - onAdd={() => navigate(configurationMenuUrl)} + onAdd={() => navigate(webhooksAddUrl)} onBack={() => navigate(configurationMenuUrl)} onNextPage={loadNextPage} onPreviousPage={loadPreviousPage} From 834addf3c0800227470cee814ba90b7456f00621 Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Thu, 10 Oct 2019 07:38:21 +0200 Subject: [PATCH 05/38] Add webhook delete --- .../WebhookCreatePage/WebhookCreatePage.tsx | 32 ++- .../WebhookDeleteDialog.stories.tsx | 19 ++ .../WebhookDeleteDialog.tsx | 50 +++++ .../components/WebhookDeleteDialog/index.ts | 2 + .../WebhookEvents/WebhookEvents.tsx | 11 +- .../WebhookStatus/WebhookStatus.tsx | 1 - .../WebhooksDetailsPage.tsx | 9 +- .../components/WebhooksList/WebhooksList.tsx | 12 ++ .../WebhooksListPage/WebhooksListPage.tsx | 3 + src/webhooks/mutations.ts | 2 +- src/webhooks/urls.ts | 10 +- src/webhooks/views/WebhooksCreate.tsx | 9 +- src/webhooks/views/WebhooksDetails.tsx | 200 ++++++++++++------ src/webhooks/views/WebhooksList.tsx | 129 ++++++++--- 14 files changed, 358 insertions(+), 131 deletions(-) create mode 100644 src/webhooks/components/WebhookDeleteDialog/WebhookDeleteDialog.stories.tsx create mode 100644 src/webhooks/components/WebhookDeleteDialog/WebhookDeleteDialog.tsx create mode 100644 src/webhooks/components/WebhookDeleteDialog/index.ts diff --git a/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx b/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx index 496792fd2..6b92e9841 100644 --- a/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx +++ b/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx @@ -12,14 +12,13 @@ import { UserError } from "@saleor/types"; import React from "react"; import { useIntl } from "react-intl"; import { ServiceList_serviceAccounts_edges_node } from "../../types/ServiceList"; -import { Webhook_webhook, Webhook_webhook_events } from "../../types/Webhook"; import WebhookEvents from "../WebhookEvents"; import WebhookInfo from "../WebhookInfo"; import WebhookStatus from "../WebhookStatus"; export interface FormData { id: string; - events: Webhook_webhook_events[]; + events: string[]; isActive: boolean; name: string; secretKey: string | null; @@ -30,7 +29,6 @@ export interface FormData { export interface WebhookCreatePageProps { disabled: boolean; errors: UserError[]; - webhook: Webhook_webhook; services: ServiceList_serviceAccounts_edges_node[]; saveButtonBarState: ConfirmButtonTransitionState; onBack: () => void; @@ -40,7 +38,6 @@ export interface WebhookCreatePageProps { const WebhookCreatePage: React.StatelessComponent = ({ disabled, errors, - webhook, saveButtonBarState, services, onBack, @@ -48,13 +45,13 @@ const WebhookCreatePage: React.StatelessComponent = ({ }) => { const intl = useIntl(); const initialForm: FormData = { - events: maybe(() => webhook.events, []), - id: maybe(() => webhook.id, null), - isActive: maybe(() => webhook.isActive, false), - name: maybe(() => webhook.name, null), - secretKey: maybe(() => webhook.secretKey, ""), - serviceAccount: maybe(() => webhook.serviceAccount, ""), - targetUrl: maybe(() => webhook.targetUrl, "") + events: [], + id: null, + isActive: false, + name: null, + secretKey: "", + serviceAccount: "", + targetUrl: "" }; return ( @@ -66,15 +63,10 @@ const WebhookCreatePage: React.StatelessComponent = ({ {intl.formatMessage(sectionNames.plugins)} webhook.name, "...") - } - )} + title={intl.formatMessage({ + defaultMessage: "Create Webhook", + description: "header" + })} />
diff --git a/src/webhooks/components/WebhookDeleteDialog/WebhookDeleteDialog.stories.tsx b/src/webhooks/components/WebhookDeleteDialog/WebhookDeleteDialog.stories.tsx new file mode 100644 index 000000000..a21cab3d9 --- /dev/null +++ b/src/webhooks/components/WebhookDeleteDialog/WebhookDeleteDialog.stories.tsx @@ -0,0 +1,19 @@ +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import Decorator from "@saleor/storybook/Decorator"; +import WebhookDeleteDialog, { + WebhookDeleteDialogProps +} from "./WebhookDeleteDialog"; + +const props: WebhookDeleteDialogProps = { + confirmButtonState: "default", + name: "Magento Importer", + onClose: () => undefined, + onConfirm: () => undefined, + open: true +}; + +storiesOf("Views / Services / Delete service", module) + .addDecorator(Decorator) + .add("default", () => ); diff --git a/src/webhooks/components/WebhookDeleteDialog/WebhookDeleteDialog.tsx b/src/webhooks/components/WebhookDeleteDialog/WebhookDeleteDialog.tsx new file mode 100644 index 000000000..05700fefc --- /dev/null +++ b/src/webhooks/components/WebhookDeleteDialog/WebhookDeleteDialog.tsx @@ -0,0 +1,50 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; + +export interface WebhookDeleteDialogProps { + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + name: string; + onClose: () => void; + onConfirm: () => void; +} + +const WebhookDeleteDialog: React.FC = ({ + confirmButtonState, + open, + name, + onClose, + onConfirm +}) => { + const intl = useIntl(); + + return ( + + + {name} + }} + /> + + + ); +}; +WebhookDeleteDialog.displayName = "WebhookDeleteDialog"; +export default WebhookDeleteDialog; diff --git a/src/webhooks/components/WebhookDeleteDialog/index.ts b/src/webhooks/components/WebhookDeleteDialog/index.ts new file mode 100644 index 000000000..4f47146e4 --- /dev/null +++ b/src/webhooks/components/WebhookDeleteDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./WebhookDeleteDialog"; +export * from "./WebhookDeleteDialog"; diff --git a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx index b9e364b6b..a0f8792b1 100644 --- a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx +++ b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx @@ -28,7 +28,7 @@ const WebhookEvents: React.StatelessComponent = ({ onChange }) => { const intl = useIntl(); - const [events, setEvents] = React.useState(); + const [events, setEvents] = React.useState(data.events); const eventsEnum = Object.values(WebhookEventTypeEnum); @@ -42,10 +42,13 @@ const WebhookEvents: React.StatelessComponent = ({ } }; + console.log(data.events); + const eventsOnChange = event => { - const newData = [events]; - addOrRemove(newData, event.name); + const newData = events; + addOrRemove(newData, event.target.name); setEvents(newData); + console.log(events.indexOf(event.target.name)); }; return ( @@ -69,7 +72,7 @@ const WebhookEvents: React.StatelessComponent = ({ diff --git a/src/webhooks/components/WebhookStatus/WebhookStatus.tsx b/src/webhooks/components/WebhookStatus/WebhookStatus.tsx index d93f511e0..68580d9d3 100644 --- a/src/webhooks/components/WebhookStatus/WebhookStatus.tsx +++ b/src/webhooks/components/WebhookStatus/WebhookStatus.tsx @@ -3,7 +3,6 @@ import CardContent from "@material-ui/core/CardContent"; import Typography from "@material-ui/core/Typography"; import CardTitle from "@saleor/components/CardTitle"; import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; -import { FormErrors } from "@saleor/types"; import React from "react"; import { useIntl } from "react-intl"; diff --git a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx index e94a1ccfd..7f025b450 100644 --- a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx +++ b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx @@ -13,14 +13,14 @@ import { WebhookEventTypeEnum } from "@saleor/types/globalTypes"; import React from "react"; import { useIntl } from "react-intl"; import { ServiceList_serviceAccounts_edges_node } from "../../types/ServiceList"; -import { Webhook_webhook, Webhook_webhook_events } from "../../types/Webhook"; +import { Webhook_webhook } from "../../types/Webhook"; import WebhookEvents from "../WebhookEvents"; import WebhookInfo from "../WebhookInfo"; import WebhookStatus from "../WebhookStatus"; export interface FormData { id: string; - events: Webhook_webhook_events[]; + events: string[]; isActive: boolean; name: string; secretKey: string | null; @@ -35,6 +35,7 @@ export interface WebhooksDetailsPageProps { services: ServiceList_serviceAccounts_edges_node[]; saveButtonBarState: ConfirmButtonTransitionState; onBack: () => void; + onDelete: () => void; onSubmit: (data: FormData) => void; } @@ -47,11 +48,12 @@ const WebhooksDetailsPage: React.StatelessComponent< saveButtonBarState, services, onBack, + onDelete, onSubmit }) => { const intl = useIntl(); const initialForm: FormData = { - events: maybe(() => webhook.events, []), + events: maybe(() => webhook.events, []).map(event => event.eventType), id: maybe(() => webhook.id, null), isActive: maybe(() => webhook.isActive, false), name: maybe(() => webhook.name, ""), @@ -107,6 +109,7 @@ const WebhooksDetailsPage: React.StatelessComponent< state={saveButtonBarState} onCancel={onBack} onSave={submit} + onDelete={onDelete} /> ); diff --git a/src/webhooks/components/WebhooksList/WebhooksList.tsx b/src/webhooks/components/WebhooksList/WebhooksList.tsx index 7c5cbe4ff..3d9844bc5 100644 --- a/src/webhooks/components/WebhooksList/WebhooksList.tsx +++ b/src/webhooks/components/WebhooksList/WebhooksList.tsx @@ -1,4 +1,5 @@ import Card from "@material-ui/core/Card"; +import IconButton from "@material-ui/core/IconButton"; import { createStyles, Theme, @@ -12,6 +13,7 @@ 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 DeleteIcon from "@material-ui/icons/Delete"; import React from "react"; import { useIntl } from "react-intl"; @@ -23,6 +25,7 @@ import { Webhooks_webhooks_edges_node } from "../../types/Webhooks"; export interface WebhooksListProps extends ListProps { webhooks: Webhooks_webhooks_edges_node[]; + onRemove: (id: string) => void; } const styles = (theme: Theme) => @@ -56,6 +59,7 @@ const WebhooksList = withStyles(styles, { name: "PluginList" })( onNextPage, pageInfo, onRowClick, + onRemove, onUpdateListSettings, onPreviousPage }: WebhooksListProps & WithStyles) => { @@ -126,6 +130,14 @@ const WebhooksList = withStyles(styles, { name: "PluginList" })( >
+ onRemove(webhook.id) : undefined + } + > + + ); diff --git a/src/webhooks/components/WebhooksListPage/WebhooksListPage.tsx b/src/webhooks/components/WebhooksListPage/WebhooksListPage.tsx index 2803f94db..e47271d46 100644 --- a/src/webhooks/components/WebhooksListPage/WebhooksListPage.tsx +++ b/src/webhooks/components/WebhooksListPage/WebhooksListPage.tsx @@ -13,6 +13,7 @@ import WebhooksList from "../WebhooksList/WebhooksList"; export interface WebhooksListPageProps extends PageListProps { webhooks: Webhooks_webhooks_edges_node[]; onBack: () => void; + onRemove: () => void; } const WebhooksListPage: React.StatelessComponent = ({ @@ -23,6 +24,7 @@ const WebhooksListPage: React.StatelessComponent = ({ onNextPage, onPreviousPage, onRowClick, + onRemove, onUpdateListSettings, pageInfo, webhooks @@ -47,6 +49,7 @@ const WebhooksListPage: React.StatelessComponent = ({ webhooks={webhooks} onNextPage={onNextPage} onPreviousPage={onPreviousPage} + onRemove={onRemove} onUpdateListSettings={onUpdateListSettings} onRowClick={onRowClick} pageInfo={pageInfo} diff --git a/src/webhooks/mutations.ts b/src/webhooks/mutations.ts index 864e482b0..5e9a66cc9 100644 --- a/src/webhooks/mutations.ts +++ b/src/webhooks/mutations.ts @@ -57,4 +57,4 @@ const webhookDelete = gql` export const TypedWebhookDelete = TypedMutation< WebhookDelete, WebhookDeleteVariables ->(WebhookDelete); +>(webhookDelete); diff --git a/src/webhooks/urls.ts b/src/webhooks/urls.ts index c8c410e1d..9edbe362f 100644 --- a/src/webhooks/urls.ts +++ b/src/webhooks/urls.ts @@ -1,17 +1,21 @@ import { stringify as stringifyQs } from "qs"; import urlJoin from "url-join"; -import { Pagination, SingleAction } from "../types"; +import { Dialog, Pagination, SingleAction } from "../types"; export const webhooksSection = "/webhooks/"; export const webhooksListPath = webhooksSection; -export type WebhooksListUrlQueryParams = Pagination & SingleAction; +export type WebhookListUrlDialog = "remove"; +export type WebhooksListUrlQueryParams = Dialog & + Pagination & + SingleAction; export const webhooksListUrl = (params?: WebhooksListUrlQueryParams) => webhooksListPath + "?" + stringifyQs(params); export const webhooksPath = (id: string) => urlJoin(webhooksSection, id); -export type WebhooksUrlQueryParams = SingleAction; +export type WebhookUrlDialog = "remove"; +export type WebhooksUrlQueryParams = Dialog & SingleAction; export const webhooksUrl = (id: string, params?: WebhooksUrlQueryParams) => webhooksPath(encodeURIComponent(id)) + "?" + stringifyQs(params); diff --git a/src/webhooks/views/WebhooksCreate.tsx b/src/webhooks/views/WebhooksCreate.tsx index e28887453..a65732003 100644 --- a/src/webhooks/views/WebhooksCreate.tsx +++ b/src/webhooks/views/WebhooksCreate.tsx @@ -1,9 +1,9 @@ import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; -import useShop from "@saleor/hooks/useShop"; import { commonMessages } from "@saleor/intl"; import { WebhookCreate as WebhookCreateData } from "@saleor/webhooks/types/WebhookCreate"; +import { WebhookEventTypeEnum } from "@saleor/types/globalTypes"; import React from "react"; import { useIntl } from "react-intl"; @@ -28,7 +28,6 @@ export const WebhooksCreate: React.StatelessComponent< const navigate = useNavigator(); const notify = useNotifier(); const intl = useIntl(); - const shop = useShop(); const onSubmit = (data: WebhookCreateData) => { if (data.webhookCreate.errors.length === 0) { @@ -48,7 +47,7 @@ export const WebhooksCreate: React.StatelessComponent< WebhookCreate({ variables: { input: { - events: data.events, + events: [WebhookEventTypeEnum.ALL_EVENTS], isActive: data.isActive, name: data.name, secretKey: data.secretKey, @@ -66,7 +65,7 @@ export const WebhooksCreate: React.StatelessComponent< return ( - {({ data, loading }) => { + {({ data }) => { return ( <> data.serviceAccounts.edges.map(edge => edge.node) )} - loading={loading} onBack={handleBack} onSubmit={handleSubmit} - permissions={maybe(() => shop.permissions)} saveButtonBarState={formTransitionState} /> diff --git a/src/webhooks/views/WebhooksDetails.tsx b/src/webhooks/views/WebhooksDetails.tsx index 2413b735f..2e9114790 100644 --- a/src/webhooks/views/WebhooksDetails.tsx +++ b/src/webhooks/views/WebhooksDetails.tsx @@ -1,14 +1,22 @@ import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; +import { commonMessages } from "@saleor/intl"; +import WebhookDeleteDialog from "@saleor/webhooks/components/WebhookDeleteDialog"; +import { WebhookDelete } from "@saleor/webhooks/types/WebhookDelete"; import React from "react"; import { useIntl } from "react-intl"; import { getMutationState, maybe } from "../../misc"; import WebhooksDetailsPage from "../components/WebhooksDetailsPage"; -import { TypedWebhookUpdate } from "../mutations"; +import { TypedWebhookDelete, TypedWebhookUpdate } from "../mutations"; import { TypedServiceListQuery, TypedWebhooksDetailsQuery } from "../queries"; -import { webhooksListUrl, WebhooksListUrlQueryParams } from "../urls"; +import { + webhooksListUrl, + WebhooksListUrlQueryParams, + webhooksUrl, + WebhookUrlDialog +} from "../urls"; export interface WebhooksDetailsProps { id: string; @@ -17,82 +25,138 @@ export interface WebhooksDetailsProps { export const WebhooksDetails: React.StatelessComponent< WebhooksDetailsProps -> = ({ id }) => { +> = ({ id, params }) => { const navigate = useNavigator(); const notify = useNotifier(); const intl = useIntl(); + const closeModal = () => + navigate( + webhooksUrl(id, { + ...params, + action: undefined, + id: undefined + }), + true + ); + + const openModal = (action: WebhookUrlDialog, tokenId?: string) => + navigate( + webhooksUrl(id, { + ...params, + action, + id: tokenId + }) + ); + + const onWebhookDelete = (data: WebhookDelete) => { + if (data.webhookDelete.errors.length === 0) { + notify({ + text: intl.formatMessage(commonMessages.savedChanges) + }); + navigate(webhooksListUrl()); + } + }; + return ( {(webhookUpdate, webhookUpdateOpts) => ( - - {WebhookDetails => { - const formTransitionState = getMutationState( - webhookUpdateOpts.called, - webhookUpdateOpts.loading, - maybe(() => webhookUpdateOpts.data.webhookUpdate.errors) - ); + + {(webhookDelete, webhookDeleteOpts) => ( + + {WebhookDetails => { + const formTransitionState = getMutationState( + webhookUpdateOpts.called, + webhookUpdateOpts.loading, + maybe(() => webhookUpdateOpts.data.webhookUpdate.errors) + ); - const formErrors = maybe( - () => webhookUpdateOpts.data.webhookUpdate.errors, - [] - ); + const handleRemoveConfirm = () => + webhookDelete({ + variables: { + id + } + }); - if (formErrors.length) { - formErrors.map(error => { - notify({ - text: error.message - }); - }); - } else { - if (webhookUpdateOpts.data) { - notify({ - text: intl.formatMessage({ - defaultMessage: "Succesfully updated plugin settings", - description: "plugin success message" - }) - }); - } - } + const formErrors = maybe( + () => webhookUpdateOpts.data.webhookUpdate.errors, + [] + ); - return ( - - {({ data }) => ( - <> - WebhookDetails.data.webhook.name)} - /> - WebhookDetails.data.webhook)} - services={maybe(() => - data.serviceAccounts.edges.map(edge => edge.node) - )} - onBack={() => navigate(webhooksListUrl())} - onSubmit={data => { - webhookUpdate({ - variables: { - id, - input: { - events: data.events, - isActive: data.isActive, - name: data.name, - secretKey: data.secretKey, - serviceAccount: data.serviceAccount, - targetUrl: data.targetUrl - } - } - }); - }} - /> - - )} - - ); - }} - + if (formErrors.length) { + formErrors.map(error => { + notify({ + text: error.message + }); + }); + } else { + if (webhookUpdateOpts.data) { + notify({ + text: intl.formatMessage({ + defaultMessage: "Succesfully updated plugin settings", + description: "plugin success message" + }) + }); + } + } + + const deleteTransitionState = getMutationState( + webhookDeleteOpts.called, + webhookDeleteOpts.loading, + maybe(() => webhookDeleteOpts.data.webhookDelete.errors) + ); + + return ( + + {({ data }) => ( + <> + WebhookDetails.data.webhook.name)} + /> + WebhookDetails.data.webhook)} + services={maybe(() => + data.serviceAccounts.edges.map(edge => edge.node) + )} + onBack={() => navigate(webhooksListUrl())} + onDelete={() => openModal("remove")} + onSubmit={data => { + webhookUpdate({ + variables: { + id, + input: { + events: data.events, + isActive: data.isActive, + name: data.name, + secretKey: data.secretKey, + serviceAccount: data.serviceAccount, + targetUrl: data.targetUrl + } + } + }); + }} + /> + WebhookDetails.data.webhook.name, + "..." + )} + onClose={closeModal} + onConfirm={handleRemoveConfirm} + open={params.action === "remove"} + /> + + )} + + ); + }} + + )} + )} ); diff --git a/src/webhooks/views/WebhooksList.tsx b/src/webhooks/views/WebhooksList.tsx index 1f0e378c8..1452105d0 100644 --- a/src/webhooks/views/WebhooksList.tsx +++ b/src/webhooks/views/WebhooksList.tsx @@ -1,19 +1,27 @@ import { configurationMenuUrl } from "@saleor/configuration"; import useListSettings from "@saleor/hooks/useListSettings"; import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; import usePaginator, { createPaginationState } from "@saleor/hooks/usePaginator"; -import { maybe } from "@saleor/misc"; +import { commonMessages } from "@saleor/intl"; +import { getMutationState, maybe } from "@saleor/misc"; import { ListViews } from "@saleor/types"; +import WebhookDeleteDialog from "@saleor/webhooks/components/WebhookDeleteDialog"; +import { WebhookDelete } from "@saleor/webhooks/types/WebhookDelete"; import React from "react"; +import { useIntl } from "react-intl"; import WebhooksListPage from "../components/WebhooksListPage/WebhooksListPage"; +import { TypedWebhookDelete } from "../mutations"; import { TypedWebhooksListQuery } from "../queries"; import { webhooksAddUrl, + webhooksListUrl, WebhooksListUrlQueryParams, - webhooksUrl + webhooksUrl, + WebhookUrlDialog } from "../urls"; interface WebhooksListProps { @@ -25,36 +33,107 @@ export const WebhooksList: React.StatelessComponent = ({ }) => { const navigate = useNavigator(); const paginate = usePaginator(); + const notify = useNotifier(); + const intl = useIntl(); const { updateListSettings, settings } = useListSettings( ListViews.WEBHOOK_LIST ); const paginationState = createPaginationState(settings.rowNumber, params); + const closeModal = () => + navigate( + webhooksListUrl({ + ...params, + action: undefined, + id: undefined + }), + true + ); + + const openModal = (action: WebhookUrlDialog, id?: string) => + navigate( + webhooksListUrl({ + ...params, + action, + id + }) + ); + + const onWebhookDelete = (data: WebhookDelete) => { + if (data.webhookDelete.errors.length === 0) { + notify({ + text: intl.formatMessage(commonMessages.savedChanges) + }); + navigate(webhooksListUrl()); + } + }; + return ( - {({ data, loading }) => { - const { loadNextPage, loadPreviousPage, pageInfo } = paginate( - maybe(() => data.webhooks.pageInfo), - paginationState, - params - ); - return ( - <> - data.webhooks.edges.map(edge => edge.node))} - pageInfo={pageInfo} - onAdd={() => navigate(webhooksAddUrl)} - onBack={() => navigate(configurationMenuUrl)} - onNextPage={loadNextPage} - onPreviousPage={loadPreviousPage} - onUpdateListSettings={updateListSettings} - onRowClick={id => () => navigate(webhooksUrl(id))} - /> - - ); - }} + {({ data, loading }) => ( + + {(webhookDelete, webhookDeleteOpts) => { + const { loadNextPage, loadPreviousPage, pageInfo } = paginate( + maybe(() => data.webhooks.pageInfo), + paginationState, + params + ); + const handleRemove = (id: string) => + navigate( + webhooksListUrl({ + ...params, + action: "remove", + id + }) + ); + const handleRemoveConfirm = () => + webhookDelete({ + variables: { + id + } + }); + + const deleteTransitionState = getMutationState( + webhookDeleteOpts.called, + webhookDeleteOpts.loading, + maybe(() => webhookDeleteOpts.data.webhookDelete.errors) + ); + + return ( + <> + + data.webhooks.edges.map(edge => edge.node) + )} + pageInfo={pageInfo} + onAdd={() => navigate(webhooksAddUrl)} + onBack={() => navigate(configurationMenuUrl)} + onNextPage={loadNextPage} + onPreviousPage={loadPreviousPage} + onRemove={handleRemove} + onUpdateListSettings={updateListSettings} + onRowClick={id => () => navigate(webhooksUrl(id))} + /> + + data.webhooks.edges.find( + edge => edge.node.id === params.id + ).node.name, + "..." + )} + onClose={closeModal} + onConfirm={handleRemoveConfirm} + open={params.action === "remove"} + /> + + ); + }} + + )} ); }; From d802ae90ce4164ea882e7d8b9ae9600c46eac592 Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Thu, 10 Oct 2019 08:09:29 +0200 Subject: [PATCH 06/38] Add webhook delele to list --- .../components/WebhooksList/WebhooksList.tsx | 11 +- .../WebhooksListPage/WebhooksListPage.tsx | 2 +- src/webhooks/views/WebhooksList.tsx | 156 +++++++++--------- 3 files changed, 83 insertions(+), 86 deletions(-) diff --git a/src/webhooks/components/WebhooksList/WebhooksList.tsx b/src/webhooks/components/WebhooksList/WebhooksList.tsx index 3d9844bc5..281a6fc1a 100644 --- a/src/webhooks/components/WebhooksList/WebhooksList.tsx +++ b/src/webhooks/components/WebhooksList/WebhooksList.tsx @@ -19,7 +19,7 @@ import { useIntl } from "react-intl"; import Skeleton from "@saleor/components/Skeleton"; import TablePagination from "@saleor/components/TablePagination"; -import { maybe, renderCollection } from "@saleor/misc"; +import { maybe, renderCollection, stopPropagation } from "@saleor/misc"; import { ListProps } from "@saleor/types"; import { Webhooks_webhooks_edges_node } from "../../types/Webhooks"; @@ -125,15 +125,18 @@ const WebhooksList = withStyles(styles, { name: "PluginList" })( )} -
-
+ onRemove(webhook.id) : undefined + webhook + ? stopPropagation(() => onRemove(webhook.id)) + : undefined } > diff --git a/src/webhooks/components/WebhooksListPage/WebhooksListPage.tsx b/src/webhooks/components/WebhooksListPage/WebhooksListPage.tsx index e47271d46..27a096ece 100644 --- a/src/webhooks/components/WebhooksListPage/WebhooksListPage.tsx +++ b/src/webhooks/components/WebhooksListPage/WebhooksListPage.tsx @@ -13,7 +13,7 @@ import WebhooksList from "../WebhooksList/WebhooksList"; export interface WebhooksListPageProps extends PageListProps { webhooks: Webhooks_webhooks_edges_node[]; onBack: () => void; - onRemove: () => void; + onRemove: (id: string) => void; } const WebhooksListPage: React.StatelessComponent = ({ diff --git a/src/webhooks/views/WebhooksList.tsx b/src/webhooks/views/WebhooksList.tsx index 1452105d0..db35f81a0 100644 --- a/src/webhooks/views/WebhooksList.tsx +++ b/src/webhooks/views/WebhooksList.tsx @@ -20,8 +20,7 @@ import { webhooksAddUrl, webhooksListUrl, WebhooksListUrlQueryParams, - webhooksUrl, - WebhookUrlDialog + webhooksUrl } from "../urls"; interface WebhooksListProps { @@ -50,90 +49,85 @@ export const WebhooksList: React.StatelessComponent = ({ true ); - const openModal = (action: WebhookUrlDialog, id?: string) => - navigate( - webhooksListUrl({ - ...params, - action, - id - }) - ); - - const onWebhookDelete = (data: WebhookDelete) => { - if (data.webhookDelete.errors.length === 0) { - notify({ - text: intl.formatMessage(commonMessages.savedChanges) - }); - navigate(webhooksListUrl()); - } - }; - return ( - {({ data, loading }) => ( - - {(webhookDelete, webhookDeleteOpts) => { - const { loadNextPage, loadPreviousPage, pageInfo } = paginate( - maybe(() => data.webhooks.pageInfo), - paginationState, - params - ); - const handleRemove = (id: string) => - navigate( - webhooksListUrl({ - ...params, - action: "remove", - id - }) + {({ data, loading, refetch }) => { + const onWebhookDelete = (data: WebhookDelete) => { + if (data.webhookDelete.errors.length === 0) { + notify({ + text: intl.formatMessage(commonMessages.savedChanges) + }); + navigate(webhooksListUrl()); + refetch(); + } + }; + return ( + + {(webhookDelete, webhookDeleteOpts) => { + const { loadNextPage, loadPreviousPage, pageInfo } = paginate( + maybe(() => data.webhooks.pageInfo), + paginationState, + params ); - const handleRemoveConfirm = () => - webhookDelete({ - variables: { - id - } - }); + const handleRemove = (id: string) => { + navigate( + webhooksListUrl({ + ...params, + action: "remove", + id + }) + ); + }; + const handleRemoveConfirm = () => { + webhookDelete({ + variables: { + id: params.id + } + }); + }; - const deleteTransitionState = getMutationState( - webhookDeleteOpts.called, - webhookDeleteOpts.loading, - maybe(() => webhookDeleteOpts.data.webhookDelete.errors) - ); + const deleteTransitionState = getMutationState( + webhookDeleteOpts.called, + webhookDeleteOpts.loading, + maybe(() => webhookDeleteOpts.data.webhookDelete.errors) + ); - return ( - <> - - data.webhooks.edges.map(edge => edge.node) - )} - pageInfo={pageInfo} - onAdd={() => navigate(webhooksAddUrl)} - onBack={() => navigate(configurationMenuUrl)} - onNextPage={loadNextPage} - onPreviousPage={loadPreviousPage} - onRemove={handleRemove} - onUpdateListSettings={updateListSettings} - onRowClick={id => () => navigate(webhooksUrl(id))} - /> - - data.webhooks.edges.find( - edge => edge.node.id === params.id - ).node.name, - "..." - )} - onClose={closeModal} - onConfirm={handleRemoveConfirm} - open={params.action === "remove"} - /> - - ); - }} - - )} + return ( + <> + + data.webhooks.edges.map(edge => edge.node) + )} + pageInfo={pageInfo} + onAdd={() => navigate(webhooksAddUrl)} + onBack={() => navigate(configurationMenuUrl)} + onNextPage={loadNextPage} + onPreviousPage={loadPreviousPage} + onRemove={handleRemove} + onUpdateListSettings={updateListSettings} + onRowClick={id => () => navigate(webhooksUrl(id))} + /> + + data.webhooks.edges.find( + edge => edge.node.id === params.id + ).node.name, + "..." + )} + onClose={closeModal} + onConfirm={handleRemoveConfirm} + open={params.action === "remove"} + /> + + ); + }} + + ); + }} ); }; From 8d1890162cd5f5684d407b84b13f5f8cae8c822d Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Thu, 10 Oct 2019 13:40:31 +0200 Subject: [PATCH 07/38] Fix webhook events type --- schema.graphql | 4 +- src/types/globalTypes.ts | 5 - .../WebhookCreatePage/WebhookCreatePage.tsx | 5 +- .../WebhookEvents/WebhookEvents.tsx | 92 ++++++++++--------- .../WebhooksDetailsPage.tsx | 15 ++- .../components/WebhooksList/WebhooksList.tsx | 40 ++++---- src/webhooks/fixtures.ts | 86 ++++++++--------- src/webhooks/types/Webhook.ts | 4 +- src/webhooks/types/WebhookCreate.ts | 4 +- src/webhooks/types/WebhookFragment.ts | 4 +- src/webhooks/types/WebhookUpdate.ts | 4 +- src/webhooks/types/Webhooks.ts | 4 +- src/webhooks/types/WebhooksDetailsFragment.ts | 4 +- src/webhooks/views/WebhooksCreate.tsx | 4 +- 14 files changed, 147 insertions(+), 128 deletions(-) diff --git a/schema.graphql b/schema.graphql index eaa7a9b2a..4dbc36710 100644 --- a/schema.graphql +++ b/schema.graphql @@ -3196,11 +3196,11 @@ type ProductVariant implements Node { name: String! product: Product! trackInventory: Boolean! - quantity: Int! quantityAllocated: Int! weight: Weight privateMeta: [MetaStore]! meta: [MetaStore]! + quantity: Int! stockQuantity: Int! priceOverride: Money price: Money @deprecated(reason: "DEPRECATED: Will be removed in Saleor 2.10, has been replaced by 'pricing.priceUndiscounted'") @@ -4315,7 +4315,7 @@ enum WebhookErrorCode { } type WebhookEvent { - eventType: String + eventType: WebhookEventTypeEnum } enum WebhookEventTypeEnum { diff --git a/src/types/globalTypes.ts b/src/types/globalTypes.ts index d3754b168..d39c8d65f 100644 --- a/src/types/globalTypes.ts +++ b/src/types/globalTypes.ts @@ -662,11 +662,6 @@ export interface SeoInput { description?: string | null; } -export interface ServiceAccountFilterInput { - search?: string | null; - isActive?: boolean | null; -} - export interface ServiceAccountInput { name?: string | null; isActive?: boolean | null; diff --git a/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx b/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx index 6b92e9841..1701f66d1 100644 --- a/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx +++ b/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx @@ -9,6 +9,7 @@ import SaveButtonBar from "@saleor/components/SaveButtonBar"; import { sectionNames } from "@saleor/intl"; import { maybe } from "@saleor/misc"; import { UserError } from "@saleor/types"; +import { WebhookEventTypeEnum } from "@saleor/types/globalTypes"; import React from "react"; import { useIntl } from "react-intl"; import { ServiceList_serviceAccounts_edges_node } from "../../types/ServiceList"; @@ -18,12 +19,13 @@ import WebhookStatus from "../WebhookStatus"; export interface FormData { id: string; - events: string[]; + events: WebhookEventTypeEnum[]; isActive: boolean; name: string; secretKey: string | null; targetUrl: string; serviceAccount: string; + allEvents: boolean; } export interface WebhookCreatePageProps { @@ -45,6 +47,7 @@ const WebhookCreatePage: React.StatelessComponent = ({ }) => { const intl = useIntl(); const initialForm: FormData = { + allEvents: false, events: [], id: null, isActive: false, diff --git a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx index a0f8792b1..b26a92284 100644 --- a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx +++ b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx @@ -1,54 +1,48 @@ 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 CardTitle from "@saleor/components/CardTitle"; import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; +import Hr from "@saleor/components/Hr"; import React from "react"; import { useIntl } from "react-intl"; import { WebhookEventTypeEnum } from "../../../types/globalTypes"; -import { FormData } from "../WebhooksDetailsPage"; interface WebhookEventsProps { - data: FormData; + data: { + allEvents: boolean; + events: string[]; + }; disabled: boolean; - onChange: (event: React.ChangeEvent) => void; + onChange: (event: React.ChangeEvent, cb?: () => void) => void; } -const useStyles = makeStyles(() => ({ - item: { - paddingBottom: 10, - paddingTop: 10 - } -})); - const WebhookEvents: React.StatelessComponent = ({ data, disabled, onChange }) => { const intl = useIntl(); - const [events, setEvents] = React.useState(data.events); - const eventsEnum = Object.values(WebhookEventTypeEnum); - const addOrRemove = (array, value) => { - const index = array.indexOf(value); - - if (index === -1) { - array.push(value); - } else { - array.splice(index, 1); - } - }; - - console.log(data.events); - - const eventsOnChange = event => { - const newData = events; - addOrRemove(newData, event.target.name); - setEvents(newData); - console.log(events.indexOf(event.target.name)); + const handleAllEventsChange = (event: React.ChangeEvent) => + onChange(event, () => + onChange({ + target: { + name: "events", + value: event.target.value ? eventsEnum.map(event => event) : [] + } + } as any) + ); + const handleEventsChange = (event: React.ChangeEvent) => { + onChange({ + target: { + name: "events", + value: event.target.value + ? data.events.concat([event.target.name]) + : data.events.filter(events => events !== event.target.name) + } + } as any); }; return ( @@ -67,17 +61,33 @@ const WebhookEvents: React.StatelessComponent = ({ description: "webhook events" })} - {eventsEnum.map((event, index) => ( -
- -
- ))} + +
+ {!data.allEvents && + eventsEnum.map((event, index) => { + if (index !== 0) { + return ( +
+ +
+ ); + } + })} ); diff --git a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx index 7f025b450..f8a301ee2 100644 --- a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx +++ b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx @@ -20,12 +20,13 @@ import WebhookStatus from "../WebhookStatus"; export interface FormData { id: string; - events: string[]; + events: WebhookEventTypeEnum[]; isActive: boolean; name: string; secretKey: string | null; targetUrl: string; serviceAccount: string; + allEvents: boolean; } export interface WebhooksDetailsPageProps { @@ -53,6 +54,16 @@ const WebhooksDetailsPage: React.StatelessComponent< }) => { const intl = useIntl(); const initialForm: FormData = { + allEvents: maybe( + () => + Object.values(WebhookEventTypeEnum).filter( + perm => + maybe(() => webhook.events, []).filter( + event => event.eventType === perm + ).length === 0 + ).length === 0, + false + ), events: maybe(() => webhook.events, []).map(event => event.eventType), id: maybe(() => webhook.id, null), isActive: maybe(() => webhook.isActive, false), @@ -93,8 +104,8 @@ const WebhooksDetailsPage: React.StatelessComponent<
- - {intl.formatMessage({ - defaultMessage: "Name", - description: "webhook name" - })} - - - {intl.formatMessage({ - defaultMessage: "Service Account", - description: "webhook service account" - })} - - - {intl.formatMessage({ - defaultMessage: "Action", - description: "user action bar" - })} - + + + {intl.formatMessage({ + defaultMessage: "Name", + description: "webhook name" + })} + + + {intl.formatMessage({ + defaultMessage: "Service Account", + description: "webhook service account" + })} + + + {intl.formatMessage({ + defaultMessage: "Action", + description: "user action bar" + })} + + diff --git a/src/webhooks/fixtures.ts b/src/webhooks/fixtures.ts index 4da3ce27b..61df7f71b 100644 --- a/src/webhooks/fixtures.ts +++ b/src/webhooks/fixtures.ts @@ -1,57 +1,47 @@ -import { ConfigurationTypeFieldEnum } from "@saleor/types/globalTypes"; -import { Plugin_plugin } from "./types/Plugin"; -import { Plugins_plugins_edges_node } from "./types/Plugins"; +import { Webhook_webhook } from "./types/Webhook"; +import { Webhooks_webhooks_edges_node } from "./types/Webhooks"; -export const pluginList: Plugins_plugins_edges_node[] = [ +export const webhookList: Webhooks_webhooks_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.", + __typename: "Webhook", + events: [], id: "Jzx123sEt==", - name: "Avalara" + isActive: true, + name: "Webhook Test", + secretKey: "dsdasdasd_asdas", + serviceAccount: { + __typename: "ServiceAccount", + id: "Jzx123sEt==", + name: "Test Account" + }, + targetUrl: "http://www.getsaleor.com" }, { - __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.", + __typename: "Webhook", + events: [], id: "Jzx123sEt==", - name: "VatLayer" + isActive: true, + name: "Webhook Test 2", + secretKey: "zxczx_asdas", + serviceAccount: { + __typename: "ServiceAccount", + id: "Jzx1ss23sEt==", + name: "Test Account 2" + }, + targetUrl: "http://www.getsaleor.com" } ]; -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" +export const webhook: Webhook_webhook = { + __typename: "Webhook", + events: [], + id: "Jzx123sEt==", + isActive: true, + name: "Webhook Test 2", + secretKey: "zxczx_asdas", + serviceAccount: { + __typename: "ServiceAccount", + id: "Jzx1ss23sEt==", + name: "Test Account 2" + }, + targetUrl: "http://www.getsaleor.com" }; diff --git a/src/webhooks/types/Webhook.ts b/src/webhooks/types/Webhook.ts index 8286a50f2..abcdd8141 100644 --- a/src/webhooks/types/Webhook.ts +++ b/src/webhooks/types/Webhook.ts @@ -2,13 +2,15 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. +import { WebhookEventTypeEnum } from "./../../types/globalTypes"; + // ==================================================== // GraphQL query operation: Webhook // ==================================================== export interface Webhook_webhook_events { __typename: "WebhookEvent"; - eventType: string | null; + eventType: WebhookEventTypeEnum | null; } export interface Webhook_webhook_serviceAccount { diff --git a/src/webhooks/types/WebhookCreate.ts b/src/webhooks/types/WebhookCreate.ts index 1e5fcac94..9874ecbbd 100644 --- a/src/webhooks/types/WebhookCreate.ts +++ b/src/webhooks/types/WebhookCreate.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { WebhookCreateInput } from "./../../types/globalTypes"; +import { WebhookCreateInput, WebhookEventTypeEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: WebhookCreate @@ -16,7 +16,7 @@ export interface WebhookCreate_webhookCreate_errors { export interface WebhookCreate_webhookCreate_webhook_events { __typename: "WebhookEvent"; - eventType: string | null; + eventType: WebhookEventTypeEnum | null; } export interface WebhookCreate_webhookCreate_webhook_serviceAccount { diff --git a/src/webhooks/types/WebhookFragment.ts b/src/webhooks/types/WebhookFragment.ts index 04132dc9f..fa750b732 100644 --- a/src/webhooks/types/WebhookFragment.ts +++ b/src/webhooks/types/WebhookFragment.ts @@ -2,13 +2,15 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. +import { WebhookEventTypeEnum } from "./../../types/globalTypes"; + // ==================================================== // GraphQL fragment: WebhookFragment // ==================================================== export interface WebhookFragment_events { __typename: "WebhookEvent"; - eventType: string | null; + eventType: WebhookEventTypeEnum | null; } export interface WebhookFragment_serviceAccount { diff --git a/src/webhooks/types/WebhookUpdate.ts b/src/webhooks/types/WebhookUpdate.ts index d58000b70..ca174bdfe 100644 --- a/src/webhooks/types/WebhookUpdate.ts +++ b/src/webhooks/types/WebhookUpdate.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { WebhookUpdateInput } from "./../../types/globalTypes"; +import { WebhookUpdateInput, WebhookEventTypeEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: WebhookUpdate @@ -16,7 +16,7 @@ export interface WebhookUpdate_webhookUpdate_errors { export interface WebhookUpdate_webhookUpdate_webhook_events { __typename: "WebhookEvent"; - eventType: string | null; + eventType: WebhookEventTypeEnum | null; } export interface WebhookUpdate_webhookUpdate_webhook_serviceAccount { diff --git a/src/webhooks/types/Webhooks.ts b/src/webhooks/types/Webhooks.ts index 6b0801cda..95a458f51 100644 --- a/src/webhooks/types/Webhooks.ts +++ b/src/webhooks/types/Webhooks.ts @@ -2,13 +2,15 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. +import { WebhookEventTypeEnum } from "./../../types/globalTypes"; + // ==================================================== // GraphQL query operation: Webhooks // ==================================================== export interface Webhooks_webhooks_edges_node_events { __typename: "WebhookEvent"; - eventType: string | null; + eventType: WebhookEventTypeEnum | null; } export interface Webhooks_webhooks_edges_node_serviceAccount { diff --git a/src/webhooks/types/WebhooksDetailsFragment.ts b/src/webhooks/types/WebhooksDetailsFragment.ts index b54fc69c0..321a86b04 100644 --- a/src/webhooks/types/WebhooksDetailsFragment.ts +++ b/src/webhooks/types/WebhooksDetailsFragment.ts @@ -2,13 +2,15 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. +import { WebhookEventTypeEnum } from "./../../types/globalTypes"; + // ==================================================== // GraphQL fragment: WebhooksDetailsFragment // ==================================================== export interface WebhooksDetailsFragment_events { __typename: "WebhookEvent"; - eventType: string | null; + eventType: WebhookEventTypeEnum | null; } export interface WebhooksDetailsFragment_serviceAccount { diff --git a/src/webhooks/views/WebhooksCreate.tsx b/src/webhooks/views/WebhooksCreate.tsx index a65732003..a21d3a9c4 100644 --- a/src/webhooks/views/WebhooksCreate.tsx +++ b/src/webhooks/views/WebhooksCreate.tsx @@ -2,8 +2,8 @@ import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; import { commonMessages } from "@saleor/intl"; -import { WebhookCreate as WebhookCreateData } from "@saleor/webhooks/types/WebhookCreate"; import { WebhookEventTypeEnum } from "@saleor/types/globalTypes"; +import { WebhookCreate as WebhookCreateData } from "@saleor/webhooks/types/WebhookCreate"; import React from "react"; import { useIntl } from "react-intl"; @@ -47,7 +47,7 @@ export const WebhooksCreate: React.StatelessComponent< WebhookCreate({ variables: { input: { - events: [WebhookEventTypeEnum.ALL_EVENTS], + events: [WebhookEventTypeEnum.ORDER_CREATED], isActive: data.isActive, name: data.name, secretKey: data.secretKey, From f19e0288a3f77cb431d0ca27c885a2b7712821bd Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Thu, 10 Oct 2019 14:08:12 +0200 Subject: [PATCH 08/38] Fix unused code --- src/webhooks/views/WebhooksCreate.tsx | 3 +-- src/webhooks/views/WebhooksDetails.tsx | 17 ----------------- 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/src/webhooks/views/WebhooksCreate.tsx b/src/webhooks/views/WebhooksCreate.tsx index a21d3a9c4..0de8fcefc 100644 --- a/src/webhooks/views/WebhooksCreate.tsx +++ b/src/webhooks/views/WebhooksCreate.tsx @@ -2,7 +2,6 @@ import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; import { commonMessages } from "@saleor/intl"; -import { WebhookEventTypeEnum } from "@saleor/types/globalTypes"; import { WebhookCreate as WebhookCreateData } from "@saleor/webhooks/types/WebhookCreate"; import React from "react"; import { useIntl } from "react-intl"; @@ -47,7 +46,7 @@ export const WebhooksCreate: React.StatelessComponent< WebhookCreate({ variables: { input: { - events: [WebhookEventTypeEnum.ORDER_CREATED], + events: data.events, isActive: data.isActive, name: data.name, secretKey: data.secretKey, diff --git a/src/webhooks/views/WebhooksDetails.tsx b/src/webhooks/views/WebhooksDetails.tsx index 2e9114790..7724f3f74 100644 --- a/src/webhooks/views/WebhooksDetails.tsx +++ b/src/webhooks/views/WebhooksDetails.tsx @@ -83,23 +83,6 @@ export const WebhooksDetails: React.StatelessComponent< [] ); - if (formErrors.length) { - formErrors.map(error => { - notify({ - text: error.message - }); - }); - } else { - if (webhookUpdateOpts.data) { - notify({ - text: intl.formatMessage({ - defaultMessage: "Succesfully updated plugin settings", - description: "plugin success message" - }) - }); - } - } - const deleteTransitionState = getMutationState( webhookDeleteOpts.called, webhookDeleteOpts.loading, From f97319c47ad11c83fca4409c287ad79716fcd4e0 Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Thu, 10 Oct 2019 14:48:19 +0200 Subject: [PATCH 09/38] Fix storybook --- src/icons/Webhooks.tsx | 4 +- .../__snapshots__/Stories.test.ts.snap | 4916 ++++++++--------- .../WebhooksCreatePage.stories.tsx | 25 + .../WebhooksDetailsPage.stories.tsx | 30 + .../WebhookListPage.stories.tsx | 30 + src/webhooks/fixtures.ts | 15 + 6 files changed, 2441 insertions(+), 2579 deletions(-) create mode 100644 src/webhooks/components/WebhookCreatePage/WebhooksCreatePage.stories.tsx create mode 100644 src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx create mode 100644 src/webhooks/components/WebhooksListPage/WebhookListPage.stories.tsx diff --git a/src/icons/Webhooks.tsx b/src/icons/Webhooks.tsx index eaa17aae7..051893abe 100644 --- a/src/icons/Webhooks.tsx +++ b/src/icons/Webhooks.tsx @@ -4,8 +4,8 @@ import React from "react"; export const Webhooks = createSvgIcon( <> diff --git a/src/storybook/__snapshots__/Stories.test.ts.snap b/src/storybook/__snapshots__/Stories.test.ts.snap index a53de1617..dc07dd54b 100644 --- a/src/storybook/__snapshots__/Stories.test.ts.snap +++ b/src/storybook/__snapshots__/Stories.test.ts.snap @@ -28233,6 +28233,44 @@ exports[`Storyshots Views / Configuration default 1`] = ` +
+
+
+ +
+
+

+ Webhooks +

+

+ View and update your site settings +

+
+
+
@@ -28711,6 +28749,44 @@ exports[`Storyshots Views / Configuration partial access 1`] = ` +
+
+
+ +
+
+

+ Webhooks +

+

+ View and update your site settings +

+
+
+
@@ -103653,7 +103729,7 @@ exports[`Storyshots Views / Services / Create service default 1`] = `
- Create New Account + Create Webhook
- Service Account Information + Webhook Information
+

+ General Information +

@@ -103698,7 +103779,7 @@ exports[`Storyshots Views / Services / Create service default 1`] = ` class="MuiFormLabel-root-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-outlined-id" data-shrink="false" > - Account Name + Webhook Name
+
+
+
+
+
+

+ Webhook specific information +

+
+ +
+ +
+
+ + ​ + +
+ + +
+
+
+
+
+ +
+ +
+

+ This URL will recieve webhook POST requests +

+
+
+
+ +
+ + +
+

+ secret key is used to create a hash signature with each payload. *optional field +

-
+
- - Permissions -
-
-
-
-
-

- Expand or restrict user's permissions to access certain part of saleor system. -

-
- -
-
-
-
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-
-
-
- - Account Status - -
-
-
-
-
-

- If you want to disable this account uncheck the box below -

- +
+
+
+
+
+

+ Expand or restrict webhooks permissions to register certain events in Saleor system. +

+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ + Webhook Status + +
+
+
+
+
+

+ If you want to disable this webhook please uncheck the box below. +

+ +
@@ -104097,7 +104239,7 @@ exports[`Storyshots Views / Services / Create service form errors 1`] = `
- Create New Account + Create Webhook
- Service Account Information + Webhook Information
+

+ General Information +

@@ -104142,7 +104289,7 @@ exports[`Storyshots Views / Services / Create service form errors 1`] = ` class="MuiFormLabel-root-id MuiFormLabel-error-id MuiInputLabel-error-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-outlined-id" data-shrink="false" > - Account Name + Webhook Name

+
+
+
+

+ Webhook specific information +

+
+ +
+ +
+
+ + ​ + +
+ + +
+
+
+
+
+ +
+ + +
+

+ This URL will recieve webhook POST requests +

+
+
+
+ +
+ + +
+

+ secret key is used to create a hash signature with each payload. *optional field +

+
-
+
- - Permissions -
-
-
-
-
-

- Expand or restrict user's permissions to access certain part of saleor system. -

-
- -
-
-
-
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-
-
-
- - Account Status - -
-
-
-
-
-

- If you want to disable this account uncheck the box below -

- +
+
+
+
+
+

+ Expand or restrict webhooks permissions to register certain events in Saleor system. +

+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ + Webhook Status + +
+
+
+
+
+

+ If you want to disable this webhook please uncheck the box below. +

+ +
@@ -104546,7 +104754,7 @@ exports[`Storyshots Views / Services / Create service loading 1`] = `
- Create New Account + Create Webhook
- Service Account Information + Webhook Information
+

+ General Information +

@@ -104591,7 +104804,7 @@ exports[`Storyshots Views / Services / Create service loading 1`] = ` class="MuiFormLabel-root-id MuiFormLabel-disabled-id MuiInputLabel-disabled-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-outlined-id" data-shrink="false" > - Account Name + Webhook Name
+
+
+
+
+
+

+ Webhook specific information +

+
+ +
+ +
+
+ + ​ + +
+ + +
+
+
+
+
+ +
+ +
+

+ This URL will recieve webhook POST requests +

+
+
+
+ +
+ + +
+

+ secret key is used to create a hash signature with each payload. *optional field +

-
+
- - Permissions -
-
-
-
-
-

- Expand or restrict user's permissions to access certain part of saleor system. -

-
- -
-
-
-
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-
-
-
- - Account Status - -
-
-
-
-
-

- If you want to disable this account uncheck the box below -

- +
+
+
+
+
+

+ Expand or restrict webhooks permissions to register certain events in Saleor system. +

+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ + Webhook Status + +
+
+
+
+
+

+ If you want to disable this webhook please uncheck the box below. +

+ +
@@ -105021,7 +105289,7 @@ exports[`Storyshots Views / Services / Service details default 1`] = `
- Magento Importer + ... Details
- Service Account Information + Webhook Information
+

+ General Information +

​ @@ -105090,125 +105363,171 @@ exports[`Storyshots Views / Services / Service details default 1`] = ` class="MuiInputBase-input-id MuiOutlinedInput-input-id" name="name" type="text" - value="Magento Importer" + value="" />
-
-
-
-
-
- - Service Account Information -
+
+
+

- + + + ​ + + + +

+
+ + ​ + +
+ + +
+
+
+
+
+ +
+ + +
+

+ This URL will recieve webhook POST requests +

+
+
+
+ +
+ + +
+

+ secret key is used to create a hash signature with each payload. *optional field +

-
-
-
- - - - - - - - - - - - - - -
- Token Note - - Key - - Actions -
- default - - **** AK05 - - -
@@ -105221,7 +105540,7 @@ exports[`Storyshots Views / Services / Service details default 1`] = ` - Permissions + Events
- Expand or restrict user's permissions to access certain part of saleor system. -

-
- -
-
-
-
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-
-
-
- - Account Status - -
-
-
-
-
-

- If you want to disable this account uncheck the box below + Expand or restrict webhooks permissions to register certain events in Saleor system.

+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ + Webhook Status + +
+
+
+
+
+

+ If you want to disable this webhook please uncheck the box below. +

+
@@ -106228,7 +106447,7 @@ exports[`Storyshots Views / Services / Service details form errors 1`] = `
- Magento Importer + ... Details
- Service Account Information + Webhook Information
+

+ General Information +

​ @@ -106297,130 +106521,176 @@ exports[`Storyshots Views / Services / Service details form errors 1`] = ` class="MuiInputBase-input-id MuiOutlinedInput-input-id" name="name" type="text" - value="Magento Importer" + value="" />

Generic form error

-
-
-
-
-
- - Service Account Information -
+
+
+

- + + + ​ + + + +

+
+ + ​ + +
+ + +
+
+
+
+
+ +
+ + +
+

+ This URL will recieve webhook POST requests +

+
+
+
+ +
+ + +
+

+ secret key is used to create a hash signature with each payload. *optional field +

-
-
- - - - - - - - - - - - - - - -
- Token Note - - Key - - Actions -
- default - - **** AK05 - - -
@@ -106433,7 +106703,7 @@ exports[`Storyshots Views / Services / Service details form errors 1`] = ` - Permissions + Events
- Expand or restrict user's permissions to access certain part of saleor system. -

-
- -
-
-
-
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-
-
-
- - Account Status - -
-
-
-
-
-

- If you want to disable this account uncheck the box below + Expand or restrict webhooks permissions to register certain events in Saleor system.

+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ + Webhook Status + +
+
+
+
+
+

+ If you want to disable this webhook please uncheck the box below. +

+
@@ -106793,12 +106963,7 @@ exports[`Storyshots Views / Services / Service details loading 1`] = `
- - ‌ - + ... Details
- Service Account Information + Webhook Information
+

+ General Information +

@@ -106843,7 +107013,7 @@ exports[`Storyshots Views / Services / Service details loading 1`] = ` class="MuiFormLabel-root-id MuiFormLabel-disabled-id MuiInputLabel-disabled-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-outlined-id" data-shrink="false" > - Account Name + Webhook Name
-
-
-
-
-
- - Service Account Information -
+
+
+

- + + + ​ + + + +

+
+ + ​ + +
+ + +
+
+
+
+
+ +
+ + +
+

+ This URL will recieve webhook POST requests +

+
+
+
+ +
+ + +
+

+ secret key is used to create a hash signature with each payload. *optional field +

-
-
- - - - - - - - - - - - - - - -
- Token Note - - Key - - Actions -
- - ‌ - - - - ‌ - - - -
@@ -107007,7 +107217,7 @@ exports[`Storyshots Views / Services / Service details loading 1`] = ` - Permissions + Events
- Expand or restrict user's permissions to access certain part of saleor system. + Expand or restrict webhooks permissions to register certain events in Saleor system.

-
- -
-
-
-
+ name="allEvents" + type="checkbox" + value="false" + /> + + + All events + + +
@@ -107099,7 +107301,7 @@ exports[`Storyshots Views / Services / Service details loading 1`] = ` @@ -107107,7 +107309,7 @@ exports[`Storyshots Views / Services / Service details loading 1`] = ` - Manage sales and vouchers + ORDER_CANCELLED
@@ -107124,7 +107326,7 @@ exports[`Storyshots Views / Services / Service details loading 1`] = ` @@ -107132,7 +107334,7 @@ exports[`Storyshots Views / Services / Service details loading 1`] = ` - Manage navigation + ORDER_CREATED
@@ -107149,7 +107351,7 @@ exports[`Storyshots Views / Services / Service details loading 1`] = ` @@ -107157,7 +107359,7 @@ exports[`Storyshots Views / Services / Service details loading 1`] = ` - Manage orders + ORDER_FULLY_PAID
@@ -107174,7 +107376,7 @@ exports[`Storyshots Views / Services / Service details loading 1`] = ` @@ -107182,7 +107384,7 @@ exports[`Storyshots Views / Services / Service details loading 1`] = ` - Manage pages + ORDER_UPDATED
@@ -107199,7 +107401,7 @@ exports[`Storyshots Views / Services / Service details loading 1`] = ` @@ -107207,114 +107409,14 @@ exports[`Storyshots Views / Services / Service details loading 1`] = ` - Manage products - - -
-
- -
-
- -
-
- -
-
-
- Account Status + Webhook Status
- If you want to disable this account uncheck the box below + If you want to disable this webhook please uncheck the box below.

@@ -107390,7 +107492,7 @@ exports[`Storyshots Views / Services / Service list default 1`] = `
- Service Accounts + Webhooks
- Create account + Create webhook
@@ -107415,102 +107517,8 @@ exports[`Storyshots Views / Services / Service list default 1`] = `
-
-
-
-
- - -
-
-
-
-
-
-
- - -
-
-
-
+ + - - -
Name + > + Service Account + + Action +
- - Slack - - - active - + Webhook Test + Test Account +
- - Facebook Market - - - active - + Webhook Test 2 - - -
- - Magento Importer - - - inactive - + Test Account 2 @@ -107914,102 +107847,8 @@ exports[`Storyshots Views / Services / Service list loading 1`] = `
-
-
-
-
- - -
-
-
-
-
-
-
- - -
-
-
-
+ +
Name + > + Service Account + + Action +
- - ‌ - + ‌ - + + ‌ + + @@ -108270,102 +108118,8 @@ exports[`Storyshots Views / Services / Service list no data 1`] = `
-
-
-
-
- - -
-
-
-
-
-
-
- - -
-
-
-
+ diff --git a/src/webhooks/components/WebhookCreatePage/WebhooksCreatePage.stories.tsx b/src/webhooks/components/WebhookCreatePage/WebhooksCreatePage.stories.tsx new file mode 100644 index 000000000..58349aa2f --- /dev/null +++ b/src/webhooks/components/WebhookCreatePage/WebhooksCreatePage.stories.tsx @@ -0,0 +1,25 @@ +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import Decorator from "@saleor/storybook/Decorator"; +import { formError } from "@saleor/storybook/misc"; +import WebhookCreatePage, { WebhookCreatePageProps } from "./WebhookCreatePage"; + +const props: WebhookCreatePageProps = { + disabled: false, + errors: [], + onBack: () => undefined, + onSubmit: () => undefined, + saveButtonBarState: "default", + services: [] +}; +storiesOf("Views / Services / Create service", module) + .addDecorator(Decorator) + .add("default", () => ) + .add("loading", () => ) + .add("form errors", () => ( + formError(field))} + /> + )); diff --git a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx new file mode 100644 index 000000000..dbb865240 --- /dev/null +++ b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx @@ -0,0 +1,30 @@ +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import Decorator from "@saleor/storybook/Decorator"; +import { formError } from "@saleor/storybook/misc"; +import WebhooksDetailsPage, { + WebhooksDetailsPageProps +} from "./WebhooksDetailsPage"; + +const props: WebhooksDetailsPageProps = { + disabled: false, + errors: [], + onBack: () => undefined, + onDelete: () => undefined, + onSubmit: () => undefined, + saveButtonBarState: "default", + services: [] +}; +storiesOf("Views / Services / Service details", module) + .addDecorator(Decorator) + .add("default", () => ) + .add("loading", () => ( + + )) + .add("form errors", () => ( + formError(field))} + /> + )); diff --git a/src/webhooks/components/WebhooksListPage/WebhookListPage.stories.tsx b/src/webhooks/components/WebhooksListPage/WebhookListPage.stories.tsx new file mode 100644 index 000000000..93d9eb879 --- /dev/null +++ b/src/webhooks/components/WebhooksListPage/WebhookListPage.stories.tsx @@ -0,0 +1,30 @@ +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import { + listActionsProps, + pageListProps, + searchPageProps, + tabPageProps +} from "@saleor/fixtures"; +import Decorator from "@saleor/storybook/Decorator"; +import { webhookList } from "../../fixtures"; +import WebhooksListPage, { WebhooksListPageProps } from "./WebhooksListPage"; + +const props: WebhooksListPageProps = { + ...listActionsProps, + ...pageListProps.default, + ...searchPageProps, + ...tabPageProps, + onBack: () => undefined, + onRemove: () => undefined, + webhooks: webhookList +}; + +storiesOf("Views / Services / Service list", module) + .addDecorator(Decorator) + .add("default", () => ) + .add("loading", () => ( + + )) + .add("no data", () => ); diff --git a/src/webhooks/fixtures.ts b/src/webhooks/fixtures.ts index 61df7f71b..c92090dd4 100644 --- a/src/webhooks/fixtures.ts +++ b/src/webhooks/fixtures.ts @@ -1,6 +1,21 @@ +import { ServiceList_serviceAccounts_edges_node } from "./types/ServiceList"; import { Webhook_webhook } from "./types/Webhook"; import { Webhooks_webhooks_edges_node } from "./types/Webhooks"; +export const services: ServiceList_serviceAccounts_edges_node[] = [ + { + __typename: "ServiceAccount", + id: "Jzx123sEt==", + isActive: true, + name: "Facebook" + }, + { + __typename: "ServiceAccount", + id: "Jzx123sEt==", + isActive: false, + name: "Twittwe" + } +]; export const webhookList: Webhooks_webhooks_edges_node[] = [ { __typename: "Webhook", From c3e8936871be18d491d249e1997d026d05b3e4fb Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Thu, 10 Oct 2019 14:49:15 +0200 Subject: [PATCH 10/38] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32070e7b7..8142d3ea7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,3 +32,4 @@ All notable, unreleased changes to this project will be documented in this file. - Allow sorting products by attribute - #180 by @dominik-zeglen - Hide variants and attributes if product has none - #179 by @dominik-zeglen - Add service account section - #188 by @dominik-zeglen +- Add webhook section - #206 by @benekex2 From 83cd51e00176b602de18c2dde8c6a04d8c675f02 Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Thu, 10 Oct 2019 16:19:06 +0200 Subject: [PATCH 11/38] Fix all events checkbox --- src/webhooks/components/WebhookEvents/WebhookEvents.tsx | 2 +- .../WebhooksDetailsPage/WebhooksDetailsPage.tsx | 8 ++------ src/webhooks/views/WebhooksCreate.tsx | 8 ++++++-- src/webhooks/views/WebhooksDetails.tsx | 5 ++++- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx index b26a92284..dda09bc3e 100644 --- a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx +++ b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx @@ -30,7 +30,7 @@ const WebhookEvents: React.StatelessComponent = ({ onChange({ target: { name: "events", - value: event.target.value ? eventsEnum.map(event => event) : [] + value: WebhookEventTypeEnum.ALL_EVENTS } } as any) ); diff --git a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx index f8a301ee2..675256f50 100644 --- a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx +++ b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx @@ -56,12 +56,8 @@ const WebhooksDetailsPage: React.StatelessComponent< const initialForm: FormData = { allEvents: maybe( () => - Object.values(WebhookEventTypeEnum).filter( - perm => - maybe(() => webhook.events, []).filter( - event => event.eventType === perm - ).length === 0 - ).length === 0, + maybe(() => webhook.events, [])[0].eventType === + WebhookEventTypeEnum.ALL_EVENTS, false ), events: maybe(() => webhook.events, []).map(event => event.eventType), diff --git a/src/webhooks/views/WebhooksCreate.tsx b/src/webhooks/views/WebhooksCreate.tsx index 0de8fcefc..2aaf021cb 100644 --- a/src/webhooks/views/WebhooksCreate.tsx +++ b/src/webhooks/views/WebhooksCreate.tsx @@ -2,6 +2,7 @@ import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; import { commonMessages } from "@saleor/intl"; +import { WebhookEventTypeEnum } from "@saleor/types/globalTypes"; import { WebhookCreate as WebhookCreateData } from "@saleor/webhooks/types/WebhookCreate"; import React from "react"; import { useIntl } from "react-intl"; @@ -42,11 +43,13 @@ export const WebhooksCreate: React.StatelessComponent< return ( {(WebhookCreate, webhookCreateOpts) => { - const handleSubmit = (data: FormData) => + const handleSubmit = (data: FormData) => { WebhookCreate({ variables: { input: { - events: data.events, + events: data.allEvents + ? [WebhookEventTypeEnum.ALL_EVENTS] + : data.events, isActive: data.isActive, name: data.name, secretKey: data.secretKey, @@ -55,6 +58,7 @@ export const WebhooksCreate: React.StatelessComponent< } } }); + }; const formTransitionState = getMutationState( webhookCreateOpts.called, diff --git a/src/webhooks/views/WebhooksDetails.tsx b/src/webhooks/views/WebhooksDetails.tsx index 7724f3f74..94f75d351 100644 --- a/src/webhooks/views/WebhooksDetails.tsx +++ b/src/webhooks/views/WebhooksDetails.tsx @@ -2,6 +2,7 @@ import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; import { commonMessages } from "@saleor/intl"; +import { WebhookEventTypeEnum } from "@saleor/types/globalTypes"; import WebhookDeleteDialog from "@saleor/webhooks/components/WebhookDeleteDialog"; import { WebhookDelete } from "@saleor/webhooks/types/WebhookDelete"; import React from "react"; @@ -111,7 +112,9 @@ export const WebhooksDetails: React.StatelessComponent< variables: { id, input: { - events: data.events, + events: data.allEvents + ? [WebhookEventTypeEnum.ALL_EVENTS] + : data.events, isActive: data.isActive, name: data.name, secretKey: data.secretKey, From c8dbe00db408c6675743c51ac8d64c901b2688c1 Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Fri, 11 Oct 2019 15:35:33 +0200 Subject: [PATCH 12/38] Fix small issues --- src/configuration/index.tsx | 2 +- .../WebhookCreatePage/WebhookCreatePage.tsx | 95 ++++--- .../WebhooksCreatePage.stories.tsx | 2 +- .../WebhookEvents/WebhookEvents.tsx | 47 ++-- .../components/WebhookInfo/WebhookInfo.tsx | 26 +- .../WebhookStatus/WebhookStatus.tsx | 5 +- .../WebhooksDetailsPage.stories.tsx | 2 +- .../WebhooksDetailsPage.tsx | 117 ++++---- .../components/WebhooksList/WebhooksList.tsx | 255 +++++++++--------- .../WebhookListPage.stories.tsx | 2 +- src/webhooks/queries.ts | 39 +-- src/webhooks/types/ServiceList.ts | 3 - src/webhooks/views/WebhooksCreate.tsx | 52 ++-- src/webhooks/views/WebhooksDetails.tsx | 104 +++---- 14 files changed, 346 insertions(+), 405 deletions(-) diff --git a/src/configuration/index.tsx b/src/configuration/index.tsx index 38af5d7d6..1ca93d41a 100644 --- a/src/configuration/index.tsx +++ b/src/configuration/index.tsx @@ -166,7 +166,7 @@ export function createConfigurationMenu(intl: IntlShape): MenuSection[] { }, { description: intl.formatMessage({ - defaultMessage: "View and update your site settings" + defaultMessage: "View and update your webhook and their settings" }), icon: , permission: PermissionEnum.MANAGE_WEBHOOKS, diff --git a/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx b/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx index 1701f66d1..af32e669d 100644 --- a/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx +++ b/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx @@ -10,12 +10,11 @@ import { sectionNames } from "@saleor/intl"; import { maybe } from "@saleor/misc"; import { UserError } from "@saleor/types"; import { WebhookEventTypeEnum } from "@saleor/types/globalTypes"; +import WebhookEvents from "@saleor/webhooks/components/WebhookEvents"; +import WebhookInfo from "@saleor/webhooks/components/WebhookInfo"; +import WebhookStatus from "@saleor/webhooks/components/WebhookStatus"; import React from "react"; import { useIntl } from "react-intl"; -import { ServiceList_serviceAccounts_edges_node } from "../../types/ServiceList"; -import WebhookEvents from "../WebhookEvents"; -import WebhookInfo from "../WebhookInfo"; -import WebhookStatus from "../WebhookStatus"; export interface FormData { id: string; @@ -59,51 +58,49 @@ const WebhookCreatePage: React.StatelessComponent = ({ return ( - {({ data, errors, hasChanged, submit, change }) => { - return ( - - - {intl.formatMessage(sectionNames.plugins)} - - - -
- services, [])} - errors={errors} - onChange={change} - /> -
-
- - - -
-
- -
- ); - }} + {({ data, errors, hasChanged, submit, change }) => ( + + + {intl.formatMessage(sectionNames.plugins)} + + + +
+ services, [])} + errors={errors} + onChange={change} + /> +
+
+ + + +
+
+ +
+ )} ); }; diff --git a/src/webhooks/components/WebhookCreatePage/WebhooksCreatePage.stories.tsx b/src/webhooks/components/WebhookCreatePage/WebhooksCreatePage.stories.tsx index 58349aa2f..114b584cb 100644 --- a/src/webhooks/components/WebhookCreatePage/WebhooksCreatePage.stories.tsx +++ b/src/webhooks/components/WebhookCreatePage/WebhooksCreatePage.stories.tsx @@ -13,7 +13,7 @@ const props: WebhookCreatePageProps = { saveButtonBarState: "default", services: [] }; -storiesOf("Views / Services / Create service", module) +storiesOf("Views / Webhook / Create webhook", module) .addDecorator(Decorator) .add("default", () => ) .add("loading", () => ) diff --git a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx index dda09bc3e..589f30bf2 100644 --- a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx +++ b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx @@ -4,9 +4,10 @@ import Typography from "@material-ui/core/Typography"; import CardTitle from "@saleor/components/CardTitle"; import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; import Hr from "@saleor/components/Hr"; +import { ChangeEvent } from "@saleor/hooks/useForm"; +import { WebhookEventTypeEnum } from "@saleor/types/globalTypes"; import React from "react"; import { useIntl } from "react-intl"; -import { WebhookEventTypeEnum } from "../../../types/globalTypes"; interface WebhookEventsProps { data: { @@ -25,16 +26,14 @@ const WebhookEvents: React.StatelessComponent = ({ const intl = useIntl(); const eventsEnum = Object.values(WebhookEventTypeEnum); - const handleAllEventsChange = (event: React.ChangeEvent) => - onChange(event, () => - onChange({ - target: { - name: "events", - value: WebhookEventTypeEnum.ALL_EVENTS - } - } as any) - ); - const handleEventsChange = (event: React.ChangeEvent) => { + const handleAllEventsChange = () => + onChange({ + target: { + name: "events", + value: WebhookEventTypeEnum.ALL_EVENTS + } + } as any); + const handleEventsChange = (event: ChangeEvent) => { onChange({ target: { name: "events", @@ -73,20 +72,18 @@ const WebhookEvents: React.StatelessComponent = ({ />
{!data.allEvents && - eventsEnum.map((event, index) => { - if (index !== 0) { - return ( -
- -
- ); - } + eventsEnum.slice(1).map(event => { + return ( +
+ +
+ ); })} diff --git a/src/webhooks/components/WebhookInfo/WebhookInfo.tsx b/src/webhooks/components/WebhookInfo/WebhookInfo.tsx index fcdb88ac5..49a732d03 100644 --- a/src/webhooks/components/WebhookInfo/WebhookInfo.tsx +++ b/src/webhooks/components/WebhookInfo/WebhookInfo.tsx @@ -10,6 +10,8 @@ import CardTitle from "@saleor/components/CardTitle"; import FormSpacer from "@saleor/components/FormSpacer"; import Hr from "@saleor/components/Hr"; import SingleSelectField from "@saleor/components/SingleSelectField"; +import { SingleAutocompleteSelectField } from "@saleor/components/SingleAutocompleteSelectField"; +import { commonMessages } from "@saleor/intl"; import { FormErrors } from "@saleor/types"; import { FormData } from "../WebhooksDetailsPage"; @@ -54,10 +56,7 @@ const WebhookInfo: React.StatelessComponent = ({ /> - {intl.formatMessage({ - defaultMessage: "General Information", - description: "webhook general information" - })} + {intl.formatMessage(commonMessages.generalInformations)} = ({ description: "webhook specific information" })} - ({ label: service.name, value: service.id }))} - name="serviceAccount" - value={data.serviceAccount} - label={intl.formatMessage({ - defaultMessage: "Assign to Service Account" - })} - onChange={onChange} + InputProps={{ + autoComplete: "off" + }} /> ) => void; + onChange: (event: FormChange) => void; } -const WebhookStatus: React.StatelessComponent = ({ +const WebhookStatus: React.FC = ({ data, disabled, onChange diff --git a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx index dbb865240..fd32a6622 100644 --- a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx +++ b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx @@ -16,7 +16,7 @@ const props: WebhooksDetailsPageProps = { saveButtonBarState: "default", services: [] }; -storiesOf("Views / Services / Service details", module) +storiesOf("Views / Webhook / Webhook details", module) .addDecorator(Decorator) .add("default", () => ) .add("loading", () => ( diff --git a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx index 675256f50..7863e05bc 100644 --- a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx +++ b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx @@ -10,13 +10,13 @@ import { sectionNames } from "@saleor/intl"; import { maybe } from "@saleor/misc"; import { UserError } from "@saleor/types"; import { WebhookEventTypeEnum } from "@saleor/types/globalTypes"; +import WebhookEvents from "@saleor/webhooks/components/WebhookEvents"; +import WebhookInfo from "@saleor/webhooks/components/WebhookInfo"; +import WebhookStatus from "@saleor/webhooks/components/WebhookStatus"; +import { ServiceList_serviceAccounts_edges_node } from "@saleor/webhooks/types/ServiceList"; +import { Webhook_webhook } from "@saleor/webhooks/types/Webhook"; import React from "react"; import { useIntl } from "react-intl"; -import { ServiceList_serviceAccounts_edges_node } from "../../types/ServiceList"; -import { Webhook_webhook } from "../../types/Webhook"; -import WebhookEvents from "../WebhookEvents"; -import WebhookInfo from "../WebhookInfo"; -import WebhookStatus from "../WebhookStatus"; export interface FormData { id: string; @@ -54,11 +54,8 @@ const WebhooksDetailsPage: React.StatelessComponent< }) => { const intl = useIntl(); const initialForm: FormData = { - allEvents: maybe( - () => - maybe(() => webhook.events, [])[0].eventType === - WebhookEventTypeEnum.ALL_EVENTS, - false + allEvents: !!maybe(() => webhook.events, []).find( + event => event.eventType === WebhookEventTypeEnum.ALL_EVENTS ), events: maybe(() => webhook.events, []).map(event => event.eventType), id: maybe(() => webhook.id, null), @@ -70,57 +67,55 @@ const WebhooksDetailsPage: React.StatelessComponent< }; return (
- {({ data, errors, hasChanged, submit, change }) => { - return ( - - - {intl.formatMessage(sectionNames.plugins)} - - webhook.name, "...") - } - )} - /> - -
- services, [])} - errors={errors} - onChange={change} - /> -
-
- - - -
-
- -
- ); - }} + {({ data, errors, hasChanged, submit, change }) => ( + + + {intl.formatMessage(sectionNames.plugins)} + + webhook.name, "...") + } + )} + /> + +
+ services, [])} + errors={errors} + onChange={change} + /> +
+
+ + + +
+
+ +
+ )} ); }; diff --git a/src/webhooks/components/WebhooksList/WebhooksList.tsx b/src/webhooks/components/WebhooksList/WebhooksList.tsx index b861aa0da..6a41c087f 100644 --- a/src/webhooks/components/WebhooksList/WebhooksList.tsx +++ b/src/webhooks/components/WebhooksList/WebhooksList.tsx @@ -1,11 +1,6 @@ import Card from "@material-ui/core/Card"; import IconButton from "@material-ui/core/IconButton"; -import { - createStyles, - Theme, - withStyles, - WithStyles -} from "@material-ui/core/styles"; +import { Theme } 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"; @@ -14,6 +9,7 @@ import TableHead from "@material-ui/core/TableHead"; import TableRow from "@material-ui/core/TableRow"; import DeleteIcon from "@material-ui/icons/Delete"; import EditIcon from "@material-ui/icons/Edit"; +import makeStyles from "@material-ui/styles/makeStyles"; import React from "react"; import { useIntl } from "react-intl"; @@ -28,140 +24,133 @@ export interface WebhooksListProps extends ListProps { onRemove: (id: string) => void; } -const styles = (theme: Theme) => - createStyles({ - [theme.breakpoints.up("lg")]: { - colAction: { - "& svg": { - color: theme.palette.primary.main - }, - textAlign: "right" +const useStyles = makeStyles((theme: Theme) => ({ + [theme.breakpoints.up("lg")]: { + colAction: { + "& svg": { + color: theme.palette.primary.main }, - colActive: {}, - colName: {} + textAlign: "right" }, - colAction: {}, colActive: {}, - colName: {}, - link: { - cursor: "pointer" - } - }); + colName: {} + }, + colAction: {}, + colActive: {}, + colName: {}, + tableRow: { + cursor: "pointer" + } +})); const numberOfColumns = 4; -const WebhooksList = withStyles(styles, { name: "PluginList" })( - ({ - classes, - settings, - webhooks, - disabled, - onNextPage, - pageInfo, - onRowClick, - onRemove, - onUpdateListSettings, - onPreviousPage - }: WebhooksListProps & WithStyles) => { - const intl = useIntl(); - return ( - -
Name + > + Service Account + + Action +
- No service accounts found + No webhooks found
- - - - {intl.formatMessage({ - defaultMessage: "Name", - description: "webhook name" - })} - - - {intl.formatMessage({ - defaultMessage: "Service Account", - description: "webhook service account" - })} - - - {intl.formatMessage({ - defaultMessage: "Action", - description: "user action bar" - })} - - - - - - - - - - {renderCollection( - webhooks, - webhook => { - return ( - = ({ + settings, + webhooks, + disabled, + onNextPage, + pageInfo, + onRowClick, + onRemove, + onUpdateListSettings, + onPreviousPage +}) => { + const intl = useIntl(); + const classes = useStyles({}); + return ( + +
+ + + + {intl.formatMessage({ + defaultMessage: "Name", + description: "webhook name" + })} + + + {intl.formatMessage({ + defaultMessage: "Service Account", + description: "webhook service account" + })} + + + {intl.formatMessage({ + defaultMessage: "Action", + description: "user action bar" + })} + + + + + + + + + + {renderCollection( + webhooks, + webhook => ( + + + {maybe(() => webhook.name, )} + + + {maybe( + () => webhook.serviceAccount.name, + + )} + + + - - {maybe(() => webhook.name, )} - - - {maybe( - () => webhook.serviceAccount.name, - - )} - - - - - - onRemove(webhook.id)) - : undefined - } - > - - - - - ); - }, - () => ( - - - {intl.formatMessage({ - defaultMessage: "No webhooks found" - })} - - - ) - )} - -
- - ); - } -); + + + onRemove(webhook.id)) + : undefined + } + > + + + + + ), + () => ( + + + {intl.formatMessage({ + defaultMessage: "No webhooks found" + })} + + + ) + )} + +
+ + ); +}; WebhooksList.displayName = "WebhooksList"; export default WebhooksList; diff --git a/src/webhooks/components/WebhooksListPage/WebhookListPage.stories.tsx b/src/webhooks/components/WebhooksListPage/WebhookListPage.stories.tsx index 93d9eb879..cf4926d74 100644 --- a/src/webhooks/components/WebhooksListPage/WebhookListPage.stories.tsx +++ b/src/webhooks/components/WebhooksListPage/WebhookListPage.stories.tsx @@ -21,7 +21,7 @@ const props: WebhooksListPageProps = { webhooks: webhookList }; -storiesOf("Views / Services / Service list", module) +storiesOf("Views / Webhook / Webhook list", module) .addDecorator(Decorator) .add("default", () => ) .add("loading", () => ( diff --git a/src/webhooks/queries.ts b/src/webhooks/queries.ts index efdecc18f..f31a92524 100644 --- a/src/webhooks/queries.ts +++ b/src/webhooks/queries.ts @@ -1,18 +1,9 @@ import gql from "graphql-tag"; import { TypedQuery } from "../queries"; -import { ServiceList, ServiceListVariables } from "./types/ServiceList"; import { Webhook, WebhookVariables } from "./types/Webhook"; import { Webhooks, WebhooksVariables } from "./types/Webhooks"; -export const serviceFragment = gql` - fragment ServiceFragment on ServiceAccount { - id - name - isActive - } -`; - export const webhooksFragment = gql` fragment WebhookFragment on Webhook { id @@ -59,37 +50,9 @@ export const TypedWebhooksListQuery = TypedQuery( webhooksList ); -const serviceList = gql` - ${serviceFragment} - query ServiceList($first: Int, $after: String, $last: Int, $before: String) { - serviceAccounts( - first: $first - after: $after - before: $before - last: $last - ) { - edges { - node { - ...ServiceFragment - } - } - pageInfo { - hasPreviousPage - hasNextPage - startCursor - endCursor - } - } - } -`; -export const TypedServiceListQuery = TypedQuery< - ServiceList, - ServiceListVariables ->(serviceList); - const webhooksDetails = gql` ${webhooksFragment} - query Webhook($id: ID!) { + query WebhookDetails($id: ID!) { webhook(id: $id) { ...WebhookFragment } diff --git a/src/webhooks/types/ServiceList.ts b/src/webhooks/types/ServiceList.ts index 0d1b614fe..fe971e15d 100644 --- a/src/webhooks/types/ServiceList.ts +++ b/src/webhooks/types/ServiceList.ts @@ -2,8 +2,6 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ServiceAccountFilterInput } from "./../../types/globalTypes"; - // ==================================================== // GraphQL query operation: ServiceList // ==================================================== @@ -43,5 +41,4 @@ export interface ServiceListVariables { after?: string | null; last?: number | null; before?: string | null; - filter?: ServiceAccountFilterInput | null; } diff --git a/src/webhooks/views/WebhooksCreate.tsx b/src/webhooks/views/WebhooksCreate.tsx index 2aaf021cb..fc58d5dff 100644 --- a/src/webhooks/views/WebhooksCreate.tsx +++ b/src/webhooks/views/WebhooksCreate.tsx @@ -10,7 +10,6 @@ import { useIntl } from "react-intl"; import { getMutationState, maybe } from "../../misc"; import WebhookCreatePage, { FormData } from "../components/WebhookCreatePage"; import { TypedWebhookCreate } from "../mutations"; -import { TypedServiceListQuery } from "../queries"; import { webhooksListUrl, WebhooksListUrlQueryParams, @@ -43,7 +42,7 @@ export const WebhooksCreate: React.StatelessComponent< return ( {(WebhookCreate, webhookCreateOpts) => { - const handleSubmit = (data: FormData) => { + const handleSubmit = (data: FormData) => WebhookCreate({ variables: { input: { @@ -58,7 +57,6 @@ export const WebhooksCreate: React.StatelessComponent< } } }); - }; const formTransitionState = getMutationState( webhookCreateOpts.called, @@ -67,33 +65,27 @@ export const WebhooksCreate: React.StatelessComponent< ); return ( - - {({ data }) => { - return ( - <> - - webhookCreateOpts.data.webhookCreate.errors, - [] - )} - services={maybe(() => - data.serviceAccounts.edges.map(edge => edge.node) - )} - onBack={handleBack} - onSubmit={handleSubmit} - saveButtonBarState={formTransitionState} - /> - - ); - }} - + <> + + webhookCreateOpts.data.webhookCreate.errors, + [] + )} + services={maybe(() => + data.serviceAccounts.edges.map(edge => edge.node) + )} + onBack={handleBack} + onSubmit={handleSubmit} + saveButtonBarState={formTransitionState} + /> + ); }} diff --git a/src/webhooks/views/WebhooksDetails.tsx b/src/webhooks/views/WebhooksDetails.tsx index 94f75d351..ed93db46b 100644 --- a/src/webhooks/views/WebhooksDetails.tsx +++ b/src/webhooks/views/WebhooksDetails.tsx @@ -5,13 +5,14 @@ import { commonMessages } from "@saleor/intl"; import { WebhookEventTypeEnum } from "@saleor/types/globalTypes"; import WebhookDeleteDialog from "@saleor/webhooks/components/WebhookDeleteDialog"; import { WebhookDelete } from "@saleor/webhooks/types/WebhookDelete"; +import { WebhookUpdate } from "@saleor/webhooks/types/WebhookUpdate"; import React from "react"; import { useIntl } from "react-intl"; import { getMutationState, maybe } from "../../misc"; import WebhooksDetailsPage from "../components/WebhooksDetailsPage"; import { TypedWebhookDelete, TypedWebhookUpdate } from "../mutations"; -import { TypedServiceListQuery, TypedWebhooksDetailsQuery } from "../queries"; +import { TypedWebhooksDetailsQuery } from "../queries"; import { webhooksListUrl, WebhooksListUrlQueryParams, @@ -59,8 +60,17 @@ export const WebhooksDetails: React.StatelessComponent< } }; + const onWebhookUpdate = (data: WebhookUpdate) => { + if (data.webhookUpdate.errors.length === 0) { + notify({ + text: intl.formatMessage(commonMessages.savedChanges) + }); + navigate(webhooksUrl(data.webhookUpdate.webhook.id)); + } + }; + return ( - + {(webhookUpdate, webhookUpdateOpts) => ( {(webhookDelete, webhookDeleteOpts) => ( @@ -91,53 +101,49 @@ export const WebhooksDetails: React.StatelessComponent< ); return ( - - {({ data }) => ( - <> - WebhookDetails.data.webhook.name)} - /> - WebhookDetails.data.webhook)} - services={maybe(() => - data.serviceAccounts.edges.map(edge => edge.node) - )} - onBack={() => navigate(webhooksListUrl())} - onDelete={() => openModal("remove")} - onSubmit={data => { - webhookUpdate({ - variables: { - id, - input: { - events: data.allEvents - ? [WebhookEventTypeEnum.ALL_EVENTS] - : data.events, - isActive: data.isActive, - name: data.name, - secretKey: data.secretKey, - serviceAccount: data.serviceAccount, - targetUrl: data.targetUrl - } - } - }); - }} - /> - WebhookDetails.data.webhook.name, - "..." - )} - onClose={closeModal} - onConfirm={handleRemoveConfirm} - open={params.action === "remove"} - /> - - )} - + <> + WebhookDetails.data.webhook.name)} + /> + WebhookDetails.data.webhook)} + services={maybe(() => + data.serviceAccounts.edges.map(edge => edge.node) + )} + onBack={() => navigate(webhooksListUrl())} + onDelete={() => openModal("remove")} + onSubmit={data => { + webhookUpdate({ + variables: { + id, + input: { + events: data.allEvents + ? [WebhookEventTypeEnum.ALL_EVENTS] + : data.events, + isActive: data.isActive, + name: data.name, + secretKey: data.secretKey, + serviceAccount: data.serviceAccount, + targetUrl: data.targetUrl + } + } + }); + }} + /> + WebhookDetails.data.webhook.name, + "..." + )} + onClose={closeModal} + onConfirm={handleRemoveConfirm} + open={params.action === "remove"} + /> + ); }} From 28bc919e47e701920c589b1b524bfb2a9223c85d Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Mon, 14 Oct 2019 16:41:41 +0200 Subject: [PATCH 13/38] Add serviceAccount search and autocomplete input --- src/containers/SearchServiceAccount/index.tsx | 24 +++ .../types/searchServiceAccount.ts | 33 ++++ src/types/globalTypes.ts | 5 + .../WebhookCreatePage/WebhookCreatePage.tsx | 117 ++++++++----- .../WebhooksCreatePage.stories.tsx | 1 + .../WebhookEvents/WebhookEvents.tsx | 54 +++--- .../components/WebhookInfo/WebhookInfo.tsx | 29 ++-- .../WebhookStatus/WebhookStatus.tsx | 8 +- .../WebhooksDetailsPage.stories.tsx | 11 +- .../WebhooksDetailsPage.tsx | 133 +++++++++------ src/webhooks/types/WebhookDetails.ts | 39 +++++ src/webhooks/views/WebhooksCreate.tsx | 104 ++++++------ src/webhooks/views/WebhooksDetails.tsx | 160 +++++++++--------- 13 files changed, 457 insertions(+), 261 deletions(-) create mode 100644 src/containers/SearchServiceAccount/index.tsx create mode 100644 src/containers/SearchServiceAccount/types/searchServiceAccount.ts create mode 100644 src/webhooks/types/WebhookDetails.ts diff --git a/src/containers/SearchServiceAccount/index.tsx b/src/containers/SearchServiceAccount/index.tsx new file mode 100644 index 000000000..7b59b27ec --- /dev/null +++ b/src/containers/SearchServiceAccount/index.tsx @@ -0,0 +1,24 @@ +import gql from "graphql-tag"; + +import BaseSearch from "../BaseSearch"; +import { + SearchServiceAccount, + SearchServiceAccountVariables +} from "./types/SearchServiceAccount"; + +export const searchServiceAccount = gql` + query SearchServiceAccount($after: String, $first: Int!, $query: String!) { + serviceAccounts(after: $after, first: $first, filter: { search: $query }) { + edges { + node { + id + name + } + } + } + } +`; + +export default BaseSearch( + searchServiceAccount +); diff --git a/src/containers/SearchServiceAccount/types/searchServiceAccount.ts b/src/containers/SearchServiceAccount/types/searchServiceAccount.ts new file mode 100644 index 000000000..fbe54676e --- /dev/null +++ b/src/containers/SearchServiceAccount/types/searchServiceAccount.ts @@ -0,0 +1,33 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: SearchServiceAccount +// ==================================================== + +export interface SearchServiceAccount_serviceAccounts_edges_node { + __typename: "ServiceAccount"; + id: string; + name: string | null; +} + +export interface SearchServiceAccount_serviceAccounts_edges { + __typename: "ServiceAccountCountableEdge"; + node: SearchServiceAccount_serviceAccounts_edges_node; +} + +export interface SearchServiceAccount_serviceAccounts { + __typename: "ServiceAccountCountableConnection"; + edges: SearchServiceAccount_serviceAccounts_edges[]; +} + +export interface SearchServiceAccount { + serviceAccounts: SearchServiceAccount_serviceAccounts | null; +} + +export interface SearchServiceAccountVariables { + after?: string | null; + first: number; + query: string; +} diff --git a/src/types/globalTypes.ts b/src/types/globalTypes.ts index d39c8d65f..d3754b168 100644 --- a/src/types/globalTypes.ts +++ b/src/types/globalTypes.ts @@ -662,6 +662,11 @@ export interface SeoInput { description?: string | null; } +export interface ServiceAccountFilterInput { + search?: string | null; + isActive?: boolean | null; +} + export interface ServiceAccountInput { name?: string | null; isActive?: boolean | null; diff --git a/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx b/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx index af32e669d..2c5c993fe 100644 --- a/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx +++ b/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx @@ -6,10 +6,12 @@ import FormSpacer from "@saleor/components/FormSpacer"; import Grid from "@saleor/components/Grid"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import useStateFromProps from "@saleor/hooks/useStateFromProps"; import { sectionNames } from "@saleor/intl"; import { maybe } from "@saleor/misc"; import { UserError } from "@saleor/types"; import { WebhookEventTypeEnum } from "@saleor/types/globalTypes"; +import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; import WebhookEvents from "@saleor/webhooks/components/WebhookEvents"; import WebhookInfo from "@saleor/webhooks/components/WebhookInfo"; import WebhookStatus from "@saleor/webhooks/components/WebhookStatus"; @@ -30,8 +32,12 @@ export interface FormData { export interface WebhookCreatePageProps { disabled: boolean; errors: UserError[]; - services: ServiceList_serviceAccounts_edges_node[]; + services?: Array<{ + id: string; + name: string; + }>; saveButtonBarState: ConfirmButtonTransitionState; + fetchServiceAccount: (data: string) => void; onBack: () => void; onSubmit: (data: FormData) => void; } @@ -41,6 +47,7 @@ const WebhookCreatePage: React.StatelessComponent = ({ errors, saveButtonBarState, services, + fetchServiceAccount, onBack, onSubmit }) => { @@ -55,52 +62,74 @@ const WebhookCreatePage: React.StatelessComponent = ({ serviceAccount: "", targetUrl: "" }; + const [ + selectedServiceAcccounts, + setSelectedServiceAcccounts + ] = useStateFromProps(""); + const servicesChoiceList = maybe( + () => + services.map(node => ({ + label: node.name, + value: node.id + })), + [] + ); return (
- {({ data, errors, hasChanged, submit, change }) => ( - - - {intl.formatMessage(sectionNames.plugins)} - - - -
- services, [])} - errors={errors} - onChange={change} - /> -
-
- - - -
-
- -
- )} + {({ data, errors, hasChanged, submit, change }) => { + const handleServiceSelect = createSingleAutocompleteSelectHandler( + change, + setSelectedServiceAcccounts, + servicesChoiceList + ); + return ( + + + {intl.formatMessage(sectionNames.webhooks)} + + + +
+ +
+
+ + + +
+
+ +
+ ); + }}
); }; diff --git a/src/webhooks/components/WebhookCreatePage/WebhooksCreatePage.stories.tsx b/src/webhooks/components/WebhookCreatePage/WebhooksCreatePage.stories.tsx index 114b584cb..004b7dab5 100644 --- a/src/webhooks/components/WebhookCreatePage/WebhooksCreatePage.stories.tsx +++ b/src/webhooks/components/WebhookCreatePage/WebhooksCreatePage.stories.tsx @@ -8,6 +8,7 @@ import WebhookCreatePage, { WebhookCreatePageProps } from "./WebhookCreatePage"; const props: WebhookCreatePageProps = { disabled: false, errors: [], + fetchServiceAccount: () => undefined, onBack: () => undefined, onSubmit: () => undefined, saveButtonBarState: "default", diff --git a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx index 589f30bf2..8c42d96cc 100644 --- a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx +++ b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx @@ -15,7 +15,7 @@ interface WebhookEventsProps { events: string[]; }; disabled: boolean; - onChange: (event: React.ChangeEvent, cb?: () => void) => void; + onChange: (event: ChangeEvent, cb?: () => void) => void; } const WebhookEvents: React.StatelessComponent = ({ @@ -26,13 +26,18 @@ const WebhookEvents: React.StatelessComponent = ({ const intl = useIntl(); const eventsEnum = Object.values(WebhookEventTypeEnum); - const handleAllEventsChange = () => - onChange({ - target: { - name: "events", - value: WebhookEventTypeEnum.ALL_EVENTS - } - } as any); + const handleAllEventsChange = (event: ChangeEvent) => + onChange(event, () => + onChange({ + target: { + name: "events", + value: event.target.value + ? WebhookEventTypeEnum.ALL_EVENTS + : data.events + } + } as any) + ); + const handleEventsChange = (event: ChangeEvent) => { onChange({ target: { @@ -70,21 +75,24 @@ const WebhookEvents: React.StatelessComponent = ({ name="allEvents" onChange={handleAllEventsChange} /> -
- {!data.allEvents && - eventsEnum.slice(1).map(event => { - return ( -
- -
- ); - })} + {!data.allEvents && ( + <> +
+ {eventsEnum.slice(1).map(event => { + return ( +
+ +
+ ); + })} + + )} ); diff --git a/src/webhooks/components/WebhookInfo/WebhookInfo.tsx b/src/webhooks/components/WebhookInfo/WebhookInfo.tsx index 49a732d03..ec2c92118 100644 --- a/src/webhooks/components/WebhookInfo/WebhookInfo.tsx +++ b/src/webhooks/components/WebhookInfo/WebhookInfo.tsx @@ -9,20 +9,24 @@ import { useIntl } from "react-intl"; import CardTitle from "@saleor/components/CardTitle"; import FormSpacer from "@saleor/components/FormSpacer"; import Hr from "@saleor/components/Hr"; -import SingleSelectField from "@saleor/components/SingleSelectField"; -import { SingleAutocompleteSelectField } from "@saleor/components/SingleAutocompleteSelectField"; +import { + SingleAutocompleteChoiceType, + SingleAutocompleteSelectField +} from "@saleor/components/SingleAutocompleteSelectField"; +import { ChangeEvent } from "@saleor/hooks/useForm"; import { commonMessages } from "@saleor/intl"; import { FormErrors } from "@saleor/types"; import { FormData } from "../WebhooksDetailsPage"; -import { ServiceList_serviceAccounts_edges_node } from "../../types/ServiceList"; - interface WebhookInfoProps { data: FormData; disabled: boolean; - services: ServiceList_serviceAccounts_edges_node[]; + serviceDisplayValue: string; + services: SingleAutocompleteChoiceType[]; errors: FormErrors<"name" | "targetUrl" | "secretKey">; onChange: (event: React.ChangeEvent) => void; + serviceOnChange: (event: ChangeEvent) => void; + fetchServiceAccount: (data: string) => void; } const useStyles = makeStyles(() => ({ @@ -40,8 +44,11 @@ const WebhookInfo: React.StatelessComponent = ({ data, disabled, services, + serviceDisplayValue, + fetchServiceAccount, errors, - onChange + onChange, + serviceOnChange }) => { const classes = useStyles({}); const intl = useIntl(); @@ -82,17 +89,15 @@ const WebhookInfo: React.StatelessComponent = ({ ({ - label: service.name, - value: service.id - }))} + choices={services} + fetchChoices={fetchServiceAccount} InputProps={{ autoComplete: "off" }} diff --git a/src/webhooks/components/WebhookStatus/WebhookStatus.tsx b/src/webhooks/components/WebhookStatus/WebhookStatus.tsx index cc54ec6e1..ffbead75f 100644 --- a/src/webhooks/components/WebhookStatus/WebhookStatus.tsx +++ b/src/webhooks/components/WebhookStatus/WebhookStatus.tsx @@ -3,16 +3,16 @@ import CardContent from "@material-ui/core/CardContent"; import Typography from "@material-ui/core/Typography"; import CardTitle from "@saleor/components/CardTitle"; import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; -import { FormChange } from "@saleor/hooks/useForm"; +import { ChangeEvent } from "@saleor/hooks/useForm"; import React from "react"; import { useIntl } from "react-intl"; import { FormData } from "../WebhooksDetailsPage"; interface WebhookStatusProps { - data: FormData; + data: boolean; disabled: boolean; - onChange: (event: FormChange) => void; + onChange: (event: ChangeEvent, cb?: () => void) => void; } const WebhookStatus: React.FC = ({ @@ -43,7 +43,7 @@ const WebhookStatus: React.FC = ({ defaultMessage: "Webhook is active", description: "webhooks active" })} - checked={data.isActive} + checked={data} onChange={onChange} disabled={disabled} /> diff --git a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx index fd32a6622..9dc02a58c 100644 --- a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx +++ b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx @@ -10,17 +10,24 @@ import WebhooksDetailsPage, { const props: WebhooksDetailsPageProps = { disabled: false, errors: [], + fetchServiceAccount: () => undefined, onBack: () => undefined, onDelete: () => undefined, onSubmit: () => undefined, saveButtonBarState: "default", - services: [] + services: [], + webhook: null }; storiesOf("Views / Webhook / Webhook details", module) .addDecorator(Decorator) .add("default", () => ) .add("loading", () => ( - + )) .add("form errors", () => ( ; saveButtonBarState: ConfirmButtonTransitionState; onBack: () => void; onDelete: () => void; + fetchServiceAccount: (data: string) => void; onSubmit: (data: FormData) => void; } @@ -48,6 +54,7 @@ const WebhooksDetailsPage: React.StatelessComponent< webhook, saveButtonBarState, services, + fetchServiceAccount, onBack, onDelete, onSubmit @@ -62,60 +69,82 @@ const WebhooksDetailsPage: React.StatelessComponent< isActive: maybe(() => webhook.isActive, false), name: maybe(() => webhook.name, ""), secretKey: maybe(() => webhook.secretKey, ""), - serviceAccount: maybe(() => webhook.serviceAccount.id, ""), + serviceAccount: maybe(() => webhook.serviceAccount.name, ""), targetUrl: maybe(() => webhook.targetUrl, "") }; + const [ + selectedServiceAcccounts, + setSelectedServiceAcccounts + ] = useStateFromProps(maybe(() => webhook.serviceAccount.name, "")); + const servicesChoiceList = maybe( + () => + services.map(node => ({ + label: node.name, + value: node.id + })), + [] + ); return (
- {({ data, errors, hasChanged, submit, change }) => ( - - - {intl.formatMessage(sectionNames.plugins)} - - webhook.name, "...") - } - )} - /> - -
- services, [])} - errors={errors} - onChange={change} - /> -
-
- - - -
-
- -
- )} + {({ data, errors, hasChanged, submit, change }) => { + const handleServiceSelect = createSingleAutocompleteSelectHandler( + change, + setSelectedServiceAcccounts, + servicesChoiceList + ); + return ( + + + {intl.formatMessage(sectionNames.webhooks)} + + webhook.name, "...") + } + )} + /> + +
+ +
+
+ + + +
+
+ +
+ ); + }}
); }; diff --git a/src/webhooks/types/WebhookDetails.ts b/src/webhooks/types/WebhookDetails.ts new file mode 100644 index 000000000..657d47ca0 --- /dev/null +++ b/src/webhooks/types/WebhookDetails.ts @@ -0,0 +1,39 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { WebhookEventTypeEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: WebhookDetails +// ==================================================== + +export interface WebhookDetails_webhook_events { + __typename: "WebhookEvent"; + eventType: WebhookEventTypeEnum | null; +} + +export interface WebhookDetails_webhook_serviceAccount { + __typename: "ServiceAccount"; + id: string; + name: string | null; +} + +export interface WebhookDetails_webhook { + __typename: "Webhook"; + id: string; + name: string | null; + events: (WebhookDetails_webhook_events | null)[] | null; + isActive: boolean; + secretKey: string | null; + targetUrl: string; + serviceAccount: WebhookDetails_webhook_serviceAccount; +} + +export interface WebhookDetails { + webhook: WebhookDetails_webhook | null; +} + +export interface WebhookDetailsVariables { + id: string; +} diff --git a/src/webhooks/views/WebhooksCreate.tsx b/src/webhooks/views/WebhooksCreate.tsx index fc58d5dff..3b6628ec5 100644 --- a/src/webhooks/views/WebhooksCreate.tsx +++ b/src/webhooks/views/WebhooksCreate.tsx @@ -1,4 +1,5 @@ import { WindowTitle } from "@saleor/components/WindowTitle"; +import SearchServiceAccount from "@saleor/containers/SearchServiceAccount"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; import { commonMessages } from "@saleor/intl"; @@ -6,7 +7,7 @@ import { WebhookEventTypeEnum } from "@saleor/types/globalTypes"; import { WebhookCreate as WebhookCreateData } from "@saleor/webhooks/types/WebhookCreate"; import React from "react"; import { useIntl } from "react-intl"; - +import { DEFAULT_INITIAL_SEARCH_DATA } from "../../config"; import { getMutationState, maybe } from "../../misc"; import WebhookCreatePage, { FormData } from "../components/WebhookCreatePage"; import { TypedWebhookCreate } from "../mutations"; @@ -40,55 +41,62 @@ export const WebhooksCreate: React.StatelessComponent< const handleBack = () => navigate(webhooksListUrl()); return ( - - {(WebhookCreate, webhookCreateOpts) => { - const handleSubmit = (data: FormData) => - WebhookCreate({ - variables: { - input: { - events: data.allEvents - ? [WebhookEventTypeEnum.ALL_EVENTS] - : data.events, - isActive: data.isActive, - name: data.name, - secretKey: data.secretKey, - serviceAccount: data.serviceAccount, - targetUrl: data.targetUrl - } - } - }); + + {({ search: searchServiceAccount, result: searchServiceAccountOpt }) => ( + + {(WebhookCreate, webhookCreateOpts) => { + const handleSubmit = (data: FormData) => + WebhookCreate({ + variables: { + input: { + events: data.allEvents + ? [WebhookEventTypeEnum.ALL_EVENTS] + : data.events, + isActive: data.isActive, + name: data.name, + secretKey: data.secretKey, + serviceAccount: data.serviceAccount, + targetUrl: data.targetUrl + } + } + }); - const formTransitionState = getMutationState( - webhookCreateOpts.called, - webhookCreateOpts.loading, - maybe(() => webhookCreateOpts.data.webhookCreate.errors) - ); + const formTransitionState = getMutationState( + webhookCreateOpts.called, + webhookCreateOpts.loading, + maybe(() => webhookCreateOpts.data.webhookCreate.errors) + ); - return ( - <> - - webhookCreateOpts.data.webhookCreate.errors, - [] - )} - services={maybe(() => - data.serviceAccounts.edges.map(edge => edge.node) - )} - onBack={handleBack} - onSubmit={handleSubmit} - saveButtonBarState={formTransitionState} - /> - - ); - }} - + return ( + <> + + webhookCreateOpts.data.webhookCreate.errors, + [] + )} + fetchServiceAccount={searchServiceAccount} + services={maybe(() => + searchServiceAccountOpt.data.serviceAccounts.edges.map( + edge => edge.node + ) + )} + onBack={handleBack} + onSubmit={handleSubmit} + saveButtonBarState={formTransitionState} + /> + + ); + }} + + )} + ); }; WebhooksCreate.displayName = "WebhooksCreate"; diff --git a/src/webhooks/views/WebhooksDetails.tsx b/src/webhooks/views/WebhooksDetails.tsx index ed93db46b..f6511ea98 100644 --- a/src/webhooks/views/WebhooksDetails.tsx +++ b/src/webhooks/views/WebhooksDetails.tsx @@ -1,4 +1,5 @@ import { WindowTitle } from "@saleor/components/WindowTitle"; +import SearchServiceAccount from "@saleor/containers/SearchServiceAccount"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; import { commonMessages } from "@saleor/intl"; @@ -8,7 +9,7 @@ import { WebhookDelete } from "@saleor/webhooks/types/WebhookDelete"; import { WebhookUpdate } from "@saleor/webhooks/types/WebhookUpdate"; import React from "react"; import { useIntl } from "react-intl"; - +import { DEFAULT_INITIAL_SEARCH_DATA } from "../../config"; import { getMutationState, maybe } from "../../misc"; import WebhooksDetailsPage from "../components/WebhooksDetailsPage"; import { TypedWebhookDelete, TypedWebhookUpdate } from "../mutations"; @@ -70,87 +71,94 @@ export const WebhooksDetails: React.StatelessComponent< }; return ( - - {(webhookUpdate, webhookUpdateOpts) => ( - - {(webhookDelete, webhookDeleteOpts) => ( - - {WebhookDetails => { - const formTransitionState = getMutationState( - webhookUpdateOpts.called, - webhookUpdateOpts.loading, - maybe(() => webhookUpdateOpts.data.webhookUpdate.errors) - ); + + {({ search: searchServiceAccount, result: searchServiceAccountOpt }) => ( + + {(webhookUpdate, webhookUpdateOpts) => ( + + {(webhookDelete, webhookDeleteOpts) => ( + + {WebhookDetails => { + const formTransitionState = getMutationState( + webhookUpdateOpts.called, + webhookUpdateOpts.loading, + maybe(() => webhookUpdateOpts.data.webhookUpdate.errors) + ); - const handleRemoveConfirm = () => - webhookDelete({ - variables: { - id - } - }); + const handleRemoveConfirm = () => + webhookDelete({ + variables: { + id + } + }); - const formErrors = maybe( - () => webhookUpdateOpts.data.webhookUpdate.errors, - [] - ); + const formErrors = maybe( + () => webhookUpdateOpts.data.webhookUpdate.errors, + [] + ); - const deleteTransitionState = getMutationState( - webhookDeleteOpts.called, - webhookDeleteOpts.loading, - maybe(() => webhookDeleteOpts.data.webhookDelete.errors) - ); + const deleteTransitionState = getMutationState( + webhookDeleteOpts.called, + webhookDeleteOpts.loading, + maybe(() => webhookDeleteOpts.data.webhookDelete.errors) + ); - return ( - <> - WebhookDetails.data.webhook.name)} - /> - WebhookDetails.data.webhook)} - services={maybe(() => - data.serviceAccounts.edges.map(edge => edge.node) - )} - onBack={() => navigate(webhooksListUrl())} - onDelete={() => openModal("remove")} - onSubmit={data => { - webhookUpdate({ - variables: { - id, - input: { - events: data.allEvents - ? [WebhookEventTypeEnum.ALL_EVENTS] - : data.events, - isActive: data.isActive, - name: data.name, - secretKey: data.secretKey, - serviceAccount: data.serviceAccount, - targetUrl: data.targetUrl - } - } - }); - }} - /> - WebhookDetails.data.webhook.name, - "..." - )} - onClose={closeModal} - onConfirm={handleRemoveConfirm} - open={params.action === "remove"} - /> - - ); - }} - + return ( + <> + WebhookDetails.data.webhook.name)} + /> + WebhookDetails.data.webhook)} + fetchServiceAccount={searchServiceAccount} + services={maybe(() => + searchServiceAccountOpt.data.serviceAccounts.edges.map( + edge => edge.node + ) + )} + onBack={() => navigate(webhooksListUrl())} + onDelete={() => openModal("remove")} + onSubmit={data => { + webhookUpdate({ + variables: { + id, + input: { + events: data.allEvents + ? [WebhookEventTypeEnum.ALL_EVENTS] + : data.events, + isActive: data.isActive, + name: data.name, + secretKey: data.secretKey, + serviceAccount: data.serviceAccount, + targetUrl: data.targetUrl + } + } + }); + }} + /> + WebhookDetails.data.webhook.name, + "..." + )} + onClose={closeModal} + onConfirm={handleRemoveConfirm} + open={params.action === "remove"} + /> + + ); + }} + + )} + )} -
+
)} -
+ ); }; WebhooksDetails.displayName = "WebhooksDetails"; From fd39ab1b85a9439f3dce5074a5136cb07d800645 Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Tue, 15 Oct 2019 12:06:19 +0200 Subject: [PATCH 14/38] Add Webhooks list search and fix events any event --- schema.graphql | 9 +- src/types/globalTypes.ts | 7 +- .../WebhookEvents/WebhookEvents.tsx | 2 +- .../WebhooksDetailsPage.tsx | 2 +- .../WebhooksListPage/WebhooksListPage.tsx | 59 +++++++----- src/webhooks/fixtures.ts | 6 -- src/webhooks/index.tsx | 2 +- src/webhooks/queries.ts | 26 ++++-- src/webhooks/types/WebhookCreate.ts | 10 +- src/webhooks/types/WebhookDetails.ts | 14 +-- src/webhooks/types/WebhookFragment.ts | 10 -- src/webhooks/types/WebhookUpdate.ts | 10 +- src/webhooks/types/Webhooks.ts | 11 +-- src/webhooks/types/WebhooksDetailsFragment.ts | 10 -- src/webhooks/urls.ts | 19 +++- src/webhooks/views/WebhooksCreate.tsx | 2 +- src/webhooks/views/WebhooksDetails.tsx | 2 +- src/webhooks/views/WebhooksList.tsx | 92 ++++++++++++++++++- src/webhooks/views/filter.ts | 28 ++++++ 19 files changed, 218 insertions(+), 103 deletions(-) create mode 100644 src/webhooks/views/filter.ts diff --git a/schema.graphql b/schema.graphql index 4dbc36710..4efcdaaa4 100644 --- a/schema.graphql +++ b/schema.graphql @@ -3327,7 +3327,7 @@ type ProductVariantUpdatePrivateMeta { type Query { webhook(id: ID!): Webhook - webhooks(before: String, after: String, first: Int, last: Int): WebhookCountableConnection + webhooks(filter: WebhookFilterInput, before: String, after: String, first: Int, last: Int): WebhookCountableConnection translations(kind: TranslatableKinds!, before: String, after: String, first: Int, last: Int): TranslatableItemConnection shop: Shop shippingZone(id: ID!): ShippingZone @@ -4319,7 +4319,7 @@ type WebhookEvent { } enum WebhookEventTypeEnum { - ALL_EVENTS + ANY_EVENTS ORDER_CREATED ORDER_FULLY_PAID ORDER_UPDATED @@ -4328,6 +4328,11 @@ enum WebhookEventTypeEnum { PRODUCT_CREATED } +input WebhookFilterInput { + search: String + isActive: Boolean +} + type WebhookUpdate { errors: [Error!] webhook: Webhook diff --git a/src/types/globalTypes.ts b/src/types/globalTypes.ts index d3754b168..509193af8 100644 --- a/src/types/globalTypes.ts +++ b/src/types/globalTypes.ts @@ -273,7 +273,7 @@ export enum VoucherTypeEnum { } export enum WebhookEventTypeEnum { - ALL_EVENTS = "ALL_EVENTS", + ANY_EVENTS = "ANY_EVENTS", CUSTOMER_CREATED = "CUSTOMER_CREATED", ORDER_CANCELLED = "ORDER_CANCELLED", ORDER_CREATED = "ORDER_CREATED", @@ -794,6 +794,11 @@ export interface WebhookCreateInput { secretKey?: string | null; } +export interface WebhookFilterInput { + search?: string | null; + isActive?: boolean | null; +} + export interface WebhookUpdateInput { name?: string | null; targetUrl?: string | null; diff --git a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx index 8c42d96cc..3b1d3319b 100644 --- a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx +++ b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx @@ -32,7 +32,7 @@ const WebhookEvents: React.StatelessComponent = ({ target: { name: "events", value: event.target.value - ? WebhookEventTypeEnum.ALL_EVENTS + ? WebhookEventTypeEnum.ANY_EVENTS : data.events } } as any) diff --git a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx index ac66d82a5..8f03f9142 100644 --- a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx +++ b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx @@ -62,7 +62,7 @@ const WebhooksDetailsPage: React.StatelessComponent< const intl = useIntl(); const initialForm: FormData = { allEvents: !!maybe(() => webhook.events, []).find( - event => event.eventType === WebhookEventTypeEnum.ALL_EVENTS + event => event.eventType === WebhookEventTypeEnum.ANY_EVENTS ), events: maybe(() => webhook.events, []).map(event => event.eventType), id: maybe(() => webhook.id, null), diff --git a/src/webhooks/components/WebhooksListPage/WebhooksListPage.tsx b/src/webhooks/components/WebhooksListPage/WebhooksListPage.tsx index 27a096ece..f184c04fb 100644 --- a/src/webhooks/components/WebhooksListPage/WebhooksListPage.tsx +++ b/src/webhooks/components/WebhooksListPage/WebhooksListPage.tsx @@ -1,33 +1,39 @@ import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; import AppHeader from "@saleor/components/AppHeader"; import Container from "@saleor/components/Container"; import PageHeader from "@saleor/components/PageHeader"; +import SearchBar from "@saleor/components/SearchBar"; import { sectionNames } from "@saleor/intl"; -import { PageListProps } from "@saleor/types"; +import { PageListProps, SearchPageProps, TabPageProps } from "@saleor/types"; import { Webhooks_webhooks_edges_node } from "../../types/Webhooks"; import WebhooksList from "../WebhooksList/WebhooksList"; -export interface WebhooksListPageProps extends PageListProps { +export interface WebhooksListPageProps + extends PageListProps, + SearchPageProps, + TabPageProps { webhooks: Webhooks_webhooks_edges_node[]; onBack: () => void; onRemove: (id: string) => void; } const WebhooksListPage: React.StatelessComponent = ({ - disabled, - settings, + currentTab, + initialSearch, onAdd, + onAll, onBack, - onNextPage, - onPreviousPage, - onRowClick, - onRemove, - onUpdateListSettings, - pageInfo, - webhooks + onSearchChange, + onTabChange, + onTabDelete, + onTabSave, + tabs, + webhooks, + ...listProps }) => { const intl = useIntl(); return ( @@ -43,17 +49,26 @@ const WebhooksListPage: React.StatelessComponent = ({ /> - + + + + ); }; diff --git a/src/webhooks/fixtures.ts b/src/webhooks/fixtures.ts index c92090dd4..4149bdb9c 100644 --- a/src/webhooks/fixtures.ts +++ b/src/webhooks/fixtures.ts @@ -19,31 +19,25 @@ export const services: ServiceList_serviceAccounts_edges_node[] = [ export const webhookList: Webhooks_webhooks_edges_node[] = [ { __typename: "Webhook", - events: [], id: "Jzx123sEt==", isActive: true, name: "Webhook Test", - secretKey: "dsdasdasd_asdas", serviceAccount: { __typename: "ServiceAccount", id: "Jzx123sEt==", name: "Test Account" }, - targetUrl: "http://www.getsaleor.com" }, { __typename: "Webhook", - events: [], id: "Jzx123sEt==", isActive: true, name: "Webhook Test 2", - secretKey: "zxczx_asdas", serviceAccount: { __typename: "ServiceAccount", id: "Jzx1ss23sEt==", name: "Test Account 2" }, - targetUrl: "http://www.getsaleor.com" } ]; export const webhook: Webhook_webhook = { diff --git a/src/webhooks/index.tsx b/src/webhooks/index.tsx index 28fee49ad..ac0497816 100644 --- a/src/webhooks/index.tsx +++ b/src/webhooks/index.tsx @@ -38,7 +38,7 @@ const Component = () => { const intl = useIntl(); return ( <> - + diff --git a/src/webhooks/queries.ts b/src/webhooks/queries.ts index f31a92524..bee136ee3 100644 --- a/src/webhooks/queries.ts +++ b/src/webhooks/queries.ts @@ -8,12 +8,7 @@ export const webhooksFragment = gql` fragment WebhookFragment on Webhook { id name - events { - eventType - } isActive - secretKey - targetUrl serviceAccount { id name @@ -30,8 +25,20 @@ export const webhooksDetailsFragment = gql` const webhooksList = gql` ${webhooksFragment} - query Webhooks($first: Int, $after: String, $last: Int, $before: String) { - webhooks(before: $before, after: $after, first: $first, last: $last) { + query Webhooks( + $first: Int + $after: String + $last: Int + $before: String + $filter: WebhookFilterInput + ) { + webhooks( + first: $first + after: $after + before: $before + last: $last + filter: $filter + ) { edges { node { ...WebhookFragment @@ -55,6 +62,11 @@ const webhooksDetails = gql` query WebhookDetails($id: ID!) { webhook(id: $id) { ...WebhookFragment + events { + eventType + } + secretKey + targetUrl } } `; diff --git a/src/webhooks/types/WebhookCreate.ts b/src/webhooks/types/WebhookCreate.ts index 9874ecbbd..e402b0116 100644 --- a/src/webhooks/types/WebhookCreate.ts +++ b/src/webhooks/types/WebhookCreate.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { WebhookCreateInput, WebhookEventTypeEnum } from "./../../types/globalTypes"; +import { WebhookCreateInput } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: WebhookCreate @@ -14,11 +14,6 @@ export interface WebhookCreate_webhookCreate_errors { message: string | null; } -export interface WebhookCreate_webhookCreate_webhook_events { - __typename: "WebhookEvent"; - eventType: WebhookEventTypeEnum | null; -} - export interface WebhookCreate_webhookCreate_webhook_serviceAccount { __typename: "ServiceAccount"; id: string; @@ -29,10 +24,7 @@ export interface WebhookCreate_webhookCreate_webhook { __typename: "Webhook"; id: string; name: string | null; - events: (WebhookCreate_webhookCreate_webhook_events | null)[] | null; isActive: boolean; - secretKey: string | null; - targetUrl: string; serviceAccount: WebhookCreate_webhookCreate_webhook_serviceAccount; } diff --git a/src/webhooks/types/WebhookDetails.ts b/src/webhooks/types/WebhookDetails.ts index 657d47ca0..0f68b655e 100644 --- a/src/webhooks/types/WebhookDetails.ts +++ b/src/webhooks/types/WebhookDetails.ts @@ -8,26 +8,26 @@ import { WebhookEventTypeEnum } from "./../../types/globalTypes"; // GraphQL query operation: WebhookDetails // ==================================================== -export interface WebhookDetails_webhook_events { - __typename: "WebhookEvent"; - eventType: WebhookEventTypeEnum | null; -} - export interface WebhookDetails_webhook_serviceAccount { __typename: "ServiceAccount"; id: string; name: string | null; } +export interface WebhookDetails_webhook_events { + __typename: "WebhookEvent"; + eventType: WebhookEventTypeEnum | null; +} + export interface WebhookDetails_webhook { __typename: "Webhook"; id: string; name: string | null; - events: (WebhookDetails_webhook_events | null)[] | null; isActive: boolean; + serviceAccount: WebhookDetails_webhook_serviceAccount; + events: (WebhookDetails_webhook_events | null)[] | null; secretKey: string | null; targetUrl: string; - serviceAccount: WebhookDetails_webhook_serviceAccount; } export interface WebhookDetails { diff --git a/src/webhooks/types/WebhookFragment.ts b/src/webhooks/types/WebhookFragment.ts index fa750b732..ad61edf7b 100644 --- a/src/webhooks/types/WebhookFragment.ts +++ b/src/webhooks/types/WebhookFragment.ts @@ -2,17 +2,10 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { WebhookEventTypeEnum } from "./../../types/globalTypes"; - // ==================================================== // GraphQL fragment: WebhookFragment // ==================================================== -export interface WebhookFragment_events { - __typename: "WebhookEvent"; - eventType: WebhookEventTypeEnum | null; -} - export interface WebhookFragment_serviceAccount { __typename: "ServiceAccount"; id: string; @@ -23,9 +16,6 @@ export interface WebhookFragment { __typename: "Webhook"; id: string; name: string | null; - events: (WebhookFragment_events | null)[] | null; isActive: boolean; - secretKey: string | null; - targetUrl: string; serviceAccount: WebhookFragment_serviceAccount; } diff --git a/src/webhooks/types/WebhookUpdate.ts b/src/webhooks/types/WebhookUpdate.ts index ca174bdfe..b8ce15cf7 100644 --- a/src/webhooks/types/WebhookUpdate.ts +++ b/src/webhooks/types/WebhookUpdate.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { WebhookUpdateInput, WebhookEventTypeEnum } from "./../../types/globalTypes"; +import { WebhookUpdateInput } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: WebhookUpdate @@ -14,11 +14,6 @@ export interface WebhookUpdate_webhookUpdate_errors { message: string | null; } -export interface WebhookUpdate_webhookUpdate_webhook_events { - __typename: "WebhookEvent"; - eventType: WebhookEventTypeEnum | null; -} - export interface WebhookUpdate_webhookUpdate_webhook_serviceAccount { __typename: "ServiceAccount"; id: string; @@ -29,10 +24,7 @@ export interface WebhookUpdate_webhookUpdate_webhook { __typename: "Webhook"; id: string; name: string | null; - events: (WebhookUpdate_webhookUpdate_webhook_events | null)[] | null; isActive: boolean; - secretKey: string | null; - targetUrl: string; serviceAccount: WebhookUpdate_webhookUpdate_webhook_serviceAccount; } diff --git a/src/webhooks/types/Webhooks.ts b/src/webhooks/types/Webhooks.ts index 95a458f51..d995aa7f5 100644 --- a/src/webhooks/types/Webhooks.ts +++ b/src/webhooks/types/Webhooks.ts @@ -2,17 +2,12 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { WebhookEventTypeEnum } from "./../../types/globalTypes"; +import { WebhookFilterInput } from "./../../types/globalTypes"; // ==================================================== // GraphQL query operation: Webhooks // ==================================================== -export interface Webhooks_webhooks_edges_node_events { - __typename: "WebhookEvent"; - eventType: WebhookEventTypeEnum | null; -} - export interface Webhooks_webhooks_edges_node_serviceAccount { __typename: "ServiceAccount"; id: string; @@ -23,10 +18,7 @@ export interface Webhooks_webhooks_edges_node { __typename: "Webhook"; id: string; name: string | null; - events: (Webhooks_webhooks_edges_node_events | null)[] | null; isActive: boolean; - secretKey: string | null; - targetUrl: string; serviceAccount: Webhooks_webhooks_edges_node_serviceAccount; } @@ -58,4 +50,5 @@ export interface WebhooksVariables { after?: string | null; last?: number | null; before?: string | null; + filter?: WebhookFilterInput | null; } diff --git a/src/webhooks/types/WebhooksDetailsFragment.ts b/src/webhooks/types/WebhooksDetailsFragment.ts index 321a86b04..777f7875c 100644 --- a/src/webhooks/types/WebhooksDetailsFragment.ts +++ b/src/webhooks/types/WebhooksDetailsFragment.ts @@ -2,17 +2,10 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { WebhookEventTypeEnum } from "./../../types/globalTypes"; - // ==================================================== // GraphQL fragment: WebhooksDetailsFragment // ==================================================== -export interface WebhooksDetailsFragment_events { - __typename: "WebhookEvent"; - eventType: WebhookEventTypeEnum | null; -} - export interface WebhooksDetailsFragment_serviceAccount { __typename: "ServiceAccount"; id: string; @@ -23,9 +16,6 @@ export interface WebhooksDetailsFragment { __typename: "Webhook"; id: string; name: string | null; - events: (WebhooksDetailsFragment_events | null)[] | null; isActive: boolean; - secretKey: string | null; - targetUrl: string; serviceAccount: WebhooksDetailsFragment_serviceAccount; } diff --git a/src/webhooks/urls.ts b/src/webhooks/urls.ts index 9edbe362f..7319aa36c 100644 --- a/src/webhooks/urls.ts +++ b/src/webhooks/urls.ts @@ -1,13 +1,26 @@ import { stringify as stringifyQs } from "qs"; import urlJoin from "url-join"; -import { Dialog, Pagination, SingleAction } from "../types"; +import { + ActiveTab, + Dialog, + Filters, + Pagination, + SingleAction, + TabActionDialog +} from "../types"; export const webhooksSection = "/webhooks/"; export const webhooksListPath = webhooksSection; -export type WebhookListUrlDialog = "remove"; -export type WebhooksListUrlQueryParams = Dialog & +export enum WebhookListUrlFiltersEnum { + query = "query" +} +export type WebhookListUrlFilters = Filters; +export type WebhookListUrlDialog = "remove" | TabActionDialog; +export type WebhooksListUrlQueryParams = ActiveTab & + WebhookListUrlFilters & + Dialog & Pagination & SingleAction; export const webhooksListUrl = (params?: WebhooksListUrlQueryParams) => diff --git a/src/webhooks/views/WebhooksCreate.tsx b/src/webhooks/views/WebhooksCreate.tsx index 3b6628ec5..95489131e 100644 --- a/src/webhooks/views/WebhooksCreate.tsx +++ b/src/webhooks/views/WebhooksCreate.tsx @@ -50,7 +50,7 @@ export const WebhooksCreate: React.StatelessComponent< variables: { input: { events: data.allEvents - ? [WebhookEventTypeEnum.ALL_EVENTS] + ? [WebhookEventTypeEnum.ANY_EVENTS] : data.events, isActive: data.isActive, name: data.name, diff --git a/src/webhooks/views/WebhooksDetails.tsx b/src/webhooks/views/WebhooksDetails.tsx index f6511ea98..8e492ead3 100644 --- a/src/webhooks/views/WebhooksDetails.tsx +++ b/src/webhooks/views/WebhooksDetails.tsx @@ -127,7 +127,7 @@ export const WebhooksDetails: React.StatelessComponent< id, input: { events: data.allEvents - ? [WebhookEventTypeEnum.ALL_EVENTS] + ? [WebhookEventTypeEnum.ANY_EVENTS] : data.events, isActive: data.isActive, name: data.name, diff --git a/src/webhooks/views/WebhooksList.tsx b/src/webhooks/views/WebhooksList.tsx index db35f81a0..44ed2bdd5 100644 --- a/src/webhooks/views/WebhooksList.tsx +++ b/src/webhooks/views/WebhooksList.tsx @@ -1,3 +1,7 @@ +import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog"; +import SaveFilterTabDialog, { + SaveFilterTabDialogFormData +} from "@saleor/components/SaveFilterTabDialog"; import { configurationMenuUrl } from "@saleor/configuration"; import useListSettings from "@saleor/hooks/useListSettings"; import useNavigator from "@saleor/hooks/useNavigator"; @@ -16,12 +20,21 @@ import { useIntl } from "react-intl"; import WebhooksListPage from "../components/WebhooksListPage/WebhooksListPage"; import { TypedWebhookDelete } from "../mutations"; import { TypedWebhooksListQuery } from "../queries"; -import { +import { WebhookListUrlDialog, + WebhookListUrlFilters, webhooksAddUrl, webhooksListUrl, WebhooksListUrlQueryParams, webhooksUrl } from "../urls"; +import { + areFiltersApplied, + deleteFilterTab, + getActiveFilters, + getFilterTabs, + getFilterVariables, + saveFilterTab +} from "./filter"; interface WebhooksListProps { params: WebhooksListUrlQueryParams; @@ -37,8 +50,23 @@ export const WebhooksList: React.StatelessComponent = ({ const { updateListSettings, settings } = useListSettings( ListViews.WEBHOOK_LIST ); - const paginationState = createPaginationState(settings.rowNumber, params); + const tabs = getFilterTabs(); + const currentTab = + params.activeTab === undefined + ? areFiltersApplied(params) + ? tabs.length + 1 + : 0 + : parseInt(params.activeTab, 0); + + const changeFilterField = (filter: WebhookListUrlFilters) => + navigate( + webhooksListUrl({ + ...getActiveFilters(params), + ...filter, + activeTab: undefined + }) + ); const closeModal = () => navigate( webhooksListUrl({ @@ -49,8 +77,45 @@ export const WebhooksList: React.StatelessComponent = ({ true ); + const openModal = (action: WebhookListUrlDialog, id?: string) => + navigate( + webhooksListUrl({ + ...params, + action, + id + }) + ); + + const handleTabChange = (tab: number) => { + navigate( + webhooksListUrl({ + activeTab: tab.toString(), + ...getFilterTabs()[tab - 1].data + }) + ); + }; + + const handleTabDelete = () => { + deleteFilterTab(currentTab); + navigate(webhooksListUrl()); + }; + + const handleTabSave = (data: SaveFilterTabDialogFormData) => { + saveFilterTab(data.name, getActiveFilters(params)); + handleTabChange(tabs.length + 1); + }; + + const paginationState = createPaginationState(settings.rowNumber, params); + const queryVariables = React.useMemo( + () => ({ + ...paginationState, + filter: getFilterVariables(params) + }), + [params] + ); + return ( - + {({ data, loading, refetch }) => { const onWebhookDelete = (data: WebhookDelete) => { if (data.webhookDelete.errors.length === 0) { @@ -95,6 +160,14 @@ export const WebhooksList: React.StatelessComponent = ({ return ( <> changeFilterField({ query })} + onAll={() => navigate(webhooksListUrl())} + onTabChange={handleTabChange} + onTabDelete={() => openModal("delete-search")} + onTabSave={() => openModal("save-search")} + tabs={tabs.map(tab => tab.name)} disabled={loading} settings={settings} webhooks={maybe(() => @@ -122,6 +195,19 @@ export const WebhooksList: React.StatelessComponent = ({ onConfirm={handleRemoveConfirm} open={params.action === "remove"} /> + + tabs[currentTab - 1].name, "...")} + /> ); }} diff --git a/src/webhooks/views/filter.ts b/src/webhooks/views/filter.ts new file mode 100644 index 000000000..1f7365ebc --- /dev/null +++ b/src/webhooks/views/filter.ts @@ -0,0 +1,28 @@ +import { WebhookFilterInput } from "@saleor/types/globalTypes"; +import { createFilterTabUtils, createFilterUtils } from "../../utils/filters"; +import { + WebhookListUrlFilters, + WebhookListUrlFiltersEnum, + WebhooksListUrlQueryParams +} from "../urls"; + +export const WEBHOOK_FILTERS_KEY = "webhookFilters"; + +export function getFilterVariables( + params: WebhookListUrlFilters +): WebhookFilterInput { + return { + search: params.query + }; +} + +export const { + deleteFilterTab, + getFilterTabs, + saveFilterTab +} = createFilterTabUtils(WEBHOOK_FILTERS_KEY); + +export const { areFiltersApplied, getActiveFilters } = createFilterUtils< + WebhooksListUrlQueryParams, + WebhookListUrlFilters +>(WebhookListUrlFiltersEnum); From 3b844eec0aaaf25f08d9adefb537e542874de085 Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Wed, 16 Oct 2019 14:03:14 +0200 Subject: [PATCH 15/38] Fix webhooks events --- src/misc.ts | 58 ++++++++++++++++++- .../WebhookEvents/WebhookEvents.tsx | 8 +-- .../WebhooksDetailsPage.tsx | 2 +- src/webhooks/views/WebhooksDetails.tsx | 2 +- 4 files changed, 63 insertions(+), 7 deletions(-) diff --git a/src/misc.ts b/src/misc.ts index 96bc1f921..460127a08 100644 --- a/src/misc.ts +++ b/src/misc.ts @@ -11,7 +11,8 @@ import { AuthorizationKeyType, OrderStatus, PaymentChargeStatusEnum, - TaxRateType + TaxRateType, + WebhookEventTypeEnum } from "./types/globalTypes"; export type RequireAtLeastOne = Pick< @@ -333,6 +334,61 @@ export const translatedTaxRates = (intl: IntlShape) => ({ [TaxRateType.WATER]: intl.formatMessage(taxRatesMessages.water) }); +const webhooksEventMessages = defineMessages({ + anyEvents: { + defaultMessage: "Any events", + description: "event" + }, + customerCreated: { + defaultMessage: "Customer created", + description: "event" + }, + orderCancelled: { + defaultMessage: "Order cancelled", + description: "event" + }, + orderCreated: { + defaultMessage: "Order created", + description: "event" + }, + orderFullyPaid: { + defaultMessage: "Order fully paid", + description: "event" + }, + orderUpdated: { + defaultMessage: "Order updated", + description: "event" + }, + productCreated: { + defaultMessage: "Product created", + description: "event" + } +}); + +export const translatedWebhookEvents = (intl: IntlShape) => ({ + [WebhookEventTypeEnum.ANY_EVENTS]: intl.formatMessage( + webhooksEventMessages.anyEvents + ), + [WebhookEventTypeEnum.CUSTOMER_CREATED]: intl.formatMessage( + webhooksEventMessages.customerCreated + ), + [WebhookEventTypeEnum.ORDER_CANCELLED]: intl.formatMessage( + webhooksEventMessages.orderCancelled + ), + [WebhookEventTypeEnum.ORDER_CREATED]: intl.formatMessage( + webhooksEventMessages.orderCreated + ), + [WebhookEventTypeEnum.ORDER_FULLY_PAID]: intl.formatMessage( + webhooksEventMessages.orderFullyPaid + ), + [WebhookEventTypeEnum.ORDER_UPDATED]: intl.formatMessage( + webhooksEventMessages.orderUpdated + ), + [WebhookEventTypeEnum.PRODUCT_CREATED]: intl.formatMessage( + webhooksEventMessages.productCreated + ) +}); + export const authorizationKeyTypes = { [AuthorizationKeyType.FACEBOOK]: "Facebook", [AuthorizationKeyType.GOOGLE_OAUTH2]: "Google OAuth2" diff --git a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx index 3b1d3319b..28774b674 100644 --- a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx +++ b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx @@ -5,6 +5,7 @@ import CardTitle from "@saleor/components/CardTitle"; import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; import Hr from "@saleor/components/Hr"; import { ChangeEvent } from "@saleor/hooks/useForm"; +import { translatedWebhookEvents } from "@saleor/misc"; import { WebhookEventTypeEnum } from "@saleor/types/globalTypes"; import React from "react"; import { useIntl } from "react-intl"; @@ -25,15 +26,14 @@ const WebhookEvents: React.StatelessComponent = ({ }) => { const intl = useIntl(); const eventsEnum = Object.values(WebhookEventTypeEnum); + const translatedEvents = translatedWebhookEvents(intl); const handleAllEventsChange = (event: ChangeEvent) => onChange(event, () => onChange({ target: { name: "events", - value: event.target.value - ? WebhookEventTypeEnum.ANY_EVENTS - : data.events + value: event.target.value ? WebhookEventTypeEnum.ANY_EVENTS : [] } } as any) ); @@ -84,7 +84,7 @@ const WebhookEvents: React.StatelessComponent = ({ diff --git a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx index 8f03f9142..292635e1e 100644 --- a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx +++ b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx @@ -69,7 +69,7 @@ const WebhooksDetailsPage: React.StatelessComponent< isActive: maybe(() => webhook.isActive, false), name: maybe(() => webhook.name, ""), secretKey: maybe(() => webhook.secretKey, ""), - serviceAccount: maybe(() => webhook.serviceAccount.name, ""), + serviceAccount: maybe(() => webhook.serviceAccount.id, ""), targetUrl: maybe(() => webhook.targetUrl, "") }; const [ diff --git a/src/webhooks/views/WebhooksDetails.tsx b/src/webhooks/views/WebhooksDetails.tsx index 8e492ead3..7590634f3 100644 --- a/src/webhooks/views/WebhooksDetails.tsx +++ b/src/webhooks/views/WebhooksDetails.tsx @@ -128,7 +128,7 @@ export const WebhooksDetails: React.StatelessComponent< input: { events: data.allEvents ? [WebhookEventTypeEnum.ANY_EVENTS] - : data.events, + : data.events.slice(1), isActive: data.isActive, name: data.name, secretKey: data.secretKey, From 8a61fa781d1131d54660bc9410873d4dde77c55c Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Wed, 16 Oct 2019 14:06:28 +0200 Subject: [PATCH 16/38] Update snapshots --- .../__snapshots__/Stories.test.ts.snap | 8254 +++++++++++++---- 1 file changed, 6387 insertions(+), 1867 deletions(-) diff --git a/src/storybook/__snapshots__/Stories.test.ts.snap b/src/storybook/__snapshots__/Stories.test.ts.snap index dc07dd54b..af213721e 100644 --- a/src/storybook/__snapshots__/Stories.test.ts.snap +++ b/src/storybook/__snapshots__/Stories.test.ts.snap @@ -28266,7 +28266,7 @@ exports[`Storyshots Views / Configuration default 1`] = `

- View and update your site settings + View and update your webhook and their settings

@@ -28782,7 +28782,7 @@ exports[`Storyshots Views / Configuration partial access 1`] = `

- View and update your site settings + View and update your webhook and their settings

@@ -103729,7 +103729,7 @@ exports[`Storyshots Views / Services / Create service default 1`] = `
- Create Webhook + Create New Account
- Webhook Information + Service Account Information
-

- General Information -

@@ -103779,7 +103774,7 @@ exports[`Storyshots Views / Services / Create service default 1`] = ` class="MuiFormLabel-root-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-outlined-id" data-shrink="false" > - Webhook Name + Account Name
-
-
-
-
-
-

- Webhook specific information -

-
- -
- -
-
- - ​ - -
- - -
-
-
-
-
- -
- -
-

- This URL will recieve webhook POST requests -

-
-
-
- -
- - -
-

- secret key is used to create a hash signature with each payload. *optional field -

-
+
-
- - Events - -
-
+ Permissions +
-
-
-

- Expand or restrict webhooks permissions to register certain events in Saleor system. -

- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
+
-
- - Webhook Status - -
-
+ Expand or restrict user's permissions to access certain part of saleor system. +

-
-
-

- If you want to disable this webhook please uncheck the box below. -

+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ + Account Status + +
+
+
+
+
+

+ If you want to disable this account uncheck the box below +

+ +
@@ -104239,7 +104173,7 @@ exports[`Storyshots Views / Services / Create service form errors 1`] = `
- Create Webhook + Create New Account
- Webhook Information + Service Account Information
-

- General Information -

@@ -104289,7 +104218,7 @@ exports[`Storyshots Views / Services / Create service form errors 1`] = ` class="MuiFormLabel-root-id MuiFormLabel-error-id MuiInputLabel-error-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-outlined-id" data-shrink="false" > - Webhook Name + Account Name

-
-
-
-

- Webhook specific information -

-
- -
- -
-
- - ​ - -
- - -
-
-
-
-
- -
- - -
-

- This URL will recieve webhook POST requests -

-
-
-
- -
- - -
-

- secret key is used to create a hash signature with each payload. *optional field -

-
-
+
-
- - Events - -
-
+ Permissions +
-
-
-

- Expand or restrict webhooks permissions to register certain events in Saleor system. -

- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
+
-
- - Webhook Status - -
-
+ Expand or restrict user's permissions to access certain part of saleor system. +

-
-
-

- If you want to disable this webhook please uncheck the box below. -

+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ + Account Status + +
+
+
+
+
+

+ If you want to disable this account uncheck the box below +

+ +
@@ -104754,7 +104622,7 @@ exports[`Storyshots Views / Services / Create service loading 1`] = `
- Create Webhook + Create New Account
- Webhook Information + Service Account Information
-

- General Information -

@@ -104804,7 +104667,7 @@ exports[`Storyshots Views / Services / Create service loading 1`] = ` class="MuiFormLabel-root-id MuiFormLabel-disabled-id MuiInputLabel-disabled-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-outlined-id" data-shrink="false" > - Webhook Name + Account Name
-
-
-
-
-
-

- Webhook specific information -

-
- -
- -
-
- - ​ - -
- - -
-
-
-
-
- -
- -
-

- This URL will recieve webhook POST requests -

-
-
-
- -
- - -
-

- secret key is used to create a hash signature with each payload. *optional field -

-
+
-
- - Events - -
-
+ Permissions +
-
-
-

- Expand or restrict webhooks permissions to register certain events in Saleor system. -

- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
+
-
- - Webhook Status - -
-
+ Expand or restrict user's permissions to access certain part of saleor system. +

-
-
-

- If you want to disable this webhook please uncheck the box below. -

+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ + Account Status + +
+
+
+
+
+

+ If you want to disable this account uncheck the box below +

+ +
@@ -105289,7 +105097,7 @@ exports[`Storyshots Views / Services / Service details default 1`] = `
- ... Details + Magento Importer
- Webhook Information + Service Account Information
-

- General Information -

​ @@ -105363,172 +105166,126 @@ exports[`Storyshots Views / Services / Service details default 1`] = ` class="MuiInputBase-input-id MuiOutlinedInput-input-id" name="name" type="text" - value="" + value="Magento Importer" />
-
-
-
-

- Webhook specific information -

-
- -
- -
-
- - ​ - -
- - -
-
-
-
-
- -
- - -
-

- This URL will recieve webhook POST requests -

-
-
-
- -
- - -
-

- secret key is used to create a hash signature with each payload. *optional field -

-
+
+
+
+ + Service Account Information + +
+ +
+
+
+
+ + + + + + + + + + + + + + + +
+ Token Note + + Key + + Actions +
+ default + + **** AK05 + + +
+
- Events + Permissions
- Expand or restrict webhooks permissions to register certain events in Saleor system. + Expand or restrict user's permissions to access certain part of saleor system.

- -
+ + + User has full access to the store + + +
+
+
+
@@ -105618,7 +105383,7 @@ exports[`Storyshots Views / Services / Service details default 1`] = ` > @@ -105626,7 +105391,7 @@ exports[`Storyshots Views / Services / Service details default 1`] = ` - ORDER_CANCELLED + Manage sales and vouchers
@@ -105641,7 +105406,7 @@ exports[`Storyshots Views / Services / Service details default 1`] = ` > @@ -105649,7 +105414,7 @@ exports[`Storyshots Views / Services / Service details default 1`] = ` - ORDER_CREATED + Manage navigation
@@ -105664,7 +105429,7 @@ exports[`Storyshots Views / Services / Service details default 1`] = ` > @@ -105672,7 +105437,7 @@ exports[`Storyshots Views / Services / Service details default 1`] = ` - ORDER_FULLY_PAID + Manage orders
@@ -105687,7 +105452,7 @@ exports[`Storyshots Views / Services / Service details default 1`] = ` > @@ -105695,7 +105460,30 @@ exports[`Storyshots Views / Services / Service details default 1`] = ` - ORDER_UPDATED + Manage pages + + +
+
+
@@ -105710,7 +105498,7 @@ exports[`Storyshots Views / Services / Service details default 1`] = ` > @@ -105718,14 +105506,83 @@ exports[`Storyshots Views / Services / Service details default 1`] = ` - PRODUCT_CREATED + Manage settings + + +
+
+ +
+
+ +
+
+
- Webhook Status + Account Status
- If you want to disable this webhook please uncheck the box below. + If you want to disable this account uncheck the box below

@@ -106447,7 +106304,7 @@ exports[`Storyshots Views / Services / Service details form errors 1`] = `
- ... Details + Magento Importer
- Webhook Information + Service Account Information
-

- General Information -

​ @@ -106521,176 +106373,130 @@ exports[`Storyshots Views / Services / Service details form errors 1`] = ` class="MuiInputBase-input-id MuiOutlinedInput-input-id" name="name" type="text" - value="" + value="Magento Importer" />

Generic form error

-
-
-
-

+

+
+
+
+ - Webhook specific information -

+ Service Account Information +
- -
- -
-
- - ​ - -
- - -
-
-
-
-
- -
- - -
-

- This URL will recieve webhook POST requests -

-
-
-
- -
- - -
-

- secret key is used to create a hash signature with each payload. *optional field -

+ Create Token + +
+
+
+ + + + + + + + + + + + + + + +
+ Token Note + + Key + + Actions +
+ default + + **** AK05 + + +
@@ -106703,7 +106509,7 @@ exports[`Storyshots Views / Services / Service details form errors 1`] = ` - Events + Permissions
- Expand or restrict webhooks permissions to register certain events in Saleor system. + Expand or restrict user's permissions to access certain part of saleor system.

- -
+ + + User has full access to the store + + +
+
+
+
@@ -106781,7 +106595,7 @@ exports[`Storyshots Views / Services / Service details form errors 1`] = ` > @@ -106789,7 +106603,7 @@ exports[`Storyshots Views / Services / Service details form errors 1`] = ` - ORDER_CANCELLED + Manage sales and vouchers
@@ -106804,7 +106618,7 @@ exports[`Storyshots Views / Services / Service details form errors 1`] = ` > @@ -106812,7 +106626,7 @@ exports[`Storyshots Views / Services / Service details form errors 1`] = ` - ORDER_CREATED + Manage navigation
@@ -106827,7 +106641,7 @@ exports[`Storyshots Views / Services / Service details form errors 1`] = ` > @@ -106835,7 +106649,7 @@ exports[`Storyshots Views / Services / Service details form errors 1`] = ` - ORDER_FULLY_PAID + Manage orders
@@ -106850,7 +106664,7 @@ exports[`Storyshots Views / Services / Service details form errors 1`] = ` > @@ -106858,7 +106672,30 @@ exports[`Storyshots Views / Services / Service details form errors 1`] = ` - ORDER_UPDATED + Manage pages + + +
+
+
@@ -106873,7 +106710,7 @@ exports[`Storyshots Views / Services / Service details form errors 1`] = ` > @@ -106881,14 +106718,83 @@ exports[`Storyshots Views / Services / Service details form errors 1`] = ` - PRODUCT_CREATED + Manage settings + + +
+
+ +
+
+ +
+
+
- Webhook Status + Account Status
- If you want to disable this webhook please uncheck the box below. + If you want to disable this account uncheck the box below

@@ -106963,7 +106869,12 @@ exports[`Storyshots Views / Services / Service details loading 1`] = `
- ... Details + + ‌ +
- Webhook Information + Service Account Information
-

- General Information -

@@ -107013,7 +106919,7 @@ exports[`Storyshots Views / Services / Service details loading 1`] = ` class="MuiFormLabel-root-id MuiFormLabel-disabled-id MuiInputLabel-disabled-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-outlined-id" data-shrink="false" > - Webhook Name + Account Name
-
-
-
-

+

+
+
+
+ - Webhook specific information -

+ Service Account Information +
- -
- -
-
- - ​ - -
- - -
-
-
-
-
- -
- - -
-

- This URL will recieve webhook POST requests -

-
-
-
- -
- - -
-

- secret key is used to create a hash signature with each payload. *optional field -

+ Create Token + +
+
+
+ + + + + + + + + + + + + + + +
+ Token Note + + Key + + Actions +
+ + ‌ + + + + ‌ + + + +
@@ -107217,7 +107083,7 @@ exports[`Storyshots Views / Services / Service details loading 1`] = ` - Events + Permissions
- Expand or restrict webhooks permissions to register certain events in Saleor system. + Expand or restrict user's permissions to access certain part of saleor system.

- -
+ tabindex="-1" + type="button" + > + + + + User has full access to the store + + +
+
+
+
@@ -107301,7 +107175,7 @@ exports[`Storyshots Views / Services / Service details loading 1`] = ` @@ -107309,7 +107183,7 @@ exports[`Storyshots Views / Services / Service details loading 1`] = ` - ORDER_CANCELLED + Manage sales and vouchers
@@ -107326,7 +107200,7 @@ exports[`Storyshots Views / Services / Service details loading 1`] = ` @@ -107334,7 +107208,7 @@ exports[`Storyshots Views / Services / Service details loading 1`] = ` - ORDER_CREATED + Manage navigation
@@ -107351,7 +107225,7 @@ exports[`Storyshots Views / Services / Service details loading 1`] = ` @@ -107359,7 +107233,7 @@ exports[`Storyshots Views / Services / Service details loading 1`] = ` - ORDER_FULLY_PAID + Manage orders
@@ -107376,7 +107250,7 @@ exports[`Storyshots Views / Services / Service details loading 1`] = ` @@ -107384,7 +107258,7 @@ exports[`Storyshots Views / Services / Service details loading 1`] = ` - ORDER_UPDATED + Manage pages
@@ -107401,7 +107275,7 @@ exports[`Storyshots Views / Services / Service details loading 1`] = ` @@ -107409,14 +107283,114 @@ exports[`Storyshots Views / Services / Service details loading 1`] = ` - PRODUCT_CREATED + Manage products + + +
+
+ +
+
+ +
+
+ +
+
+
- Webhook Status + Account Status
- If you want to disable this webhook please uncheck the box below. + If you want to disable this account uncheck the box below

@@ -107492,7 +107466,7 @@ exports[`Storyshots Views / Services / Service list default 1`] = `
- Webhooks + Service Accounts
- Create webhook + Create account
@@ -107517,8 +107491,102 @@ exports[`Storyshots Views / Services / Service list default 1`] = `
+
+
+
+
+ + +
+
+
+
+
+
+
+ + +
+
+
+
- + /> - + + +
Name - Service Account - - Action -
+ + Magento Importer + + + inactive + @@ -107847,8 +107990,102 @@ exports[`Storyshots Views / Services / Service list loading 1`] = `
+
+
+
+
+ + +
+
+
+
+
+
+
+ + +
+
+
+
- + /> - @@ -126920,3 +126920,9 @@ exports[`Storyshots Views / Webhook / Webhook list no data 1`] = ` `; + +exports[`Storyshots Views / Webhooks / Delete webhook default 1`] = ` +
+`; From 1ec53b49b5354918cffcb2fb5dcac1ae0cbd0735 Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Thu, 17 Oct 2019 15:52:30 +0200 Subject: [PATCH 26/38] Fix storybook names --- .../components/WebhookCreatePage/WebhooksCreatePage.stories.tsx | 2 +- .../WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/webhooks/components/WebhookCreatePage/WebhooksCreatePage.stories.tsx b/src/webhooks/components/WebhookCreatePage/WebhooksCreatePage.stories.tsx index bf6eaf1c5..dc9e5320c 100644 --- a/src/webhooks/components/WebhookCreatePage/WebhooksCreatePage.stories.tsx +++ b/src/webhooks/components/WebhookCreatePage/WebhooksCreatePage.stories.tsx @@ -14,7 +14,7 @@ const props: WebhookCreatePageProps = { saveButtonBarState: "default", services: [] }; -storiesOf("Views / Webhook / Create webhook", module) +storiesOf("Views / Webhooks / Create webhook", module) .addDecorator(Decorator) .add("default", () => ) .add("loading", () => ) diff --git a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx index 6742e3126..11d17e6b5 100644 --- a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx +++ b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx @@ -18,7 +18,7 @@ const props: WebhooksDetailsPageProps = { services: [], webhook: null }; -storiesOf("Views / Webhook / Webhook details", module) +storiesOf("Views / Webhooks / Webhook details", module) .addDecorator(Decorator) .add("default", () => ) .add("loading", () => ( From ec01fec82157f11964884a91addca7ecadd6c3f3 Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Thu, 17 Oct 2019 15:52:48 +0200 Subject: [PATCH 27/38] Add fixed table layout --- .../components/WebhooksList/WebhooksList.tsx | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/webhooks/components/WebhooksList/WebhooksList.tsx b/src/webhooks/components/WebhooksList/WebhooksList.tsx index ac24b79e5..823407bbb 100644 --- a/src/webhooks/components/WebhooksList/WebhooksList.tsx +++ b/src/webhooks/components/WebhooksList/WebhooksList.tsx @@ -33,11 +33,21 @@ const useStyles = makeStyles((theme: Theme) => ({ textAlign: "right" }, colActive: {}, - colName: {} + colName: { + "&&": { + width: "auto" + } + } }, colAction: {}, colActive: {}, - colName: {}, + colName: { + paddingLeft: 0, + width: 250 + }, + table: { + tableLayout: "fixed" + }, tableRow: { cursor: "pointer" } @@ -60,7 +70,7 @@ const WebhooksList: React.FC = ({ const classes = useStyles({}); return ( -
Name - Service Account - - Action -
- ‌ + + ‌ + - - ‌ - + class="MuiTypography-root-id MuiTypography-caption-id" + data-tc="isActive" + /> @@ -108118,8 +108346,102 @@ exports[`Storyshots Views / Services / Service list no data 1`] = `
+
+
+
+
+ + +
+
+
+
+
+
+
+ + +
+
+
+
- + /> @@ -118306,3 +118620,4209 @@ exports[`Storyshots Views / Translations / Language list no data 1`] = ` `; + +exports[`Storyshots Views / Webhook / Create webhook default 1`] = ` +
+
+
+
+
+ Create Webhook +
+
+
+
+
+
+
+
+
+ + Webhook Information + +
+
+
+
+
+

+ General Informations +

+
+ +
+ + +
+
+
+
+
+

+ Webhook specific information +

+
+
+ + +
+
+
+
+ +
+ + +
+

+ This URL will recieve webhook POST requests +

+
+
+
+ +
+ + +
+

+ secret key is used to create a hash signature with each payload. *optional field +

+
+
+
+
+
+
+
+ + Events + +
+
+
+
+
+

+ Expand or restrict webhooks permissions to register certain events in Saleor system. +

+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ + Webhook Status + +
+
+
+
+
+

+ If you want to disable this webhook please uncheck the box below. +

+ +
+
+
+
+
+ +
+`; + +exports[`Storyshots Views / Webhook / Create webhook form errors 1`] = ` +
+
+
+
+
+ Create Webhook +
+
+
+
+
+
+
+
+
+ + Webhook Information + +
+
+
+
+
+

+ General Informations +

+
+ +
+ + +
+

+ Generic form error +

+
+
+
+
+

+ Webhook specific information +

+
+
+ + +
+
+
+
+ +
+ + +
+

+ This URL will recieve webhook POST requests +

+
+
+
+ +
+ + +
+

+ secret key is used to create a hash signature with each payload. *optional field +

+
+
+
+
+
+
+
+ + Events + +
+
+
+
+
+

+ Expand or restrict webhooks permissions to register certain events in Saleor system. +

+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ + Webhook Status + +
+
+
+
+
+

+ If you want to disable this webhook please uncheck the box below. +

+ +
+
+
+
+
+ +
+`; + +exports[`Storyshots Views / Webhook / Create webhook loading 1`] = ` +
+
+
+
+
+ Create Webhook +
+
+
+
+
+
+
+
+
+ + Webhook Information + +
+
+
+
+
+

+ General Informations +

+
+ +
+ + +
+
+
+
+
+

+ Webhook specific information +

+
+
+ + +
+
+
+
+ +
+ + +
+

+ This URL will recieve webhook POST requests +

+
+
+
+ +
+ + +
+

+ secret key is used to create a hash signature with each payload. *optional field +

+
+
+
+
+
+
+
+ + Events + +
+
+
+
+
+

+ Expand or restrict webhooks permissions to register certain events in Saleor system. +

+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ + Webhook Status + +
+
+
+
+
+

+ If you want to disable this webhook please uncheck the box below. +

+ +
+
+
+
+
+ +
+`; + +exports[`Storyshots Views / Webhook / Webhook details default 1`] = ` +
+
+
+
+
+ ... Details +
+
+
+
+
+
+
+
+
+ + Webhook Information + +
+
+
+
+
+

+ General Informations +

+
+ +
+ + +
+
+
+
+
+

+ Webhook specific information +

+
+
+ + +
+
+
+
+ +
+ + +
+

+ This URL will recieve webhook POST requests +

+
+
+
+ +
+ + +
+

+ secret key is used to create a hash signature with each payload. *optional field +

+
+
+
+
+
+
+
+ + Events + +
+
+
+
+
+

+ Expand or restrict webhooks permissions to register certain events in Saleor system. +

+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ + Webhook Status + +
+
+
+
+
+

+ If you want to disable this webhook please uncheck the box below. +

+ +
+
+
+
+
+ +
+`; + +exports[`Storyshots Views / Webhook / Webhook details form errors 1`] = ` +
+
+
+
+
+ ... Details +
+
+
+
+
+
+
+
+
+ + Webhook Information + +
+
+
+
+
+

+ General Informations +

+
+ +
+ + +
+

+ Generic form error +

+
+
+
+
+

+ Webhook specific information +

+
+
+ + +
+
+
+
+ +
+ + +
+

+ This URL will recieve webhook POST requests +

+
+
+
+ +
+ + +
+

+ secret key is used to create a hash signature with each payload. *optional field +

+
+
+
+
+
+
+
+ + Events + +
+
+
+
+
+

+ Expand or restrict webhooks permissions to register certain events in Saleor system. +

+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ + Webhook Status + +
+
+
+
+
+

+ If you want to disable this webhook please uncheck the box below. +

+ +
+
+
+
+
+ +
+`; + +exports[`Storyshots Views / Webhook / Webhook details loading 1`] = ` +
+
+
+
+
+ ... Details +
+
+
+
+
+
+
+
+
+ + Webhook Information + +
+
+
+
+
+

+ General Informations +

+
+ +
+ + +
+
+
+
+
+

+ Webhook specific information +

+
+
+ + +
+
+
+
+ +
+ + +
+

+ This URL will recieve webhook POST requests +

+
+
+
+ +
+ + +
+

+ secret key is used to create a hash signature with each payload. *optional field +

+
+
+
+
+
+
+
+ + Events + +
+
+
+
+
+

+ Expand or restrict webhooks permissions to register certain events in Saleor system. +

+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ + Webhook Status + +
+
+
+
+
+

+ If you want to disable this webhook please uncheck the box below. +

+ +
+
+
+
+
+ +
+`; + +exports[`Storyshots Views / Webhook / Webhook list default 1`] = ` +
+
+
+
+ Webhooks +
+
+
+ +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+ + +
+
+
+
+
+
Name - Service Account - - Action -
- No webhooks found + No service accounts found
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ Name + + Service Account + + Action +
+ Webhook Test + + Test Account + + + +
+ Webhook Test 2 + + Test Account 2 + + + +
+
+ + + +`; + +exports[`Storyshots Views / Webhook / Webhook list loading 1`] = ` +
+
+
+
+ Webhooks +
+
+
+ +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+ + +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + +
+ Name + + Service Account + + Action +
+ + ‌ + + + + ‌ + + + + +
+
+
+
+
+`; + +exports[`Storyshots Views / Webhook / Webhook list no data 1`] = ` +
+
+
+
+ Webhooks +
+
+
+ +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+ + +
+
+
+
+
+ + + + + + + + + + + + + + + + + + +
+ Name + + Service Account + + Action +
+ No webhooks found +
+
+
+
+
+`; From 69d6b0758beb13ae6d35734e8a2c4fa5900c8d46 Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Wed, 16 Oct 2019 14:09:10 +0200 Subject: [PATCH 17/38] Fix event any label --- src/webhooks/components/WebhookEvents/WebhookEvents.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx index 28774b674..110907a32 100644 --- a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx +++ b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx @@ -68,10 +68,7 @@ const WebhookEvents: React.StatelessComponent = ({ From c9762ffbf19245c90f6aefdf7779e3f58a7eabab Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Wed, 16 Oct 2019 14:11:29 +0200 Subject: [PATCH 18/38] Update snapshots --- src/storybook/__snapshots__/Stories.test.ts.snap | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/storybook/__snapshots__/Stories.test.ts.snap b/src/storybook/__snapshots__/Stories.test.ts.snap index 40345b148..639873bb7 100644 --- a/src/storybook/__snapshots__/Stories.test.ts.snap +++ b/src/storybook/__snapshots__/Stories.test.ts.snap @@ -121982,7 +121982,7 @@ exports[`Storyshots Views / Webhook / Create webhook default 1`] = ` - All events + Any events
- All events + Any events
- All events + Any events
- All events + Any events
- All events + Any events
- All events + Any events
Date: Wed, 16 Oct 2019 14:51:00 +0200 Subject: [PATCH 19/38] Fix import --- src/containers/SearchServiceAccount/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/containers/SearchServiceAccount/index.tsx b/src/containers/SearchServiceAccount/index.tsx index 7b59b27ec..af3574f7d 100644 --- a/src/containers/SearchServiceAccount/index.tsx +++ b/src/containers/SearchServiceAccount/index.tsx @@ -4,7 +4,7 @@ import BaseSearch from "../BaseSearch"; import { SearchServiceAccount, SearchServiceAccountVariables -} from "./types/SearchServiceAccount"; +} from "./types/searchServiceAccount"; export const searchServiceAccount = gql` query SearchServiceAccount($after: String, $first: Int!, $query: String!) { From d6c5e48d7ecadc882138279a558e6b50e0edf3d2 Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Thu, 17 Oct 2019 12:24:36 +0200 Subject: [PATCH 20/38] Move events translation enum to component --- src/misc.ts | 55 ------------------- .../WebhookEvents/WebhookEvents.tsx | 33 ++++++++++- 2 files changed, 31 insertions(+), 57 deletions(-) diff --git a/src/misc.ts b/src/misc.ts index 460127a08..4217de160 100644 --- a/src/misc.ts +++ b/src/misc.ts @@ -334,61 +334,6 @@ export const translatedTaxRates = (intl: IntlShape) => ({ [TaxRateType.WATER]: intl.formatMessage(taxRatesMessages.water) }); -const webhooksEventMessages = defineMessages({ - anyEvents: { - defaultMessage: "Any events", - description: "event" - }, - customerCreated: { - defaultMessage: "Customer created", - description: "event" - }, - orderCancelled: { - defaultMessage: "Order cancelled", - description: "event" - }, - orderCreated: { - defaultMessage: "Order created", - description: "event" - }, - orderFullyPaid: { - defaultMessage: "Order fully paid", - description: "event" - }, - orderUpdated: { - defaultMessage: "Order updated", - description: "event" - }, - productCreated: { - defaultMessage: "Product created", - description: "event" - } -}); - -export const translatedWebhookEvents = (intl: IntlShape) => ({ - [WebhookEventTypeEnum.ANY_EVENTS]: intl.formatMessage( - webhooksEventMessages.anyEvents - ), - [WebhookEventTypeEnum.CUSTOMER_CREATED]: intl.formatMessage( - webhooksEventMessages.customerCreated - ), - [WebhookEventTypeEnum.ORDER_CANCELLED]: intl.formatMessage( - webhooksEventMessages.orderCancelled - ), - [WebhookEventTypeEnum.ORDER_CREATED]: intl.formatMessage( - webhooksEventMessages.orderCreated - ), - [WebhookEventTypeEnum.ORDER_FULLY_PAID]: intl.formatMessage( - webhooksEventMessages.orderFullyPaid - ), - [WebhookEventTypeEnum.ORDER_UPDATED]: intl.formatMessage( - webhooksEventMessages.orderUpdated - ), - [WebhookEventTypeEnum.PRODUCT_CREATED]: intl.formatMessage( - webhooksEventMessages.productCreated - ) -}); - export const authorizationKeyTypes = { [AuthorizationKeyType.FACEBOOK]: "Facebook", [AuthorizationKeyType.GOOGLE_OAUTH2]: "Google OAuth2" diff --git a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx index 110907a32..3473fe947 100644 --- a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx +++ b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx @@ -5,7 +5,6 @@ import CardTitle from "@saleor/components/CardTitle"; import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; import Hr from "@saleor/components/Hr"; import { ChangeEvent } from "@saleor/hooks/useForm"; -import { translatedWebhookEvents } from "@saleor/misc"; import { WebhookEventTypeEnum } from "@saleor/types/globalTypes"; import React from "react"; import { useIntl } from "react-intl"; @@ -26,7 +25,37 @@ const WebhookEvents: React.StatelessComponent = ({ }) => { const intl = useIntl(); const eventsEnum = Object.values(WebhookEventTypeEnum); - const translatedEvents = translatedWebhookEvents(intl); + + const translatedEvents = { + [WebhookEventTypeEnum.ANY_EVENTS]: intl.formatMessage({ + defaultMessage: "Any events", + description: "event" + }), + [WebhookEventTypeEnum.CUSTOMER_CREATED]: intl.formatMessage({ + defaultMessage: "Customer created", + description: "event" + }), + [WebhookEventTypeEnum.ORDER_CANCELLED]: intl.formatMessage({ + defaultMessage: "Order cancelled", + description: "event" + }), + [WebhookEventTypeEnum.ORDER_CREATED]: intl.formatMessage({ + defaultMessage: "Order created", + description: "event" + }), + [WebhookEventTypeEnum.ORDER_FULLY_PAID]: intl.formatMessage({ + defaultMessage: "Order fully paid", + description: "event" + }), + [WebhookEventTypeEnum.ORDER_UPDATED]: intl.formatMessage({ + defaultMessage: "Order updated", + description: "event" + }), + [WebhookEventTypeEnum.PRODUCT_CREATED]: intl.formatMessage({ + defaultMessage: "Product created", + description: "event" + }) + }; const handleAllEventsChange = (event: ChangeEvent) => onChange(event, () => From b4da5edb7ad049d68699956cfaffb8c9cdd1ca79 Mon Sep 17 00:00:00 2001 From: dominik-zeglen Date: Thu, 17 Oct 2019 13:47:11 +0200 Subject: [PATCH 21/38] Improve code consistency --- src/intl.ts | 1 + src/misc.ts | 157 +----------------- .../OrderDraftFinalizeDialog.tsx | 61 +++---- src/orders/views/OrderDetails/index.tsx | 10 +- .../CountryTaxesPage/CountryTaxesPage.tsx | 114 ++++++++++++- 5 files changed, 149 insertions(+), 194 deletions(-) diff --git a/src/intl.ts b/src/intl.ts index a15b105a1..4907da27a 100644 --- a/src/intl.ts +++ b/src/intl.ts @@ -1,4 +1,5 @@ import { defineMessages, IntlShape } from "react-intl"; +import { TaxRateType } from "./types/globalTypes"; export const commonMessages = defineMessages({ availability: { diff --git a/src/misc.ts b/src/misc.ts index 96bc1f921..54dd931ee 100644 --- a/src/misc.ts +++ b/src/misc.ts @@ -1,8 +1,8 @@ import moment from "moment-timezone"; import { MutationFunction, MutationResult } from "react-apollo"; +import { defineMessages, IntlShape } from "react-intl"; import urlJoin from "url-join"; -import { defineMessages, IntlShape } from "react-intl"; import { ConfirmButtonTransitionState } from "./components/ConfirmButton/ConfirmButton"; import { APP_MOUNT_URI } from "./config"; import { AddressType } from "./customers/types"; @@ -10,8 +10,7 @@ import { PartialMutationProviderOutput, UserError } from "./types"; import { AuthorizationKeyType, OrderStatus, - PaymentChargeStatusEnum, - TaxRateType + PaymentChargeStatusEnum } from "./types/globalTypes"; export type RequireAtLeastOne = Pick< @@ -181,158 +180,6 @@ export const transformAddressToForm = (data: AddressType) => ({ streetAddress2: maybe(() => data.streetAddress2, "") }); -const taxRatesMessages = defineMessages({ - accommodation: { - defaultMessage: "Accommodation", - description: "tax rate" - }, - admissionToCulturalEvents: { - defaultMessage: "Admission to cultural events", - description: "tax rate" - }, - admissionToEntertainmentEvents: { - defaultMessage: "Admission to entertainment events", - description: "tax rate" - }, - admissionToSportingEvents: { - defaultMessage: "Admission to sporting events", - description: "tax rate" - }, - advertising: { - defaultMessage: "Advertising", - description: "tax rate" - }, - agriculturalSupplies: { - defaultMessage: "Agricultural supplies", - description: "tax rate" - }, - babyFoodstuffs: { - defaultMessage: "Baby foodstuffs", - description: "tax rate" - }, - bikes: { - defaultMessage: "Bikes", - description: "tax rate" - }, - books: { - defaultMessage: "Books", - description: "tax rate" - }, - childrensClothing: { - defaultMessage: "Children's clothing", - description: "tax rate" - }, - domesticFuel: { - defaultMessage: "Domestic fuel", - description: "tax rate" - }, - domesticServices: { - defaultMessage: "Domestic services", - description: "tax rate" - }, - ebooks: { - defaultMessage: "E-books", - description: "tax rate" - }, - foodstuffs: { - defaultMessage: "Foodstuffs", - description: "tax rate" - }, - hotels: { - defaultMessage: "Hotels", - description: "tax rate" - }, - medical: { - defaultMessage: "Medical", - description: "tax rate" - }, - newspapers: { - defaultMessage: "Newspapers", - description: "tax rate" - }, - passengerTransport: { - defaultMessage: "Passenger transport", - description: "tax rate" - }, - pharmaceuticals: { - defaultMessage: "Pharmaceuticals", - description: "tax rate" - }, - propertyRenovations: { - defaultMessage: "Property renovations", - description: "tax rate" - }, - restaurants: { - defaultMessage: "Restaurants", - description: "tax rate" - }, - socialHousing: { - defaultMessage: "Social housing", - description: "tax rate" - }, - standard: { - defaultMessage: "Standard", - description: "tax rate" - }, - water: { - defaultMessage: "Water", - description: "tax rate" - } -}); - -export const translatedTaxRates = (intl: IntlShape) => ({ - [TaxRateType.ACCOMMODATION]: intl.formatMessage( - taxRatesMessages.accommodation - ), - [TaxRateType.ADMISSION_TO_CULTURAL_EVENTS]: intl.formatMessage( - taxRatesMessages.admissionToCulturalEvents - ), - [TaxRateType.ADMISSION_TO_ENTERTAINMENT_EVENTS]: intl.formatMessage( - taxRatesMessages.admissionToEntertainmentEvents - ), - [TaxRateType.ADMISSION_TO_SPORTING_EVENTS]: intl.formatMessage( - taxRatesMessages.admissionToSportingEvents - ), - [TaxRateType.ADVERTISING]: intl.formatMessage(taxRatesMessages.advertising), - [TaxRateType.AGRICULTURAL_SUPPLIES]: intl.formatMessage( - taxRatesMessages.agriculturalSupplies - ), - [TaxRateType.BABY_FOODSTUFFS]: intl.formatMessage( - taxRatesMessages.babyFoodstuffs - ), - [TaxRateType.BIKES]: intl.formatMessage(taxRatesMessages.bikes), - [TaxRateType.BOOKS]: intl.formatMessage(taxRatesMessages.books), - [TaxRateType.CHILDRENS_CLOTHING]: intl.formatMessage( - taxRatesMessages.childrensClothing - ), - [TaxRateType.DOMESTIC_FUEL]: intl.formatMessage( - taxRatesMessages.domesticFuel - ), - [TaxRateType.DOMESTIC_SERVICES]: intl.formatMessage( - taxRatesMessages.domesticServices - ), - [TaxRateType.E_BOOKS]: intl.formatMessage(taxRatesMessages.ebooks), - [TaxRateType.FOODSTUFFS]: intl.formatMessage(taxRatesMessages.foodstuffs), - [TaxRateType.HOTELS]: intl.formatMessage(taxRatesMessages.hotels), - [TaxRateType.MEDICAL]: intl.formatMessage(taxRatesMessages.medical), - [TaxRateType.NEWSPAPERS]: intl.formatMessage(taxRatesMessages.newspapers), - [TaxRateType.PASSENGER_TRANSPORT]: intl.formatMessage( - taxRatesMessages.passengerTransport - ), - [TaxRateType.PHARMACEUTICALS]: intl.formatMessage( - taxRatesMessages.pharmaceuticals - ), - [TaxRateType.PROPERTY_RENOVATIONS]: intl.formatMessage( - taxRatesMessages.propertyRenovations - ), - [TaxRateType.RESTAURANTS]: intl.formatMessage(taxRatesMessages.restaurants), - [TaxRateType.SOCIAL_HOUSING]: intl.formatMessage( - taxRatesMessages.socialHousing - ), - [TaxRateType.STANDARD]: intl.formatMessage(taxRatesMessages.standard), - [TaxRateType.WATER]: intl.formatMessage(taxRatesMessages.water) -}); - export const authorizationKeyTypes = { [AuthorizationKeyType.FACEBOOK]: "Facebook", [AuthorizationKeyType.GOOGLE_OAUTH2]: "Google OAuth2" diff --git a/src/orders/components/OrderDraftFinalizeDialog/OrderDraftFinalizeDialog.tsx b/src/orders/components/OrderDraftFinalizeDialog/OrderDraftFinalizeDialog.tsx index 91ae73a5f..03c7ed34b 100644 --- a/src/orders/components/OrderDraftFinalizeDialog/OrderDraftFinalizeDialog.tsx +++ b/src/orders/components/OrderDraftFinalizeDialog/OrderDraftFinalizeDialog.tsx @@ -5,12 +5,13 @@ import { FormattedMessage, IntlShape, useIntl } from "react-intl"; import ActionDialog from "@saleor/components/ActionDialog"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; -export type OrderDraftFinalizeWarning = - | "no-shipping" - | "no-billing" - | "no-user" - | "no-shipping-method" - | "unnecessary-shipping-method"; +export enum OrderDraftFinalizeWarning { + NO_SHIPPING, + NO_BILLING, + NO_USER, + NO_SHIPPING_METHOD, + UNNECESSARY_SHIPPING_METHOD +} export interface OrderDraftFinalizeDialogProps { confirmButtonState: ConfirmButtonTransitionState; @@ -21,30 +22,29 @@ export interface OrderDraftFinalizeDialogProps { onConfirm: () => void; } -const warningToText = (warning: OrderDraftFinalizeWarning, intl: IntlShape) => { - switch (warning) { - case "no-shipping": - return intl.formatMessage({ - defaultMessage: "No shipping address" - }); - case "no-billing": - return intl.formatMessage({ - defaultMessage: "No billing address" - }); - case "no-user": - return intl.formatMessage({ - defaultMessage: "No user information" - }); - case "no-shipping-method": - return intl.formatMessage({ - defaultMessage: "Some products require shipping, but no method provided" - }); - case "unnecessary-shipping-method": - return intl.formatMessage({ +function translateWarnings( + intl: IntlShape +): Record { + return { + [OrderDraftFinalizeWarning.NO_BILLING]: intl.formatMessage({ + defaultMessage: "No billing address" + }), + [OrderDraftFinalizeWarning.NO_SHIPPING]: intl.formatMessage({ + defaultMessage: "No shipping address" + }), + [OrderDraftFinalizeWarning.NO_SHIPPING_METHOD]: intl.formatMessage({ + defaultMessage: "Some products require shipping, but no method provided" + }), + [OrderDraftFinalizeWarning.NO_USER]: intl.formatMessage({ + defaultMessage: "No user information" + }), + [OrderDraftFinalizeWarning.UNNECESSARY_SHIPPING_METHOD]: intl.formatMessage( + { defaultMessage: "Shipping method provided, but no product requires it" - }); - } -}; + } + ) + }; +} const OrderDraftFinalizeDialog: React.StatelessComponent< OrderDraftFinalizeDialogProps @@ -57,6 +57,7 @@ const OrderDraftFinalizeDialog: React.StatelessComponent< orderNumber }) => { const intl = useIntl(); + const translatedWarnings = translateWarnings(intl); return (
    {warnings.map(warning => ( -
  • {warningToText(warning, intl)}
  • +
  • {translatedWarnings[warning]}
  • ))}
diff --git a/src/orders/views/OrderDetails/index.tsx b/src/orders/views/OrderDetails/index.tsx index 8a4052c42..928bbbf8a 100644 --- a/src/orders/views/OrderDetails/index.tsx +++ b/src/orders/views/OrderDetails/index.tsx @@ -38,13 +38,13 @@ import { OrderDetailsMessages } from "./OrderDetailsMessages"; const orderDraftFinalizeWarnings = (order: OrderDetails_order) => { const warnings = [] as OrderDraftFinalizeWarning[]; if (!(order && order.shippingAddress)) { - warnings.push("no-shipping"); + warnings.push(OrderDraftFinalizeWarning.NO_SHIPPING); } if (!(order && order.billingAddress)) { - warnings.push("no-billing"); + warnings.push(OrderDraftFinalizeWarning.NO_BILLING); } if (!(order && (order.user || order.userEmail))) { - warnings.push("no-user"); + warnings.push(OrderDraftFinalizeWarning.NO_USER); } if ( order && @@ -52,7 +52,7 @@ const orderDraftFinalizeWarnings = (order: OrderDetails_order) => { order.lines.filter(line => line.isShippingRequired).length > 0 && order.shippingMethod === null ) { - warnings.push("no-shipping-method"); + warnings.push(OrderDraftFinalizeWarning.NO_SHIPPING_METHOD); } if ( order && @@ -60,7 +60,7 @@ const orderDraftFinalizeWarnings = (order: OrderDetails_order) => { order.lines.filter(line => line.isShippingRequired).length === 0 && order.shippingMethod !== null ) { - warnings.push("unnecessary-shipping-method"); + warnings.push(OrderDraftFinalizeWarning.UNNECESSARY_SHIPPING_METHOD); } return warnings; }; diff --git a/src/taxes/components/CountryTaxesPage/CountryTaxesPage.tsx b/src/taxes/components/CountryTaxesPage/CountryTaxesPage.tsx index b1ddf1f72..ad251f9e3 100644 --- a/src/taxes/components/CountryTaxesPage/CountryTaxesPage.tsx +++ b/src/taxes/components/CountryTaxesPage/CountryTaxesPage.tsx @@ -6,7 +6,7 @@ import TableCell from "@material-ui/core/TableCell"; import TableHead from "@material-ui/core/TableHead"; import TableRow from "@material-ui/core/TableRow"; import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; +import { FormattedMessage, IntlShape, useIntl } from "react-intl"; import AppHeader from "@saleor/components/AppHeader"; import { Container } from "@saleor/components/Container"; @@ -14,7 +14,8 @@ import Grid from "@saleor/components/Grid"; import PageHeader from "@saleor/components/PageHeader"; import Skeleton from "@saleor/components/Skeleton"; import { sectionNames } from "@saleor/intl"; -import { maybe, renderCollection, translatedTaxRates } from "../../../misc"; +import { TaxRateType } from "@saleor/types/globalTypes"; +import { maybe, renderCollection } from "../../../misc"; import { CountryList_shop_countries_vat_reducedRates } from "../../types/CountryList"; const styles = createStyles({ @@ -23,6 +24,111 @@ const styles = createStyles({ } }); +function translateTaxRates(intl: IntlShape): Record { + return { + [TaxRateType.ACCOMMODATION]: intl.formatMessage({ + defaultMessage: "Accommodation", + description: "tax rate" + }), + [TaxRateType.ADMISSION_TO_CULTURAL_EVENTS]: intl.formatMessage({ + defaultMessage: "Admission to cultural events", + description: "tax rate" + }), + [TaxRateType.ADMISSION_TO_ENTERTAINMENT_EVENTS]: intl.formatMessage({ + defaultMessage: "Admission to entertainment events", + description: "tax rate" + }), + [TaxRateType.ADMISSION_TO_SPORTING_EVENTS]: intl.formatMessage({ + defaultMessage: "Admission to sporting events", + description: "tax rate" + }), + [TaxRateType.ADVERTISING]: intl.formatMessage({ + defaultMessage: "Advertising", + description: "tax rate" + }), + [TaxRateType.AGRICULTURAL_SUPPLIES]: intl.formatMessage({ + defaultMessage: "Agricultural supplies", + description: "tax rate" + }), + [TaxRateType.BABY_FOODSTUFFS]: intl.formatMessage({ + defaultMessage: "Baby foodstuffs", + description: "tax rate" + }), + [TaxRateType.BIKES]: intl.formatMessage({ + defaultMessage: "Bikes", + description: "tax rate" + }), + [TaxRateType.BOOKS]: intl.formatMessage({ + defaultMessage: "Books", + description: "tax rate" + }), + [TaxRateType.CHILDRENS_CLOTHING]: intl.formatMessage({ + defaultMessage: "Children's clothing", + description: "tax rate" + }), + [TaxRateType.DOMESTIC_FUEL]: intl.formatMessage({ + defaultMessage: "Domestic fuel", + description: "tax rate" + }), + [TaxRateType.DOMESTIC_SERVICES]: intl.formatMessage({ + defaultMessage: "Domestic services", + description: "tax rate" + }), + [TaxRateType.E_BOOKS]: intl.formatMessage({ + defaultMessage: "E-books", + description: "tax rate" + }), + [TaxRateType.FOODSTUFFS]: intl.formatMessage({ + defaultMessage: "Foodstuffs", + description: "tax rate" + }), + [TaxRateType.HOTELS]: intl.formatMessage({ + defaultMessage: "Hotels", + description: "tax rate" + }), + [TaxRateType.MEDICAL]: intl.formatMessage({ + defaultMessage: "Medical", + description: "tax rate" + }), + [TaxRateType.NEWSPAPERS]: intl.formatMessage({ + defaultMessage: "Newspapers", + description: "tax rate" + }), + [TaxRateType.PASSENGER_TRANSPORT]: intl.formatMessage({ + defaultMessage: "Passenger transport", + description: "tax rate" + }), + [TaxRateType.PHARMACEUTICALS]: intl.formatMessage({ + defaultMessage: "Pharmaceuticals", + description: "tax rate" + }), + [TaxRateType.PROPERTY_RENOVATIONS]: intl.formatMessage({ + defaultMessage: "Property renovations", + description: "tax rate" + }), + [TaxRateType.RESTAURANTS]: intl.formatMessage({ + defaultMessage: "Restaurants", + description: "tax rate" + }), + [TaxRateType.SOCIAL_HOUSING]: intl.formatMessage({ + defaultMessage: "Social housing", + description: "tax rate" + }), + [TaxRateType.STANDARD]: intl.formatMessage({ + defaultMessage: "Standard", + description: "tax rate" + }), + [TaxRateType.WATER]: intl.formatMessage({ + defaultMessage: "Water", + description: "tax rate" + }), + [TaxRateType.WINE]: intl.formatMessage({ + defaultMessage: "Wine", + description: "tax rate" + }) + }; +} + export interface CountryTaxesPageProps { countryName: string; taxCategories: CountryList_shop_countries_vat_reducedRates[]; @@ -37,8 +143,8 @@ const CountryTaxesPage = withStyles(styles, { name: "CountryTaxesPage" })( onBack }: CountryTaxesPageProps & WithStyles) => { const intl = useIntl(); + const translatedTaxRates = translateTaxRates(intl); - const taxRates = translatedTaxRates(intl); return ( @@ -82,7 +188,7 @@ const CountryTaxesPage = withStyles(styles, { name: "CountryTaxesPage" })( > {maybe( - () => taxRates[taxCategory.rateType], + () => translatedTaxRates[taxCategory.rateType], )} From 297b04074bfbfc98d754df8a672412420000a759 Mon Sep 17 00:00:00 2001 From: dominik-zeglen Date: Thu, 17 Oct 2019 13:53:17 +0200 Subject: [PATCH 22/38] Fix types --- src/intl.ts | 1 - .../stories/orders/OrderDraftFinalizeDialog.tsx | 10 ++++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/intl.ts b/src/intl.ts index 4907da27a..a15b105a1 100644 --- a/src/intl.ts +++ b/src/intl.ts @@ -1,5 +1,4 @@ import { defineMessages, IntlShape } from "react-intl"; -import { TaxRateType } from "./types/globalTypes"; export const commonMessages = defineMessages({ availability: { diff --git a/src/storybook/stories/orders/OrderDraftFinalizeDialog.tsx b/src/storybook/stories/orders/OrderDraftFinalizeDialog.tsx index 5df866e84..13195baff 100644 --- a/src/storybook/stories/orders/OrderDraftFinalizeDialog.tsx +++ b/src/storybook/stories/orders/OrderDraftFinalizeDialog.tsx @@ -2,7 +2,8 @@ import { storiesOf } from "@storybook/react"; import React from "react"; import OrderDraftFinalize, { - OrderDraftFinalizeDialogProps + OrderDraftFinalizeDialogProps, + OrderDraftFinalizeWarning } from "../../../orders/components/OrderDraftFinalizeDialog"; import Decorator from "../../Decorator"; @@ -21,6 +22,11 @@ storiesOf("Orders / OrderDraftFinalizeDialog", module) .add("with warnings", () => ( )); From 7bd69bf83397641a0615b98a77fa6bd293e10376 Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Thu, 17 Oct 2019 13:59:18 +0200 Subject: [PATCH 23/38] Fix commented issues --- src/misc.ts | 3 +- .../WebhookCreatePage/WebhookCreatePage.tsx | 24 +++++----- .../WebhooksCreatePage.stories.tsx | 2 +- .../WebhookDeleteDialog.stories.tsx | 2 +- .../WebhookEvents/WebhookEvents.tsx | 28 ++++++------ .../components/WebhookInfo/WebhookInfo.tsx | 8 ++-- .../WebhooksDetailsPage.stories.tsx | 2 +- .../WebhooksDetailsPage.tsx | 20 ++++----- .../components/WebhooksList/WebhooksList.tsx | 2 +- src/webhooks/fixtures.ts | 14 +++--- src/webhooks/queries.ts | 4 +- src/webhooks/types/ServiceFragment.ts | 14 ------ src/webhooks/types/ServiceList.ts | 44 ------------------- src/webhooks/types/Webhook.ts | 39 ---------------- src/webhooks/views/WebhooksCreate.tsx | 6 +-- src/webhooks/views/WebhooksDetails.tsx | 19 ++++---- src/webhooks/views/WebhooksList.tsx | 7 ++- 17 files changed, 64 insertions(+), 174 deletions(-) delete mode 100644 src/webhooks/types/ServiceFragment.ts delete mode 100644 src/webhooks/types/ServiceList.ts delete mode 100644 src/webhooks/types/Webhook.ts diff --git a/src/misc.ts b/src/misc.ts index 4217de160..96bc1f921 100644 --- a/src/misc.ts +++ b/src/misc.ts @@ -11,8 +11,7 @@ import { AuthorizationKeyType, OrderStatus, PaymentChargeStatusEnum, - TaxRateType, - WebhookEventTypeEnum + TaxRateType } from "./types/globalTypes"; export type RequireAtLeastOne = Pick< diff --git a/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx b/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx index 2c5c993fe..ac5de0bfa 100644 --- a/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx +++ b/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx @@ -6,7 +6,7 @@ import FormSpacer from "@saleor/components/FormSpacer"; import Grid from "@saleor/components/Grid"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; -import useStateFromProps from "@saleor/hooks/useStateFromProps"; +import { SearchServiceAccount_serviceAccounts_edges_node } from "@saleor/containers/SearchServiceAccount/types/SearchServiceAccount"; import { sectionNames } from "@saleor/intl"; import { maybe } from "@saleor/misc"; import { UserError } from "@saleor/types"; @@ -32,12 +32,9 @@ export interface FormData { export interface WebhookCreatePageProps { disabled: boolean; errors: UserError[]; - services?: Array<{ - id: string; - name: string; - }>; + services?: SearchServiceAccount_serviceAccounts_edges_node[]; saveButtonBarState: ConfirmButtonTransitionState; - fetchServiceAccount: (data: string) => void; + fetchServiceAccounts: (data: string) => void; onBack: () => void; onSubmit: (data: FormData) => void; } @@ -47,7 +44,7 @@ const WebhookCreatePage: React.StatelessComponent = ({ errors, saveButtonBarState, services, - fetchServiceAccount, + fetchServiceAccounts, onBack, onSubmit }) => { @@ -62,10 +59,9 @@ const WebhookCreatePage: React.StatelessComponent = ({ serviceAccount: "", targetUrl: "" }; - const [ - selectedServiceAcccounts, - setSelectedServiceAcccounts - ] = useStateFromProps(""); + const [selectedServiceAcccount, setSelectedServiceAcccount] = React.useState( + "" + ); const servicesChoiceList = maybe( () => services.map(node => ({ @@ -80,7 +76,7 @@ const WebhookCreatePage: React.StatelessComponent = ({ {({ data, errors, hasChanged, submit, change }) => { const handleServiceSelect = createSingleAutocompleteSelectHandler( change, - setSelectedServiceAcccounts, + setSelectedServiceAcccount, servicesChoiceList ); return ( @@ -99,9 +95,9 @@ const WebhookCreatePage: React.StatelessComponent = ({ undefined, + fetchServiceAccounts: () => undefined, onBack: () => undefined, onSubmit: () => undefined, saveButtonBarState: "default", diff --git a/src/webhooks/components/WebhookDeleteDialog/WebhookDeleteDialog.stories.tsx b/src/webhooks/components/WebhookDeleteDialog/WebhookDeleteDialog.stories.tsx index a21cab3d9..1117de287 100644 --- a/src/webhooks/components/WebhookDeleteDialog/WebhookDeleteDialog.stories.tsx +++ b/src/webhooks/components/WebhookDeleteDialog/WebhookDeleteDialog.stories.tsx @@ -14,6 +14,6 @@ const props: WebhookDeleteDialogProps = { open: true }; -storiesOf("Views / Services / Delete service", module) +storiesOf("Views / Webhooks / Delete webhook", module) .addDecorator(Decorator) .add("default", () => ); diff --git a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx index 3473fe947..21659b006 100644 --- a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx +++ b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx @@ -64,7 +64,7 @@ const WebhookEvents: React.StatelessComponent = ({ name: "events", value: event.target.value ? WebhookEventTypeEnum.ANY_EVENTS : [] } - } as any) + }) ); const handleEventsChange = (event: ChangeEvent) => { @@ -75,7 +75,7 @@ const WebhookEvents: React.StatelessComponent = ({ ? data.events.concat([event.target.name]) : data.events.filter(events => events !== event.target.name) } - } as any); + }); }; return ( @@ -104,19 +104,17 @@ const WebhookEvents: React.StatelessComponent = ({ {!data.allEvents && ( <>
- {eventsEnum.slice(1).map(event => { - return ( -
- -
- ); - })} + {eventsEnum.slice(1).map(event => ( +
+ +
+ ))} )} diff --git a/src/webhooks/components/WebhookInfo/WebhookInfo.tsx b/src/webhooks/components/WebhookInfo/WebhookInfo.tsx index ec2c92118..61585444d 100644 --- a/src/webhooks/components/WebhookInfo/WebhookInfo.tsx +++ b/src/webhooks/components/WebhookInfo/WebhookInfo.tsx @@ -26,7 +26,7 @@ interface WebhookInfoProps { errors: FormErrors<"name" | "targetUrl" | "secretKey">; onChange: (event: React.ChangeEvent) => void; serviceOnChange: (event: ChangeEvent) => void; - fetchServiceAccount: (data: string) => void; + fetchServiceAccounts: (data: string) => void; } const useStyles = makeStyles(() => ({ @@ -45,7 +45,7 @@ const WebhookInfo: React.StatelessComponent = ({ disabled, services, serviceDisplayValue, - fetchServiceAccount, + fetchServiceAccounts, errors, onChange, serviceOnChange @@ -97,7 +97,7 @@ const WebhookInfo: React.StatelessComponent = ({ onChange={serviceOnChange} value={data.serviceAccount} choices={services} - fetchChoices={fetchServiceAccount} + fetchChoices={fetchServiceAccounts} InputProps={{ autoComplete: "off" }} @@ -107,7 +107,7 @@ const WebhookInfo: React.StatelessComponent = ({ disabled={disabled} error={!!errors.targetUrl} helperText={intl.formatMessage({ - defaultMessage: "This URL will recieve webhook POST requests", + defaultMessage: "This URL will receive webhook POST requests", description: "webhook target url help text" })} label={intl.formatMessage({ diff --git a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx index 9dc02a58c..6742e3126 100644 --- a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx +++ b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx @@ -10,7 +10,7 @@ import WebhooksDetailsPage, { const props: WebhooksDetailsPageProps = { disabled: false, errors: [], - fetchServiceAccount: () => undefined, + fetchServiceAccounts: () => undefined, onBack: () => undefined, onDelete: () => undefined, onSubmit: () => undefined, diff --git a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx index 292635e1e..d1057e2ca 100644 --- a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx +++ b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx @@ -6,6 +6,7 @@ import FormSpacer from "@saleor/components/FormSpacer"; import Grid from "@saleor/components/Grid"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import { SearchServiceAccount_serviceAccounts_edges_node } from "@saleor/containers/SearchServiceAccount/types/SearchServiceAccount"; import useStateFromProps from "@saleor/hooks/useStateFromProps"; import { sectionNames } from "@saleor/intl"; import { maybe } from "@saleor/misc"; @@ -15,7 +16,7 @@ import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/single import WebhookEvents from "@saleor/webhooks/components/WebhookEvents"; import WebhookInfo from "@saleor/webhooks/components/WebhookInfo"; import WebhookStatus from "@saleor/webhooks/components/WebhookStatus"; -import { Webhook_webhook } from "@saleor/webhooks/types/Webhook"; +import { WebhookDetails_webhook } from "@saleor/webhooks/types/WebhookDetails"; import React from "react"; import { useIntl } from "react-intl"; @@ -34,27 +35,22 @@ export interface FormData { export interface WebhooksDetailsPageProps { disabled: boolean; errors: UserError[]; - webhook: Webhook_webhook; - services?: Array<{ - id: string; - name: string; - }>; + webhook: WebhookDetails_webhook; + services?: SearchServiceAccount_serviceAccounts_edges_node[]; saveButtonBarState: ConfirmButtonTransitionState; onBack: () => void; onDelete: () => void; - fetchServiceAccount: (data: string) => void; + fetchServiceAccounts: (data: string) => void; onSubmit: (data: FormData) => void; } -const WebhooksDetailsPage: React.StatelessComponent< - WebhooksDetailsPageProps -> = ({ +const WebhooksDetailsPage: React.FC = ({ disabled, errors, webhook, saveButtonBarState, services, - fetchServiceAccount, + fetchServiceAccounts, onBack, onDelete, onSubmit @@ -115,7 +111,7 @@ const WebhooksDetailsPage: React.StatelessComponent< disabled={disabled} serviceDisplayValue={selectedServiceAcccounts} services={servicesChoiceList} - fetchServiceAccount={fetchServiceAccount} + fetchServiceAccounts={fetchServiceAccounts} errors={errors} serviceOnChange={handleServiceSelect} onChange={change} diff --git a/src/webhooks/components/WebhooksList/WebhooksList.tsx b/src/webhooks/components/WebhooksList/WebhooksList.tsx index 6a41c087f..ac24b79e5 100644 --- a/src/webhooks/components/WebhooksList/WebhooksList.tsx +++ b/src/webhooks/components/WebhooksList/WebhooksList.tsx @@ -43,7 +43,7 @@ const useStyles = makeStyles((theme: Theme) => ({ } })); -const numberOfColumns = 4; +const numberOfColumns = 3; const WebhooksList: React.FC = ({ settings, diff --git a/src/webhooks/fixtures.ts b/src/webhooks/fixtures.ts index 4149bdb9c..46eab5ef9 100644 --- a/src/webhooks/fixtures.ts +++ b/src/webhooks/fixtures.ts @@ -1,18 +1,16 @@ -import { ServiceList_serviceAccounts_edges_node } from "./types/ServiceList"; -import { Webhook_webhook } from "./types/Webhook"; +import { SearchServiceAccount_serviceAccounts_edges_node } from "@saleor/containers/SearchServiceAccount/types/SearchServiceAccount"; +import { WebhookDetails_webhook } from "./types/WebhookDetails"; import { Webhooks_webhooks_edges_node } from "./types/Webhooks"; -export const services: ServiceList_serviceAccounts_edges_node[] = [ +export const services: SearchServiceAccount_serviceAccounts_edges_node[] = [ { __typename: "ServiceAccount", id: "Jzx123sEt==", - isActive: true, name: "Facebook" }, { __typename: "ServiceAccount", id: "Jzx123sEt==", - isActive: false, name: "Twittwe" } ]; @@ -26,7 +24,7 @@ export const webhookList: Webhooks_webhooks_edges_node[] = [ __typename: "ServiceAccount", id: "Jzx123sEt==", name: "Test Account" - }, + } }, { __typename: "Webhook", @@ -37,10 +35,10 @@ export const webhookList: Webhooks_webhooks_edges_node[] = [ __typename: "ServiceAccount", id: "Jzx1ss23sEt==", name: "Test Account 2" - }, + } } ]; -export const webhook: Webhook_webhook = { +export const webhook: WebhookDetails_webhook = { __typename: "Webhook", events: [], id: "Jzx123sEt==", diff --git a/src/webhooks/queries.ts b/src/webhooks/queries.ts index bee136ee3..bdfdedf4d 100644 --- a/src/webhooks/queries.ts +++ b/src/webhooks/queries.ts @@ -1,7 +1,7 @@ import gql from "graphql-tag"; import { TypedQuery } from "../queries"; -import { Webhook, WebhookVariables } from "./types/Webhook"; +import { WebhookDetails, WebhookDetailsVariables } from "./types/WebhookDetails"; import { Webhooks, WebhooksVariables } from "./types/Webhooks"; export const webhooksFragment = gql` @@ -70,6 +70,6 @@ const webhooksDetails = gql` } } `; -export const TypedWebhooksDetailsQuery = TypedQuery( +export const TypedWebhooksDetailsQuery = TypedQuery( webhooksDetails ); diff --git a/src/webhooks/types/ServiceFragment.ts b/src/webhooks/types/ServiceFragment.ts deleted file mode 100644 index 5c0e96fec..000000000 --- a/src/webhooks/types/ServiceFragment.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -// ==================================================== -// GraphQL fragment: ServiceFragment -// ==================================================== - -export interface ServiceFragment { - __typename: "ServiceAccount"; - id: string; - name: string | null; - isActive: boolean | null; -} diff --git a/src/webhooks/types/ServiceList.ts b/src/webhooks/types/ServiceList.ts deleted file mode 100644 index fe971e15d..000000000 --- a/src/webhooks/types/ServiceList.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -// ==================================================== -// GraphQL query operation: ServiceList -// ==================================================== - -export interface ServiceList_serviceAccounts_edges_node { - __typename: "ServiceAccount"; - id: string; - name: string | null; - isActive: boolean | null; -} - -export interface ServiceList_serviceAccounts_edges { - __typename: "ServiceAccountCountableEdge"; - node: ServiceList_serviceAccounts_edges_node; -} - -export interface ServiceList_serviceAccounts_pageInfo { - __typename: "PageInfo"; - hasPreviousPage: boolean; - hasNextPage: boolean; - startCursor: string | null; - endCursor: string | null; -} - -export interface ServiceList_serviceAccounts { - __typename: "ServiceAccountCountableConnection"; - edges: ServiceList_serviceAccounts_edges[]; - pageInfo: ServiceList_serviceAccounts_pageInfo; -} - -export interface ServiceList { - serviceAccounts: ServiceList_serviceAccounts | null; -} - -export interface ServiceListVariables { - first?: number | null; - after?: string | null; - last?: number | null; - before?: string | null; -} diff --git a/src/webhooks/types/Webhook.ts b/src/webhooks/types/Webhook.ts deleted file mode 100644 index abcdd8141..000000000 --- a/src/webhooks/types/Webhook.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -import { WebhookEventTypeEnum } from "./../../types/globalTypes"; - -// ==================================================== -// GraphQL query operation: Webhook -// ==================================================== - -export interface Webhook_webhook_events { - __typename: "WebhookEvent"; - eventType: WebhookEventTypeEnum | null; -} - -export interface Webhook_webhook_serviceAccount { - __typename: "ServiceAccount"; - id: string; - name: string | null; -} - -export interface Webhook_webhook { - __typename: "Webhook"; - id: string; - name: string | null; - events: (Webhook_webhook_events | null)[] | null; - isActive: boolean; - secretKey: string | null; - targetUrl: string; - serviceAccount: Webhook_webhook_serviceAccount; -} - -export interface Webhook { - webhook: Webhook_webhook | null; -} - -export interface WebhookVariables { - id: string; -} diff --git a/src/webhooks/views/WebhooksCreate.tsx b/src/webhooks/views/WebhooksCreate.tsx index 95489131e..afa3c906c 100644 --- a/src/webhooks/views/WebhooksCreate.tsx +++ b/src/webhooks/views/WebhooksCreate.tsx @@ -44,9 +44,9 @@ export const WebhooksCreate: React.StatelessComponent< {({ search: searchServiceAccount, result: searchServiceAccountOpt }) => ( - {(WebhookCreate, webhookCreateOpts) => { + {(webhookCreate, webhookCreateOpts) => { const handleSubmit = (data: FormData) => - WebhookCreate({ + webhookCreate({ variables: { input: { events: data.allEvents @@ -81,7 +81,7 @@ export const WebhooksCreate: React.StatelessComponent< () => webhookCreateOpts.data.webhookCreate.errors, [] )} - fetchServiceAccount={searchServiceAccount} + fetchServiceAccounts={searchServiceAccount} services={maybe(() => searchServiceAccountOpt.data.serviceAccounts.edges.map( edge => edge.node diff --git a/src/webhooks/views/WebhooksDetails.tsx b/src/webhooks/views/WebhooksDetails.tsx index 7590634f3..8ed049baf 100644 --- a/src/webhooks/views/WebhooksDetails.tsx +++ b/src/webhooks/views/WebhooksDetails.tsx @@ -26,9 +26,10 @@ export interface WebhooksDetailsProps { params: WebhooksListUrlQueryParams; } -export const WebhooksDetails: React.StatelessComponent< - WebhooksDetailsProps -> = ({ id, params }) => { +export const WebhooksDetails: React.FC = ({ + id, + params +}) => { const navigate = useNavigator(); const notify = useNotifier(); const intl = useIntl(); @@ -78,7 +79,7 @@ export const WebhooksDetails: React.StatelessComponent< {(webhookDelete, webhookDeleteOpts) => ( - {WebhookDetails => { + {webhookDetails => { const formTransitionState = getMutationState( webhookUpdateOpts.called, webhookUpdateOpts.loading, @@ -106,14 +107,14 @@ export const WebhooksDetails: React.StatelessComponent< return ( <> WebhookDetails.data.webhook.name)} + title={maybe(() => webhookDetails.data.webhook.name)} /> WebhookDetails.data.webhook)} - fetchServiceAccount={searchServiceAccount} + webhook={maybe(() => webhookDetails.data.webhook)} + fetchServiceAccounts={searchServiceAccount} services={maybe(() => searchServiceAccountOpt.data.serviceAccounts.edges.map( edge => edge.node @@ -142,7 +143,7 @@ export const WebhooksDetails: React.StatelessComponent< WebhookDetails.data.webhook.name, + () => webhookDetails.data.webhook.name, "..." )} onClose={closeModal} diff --git a/src/webhooks/views/WebhooksList.tsx b/src/webhooks/views/WebhooksList.tsx index 44ed2bdd5..beeeb9b5d 100644 --- a/src/webhooks/views/WebhooksList.tsx +++ b/src/webhooks/views/WebhooksList.tsx @@ -20,7 +20,8 @@ import { useIntl } from "react-intl"; import WebhooksListPage from "../components/WebhooksListPage/WebhooksListPage"; import { TypedWebhookDelete } from "../mutations"; import { TypedWebhooksListQuery } from "../queries"; -import { WebhookListUrlDialog, +import { + WebhookListUrlDialog, WebhookListUrlFilters, webhooksAddUrl, webhooksListUrl, @@ -40,9 +41,7 @@ interface WebhooksListProps { params: WebhooksListUrlQueryParams; } -export const WebhooksList: React.StatelessComponent = ({ - params -}) => { +export const WebhooksList: React.FC = ({ params }) => { const navigate = useNavigator(); const paginate = usePaginator(); const notify = useNotifier(); From f84493fdab55cb5a466ab894970d74e20cb843ee Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Thu, 17 Oct 2019 14:38:01 +0200 Subject: [PATCH 24/38] Fix service account search --- src/containers/SearchServiceAccount/index.tsx | 20 +++++++++++++----- .../types/searchServiceAccount.ts | 21 +++++++++++++------ .../WebhookCreatePage/WebhookCreatePage.tsx | 4 ++-- .../components/WebhookInfo/WebhookInfo.tsx | 5 ++--- .../WebhooksDetailsPage.tsx | 4 ++-- src/webhooks/fixtures.ts | 4 ++-- src/webhooks/views/WebhooksCreate.tsx | 2 +- src/webhooks/views/WebhooksDetails.tsx | 2 +- 8 files changed, 40 insertions(+), 22 deletions(-) diff --git a/src/containers/SearchServiceAccount/index.tsx b/src/containers/SearchServiceAccount/index.tsx index af3574f7d..b617f92cf 100644 --- a/src/containers/SearchServiceAccount/index.tsx +++ b/src/containers/SearchServiceAccount/index.tsx @@ -1,24 +1,34 @@ import gql from "graphql-tag"; -import BaseSearch from "../BaseSearch"; +import { pageInfoFragment } from "@saleor/queries"; +import TopLevelSearch from "../TopLevelSearch"; import { SearchServiceAccount, SearchServiceAccountVariables } from "./types/searchServiceAccount"; export const searchServiceAccount = gql` + ${pageInfoFragment} query SearchServiceAccount($after: String, $first: Int!, $query: String!) { - serviceAccounts(after: $after, first: $first, filter: { search: $query }) { + search: serviceAccounts( + after: $after + first: $first + filter: { search: $query } + ) { edges { node { id name } } + pageInfo { + ...PageInfoFragment + } } } `; -export default BaseSearch( - searchServiceAccount -); +export default TopLevelSearch< + SearchServiceAccount, + SearchServiceAccountVariables +>(searchServiceAccount); diff --git a/src/containers/SearchServiceAccount/types/searchServiceAccount.ts b/src/containers/SearchServiceAccount/types/searchServiceAccount.ts index fbe54676e..33c63466c 100644 --- a/src/containers/SearchServiceAccount/types/searchServiceAccount.ts +++ b/src/containers/SearchServiceAccount/types/searchServiceAccount.ts @@ -6,24 +6,33 @@ // GraphQL query operation: SearchServiceAccount // ==================================================== -export interface SearchServiceAccount_serviceAccounts_edges_node { +export interface SearchServiceAccount_search_edges_node { __typename: "ServiceAccount"; id: string; name: string | null; } -export interface SearchServiceAccount_serviceAccounts_edges { +export interface SearchServiceAccount_search_edges { __typename: "ServiceAccountCountableEdge"; - node: SearchServiceAccount_serviceAccounts_edges_node; + node: SearchServiceAccount_search_edges_node; } -export interface SearchServiceAccount_serviceAccounts { +export interface SearchServiceAccount_search_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface SearchServiceAccount_search { __typename: "ServiceAccountCountableConnection"; - edges: SearchServiceAccount_serviceAccounts_edges[]; + edges: SearchServiceAccount_search_edges[]; + pageInfo: SearchServiceAccount_search_pageInfo; } export interface SearchServiceAccount { - serviceAccounts: SearchServiceAccount_serviceAccounts | null; + search: SearchServiceAccount_search | null; } export interface SearchServiceAccountVariables { diff --git a/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx b/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx index ac5de0bfa..95568c615 100644 --- a/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx +++ b/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx @@ -6,7 +6,7 @@ import FormSpacer from "@saleor/components/FormSpacer"; import Grid from "@saleor/components/Grid"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; -import { SearchServiceAccount_serviceAccounts_edges_node } from "@saleor/containers/SearchServiceAccount/types/SearchServiceAccount"; +import { SearchServiceAccount_search_edges_node } from "@saleor/containers/SearchServiceAccount/types/SearchServiceAccount"; import { sectionNames } from "@saleor/intl"; import { maybe } from "@saleor/misc"; import { UserError } from "@saleor/types"; @@ -32,7 +32,7 @@ export interface FormData { export interface WebhookCreatePageProps { disabled: boolean; errors: UserError[]; - services?: SearchServiceAccount_serviceAccounts_edges_node[]; + services?: SearchServiceAccount_search_edges_node[]; saveButtonBarState: ConfirmButtonTransitionState; fetchServiceAccounts: (data: string) => void; onBack: () => void; diff --git a/src/webhooks/components/WebhookInfo/WebhookInfo.tsx b/src/webhooks/components/WebhookInfo/WebhookInfo.tsx index 61585444d..387f1d6dc 100644 --- a/src/webhooks/components/WebhookInfo/WebhookInfo.tsx +++ b/src/webhooks/components/WebhookInfo/WebhookInfo.tsx @@ -9,9 +9,8 @@ import { useIntl } from "react-intl"; import CardTitle from "@saleor/components/CardTitle"; import FormSpacer from "@saleor/components/FormSpacer"; import Hr from "@saleor/components/Hr"; -import { - SingleAutocompleteChoiceType, - SingleAutocompleteSelectField +import SingleAutocompleteSelectField, { + SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField"; import { ChangeEvent } from "@saleor/hooks/useForm"; import { commonMessages } from "@saleor/intl"; diff --git a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx index d1057e2ca..6f53bcc69 100644 --- a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx +++ b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx @@ -6,7 +6,7 @@ import FormSpacer from "@saleor/components/FormSpacer"; import Grid from "@saleor/components/Grid"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; -import { SearchServiceAccount_serviceAccounts_edges_node } from "@saleor/containers/SearchServiceAccount/types/SearchServiceAccount"; +import { SearchServiceAccount_search_edges_node } from "@saleor/containers/SearchServiceAccount/types/SearchServiceAccount"; import useStateFromProps from "@saleor/hooks/useStateFromProps"; import { sectionNames } from "@saleor/intl"; import { maybe } from "@saleor/misc"; @@ -36,7 +36,7 @@ export interface WebhooksDetailsPageProps { disabled: boolean; errors: UserError[]; webhook: WebhookDetails_webhook; - services?: SearchServiceAccount_serviceAccounts_edges_node[]; + services?: SearchServiceAccount_search_edges_node[]; saveButtonBarState: ConfirmButtonTransitionState; onBack: () => void; onDelete: () => void; diff --git a/src/webhooks/fixtures.ts b/src/webhooks/fixtures.ts index 46eab5ef9..6b55347fc 100644 --- a/src/webhooks/fixtures.ts +++ b/src/webhooks/fixtures.ts @@ -1,8 +1,8 @@ -import { SearchServiceAccount_serviceAccounts_edges_node } from "@saleor/containers/SearchServiceAccount/types/SearchServiceAccount"; +import { SearchServiceAccount_search_edges_node } from "@saleor/containers/SearchServiceAccount/types/SearchServiceAccount"; import { WebhookDetails_webhook } from "./types/WebhookDetails"; import { Webhooks_webhooks_edges_node } from "./types/Webhooks"; -export const services: SearchServiceAccount_serviceAccounts_edges_node[] = [ +export const services: SearchServiceAccount_search_edges_node[] = [ { __typename: "ServiceAccount", id: "Jzx123sEt==", diff --git a/src/webhooks/views/WebhooksCreate.tsx b/src/webhooks/views/WebhooksCreate.tsx index afa3c906c..4ee01b5cb 100644 --- a/src/webhooks/views/WebhooksCreate.tsx +++ b/src/webhooks/views/WebhooksCreate.tsx @@ -83,7 +83,7 @@ export const WebhooksCreate: React.StatelessComponent< )} fetchServiceAccounts={searchServiceAccount} services={maybe(() => - searchServiceAccountOpt.data.serviceAccounts.edges.map( + searchServiceAccountOpt.data.search.edges.map( edge => edge.node ) )} diff --git a/src/webhooks/views/WebhooksDetails.tsx b/src/webhooks/views/WebhooksDetails.tsx index 8ed049baf..89099dc50 100644 --- a/src/webhooks/views/WebhooksDetails.tsx +++ b/src/webhooks/views/WebhooksDetails.tsx @@ -116,7 +116,7 @@ export const WebhooksDetails: React.FC = ({ webhook={maybe(() => webhookDetails.data.webhook)} fetchServiceAccounts={searchServiceAccount} services={maybe(() => - searchServiceAccountOpt.data.serviceAccounts.edges.map( + searchServiceAccountOpt.data.search.edges.map( edge => edge.node ) )} From 57a3ed88aea6e606efd53695ac02c84017682883 Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Thu, 17 Oct 2019 14:41:32 +0200 Subject: [PATCH 25/38] Update snapshots --- .../__snapshots__/Stories.test.ts.snap | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/storybook/__snapshots__/Stories.test.ts.snap b/src/storybook/__snapshots__/Stories.test.ts.snap index 8b43d7c53..c364ac4c9 100644 --- a/src/storybook/__snapshots__/Stories.test.ts.snap +++ b/src/storybook/__snapshots__/Stories.test.ts.snap @@ -122919,7 +122919,7 @@ exports[`Storyshots Views / Webhook / Create webhook default 1`] = `

- This URL will recieve webhook POST requests + This URL will receive webhook POST requests

- This URL will recieve webhook POST requests + This URL will receive webhook POST requests

- This URL will recieve webhook POST requests + This URL will receive webhook POST requests

- This URL will recieve webhook POST requests + This URL will receive webhook POST requests

- This URL will recieve webhook POST requests + This URL will receive webhook POST requests

- This URL will recieve webhook POST requests + This URL will receive webhook POST requests

No webhooks found
+
From 712d7761209b7af6972ae449c0a800af28efd6b4 Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Thu, 17 Oct 2019 15:56:08 +0200 Subject: [PATCH 28/38] Remove service list from fixtures --- src/webhooks/fixtures.ts | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/webhooks/fixtures.ts b/src/webhooks/fixtures.ts index 6b55347fc..3d828832d 100644 --- a/src/webhooks/fixtures.ts +++ b/src/webhooks/fixtures.ts @@ -1,19 +1,6 @@ -import { SearchServiceAccount_search_edges_node } from "@saleor/containers/SearchServiceAccount/types/SearchServiceAccount"; import { WebhookDetails_webhook } from "./types/WebhookDetails"; import { Webhooks_webhooks_edges_node } from "./types/Webhooks"; -export const services: SearchServiceAccount_search_edges_node[] = [ - { - __typename: "ServiceAccount", - id: "Jzx123sEt==", - name: "Facebook" - }, - { - __typename: "ServiceAccount", - id: "Jzx123sEt==", - name: "Twittwe" - } -]; export const webhookList: Webhooks_webhooks_edges_node[] = [ { __typename: "Webhook", From 844931cd6bd0d38d85a12e596a46cb7888e36d02 Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Thu, 17 Oct 2019 16:00:57 +0200 Subject: [PATCH 29/38] Fix stories name --- .../components/WebhooksListPage/WebhookListPage.stories.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webhooks/components/WebhooksListPage/WebhookListPage.stories.tsx b/src/webhooks/components/WebhooksListPage/WebhookListPage.stories.tsx index cf4926d74..f772fdf9f 100644 --- a/src/webhooks/components/WebhooksListPage/WebhookListPage.stories.tsx +++ b/src/webhooks/components/WebhooksListPage/WebhookListPage.stories.tsx @@ -21,7 +21,7 @@ const props: WebhooksListPageProps = { webhooks: webhookList }; -storiesOf("Views / Webhook / Webhook list", module) +storiesOf("Views / Webhooks / Webhook list", module) .addDecorator(Decorator) .add("default", () => ) .add("loading", () => ( From c27609604131511bad0b8e563c98b52686c41965 Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Thu, 17 Oct 2019 16:39:37 +0200 Subject: [PATCH 30/38] Fix webhooks evetns checkbox --- .../WebhookEvents/WebhookEvents.tsx | 20 ++++--------------- .../WebhooksDetailsPage.tsx | 4 +++- src/webhooks/views/WebhooksDetails.tsx | 2 +- 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx index 21659b006..5ae897912 100644 --- a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx +++ b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx @@ -8,6 +8,7 @@ import { ChangeEvent } from "@saleor/hooks/useForm"; import { WebhookEventTypeEnum } from "@saleor/types/globalTypes"; import React from "react"; import { useIntl } from "react-intl"; +import { toggle } from "@saleor/utils/lists"; interface WebhookEventsProps { data: { @@ -57,26 +58,13 @@ const WebhookEvents: React.StatelessComponent = ({ }) }; - const handleAllEventsChange = (event: ChangeEvent) => - onChange(event, () => - onChange({ - target: { - name: "events", - value: event.target.value ? WebhookEventTypeEnum.ANY_EVENTS : [] - } - }) - ); - - const handleEventsChange = (event: ChangeEvent) => { + const handleEventsChange = (event: ChangeEvent) => onChange({ target: { name: "events", - value: event.target.value - ? data.events.concat([event.target.name]) - : data.events.filter(events => events !== event.target.name) + value: toggle(event.target.name, data.events, (a, b) => a === b) } }); - }; return ( @@ -99,7 +87,7 @@ const WebhookEvents: React.StatelessComponent = ({ disabled={disabled} label={translatedEvents.ANY_EVENTS} name="allEvents" - onChange={handleAllEventsChange} + onChange={onChange} /> {!data.allEvents && ( <> diff --git a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx index 6f53bcc69..9d6c54a18 100644 --- a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx +++ b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx @@ -60,7 +60,9 @@ const WebhooksDetailsPage: React.FC = ({ allEvents: !!maybe(() => webhook.events, []).find( event => event.eventType === WebhookEventTypeEnum.ANY_EVENTS ), - events: maybe(() => webhook.events, []).map(event => event.eventType), + events: maybe(() => webhook.events, []) + .map(event => event.eventType) + .filter(event => event !== WebhookEventTypeEnum.ANY_EVENTS), id: maybe(() => webhook.id, null), isActive: maybe(() => webhook.isActive, false), name: maybe(() => webhook.name, ""), diff --git a/src/webhooks/views/WebhooksDetails.tsx b/src/webhooks/views/WebhooksDetails.tsx index 89099dc50..c7fffc2f6 100644 --- a/src/webhooks/views/WebhooksDetails.tsx +++ b/src/webhooks/views/WebhooksDetails.tsx @@ -129,7 +129,7 @@ export const WebhooksDetails: React.FC = ({ input: { events: data.allEvents ? [WebhookEventTypeEnum.ANY_EVENTS] - : data.events.slice(1), + : data.events, isActive: data.isActive, name: data.name, secretKey: data.secretKey, From 42606d0c6ad16308f15e6fb8222f5a8343181578 Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Fri, 18 Oct 2019 10:56:23 +0200 Subject: [PATCH 31/38] Fix imports order --- src/webhooks/components/WebhookEvents/WebhookEvents.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx index 5ae897912..0faa64c41 100644 --- a/src/webhooks/components/WebhookEvents/WebhookEvents.tsx +++ b/src/webhooks/components/WebhookEvents/WebhookEvents.tsx @@ -6,9 +6,9 @@ import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; import Hr from "@saleor/components/Hr"; import { ChangeEvent } from "@saleor/hooks/useForm"; import { WebhookEventTypeEnum } from "@saleor/types/globalTypes"; +import { toggle } from "@saleor/utils/lists"; import React from "react"; import { useIntl } from "react-intl"; -import { toggle } from "@saleor/utils/lists"; interface WebhookEventsProps { data: { From b82f8bc14cae8e378eb1dc898d12ff2a045638c7 Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Fri, 18 Oct 2019 11:07:26 +0200 Subject: [PATCH 32/38] Update snapshots --- .../__snapshots__/Stories.test.ts.snap | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/storybook/__snapshots__/Stories.test.ts.snap b/src/storybook/__snapshots__/Stories.test.ts.snap index c364ac4c9..e8e4b2817 100644 --- a/src/storybook/__snapshots__/Stories.test.ts.snap +++ b/src/storybook/__snapshots__/Stories.test.ts.snap @@ -122715,7 +122715,7 @@ exports[`Storyshots Views / Translations / Language list no data 1`] = ` `; -exports[`Storyshots Views / Webhook / Create webhook default 1`] = ` +exports[`Storyshots Views / Webhooks / Create webhook default 1`] = `
@@ -123224,7 +123224,7 @@ exports[`Storyshots Views / Webhook / Create webhook default 1`] = `
`; -exports[`Storyshots Views / Webhook / Create webhook form errors 1`] = ` +exports[`Storyshots Views / Webhooks / Create webhook form errors 1`] = `
@@ -123738,7 +123738,7 @@ exports[`Storyshots Views / Webhook / Create webhook form errors 1`] = `
`; -exports[`Storyshots Views / Webhook / Create webhook loading 1`] = ` +exports[`Storyshots Views / Webhooks / Create webhook loading 1`] = `
@@ -124267,7 +124267,13 @@ exports[`Storyshots Views / Webhook / Create webhook loading 1`] = `
`; -exports[`Storyshots Views / Webhook / Webhook details default 1`] = ` +exports[`Storyshots Views / Webhooks / Delete webhook default 1`] = ` +
+`; + +exports[`Storyshots Views / Webhooks / Webhook details default 1`] = `
@@ -124777,7 +124783,7 @@ exports[`Storyshots Views / Webhook / Webhook details default 1`] = `
`; -exports[`Storyshots Views / Webhook / Webhook details form errors 1`] = ` +exports[`Storyshots Views / Webhooks / Webhook details form errors 1`] = `
@@ -125292,7 +125298,7 @@ exports[`Storyshots Views / Webhook / Webhook details form errors 1`] = `
`; -exports[`Storyshots Views / Webhook / Webhook details loading 1`] = ` +exports[`Storyshots Views / Webhooks / Webhook details loading 1`] = `
@@ -125822,7 +125828,7 @@ exports[`Storyshots Views / Webhook / Webhook details loading 1`] = `
`; -exports[`Storyshots Views / Webhook / Webhook list default 1`] = ` +exports[`Storyshots Views / Webhooks / Webhook list default 1`] = `
@@ -125958,7 +125964,7 @@ exports[`Storyshots Views / Webhook / Webhook list default 1`] = ` class="MuiPaper-root-id MuiPaper-elevation0-id MuiPaper-rounded-id MuiCard-root-id" >
`; -exports[`Storyshots Views / Webhook / Webhook list loading 1`] = ` +exports[`Storyshots Views / Webhooks / Webhook list loading 1`] = `
@@ -126386,7 +126392,7 @@ exports[`Storyshots Views / Webhook / Webhook list loading 1`] = ` class="MuiPaper-root-id MuiPaper-elevation0-id MuiPaper-rounded-id MuiCard-root-id" >
`; -exports[`Storyshots Views / Webhook / Webhook list no data 1`] = ` +exports[`Storyshots Views / Webhooks / Webhook list no data 1`] = `
@@ -126755,7 +126761,7 @@ exports[`Storyshots Views / Webhook / Webhook list no data 1`] = ` class="MuiPaper-root-id MuiPaper-elevation0-id MuiPaper-rounded-id MuiCard-root-id" >
`; - -exports[`Storyshots Views / Webhooks / Delete webhook default 1`] = ` -
-`; From 261c6e621c013227408a8158047e29a90be841cc Mon Sep 17 00:00:00 2001 From: dominik-zeglen Date: Fri, 18 Oct 2019 11:26:01 +0200 Subject: [PATCH 33/38] Remove bad types --- src/containers/SearchServiceAccount/index.tsx | 2 +- .../types/searchServiceAccount.ts | 42 ------------------- 2 files changed, 1 insertion(+), 43 deletions(-) delete mode 100644 src/containers/SearchServiceAccount/types/searchServiceAccount.ts diff --git a/src/containers/SearchServiceAccount/index.tsx b/src/containers/SearchServiceAccount/index.tsx index b617f92cf..dd8cfa60f 100644 --- a/src/containers/SearchServiceAccount/index.tsx +++ b/src/containers/SearchServiceAccount/index.tsx @@ -5,7 +5,7 @@ import TopLevelSearch from "../TopLevelSearch"; import { SearchServiceAccount, SearchServiceAccountVariables -} from "./types/searchServiceAccount"; +} from "./types/SearchServiceAccount"; export const searchServiceAccount = gql` ${pageInfoFragment} diff --git a/src/containers/SearchServiceAccount/types/searchServiceAccount.ts b/src/containers/SearchServiceAccount/types/searchServiceAccount.ts deleted file mode 100644 index 33c63466c..000000000 --- a/src/containers/SearchServiceAccount/types/searchServiceAccount.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -// ==================================================== -// GraphQL query operation: SearchServiceAccount -// ==================================================== - -export interface SearchServiceAccount_search_edges_node { - __typename: "ServiceAccount"; - id: string; - name: string | null; -} - -export interface SearchServiceAccount_search_edges { - __typename: "ServiceAccountCountableEdge"; - node: SearchServiceAccount_search_edges_node; -} - -export interface SearchServiceAccount_search_pageInfo { - __typename: "PageInfo"; - endCursor: string | null; - hasNextPage: boolean; - hasPreviousPage: boolean; - startCursor: string | null; -} - -export interface SearchServiceAccount_search { - __typename: "ServiceAccountCountableConnection"; - edges: SearchServiceAccount_search_edges[]; - pageInfo: SearchServiceAccount_search_pageInfo; -} - -export interface SearchServiceAccount { - search: SearchServiceAccount_search | null; -} - -export interface SearchServiceAccountVariables { - after?: string | null; - first: number; - query: string; -} From 4f12124b4fa1add4f49e6a687a37c28b6d2f10a2 Mon Sep 17 00:00:00 2001 From: dominik-zeglen Date: Fri, 18 Oct 2019 11:32:12 +0200 Subject: [PATCH 34/38] Add types --- .../types/SearchServiceAccount.ts | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/containers/SearchServiceAccount/types/SearchServiceAccount.ts diff --git a/src/containers/SearchServiceAccount/types/SearchServiceAccount.ts b/src/containers/SearchServiceAccount/types/SearchServiceAccount.ts new file mode 100644 index 000000000..33c63466c --- /dev/null +++ b/src/containers/SearchServiceAccount/types/SearchServiceAccount.ts @@ -0,0 +1,42 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: SearchServiceAccount +// ==================================================== + +export interface SearchServiceAccount_search_edges_node { + __typename: "ServiceAccount"; + id: string; + name: string | null; +} + +export interface SearchServiceAccount_search_edges { + __typename: "ServiceAccountCountableEdge"; + node: SearchServiceAccount_search_edges_node; +} + +export interface SearchServiceAccount_search_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface SearchServiceAccount_search { + __typename: "ServiceAccountCountableConnection"; + edges: SearchServiceAccount_search_edges[]; + pageInfo: SearchServiceAccount_search_pageInfo; +} + +export interface SearchServiceAccount { + search: SearchServiceAccount_search | null; +} + +export interface SearchServiceAccountVariables { + after?: string | null; + first: number; + query: string; +} From 9a5f95b68f2dbd64f292668ac9ce56d1c5bf4478 Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Fri, 18 Oct 2019 14:01:26 +0200 Subject: [PATCH 35/38] Fix webhook api errors --- src/types/globalTypes.ts | 8 ++++ .../WebhookCreatePage/WebhookCreatePage.tsx | 11 +++--- .../WebhooksCreatePage.stories.tsx | 13 ++++++- .../components/WebhookInfo/WebhookInfo.tsx | 38 ++++++++++++++++++- .../WebhooksDetailsPage.stories.tsx | 13 ++++++- .../WebhooksDetailsPage.tsx | 9 +++-- src/webhooks/mutations.ts | 10 +++++ src/webhooks/types/WebhookCreate.ts | 10 ++++- src/webhooks/types/WebhookUpdate.ts | 10 ++++- src/webhooks/views/WebhooksCreate.tsx | 6 +-- src/webhooks/views/WebhooksDetails.tsx | 8 ++-- 11 files changed, 114 insertions(+), 22 deletions(-) diff --git a/src/types/globalTypes.ts b/src/types/globalTypes.ts index eb0eafe33..1b4c9abd9 100644 --- a/src/types/globalTypes.ts +++ b/src/types/globalTypes.ts @@ -286,6 +286,14 @@ export enum VoucherTypeEnum { SPECIFIC_PRODUCT = "SPECIFIC_PRODUCT", } +export enum WebhookErrorCode { + GRAPHQL_ERROR = "GRAPHQL_ERROR", + INVALID = "INVALID", + NOT_FOUND = "NOT_FOUND", + REQUIRED = "REQUIRED", + UNIQUE = "UNIQUE", +} + export enum WebhookEventTypeEnum { ANY_EVENTS = "ANY_EVENTS", CUSTOMER_CREATED = "CUSTOMER_CREATED", diff --git a/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx b/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx index 95568c615..4aaddff03 100644 --- a/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx +++ b/src/webhooks/components/WebhookCreatePage/WebhookCreatePage.tsx @@ -9,12 +9,12 @@ import SaveButtonBar from "@saleor/components/SaveButtonBar"; import { SearchServiceAccount_search_edges_node } from "@saleor/containers/SearchServiceAccount/types/SearchServiceAccount"; import { sectionNames } from "@saleor/intl"; import { maybe } from "@saleor/misc"; -import { UserError } from "@saleor/types"; import { WebhookEventTypeEnum } from "@saleor/types/globalTypes"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; import WebhookEvents from "@saleor/webhooks/components/WebhookEvents"; import WebhookInfo from "@saleor/webhooks/components/WebhookInfo"; import WebhookStatus from "@saleor/webhooks/components/WebhookStatus"; +import { WebhookCreate_webhookCreate_webhookErrors } from "@saleor/webhooks/types/WebhookCreate"; import React from "react"; import { useIntl } from "react-intl"; @@ -31,7 +31,7 @@ export interface FormData { export interface WebhookCreatePageProps { disabled: boolean; - errors: UserError[]; + errors: WebhookCreate_webhookCreate_webhookErrors[]; services?: SearchServiceAccount_search_edges_node[]; saveButtonBarState: ConfirmButtonTransitionState; fetchServiceAccounts: (data: string) => void; @@ -39,9 +39,9 @@ export interface WebhookCreatePageProps { onSubmit: (data: FormData) => void; } -const WebhookCreatePage: React.StatelessComponent = ({ +const WebhookCreatePage: React.FC = ({ disabled, - errors, + errors: apiErrors, saveButtonBarState, services, fetchServiceAccounts, @@ -72,7 +72,7 @@ const WebhookCreatePage: React.StatelessComponent = ({ ); return ( -
+ {({ data, errors, hasChanged, submit, change }) => { const handleServiceSelect = createSingleAutocompleteSelectHandler( change, @@ -98,6 +98,7 @@ const WebhookCreatePage: React.StatelessComponent = ({ serviceDisplayValue={selectedServiceAcccount} services={servicesChoiceList} fetchServiceAccounts={fetchServiceAccounts} + apiErrors={apiErrors} errors={errors} serviceOnChange={handleServiceSelect} onChange={change} diff --git a/src/webhooks/components/WebhookCreatePage/WebhooksCreatePage.stories.tsx b/src/webhooks/components/WebhookCreatePage/WebhooksCreatePage.stories.tsx index dc9e5320c..a927deeef 100644 --- a/src/webhooks/components/WebhookCreatePage/WebhooksCreatePage.stories.tsx +++ b/src/webhooks/components/WebhookCreatePage/WebhooksCreatePage.stories.tsx @@ -2,7 +2,7 @@ import { storiesOf } from "@storybook/react"; import React from "react"; import Decorator from "@saleor/storybook/Decorator"; -import { formError } from "@saleor/storybook/misc"; +import { WebhookErrorCode } from "@saleor/types/globalTypes"; import WebhookCreatePage, { WebhookCreatePageProps } from "./WebhookCreatePage"; const props: WebhookCreatePageProps = { @@ -21,6 +21,15 @@ storiesOf("Views / Webhooks / Create webhook", module) .add("form errors", () => ( formError(field))} + errors={[ + { + code: WebhookErrorCode.INVALID, + field: null + } + ].map(error => ({ + __typename: "WebhookError", + message: "Generic form error", + ...error + }))} /> )); diff --git a/src/webhooks/components/WebhookInfo/WebhookInfo.tsx b/src/webhooks/components/WebhookInfo/WebhookInfo.tsx index 387f1d6dc..e1687dbe9 100644 --- a/src/webhooks/components/WebhookInfo/WebhookInfo.tsx +++ b/src/webhooks/components/WebhookInfo/WebhookInfo.tsx @@ -4,7 +4,7 @@ import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; import makeStyles from "@material-ui/styles/makeStyles"; import React from "react"; -import { useIntl } from "react-intl"; +import { IntlShape, useIntl } from "react-intl"; import CardTitle from "@saleor/components/CardTitle"; import FormSpacer from "@saleor/components/FormSpacer"; @@ -15,9 +15,12 @@ import SingleAutocompleteSelectField, { import { ChangeEvent } from "@saleor/hooks/useForm"; import { commonMessages } from "@saleor/intl"; import { FormErrors } from "@saleor/types"; +import { WebhookErrorCode } from "@saleor/types/globalTypes"; +import { WebhookCreate_webhookCreate_webhookErrors } from "@saleor/webhooks/types/WebhookCreate"; import { FormData } from "../WebhooksDetailsPage"; interface WebhookInfoProps { + apiErrors: WebhookCreate_webhookCreate_webhookErrors[]; data: FormData; disabled: boolean; serviceDisplayValue: string; @@ -40,6 +43,7 @@ const useStyles = makeStyles(() => ({ })); const WebhookInfo: React.StatelessComponent = ({ + apiErrors, data, disabled, services, @@ -51,6 +55,18 @@ const WebhookInfo: React.StatelessComponent = ({ }) => { const classes = useStyles({}); const intl = useIntl(); + const translatedErrors = translateErrors(intl); + const serviceAccountsError = + apiErrors.filter(error => error.field === null).length > 0; + + function translateErrors(intl: IntlShape) { + return { + [WebhookErrorCode.INVALID]: intl.formatMessage({ + defaultMessage: "Missing token or serviceAccount", + description: "webhook service account error" + }) + }; + } return ( @@ -92,6 +108,14 @@ const WebhookInfo: React.StatelessComponent = ({ label={intl.formatMessage({ defaultMessage: "Assign to Service Account" })} + error={serviceAccountsError} + helperText={ + serviceAccountsError && + intl.formatMessage({ + defaultMessage: "Missing token or serviceAccount", + description: "webhook service account error" + }) + } name="serviceAccount" onChange={serviceOnChange} value={data.serviceAccount} @@ -136,6 +160,18 @@ const WebhookInfo: React.StatelessComponent = ({ value={data.secretKey} onChange={onChange} /> + {apiErrors.length > 0 && ( + <> + + {apiErrors + .filter(error => error.field === null) + .map(error => ( + + {translatedErrors[error.code]} + + ))} + + )} ); diff --git a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx index 11d17e6b5..5e30a9cc9 100644 --- a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx +++ b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.stories.tsx @@ -2,7 +2,7 @@ import { storiesOf } from "@storybook/react"; import React from "react"; import Decorator from "@saleor/storybook/Decorator"; -import { formError } from "@saleor/storybook/misc"; +import { WebhookErrorCode } from "@saleor/types/globalTypes"; import WebhooksDetailsPage, { WebhooksDetailsPageProps } from "./WebhooksDetailsPage"; @@ -32,6 +32,15 @@ storiesOf("Views / Webhooks / Webhook details", module) .add("form errors", () => ( formError(field))} + errors={[ + { + code: WebhookErrorCode.INVALID, + field: null + } + ].map(error => ({ + __typename: "WebhookError", + message: "Generic form error", + ...error + }))} /> )); diff --git a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx index 9d6c54a18..ba88c0932 100644 --- a/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx +++ b/src/webhooks/components/WebhooksDetailsPage/WebhooksDetailsPage.tsx @@ -10,12 +10,12 @@ import { SearchServiceAccount_search_edges_node } from "@saleor/containers/Searc import useStateFromProps from "@saleor/hooks/useStateFromProps"; import { sectionNames } from "@saleor/intl"; import { maybe } from "@saleor/misc"; -import { UserError } from "@saleor/types"; import { WebhookEventTypeEnum } from "@saleor/types/globalTypes"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; import WebhookEvents from "@saleor/webhooks/components/WebhookEvents"; import WebhookInfo from "@saleor/webhooks/components/WebhookInfo"; import WebhookStatus from "@saleor/webhooks/components/WebhookStatus"; +import { WebhookCreate_webhookCreate_webhookErrors } from "@saleor/webhooks/types/WebhookCreate"; import { WebhookDetails_webhook } from "@saleor/webhooks/types/WebhookDetails"; import React from "react"; @@ -34,7 +34,7 @@ export interface FormData { export interface WebhooksDetailsPageProps { disabled: boolean; - errors: UserError[]; + errors: WebhookCreate_webhookCreate_webhookErrors[]; webhook: WebhookDetails_webhook; services?: SearchServiceAccount_search_edges_node[]; saveButtonBarState: ConfirmButtonTransitionState; @@ -46,7 +46,7 @@ export interface WebhooksDetailsPageProps { const WebhooksDetailsPage: React.FC = ({ disabled, - errors, + errors: apiErrors, webhook, saveButtonBarState, services, @@ -83,7 +83,7 @@ const WebhooksDetailsPage: React.FC = ({ [] ); return ( - + {({ data, errors, hasChanged, submit, change }) => { const handleServiceSelect = createSingleAutocompleteSelectHandler( change, @@ -109,6 +109,7 @@ const WebhooksDetailsPage: React.FC = ({
{ - if (data.webhookCreate.errors.length === 0) { + if (data.webhookCreate.webhookErrors.length === 0) { notify({ text: intl.formatMessage(commonMessages.savedChanges) }); @@ -64,7 +64,7 @@ export const WebhooksCreate: React.StatelessComponent< const formTransitionState = getMutationState( webhookCreateOpts.called, webhookCreateOpts.loading, - maybe(() => webhookCreateOpts.data.webhookCreate.errors) + maybe(() => webhookCreateOpts.data.webhookCreate.webhookErrors) ); return ( @@ -78,7 +78,7 @@ export const WebhooksCreate: React.StatelessComponent< webhookCreateOpts.data.webhookCreate.errors, + () => webhookCreateOpts.data.webhookCreate.webhookErrors, [] )} fetchServiceAccounts={searchServiceAccount} diff --git a/src/webhooks/views/WebhooksDetails.tsx b/src/webhooks/views/WebhooksDetails.tsx index c7fffc2f6..68b231851 100644 --- a/src/webhooks/views/WebhooksDetails.tsx +++ b/src/webhooks/views/WebhooksDetails.tsx @@ -63,7 +63,7 @@ export const WebhooksDetails: React.FC = ({ }; const onWebhookUpdate = (data: WebhookUpdate) => { - if (data.webhookUpdate.errors.length === 0) { + if (data.webhookUpdate.webhookErrors.length === 0) { notify({ text: intl.formatMessage(commonMessages.savedChanges) }); @@ -83,7 +83,9 @@ export const WebhooksDetails: React.FC = ({ const formTransitionState = getMutationState( webhookUpdateOpts.called, webhookUpdateOpts.loading, - maybe(() => webhookUpdateOpts.data.webhookUpdate.errors) + maybe( + () => webhookUpdateOpts.data.webhookUpdate.webhookErrors + ) ); const handleRemoveConfirm = () => @@ -94,7 +96,7 @@ export const WebhooksDetails: React.FC = ({ }); const formErrors = maybe( - () => webhookUpdateOpts.data.webhookUpdate.errors, + () => webhookUpdateOpts.data.webhookUpdate.webhookErrors, [] ); From 9d3da33fc911759ddd50feb4197d7178b5cde59a Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Fri, 18 Oct 2019 14:03:03 +0200 Subject: [PATCH 36/38] Update snapshots --- .../__snapshots__/Stories.test.ts.snap | 60 ++++++++++++------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/src/storybook/__snapshots__/Stories.test.ts.snap b/src/storybook/__snapshots__/Stories.test.ts.snap index e8e4b2817..e9264fe09 100644 --- a/src/storybook/__snapshots__/Stories.test.ts.snap +++ b/src/storybook/__snapshots__/Stories.test.ts.snap @@ -123285,13 +123285,13 @@ exports[`Storyshots Views / Webhooks / Create webhook form errors 1`] = ` class="MuiFormControl-root-id MuiFormControl-fullWidth-id" >
-

- Generic form error -

+

+ Missing token or serviceAccount +

+
+

+ Missing token or serviceAccount +

@@ -124844,13 +124852,13 @@ exports[`Storyshots Views / Webhooks / Webhook details form errors 1`] = ` class="MuiFormControl-root-id MuiFormControl-fullWidth-id" >
-

- Generic form error -

+

+ Missing token or serviceAccount +

+
+

+ Missing token or serviceAccount +

From c40bd1a2e6e386dd85d030d9c9e9b1bbee01b143 Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Fri, 18 Oct 2019 14:07:17 +0200 Subject: [PATCH 37/38] Fix error message --- src/webhooks/components/WebhookInfo/WebhookInfo.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/webhooks/components/WebhookInfo/WebhookInfo.tsx b/src/webhooks/components/WebhookInfo/WebhookInfo.tsx index e1687dbe9..11da21fc8 100644 --- a/src/webhooks/components/WebhookInfo/WebhookInfo.tsx +++ b/src/webhooks/components/WebhookInfo/WebhookInfo.tsx @@ -62,7 +62,7 @@ const WebhookInfo: React.StatelessComponent = ({ function translateErrors(intl: IntlShape) { return { [WebhookErrorCode.INVALID]: intl.formatMessage({ - defaultMessage: "Missing token or serviceAccount", + defaultMessage: "Missing service account", description: "webhook service account error" }) }; @@ -112,7 +112,7 @@ const WebhookInfo: React.StatelessComponent = ({ helperText={ serviceAccountsError && intl.formatMessage({ - defaultMessage: "Missing token or serviceAccount", + defaultMessage: "Missing service account", description: "webhook service account error" }) } From 13da934927a1eb468708b27ed1340983b12a9f84 Mon Sep 17 00:00:00 2001 From: Krzysztof Bialoglowicz Date: Fri, 18 Oct 2019 14:33:05 +0200 Subject: [PATCH 38/38] Fix error messages with service account --- src/intl.ts | 3 ++ .../__snapshots__/Stories.test.ts.snap | 20 ++----------- .../components/WebhookInfo/WebhookInfo.tsx | 30 ++----------------- 3 files changed, 7 insertions(+), 46 deletions(-) diff --git a/src/intl.ts b/src/intl.ts index 867bf279c..45839e65a 100644 --- a/src/intl.ts +++ b/src/intl.ts @@ -47,6 +47,9 @@ export const commonMessages = defineMessages({ properties: { defaultMessage: "Properties" }, + requiredField: { + defaultMessage: "This field is required" + }, savedChanges: { defaultMessage: "Saved changes" }, diff --git a/src/storybook/__snapshots__/Stories.test.ts.snap b/src/storybook/__snapshots__/Stories.test.ts.snap index e9264fe09..9eeaa4605 100644 --- a/src/storybook/__snapshots__/Stories.test.ts.snap +++ b/src/storybook/__snapshots__/Stories.test.ts.snap @@ -123389,7 +123389,7 @@ exports[`Storyshots Views / Webhooks / Create webhook form errors 1`] = `

- Missing token or serviceAccount + This field is required

@@ -123479,14 +123479,6 @@ exports[`Storyshots Views / Webhooks / Create webhook form errors 1`] = ` secret key is used to create a hash signature with each payload. *optional field

-
-

- Missing token or serviceAccount -

@@ -124957,7 +124949,7 @@ exports[`Storyshots Views / Webhooks / Webhook details form errors 1`] = `

- Missing token or serviceAccount + This field is required

@@ -125047,14 +125039,6 @@ exports[`Storyshots Views / Webhooks / Webhook details form errors 1`] = ` secret key is used to create a hash signature with each payload. *optional field

-
-

- Missing token or serviceAccount -

diff --git a/src/webhooks/components/WebhookInfo/WebhookInfo.tsx b/src/webhooks/components/WebhookInfo/WebhookInfo.tsx index 11da21fc8..de17ae2db 100644 --- a/src/webhooks/components/WebhookInfo/WebhookInfo.tsx +++ b/src/webhooks/components/WebhookInfo/WebhookInfo.tsx @@ -4,7 +4,7 @@ import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; import makeStyles from "@material-ui/styles/makeStyles"; import React from "react"; -import { IntlShape, useIntl } from "react-intl"; +import { useIntl } from "react-intl"; import CardTitle from "@saleor/components/CardTitle"; import FormSpacer from "@saleor/components/FormSpacer"; @@ -15,7 +15,6 @@ import SingleAutocompleteSelectField, { import { ChangeEvent } from "@saleor/hooks/useForm"; import { commonMessages } from "@saleor/intl"; import { FormErrors } from "@saleor/types"; -import { WebhookErrorCode } from "@saleor/types/globalTypes"; import { WebhookCreate_webhookCreate_webhookErrors } from "@saleor/webhooks/types/WebhookCreate"; import { FormData } from "../WebhooksDetailsPage"; @@ -55,19 +54,9 @@ const WebhookInfo: React.StatelessComponent = ({ }) => { const classes = useStyles({}); const intl = useIntl(); - const translatedErrors = translateErrors(intl); const serviceAccountsError = apiErrors.filter(error => error.field === null).length > 0; - function translateErrors(intl: IntlShape) { - return { - [WebhookErrorCode.INVALID]: intl.formatMessage({ - defaultMessage: "Missing service account", - description: "webhook service account error" - }) - }; - } - return ( = ({ error={serviceAccountsError} helperText={ serviceAccountsError && - intl.formatMessage({ - defaultMessage: "Missing service account", - description: "webhook service account error" - }) + intl.formatMessage(commonMessages.requiredField) } name="serviceAccount" onChange={serviceOnChange} @@ -160,18 +146,6 @@ const WebhookInfo: React.StatelessComponent = ({ value={data.secretKey} onChange={onChange} /> - {apiErrors.length > 0 && ( - <> - - {apiErrors - .filter(error => error.field === null) - .map(error => ( - - {translatedErrors[error.code]} - - ))} - - )} );