docbrown/app/javascript/chat/channels.jsx
Mario See faf1c6719b more testing for connect components (#1046)
* adding more tests

- covers article.jsx and elements created from its props and state
- added png as static file that needs stubbing

* video + channelDetails test coverage

* chat + channels tests

* channels cc refactor

* yarn install

* update snapshot and string spacing

* chat.jsx test

mostly tests rendering elements
- does not test imported components, as those are already tested separately
- does not imported functions from actions or utils as those will be tested separately as well

* cleaning up

- mocked response with flush promises for state/component to reflect appropriate changes

* snapshot updates
2018-11-19 15:07:54 -05:00

185 lines
5.1 KiB
JavaScript

import { h } from 'preact';
import PropTypes from 'prop-types';
import ConfigImage from 'images/three-dots.svg';
import GroupImage from 'images/organization.svg';
const Channels = ({
activeChannelId,
chatChannels,
handleSwitchChannel,
expanded,
filterQuery,
channelsLoaded,
incomingVideoCallChannelIds,
}) => {
const channels = chatChannels.map(channel => {
if (!channel) {
return;
}
const isActive = parseInt(activeChannelId, 10) === channel.id;
let lastOpened = channel.last_opened_at;
if (!lastOpened) {
if (channel.channel_users[window.currentUser.username]) {
lastOpened =
channel.channel_users[window.currentUser.username].last_opened_at;
} else {
lastOpened = new Date();
}
}
const isUnopened =
new Date(channel.last_message_at) > new Date(lastOpened) &&
channel.messages_count > 0;
const otherClassname = isActive
? 'chatchanneltab--active'
: 'chatchanneltab--inactive';
const name =
channel.channel_type === 'direct'
? `@${channel.slug
.replace(`${window.currentUser.username}/`, '')
.replace(`/${window.currentUser.username}`, '')}`
: channel.channel_name;
const newMessagesIndicatorClass = isUnopened ? 'new' : 'old';
const modififedSlug =
channel.channel_type === 'direct' ? name : channel.slug;
const indicatorPic =
channel.channel_type === 'direct' ? (
<img
alt={channel.channel_name}
src={channel.channel_users[name.replace('@', '')].profile_image}
className="chatchanneltabindicatordirectimage"
/>
) : (
<img alt={channel.channel_name} src={GroupImage} />
);
let channelColor = 'transparent';
if (channel.channel_type === 'direct' && isActive) {
channelColor = channel.channel_users[name.replace('@', '')].darker_color;
} else if (isActive) {
channelColor = '#4e57ef';
}
let content = '';
const contentInner = (
<span
data-channel-slug={modififedSlug}
className={`chatchanneltabindicator chatchanneltabindicator--${newMessagesIndicatorClass}`}
data-channel-id={channel.id}
>
{indicatorPic}
</span>
);
if (expanded) {
content = (
<span>
{contentInner}
{name}
</span>
);
} else if (channel.channel_type === 'direct') {
content = contentInner;
} else {
content = name;
}
let callIndicator = '';
if (
incomingVideoCallChannelIds &&
incomingVideoCallChannelIds.includes(channel.id)
) {
callIndicator = (
<span
role="img"
aria-label="emoji"
className="chatchanneltabindicator chatchanneltabindicator--phone"
>
📞
</span>
);
}
return (
<button
type="button"
key={channel.id}
className="chatchanneltabbutton"
onClick={handleSwitchChannel}
data-channel-id={channel.id}
data-channel-slug={modififedSlug}
>
<span
className={`chatchanneltab ${otherClassname} chatchanneltab--${newMessagesIndicatorClass}`}
data-channel-id={channel.id}
data-channel-slug={modififedSlug}
style={{
border: `1px solid ${channelColor}`,
boxShadow: `3px 3px 0px ${channelColor}`,
}}
>
{callIndicator}
{content}
</span>
</button>
);
});
let channelsListFooter = '';
if (channels.length === 30) {
channelsListFooter = (
<div className="chatchannels__channelslistfooter">...</div>
);
}
let topNotice = '';
if (
expanded &&
filterQuery.length === 0 &&
channelsLoaded &&
(channels.length === 0 || channels[0].messages_count === 0)
) {
topNotice = (
<div className="chatchannels__channelslistheader">
<span role="img" aria-label="emoji">
👋
</span>
{' '}
Welcome to
<b> DEV Connect</b>
! You may message anyone you mutually follow.
</div>
);
}
let configFooter = '';
if (expanded) {
configFooter = (
<div className="chatchannels__config">
<img alt="" src={ConfigImage} style={{ height: '18px' }} />
<div className="chatchannels__configmenu">
<a href="/settings">DEV Settings</a>
<a href="/report-abuse">Report Abuse</a>
</div>
</div>
);
}
return (
<div className="chatchannels">
<div
className="chatchannels__channelslist"
id="chatchannels__channelslist"
>
{topNotice}
{channels}
{channelsListFooter}
</div>
{configFooter}
</div>
);
};
Channels.propTypes = {
activeChannelId: PropTypes.number.isRequired,
chatChannels: PropTypes.array.isRequired,
handleSwitchChannel: PropTypes.func.isRequired,
expanded: PropTypes.bool.isRequired,
filterQuery: PropTypes.string.isRequired,
channelsLoaded: PropTypes.bool.isRequired,
incomingVideoCallChannelIds: PropTypes.array.isRequired,
};
export default Channels;