Skip to content
This repository was archived by the owner on Oct 11, 2022. It is now read-only.
Closed
193 changes: 103 additions & 90 deletions src/components/composer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import { LoadingSelect } from '../loading';
import Titlebar from '../../views/titlebar';
import type { Dispatch } from 'redux';
import {
ComposerSlider,
Overlay,
Container,
ThreadDescription,
ThreadTitle,
Expand Down Expand Up @@ -339,8 +341,9 @@ class ComposerWithData extends Component<Props, State> {
}
};

onCancelClick = () => {
this.activateLastThread();
onCancelClick = async () => {
await this.activateLastThread();
this.props.dispatch(closeComposer());
};

handleTitleBodyChange = titleOrBody => {
Expand Down Expand Up @@ -493,6 +496,8 @@ class ComposerWithData extends Component<Props, State> {
postWasPublished: true,
});

this.props.dispatch(closeComposer());

// redirect the user to the thread
// if they are in the inbox, select it
this.props.dispatch(
Expand Down Expand Up @@ -530,8 +535,10 @@ class ComposerWithData extends Component<Props, State> {
const {
data: { user },
threadSliderIsOpen,
isOpen,
networkOnline,
websocketConnection,
isSlider,
} = this.props;
const dataExists = user && availableCommunities && availableChannels;

Expand All @@ -541,98 +548,104 @@ class ComposerWithData extends Component<Props, State> {
websocketConnection !== 'reconnected');

return (
<Container>
<Titlebar provideBack title={'New conversation'} noComposer />
<Dropdowns>
<span>To:</span>
{!dataExists ? (
<LoadingSelect />
) : (
<RequiredSelector
data-cy="composer-community-selector"
onChange={this.setActiveCommunity}
value={activeCommunity}
>
{availableCommunities.map(community => {
return (
<option key={community.id} value={community.id}>
{community.name}
</option>
);
})}
</RequiredSelector>
)}
{!dataExists ? (
<LoadingSelect />
) : (
<RequiredSelector
data-cy="composer-channel-selector"
onChange={this.setActiveChannel}
value={activeChannel}
>
{availableChannels
.filter(channel => channel.community.id === activeCommunity)
.map(channel => {
<ComposerSlider isSlider={isSlider} isOpen={isOpen}>
<Overlay
isOpen={isOpen}
onClick={this.closeComposer}
data-cy="thread-composer-overlay"
/>
<Container>
<Titlebar provideBack title={'New conversation'} noComposer />
<Dropdowns>
<span>To:</span>
{!dataExists ? (
<LoadingSelect />
) : (
<RequiredSelector
data-cy="composer-community-selector"
onChange={this.setActiveCommunity}
value={activeCommunity}
>
{availableCommunities.map(community => {
return (
<option key={channel.id} value={channel.id}>
{channel.name}
<option key={community.id} value={community.id}>
{community.name}
</option>
);
})}
</RequiredSelector>
)}
</Dropdowns>
<ThreadInputs>
<Textarea
data-cy="composer-title-input"
onChange={this.changeTitle}
style={ThreadTitle}
value={this.state.title}
placeholder={"What's up?"}
ref={'titleTextarea'}
autoFocus={!threadSliderIsOpen}
/>

<Editor
version={2}
onChange={this.changeBody}
state={this.state.body}
style={ThreadDescription}
editorRef={editor => (this.bodyEditor = editor)}
editorKey="thread-composer"
placeholder={'Write more thoughts here...'}
className={'threadComposer'}
/>
</ThreadInputs>

<Actions>
{networkDisabled && (
<DisabledWarning>
Lost connection to the internet or server...
</DisabledWarning>
)}

<FlexRow>
<TextButton hoverColor="warn.alt" onClick={this.onCancelClick}>
Cancel
</TextButton>
<Button
data-cy="composer-publish-button"
onClick={this.publishThread}
loading={isPublishing}
disabled={
!title ||
title.trim().length === 0 ||
isPublishing ||
networkDisabled
}
color={'brand'}
>
Publish
</Button>
</FlexRow>
</Actions>
</Container>
</RequiredSelector>
)}
{!dataExists ? (
<LoadingSelect />
) : (
<RequiredSelector
data-cy="composer-channel-selector"
onChange={this.setActiveChannel}
value={activeChannel}
>
{availableChannels
.filter(channel => channel.community.id === activeCommunity)
.map(channel => {
return (
<option key={channel.id} value={channel.id}>
{channel.name}
</option>
);
})}
</RequiredSelector>
)}
</Dropdowns>
<ThreadInputs>
<Textarea
data-cy="composer-title-input"
onChange={this.changeTitle}
style={ThreadTitle}
value={this.state.title}
placeholder={"What's up?"}
ref={'titleTextarea'}
autoFocus={!threadSliderIsOpen}
/>

<Editor
onChange={this.changeBody}
state={this.state.body}
style={ThreadDescription}
editorRef={editor => (this.bodyEditor = editor)}
editorKey="thread-composer"
placeholder={'Write more thoughts here...'}
className={'threadComposer'}
/>
</ThreadInputs>

<Actions>
{networkDisabled && (
<DisabledWarning>
Lost connection to the internet or server...
</DisabledWarning>
)}

<FlexRow>
<TextButton hoverColor="warn.alt" onClick={this.onCancelClick}>
Cancel
</TextButton>
<Button
data-cy="composer-publish-button"
onClick={this.publishThread}
loading={isPublishing}
disabled={
!title ||
title.trim().length === 0 ||
isPublishing ||
networkDisabled
}
color={'brand'}
>
Publish
</Button>
</FlexRow>
</Actions>
</Container>
</ComposerSlider>
);
}
}
Expand Down
48 changes: 45 additions & 3 deletions src/components/composer/style.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,56 @@
import styled from 'styled-components';
import styled, { css } from 'styled-components';
import theme from 'shared/theme';
import { hexa, Shadow, FlexRow, FlexCol, zIndex } from '../globals';

export const ComposerSlider = styled.div`
display: ${props => (props.isSlider ? 'none' : 'block')};
${props =>
props.isSlider &&
props.isOpen &&
css`
display: block;
position: fixed;
width: 50%;
top: 0;
right: 0;
bottom: 0;
z-index: ${zIndex.composer};
`}
`;

export const Overlay = styled.div`
${props =>
props.isOpen
? `
position: fixed;
top: 48px;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
z-index: 3000;
background: #000;
pointer-events: auto;
opacity: 0.4;
`
: `
opacity: 0;
pointer-events: none;

`};
`;

export const Container = styled(FlexCol)`
background-color: ${theme.bg.default};
display: grid;
grid-template-rows: 60px 1fr 64px;
grid-template-rows: 50px 1fr 64px;
grid-template-columns: 100%;
grid-template-areas: 'header' 'body' 'footer';
align-self: stretch;
flex: auto;
overflow: hidden;
height: calc(100vh - 48px);
height: 100vh;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not change, otherwise the thread composer overflows on /new/thread! (48px is the navbar height)

Suggested change
height: 100vh;
height: calc(100vh - 48px);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh I missed that, probably an idea to only add those styles with the isSlider props, similar to other styles


@media (max-width: 768px) {
grid-template-rows: 48px 64px 1fr 64px;
Expand All @@ -33,6 +72,7 @@ export const Actions = styled(FlexCol)`
align-items: center;
position: relative;
grid-area: footer;
z-index: ${zIndex.composer};

@media (max-width: 768px) {
padding: 8px;
Expand Down Expand Up @@ -122,11 +162,13 @@ export const OptionalSelector = styled(Selector)`
`;

export const ThreadInputs = styled(FlexCol)`
position: relative;
grid-area: body;
overflow-y: scroll;
padding: 64px;
padding-left: 80px;
background-color: ${theme.bg.default};
z-index: ${zIndex.composer};

@media (max-width: 768px) {
max-width: 100vw;
Expand Down
2 changes: 1 addition & 1 deletion src/components/globals/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export const zIndex = new function() {
this.dropDown = this.chrome + 1; // dropDowns shouldn't appear behind the navBar

this.slider = window.innerWidth < 768 ? this.chrome + 1 : this.chrome; // slider should appear significantly above the base to leave room for other elements
this.composer = this.slider - 2; // composer should never appear above the slider
this.composer = 4000; // should cover all screen except toasts
this.chatInput = this.slider + 1; // the slider chatInput should always appear above the slider
this.flyout = this.chatInput + 3; // flyout may overlap with chatInput and should take precedence

Expand Down
Loading