saleor-dashboard/src/apps/components/AppFrame/AppFrame.tsx
Patryk Andrzejewski 3118741db8
Feature flags strategies (#3800)
* Feature flags

* Feature flags

* Feature flags

* Feature flags

* Feature flags

* Feature flags

* Types

* use @swc/jest

* Avoid calling constructors inside

* Types

* Types

* remove flagsmith

* Change to payload

* Change to payload

* Update tests

* Split resolver
2023-06-27 13:30:20 +02:00

106 lines
2.6 KiB
TypeScript

// @ts-strict-ignore
import { useAppDashboardUpdates } from "@dashboard/apps/components/AppFrame/useAppDashboardUpdates";
import { useUpdateAppToken } from "@dashboard/apps/components/AppFrame/useUpdateAppToken";
import { AppDetailsUrlQueryParams } from "@dashboard/apps/urls";
import { useAllFlags } from "@dashboard/featureFlags";
import { CircularProgress } from "@material-ui/core";
import clsx from "clsx";
import React, { useCallback } from "react";
import { AppIFrame } from "./AppIFrame";
import { useStyles } from "./styles";
import { useAppActions } from "./useAppActions";
import useTokenRefresh from "./useTokenRefresh";
interface Props {
src: string;
appToken: string;
appId: string;
className?: string;
params?: AppDetailsUrlQueryParams;
refetch?: () => void;
onError?(): void;
}
const getOrigin = (url: string) => new URL(url).origin;
export const AppFrame: React.FC<Props> = ({
src,
appToken,
appId,
className,
params,
onError,
refetch,
}) => {
const frameRef = React.useRef<HTMLIFrameElement | null>(null);
const classes = useStyles();
const appOrigin = getOrigin(src);
const flags = useAllFlags();
/**
* React on messages from App
*/
const { postToExtension, handshakeDone, setHandshakeDone } = useAppActions(
frameRef.current,
appOrigin,
appId,
appToken,
);
/**
* Listen to Dashboard context like theme or locale and inform app about it
*/
useAppDashboardUpdates(frameRef.current, appOrigin, handshakeDone, appId);
useTokenRefresh(appToken, refetch);
const handleLoad = useCallback(() => {
/**
* @deprecated
*
* Move handshake to notifyReady, so app is requesting token after it's ready to receive it
* Currently handshake it 2 times, for compatibility
*/
postToExtension({
type: "handshake",
payload: {
token: appToken,
version: 1,
},
});
setHandshakeDone(true);
}, [appToken, postToExtension, setHandshakeDone]);
useUpdateAppToken({
postToExtension,
appToken,
/**
* If app is not ready, ignore this flow
*/
enabled: handshakeDone,
});
return (
<>
{!handshakeDone && (
<div className={classes.loader}>
<CircularProgress color="primary" />
</div>
)}
<AppIFrame
ref={frameRef}
src={src}
appId={appId}
featureFlags={flags}
params={params}
onLoad={handleLoad}
onError={onError}
className={clsx(classes.iframe, className, {
[classes.iframeHidden]: !handshakeDone,
})}
/>
</>
);
};