The communications platform that puts data protection first.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
Rocket.Chat/client/providers/EditableSettingsProvider.tsx

145 lines
4.1 KiB

import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
import { Mongo } from 'meteor/mongo';
import { Tracker } from 'meteor/tracker';
import React, { useEffect, useMemo, FunctionComponent, useRef, MutableRefObject } from 'react';
import { SettingId, GroupId } from '../../definition/ISetting';
import { EditableSettingsContext, IEditableSetting, EditableSettingsContextValue } from '../contexts/EditableSettingsContext';
import { useSettings, SettingsContextQuery } from '../contexts/SettingsContext';
import { createReactiveSubscriptionFactory } from './createReactiveSubscriptionFactory';
const defaultQuery: SettingsContextQuery = {};
type EditableSettingsProviderProps = {
readonly query: SettingsContextQuery;
};
const EditableSettingsProvider: FunctionComponent<EditableSettingsProviderProps> = ({
children,
query = defaultQuery,
}) => {
const settingsCollectionRef = useRef<Mongo.Collection<IEditableSetting>>(null) as MutableRefObject<Mongo.Collection<IEditableSetting>>;
const persistedSettings = useSettings(query);
const getSettingsCollection = useMutableCallback(() => {
if (!settingsCollectionRef.current) {
settingsCollectionRef.current = new Mongo.Collection<any>(null);
}
return settingsCollectionRef.current;
}) as () => Mongo.Collection<IEditableSetting>;
useEffect(() => {
const settingsCollection = getSettingsCollection();
settingsCollection.remove({ _id: { $nin: persistedSettings.map(({ _id }) => _id) } });
for (const { _id, ...fields } of persistedSettings) {
settingsCollection.upsert(_id, { $set: { ...fields }, $unset: { changed: true } });
}
}, [getSettingsCollection, persistedSettings]);
const queryEditableSetting = useMemo(
() => createReactiveSubscriptionFactory(
(_id: SettingId): IEditableSetting | undefined => {
const settingsCollection = getSettingsCollection();
const editableSetting = settingsCollection.findOne(_id);
if (!editableSetting) {
return undefined;
}
if (editableSetting.blocked) {
return { ...editableSetting, disabled: true };
}
if (!editableSetting.enableQuery) {
return { ...editableSetting, disabled: false };
}
const queries = [].concat(typeof editableSetting.enableQuery === 'string'
? JSON.parse(editableSetting.enableQuery)
: editableSetting.enableQuery);
return {
...editableSetting,
disabled: !queries.every((query) => settingsCollection.find(query).count() > 0),
};
},
),
[getSettingsCollection],
);
const queryEditableSettings = useMemo(
() => createReactiveSubscriptionFactory(
(query = {}) => getSettingsCollection().find({
...('_id' in query) && { _id: { $in: query._id } },
...('group' in query) && { group: query.group },
...('section' in query) && (
query.section
? { section: query.section }
: {
$or: [
{ section: { $exists: false } },
{ section: '' },
],
}
),
...('changed' in query) && { changed: query.changed },
}, {
sort: {
section: 1,
sorter: 1,
i18nLabel: 1,
},
}).fetch(),
),
[getSettingsCollection],
);
const queryGroupSections = useMemo(
() => createReactiveSubscriptionFactory(
(_id: GroupId) => Array.from(new Set(
getSettingsCollection().find({
group: _id,
}, {
fields: {
section: 1,
},
sort: {
section: 1,
sorter: 1,
i18nLabel: 1,
},
}).fetch().map(({ section }) => section || ''),
)),
),
[getSettingsCollection],
);
const dispatch = useMutableCallback((changes: Partial<IEditableSetting>[]): void => {
for (const { _id, ...data } of changes) {
if (!_id) {
continue;
}
getSettingsCollection().update(_id, { $set: data });
}
Tracker.flush();
});
const contextValue = useMemo<EditableSettingsContextValue>(() => ({
queryEditableSetting,
queryEditableSettings,
queryGroupSections,
dispatch,
}), [
queryEditableSetting,
queryEditableSettings,
queryGroupSections,
dispatch,
]);
return <EditableSettingsContext.Provider children={children} value={contextValue} />;
};
export default EditableSettingsProvider;