snapshot of https://github.com/RocketChat/Rocket.Chat.git (develop, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s

This commit is contained in:
upstream-mirror
2026-09-16 01:21:02 +05:00
commit 30810eecd7
10161 changed files with 987110 additions and 0 deletions

View File

@@ -0,0 +1,32 @@
import type { ILivechatAgent, ILivechatVisitor, IRoom, IUser } from '@rocket.chat/core-typings';
import { useForm } from 'react-hook-form';
import { createEndOfToday, createStartOfToday } from '../utils/dateRange';
export type AuditFields = {
msg: string;
dateRange: {
start?: Date;
end?: Date;
};
rid: IRoom['_id'];
users: Exclude<IUser['username'], undefined>[];
visitor: ILivechatVisitor['_id'];
agent: ILivechatAgent['_id'];
};
export const useAuditForm = () => {
return useForm<AuditFields>({
defaultValues: {
msg: '',
dateRange: {
start: createStartOfToday(),
end: createEndOfToday(),
},
rid: undefined,
users: [],
visitor: undefined,
agent: undefined,
},
});
};

View File

@@ -0,0 +1,48 @@
import type { IAuditLog, IMessage } from '@rocket.chat/core-typings';
import { useEndpoint } from '@rocket.chat/ui-contexts';
import { useMutation } from '@tanstack/react-query';
import type { AuditFields } from './useAuditForm';
import { mapMessageFromApi } from '../../../lib/utils/mapMessageFromApi';
export const useAuditMutation = (type: IAuditLog['fields']['type']) => {
const getAuditMessages = useEndpoint('POST', '/v1/audit.messages');
const getOmnichannelAuditMessages = useEndpoint('POST', '/v1/audit.omnichannelMessages');
return useMutation({
mutationKey: ['audit'] as const,
mutationFn: async ({ msg, dateRange, rid, users, visitor, agent }: AuditFields): Promise<IMessage[]> => {
const startDate = (dateRange.start ?? new Date(0)).toISOString();
const endDate = (dateRange.end ?? new Date()).toISOString();
if (type === 'l') {
const { messages } = await getOmnichannelAuditMessages({
type,
msg,
startDate,
endDate,
users,
// TODO: the Omnichannel audit form collects visitor/agent (required fields) but they are
// dropped here — carried over from the original DDP flow. Forwarding them would let the
// omnichannel audit filter by the selected visitor/agent. Left for investigation.
visitor: '',
agent: '',
});
return messages.map((message) => mapMessageFromApi(message));
}
const { messages } = await getAuditMessages({
type,
msg,
startDate,
endDate,
rid,
users,
visitor,
agent,
});
return messages.map((message) => mapMessageFromApi(message));
},
});
};

View File

@@ -0,0 +1,27 @@
import type { IAuditLog } from '@rocket.chat/core-typings';
import { useStableCallback } from '@rocket.chat/fuselage-hooks';
import { useRoute, useRouteParameter } from '@rocket.chat/ui-contexts';
import type { SetStateAction } from 'react';
import { useMemo } from 'react';
const typeToTabMap: Record<IAuditLog['fields']['type'], string> = {
'': 'rooms',
'u': 'users',
'd': 'direct',
'l': 'omnichannel',
};
const tabToTabMap = new Map(Object.entries(typeToTabMap).map(([type, tab]) => [tab, type as IAuditLog['fields']['type']]));
export const useAuditTab = () => {
const tab = useRouteParameter('tab');
const type = useMemo(() => tabToTabMap.get(tab ?? 'rooms') ?? '', [tab]);
const auditRoute = useRoute('audit-home');
const setType = useStableCallback((newType: SetStateAction<IAuditLog['fields']['type']>) => {
auditRoute.replace({ tab: typeToTabMap[typeof newType === 'function' ? newType(type) : newType] ?? 'rooms' });
});
return [type, setType] as const;
};

View File

@@ -0,0 +1,13 @@
import { useEndpoint } from '@rocket.chat/ui-contexts';
import { useMutation } from '@tanstack/react-query';
export const useSendTelemetryMutation = () => {
const sendTelemetry = useEndpoint('POST', '/v1/statistics.telemetry');
return useMutation({
mutationFn: sendTelemetry,
onError: (error) => {
console.warn(error);
},
});
};

View File

