Code enhancements to feature - Sysadmin manage user settings (#27636)

* A bunch of refactoring to simplify things

* Unifged getUnreadScrollPositionPreference selector

* Unifed a selector

* Unifed a selector

* Renaming currentUserId to userId

* Renaming currentUserId to userId

* Fixed a typo
Этот коммит содержится в:
Harshil Sharma
2024-07-16 19:55:08 +05:30
коммит произвёл GitHub
родитель 80aaeb9d03
Коммит 4a48a6f020
23 изменённых файлов: 125 добавлений и 181 удалений

Просмотреть файл

@@ -6,7 +6,7 @@ import React, {useCallback, useState} from 'react';
import ConfirmModal from 'components/confirm_modal';
type Props = Omit<React.ComponentProps<typeof ConfirmModal>, 'show'> & {
onExited?: () => void;
onExited: () => void;
};
export default function ConfirmModalRedux(props: Props) {

Просмотреть файл

@@ -10,7 +10,6 @@ import {updateUserActive, revokeAllSessionsForUser} from 'mattermost-redux/actio
import {getConfig} from 'mattermost-redux/selectors/entities/general';
import {
get,
getFromPreferences, getUnreadScrollPositionFromPreference,
getUnreadScrollPositionPreference,
makeGetCategory, makeGetUserCategory,
syncedDraftsAreAllowed,
@@ -25,7 +24,7 @@ import type {OwnProps} from './user_settings_advanced';
import AdvancedSettingsDisplay from './user_settings_advanced';
function makeMapStateToProps(state: GlobalState, props: OwnProps) {
const getAdvancedSettingsCategory = props.adminMode ? makeGetUserCategory(props.currentUser.id) : makeGetCategory();
const getAdvancedSettingsCategory = props.adminMode ? makeGetUserCategory(props.user.id) : makeGetCategory();
return (state: GlobalState, props: OwnProps) => {
const config = getConfig(state);
@@ -34,22 +33,17 @@ function makeMapStateToProps(state: GlobalState, props: OwnProps) {
const enableUserDeactivation = config.EnableUserDeactivation === 'true';
const enableJoinLeaveMessage = config.EnableJoinLeaveMessageByDefault === 'true';
let getPreference = (prefCategory: string, prefName: string, defaultValue: string) => get(state, prefCategory, prefName, defaultValue);
if (props.adminMode && props.userPreferences) {
// This ties the function to the current value of userPreferences for the current execution of this function
const preferences = props.userPreferences;
getPreference = (prefCategory, prefName, defaultValue) => getFromPreferences(preferences, prefCategory, prefName, defaultValue);
}
const userPreferences = props.adminMode && props.userPreferences ? props.userPreferences : undefined;
return {
advancedSettingsCategory: getAdvancedSettingsCategory(state, Preferences.CATEGORY_ADVANCED_SETTINGS),
sendOnCtrlEnter: getPreference(Preferences.CATEGORY_ADVANCED_SETTINGS, 'send_on_ctrl_enter', 'false'),
codeBlockOnCtrlEnter: getPreference(Preferences.CATEGORY_ADVANCED_SETTINGS, 'code_block_ctrl_enter', 'true'),
formatting: getPreference(Preferences.CATEGORY_ADVANCED_SETTINGS, 'formatting', 'true'),
joinLeave: getPreference(Preferences.CATEGORY_ADVANCED_SETTINGS, 'join_leave', enableJoinLeaveMessage.toString()),
syncDrafts: getPreference(Preferences.CATEGORY_ADVANCED_SETTINGS, 'sync_drafts', 'true'),
currentUser: props.adminMode && props.currentUser ? props.currentUser : getCurrentUser(state),
unreadScrollPosition: props.adminMode && props.userPreferences ? getUnreadScrollPositionFromPreference(props.userPreferences) : getUnreadScrollPositionPreference(state),
sendOnCtrlEnter: get(state, Preferences.CATEGORY_ADVANCED_SETTINGS, 'send_on_ctrl_enter', 'false', userPreferences),
codeBlockOnCtrlEnter: get(state, Preferences.CATEGORY_ADVANCED_SETTINGS, 'code_block_ctrl_enter', 'true', userPreferences),
formatting: get(state, Preferences.CATEGORY_ADVANCED_SETTINGS, 'formatting', 'true', userPreferences),
joinLeave: get(state, Preferences.CATEGORY_ADVANCED_SETTINGS, 'join_leave', enableJoinLeaveMessage.toString(), userPreferences),
syncDrafts: get(state, Preferences.CATEGORY_ADVANCED_SETTINGS, 'sync_drafts', 'true', userPreferences),
user: props.adminMode && props.user ? props.user : getCurrentUser(state),
unreadScrollPosition: getUnreadScrollPositionPreference(state, userPreferences),
enablePreviewFeatures,
enableUserDeactivation,
syncedDraftsAreAllowed: syncedDraftsAreAllowed(state),

Просмотреть файл

@@ -8,7 +8,7 @@ import type {Dispatch} from 'redux';
import {savePreferences} from 'mattermost-redux/actions/preferences';
import {Preferences} from 'mattermost-redux/constants';
import {getConfig} from 'mattermost-redux/selectors/entities/general';
import {get as getPreference, getFromPreferences} from 'mattermost-redux/selectors/entities/preferences';
import {get} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
import type {GlobalState} from 'types/store';
@@ -19,27 +19,11 @@ import JoinLeaveSection from './join_leave_section';
export function mapStateToProps(state: GlobalState, props: OwnProps) {
const config = getConfig(state);
const enableJoinLeaveMessage = config.EnableJoinLeaveMessageByDefault === 'true';
let joinLeave: string;
if (props.adminMode && props.userPreferences) {
joinLeave = getFromPreferences(
props.userPreferences,
Preferences.CATEGORY_ADVANCED_SETTINGS,
Preferences.ADVANCED_FILTER_JOIN_LEAVE,
enableJoinLeaveMessage.toString(),
);
} else {
joinLeave = getPreference(
state,
Preferences.CATEGORY_ADVANCED_SETTINGS,
Preferences.ADVANCED_FILTER_JOIN_LEAVE,
enableJoinLeaveMessage.toString(),
);
}
const userPreference = props.adminMode && props.userPreferences ? props.userPreferences : undefined;
return {
currentUserId: props.adminMode ? props.currentUserId : getCurrentUserId(state),
joinLeave,
userId: props.adminMode ? props.userId : getCurrentUserId(state),
joinLeave: get(state, Preferences.CATEGORY_ADVANCED_SETTINGS, Preferences.ADVANCED_FILTER_JOIN_LEAVE, enableJoinLeaveMessage.toString(), userPreference),
};
}

Просмотреть файл

@@ -20,7 +20,7 @@ describe('components/user_settings/advanced/JoinLeaveSection', () => {
const defaultProps = {
active: false,
areAllSectionsInactive: false,
currentUserId: 'current_user_id',
userId: 'current_user_id',
joinLeave: 'true',
onUpdateSection: jest.fn(),
renderOnOffLabel: jest.fn(),
@@ -149,7 +149,7 @@ describe('mapStateToProps', () => {
} as unknown as GlobalState;
test('configuration default to true', () => {
const props = mapStateToProps(initialState, {adminMode: false, currentUserId: ''});
const props = mapStateToProps(initialState, {adminMode: false, userId: ''});
expect(props.joinLeave).toEqual('true');
});
@@ -163,7 +163,7 @@ describe('mapStateToProps', () => {
},
},
});
const props = mapStateToProps(testState, {currentUserId: '', adminMode: false});
const props = mapStateToProps(testState, {userId: '', adminMode: false});
expect(props.joinLeave).toEqual('false');
});
@@ -186,7 +186,7 @@ describe('mapStateToProps', () => {
},
},
});
const props = mapStateToProps(testState, {adminMode: false, currentUserId: ''});
const props = mapStateToProps(testState, {adminMode: false, userId: ''});
expect(props.joinLeave).toEqual('true');
});
@@ -204,7 +204,7 @@ describe('mapStateToProps', () => {
},
},
});
const props = mapStateToProps(testState, {adminMode: false, currentUserId: ''});
const props = mapStateToProps(testState, {adminMode: false, userId: ''});
expect(props.joinLeave).toEqual('false');
});
@@ -229,14 +229,14 @@ describe('mapStateToProps', () => {
};
const propsWithAdminMode = mapStateToProps(testState, {
currentUserId: 'user_1',
userId: 'user_1',
adminMode: true,
userPreferences,
});
expect(propsWithAdminMode.joinLeave).toEqual('true');
const propsWithoutAdminMode = mapStateToProps(testState, {
currentUserId: 'user_1',
userId: 'user_1',
adminMode: false,
userPreferences,
});

Просмотреть файл

@@ -18,7 +18,7 @@ import {a11yFocus} from 'utils/utils';
export type OwnProps = {
adminMode?: boolean;
currentUserId: string;
userId: string;
userPreferences?: PreferencesType;
}
@@ -78,9 +78,9 @@ export default class JoinLeaveSection extends React.PureComponent<Props, State>
};
public handleSubmit = (): void => {
const {actions, currentUserId, onUpdateSection} = this.props;
const joinLeavePreference = {category: Preferences.CATEGORY_ADVANCED_SETTINGS, user_id: currentUserId, name: Preferences.ADVANCED_FILTER_JOIN_LEAVE, value: this.state.joinLeaveState};
actions.savePreferences(currentUserId, [joinLeavePreference]);
const {actions, userId, onUpdateSection} = this.props;
const joinLeavePreference = {category: Preferences.CATEGORY_ADVANCED_SETTINGS, user_id: userId, name: Preferences.ADVANCED_FILTER_JOIN_LEAVE, value: this.state.joinLeaveState};
actions.savePreferences(userId, [joinLeavePreference]);
onUpdateSection();
};

