Skip to content
Snippets Groups Projects
Commit 1176ca07 authored by Reinoud Bokhorst's avatar Reinoud Bokhorst
Browse files

OSB-31: child panel implementation, V2.1

parent 8916d561
No related branches found
No related tags found
2 merge requests!89Monitoring maintenance Epic branch merge,!1Resolve OSB-13 "Monitoringmaintenance "
......@@ -2,7 +2,7 @@
"name": "maintenancedb_view",
"version": "0.1.0",
"description": "WebPage meant to display the content of the maintenance db in the web browser,",
"proxy": "http://localhost:8080",
"proxy": "http://lofarmonitortest.control.lofar",
"scripts": {
"flow": "flow",
"build-css": "node-sass-chokidar src/ -o src/",
......
......@@ -2,9 +2,10 @@ import React, {
Component
} from 'react';
import {connect} from "react-redux";
import {setChildPanelData} from '../redux/actions/stationOverviewPageActions'
import {unpinChildPanelData} from '../redux/actions/stationOverviewPageActions'
import {
Button,
Table,
Badge,
Tooltip,
......@@ -14,7 +15,7 @@ import {
TabContent,
Nav
} from 'reactstrap';
import { IoMdArrowDropdown as DropDownIcon} from 'react-icons/io';
import { IoMdCloseCircleOutline as CloseIcon} from 'react-icons/io';
import {
unique_id
} from '../utils/utils.js'
......@@ -27,98 +28,71 @@ import ReactTableContainer from "react-table-container";
import moment from 'moment';
import classnames from 'classnames';
import './StationTestChildView.css';
class StationTestChildViewC extends Component {
render(){
if (this.props.data === null) {
return <i>Hover mouse over an error</i>;
}
class StationTestChildViewC extends Component {
let renderedErrorsPerPolarization = [];
let errorDetails = [];
for(let polarization of ['X', 'Y']){
renderedErrorsPerPolarization.push(
<tr key={polarization}>
<th scope="row">{polarization}</th>
{this.props.data[polarization].map((item, key) =>
<td key={key}>
<Badge className='error-type-badge'>{item.error_type}</Badge>
</td>)
}
</tr>
)
this.props.data[polarization].forEach((item, key) => {
let renderDetails = <em>see element error</em>
if(Object.keys(item.details).length> 0){
renderDetails = (
<ul style={{listStyleType: 'none'}}>
{Object.keys(item.details).map((parameter, key) =>{
const parameter_value = item.details[parameter]
const rendered_parameter = parameter === 'percentage'? parameter_value.toFixed(2) + '%' : parameter_value
return (<li key={key}>{parameter}: {rendered_parameter}</li>)
})
}
</ul>)
}
errorDetails.push(
<React.Fragment key={key + polarization}>
<div><em>{polarization} - {item.error_type}</em></div>
{renderDetails}
</React.Fragment>
)
})
}
unpinPanel = () => {
this.props.unpinChildPanelData();
}
render() {
let rows;
let rows = [];
// default value when data is null
rows = <tr><td><i>Hover the mouse over an error to view the details. Right-click on the error to pin it on this panel.</i></td></tr>;
for (let polarization of ['X', 'Y']){
let d = this.props.data[polarization];
let p = polarization;
if (this.props.data !== null) {
rows = [];
let err_types = Object.keys(d);
for (let polarization of ['X', 'Y']){
let d = this.props.data[polarization];
let p = polarization;
d.forEach((item, key) => {
let err_types = Object.keys(d);
let err_details = Object.keys(item.details).map((parameter, key) =>{
const parameter_value = item.details[parameter]
const rendered_parameter = parameter === 'percentage'? parameter_value.toFixed(2) + '%' : parameter_value
d.forEach((item, key) => {
return (<li key={key}>{parameter}: {rendered_parameter}</li>)
});
let err_details = Object.keys(item.details).map((parameter, key) =>{
const parameter_value = item.details[parameter]
const rendered_parameter = parameter === 'percentage'? parameter_value.toFixed(2) + '%' : parameter_value
if (parameter !== 'url') {
return (<li key={key}>{parameter}: {rendered_parameter}</li>)
}
});
if (err_details.length === 0) {
err_details = <li><em>see element error</em></li>;
}
if (err_details.length === 0) {
err_details = <li><em>see element error</em></li>;
}
rows.push(
<tr key={p}>
<th scope="row">{p}</th>
<td key={key}>
<Badge className='error-type-badge'>{item.error_type}</Badge>
</td>
<td>
<ul style={{listStyleType: 'none'}}>
{ err_details }
</ul>
</td>
</tr>
);
rows.push(
<tr key={p}>
<th scope="row">{p} - <Badge className='error-type-badge'>{item.error_type}</Badge></th>
<td>
<ul style={{listStyleType: 'none'}}>
{ err_details }
</ul>
</td>
</tr>
);
p = "";
});
p = "";
});
}
}
let unpinButton = "";
if (this.props.isPinned) {
unpinButton = <Button title="Click to unpin the error details" color="info" size="xs" style={{float:'right'}} onClick={this.unpinPanel}>
<CloseIcon/>&nbsp;unpin
</Button>
}
return <div>
<h5>Errors details</h5>
<div className="stcv-header">Errors details {unpinButton}</div>
<Table size='sm'>
<tbody>
{rows}
......@@ -136,6 +110,8 @@ const StationTestChildView = connect(state => {
return {
...state.station_page.child_panel,
};
}, {
unpinChildPanelData
})(StationTestChildViewC);
......
......@@ -74,27 +74,38 @@ class GenericStatusC extends Component {
}
onMouseOver = () => {
if (this.props.errors_per_polarization) {
this.props.setChildPanelData(this.props.errors_per_polarization);
}
this.props.setChildPanelData(this.props.errors_per_polarization);
}
onMouseOut = () => {
if (this.props.errors_per_polarization) {
this.props.setChildPanelData(null);
}
this.props.setChildPanelData(null);
}
// left-click with mouse
onClick = () => {
console.log('click (TODO, switch to tiles page)');
}
// right-click with mouse
onContextMenu = (e) => {
e.preventDefault();
this.props.setChildPanelData(this.props.errors_per_polarization, true);
}
render(){
let jsx = "";
if (this.props.errors_per_polarization) {
jsx = <td className={this.getClass()} onMouseOver={this.onMouseOver} onMouseOut={this.onMouseOut}>
if (this.props.n_errors > 0) {
jsx = <td className={this.getClass()}
onContextMenu={this.onContextMenu}
onClick={this.onClick}
onMouseOver={this.onMouseOver}
onMouseOut={this.onMouseOut}>
{this.props.n_errors}
</td>
}
else {
jsx = <td className={this.getClass()}>
jsx = <td className={this.getClass()} onClick={this.onClick}>
{this.props.n_errors === 0 ? ' ' : this.props.n_errors}
</td>
}
......@@ -108,46 +119,20 @@ const GenericStatus = connect(null, {
})(GenericStatusC);
class StationSummaryLine extends Component {
/**
* TestLine: renders a table row with the results of one station test or RTSM run.
*/
class TestLine extends Component {
formatDate(date){
const result = moment(date).format('DD-MM-YYYY HH:mm');
return result
}
renderHeader(){
const date = this.formatDate(this.props.data.end_date);
const jsx = (
<td>{this.props.test_type} {date}</td>
)
return jsx
}
renderHBA(){
const jsx = this.renderHeader()
return <tr>{jsx}{this.renderComponentErrors()}</tr>
}
renderLBH(){
const jsx = this.renderHeader()
return <tr>{jsx}{this.renderComponentErrors()}</tr>
}
renderLBL(){
const jsx = this.renderHeader()
return <tr>{jsx}{this.renderComponentErrors()}</tr>
}
renderGeneric(){
const jsx = this.renderHeader()
return <tr>{jsx}{this.renderComponentErrors()}</tr>
}
renderComponentErrors(){
const component_errors = this.props.data.component_errors;
const component_type = this.props.component_type
const rendered_component_errors = this.props.ordered_component_ids.map((item, key) =>
{
const component_type = this.props.component_type;
const rendered_component_errors = this.props.ordered_component_ids.map((item, key) => {
let component_errors_count = 0
const errorsPerPolarization = {X:[], Y:[]}
for(let polarization of ['X', 'Y']){
......@@ -159,7 +144,6 @@ class StationSummaryLine extends Component {
}
if (component_errors_count > 0){
return <GenericStatus key={key} component_id={item} errors_per_polarization={errorsPerPolarization} n_errors={component_errors_count} status = 'error' />
}
else{
......@@ -170,16 +154,12 @@ class StationSummaryLine extends Component {
}
render (){
switch (this.props.component_type) {
case 'HBA':
return this.renderHBA();
case 'LBH':
return this.renderLBH();
case 'LBL':
return this.renderLBL();
default:
return this.renderGeneric();
}
const date = this.formatDate(this.props.data.end_date);
return <tr>
<td>{this.props.test_type} {date}</td>
{this.renderComponentErrors()}
</tr>
}
}
......@@ -191,7 +171,7 @@ class RTSMSummaryLine extends Component {
}
renderTestLine(key, data, component_id_list){
return (<StationSummaryLine className="collapse open" key={key} ordered_component_ids={component_id_list} test_type="RT" component_type={this.props.component_type} station_type={this.props.station_type} data={data}/>)
return (<TestLine className="collapse open" key={key} ordered_component_ids={component_id_list} test_type="RT" component_type={this.props.component_type} station_type={this.props.station_type} data={data}/>)
}
renderTestSummaryLine(data, component_id_list){
......@@ -223,6 +203,7 @@ class RTSMSummaryLine extends Component {
Object.keys(summary).forEach(item => summary[item] /= n_tests/50. )
return summary
}
renderDateRange(data){
const lastTest = data[0]
const firstTest = data[data.length - 1]
......@@ -241,7 +222,9 @@ class RTSMSummaryLine extends Component {
}
toggleDisplaySingleTests = (e) => {
this.setState({displaySingleTests:!this.state.displaySingleTests})
this.setState({
displaySingleTests:!this.state.displaySingleTests
});
}
render(){
......@@ -264,7 +247,8 @@ class RTSMSummaryLine extends Component {
RT {this.renderDateRange(this.props.data)}
<DropDownIcon className={"line-header-dropdownbutton " + dropdownAdditionStyles} color="black" />
</td>
{summaryLine}</tr>
{summaryLine}
</tr>
{all_rtsm}
</React.Fragment>
)
......@@ -274,6 +258,14 @@ class RTSMSummaryLine extends Component {
}
}
/**
* ComponentClass; renders a table of station tests and rtsm data for a component (HBA, RSP, LBH, etc.)
*
* Props:
* station_type: C, R or I
* type: component type
* data: Data for this component
*/
class ComponentClass extends Component {
computeComponentIDList(componentType){
......@@ -298,11 +290,11 @@ class ComponentClass extends Component {
return jsx
}
renderTestLine(key, data, component_id_list){
return (<StationSummaryLine key={key} ordered_component_ids={component_id_list} test_type="ST" component_type={this.props.type} station_type={this.props.station_type} data={data}/>)
renderStationTestLine(key, data, component_id_list){
return (<TestLine key={key} ordered_component_ids={component_id_list} test_type="ST" component_type={this.props.type} station_type={this.props.station_type} data={data}/>)
}
renderTestSummaryLine(key, data, component_id_list){
renderRTSMSummaryLine(key, data, component_id_list){
return (<RTSMSummaryLine key={key} ordered_component_ids={component_id_list} component_type={this.props.type} station_type={this.props.station_type} data={data}/>)
}
......@@ -311,29 +303,28 @@ class ComponentClass extends Component {
const rows = []
var tmp_rtsm_set = []
for(let i=0; i<data.length - 1; i++){
for (let i=0; i<data.length - 1; i++){
const next_item = data[i + 1]
const current_item = data[i]
if(current_item.test_type === 'R' ){
if (current_item.test_type === 'R' ){
tmp_rtsm_set.push(current_item)
}
if(current_item.test_type === 'R' && next_item.test_type === 'S'){
rows.push(this.renderTestSummaryLine(rows.length, tmp_rtsm_set, component_id_list))
if (current_item.test_type === 'R' && next_item.test_type === 'S'){
rows.push(this.renderRTSMSummaryLine(rows.length, tmp_rtsm_set, component_id_list))
tmp_rtsm_set = []
}else if(current_item.test_type === 'S'){
rows.push(this.renderTestLine(rows.length, current_item, component_id_list));
} else if (current_item.test_type === 'S'){
rows.push(this.renderStationTestLine(rows.length, current_item, component_id_list));
}
}
const lastTest = data[data.length - 1]
if(lastTest.test_type === 'R'){
if (lastTest.test_type === 'R'){
tmp_rtsm_set.push(lastTest)
}else{
rows.push(this.renderTestLine(rows.length, lastTest, component_id_list));
} else {
rows.push(this.renderStationTestLine(rows.length, lastTest, component_id_list));
}
if (tmp_rtsm_set.length > 0) {
rows.push(<RTSMSummaryLine key={rows.length} data={tmp_rtsm_set} component_type={this.props.type} ordered_component_ids={component_id_list}/>);
rows.push(this.renderRTSMSummaryLine(rows.length, tmp_rtsm_set, component_id_list))
tmp_rtsm_set = []
}
return rows
......@@ -405,7 +396,7 @@ class StationTestViewC extends Component {
const componentListTabs = Object.keys(this.props.data).map((componentType, key) =>
<TabPane key={key} tabId={componentType}>
<ComponentClass key={key} station_type={stationType} type={componentType} data={this.props.data[componentType]}/>
<ComponentClass key={componentType} station_type={stationType} type={componentType} data={this.props.data[componentType]}/>
</TabPane>
);
......
......@@ -184,16 +184,14 @@ class StationOverviewPageC extends Component {
<Header active_page={this.props.location} />
<ToolBar/>
{this.renderErrorIfParameterMissing()}
<Container fluid={true} style={{padding: '10px'}}>
<Row>
<Col md="8"><StationTestView url={this.getStationSummaryURL()} /></Col>
<Col md="4"><StationTestChildView /></Col>
</Row>
</Container>
{ this.isParameterMissing() ? "" :
<Container fluid={true} style={{padding: '10px'}}>
<Row>
<Col md="8"><StationTestView url={this.getStationSummaryURL()} /></Col>
<Col md="4"><StationTestChildView /></Col>
</Row>
</Container>
}
</React.Fragment>
);
}
......
export const SET_CHILD_PANEL_DATA = "SET_CHILD_PANEL_DATA";
export const UNPIN_CHILD_PANEL_DATA = "UNPIN_CHILD_PANEL_DATA";
export const setChildPanelData = data => ({
export const setChildPanelData = (data, pin = false) => ({
type: SET_CHILD_PANEL_DATA,
payload: { data }
payload: { data, pin }
});
export const unpinChildPanelData = () => ({
type: UNPIN_CHILD_PANEL_DATA,
payload: null
});
import {
SET_CHILD_PANEL_DATA
SET_CHILD_PANEL_DATA,
UNPIN_CHILD_PANEL_DATA
} from '../actions/stationOverviewPageActions.js'
......@@ -7,7 +8,8 @@ const initialState = {
// Child panel showing data on mouse hover
child_panel: {
data: null
data: null,
isPinned: false
},
layout: {
......@@ -59,10 +61,23 @@ const initialState = {
export default function(state = initialState, action) {
switch (action.type) {
case SET_CHILD_PANEL_DATA:
if (state.child_panel.isPinned && ! action.payload.pin) {
return state;
}
return {
...state,
child_panel: {
data: action.payload.data
data: action.payload.data,
isPinned: action.payload.pin
}
};
case UNPIN_CHILD_PANEL_DATA:
return {
...state,
child_panel: {
data: null,
isPinned: false
}
};
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment