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:
Lukasz Ostrowski 2022-10-13 17:13:08 +02:00 committed by GitHub
parent be76836e12
commit 1fb4479058
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 178 additions and 3 deletions

View file

@ -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"

View file

@ -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>
);
}
}
};

View file

@ -0,0 +1 @@
export * from "./InstallWithManifestFormButton";

View file

@ -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>

View file

@ -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);

View file

@ -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"