Update app-sdk and pass saleor versions to handshake event for apps (#3789)

* Update app-sdk (early build) and pass saleor versions to handshake event for apps

* Add changeset

* Fix sdk version

* Fix broken external app context

* cr fixes
This commit is contained in:
Lukasz Ostrowski 2023-06-28 15:06:08 +02:00 committed by GitHub
parent eb92e08670
commit 6640294078
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 100 additions and 54 deletions

View file

@ -0,0 +1,5 @@
---
"saleor-dashboard": patch
---
Dashboard is sending Saleor and Dashboard versions with Handshake event to apps, via AppBridge. To achieve that, @saleor/app-sdk was updated to 0.41.0

14
package-lock.json generated
View file

@ -117,7 +117,7 @@
"@graphql-codegen/typescript-react-apollo": "^3.2.5", "@graphql-codegen/typescript-react-apollo": "^3.2.5",
"@percy/cli": "^1.21.0", "@percy/cli": "^1.21.0",
"@percy/cypress": "^3.1.2", "@percy/cypress": "^3.1.2",
"@saleor/app-sdk": "0.39.1", "@saleor/app-sdk": "0.41.0",
"@swc/jest": "^0.2.26", "@swc/jest": "^0.2.26",
"@types/apollo-upload-client": "^17.0.2", "@types/apollo-upload-client": "^17.0.2",
"@types/color-convert": "^2.0.0", "@types/color-convert": "^2.0.0",
@ -7803,9 +7803,9 @@
} }
}, },
"node_modules/@saleor/app-sdk": { "node_modules/@saleor/app-sdk": {
"version": "0.39.1", "version": "0.41.0",
"resolved": "https://registry.npmjs.org/@saleor/app-sdk/-/app-sdk-0.39.1.tgz", "resolved": "https://registry.npmjs.org/@saleor/app-sdk/-/app-sdk-0.41.0.tgz",
"integrity": "sha512-PBREZWwkk+DHCBhOZzsuFdp7/vLItxfAqKD+gcZ5QxzSAt82S0/FS6ii7igpW3H+bEiK4oBUjMxgUyhJMOXQHw==", "integrity": "sha512-9Yc73N8QvqfHlhsPzuWqwlbl+o/gq/VJ+HB2OUro68zTF+rapEssb79OUGLp2JmnTlM4xovCiPwPlDsW8nVSqw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@changesets/cli": "^2.26.0", "@changesets/cli": "^2.26.0",
@ -40625,9 +40625,9 @@
} }
}, },
"@saleor/app-sdk": { "@saleor/app-sdk": {
"version": "0.39.1", "version": "0.41.0",
"resolved": "https://registry.npmjs.org/@saleor/app-sdk/-/app-sdk-0.39.1.tgz", "resolved": "https://registry.npmjs.org/@saleor/app-sdk/-/app-sdk-0.41.0.tgz",
"integrity": "sha512-PBREZWwkk+DHCBhOZzsuFdp7/vLItxfAqKD+gcZ5QxzSAt82S0/FS6ii7igpW3H+bEiK4oBUjMxgUyhJMOXQHw==", "integrity": "sha512-9Yc73N8QvqfHlhsPzuWqwlbl+o/gq/VJ+HB2OUro68zTF+rapEssb79OUGLp2JmnTlM4xovCiPwPlDsW8nVSqw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@changesets/cli": "^2.26.0", "@changesets/cli": "^2.26.0",

View file

@ -124,7 +124,7 @@
"@graphql-codegen/typescript-react-apollo": "^3.2.5", "@graphql-codegen/typescript-react-apollo": "^3.2.5",
"@percy/cli": "^1.21.0", "@percy/cli": "^1.21.0",
"@percy/cypress": "^3.1.2", "@percy/cypress": "^3.1.2",
"@saleor/app-sdk": "0.39.1", "@saleor/app-sdk": "0.41.0",
"@swc/jest": "^0.2.26", "@swc/jest": "^0.2.26",
"@types/apollo-upload-client": "^17.0.2", "@types/apollo-upload-client": "^17.0.2",
"@types/color-convert": "^2.0.0", "@types/color-convert": "^2.0.0",

View file

@ -4,6 +4,7 @@ import { useUpdateAppToken } from "@dashboard/apps/components/AppFrame/useUpdate
import { AppDetailsUrlQueryParams } from "@dashboard/apps/urls"; import { AppDetailsUrlQueryParams } from "@dashboard/apps/urls";
import { useAllFlags } from "@dashboard/featureFlags"; import { useAllFlags } from "@dashboard/featureFlags";
import { CircularProgress } from "@material-ui/core"; import { CircularProgress } from "@material-ui/core";
import { DashboardEventFactory } from "@saleor/app-sdk/app-bridge";
import clsx from "clsx"; import clsx from "clsx";
import React, { useCallback } from "react"; import React, { useCallback } from "react";
@ -19,6 +20,8 @@ interface Props {
className?: string; className?: string;
params?: AppDetailsUrlQueryParams; params?: AppDetailsUrlQueryParams;
refetch?: () => void; refetch?: () => void;
dashboardVersion: string;
coreVersion?: string;
onError?(): void; onError?(): void;
} }
@ -32,6 +35,8 @@ export const AppFrame: React.FC<Props> = ({
params, params,
onError, onError,
refetch, refetch,
dashboardVersion,
coreVersion,
}) => { }) => {
const frameRef = React.useRef<HTMLIFrameElement | null>(null); const frameRef = React.useRef<HTMLIFrameElement | null>(null);
const classes = useStyles(); const classes = useStyles();
@ -46,6 +51,10 @@ export const AppFrame: React.FC<Props> = ({
appOrigin, appOrigin,
appId, appId,
appToken, appToken,
{
core: coreVersion,
dashboard: dashboardVersion,
},
); );
/** /**
@ -62,13 +71,12 @@ export const AppFrame: React.FC<Props> = ({
* Move handshake to notifyReady, so app is requesting token after it's ready to receive it * Move handshake to notifyReady, so app is requesting token after it's ready to receive it
* Currently handshake it 2 times, for compatibility * Currently handshake it 2 times, for compatibility
*/ */
postToExtension({ postToExtension(
type: "handshake", DashboardEventFactory.createHandshakeEvent(appToken, 1, {
payload: { core: coreVersion,
token: appToken, dashboard: dashboardVersion,
version: 1, }),
}, );
});
setHandshakeDone(true); setHandshakeDone(true);
}, [appToken, postToExtension, setHandshakeDone]); }, [appToken, postToExtension, setHandshakeDone]);

