Skip to content

Commit

Permalink
Merge branch 'develop' into feat/update-contact-endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
tapiarafael committed Sep 2, 2024
2 parents 559340c + 037128c commit d1858ad
Show file tree
Hide file tree
Showing 83 changed files with 7,037 additions and 6,870 deletions.
7 changes: 7 additions & 0 deletions .changeset/brown-singers-appear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@rocket.chat/ui-client': minor
'@rocket.chat/i18n': minor
'@rocket.chat/meteor': minor
---

added `sidepanelNavigation` to feature preview list

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion apps/meteor/client/hooks/useEndpointAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type UseEndpointActionOptions<TPathPattern extends PathPattern> = (undefined ext
export function useEndpointAction<TMethod extends Method, TPathPattern extends PathPattern>(
method: TMethod,
pathPattern: TPathPattern,
options: UseEndpointActionOptions<TPathPattern> = { keys: {} as UrlParams<TPathPattern> },
options: NoInfer<UseEndpointActionOptions<TPathPattern>> = { keys: {} as UrlParams<TPathPattern> },
) {
const sendData = useEndpoint(method, pathPattern, options.keys as UrlParams<TPathPattern>);

Expand Down
4 changes: 2 additions & 2 deletions apps/meteor/client/hooks/useEndpointData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ const deprecationWarning = log('useEndpointData is deprecated, use @tanstack/rea
*/
export const useEndpointData = <TPathPattern extends PathPattern>(
endpoint: TPathPattern,
options: {
options: NoInfer<{
keys?: UrlParams<TPathPattern>;
params?: OperationParams<'GET', TPathPattern>;
initialValue?: Serialized<OperationResult<'GET', TPathPattern>> | (() => Serialized<OperationResult<'GET', TPathPattern>>);
} = {},
}> = {},
): AsyncState<Serialized<OperationResult<'GET', TPathPattern>>> & {
reload: () => void;
} => {
Expand Down
14 changes: 7 additions & 7 deletions apps/meteor/client/lib/createRouteGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type IRouterPaths, type RouteName, type RouterPathPattern } from '@rocket.chat/ui-contexts';
import type { IRouterPaths, RouteName, RouterPathPattern } from '@rocket.chat/ui-contexts';
import React, { type ElementType, type ReactNode } from 'react';

import { router } from '../providers/RouterProvider';
Expand All @@ -9,21 +9,21 @@ type GroupName = 'omnichannel' | 'marketplace' | 'account' | 'admin';

type GroupPrefix<TGroupName extends GroupName> = IRouterPaths[`${TGroupName}-index`]['pattern'];

type RouteNamesOf<TGroupName extends GroupName> = Extract<
type RouteNamesOf<TGroupName extends GroupName> = (
| keyof {
[TRouteName in RouteName as IRouterPaths[TRouteName]['pattern'] extends `${GroupPrefix<TGroupName>}/${string}`
? TRouteName
: never]: never;
}
| `${GroupName}-index`,
RouteName
>;
| `${GroupName}-index`
) &
RouteName;

type TrimPrefix<T extends string, P extends string> = T extends `${P}${infer U}` ? U : T;
type TrimPrefix<T, P extends string> = T extends `${P}${infer U}` ? U : T;

export const createRouteGroup = <TGroupName extends GroupName>(
name: TGroupName,
prefix: GroupPrefix<TGroupName>,
prefix: NoInfer<GroupPrefix<TGroupName>>,
RouterComponent: ElementType<{
children?: ReactNode;
}>,
Expand Down
9 changes: 3 additions & 6 deletions apps/meteor/client/lib/getLocalePercentage.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
export const getLocalePercentage = (locale: string, total: number, fraction: number, decimalCount = 2): string => {
const option = {
export const getLocalePercentage = (locale: string, total: number, fraction: number, decimalCount = 2) =>
new Intl.NumberFormat(locale, {
style: 'percent',
minimumFractionDigits: decimalCount,
maximumFractionDigits: decimalCount,
};

return new Intl.NumberFormat(locale, option).format(fraction / total);
};
}).format(fraction / total);
4 changes: 2 additions & 2 deletions apps/meteor/client/providers/CallProvider/CallProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
} from '@rocket.chat/core-typings';
import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
import { Random } from '@rocket.chat/random';
import type { Device, IExperimentalHTMLAudioElement } from '@rocket.chat/ui-contexts';
import type { Device } from '@rocket.chat/ui-contexts';
import {
useRouter,
useUser,
Expand Down Expand Up @@ -65,7 +65,7 @@ export const CallProvider = ({ children }: CallProviderProps) => {

const hasVoIPEnterpriseLicense = useIsVoipEnterprise();

const remoteAudioMediaRef = useRef<IExperimentalHTMLAudioElement>(null); // TODO: Create a dedicated file for the AUDIO and make the controls accessible
const remoteAudioMediaRef = useRef<HTMLAudioElement>(null); // TODO: Create a dedicated file for the AUDIO and make the controls accessible

const [queueCounter, setQueueCounter] = useState(0);
const [queueName, setQueueName] = useState('');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
import type { Device, IExperimentalHTMLAudioElement, DeviceContextValue } from '@rocket.chat/ui-contexts';
import type { Device, DeviceContextValue } from '@rocket.chat/ui-contexts';
import { DeviceContext } from '@rocket.chat/ui-contexts';
import type { ReactElement, ReactNode } from 'react';
import React, { useEffect, useState, useMemo } from 'react';
Expand Down Expand Up @@ -33,7 +33,7 @@ export const DeviceProvider = ({ children }: DeviceProviderProps): ReactElement
};

const setAudioOutputDevice = useMutableCallback(
({ outputDevice, HTMLAudioElement }: { outputDevice: Device; HTMLAudioElement: IExperimentalHTMLAudioElement }): void => {
({ outputDevice, HTMLAudioElement }: { outputDevice: Device; HTMLAudioElement: HTMLAudioElement }): void => {
if (!isSetSinkIdAvailable()) {
throw new Error('setSinkId is not available in this browser');
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import type { IExperimentalHTMLAudioElement } from '@rocket.chat/ui-contexts';

export const isSetSinkIdAvailable = (): boolean => {
const audio = new Audio() as IExperimentalHTMLAudioElement;
const audio = new Audio();
return !!audio.setSinkId;
};
2 changes: 1 addition & 1 deletion apps/meteor/client/providers/TranslationProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ const useI18next = (lng: string): typeof i18next => {
loadPath: 'i18n/{{lng}}.json',
parse: (data: string, _lngs?: string | string[], namespaces: string | string[] = []) =>
extractTranslationKeys(JSON.parse(data), namespaces),
request: (_options, url, _payload, callback) => {
request: (_options: unknown, url: string, _payload: unknown, callback: (error: unknown, data: unknown) => void) => {
const params = url.split('/');

const lng = params[params.length - 1];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,21 @@ import { useForm } from 'react-hook-form';

import { Page, PageHeader, PageScrollableContentWithShadow, PageFooter } from '../../../components/Page';

const handleEnableQuery = (features: FeaturePreviewProps[]) => {
return features.map((item) => {
if (item.enableQuery) {
const expected = item.enableQuery.value;
const received = features.find((el) => el.name === item.enableQuery?.name)?.value;
if (expected !== received) {
item.disabled = true;
item.value = false;
} else {
item.disabled = false;
}
}
return item;
});
};
const AccountFeaturePreviewPage = () => {
const t = useTranslation();
const dispatchToastMessage = useToastMessageDispatch();
Expand Down Expand Up @@ -71,7 +86,7 @@ const AccountFeaturePreviewPage = () => {
};

const grouppedFeaturesPreview = Object.entries(
featuresPreview.reduce((result, currentValue) => {
handleEnableQuery(featuresPreview).reduce((result, currentValue) => {
(result[currentValue.group] = result[currentValue.group] || []).push(currentValue);
return result;
}, {} as Record<FeaturePreviewProps['group'], FeaturePreviewProps[]>),
Expand Down Expand Up @@ -108,7 +123,13 @@ const AccountFeaturePreviewPage = () => {
<Field>
<FieldRow>
<FieldLabel htmlFor={feature.name}>{t(feature.i18n)}</FieldLabel>
<ToggleSwitch id={feature.name} checked={feature.value} name={feature.name} onChange={handleFeatures} />
<ToggleSwitch
id={feature.name}
checked={feature.value}
name={feature.name}
onChange={handleFeatures}
disabled={feature.disabled}
/>
</FieldRow>
{feature.description && <FieldHint mbs={12}>{t(feature.description)}</FieldHint>}
</Field>
Expand Down
15 changes: 8 additions & 7 deletions apps/meteor/client/views/admin/viewLogs/ansispan.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-control-regex */
const foregroundColors = {
30: 'var(--rcx-color-font-secondary-info, #6C727A)',
31: 'var(--rcx-color-font-danger, #D40C26)',
Expand All @@ -16,13 +17,13 @@ export const ansispan = (str: string): string => {
.replace(/>/g, '&gt;')
.replace(/</g, '&lt;')
.replace(/(.\d{8}-\d\d:\d\d:\d\d\.\d\d\d\(?.{0,2}\)?)/, '<span>$1</span>')
.replace(/\033\[1m/g, '<strong>')
.replace(/\033\[22m/g, '</strong>')
.replace(/\033\[3m/g, '<em>')
.replace(/\033\[23m/g, '</em>')
.replace(/\033\[m/g, '</span>')
.replace(/\033\[0m/g, '</span>')
.replace(/\033\[39m/g, '</span>');
.replace(/\x1b\[1m/g, '<strong>')
.replace(/\x1b\[22m/g, '</strong>')
.replace(/\x1b\[3m/g, '<em>')
.replace(/\x1b\[23m/g, '</em>')
.replace(/\x1b\[m/g, '</span>')
.replace(/\x1b\[0m/g, '</span>')
.replace(/\x1b\[39m/g, '</span>');
return Object.entries(foregroundColors).reduce((str, [ansiCode, color]) => {
const span = `<span style="color: ${color}">`;
return str.replace(new RegExp(`\\033\\[${ansiCode}m`, 'g'), span).replace(new RegExp(`\\033\\[0;${ansiCode}m`, 'g'), span);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ export const Default: ComponentStory<typeof CounterContainer> = (args) => <Count
Default.storyName = 'CounterContainer';
Default.args = {
initialData: [
{ title: 'total conversations', value: 10 },
{ title: 'open conversations', value: 10 },
{ title: 'total messages', value: 10 },
{ title: 'total visitors' },
{ title: 'Total_conversations', value: 10 },
{ title: 'Open_conversations', value: 10 },
{ title: 'Total_messages', value: 10 },
{ title: 'Total_visitors', value: 0 },
],
data: [],
data: { totalizers: [] },
};
Original file line number Diff line number Diff line change
@@ -1,15 +1,31 @@
import { Skeleton } from '@rocket.chat/fuselage';
import type { TranslationKey } from '@rocket.chat/ui-contexts';
import { useTranslation } from '@rocket.chat/ui-contexts';
import React, { useEffect, useState } from 'react';

import { AsyncStatePhase } from '../../../../hooks/useAsyncState';
import CounterItem from './CounterItem';
import CounterRow from './CounterRow';

const CounterContainer = ({ data, state, initialData, ...props }) => {
export type DataType = {
title: string;
value: number | string;
}[];

type Totalizers = {
totalizers: DataType;
};

type CounterContainerProps = {
data?: Totalizers;
state: AsyncStatePhase;
initialData: DataType;
};

const CounterContainer = ({ data, state, initialData, ...props }: CounterContainerProps) => {
const t = useTranslation();

const [displayData, setDisplayData] = useState(initialData);
const [displayData, setDisplayData] = useState<DataType>(initialData);

const { totalizers } = data || { totalizers: initialData };

Expand All @@ -22,7 +38,7 @@ const CounterContainer = ({ data, state, initialData, ...props }) => {
return (
<CounterRow {...props}>
{displayData.map(({ title, value }, i) => (
<CounterItem key={i} title={title ? t(title) : <Skeleton width='x60' />} count={value} />
<CounterItem key={i} title={title ? t(title as TranslationKey) : <Skeleton width='x60' />} count={value} />
))}
</CounterRow>
);
Expand Down
87 changes: 87 additions & 0 deletions apps/meteor/client/views/room/hooks/useRetentionPolicy.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { mockAppRoot } from '@rocket.chat/mock-providers';
import { renderHook } from '@testing-library/react';

import { createFakeRoom } from '../../../../tests/mocks/data';
import { useRetentionPolicy } from './useRetentionPolicy';

const getGlobalSettings = ({
enabled = false,
filesOnly = false,
doNotPrunePinned = false,
ignoreThreads = false,
appliesToChannels = false,
appliesToGroups = false,
appliesToDMs = false,
}) => {
return mockAppRoot()
.withSetting('RetentionPolicy_Enabled', enabled)
.withSetting('RetentionPolicy_FilesOnly', filesOnly)
.withSetting('RetentionPolicy_DoNotPrunePinned', doNotPrunePinned)
.withSetting('RetentionPolicy_DoNotPruneThreads', ignoreThreads)
.withSetting('RetentionPolicy_AppliesToChannels', appliesToChannels)
.withSetting('RetentionPolicy_AppliesToGroups', appliesToGroups)
.withSetting('RetentionPolicy_AppliesToDMs', appliesToDMs);
};

const defaultValue = {
enabled: false,
isActive: false,
filesOnly: false,
excludePinned: false,
ignoreThreads: false,
};

const roomTypeConfig = {
c: { appliesToChannels: true },
p: { appliesToGroups: true },
d: { appliesToDMs: true },
};

const CHANNELS_TYPE = 'c';

it('should return the default value if global retention is not enabled', async () => {
const fakeRoom = createFakeRoom({ t: CHANNELS_TYPE });

const { result } = renderHook(() => useRetentionPolicy(fakeRoom), {
legacyRoot: true,
wrapper: getGlobalSettings({}).build(),
});

expect(result.current).toEqual(expect.objectContaining(defaultValue));
});

it('should return enabled true if global retention is enabled', async () => {
const fakeRoom = createFakeRoom({ t: CHANNELS_TYPE });

const { result } = renderHook(() => useRetentionPolicy(fakeRoom), {
legacyRoot: true,
wrapper: getGlobalSettings({ enabled: true }).build(),
});

expect(result.current).toEqual(expect.objectContaining({ ...defaultValue, enabled: true }));
});

it('should return enabled and active true global retention is active for rooms of the type', async () => {
const fakeRoom = createFakeRoom({ t: CHANNELS_TYPE });

const { result } = renderHook(() => useRetentionPolicy(fakeRoom), {
legacyRoot: true,
wrapper: getGlobalSettings({ enabled: true, ...roomTypeConfig[CHANNELS_TYPE] }).build(),
});

expect(result.current).toEqual(expect.objectContaining({ ...defaultValue, enabled: true, isActive: true }));
});

it.failing(
'should isActive be false if global retention is active for rooms of the type and room has retention.enabled false',
async () => {
const fakeRoom = createFakeRoom({ t: CHANNELS_TYPE, retention: { enabled: false } });

const { result } = renderHook(() => useRetentionPolicy(fakeRoom), {
legacyRoot: true,
wrapper: getGlobalSettings({ enabled: true, ...roomTypeConfig[CHANNELS_TYPE] }).build(),
});

expect(result.current?.isActive).toBe(false);
},
);
2 changes: 1 addition & 1 deletion apps/meteor/ee/server/services/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
"pino-pretty": "^7.6.1",
"pm2": "^5.2.0",
"ts-node": "^10.9.1",
"typescript": "~5.3.3"
"typescript": "~5.5.4"
},
"volta": {
"extends": "../../../package.json"
Expand Down
4 changes: 2 additions & 2 deletions apps/meteor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@
"supports-color": "~7.2.0",
"template-file": "^6.0.1",
"ts-node": "^10.9.1",
"typescript": "~5.3.3"
"typescript": "~5.5.4"
},
"dependencies": {
"@babel/runtime": "~7.22.15",
Expand Down Expand Up @@ -430,7 +430,7 @@
"turndown": "^7.1.2",
"twilio": "^3.76.1",
"twit": "^2.2.11",
"typia": "^5.3.3",
"typia": "~6.9.0",
"ua-parser-js": "^1.0.37",
"underscore": "^1.13.6",
"universal-perf-hooks": "^1.0.1",
Expand Down
4 changes: 3 additions & 1 deletion apps/meteor/server/services/federation/Federation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ const allowedActionsInFederatedRooms: ValueOf<typeof RoomMemberActions>[] = [
RoomMemberActions.LEAVE,
];

const allowedActionsForModerators = allowedActionsInFederatedRooms.filter((action) => action !== RoomMemberActions.SET_AS_OWNER);
const allowedActionsForModerators: ValueOf<typeof RoomMemberActions>[] = allowedActionsInFederatedRooms.filter(
(action) => action !== RoomMemberActions.SET_AS_OWNER,
);

const allowedRoomSettingsChangesInFederatedRooms: ValueOf<typeof RoomSettingsEnum>[] = [RoomSettingsEnum.NAME, RoomSettingsEnum.TOPIC];

Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/tests/mocks/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export function createFakeUser(overrides?: Partial<IUser>): IUser {
};
}

export const createFakeRoom = (overrides?: Partial<IRoom>): IRoom => ({
export const createFakeRoom = (overrides?: Partial<IRoom & { retention?: { enabled: boolean } }>): IRoom => ({
_id: faker.database.mongodbObjectId(),
_updatedAt: faker.date.recent(),
t: faker.helpers.arrayElement(['c', 'p', 'd']),
Expand Down
Loading

0 comments on commit d1858ad

Please sign in to comment.