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

161 lines
4.3 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;