diff --git a/src/scenes/EarlyAccess/EarlyAccess.tsx b/src/scenes/EarlyAccess/EarlyAccess.tsx new file mode 100644 index 0000000000..562d47a27f --- /dev/null +++ b/src/scenes/EarlyAccess/EarlyAccess.tsx @@ -0,0 +1,114 @@ +import { + Button, + Dialog, + DialogActions, + DialogContent, + DialogProps, + DialogTitle, + List, + ListItem, + ListItemText, + Switch, + Typography, +} from '@mui/material'; +import Markdown from 'markdown-to-jsx'; +import { EarlyAccessFeature } from 'posthog-js'; +import { useActiveFeatureFlags, usePostHog } from 'posthog-js/react'; +import { Fragment, memo, useEffect, useState } from 'react'; + +export const EarlyAccessDialog = ({ children, ...props }: DialogProps) => ( + + Early Access Features + + + + + + + +); + +const EarlyAccessFeatures = () => { + const postHog = usePostHog(); + + const active = new Set(useActiveFeatureFlags()); + + const toggle = (flag: string, next: boolean) => { + postHog.updateEarlyAccessFeatureEnrollment(flag, next); + }; + + const [features, setFeatures] = useState([]); + useEffect(() => { + postHog.getEarlyAccessFeatures(setFeatures, true); + }, [postHog, setFeatures]); + + return ( + + {features.map((feature) => { + const flag = feature.flagKey!; + const enabled = active.has(flag); + return ( + + {feature.description}} + secondaryTypographyProps={{ component: 'div' }} + sx={{ whiteSpace: 'pre' }} + id={`switch-list-label-${flag}`} + /> + toggle(flag, !enabled)} + checked={enabled} + inputProps={{ + 'aria-labelledby': `switch-list-label-${flag}`, + }} + /> + + ); + })} + {features.length === 0 && ( + + No early access features are currently available. +
Check back later! +
+ )} +
+ ); +}; + +const Description = memo(function Description({ + children, +}: { + children: string; +}) { + return ( + + {children} + + ); +}); diff --git a/src/scenes/Root/Header/ProfileMenu/EarlyAccessMenuItem.tsx b/src/scenes/Root/Header/ProfileMenu/EarlyAccessMenuItem.tsx new file mode 100644 index 0000000000..cc08ea9f5a --- /dev/null +++ b/src/scenes/Root/Header/ProfileMenu/EarlyAccessMenuItem.tsx @@ -0,0 +1,20 @@ +import { MenuItem, MenuItemProps } from '@mui/material'; +import { useDialog } from '../../../../components/Dialog'; +import { EarlyAccessDialog } from '../../../EarlyAccess/EarlyAccess'; + +export const EarlyAccessMenuItem = (props: MenuItemProps) => { + const [state, open] = useDialog(); + return ( + <> + { + open(); + props.onClick?.(event); + }} + > + Early Access Features + + + + ); +}; diff --git a/src/scenes/Root/Header/ProfileMenu/ProfileMenu.tsx b/src/scenes/Root/Header/ProfileMenu/ProfileMenu.tsx index 1556bc2423..b6c110d01c 100644 --- a/src/scenes/Root/Header/ProfileMenu/ProfileMenu.tsx +++ b/src/scenes/Root/Header/ProfileMenu/ProfileMenu.tsx @@ -5,6 +5,7 @@ import { ImpersonationContext } from '~/api/client/ImpersonationContext'; import { MenuItemLink } from '../../../../components/Routing'; import { useSession } from '../../../../components/Session'; import { ChangePasswordMenuItem } from './ChangePasswordMenuItem'; +import { EarlyAccessMenuItem } from './EarlyAccessMenuItem'; import { ImpersonationMenuItem } from './ImpersonationDialog'; import { ToggleUploadManagerMenuItem } from './ToggleUploadManagerMenuItem'; @@ -49,6 +50,7 @@ export const ProfileMenu = (props: Partial) => { )} + Sign Out );