Skip to content

Commit

Permalink
Merge branch 'develop' into chore/status-bullet-colors
Browse files Browse the repository at this point in the history
  • Loading branch information
kodiakhq[bot] authored May 24, 2023
2 parents f6d5b4f + d40e4c0 commit 8d330d9
Show file tree
Hide file tree
Showing 142 changed files with 4,869 additions and 129 deletions.
9 changes: 8 additions & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,18 @@
/.github/ @RocketChat/Architecture
/_templates/ @RocketChat/Architecture
/apps/meteor/client/ @RocketChat/frontend
/apps/meteor/tests/ @RocketChat/Architecture
/apps/meteor/tests/e2e @RocketChat/frontend
/apps/meteor/tests/end-to-end @RocketChat/backend
/apps/meteor/tests/unit/app @RocketChat/backend
/apps/meteor/tests/unit/app/ui-utils @RocketChat/frontend
/apps/meteor/tests/unit/client @RocketChat/frontend
/apps/meteor/tests/unit/server @RocketChat/backend
/apps/meteor/app/apps/ @RocketChat/apps
/apps/meteor/app/livechat @RocketChat/omnichannel
/apps/meteor/app/voip @RocketChat/omnichannel
/apps/meteor/app/sms @RocketChat/omnichannel
/apps/meteor/server @RocketChat/backend
/apps/meteor/server/models @RocketChat/Architecture
/apps/meteor/packages/rocketchat-livechat @RocketChat/omnichannel
/apps/meteor/server/services/voip @RocketChat/omnichannel
/apps/meteor/server/services/omnichannel-voip @RocketChat/omnichannel
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Box, ProgressBar } from '@rocket.chat/fuselage';
import type { ReactNode } from 'react';
import React from 'react';

const GenericResourceUsage = ({
title,
value,
max,
percentage,
threshold = 80,
variant = percentage < threshold ? 'success' : 'danger',
subTitle,
...props
}: {
title: string;
subTitle?: ReactNode;
value: number;
max: number;
percentage: number;
threshold?: number;
variant?: 'warning' | 'danger' | 'success';
}) => {
return (
<Box w='x180' h='x40' mi='x8' fontScale='c1' display='flex' flexDirection='column' justifyContent='space-around' {...props}>
<Box display='flex' justifyContent='space-between'>
<Box color='default'>{title}</Box>
{subTitle && <Box color='hint'>{subTitle}</Box>}
<Box color='hint'>
{value}/{max}
</Box>
</Box>
<ProgressBar percentage={percentage} variant={variant} />
</Box>
);
};

export default GenericResourceUsage;
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Box, Skeleton } from '@rocket.chat/fuselage';
import React from 'react';

const GenericResourceUsageSkeleton = ({ title, ...props }: { title?: string }) => {
return (
<Box w='x180' h='x40' mi='x8' fontScale='c1' display='flex' flexDirection='column' justifyContent='space-around' {...props}>
{title ? <Box color='default'>{title}</Box> : <Skeleton w='full' />}
<Skeleton w='full' />
</Box>
);
};

export default GenericResourceUsageSkeleton;
4 changes: 4 additions & 0 deletions apps/meteor/client/components/GenericResourceUsage/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import GenericResourceUsage from './GenericResourceUsage';
import GenericResourceUsageSkeleton from './GenericResourceUsageSkeleton';

