Skip to content
This repository has been archived by the owner on Mar 13, 2024. It is now read-only.

Sidebar reorganization #1374

Merged
merged 19 commits into from
Aug 1, 2018
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 27 additions & 10 deletions components/more_channels/more_channels.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export default class MoreChannels extends React.Component {
teamName: PropTypes.string.isRequired,
onModalDismissed: PropTypes.func,
handleNewChannel: PropTypes.func,
bodyOnly: PropTypes.bool,
actions: PropTypes.shape({
getChannels: PropTypes.func.isRequired,
}).isRequired,
Expand All @@ -50,6 +51,10 @@ export default class MoreChannels extends React.Component {

handleHide = () => {
this.setState({show: false});

if (this.props.bodyOnly) {
this.handleExit();
}
}

handleExit = () => {
Expand Down Expand Up @@ -125,6 +130,7 @@ export default class MoreChannels extends React.Component {
const {
channels,
teamId,
bodyOnly,
} = this.props;

const {
Expand Down Expand Up @@ -172,6 +178,26 @@ export default class MoreChannels extends React.Component {
</TeamPermissionGate>
);

const body = (
<React.Fragment>
<SearchableChannelList
channels={search ? searchedChannels : channels}
channelsPerPage={CHANNELS_PER_PAGE}
nextPage={this.nextPage}
isSearch={search}
search={this.search}
handleJoin={this.handleJoin}
noResultsText={createChannelHelpText}
createChannelButton={bodyOnly && createNewChannelButton}
/>
{serverError}
</React.Fragment>
);

if (bodyOnly) {
return body;
}

return (
<Modal
dialogClassName='more-modal more-modal--action'
Expand All @@ -189,16 +215,7 @@ export default class MoreChannels extends React.Component {
{createNewChannelButton}
</Modal.Header>
<Modal.Body>
<SearchableChannelList
channels={search ? searchedChannels : channels}
channelsPerPage={CHANNELS_PER_PAGE}
nextPage={this.nextPage}
isSearch={search}
search={this.search}
handleJoin={this.handleJoin}
noResultsText={createChannelHelpText}
/>
{serverError}
{body}
</Modal.Body>
</Modal>
);
Expand Down
60 changes: 36 additions & 24 deletions components/more_direct_channels/more_direct_channels.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export default class MoreDirectChannels extends React.Component {
restrictDirectMessage: PropTypes.string,
onModalDismissed: PropTypes.func,
onHide: PropTypes.func,

bodyOnly: PropTypes.bool,
actions: PropTypes.shape({
getProfiles: PropTypes.func.isRequired,
getProfilesInTeam: PropTypes.func.isRequired,
Expand Down Expand Up @@ -133,6 +133,10 @@ export default class MoreDirectChannels extends React.Component {
handleHide = () => {
this.props.actions.setModalSearchTerm('');
this.setState({show: false});

if (this.props.bodyOnly) {
this.handleExit();
}
}

setUsersLoadingState = (loadingState) => {
Expand Down Expand Up @@ -353,6 +357,36 @@ export default class MoreDirectChannels extends React.Component {
users = active.concat(inactive);
}

const body = (
<MultiSelect
key='moreDirectChannelsList'
ref='multiselect'
options={users}
optionRenderer={this.renderOption}
values={this.state.values}
valueKey='id'
valueRenderer={this.renderValue}
perPage={USERS_PER_PAGE}
handlePageChange={this.handlePageChange}
handleInput={this.search}
handleDelete={this.handleDelete}
handleAdd={this.addValue}
handleSubmit={this.handleSubmit}
noteText={note}
maxValues={MAX_SELECTABLE_VALUES}
numRemainingText={numRemainingText}
buttonSubmitText={buttonSubmitText}
buttonSubmitLoadingText={buttonSubmitLoadingText}
submitImmediatelyOn={this.handleSubmitImmediatelyOn}
saving={this.state.saving}
loading={this.state.loadingUsers}
/>
);

if (this.props.bodyOnly) {
return body;
}

return (
<Modal
dialogClassName={'more-modal more-direct-channels'}
Expand All @@ -369,29 +403,7 @@ export default class MoreDirectChannels extends React.Component {
</Modal.Title>
</Modal.Header>
<Modal.Body>
<MultiSelect
key='moreDirectChannelsList'
ref='multiselect'
options={users}
optionRenderer={this.renderOption}
values={this.state.values}
valueKey='id'
valueRenderer={this.renderValue}
perPage={USERS_PER_PAGE}
handlePageChange={this.handlePageChange}
handleInput={this.search}
handleDelete={this.handleDelete}
handleAdd={this.addValue}
handleSubmit={this.handleSubmit}
noteText={note}
maxValues={MAX_SELECTABLE_VALUES}
numRemainingText={numRemainingText}
buttonSubmitText={buttonSubmitText}
buttonSubmitLoadingText={buttonSubmitLoadingText}
submitImmediatelyOn={this.handleSubmitImmediatelyOn}
saving={this.state.saving}
loading={this.state.loadingUsers}
/>
{body}
</Modal.Body>
</Modal>
);
Expand Down
32 changes: 28 additions & 4 deletions components/searchable_channel_list.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,24 @@ export default class SearchableChannelList extends React.Component {
}
}

return (
<div className='filtered-user-list'>
<div className='filter-row'>
<div className='col-sm-12'>
let input = (
<div className='filter-row filter-row--full'>
<div className='col-sm-12'>
<QuickInput
id='searchChannelsTextbox'
ref='filter'
className='form-control filter-textbox'
placeholder={localizeMessage('filtered_channels_list.search', 'Search channels')}
onInput={this.doSearch}
/>
</div>
</div>
);

if (this.props.createChannelButton) {
input = (
<div className='channel_search'>
<div className='search_input'>
<QuickInput
id='searchChannelsTextbox'
ref='filter'
Expand All @@ -193,7 +207,16 @@ export default class SearchableChannelList extends React.Component {
onInput={this.doSearch}
/>
</div>
<div className='create_button'>
{this.props.createChannelButton}
</div>
</div>
);
}

return (
<div className='filtered-user-list'>
{input}
<div
ref='channelList'
className='more-modal__list'
Expand Down Expand Up @@ -224,4 +247,5 @@ SearchableChannelList.propTypes = {
search: PropTypes.func.isRequired,
handleJoin: PropTypes.func.isRequired,
noResultsText: PropTypes.object,
createChannelButton: PropTypes.element,
};
175 changes: 175 additions & 0 deletions components/sidebar/channel_create.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import React from 'react';
import Permissions from 'mattermost-redux/constants/permissions';
import {OverlayTrigger, Tooltip} from 'react-bootstrap';
import {FormattedMessage} from 'react-intl';
import {PropTypes} from 'prop-types';

import TeamPermissionGate from 'components/permissions_gates/team_permission_gate';

import * as Utils from 'utils/utils.jsx';

export default class ChannelCreate extends React.PureComponent {
static propTypes = {
channelType: PropTypes.string.isRequired,
teamId: PropTypes.string.isRequired,
createPublicChannel: PropTypes.func.isRequired,
createPrivateChannel: PropTypes.func.isRequired,
createDirectMessage: PropTypes.func.isRequired,
createPublicDirectChannel: PropTypes.func.isRequired,
};

render() {
const {
channelType,
teamId,
createPublicChannel,
createPrivateChannel,
createDirectMessage,
createPublicDirectChannel,
} = this.props;

let tooltipTriggers = ['hover', 'focus'];

if (Utils.isMobile()) {
tooltipTriggers = [];
}

const createChannelTootlip = (
<Tooltip id='new-channel-tooltip' >
<FormattedMessage
id='sidebar.createChannel'
defaultMessage='Create new public channel'
/>
</Tooltip>
);
const createGroupTootlip = (
<Tooltip id='new-group-tooltip'>
<FormattedMessage
id='sidebar.createGroup'
defaultMessage='Create new private channel'
/>
</Tooltip>
);

const createDirectMessageTooltip = (
<Tooltip
id='new-group-tooltip'
className='hidden-xs'
>
<FormattedMessage
id='sidebar.createDirectMessage'
defaultMessage='Create new direct message'
/>
</Tooltip>
);

const createPublicChannelIcon = (
<OverlayTrigger
trigger={tooltipTriggers}
delayShow={500}
placement='top'
overlay={createChannelTootlip}
>
<button
id='createPublicChannel'
className='add-channel-btn cursor--pointer style--none'
onClick={createPublicChannel}
>
{'+'}
</button>
</OverlayTrigger>
);

const createPrivateChannelIcon = (
<OverlayTrigger
trigger={tooltipTriggers}
delayShow={500}
placement='top'
overlay={createGroupTootlip}
>
<button
id='createPrivateChannel'
className='add-channel-btn cursor--pointer style--none'
onClick={createPrivateChannel}
>
{'+'}
</button>
</OverlayTrigger>
);

const createDirectMessageIcon = (
<OverlayTrigger
className='hidden-xs'
delayShow={500}
placement='top'
overlay={createDirectMessageTooltip}
>
<button
className='add-channel-btn cursor--pointer style--none'
onClick={createDirectMessage}
>
{'+'}
</button>
</OverlayTrigger>
);

const createPublicDirectChannelTooltip = (
<Tooltip
id='new-group-tooltip'
className='hidden-xs'
>
<FormattedMessage
id='sidebar.createChannelDirectChannel'
defaultMessage='Create new channel or direct message'
/>
</Tooltip>
);

const createPublicDirectChannelIcon = (
<OverlayTrigger
className='hidden-xs'
delayShow={500}
placement='top'
overlay={createPublicDirectChannelTooltip}
>
<button
className='add-channel-btn cursor--pointer style--none'
onClick={createPublicDirectChannel}
>
{'+'}
</button>
</OverlayTrigger>
);

switch (channelType) {
case 'public':
return (
<TeamPermissionGate
teamId={teamId}
permissions={[Permissions.CREATE_PUBLIC_CHANNEL]}
>
{createPublicChannelIcon}
</TeamPermissionGate>
);
case 'private':
return (
<TeamPermissionGate
teamId={teamId}
permissions={[Permissions.CREATE_PRIVATE_CHANNEL]}
>
{createPrivateChannelIcon}
</TeamPermissionGate>
);
case 'direct':
return createDirectMessageIcon;
case 'recent':
case 'alpha':
return createPublicDirectChannelIcon;
}

return null;
}
}
Loading