diff --git a/SAS/TMSS/frontend/tmss_webapp/src/layout/components/CustomDialog.js b/SAS/TMSS/frontend/tmss_webapp/src/layout/components/CustomDialog.js index c8b2fc0f1307fb23cf51dbe4829d42abecbd4015..f6ac2e9b534b7af076fffe9c2cb061aca098af23 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/layout/components/CustomDialog.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/layout/components/CustomDialog.js @@ -42,7 +42,7 @@ export class CustomDialog extends Component { {/* Action button based on the 'actions' props */} {this.props.actions && this.props.actions.map((action, index) => { return ( - <Button key={action.id} label={action.title} onClick={action.callback} className= {(action.className)? action.className: "" }/> + <Button key={action.id} label={action.title} onClick={action.callback} className= {(action.className)? action.className: "" } style={(action.style)? action.style: {}}/> ); })} </div> diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/excelview.schedulingset.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/excelview.schedulingset.js index e4f9a04a00bf5c6d8e3ba19c5ebb989a2cc1d80d..6a1591531ac9f8f82b8d0058c5051f55ebae39d7 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/excelview.schedulingset.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/excelview.schedulingset.js @@ -178,7 +178,7 @@ export class SchedulingSetCreate extends Component { this.emptyAGSU = {}; this.priorityQueuelist = []; this.intervelTrigger = null; - + this.warningClipboardData = '' this.onProjectChange = this.onProjectChange.bind(this); this.setSchedulingSetParams = this.setSchedulingSetParams.bind(this); this.onStrategyChange = this.onStrategyChange.bind(this); @@ -213,6 +213,7 @@ export class SchedulingSetCreate extends Component { this.setSUSet = this.setSUSet.bind(this); this.copyClipText = this.copyClipText.bind(this); this.observOptionTemplate = this.observOptionTemplate.bind(this); + this.copyWarningContent = this.copyWarningContent.bind(this); this.formRules = { // Form validation rules project: {required: true, message: "Select project to get Scheduling Sets"}, @@ -1465,10 +1466,14 @@ export class SchedulingSetCreate extends Component { this.agSUWithDefaultValue['min_calibrator_elevation'] = ((this.constraintSchema.schema.properties.sky.properties.min_elevation.properties.calibrator.default * 180) / Math.PI).toFixed(2); this.agSUWithDefaultValue['offset_from'] = (this.constraintSchema.schema.properties.sky.properties.transit_offset.properties.from.default<0?'-':'')+UnitConverter.getSecsToHHmmss(this.constraintSchema.schema.properties.sky.properties.transit_offset.properties.from.default); this.agSUWithDefaultValue['offset_to'] = (this.constraintSchema.schema.properties.sky.properties.transit_offset.properties.to.default<0?'-':'')+UnitConverter.getSecsToHHmmss(this.constraintSchema.schema.properties.sky.properties.transit_offset.properties.to.default); - this.agSUWithDefaultValue['offset_from_max'] = this.constraintSchema.schema.properties.sky.properties.transit_offset.properties.from.maximum; - this.agSUWithDefaultValue['offset_from_min'] = this.constraintSchema.schema.properties.sky.properties.transit_offset.properties.from.minimum; - this.agSUWithDefaultValue['offset_to_max'] = this.constraintSchema.schema.properties.sky.properties.transit_offset.properties.to.maximum; - this.agSUWithDefaultValue['offset_to_min'] = this.constraintSchema.schema.properties.sky.properties.transit_offset.properties.to.minimum; + const maxOffsetFrom = this.constraintSchema.schema.properties.sky.properties.transit_offset.properties.from.maximum; + const minOffsetFrom = this.constraintSchema.schema.properties.sky.properties.transit_offset.properties.from.minimum; + this.agSUWithDefaultValue['offset_from_max'] = maxOffsetFrom; + this.agSUWithDefaultValue['offset_from_min'] = minOffsetFrom; + const maxOffsetTo = this.constraintSchema.schema.properties.sky.properties.transit_offset.properties.to.maximum; + const minOffsetTo = this.constraintSchema.schema.properties.sky.properties.transit_offset.properties.to.minimum; + this.agSUWithDefaultValue['offset_to_max'] = maxOffsetTo; + this.agSUWithDefaultValue['offset_to_min'] = minOffsetTo; this.agSUWithDefaultValue['md_sun'] = ((this.constraintSchema.schema.properties.sky.properties.min_distance.properties.sun.default * 180) / Math.PI).toFixed(2); this.agSUWithDefaultValue['md_moon'] = ((this.constraintSchema.schema.properties.sky.properties.min_distance.properties.moon.default * 180) / Math.PI).toFixed(2); this.agSUWithDefaultValue['md_jupiter'] = ((this.constraintSchema.schema.properties.sky.properties.min_distance.properties.jupiter.default) / Math.PI).toFixed(2); @@ -1519,8 +1524,30 @@ export class SchedulingSetCreate extends Component { } } }, }, - {headerName: 'Offset Window From',field: 'offset_from',cellRenderer: 'betweenRenderer',cellEditor: 'offsetTimeInputmask',valueSetter: 'newValueSetter',}, - {headerName: 'Offset Window To',field: 'offset_to', cellRenderer: 'betweenRenderer',cellEditor: 'offsetTimeInputmask',valueSetter: 'newValueSetter', }, + {headerName: 'Offset Window From',field: 'offset_from',cellRenderer: 'betweenRenderer',cellEditor: 'offsetTimeInputmask',valueSetter: 'newValueSetter',cellStyle: function(params) { + const cellValue = _.split(params.value, ":"); + if ( typeof params.value === 'undefined' || + (cellValue.length !== 3 || isNaN(cellValue[1]) || cellValue[1]>59 || isNaN(cellValue[2]) || cellValue[2]>59)){ + return { backgroundColor: BG_COLOR}; + } else if ( UnitConverter.getHHmmssToSecs(params.value) < minOffsetFrom || + UnitConverter.getHHmmssToSecs(params.value) > maxOffsetFrom) { + return { backgroundColor: BG_COLOR}; + } else { + return { backgroundColor: ''}; + } + }}, + {headerName: 'Offset Window To',field: 'offset_to', cellRenderer: 'betweenRenderer',cellEditor: 'offsetTimeInputmask',valueSetter: 'newValueSetter', cellStyle: function(params) { + const cellValue = _.split(params.value, ":"); + if ( typeof params.value === 'undefined' || + (cellValue.length !== 3 || isNaN(cellValue[1]) || cellValue[1]>59 || isNaN(cellValue[2]) || cellValue[2]>59)){ + return { backgroundColor: BG_COLOR}; + } else if ( UnitConverter.getHHmmssToSecs(params.value) < minOffsetTo || + UnitConverter.getHHmmssToSecs(params.value) > maxOffsetTo) { + return { backgroundColor: BG_COLOR}; + } else { + return { backgroundColor: ''}; + } + }}, ], }); this.colKeyOrder.push('md_sun'); @@ -1700,6 +1727,7 @@ export class SchedulingSetCreate extends Component { let inValidCount = 0; let isValidRow = true; let errorDisplay = []; + let warningClipboardData = ''; //const colDefkeys = Object.keys(this.columnDefinition); const mandatoryKeys = ['suname','sudesc','priority_queue','scheduler','min_target_elevation','min_calibrator_elevation','offset_from','offset_to','md_sun','md_moon','md_jupiter','param_0~angle1','param_0~angle2','param_0~direction_type','param_1~angle1','param_1~angle2','param_1~direction_type','param_2~angle1','param_2~angle2','param_2~direction_type']; let tmpMandatoryKeys = []; @@ -1711,12 +1739,13 @@ export class SchedulingSetCreate extends Component { this.state.gridApi.forEachNode(function (node) { isValidRow = true; - let errorMsg = 'Row # ['+(Number(node.rowIndex)+1) +'] : '; + let errorMsg = 'Row # ['+(Number(node.rowIndex)+1) +']'; tmpMandatoryKeys = []; const rowData = node.data; let isFixedTimeScheduler = false; let hasData = true; if (rowData) { + errorMsg = errorMsg + ` (${rowData['suname']}) : ` for(const key of mandatoryKeys) { if (rowData[key] === '') { if ( key === 'suname' ){ @@ -2004,11 +2033,12 @@ export class SchedulingSetCreate extends Component { } else { inValidCount++; tmpRowData[node.rowIndex]['isValid'] = false; + warningClipboardData = warningClipboardData + errorMsg.slice(0, -2) + '\n'; errorDisplay.push(errorMsg.slice(0, -2)); } } }); - + this.warningClipboardData = warningClipboardData; if (validCount > 0 && inValidCount === 0) { // save SU directly this.saveSU(); @@ -2036,6 +2066,10 @@ export class SchedulingSetCreate extends Component { this.onClose = () => { this.setState({confirmDialogVisible: false}); }; + this.actions = [ + {id: "copy_warning_btn", style: {float: 'left', backgroundColor: '#ffbb08', borderColor: '#ffbb08'}, title: "Copy Warning", callback: this.copyWarningContent}, + {id: "yes_btn", title: "Yes", callback: this.saveSU}, + {id: "cancel_btn", title: "No", callback: this.onCancel},]; this.dialogType = "confirmation"; this.dialogHeader = "Save Scheduling Unit(s)"; this.dialogMsg = "Some of the Scheduling Unit(s) has invalid data, Do you want to ignore and save valid Scheduling Unit(s) only?"; @@ -2043,6 +2077,15 @@ export class SchedulingSetCreate extends Component { } } + /** + * Copy warning content to clipboard + */ + + async copyWarningContent() { + await navigator.clipboard.writeText(this.warningClipboardData); + this.growl.show({severity: 'success', summary: '', detail: 'Warning copied to clipboard '}); + } + /** * Show the content in custom dialog */ @@ -2050,7 +2093,7 @@ export class SchedulingSetCreate extends Component { if (typeof this.state.errorDisplay === 'undefined' || this.state.errorDisplay.length === 0 ){ return ""; } else { - return <> <br/>Invalid Rows:- Row # and Invalid columns <br/>{this.state.errorDisplay && this.state.errorDisplay.length>0 && + return <> <br/>Invalid Rows:- Row # , Name and Invalid columns<br/>{this.state.errorDisplay && this.state.errorDisplay.length>0 && this.state.errorDisplay.map((msg, index) => ( <React.Fragment key={index+10} > <span key={'label1-'+ index}>{msg}</span> <br /> @@ -2301,6 +2344,7 @@ export class SchedulingSetCreate extends Component { let updateSu = await ScheduleService.updateSUDraftFromObservStrategy(observStrategy, newSU, taskDrafts, this.state.tasksToUpdate, tmpStationGroups); suUpdateStatus['suStatus']= "Success"; suUpdateStatus['taskName']= updateSu.taskName; + suUpdateStatus['suId'] = updateSu.id; if (updateSu && !updateSu.isSUUpdated) { isUpdated = false; suUpdateStatus['taskStatus']= "Failed"; @@ -2324,6 +2368,7 @@ export class SchedulingSetCreate extends Component { let updateSu = await ScheduleService.saveSUDraftFromObservStrategy(observStrategy, newSchedulueUnit, newConstraint, tmpStationGroups); suUpdateStatus['suStatus']= "Success"; suUpdateStatus['taskName']= updateSu.taskName; + suUpdateStatus['suId'] = updateSu.id; if (updateSu && !updateSu.isSUUpdated) { isUpdated = false; suUpdateStatus['taskStatus']= "Failed"; @@ -2342,12 +2387,12 @@ export class SchedulingSetCreate extends Component { this.showIcon = true; this.dialogWidth = "60vw"; if (isUpdated) { - this.dialogMsg = '['+newSUCount+'] Scheduling Units are created & ['+existingSUCount+'] Scheduling Units are updated successfully.'; + this.dialogMsg = newSUCount+' Scheduling Units are created & '+existingSUCount+' Scheduling Units are updated successfully.'; } else { this.dialogHeader = "Warning"; - this.dialogMsg = '['+newSUCount+'] Scheduling Units are created & ['+existingSUCount+'] Scheduling Units are updated successfully, and there are some Schedule Unit/Task failed to create/update'; + this.dialogMsg = newSUCount+' Scheduling Units are created & '+existingSUCount+' Scheduling Units are updated successfully, and there are some Schedule Unit/Task failed to create/update'; } - + this.actions= null; this.dialogContent = this.getSchedulingDialogContent; this.onCancel = null; this.onClose = this.reset; @@ -2376,6 +2421,7 @@ export class SchedulingSetCreate extends Component { <div style={{marginTop: '1em'}}> <b>Scheduling Unit(s) & Task(s) status</b> <DataTable value={suStatus} resizableColumns columnResizeMode="expand" className="card" style={{paddingLeft: '0em'}}> + <Column field="suId" header="Scheduling Unit ID"></Column> <Column field="suName" header="Scheduling Unit Name"></Column> <Column field="action" header="Action"></Column> <Column field="suStatus" header="Scheduling Unit Status"></Column>