From 6c78be33fc84a8a3de9b8938c707c8f8511816a7 Mon Sep 17 00:00:00 2001 From: dominik-zeglen Date: Fri, 8 Nov 2019 11:25:17 +0100 Subject: [PATCH] Add secret fields edit dialogs --- src/components/ActionDialog/ActionDialog.tsx | 5 +- .../PluginAuthorization.tsx | 14 +-- .../PluginSecretFieldDialog.tsx | 93 ++++++++++++++++++ .../PluginSecretFieldDialog/index.ts | 2 + src/plugins/views/PluginsDetails.tsx | 97 ++++++++++++++----- src/types.ts | 5 + 6 files changed, 181 insertions(+), 35 deletions(-) create mode 100644 src/plugins/components/PluginSecretFieldDialog/PluginSecretFieldDialog.tsx create mode 100644 src/plugins/components/PluginSecretFieldDialog/index.ts diff --git a/src/components/ActionDialog/ActionDialog.tsx b/src/components/ActionDialog/ActionDialog.tsx index 5607851ba..737ce0723 100644 --- a/src/components/ActionDialog/ActionDialog.tsx +++ b/src/components/ActionDialog/ActionDialog.tsx @@ -9,6 +9,7 @@ import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; import { buttonMessages } from "@saleor/intl"; +import { DialogProps } from "@saleor/types"; import ConfirmButton, { ConfirmButtonTransitionState } from "../ConfirmButton/ConfirmButton"; @@ -26,15 +27,13 @@ const useStyles = makeStyles( { name: "ActionDialog" } ); -interface ActionDialogProps { +interface ActionDialogProps extends DialogProps { children?: React.ReactNode; confirmButtonLabel?: string; confirmButtonState: ConfirmButtonTransitionState; maxWidth?: "xs" | "sm" | "md" | "lg" | "xl" | false; - open: boolean; title: string; variant?: "default" | "delete"; - onClose?(); onConfirm(); } diff --git a/src/plugins/components/PluginAuthorization/PluginAuthorization.tsx b/src/plugins/components/PluginAuthorization/PluginAuthorization.tsx index 2438abb24..a590141c3 100644 --- a/src/plugins/components/PluginAuthorization/PluginAuthorization.tsx +++ b/src/plugins/components/PluginAuthorization/PluginAuthorization.tsx @@ -21,7 +21,7 @@ interface PluginAuthorizationProps { const useStyles = makeStyles(theme => ({ button: { - marginRight: theme.spacing() + marginLeft: theme.spacing() }, hr: { margin: theme.spacing(2, 0) @@ -55,7 +55,7 @@ const PluginAuthorization: React.FC = props => { /> {secretFields.map((field, fieldIndex) => ( - <> +
{field.type === ConfigurationTypeFieldEnum.SECRET ? (
@@ -78,14 +78,14 @@ const PluginAuthorization: React.FC = props => { ) : ( <> + - @@ -94,7 +94,7 @@ const PluginAuthorization: React.FC = props => { {fieldIndex !== secretFields.length - 1 && (
)} - + ))} diff --git a/src/plugins/components/PluginSecretFieldDialog/PluginSecretFieldDialog.tsx b/src/plugins/components/PluginSecretFieldDialog/PluginSecretFieldDialog.tsx new file mode 100644 index 000000000..06edabbf4 --- /dev/null +++ b/src/plugins/components/PluginSecretFieldDialog/PluginSecretFieldDialog.tsx @@ -0,0 +1,93 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import TextField from "@material-ui/core/TextField"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + +import ConfirmButton, { + ConfirmButtonTransitionState +} from "@saleor/components/ConfirmButton"; +import Form from "@saleor/components/Form"; +import Skeleton from "@saleor/components/Skeleton"; +import { buttonMessages } from "@saleor/intl"; +import { Plugin_plugin_configuration } from "@saleor/plugins/types/Plugin"; +import { DialogProps } from "@saleor/types"; + +interface PluginSecretFieldDialogFormData { + value: string; +} +interface PluginSecretFieldDialogProps extends DialogProps { + confirmButtonState: ConfirmButtonTransitionState; + field: Plugin_plugin_configuration; + onConfirm: (data: PluginSecretFieldDialogFormData) => void; +} + +const PluginSecretFieldDialog: React.FC = ({ + confirmButtonState, + field, + onClose, + onConfirm, + open +}) => { + const intl = useIntl(); + + const initialForm: PluginSecretFieldDialogFormData = { + value: "" + }; + + return ( + + + {field ? ( + field.value === null ? ( + intl.formatMessage({ + defaultMessage: "Add Value to Authorization Field", + description: "header" + }) + ) : ( + intl.formatMessage({ + defaultMessage: "Edit Authorization Field", + description: "header" + }) + ) + ) : ( + + )} + +
+ {({ change, data, submit }) => ( + <> + + + + + + + + + + + )} +
+
+ ); +}; + +PluginSecretFieldDialog.displayName = "PluginSecretFieldDialog"; +export default PluginSecretFieldDialog; diff --git a/src/plugins/components/PluginSecretFieldDialog/index.ts b/src/plugins/components/PluginSecretFieldDialog/index.ts new file mode 100644 index 000000000..bd4d72512 --- /dev/null +++ b/src/plugins/components/PluginSecretFieldDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./PluginSecretFieldDialog"; +export * from "./PluginSecretFieldDialog"; diff --git a/src/plugins/views/PluginsDetails.tsx b/src/plugins/views/PluginsDetails.tsx index 5b76d3c33..edd4f1b1f 100644 --- a/src/plugins/views/PluginsDetails.tsx +++ b/src/plugins/views/PluginsDetails.tsx @@ -1,15 +1,20 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + +import ActionDialog from "@saleor/components/ActionDialog"; 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 { commonMessages } from "@saleor/intl"; import { ConfigurationItemInput } from "@saleor/types/globalTypes"; import { getMutationState, maybe } from "../../misc"; import PluginsDetailsPage from "../components/PluginsDetailsPage"; +import PluginSecretFieldDialog from "../components/PluginSecretFieldDialog"; import { TypedPluginUpdate } from "../mutations"; import { TypedPluginsDetailsQuery } from "../queries"; import { Plugin_plugin_configuration } from "../types/Plugin"; +import { PluginUpdate } from "../types/PluginUpdate"; import { pluginsListUrl, pluginsUrl, @@ -66,11 +71,20 @@ export const PluginsDetails: React.FC = ({ }) ); + const handleUpdate = (data: PluginUpdate) => { + if (data.pluginUpdate.errors.length === 0) { + notify({ + text: intl.formatMessage(commonMessages.savedChanges) + }); + closeModal(); + } + }; + return ( - - {(pluginUpdate, pluginUpdateOpts) => ( - - {pluginDetails => { + + {pluginDetails => ( + + {(pluginUpdate, pluginUpdateOpts) => { const formTransitionState = getMutationState( pluginUpdateOpts.called, pluginUpdateOpts.loading, @@ -82,22 +96,20 @@ export const PluginsDetails: React.FC = ({ [] ); - if (formErrors.length) { - formErrors.map(error => { - notify({ - text: error.message - }); + const handleFieldUpdate = (value: string) => + pluginUpdate({ + variables: { + id, + input: { + configuration: [ + { + name: params.field, + value + } + ] + } + } }); - } else { - if (pluginUpdateOpts.data) { - notify({ - text: intl.formatMessage({ - defaultMessage: "Succesfully updated plugin settings", - description: "plugin success message" - }) - }); - } - } return ( <> @@ -107,7 +119,9 @@ export const PluginsDetails: React.FC = ({ pluginDetails.data.plugin)} onBack={() => navigate(pluginsListUrl())} onClear={field => openModal("clear", field)} @@ -127,12 +141,45 @@ export const PluginsDetails: React.FC = ({ }) } /> + {maybe(() => pluginDetails.data.plugin.configuration) && ( + <> + handleFieldUpdate(null)} + > + + + + + + pluginDetails.data.plugin.configuration.find( + field => field.name === params.field + ) + )} + onClose={closeModal} + onConfirm={formData => handleFieldUpdate(formData.value)} + open={params.action === "edit" && !!params.field} + /> + + )} ); }} - + )} - + ); }; PluginsDetails.displayName = "PluginsDetails"; diff --git a/src/types.ts b/src/types.ts index d1f0fe3a7..5bae68335 100644 --- a/src/types.ts +++ b/src/types.ts @@ -9,6 +9,11 @@ export interface UserError { message: string; } +export interface DialogProps { + open: boolean; + onClose: () => void; +} + export interface ListSettings { columns?: TColumn[]; rowNumber: number;