Inform about app replacements of plugins in plugins page (#4047)
* Inform about app replacements of plugins in plugins page * Change Alert implementation to macaw Box
This commit is contained in:
parent
677f77771a
commit
a25a8db3d0
8 changed files with 132 additions and 7 deletions
5
.changeset/eight-wombats-do.md
Normal file
5
.changeset/eight-wombats-do.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"saleor-dashboard": minor
|
||||
---
|
||||
|
||||
Added information in Plugins Page about the App Store. Now plugins page informs that Apps will replace plugins in the future. Also every plugin that is "active" will display an inline message to visit the App Store for the app replacement
|
|
@ -3511,6 +3511,9 @@
|
|||
"context": "dialog header",
|
||||
"string": "Cancel Orders"
|
||||
},
|
||||
"NL6mvR": {
|
||||
"string": "Visit App Store to replace with the App"
|
||||
},
|
||||
"NLNonj": {
|
||||
"context": "send to channel select label",
|
||||
"string": "Send to channel"
|
||||
|
@ -8667,6 +8670,9 @@
|
|||
"context": "table header channel col label",
|
||||
"string": "Channel"
|
||||
},
|
||||
"yfhLcv": {
|
||||
"string": "We are working on replacing plugins with apps. Read more about"
|
||||
},
|
||||
"yhv3HX": {
|
||||
"context": "voucher requirements, header",
|
||||
"string": "Minimum Requirements"
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { Typography } from "@material-ui/core";
|
||||
import { TypographyProps } from "@material-ui/core/Typography";
|
||||
import { makeStyles } from "@saleor/macaw-ui";
|
||||
import React from "react";
|
||||
import { Text, TextProps } from "@saleor/macaw-ui/next";
|
||||
import React, { HTMLAttributes } from "react";
|
||||
|
||||
const useStyles = makeStyles(
|
||||
{
|
||||
|
@ -18,6 +19,9 @@ interface ExternalLinkProps extends React.HTMLProps<HTMLAnchorElement> {
|
|||
typographyProps?: TypographyProps;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use ExternalLinkNext
|
||||
*/
|
||||
const ExternalLink: React.FC<ExternalLinkProps> = props => {
|
||||
const { className, children, href, typographyProps, target, rel, ...rest } =
|
||||
props;
|
||||
|
@ -42,3 +46,18 @@ const ExternalLink: React.FC<ExternalLinkProps> = props => {
|
|||
};
|
||||
ExternalLink.displayName = "ExternalLink";
|
||||
export default ExternalLink;
|
||||
|
||||
export const ExternalLinkNext = (
|
||||
props: TextProps & Omit<HTMLAttributes<HTMLAnchorElement>, "children">,
|
||||
) => {
|
||||
const opensNewTab = props.target === "_blank";
|
||||
|
||||
return (
|
||||
<Text
|
||||
{...props}
|
||||
as="a"
|
||||
rel={props.rel ?? opensNewTab ? "noopener noreferer" : ""}
|
||||
textDecoration="none"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -5,13 +5,20 @@ import TableRowLink from "@dashboard/components/TableRowLink";
|
|||
import { PluginBaseFragment } from "@dashboard/graphql";
|
||||
import useNavigator from "@dashboard/hooks/useNavigator";
|
||||
import { renderCollection } from "@dashboard/misc";
|
||||
import { getPluginsWithAppReplacementsIds } from "@dashboard/plugins/plugins-with-app-replacements";
|
||||
import { PluginListUrlSortField, pluginUrl } from "@dashboard/plugins/urls";
|
||||
import { ListProps, SortPage } from "@dashboard/types";
|
||||
import { TableBody, TableCell, TableFooter } from "@material-ui/core";
|
||||
import {
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableFooter,
|
||||
Typography,
|
||||
} from "@material-ui/core";
|
||||
import { EditIcon, makeStyles } from "@saleor/macaw-ui";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import { pluginsMiscMessages } from "./messages";
|
||||
import PluginChannelAvailabilityCell from "./PluginChannelAvailabilityCell";
|
||||
import PluginChannelConfigurationCell from "./PluginChannelConfigurationCell";
|
||||
import PluginListTableHead from "./PluginListTableHead";
|
||||
|
@ -25,6 +32,10 @@ export const useStyles = makeStyles(
|
|||
{ name: "PluginsList" },
|
||||
);
|
||||
|
||||
const pluginsWithAppReplacements = getPluginsWithAppReplacementsIds();
|
||||
const hasAppReplacement = (pluginId: string) =>
|
||||
pluginsWithAppReplacements.includes(pluginId);
|
||||
|
||||
export interface PluginListProps
|
||||
extends ListProps,
|
||||
SortPage<PluginListUrlSortField> {
|
||||
|
@ -56,8 +67,16 @@ const PluginList: React.FC<PluginListProps> = props => {
|
|||
<TableBody>
|
||||
{renderCollection(
|
||||
plugins,
|
||||
plugin =>
|
||||
plugin ? (
|
||||
plugin => {
|
||||
const hasReplacement = plugin && hasAppReplacement(plugin.id);
|
||||
const activeChannelConfigurations =
|
||||
plugin?.channelConfigurations?.filter(c => c.active);
|
||||
const isActive =
|
||||
plugin?.globalConfiguration?.active ||
|
||||
(activeChannelConfigurations &&
|
||||
activeChannelConfigurations.length > 0);
|
||||
|
||||
return plugin ? (
|
||||
<TableRowLink
|
||||
data-test-id="plugin"
|
||||
hover={!!plugin}
|
||||
|
@ -67,7 +86,16 @@ const PluginList: React.FC<PluginListProps> = props => {
|
|||
onClick={() => plugin && navigate(pluginUrl(plugin.id))}
|
||||
key={plugin ? plugin.id : "skeleton"}
|
||||
>
|
||||
<TableCell colSpan={5}>{plugin.name}</TableCell>
|
||||
<TableCell colSpan={5}>
|
||||
<Typography>{plugin.name}</Typography>
|
||||
{hasReplacement && isActive && (
|
||||
<Typography variant="caption" color="error">
|
||||
{intl.formatMessage(
|
||||
pluginsMiscMessages.appReplacementMessage,
|
||||
)}
|
||||
</Typography>
|
||||
)}
|
||||
</TableCell>
|
||||
<PluginChannelConfigurationCell plugin={plugin} />
|
||||
<PluginChannelAvailabilityCell plugin={plugin} />
|
||||
<TableCell align="right">
|
||||
|
@ -80,7 +108,8 @@ const PluginList: React.FC<PluginListProps> = props => {
|
|||
<Skeleton />
|
||||
</TableCell>
|
||||
</TableRowLink>
|
||||
),
|
||||
);
|
||||
},
|
||||
() => (
|
||||
<TableRowLink>
|
||||
<TableCell colSpan={totalColSpan}>
|
||||
|
|
|
@ -75,3 +75,10 @@ export const pluginStatusMessages = defineMessages({
|
|||
description: "status label deactivated",
|
||||
},
|
||||
});
|
||||
|
||||
export const pluginsMiscMessages = defineMessages({
|
||||
appReplacementMessage: {
|
||||
defaultMessage: "Visit App Store to replace with the App",
|
||||
id: 'NL6mvR',
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
// @ts-strict-ignore
|
||||
import { TopNav } from "@dashboard/components/AppLayout/TopNav";
|
||||
import { ExternalLinkNext } from "@dashboard/components/ExternalLink";
|
||||
import FilterBar from "@dashboard/components/FilterBar";
|
||||
import { ListPageLayout } from "@dashboard/components/Layouts";
|
||||
import { configurationMenuUrl } from "@dashboard/configuration";
|
||||
import { PluginBaseFragment } from "@dashboard/graphql";
|
||||
import { sectionNames } from "@dashboard/intl";
|
||||
import { getStatusColor } from "@dashboard/misc";
|
||||
import { PluginListUrlSortField } from "@dashboard/plugins/urls";
|
||||
import {
|
||||
FilterPageProps,
|
||||
|
@ -13,6 +15,7 @@ import {
|
|||
TabPageProps,
|
||||
} from "@dashboard/types";
|
||||
import { Card } from "@material-ui/core";
|
||||
import { Box, Text } from "@saleor/macaw-ui/next";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
|
@ -22,7 +25,10 @@ import {
|
|||
PluginFilterKeys,
|
||||
PluginListFilterOpts,
|
||||
} from "./filters";
|
||||
import { pluginsFilterErrorMessages } from "./messages";
|
||||
import {
|
||||
pluginsFilterErrorMessages,
|
||||
pluginsListPageMessages,
|
||||
} from "./messages";
|
||||
|
||||
export interface PluginsListPageProps
|
||||
extends PageListProps,
|
||||
|
@ -56,6 +62,27 @@ const PluginsListPage: React.FC<PluginsListPageProps> = ({
|
|||
title={intl.formatMessage(sectionNames.plugins)}
|
||||
/>
|
||||
<Card>
|
||||
<div>
|
||||
<Box
|
||||
paddingX={7}
|
||||
paddingY={5}
|
||||
marginBottom={5}
|
||||
__backgroundColor={getStatusColor("warning")}
|
||||
>
|
||||
<Text variant="heading" as="h2">
|
||||
{intl.formatMessage(pluginsListPageMessages.warningHeadline)}
|
||||
</Text>
|
||||
<Text variant="body">
|
||||
{intl.formatMessage(pluginsListPageMessages.appStoreWarning)}{" "}
|
||||
<ExternalLinkNext
|
||||
target="_blank"
|
||||
href="https://docs.saleor.io/docs/3.x/developer/app-store/overview"
|
||||
>
|
||||
Saleor App Store.
|
||||
</ExternalLinkNext>
|
||||
</Text>
|
||||
</Box>
|
||||
</div>
|
||||
<FilterBar
|
||||
errorMessages={pluginsFilterErrorMessages}
|
||||
currentTab={currentTab}
|
||||
|
|
|
@ -12,3 +12,15 @@ export const pluginsFilterErrorMessages = defineMessages({
|
|||
description: "plugin filters error messages channels",
|
||||
},
|
||||
});
|
||||
|
||||
export const pluginsListPageMessages = defineMessages({
|
||||
appStoreWarning: {
|
||||
defaultMessage:
|
||||
"We are working on replacing plugins with apps. Read more about",
|
||||
id: "yfhLcv",
|
||||
},
|
||||
warningHeadline: {
|
||||
defaultMessage: "Warning",
|
||||
id: "3SVI5p",
|
||||
},
|
||||
});
|
||||
|
|
20
src/plugins/plugins-with-app-replacements.ts
Normal file
20
src/plugins/plugins-with-app-replacements.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* Provides a static list of plugins IDs that are already re-implemented
|
||||
* as apps and available in the App Store.
|
||||
*
|
||||
* In the future they will be officially deprecated, but now called "with app replacements"
|
||||
*
|
||||
* Ids are part of plugins query
|
||||
* https://docs.saleor.io/docs/3.x/api-reference/miscellaneous/queries/plugins
|
||||
*/
|
||||
export const getPluginsWithAppReplacementsIds = () => {
|
||||
return [
|
||||
"mirumee.payments.adyen",
|
||||
"mirumee.taxes.avalara",
|
||||
"mirumee.invoicing",
|
||||
"mirumee.notifications.sendgrid_email",
|
||||
"saleor.payments.stripe",
|
||||
"mirumee.payments.stripe",
|
||||
"mirumee.notifications.user_email",
|
||||
];
|
||||
};
|
Loading…
Reference in a new issue