@@ -0,0 +1,78 @@
import { mockAppRoot } from '@rocket.chat/mock-providers';
import { renderHook, waitFor } from '@testing-library/react';
import { useSettingSelectOptions } from './useSettingSelectOptions';
// TODO: check if the return of items matches the settings we mocked
describe('useSettingSelectOptions', () => {
it('should return the ordered list of options', async () => {
const { result } = renderHook(() => useSettingSelectOptions(), {
wrapper: mockAppRoot()
.withSetting('test1', true)
.withSetting('test2', true)
.withSetting('test3', true)
.withSetting('test4', true)
.withSetting('test5', true)
.withSetting('test6', true)
.withSetting('test7', true)
.withSetting('test8', true)
.withSetting('test9', true)
.withSetting('test10', true)
.withSetting('test11', true)
.withSetting('test12', true)
.withSetting('test13', true)
.withSetting('test14', true)
.withSetting('test15', true)
.build(),
});
await waitFor(() => expect(result.current?.data?.pages[0][0]).toEqual({ _id: 'test1', label: 'test1', value: 'test1' }));
await waitFor(() => expect(result.current?.data?.pages[0][1]).toEqual({ _id: 'test2', label: 'test2', value: 'test2' }));
await waitFor(() => expect(result.current?.data?.pages[0][2]).toEqual({ _id: 'test3', label: 'test3', value: 'test3' }));
await waitFor(() => expect(result.current?.data?.pages[0][3]).toEqual({ _id: 'test4', label: 'test4', value: 'test4' }));
await waitFor(() => expect(result.current?.data?.pages[0][4]).toEqual({ _id: 'test5', label: 'test5', value: 'test5' }));
await waitFor(() => expect(result.current?.data?.pages[0][5]).toEqual({ _id: 'test6', label: 'test6', value: 'test6' }));
await waitFor(() => expect(result.current?.data?.pages[0][6]).toEqual({ _id: 'test7', label: 'test7', value: 'test7' }));
await waitFor(() => expect(result.current?.data?.pages[0][7]).toEqual({ _id: 'test8', label: 'test8', value: 'test8' }));
await waitFor(() => expect(result.current?.data?.pages[0][8]).toEqual({ _id: 'test9', label: 'test9', value: 'test9' }));
await waitFor(() => expect(result.current?.data?.pages[0][9]).toEqual({ _id: 'test10', label: 'test10', value: 'test10' }));
await waitFor(() => expect(result.current?.data?.pages[0][10]).toEqual({ _id: 'test11', label: 'test11', value: 'test11' }));
await waitFor(() => expect(result.current?.data?.pages[0][11]).toEqual({ _id: 'test12', label: 'test12', value: 'test12' }));
await waitFor(() => expect(result.current?.data?.pages[0][12]).toEqual({ _id: 'test13', label: 'test13', value: 'test13' }));
await waitFor(() => expect(result.current?.data?.pages[0][13]).toEqual({ _id: 'test14', label: 'test14', value: 'test14' }));
await waitFor(() => expect(result.current?.data?.pages[0][14]).toEqual({ _id: 'test15', label: 'test15', value: 'test15' }));
await waitFor(() => expect(result.current?.data?.pages[0]).toHaveLength(15));
});
it('should return the list of filtered options', async () => {
const { result } = renderHook(() => useSettingSelectOptions('TeSt1'), {
wrapper: mockAppRoot()
.withSetting('test1', true)
.withSetting('test2', true)
.withSetting('test3', true)
.withSetting('test4', true)
.withSetting('test5', true)
.withSetting('test6', true)
.withSetting('test7', true)
.withSetting('test8', true)
.withSetting('test9', true)
.withSetting('test10', true)
.withSetting('test11', true)
.withSetting('test12', true)
.withSetting('test13', true)
.withSetting('test14', true)
.withSetting('test15', true)
.build(),
});
await waitFor(() => expect(result.current?.data?.pages[0][0]).toEqual({ _id: 'test1', label: 'test1', value: 'test1' }));
await waitFor(() => expect(result.current?.data?.pages[0][1]).toEqual({ _id: 'test10', label: 'test10', value: 'test10' }));
await waitFor(() => expect(result.current?.data?.pages[0][2]).toEqual({ _id: 'test11', label: 'test11', value: 'test11' }));
await waitFor(() => expect(result.current?.data?.pages[0][3]).toEqual({ _id: 'test12', label: 'test12', value: 'test12' }));
await waitFor(() => expect(result.current?.data?.pages[0][4]).toEqual({ _id: 'test13', label: 'test13', value: 'test13' }));
await waitFor(() => expect(result.current?.data?.pages[0][5]).toEqual({ _id: 'test14', label: 'test14', value: 'test14' }));
await waitFor(() => expect(result.current?.data?.pages[0][6]).toEqual({ _id: 'test15', label: 'test15', value: 'test15' }));
await waitFor(() => expect(result.current?.data?.pages[0]).toHaveLength(7));
});
});

View File

@@ -0,0 +1,41 @@
import { useSettings } from '@rocket.chat/ui-contexts';
import { useInfiniteQuery } from '@tanstack/react-query';
import { useCallback } from 'react';
type SettingSelectOption = {
label: string;
value: string;
_id: string;
};
export const useSettingSelectOptions = (filter = '') => {
const settings = useSettings();
const fetchData = useCallback(
async (start = 0): Promise<SettingSelectOption[]> => {
return settings
.map(({ _id }) => ({ label: _id, value: _id, _id }))
.filter(({ label }) => label.toUpperCase().includes(filter.toUpperCase()))
.slice(start, start + 50);
},
[filter, settings],
);
return useInfiniteQuery({
queryKey: ['settings', filter],
queryFn: ({ pageParam }) => fetchData(pageParam),
getNextPageParam: (lastPage, _allPages, lastPageParam) => {
if (lastPage.length === 0) {
return undefined;
}
return lastPageParam + 1;
},
getPreviousPageParam: (_firstPage, _allPages, firstPageParam) => {
if (firstPageParam <= 1) {
return undefined;
}
return firstPageParam - 1;
},
initialPageParam: 0,
});
};