diff --git a/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_suSummary.scss b/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_suSummary.scss index 5dd93b1f821a40844c462dde3c230dcc3e65dc8d..20832f18a82194b11ef531c965f3dd22a6b18d89 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_suSummary.scss +++ b/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_suSummary.scss @@ -56,4 +56,11 @@ overflow-y: scroll; border: 1px solid lightgrey; padding: 0px 10px 10px 10px; + left: 15px; + max-width: 5rem !important; + } + + .station-information { + display: flex; + column-gap: 5rem; } \ No newline at end of file diff --git a/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_timeline.scss b/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_timeline.scss index 74fb81eb3404d0205df2f84a77ffcf73f5ac9a71..da719c4ab245ac3f3cadf35321a667c961f05d07 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_timeline.scss +++ b/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_timeline.scss @@ -113,8 +113,25 @@ .timeline-details-pane { font-size: 14px; + flex-direction: column; } +.timeline-details-header { + display: flex; +} + +.timeline-details-overview { + display: flex; + flex-direction: column; + + .group { + display: flex; + flex-direction: row; + line-height: 0; + } +} + + #now-btn { margin-left: 10px; } diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/summary.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/summary.js index 71bc7a2fcb9415b023bf00c1bb74ebf87e33bfc7..23ca5775c061e9a9d411a9ff022012ae6faced5e 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/summary.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/summary.js @@ -44,11 +44,11 @@ export class SchedulingUnitSummary extends Component { this.showCancelSUConfirmation = this.showCancelSUConfirmation.bind(this); this.cancelSchedulingUnit = this.cancelSchedulingUnit.bind(this); this.closeDialog = this.closeDialog.bind(this); - } + } /** * Function to close the summary panel and call parent callback function to close. - */ + */ closeSUDets() { if (this.props.closeCallback) { this.props.closeCallback(); @@ -57,7 +57,7 @@ export class SchedulingUnitSummary extends Component { /** * Order the properties in the constraint object in the predefined order - * @param {Object} constraintsDoc + * @param {Object} constraintsDoc */ getOrderedConstraints(constraintsDoc, constraintsOrder) { let orderedConstraints = {}; @@ -72,7 +72,7 @@ export class SchedulingUnitSummary extends Component { } /** - * warn before cancel the page if any changes detected + * warn before cancel the page if any changes detected */ checkIsDirty() { if (this.state.isDirty) { @@ -86,7 +86,7 @@ export class SchedulingUnitSummary extends Component { /** * Format the constraint object i.e removes the empty values to show only available values. - * @param {Object} constraint + * @param {Object} constraint */ getFormattedConstraint(constraint) { if (constraint) { @@ -133,7 +133,7 @@ export class SchedulingUnitSummary extends Component { refPointing['pointing']['angle1'] = UnitConverter.getAngleInput(refPointing['pointing']['angle1']); refPointing['pointing']['angle2'] = UnitConverter.getAngleInput(refPointing['pointing']['angle2'], true); refPointing['enabled'] = refPointing.enabled?'true':'false'; - newObject[objectKey.replace(/_/g, ' ')] = refPointing; + newObject[objectKey.replace(/_/g, ' ')] = refPointing; } else { let object = this.getFormattedConstraint(constraint[objectKey]); if (object) { @@ -156,9 +156,9 @@ export class SchedulingUnitSummary extends Component { } /** - * Gets the output from the SchedulingConstraints editor without output formatting so that the values entered in the + * Gets the output from the SchedulingConstraints editor without output formatting so that the values entered in the * editor can be shown in the summary without any conversion. - * @param {Object} jsonOutput + * @param {Object} jsonOutput */ setConstraintsEditorOutput(jsonOutput, errors) { /* to update particular value on current component */ @@ -181,11 +181,11 @@ export class SchedulingUnitSummary extends Component { } async componentDidMount() { - const promises = [ + const promises = [ AuthUtil.getUserRolePermission() ]; this.setState({disableCancelBtn: this.props.schedulingUnit.status === 'cancelled'?true:false}); - this.updateConstraintTemplate(); + this.updateConstraintTemplate(); await Promise.all(promises).then(responses => { this.setState({userrole: responses[0],editCheck:1}); }); @@ -193,15 +193,15 @@ export class SchedulingUnitSummary extends Component { /** * Add new fields for plus/minu value for offset (from & to) - * @param {*} constraintTemplate - * @returns + * @param {*} constraintTemplate + * @returns */ async updateConstraintTemplate() { if (this.props.constraintsTemplate) { let constraintTemplate = this.props.constraintsTemplate; - constraintTemplate.schema.properties.sky.properties.transit_offset.properties.from.default = + constraintTemplate.schema.properties.sky.properties.transit_offset.properties.from.default = UnitConverter.getSecsToHHmmssWithSign(this.props.constraintsTemplate.schema.properties.sky.properties.transit_offset.properties.from.default); - constraintTemplate.schema.properties.sky.properties.transit_offset.properties.to.default = + constraintTemplate.schema.properties.sky.properties.transit_offset.properties.to.default = UnitConverter.getSecsToHHmmssWithSign(this.props.constraintsTemplate.schema.properties.sky.properties.transit_offset.properties.to.default); this.setState({constraintTemplate: constraintTemplate}); } @@ -209,8 +209,8 @@ export class SchedulingUnitSummary extends Component { /** * Format constraint field value for UI - * @param {*} scheduling_constraints_doc - * @returns + * @param {*} scheduling_constraints_doc + * @returns */ formatConstraintDocForUI(scheduleunit) { if (scheduleunit.scheduling_constraints_doc && scheduleunit.scheduling_constraints_doc.sky && scheduleunit.scheduling_constraints_doc.sky.transit_offset) { @@ -223,7 +223,7 @@ export class SchedulingUnitSummary extends Component { } return scheduleunit; } - + /** * Confirm Autodeletion before update the value */ @@ -233,7 +233,7 @@ export class SchedulingUnitSummary extends Component { dialog.header= "Confirm Pin/Unpin data after ingest"; dialog.detail = this.props.schedulingUnit.output_pinned ? 'Do you want to Unpin data after ingest?' : 'Do you want to Pin data after ingest?'; dialog.content = ''; - dialog.actions = [{id: 'yes', title: this.props.schedulingUnit.output_pinned?'Unpin data': 'Pin data', + dialog.actions = [{id: 'yes', title: this.props.schedulingUnit.output_pinned?'Unpin data': 'Pin data', className:this.props.schedulingUnit.output_pinned?'act-btn-dispose':'', callback: this.setAutoDeletion}, {id: 'no', title: 'Cancel', className:'act-btn-cancel', callback: this.closeDialog}]; dialog.onSubmit = this.setAutoDeletion; @@ -255,7 +255,7 @@ export class SchedulingUnitSummary extends Component { async setAutoDeletion() { let suCopy = _.cloneDeep(this.props.schedulingUnit); let tasks = []; - let updatedResSU = await ScheduleService.updateSchedulingUnitValue('blueprint', + let updatedResSU = await ScheduleService.updateSchedulingUnitValue('blueprint', {id: this.props.schedulingUnit.id, 'output_pinned': !this.props.schedulingUnit.output_pinned}, tasks); if (updatedResSU) { appGrowl.show({ severity: 'success', summary: 'Success', detail: `${updatedResSU.output_pinned?'Pin':'Unpin'} data after ingest updated successfully` }); @@ -306,7 +306,7 @@ export class SchedulingUnitSummary extends Component { } render() { - const permissions = this.state.userrole.userRolePermission.scheduleunit; + const permissions = this.state.userrole.userRolePermission.scheduleunit; let schedulingUnit = _.cloneDeep(this.props.schedulingUnit); if (this.currentSU.id !== schedulingUnit.id) { this.setState({schedulingUnit: schedulingUnit}); @@ -325,97 +325,131 @@ export class SchedulingUnitSummary extends Component { } return task; }); - const constraintsTemplate = this.props.constraintsTemplate; + const constraintsTemplate = this.props.constraintsTemplate; // After receiving output from the SchedulingConstraint editor order and format it to display schedulingUnit = this.formatConstraintDocForUI(schedulingUnit); - let constraintsDoc = schedulingUnit.scheduling_constraints_doc ? this.getOrderedConstraints(schedulingUnit.scheduling_constraints_doc,this.constraintsOrder) : null; + let constraintsDoc = schedulingUnit.scheduling_constraints_doc ? this.getOrderedConstraints(schedulingUnit.scheduling_constraints_doc,this.constraintsOrder) : null; let disableBtn= this.state.showerror!==0 ?true: false; return ( <React.Fragment> {schedulingUnit && <div className="p-grid timeline-details-pane" style={{ marginTop: '10px' }}> + <div className="timeline-details-header"> <h6 className="col-lg-9 col-sm-9">Scheduling Unit Details</h6> <Link onClick={this.redirectToSUDetails} title="View Full Details"> <i className="fa fa-eye" style={{paddingRight: '3px'}}></i></Link> - <Link onClick={this.showCancelSUConfirmation} - title={this.state.schedulingUnit.status === 'cancelled'?"Scheduling Unit already cancelled":"Cancel Scheduling Unit"} + <Link onClick={this.showCancelSUConfirmation} + title={this.state.schedulingUnit.status === 'cancelled'?"Scheduling Unit already cancelled":"Cancel Scheduling Unit"} className={this.state.schedulingUnit.status === 'cancelled'?"act-btn-disable":""} > - <i className="fa fa-ban" - style={{fontSize: '16px', paddingRight: '3px', color: this.state.schedulingUnit.status === 'cancelled'?'gray':'', + <i className="fa fa-ban" + style={{fontSize: '16px', paddingRight: '3px', color: this.state.schedulingUnit.status === 'cancelled'?'gray':'', cursor: this.state.schedulingUnit.status === 'cancelled'?'not-allowed':''}}></i></Link> - <Link onClick={this.confirmAutoDeletion} + <Link onClick={this.confirmAutoDeletion} title ={permissions.autodeletion? this.state.schedulingUnit.output_pinned? 'Unpin data after ingest' : 'Pin data after ingest' : `${this.access_denied_message} to do Pin/Unpin data after ingest`}> <i className="fa fa-thumbtack" style={{fontSize: '16px', paddingRight: '3px'}}></i></Link> <Link to={this.props.location ? this.props.location.pathname : "/su/timelineview"} onClick={this.closeSUDets} title="Close Details"><i className="fa fa-times"></i></Link> - <div className="col-5"><label>Name:</label></div> - <div className="col-7">{schedulingUnit.name}</div> - <div className="col-5"><label>Scheduling Unit Id:</label></div> - <div className="col-7">{schedulingUnit.id}</div> - <div className="col-5"><label>Project:</label></div> - <div className="col-7">{schedulingUnit.project}</div> - <div className="col-5"><label>Start Time:</label></div> - <div className="col-7">{moment.utc(schedulingUnit.start_time).format(UIConstants.CALENDAR_DATETIME_FORMAT)}</div> - <div className="col-5"><label>Stop Time:</label></div> - <div className="col-7">{moment.utc(schedulingUnit.stop_time).format(UIConstants.CALENDAR_DATETIME_FORMAT)}</div> - <div className="col-5"><label>Status:</label></div> - <div className="col-7"> - <span className={"tag-content p-chips-token-label su-"+schedulingUnit.status}>{schedulingUnit.status}</span> + </div> + <div className="timeline-details-overview"> + <div className="group"> + <label className="col-5">Name:</label> + <div className="col-5">{schedulingUnit.name}</div> + </div> + <div className="group"> + <label className="col-5">Scheduling Unit Id:</label> + <div className="col-5">{schedulingUnit.id}</div> + </div> + + <div className="group"> + <label className="col-5">Project:</label> + <div className="col-5">{schedulingUnit.project}</div> + </div> + + <div className="group"> + <label className="col-5">Start Time:</label> + <div className="col-5"> + {moment.utc(schedulingUnit.start_time).format(UIConstants.CALENDAR_DATETIME_FORMAT)} + </div> + </div> + + <div className="group"> + <label className="col-5">Stop Time:</label> + <div className="col-5"> + {moment.utc(schedulingUnit.stop_time).format(UIConstants.CALENDAR_DATETIME_FORMAT)} + </div> + </div> + + <div className="group"> + <label className="col-5">Status:</label> + <div className="col-5"> + <span className={"tag-content p-chips-token-label su-" + schedulingUnit.status}> + {schedulingUnit.status} + </span> + </div> + </div> + {schedulingUnit.status === 'unschedulable' && + <div className="group"> + <label className="col-5">Unschedule Reason:</label> + <div className="col-5">{schedulingUnit.unschedulable_reason}</div> + </div> + } </div> - {schedulingUnit.status === 'unschedulable' && - <> - <div className="col-5"><label>Unschedule Reason:</label></div> - <div className="col-7">{schedulingUnit.unschedulable_reason}</div> - </> - } - {constraintsDoc && + {constraintsDoc && <> - <> + <> <div className="col-12 constraints-summary" style={{ top:"0px",position:"relative",}}> <label>Constraints:</label> - {permissions.edit && (_.includes(_.split(process.env.REACT_APP_CONSTRAINT_EDITABLE_STATUS, ',' ), schedulingUnit.status)) ? - <i class="fa fa-pencil-alt" style={{ marginLeft:"5px",position:"absolute",top:"-3px",cursor:"pointer"}} - title = {'Edit Scheduling Constraint'} + {permissions.edit && (_.includes(_.split(process.env.REACT_APP_CONSTRAINT_EDITABLE_STATUS, ',' ), schedulingUnit.status)) ? + <i class="fa fa-pencil-alt" style={{ marginLeft:"5px",cursor:"pointer"}} + title = {'Edit Scheduling Constraint'} onClick={()=> this.props.onCloseFn(true)}> </i> : - <i class="fa fa-pencil-alt" style={{ marginLeft:"5px",position:"absolute",top:"-3px",color:"grey",cursor:"not-allowed"}} - title = {permissions.edit?`Constraints of scheduling unit with status ${schedulingUnit.status} cannot be edited`: + <i class="fa fa-pencil-alt" style={{ marginLeft:"5px",color:"grey",cursor:"not-allowed"}} + title = {permissions.edit?`Constraints of scheduling unit with status ${schedulingUnit.status} cannot be edited`: `Don't have permission to edit constraints`} onClick={()=> false }></i> } - </div> + </div> <div className="col-12"> <JsonToTable json={constraintsDoc} /> </div> </> - + </> - } - - <div className="col-12"><label>Stations:</label></div> - <div className="col-12 station-list"> - {this.props.stationGroup && this.props.stationGroup.map((station, index) => ( - <div key={`stn-${index}`}>{station}</div> - ))} - </div> - {this.props.missingStations && this.props.missingStations.length>0 && - <> - <div className="col-12"><label>Missing Stations:</label></div> + } + + <div className="station-information"> + <div> + <div className="col-12"><label>Stations:</label></div> <div className="col-12 station-list"> - {this.props.missingStations && this.props.missingStations.map((station, index) => ( - <div key={`mis-stn-${index}`}>{station}</div> + {this.props.stationGroup && this.props.stationGroup.map((station, index) => ( + <div key={`stn-${index}`}>{station}</div> ))} + </div> + </div> + <div> + <div className="col-12"><label>Missing Stations:</label></div> + <div className="col-12 station-list"> + <div>MOI</div> + </div> + {this.props.missingStations && this.props.missingStations.length>0 && + <div className="col-12 station-list"> + {this.props.missingStations && this.props.missingStations.map((station, index) => ( + <div key={`mis-stn-${index}`}>{station}</div> + ))} + </div> + } </div> - </> - } - + </div> + + <div className="col-12 task-summary"> <label>Tasks:</label> - <ViewTable - data={suTaskList} - defaultcolumns={[{id: "ID", name: "Name", short_description: "Short Description" , - typeValue:"Type", controlId: 'Control ID', - start_time:{name:"Start Time", format:UIConstants.CALENDAR_DATETIME_FORMAT}, - stop_time:{name:"End Time", format:UIConstants.CALENDAR_DATETIME_FORMAT}, + <ViewTable + data={suTaskList} + defaultcolumns={[{id: "ID", name: "Name", short_description: "Short Description" , + typeValue:"Type", controlId: 'Control ID', + start_time:{name:"Start Time", format:UIConstants.CALENDAR_DATETIME_FORMAT}, + stop_time:{name:"End Time", format:UIConstants.CALENDAR_DATETIME_FORMAT}, status: {name:"Status", showTag: true, tagClass: 'su-$dynamic$'}, unschedulable_reason: {name:"Unschedulable Reason"}, antenna_set: "Antenna Set", band: 'Band', obsolete: 'Obsolete'}]} optionalcolumns={[{actionpath: "actionpath"}]} columnclassname={[{"ID": "filter-input-50","Name":"filter-input-75","Type":"filter-input-75","Control ID":"filter-input-75", "Start Time": "filter-input-75", "End Time": "filter-input-75", @@ -428,72 +462,72 @@ export class SchedulingUnitSummary extends Component { showColumnFilter={false} allowColumnSelection={false} /> - </div> + </div> </div> - } + } {/* model for Constraints start */} - <div className={`custom-dlg`}> - <Dialog inputId="edit_constraint" - maximizable maximized={false} - style={{ width: '80vw' }} - header="Scheduling Constraints - Edit" + <div className={`custom-dlg`}> + <Dialog inputId="edit_constraint" + maximizable maximized={false} + style={{ width: '80vw' }} + header="Scheduling Constraints - Edit" visible={this.props.onClose || false} onHide = { () => { if (this.state.editCheck < 3) { this.setState({ - editCheck:1 + editCheck:1 },this.props.onCloseFn(false)); } else { if (this.props.onSavedisable === false) this.setState({ - editCheck:1 - }, this.props.cancelCheckstatus(true)); - } + editCheck:1 + }, this.props.cancelCheckstatus(true)); + } } } modal={true} footer={ - <div> + <div> <Button key="submit" className="p-button-primary" - disabled={disableBtn} + disabled={disableBtn} icon="pi pi-check" label="Save" onClick={() => { - this.props.onUpdate(this.props.schedulingUnit.id,this.state.updatedConstraintsValue) + this.props.onUpdate(this.props.schedulingUnit.id,this.state.updatedConstraintsValue) this.setState({ - editCheck:1 + editCheck:1 }); } } - /> + /> <Button key="cancel" className="act-btn-cancel" icon="pi pi-times" label="Cancel" onClick={() => { if (this.state.editCheck < 3) { this.setState({ - editCheck:1 + editCheck:1 },this.props.onCloseFn(false)); } else { if (this.props.onSavedisable === false) this.setState({ - editCheck:1 - }, this.props.cancelCheckstatus(true)); - } - }} - /> + editCheck:1 + }, this.props.cancelCheckstatus(true)); + } + }} + /> </div> } - > + > <SchedulingConstraints constraintTemplate={constraintsTemplate} initValue={this.props.schedulingUnit.scheduling_constraints_doc} - callback={this.setConstraintsEditorOutput} - /> + callback={this.setConstraintsEditorOutput} + /> </Dialog> </div> {/* moder for Constraints End */} <CustomDialog type="confirmation" visible={this.props.cancelStatus} width="40vw" - header={'Edit Scheduling Constraints'} message={'Do you want to discard your changes? Your changes to the Constraints will not be saved.'} - content={''} + header={'Edit Scheduling Constraints'} message={'Do you want to discard your changes? Your changes to the Constraints will not be saved.'} + content={''} onClose = { () => { if (this.state.editCheck < 3 && this.state.close === true) { @@ -511,7 +545,7 @@ export class SchedulingUnitSummary extends Component { } } - actions={ [ {id:"yes", title: 'Discard', callback: () =>{ + actions={ [ {id:"yes", title: 'Discard', callback: () =>{ this.setState({ editCheck: 1, close:true