Merge pull request #246 from mirumee/add/plugin-fields

Add secret fields in plugin configuration
This commit is contained in:
Marcin Gębala 2019-11-12 16:51:54 +01:00 committed by GitHub
commit 8170f9e14e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 1366 additions and 395 deletions

View file

@ -6,6 +6,7 @@ All notable, unreleased changes to this project will be documented in this file.
- Fix minor bugs - #244 by @dominik-zeglen - Fix minor bugs - #244 by @dominik-zeglen
- Fix tax settings updating - #243 by @dominik-zeglen - Fix tax settings updating - #243 by @dominik-zeglen
- Add secret fields in plugin configuration - #246 by @dominik-zeglen
- Fix subcategories pagination - #249 by @dominik-zeglen - Fix subcategories pagination - #249 by @dominik-zeglen
## 2.0.0 ## 2.0.0

View file

@ -1,6 +1,6 @@
msgid "" msgid ""
msgstr "" msgstr ""
"POT-Creation-Date: 2019-11-07T13:41:50.654Z\n" "POT-Creation-Date: 2019-11-08T10:47:25.155Z\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -223,6 +223,14 @@ msgctxt "add attribute value"
msgid "Add Value" msgid "Add Value"
msgstr "" msgstr ""
#: build/locale/src/plugins/components/PluginSecretFieldDialog/PluginSecretFieldDialog.json
#. [src.plugins.components.PluginSecretFieldDialog.3032939398] - header
#. defaultMessage is:
#. Add Value to Authorization Field
msgctxt "header"
msgid "Add Value to Authorization Field"
msgstr ""
#: build/locale/src/shipping/components/ShippingZoneRateDialog/ShippingZoneRateDialog.json #: build/locale/src/shipping/components/ShippingZoneRateDialog/ShippingZoneRateDialog.json
#. [src.shipping.components.ShippingZoneRateDialog.1397795758] - add weight based shipping method, dialog header #. [src.shipping.components.ShippingZoneRateDialog.1397795758] - add weight based shipping method, dialog header
#. defaultMessage is: #. defaultMessage is:
@ -1499,6 +1507,22 @@ msgctxt "authentication provider name"
msgid "Authentication type" msgid "Authentication type"
msgstr "" msgstr ""
#: build/locale/src/plugins/components/PluginAuthorization/PluginAuthorization.json
#. [src.plugins.components.PluginAuthorization.768575093] - section header
#. defaultMessage is:
#. Authorization
msgctxt "section header"
msgid "Authorization"
msgstr ""
#: build/locale/src/plugins/views/PluginsDetails.json
#. [src.plugins.views.1096544448] - header
#. defaultMessage is:
#. Authorization Field Delete
msgctxt "header"
msgid "Authorization Field Delete"
msgstr ""
#: build/locale/src/collections/components/CollectionList/CollectionList.json #: build/locale/src/collections/components/CollectionList/CollectionList.json
#. [src.collections.components.CollectionList.3326160357] - collection availability #. [src.collections.components.CollectionList.3326160357] - collection availability
#. defaultMessage is: #. defaultMessage is:
@ -1915,6 +1939,14 @@ msgctxt "description"
msgid "City" msgid "City"
msgstr "" msgstr ""
#: build/locale/src/intl.json
#. [src.clear] - button
#. defaultMessage is:
#. Clear
msgctxt "button"
msgid "Clear"
msgstr ""
#: build/locale/src/discounts/components/VoucherList/VoucherList.json #: build/locale/src/discounts/components/VoucherList/VoucherList.json
#. [src.discounts.components.VoucherList.78726751] - voucher code #. [src.discounts.components.VoucherList.78726751] - voucher code
#. defaultMessage is: #. defaultMessage is:
@ -2275,6 +2307,14 @@ msgctxt "description"
msgid "Country area" msgid "Country area"
msgstr "" msgstr ""
#: build/locale/src/intl.json
#. [src.create] - button
#. defaultMessage is:
#. Create
msgctxt "button"
msgid "Create"
msgstr ""
#: build/locale/src/products/components/ProductVariantCreateDialog/ProductVariantCreateDialog.json #: build/locale/src/products/components/ProductVariantCreateDialog/ProductVariantCreateDialog.json
#. [src.products.components.ProductVariantCreateDialog.4120989039] - create multiple variants, button #. [src.products.components.ProductVariantCreateDialog.4120989039] - create multiple variants, button
#. defaultMessage is: #. defaultMessage is:
@ -3523,6 +3563,14 @@ msgctxt "dialog title"
msgid "Edit Address" msgid "Edit Address"
msgstr "" msgstr ""
#: build/locale/src/plugins/components/PluginSecretFieldDialog/PluginSecretFieldDialog.json
#. [src.plugins.components.PluginSecretFieldDialog.4269236107] - header
#. defaultMessage is:
#. Edit Authorization Field
msgctxt "header"
msgid "Edit Authorization Field"
msgstr ""
#: build/locale/src/orders/components/OrderAddressEditDialog/OrderAddressEditDialog.json #: build/locale/src/orders/components/OrderAddressEditDialog/OrderAddressEditDialog.json
#. [src.orders.components.OrderAddressEditDialog.3982060155] - dialog header #. [src.orders.components.OrderAddressEditDialog.3982060155] - dialog header
#. defaultMessage is: #. defaultMessage is:
@ -7923,14 +7971,6 @@ msgctxt "order subtotal price"
msgid "Subtotal" msgid "Subtotal"
msgstr "" msgstr ""
#: build/locale/src/plugins/views/PluginsDetails.json
#. [src.plugins.views.100549097] - plugin success message
#. defaultMessage is:
#. Succesfully updated plugin settings
msgctxt "plugin success message"
msgid "Succesfully updated plugin settings"
msgstr ""
#: build/locale/src/auth/components/ResetPasswordSuccessPage/ResetPasswordSuccessPage.json #: build/locale/src/auth/components/ResetPasswordSuccessPage/ResetPasswordSuccessPage.json
#. [src.auth.components.ResetPasswordSuccessPage.4066297200] #. [src.auth.components.ResetPasswordSuccessPage.4066297200]
#. defaultMessage is: #. defaultMessage is:
@ -8095,6 +8135,14 @@ msgctxt "description"
msgid "The new dashboard and the GraphQL API are preview-quality software." msgid "The new dashboard and the GraphQL API are preview-quality software."
msgstr "" msgstr ""
#: build/locale/src/plugins/views/PluginsDetails.json
#. [src.plugins.views.955370043]
#. defaultMessage is:
#. The plugin may stop working after this field is cleared. Are you sure you want to proceed?
msgctxt "description"
msgid "The plugin may stop working after this field is cleared. Are you sure you want to proceed?"
msgstr ""
#: build/locale/src/customers/components/CustomerCreateAddress/CustomerCreateAddress.json #: build/locale/src/customers/components/CustomerCreateAddress/CustomerCreateAddress.json
#. [src.customers.components.CustomerCreateAddress.401345057] #. [src.customers.components.CustomerCreateAddress.401345057]
#. defaultMessage is: #. defaultMessage is:
@ -8128,13 +8176,9 @@ msgid "There is no address to show for this customer"
msgstr "" msgstr ""
#: build/locale/src/plugins/components/PluginsDetailsPage/PluginsDetailsPage.json #: build/locale/src/plugins/components/PluginsDetailsPage/PluginsDetailsPage.json
#. [src.plugins.components.PluginsDetailsPage.2277745418] #. [src.plugins.components.PluginsDetailsPage.3799756739]
#. defaultMessage is: #. defaultMessage is:
#. These are general information about your store. They define what is the URL of your store and what is shown in brow sers taskbar. #. These are general information about your store. They define what is the URL of your store and what is shown in browsers taskbar.
msgctxt "description"
msgid "These are general information about your store. They define what is the URL of your store and what is shown in brow sers taskbar."
msgstr ""
#: build/locale/src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.json #: build/locale/src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.json
#. [src.siteSettings.components.SiteSettingsPage.3799756739] #. [src.siteSettings.components.SiteSettingsPage.3799756739]
#. defaultMessage is: #. defaultMessage is:

View file

