diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/create.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/create.js index c44523abce0b03dcbfb380b23f30ef526a4bf511..991aa8e152285f47d28f995c9a430c0140b0221d 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/create.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/create.js @@ -1,16 +1,16 @@ import PropTypes from 'prop-types'; -import React, {Component} from 'react'; -import {Redirect} from 'react-router-dom'; +import React, { Component } from 'react'; +import { Redirect } from 'react-router-dom'; import _ from 'lodash'; import $RefParser from "@apidevtools/json-schema-ref-parser"; import moment from 'moment'; -import {publish} from '../../App'; +import { publish } from '../../App'; -import {Checkbox} from 'primereact/checkbox'; -import {InputText} from 'primereact/inputtext'; -import {InputTextarea} from 'primereact/inputtextarea'; -import {Dropdown} from 'primereact/dropdown'; -import {Toast} from 'primereact/toast'; +import { Checkbox } from 'primereact/checkbox'; +import { InputText } from 'primereact/inputtext'; +import { InputTextarea } from 'primereact/inputtextarea'; +import { Dropdown } from 'primereact/dropdown'; +import { Toast } from 'primereact/toast'; import AppLoader from '../../layout/components/AppLoader'; import Jeditor from '../../components/JSONEditor/JEditor'; import UnitConversion from '../../utils/unit.converter'; @@ -23,14 +23,14 @@ import ParserUtility from '../../utils/parser.utility'; import PageHeader from '../../layout/components/PageHeader'; import SchedulingConstraint from './Scheduling.Constraints'; import Stations from './Stations'; -import {CustomDialog} from '../../layout/components/CustomDialog'; +import { CustomDialog } from '../../layout/components/CustomDialog'; import SchedulingSet from './schedulingset.create'; import UtilService from '../../services/util.service'; import ReactTooltip from "react-tooltip"; import AuthUtil from '../../utils/auth.util'; -import {appGrowl, setAppGrowl} from '../../layout/components/AppGrowl'; +import { appGrowl, setAppGrowl } from '../../layout/components/AppGrowl'; import FormActionbar from '../../components/FormActionbar'; -import {getConstraintTemplate, getTaskTemplateForTask} from "./create.helper"; +import { getConstraintTemplate, getTaskTemplateForTask } from "./create.helper"; import ObservationStrategySelector, { queryMatchingObservationStrategyTemplates } from "./components/ObservationStrategySelector"; @@ -40,24 +40,24 @@ import ProjectScheduleSetSelector from "./components/ProjectScheduleSetSelector" * Component to create a new SchedulingUnit from Observation strategy template */ export class SchedulingUnitCreate extends Component { - constructor(props) { + constructor(props) { super(props); this.state = { observStrategyFilters: { states: ['active'], purpose: [] }, - constraintValidEditor:false, - validForm:false, - validConstraints:false, - validSpecification:false, + constraintValidEditor: false, + validForm: false, + validConstraints: false, + validSpecification: false, userrole: {}, selectedProject: {}, showAddSet: false, showDialog: false, isDirty: false, isLoading: true, // Flag for loading spinner - dialog: {header: '', detail: ''}, // Dialog properties + dialog: { header: '', detail: '' }, // Dialog properties touched: {}, redirect: null, // URL to redirect errors: [], // Form Validation errors @@ -98,10 +98,10 @@ export class SchedulingUnitCreate extends Component { this.myRoles = {}; this.nameInput = React.createRef(); // Ref to Name field for auto focus this.formRules = { // Form validation rules - name: {required: true, message: "Name can not be empty"}, - description: {required: true, message: "Description can not be empty"}, - project: {required: true, message: "Select project to get Scheduling Sets"}, - scheduling_set_id: {required: true, message: "Select the Scheduling Set"}, + name: { required: true, message: "Name can not be empty" }, + description: { required: true, message: "Description can not be empty" }, + project: { required: true, message: "Select project to get Scheduling Sets" }, + scheduling_set_id: { required: true, message: "Select the Scheduling Set" }, }; this.isDebuggLoggingEnabled = false this.setEditorOutput = this.setEditorOutput.bind(this); @@ -128,21 +128,21 @@ export class SchedulingUnitCreate extends Component { this.init = this.init.bind(this); } - + componentDidMount() { this.init(); } async init() { const permission = await AuthUtil.getUserPermissionByModule('scheduleunit_draft'); - this.setState({userrole: permission}); + this.setState({ userrole: permission }); const promises = [ProjectService.getProjectList(false, 'name,url'), - TaskService.getTaskTemplates(), - ScheduleService.getSchedulingConstraintTemplates(), - UtilService.getPriorityQueueType(), - TaskService.getTaskFilterDefinition('draft'), - ScheduleService.getStrategyPurpose(), - ScheduleService.getStrategyState(), - ProjectService.getMyRoles(), + TaskService.getTaskTemplates(), + ScheduleService.getSchedulingConstraintTemplates(), + UtilService.getPriorityQueueType(), + TaskService.getTaskFilterDefinition('draft'), + ScheduleService.getStrategyPurpose(), + ScheduleService.getStrategyState(), + ProjectService.getMyRoles(), ]; Promise.all(promises).then(async (responses) => { this.projects = responses[0]; @@ -166,7 +166,7 @@ export class SchedulingUnitCreate extends Component { }) } if (this.state.schedulingUnit.project) { - const selectedProject = _.filter(this.projects, {'name': this.state.schedulingUnit.project}); + const selectedProject = _.filter(this.projects, { 'name': this.state.schedulingUnit.project }); const projectSchedSets = await ScheduleService.getSchedulingSets(`project=${encodeURIComponent(this.state.schedulingUnit.project)}`); let tmpSU = this.state.schedulingUnit; tmpSU['output_pinned'] = selectedProject[0].auto_pin; @@ -177,12 +177,12 @@ export class SchedulingUnitCreate extends Component { schedulingUnit: tmpSU }); } else { - this.setState({isLoading: false}); + this.setState({ isLoading: false }); } }); - let observStrategyFilter = UtilService.localStore({type: 'get', key: 'strategyFilterSUCreate'}); + let observStrategyFilter = UtilService.localStore({ type: 'get', key: 'strategyFilterSUCreate' }); if (Object.keys(observStrategyFilter).length === 0) { - observStrategyFilter = {states: ['active'], purpose: []} + observStrategyFilter = { states: ['active'], purpose: [] } } this.setState({ @@ -199,7 +199,7 @@ export class SchedulingUnitCreate extends Component { if (filterValues) { let optionList = []; filterValues.forEach(choice => { - const tmpVar = {name: choice.value, value: choice.value}; + const tmpVar = { name: choice.value, value: choice.value }; if (filterId === 'purpose') { optionList.push(tmpVar); } @@ -220,18 +220,21 @@ export class SchedulingUnitCreate extends Component { let schedulingUnit = this.state.schedulingUnit; schedulingUnit.project = projectName; schedulingUnit.scheduling_set_id = null; - const selectedProject = _.filter(this.projects, {'name': projectName}); + const selectedProject = _.filter(this.projects, { 'name': projectName }); schedulingUnit['output_pinned'] = selectedProject[0].auto_pin; if (!this.state.isDirty) { publish('edit-dirty', true); } + this.setState({ selectedProject: selectedProject, schedulingUnit: schedulingUnit, schedulingSets: projectSchedSets, - validForm: this.validateForm('project'), + validForm: this.validateForm('project', projectName, schedulingUnit) && this.validateForm('scheduling_set_id'), // project is valid, we selected, but we deselected scheduling isDirty: true }); + + } /** @@ -239,10 +242,11 @@ export class SchedulingUnitCreate extends Component { * It generates the JSON schema for JSON editor and defult vales for the parameters to be captured * @param {number} strategyId */ - async changeStrategy(strategyId) { - const observStrategy = _.cloneDeep(_.find(this.state.observStrategies, {'id': strategyId})); + async changeStrategy(strategyId, isSecondRound = false) { + if (this.isDebuggLoggingEnabled) console.log("changing strategy to " + strategyId) + const observStrategy = _.cloneDeep(_.find(this.state.observStrategies, { 'id': strategyId })); if (ParserUtility.addStationParameters(observStrategy)) { - this.setState({ + this.setState({ observStrategy: observStrategy, constraintSchema: null }); @@ -259,6 +263,8 @@ export class SchedulingUnitCreate extends Component { let bandPassFilter = null; // Take the constraint template schema as mentioned in the observing strategy this.setStrategyConstraint(observStrategy.template.scheduling_constraints_template.name, observStrategy.template.scheduling_constraints_template.version); + if (this.isDebuggLoggingEnabled) console.log(" was one changing strategy to " + strategyId) + const $strategyRefs = await $RefParser.resolve(observStrategy.template); // TODo: This schema reference resolving code has to be moved to common file and needs to rework for (const param of parameters) { @@ -280,17 +286,18 @@ export class SchedulingUnitCreate extends Component { stationGroups[param.name] = $strategyRefs.get(param.refs[0]); } else { const taskTemplate = getTaskTemplateForTask(this.taskTemplates, task); - + if (this.isDebuggLoggingEnabled) console.log("changing strategy to " + strategyId) if (['target observation', 'beamforming observation'].indexOf(taskTemplate.name.toLowerCase()) >= 0) { observationType = taskTemplate.name; } + if (this.isDebuggLoggingEnabled) console.log("observation type changed to " + observationType) // Get the default Bandpass filter and pass to the editor for frequency calculation from subband list if (taskTemplate.type_value === 'observation' && task.specifications_doc.station_configuration?.filter) { bandPassFilter = task.specifications_doc.station_configuration?.filter; } else if (taskTemplate.type_value === 'observation' && taskTemplate.ref_resolved_schema.definitions.filter) { bandPassFilter = taskTemplate.ref_resolved_schema.definitions.filter.default; } - schema.definitions = {...schema.definitions, ...taskTemplate?.ref_resolved_schema.definitions}; + schema.definitions = { ...schema.definitions, ...taskTemplate?.ref_resolved_schema.definitions }; taskPaths.reverse(); const paramProp = await ParserUtility.getParamProperty($strategyRefs, taskPaths, taskTemplate.ref_resolved_schema, this.taskFilters); schema.properties[param.name] = _.cloneDeep(paramProp); @@ -304,18 +311,20 @@ export class SchedulingUnitCreate extends Component { } } } + if (!this.state.isDirty) { publish('edit-dirty', true); } + if (this.isDebuggLoggingEnabled) console.log("changing strategy in progress " + schema, stationGroups, paramsOutput, bandPassFilter) this.setState({ observStrategy: observStrategy, paramsSchema: _.cloneDeep(schema), constraintParamsOutput: null, observationType: observationType, stationsCollapsed: false, paramsOutput: paramsOutput, stationGroups: stationGroups, bandPassFilter: bandPassFilter, isDirty: true - }); + }, this.state.callbackFunction); // Function called to clear the JSON Editor fields and reload with new schema - if (this.state.editorFunction) { - this.state.editorFunction(); + if (!isSecondRound) { + setTimeout(() => { this.changeStrategy(strategyId, true) }, 1); } } @@ -329,8 +338,8 @@ export class SchedulingUnitCreate extends Component { this.paramsOutput = jsonOutput; this.validEditor = errors.length === 0; this.updateParameters(); - if (errors.length > 0 ) { - this.setState({errors: [...errors]}) + if (errors.length > 0) { + this.setState({ errors: [...errors] }) } this.setState({ paramsOutput: jsonOutput, @@ -345,10 +354,12 @@ export class SchedulingUnitCreate extends Component { * @param {Object} updatedSpecificationDoc Object which needs to be validated */ async validateSpecificationsDoc(updatedObservStrategy) { + if (updatedObservStrategy) { const promises = []; promises.push(ScheduleService.validateSpecificationsDoc(updatedObservStrategy.scheduling_unit_template, updatedObservStrategy.template)) const validation_result = await Promise.all(promises); + if (this.isDebuggLoggingEnabled) console.log("validateSpecificationsDoc", updatedObservStrategy, validation_result) if (validation_result.length > 0) { let validationMessage = validation_result[0]['message']; if (validation_result[0]['valid']) { @@ -366,11 +377,11 @@ export class SchedulingUnitCreate extends Component { if (updatedConstraintParmas) { let schedulingConstraintsDoc = updatedConstraintParmas.scheduling_constraints_doc; if (schedulingConstraintsDoc.time) - for (const key of _.keys(schedulingConstraintsDoc.time)) { - if (!schedulingConstraintsDoc.time[key]) { - delete schedulingConstraintsDoc.time[key]; + for (const key of _.keys(schedulingConstraintsDoc.time)) { + if (!schedulingConstraintsDoc.time[key]) { + delete schedulingConstraintsDoc.time[key]; + } } - } const promises = []; promises.push(ScheduleService.validateSpecificationsDoc(updatedConstraintParmas.constraint.url, schedulingConstraintsDoc)) const validation_result = await Promise.all(promises); @@ -414,7 +425,7 @@ export class SchedulingUnitCreate extends Component { if (defaultValues) { this.defaultConstraints = parentProps; } else { - this.setState({constraintInitParams: parentProps}); + this.setState({ constraintInitParams: parentProps }); } // After converting the sky values, set the value directly in the JSON editor using the function passed from the editor if (this.state.constraintEditorFunction) { @@ -430,8 +441,8 @@ export class SchedulingUnitCreate extends Component { this.constraintParamsOutput = jsonOutput; // When the constraint template is changed, get the default values from the template and overwrite with values from strategy if (!this.state.constraintParamsOutput) { - if (this.state.observStrategy.template!==undefined) { - this.loadConstraints(_.cloneDeep(this.state.observStrategy.template.scheduling_constraints_doc), _.cloneDeep(jsonOutput), false); + if (this.state.observStrategy.template !== undefined) { + this.loadConstraints(_.cloneDeep(this.state.observStrategy.template.scheduling_constraints_doc), _.cloneDeep(jsonOutput), false); } } this.constraintValidEditor = err.length === 0; @@ -470,7 +481,7 @@ export class SchedulingUnitCreate extends Component { * @param {object} value */ async setSchedUnitParams(key, value) { - if (this.isDebuggLoggingEnabled) console.log("setSchedUnitParams",key,value) + if (this.isDebuggLoggingEnabled) console.log("setSchedUnitParams", key, value) this.setState({ touched: { ...this.state.touched, @@ -492,7 +503,7 @@ export class SchedulingUnitCreate extends Component { schedulingUnit[key] = value; let schedulingUnitList = await ScheduleService.getSchedulingBySet(value, 'observation_strategy_template_id'); let observationIdSet = _.uniq(_.map(schedulingUnitList, 'observation_strategy_template_id')); - this.setState({observationIdSet: observationIdSet}); + this.setState({ observationIdSet: observationIdSet }); } else { schedulingUnit[key] = value; } @@ -501,23 +512,26 @@ export class SchedulingUnitCreate extends Component { if (!this.state.isDirty) { publish('edit-dirty', true); } - this.setState({schedulingUnit: schedulingUnit,validForm: this.validateForm(key), validEditor: this.validateEditor(), isDirty: true},this.validateEditor); + this.setState({ schedulingUnit: schedulingUnit, validForm: this.validateForm(key, value), validEditor: this.validateEditor(), isDirty: true }, this.validateEditor); } else { - this.setState({schedulingUnit: schedulingUnit, validForm: this.validateForm(key), validEditor: this.validateEditor()}, this.validateEditor); + this.setState({ schedulingUnit: schedulingUnit, validForm: this.validateForm(key, value), validEditor: this.validateEditor() }, this.validateEditor); } + + } + /** * JEditor's function that to be called when parent wants to trigger change in the JSON Editor * @param {Function} editorFunction */ setEditorFunction(editorFunction) { - this.setState({editorFunction: editorFunction}); + this.setState({ editorFunction: editorFunction }); } setConstraintEditorFun(editorFunction) { - this.setState({constraintEditorFunction: editorFunction}); + this.setState({ constraintEditorFunction: editorFunction }); } /** @@ -525,8 +539,10 @@ export class SchedulingUnitCreate extends Component { * If no argument passed for fieldName, validates all fields in the form. * @param {string} fieldName */ - validateForm(fieldName) { - + validateForm(fieldName, value = this.state.schedulingUnit[fieldName], schedulingUnit = this.state.schedulingUnit) { + + if (this.isDebuggLoggingEnabled) console.log("validateForm validating " + fieldName + " with value " + value, this.state.schedulingUnit) + let validForm = false; let errors = this.state.errors; let validFields = this.state.validFields; @@ -536,24 +552,27 @@ export class SchedulingUnitCreate extends Component { delete validFields[fieldName]; if (this.formRules[fieldName]) { const rule = this.formRules[fieldName]; - const fieldValue = this.state.schedulingUnit[fieldName]; - + const fieldValue = value if (rule.required) { if (!fieldValue) { - if (this.isDebuggLoggingEnabled) console.log("validateForm",fieldName,rule,fieldValue, this.state.schedulingUnit) + + if (this.isDebuggLoggingEnabled) console.log(" Not Filled. validateForm", fieldName, rule, fieldValue, this.state.schedulingUnit) errors[fieldName] = rule.message ? rule.message : `${fieldName} is required`; } else { + + if (this.isDebuggLoggingEnabled) console.log(" All Good validateForm", fieldName, rule, fieldValue, this.state.schedulingUnit) validFields[fieldName] = true; } } } } else { + errors = {}; validFields = {}; for (const fieldName in this.formRules) { const rule = this.formRules[fieldName]; - const fieldValue = this.state.schedulingUnit[fieldName]; + const fieldValue = schedulingUnit[fieldName]; if (rule.required) { if (!fieldValue) { errors[fieldName] = rule.message ? rule.message : `${fieldName} is required`; @@ -564,16 +583,22 @@ export class SchedulingUnitCreate extends Component { } } const updatedErrors = errors.length > 0 ? [...this.state.errors, errors] : this.state.errors - const updatedValidFields = validFields ? {...this.state.validFields, ...validFields} : this.state.validFields; - this.setState({errors: updatedErrors, validFields: updatedValidFields}); - if (Object.keys(validFields).length === Object.keys(this.formRules).length) { + const updatedValidFields = validFields ? { ...this.state.validFields, ...validFields } : this.state.validFields; + if (this.isDebuggLoggingEnabled) console.log("set state validFields", updatedValidFields) + this.setState({ errors: updatedErrors, validFields: updatedValidFields }); + let lengthkeys = Object.keys(validFields).length; + let lengthRules = Object.keys(this.formRules).length; + + if (lengthkeys === lengthRules) { validForm = true; } const validStations = this.validateStations(); - return validForm && validStations && _.sum(_.values(this.state.missingStnErorsofTask)) <= 0; + let sumofstations = _.sum(_.values(this.state.missingStnErorsofTask)) <= 0; + if (this.isDebuggLoggingEnabled) console.log("Validating Form result:" + validForm, " validStations:", validStations, " sumofstations:" + sumofstations, "lengthkeys+" + lengthkeys + " , lengthRules+", lengthRules, validFields, this.formRules, schedulingUnit) + return validForm && validStations && sumofstations; } - /** + /* * Checks if at least one station selected for each station_group parameter and max_nr_missing station value is entered. * @returns Boolean */ @@ -648,21 +673,21 @@ export class SchedulingUnitCreate extends Component { let station_groups = []; if (ref.includes("station_groups")) { if (this.state.selectedStationsOfTask[param.name]) - for (const selectedGroup of this.state.selectedStationsOfTask[param.name]) { - const stnGroup = this.state.missingStationsofTask[param.name][selectedGroup]; - station_groups.push({ - stations: stnGroup.stations, - max_nr_missing: parseInt(stnGroup.max_nr_missing) - }); - } + for (const selectedGroup of this.state.selectedStationsOfTask[param.name]) { + const stnGroup = this.state.missingStationsofTask[param.name][selectedGroup]; + station_groups.push({ + stations: stnGroup.stations, + max_nr_missing: parseInt(stnGroup.max_nr_missing) + }); + } - if ( this.state.customStationsOfTask[param.name]) - for (const customGroup of this.state.customStationsOfTask[param.name]) { - station_groups.push({ - stations: customGroup.stations, - max_nr_missing: parseInt(customGroup.max_nr_missing) - }); - } + if (this.state.customStationsOfTask[param.name]) + for (const customGroup of this.state.customStationsOfTask[param.name]) { + station_groups.push({ + stations: customGroup.stations, + max_nr_missing: parseInt(customGroup.max_nr_missing) + }); + } $refs.set(observStrategy.template.parameters[index]['refs'][refIndex], station_groups); } else { $refs.set(observStrategy.template.parameters[index]['refs'][refIndex], this.state.paramsOutput[param.name]); @@ -682,7 +707,7 @@ export class SchedulingUnitCreate extends Component { validSpecificationMessage: message }) } - this.setState({updatedObservStrategy: observStrategy}); + this.setState({ updatedObservStrategy: observStrategy }); } /** @@ -690,29 +715,29 @@ export class SchedulingUnitCreate extends Component { */ updateConstraintsParams() { const constStrategy = _.cloneDeep(this.state.constraintParamsOutput); - if (constStrategy) - for (let type in constStrategy.time) { - if (constStrategy.scheduler === 'online' || constStrategy.scheduler === 'dynamic') { - // delete constStrategy.time.at; - } - if (!constStrategy.time.after) { - delete constStrategy.time.after; - } - if (!constStrategy.time.before) { - delete constStrategy.time.before; - } - if (constStrategy.time[type] && constStrategy.time[type].length > 0) { - if (typeof constStrategy.time[type] === 'string') { - constStrategy.time[type] = `${moment(constStrategy.time[type]).format("YYYY-MM-DDTHH:mm:ss.SSSSS", {trim: false})}Z`; - } else { - constStrategy.time[type].forEach(time => { - for (let key in time) { - time[key] = `${moment(time[key]).format("YYYY-MM-DDTHH:mm:ss.SSSSS", {trim: false})}Z`; - } - }) + if (constStrategy) + for (let type in constStrategy.time) { + if (constStrategy.scheduler === 'online' || constStrategy.scheduler === 'dynamic') { + // delete constStrategy.time.at; + } + if (!constStrategy.time.after) { + delete constStrategy.time.after; + } + if (!constStrategy.time.before) { + delete constStrategy.time.before; + } + if (constStrategy.time[type] && constStrategy.time[type].length > 0) { + if (typeof constStrategy.time[type] === 'string') { + constStrategy.time[type] = `${moment(constStrategy.time[type]).format("YYYY-MM-DDTHH:mm:ss.SSSSS", { trim: false })}Z`; + } else { + constStrategy.time[type].forEach(time => { + for (let key in time) { + time[key] = `${moment(time[key]).format("YYYY-MM-DDTHH:mm:ss.SSSSS", { trim: false })}Z`; + } + }) + } } } - } if (constStrategy?.sky.transit_offset) { constStrategy.sky.transit_offset.from = UnitConversion.getHHmmssToSecs(constStrategy.sky.transit_offset.from); constStrategy.sky.transit_offset.to = UnitConversion.getHHmmssToSecs(constStrategy.sky.transit_offset.to); @@ -727,9 +752,9 @@ export class SchedulingUnitCreate extends Component { if (this.state.constraintValidEditor) { this.validateSchedulingConstraints(const_strategy) } else { - this.setState({validConstraints: false, validConstraintMessage: 'Constraints specification is not valid'}) + this.setState({ validConstraints: false, validConstraintMessage: 'Constraints specification is not valid' }) } - this.setState({updatedConstraintParmas: const_strategy}); + this.setState({ updatedConstraintParmas: const_strategy }); } /** @@ -764,7 +789,7 @@ export class SchedulingUnitCreate extends Component { detail: 'Scheduling Unit and Tasks are created successfully' }); if (this.state.createAnother) { - this.setState({schedulingUnit: schedulingUnit.data, isDirty: false}); + this.setState({ schedulingUnit: schedulingUnit.data, isDirty: false }); this.reset(); } else { this.setState({ @@ -788,14 +813,14 @@ export class SchedulingUnitCreate extends Component { */ checkIsDirty() { if (this.state.isDirty) { - this.setState({showDialog: true}); + this.setState({ showDialog: true }); } else { this.cancelCreate(); } } close() { - this.setState({showDialog: false}); + this.setState({ showDialog: false }); } /** @@ -812,19 +837,19 @@ export class SchedulingUnitCreate extends Component { } else { this.props.history.length > 1 ? this.state.isDirty ? this.props.history.go(-2) : this.props.history.go(-1) : this.props.history.push(`/schedulingunit`); } - this.setState({showDialog: false}); + this.setState({ showDialog: false }); } async setStrategyConstraint(name, version) { let strategyConstraint = getConstraintTemplate(this.constraintTemplates, name, version) - let schedulingUnit = {...this.state.schedulingUnit}; + let schedulingUnit = { ...this.state.schedulingUnit }; schedulingUnit.scheduling_constraints_template_id = strategyConstraint ? strategyConstraint.id : ''; strategyConstraint.ref_resolved_schema.properties.sky.properties.transit_offset.properties.from.default = UnitConversion.getSecsToHHmmssWithSign(strategyConstraint.ref_resolved_schema.properties.sky.properties.transit_offset.properties.from.default); strategyConstraint.ref_resolved_schema.properties.sky.properties.transit_offset.properties.to.default = UnitConversion.getSecsToHHmmssWithSign(strategyConstraint.ref_resolved_schema.properties.sky.properties.transit_offset.properties.to.default); strategyConstraint.ref_resolved_schema.properties.sky.properties.min_distance.properties.sun.propertyOrder = 1; strategyConstraint.ref_resolved_schema.properties.sky.properties.min_distance.properties.moon.propertyOrder = 2; strategyConstraint.ref_resolved_schema.properties.sky.properties.min_distance.properties.jupiter.propertyOrder = 3; - this.setState({constraintSchema: strategyConstraint, schedulingUnit}); + this.setState({ constraintSchema: strategyConstraint, schedulingUnit }); } /** @@ -837,7 +862,7 @@ export class SchedulingUnitCreate extends Component { let multiCreateCount = this.state.multiCreateCount; this.setState({ isDirty: false, - dialog: {header: '', detail: ''}, + dialog: { header: '', detail: '' }, errors: [], schedulingSets: this.props.match?.params?.project ? schedulingSets : [], schedulingUnit: { @@ -846,7 +871,7 @@ export class SchedulingUnitCreate extends Component { project: selectedProject || null, scheduling_constraints_template_id: this.constraintTemplates[0].id, rank: '', - output_pinned: this.props.match?.params?.project ? ((_.find(this.projects, {'name': selectedProject}))?.auto_pin) : null + output_pinned: this.props.match?.params?.project ? ((_.find(this.projects, { 'name': selectedProject }))?.auto_pin) : null }, projectDisabled: (this.props.match?.params?.project ? true : false), observStrategy: {}, @@ -887,7 +912,7 @@ export class SchedulingUnitCreate extends Component { missingStnErorsofTask, customStationsOfTask }, () => { - this.setState({validForm: this.validateForm(), isDirty: true}); + this.setState({ validForm: this.validateForm(), isDirty: true }); if (!this.state.isDirty) { publish('edit-dirty', true); } @@ -899,7 +924,7 @@ export class SchedulingUnitCreate extends Component { missingStnErorsofTask, customStationsOfTask }, () => { - this.setState({validForm: this.validateForm()}); + this.setState({ validForm: this.validateForm() }); }); } } else { @@ -909,7 +934,7 @@ export class SchedulingUnitCreate extends Component { missingStnErorsofTask, customStationsOfTask }, () => { - this.setState({validForm: this.validateForm()}); + this.setState({ validForm: this.validateForm() }); }); } }; @@ -919,12 +944,12 @@ export class SchedulingUnitCreate extends Component { const schedulingSets = await ScheduleService.getSchedulingSets(`project=${encodeURIComponent(this.state.schedulingUnit.project)}`); if (this.state.newSet) { tmpSU.scheduling_set_id = this.state.newSet.id; - this.setState({ + this.setState({ schedulingUnit: tmpSU, newSet: null }); } - this.setState({saveDialogVisible: false, showAddSet: false, schedulingSets: schedulingSets}); + this.setState({ saveDialogVisible: false, showAddSet: false, schedulingSets: schedulingSets }); } /** @@ -932,7 +957,7 @@ export class SchedulingUnitCreate extends Component { * @param {SU Set Name} suSet */ setSUSet(suSet) { - this.setState({newSet: suSet}); + this.setState({ newSet: suSet }); } /** @@ -940,16 +965,17 @@ export class SchedulingUnitCreate extends Component { * @param {*} e */ setCreateAnother(e) { - this.setState({'createAnother': e.target.checked}) + this.setState({ 'createAnother': e.target.checked }) } render() { - let isSaveEnabled = ( this.state.constraintValidEditor && this.state.validEditor && this.state.validForm && this.state.validConstraints && this.state.validSpecification) + let isSaveEnabled = (this.state.constraintValidEditor && this.state.validEditor && this.state.validForm && this.state.validConstraints && this.state.validSpecification) + if (this.isDebuggLoggingEnabled) console.log("isSaveEnabled: " + isSaveEnabled + " constraintValidEditor: " + this.state.constraintValidEditor + " ,vvalidEditor:" + this.state.validEditor + " ,validForm:" + this.state.validForm + " ,validConstraints:" + this.state.validConstraints + " ,validSpecification:" + this.state.validSpecification); if (this.state.redirect) { - return <Redirect to={{pathname: this.state.redirect}}></Redirect> + return <Redirect to={{ pathname: this.state.redirect }}></Redirect> } const schema = this.state.paramsSchema; - const {scheduleunit_draft} = this.state.userrole; + const { scheduleunit_draft } = this.state.userrole; let jeditor = null; if (schema) { jeditor = React.createElement(Jeditor, { @@ -965,19 +991,19 @@ export class SchedulingUnitCreate extends Component { } return ( <React.Fragment> - <Toast ref={(el) => this.growl = el}/> - <PageHeader location={this.props.location} className="SchedulingUnit-PageHeader" title={'Scheduling Unit - Add'} - actions={[{ - icon: 'fa-window-close', title: 'Click to close Scheduling Unit creation', - type: 'button', actOn: 'click', props: {callback: this.checkIsDirty} - }]}/> - {this.state.isLoading ? <AppLoader/> : + <Toast ref={(el) => this.growl = el} /> + <PageHeader location={this.props.location} className="SchedulingUnit-PageHeader" title={'Scheduling Unit - Add'} + actions={[{ + icon: 'fa-window-close', title: 'Click to close Scheduling Unit creation', + type: 'button', actOn: 'click', props: { callback: this.checkIsDirty } + }]} /> + {this.state.isLoading ? <AppLoader /> : <> <div> <div className="p-fluid"> <div className="p-field p-grid"> <label htmlFor="schedUnitName" className="col-lg-2 col-md-2 col-sm-12">Name <span - style={{color: 'red'}}>*</span></label> + style={{ color: 'red' }}>*</span></label> <div className="col-lg-3 col-md-3 col-sm-12" data-testid="namediv"> <InputText className={(this.state.errors.name && this.state.touched.name) ? 'input-error' : ''} @@ -989,7 +1015,7 @@ export class SchedulingUnitCreate extends Component { }} value={this.state.schedulingUnit.name} autoFocus onChange={(e) => this.setSchedUnitParams('name', e.target.value)} - onBlur={(e) => this.setSchedUnitParams('name', e.target.value)}/> + onBlur={(e) => this.setSchedUnitParams('name', e.target.value)} /> <label className={(this.state.errors.name && this.state.touched.name) ? "error" : "info"}> {this.state.errors.name && this.state.touched.name ? this.state.errors.name : "Max 128 characters"} @@ -997,8 +1023,8 @@ export class SchedulingUnitCreate extends Component { </div> <div className="col-lg-1 col-md-1 col-sm-12"></div> <label htmlFor="description" - className="col-lg-2 col-md-2 col-sm-12">Description <span - style={{color: 'red'}}>*</span></label> + className="col-lg-2 col-md-2 col-sm-12">Description <span + style={{ color: 'red' }}>*</span></label> <div className="col-lg-3 col-md-3 col-sm-12"> <InputTextarea className={(this.state.errors.description && this.state.touched.description) ? 'input-error' : ''} @@ -1007,7 +1033,7 @@ export class SchedulingUnitCreate extends Component { tooltipOptions={this.tooltipOptions} maxLength="128" data-testid="description" value={this.state.schedulingUnit.description} onChange={(e) => this.setSchedUnitParams('description', e.target.value)} - onBlur={(e) => this.setSchedUnitParams('description', e.target.value)}/> + onBlur={(e) => this.setSchedUnitParams('description', e.target.value)} /> <label className={(this.state.errors.description && this.state.touched.description) ? "error" : "info"}> {(this.state.errors.description && this.state.touched.description) ? this.state.errors.description : "Max 255 characters"} @@ -1033,36 +1059,36 @@ export class SchedulingUnitCreate extends Component { <label htmlFor="rank" className="col-lg-2 col-md-2 col-sm-12">Rank</label> <div className="col-lg-3 col-md-3 col-sm-12" data-testid="rank"> <input type="number" - data-for="reacttooltip" - data-iscapture="true" - data-tip="Priority of this scheduling unit w.r.t. other scheduling units within the same queue and project.. Min-0.0000, Max-1.0000" - id="proj-rank" name="rank" data-testid="rank" - className="p-inputtext p-component p-filled" - value={this.state.schedulingUnit.rank} - step="0.0001" - lang="en" - onChange={(e) => this.setSchedUnitParams('rank', e.target.value)}/> + data-for="reacttooltip" + data-iscapture="true" + data-tip="Priority of this scheduling unit w.r.t. other scheduling units within the same queue and project.. Min-0.0000, Max-1.0000" + id="proj-rank" name="rank" data-testid="rank" + className="p-inputtext p-component p-filled" + value={this.state.schedulingUnit.rank} + step="0.0001" + lang="en" + onChange={(e) => this.setSchedUnitParams('rank', e.target.value)} /> </div> <div className="col-lg-1 col-md-1 col-sm-12"></div> <label htmlFor="priority_queue" className="col-lg-2 col-md-2 col-sm-12">Priority Queue</label> <div className="col-lg-3 col-md-3 col-sm-10"> <Dropdown data-testid="priority_queue" id="priority_queue" optionLabel="value" - optionValue="value" - tooltip="Priority queue of this scheduling unit. Queues provide a strict ordering between scheduling units." - tooltipOptions={this.tooltipOptions} - value={this.state.schedulingUnit.priority_queue} - options={this.priorityQueueTypes} - onChange={(e) => { - this.setSchedUnitParams('priority_queue', e.value) - }} - placeholder="Select Priority Queue"/> + optionValue="value" + tooltip="Priority queue of this scheduling unit. Queues provide a strict ordering between scheduling units." + tooltipOptions={this.tooltipOptions} + value={this.state.schedulingUnit.priority_queue} + options={this.priorityQueueTypes} + onChange={(e) => { + this.setSchedUnitParams('priority_queue', e.value) + }} + placeholder="Select Priority Queue" /> </div> </div> <div className="p-field p-grid"> <label htmlFor="observStrategy" className="col-lg-2 col-md-2 col-sm-12"> - Observation Strategy <span style={{color: 'red'}}>*</span> + Observation Strategy <span style={{ color: 'red' }}>*</span> </label> {<ObservationStrategySelector selectedPurpose={this.state.observStrategyFilters.purpose} @@ -1081,23 +1107,23 @@ export class SchedulingUnitCreate extends Component { Data</label> <div className="col-lg-3 col-md-3 col-sm-12" data-testid="autodeletion"> <Checkbox inputId="trigger" role="trigger" - tooltip="Do not delete data automatically after successful ingest" - tooltipOptions={this.tooltipOptions} - checked={this.state.schedulingUnit.output_pinned} - onChange={(e) => this.setSchedUnitParams('output_pinned', e.target.checked)} + tooltip="Do not delete data automatically after successful ingest" + tooltipOptions={this.tooltipOptions} + checked={this.state.schedulingUnit.output_pinned} + onChange={(e) => this.setSchedUnitParams('output_pinned', e.target.checked)} ></Checkbox> </div> - + </div> {_.keys(this.state.stationGroups).length > 0 && <div className='grouping'> <fieldset> <h3 className="card-title level-1 je-object__title" - style={{display: "inline-block"}}> + style={{ display: "inline-block" }}> <button type="button" - title={this.state.stationsCollapsed ? "Expand" : "Collapse"} - className="btn btn-secondary btn-sm json-editor-btn-collapse json-editor-btntype-toggle" - onClick={() => this.setState({stationsCollapsed: !this.state.stationsCollapsed})}> + title={this.state.stationsCollapsed ? "Expand" : "Collapse"} + className="btn btn-secondary btn-sm json-editor-btn-collapse json-editor-btntype-toggle" + onClick={() => this.setState({ stationsCollapsed: !this.state.stationsCollapsed })}> <i className={this.state.stationsCollapsed ? "fas fa-caret-right" : "fas fa-caret-down"}></i> </button> <label>Station specification</label> @@ -1121,16 +1147,16 @@ export class SchedulingUnitCreate extends Component { </div> {this.state.constraintSchema && <div className="p-fluid"> <fieldset className="border-style"> - <div className="p-col-12" style={{width: "100%"}}> + <div className="p-col-12" style={{ width: "100%" }}> <SchedulingConstraint constraintTemplate={this.state.constraintSchema} // initValue={this.state.constraintInitParams} // No need to pass this value as the values are set with callback callback={this.setConstraintsEditorOutput} - parentFunction={this.setConstraintEditorFun}/> + parentFunction={this.setConstraintEditorFun} /> </div> </fieldset> <div className="p-col-12" - style={{marginLeft: '0.4em', marginTop: '-10px', paddingTop: '0px'}}> + style={{ marginLeft: '0.4em', marginTop: '-10px', paddingTop: '0px' }}> <label className={this.state.validConstraints ? "info" : "error"}> {this.state.validConstraintMessage ? this.state.validConstraintMessage : ""} </label> @@ -1140,8 +1166,8 @@ export class SchedulingUnitCreate extends Component { {this.state.paramsSchema && <div className="p-fluid"> <fieldset className="border-style"> - <div style={{marginLeft: '-0.5em'}}> - <div className="p-col-12" style={{width: "100%"}}> + <div style={{ marginLeft: '-0.5em' }}> + <div className="p-col-12" style={{ width: "100%" }}> {jeditor} </div> </div> @@ -1159,16 +1185,16 @@ export class SchedulingUnitCreate extends Component { </div> } </div> - <div className="p-breadcrumb footer-long-div actions" style={{marginLeft: '2em !important'}}> + <div className="p-breadcrumb footer-long-div actions" style={{ marginLeft: '2em !important' }}> <FormActionbar createAnotherCallBack={this.setCreateAnother} - createAnother={this.state.createAnother} - tooltip="Select checkbox to create another Scheduling Unit after saving this Scheduling Unit" - submitTitle={(!this.state.constraintValidEditor || !this.state.validEditor || !this.state.validForm || !this.state.validConstraints || !this.state.validSpecification) ? "" : "Save Scheduling Unit"} - onSubmit={this.saveSchedulingUnit} - disableSaveBtn={!isSaveEnabled} - onCancel={this.checkIsDirty}/> + createAnother={this.state.createAnother} + tooltip="Select checkbox to create another Scheduling Unit after saving this Scheduling Unit" + submitTitle={(!this.state.constraintValidEditor || !this.state.validEditor || !this.state.validForm || !this.state.validConstraints || !this.state.validSpecification) ? "" : "Save Scheduling Unit"} + onSubmit={this.saveSchedulingUnit} + disableSaveBtn={!isSaveEnabled} + onCancel={this.checkIsDirty} /> </div> - <ReactTooltip id="reacttooltip" place={'left'} type={'dark'} effect={'solid'} multiline={true}/> + <ReactTooltip id="reacttooltip" place={'left'} type={'dark'} effect={'solid'} multiline={true} /> </> } @@ -1176,18 +1202,18 @@ export class SchedulingUnitCreate extends Component { <div className="p-grid" data-testid="confirm_dialog"> {this.state.showAddSet && <SchedulingSet callbackFunction={this.setSUSet} project={this.state.selectedProject[0]} - onCancel={this.refreshSchedulingSet}/> + onCancel={this.refreshSchedulingSet} /> } <CustomDialog type="confirmation" visible={this.state.showDialog} width="40vw" - header={'Add Scheduling Unit'} - message={'Do you want to discard your changes? A new Scheduling Unit will not be created'} - content={''} onClose={this.close} actions={[{ - id: "yes", - title: 'Discard', - callback: this.cancelCreate, - className: 'act-btn-dispose' - }, - {id: "no", title: 'Cancel', className: 'act-btn-cancel', callback: this.close}]} + header={'Add Scheduling Unit'} + message={'Do you want to discard your changes? A new Scheduling Unit will not be created'} + content={''} onClose={this.close} actions={[{ + id: "yes", + title: 'Discard', + callback: this.cancelCreate, + className: 'act-btn-dispose' + }, + { id: "no", title: 'Cancel', className: 'act-btn-cancel', callback: this.close }]} > </CustomDialog> </div> @@ -1198,8 +1224,8 @@ export class SchedulingUnitCreate extends Component { SchedulingUnitCreate.propTypes = { match: PropTypes.object, - history: PropTypes.object, - location: PropTypes.oneOfType([PropTypes.object, PropTypes.string]) + history: PropTypes.object, + location: PropTypes.oneOfType([PropTypes.object, PropTypes.string]) } export default SchedulingUnitCreate; \ No newline at end of file