Просмотреть файл

@@ -7,7 +7,7 @@ import type {ConnectedProps} from 'react-redux';
import {savePreferences} from 'mattermost-redux/actions/preferences';
import {Preferences} from 'mattermost-redux/constants';
import {isPerformanceDebuggingEnabled} from 'mattermost-redux/selectors/entities/general';
import {getBool, getBoolFromPreferences, getUserPreferences} from 'mattermost-redux/selectors/entities/preferences';
import {getBool, getUserPreferences} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
import type {GlobalState} from 'types/store';
@@ -16,17 +16,13 @@ import type {OwnProps} from './performance_debugging_section';
import PerformanceDebuggingSection from './performance_debugging_section';
function mapStateToProps(state: GlobalState, props: OwnProps) {
let getPreference = (prefCategory: string, prefName: string) => getBool(state, prefCategory, prefName);
if (props.adminMode && props.currentUserId) {
const userPreferences = getUserPreferences(state, props.currentUserId);
getPreference = (prefCategory: string, prefName: string) => getBoolFromPreferences(userPreferences, prefCategory, prefName);
}
const userPreferences = props.adminMode && props.userId ? getUserPreferences(state, props.userId) : undefined;
return {
currentUserId: props.adminMode ? props.currentUserId : getCurrentUserId(state),
disableClientPlugins: getPreference(Preferences.CATEGORY_PERFORMANCE_DEBUGGING, Preferences.NAME_DISABLE_CLIENT_PLUGINS),
disableTelemetry: getPreference(Preferences.CATEGORY_PERFORMANCE_DEBUGGING, Preferences.NAME_DISABLE_TELEMETRY),
disableTypingMessages: getPreference(Preferences.CATEGORY_PERFORMANCE_DEBUGGING, Preferences.NAME_DISABLE_TYPING_MESSAGES),
userId: props.adminMode ? props.userId : getCurrentUserId(state),
disableClientPlugins: getBool(state, Preferences.CATEGORY_PERFORMANCE_DEBUGGING, Preferences.NAME_DISABLE_CLIENT_PLUGINS, undefined, userPreferences),
disableTelemetry: getBool(state, Preferences.CATEGORY_PERFORMANCE_DEBUGGING, Preferences.NAME_DISABLE_TELEMETRY, undefined, userPreferences),
disableTypingMessages: getBool(state, Preferences.CATEGORY_PERFORMANCE_DEBUGGING, Preferences.NAME_DISABLE_TYPING_MESSAGES, undefined, userPreferences),
performanceDebuggingEnabled: isPerformanceDebuggingEnabled(state),
};

Просмотреть файл

@@ -16,7 +16,7 @@ import type {PropsFromRedux} from './index';
export type OwnProps = {
adminMode?: boolean;
currentUserId?: string;
userId: string;
}
type Props = PropsFromRedux & OwnProps & {
@@ -116,7 +116,7 @@ function PerformanceDebuggingSectionExpanded(props: Props) {
const [disableTypingMessages, setDisableTypingMessages] = useState(props.disableTypingMessages);
const handleSubmit = useCallback(() => {
if (!props.currentUserId) {
if (!props.userId) {
return;
}
@@ -124,7 +124,7 @@ function PerformanceDebuggingSectionExpanded(props: Props) {
if (disableClientPlugins !== props.disableClientPlugins) {
preferences.push({
user_id: props.currentUserId,
user_id: props.userId,
category: Preferences.CATEGORY_PERFORMANCE_DEBUGGING,
name: Preferences.NAME_DISABLE_CLIENT_PLUGINS,
value: disableClientPlugins.toString(),
@@ -132,7 +132,7 @@ function PerformanceDebuggingSectionExpanded(props: Props) {
}
if (disableTelemetry !== props.disableTelemetry) {
preferences.push({
user_id: props.currentUserId,
user_id: props.userId,
category: Preferences.CATEGORY_PERFORMANCE_DEBUGGING,
name: Preferences.NAME_DISABLE_TELEMETRY,
value: disableTelemetry.toString(),
@@ -140,20 +140,20 @@ function PerformanceDebuggingSectionExpanded(props: Props) {
}
if (disableTypingMessages !== props.disableTypingMessages) {
preferences.push({
user_id: props.currentUserId,
user_id: props.userId,
category: Preferences.CATEGORY_PERFORMANCE_DEBUGGING,
name: Preferences.NAME_DISABLE_TYPING_MESSAGES,
value: disableTypingMessages.toString(),
});
}
if (preferences.length !== 0 && props.currentUserId) {
props.savePreferences(props.currentUserId, preferences);
if (preferences.length !== 0 && props.userId) {
props.savePreferences(props.userId, preferences);
}
props.onUpdateSection('');
}, [
props.currentUserId,
props.userId,
props.onUpdateSection,
props.savePreferences,
disableClientPlugins,

Просмотреть файл

@@ -27,7 +27,7 @@ describe('components/user_settings/display/UserSettingsDisplay', () => {
});
const requiredProps: ComponentProps<typeof AdvancedSettingsDisplay> = {
currentUser: user,
user,
updateSection: jest.fn(),
activeSection: '',
closeModal: jest.fn(),
@@ -78,7 +78,7 @@ describe('components/user_settings/display/UserSettingsDisplay', () => {
wrapper.instance().handleDeactivateAccountSubmit();
expect(updateUserActive).toHaveBeenCalled();
expect(updateUserActive).toHaveBeenCalledWith(requiredProps.currentUser.id, false);
expect(updateUserActive).toHaveBeenCalledWith(requiredProps.user.id, false);
});
test('handleDeactivateAccountSubmit() should have called revokeAllSessions', () => {
@@ -86,7 +86,7 @@ describe('components/user_settings/display/UserSettingsDisplay', () => {
wrapper.instance().handleDeactivateAccountSubmit();
expect(requiredProps.actions.revokeAllSessionsForUser).toHaveBeenCalled();
expect(requiredProps.actions.revokeAllSessionsForUser).toHaveBeenCalledWith(requiredProps.currentUser.id);
expect(requiredProps.actions.revokeAllSessionsForUser).toHaveBeenCalledWith(requiredProps.user.id);
});
test('handleDeactivateAccountSubmit() should have updated state.serverError', async () => {

Просмотреть файл

@@ -42,7 +42,7 @@ type Settings = {
export type OwnProps = {
adminMode?: boolean;
currentUser: UserProfile;
user: UserProfile;
userPreferences?: PreferencesType;
}
@@ -166,13 +166,13 @@ export default class AdvancedSettingsDisplay extends React.PureComponent<Props,
};
handleSubmit = async (settings: string[]): Promise<void> => {
if (!this.props.currentUser) {
if (!this.props.user) {
return;
}
const preferences: PreferenceType[] = [];
const {actions, currentUser} = this.props;
const userId = currentUser.id;
const {actions, user} = this.props;
const userId = user.id;
// this should be refactored so we can actually be certain about what type everything is
(Array.isArray(settings) ? settings : [settings]).forEach((setting) => {
@@ -191,7 +191,7 @@ export default class AdvancedSettingsDisplay extends React.PureComponent<Props,
};
handleDeactivateAccountSubmit = async (): Promise<void> => {
const userId = this.props.currentUser.id;
const userId = this.props.user.id;
this.setState({isSaving: true});
@@ -803,9 +803,8 @@ export default class AdvancedSettingsDisplay extends React.PureComponent<Props,
let deactivateAccountSection: ReactNode = '';
let makeConfirmationModal: ReactNode = '';
const currentUser = this.props.currentUser;
if (currentUser.auth_service === '' && this.props.enableUserDeactivation && !this.props.adminMode) {
if (this.props.user.auth_service === '' && this.props.enableUserDeactivation && !this.props.adminMode) {
const active = this.props.activeSection === 'deactivateAccount';
let max = null;
if (active) {
@@ -939,7 +938,7 @@ export default class AdvancedSettingsDisplay extends React.PureComponent<Props,
renderOnOffLabel={this.renderOnOffLabel}
adminMode={this.props.adminMode}
userPreferences={this.props.userPreferences}
currentUserId={this.props.currentUser.id}
userId={this.props.user.id}
/>
{previewFeaturesSectionDivider}
{previewFeaturesSection}
@@ -948,7 +947,7 @@ export default class AdvancedSettingsDisplay extends React.PureComponent<Props,
onUpdateSection={this.handleUpdateSection}
areAllSectionsInactive={this.props.activeSection === ''}
adminMode={this.props.adminMode}
currentUserId={this.props.currentUser.id}
userId={this.props.user.id}
/>
{unreadScrollPositionSectionDivider}
{unreadScrollPositionSection}

Просмотреть файл

@@ -16,7 +16,6 @@ import {
get,
isCollapsedThreadsAllowed,
getCollapsedThreadsPreference,
getFromPreferences,
} from 'mattermost-redux/selectors/entities/preferences';
import {
generateCurrentTimezoneLabel,
@@ -50,6 +49,7 @@ export function makeMapStateToProps() {
const configTeammateNameDisplay = config.TeammateNameDisplay as string;
const emojiPickerEnabled = config.EnableEmojiPicker === 'true';
const lastActiveTimeEnabled = config.EnableLastActiveTime === 'true';
const userPreference = props.adminMode && props.userPreferences ? props.userPreferences : undefined;
let lastActiveDisplay = true;
const user = props.adminMode ? props.user : getUser(state, currentUserId);
@@ -62,12 +62,6 @@ export function makeMapStateToProps() {
userLocale = config.DefaultClientLocale as string;
}
let getPreference = (prefCategory: string, prefName: string, defaultValue: string) => get(state, prefCategory, prefName, defaultValue);
if (props.adminMode && props.userPreferences) {
const preferences = props.userPreferences;
getPreference = (prefCategory: string, prefName: string, defaultValue: string) => getFromPreferences(preferences, prefCategory, prefName, defaultValue);
}
return {
lockTeammateNameDisplay,
allowCustomThemes,
@@ -80,19 +74,18 @@ export function makeMapStateToProps() {
timezoneLabel,
userTimezone,
shouldAutoUpdateTimezone,
currentUserTimezone: getUserCurrentTimezone(userTimezone) as string,
availabilityStatusOnPosts: getPreference(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.AVAILABILITY_STATUS_ON_POSTS, Preferences.AVAILABILITY_STATUS_ON_POSTS_DEFAULT),
militaryTime: getPreference(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.USE_MILITARY_TIME, Preferences.USE_MILITARY_TIME_DEFAULT),
teammateNameDisplay: getPreference(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.NAME_NAME_FORMAT, configTeammateNameDisplay),
channelDisplayMode: getPreference(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.CHANNEL_DISPLAY_MODE, Preferences.CHANNEL_DISPLAY_MODE_DEFAULT),
messageDisplay: getPreference(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.MESSAGE_DISPLAY, Preferences.MESSAGE_DISPLAY_DEFAULT),
colorizeUsernames: getPreference(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.COLORIZE_USERNAMES, Preferences.COLORIZE_USERNAMES_DEFAULT),
collapseDisplay: getPreference(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.COLLAPSE_DISPLAY, Preferences.COLLAPSE_DISPLAY_DEFAULT),
availabilityStatusOnPosts: get(state, Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.AVAILABILITY_STATUS_ON_POSTS, Preferences.AVAILABILITY_STATUS_ON_POSTS_DEFAULT, userPreference),
militaryTime: get(state, Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.USE_MILITARY_TIME, Preferences.USE_MILITARY_TIME_DEFAULT, userPreference),
teammateNameDisplay: get(state, Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.NAME_NAME_FORMAT, configTeammateNameDisplay, userPreference),
channelDisplayMode: get(state, Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.CHANNEL_DISPLAY_MODE, Preferences.CHANNEL_DISPLAY_MODE_DEFAULT, userPreference),
messageDisplay: get(state, Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.MESSAGE_DISPLAY, Preferences.MESSAGE_DISPLAY_DEFAULT, userPreference),
colorizeUsernames: get(state, Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.COLORIZE_USERNAMES, Preferences.COLORIZE_USERNAMES_DEFAULT, userPreference),
collapseDisplay: get(state, Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.COLLAPSE_DISPLAY, Preferences.COLLAPSE_DISPLAY_DEFAULT, userPreference),
collapsedReplyThreadsAllowUserPreference: isCollapsedThreadsAllowed(state) && getConfig(state).CollapsedThreads !== CollapsedThreads.ALWAYS_ON,
collapsedReplyThreads: getCollapsedThreadsPreference(state),
clickToReply: getPreference(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.CLICK_TO_REPLY, Preferences.CLICK_TO_REPLY_DEFAULT),
linkPreviewDisplay: getPreference(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.LINK_PREVIEW_DISPLAY, Preferences.LINK_PREVIEW_DISPLAY_DEFAULT),
oneClickReactionsOnPosts: getPreference(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.ONE_CLICK_REACTIONS_ENABLED, Preferences.ONE_CLICK_REACTIONS_ENABLED_DEFAULT),
clickToReply: get(state, Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.CLICK_TO_REPLY, Preferences.CLICK_TO_REPLY_DEFAULT, userPreference),
linkPreviewDisplay: get(state, Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.LINK_PREVIEW_DISPLAY, Preferences.LINK_PREVIEW_DISPLAY_DEFAULT, userPreference),
oneClickReactionsOnPosts: get(state, Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.ONE_CLICK_REACTIONS_ENABLED, Preferences.ONE_CLICK_REACTIONS_ENABLED_DEFAULT, userPreference),
emojiPickerEnabled,
lastActiveDisplay,
lastActiveTimeEnabled,

Просмотреть файл

@@ -103,7 +103,6 @@ type Props = OwnProps & {
userLocale: string;
enableThemeSelection: boolean;
configTeammateNameDisplay: string;
currentUserTimezone: string;
shouldAutoUpdateTimezone: boolean | string;
lockTeammateNameDisplay: boolean;
militaryTime: string;

Просмотреть файл

@@ -97,7 +97,7 @@ export default function UserSettings(props: Props) {
closeModal={props.closeModal}
collapseModal={props.collapseModal}
adminMode={props.adminMode}
currentUserId={props.user.id}
userId={props.user.id}
userPreferences={props.userPreferences}
/>
</div>
@@ -111,7 +111,7 @@ export default function UserSettings(props: Props) {
closeModal={props.closeModal}
collapseModal={props.collapseModal}
adminMode={props.adminMode}
currentUser={props.user}
user={props.user}
userPreferences={props.userPreferences}
/>
</div>

Просмотреть файл

@@ -28,10 +28,10 @@ function mapStateToProps(state: GlobalState, ownProps: OwnProps) {
const sendEmailNotifications = config.SendEmailNotifications === 'true';
const requireEmailVerification = config.RequireEmailVerification === 'true';
const currentUser = ownProps.adminMode && ownProps.userID ? getUserSelector(state, ownProps.userID) : getCurrentUser(state);
const user = ownProps.adminMode && ownProps.userID ? getUserSelector(state, ownProps.userID) : getCurrentUser(state);
return {
currentUser,
user,
userPreferences: ownProps.adminMode && ownProps.userID ? getUserPreferencesSelector(state, ownProps.userID) : undefined,
sendEmailNotifications,
requireEmailVerification,

Просмотреть файл

@@ -16,7 +16,7 @@ import ConfirmModal from 'components/confirm_modal';
import SettingsSidebar from 'components/settings_sidebar';
import UserSettings from 'components/user_settings';
import LoadingSpinner from 'components/widgets/loading/loading_spinner';
import SmartLoader from 'components/widgets/smartLoader';
import SmartLoader from 'components/widgets/smart_loader';
import Constants from 'utils/constants';
import {cmdOrCtrlPressed, isKeyPressed} from 'utils/keyboard';
@@ -28,7 +28,6 @@ import type {PluginConfiguration} from 'types/plugins/user_settings';
export type OwnProps = {
userID?: string;
adminMode?: boolean;
currentUser?: UserProfile;
isContentProductSettings: boolean;
userPreferences?: PreferencesType;
}
@@ -42,6 +41,7 @@ export type Props = OwnProps & {
getUser: (userID: string) => Promise<unknown>;
};
pluginSettings: {[pluginId: string]: PluginConfiguration};
user?: UserProfile;
}
type State = {
@@ -106,7 +106,7 @@ class UserSettingsModal extends React.PureComponent<Props, State> {
this.props.actions.getUserPreferences(this.props.userID);
}
if (!this.props.currentUser) {
if (!this.props.user) {
this.props.actions.getUser(this.props.userID);
}
}
@@ -312,12 +312,12 @@ class UserSettingsModal extends React.PureComponent<Props, State> {
let modalTitle: string;
if (this.props.adminMode && this.props.currentUser) {
if (this.props.adminMode && this.props.user) {
modalTitle = formatMessage({
id: 'userSettings.adminMode.modal_header',
defaultMessage: "{userDisplayName}'s Settings",
}, {
userDisplayName: getDisplayName(this.props.currentUser),
userDisplayName: getDisplayName(this.props.user),
});
} else {
modalTitle = this.props.isContentProductSettings ? formatMessage({
@@ -365,7 +365,7 @@ class UserSettingsModal extends React.PureComponent<Props, State> {
{
this.props.adminMode &&
<SmartLoader
loading={this.props.adminMode && (!this.props.userPreferences || !this.props.currentUser)}
loading={this.props.adminMode && (!this.props.userPreferences || !this.props.user)}
className='loadingIndicator'
onLoaded={this.setLoadingFinished}
>
@@ -374,7 +374,7 @@ class UserSettingsModal extends React.PureComponent<Props, State> {
}
{
!this.state.loading && this.props.currentUser &&
!this.state.loading && this.props.user &&
<div className='settings-table'>
<div className='settings-links'>
<SettingsSidebar
@@ -400,7 +400,7 @@ class UserSettingsModal extends React.PureComponent<Props, State> {
}
}
pluginSettings={this.props.pluginSettings}
user={this.props.currentUser}
user={this.props.user}
adminMode={this.props.adminMode}
userPreferences={this.props.userPreferences}
/>

Просмотреть файл

@@ -4,7 +4,7 @@
import {connect} from 'react-redux';
import {savePreferences} from 'mattermost-redux/actions/preferences';
import {getUserVisibleDmGmLimit, getVisibleDmGmLimit} from 'mattermost-redux/selectors/entities/preferences';
import {getVisibleDmGmLimit} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
import type {GlobalState} from 'types/store';
@@ -13,9 +13,10 @@ import type {OwnProps} from './limit_visible_gms_dms';
import LimitVisibleGMsDMs from './limit_visible_gms_dms';
function mapStateToProps(state: GlobalState, ownProps: OwnProps) {
const userPreferences = ownProps.adminMode && ownProps.userPreferences ? ownProps.userPreferences : undefined;
return {
currentUserId: ownProps.adminMode ? ownProps.currentUserId : getCurrentUserId(state),
dmGmLimit: ownProps.adminMode && ownProps.userPreferences ? getUserVisibleDmGmLimit(ownProps.userPreferences) : getVisibleDmGmLimit(state),
userId: ownProps.adminMode ? ownProps.userId : getCurrentUserId(state),
dmGmLimit: getVisibleDmGmLimit(state, userPreferences),
};
}

Просмотреть файл

@@ -25,7 +25,7 @@ type Limit = {
export type OwnProps = {
adminMode?: boolean;
currentUserId?: string;
userId: string;
userPreferences?: PreferencesType;
}
@@ -104,14 +104,14 @@ export default class LimitVisibleGMsDMs extends React.PureComponent<Props, State
};
handleSubmit = async () => {
if (!this.props.currentUserId) {
if (!this.props.userId) {
return;
}
this.setState({isSaving: true});
await this.props.savePreferences(this.props.currentUserId, [{
user_id: this.props.currentUserId,
await this.props.savePreferences(this.props.userId, [{
user_id: this.props.userId,
category: Preferences.CATEGORY_SIDEBAR_SETTINGS,
name: Preferences.LIMIT_VISIBLE_DMS_GMS,
value: this.state.limit.value.toString(),

Просмотреть файл

@@ -4,9 +4,7 @@
import {connect} from 'react-redux';
import {savePreferences} from 'mattermost-redux/actions/preferences';
import {getConfig} from 'mattermost-redux/selectors/entities/general';
import {
calculateUserShouldShowUnreadsCategory,
shouldShowUnreadsCategory,
} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
@@ -17,10 +15,10 @@ import type {OwnProps} from './show_unreads_category';
import ShowUnreadsCategory from './show_unreads_category';
function mapStateToProps(state: GlobalState, props: OwnProps) {
const serverDefault = getConfig(state).ExperimentalGroupUnreadChannels;
const userPreferences = props.adminMode && props.userPreferences ? props.userPreferences : undefined;
return {
currentUserId: props.adminMode ? props.currentUserId : getCurrentUserId(state),
showUnreadsCategory: props.adminMode && props.userPreferences ? calculateUserShouldShowUnreadsCategory(props.userPreferences, serverDefault) : shouldShowUnreadsCategory(state),
userId: props.adminMode ? props.userId : getCurrentUserId(state),
showUnreadsCategory: shouldShowUnreadsCategory(state, userPreferences),
};
}

Просмотреть файл

@@ -18,7 +18,7 @@ import {a11yFocus} from 'utils/utils';
export type OwnProps = {
adminMode?: boolean;
currentUserId?: string;
userId: string;
userPreferences?: PreferencesType;
}
@@ -80,15 +80,15 @@ export default class ShowUnreadsCategory extends React.PureComponent<Props, Stat
};
handleSubmit = async () => {
if (!this.props.currentUserId) {
if (!this.props.userId) {
// Only for type safety, won't actually happen
return;
}
this.setState({isSaving: true});
await this.props.savePreferences(this.props.currentUserId, [{
user_id: this.props.currentUserId,
await this.props.savePreferences(this.props.userId, [{
user_id: this.props.userId,
category: Preferences.CATEGORY_SIDEBAR_SETTINGS,
name: Preferences.SHOW_UNREAD_SECTION,
value: this.state.checked.toString(),

Просмотреть файл

@@ -18,7 +18,7 @@ export interface Props {
closeModal: () => void;
collapseModal: () => void;
adminMode?: boolean;
currentUserId?: string;
userId: string;
userPreferences?: PreferencesType;
}
@@ -54,7 +54,7 @@ export default function UserSettingsSidebar(props: Props): JSX.Element {
updateSection={props.updateSection}
areAllSectionsInactive={props.activeSection === ''}
adminMode={props.adminMode}
currentUserId={props.currentUserId}
userId={props.userId}
userPreferences={props.userPreferences}
/>
<div className='divider-dark'/>
@@ -63,7 +63,7 @@ export default function UserSettingsSidebar(props: Props): JSX.Element {
updateSection={props.updateSection}
areAllSectionsInactive={props.activeSection === ''}
adminMode={props.adminMode}
currentUserId={props.currentUserId}
userId={props.userId}
userPreferences={props.userPreferences}
/>
<div className='divider-dark'/>

Просмотреть файл

@@ -3,7 +3,7 @@
import React, {type ReactNode, useEffect, useState} from 'react';
const DEFAULT_MIN_LOADER_DURATION = 1500;
const DEFAULT_MIN_LOADER_DURATION = 1000;
type Props = {
loading: boolean;

Просмотреть файл

@@ -102,7 +102,7 @@ export function makeFilterAutoclosedDMs(): (state: GlobalState, channels: Channe
getCurrentUserId,
getMyChannelMemberships,
getChannelMessageCounts,
getVisibleDmGmLimit,
(state) => getVisibleDmGmLimit(state),
getMyPreferences,
isCollapsedThreadsEnabled,
(channels, categoryType, currentChannelId, profiles, currentUserId, myMembers, messageCounts, limitPref, myPreferences, collapsedThreads) => {

Просмотреть файл

@@ -16,11 +16,15 @@ export function getMyPreferences(state: GlobalState): { [x: string]: PreferenceT
return state.entities.preferences.myPreferences;
}
export function getUserPreferences(state: GlobalState, userID: string): { [x: string]: PreferenceType } {
export function getUserPreferences(state: GlobalState, userID: string): PreferencesType {
return state.entities.preferences.userPreferences[userID];
}
export function get(state: GlobalState, category: string, name: string, defaultValue: any = '') {
export function get(state: GlobalState, category: string, name: string, defaultValue: any = '', preferences?: PreferencesType) {
if (preferences) {
return getFromPreferences(preferences, category, name, defaultValue);
}
const key = getPreferenceKey(category, name);
const prefs = getMyPreferences(state);
@@ -41,18 +45,13 @@ export function getFromPreferences(preferences: PreferencesType, category: strin
return preferences[key].value;
}
export function getBool(state: GlobalState, category: string, name: string, defaultValue = false): boolean {
const value = get(state, category, name, String(defaultValue));
export function getBool(state: GlobalState, category: string, name: string, defaultValue = false, userPreferences?: PreferencesType): boolean {
const value = get(state, category, name, String(defaultValue), userPreferences);
return value !== 'false';
}
export function getBoolFromPreferences(userPreferences: PreferencesType, category: string, name: string, defaultValue = false): boolean {
const value = getFromPreferences(userPreferences, category, name, String(defaultValue));
return value !== 'false';
}
export function getInt(state: GlobalState, category: string, name: string, defaultValue = 0): number {
const value = get(state, category, name, defaultValue);
export function getInt(state: GlobalState, category: string, name: string, defaultValue = 0, userPreferences?: PreferencesType): number {
const value = get(state, category, name, defaultValue, userPreferences);
return parseInt(value, 10);
}
@@ -219,42 +218,29 @@ export function makeGetStyleFromTheme<Style>(): (state: GlobalState, getStyleFro
);
}
export function calculateUserShouldShowUnreadsCategory(userPreferences: PreferencesType, serverDefault?: string): boolean {
const userPreference = getFromPreferences(userPreferences, Preferences.CATEGORY_SIDEBAR_SETTINGS, Preferences.SHOW_UNREAD_SECTION);
const oldUserPreference = getFromPreferences(userPreferences, Preferences.CATEGORY_SIDEBAR_SETTINGS, '');
return calculateShouldShowUnreadsCategory(userPreference, oldUserPreference, serverDefault);
}
export function calculateShouldShowUnreadsCategory(userPreference: string, oldUserPreference: string, serverDefault?: string): boolean {
// Prefer the show_unread_section user preference over the previous version
if (userPreference) {
return userPreference === 'true';
}
if (oldUserPreference) {
return JSON.parse(oldUserPreference).unreads_at_top === 'true';
}
// The user setting is not set, so use the system default
return serverDefault === General.DEFAULT_ON;
}
// shouldShowUnreadsCategory returns true if the user has unereads grouped separately with the new sidebar enabled.
export const shouldShowUnreadsCategory: (state: GlobalState) => boolean = createSelector(
export const shouldShowUnreadsCategory: (state: GlobalState, userPreferences?: PreferencesType) => boolean = createSelector(
'shouldShowUnreadsCategory',
(state: GlobalState) => get(state, Preferences.CATEGORY_SIDEBAR_SETTINGS, Preferences.SHOW_UNREAD_SECTION),
(state: GlobalState) => get(state, Preferences.CATEGORY_SIDEBAR_SETTINGS, ''),
(state: GlobalState, userPreferences?: PreferencesType) => get(state, Preferences.CATEGORY_SIDEBAR_SETTINGS, Preferences.SHOW_UNREAD_SECTION, '', userPreferences),
(state: GlobalState, userPreferences?: PreferencesType) => get(state, Preferences.CATEGORY_SIDEBAR_SETTINGS, '', '', userPreferences),
(state: GlobalState) => getConfig(state).ExperimentalGroupUnreadChannels,
calculateShouldShowUnreadsCategory,
(userPreference: string, oldUserPreference: string, serverDefault?: string): boolean => {
// Prefer the show_unread_section user preference over the previous version
if (userPreference) {
return userPreference === 'true';
}
if (oldUserPreference) {
return JSON.parse(oldUserPreference).unreads_at_top === 'true';
}
// The user setting is not set, so use the system default
return serverDefault === General.DEFAULT_ON;
},
);
export function getUnreadScrollPositionPreference(state: GlobalState): string {
return get(state, Preferences.CATEGORY_ADVANCED_SETTINGS, Preferences.UNREAD_SCROLL_POSITION, Preferences.UNREAD_SCROLL_POSITION_START_FROM_LEFT);
}
export function getUnreadScrollPositionFromPreference(userPreferences: PreferencesType): string {
return getFromPreferences(userPreferences, Preferences.CATEGORY_ADVANCED_SETTINGS, Preferences.UNREAD_SCROLL_POSITION, Preferences.UNREAD_SCROLL_POSITION_START_FROM_LEFT);
export function getUnreadScrollPositionPreference(state: GlobalState, userPreferences?: PreferencesType): string {
return get(state, Preferences.CATEGORY_ADVANCED_SETTINGS, Preferences.UNREAD_SCROLL_POSITION, Preferences.UNREAD_SCROLL_POSITION_START_FROM_LEFT, userPreferences);
}
export function getCollapsedThreadsPreference(state: GlobalState): string {
@@ -334,15 +320,9 @@ export function syncedDraftsAreAllowedAndEnabled(state: GlobalState): boolean {
return isConfiguredForFeature && isConfiguredForUser;
}
export function getVisibleDmGmLimit(state: GlobalState) {
export function getVisibleDmGmLimit(state: GlobalState, userPreferences?: PreferencesType) {
const defaultLimit = 40;
return getInt(state, Preferences.CATEGORY_SIDEBAR_SETTINGS, Preferences.LIMIT_VISIBLE_DMS_GMS, defaultLimit);
}
export function getUserVisibleDmGmLimit(userPreferences: PreferencesType) {
const defaultLimit = 40;
const value = getFromPreferences(userPreferences, Preferences.CATEGORY_SIDEBAR_SETTINGS, Preferences.LIMIT_VISIBLE_DMS_GMS, defaultLimit);
return parseInt(value, 10);
return getInt(state, Preferences.CATEGORY_SIDEBAR_SETTINGS, Preferences.LIMIT_VISIBLE_DMS_GMS, defaultLimit, userPreferences);
}
export function onboardingTourTipsEnabled(state: GlobalState): boolean {

Просмотреть файл

@@ -197,7 +197,7 @@ export function makeGetFilteredChannelIdsForCategory(): (state: GlobalState, cat
'makeGetFilteredChannelIdsForCategory',
getChannelIdsForCategory,
getUnreadChannelIdsSet,
shouldShowUnreadsCategory,
(state: GlobalState) => shouldShowUnreadsCategory(state),
(channelIds, unreadChannelIdsSet, showUnreadsCategory) => {
if (!showUnreadsCategory) {
return channelIds;
@@ -220,7 +220,7 @@ export function makeGetUnreadIdsForCategory(): (state: GlobalState, category: Ch
'makeGetFilteredChannelIdsForCategory',
getChannelIdsForCategory,
getUnreadChannelIdsSet,
shouldShowUnreadsCategory,
(state: GlobalState) => shouldShowUnreadsCategory(state),
(channelIds, unreadChannelIdsSet, showUnreadsCategory) => {
if (showUnreadsCategory) {
return emptyList;