@ -960,7 +960,7 @@ type CollectionUpdatePrivateMeta {
type ConfigurationItem { type ConfigurationItem {
name: String! name: String!
value: String! value: String
type: ConfigurationTypeFieldEnum type: ConfigurationTypeFieldEnum
helpText: String helpText: String
label: String label: String
@ -974,6 +974,8 @@ input ConfigurationItemInput {
enum ConfigurationTypeFieldEnum { enum ConfigurationTypeFieldEnum {
STRING STRING
BOOLEAN BOOLEAN
SECRET
PASSWORD
} }
enum CountryCode { enum CountryCode {

View file

@ -9,6 +9,7 @@ import React from "react";
import { FormattedMessage, useIntl } from "react-intl"; import { FormattedMessage, useIntl } from "react-intl";
import { buttonMessages } from "@saleor/intl"; import { buttonMessages } from "@saleor/intl";
import { DialogProps } from "@saleor/types";
import ConfirmButton, { import ConfirmButton, {
ConfirmButtonTransitionState ConfirmButtonTransitionState
} from "../ConfirmButton/ConfirmButton"; } from "../ConfirmButton/ConfirmButton";
@ -26,15 +27,13 @@ const useStyles = makeStyles(
{ name: "ActionDialog" } { name: "ActionDialog" }
); );
interface ActionDialogProps { interface ActionDialogProps extends DialogProps {
children?: React.ReactNode; children?: React.ReactNode;
confirmButtonLabel?: string; confirmButtonLabel?: string;
confirmButtonState: ConfirmButtonTransitionState; confirmButtonState: ConfirmButtonTransitionState;
maxWidth?: "xs" | "sm" | "md" | "lg" | "xl" | false; maxWidth?: "xs" | "sm" | "md" | "lg" | "xl" | false;
open: boolean;
title: string; title: string;
variant?: "default" | "delete"; variant?: "default" | "delete";
onClose?();
onConfirm(); onConfirm();
} }

View file

@ -86,10 +86,18 @@ export const buttonMessages = defineMessages({
defaultMessage: "Cancel", defaultMessage: "Cancel",
description: "button" description: "button"
}, },
clear: {
defaultMessage: "Clear",
description: "button"
},
confirm: { confirm: {
defaultMessage: "Confirm", defaultMessage: "Confirm",
description: "button" description: "button"
}, },
create: {
defaultMessage: "Create",
description: "button"
},
delete: { delete: {
defaultMessage: "Delete", defaultMessage: "Delete",
description: "button" description: "button"

View file

@ -0,0 +1,105 @@
import Button from "@material-ui/core/Button";
import Card from "@material-ui/core/Card";
import CardContent from "@material-ui/core/CardContent";
import makeStyles from "@material-ui/core/styles/makeStyles";
import Typography from "@material-ui/core/Typography";
import React from "react";
import { FormattedMessage, useIntl } from "react-intl";
import CardTitle from "@saleor/components/CardTitle";
import Hr from "@saleor/components/Hr";
import { buttonMessages } from "@saleor/intl";
import { Plugin_plugin_configuration } from "@saleor/plugins/types/Plugin";
import { isSecretField } from "@saleor/plugins/utils";
import { ConfigurationTypeFieldEnum } from "@saleor/types/globalTypes";
interface PluginAuthorizationProps {
fields: Plugin_plugin_configuration[];
onClear: (field: string) => void;
onEdit: (field: string) => void;
}
const useStyles = makeStyles(theme => ({
button: {
marginLeft: theme.spacing()
},
hr: {
margin: theme.spacing(2, 0)
},
item: {
alignItems: "center",
display: "flex"
},
spacer: {
flex: 1
}
}));
const PluginAuthorization: React.FC<PluginAuthorizationProps> = props => {
const { fields, onClear, onEdit } = props;
const classes = useStyles(props);
const intl = useIntl();
const secretFields = fields.filter(field =>
isSecretField(fields, field.name)
);
return (
<Card>
<CardTitle
title={intl.formatMessage({
defaultMessage: "Authorization",
description: "section header"
})}
/>
<CardContent>
{secretFields.map((field, fieldIndex) => (
<React.Fragment key={field.name}>
<div className={classes.item} key={field.name}>
{field.type === ConfigurationTypeFieldEnum.SECRET ? (
<div>
<Typography variant="body1">{field.label}</Typography>
{field.value !== null && (
<Typography>**** {field.value}</Typography>
)}
</div>
) : (
<Typography variant="body1">{field.label}</Typography>
)}
<div className={classes.spacer} />
{field.value === null ? (
<Button
className={classes.button}
color="primary"
onClick={() => onEdit(field.name)}
>
<FormattedMessage {...buttonMessages.create} />
</Button>
) : (
<>
<Button color="primary" onClick={() => onClear(field.name)}>
<FormattedMessage {...buttonMessages.clear} />
</Button>
<Button
className={classes.button}
color="primary"
onClick={() => onEdit(field.name)}
>
<FormattedMessage {...buttonMessages.edit} />
</Button>
</>
)}
</div>
{fieldIndex !== secretFields.length - 1 && (
<Hr className={classes.hr} />
)}
</React.Fragment>
))}
</CardContent>
</Card>
);
};
PluginAuthorization.displayName = "PluginAuthorization";
export default PluginAuthorization;

View file

@ -0,0 +1,2 @@
export { default } from "./PluginAuthorization";
export * from "./PluginAuthorization";

View file

@ -0,0 +1,36 @@
import { storiesOf } from "@storybook/react";
import React from "react";
import { ConfigurationTypeFieldEnum } from "@saleor/types/globalTypes";
import Decorator from "../../../storybook/Decorator";
import PluginSecretFieldDialog, {
PluginSecretFieldDialogProps
} from "./PluginSecretFieldDialog";
const props: PluginSecretFieldDialogProps = {
confirmButtonState: "default",
field: {
__typename: "ConfigurationItem",
helpText: "",
label: "Generic Secret Field",
name: "secret",
type: ConfigurationTypeFieldEnum.SECRET,
value: "value"
},
onClose: () => undefined,
onConfirm: () => undefined,
open: true
};
storiesOf("Views / Plugins / Edit secret field", module)
.addDecorator(Decorator)
.add("secret key", () => <PluginSecretFieldDialog {...props} />)
.add("password", () => (
<PluginSecretFieldDialog
{...props}
field={{
...props.field,
type: ConfigurationTypeFieldEnum.PASSWORD
}}
/>
));

View file

@ -0,0 +1,99 @@
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 { maybe } from "@saleor/misc";
import { Plugin_plugin_configuration } from "@saleor/plugins/types/Plugin";
import { DialogProps } from "@saleor/types";
import { ConfigurationTypeFieldEnum } from "@saleor/types/globalTypes";
export interface PluginSecretFieldDialogFormData {
value: string;
}
export interface PluginSecretFieldDialogProps extends DialogProps {
confirmButtonState: ConfirmButtonTransitionState;
field: Plugin_plugin_configuration;
onConfirm: (data: PluginSecretFieldDialogFormData) => void;
}
const PluginSecretFieldDialog: React.FC<PluginSecretFieldDialogProps> = ({
confirmButtonState,
field,
onClose,
onConfirm,
open
}) => {
const intl = useIntl();
const initialForm: PluginSecretFieldDialogFormData = {
value: ""
};
return (
<Dialog fullWidth onClose={onClose} open={open} maxWidth="sm">
<DialogTitle>
{field ? (
field.value === null ? (
intl.formatMessage({
defaultMessage: "Add Value to Authorization Field",
description: "header"
})
) : (
intl.formatMessage({
defaultMessage: "Edit Authorization Field",
description: "header"
})
)
) : (
<Skeleton />
)}
</DialogTitle>
<Form initial={initialForm} onSubmit={onConfirm}>
{({ change, data, submit }) => (
<>
<DialogContent>
<TextField
fullWidth
label={field && field.label}
name="value"
type={
maybe(() => field.type) ===
ConfigurationTypeFieldEnum.PASSWORD && "password"
}
value={data.value || ""}
onChange={change}
/>
</DialogContent>
<DialogActions>
<Button onClick={onClose}>
<FormattedMessage {...buttonMessages.back} />
</Button>
<ConfirmButton
transitionState={confirmButtonState}
color="primary"
variant="contained"
onClick={submit}
>
<FormattedMessage {...buttonMessages.confirm} />
</ConfirmButton>
</DialogActions>
</>
)}
</Form>
</Dialog>
);
};
PluginSecretFieldDialog.displayName = "PluginSecretFieldDialog";
export default PluginSecretFieldDialog;

View file

@ -0,0 +1,2 @@
export { default } from "./PluginSecretFieldDialog";
export * from "./PluginSecretFieldDialog";

View file

@ -9,6 +9,7 @@ import { ConfigurationTypeFieldEnum } from "@saleor/types/globalTypes";
import React from "react"; import React from "react";
import { useIntl } from "react-intl"; import { useIntl } from "react-intl";
import { Plugin_plugin_configuration } from "@saleor/plugins/types/Plugin";
import { FormData } from "../PluginsDetailsPage"; import { FormData } from "../PluginsDetailsPage";
interface PluginSettingsProps { interface PluginSettingsProps {
@ -16,19 +17,26 @@ interface PluginSettingsProps {
errors: FormErrors<"name" | "configuration">; errors: FormErrors<"name" | "configuration">;
disabled: boolean; disabled: boolean;
onChange: (event: React.ChangeEvent<any>) => void; onChange: (event: React.ChangeEvent<any>) => void;
fields: Array<{ fields: Plugin_plugin_configuration[];
name: string;
type: ConfigurationTypeFieldEnum | null;
value: string;
helpText: string | null;
label: string | null;
}>;
} }
const useStyles = makeStyles(() => ({ const useStyles = makeStyles(theme => ({
authItem: {
display: "flex"
},
button: {
marginRight: theme.spacing()
},
item: { item: {
paddingBottom: 10, "&:not(:last-child)": {
paddingTop: 10 marginBottom: theme.spacing(3)
}
},
itemLabel: {
fontWeight: 500
},
spacer: {
flex: 1
} }
})); }));
@ -41,6 +49,7 @@ const PluginSettings: React.FC<PluginSettingsProps> = ({
}) => { }) => {
const classes = useStyles({}); const classes = useStyles({});
const intl = useIntl(); const intl = useIntl();
return ( return (
<Card> <Card>
<CardTitle <CardTitle
@ -50,35 +59,40 @@ const PluginSettings: React.FC<PluginSettingsProps> = ({
})} })}
/> />
<CardContent> <CardContent>
{data.configuration.map((configuration, index) => ( {data.configuration.map(field => {
<div className={classes.item} key={index}> const fieldData = fields.find(
{fields[index].type === ConfigurationTypeFieldEnum.STRING && ( configField => configField.name === field.name
<TextField );
disabled={disabled}
error={!!errors.name} return (
helperText={fields[index].helpText} <div className={classes.item} key={field.name}>
label={fields[index].label} {fieldData.type === ConfigurationTypeFieldEnum.BOOLEAN ? (
name={configuration.name} <ControlledCheckbox
fullWidth name={field.name}
value={configuration.value} label={fieldData.label}
onChange={onChange} checked={
/> typeof field.value !== "boolean"
)} ? field.value === "true"
{fields[index].type === ConfigurationTypeFieldEnum.BOOLEAN && ( : field.value
<ControlledCheckbox }
name={configuration.name} onChange={onChange}
label={fields[index].label} disabled={disabled}
checked={ />
typeof configuration.value !== "boolean" ) : (
? configuration.value === "true" <TextField
: configuration.value disabled={disabled}
} error={!!errors.name}
onChange={onChange} helperText={fieldData.helpText}
disabled={disabled} label={fieldData.label}
/> name={field.name}
)} fullWidth
</div> value={field.value}
))} onChange={onChange}
/>
)}
</div>
);
})}
</CardContent> </CardContent>
</Card> </Card>
); );

View file

@ -1,3 +1,4 @@
import makeStyles from "@material-ui/core/styles/makeStyles";
import Typography from "@material-ui/core/Typography"; import Typography from "@material-ui/core/Typography";
import AppHeader from "@saleor/components/AppHeader"; import AppHeader from "@saleor/components/AppHeader";
import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton";
@ -13,7 +14,12 @@ import { ConfigurationItemInput } from "@saleor/types/globalTypes";
import React from "react"; import React from "react";
import { useIntl } from "react-intl"; import { useIntl } from "react-intl";
import CardSpacer from "@saleor/components/CardSpacer";
import Hr from "@saleor/components/Hr";
import { ChangeEvent } from "@saleor/hooks/useForm";
import { isSecretField } from "@saleor/plugins/utils";
import { Plugin_plugin } from "../../types/Plugin"; import { Plugin_plugin } from "../../types/Plugin";
import PluginAuthorization from "../PluginAuthorization";
import PluginInfo from "../PluginInfo"; import PluginInfo from "../PluginInfo";
import PluginSettings from "../PluginSettings"; import PluginSettings from "../PluginSettings";
@ -28,27 +34,52 @@ export interface PluginsDetailsPageProps {
plugin: Plugin_plugin; plugin: Plugin_plugin;
saveButtonBarState: ConfirmButtonTransitionState; saveButtonBarState: ConfirmButtonTransitionState;
onBack: () => void; onBack: () => void;
onClear: (field: string) => void;
onEdit: (field: string) => void;
onSubmit: (data: FormData) => void; onSubmit: (data: FormData) => void;
} }
const PluginsDetailsPage: React.FC<PluginsDetailsPageProps> = ({ const useStyles = makeStyles(
disabled, {
errors, spacer: {
plugin, gridColumnEnd: "span 2"
saveButtonBarState, }
onBack, },
onSubmit {
}) => { name: "PluginsDetailsPage"
}
);
const PluginsDetailsPage: React.FC<PluginsDetailsPageProps> = props => {
const {
disabled,
errors,
plugin,
saveButtonBarState,
onBack,
onClear,
onEdit,
onSubmit
} = props;
const classes = useStyles(props);
const intl = useIntl(); const intl = useIntl();
const initialForm: FormData = { const initialForm: FormData = {
active: maybe(() => plugin.active, false), active: maybe(() => plugin.active, false),
configuration: maybe(() => plugin.configuration, []) configuration: maybe(() =>
plugin.configuration
.filter(field => !isSecretField(plugin.configuration, field.name))
.map(field => ({
...field,
value: field.value || ""
}))
)
}; };
return ( return (
<Form errors={errors} initial={initialForm} onSubmit={onSubmit}> <Form errors={errors} initial={initialForm} onSubmit={onSubmit}>
{({ data, errors, hasChanged, submit, set, triggerChange }) => { {({ data, errors, hasChanged, submit, set, triggerChange }) => {
const onChange = event => { const onChange = (event: ChangeEvent) => {
const newData = { const newData = {
active: data.active, active: data.active,
configuration: data.configuration configuration: data.configuration
@ -94,7 +125,7 @@ const PluginsDetailsPage: React.FC<PluginsDetailsPageProps> = ({
<Typography> <Typography>
{intl.formatMessage({ {intl.formatMessage({
defaultMessage: defaultMessage:
"These are general information about your store. They define what is the URL of your store and what is shown in brow sers taskbar." "These are general information about your store. They define what is the URL of your store and what is shown in browsers taskbar."
})} })}
</Typography> </Typography>
</div> </div>
@ -106,6 +137,7 @@ const PluginsDetailsPage: React.FC<PluginsDetailsPageProps> = ({
/> />
{data.configuration && ( {data.configuration && (
<> <>
<Hr className={classes.spacer} />
<div> <div>
<Typography variant="h6"> <Typography variant="h6">
{intl.formatMessage({ {intl.formatMessage({
@ -120,13 +152,29 @@ const PluginsDetailsPage: React.FC<PluginsDetailsPageProps> = ({
})} })}
</Typography> </Typography>
</div> </div>
<PluginSettings <div>
data={data} <PluginSettings
fields={maybe(() => plugin.configuration, [])} data={data}
errors={errors} fields={maybe(() => plugin.configuration, [])}
disabled={disabled} errors={errors}
onChange={onChange} disabled={disabled}
/> onChange={onChange}
/>
{maybe(() =>
plugin.configuration.some(field =>
isSecretField(plugin.configuration, field.name)
)
) && (
<>
<CardSpacer />
<PluginAuthorization
fields={plugin.configuration}
onClear={onClear}
onEdit={onEdit}
/>
</>
)}
</div>
</> </>
)} )}
</Grid> </Grid>

View file

@ -30,7 +30,7 @@ export const plugin: Plugin_plugin = {
label: "Username or account", label: "Username or account",
name: "Username or account", name: "Username or account",
type: ConfigurationTypeFieldEnum.STRING, type: ConfigurationTypeFieldEnum.STRING,
value: "" value: "avatax_user"
}, },
{ {
__typename: "ConfigurationItem", __typename: "ConfigurationItem",
@ -38,8 +38,32 @@ export const plugin: Plugin_plugin = {
label: "Password or license", label: "Password or license",
name: "Password or license", name: "Password or license",
type: ConfigurationTypeFieldEnum.STRING, type: ConfigurationTypeFieldEnum.STRING,
value: "TEM8S2-2ET83-CGKP1-DPSI2-EPZO1"
},
{
__typename: "ConfigurationItem",
helpText: "This key will enable you to connect to Avatax API",
label: "API key",
name: "apiKey",
type: ConfigurationTypeFieldEnum.SECRET,
value: "9ab9"
},
{
__typename: "ConfigurationItem",
helpText: "",
label: "Password",
name: "password",
type: ConfigurationTypeFieldEnum.PASSWORD,
value: "" value: ""
}, },
{
__typename: "ConfigurationItem",
helpText: "",
label: "Empty Password",
name: "password-not-set",
type: ConfigurationTypeFieldEnum.PASSWORD,
value: null
},
{ {
__typename: "ConfigurationItem", __typename: "ConfigurationItem",
helpText: "Determines if Saleor should use Avatax sandbox API.", helpText: "Determines if Saleor should use Avatax sandbox API.",
@ -51,7 +75,6 @@ export const plugin: Plugin_plugin = {
], ],
description: 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.", "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", id: "UGx1Z2luQ29uZmlndXJhdGlvbjoy",
name: "Username or account" name: "Username or account"
}; };

View file

@ -8,7 +8,8 @@ import { WindowTitle } from "../components/WindowTitle";
import { import {
pluginsListPath, pluginsListPath,
PluginsListUrlQueryParams, PluginsListUrlQueryParams,
pluginsPath pluginsPath,
PluginsUrlQueryParams
} from "./urls"; } from "./urls";
import PluginsDetailsComponent from "./views/PluginsDetails"; import PluginsDetailsComponent from "./views/PluginsDetails";
import PluginsListComponent from "./views/PluginsList"; import PluginsListComponent from "./views/PluginsList";
@ -21,7 +22,7 @@ const PluginList: React.FC<RouteComponentProps<any>> = ({ location }) => {
const PageDetails: React.FC<RouteComponentProps<any>> = ({ match }) => { const PageDetails: React.FC<RouteComponentProps<any>> = ({ match }) => {
const qs = parseQs(location.search.substr(1)); const qs = parseQs(location.search.substr(1));
const params: PluginsListUrlQueryParams = qs; const params: PluginsUrlQueryParams = qs;
return ( return (
<PluginsDetailsComponent <PluginsDetailsComponent

View file

@ -12,7 +12,7 @@ export interface Plugin_plugin_configuration {
__typename: "ConfigurationItem"; __typename: "ConfigurationItem";
name: string; name: string;
type: ConfigurationTypeFieldEnum | null; type: ConfigurationTypeFieldEnum | null;
value: string; value: string | null;
helpText: string | null; helpText: string | null;
label: string | null; label: string | null;
} }

View file

@ -2,7 +2,10 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { PluginUpdateInput, ConfigurationTypeFieldEnum } from "./../../types/globalTypes"; import {
PluginUpdateInput,
ConfigurationTypeFieldEnum
} from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: PluginUpdate // GraphQL mutation operation: PluginUpdate
@ -18,7 +21,7 @@ export interface PluginUpdate_pluginUpdate_plugin_configuration {
__typename: "ConfigurationItem"; __typename: "ConfigurationItem";
name: string; name: string;
type: ConfigurationTypeFieldEnum | null; type: ConfigurationTypeFieldEnum | null;
value: string; value: string | null;
helpText: string | null; helpText: string | null;
label: string | null; label: string | null;
} }
@ -29,7 +32,9 @@ export interface PluginUpdate_pluginUpdate_plugin {
name: string; name: string;
description: string; description: string;
active: boolean; active: boolean;
configuration: (PluginUpdate_pluginUpdate_plugin_configuration | null)[] | null; configuration:
| (PluginUpdate_pluginUpdate_plugin_configuration | null)[]
| null;
} }
export interface PluginUpdate_pluginUpdate { export interface PluginUpdate_pluginUpdate {

View file

@ -12,7 +12,7 @@ export interface PluginsDetailsFragment_configuration {
__typename: "ConfigurationItem"; __typename: "ConfigurationItem";
name: string; name: string;
type: ConfigurationTypeFieldEnum | null; type: ConfigurationTypeFieldEnum | null;
value: string; value: string | null;
helpText: string | null; helpText: string | null;
label: string | null; label: string | null;
} }

View file

@ -1,7 +1,7 @@
import { stringify as stringifyQs } from "qs"; import { stringify as stringifyQs } from "qs";
import urlJoin from "url-join"; import urlJoin from "url-join";
import { Pagination, SingleAction } from "../types"; import { Dialog, Pagination, SingleAction } from "../types";
export const pluginsSection = "/plugins/"; export const pluginsSection = "/plugins/";
@ -11,6 +11,9 @@ export const pluginsListUrl = (params?: PluginsListUrlQueryParams) =>
pluginsListPath + "?" + stringifyQs(params); pluginsListPath + "?" + stringifyQs(params);
export const pluginsPath = (id: string) => urlJoin(pluginsSection, id); export const pluginsPath = (id: string) => urlJoin(pluginsSection, id);
export type PluginsUrlQueryParams = SingleAction; export type PluginUrlDialog = "clear" | "edit";
export type PluginsUrlQueryParams = Dialog<PluginUrlDialog> & {
field?: string;
};
export const pluginsUrl = (id: string, params?: PluginsUrlQueryParams) => export const pluginsUrl = (id: string, params?: PluginsUrlQueryParams) =>
pluginsPath(encodeURIComponent(id)) + "?" + stringifyQs(params); pluginsPath(encodeURIComponent(id)) + "?" + stringifyQs(params);

12
src/plugins/utils.ts Normal file
View file

@ -0,0 +1,12 @@
import { ConfigurationTypeFieldEnum } from "@saleor/types/globalTypes";
import { Plugin_plugin_configuration } from "./types/Plugin";
export function isSecretField(
config: Plugin_plugin_configuration[],
field: string
) {
return [
ConfigurationTypeFieldEnum.PASSWORD,
ConfigurationTypeFieldEnum.SECRET
].includes(config.find(configField => configField.name === field).type);
}

View file

@ -0,0 +1,87 @@
import {
ConfigurationItemInput,
ConfigurationTypeFieldEnum
} from "../../types/globalTypes";
import { Plugin_plugin_configuration } from "../types/Plugin";
import { getConfigurationInput } from "./PluginsDetails";
const baseConfig: Omit<
Plugin_plugin_configuration,
"name" | "type" | "value"
> = {
__typename: "ConfigurationItem",
helpText: "",
label: ""
};
const config: Plugin_plugin_configuration[] = [
{
...baseConfig,
name: "field-1",
type: ConfigurationTypeFieldEnum.STRING,
value: "val1"
},
{
...baseConfig,
name: "field-2",
type: ConfigurationTypeFieldEnum.STRING,
value: "val2"
},
{
...baseConfig,
name: "field-3",
type: ConfigurationTypeFieldEnum.PASSWORD,
value: ""
},
{
...baseConfig,
name: "field-4",
type: ConfigurationTypeFieldEnum.SECRET,
value: "val4"
}
];
const input: ConfigurationItemInput[] = [
{
name: "field-1",
value: "value1"
},
{
name: "field-2",
value: "value2"
},
{
name: "field-3",
value: "value3"
},
{
name: "field-4",
value: "value4"
}
];
test("Ensure that no secret is sent in input", () => {
const output: ConfigurationItemInput[] = getConfigurationInput(config, input);
expect(output).toHaveLength(2);
expect(
output.find(
field =>
config.find(configField => configField.name === field.name).type ===
ConfigurationTypeFieldEnum.PASSWORD
)
).toBeFalsy();
expect(
output.find(
field =>
config.find(configField => configField.name === field.name).type ===
ConfigurationTypeFieldEnum.SECRET
)
).toBeFalsy();
});
test("Handles null input", () => {
const output = getConfigurationInput(null, null);
expect(output).toBeNull();
});

View file

@ -1,30 +1,90 @@
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 { WindowTitle } from "@saleor/components/WindowTitle";
import useNavigator from "@saleor/hooks/useNavigator"; import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier"; import useNotifier from "@saleor/hooks/useNotifier";
import React from "react"; import { commonMessages } from "@saleor/intl";
import { useIntl } from "react-intl"; import { ConfigurationItemInput } from "@saleor/types/globalTypes";
import { getMutationState, maybe } from "../../misc"; import { getMutationState, maybe } from "../../misc";
import PluginsDetailsPage from "../components/PluginsDetailsPage"; import PluginsDetailsPage from "../components/PluginsDetailsPage";
import PluginSecretFieldDialog from "../components/PluginSecretFieldDialog";
import { TypedPluginUpdate } from "../mutations"; import { TypedPluginUpdate } from "../mutations";
import { TypedPluginsDetailsQuery } from "../queries"; import { TypedPluginsDetailsQuery } from "../queries";
import { pluginsListUrl, PluginsListUrlQueryParams } from "../urls"; import { Plugin_plugin_configuration } from "../types/Plugin";
import { PluginUpdate } from "../types/PluginUpdate";
import {
pluginsListUrl,
pluginsUrl,
PluginsUrlQueryParams,
PluginUrlDialog
} from "../urls";
import { isSecretField } from "../utils";
export interface PluginsDetailsProps { export interface PluginsDetailsProps {
id: string; id: string;
params: PluginsListUrlQueryParams; params: PluginsUrlQueryParams;
} }
export const PluginsDetails: React.FC<PluginsDetailsProps> = ({ id }) => { export function getConfigurationInput(
config: Plugin_plugin_configuration[] | null,
input: ConfigurationItemInput[] | null
): ConfigurationItemInput[] | null {
if (config === null || input === null) {
return null;
}
return input
.filter(field => !isSecretField(config, field.name))
.map(field => ({
name: field.name,
value: field.value.toString()
}));
}
export const PluginsDetails: React.FC<PluginsDetailsProps> = ({
id,
params
}) => {
const navigate = useNavigator(); const navigate = useNavigator();
const notify = useNotifier(); const notify = useNotifier();
const intl = useIntl(); const intl = useIntl();
const closeModal = () =>
navigate(
pluginsUrl(id, {
...params,
action: undefined,
field: undefined
}),
true
);
const openModal = (action: PluginUrlDialog, field?: string) =>
navigate(
pluginsUrl(id, {
...params,
action,
field
})
);
const handleUpdate = (data: PluginUpdate) => {
if (data.pluginUpdate.errors.length === 0) {
notify({
text: intl.formatMessage(commonMessages.savedChanges)
});
closeModal();
}
};
return ( return (
<TypedPluginUpdate> <TypedPluginsDetailsQuery variables={{ id }}>
{(pluginUpdate, pluginUpdateOpts) => ( {pluginDetails => (
<TypedPluginsDetailsQuery variables={{ id }}> <TypedPluginUpdate onCompleted={handleUpdate}>
{PluginDetails => { {(pluginUpdate, pluginUpdateOpts) => {
const formTransitionState = getMutationState( const formTransitionState = getMutationState(
pluginUpdateOpts.called, pluginUpdateOpts.called,
pluginUpdateOpts.loading, pluginUpdateOpts.loading,
@ -36,62 +96,90 @@ export const PluginsDetails: React.FC<PluginsDetailsProps> = ({ id }) => {
[] []
); );
if (formErrors.length) { const handleFieldUpdate = (value: string) =>
formErrors.map(error => { pluginUpdate({
notify({ variables: {
text: error.message 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 ( return (
<> <>
<WindowTitle <WindowTitle
title={maybe(() => PluginDetails.data.plugin.name)} title={maybe(() => pluginDetails.data.plugin.name)}
/> />
<PluginsDetailsPage <PluginsDetailsPage
disabled={PluginDetails.loading} disabled={pluginDetails.loading}
errors={formErrors} errors={formErrors}
saveButtonBarState={formTransitionState} saveButtonBarState={
plugin={maybe(() => PluginDetails.data.plugin)} !params.action ? formTransitionState : "default"
}
plugin={maybe(() => pluginDetails.data.plugin)}
onBack={() => navigate(pluginsListUrl())} onBack={() => navigate(pluginsListUrl())}
onSubmit={formData => { onClear={field => openModal("clear", field)}
const configurationInput = onEdit={field => openModal("edit", field)}
formData.configuration && onSubmit={formData =>
formData.configuration.map(item => {
return {
name: item.name,
value: item.value.toString()
};
});
pluginUpdate({ pluginUpdate({
variables: { variables: {
id, id,
input: { input: {
active: formData.active, active: formData.active,
configuration: configurationInput configuration: getConfigurationInput(
? configurationInput pluginDetails.data.plugin.configuration,
: null formData.configuration
)
} }
} }
}); })
}} }
/> />
{maybe(() => pluginDetails.data.plugin.configuration) && (
<>
<ActionDialog
confirmButtonState={
!!params.action ? formTransitionState : "default"
}
onClose={closeModal}
open={params.action === "clear" && !!params.field}
title={intl.formatMessage({
defaultMessage: "Authorization Field Delete",
description: "header"
})}
onConfirm={() => handleFieldUpdate(null)}
>
<DialogContentText>
<FormattedMessage defaultMessage="The plugin may stop working after this field is cleared. Are you sure you want to proceed?" />
</DialogContentText>
</ActionDialog>
<PluginSecretFieldDialog
confirmButtonState={
!!params.action ? formTransitionState : "default"
}
field={maybe(() =>
pluginDetails.data.plugin.configuration.find(
field => field.name === params.field
)
)}
onClose={closeModal}
onConfirm={formData => handleFieldUpdate(formData.value)}
open={params.action === "edit" && !!params.field}
/>
</>
)}
</> </>
); );
}} }}
</TypedPluginsDetailsQuery> </TypedPluginUpdate>
)} )}
</TypedPluginUpdate> </TypedPluginsDetailsQuery>
); );
}; };
PluginsDetails.displayName = "PluginsDetails"; PluginsDetails.displayName = "PluginsDetails";

View file

@ -78529,6 +78529,18 @@ exports[`Storyshots Views / Pages / Page list no data 1`] = `
</div> </div>
`; `;
exports[`Storyshots Views / Plugins / Edit secret field password 1`] = `
<div
style="padding:24px"
/>
`;
exports[`Storyshots Views / Plugins / Edit secret field secret key 1`] = `
<div
style="padding:24px"
/>
`;
exports[`Storyshots Views / Plugins / Plugin details default 1`] = ` exports[`Storyshots Views / Plugins / Plugin details default 1`] = `
<div <div
style="padding:24px" style="padding:24px"
@ -78565,7 +78577,7 @@ exports[`Storyshots Views / Plugins / Plugin details default 1`] = `
<div <div
class="MuiTypography-root-id MuiTypography-body1-id" class="MuiTypography-root-id MuiTypography-body1-id"
> >
These are general information about your store. They define what is the URL of your store and what is shown in brow sers taskbar. These are general information about your store. They define what is the URL of your store and what is shown in browsers taskbar.
</div> </div>
</div> </div>
<div <div
@ -78646,6 +78658,9 @@ exports[`Storyshots Views / Plugins / Plugin details default 1`] = `
</label> </label>
</div> </div>
</div> </div>
<hr
class="makeStyles-root-id PluginsDetailsPage-spacer-id"
/>
<div> <div>
<div <div
class="MuiTypography-root-id MuiTypography-h6-id" class="MuiTypography-root-id MuiTypography-h6-id"
@ -78658,142 +78673,277 @@ exports[`Storyshots Views / Plugins / Plugin details default 1`] = `
This adress will be used to generate invoices and calculate shipping rates. Email adress you provide here will be used as a contact adress for your customers. This adress will be used to generate invoices and calculate shipping rates. Email adress you provide here will be used as a contact adress for your customers.
</div> </div>
</div> </div>
<div <div>
class="MuiPaper-root-id MuiPaper-elevation0-id MuiCard-root-id MuiPaper-rounded-id"
>
<div <div
class="makeStyles-root-id" class="MuiPaper-root-id MuiPaper-elevation0-id MuiCard-root-id MuiPaper-rounded-id"
> >
<span
class="MuiTypography-root-id makeStyles-title-id MuiTypography-h5-id"
>
Plugin Settings
</span>
<div <div
class="makeStyles-toolbar-id" class="makeStyles-root-id"
>
<span
class="MuiTypography-root-id makeStyles-title-id MuiTypography-h5-id"
>
Plugin Settings
</span>
<div
class="makeStyles-toolbar-id"
/>
</div>
<div
class="makeStyles-children-id"
/> />
<hr
class="makeStyles-hr-id"
/>
<div
class="MuiCardContent-root-id"
>
<div
class="makeStyles-item-id"
>
<div
class="MuiFormControl-root-id MuiTextField-root-id MuiFormControl-fullWidth-id"
>
<label
class="MuiFormLabel-root-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-shrink-id MuiInputLabel-outlined-id MuiFormLabel-filled-id"
data-shrink="true"
>
Username or account
</label>
<div
class="MuiInputBase-root-id MuiOutlinedInput-root-id MuiInputBase-fullWidth-id MuiInputBase-formControl-id"
>
<input
aria-invalid="false"
class="MuiInputBase-input-id MuiOutlinedInput-input-id"
name="Username or account"
type="text"
value="avatax_user"
/>
<fieldset
aria-hidden="true"
class="PrivateNotchedOutline-root-id MuiOutlinedInput-notchedOutline-id"
style="padding-left:8px"
>
<legend
class="PrivateNotchedOutline-legend-id"
style="width:0"
>
<span>
</span>
</legend>
</fieldset>
</div>
<p
class="MuiFormHelperText-root-id MuiFormHelperText-contained-id MuiFormHelperText-filled-id"
>
Provide user or account details
</p>
</div>
</div>
<div
class="makeStyles-item-id"
>
<div
class="MuiFormControl-root-id MuiTextField-root-id MuiFormControl-fullWidth-id"
>
<label
class="MuiFormLabel-root-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-shrink-id MuiInputLabel-outlined-id MuiFormLabel-filled-id"
data-shrink="true"
>
Password or license
</label>
<div
class="MuiInputBase-root-id MuiOutlinedInput-root-id MuiInputBase-fullWidth-id MuiInputBase-formControl-id"
>
<input
aria-invalid="false"
class="MuiInputBase-input-id MuiOutlinedInput-input-id"
name="Password or license"
type="text"
value="TEM8S2-2ET83-CGKP1-DPSI2-EPZO1"
/>
<fieldset
aria-hidden="true"
class="PrivateNotchedOutline-root-id MuiOutlinedInput-notchedOutline-id"
style="padding-left:8px"
>
<legend
class="PrivateNotchedOutline-legend-id"
style="width:0"
>
<span>
</span>
</legend>
</fieldset>
</div>
<p
class="MuiFormHelperText-root-id MuiFormHelperText-contained-id MuiFormHelperText-filled-id"
>
Provide password or license details
</p>
</div>
</div>
<div
class="makeStyles-item-id"
>
<label
class="MuiFormControlLabel-root-id"
>
<button
class="MuiButtonBase-root-id makeStyles-root-id"
tabindex="0"
type="button"
>
<input
class="makeStyles-box-id makeStyles-checked-id"
name="Use sandbox"
type="checkbox"
value="true"
/>
</button>
<span
class="MuiTypography-root-id MuiFormControlLabel-label-id MuiTypography-body1-id"
>
Use sandbox
</span>
</label>
</div>
</div>
</div> </div>
<div <div
class="makeStyles-children-id" class="makeStyles-spacer-id"
/>
<hr
class="makeStyles-hr-id"
/> />
<div <div
class="MuiCardContent-root-id" class="MuiPaper-root-id MuiPaper-elevation0-id MuiCard-root-id MuiPaper-rounded-id"
> >
<div <div
class="makeStyles-item-id" class="makeStyles-root-id"
> >
<div <span
class="MuiFormControl-root-id MuiTextField-root-id MuiFormControl-fullWidth-id" class="MuiTypography-root-id makeStyles-title-id MuiTypography-h5-id"
> >
<label Authorization
class="MuiFormLabel-root-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-outlined-id" </span>
data-shrink="false" <div
> class="makeStyles-toolbar-id"
Username or account />
</label>
<div
class="MuiInputBase-root-id MuiOutlinedInput-root-id MuiInputBase-fullWidth-id MuiInputBase-formControl-id"
>
<input
aria-invalid="false"
class="MuiInputBase-input-id MuiOutlinedInput-input-id"
name="Username or account"
type="text"
value=""
/>
<fieldset
aria-hidden="true"
class="PrivateNotchedOutline-root-id MuiOutlinedInput-notchedOutline-id"
style="padding-left:8px"
>
<legend
class="PrivateNotchedOutline-legend-id"
style="width:0.01px"
>
<span>
</span>
</legend>
</fieldset>
</div>
<p
class="MuiFormHelperText-root-id MuiFormHelperText-contained-id"
>
Provide user or account details
</p>
</div>
</div> </div>
<div <div
class="makeStyles-item-id" class="makeStyles-children-id"
/>
<hr
class="makeStyles-hr-id"
/>
<div
class="MuiCardContent-root-id"
> >
<div <div
class="MuiFormControl-root-id MuiTextField-root-id MuiFormControl-fullWidth-id" class="makeStyles-item-id"
> >
<label <div>
class="MuiFormLabel-root-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-outlined-id" <div
data-shrink="false" class="MuiTypography-root-id MuiTypography-body1-id"
>
Password or license
</label>
<div
class="MuiInputBase-root-id MuiOutlinedInput-root-id MuiInputBase-fullWidth-id MuiInputBase-formControl-id"
>
<input
aria-invalid="false"
class="MuiInputBase-input-id MuiOutlinedInput-input-id"
name="Password or license"
type="text"
value=""
/>
<fieldset
aria-hidden="true"
class="PrivateNotchedOutline-root-id MuiOutlinedInput-notchedOutline-id"
style="padding-left:8px"
> >
<legend API key
class="PrivateNotchedOutline-legend-id" </div>
style="width:0.01px" <div
> class="MuiTypography-root-id MuiTypography-body1-id"
<span> >
**** 9ab9
</span> </div>
</legend>
</fieldset>
</div> </div>
<p <div
class="MuiFormHelperText-root-id MuiFormHelperText-contained-id" class="makeStyles-spacer-id"
> />
Provide password or license details
</p>
</div>
</div>
<div
class="makeStyles-item-id"
>
<label
class="MuiFormControlLabel-root-id"
>
<button <button
class="MuiButtonBase-root-id makeStyles-root-id" class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
tabindex="0" tabindex="0"
type="button" type="button"
> >
<input <span
class="makeStyles-box-id makeStyles-checked-id" class="MuiButton-label-id"
name="Use sandbox" >
type="checkbox" Clear
value="true" </span>
/>
</button> </button>
<span <button
class="MuiTypography-root-id MuiFormControlLabel-label-id MuiTypography-body1-id" class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id makeStyles-button-id MuiButton-textPrimary-id"
tabindex="0"
type="button"
> >
Use sandbox <span
</span> class="MuiButton-label-id"
</label> >
Edit
</span>
</button>
</div>
<hr
class="makeStyles-root-id makeStyles-hr-id"
/>
<div
class="makeStyles-item-id"
>
<div
class="MuiTypography-root-id MuiTypography-body1-id"
>
Password
</div>
<div
class="makeStyles-spacer-id"
/>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
tabindex="0"
type="button"
>
<span
class="MuiButton-label-id"
>
Clear
</span>
</button>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id makeStyles-button-id MuiButton-textPrimary-id"
tabindex="0"
type="button"
>
<span
class="MuiButton-label-id"
>
Edit
</span>
</button>
</div>
<hr
class="makeStyles-root-id makeStyles-hr-id"
/>
<div
class="makeStyles-item-id"
>
<div
class="MuiTypography-root-id MuiTypography-body1-id"
>
Empty Password
</div>
<div
class="makeStyles-spacer-id"
/>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id makeStyles-button-id MuiButton-textPrimary-id"
tabindex="0"
type="button"
>
<span
class="MuiButton-label-id"
>
Create
</span>
</button>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -78839,7 +78989,7 @@ exports[`Storyshots Views / Plugins / Plugin details form errors 1`] = `
<div <div
class="MuiTypography-root-id MuiTypography-body1-id" class="MuiTypography-root-id MuiTypography-body1-id"
> >
These are general information about your store. They define what is the URL of your store and what is shown in brow sers taskbar. These are general information about your store. They define what is the URL of your store and what is shown in browsers taskbar.
</div> </div>
</div> </div>
<div <div
@ -78920,6 +79070,9 @@ exports[`Storyshots Views / Plugins / Plugin details form errors 1`] = `
</label> </label>
</div> </div>
</div> </div>
<hr
class="makeStyles-root-id PluginsDetailsPage-spacer-id"
/>
<div> <div>
<div <div
class="MuiTypography-root-id MuiTypography-h6-id" class="MuiTypography-root-id MuiTypography-h6-id"
@ -78932,142 +79085,277 @@ exports[`Storyshots Views / Plugins / Plugin details form errors 1`] = `
This adress will be used to generate invoices and calculate shipping rates. Email adress you provide here will be used as a contact adress for your customers. This adress will be used to generate invoices and calculate shipping rates. Email adress you provide here will be used as a contact adress for your customers.
</div> </div>
</div> </div>
<div <div>
class="MuiPaper-root-id MuiPaper-elevation0-id MuiCard-root-id MuiPaper-rounded-id"
>
<div <div
class="makeStyles-root-id" class="MuiPaper-root-id MuiPaper-elevation0-id MuiCard-root-id MuiPaper-rounded-id"
> >
<span
class="MuiTypography-root-id makeStyles-title-id MuiTypography-h5-id"
>
Plugin Settings
</span>
<div <div
class="makeStyles-toolbar-id" class="makeStyles-root-id"
>
<span
class="MuiTypography-root-id makeStyles-title-id MuiTypography-h5-id"
>
Plugin Settings
</span>
<div
class="makeStyles-toolbar-id"
/>
</div>
<div
class="makeStyles-children-id"
/> />
<hr
class="makeStyles-hr-id"
/>
<div
class="MuiCardContent-root-id"
>
<div
class="makeStyles-item-id"
>
<div
class="MuiFormControl-root-id MuiTextField-root-id MuiFormControl-fullWidth-id"
>
<label
class="MuiFormLabel-root-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-shrink-id MuiInputLabel-outlined-id MuiFormLabel-filled-id"
data-shrink="true"
>
Username or account
</label>
<div
class="MuiInputBase-root-id MuiOutlinedInput-root-id MuiInputBase-fullWidth-id MuiInputBase-formControl-id"
>
<input
aria-invalid="false"
class="MuiInputBase-input-id MuiOutlinedInput-input-id"
name="Username or account"
type="text"
value="avatax_user"
/>
<fieldset
aria-hidden="true"
class="PrivateNotchedOutline-root-id MuiOutlinedInput-notchedOutline-id"
style="padding-left:8px"
>
<legend
class="PrivateNotchedOutline-legend-id"
style="width:0"
>
<span>
</span>
</legend>
</fieldset>
</div>
<p
class="MuiFormHelperText-root-id MuiFormHelperText-contained-id MuiFormHelperText-filled-id"
>
Provide user or account details
</p>
</div>
</div>
<div
class="makeStyles-item-id"
>
<div
class="MuiFormControl-root-id MuiTextField-root-id MuiFormControl-fullWidth-id"
>
<label
class="MuiFormLabel-root-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-shrink-id MuiInputLabel-outlined-id MuiFormLabel-filled-id"
data-shrink="true"
>
Password or license
</label>
<div
class="MuiInputBase-root-id MuiOutlinedInput-root-id MuiInputBase-fullWidth-id MuiInputBase-formControl-id"
>
<input
aria-invalid="false"
class="MuiInputBase-input-id MuiOutlinedInput-input-id"
name="Password or license"
type="text"
value="TEM8S2-2ET83-CGKP1-DPSI2-EPZO1"
/>
<fieldset
aria-hidden="true"
class="PrivateNotchedOutline-root-id MuiOutlinedInput-notchedOutline-id"
style="padding-left:8px"
>
<legend
class="PrivateNotchedOutline-legend-id"
style="width:0"
>
<span>
</span>
</legend>
</fieldset>
</div>
<p
class="MuiFormHelperText-root-id MuiFormHelperText-contained-id MuiFormHelperText-filled-id"
>
Provide password or license details
</p>
</div>
</div>
<div
class="makeStyles-item-id"
>
<label
class="MuiFormControlLabel-root-id"
>
<button
class="MuiButtonBase-root-id makeStyles-root-id"
tabindex="0"
type="button"
>
<input
class="makeStyles-box-id makeStyles-checked-id"
name="Use sandbox"
type="checkbox"
value="true"
/>
</button>
<span
class="MuiTypography-root-id MuiFormControlLabel-label-id MuiTypography-body1-id"
>
Use sandbox
</span>
</label>
</div>
</div>
</div> </div>
<div <div
class="makeStyles-children-id" class="makeStyles-spacer-id"
/>
<hr
class="makeStyles-hr-id"
/> />
<div <div
class="MuiCardContent-root-id" class="MuiPaper-root-id MuiPaper-elevation0-id MuiCard-root-id MuiPaper-rounded-id"
> >
<div <div
class="makeStyles-item-id" class="makeStyles-root-id"
> >
<div <span
class="MuiFormControl-root-id MuiTextField-root-id MuiFormControl-fullWidth-id" class="MuiTypography-root-id makeStyles-title-id MuiTypography-h5-id"
> >
<label Authorization
class="MuiFormLabel-root-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-outlined-id" </span>
data-shrink="false" <div
> class="makeStyles-toolbar-id"
Username or account />
</label>
<div
class="MuiInputBase-root-id MuiOutlinedInput-root-id MuiInputBase-fullWidth-id MuiInputBase-formControl-id"
>
<input
aria-invalid="false"
class="MuiInputBase-input-id MuiOutlinedInput-input-id"
name="Username or account"
type="text"
value=""
/>
<fieldset
aria-hidden="true"
class="PrivateNotchedOutline-root-id MuiOutlinedInput-notchedOutline-id"
style="padding-left:8px"
>
<legend
class="PrivateNotchedOutline-legend-id"
style="width:0.01px"
>
<span>
</span>
</legend>
</fieldset>
</div>
<p
class="MuiFormHelperText-root-id MuiFormHelperText-contained-id"
>
Provide user or account details
</p>
</div>
</div> </div>
<div <div
class="makeStyles-item-id" class="makeStyles-children-id"
/>
<hr
class="makeStyles-hr-id"
/>
<div
class="MuiCardContent-root-id"
> >
<div <div
class="MuiFormControl-root-id MuiTextField-root-id MuiFormControl-fullWidth-id" class="makeStyles-item-id"
> >
<label <div>
class="MuiFormLabel-root-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-outlined-id" <div
data-shrink="false" class="MuiTypography-root-id MuiTypography-body1-id"
>
Password or license
</label>
<div
class="MuiInputBase-root-id MuiOutlinedInput-root-id MuiInputBase-fullWidth-id MuiInputBase-formControl-id"
>
<input
aria-invalid="false"
class="MuiInputBase-input-id MuiOutlinedInput-input-id"
name="Password or license"
type="text"
value=""
/>
<fieldset
aria-hidden="true"
class="PrivateNotchedOutline-root-id MuiOutlinedInput-notchedOutline-id"
style="padding-left:8px"
> >
<legend API key
class="PrivateNotchedOutline-legend-id" </div>
style="width:0.01px" <div
> class="MuiTypography-root-id MuiTypography-body1-id"
<span> >
**** 9ab9
</span> </div>
</legend>
</fieldset>
</div> </div>
<p <div
class="MuiFormHelperText-root-id MuiFormHelperText-contained-id" class="makeStyles-spacer-id"
> />
Provide password or license details
</p>
</div>
</div>
<div
class="makeStyles-item-id"
>
<label
class="MuiFormControlLabel-root-id"
>
<button <button
class="MuiButtonBase-root-id makeStyles-root-id" class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
tabindex="0" tabindex="0"
type="button" type="button"
> >
<input <span
class="makeStyles-box-id makeStyles-checked-id" class="MuiButton-label-id"
name="Use sandbox" >
type="checkbox" Clear
value="true" </span>
/>
</button> </button>
<span <button
class="MuiTypography-root-id MuiFormControlLabel-label-id MuiTypography-body1-id" class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id makeStyles-button-id MuiButton-textPrimary-id"
tabindex="0"
type="button"
> >
Use sandbox <span
</span> class="MuiButton-label-id"
</label> >
Edit
</span>
</button>
</div>
<hr
class="makeStyles-root-id makeStyles-hr-id"
/>
<div
class="makeStyles-item-id"
>
<div
class="MuiTypography-root-id MuiTypography-body1-id"
>
Password
</div>
<div
class="makeStyles-spacer-id"
/>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id MuiButton-textPrimary-id"
tabindex="0"
type="button"
>
<span
class="MuiButton-label-id"
>
Clear
</span>
</button>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id makeStyles-button-id MuiButton-textPrimary-id"
tabindex="0"
type="button"
>
<span
class="MuiButton-label-id"
>
Edit
</span>
</button>
</div>
<hr
class="makeStyles-root-id makeStyles-hr-id"
/>
<div
class="makeStyles-item-id"
>
<div
class="MuiTypography-root-id MuiTypography-body1-id"
>
Empty Password
</div>
<div
class="makeStyles-spacer-id"
/>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-text-id makeStyles-button-id MuiButton-textPrimary-id"
tabindex="0"
type="button"
>
<span
class="MuiButton-label-id"
>
Create
</span>
</button>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -79113,7 +79401,7 @@ exports[`Storyshots Views / Plugins / Plugin details loading 1`] = `
<div <div
class="MuiTypography-root-id MuiTypography-body1-id" class="MuiTypography-root-id MuiTypography-body1-id"
> >
These are general information about your store. They define what is the URL of your store and what is shown in brow sers taskbar. These are general information about your store. They define what is the URL of your store and what is shown in browsers taskbar.
</div> </div>
</div> </div>
<div <div
@ -79182,16 +79470,49 @@ exports[`Storyshots Views / Plugins / Plugin details loading 1`] = `
</label> </label>
</div> </div>
</div> </div>
</div>
</div>
</form>
</div>
`;
exports[`Storyshots Views / Plugins / Plugin details not configurable 1`] = `
<div
style="padding:24px"
>
<form>
<div
class="makeStyles-root-id"
>
<div
class="makeStyles-root-id"
>
<div
class="MuiTypography-root-id makeStyles-title-id MuiTypography-h5-id"
>
Username or account Details
</div>
<div
class="makeStyles-action-id"
>
<div
class="makeStyles-root-id"
/>
</div>
</div>
<div
class="makeStyles-root-id makeStyles-inverted-id"
>
<div> <div>
<div <div
class="MuiTypography-root-id MuiTypography-h6-id" class="MuiTypography-root-id MuiTypography-h6-id"
> >
Plugin Settings Plugin Information and Status
</div> </div>
<div <div
class="MuiTypography-root-id MuiTypography-body1-id" class="MuiTypography-root-id MuiTypography-body1-id"
> >
This adress will be used to generate invoices and calculate shipping rates. Email adress you provide here will be used as a contact adress for your customers. These are general information about your store. They define what is the URL of your store and what is shown in browsers taskbar.
</div> </div>
</div> </div>
<div <div
@ -79203,7 +79524,7 @@ exports[`Storyshots Views / Plugins / Plugin details loading 1`] = `
<span <span
class="MuiTypography-root-id makeStyles-title-id MuiTypography-h5-id" class="MuiTypography-root-id makeStyles-title-id MuiTypography-h5-id"
> >
Plugin Settings Plugin Information and Status
</span> </span>
<div <div
class="makeStyles-toolbar-id" class="makeStyles-toolbar-id"
@ -79217,7 +79538,60 @@ exports[`Storyshots Views / Plugins / Plugin details loading 1`] = `
/> />
<div <div
class="MuiCardContent-root-id" class="MuiCardContent-root-id"
/> >
<div
class="MuiTypography-root-id makeStyles-title-id MuiTypography-h6-id"
>
Plugin Name
</div>
<div
class="MuiTypography-root-id MuiTypography-body1-id"
>
Username or account
</div>
<div
class="MuiTypography-root-id makeStyles-title-id MuiTypography-h6-id"
>
Description
</div>
<div
class="MuiTypography-root-id MuiTypography-body1-id"
>
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.
</div>
<div
class="makeStyles-spacer-id"
/>
<hr
class="makeStyles-root-id"
/>
<div
class="MuiTypography-root-id makeStyles-status-id MuiTypography-body1-id"
>
Status
</div>
<label
class="MuiFormControlLabel-root-id"
>
<button
class="MuiButtonBase-root-id makeStyles-root-id"
tabindex="0"
type="button"
>
<input
class="makeStyles-box-id makeStyles-checked-id"
name="active"
type="checkbox"
value="true"
/>
</button>
<span
class="MuiTypography-root-id MuiFormControlLabel-label-id MuiTypography-body1-id"
>
Set plugin as Active
</span>
</label>
</div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -13,6 +13,8 @@ const props: PluginsDetailsPageProps = {
disabled: false, disabled: false,
errors: [], errors: [],
onBack: () => undefined, onBack: () => undefined,
onClear: () => undefined,
onEdit: () => undefined,
onSubmit: () => undefined, onSubmit: () => undefined,
plugin, plugin,
saveButtonBarState: "default" saveButtonBarState: "default"
@ -33,4 +35,13 @@ storiesOf("Views / Plugins / Plugin details", module)
"Password or license" "Password or license"
] as Array<keyof FormData>).map(formError)} ] as Array<keyof FormData>).map(formError)}
/> />
))
.add("not configurable", () => (
<PluginsDetailsPage
{...props}
plugin={{
...plugin,
configuration: null
}}
/>
)); ));

View file

@ -9,6 +9,11 @@ export interface UserError {
message: string; message: string;
} }
export interface DialogProps {
open: boolean;
onClose: () => void;
}
export interface ListSettings<TColumn extends string = string> { export interface ListSettings<TColumn extends string = string> {
columns?: TColumn[]; columns?: TColumn[];
rowNumber: number; rowNumber: number;

View file

@ -8,39 +8,41 @@
export enum AddressTypeEnum { export enum AddressTypeEnum {
BILLING = "BILLING", BILLING = "BILLING",
SHIPPING = "SHIPPING", SHIPPING = "SHIPPING"
} }
export enum AttributeInputTypeEnum { export enum AttributeInputTypeEnum {
DROPDOWN = "DROPDOWN", DROPDOWN = "DROPDOWN",
MULTISELECT = "MULTISELECT", MULTISELECT = "MULTISELECT"
} }
export enum AttributeTypeEnum { export enum AttributeTypeEnum {
PRODUCT = "PRODUCT", PRODUCT = "PRODUCT",
VARIANT = "VARIANT", VARIANT = "VARIANT"
} }
export enum AttributeValueType { export enum AttributeValueType {
COLOR = "COLOR", COLOR = "COLOR",
GRADIENT = "GRADIENT", GRADIENT = "GRADIENT",
STRING = "STRING", STRING = "STRING",
URL = "URL", URL = "URL"
} }
export enum AuthorizationKeyType { export enum AuthorizationKeyType {
FACEBOOK = "FACEBOOK", FACEBOOK = "FACEBOOK",
GOOGLE_OAUTH2 = "GOOGLE_OAUTH2", GOOGLE_OAUTH2 = "GOOGLE_OAUTH2"
} }
export enum CollectionPublished { export enum CollectionPublished {
HIDDEN = "HIDDEN", HIDDEN = "HIDDEN",
PUBLISHED = "PUBLISHED", PUBLISHED = "PUBLISHED"
} }
export enum ConfigurationTypeFieldEnum { export enum ConfigurationTypeFieldEnum {
BOOLEAN = "BOOLEAN", BOOLEAN = "BOOLEAN",
STRING = "STRING", PASSWORD = "PASSWORD",
SECRET = "SECRET",
STRING = "STRING"
} }
export enum CountryCode { export enum CountryCode {
@ -293,23 +295,23 @@ export enum CountryCode {
YT = "YT", YT = "YT",
ZA = "ZA", ZA = "ZA",
ZM = "ZM", ZM = "ZM",
ZW = "ZW", ZW = "ZW"
} }
export enum DiscountStatusEnum { export enum DiscountStatusEnum {
ACTIVE = "ACTIVE", ACTIVE = "ACTIVE",
EXPIRED = "EXPIRED", EXPIRED = "EXPIRED",
SCHEDULED = "SCHEDULED", SCHEDULED = "SCHEDULED"
} }
export enum DiscountValueTypeEnum { export enum DiscountValueTypeEnum {
FIXED = "FIXED", FIXED = "FIXED",
PERCENTAGE = "PERCENTAGE", PERCENTAGE = "PERCENTAGE"
} }
export enum FulfillmentStatus { export enum FulfillmentStatus {
CANCELED = "CANCELED", CANCELED = "CANCELED",
FULFILLED = "FULFILLED", FULFILLED = "FULFILLED"
} }
export enum LanguageCodeEnum { export enum LanguageCodeEnum {
@ -355,19 +357,19 @@ export enum LanguageCodeEnum {
UK = "UK", UK = "UK",
VI = "VI", VI = "VI",
ZH_HANS = "ZH_HANS", ZH_HANS = "ZH_HANS",
ZH_HANT = "ZH_HANT", ZH_HANT = "ZH_HANT"
} }
export enum OrderAction { export enum OrderAction {
CAPTURE = "CAPTURE", CAPTURE = "CAPTURE",
MARK_AS_PAID = "MARK_AS_PAID", MARK_AS_PAID = "MARK_AS_PAID",
REFUND = "REFUND", REFUND = "REFUND",
VOID = "VOID", VOID = "VOID"
} }
export enum OrderDirection { export enum OrderDirection {
ASC = "ASC", ASC = "ASC",
DESC = "DESC", DESC = "DESC"
} }
export enum OrderEventsEmailsEnum { export enum OrderEventsEmailsEnum {
@ -376,7 +378,7 @@ export enum OrderEventsEmailsEnum {
ORDER_CONFIRMATION = "ORDER_CONFIRMATION", ORDER_CONFIRMATION = "ORDER_CONFIRMATION",
PAYMENT_CONFIRMATION = "PAYMENT_CONFIRMATION", PAYMENT_CONFIRMATION = "PAYMENT_CONFIRMATION",
SHIPPING_CONFIRMATION = "SHIPPING_CONFIRMATION", SHIPPING_CONFIRMATION = "SHIPPING_CONFIRMATION",
TRACKING_UPDATED = "TRACKING_UPDATED", TRACKING_UPDATED = "TRACKING_UPDATED"
} }
export enum OrderEventsEnum { export enum OrderEventsEnum {
@ -400,7 +402,7 @@ export enum OrderEventsEnum {
PLACED = "PLACED", PLACED = "PLACED",
PLACED_FROM_DRAFT = "PLACED_FROM_DRAFT", PLACED_FROM_DRAFT = "PLACED_FROM_DRAFT",
TRACKING_UPDATED = "TRACKING_UPDATED", TRACKING_UPDATED = "TRACKING_UPDATED",
UPDATED_ADDRESS = "UPDATED_ADDRESS", UPDATED_ADDRESS = "UPDATED_ADDRESS"
} }
export enum OrderStatus { export enum OrderStatus {
@ -408,7 +410,7 @@ export enum OrderStatus {
DRAFT = "DRAFT", DRAFT = "DRAFT",
FULFILLED = "FULFILLED", FULFILLED = "FULFILLED",
PARTIALLY_FULFILLED = "PARTIALLY_FULFILLED", PARTIALLY_FULFILLED = "PARTIALLY_FULFILLED",
UNFULFILLED = "UNFULFILLED", UNFULFILLED = "UNFULFILLED"
} }
export enum OrderStatusFilter { export enum OrderStatusFilter {
@ -417,7 +419,7 @@ export enum OrderStatusFilter {
PARTIALLY_FULFILLED = "PARTIALLY_FULFILLED", PARTIALLY_FULFILLED = "PARTIALLY_FULFILLED",
READY_TO_CAPTURE = "READY_TO_CAPTURE", READY_TO_CAPTURE = "READY_TO_CAPTURE",
READY_TO_FULFILL = "READY_TO_FULFILL", READY_TO_FULFILL = "READY_TO_FULFILL",
UNFULFILLED = "UNFULFILLED", UNFULFILLED = "UNFULFILLED"
} }
export enum PaymentChargeStatusEnum { export enum PaymentChargeStatusEnum {
@ -425,7 +427,7 @@ export enum PaymentChargeStatusEnum {
FULLY_REFUNDED = "FULLY_REFUNDED", FULLY_REFUNDED = "FULLY_REFUNDED",
NOT_CHARGED = "NOT_CHARGED", NOT_CHARGED = "NOT_CHARGED",
PARTIALLY_CHARGED = "PARTIALLY_CHARGED", PARTIALLY_CHARGED = "PARTIALLY_CHARGED",
PARTIALLY_REFUNDED = "PARTIALLY_REFUNDED", PARTIALLY_REFUNDED = "PARTIALLY_REFUNDED"
} }
export enum PermissionEnum { export enum PermissionEnum {
@ -443,7 +445,7 @@ export enum PermissionEnum {
MANAGE_STAFF = "MANAGE_STAFF", MANAGE_STAFF = "MANAGE_STAFF",
MANAGE_TRANSLATIONS = "MANAGE_TRANSLATIONS", MANAGE_TRANSLATIONS = "MANAGE_TRANSLATIONS",
MANAGE_USERS = "MANAGE_USERS", MANAGE_USERS = "MANAGE_USERS",
MANAGE_WEBHOOKS = "MANAGE_WEBHOOKS", MANAGE_WEBHOOKS = "MANAGE_WEBHOOKS"
} }
export enum ProductErrorCode { export enum ProductErrorCode {
@ -457,7 +459,7 @@ export enum ProductErrorCode {
NOT_PRODUCTS_IMAGE = "NOT_PRODUCTS_IMAGE", NOT_PRODUCTS_IMAGE = "NOT_PRODUCTS_IMAGE",
REQUIRED = "REQUIRED", REQUIRED = "REQUIRED",
UNIQUE = "UNIQUE", UNIQUE = "UNIQUE",
VARIANT_NO_DIGITAL_CONTENT = "VARIANT_NO_DIGITAL_CONTENT", VARIANT_NO_DIGITAL_CONTENT = "VARIANT_NO_DIGITAL_CONTENT"
} }
export enum ProductOrderField { export enum ProductOrderField {
@ -466,37 +468,37 @@ export enum ProductOrderField {
NAME = "NAME", NAME = "NAME",
PRICE = "PRICE", PRICE = "PRICE",
PUBLISHED = "PUBLISHED", PUBLISHED = "PUBLISHED",
TYPE = "TYPE", TYPE = "TYPE"
} }
export enum ProductTypeConfigurable { export enum ProductTypeConfigurable {
CONFIGURABLE = "CONFIGURABLE", CONFIGURABLE = "CONFIGURABLE",
SIMPLE = "SIMPLE", SIMPLE = "SIMPLE"
} }
export enum ProductTypeEnum { export enum ProductTypeEnum {
DIGITAL = "DIGITAL", DIGITAL = "DIGITAL",
SHIPPABLE = "SHIPPABLE", SHIPPABLE = "SHIPPABLE"
} }
export enum SaleType { export enum SaleType {
FIXED = "FIXED", FIXED = "FIXED",
PERCENTAGE = "PERCENTAGE", PERCENTAGE = "PERCENTAGE"
} }
export enum ShippingMethodTypeEnum { export enum ShippingMethodTypeEnum {
PRICE = "PRICE", PRICE = "PRICE",
WEIGHT = "WEIGHT", WEIGHT = "WEIGHT"
} }
export enum StaffMemberStatus { export enum StaffMemberStatus {
ACTIVE = "ACTIVE", ACTIVE = "ACTIVE",
DEACTIVATED = "DEACTIVATED", DEACTIVATED = "DEACTIVATED"
} }
export enum StockAvailability { export enum StockAvailability {
IN_STOCK = "IN_STOCK", IN_STOCK = "IN_STOCK",
OUT_OF_STOCK = "OUT_OF_STOCK", OUT_OF_STOCK = "OUT_OF_STOCK"
} }
export enum TaxRateType { export enum TaxRateType {
@ -524,19 +526,19 @@ export enum TaxRateType {
SOCIAL_HOUSING = "SOCIAL_HOUSING", SOCIAL_HOUSING = "SOCIAL_HOUSING",
STANDARD = "STANDARD", STANDARD = "STANDARD",
WATER = "WATER", WATER = "WATER",
WINE = "WINE", WINE = "WINE"
} }
export enum VoucherDiscountType { export enum VoucherDiscountType {
FIXED = "FIXED", FIXED = "FIXED",
PERCENTAGE = "PERCENTAGE", PERCENTAGE = "PERCENTAGE",
SHIPPING = "SHIPPING", SHIPPING = "SHIPPING"
} }
export enum VoucherTypeEnum { export enum VoucherTypeEnum {
ENTIRE_ORDER = "ENTIRE_ORDER", ENTIRE_ORDER = "ENTIRE_ORDER",
SHIPPING = "SHIPPING", SHIPPING = "SHIPPING",
SPECIFIC_PRODUCT = "SPECIFIC_PRODUCT", SPECIFIC_PRODUCT = "SPECIFIC_PRODUCT"
} }
export enum WebhookErrorCode { export enum WebhookErrorCode {
@ -544,7 +546,7 @@ export enum WebhookErrorCode {
INVALID = "INVALID", INVALID = "INVALID",
NOT_FOUND = "NOT_FOUND", NOT_FOUND = "NOT_FOUND",
REQUIRED = "REQUIRED", REQUIRED = "REQUIRED",
UNIQUE = "UNIQUE", UNIQUE = "UNIQUE"
} }
export enum WebhookEventTypeEnum { export enum WebhookEventTypeEnum {
@ -555,14 +557,14 @@ export enum WebhookEventTypeEnum {
ORDER_FULFILLED = "ORDER_FULFILLED", ORDER_FULFILLED = "ORDER_FULFILLED",
ORDER_FULLY_PAID = "ORDER_FULLY_PAID", ORDER_FULLY_PAID = "ORDER_FULLY_PAID",
ORDER_UPDATED = "ORDER_UPDATED", ORDER_UPDATED = "ORDER_UPDATED",
PRODUCT_CREATED = "PRODUCT_CREATED", PRODUCT_CREATED = "PRODUCT_CREATED"
} }
export enum WeightUnitsEnum { export enum WeightUnitsEnum {
G = "G", G = "G",
KG = "KG", KG = "KG",
LB = "LB", LB = "LB",
OZ = "OZ", OZ = "OZ"
} }
export interface AddressInput { export interface AddressInput {