export { GenericResourceUsage, GenericResourceUsageSkeleton };
3 changes: 2 additions & 1 deletion apps/meteor/client/components/Page/PageHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const PageHeader: FC<PageHeaderProps> = ({ children = undefined, title, onClickB
<Box
borderBlockEndWidth='default'
minHeight='x64'
pb='x8'
borderBlockEndColor={borderBlockEndColor ?? border ? 'extra-light' : 'transparent'}
{...props}
>
Expand All @@ -30,7 +31,7 @@ const PageHeader: FC<PageHeaderProps> = ({ children = undefined, title, onClickB
marginInline='x24'
display='flex'
flexDirection='row'
flexWrap='nowrap'
flexWrap='wrap'
alignItems='center'
color='default'
{...props}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Box, ProgressBar, Skeleton } from '@rocket.chat/fuselage';
/* eslint-disable react/no-multi-comp */
import { useTranslation } from '@rocket.chat/ui-contexts';
import React from 'react';

import { GenericResourceUsage, GenericResourceUsageSkeleton } from '../../../components/GenericResourceUsage';
import { useActiveConnections } from './hooks/useActiveConnections';

const CustomUserActiveConnections = () => {
Expand All @@ -10,27 +11,12 @@ const CustomUserActiveConnections = () => {
const result = useActiveConnections();

if (result.isLoading || result.isError) {
return (
<Box w='x180' h='x40' mi='x8' fontScale='c1' display='flex' flexDirection='column' justifyContent='space-around'>
<Box color='default'>{t('Active_connections')}</Box>
<Skeleton w='full' />
</Box>
);
return <GenericResourceUsageSkeleton title={t('Active_connections')} />;
}

const { current, max, percentage } = result.data;

return (
<Box w='x180' h='x40' mi='x8' fontScale='c1' display='flex' flexDirection='column' justifyContent='space-around'>
<Box display='flex' justifyContent='space-between'>
<Box color='default'>{t('Active_connections')}</Box>
<Box color='hint'>
{current}/{max}
</Box>
</Box>
<ProgressBar percentage={percentage} variant={percentage < 80 ? 'success' : 'danger'} />
</Box>
);
return <GenericResourceUsage title={t('Active_connections')} value={current} max={max} percentage={percentage} />;
};

export default CustomUserActiveConnections;
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Box, ProgressBar } from '@rocket.chat/fuselage';
import { useTranslation } from '@rocket.chat/ui-contexts';
import type { ReactElement } from 'react';
import React from 'react';

import { GenericResourceUsage } from '../../../components/GenericResourceUsage';

const EnabledAppsCount = ({
variant,
percentage,
Expand All @@ -22,28 +23,14 @@ const EnabledAppsCount = ({
const marketplaceAppsCountText: string = t('Apps_Count_Enabled', { count: enabled });

return (
<Box
display='flex'
flexDirection='column'
mi='16px'
minWidth='200px'
justifyContent='center'
data-tooltip={t('Apps_Count_Enabled_tooltip', {
number: enabled,
context: context === 'private' ? 'private' : 'marketplace',
})}
>
<Box display='flex' flexDirection='row' alignItems='center' justifyContent='space-between' w='full'>
<Box fontScale='c1'>{context === 'private' ? privateAppsCountText : marketplaceAppsCountText}</Box>

<Box fontScale='c1' color='annotation'>
{`${enabled} / ${limit}`}
</Box>
</Box>
<Box mbs='x8'>
<ProgressBar variant={variant} percentage={percentage} />
</Box>
</Box>
<GenericResourceUsage
title={context === 'private' ? privateAppsCountText : marketplaceAppsCountText}
value={enabled}
max={limit}
percentage={percentage}
threshold={80}
variant={variant}
/>
);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { Box, Button, ButtonGroup, Skeleton } from '@rocket.chat/fuselage';
import { Button, ButtonGroup } from '@rocket.chat/fuselage';
import { usePermission, useRoute, useRouteParameter, useSetModal, useTranslation } from '@rocket.chat/ui-contexts';
import type { ReactElement } from 'react';
import React, { useCallback } from 'react';

import { GenericResourceUsageSkeleton } from '../../../components/GenericResourceUsage';
import Page from '../../../components/Page';
import UnlimitedAppsUpsellModal from '../UnlimitedAppsUpsellModal';
import { useAppsCountQuery } from '../hooks/useAppsCountQuery';
import EnabledAppsCount from './EnabledAppsCount';
Expand All @@ -20,40 +22,27 @@ const MarketplaceHeader = ({ title }: { title: string }): ReactElement | null =>
route.push({ context, page: 'install' });
}, [context, route]);

if (result.isLoading) {
return (
<Box w='x180' h='x40' mi='x8' fontScale='c1' display='flex' flexDirection='column' justifyContent='space-around'>
<Box color='default'>{t('Active_connections')}</Box>
<Skeleton w='full' />
</Box>
);
}

if (result.isError) {
return null;
}

return (
<Box display='flex' pi='24px' pb='12px' alignItems='center' justifyContent='space-between'>
<Box fontScale='h2'>{title}</Box>
<Box display='flex' flexDirection='row' flexWrap='wrap'>
{!result.data.hasUnlimitedApps && <EnabledAppsCount {...result.data} context={context} />}
{isAdmin && (
<ButtonGroup>
{!result.data.hasUnlimitedApps && (
<Button
onClick={() => {
setModal(<UnlimitedAppsUpsellModal onClose={handleModalClose} />);
}}
>
{t('Enable_unlimited_apps')}
</Button>
)}
{context === 'private' && <Button onClick={handleUploadButtonClick}>{t('Upload_private_app')}</Button>}
</ButtonGroup>
<Page.Header title={title}>
<ButtonGroup flexWrap='wrap' justifyContent='flex-end'>
{result.isLoading && <GenericResourceUsageSkeleton />}
{result.isSuccess && !result.data.hasUnlimitedApps && <EnabledAppsCount {...result.data} context={context} />}
{isAdmin && result.isSuccess && !result.data.hasUnlimitedApps && (
<Button
onClick={() => {
setModal(<UnlimitedAppsUpsellModal onClose={handleModalClose} />);
}}
>
{t('Enable_unlimited_apps')}
</Button>
)}
</Box>
</Box>
{isAdmin && context === 'private' && <Button onClick={handleUploadButtonClick}>{t('Upload_private_app')}</Button>}
</ButtonGroup>
</Page.Header>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const useAppsCountQuery = (context: MarketplaceRouteContext) => {
const getAppsCount = useEndpoint('GET', '/apps/count');

return useQuery(
['apps/count', { context }],
['apps/count', context],
async () => {
const data = await getAppsCount();

Expand Down
14 changes: 12 additions & 2 deletions apps/meteor/ee/app/license/server/license.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,15 +174,15 @@ class LicenseClass {
return item;
}
if (!this._validateURL(license.url, this.url)) {
item.valid = false;
this.invalidate(item);
console.error(`#### License error: invalid url, licensed to ${license.url}, used on ${this.url}`);
this._invalidModules(license.modules);
return item;
}
}

if (license.expiry && this._validateExpiration(license.expiry)) {
item.valid = false;
this.invalidate(item);
console.error(`#### License error: expired, valid until ${license.expiry}`);
this._invalidModules(license.modules);
return item;
Expand Down Expand Up @@ -212,6 +212,12 @@ class LicenseClass {
this.showLicenses();
}

invalidate(item: IValidLicense): void {
item.valid = false;

EnterpriseLicenses.emit('invalidate');
}

async canAddNewUser(): Promise<boolean> {
if (!maxActiveUsers) {
return true;
Expand Down Expand Up @@ -421,6 +427,10 @@ export function onValidateLicenses(cb: (...args: any[]) => void): void {
EnterpriseLicenses.on('validate', cb);
}

export function onInvalidateLicense(cb: (...args: any[]) => void): void {
EnterpriseLicenses.on('invalidate', cb);
}

export function flatModules(modulesAndBundles: string[]): string[] {
const bundles = modulesAndBundles.filter(isBundle);
const modules = modulesAndBundles.filter((x) => !isBundle(x));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { ProgressBar, Box } from '@rocket.chat/fuselage';
import { useTranslation } from '@rocket.chat/ui-contexts';
import type { ReactElement } from 'react';
import React from 'react';

import { GenericResourceUsage } from '../../../../../../client/components/GenericResourceUsage';

type SeatsCapUsageProps = {
limit: number;
members: number;
Expand All @@ -11,26 +12,9 @@ type SeatsCapUsageProps = {
const SeatsCapUsage = ({ limit, members }: SeatsCapUsageProps): ReactElement => {
const t = useTranslation();
const percentage = Math.max(0, Math.min((100 / limit) * members, 100));
const closeToLimit = percentage >= 80;
const reachedLimit = percentage >= 100;
const seatsLeft = Math.max(0, limit - members);

return (
<Box display='flex' flexDirection='column' minWidth='x180'>
<Box
color={reachedLimit ? 'status-font-on-danger' : 'default'}
display='flex'
flexDirection='row'
justifyContent='space-between'
fontScale='c1'
mb='x8'
>
<div role='status'>{t('Seats_Available', { seatsLeft })}</div>
<Box color={reachedLimit ? 'status-font-on-danger' : 'hint'}>{`${members}/${limit}`}</Box>
</Box>
<ProgressBar percentage={percentage} variant={closeToLimit ? 'danger' : 'success'} />
</Box>
);
return <GenericResourceUsage title={t('Seats_Available', { seatsLeft })} value={members} max={limit} percentage={percentage} />;
};

export default SeatsCapUsage;
15 changes: 9 additions & 6 deletions apps/meteor/ee/client/views/admin/users/useSeatsCap.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useEndpointData } from '../../../../../client/hooks/useEndpointData';
import { useEndpoint } from '@rocket.chat/ui-contexts';
import { useQuery } from '@tanstack/react-query';

export const useSeatsCap = ():
| {
Expand All @@ -7,15 +8,17 @@ export const useSeatsCap = ():
reload: () => void;
}
| undefined => {
const { value, reload } = useEndpointData('/v1/licenses.maxActiveUsers');
const fetch = useEndpoint('GET', '/v1/licenses.maxActiveUsers');

if (!value) {
const result = useQuery(['/v1/licenses.maxActiveUsers'], () => fetch());

if (!result.isSuccess) {
return undefined;
}

return {
activeUsers: value.activeUsers,
maxActiveUsers: value.maxActiveUsers ?? Number.POSITIVE_INFINITY,
reload,
activeUsers: result.data.activeUsers,
maxActiveUsers: result.data.maxActiveUsers ?? Number.POSITIVE_INFINITY,
reload: () => result.refetch(),
};
};
8 changes: 8 additions & 0 deletions apps/meteor/ee/server/apps/orchestrator.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,14 @@ export class AppServerOrchestrator {
this._rocketchatLogger.info(`Loaded the Apps Framework and loaded a total of ${this.getManager().get({ enabled: true }).length} Apps!`);
}

async disableApps() {
await this.getManager()
.get()
.forEach((app) => {
this.getManager().disable(app.getID());
});
}

async unload() {
// Don't try to unload it if it's already been
// unlaoded or wasn't unloaded to start with
Expand Down
1 change: 1 addition & 0 deletions apps/meteor/ee/server/startup/apps/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import './trialExpiration';
10 changes: 10 additions & 0 deletions apps/meteor/ee/server/startup/apps/trialExpiration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Meteor } from 'meteor/meteor';

import { Apps } from '../../apps';
import { onInvalidateLicense } from '../../../app/license/server/license';

Meteor.startup(() => {
onInvalidateLicense(() => {
void Apps.disableApps();
});
});
Loading

0 comments on commit 8d330d9

Please sign in to comment.