diff --git a/LCU/Maintenance/MDB_WebView/maintenancedb_view/public/index.html b/LCU/Maintenance/MDB_WebView/maintenancedb_view/public/index.html index 220f25585d0a20a827abb36046a4e319944fc185..e3bf9b465f6efaf99291c27e57600268f217c00f 100644 --- a/LCU/Maintenance/MDB_WebView/maintenancedb_view/public/index.html +++ b/LCU/Maintenance/MDB_WebView/maintenancedb_view/public/index.html @@ -1,4 +1,4 @@ -<!DOCTYPE html> +:<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> diff --git a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/components/LatestObservations.css b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/components/LatestObservations.css index d851907ef40a51bebef7dd2589429bf48c1780dc..3ec2c0158b7b87ed251af31b361753b754e2e02c 100644 --- a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/components/LatestObservations.css +++ b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/components/LatestObservations.css @@ -5,3 +5,9 @@ /* Data colors */ .hoverable:hover { background-color: #bdbdbd; } + +.table-wrapper { + width: 10em; + max-height: 10em; + overflow: auto; + display: block; } diff --git a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/components/LatestObservations.js b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/components/LatestObservations.js index fcaab40a1b264176c3527ce70e3689a41fbc6018..13d6edba1f489ce8fb0677712e0ecee898c9a2e9 100644 --- a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/components/LatestObservations.js +++ b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/components/LatestObservations.js @@ -28,11 +28,16 @@ class RTSMBadge extends Component { class SORow extends Component { constructor(props){ super(props); - this.state = {popoverOpen:false}; + this.state = {popoverOpen:false, mouseOverPopup:false}; this.id = unique_id(); this.togglePopover = this.togglePopover.bind(this); + this.mouseDown = this.mouseDown.bind(this); } + mouseDown(e){ + if(e.button === 1) + this.setState({mouseOverPopup: !this.state.mouseOverPopup}); + } renderObservationID() { return this.props.data.observation_id; } @@ -46,7 +51,9 @@ class SORow extends Component { } togglePopover(){ - this.setState({popoverOpen: !this.state.popoverOpen}); + if(this.state.mouseOverPopup === false){ + this.setState({popoverOpen: !this.state.popoverOpen}); + } } render() { @@ -55,20 +62,22 @@ class SORow extends Component { const stations_and_errors = data.station_involved.map((station) => <tr><th scope="row">{station.station_name}</th> <td>{station.n_errors}</td></tr>) return ( - <tr id={this.id} onMouseOver={this.togglePopover} onMouseOut={this.togglePopover} className="hoverable"> + <tr id={this.id} onMouseOver={this.togglePopover} onMouseOut={this.togglePopover} + onMouseDown={this.mouseDown} + className="hoverable"> <th scope="row">{ this.renderObservationID() }</th> <td>{ moment(start_datetime).format('lll') }</td> <td>{ this.renderStationsInvolved() }</td> <td>{ this.renderStationsWithProblems() }</td> <td>{ total_component_errors }</td> - <Popover placement="auto" isOpen={this.state.popoverOpen} target={ this.id } toggle={this.togglePopover}> + <Popover placement="auto-start" isOpen={this.state.popoverOpen} target={ this.id }> <PopoverHeader>{data.observation_id}</PopoverHeader> <PopoverBody> <strong>Start:</strong> { start_datetime}<br/> <strong>End:</strong> { end_datetime }<br/> <strong>Mode:</strong> { mode.join(',') }<br/> - <Table size="sm" className="so-table"> + <Table size="sm" className="so-table table-wrapper"> <thead><th>Station name</th><th>errors</th></thead> <tbody>{stations_and_errors}</tbody> </Table> diff --git a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/components/LatestObservations.scss b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/components/LatestObservations.scss index 49e45e5ae464c86c40a86d25db12e6ebc293b82a..d1199fbe15d96ead401f3bc8d3678f7ac038afde 100644 --- a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/components/LatestObservations.scss +++ b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/components/LatestObservations.scss @@ -7,3 +7,10 @@ .hoverable:hover { background-color: $secondary; } + +.table-wrapper { + width: 10em; + max-height: 10em; + overflow: auto; + display: block; +} diff --git a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/components/StationStatistics.js b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/components/StationStatistics.js index 0c7ea0ef249be44cc4ecf8c56da98b3ac0e55b36..a17e74754431ca0b75b6841fb9d905bb6d7ff07e 100644 --- a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/components/StationStatistics.js +++ b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/components/StationStatistics.js @@ -2,28 +2,65 @@ import React, { Component } from 'react'; import AutoLoadWrapper from '../utils/autoLoader.js' import { unique_id } from '../utils/utils.js' import ReactVegaLite from 'react-vega-lite' -import { Table, Badge, Popover, PopoverHeader, PopoverBody } from 'reactstrap'; -/** - * SORow; Class to render the row for a station in the StationOverview. - */ -class SORow extends Component { - render() { +import { Table, Badge, Popover, PopoverHeader, PopoverBody, Form, Input } from 'reactstrap'; +import { connect } from 'react-redux'; +import {setStationStatisticsTestType, setStationStatisticsAveragingWindow} from '../redux/actions/actions' - return ( - <tr className="hoverable"> - <th scope="row">{ "ciao" }</th> - </tr> - ); +class ToolBarC extends Component { + + setAveragingWindow(e){ + this.props.setStationStatisticsAveragingWindow(e.target.value); + } + + setTestType(e){ + this.props.setStationStatisticsTestType(e.target.value); + } + render(){ + return (<div className="sts-toolbar"> + <Form inline> + <select className="form-control custom-select custom-select-sm" + id="selected-group" value={this.props.test_type} + onChange={(e)=>this.setTestType(e)} + style={{width: 'auto'}}> + <option value="B">Both test types</option> + <option value="R">RTSM</option> + <option value="S">StationTest</option> + </select> + <Input type="select" className="form-control custom-select custom-select-sm" + onChange={(e)=>this.setAveragingWindow(e)}> + <option value={1}>day</option> + <option value={7}>week</option> + <option value={30}>month</option> + </Input> + </Form> + </div>); } } + +const mapDispatchToPropsToolBar = { + setStationStatisticsAveragingWindow, + setStationStatisticsTestType +}; + + +const ToolBar = connect(null, mapDispatchToPropsToolBar)(ToolBarC); + + class StationStatisticsC extends Component { + constructor(props){ + super(props); + this.state = {}; + this.ref = React.createRef(); + this.getErrorsPerTypeSpec.bind(this); + } getErrorsPerStation() { if(this.props.data.errors_per_station !== undefined){ return {values:this.props.data.errors_per_station}; } } + getErrorsPerType() { if(this.props.data.errors_per_type !== undefined){ return {values:this.props.data.errors_per_type}; @@ -31,7 +68,7 @@ class StationStatisticsC extends Component { } getErrorsPerTypeSpec(){ - return {"$schema": "https://vega.github.io/schema/vega-lite/v2.json", + let base_schema = {"$schema": "https://vega.github.io/schema/vega-lite/v2.json", "mark": "bar", "encoding": { "x": { @@ -50,13 +87,21 @@ class StationStatisticsC extends Component { } } } + return base_schema; } render() { return ( - <div className="station-statistics-ctrl"> + <React.Fragment> + <h5 className="react-grid-item-header"> + Station statistics + <ToolBar /> + </h5> + <div className="react-grid-item-body" id="plot" ref={this.ref} > <ReactVegaLite spec={this.getErrorsPerTypeSpec()} data={this.getErrorsPerType()} /> </div> + </React.Fragment> + ); } } diff --git a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/components/StationTestSummary.js b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/components/StationTestSummary.js index 3357a5d0c0ecb111c08f3dfbb7b575fe9f734591..ccb8efd0962f64e0c70e5f7253a9656636ae58c9 100644 --- a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/components/StationTestSummary.js +++ b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/components/StationTestSummary.js @@ -37,7 +37,7 @@ class STSRow extends Component { return ( <tr> - <th scope="row" style={{"white-space": "nowrap"}}>{ this.renderStartDate() }</th> + <th scope="row" style={{whiteSpace: "nowrap"}}>{ this.renderStartDate() }</th> <th>{ props.time }</th> <th>{ props.station }</th> <td>{ component }</td> diff --git a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/pages/LandingPage.js b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/pages/LandingPage.js index e0c56fa1cc6c59804b7f44c6e087f4874a7086c8..bedc109908057318389905ab59573492ab228011 100644 --- a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/pages/LandingPage.js +++ b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/pages/LandingPage.js @@ -94,17 +94,17 @@ class ToolBarC extends Component { } -const mapStateToProps = state => { - return { ...state.mainFilters }; +const mapStateToPropsToolBar = state => { + return { ...state.mainFilters}; }; -const mapDispatchToProps = { +const mapDispatchToPropsToolBar = { setStationGroup, setErrorsOnly, setPeriod }; -const ToolBar = connect(mapStateToProps, mapDispatchToProps)(ToolBarC); +const ToolBar = connect(mapStateToPropsToolBar, mapDispatchToPropsToolBar)(ToolBarC); @@ -142,10 +142,11 @@ class LandingPageC extends Component { return `/api/view/ctrl_latest_observation?format=json&station_group=${this.props.selectedStationGroup}&from_date=${nDaysAgo_String}&errors_only=${this.props.errorsOnly}`; } getStationStatisticsURL() { - var nDaysAgo = moment().add(-this.props.period*100, 'days').format('YYYY-MM-DD'); + var nDaysAgo = moment().add(-this.props.period, 'days').format('YYYY-MM-DD'); var now = moment().format('YYYY-MM-DD'); - var averaging_interval = 12 - return `/api/view/ctrl_stationtest_statistics?format=json&from_date=${nDaysAgo}&to_date=${now}&averaging_interval=${averaging_interval}`; + var averaging_interval = this.props.station_statistics.averaging_window + var test_type = this.props.station_statistics.test_type + return `/api/view/ctrl_stationtest_statistics?format=json&from_date=${nDaysAgo}&to_date=${now}&averaging_interval=${averaging_interval}&test_type=${test_type}`; } render() { return (<div> @@ -165,7 +166,7 @@ class LandingPageC extends Component { body: <StationTestSummary url={this.getStationTestSummaryURL()}/> })} {createGridPanel({ - key: "br", renderHeader: true, title: "Station Statistics", + key: "br", renderHeader: false, body: <StationStatistics url={this.getStationStatisticsURL()}/> })} </ResponsiveGridLayout> </div>); @@ -174,7 +175,7 @@ class LandingPageC extends Component { const LandingPage = connect(state => { - return { ...state.mainFilters }; + return { ...state.mainFilters, ...state.landing_page }; }, null)(LandingPageC); diff --git a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/redux/actions/actionTypes.js b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/redux/actions/actionTypes.js index cbd63119b2bb7a97e9589b57dc2ac977b6286980..3851ef1eb48f325a1fbd2dc9d67f043340bbf4b3 100644 --- a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/redux/actions/actionTypes.js +++ b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/redux/actions/actionTypes.js @@ -2,8 +2,9 @@ export const SET_STATION_GROUP = "SET_STATION_GROUP"; export const SET_ERRORS_ONLY = "SET_ERRORS_ONLY"; export const SET_PERIOD = "SET_PERIOD"; - - export const FETCH_ERRORTYPES_BEGIN = 'FETCH_ERRORTYPES_BEGIN'; export const FETCH_ERRORTYPES_SUCCESS = 'FETCH_ERRORTYPES_SUCCESS'; export const FETCH_ERRORTYPES_FAILURE = 'FETCH_ERRORTYPES_FAILURE'; +export const SET_COMPONENT_SIZES = "SET_COMPONENT_SIZES"; +export const SET_AVERAGING_WINDOW = "SET_AVERAGING_WINDOW"; +export const SET_TEST_TYPE = "SET_TEST_TYPE"; diff --git a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/redux/actions/actions.js b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/redux/actions/actions.js index da41c7fc67a328eb80f58265e54791a102ceb6d7..b50cd773e7c14b01dcfb860b474fc04e16c7cf48 100644 --- a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/redux/actions/actions.js +++ b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/redux/actions/actions.js @@ -1,5 +1,8 @@ -import { SET_STATION_GROUP, SET_ERRORS_ONLY, SET_PERIOD } from "./actionTypes"; +import { SET_STATION_GROUP, + SET_ERRORS_ONLY, + SET_PERIOD, + SET_COMPONENT_SIZES, SET_AVERAGING_WINDOW, SET_TEST_TYPE } from "./actionTypes"; @@ -17,3 +20,19 @@ export const setPeriod = period => ({ type: SET_PERIOD, payload: { period } }); + + +export const setComponentsSizes = (componentName, componentSizes) => ({ + type: SET_COMPONENT_SIZES, + payload: { componentName: componentSizes } +}); + +export const setStationStatisticsAveragingWindow = averagingWindow => ({ + type: SET_AVERAGING_WINDOW, + payload: { averagingWindow } +}); + +export const setStationStatisticsTestType = test_type => ({ + type: SET_TEST_TYPE, + payload: { test_type } +}); diff --git a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/redux/reducers/index.js b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/redux/reducers/index.js index 471fbf229cf401155cef101205ae0107fc253f6b..1f7d586d6ba2dd822f984b3b5c68acbb98a196e6 100644 --- a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/redux/reducers/index.js +++ b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/redux/reducers/index.js @@ -1,8 +1,10 @@ import { combineReducers } from "redux"; import appInitData from "./appInitData"; import mainFilters from "./mainFilters"; +import landingPageReducers from "./landingPageReducers"; export default combineReducers({ appInitData, - mainFilters + mainFilters, + landing_page:landingPageReducers }); diff --git a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/redux/reducers/mainFilters.js b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/redux/reducers/mainFilters.js index 01dceb7460b73f2a77787c07a571baf52bd2db37..80eef4ef107de389c79c699d14306c5085564b0a 100644 --- a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/redux/reducers/mainFilters.js +++ b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/redux/reducers/mainFilters.js @@ -6,7 +6,7 @@ import { const initialState = { - selectedStationGroup: 'R', + selectedStationGroup: 'A', errorsOnly: false, period: 14 // days }; diff --git a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/utils/autoLoader.js b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/utils/autoLoader.js index be9df5808a228d69deb951294605dc64b1597862..c6fd9b85eb8dfbf6cd490902bf71c792d51d9cb2 100644 --- a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/utils/autoLoader.js +++ b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/utils/autoLoader.js @@ -95,7 +95,7 @@ function AutoLoadWrapper(WrappedComponent) { } render() { - console.log('render'); + console.log('render', this); let loadingHtml = ""; if (this.state.isLoading) { loadingHtml = <div className="alLoading"></div>;