From 2b8a5353be9cde505f3ea4076e31cf72aaa06649 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Thu, 29 Nov 2018 12:27:31 +0200 Subject: [PATCH] Fix log live updating and add autoscrolling --- .../frontend/src/pages/dashboard/Log.js | 46 ++++++++++++++++++- .../frontend/src/pages/dashboard/Modal.js | 1 + .../frontend/src/pages/dashboard/index.js | 17 +++---- 3 files changed, 55 insertions(+), 9 deletions(-) diff --git a/maubot/management/frontend/src/pages/dashboard/Log.js b/maubot/management/frontend/src/pages/dashboard/Log.js index 7e710f9..2cbbe31 100644 --- a/maubot/management/frontend/src/pages/dashboard/Log.js +++ b/maubot/management/frontend/src/pages/dashboard/Log.js @@ -113,13 +113,57 @@ class LogEntry extends PureComponent { } class Log extends PureComponent { + constructor(props) { + super(props) + + this.linesRef = React.createRef() + this.linesBottomRef = React.createRef() + } + + getSnapshotBeforeUpdate() { + if (this.linesRef.current && this.linesBottomRef.current) { + return Log.isVisible(this.linesRef.current, this.linesBottomRef.current) + } + return false + } + + + componentDidUpdate(_1, _2, wasVisible) { + if (wasVisible) { + Log.scrollParentToChild(this.linesRef.current, this.linesBottomRef.current) + } + } + + componentDidMount() { + if (this.linesRef.current && this.linesBottomRef.current) { + Log.scrollParentToChild(this.linesRef.current, this.linesBottomRef.current) + } + } + + static scrollParentToChild(parent, child) { + const parentRect = parent.getBoundingClientRect() + const childRect = child.getBoundingClientRect() + + if (!Log.isVisible(parent, child)) { + parent.scrollBy({ top: (childRect.top + parent.scrollTop) - parentRect.top }) + } + } + + static isVisible(parent, child) { + const parentRect = parent.getBoundingClientRect() + const childRect = child.getBoundingClientRect() + return (childRect.top >= parentRect.top) + && (childRect.top <= parentRect.top + parent.clientHeight) + } + render() { return ( -
+
{this.props.lines.map(data => )}
+
) } diff --git a/maubot/management/frontend/src/pages/dashboard/Modal.js b/maubot/management/frontend/src/pages/dashboard/Modal.js index 9bfc48e..b51301a 100644 --- a/maubot/management/frontend/src/pages/dashboard/Modal.js +++ b/maubot/management/frontend/src/pages/dashboard/Modal.js @@ -30,6 +30,7 @@ class Modal extends Component { open = () => this.setState({ open: true }) close = () => this.setState({ open: false }) + isOpen = () => this.state.open render() { return this.state.open && ( diff --git a/maubot/management/frontend/src/pages/dashboard/index.js b/maubot/management/frontend/src/pages/dashboard/index.js index a688ff5..c593bd0 100644 --- a/maubot/management/frontend/src/pages/dashboard/index.js +++ b/maubot/management/frontend/src/pages/dashboard/index.js @@ -34,11 +34,11 @@ class Dashboard extends Component { sidebarOpen: false, modalOpen: false, logFocus: null, + logLines: [], } - this.logLines = [] - this.logMap = {} this.logModal = { open: () => undefined, + isOpen: () => false, } window.maubot = this } @@ -80,20 +80,21 @@ class Dashboard extends Component { } else if (entry.name.startsWith("instance.")) { entry.nameLink = `/instance/${entry.name.substr("instance.".length)}` } - (this.logMap[entry.name] || (this.logMap[entry.name] = [])).push(entry) } logs.onHistory = history => { for (const data of history) { processEntry(data) } - this.logLines = history - this.setState({ logFocus: this.state.logFocus }) + this.setState({ + logLines: history, + }) } logs.onLog = data => { processEntry(data) - this.logLines.push(data) - this.setState({ logFocus: this.state.logFocus }) + this.setState({ + logLines: this.state.logLines.concat(data), + }) } } @@ -209,7 +210,7 @@ class Dashboard extends Component { renderModal() { return this.logModal = ref}> - + }