exclude file count on channel stats api call on from channel header (#22624)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
932790f99a
Коммит
529ab959e2
@@ -65,7 +65,7 @@ export function emitChannelClickEvent(channel: Channel) {
|
||||
const currentChannelId = getCurrentChannelId(state);
|
||||
const previousRhsState = getPreviousRhsState(state);
|
||||
|
||||
dispatch(getChannelStats(chan.id));
|
||||
dispatch(getChannelStats(chan.id, true));
|
||||
|
||||
const penultimate = LocalStorageStore.getPreviousChannelName(userId, teamId);
|
||||
const penultimateType = LocalStorageStore.getPreviousViewedType(userId, teamId);
|
||||
|
||||
@@ -3,8 +3,11 @@
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import {Channel, ChannelStats} from '@mattermost/types/channels';
|
||||
import {act} from '@testing-library/react';
|
||||
|
||||
import {renderWithIntl} from 'tests/react_testing_utils';
|
||||
|
||||
import {Channel, ChannelStats} from '@mattermost/types/channels';
|
||||
import {UserProfile} from '@mattermost/types/users';
|
||||
import {Team} from '@mattermost/types/teams';
|
||||
|
||||
@@ -40,6 +43,7 @@ describe('channel_info_rhs', () => {
|
||||
showChannelFiles: jest.fn(),
|
||||
showPinnedPosts: jest.fn(),
|
||||
showChannelMembers: jest.fn(),
|
||||
getChannelStats: jest.fn().mockImplementation(() => Promise.resolve({data: {}})),
|
||||
},
|
||||
};
|
||||
let props = {...OriginalProps};
|
||||
@@ -49,20 +53,24 @@ describe('channel_info_rhs', () => {
|
||||
});
|
||||
|
||||
describe('about area', () => {
|
||||
test('should be editable', () => {
|
||||
test('should be editable', async () => {
|
||||
renderWithIntl(
|
||||
<ChannelInfoRHS
|
||||
{...props}
|
||||
/>,
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
props.actions.getChannelStats();
|
||||
});
|
||||
|
||||
expect(mockAboutArea).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
canEditChannelProperties: true,
|
||||
}),
|
||||
);
|
||||
});
|
||||
test('should not be editable in archived channel', () => {
|
||||
test('should not be editable in archived channel', async () => {
|
||||
props.isArchived = true;
|
||||
|
||||
renderWithIntl(
|
||||
@@ -71,6 +79,10 @@ describe('channel_info_rhs', () => {
|
||||
/>,
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
props.actions.getChannelStats();
|
||||
});
|
||||
|
||||
expect(mockAboutArea).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
canEditChannelProperties: false,
|
||||
|
||||
@@ -64,6 +64,7 @@ export interface Props {
|
||||
showChannelFiles: (channelId: string) => void;
|
||||
showPinnedPosts: (channelId: string | undefined) => void;
|
||||
showChannelMembers: (channelId: string) => void;
|
||||
getChannelStats: (channelId: string) => Promise<{data: ChannelStats}>;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -192,6 +193,7 @@ const ChannelInfoRhs = ({
|
||||
showChannelFiles: actions.showChannelFiles,
|
||||
showPinnedPosts: actions.showPinnedPosts,
|
||||
showChannelMembers: actions.showChannelMembers,
|
||||
getChannelStats: actions.getChannelStats,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -16,7 +16,7 @@ import {Constants, ModalIdentifiers} from 'utils/constants';
|
||||
import {getCurrentUser} from 'mattermost-redux/selectors/entities/common';
|
||||
import {getIsMobileView} from 'selectors/views/browser';
|
||||
import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams';
|
||||
import {unfavoriteChannel, favoriteChannel} from 'mattermost-redux/actions/channels';
|
||||
import {unfavoriteChannel, favoriteChannel, getChannelStats} from 'mattermost-redux/actions/channels';
|
||||
import {muteChannel, unmuteChannel} from 'actions/channel_actions';
|
||||
import {openModal} from 'actions/views/modals';
|
||||
import {getDisplayNameByUser, getUserIdFromChannelId} from 'utils/utils';
|
||||
@@ -92,6 +92,7 @@ function mapDispatchToProps(dispatch: Dispatch<AnyAction>) {
|
||||
showChannelFiles,
|
||||
showPinnedPosts,
|
||||
showChannelMembers,
|
||||
getChannelStats,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import {fireEvent, screen} from '@testing-library/react';
|
||||
import {act, fireEvent, screen} from '@testing-library/react';
|
||||
|
||||
import {Channel, ChannelStats} from '@mattermost/types/channels';
|
||||
import {renderWithIntl} from 'tests/react_testing_utils';
|
||||
import Constants from 'utils/constants';
|
||||
|
||||
import {Channel, ChannelStats} from '@mattermost/types/channels';
|
||||
|
||||
import Menu from './menu';
|
||||
|
||||
describe('channel_info_rhs/menu', () => {
|
||||
@@ -20,6 +21,7 @@ describe('channel_info_rhs/menu', () => {
|
||||
showChannelFiles: jest.fn(),
|
||||
showPinnedPosts: jest.fn(),
|
||||
showChannelMembers: jest.fn(),
|
||||
getChannelStats: jest.fn().mockImplementation(() => Promise.resolve({data: {files_count: 3, pinnedpost_count: 12, member_count: 32}})),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -29,10 +31,11 @@ describe('channel_info_rhs/menu', () => {
|
||||
showChannelFiles: jest.fn(),
|
||||
showPinnedPosts: jest.fn(),
|
||||
showChannelMembers: jest.fn(),
|
||||
getChannelStats: jest.fn().mockImplementation(() => Promise.resolve({data: {files_count: 3, pinnedpost_count: 12, member_count: 32}})),
|
||||
};
|
||||
});
|
||||
|
||||
test('should display notifications preferences', () => {
|
||||
test('should display notifications preferences', async () => {
|
||||
const props = {...defaultProps};
|
||||
props.actions.openNotificationSettings = jest.fn();
|
||||
|
||||
@@ -42,13 +45,17 @@ describe('channel_info_rhs/menu', () => {
|
||||
/>,
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
props.actions.getChannelStats();
|
||||
});
|
||||
|
||||
expect(screen.getByText('Notification Preferences')).toBeInTheDocument();
|
||||
fireEvent.click(screen.getByText('Notification Preferences'));
|
||||
|
||||
expect(props.actions.openNotificationSettings).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should NOT display notifications preferences in a DM', () => {
|
||||
test('should NOT display notifications preferences in a DM', async () => {
|
||||
const props = {
|
||||
...defaultProps,
|
||||
channel: {type: Constants.DM_CHANNEL} as Channel,
|
||||
@@ -60,10 +67,14 @@ describe('channel_info_rhs/menu', () => {
|
||||
/>,
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
props.actions.getChannelStats();
|
||||
});
|
||||
|
||||
expect(screen.queryByText('Notification Preferences')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should NOT display notifications preferences in an archived channel', () => {
|
||||
test('should NOT display notifications preferences in an archived channel', async () => {
|
||||
const props = {
|
||||
...defaultProps,
|
||||
isArchived: true,
|
||||
@@ -75,10 +86,14 @@ describe('channel_info_rhs/menu', () => {
|
||||
/>,
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
props.actions.getChannelStats();
|
||||
});
|
||||
|
||||
expect(screen.queryByText('Notification Preferences')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should display the number of files', () => {
|
||||
test('should display the number of files', async () => {
|
||||
const props = {...defaultProps};
|
||||
props.actions.showChannelFiles = jest.fn();
|
||||
|
||||
@@ -88,6 +103,10 @@ describe('channel_info_rhs/menu', () => {
|
||||
/>,
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
props.actions.getChannelStats();
|
||||
});
|
||||
|
||||
const fileItem = screen.getByText('Files');
|
||||
expect(fileItem).toBeInTheDocument();
|
||||
expect(fileItem.parentElement).toHaveTextContent('3');
|
||||
@@ -96,7 +115,7 @@ describe('channel_info_rhs/menu', () => {
|
||||
expect(props.actions.showChannelFiles).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should display the pinned messages', () => {
|
||||
test('should display the pinned messages', async () => {
|
||||
const props = {...defaultProps};
|
||||
props.actions.showPinnedPosts = jest.fn();
|
||||
|
||||
@@ -106,6 +125,10 @@ describe('channel_info_rhs/menu', () => {
|
||||
/>,
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
props.actions.getChannelStats();
|
||||
});
|
||||
|
||||
const fileItem = screen.getByText('Pinned Messages');
|
||||
expect(fileItem).toBeInTheDocument();
|
||||
expect(fileItem.parentElement).toHaveTextContent('12');
|
||||
@@ -114,7 +137,7 @@ describe('channel_info_rhs/menu', () => {
|
||||
expect(props.actions.showPinnedPosts).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should display members', () => {
|
||||
test('should display members', async () => {
|
||||
const props = {...defaultProps};
|
||||
props.actions.showChannelMembers = jest.fn();
|
||||
|
||||
@@ -124,6 +147,10 @@ describe('channel_info_rhs/menu', () => {
|
||||
/>,
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
props.actions.getChannelStats();
|
||||
});
|
||||
|
||||
const membersItem = screen.getByText('Members');
|
||||
expect(membersItem).toBeInTheDocument();
|
||||
expect(membersItem.parentElement).toHaveTextContent('32');
|
||||
@@ -132,7 +159,7 @@ describe('channel_info_rhs/menu', () => {
|
||||
expect(props.actions.showChannelMembers).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should NOT display members in DM', () => {
|
||||
test('should NOT display members in DM', async () => {
|
||||
const props = {
|
||||
...defaultProps,
|
||||
channel: {type: Constants.DM_CHANNEL} as Channel,
|
||||
@@ -144,6 +171,10 @@ describe('channel_info_rhs/menu', () => {
|
||||
/>,
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
props.actions.getChannelStats();
|
||||
});
|
||||
|
||||
const membersItem = screen.queryByText('Members');
|
||||
expect(membersItem).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import React, {useEffect, useState} from 'react';
|
||||
import styled from 'styled-components';
|
||||
import {useIntl} from 'react-intl';
|
||||
|
||||
import {Constants} from 'utils/constants';
|
||||
|
||||
import LoadingSpinner from 'components/widgets/loading/loading_spinner';
|
||||
|
||||
import {Channel, ChannelStats} from '@mattermost/types/channels';
|
||||
|
||||
const MenuItemContainer = styled.div`
|
||||
@@ -32,6 +34,9 @@ const RightSide = styled.div`
|
||||
const Badge = styled.div`
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
width: 20px;
|
||||
display: flex;
|
||||
place-content: center;
|
||||
`;
|
||||
|
||||
interface MenuItemProps {
|
||||
@@ -39,7 +44,7 @@ interface MenuItemProps {
|
||||
icon: JSX.Element;
|
||||
text: string;
|
||||
opensSubpanel?: boolean;
|
||||
badge?: string|number;
|
||||
badge?: string|number|JSX.Element;
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
@@ -94,14 +99,26 @@ interface MenuProps {
|
||||
showChannelFiles: (channelId: string) => void;
|
||||
showPinnedPosts: (channelId: string | undefined) => void;
|
||||
showChannelMembers: (channelId: string) => void;
|
||||
getChannelStats: (channelId: string) => Promise<{data: ChannelStats}>;
|
||||
};
|
||||
}
|
||||
|
||||
const Menu = ({channel, channelStats, isArchived, className, actions}: MenuProps) => {
|
||||
const {formatMessage} = useIntl();
|
||||
const [loadingStats, setLoadingStats] = useState(true);
|
||||
|
||||
const showNotificationPreferences = channel.type !== Constants.DM_CHANNEL && !isArchived;
|
||||
const showMembers = channel.type !== Constants.DM_CHANNEL;
|
||||
const fileCount = channelStats?.files_count >= 0 ? channelStats?.files_count : 0;
|
||||
|
||||
useEffect(() => {
|
||||
actions.getChannelStats(channel.id).then(() => {
|
||||
setLoadingStats(false);
|
||||
});
|
||||
return () => {
|
||||
setLoadingStats(true);
|
||||
};
|
||||
}, [channel.id]);
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -135,7 +152,7 @@ const Menu = ({channel, channelStats, isArchived, className, actions}: MenuProps
|
||||
icon={<i className='icon icon-file-text-outline'/>}
|
||||
text={formatMessage({id: 'channel_info_rhs.menu.files', defaultMessage: 'Files'})}
|
||||
opensSubpanel={true}
|
||||
badge={channelStats?.files_count}
|
||||
badge={loadingStats ? <LoadingSpinner/> : fileCount}
|
||||
onClick={() => actions.showChannelFiles(channel.id)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,6 @@ import {ChannelTypes, PreferenceTypes, UserTypes} from 'mattermost-redux/action_
|
||||
|
||||
import {Client4} from 'mattermost-redux/client';
|
||||
|
||||
import {General, Preferences} from '../constants';
|
||||
import {CategoryTypes} from 'mattermost-redux/constants/channel_categories';
|
||||
import {MarkUnread} from 'mattermost-redux/constants/channels';
|
||||
|
||||
@@ -25,12 +24,15 @@ import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
|
||||
|
||||
import {ActionFunc, ActionResult, DispatchFunc, GetStateFunc} from 'mattermost-redux/types/actions';
|
||||
|
||||
import {getChannelsIdForTeam, getChannelByName} from 'mattermost-redux/utils/channel_utils';
|
||||
|
||||
import {isMinimumServerVersion} from 'mattermost-redux/utils/helpers';
|
||||
|
||||
import {Channel, ChannelNotifyProps, ChannelMembership, ChannelModerationPatch, ChannelsWithTotalCount, ChannelSearchOpts} from '@mattermost/types/channels';
|
||||
|
||||
import {PreferenceType} from '@mattermost/types/preferences';
|
||||
|
||||
import {getChannelsIdForTeam, getChannelByName} from 'mattermost-redux/utils/channel_utils';
|
||||
import {isMinimumServerVersion} from 'mattermost-redux/utils/helpers';
|
||||
import {General, Preferences} from '../constants';
|
||||
|
||||
import {addChannelToInitialCategory, addChannelToCategory} from './channel_categories';
|
||||
import {logError} from './errors';
|
||||
@@ -1074,11 +1076,11 @@ export function searchGroupChannels(term: string): ActionFunc {
|
||||
});
|
||||
}
|
||||
|
||||
export function getChannelStats(channelId: string): ActionFunc {
|
||||
export function getChannelStats(channelId: string, excludeFilesCount?: boolean): ActionFunc {
|
||||
return async (dispatch: DispatchFunc, getState: GetStateFunc) => {
|
||||
let stat;
|
||||
try {
|
||||
stat = await Client4.getChannelStats(channelId);
|
||||
stat = await Client4.getChannelStats(channelId, excludeFilesCount);
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(error, dispatch, getState);
|
||||
dispatch(logError(error));
|
||||
|
||||
@@ -1782,9 +1782,10 @@ export default class Client4 {
|
||||
);
|
||||
};
|
||||
|
||||
getChannelStats = (channelId: string) => {
|
||||
getChannelStats = (channelId: string, excludeFilesCount = false) => {
|
||||
const param = excludeFilesCount ? `?exclude_files_count=${excludeFilesCount}` : '';
|
||||
return this.doFetch<ChannelStats>(
|
||||
`${this.getChannelRoute(channelId)}/stats`,
|
||||
`${this.getChannelRoute(channelId)}/stats${param}`,
|
||||
{method: 'get'},
|
||||
);
|
||||
};
|
||||
|
||||
Ссылка в новой задаче
Block a user