View file

@ -6,6 +6,7 @@ import { getAppMountUri } from "@dashboard/config";
import useNavigator from "@dashboard/hooks/useNavigator"; import useNavigator from "@dashboard/hooks/useNavigator";
import useNotifier from "@dashboard/hooks/useNotifier"; import useNotifier from "@dashboard/hooks/useNotifier";
import { import {
DashboardEventFactory,
DispatchResponseEvent, DispatchResponseEvent,
NotificationAction, NotificationAction,
NotifyReady, NotifyReady,
@ -185,6 +186,10 @@ const useNotifyReadyAction = (
frameEl: HTMLIFrameElement | null, frameEl: HTMLIFrameElement | null,
appOrigin: string, appOrigin: string,
appToken: string, appToken: string,
versions: {
core: string;
dashboard: string;
},
) => { ) => {
const postToExtension = usePostToExtension(frameEl, appOrigin); const postToExtension = usePostToExtension(frameEl, appOrigin);
@ -192,13 +197,12 @@ const useNotifyReadyAction = (
return { return {
handle(action: NotifyReady) { handle(action: NotifyReady) {
postToExtension({ postToExtension(
type: "handshake", DashboardEventFactory.createHandshakeEvent(appToken, 1, {
payload: { core: versions.core,
token: appToken, dashboard: versions.dashboard,
version: 1, }),
}, );
});
return createResponseStatus(action.payload.actionId, true); return createResponseStatus(action.payload.actionId, true);
}, },
}; };

View file

@ -3,11 +3,18 @@ import { usePostToExtension } from "@dashboard/apps/components/AppFrame/usePostT
import { Actions, DispatchResponseEvent } from "@saleor/app-sdk/app-bridge"; import { Actions, DispatchResponseEvent } from "@saleor/app-sdk/app-bridge";
import React, { useState } from "react"; import React, { useState } from "react";
/**
* TODO Refactor to named attributes
*/
export const useAppActions = ( export const useAppActions = (
frameEl: HTMLIFrameElement | null, frameEl: HTMLIFrameElement | null,
appOrigin: string, appOrigin: string,
appId: string, appId: string,
appToken: string, appToken: string,
versions: {
core: string;
dashboard: string;
},
) => { ) => {
const postToExtension = usePostToExtension(frameEl, appOrigin); const postToExtension = usePostToExtension(frameEl, appOrigin);
@ -21,6 +28,7 @@ export const useAppActions = (
frameEl, frameEl,
appOrigin, appOrigin,
appToken, appToken,
versions,
); );
/** /**

View file

@ -5,7 +5,9 @@ import {
topBarHeight, topBarHeight,
} from "@dashboard/components/AppLayout/consts"; } from "@dashboard/components/AppLayout/consts";
import { DetailPageLayout } from "@dashboard/components/Layouts"; import { DetailPageLayout } from "@dashboard/components/Layouts";
import { APP_VERSION } from "@dashboard/config";
import { AppQuery } from "@dashboard/graphql"; import { AppQuery } from "@dashboard/graphql";
import useShop from "@dashboard/hooks/useShop";
import { Box } from "@saleor/macaw-ui/next"; import { Box } from "@saleor/macaw-ui/next";
import React from "react"; import React from "react";
@ -24,38 +26,51 @@ export const AppPage: React.FC<AppPageProps> = ({
url, url,
onError, onError,
refetch, refetch,
}) => ( }) => {
<DetailPageLayout gridTemplateColumns={1} withSavebar={false}> const shop = useShop();
<AppPageNav
goBackUrl={AppUrls.resolveAppListUrl()} /**
appId={data.id} * TODO Make some loading state
name={data?.name} */
supportUrl={data?.supportUrl} if (!shop?.version) {
homepageUrl={data?.homepageUrl} return null;
author={data?.author} }
appLogoUrl={data?.brand?.logo.default}
/> return (
<DetailPageLayout.Content> <DetailPageLayout gridTemplateColumns={1} withSavebar={false}>
<Box <AppPageNav
position="relative" goBackUrl={AppUrls.resolveAppListUrl()}
// It removes extra space between iframe and container appId={data?.id}
__lineHeight={0} name={data?.name}
height="100%" supportUrl={data?.supportUrl}
__minHeight={`calc(100vh - ${borderHeight} - ${topBarHeight})`} homepageUrl={data?.homepageUrl}
> author={data?.author}
{url && data?.id && data?.accessToken && ( appLogoUrl={data?.brand?.logo.default}
<AppFrame />
src={url} <DetailPageLayout.Content>
appToken={data?.accessToken ?? ""} <Box
onError={onError} position="relative"
appId={data?.id ?? ""} // It removes extra space between iframe and container
refetch={refetch} __lineHeight={0}
/> height="100%"
)} __minHeight={`calc(100vh - ${borderHeight} - ${topBarHeight})`}
</Box> >
</DetailPageLayout.Content> {url && data?.id && data?.accessToken && (
</DetailPageLayout> <AppFrame
); src={url}
appToken={data?.accessToken ?? ""}
onError={onError}
appId={data?.id ?? ""}
refetch={refetch}
coreVersion={shop.version}
dashboardVersion={APP_VERSION}
/>
)}
</Box>
</DetailPageLayout.Content>
</DetailPageLayout>
);
};
AppPage.displayName = "AppPage"; AppPage.displayName = "AppPage";
export default AppPage; export default AppPage;

View file

@ -1,6 +1,8 @@
import { AppUrls } from "@dashboard/apps/urls"; import { AppUrls } from "@dashboard/apps/urls";
import { APP_VERSION } from "@dashboard/config";
import { AppExtensionTargetEnum } from "@dashboard/graphql"; import { AppExtensionTargetEnum } from "@dashboard/graphql";
import useNavigator from "@dashboard/hooks/useNavigator"; import useNavigator from "@dashboard/hooks/useNavigator";
import useShop from "@dashboard/hooks/useShop";
import React from "react"; import React from "react";
import { AppDialog } from "../AppDialog"; import { AppDialog } from "../AppDialog";
@ -11,6 +13,8 @@ export const ExternalAppProvider: React.FC = ({ children }) => {
const [open, setOpen] = React.useState(false); const [open, setOpen] = React.useState(false);
const [appData, setAppData] = React.useState<AppData | undefined>(); const [appData, setAppData] = React.useState<AppData | undefined>();
const shop = useShop();
const handleClose = () => { const handleClose = () => {
setOpen(false); setOpen(false);
setAppData(undefined); setAppData(undefined);
@ -26,6 +30,8 @@ export const ExternalAppProvider: React.FC = ({ children }) => {
appToken={appData.appToken} appToken={appData.appToken}
appId={appData.id} appId={appData.id}
params={appData.params} params={appData.params}
dashboardVersion={APP_VERSION}
coreVersion={shop?.version}
/> />
)} )}
</AppDialog> </AppDialog>