[MM-58356] Improve logic for rendering start call button in user profile popover (#27840)
* Improve logic for rendering start call button in user profile popover * Fix typo * Fix potential error when plugin is not enabled * Improve selector logic
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
7dd84f623a
Коммит
aca39fb1ef
@@ -148,6 +148,9 @@ function getBasePropsAndState(): [Props, DeepPartial<GlobalState>] {
|
||||
// @ts-ignore
|
||||
'plugins-com.mattermost.calls': {
|
||||
sessions: {},
|
||||
callsConfig: {
|
||||
DefaultEnabled: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
const props: Props = {
|
||||
@@ -301,7 +304,7 @@ describe('components/ProfilePopover', () => {
|
||||
expect(await screen.findByLabelText('Start Call')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should not show start a call button when calls are disabled', async () => {
|
||||
test('should not show start call button when plugin is disabled', async () => {
|
||||
const [props, initialState] = getBasePropsAndState();
|
||||
initialState.plugins!.plugins = {};
|
||||
|
||||
@@ -318,11 +321,47 @@ describe('components/ProfilePopover', () => {
|
||||
expect(button).toBeDisabled();
|
||||
});
|
||||
|
||||
test('should not show the start call button when callsChannelState.enabled is false', async () => {
|
||||
(Client4.getCallsChannelState as jest.Mock).mockImplementationOnce(async () => ({enabled: false}));
|
||||
test('should not show start call button when calls in channel have been explicitly disabled', async () => {
|
||||
const [props, initialState] = getBasePropsAndState();
|
||||
(initialState as any)['plugins-com.mattermost.calls'].channels = {dmChannelId: {enabled: false}};
|
||||
|
||||
renderWithPluginReducers(<ProfilePopover {...props}/>, initialState);
|
||||
expect(await screen.findByLabelText('Start Call')).not.toBeInTheDocument();
|
||||
expect(await screen.queryByLabelText('Start Call')).not.toBeInTheDocument();
|
||||
expect(await screen.queryByLabelText('Call with user is ongoing')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should not show start call button for users when calls test mode is on', async () => {
|
||||
const [props, initialState] = getBasePropsAndState();
|
||||
(initialState as any)['plugins-com.mattermost.calls'].callsConfig = {DefaultEnabled: false};
|
||||
|
||||
renderWithPluginReducers(<ProfilePopover {...props}/>, initialState);
|
||||
expect(await screen.queryByLabelText('Start Call')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should show start call button for users when calls test mode is on if calls in channel have been explicitly enabled', async () => {
|
||||
const [props, initialState] = getBasePropsAndState();
|
||||
(initialState as any)['plugins-com.mattermost.calls'].callsConfig = {DefaultEnabled: false};
|
||||
(initialState as any)['plugins-com.mattermost.calls'].channels = {dmChannelId: {enabled: true}};
|
||||
|
||||
renderWithPluginReducers(<ProfilePopover {...props}/>, initialState);
|
||||
expect(await screen.queryByLabelText('Start Call')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should show start call button for admin when calls test mode is on', async () => {
|
||||
const [props, initialState] = getBasePropsAndState();
|
||||
(initialState as any)['plugins-com.mattermost.calls'].callsConfig = {DefaultEnabled: false};
|
||||
initialState.entities = {
|
||||
...initialState.entities!,
|
||||
users: {
|
||||
...initialState.entities!.users,
|
||||
profiles: {
|
||||
...initialState.entities!.users!.profiles,
|
||||
currentUser: TestHelper.getUserMock({id: 'currentUser', roles: General.SYSTEM_ADMIN_ROLE}),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
renderWithPluginReducers(<ProfilePopover {...props}/>, initialState);
|
||||
expect(await screen.findByLabelText('Start Call')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {useCallback, useEffect, useState} from 'react';
|
||||
import React from 'react';
|
||||
import {useIntl} from 'react-intl';
|
||||
import {useSelector} from 'react-redux';
|
||||
|
||||
import {Client4} from 'mattermost-redux/client';
|
||||
import {getChannelByName} from 'mattermost-redux/selectors/entities/channels';
|
||||
import {getUser} from 'mattermost-redux/selectors/entities/users';
|
||||
import {isSystemAdmin} from 'mattermost-redux/utils/user_utils';
|
||||
|
||||
import {isCallsEnabled as getIsCallsEnabled, getSessionsInCalls} from 'selectors/calls';
|
||||
import {
|
||||
isCallsEnabled as getIsCallsEnabled,
|
||||
getSessionsInCalls,
|
||||
getCallsConfig,
|
||||
callsChannelExplicitlyDisabled,
|
||||
callsChannelExplicitlyEnabled,
|
||||
} from 'selectors/calls';
|
||||
|
||||
import ProfilePopoverCallButton from 'components/profile_popover/profile_popover_calls_button';
|
||||
import WithTooltip from 'components/with_tooltip';
|
||||
@@ -24,11 +31,6 @@ type Props = {
|
||||
username: string;
|
||||
}
|
||||
|
||||
type ChannelCallsState = {
|
||||
enabled: boolean;
|
||||
id: string;
|
||||
};
|
||||
|
||||
export function isUserInCall(state: GlobalState, userId: string, channelId: string) {
|
||||
const sessionsInCall = getSessionsInCalls(state)[channelId] || {};
|
||||
|
||||
@@ -52,6 +54,36 @@ const CallButton = ({
|
||||
const isCallsEnabled = useSelector((state: GlobalState) => getIsCallsEnabled(state));
|
||||
const dmChannel = useSelector((state: GlobalState) => getChannelByName(state, getDirectChannelName(currentUserId, userId)));
|
||||
|
||||
const shouldRenderButton = useSelector((state: GlobalState) => {
|
||||
// 1. No one should get the button if the plugin is disabled.
|
||||
if (!isCallsEnabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. No one should get the button if calls in channel have been explicitly disabled in the DM channel.
|
||||
if (callsChannelExplicitlyDisabled(state, dmChannel?.id ?? '')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. Admins should get the button unless calls have been explicitly disabled in the DM channel. This
|
||||
// should apply in test mode as well (DefaultEnabled = false).
|
||||
if (isSystemAdmin(getUser(state, currentUserId)?.roles)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 4. Users should only see the button if test mode is off (DefaultEnabled = true) and calls in the DM channel are not disabled.
|
||||
if (getCallsConfig(state).DefaultEnabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 5. Everyone should see the button if calls have been explicitly enabled in the DM channel, regardless of test mode state.
|
||||
if (callsChannelExplicitlyEnabled(state, dmChannel?.id ?? '')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
const hasDMCall = useSelector((state: GlobalState) => {
|
||||
if (isCallsEnabled && dmChannel) {
|
||||
return isUserInCall(state, currentUserId, dmChannel.id) || isUserInCall(state, userId, dmChannel.id);
|
||||
@@ -59,28 +91,7 @@ const CallButton = ({
|
||||
return false;
|
||||
});
|
||||
|
||||
const [callsDMChannelState, setCallsDMChannelState] = useState<ChannelCallsState>();
|
||||
|
||||
const getCallsChannelState = useCallback((channelId: string): Promise<ChannelCallsState> => {
|
||||
let data: Promise<ChannelCallsState>;
|
||||
try {
|
||||
data = Client4.getCallsChannelState(channelId);
|
||||
} catch (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
return data;
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (isCallsEnabled && dmChannel) {
|
||||
getCallsChannelState(dmChannel.id).then((data) => {
|
||||
setCallsDMChannelState(data);
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
|
||||
if (!isCallsEnabled || callsDMChannelState?.enabled === false) {
|
||||
if (!shouldRenderButton) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import {suitePluginIds} from 'utils/constants';
|
||||
|
||||
import type {GlobalState} from 'types/store';
|
||||
|
||||
const CALLS_PLUGIN = 'plugins-com.mattermost.calls';
|
||||
const CALLS_PLUGIN = `plugins-${suitePluginIds.calls}`;
|
||||
|
||||
export function isCallsEnabled(state: GlobalState, minVersion = '0.4.2') {
|
||||
return Boolean(state.plugins.plugins[suitePluginIds.calls] &&
|
||||
@@ -20,17 +20,37 @@ export function isCallsEnabled(state: GlobalState, minVersion = '0.4.2') {
|
||||
export function isCallsRingingEnabledOnServer(state: GlobalState) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
return Boolean(state[`plugins-${suitePluginIds.calls}`]?.callsConfig?.EnableRinging);
|
||||
return Boolean(state[CALLS_PLUGIN]?.callsConfig?.EnableRinging);
|
||||
}
|
||||
|
||||
export function getSessionsInCalls(state: GlobalState): Record<string, Record<string, UserSessionState>> {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
return state[CALLS_PLUGIN].sessions || {};
|
||||
return state[CALLS_PLUGIN]?.sessions || {};
|
||||
}
|
||||
|
||||
export function getCallsConfig(state: GlobalState): CallsConfig {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
return state[CALLS_PLUGIN].callsConfig;
|
||||
return state[CALLS_PLUGIN]?.callsConfig;
|
||||
}
|
||||
|
||||
export function getCallsChannelState(state: GlobalState, channelId: string): {enabled?: boolean} {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
if (!state[CALLS_PLUGIN] || !state[CALLS_PLUGIN].channels) {
|
||||
return {};
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
return state[CALLS_PLUGIN].channels[channelId] || {};
|
||||
}
|
||||
|
||||
export function callsChannelExplicitlyEnabled(state: GlobalState, channelId: string) {
|
||||
return Boolean(getCallsChannelState(state, channelId).enabled);
|
||||
}
|
||||
|
||||
export function callsChannelExplicitlyDisabled(state: GlobalState, channelId: string) {
|
||||
const enabled = getCallsChannelState(state, channelId).enabled;
|
||||
return (typeof enabled !== 'undefined') && !enabled;
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user