mirror of
https://github.com/strapi/strapi.git
synced 2025-11-06 13:01:40 +00:00
Merge pull request #15738 from strapi/chore/ee-seats-fe-review
This commit is contained in:
commit
0a42f13814
@ -9,7 +9,6 @@ import {
|
|||||||
} from '@strapi/helper-plugin';
|
} from '@strapi/helper-plugin';
|
||||||
import { useQueries } from 'react-query';
|
import { useQueries } from 'react-query';
|
||||||
import get from 'lodash/get';
|
import get from 'lodash/get';
|
||||||
import useLicenseLimitInfos from 'ee_else_ce/hooks/useLicenseLimitInfos';
|
|
||||||
import packageJSON from '../../../../package.json';
|
import packageJSON from '../../../../package.json';
|
||||||
import { useConfigurations } from '../../hooks';
|
import { useConfigurations } from '../../hooks';
|
||||||
import PluginsInitializer from '../PluginsInitializer';
|
import PluginsInitializer from '../PluginsInitializer';
|
||||||
@ -73,10 +72,6 @@ const AuthenticatedApp = () => {
|
|||||||
}
|
}
|
||||||
}, [userRoles, appInfos]);
|
}, [userRoles, appInfos]);
|
||||||
|
|
||||||
// This hook fetches license allowances in 'ee' mode and stores data in redux for global access.
|
|
||||||
// It does nothing in 'ce'.
|
|
||||||
useLicenseLimitInfos();
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const getUserId = async () => {
|
const getUserId = async () => {
|
||||||
const userId = await hashAdminUserEmail(userInfo);
|
const userId = await hashAdminUserEmail(userInfo);
|
||||||
|
|||||||
@ -52,11 +52,6 @@ jest.mock('../../RBACProvider', () => {
|
|||||||
return Compo;
|
return Compo;
|
||||||
});
|
});
|
||||||
|
|
||||||
jest.mock('ee_else_ce/hooks/useLicenseLimitInfos', () => ({
|
|
||||||
__esModule: true,
|
|
||||||
default: jest.fn(),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const queryClient = new QueryClient({
|
const queryClient = new QueryClient({
|
||||||
defaultOptions: {
|
defaultOptions: {
|
||||||
queries: {
|
queries: {
|
||||||
|
|||||||
@ -10,5 +10,5 @@ export { default as usePermissionsDataManager } from './usePermissionsDataManage
|
|||||||
export { default as useReleaseNotification } from './useReleaseNotification';
|
export { default as useReleaseNotification } from './useReleaseNotification';
|
||||||
export { default as useThemeToggle } from './useThemeToggle';
|
export { default as useThemeToggle } from './useThemeToggle';
|
||||||
export { default as useRegenerate } from './useRegenerate';
|
export { default as useRegenerate } from './useRegenerate';
|
||||||
export { default as useLicenseLimitInfos } from './useLicenseLimitInfos';
|
export { default as useLicenseLimit } from './useLicenseLimits';
|
||||||
export { default as useLicenseLimitNotification } from './useLicenseLimitNotification';
|
export { default as useLicenseLimitNotification } from './useLicenseLimitNotification';
|
||||||
|
|||||||
@ -1,5 +0,0 @@
|
|||||||
const useLicenseLimitInfos = () => {
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useLicenseLimitInfos;
|
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
const useLicenseLimits = () => {};
|
||||||
|
|
||||||
|
export default useLicenseLimits;
|
||||||
@ -101,13 +101,11 @@ const ListPage = () => {
|
|||||||
const isLoading =
|
const isLoading =
|
||||||
(status !== 'success' && status !== 'error') || (status === 'success' && isFetching);
|
(status !== 'success' && status !== 'error') || (status === 'success' && isFetching);
|
||||||
|
|
||||||
const createAction = canCreate ? <CreateAction onClick={handleToggle} /> : undefined;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Main aria-busy={isLoading}>
|
<Main aria-busy={isLoading}>
|
||||||
<SettingsPageTitle name="Users" />
|
<SettingsPageTitle name="Users" />
|
||||||
<HeaderLayout
|
<HeaderLayout
|
||||||
primaryAction={createAction}
|
primaryAction={canCreate && <CreateAction onClick={handleToggle} />}
|
||||||
title={title}
|
title={title}
|
||||||
subtitle={formatMessage({
|
subtitle={formatMessage({
|
||||||
id: 'Settings.permissions.users.listview.header.subtitle',
|
id: 'Settings.permissions.users.listview.header.subtitle',
|
||||||
|
|||||||
@ -114,8 +114,9 @@
|
|||||||
"Settings.application.get-help": "Get help",
|
"Settings.application.get-help": "Get help",
|
||||||
"Settings.application.link-pricing": "See all pricing plans",
|
"Settings.application.link-pricing": "See all pricing plans",
|
||||||
"Settings.application.link-upgrade": "Upgrade your admin panel",
|
"Settings.application.link-upgrade": "Upgrade your admin panel",
|
||||||
"Settings.application.ee.link-contact-sales": "Contact sales",
|
"Settings.application.ee.admin-seats.count": "{currentUserCount}/{permittedSeats}",
|
||||||
"Settings.application.ee.link-add-seats": "Add seats",
|
"Settings.application.ee.admin-seats.at-limit-tooltip": "At limit: add seats to invite more users",
|
||||||
|
"Settings.application.ee.admin-seats.add-seats": "{isHostedOnStrapiCloud, select, true {Add seats} false {Contact sales}}",
|
||||||
"Settings.application.node-version": "node version",
|
"Settings.application.node-version": "node version",
|
||||||
"Settings.application.strapi-version": "strapi version",
|
"Settings.application.strapi-version": "strapi version",
|
||||||
"Settings.application.strapiVersion": "strapi version",
|
"Settings.application.strapiVersion": "strapi version",
|
||||||
@ -845,10 +846,8 @@
|
|||||||
"notification.version.update.message": "A new version of Strapi is available!",
|
"notification.version.update.message": "A new version of Strapi is available!",
|
||||||
"notification.warning.title": "Warning:",
|
"notification.warning.title": "Warning:",
|
||||||
"notification.warning.404": "404 - Not found",
|
"notification.warning.404": "404 - Not found",
|
||||||
"notification.ee.warning.over-seat-limit": "Add seats to re-enable Users. If you already did it but it's not reflected in Strapi yet, make sure to restart your app.",
|
"notification.ee.warning.over-.message": "Add seats to {licenseLimitStatus, select, OVER_LIMIT {invite} AT_LIMIT {re-enable}} Users. If you already did it but it's not reflected in Strapi yet, make sure to restart your app.",
|
||||||
"notification.ee.warning.over-seat-limit.title": "Over seat limit ({currentUserCount}/{permittedSeats})",
|
"notification.ee.warning.at-seat-limit.title": "{licenseLimitStatus, select, OVER_LIMIT {Over} AT_LIMIT {At}} seat limit ({currentUserCount}/{permittedSeats})",
|
||||||
"notification.ee.warning.at-seat-limit": "Add seats to invite more Users. If you already did it but it's not reflected in Strapi yet, make sure to restart your app.",
|
|
||||||
"notification.ee.warning.at-seat-limit.title": "At seat limit ({currentUserCount}/{permittedSeats})",
|
|
||||||
"or": "OR",
|
"or": "OR",
|
||||||
"request.error.model.unknown": "This model doesn't exist",
|
"request.error.model.unknown": "This model doesn't exist",
|
||||||
"skipToContent": "Skip to content",
|
"skipToContent": "Skip to content",
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// eslint-disable-next-line import/prefer-default-export
|
// eslint-disable-next-line import/prefer-default-export
|
||||||
export { default as useAuthProviders } from './useAuthProviders';
|
export { default as useAuthProviders } from './useAuthProviders';
|
||||||
export { default as useLicenseLimitNotification } from './useLicenseLimitNotification';
|
export { default as useLicenseLimitNotification } from './useLicenseLimitNotification';
|
||||||
export { default as useLicenseLimitInfos } from './useLicenseLimitInfos';
|
export { default as useLicenseLimits } from './useLicenseLimits';
|
||||||
|
|||||||
@ -1,70 +0,0 @@
|
|||||||
import { useEffect } from 'react';
|
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
|
||||||
import { useFetchClient } from '@strapi/helper-plugin';
|
|
||||||
import { useQuery } from 'react-query';
|
|
||||||
import { produce } from 'immer';
|
|
||||||
|
|
||||||
import { useInjectReducer } from '../../../../admin/src/hooks/useInjectReducer';
|
|
||||||
|
|
||||||
const NS = 'StrapiAdmin/ee_license-info';
|
|
||||||
const ACTION_EE_LICENSE_INFO_SET_DATA = 'StrapiAdmin/EE_LICENSE_INFO_GET_DATA';
|
|
||||||
|
|
||||||
const initalState = {
|
|
||||||
serverState: {
|
|
||||||
currentUserCount: null,
|
|
||||||
permittedSeats: null,
|
|
||||||
shouldNotify: false,
|
|
||||||
licenseLimitStatus: null,
|
|
||||||
isHostedOnStrapiCloud: false,
|
|
||||||
licenseType: null,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const reducer = (state = initalState, action) =>
|
|
||||||
/* eslint-disable-next-line consistent-return */
|
|
||||||
produce(state, (draft) => {
|
|
||||||
switch (action.type) {
|
|
||||||
case ACTION_EE_LICENSE_INFO_SET_DATA: {
|
|
||||||
draft.serverState = action.payload;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return draft;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const actionSetData = (payload) => {
|
|
||||||
return {
|
|
||||||
type: ACTION_EE_LICENSE_INFO_SET_DATA,
|
|
||||||
payload,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const useLicenseLimitInfos = () => {
|
|
||||||
const instance = useFetchClient();
|
|
||||||
const fetchLicenseLimitInfo = async () => {
|
|
||||||
const {
|
|
||||||
data: { data },
|
|
||||||
} = await instance.get('/admin/license-limit-information');
|
|
||||||
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
|
|
||||||
const { data, status } = useQuery('license-limit-info', fetchLicenseLimitInfo);
|
|
||||||
|
|
||||||
const state = useSelector((state) => state?.[NS] ?? initalState);
|
|
||||||
const dispatch = useDispatch();
|
|
||||||
|
|
||||||
useInjectReducer(NS, reducer);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (status === 'success' && data) {
|
|
||||||
dispatch(actionSetData(data));
|
|
||||||
}
|
|
||||||
}, [data, status, dispatch]);
|
|
||||||
|
|
||||||
return state.serverState;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useLicenseLimitInfos;
|
|
||||||
@ -4,110 +4,76 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
|
import { useIntl } from 'react-intl';
|
||||||
import { useLocation } from 'react-router';
|
import { useLocation } from 'react-router';
|
||||||
import { useNotification } from '@strapi/helper-plugin';
|
import { useNotification } from '@strapi/helper-plugin';
|
||||||
import useLicenseLimitInfos from '../useLicenseLimitInfos';
|
import useLicenseLimits from '../useLicenseLimits';
|
||||||
|
|
||||||
const notificationBody = (
|
const STORAGE_KEY_PREFIX = 'strapi-notification-seat-limit-disabled';
|
||||||
currentUserCount,
|
|
||||||
permittedSeats,
|
|
||||||
licenseLimitStatus,
|
|
||||||
isHostedOnStrapiCloud
|
|
||||||
) => {
|
|
||||||
let notification = {};
|
|
||||||
const linkURL = isHostedOnStrapiCloud
|
|
||||||
? 'https://cloud.strapi.io/profile/billing'
|
|
||||||
: 'https://strapi.chargebeeportal.com/portal/v2/login?forward=portal_main';
|
|
||||||
const linkLabel = isHostedOnStrapiCloud ? 'ADD SEATS' : 'CONTACT SALES';
|
|
||||||
|
|
||||||
if (licenseLimitStatus === 'OVER_LIMIT') {
|
const BILLING_STRAPI_CLOUD_URL = 'https://cloud.strapi.io/profile/billing';
|
||||||
notification = {
|
const BILLING_SELF_HOSTED_URL =
|
||||||
type: 'warning',
|
'https://strapi.chargebeeportal.com/portal/v2/login?forward=portal_main';
|
||||||
message: {
|
|
||||||
id: 'notification.ee.warning.over-seat-limit',
|
|
||||||
defaultMessage:
|
|
||||||
"Add seats to re-enable users. If you already did it but it's not reflected in Strapi yet, make sure to restart your app.",
|
|
||||||
},
|
|
||||||
// Title is translated in the Notification component
|
|
||||||
title: {
|
|
||||||
id: 'notification.ee.warning.over-seat-limit.title',
|
|
||||||
defaultMessage: 'Over seat limit ({currentUserCount}/{permittedSeats})',
|
|
||||||
values: { currentUserCount, permittedSeats },
|
|
||||||
},
|
|
||||||
link: {
|
|
||||||
url: linkURL,
|
|
||||||
label: linkLabel,
|
|
||||||
},
|
|
||||||
blockTransition: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
return notification;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (licenseLimitStatus === 'AT_LIMIT') {
|
|
||||||
notification = {
|
|
||||||
type: 'softWarning',
|
|
||||||
message: {
|
|
||||||
id: 'notification.ee.warning.at-seat-limit',
|
|
||||||
defaultMessage:
|
|
||||||
"Add seats to re-enable users. If you already did it but it's not reflected in Strapi yet, make sure to restart your app.",
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
id: 'notification.ee.warning.at-seat-limit.title',
|
|
||||||
defaultMessage: 'At seat limit ({currentUserCount}/{permittedSeats})',
|
|
||||||
values: { currentUserCount, permittedSeats },
|
|
||||||
},
|
|
||||||
link: {
|
|
||||||
url: linkURL,
|
|
||||||
label: linkLabel,
|
|
||||||
},
|
|
||||||
blockTransition: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
return notification;
|
|
||||||
}
|
|
||||||
|
|
||||||
return notification;
|
|
||||||
};
|
|
||||||
|
|
||||||
const shouldDisplayNotification = (pathname) => {
|
|
||||||
const isLocation = (string) => pathname.includes(string);
|
|
||||||
const shownInSession = window.sessionStorage.getItem(`notification-${pathname}`);
|
|
||||||
|
|
||||||
if (isLocation('/') && shownInSession) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isLocation('users') && shownInSession) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const useLicenseLimitNotification = () => {
|
const useLicenseLimitNotification = () => {
|
||||||
let licenseLimitInfos = useLicenseLimitInfos();
|
const { formatMessage } = useIntl();
|
||||||
|
let { license } = useLicenseLimits();
|
||||||
const toggleNotification = useNotification();
|
const toggleNotification = useNotification();
|
||||||
const location = useLocation();
|
const { pathname } = useLocation();
|
||||||
|
|
||||||
// eslint-disable-next-line consistent-return
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!licenseLimitInfos || !licenseLimitInfos.permittedSeats) return;
|
if (!license?.data) {
|
||||||
|
return;
|
||||||
if (!shouldDisplayNotification(location.pathname)) return;
|
}
|
||||||
|
|
||||||
const { currentUserCount, permittedSeats, licenseLimitStatus, isHostedOnStrapiCloud } =
|
const { currentUserCount, permittedSeats, licenseLimitStatus, isHostedOnStrapiCloud } =
|
||||||
licenseLimitInfos;
|
license?.data ?? {};
|
||||||
const notification = notificationBody(
|
|
||||||
|
const shouldDisplayNotification =
|
||||||
|
permittedSeats &&
|
||||||
|
window.sessionStorage.getItem(`${STORAGE_KEY_PREFIX}-${pathname}`) &&
|
||||||
|
['/', '/users'].every(pathname.includes);
|
||||||
|
|
||||||
|
if (shouldDisplayNotification) {
|
||||||
|
toggleNotification({
|
||||||
|
type: licenseLimitStatus === 'OVER_LIMIT' ? 'warning' : 'softWarning',
|
||||||
|
message: formatMessage(
|
||||||
|
{
|
||||||
|
id: 'notification.ee.warning.seat-limit.message',
|
||||||
|
defaultMessage:
|
||||||
|
"Add seats to invite more Users. If you already did it but it's not reflected in Strapi yet, make sure to restart your app.",
|
||||||
|
},
|
||||||
|
{ licenseLimitStatus }
|
||||||
|
),
|
||||||
|
title: formatMessage(
|
||||||
|
{
|
||||||
|
id: 'notification.ee.warning.seat-limit.title',
|
||||||
|
defaultMessage: 'Over seat limit ({currentUserCount}/{permittedSeats})',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
licenseLimitStatus,
|
||||||
currentUserCount,
|
currentUserCount,
|
||||||
permittedSeats,
|
permittedSeats,
|
||||||
licenseLimitStatus,
|
}
|
||||||
isHostedOnStrapiCloud
|
),
|
||||||
);
|
link: {
|
||||||
const onClose = () => window.sessionStorage.setItem(`notification-${location.pathname}`, true);
|
url: isHostedOnStrapiCloud ? BILLING_STRAPI_CLOUD_URL : BILLING_SELF_HOSTED_URL,
|
||||||
toggleNotification({ ...notification, onClose });
|
label: formatMessage(
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
{
|
||||||
}, []);
|
id: 'notification.ee.warning.seat-limit.link',
|
||||||
|
defaultMessage:
|
||||||
|
'{isHostedOnStrapiCloud, select, true {ADD SEATS} other {CONTACT SALES}}',
|
||||||
|
},
|
||||||
|
{ isHostedOnStrapiCloud }
|
||||||
|
),
|
||||||
|
},
|
||||||
|
blockTransition: true,
|
||||||
|
onClose() {
|
||||||
|
window.sessionStorage.setItem(`${STORAGE_KEY_PREFIX}-${pathname}`, true);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [toggleNotification, license.data, pathname, formatMessage]);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useLicenseLimitNotification;
|
export default useLicenseLimitNotification;
|
||||||
|
|||||||
19
packages/core/admin/ee/admin/hooks/useLicenseLimits/index.js
Normal file
19
packages/core/admin/ee/admin/hooks/useLicenseLimits/index.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { useFetchClient } from '@strapi/helper-plugin';
|
||||||
|
import { useQuery } from 'react-query';
|
||||||
|
|
||||||
|
const useLicenseLimits = () => {
|
||||||
|
const { get } = useFetchClient();
|
||||||
|
const fetchLicenseLimitInfo = async () => {
|
||||||
|
const {
|
||||||
|
data: { data },
|
||||||
|
} = await get('/admin/license-limit-information');
|
||||||
|
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
const license = useQuery(['ee', 'license-limit-info'], fetchLicenseLimitInfo);
|
||||||
|
|
||||||
|
return { license };
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useLicenseLimits;
|
||||||
@ -9,19 +9,20 @@ import { Stack } from '@strapi/design-system/Stack';
|
|||||||
import { Link } from '@strapi/design-system/v2/Link';
|
import { Link } from '@strapi/design-system/v2/Link';
|
||||||
import ExternalLink from '@strapi/icons/ExternalLink';
|
import ExternalLink from '@strapi/icons/ExternalLink';
|
||||||
import ExclamationMarkCircle from '@strapi/icons/ExclamationMarkCircle';
|
import ExclamationMarkCircle from '@strapi/icons/ExclamationMarkCircle';
|
||||||
import { useLicenseLimitInfos } from '../../../../../../hooks';
|
import { pxToRem } from '@strapi/helper-plugin';
|
||||||
|
import { useLicenseLimits } from '../../../../../../hooks';
|
||||||
|
|
||||||
|
const BILLING_STRAPI_CLOUD_URL = 'https://cloud.strapi.io/profile/billing';
|
||||||
|
const BILLING_SELF_HOSTED_URL = 'https://share.hsforms.com/1WhxtbTkJSUmfqqEuv4pwuA43qp4';
|
||||||
|
|
||||||
const AdminSeatInfo = () => {
|
const AdminSeatInfo = () => {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const licenseLimitInfos = useLicenseLimitInfos();
|
const { license } = useLicenseLimits();
|
||||||
const { licenseLimitStatus, currentUserCount, permittedSeats, isHostedOnStrapiCloud } =
|
const { licenseLimitStatus, currentUserCount, permittedSeats, isHostedOnStrapiCloud } =
|
||||||
licenseLimitInfos;
|
license?.data ?? {};
|
||||||
const linkURL = isHostedOnStrapiCloud
|
|
||||||
? 'https://cloud.strapi.io/profile/billing'
|
|
||||||
: 'https://share.hsforms.com/1WhxtbTkJSUmfqqEuv4pwuA43qp4';
|
|
||||||
|
|
||||||
if (!permittedSeats) {
|
if (!permittedSeats) {
|
||||||
return <></>;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -39,34 +40,44 @@ const AdminSeatInfo = () => {
|
|||||||
textColor={licenseLimitStatus === 'OVER_LIMIT' ? 'danger500' : ''}
|
textColor={licenseLimitStatus === 'OVER_LIMIT' ? 'danger500' : ''}
|
||||||
fontWeight={licenseLimitStatus === 'OVER_LIMIT' ? 'bold' : ''}
|
fontWeight={licenseLimitStatus === 'OVER_LIMIT' ? 'bold' : ''}
|
||||||
>
|
>
|
||||||
{currentUserCount || 'NA'}
|
{formatMessage(
|
||||||
|
{
|
||||||
|
id: 'Settings.application.ee.admin-seats.count',
|
||||||
|
defaultMessage: '{currentUserCount}/{permittedSeats}',
|
||||||
|
},
|
||||||
|
{ permittedSeats, currentUserCount }
|
||||||
|
)}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography as="p">/</Typography>
|
|
||||||
<Typography as="p">{permittedSeats || 'NA'}</Typography>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
{licenseLimitStatus === 'AT_LIMIT' && (
|
{licenseLimitStatus === 'AT_LIMIT' && (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
description={formatMessage({
|
description={formatMessage({
|
||||||
id: 'Settings.application.admin-seats.at-limit-tooltip',
|
id: 'Settings.application.ee.admin-seats.at-limit-tooltip',
|
||||||
defaultMessage: 'At limit: add seats to invite more users',
|
defaultMessage: 'At limit: add seats to invite more users',
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
width={`${14 / 16}rem`}
|
width={`${pxToRem(14)}rem`}
|
||||||
height={`${14 / 16}rem`}
|
height={`${pxToRem(14)}rem`}
|
||||||
color="danger500"
|
color="danger500"
|
||||||
as={ExclamationMarkCircle}
|
as={ExclamationMarkCircle}
|
||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
<Link href={linkURL} isExternal endIcon={<ExternalLink />}>
|
<Link
|
||||||
{formatMessage({
|
href={isHostedOnStrapiCloud ? BILLING_STRAPI_CLOUD_URL : BILLING_SELF_HOSTED_URL}
|
||||||
id: isHostedOnStrapiCloud
|
isExternal
|
||||||
? 'Settings.application.ee.link-add-seats'
|
endIcon={<ExternalLink />}
|
||||||
: 'Settings.application.ee.link-contact-sales',
|
>
|
||||||
defaultMessage: isHostedOnStrapiCloud ? 'Add seats' : 'Contact sales',
|
{formatMessage(
|
||||||
})}
|
{
|
||||||
|
id: 'Settings.application.ee.admin-seats.add-seats',
|
||||||
|
defaultMessage:
|
||||||
|
'{isHostedOnStrapiCloud, select, true {Add seats} false {Contact sales}}',
|
||||||
|
},
|
||||||
|
{ isHostedOnStrapiCloud }
|
||||||
|
)}
|
||||||
</Link>
|
</Link>
|
||||||
</GridItem>
|
</GridItem>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -7,11 +7,11 @@ import { Icon } from '@strapi/design-system/Icon';
|
|||||||
import { Stack } from '@strapi/design-system';
|
import { Stack } from '@strapi/design-system';
|
||||||
import Envelop from '@strapi/icons/Envelop';
|
import Envelop from '@strapi/icons/Envelop';
|
||||||
import ExclamationMarkCircle from '@strapi/icons/ExclamationMarkCircle';
|
import ExclamationMarkCircle from '@strapi/icons/ExclamationMarkCircle';
|
||||||
import { useLicenseLimitInfos } from '../../../../../../hooks';
|
import { useLicenseLimits } from '../../../../../../hooks';
|
||||||
|
|
||||||
const CreateAction = ({ onClick }) => {
|
const CreateAction = ({ onClick }) => {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const licenseLimitInfos = useLicenseLimitInfos();
|
const licenseLimitInfos = useLicenseLimits();
|
||||||
const { licenseLimitStatus, permittedSeats } = licenseLimitInfos;
|
const { licenseLimitStatus, permittedSeats } = licenseLimitInfos;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user