Skip to content

Commit

Permalink
feat: workspace info admin page (#30434)
Browse files Browse the repository at this point in the history
  • Loading branch information
hugocostadev authored Oct 31, 2023
1 parent 180d400 commit 5d55a93
Show file tree
Hide file tree
Showing 49 changed files with 966 additions and 1,228 deletions.
5 changes: 5 additions & 0 deletions .changeset/workspace-status-admin-page.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": minor
---

Added a new Admin page called `Workspace info` in place of Information page, to make it easier to check the license
11 changes: 3 additions & 8 deletions apps/meteor/app/api/server/lib/getServerInfo.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
import type { IWorkspaceInfo } from '@rocket.chat/core-typings';

import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import {
getCachedSupportedVersionsToken,
wrapPromise,
} from '../../../cloud/server/functions/supportedVersionsToken/supportedVersionsToken';
import { Info, minimumClientVersions } from '../../../utils/rocketchat.info';

type ServerInfo = {
info?: typeof Info;
supportedVersions?: { signed: string };
minimumClientVersions: typeof minimumClientVersions;
version: string;
};

const removePatchInfo = (version: string): string => version.replace(/(\d+\.\d+).*/, '$1');

export async function getServerInfo(userId?: string): Promise<ServerInfo> {
export async function getServerInfo(userId?: string): Promise<IWorkspaceInfo> {
const hasPermissionToViewStatistics = userId && (await hasPermissionAsync(userId, 'view-statistics'));
const supportedVersionsToken = await wrapPromise(getCachedSupportedVersionsToken());

Expand Down
33 changes: 23 additions & 10 deletions apps/meteor/app/statistics/server/lib/statistics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,18 +305,30 @@ export const statistics = {
);

// Message statistics
statistics.totalChannelMessages = (await Rooms.findByType('c', { projection: { msgs: 1 } }).toArray()).reduce(
function _countChannelMessages(num: number, room: IRoom) {
const channels = await Rooms.findByType('c', { projection: { msgs: 1, prid: 1 } }).toArray();
const totalChannelDiscussionsMessages = await channels.reduce(function _countChannelDiscussionsMessages(num: number, room: IRoom) {
return num + (room.prid ? room.msgs : 0);
}, 0);
statistics.totalChannelMessages =
(await channels.reduce(function _countChannelMessages(num: number, room: IRoom) {
return num + room.msgs;
},
0,
);
statistics.totalPrivateGroupMessages = (await Rooms.findByType('p', { projection: { msgs: 1 } }).toArray()).reduce(
function _countPrivateGroupMessages(num: number, room: IRoom) {
}, 0)) - totalChannelDiscussionsMessages;

const privateGroups = await Rooms.findByType('p', { projection: { msgs: 1, prid: 1 } }).toArray();
const totalPrivateGroupsDiscussionsMessages = await privateGroups.reduce(function _countPrivateGroupsDiscussionsMessages(
num: number,
room: IRoom,
) {
return num + (room.prid ? room.msgs : 0);
},
0);
statistics.totalPrivateGroupMessages =
(await privateGroups.reduce(function _countPrivateGroupMessages(num: number, room: IRoom) {
return num + room.msgs;
},
0,
);
}, 0)) - totalPrivateGroupsDiscussionsMessages;

statistics.totalDiscussionsMessages = totalPrivateGroupsDiscussionsMessages + totalChannelDiscussionsMessages;

statistics.totalDirectMessages = (await Rooms.findByType('d', { projection: { msgs: 1 } }).toArray()).reduce(
function _countDirectMessages(num: number, room: IRoom) {
return num + room.msgs;
Expand All @@ -332,6 +344,7 @@ export const statistics = {
statistics.totalMessages =
statistics.totalChannelMessages +
statistics.totalPrivateGroupMessages +
statistics.totalDiscussionsMessages +
statistics.totalDirectMessages +
statistics.totalLivechatMessages;

Expand Down
10 changes: 8 additions & 2 deletions apps/meteor/client/hooks/useLicense.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,21 @@ const invalidateQueryClientLicenses = (() => {
export const useLicense = (params?: LicenseParams): UseQueryResult<Serialized<LicenseDataType>> => {
const getLicenses = useEndpoint('GET', '/v1/licenses.info');

const queryClient = useQueryClient();
const invalidateQueries = useInvalidateLicense();

const notify = useSingleStream('notify-all');

useEffect(() => notify('license', () => invalidateQueryClientLicenses(queryClient)), [notify, queryClient]);
useEffect(() => notify('license', () => invalidateQueries()), [notify, invalidateQueries]);

return useQuery(['licenses', 'getLicenses', params?.loadValues], () => getLicenses({ ...params }), {
staleTime: Infinity,
keepPreviousData: true,
select: (data) => data.license,
});
};

export const useInvalidateLicense = () => {
const queryClient = useQueryClient();

return () => invalidateQueryClientLicenses(queryClient);
};
69 changes: 69 additions & 0 deletions apps/meteor/client/hooks/useWorkspaceInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import type { IStats, IWorkspaceInfo, Serialized } from '@rocket.chat/core-typings';
import type { IInstance } from '@rocket.chat/rest-typings';
import { useEndpoint } from '@rocket.chat/ui-contexts';
import { useMutation, useQueries, useQueryClient } from '@tanstack/react-query';

export const useWorkspaceInfo = () => {
const getStatistics = useEndpoint('GET', '/v1/statistics');
const getInstances = useEndpoint('GET', '/v1/instances.get');
const getServerInfo = useEndpoint('GET', '/info');

return useQueries({
queries: [
{
queryKey: ['info', 'serverInfo'],
queryFn: async () => {
const data = await getServerInfo();

if (!('minimumClientVersions' in data)) {
throw new Error('Invalid server info');
}
if (!('info' in data)) {
throw new Error('Invalid server info');
}
if (!('version' in data)) {
throw new Error('Invalid server info');
}

return data as IWorkspaceInfo;
},
staleTime: Infinity,
keepPreviousData: true,
},
{
queryKey: ['info', 'instances'],
queryFn: () => getInstances(),
staleTime: Infinity,
keepPreviousData: true,
select({ instances }: Serialized<{ instances: IInstance[] }>) {
return instances.map((instance) => ({
...instance,
...(instance.instanceRecord && {
instanceRecord: {
...instance.instanceRecord,
_createdAt: new Date(instance.instanceRecord._createdAt),
},
}),
})) as IInstance[];
},
},
{
queryKey: ['info', 'statistics'],
queryFn: () => getStatistics({ refresh: 'true' }),
staleTime: Infinity,
keepPreviousData: true,
select: (data: Serialized<IStats>) => ({
...data,
lastMessageSentAt: data.lastMessageSentAt ? new Date(data.lastMessageSentAt) : undefined,
}),
},
],
});
};

export const useRefreshStatistics = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: () => queryClient.invalidateQueries(['info', 'statistics']),
});
};
12 changes: 12 additions & 0 deletions apps/meteor/client/lib/utils/isOverLicenseLimits.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { LicenseLimitKind } from '@rocket.chat/license';

type Limits = Record<
LicenseLimitKind,
{
max: number;
value?: number;
}
>;

export const isOverLicenseLimits = (limits: Limits): boolean =>
Object.values(limits).some((limit) => limit.value !== undefined && limit.value > limit.max);
13 changes: 0 additions & 13 deletions apps/meteor/client/views/admin/info/Feature.js

This file was deleted.

26 changes: 0 additions & 26 deletions apps/meteor/client/views/admin/info/Feature.stories.tsx

This file was deleted.

Loading

0 comments on commit 5d55a93

Please sign in to comment.