diff --git a/apps/meteor/client/views/admin/EditableSettingsContext.spec.tsx b/apps/meteor/client/views/admin/EditableSettingsContext.spec.tsx
new file mode 100644
index 00000000000..8941812d83c
--- /dev/null
+++ b/apps/meteor/client/views/admin/EditableSettingsContext.spec.tsx
@@ -0,0 +1,61 @@
+import { mockAppRoot as _mockAppRoot } from '@rocket.chat/mock-providers';
+import { renderHook } from '@testing-library/react';
+
+import { useEditableSettingVisibilityQuery } from './EditableSettingsContext';
+import EditableSettingsProvider from './settings/EditableSettingsProvider';
+
+const mockAppRoot = () => _mockAppRoot().wrap((children) => {children});
+
+describe('useEditableSettingVisibilityQuery', () => {
+ it('should return true when no query is provided', () => {
+ const { result } = renderHook(() => useEditableSettingVisibilityQuery(), {
+ wrapper: mockAppRoot().build(),
+ });
+
+ expect(result.current).toBe(true);
+ });
+
+ it('should handle settings with a query', () => {
+ const { result } = renderHook(() => useEditableSettingVisibilityQuery({ _id: 'setting1', value: true }), {
+ wrapper: mockAppRoot().withSetting('setting1', true).build(),
+ });
+
+ expect(result.current).toBe(true);
+ });
+
+ it('should handle multiple conditions in enableQuery', () => {
+ const { result } = renderHook(
+ () =>
+ useEditableSettingVisibilityQuery([
+ { _id: 'setting5', value: true },
+ { _id: 'setting6', value: true },
+ ]),
+ {
+ wrapper: mockAppRoot().withSetting('setting5', true).withSetting('setting6', true).build(),
+ },
+ );
+
+ expect(result.current).toBe(true);
+
+ const { result: result2 } = renderHook(
+ () =>
+ useEditableSettingVisibilityQuery([
+ { _id: 'setting5', value: true },
+ { _id: 'setting6', value: true },
+ ]),
+ {
+ wrapper: mockAppRoot().withSetting('setting5', true).withSetting('setting6', false).build(),
+ },
+ );
+
+ expect(result2.current).toBe(false);
+ });
+
+ it('should handle string queries', () => {
+ const { result } = renderHook(() => useEditableSettingVisibilityQuery(JSON.stringify({ _id: 'setting7', value: true })), {
+ wrapper: mockAppRoot().withSetting('setting7', true).build(),
+ });
+
+ expect(result.current).toBe(true);
+ });
+});
diff --git a/apps/meteor/client/views/admin/EditableSettingsContext.ts b/apps/meteor/client/views/admin/EditableSettingsContext.ts
index cbfb86259fe..9d34eaa4341 100644
--- a/apps/meteor/client/views/admin/EditableSettingsContext.ts
+++ b/apps/meteor/client/views/admin/EditableSettingsContext.ts
@@ -1,4 +1,5 @@
import type { ISetting } from '@rocket.chat/core-typings';
+import { createFilterFromQuery } from '@rocket.chat/mongo-adapter';
import { createContext, useContext } from 'react';
import { create, type StoreApi, type UseBoundStore } from 'zustand';
import { useShallow } from 'zustand/shallow';
@@ -21,6 +22,28 @@ export const compareSettings = (a: EditableSetting, b: EditableSetting): number
return i18nLabel;
};
+export const performSettingQuery = (
+ query:
+ | string
+ | {
+ _id: string;
+ value: unknown;
+ }
+ | {
+ _id: string;
+ value: unknown;
+ }[]
+ | undefined,
+ settings: ISetting[],
+) => {
+ if (!query) {
+ return true;
+ }
+
+ const queries = [].concat(typeof query === 'string' ? JSON.parse(query) : query);
+ return queries.every((query) => settings.some(createFilterFromQuery(query)));
+};
+
type EditableSettingsContextQuery =
| {
group: ISetting['_id'];
@@ -125,3 +148,14 @@ export const useEditableSettingsDispatch = (): ((changes: Partial state.mutate);
};
+
+export const useEditableSettingVisibilityQuery = (query?: ISetting['enableQuery'] | ISetting['displayQuery']): boolean => {
+ const { useEditableSettingsStore } = useContext(EditableSettingsContext);
+
+ return useEditableSettingsStore((state) => {
+ if (!query) {
+ return true;
+ }
+ return performSettingQuery(query, state.state);
+ });
+};
diff --git a/apps/meteor/client/views/admin/settings/EditableSettingsProvider.tsx b/apps/meteor/client/views/admin/settings/EditableSettingsProvider.tsx
index 8fd724ee1b3..5124da92d46 100644
--- a/apps/meteor/client/views/admin/settings/EditableSettingsProvider.tsx
+++ b/apps/meteor/client/views/admin/settings/EditableSettingsProvider.tsx
@@ -1,37 +1,14 @@
import type { ISetting } from '@rocket.chat/core-typings';
-import { createFilterFromQuery } from '@rocket.chat/mongo-adapter';
import { useSettings } from '@rocket.chat/ui-contexts';
import type { ReactNode } from 'react';
import { useEffect, useMemo, useState } from 'react';
import { create } from 'zustand';
import type { EditableSetting, IEditableSettingsState } from '../EditableSettingsContext';
-import { EditableSettingsContext } from '../EditableSettingsContext';
+import { EditableSettingsContext, performSettingQuery } from '../EditableSettingsContext';
const defaultOmit: Array = ['Cloud_Workspace_AirGapped_Restrictions_Remaining_Days'];
-const performSettingQuery = (
- query:
- | string
- | {
- _id: string;
- value: unknown;
- }
- | {
- _id: string;
- value: unknown;
- }[]
- | undefined,
- settings: ISetting[],
-) => {
- if (!query) {
- return true;
- }
-
- const queries = [].concat(typeof query === 'string' ? JSON.parse(query) : query);
- return queries.every((query) => settings.some(createFilterFromQuery(query)));
-};
-
type EditableSettingsProviderProps = {
children?: ReactNode;
};
@@ -48,6 +25,8 @@ const EditableSettingsProvider = ({ children }: EditableSettingsProviderProps) =
(persisted): EditableSetting => ({
...persisted,
changed: false,
+ // TODO: This might not be needed anymore due to implementation of useEditableSettingVisibilityQuery
+ // This was left here to avoid unexpected breaking changes
disabled: persisted.blocked || !performSettingQuery(persisted.enableQuery, persistedSettings),
invisible: !performSettingQuery(persisted.displayQuery, persistedSettings),
}),
@@ -62,6 +41,8 @@ const EditableSettingsProvider = ({ children }: EditableSettingsProviderProps) =
...state.find(({ _id }) => _id === persisted._id),
...persisted,
changed: false,
+ // TODO: This might not be needed anymore due to implementation of useEditableSettingVisibilityQuery
+ // This was left here to avoid unexpected breaking changes
disabled: persisted.blocked || !performSettingQuery(persisted.enableQuery, state),
invisible: !performSettingQuery(persisted.displayQuery, state),
}),
@@ -85,8 +66,6 @@ const EditableSettingsProvider = ({ children }: EditableSettingsProviderProps) =
return {
...current,
...change,
- disabled: persisted.blocked || !performSettingQuery(persisted.enableQuery, state),
- invisible: !performSettingQuery(persisted.displayQuery, state),
};
}),
}));
diff --git a/apps/meteor/client/views/admin/settings/Setting/Setting.tsx b/apps/meteor/client/views/admin/settings/Setting/Setting.tsx
index 484eb34cacf..04f4e8cf061 100644
--- a/apps/meteor/client/views/admin/settings/Setting/Setting.tsx
+++ b/apps/meteor/client/views/admin/settings/Setting/Setting.tsx
@@ -10,7 +10,7 @@ import { useTranslation } from 'react-i18next';
import MemoizedSetting from './MemoizedSetting';
import MarkdownText from '../../../../components/MarkdownText';
-import { useEditableSetting, useEditableSettingsDispatch } from '../../EditableSettingsContext';
+import { useEditableSetting, useEditableSettingsDispatch, useEditableSettingVisibilityQuery } from '../../EditableSettingsContext';
import { useHasSettingModule } from '../hooks/useHasSettingModule';
type SettingProps = {
@@ -96,7 +96,10 @@ function Setting({ className = undefined, settingId, sectionChanged }: SettingPr
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [setting.value, (setting as ISettingColor).editor, update, persistedSetting]);
- const { _id, disabled, readonly, type, packageValue, i18nLabel, i18nDescription, alert, invisible } = setting;
+ const { _id, readonly, type, packageValue, i18nLabel, i18nDescription, alert } = setting;
+
+ const disabled = !useEditableSettingVisibilityQuery(persistedSetting.enableQuery);
+ const invisible = !useEditableSettingVisibilityQuery(persistedSetting.displayQuery);
const labelText = (i18n.exists(i18nLabel) && t(i18nLabel)) || (i18n.exists(_id) && t(_id)) || i18nLabel || _id;
@@ -162,7 +165,7 @@ function Setting({ className = undefined, settingId, sectionChanged }: SettingPr
showUpgradeButton={showUpgradeButton}
sectionChanged={sectionChanged}
{...setting}
- disabled={setting.disabled || shouldDisableEnterprise}
+ disabled={disabled || shouldDisableEnterprise}
value={value}
editor={editor}
hasResetButton={hasResetButton}