aboutsummaryrefslogtreecommitdiffstats
path: root/dashboard/assets/components/Dashboard.jsx
diff options
context:
space:
mode:
Diffstat (limited to 'dashboard/assets/components/Dashboard.jsx')
-rw-r--r--dashboard/assets/components/Dashboard.jsx45
1 files changed, 31 insertions, 14 deletions
diff --git a/dashboard/assets/components/Dashboard.jsx b/dashboard/assets/components/Dashboard.jsx
index 8e6bf9869..63c2186ad 100644
--- a/dashboard/assets/components/Dashboard.jsx
+++ b/dashboard/assets/components/Dashboard.jsx
@@ -24,6 +24,7 @@ import Header from './Header';
import Body from './Body';
import {MENU} from '../common';
import type {Content} from '../types/content';
+import {inserter as logInserter} from './Logs';
// deepUpdate updates an object corresponding to the given update data, which has
// the shape of the same structure as the original object. updater also has the same
@@ -75,8 +76,11 @@ const appender = <T>(limit: number, mapper = replacer) => (update: Array<T>, pre
...update.map(sample => mapper(sample)),
].slice(-limit);
-// defaultContent is the initial value of the state content.
-const defaultContent: Content = {
+// defaultContent returns the initial value of the state content. Needs to be a function in order to
+// instantiate the object again, because it is used by the state, and isn't automatically cleaned
+// when a new connection is established. The state is mutated during the update in order to avoid
+// the execution of unnecessary operations (e.g. copy of the log array).
+const defaultContent: () => Content = () => ({
general: {
version: null,
commit: null,
@@ -95,10 +99,14 @@ const defaultContent: Content = {
diskRead: [],
diskWrite: [],
},
- logs: {
- log: [],
+ logs: {
+ chunks: [],
+ endTop: false,
+ endBottom: true,
+ topChanged: 0,
+ bottomChanged: 0,
},
-};
+});
// updaters contains the state updater functions for each path of the state.
//
@@ -122,9 +130,7 @@ const updaters = {
diskRead: appender(200),
diskWrite: appender(200),
},
- logs: {
- log: appender(200),
- },
+ logs: logInserter(5),
};
// styles contains the constant styles of the component.
@@ -151,10 +157,11 @@ export type Props = {
};
type State = {
- active: string, // active menu
- sideBar: boolean, // true if the sidebar is opened
- content: Content, // the visualized data
- shouldUpdate: Object, // labels for the components, which need to re-render based on the incoming message
+ active: string, // active menu
+ sideBar: boolean, // true if the sidebar is opened
+ content: Content, // the visualized data
+ shouldUpdate: Object, // labels for the components, which need to re-render based on the incoming message
+ server: ?WebSocket,
};
// Dashboard is the main component, which renders the whole page, makes connection with the server and
@@ -165,8 +172,9 @@ class Dashboard extends Component<Props, State> {
this.state = {
active: MENU.get('home').id,
sideBar: true,
- content: defaultContent,
+ content: defaultContent(),
shouldUpdate: {},
+ server: null,
};
}
@@ -181,7 +189,7 @@ class Dashboard extends Component<Props, State> {
// PROD is defined by webpack.
const server = new WebSocket(`${((window.location.protocol === 'https:') ? 'wss://' : 'ws://')}${PROD ? window.location.host : 'localhost:8080'}/api`);
server.onopen = () => {
- this.setState({content: defaultContent, shouldUpdate: {}});
+ this.setState({content: defaultContent(), shouldUpdate: {}, server});
};
server.onmessage = (event) => {
const msg: $Shape<Content> = JSON.parse(event.data);
@@ -192,10 +200,18 @@ class Dashboard extends Component<Props, State> {
this.update(msg);
};
server.onclose = () => {
+ this.setState({server: null});
setTimeout(this.reconnect, 3000);
};
};
+ // send sends a message to the server, which can be accessed only through this function for safety reasons.
+ send = (msg: string) => {
+ if (this.state.server != null) {
+ this.state.server.send(msg);
+ }
+ };
+
// update updates the content corresponding to the incoming message.
update = (msg: $Shape<Content>) => {
this.setState(prevState => ({
@@ -226,6 +242,7 @@ class Dashboard extends Component<Props, State> {
active={this.state.active}
content={this.state.content}
shouldUpdate={this.state.shouldUpdate}
+ send={this.send}
/>
</div>
);