fix mention in chat (#10493)

* fix mention in chat

* fix mention bug

* fix conflict issue

* fix load channel issue initally render

* add test case

* remove comments and add nitpick
This commit is contained in:
narender2031 2020-12-23 16:51:28 +05:30 committed by GitHub
parent 254b8334a5
commit 01f7dbd24f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 48 additions and 15 deletions

View file

@ -1066,7 +1066,7 @@
display: none;
z-index: 1;
border-top: 1px solid #dbdbdb;
bottom: 60px;
bottom: 90px;
width: 100%;
max-height: 280px;
overflow-x: scroll;

View file

@ -59,7 +59,7 @@ class SearchController < ApplicationController
def chat_channels
search_user_id = if chat_channel_params[:user_id].present?
[current_user.id, SiteConfig.mascot_user_id]
[current_user.id, SiteConfig.mascot_user_id, chat_channel_params[:user_id]].reject(&:blank?)
else
[current_user.id]
end

View file

@ -1,5 +1,5 @@
import { h } from 'preact';
import { render } from '@testing-library/preact';
import { fireEvent, render } from '@testing-library/preact';
import fetch from 'jest-fetch-mock';
import { JSDOM } from 'jsdom';
import { axe } from 'jest-axe';
@ -226,4 +226,19 @@ describe('<Chat />', () => {
}),
).toBeDefined();
});
it('should show mention pop-up on keyUp @', async () => {
const { getByLabelText, getByTestId } = render(<Chat {...getRootData()} />);
const inputField = getByLabelText('Compose a message');
expect(inputField).toBeDefined();
fireEvent.change(inputField, { target: { value: '@' } });
const mentionModal = getByTestId('mentionList');
const allButton = getByTestId('all');
expect(mentionModal).toBeDefined();
expect(allButton).toBeDefined();
});
});

View file

@ -261,7 +261,7 @@ export default class Chat extends Component {
activeChannel ||
this.filterForActiveChannel(channels, activeChannelId),
});
this.setupChannel(activeChannelId);
this.setupChannel(activeChannelId, activeChannel);
} else if (activeChannelId) {
this.setState({
scrolled: false,
@ -273,7 +273,7 @@ export default class Chat extends Component {
activeChannel ||
this.filterForActiveChannel(channels, activeChannelId),
});
this.setupChannel(activeChannelId);
this.setupChannel(activeChannelId, activeChannel);
} else if (channels.length > 0) {
this.setState({
chatChannels: channels,
@ -288,6 +288,7 @@ export default class Chat extends Component {
channels[0].channel_modified_slug,
channels,
);
this.setupChannels(channels);
} else {
this.setState({ channelsLoaded: true });
}
@ -323,9 +324,10 @@ export default class Chat extends Component {
};
setupChannels = (channels) => {
const { activeChannel } = this.state;
channels.forEach((channel, index) => {
if (index < 3) {
this.setupChannel(channel.chat_channel_id);
this.setupChannel(channel.chat_channel_id, activeChannel);
}
});
};
@ -353,8 +355,8 @@ export default class Chat extends Component {
});
};
setupChannel = (channelId) => {
const { messages, messageOffset, activeChannel, appDomain } = this.state;
setupChannel = (channelId, activeChannel) => {
const { messages, messageOffset, appDomain } = this.state;
if (
!messages[channelId] ||
messages[channelId].length === 0 ||
@ -362,7 +364,11 @@ export default class Chat extends Component {
) {
getAllMessages(channelId, messageOffset, this.receiveAllMessages);
}
if (activeChannel && activeChannel.channel_type !== 'direct') {
if (
activeChannel &&
activeChannel.channel_type !== 'direct' &&
activeChannel.chat_channel_id === channelId
) {
getContent(
`/chat_channels/${channelId}/channel_info`,
this.setOpenChannelUsers,
@ -822,21 +828,26 @@ export default class Chat extends Component {
if (index > -1) {
newUnopenedChannelIds.splice(index, 1);
}
let updatedActiveChannel = this.filterForActiveChannel(
channelList,
id,
currentUserId,
);
this.setState({
activeChannel: this.filterForActiveChannel(
channelList,
id,
currentUserId,
),
activeChannel: updatedActiveChannel,
activeChannelId: parseInt(id, 10),
scrolled: false,
showAlert: false,
allMessagesLoaded: false,
showMemberlist: false,
unopenedChannelIds: unopenedChannelIds.filter(
(unopenedId) => unopenedId !== id,
),
});
this.setupChannel(id);
this.setupChannel(id, updatedActiveChannel);
const params = new URLSearchParams(window.location.search);
if (params.get('ref') === 'group_invite') {
@ -1231,6 +1242,7 @@ export default class Chat extends Component {
<Button
data-channel-type={type}
onClick={this.triggerChannelTypeFilter}
data-testid={name}
className={`chat__channeltypefilterbutton crayons-indicator crayons-indicator--${
type === active ? 'accent' : ''
}`}
@ -1634,6 +1646,8 @@ export default class Chat extends Component {
const { activeChannel } = this.state;
const mention = e.keyCode === 64;
if (mention && activeChannel.channel_type !== 'direct') {
const memberListElement = document.getElementById('mentionList');
memberListElement.focus();
this.setState({ showMemberlist: true });
}
};
@ -1687,6 +1701,7 @@ export default class Chat extends Component {
el.value = `${before + name} ${after}`;
el.selectionStart = start + name.length + 1;
el.selectionEnd = start + name.length + 1;
el.dispatchEvent(new Event('input'));
el.focus();
this.setState({ showMemberlist: false });
};
@ -1745,13 +1760,16 @@ export default class Chat extends Component {
channelUsers,
memberFilterQuery,
} = this.state;
const filterRegx = new RegExp(memberFilterQuery, 'gi');
return (
<div
className={
showMemberlist ? 'mention__list mention__visible' : 'mention__list'
}
id="mentionList"
data-testid="mentionList"
>
{showMemberlist
? Object.values(channelUsers[activeChannelId])