Apps list page enchancements (#2035)
* Remove marketplace from Apps list * Move apps in progress to bottom * Remove pagination from InstalledApps * Add apps permissions tooltip * Activate/deactivate InstalledApps from list * Add changes description to CHANGELOG * Update package.json to include macaw required changes * Upadte fixtures * Rename Local Apps -> Third Party Apps * Update macaw, fix TS errors * Refactor AppPermission component to use permission fragment * Add fragment for app list query, refactor InstalledApps props type * Fix check for usage within context inside useAppListContext * Remove redundant errors check in mutation hooks inside AppsList * Update extracted messages * Fix AppListPage stories failing * Fix Tooltip not working in failed installed apps * Update messages
This commit is contained in:
parent
1a19289e43
commit
5138608f86
21 changed files with 726 additions and 778 deletions
|
@ -6,6 +6,7 @@ All notable, unreleased changes to this project will be documented in this file.
|
||||||
- Added links instead of imperative navigation with onClick - #1969 by @taniotanio7
|
- Added links instead of imperative navigation with onClick - #1969 by @taniotanio7
|
||||||
- Fixed clearing attribute values - #2047 by @witoszekdev
|
- Fixed clearing attribute values - #2047 by @witoszekdev
|
||||||
- Fixed EditorJS integration in RichTextEditor input - #2052 by @witoszekdev
|
- Fixed EditorJS integration in RichTextEditor input - #2052 by @witoszekdev
|
||||||
|
- Improvements to the app list page: added toggle and permision preview - #2035 by @witoszekdev
|
||||||
- Added links to table pagination buttons - #2063 by @witoszekdev
|
- Added links to table pagination buttons - #2063 by @witoszekdev
|
||||||
- Using push instead of replace to history stack for pagination navigation - #2063 by @witoszekdev
|
- Using push instead of replace to history stack for pagination navigation - #2063 by @witoszekdev
|
||||||
|
|
||||||
|
|
|
@ -86,6 +86,9 @@
|
||||||
"context": "error message",
|
"context": "error message",
|
||||||
"string": "This attribute is already assigned."
|
"string": "This attribute is already assigned."
|
||||||
},
|
},
|
||||||
|
"+iV0gu": {
|
||||||
|
"string": "Internal Apps"
|
||||||
|
},
|
||||||
"+iVKR1": {
|
"+iVKR1": {
|
||||||
"context": "assign attribute value button",
|
"context": "assign attribute value button",
|
||||||
"string": "Assign value"
|
"string": "Assign value"
|
||||||
|
@ -1658,6 +1661,10 @@
|
||||||
"BtErCZ": {
|
"BtErCZ": {
|
||||||
"string": "Search Plugins..."
|
"string": "Search Plugins..."
|
||||||
},
|
},
|
||||||
|
"BvmnJq": {
|
||||||
|
"context": "section header",
|
||||||
|
"string": "Third Party Apps"
|
||||||
|
},
|
||||||
"Bx367s": {
|
"Bx367s": {
|
||||||
"context": "product is hidden",
|
"context": "product is hidden",
|
||||||
"string": "Hidden"
|
"string": "Hidden"
|
||||||
|
@ -2760,10 +2767,6 @@
|
||||||
"context": "filtering option",
|
"context": "filtering option",
|
||||||
"string": "All Warehouses"
|
"string": "All Warehouses"
|
||||||
},
|
},
|
||||||
"JufWFT": {
|
|
||||||
"context": "app installation error",
|
|
||||||
"string": "There was a problem during installation"
|
|
||||||
},
|
|
||||||
"Jwuu4X": {
|
"Jwuu4X": {
|
||||||
"context": "select product informations to be exported",
|
"context": "select product informations to be exported",
|
||||||
"string": "Information exported:"
|
"string": "Information exported:"
|
||||||
|
@ -3930,10 +3933,6 @@
|
||||||
"context": "order subtotal price",
|
"context": "order subtotal price",
|
||||||
"string": "Subtotal"
|
"string": "Subtotal"
|
||||||
},
|
},
|
||||||
"TBaMo2": {
|
|
||||||
"context": "about app",
|
|
||||||
"string": "About"
|
|
||||||
},
|
|
||||||
"TC/EOG": {
|
"TC/EOG": {
|
||||||
"context": "status section title",
|
"context": "status section title",
|
||||||
"string": "Status in channel"
|
"string": "Status in channel"
|
||||||
|
@ -4596,6 +4595,10 @@
|
||||||
"context": "filters error messages value required",
|
"context": "filters error messages value required",
|
||||||
"string": "Choose a value"
|
"string": "Choose a value"
|
||||||
},
|
},
|
||||||
|
"Xl0o2y": {
|
||||||
|
"context": "app installation error",
|
||||||
|
"string": "Problem occured during installation"
|
||||||
|
},
|
||||||
"XlPKAR": {
|
"XlPKAR": {
|
||||||
"context": "WarehouseSettings private stock description",
|
"context": "WarehouseSettings private stock description",
|
||||||
"string": "If enabled stock in this warehouse won't be shown"
|
"string": "If enabled stock in this warehouse won't be shown"
|
||||||
|
@ -4809,10 +4812,6 @@
|
||||||
"context": "subsection header",
|
"context": "subsection header",
|
||||||
"string": "Shipping Address"
|
"string": "Shipping Address"
|
||||||
},
|
},
|
||||||
"ZeD2TK": {
|
|
||||||
"context": "section header",
|
|
||||||
"string": "Third-party Apps"
|
|
||||||
},
|
|
||||||
"Zg0dRo": {
|
"Zg0dRo": {
|
||||||
"context": "dialog description",
|
"context": "dialog description",
|
||||||
"string": "You have changed customer assigned to this order. What would you like to do with the shipping address?"
|
"string": "You have changed customer assigned to this order. What would you like to do with the shipping address?"
|
||||||
|
@ -7505,9 +7504,6 @@
|
||||||
"context": "section header",
|
"context": "section header",
|
||||||
"string": "Plugin Information and Status"
|
"string": "Plugin Information and Status"
|
||||||
},
|
},
|
||||||
"w4R/SO": {
|
|
||||||
"string": "Local Apps"
|
|
||||||
},
|
|
||||||
"w6Gau0": {
|
"w6Gau0": {
|
||||||
"context": "deactivate named app",
|
"context": "deactivate named app",
|
||||||
"string": "Are you sure you want to disable {name}? Your data will be kept until you reactivate the app. You will be still billed for the app."
|
"string": "Are you sure you want to disable {name}? Your data will be kept until you reactivate the app. You will be still billed for the app."
|
||||||
|
@ -7630,6 +7626,10 @@
|
||||||
"xJQX5t": {
|
"xJQX5t": {
|
||||||
"string": "No staff members found"
|
"string": "No staff members found"
|
||||||
},
|
},
|
||||||
|
"xNfh4L": {
|
||||||
|
"context": "app permissions tooltip header",
|
||||||
|
"string": "App permissions"
|
||||||
|
},
|
||||||
"xOEZjV": {
|
"xOEZjV": {
|
||||||
"context": "attribute's label",
|
"context": "attribute's label",
|
||||||
"string": "Default Label"
|
"string": "Default Label"
|
||||||
|
|
49
src/apps/components/AppPermissions/AppPermissions.tsx
Normal file
49
src/apps/components/AppPermissions/AppPermissions.tsx
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
import { AppPermissionFragment } from "@saleor/graphql";
|
||||||
|
import {
|
||||||
|
IconButton,
|
||||||
|
makeStyles,
|
||||||
|
PermissionsIcon,
|
||||||
|
Tooltip
|
||||||
|
} from "@saleor/macaw-ui";
|
||||||
|
import React from "react";
|
||||||
|
import { FormattedMessage } from "react-intl";
|
||||||
|
|
||||||
|
const useStyles = makeStyles(
|
||||||
|
() => ({
|
||||||
|
list: {
|
||||||
|
margin: 0,
|
||||||
|
paddingLeft: "16px"
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
{ name: "AppPermissions" }
|
||||||
|
);
|
||||||
|
|
||||||
|
interface AppPermissionsProps {
|
||||||
|
permissions: AppPermissionFragment[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AppPermissions = ({ permissions }: AppPermissionsProps) => {
|
||||||
|
const classes = useStyles();
|
||||||
|
return (
|
||||||
|
<Tooltip
|
||||||
|
header={
|
||||||
|
<FormattedMessage
|
||||||
|
defaultMessage="App permissions"
|
||||||
|
id="xNfh4L"
|
||||||
|
description="app permissions tooltip header"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
title={
|
||||||
|
<ul className={classes.list}>
|
||||||
|
{permissions.map(permission => (
|
||||||
|
<li key={permission.code}>{permission.name}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<IconButton variant="secondary" color="primary">
|
||||||
|
<PermissionsIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
};
|
|
@ -4,16 +4,20 @@ import {
|
||||||
TableBody,
|
TableBody,
|
||||||
TableCell,
|
TableCell,
|
||||||
TableRow,
|
TableRow,
|
||||||
Tooltip,
|
|
||||||
Typography
|
Typography
|
||||||
} from "@material-ui/core";
|
} from "@material-ui/core";
|
||||||
import ErrorIcon from "@material-ui/icons/Error";
|
|
||||||
import { Button } from "@saleor/components/Button";
|
import { Button } from "@saleor/components/Button";
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
import { IconButton } from "@saleor/components/IconButton";
|
import { IconButton } from "@saleor/components/IconButton";
|
||||||
import { TableButtonWrapper } from "@saleor/components/TableButtonWrapper/TableButtonWrapper";
|
import { TableButtonWrapper } from "@saleor/components/TableButtonWrapper/TableButtonWrapper";
|
||||||
import { AppsInstallationsQuery, JobStatusEnum } from "@saleor/graphql";
|
import { AppsInstallationsQuery, JobStatusEnum } from "@saleor/graphql";
|
||||||
import { DeleteIcon, ResponsiveTable } from "@saleor/macaw-ui";
|
import {
|
||||||
|
DeleteIcon,
|
||||||
|
Indicator,
|
||||||
|
ResponsiveTable,
|
||||||
|
Tooltip,
|
||||||
|
TooltipMountWrapper
|
||||||
|
} from "@saleor/macaw-ui";
|
||||||
import { renderCollection } from "@saleor/misc";
|
import { renderCollection } from "@saleor/misc";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
@ -82,17 +86,14 @@ const AppsInProgress: React.FC<AppsInProgressProps> = ({
|
||||||
>
|
>
|
||||||
<Typography variant="body2" className={classes.error}>
|
<Typography variant="body2" className={classes.error}>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id="JufWFT"
|
id="Xl0o2y"
|
||||||
defaultMessage="There was a problem during installation"
|
defaultMessage="Problem occured during installation"
|
||||||
description="app installation error"
|
description="app installation error"
|
||||||
/>
|
/>
|
||||||
<Tooltip
|
<Tooltip title={message} variant="error">
|
||||||
title={<Typography variant="body2">{message}</Typography>}
|
<TooltipMountWrapper>
|
||||||
classes={{
|
<Indicator icon="error" />
|
||||||
tooltip: classes.customTooltip
|
</TooltipMountWrapper>
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ErrorIcon />
|
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Typography>
|
</Typography>
|
||||||
<TableButtonWrapper>
|
<TableButtonWrapper>
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { AppListContext } from "@saleor/apps/context";
|
||||||
import {
|
import {
|
||||||
listActionsProps,
|
listActionsProps,
|
||||||
pageListProps,
|
pageListProps,
|
||||||
|
@ -36,6 +37,13 @@ const props: AppsListPageProps = {
|
||||||
|
|
||||||
storiesOf("Views / Apps / Apps list", module)
|
storiesOf("Views / Apps / Apps list", module)
|
||||||
.addDecorator(Decorator)
|
.addDecorator(Decorator)
|
||||||
|
.addDecorator(story => (
|
||||||
|
<AppListContext.Provider
|
||||||
|
value={{ activateApp: () => undefined, deactivateApp: () => undefined }}
|
||||||
|
>
|
||||||
|
{story()}
|
||||||
|
</AppListContext.Provider>
|
||||||
|
))
|
||||||
.addDecorator(PaginatorContextDecorator)
|
.addDecorator(PaginatorContextDecorator)
|
||||||
.add("default", () => <AppsListPage {...props} />)
|
.add("default", () => <AppsListPage {...props} />)
|
||||||
.add("loading", () => (
|
.add("loading", () => (
|
||||||
|
|
|
@ -10,7 +10,6 @@ import { useIntl } from "react-intl";
|
||||||
import AppsInProgress from "../AppsInProgress/AppsInProgress";
|
import AppsInProgress from "../AppsInProgress/AppsInProgress";
|
||||||
import CustomApps from "../CustomApps/CustomApps";
|
import CustomApps from "../CustomApps/CustomApps";
|
||||||
import InstalledApps from "../InstalledApps/InstalledApps";
|
import InstalledApps from "../InstalledApps/InstalledApps";
|
||||||
import Marketplace from "../Marketplace";
|
|
||||||
|
|
||||||
export interface AppsListPageProps extends ListProps {
|
export interface AppsListPageProps extends ListProps {
|
||||||
installedAppsList: AppsListQuery["apps"]["edges"];
|
installedAppsList: AppsListQuery["apps"]["edges"];
|
||||||
|
@ -43,17 +42,6 @@ const AppsListPage: React.FC<AppsListPageProps> = ({
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<PageHeader title={intl.formatMessage(sectionNames.apps)} />
|
<PageHeader title={intl.formatMessage(sectionNames.apps)} />
|
||||||
{!!appsInProgress?.length && (
|
|
||||||
<>
|
|
||||||
<AppsInProgress
|
|
||||||
appsList={appsInProgress}
|
|
||||||
disabled={loadingAppsInProgress}
|
|
||||||
onAppInstallRetry={onAppInstallRetry}
|
|
||||||
onRemove={onAppInProgressRemove}
|
|
||||||
/>
|
|
||||||
<CardSpacer />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
<InstalledApps
|
<InstalledApps
|
||||||
appsList={installedAppsList}
|
appsList={installedAppsList}
|
||||||
onRemove={onInstalledAppRemove}
|
onRemove={onInstalledAppRemove}
|
||||||
|
@ -65,8 +53,17 @@ const AppsListPage: React.FC<AppsListPageProps> = ({
|
||||||
getCustomAppHref={getCustomAppHref}
|
getCustomAppHref={getCustomAppHref}
|
||||||
onRemove={onCustomAppRemove}
|
onRemove={onCustomAppRemove}
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
{!!appsInProgress?.length && (
|
||||||
<Marketplace />
|
<>
|
||||||
|
<CardSpacer />
|
||||||
|
<AppsInProgress
|
||||||
|
appsList={appsInProgress}
|
||||||
|
disabled={loadingAppsInProgress}
|
||||||
|
onAppInstallRetry={onAppInstallRetry}
|
||||||
|
onRemove={onAppInProgressRemove}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,19 +1,18 @@
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
|
Switch,
|
||||||
TableBody,
|
TableBody,
|
||||||
TableCell,
|
TableCell,
|
||||||
TableFooter,
|
|
||||||
TableRow,
|
TableRow,
|
||||||
Typography
|
Typography
|
||||||
} from "@material-ui/core";
|
} from "@material-ui/core";
|
||||||
import { appDetailsUrl, appUrl } from "@saleor/apps/urls";
|
import { useAppListContext } from "@saleor/apps/context";
|
||||||
import { Button } from "@saleor/components/Button";
|
import { appUrl } from "@saleor/apps/urls";
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
import { IconButton } from "@saleor/components/IconButton";
|
import { IconButton } from "@saleor/components/IconButton";
|
||||||
import { TableButtonWrapper } from "@saleor/components/TableButtonWrapper/TableButtonWrapper";
|
import { TableButtonWrapper } from "@saleor/components/TableButtonWrapper/TableButtonWrapper";
|
||||||
import { TablePaginationWithContext } from "@saleor/components/TablePagination";
|
|
||||||
import TableRowLink from "@saleor/components/TableRowLink";
|
import TableRowLink from "@saleor/components/TableRowLink";
|
||||||
import { AppsListQuery } from "@saleor/graphql";
|
import { AppListItemFragment, AppsListQuery } from "@saleor/graphql";
|
||||||
import { DeleteIcon, ResponsiveTable } from "@saleor/macaw-ui";
|
import { DeleteIcon, ResponsiveTable } from "@saleor/macaw-ui";
|
||||||
import { renderCollection } from "@saleor/misc";
|
import { renderCollection } from "@saleor/misc";
|
||||||
import { ListProps } from "@saleor/types";
|
import { ListProps } from "@saleor/types";
|
||||||
|
@ -22,14 +21,13 @@ import React from "react";
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
import { useStyles } from "../../styles";
|
import { useStyles } from "../../styles";
|
||||||
|
import { AppPermissions } from "../AppPermissions/AppPermissions";
|
||||||
import AppsSkeleton from "../AppsSkeleton";
|
import AppsSkeleton from "../AppsSkeleton";
|
||||||
import DeactivatedText from "../DeactivatedText";
|
|
||||||
|
|
||||||
export interface InstalledAppsProps extends ListProps {
|
export interface InstalledAppsProps extends ListProps {
|
||||||
appsList: AppsListQuery["apps"]["edges"];
|
appsList: AppsListQuery["apps"]["edges"];
|
||||||
onRemove: (id: string) => void;
|
onRemove: (id: string) => void;
|
||||||
}
|
}
|
||||||
const numberOfColumns = 2;
|
|
||||||
|
|
||||||
const InstalledApps: React.FC<InstalledAppsProps> = ({
|
const InstalledApps: React.FC<InstalledAppsProps> = ({
|
||||||
appsList,
|
appsList,
|
||||||
|
@ -41,26 +39,26 @@ const InstalledApps: React.FC<InstalledAppsProps> = ({
|
||||||
}) => {
|
}) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const classes = useStyles(props);
|
const classes = useStyles(props);
|
||||||
|
const { activateApp, deactivateApp } = useAppListContext();
|
||||||
|
|
||||||
|
const getHandleToggle = (app: AppListItemFragment) => () => {
|
||||||
|
if (app.isActive) {
|
||||||
|
deactivateApp(app.id);
|
||||||
|
} else {
|
||||||
|
activateApp(app.id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className={classes.apps}>
|
<Card className={classes.apps}>
|
||||||
<CardTitle
|
<CardTitle
|
||||||
title={intl.formatMessage({
|
title={intl.formatMessage({
|
||||||
id: "ZeD2TK",
|
id: "BvmnJq",
|
||||||
defaultMessage: "Third-party Apps",
|
defaultMessage: "Third Party Apps",
|
||||||
description: "section header"
|
description: "section header"
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
<ResponsiveTable>
|
<ResponsiveTable>
|
||||||
<TableFooter>
|
|
||||||
<TableRow>
|
|
||||||
<TablePaginationWithContext
|
|
||||||
colSpan={numberOfColumns}
|
|
||||||
settings={settings}
|
|
||||||
onUpdateListSettings={onUpdateListSettings}
|
|
||||||
/>
|
|
||||||
</TableRow>
|
|
||||||
</TableFooter>
|
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{renderCollection(
|
{renderCollection(
|
||||||
appsList,
|
appsList,
|
||||||
|
@ -75,11 +73,6 @@ const InstalledApps: React.FC<InstalledAppsProps> = ({
|
||||||
<span data-tc="name" className={classes.appName}>
|
<span data-tc="name" className={classes.appName}>
|
||||||
{app.node.name}
|
{app.node.name}
|
||||||
</span>
|
</span>
|
||||||
{!app.node.isActive && (
|
|
||||||
<div className={classes.statusWrapper}>
|
|
||||||
<DeactivatedText />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className={classes.colAction}>
|
<TableCell className={classes.colAction}>
|
||||||
{app.node.appUrl && (
|
{app.node.appUrl && (
|
||||||
|
@ -91,14 +84,12 @@ const InstalledApps: React.FC<InstalledAppsProps> = ({
|
||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
<TableButtonWrapper>
|
<TableButtonWrapper>
|
||||||
<Button href={appDetailsUrl(app.node.id)}>
|
<Switch
|
||||||
<FormattedMessage
|
checked={app.node.isActive}
|
||||||
id="TBaMo2"
|
onChange={getHandleToggle(app.node)}
|
||||||
defaultMessage="About"
|
/>
|
||||||
description="about app"
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
</TableButtonWrapper>
|
</TableButtonWrapper>
|
||||||
|
<AppPermissions permissions={app.node.permissions} />
|
||||||
<TableButtonWrapper>
|
<TableButtonWrapper>
|
||||||
<IconButton
|
<IconButton
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
export * from "./Marketplace";
|
|
||||||
export { default } from "./Marketplace";
|
|
21
src/apps/context.ts
Normal file
21
src/apps/context.ts
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/* eslint-disable @typescript-eslint/no-empty-function */
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export interface AppListContextValues {
|
||||||
|
activateApp: (appId: string) => void;
|
||||||
|
deactivateApp: (appId: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AppListContext = React.createContext<
|
||||||
|
AppListContextValues | undefined
|
||||||
|
>(undefined);
|
||||||
|
|
||||||
|
export const useAppListContext = () => {
|
||||||
|
const context = React.useContext(AppListContext);
|
||||||
|
|
||||||
|
if (!context) {
|
||||||
|
throw new Error("useAppListContext must be used within a AppListContext");
|
||||||
|
}
|
||||||
|
|
||||||
|
return context;
|
||||||
|
};
|
|
@ -17,7 +17,14 @@ export const appsList: AppsListQuery["apps"]["edges"] = [
|
||||||
isActive: true,
|
isActive: true,
|
||||||
name: "app",
|
name: "app",
|
||||||
type: AppTypeEnum.THIRDPARTY,
|
type: AppTypeEnum.THIRDPARTY,
|
||||||
appUrl: null
|
appUrl: null,
|
||||||
|
permissions: [
|
||||||
|
{
|
||||||
|
__typename: "Permission",
|
||||||
|
code: PermissionEnum.MANAGE_USERS,
|
||||||
|
name: "Manage customers."
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -28,7 +35,19 @@ export const appsList: AppsListQuery["apps"]["edges"] = [
|
||||||
isActive: false,
|
isActive: false,
|
||||||
name: "app1",
|
name: "app1",
|
||||||
type: AppTypeEnum.THIRDPARTY,
|
type: AppTypeEnum.THIRDPARTY,
|
||||||
appUrl: "http://localhost:3000"
|
appUrl: "http://localhost:3000",
|
||||||
|
permissions: [
|
||||||
|
{
|
||||||
|
__typename: "Permission",
|
||||||
|
code: PermissionEnum.MANAGE_ORDERS,
|
||||||
|
name: "Manage orders."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
__typename: "Permission",
|
||||||
|
code: PermissionEnum.MANAGE_USERS,
|
||||||
|
name: "Manage customers."
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
@ -42,7 +61,19 @@ export const customAppsList: AppsListQuery["apps"]["edges"] = [
|
||||||
isActive: true,
|
isActive: true,
|
||||||
name: "app custom",
|
name: "app custom",
|
||||||
type: AppTypeEnum.LOCAL,
|
type: AppTypeEnum.LOCAL,
|
||||||
appUrl: null
|
appUrl: null,
|
||||||
|
permissions: [
|
||||||
|
{
|
||||||
|
__typename: "Permission",
|
||||||
|
code: PermissionEnum.MANAGE_ORDERS,
|
||||||
|
name: "Manage orders."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
__typename: "Permission",
|
||||||
|
code: PermissionEnum.MANAGE_USERS,
|
||||||
|
name: "Manage customers."
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
|
@ -26,11 +26,7 @@ export const appsList = gql`
|
||||||
totalCount
|
totalCount
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
id
|
...AppListItem
|
||||||
name
|
|
||||||
isActive
|
|
||||||
type
|
|
||||||
appUrl
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,13 +75,12 @@ export const useStyles = makeStyles(
|
||||||
padding: "0!important"
|
padding: "0!important"
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
"& svg": {
|
"& button": {
|
||||||
bottom: theme.spacing(0.2),
|
marginLeft: theme.spacing(0.6)
|
||||||
marginLeft: theme.spacing(0.6),
|
|
||||||
position: "relative"
|
|
||||||
},
|
},
|
||||||
color: theme.palette.error.main,
|
color: theme.palette.error.main,
|
||||||
margin: theme.spacing(0, 1, 0.7, 0)
|
marginRight: theme.spacing(1),
|
||||||
|
alignItems: "flex-end"
|
||||||
},
|
},
|
||||||
headerLinkContainer: {
|
headerLinkContainer: {
|
||||||
"& svg": {
|
"& svg": {
|
||||||
|
|
|
@ -5,7 +5,12 @@ import { ActiveTab, Dialog, Pagination, SingleAction } from "../types";
|
||||||
|
|
||||||
export const MANIFEST_ATTR = "manifestUrl";
|
export const MANIFEST_ATTR = "manifestUrl";
|
||||||
|
|
||||||
export type AppListUrlDialog = "remove" | "remove-app" | "remove-custom-app";
|
export type AppListUrlDialog =
|
||||||
|
| "remove"
|
||||||
|
| "remove-app"
|
||||||
|
| "remove-custom-app"
|
||||||
|
| "app-activate"
|
||||||
|
| "app-deactivate";
|
||||||
|
|
||||||
export type AppDetailsUrlDialog = "app-activate" | "app-deactivate";
|
export type AppDetailsUrlDialog = "app-activate" | "app-deactivate";
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
import { useApolloClient } from "@apollo/client";
|
import { useApolloClient } from "@apollo/client";
|
||||||
|
import AppActivateDialog from "@saleor/apps/components/AppActivateDialog";
|
||||||
|
import AppDeactivateDialog from "@saleor/apps/components/AppDeactivateDialog";
|
||||||
|
import { AppListContext, AppListContextValues } from "@saleor/apps/context";
|
||||||
import {
|
import {
|
||||||
AppDeleteFailedInstallationMutation,
|
|
||||||
AppDeleteMutation,
|
|
||||||
AppsInstallationsQuery,
|
AppsInstallationsQuery,
|
||||||
AppsListQuery,
|
AppsListQuery,
|
||||||
AppSortField,
|
AppSortField,
|
||||||
AppTypeEnum,
|
AppTypeEnum,
|
||||||
JobStatusEnum,
|
JobStatusEnum,
|
||||||
OrderDirection,
|
OrderDirection,
|
||||||
|
useAppActivateMutation,
|
||||||
|
useAppDeactivateMutation,
|
||||||
useAppDeleteFailedInstallationMutation,
|
useAppDeleteFailedInstallationMutation,
|
||||||
useAppDeleteMutation,
|
useAppDeleteMutation,
|
||||||
useAppRetryInstallMutation,
|
useAppRetryInstallMutation,
|
||||||
|
@ -23,7 +26,6 @@ import usePaginator, {
|
||||||
PaginatorContext
|
PaginatorContext
|
||||||
} from "@saleor/hooks/usePaginator";
|
} from "@saleor/hooks/usePaginator";
|
||||||
import { ListViews } from "@saleor/types";
|
import { ListViews } from "@saleor/types";
|
||||||
import getAppErrorMessage from "@saleor/utils/errors/app";
|
|
||||||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||||
import React, { useEffect, useRef } from "react";
|
import React, { useEffect, useRef } from "react";
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
|
@ -131,17 +133,36 @@ export const AppsList: React.FC<AppsListProps> = ({ params }) => {
|
||||||
};
|
};
|
||||||
const [retryInstallApp] = useAppRetryInstallMutation({
|
const [retryInstallApp] = useAppRetryInstallMutation({
|
||||||
onCompleted: data => {
|
onCompleted: data => {
|
||||||
const errors = data.appRetryInstall.errors;
|
if (!data?.appRetryInstall?.errors?.length) {
|
||||||
if (!errors.length) {
|
|
||||||
const appInstallation = data.appRetryInstall.appInstallation;
|
const appInstallation = data.appRetryInstall.appInstallation;
|
||||||
setActiveInstallations(installations => [
|
setActiveInstallations(installations => [
|
||||||
...installations,
|
...installations,
|
||||||
{ id: appInstallation.id, name: appInstallation.appName }
|
{ id: appInstallation.id, name: appInstallation.appName }
|
||||||
]);
|
]);
|
||||||
} else {
|
}
|
||||||
errors.forEach(error =>
|
}
|
||||||
notify({ status: "error", text: getAppErrorMessage(error, intl) })
|
});
|
||||||
);
|
const [activateApp, activateAppResult] = useAppActivateMutation({
|
||||||
|
onCompleted: data => {
|
||||||
|
if (!data?.appActivate?.errors?.length) {
|
||||||
|
notify({
|
||||||
|
status: "success",
|
||||||
|
text: intl.formatMessage(messages.appActivated)
|
||||||
|
});
|
||||||
|
refetch();
|
||||||
|
closeModal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const [deactivateApp, deactivateAppResult] = useAppDeactivateMutation({
|
||||||
|
onCompleted: data => {
|
||||||
|
if (!data?.appDeactivate?.errors?.length) {
|
||||||
|
notify({
|
||||||
|
status: "success",
|
||||||
|
text: intl.formatMessage(messages.appDeactivated)
|
||||||
|
});
|
||||||
|
refetch();
|
||||||
|
closeModal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -150,30 +171,18 @@ export const AppsList: React.FC<AppsListProps> = ({ params }) => {
|
||||||
AppListUrlQueryParams
|
AppListUrlQueryParams
|
||||||
>(navigate, appsListUrl, params);
|
>(navigate, appsListUrl, params);
|
||||||
|
|
||||||
const onAppRemove = (data: AppDeleteMutation) => {
|
|
||||||
const errors = data.appDelete.errors;
|
|
||||||
if (errors.length === 0) {
|
|
||||||
if (data.appDelete.app.type === AppTypeEnum.LOCAL) {
|
|
||||||
customAppsRefetch();
|
|
||||||
} else {
|
|
||||||
refetch();
|
|
||||||
}
|
|
||||||
closeModal();
|
|
||||||
refetchExtensionList();
|
|
||||||
removeAppNotify();
|
|
||||||
} else {
|
|
||||||
errors.forEach(error =>
|
|
||||||
notify({
|
|
||||||
status: "error",
|
|
||||||
text: getAppErrorMessage(error, intl)
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const [deleteApp, deleteAppOpts] = useAppDeleteMutation({
|
const [deleteApp, deleteAppOpts] = useAppDeleteMutation({
|
||||||
onCompleted: data => {
|
onCompleted: data => {
|
||||||
onAppRemove(data);
|
if (!data?.appDelete?.errors?.length) {
|
||||||
|
if (data.appDelete.app.type === AppTypeEnum.LOCAL) {
|
||||||
|
customAppsRefetch();
|
||||||
|
} else {
|
||||||
|
refetch();
|
||||||
|
}
|
||||||
|
closeModal();
|
||||||
|
refetchExtensionList();
|
||||||
|
removeAppNotify();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const [
|
const [
|
||||||
|
@ -181,7 +190,11 @@ export const AppsList: React.FC<AppsListProps> = ({ params }) => {
|
||||||
deleteInProgressAppOpts
|
deleteInProgressAppOpts
|
||||||
] = useAppDeleteFailedInstallationMutation({
|
] = useAppDeleteFailedInstallationMutation({
|
||||||
onCompleted: data => {
|
onCompleted: data => {
|
||||||
onAppInProgressRemove(data);
|
if (!data?.appDeleteFailedInstallation?.errors?.length) {
|
||||||
|
removeAppNotify();
|
||||||
|
appsInProgressRefetch();
|
||||||
|
closeModal();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -256,77 +269,92 @@ export const AppsList: React.FC<AppsListProps> = ({ params }) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const onAppInProgressRemove = (data: AppDeleteFailedInstallationMutation) => {
|
const handleActivateAppConfirm = () =>
|
||||||
const errors = data.appDeleteFailedInstallation.errors;
|
activateApp({ variables: { id: params.id } });
|
||||||
if (errors.length === 0) {
|
|
||||||
removeAppNotify();
|
const handleDeactivateAppConfirm = () =>
|
||||||
appsInProgressRefetch();
|
deactivateApp({ variables: { id: params.id } });
|
||||||
closeModal();
|
|
||||||
} else {
|
|
||||||
errors.forEach(error =>
|
|
||||||
notify({
|
|
||||||
status: "error",
|
|
||||||
text: getAppErrorMessage(error, intl)
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const onAppInstallRetry = (id: string) =>
|
const onAppInstallRetry = (id: string) =>
|
||||||
retryInstallApp({ variables: { id } });
|
retryInstallApp({ variables: { id } });
|
||||||
|
|
||||||
const installedApps = data?.apps?.edges;
|
const installedApps = data?.apps?.edges;
|
||||||
const customApps = customAppsData?.apps?.edges;
|
const customApps = customAppsData?.apps?.edges;
|
||||||
|
|
||||||
|
const context: AppListContextValues = React.useMemo(
|
||||||
|
() => ({
|
||||||
|
activateApp: id => openModal("app-activate", { id }),
|
||||||
|
deactivateApp: id => openModal("app-deactivate", { id })
|
||||||
|
}),
|
||||||
|
[activateApp, deactivateApp]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PaginatorContext.Provider value={paginationValues}>
|
<AppListContext.Provider value={context}>
|
||||||
<AppDeleteDialog
|
<PaginatorContext.Provider value={paginationValues}>
|
||||||
confirmButtonState={deleteAppOpts.status}
|
<AppDeleteDialog
|
||||||
name={getCurrentAppName(
|
confirmButtonState={deleteAppOpts.status}
|
||||||
params.id,
|
name={getCurrentAppName(
|
||||||
action === "remove-app" ? installedApps : customApps
|
params.id,
|
||||||
)}
|
action === "remove-app" ? installedApps : customApps
|
||||||
onClose={closeModal}
|
)}
|
||||||
onConfirm={handleRemoveConfirm}
|
onClose={closeModal}
|
||||||
type={action === "remove-app" ? "EXTERNAL" : "CUSTOM"}
|
onConfirm={handleRemoveConfirm}
|
||||||
open={action === "remove-app" || action === "remove-custom-app"}
|
type={action === "remove-app" ? "EXTERNAL" : "CUSTOM"}
|
||||||
/>
|
open={action === "remove-app" || action === "remove-custom-app"}
|
||||||
<AppInProgressDeleteDialog
|
/>
|
||||||
confirmButtonState={deleteInProgressAppOpts.status}
|
<AppActivateDialog
|
||||||
name={getAppInProgressName(
|
confirmButtonState={activateAppResult.status}
|
||||||
params.id,
|
name={getCurrentAppName(params.id, installedApps)}
|
||||||
appsInProgressData?.appsInstallations
|
onClose={closeModal}
|
||||||
)}
|
onConfirm={handleActivateAppConfirm}
|
||||||
onClose={closeModal}
|
open={params.action === "app-activate"}
|
||||||
onConfirm={handleRemoveInProgressConfirm}
|
/>
|
||||||
open={action === "remove"}
|
<AppDeactivateDialog
|
||||||
/>
|
confirmButtonState={deactivateAppResult.status}
|
||||||
<AppsListPage
|
name={getCurrentAppName(params.id, installedApps)}
|
||||||
installedAppsList={installedApps}
|
onClose={closeModal}
|
||||||
customAppsList={customApps}
|
onConfirm={handleDeactivateAppConfirm}
|
||||||
appsInProgressList={appsInProgressData}
|
open={params.action === "app-deactivate"}
|
||||||
loadingAppsInProgress={loadingAppsInProgress}
|
/>
|
||||||
disabled={loading || customAppsLoading}
|
<AppInProgressDeleteDialog
|
||||||
settings={settings}
|
confirmButtonState={deleteInProgressAppOpts.status}
|
||||||
onUpdateListSettings={updateListSettings}
|
name={getAppInProgressName(
|
||||||
onAppInstallRetry={onAppInstallRetry}
|
params.id,
|
||||||
getCustomAppHref={id => customAppUrl(id)}
|
appsInProgressData?.appsInstallations
|
||||||
onInstalledAppRemove={id =>
|
)}
|
||||||
openModal("remove-app", {
|
onClose={closeModal}
|
||||||
id
|
onConfirm={handleRemoveInProgressConfirm}
|
||||||
})
|
open={action === "remove"}
|
||||||
}
|
/>
|
||||||
onCustomAppRemove={id =>
|
<AppsListPage
|
||||||
openModal("remove-custom-app", {
|
installedAppsList={installedApps}
|
||||||
id
|
customAppsList={customApps}
|
||||||
})
|
appsInProgressList={appsInProgressData}
|
||||||
}
|
loadingAppsInProgress={loadingAppsInProgress}
|
||||||
onAppInProgressRemove={id =>
|
disabled={loading || customAppsLoading}
|
||||||
openModal("remove", {
|
settings={settings}
|
||||||
id
|
onUpdateListSettings={updateListSettings}
|
||||||
})
|
onAppInstallRetry={onAppInstallRetry}
|
||||||
}
|
getCustomAppHref={id => customAppUrl(id)}
|
||||||
/>
|
onInstalledAppRemove={id =>
|
||||||
</PaginatorContext.Provider>
|
openModal("remove-app", {
|
||||||
|
id
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onCustomAppRemove={id =>
|
||||||
|
openModal("remove-custom-app", {
|
||||||
|
id
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onAppInProgressRemove={id =>
|
||||||
|
openModal("remove", {
|
||||||
|
id
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</PaginatorContext.Provider>
|
||||||
|
</AppListContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -20,5 +20,15 @@ export const messages = defineMessages({
|
||||||
id: "5t/4um",
|
id: "5t/4um",
|
||||||
defaultMessage: "Couldn’t Install {name}",
|
defaultMessage: "Couldn’t Install {name}",
|
||||||
description: "message title"
|
description: "message title"
|
||||||
|
},
|
||||||
|
appActivated: {
|
||||||
|
id: "D/+84n",
|
||||||
|
defaultMessage: "App activated",
|
||||||
|
description: "snackbar text"
|
||||||
|
},
|
||||||
|
appDeactivated: {
|
||||||
|
id: "USO8PB",
|
||||||
|
defaultMessage: "App deactivated",
|
||||||
|
description: "snackbar text"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -54,7 +54,7 @@ export interface AppListViewSettings {
|
||||||
|
|
||||||
export const defaultListSettings: AppListViewSettings = {
|
export const defaultListSettings: AppListViewSettings = {
|
||||||
[ListViews.APPS_LIST]: {
|
[ListViews.APPS_LIST]: {
|
||||||
rowNumber: 10
|
rowNumber: 100
|
||||||
},
|
},
|
||||||
[ListViews.ATTRIBUTE_VALUE_LIST]: {
|
[ListViews.ATTRIBUTE_VALUE_LIST]: {
|
||||||
rowNumber: 10
|
rowNumber: 10
|
||||||
|
|
|
@ -31,3 +31,23 @@ export const appFragment = gql`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const appListItemFragment = gql`
|
||||||
|
fragment AppListItem on App {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
isActive
|
||||||
|
type
|
||||||
|
appUrl
|
||||||
|
permissions {
|
||||||
|
...AppPermission
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const appPermissionFragment = gql`
|
||||||
|
fragment AppPermission on Permission {
|
||||||
|
name
|
||||||
|
code
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
|
@ -47,6 +47,24 @@ export const AppFragmentDoc = gql`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
${WebhookFragmentDoc}`;
|
${WebhookFragmentDoc}`;
|
||||||
|
export const AppPermissionFragmentDoc = gql`
|
||||||
|
fragment AppPermission on Permission {
|
||||||
|
name
|
||||||
|
code
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export const AppListItemFragmentDoc = gql`
|
||||||
|
fragment AppListItem on App {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
isActive
|
||||||
|
type
|
||||||
|
appUrl
|
||||||
|
permissions {
|
||||||
|
...AppPermission
|
||||||
|
}
|
||||||
|
}
|
||||||
|
${AppPermissionFragmentDoc}`;
|
||||||
export const AttributeFragmentDoc = gql`
|
export const AttributeFragmentDoc = gql`
|
||||||
fragment Attribute on Attribute {
|
fragment Attribute on Attribute {
|
||||||
id
|
id
|
||||||
|
@ -3135,16 +3153,12 @@ export const AppsListDocument = gql`
|
||||||
totalCount
|
totalCount
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
id
|
...AppListItem
|
||||||
name
|
|
||||||
isActive
|
|
||||||
type
|
|
||||||
appUrl
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
${AppListItemFragmentDoc}`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __useAppsListQuery__
|
* __useAppsListQuery__
|
||||||
|
|
|
@ -5251,7 +5251,7 @@ export type AppsListQueryVariables = Exact<{
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type AppsListQuery = { __typename: 'Query', apps: { __typename: 'AppCountableConnection', totalCount: number | null, pageInfo: { __typename: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor: string | null, endCursor: string | null }, edges: Array<{ __typename: 'AppCountableEdge', node: { __typename: 'App', id: string, name: string | null, isActive: boolean | null, type: AppTypeEnum | null, appUrl: string | null } }> } | null };
|
export type AppsListQuery = { __typename: 'Query', apps: { __typename: 'AppCountableConnection', totalCount: number | null, pageInfo: { __typename: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor: string | null, endCursor: string | null }, edges: Array<{ __typename: 'AppCountableEdge', node: { __typename: 'App', id: string, name: string | null, isActive: boolean | null, type: AppTypeEnum | null, appUrl: string | null, permissions: Array<{ __typename: 'Permission', name: string, code: PermissionEnum }> | null } }> } | null };
|
||||||
|
|
||||||
export type AppsInstallationsQueryVariables = Exact<{ [key: string]: never; }>;
|
export type AppsInstallationsQueryVariables = Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
|
@ -5909,6 +5909,10 @@ export type AddressFragment = { __typename: 'Address', city: string, cityArea: s
|
||||||
|
|
||||||
export type AppFragment = { __typename: 'App', id: string, name: string | null, created: any | null, isActive: boolean | null, type: AppTypeEnum | null, homepageUrl: string | null, appUrl: string | null, configurationUrl: string | null, supportUrl: string | null, version: string | null, accessToken: string | null, privateMetadata: Array<{ __typename: 'MetadataItem', key: string, value: string }>, metadata: Array<{ __typename: 'MetadataItem', key: string, value: string }>, tokens: Array<{ __typename: 'AppToken', authToken: string | null, id: string, name: string | null }> | null, webhooks: Array<{ __typename: 'Webhook', id: string, name: string, isActive: boolean, app: { __typename: 'App', id: string, name: string | null } }> | null };
|
export type AppFragment = { __typename: 'App', id: string, name: string | null, created: any | null, isActive: boolean | null, type: AppTypeEnum | null, homepageUrl: string | null, appUrl: string | null, configurationUrl: string | null, supportUrl: string | null, version: string | null, accessToken: string | null, privateMetadata: Array<{ __typename: 'MetadataItem', key: string, value: string }>, metadata: Array<{ __typename: 'MetadataItem', key: string, value: string }>, tokens: Array<{ __typename: 'AppToken', authToken: string | null, id: string, name: string | null }> | null, webhooks: Array<{ __typename: 'Webhook', id: string, name: string, isActive: boolean, app: { __typename: 'App', id: string, name: string | null } }> | null };
|
||||||
|
|
||||||
|
export type AppListItemFragment = { __typename: 'App', id: string, name: string | null, isActive: boolean | null, type: AppTypeEnum | null, appUrl: string | null, permissions: Array<{ __typename: 'Permission', name: string, code: PermissionEnum }> | null };
|
||||||
|
|
||||||
|
export type AppPermissionFragment = { __typename: 'Permission', name: string, code: PermissionEnum };
|
||||||
|
|
||||||
export type AttributeValueFragment = { __typename: 'AttributeValue', id: string, name: string | null, slug: string | null, reference: string | null, boolean: boolean | null, date: any | null, dateTime: any | null, value: string | null, file: { __typename: 'File', url: string, contentType: string | null } | null };
|
export type AttributeValueFragment = { __typename: 'AttributeValue', id: string, name: string | null, slug: string | null, reference: string | null, boolean: boolean | null, date: any | null, dateTime: any | null, value: string | null, file: { __typename: 'File', url: string, contentType: string | null } | null };
|
||||||
|
|
||||||
export type AttributeValueDetailsFragment = { __typename: 'AttributeValue', richText: any | null, id: string, name: string | null, slug: string | null, reference: string | null, boolean: boolean | null, date: any | null, dateTime: any | null, value: string | null, file: { __typename: 'File', url: string, contentType: string | null } | null };
|
export type AttributeValueDetailsFragment = { __typename: 'AttributeValue', richText: any | null, id: string, name: string | null, slug: string | null, reference: string | null, boolean: boolean | null, date: any | null, dateTime: any | null, value: string | null, file: { __typename: 'File', url: string, contentType: string | null } | null };
|
||||||
|
|
|
@ -19,8 +19,8 @@ export const commonMessages = defineMessages({
|
||||||
defaultMessage: "Channel"
|
defaultMessage: "Channel"
|
||||||
},
|
},
|
||||||
customApps: {
|
customApps: {
|
||||||
id: "w4R/SO",
|
id: "+iV0gu",
|
||||||
defaultMessage: "Local Apps"
|
defaultMessage: "Internal Apps"
|
||||||
},
|
},
|
||||||
dashboard: {
|
dashboard: {
|
||||||
id: "hzSNj4",
|
id: "hzSNj4",
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue