Skip to content

Commit

Permalink
fix(client): restrict log height
Browse files Browse the repository at this point in the history
* refactor log for resizing to work like properties container resizing
* log has maximum height of 300

Closes #2258
  • Loading branch information
philippfromme committed Oct 12, 2021
1 parent 24eeed7 commit cad2f17
Show file tree
Hide file tree
Showing 8 changed files with 399 additions and 264 deletions.
2 changes: 1 addition & 1 deletion client/src/app/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -1955,7 +1955,7 @@ export class App extends PureComponent {

<Log
entries={ logEntries }
layout={ layout.log }
layout={ layout }
onClear={ this.clearLog }
onLayoutChanged={ this.handleLayoutChanged }
onUpdateMenu={ this.updateMenu }
Expand Down
204 changes: 127 additions & 77 deletions client/src/app/Log.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import css from './Log.less';

import classNames from 'classnames';

import { isFunction } from 'min-dash';

import { Fill } from './slot-fill';

import dragger from '../util/dom/dragger';
Expand All @@ -22,95 +24,129 @@ import {
throttle
} from '../util';

const DEFAULT_LAYOUT = {
export const DEFAULT_LAYOUT = {
height: 130,
open: false
};

export const MIN_HEIGHT = 25;
export const MAX_HEIGHT = 300;

export const KEYCODE_ESCAPE = 27;


/**
* A log component
* A log component.
*
* <Log
* entries={ [ { message, category }, ... ] }
* layout={ height, open }
* layout={ { log: { height, open } } }
* onClear={ () => { } }
* onLayoutChanged= { () => { } }
* onUpdateMenu = { () => { } } />
*
*/
export default class Log extends PureComponent {
static defaultProps = {
entries: [],
layout: DEFAULT_LAYOUT
};

constructor(props) {
super(props);

this.panelRef = React.createRef();

this.handleResize = throttle(this.handleResize);
}

changeLayout = (newLayout) => {
this.props.onLayoutChanged({
log: newLayout
});
}

toggle = () => {
const {
layout
} = this.props;
this.ref = new React.createRef();
this.focusRef = React.createRef();

this.changeLayout({
...layout,
open: !layout.open
});
this.context = {};
}

handleResizeStart = event => {
handleResizeStart = (event) => {
const onDragStart = dragger(this.handleResize);

this.originalHeight = this.currentHeight;

onDragStart(event);

const {
height,
open
} = getLayoutFromProps(this.props);

this.context = {
open,
startHeight: height
};
}

handleResize = (_, delta) => {
const {
y
} = delta;
const { y: dy } = delta;

if (y === 0) {
if (dy === 0) {
return;
}

const newHeight = this.originalHeight - y;
const { startHeight } = this.context;

const open = newHeight > 25;
const {
height,
open
} = getLayout(dy, startHeight);

const height = open ? newHeight : DEFAULT_LAYOUT.height;
this.context = {
...this.context,
height,
open
};

if (this.ref.current) {
this.ref.current.classList.toggle('open', open);
this.ref.current.style.height = `${ open ? height : 0 }px`;
}
}

handleResizeEnd = () => {
const {
height,
open
} = this.context;

this.context = {};

this.changeLayout({
open,
height
log: {
height,
open
}
});
}

checkFocus = () => {
handleToggle = () => {
const { layout = {} } = this.props;

const panel = this.panelRef.current;
const { log = {} } = layout;

const {
entries
} = this.props;
this.changeLayout({
log: {
...DEFAULT_LAYOUT,
...log,
open: !log.open
}
});
}

changeLayout = (layout = {}) => {
const { onLayoutChanged } = this.props;

if (isFunction(onLayoutChanged)) {
onLayoutChanged(layout);
}
}

checkFocus = () => {
const panel = this.focusRef.current;

const { entries } = this.props;

const lastIdx = entries.length - 1;

if (lastIdx !== -1) {
const node = panel.querySelector(`*[data-idx='${lastIdx}']`);
const node = panel.querySelector(`*[data-idx='${ lastIdx }']`);

node.scrollIntoView();
}
Expand All @@ -128,37 +164,23 @@ export default class Log extends PureComponent {
}

handleKeyDown = (event) => {
const { keyCode } = event;

const {
keyCode,
ctrlKey,
metaKey
} = event;

if (keyCode === 27) { // ESC
if (keyCode === KEYCODE_ESCAPE) {
event.preventDefault();

return this.toggle();
}

if (keyCode === 65 && (ctrlKey || metaKey)) { // <A>
event.preventDefault();

return this.handleCopy();
return this.handleToggle();
}
}

handleCopy = (event) => {
selectText(this.panelRef.current);
handleCopy = () => {
selectText(this.focusRef.current);

document.execCommand('copy');
}

updateMenu = () => {

const {
onUpdateMenu
} = this.props;
const { onUpdateMenu } = this.props;

const enabled = hasSelection();

Expand Down Expand Up @@ -197,19 +219,15 @@ export default class Log extends PureComponent {
}

render() {

const {
entries,
layout,
entries = [],
onClear
} = this.props;

const {
height,
open
} = layout;

this.currentHeight = height;
} = getLayoutFromProps(this.props);

return (
<div
Expand All @@ -223,7 +241,7 @@ export default class Log extends PureComponent {
<button
className={ classNames('btn', 'toggle-button', { 'btn--active': open }) }
title="Toggle log"
onClick={ this.toggle }
onClick={ this.handleToggle }
>Log</button>
</Fill>

Expand All @@ -236,12 +254,13 @@ export default class Log extends PureComponent {
></div>
<div
className="body"
ref={ this.ref }
style={ { height } }>

<div
tabIndex="0"
className="entries"
ref={ this.panelRef }
ref={ this.focusRef }
onKeyDown={ this.handleKeyDown }
onFocus={ this.updateMenu }
>
Expand All @@ -259,7 +278,7 @@ export default class Log extends PureComponent {
category
} = entry;

var msg;
let msg;

if (message) {
msg = message;
Expand Down Expand Up @@ -295,19 +314,50 @@ export default class Log extends PureComponent {
}


// helpers //////////

function getLayout(dy, initialHeight) {
let height = Math.min(initialHeight - dy, MAX_HEIGHT);

const open = height >= MIN_HEIGHT;

if (!open) {
height = DEFAULT_LAYOUT.height;
}

return {
height,
open
};
}

function getLayoutFromProps(props) {
const layout = props.layout || {};

const log = layout.log || DEFAULT_LAYOUT;

const { open } = log;

const height = open ? log.height : 0;

// helpers /////////////////////////////////
return {
height,
open
};
}

function hasSelection() {
return window.getSelection().toString() !== '';
}

function selectText(element) {
let range, selection;

selection = window.getSelection();

range = document.createRange();
range.selectNodeContents(element);

selection.removeAllRanges();
selection.addRange(range);
}

function hasSelection() {
return window.getSelection().toString() !== '';
}
2 changes: 2 additions & 0 deletions client/src/app/Log.less
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
flex-direction: column;
flex: none;

z-index: 100;

.header {
display: flex;
justify-content: flex-end;
Expand Down
4 changes: 2 additions & 2 deletions client/src/app/__tests__/AppSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1660,7 +1660,7 @@ describe('<App>', function() {
const log = tree.find(Log).first();

// then
expect(log.props().layout.open).to.be.true;
expect(log.props().layout.log.open).to.be.true;
});


Expand All @@ -1685,7 +1685,7 @@ describe('<App>', function() {
category: 'bar'
}]);

expect(log.props().layout.open).to.be.true;
expect(log.props().layout.log.open).to.be.true;
});

});
Expand Down
Loading

0 comments on commit cad2f17

Please sign in to comment.