diff --git a/frontend/src/component/changeRequest/ProjectChangeRequests/ChangeRequestsTabs/ChangeRequestsTabs.tsx b/frontend/src/component/changeRequest/ProjectChangeRequests/ChangeRequestsTabs/ChangeRequestsTabs.tsx index 32146f69e4..8e58404db4 100644 --- a/frontend/src/component/changeRequest/ProjectChangeRequests/ChangeRequestsTabs/ChangeRequestsTabs.tsx +++ b/frontend/src/component/changeRequest/ProjectChangeRequests/ChangeRequestsTabs/ChangeRequestsTabs.tsx @@ -271,7 +271,7 @@ export const ChangeRequestsTabs = ({ } elseShow={ - None of the changes where submitted yet. + None of the changes were submitted yet. } /> diff --git a/frontend/src/component/changeRequest/ProjectChangeRequests/ProjectChangeRequests.tsx b/frontend/src/component/changeRequest/ProjectChangeRequests/ProjectChangeRequests.tsx index dd9b699e9a..f659aba0d4 100644 --- a/frontend/src/component/changeRequest/ProjectChangeRequests/ProjectChangeRequests.tsx +++ b/frontend/src/component/changeRequest/ProjectChangeRequests/ProjectChangeRequests.tsx @@ -5,12 +5,17 @@ import { useProjectNameOrId } from 'hooks/api/getters/useProject/useProject'; import { ChangeRequestsTabs } from './ChangeRequestsTabs/ChangeRequestsTabs'; import { SortingRule } from 'react-table'; import { useProjectChangeRequests } from 'hooks/api/getters/useProjectChangeRequests/useProjectChangeRequests'; +import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; +import { PageContent } from 'component/common/PageContent/PageContent'; +import { PageHeader } from 'component/common/PageHeader/PageHeader'; +import { PremiumFeature } from 'component/common/PremiumFeature/PremiumFeature'; const defaultSort: SortingRule = { id: 'updatedAt', desc: true }; export const ProjectChangeRequests = () => { const projectId = useRequiredPathParam('projectId'); const projectName = useProjectNameOrId(projectId); + const { isOss, isPro } = useUiConfig(); usePageTitle(`Change requests – ${projectName}`); @@ -21,6 +26,14 @@ export const ProjectChangeRequests = () => { defaultSort ); + if (isOss() || isPro()) { + return ( + + + + ); + } + return ( ({ +const PremiumFeatureWrapper = styled(Box, { + shouldForwardProp: prop => prop !== 'tooltip', +})<{ tooltip?: boolean }>(({ theme, tooltip }) => ({ display: 'flex', flexDirection: 'column', - padding: theme.spacing(1, 0.5), + alignItems: tooltip ? 'start' : 'center', + textAlign: tooltip ? 'left' : 'center', + backgroundColor: tooltip ? 'transparent' : theme.palette.secondaryContainer, + borderRadius: tooltip ? 0 : theme.shape.borderRadiusLarge, + padding: tooltip ? theme.spacing(1, 0.5) : theme.spacing(7.5, 1), })); const StyledTitle = styled(Typography)(({ theme }) => ({ display: 'inline-flex', alignItems: 'center', fontWeight: theme.fontWeight.bold, - fontSize: theme.fontSizes.smallBody, gap: theme.spacing(1), })); -const StyledBody = styled(Typography)(({ theme }) => ({ +const StyledBody = styled('div', { + shouldForwardProp: prop => prop !== 'tooltip', +})<{ tooltip?: boolean }>(({ theme, tooltip }) => ({ + margin: tooltip ? theme.spacing(1, 0) : theme.spacing(3, 0, 5, 0), +})); + +const StyledTypography = styled(Typography)(({ theme }) => ({ fontSize: theme.fontSizes.smallBody, - margin: theme.spacing(1, 0), +})); + +const StyledButtonContainer = styled('div')(() => ({ + display: 'flex', })); const StyledLink = styled(Link)(({ theme }) => ({ fontSize: theme.fontSizes.smallBody, - width: 'fit-content', })); -enum FeatureLevelTitle { - PRO = 'Pro & Enterprise feature', - ENTERPRISE = 'Enterprise feature', +enum FeaturePlan { + PRO = 'Pro & Enterprise', + ENTERPRISE = 'Enterprise', } -export enum PlausibleOrigin { - PROJECT = 'Projects', - ACCESS = 'Access', - CHANGE_REQUEST = 'Change Request', -} +const PremiumFeatures = { + ['Adding new projects']: { + plan: FeaturePlan.PRO, + url: '', + }, + ['Access']: { + plan: FeaturePlan.PRO, + url: 'https://docs.getunleash.io/reference/rbac', + }, + ['Change Requests']: { + plan: FeaturePlan.ENTERPRISE, + url: 'https://docs.getunleash.io/reference/change-requests', + }, +}; + +type PremiumFeature = keyof typeof PremiumFeatures; + +const UPGRADE_URL = 'https://www.getunleash.io/plans'; export interface PremiumFeatureProps { - children: React.ReactNode; - origin?: PlausibleOrigin; - center?: boolean; - enterpriseOnly?: boolean; + feature: PremiumFeature; + tooltip?: boolean; } -export const PremiumFeature = ({ - children, - origin, - center, - enterpriseOnly = false, -}: PremiumFeatureProps) => { +export const PremiumFeature = ({ feature, tooltip }: PremiumFeatureProps) => { + const { url, plan } = PremiumFeatures[feature]; + const tracker = usePlausibleTracker(); const handleClick = () => { - if (origin) { - tracker.trackEvent('upgrade_plan_clicked', { - props: { origin }, - }); - } + tracker.trackEvent('upgrade_plan_clicked', { + props: { feature }, + }); }; + const featureLabel = Boolean(url) ? ( + + {feature} + + ) : ( + feature + ); + + const featureMessage = ( + <> + {featureLabel} is a feature available for the{' '} + {plan}{' '} + {plan === FeaturePlan.PRO ? 'plans' : 'plan'} + + ); + return ( - + - {enterpriseOnly - ? FeatureLevelTitle.ENTERPRISE - : FeatureLevelTitle.PRO} + {`${plan} feature`} - {children} - - Upgrade now - + + + + {featureMessage}. You need to upgrade your plan + if you want to use it + + + + + Upgrade now + + + + } + elseShow={ + <> + + + {featureMessage} + + + You need to upgrade your plan if you want to use + it + + + + + + + } + /> ); }; diff --git a/frontend/src/component/project/Project/ProjectSettings/ChangeRequestConfiguration/ChangeRequestConfiguration.tsx b/frontend/src/component/project/Project/ProjectSettings/ChangeRequestConfiguration/ChangeRequestConfiguration.tsx index b8a6663e3d..7f5d2607d3 100644 --- a/frontend/src/component/project/Project/ProjectSettings/ChangeRequestConfiguration/ChangeRequestConfiguration.tsx +++ b/frontend/src/component/project/Project/ProjectSettings/ChangeRequestConfiguration/ChangeRequestConfiguration.tsx @@ -1,7 +1,7 @@ import { useContext } from 'react'; import { PageContent } from 'component/common/PageContent/PageContent'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; -import { Alert, Link, styled } from '@mui/material'; +import { Alert } from '@mui/material'; import { PageHeader } from 'component/common/PageHeader/PageHeader'; import AccessContext from 'contexts/AccessContext'; import { UPDATE_PROJECT } from 'component/providers/AccessProvider/permissions'; @@ -9,15 +9,8 @@ import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; import { usePageTitle } from 'hooks/usePageTitle'; import { useProjectNameOrId } from 'hooks/api/getters/useProject/useProject'; import { ChangeRequestTable } from './ChangeRequestTable'; -import { - PlausibleOrigin, - PremiumFeature, -} from 'component/common/PremiumFeature/PremiumFeature'; - -const StyledLink = styled(Link)(({ theme }) => ({ - fontSize: theme.fontSizes.smallBody, - width: 'fit-content', -})); +import { PremiumFeature } from 'component/common/PremiumFeature/PremiumFeature'; +import { ChangeRequestProcessHelp } from './ChangeRequestProcessHelp/ChangeRequestProcessHelp'; export const ChangeRequestConfiguration = () => { const projectId = useRequiredPathParam('projectId'); @@ -25,37 +18,29 @@ export const ChangeRequestConfiguration = () => { const { hasAccess } = useContext(AccessContext); const { isOss, isPro } = useUiConfig(); - usePageTitle(`Project change request – ${projectName}`); + usePageTitle(`Project change request configuration – ${projectName}`); if (isOss() || isPro()) { return ( } + header={ + } + /> + } sx={{ justifyContent: 'center' }} > - - <> - If you want to use{' '} - - "Change Requests" - {' '} - you will need to upgrade to Enterprise plan - - + ); } if (!hasAccess(UPDATE_PROJECT, projectId)) { return ( - }> + } + > You need project owner permissions to access this section. diff --git a/frontend/src/component/project/ProjectAccess/ProjectAccess.tsx b/frontend/src/component/project/ProjectAccess/ProjectAccess.tsx index 0d9d018147..9d53ac91fa 100644 --- a/frontend/src/component/project/ProjectAccess/ProjectAccess.tsx +++ b/frontend/src/component/project/ProjectAccess/ProjectAccess.tsx @@ -1,7 +1,7 @@ import { useContext } from 'react'; import { PageContent } from 'component/common/PageContent/PageContent'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; -import { Alert, Box, Link, styled } from '@mui/material'; +import { Alert } from '@mui/material'; import { PageHeader } from 'component/common/PageHeader/PageHeader'; import AccessContext from 'contexts/AccessContext'; import { UPDATE_PROJECT } from 'component/providers/AccessProvider/permissions'; @@ -9,15 +9,7 @@ import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; import { usePageTitle } from 'hooks/usePageTitle'; import { ProjectAccessTable } from 'component/project/ProjectAccess/ProjectAccessTable/ProjectAccessTable'; import { useProjectNameOrId } from 'hooks/api/getters/useProject/useProject'; -import { - PlausibleOrigin, - PremiumFeature, -} from 'component/common/PremiumFeature/PremiumFeature'; - -const StyledLink = styled(Link)(({ theme }) => ({ - fontSize: theme.fontSizes.smallBody, - width: 'fit-content', -})); +import { PremiumFeature } from 'component/common/PremiumFeature/PremiumFeature'; export const ProjectAccess = () => { const projectId = useRequiredPathParam('projectId'); @@ -28,37 +20,18 @@ export const ProjectAccess = () => { if (isOss()) { return ( - }> - - - <> - Controlling access to projects requires a paid - version of Unleash. Check out{' '} - - getunleash.io - {' '} - to find out more. - - - + } + sx={{ justifyContent: 'center' }} + > + ); } if (!hasAccess(UPDATE_PROJECT, projectId)) { return ( - }> + }> You need project owner permissions to access this section. diff --git a/frontend/src/component/project/ProjectList/ProjectList.tsx b/frontend/src/component/project/ProjectList/ProjectList.tsx index f9b9c4b46b..0362eb890f 100644 --- a/frontend/src/component/project/ProjectList/ProjectList.tsx +++ b/frontend/src/component/project/ProjectList/ProjectList.tsx @@ -20,10 +20,7 @@ import { TablePlaceholder } from 'component/common/Table'; import { useMediaQuery } from '@mui/material'; import theme from 'themes/theme'; import { Search } from 'component/common/Search/Search'; -import { - PlausibleOrigin, - PremiumFeature, -} from 'component/common/PremiumFeature/PremiumFeature'; +import { PremiumFeature } from 'component/common/PremiumFeature/PremiumFeature'; import { ITooltipResolverProps } from 'component/common/TooltipResolver/TooltipResolver'; import { ReactComponent as ProPlanIcon } from 'assets/icons/pro-enterprise-feature-badge.svg'; @@ -48,10 +45,7 @@ function resolveCreateButtonData( disabled: true, tooltip: { titleComponent: ( - - To be able to add more projects you need to upgrade to - Pro or Enterprise plan - + ), sx: { maxWidth: '320px' }, variant: 'custom',