Add quick app install from manifest (#2378)
* Create a button that navigates to app install page * Add translations keys * Extract messages * Change type literal to enum * Update snapshots
This commit is contained in:
parent
be76836e12
commit
1fb4479058
6 changed files with 178 additions and 3 deletions
|
@ -3627,6 +3627,9 @@
|
|||
"context": "product field",
|
||||
"string": "Charge Taxes"
|
||||
},
|
||||
"QVraQY": {
|
||||
"string": "App manifest URL"
|
||||
},
|
||||
"QY7FSs": {
|
||||
"context": "button",
|
||||
"string": "create product type"
|
||||
|
@ -6007,6 +6010,10 @@
|
|||
"context": "set balance dialog subtitle",
|
||||
"string": "What would you like to set cards balance to. When you change the balance both values will be changed"
|
||||
},
|
||||
"kIXV5V": {
|
||||
"context": "install with app manifest button",
|
||||
"string": "Install with App Manifest"
|
||||
},
|
||||
"kIvvax": {
|
||||
"string": "Search Products..."
|
||||
},
|
||||
|
@ -6461,6 +6468,9 @@
|
|||
"context": "dialog title",
|
||||
"string": "Delete Warehouse"
|
||||
},
|
||||
"o/q4fc": {
|
||||
"string": "Usually ends with /api/manifest"
|
||||
},
|
||||
"o5KXAN": {
|
||||
"context": "delete webhook",
|
||||
"string": "Are you sure you want to delete {name}?"
|
||||
|
@ -7247,6 +7257,9 @@
|
|||
"context": "order history message",
|
||||
"string": "Order was confirmed"
|
||||
},
|
||||
"ubmFc8": {
|
||||
"string": "Install"
|
||||
},
|
||||
"ud0w8h": {
|
||||
"context": "number of postal code ranges",
|
||||
"string": "{number} postal code ranges"
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
import { TextField } from "@material-ui/core";
|
||||
import { Button } from "@saleor/components/Button";
|
||||
import { makeStyles } from "@saleor/macaw-ui";
|
||||
import React, { useState } from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
enum AvailableStates {
|
||||
Initial,
|
||||
InputOpen,
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
installButton: {
|
||||
marginLeft: theme.spacing(2),
|
||||
height: 52,
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: "InstallWithManifestFormButton",
|
||||
},
|
||||
);
|
||||
|
||||
interface Props {
|
||||
onSubmitted(manifestUrl: string): void;
|
||||
}
|
||||
|
||||
export const InstallWithManifestFormButton = ({ onSubmitted }: Props) => {
|
||||
const styles = useStyles();
|
||||
const intl = useIntl();
|
||||
|
||||
const [state, setState] = useState<AvailableStates>(AvailableStates.Initial);
|
||||
|
||||
const handleFormSubmit: React.FormEventHandler<HTMLFormElement> = e => {
|
||||
e.preventDefault();
|
||||
|
||||
const form = new FormData(e.currentTarget);
|
||||
const inputValue = form.get("manifest-url") as string;
|
||||
|
||||
try {
|
||||
new URL(inputValue);
|
||||
|
||||
onSubmitted(inputValue);
|
||||
} catch (e) {
|
||||
console.error("Invalid URL from input. Should be validated by browser");
|
||||
}
|
||||
};
|
||||
|
||||
switch (state) {
|
||||
case AvailableStates.Initial: {
|
||||
return (
|
||||
<Button
|
||||
variant="secondary"
|
||||
data-test-id="add-app-from-manifest"
|
||||
onClick={() => setState(AvailableStates.InputOpen)}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="kIXV5V"
|
||||
defaultMessage="Install with App Manifest"
|
||||
description="install with app manifest button"
|
||||
/>
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
case AvailableStates.InputOpen: {
|
||||
return (
|
||||
<form onSubmit={handleFormSubmit}>
|
||||
<TextField
|
||||
required
|
||||
type="url"
|
||||
name="manifest-url"
|
||||
label={intl.formatMessage({
|
||||
id: "QVraQY",
|
||||
defaultMessage: "App manifest URL",
|
||||
})}
|
||||
defaultValue=""
|
||||
helperText={intl.formatMessage({
|
||||
id: "o/q4fc",
|
||||
defaultMessage: "Usually ends with /api/manifest",
|
||||
})}
|
||||
/>
|
||||
<Button
|
||||
size="medium"
|
||||
type="submit"
|
||||
className={styles.installButton}
|
||||
variant="primary"
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "ubmFc8",
|
||||
defaultMessage: "Install",
|
||||
})}
|
||||
</Button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
export * from "./InstallWithManifestFormButton";
|
|
@ -6,18 +6,20 @@ import {
|
|||
TableRow,
|
||||
Typography,
|
||||
} from "@material-ui/core";
|
||||
import { InstallWithManifestFormButton } from "@saleor/apps/components/InstallWithManifestFormButton";
|
||||
import { useAppListContext } from "@saleor/apps/context";
|
||||
import { appUrl } from "@saleor/apps/urls";
|
||||
import { appUrl, createAppInstallUrl } from "@saleor/apps/urls";
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import { IconButton } from "@saleor/components/IconButton";
|
||||
import { TableButtonWrapper } from "@saleor/components/TableButtonWrapper/TableButtonWrapper";
|
||||
import TableRowLink from "@saleor/components/TableRowLink";
|
||||
import { AppListItemFragment, AppsListQuery } from "@saleor/graphql";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import { DeleteIcon, ResponsiveTable } from "@saleor/macaw-ui";
|
||||
import { renderCollection } from "@saleor/misc";
|
||||
import { ListProps } from "@saleor/types";
|
||||
import clsx from "clsx";
|
||||
import React from "react";
|
||||
import React, { useCallback } from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
import { useStyles } from "../../styles";
|
||||
|
@ -37,6 +39,14 @@ const InstalledApps: React.FC<InstalledAppsProps> = ({
|
|||
const intl = useIntl();
|
||||
const classes = useStyles(props);
|
||||
const { activateApp, deactivateApp } = useAppListContext();
|
||||
const navigate = useNavigator();
|
||||
|
||||
const navigateToAppInstallPage = useCallback(
|
||||
(url: string) => {
|
||||
navigate(createAppInstallUrl(url));
|
||||
},
|
||||
[navigate],
|
||||
);
|
||||
|
||||
const getHandleToggle = (app: AppListItemFragment) => () => {
|
||||
if (app.isActive) {
|
||||
|
@ -54,6 +64,11 @@ const InstalledApps: React.FC<InstalledAppsProps> = ({
|
|||
defaultMessage: "Third Party Apps",
|
||||
description: "section header",
|
||||
})}
|
||||
toolbar={
|
||||
<InstallWithManifestFormButton
|
||||
onSubmitted={navigateToAppInstallPage}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<ResponsiveTable>
|
||||
<TableBody>
|
||||
|
|
|
@ -54,7 +54,8 @@ export const appDeepPath = (id: string, subPath: string) =>
|
|||
urlJoin(appPath(id), subPath);
|
||||
export const customAppPath = (id: string) => urlJoin(customAppListPath, id);
|
||||
export const appInstallPath = urlJoin(appsSection, "install");
|
||||
export const appInstallUrl = appInstallPath;
|
||||
export const createAppInstallUrl = (manifestUrl: string) =>
|
||||
`${appInstallPath}?manifestUrl=${manifestUrl}`;
|
||||
|
||||
export const appDetailsUrl = (id: string, params?: AppDetailsUrlQueryParams) =>
|
||||
appDetailsPath(encodeURIComponent(id)) + "?" + stringifyQs(params);
|
||||
|
|
|
@ -25459,6 +25459,22 @@ exports[`Storyshots Views / Apps / Apps list default 1`] = `
|
|||
Third Party Apps
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="MuiCardHeader-action-id"
|
||||
>
|
||||
<button
|
||||
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-outlined-id MuiButton-outlinedPrimary-id"
|
||||
data-test-id="add-app-from-manifest"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="MuiButton-label-id"
|
||||
>
|
||||
Install with App Manifest
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ResponsiveTable-root-id"
|
||||
|
@ -25997,6 +26013,22 @@ exports[`Storyshots Views / Apps / Apps list loading 1`] = `
|
|||
Third Party Apps
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="MuiCardHeader-action-id"
|
||||
>
|
||||
<button
|
||||
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-outlined-id MuiButton-outlinedPrimary-id"
|
||||
data-test-id="add-app-from-manifest"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="MuiButton-label-id"
|
||||
>
|
||||
Install with App Manifest
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ResponsiveTable-root-id"
|
||||
|
@ -26138,6 +26170,22 @@ exports[`Storyshots Views / Apps / Apps list no data 1`] = `
|
|||
Third Party Apps
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="MuiCardHeader-action-id"
|
||||
>
|
||||
<button
|
||||
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-outlined-id MuiButton-outlinedPrimary-id"
|
||||
data-test-id="add-app-from-manifest"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="MuiButton-label-id"
|
||||
>
|
||||
Install with App Manifest
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ResponsiveTable-root-id"
|
||||
|
|
Loading…
Reference in a new issue