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 bc9e806fb37db9838c705ba69a160a1f109f8a50..1c9d6e9168e65e72cffab0c42ea6bdbff7bef714 100644 --- a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/components/StationStatistics.js +++ b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/components/StationStatistics.js @@ -33,13 +33,19 @@ class ToolBarC extends Component { <option value={7}>week</option> <option value={30}>month</option> </Input> + <Input type="select" className="form-control custom-select custom-select-sm" + onChange={(e)=>this.props.switchHistogramEvent(e)} + value={this.props.histogramType}> + <option value="per_error_type">per error type</option> + <option value="per_station">per station</option> + </Input> </Form> </div>); } } const mapStateToPropsToolBar = state => { - return { ...state.landing_page.station_statistics}; + return { ...state.landing_page.station_statistics, ...state.layout}; }; const mapDispatchToPropsToolBar = { @@ -54,7 +60,7 @@ const ToolBar = connect(mapStateToPropsToolBar, mapDispatchToPropsToolBar)(ToolB class StationStatisticsC extends Component { constructor(props){ super(props); - this.state = {}; + this.state = {histogramType: 'per_error_type'}; this.ref = React.createRef(); this.getErrorsPerTypeSpec.bind(this); } @@ -71,9 +77,19 @@ class StationStatisticsC extends Component { } } - getErrorsPerTypeSpec(){ - let base_schema = {"$schema": "https://vega.github.io/schema/vega-lite/v2.json", + getBaseSpec(){ + return {"$schema": "https://vega.github.io/schema/vega-lite/v2.json", "mark": "bar", + "autosize": { + "type": "fit", + "resize": true, + "contains": "padding" + }, + "config":{ + "legend":{ + "columns": 2 + } + }, "encoding": { "x": { "field": "time", @@ -84,25 +100,60 @@ class StationStatisticsC extends Component { "field": "n_errors", "type": "quantitative", "axis": {"title": "number of errors"} - }, - "color": { + }} + } + } + + getErrorsPerTypeSpec(){ + let schema = this.getBaseSpec(); + schema.encoding["color"] = { "field": "error_type", "type": "nominal" } - } + + return schema; + } + + getErrorsPerStationSpec(){ + let schema = this.getBaseSpec(); + schema.encoding["color"] = { "field": "station_name", + "type": "nominal"} + schema.config.legend.columns = 3 + return schema; + } + + + getSpecData(histogram_type){ + switch (histogram_type) { + case "per_error_type": + return {spec:this.getErrorsPerTypeSpec(), data:this.getErrorsPerType()}; + case "per_station": + return {spec:this.getErrorsPerStationSpec(), data:this.getErrorsPerStation()}; + default: + return {spec:this.getErrorsPerTypeSpec(), data:this.getErrorsPerType()}; } - return base_schema; } + render() { + const {spec, data} = this.getSpecData(this.state.histogramType); + if (this.ref.current !== null){ + const width = this.ref.current.parentElement.clientWidth + const height = this.ref.current.parentElement.clientHeight + spec.width = width + spec.height = height + + } return ( <React.Fragment> <h5 className="react-grid-item-header"> Station statistics - <ToolBar /> + <ToolBar + histogramType={this.state.histogramType} + switchHistogramEvent={e => this.setState({histogramType:e.target.value})} /> </h5> <div className="react-grid-item-body" id="plot" ref={this.ref} > - <ReactVegaLite spec={this.getErrorsPerTypeSpec()} - data={this.getErrorsPerType()} /> + <ReactVegaLite spec={spec} + data={data} /> </div> </React.Fragment> 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 bedc109908057318389905ab59573492ab228011..b97a52296efdfed09ab0e727c4b1214dea577ab3 100644 --- a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/pages/LandingPage.js +++ b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/pages/LandingPage.js @@ -10,7 +10,7 @@ import { Responsive, WidthProvider } from 'react-grid-layout'; import { Button, ButtonGroup, Form } from 'reactstrap'; import * as moment from 'moment'; import { connect } from "react-redux"; -import { setStationGroup, setErrorsOnly, setPeriod } from "../redux/actions/actions.js"; +import { setStationGroup, setErrorsOnly, setPeriod, setNewLayout } from "../redux/actions/actions.js"; import 'react-grid-layout/css/styles.css'; import 'react-resizable/css/styles.css'; import '../themes/lofar-styles.css'; @@ -106,12 +106,11 @@ const mapDispatchToPropsToolBar = { const ToolBar = connect(mapStateToPropsToolBar, mapDispatchToPropsToolBar)(ToolBarC); - - /* Boiler plate for a Grid panel. Looks like a React component but is ordinary function! */ function createGridPanel(props) { let body = props.body; + console.log("props on create grid", props) if (props.renderHeader) { body = <React.Fragment> <h5 className="react-grid-item-header">{props.title}</h5> @@ -127,7 +126,6 @@ function createGridPanel(props) { ); } - class LandingPageC extends Component { getStationOverviewURL() { @@ -152,7 +150,7 @@ class LandingPageC extends Component { return (<div> <Header active_page={this.props.location}/> <ToolBar /> - <ResponsiveGridLayout className="layout" layouts={layout.panels} measureBeforeMount={true} breakpoints={layout.breakpoints} cols={layout.cols}> + <ResponsiveGridLayout className="layout" layouts={layout.panels} measureBeforeMount={true} breakpoints={layout.breakpoints} cols={layout.cols} onResizeStop={e=>this.props.setNewLayout(e)}> {createGridPanel({ key: "ul", renderHeader: true, title: "Station overview", body: <StationOverview url={this.getStationOverviewURL()}/> @@ -173,10 +171,8 @@ class LandingPageC extends Component { } } - const LandingPage = connect(state => { - return { ...state.mainFilters, ...state.landing_page }; -}, null)(LandingPageC); - + return { ...state.mainFilters, ...state.landing_page, ...state.layout }; +}, {setNewLayout})(LandingPageC); export default LandingPage; 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 b50cd773e7c14b01dcfb860b474fc04e16c7cf48..88c909058fe5b440de3a8c6c25e8a99252e8e7e0 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 @@ -22,9 +22,9 @@ export const setPeriod = period => ({ }); -export const setComponentsSizes = (componentName, componentSizes) => ({ +export const setNewLayout = newLayout => ({ type: SET_COMPONENT_SIZES, - payload: { componentName: componentSizes } + payload: { newLayout } }); export const setStationStatisticsAveragingWindow = averagingWindow => ({ 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 1f7d586d6ba2dd822f984b3b5c68acbb98a196e6..3aa3c00c0845b5a13751c1aef69519b1d4543081 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 @@ -2,9 +2,11 @@ import { combineReducers } from "redux"; import appInitData from "./appInitData"; import mainFilters from "./mainFilters"; import landingPageReducers from "./landingPageReducers"; +import layout from "./layout"; export default combineReducers({ appInitData, mainFilters, - landing_page:landingPageReducers + landing_page:landingPageReducers, + layout:layout }); diff --git a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/redux/reducers/layout.js b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/redux/reducers/layout.js index 742c1a097544b597a142d10504e3e948bd64f9d6..0373e87fd4541322cdaab5973556ea6b0ff5e831 100644 --- a/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/redux/reducers/layout.js +++ b/LCU/Maintenance/MDB_WebView/maintenancedb_view/src/redux/reducers/layout.js @@ -1,17 +1,15 @@ import { SET_COMPONENT_SIZES } from '../actions/actionTypes.js' const initialState = { - station_statistics = { width: 0, height:0} + layout:[] }; export default function(state = initialState, action) { switch (action.type) { case SET_COMPONENT_SIZES: { - const { payload } = action.payload; - return { ...state, - payload.componentName: payload.componentSizes + layout: action.payload.newLayout }; } default: