Skip to content

Commit c1cb2e8

Browse files
feat: collapse big messages (#810)
* Updating Message component to add ability to collapse long running messages. Height is broadcast out to parent on height toggle. See: #790 * Cleanup of the Message component including simplifying the read-more expand/collapse functionality. * fix: cleanup & properly updating the height --------- Co-authored-by: Jannis Mattheis <contact@jmattheis.de>
1 parent 2498e6e commit c1cb2e8

File tree

1 file changed

+64
-6
lines changed

1 file changed

+64
-6
lines changed

ui/src/message/Message.tsx

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
1+
import {Button} from '@material-ui/core';
12
import IconButton from '@material-ui/core/IconButton';
23
import {createStyles, Theme, withStyles, WithStyles} from '@material-ui/core/styles';
34
import Typography from '@material-ui/core/Typography';
5+
import {ExpandLess, ExpandMore} from '@material-ui/icons';
46
import Delete from '@material-ui/icons/Delete';
5-
import React from 'react';
7+
import React, {RefObject} from 'react';
68
import TimeAgo from 'react-timeago';
79
import Container from '../common/Container';
8-
import * as config from '../config';
910
import {Markdown} from '../common/Markdown';
10-
import {RenderMode, contentType} from './extras';
11+
import * as config from '../config';
1112
import {IMessageExtras} from '../types';
13+
import {contentType, RenderMode} from './extras';
14+
15+
const PREVIEW_LENGTH = 500;
1216

1317
const styles = (theme: Theme) =>
1418
createStyles({
@@ -52,7 +56,12 @@ const styles = (theme: Theme) =>
5256
whiteSpace: 'pre-wrap',
5357
},
5458
content: {
59+
maxHeight: PREVIEW_LENGTH,
5560
wordBreak: 'break-all',
61+
overflowY: 'hidden',
62+
'&.expanded': {
63+
maxHeight: 'none',
64+
},
5665
'& p': {
5766
margin: 0,
5867
},
@@ -79,6 +88,11 @@ interface IProps {
7988
height: (height: number) => void;
8089
}
8190

91+
interface IState {
92+
expanded: boolean;
93+
isOverflowing: boolean;
94+
}
95+
8296
const priorityColor = (priority: number) => {
8397
if (priority >= 4 && priority <= 7) {
8498
return 'rgba(230, 126, 34, 0.7)';
@@ -89,14 +103,39 @@ const priorityColor = (priority: number) => {
89103
}
90104
};
91105

92-
class Message extends React.PureComponent<IProps & WithStyles<typeof styles>> {
106+
class Message extends React.PureComponent<IProps & WithStyles<typeof styles>, IState> {
107+
public state = {expanded: false, isOverflowing: false};
93108
private node: HTMLDivElement | null = null;
109+
private previewRef: RefObject<HTMLDivElement>;
110+
111+
constructor(props: IProps & WithStyles<typeof styles>) {
112+
super(props);
113+
this.previewRef = React.createRef();
114+
}
94115

95-
public componentDidMount = () =>
116+
public componentDidMount = () => {
117+
if (this.previewRef.current) {
118+
this.setState({
119+
isOverflowing:
120+
this.previewRef.current.scrollHeight > this.previewRef.current.clientHeight,
121+
});
122+
}
123+
this.updateHeightInParent();
124+
};
125+
126+
public togglePreviewHeight = () => {
127+
this.setState(
128+
(state) => ({expanded: !state.expanded}),
129+
() => this.updateHeightInParent()
130+
);
131+
};
132+
133+
private updateHeightInParent = () =>
96134
this.props.height(this.node ? this.node.getBoundingClientRect().height : 0);
97135

98136
private renderContent = () => {
99137
const content = this.props.content;
138+
100139
switch (contentType(this.props.extras)) {
101140
case RenderMode.Markdown:
102141
return <Markdown>{content}</Markdown>;
@@ -114,6 +153,7 @@ class Message extends React.PureComponent<IProps & WithStyles<typeof styles>> {
114153
<Container
115154
style={{
116155
display: 'flex',
156+
flexWrap: 'wrap',
117157
borderLeftColor: priorityColor(priority),
118158
borderLeftWidth: 6,
119159
borderLeftStyle: 'solid',
@@ -141,10 +181,28 @@ class Message extends React.PureComponent<IProps & WithStyles<typeof styles>> {
141181
<Delete />
142182
</IconButton>
143183
</div>
144-
<Typography component="div" className={`${classes.content} content`}>
184+
185+
<Typography
186+
component="div"
187+
ref={this.previewRef}
188+
className={`${classes.content} content ${
189+
this.state.isOverflowing && this.state.expanded ? 'expanded' : ''
190+
}`}>
145191
{this.renderContent()}
146192
</Typography>
147193
</div>
194+
{this.state.isOverflowing && (
195+
<Button
196+
style={{marginTop: 16}}
197+
onClick={() => this.togglePreviewHeight()}
198+
variant="contained"
199+
color="primary"
200+
size="large"
201+
fullWidth={true}
202+
startIcon={this.state.expanded ? <ExpandLess /> : <ExpandMore />}>
203+
{this.state.expanded ? 'Read Less' : 'Read More'}
204+
</Button>
205+
)}
148206
</Container>
149207
</div>
150208
);

0 commit comments

Comments
 (0)