exclude file count on channel stats api call on from channel header (#22624)

Этот коммит содержится в:
Ashish Dhama
2023-03-29 10:48:32 +05:30
коммит произвёл GitHub
родитель 932790f99a
Коммит 529ab959e2
8 изменённых файлов: 90 добавлений и 24 удалений

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

@@ -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'},
);
};