Skip to content
Snippets Groups Projects
Select Git revision
  • fba183b9efaa88220c7df65d69f9c92d5b2ef8da
  • master default protected
  • L2SS-1914-fix_job_dispatch
  • TMSS-3170
  • TMSS-3167
  • TMSS-3161
  • TMSS-3158-Front-End-Only-Allow-Changing-Again
  • TMSS-3133
  • TMSS-3319-Fix-Templates
  • test-fix-deploy
  • TMSS-3134
  • TMSS-2872
  • defer-state
  • add-custom-monitoring-points
  • TMSS-3101-Front-End-Only
  • TMSS-984-choices
  • SDC-1400-Front-End-Only
  • TMSS-3079-PII
  • TMSS-2936
  • check-for-max-244-subbands
  • TMSS-2927---Front-End-Only-PXII
  • Before-Remove-TMSS
  • LOFAR-Release-4_4_318 protected
  • LOFAR-Release-4_4_317 protected
  • LOFAR-Release-4_4_316 protected
  • LOFAR-Release-4_4_315 protected
  • LOFAR-Release-4_4_314 protected
  • LOFAR-Release-4_4_313 protected
  • LOFAR-Release-4_4_312 protected
  • LOFAR-Release-4_4_311 protected
  • LOFAR-Release-4_4_310 protected
  • LOFAR-Release-4_4_309 protected
  • LOFAR-Release-4_4_308 protected
  • LOFAR-Release-4_4_307 protected
  • LOFAR-Release-4_4_306 protected
  • LOFAR-Release-4_4_304 protected
  • LOFAR-Release-4_4_303 protected
  • LOFAR-Release-4_4_302 protected
  • LOFAR-Release-4_4_301 protected
  • LOFAR-Release-4_4_300 protected
  • LOFAR-Release-4_4_299 protected
41 results

create.js

Blame
  • Reinder Kraaij's avatar
    Resolve TMSS-2899 "Front end only save button tweak"
    Reinder Kraaij authored
    fba183b9
    History
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    create.js 60.54 KiB
    import PropTypes from 'prop-types';
    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 {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';
    import UnitConverter from '../../utils/unit.converter';
    import ProjectService from '../../services/project.service';
    import ScheduleService from '../../services/schedule.service';
    import TaskService from '../../services/task.service';
    import UIConstants from '../../utils/ui.constants';
    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 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 FormActionbar from '../../components/FormActionbar';
    import {getConstraintTemplate, getTaskTemplateForTask} from "./create.helper";
    import ObservationStrategySelector, {
        queryMatchingObservationStrategyTemplates
    } from "./components/ObservationStrategySelector";
    import ProjectScheduleSetSelector from "./components/ProjectScheduleSetSelector";
    
    /**
     * Component to create a new SchedulingUnit from Observation strategy template
     */
    export class SchedulingUnitCreate extends Component {
            constructor(props) {
            super(props);
            this.state = {
                observStrategyFilters: {
                    states: ['active'],
                    purpose: []
                },
                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
                touched: {},
                redirect: null,                         // URL to redirect
                errors: [],                             // Form Validation errors
                schedulingSets: [],                     // Scheduling set of the selected project
                missing_StationFieldsErrors: [],         // Validation for max no.of missing station
                stationOptions: [],
                stationGroups: {},
                customSelectedStations: [],             // custom stations
                selectedStationsOfTask: {},
                missingStationsofTask: {},
                missingStnErorsofTask: {},
                customStationsOfTask: {},
                stationsCollapsed: false,
                schedulingUnit: {
                    name: '',
                    description: '',
                    project: (props.match ? props.match.params.project : null) || null,
                    rank: '',
                },
                projectDisabled: (props.match ? (props.match.params.project ? true : false) : false),      // Disable project selection if
                observStrategy: {},                     // Selected strategy to create SU
                paramsSchema: null,                     // JSON Schema to be generated from strategy template to pass to JSOn editor
                constraintSchema: null,
                validEditor: false,                     // For JSON editor validation
                validFields: {},                        // For Form Validation            
                newSet: null,
                observationIdSet: [],
                createAnother: false,
                multiCreateCount: 1
            };
            this.defaultConstraints = {}
            this.taskFilters = [];                      // To get Short_Description details
            this.priorityQueueTypes = [];
            this.projects = [];                         // All projects to load project dropdown
            this.taskTemplates = [];                    // All task templates to be filtered based on tasks in selected strategy template
            this.tooltipOptions = UIConstants.tooltipOptions;
            this.constraintTemplates = [];
            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"},
            };
    
            this.setEditorOutput = this.setEditorOutput.bind(this);
            this.setConstraintsEditorOutput = this.setConstraintsEditorOutput.bind(this);
            this.setConstraintEditorFun = this.setConstraintEditorFun.bind(this);
            this.changeProject = this.changeProject.bind(this);
            this.changeStrategy = this.changeStrategy.bind(this);
            this.setStrategyConstraint = this.setStrategyConstraint.bind(this);
            this.setSchedUnitParams = this.setSchedUnitParams.bind(this);
            this.validateForm = this.validateForm.bind(this);
            this.validateStations = this.validateStations.bind(this);
            this.validateEditor = this.validateEditor.bind(this);
            this.setEditorFunction = this.setEditorFunction.bind(this);
            this.saveSchedulingUnit = this.saveSchedulingUnit.bind(this);
            this.cancelCreate = this.cancelCreate.bind(this);
            this.reset = this.reset.bind(this);
            this.refreshSchedulingSet = this.refreshSchedulingSet.bind(this);
            this.checkIsDirty = this.checkIsDirty.bind(this);
            this.close = this.close.bind(this);
            this.setSUSet = this.setSUSet.bind(this);
            this.updateConstraintsParams = this.updateConstraintsParams.bind(this);
            this.setCreateAnother = this.setCreateAnother.bind(this);
            this.setState = this.setState.bind(this);
        }
    
        async componentDidMount() {
            const permission = await AuthUtil.getUserPermissionByModule('scheduleunit_draft');
            this.setState({userrole: permission});
            const promises = [ProjectService.getProjectList(false, 'name,url'),
                TaskService.getTaskTemplates(),
                ScheduleService.getSchedulingConstraintTemplates(),
                ScheduleService.getStationGroup(),
                UtilService.getPriorityQueueType(),
                TaskService.getTaskFilterDefinition('draft'),
                ScheduleService.getStrategyPurpose(),
                ScheduleService.getStrategyState(),
                ProjectService.getMyRoles(),
            ];
            Promise.all(promises).then(async (responses) => {
                this.projects = responses[0];
                this.taskTemplates = responses[1];
                this.constraintTemplates = responses[2];
                this.stations = responses[3];
                this.priorityQueueTypes = responses[4];
                this.taskFilters = responses[5];
                this.templatePurposes = this.getStrategyFilterOptions(responses[6], 'purpose');
                this.templateState = this.getStrategyFilterOptions(responses[7], 'state');
                this.myRoles = responses[8];
                const systemRoles = this.myRoles.system_roles.map(role => {
                    return role.toLowerCase()
                });
                const projectRoles = Object.fromEntries(
                    Object.entries(this.myRoles.project_roles).map(([project, roles]) => [project.toLowerCase(), roles])
                );
                // Users with system_roles other than superuser, operator & support can view the projects for which they have shared_support project_role
                if (_.intersection(systemRoles, ['superuser', 'operator', 'support']).length < 1) {
                    this.projects = _.filter(this.projects, (project) => {
                        return _.includes(projectRoles[project.name.toLowerCase()], 'shared_support')
                    })
                }
                if (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;
                    this.setState({
                        isLoading: false,
                        schedulingSets: projectSchedSets,
                        selectedProject: selectedProject,
                        schedulingUnit: tmpSU
                    });
                } else {
                    this.setState({isLoading: false});
                }
            });
            let observStrategyFilter = UtilService.localStore({type: 'get', key: 'strategyFilterSUCreate'});
            if (Object.keys(observStrategyFilter).length === 0) {
                observStrategyFilter = {states: ['active'], purpose: []}
            }
    
            this.setState({
                observStrategies: await this.getMatchingObservationStrategyTemplates(observStrategyFilter),
                observStrategyFilters: observStrategyFilter
            });
        }
    
        async getMatchingObservationStrategyTemplates(filters) {
            return await queryMatchingObservationStrategyTemplates(filters)
        }
    
        getStrategyFilterOptions(filterValues, filterId) {
            if (filterValues) {
                let optionList = [];
                filterValues.forEach(choice => {
                    const tmpVar = {name: choice.value, value: choice.value};
                    if (filterId === 'purpose') {
                        optionList.push(tmpVar);
                    }
                    if (filterId === 'state' && tmpVar.value !== 'obsolete') {
                        optionList.push(tmpVar);
                    }
                });
                return _.sortBy(optionList, ['name']);
            }
        }
    
        /**
         * Function to call on change of project and reload scheduling set dropdown
         * @param {string} projectName
         */
        async changeProject(projectName) {
            const projectSchedSets = await ScheduleService.getSchedulingSets(`project=${encodeURIComponent(projectName)}`);
            let schedulingUnit = this.state.schedulingUnit;
            schedulingUnit.project = projectName;
            schedulingUnit.scheduling_set_id = null;
            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'),
                isDirty: true
            });
        }
    
        /**
         * Function called when observation strategy template is changed.
         * 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}));
            if (ParserUtility.addStationParameters(observStrategy)) {
                 this.setState({
                    observStrategy: observStrategy,
                    constraintSchema: null
                });
            }
            let stationGroups = {};
            const tasks = observStrategy.template.tasks;
            const parameters = observStrategy.template.parameters;
            let paramsOutput = {};
            let schema = {
                type: 'object', additionalProperties: false,
                properties: {}, definitions: {}
            };
            let observationType = null;
            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);
            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) {
                // TODO: make parameter handling more generic, instead of task specific.
                if (!param.refs[0].startsWith("#/tasks/")) {
                    continue;
                }
    
                let taskPaths = param.refs[0].split("/");
                const taskName = taskPaths[2];
                /**
                 * For Short_Description, the task path length will be 4, so added below condition to get short_description details
                 *  #/tasks/Combined Observation/short_description
                 */
                taskPaths = taskPaths.slice((taskPaths.length === 4 ? 3 : 4), taskPaths.length);
                const task = tasks[taskName];
                if (task) {
                    if (taskPaths.includes("station_groups")) {
                        stationGroups[param.name] = $strategyRefs.get(param.refs[0]);
                    } else {
                        const taskTemplate = getTaskTemplateForTask(this.taskTemplates, task);
    
                        if (['target observation', 'beamforming observation'].indexOf(taskTemplate.name.toLowerCase()) >= 0) {
                            observationType = taskTemplate.name;
                        }
                        // 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};
                        taskPaths.reverse();
                        const paramProp = await ParserUtility.getParamProperty($strategyRefs, taskPaths, taskTemplate.ref_resolved_schema, this.taskFilters);
                        schema.properties[param.name] = _.cloneDeep(paramProp);
                        if (schema.properties[param.name]) {
                            schema.properties[param.name].title = param.name;
                            try {
                                schema.properties[param.name].default = $strategyRefs.get(param.refs[0]);
                            } catch (err) { /* empty */ }
                            paramsOutput[param.name] = schema.properties[param.name].default || ParserUtility.getDefaultParamValue(schema.properties[param.name].type);
                        }
                    }
                }
            }
            if (!this.state.isDirty) {
                publish('edit-dirty', true);
            }
            this.setState({
                observStrategy: observStrategy, paramsSchema: _.cloneDeep(schema), constraintParamsOutput: null,
                observationType: observationType, stationsCollapsed: false,
                paramsOutput: paramsOutput, stationGroups: stationGroups,
                bandPassFilter: bandPassFilter, isDirty: true
            });
            // Function called to clear the JSON Editor fields and reload with new schema
            if (this.state.editorFunction) {
                this.state.editorFunction();
            }
        }
    
        /**
         * This is the callback method to be passed to the JSON editor.
         * JEditor will call this function when there is change in the editor.
         * @param {Object} jsonOutput
         * @param {Array} errors
         */
        setEditorOutput(jsonOutput, errors) {
            this.paramsOutput = jsonOutput;
            this.validEditor = errors.length === 0;
            this.updateParameters();
            if (errors.length > 0 ) {
                this.setState({errors: [...errors]})
            }
            this.setState({
                paramsOutput: jsonOutput,
                validEditor: errors.length === 0,
                validForm: this.validateForm()
            });
        }
    
        /**
         * Common function validate specification
         * @param {String} template Template url
         * @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 (validation_result.length > 0) {
                    let validationMessage = validation_result[0]['message'];
                    if (validation_result[0]['valid']) {
                        validationMessage = "Task Parameters specification is valid"
                    }
                    this.setState({
                        validSpecification: validation_result[0]['valid'],
                        validSpecificationMessage: validationMessage
                    });
                }
            }
        }
    
        async validateSchedulingConstraints(updatedConstraintParmas) {
            if (updatedConstraintParmas) {
                let schedulingConstraintsDoc = updatedConstraintParmas.scheduling_constraints_doc;
                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);
                if (validation_result.length > 0) {
                    let validationMessage = validation_result[0]['message'];
                    if (validation_result[0]['valid']) {
                        validationMessage = "Constraints specification is valid"
                    }
                    this.setState({
                        validConstraints: validation_result[0]['valid'],
                        validConstraintMessage: validationMessage
                    });
                }
            }
        }
    
        loadConstraints(properties, parentProps, defaultValues) {
            parentProps = parentProps ? parentProps : _.cloneDeep(this.defaultConstraints);
            for (const key in properties) {
                let propertyValue = properties[key];
                if (propertyValue instanceof Object && key !== "reference_pointing") {
                    if (defaultValues) {
                        parentProps[key] = propertyValue;
                        this.loadConstraints(propertyValue, parentProps[key], true);
                    } else {
                        this.loadConstraints(propertyValue, parentProps[key], false);
                    }
                } else {
                    if (_.includes(['from', 'to'], key)) {
                        propertyValue = (propertyValue < 0 ? '-' : '') + UnitConverter.getSecsToHHmmss(propertyValue);
                    }
                    if (!_.includes(_.keys(parentProps), "angle1") && _.includes(['sun', 'moon', 'jupiter', 'target', 'calibrator'], key) && !defaultValues) {
                        propertyValue = ((propertyValue * 180) / Math.PI).toFixed(2);
                    }
                    if (_.includes(['between', 'not_between'], key)) {
                        propertyValue = [];
                    }
                    parentProps[key] = propertyValue;
                }
            }
            if (defaultValues) {
                this.defaultConstraints = parentProps;
            } else {
                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) {
                this.state.constraintEditorFunction("setValue", [parentProps]);
            }
        }
    
        setConstraintsEditorOutput(jsonOutput, errors) {
            let err = [...errors];
            if (jsonOutput.scheduler === 'online' || jsonOutput.scheduler === 'dynamic') {
                err = err.filter(e => e.path !== 'root.time.at');
            }
            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);
                }
            }
            this.constraintValidEditor = err.length === 0;
            if (!this.state.isDirty && this.state.constraintParamsOutput && !_.isEqual(this.state.constraintParamsOutput, jsonOutput)) {
                if (!_.isEmpty(this.state.observStrategy)) {
                    if (!this.state.isDirty) {
                        publish('edit-dirty', true);
                    }
                    this.setState({
                        constraintParamsOutput: jsonOutput,
                        constraintValidEditor: err.length === 0,
                        validForm: this.validateForm(),
                        isDirty: true
                    });
                }
            } else {
                this.setState({
                    constraintParamsOutput: jsonOutput,
                    constraintValidEditor: err.length === 0,
                    validForm: this.validateForm()
                });
            }
            this.updateConstraintsParams();
        }
    
        /**
         * This function is mainly added for Unit Tests. If this function is removed Unit Tests will fail.
         */
        validateEditor() {
            return this.validEditor && this.constraintValidEditor ? true : false;
        }
    
        /**
         * Function to set form values to the SU object
         * @param {string} key
         * @param {object} value
         */
        async setSchedUnitParams(key, value) {
            this.setState({
                touched: {
                    ...this.state.touched,
                    [key]: true
                }
            });
            let schedulingUnit = _.cloneDeep(this.state.schedulingUnit);
            if (key === 'rank') {
                const previousValue = schedulingUnit.rank;
                value = value.replace(/([^0-9.]+)/, "");
                const match = /(\d{0,1})[^.]*((?:\.\d{0,4})?)/g.exec(value);
                const val = match[1] + match[2];
                if (val === '' || (val >= 0 && val <= 1)) {
                    schedulingUnit[key] = val === '' ? '' : Number(val);
                } else {
                    schedulingUnit[key] = previousValue;
                }
            } else if (key === 'scheduling_set_id') {
                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});
            } else {
                schedulingUnit[key] = value;
            }
    
            if (!this.state.isDirty && !_.isEqual(this.state.schedulingUnit, schedulingUnit)) {
                if (!this.state.isDirty) {
                    publish('edit-dirty', true);
                }
                this.setState({schedulingUnit: schedulingUnit});
                this.setState({validForm: this.validateForm(key), validEditor: this.validateEditor(), isDirty: true});
            } else {
                this.setState({schedulingUnit: schedulingUnit});
                this.setState({validForm: this.validateForm(key), 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});
        }
    
        setConstraintEditorFun(editorFunction) {
            this.setState({constraintEditorFunction: editorFunction});
        }
    
        /**
         * Validation function to validate the form or field based on the form rules.
         * If no argument passed for fieldName, validates all fields in the form.
         * @param {string} fieldName
         */
        validateForm(fieldName) {
            let validForm = false;
            let errors = this.state.errors;
            let validFields = this.state.validFields;
            if (fieldName) {
                delete errors[fieldName];
                delete validFields[fieldName];
                if (this.formRules[fieldName]) {
                    const rule = this.formRules[fieldName];
                    const fieldValue = this.state.schedulingUnit[fieldName];
                    if (rule.required) {
                        if (!fieldValue) {
                            errors[fieldName] = rule.message ? rule.message : `${fieldName} is required`;
                        } else {
                            validFields[fieldName] = true;
                        }
                    }
                }
            } else {
                errors = {};
                validFields = {};
                for (const fieldName in this.formRules) {
                    const rule = this.formRules[fieldName];
                    const fieldValue = this.state.schedulingUnit[fieldName];
                    if (rule.required) {
                        if (!fieldValue) {
                            errors[fieldName] = rule.message ? rule.message : `${fieldName} is required`;
                        } else {
                            validFields[fieldName] = true;
                        }
                    }
                }
            }
            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) {
                validForm = true;
            }
            const validStations = this.validateStations();
            return validForm && validStations && _.sum(_.values(this.state.missingStnErorsofTask)) <= 0;
        }
    
        /**
         * Checks if at least one station selected for each station_group parameter and max_nr_missing station value is entered.
         * @returns Boolean
         */
        validateStations() {
            let validStations = false;
            // Check if at least one station selected for all station groups(parameters)
            // Break the loop if any of the required condition check is not satisfied
            for (const stationGroup of _.keys(this.state.stationGroups)) {
                // Check if the selected stations and custom stations are not empty
                if (this.state.selectedStationsOfTask[stationGroup] && this.state.customStationsOfTask[stationGroup]) {
                    // Get the stations list for the station group(parameter)
                    const stationsList = this.state.selectedStationsOfTask[stationGroup].concat(this.state.customStationsOfTask[stationGroup]);
                    //If stationsList is empty then no station group and custom stations are selected
                    if (stationsList.length === 0) {
                        validStations = false;
                        break;
                    } else {
                        //If predefined station group(Dutch, Remote, etc.,) is/are selected, validate if max_nr_missing is entered
                        if (this.state.selectedStationsOfTask[stationGroup].length > 0) {
                            for (const selectedStations of this.state.selectedStationsOfTask[stationGroup]) {
                                const selectedGroup = this.state.missingStationsofTask[stationGroup][selectedStations]
                                if (selectedGroup) {
                                    if (selectedGroup.max_nr_missing === "") {
                                        validStations = false;
                                        break;
                                    } else {
                                        validStations = true;
                                    }
                                }
                            }
                            if (!validStations) {
                                break;
                            } else {
                                validStations = true;
                            }
                        }
                        //If custom station group(s) is/are selected, validate if max_nr_missing is entered
                        if (this.state.customStationsOfTask[stationGroup].length > 0) {
                            for (const customStations of this.state.customStationsOfTask[stationGroup]) {
                                if (customStations.max_nr_missing === "") {
                                    validStations = false;
                                    break;
                                } else {
                                    validStations = true;
                                }
                            }
                            if (!validStations) {
                                break;
                            } else {
                                validStations = true;
                            }
                        }
                    }
                } else {
                    validStations = false;
                    break;
                }
            }
            return validStations;
        }
    
        /**
         * Function to update task parameters
         */
        async updateParameters() {
            let observStrategy = _.cloneDeep(this.state.observStrategy);
            const $refs = await $RefParser.resolve(observStrategy.template);
            observStrategy.template.parameters.forEach(async (param, index) => {
                // $refs.set(observStrategy.template.parameters[index]['refs'][0], this.state.paramsOutput[param.name]);
                let refIndex = 0;
                for (const ref of param.refs) {
                    let station_groups = [];
                    if (ref.includes("station_groups")) {
                        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 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]);
                    }
                    refIndex++;
                }
            });
            if (this.state.validEditor) {
                this.validateSpecificationsDoc(observStrategy);
            } else {
                let message = 'Task Parameters specification is not valid: '
                this.state.errors.forEach(error => {
                    message = message + error.message + "\n"
                })
                this.setState({
                    validSpecification: false,
                    validSpecificationMessage: message
                })
            }
            this.setState({updatedObservStrategy: observStrategy});
        }
    
        /**
         * Function to update constraints
         */
        updateConstraintsParams() {
            const constStrategy = _.cloneDeep(this.state.constraintParamsOutput);
         
            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);
            }
            UnitConversion.degreeToRadians(constStrategy.sky);
            const const_strategy = {
                scheduling_constraints_doc: constStrategy,
                id: this.state.constraintSchema.id,
                constraint: this.state.constraintSchema
            };
            if (this.state.constraintValidEditor) {
                this.validateSchedulingConstraints(const_strategy)
            } else {
                this.setState({validConstraints: false, validConstraintMessage: 'Constraints specification is not valid'})
            }
            this.setState({updatedConstraintParmas: const_strategy});
        }
    
        /**
         * Function to create Scheduling unit
         */
        async saveSchedulingUnit() {
            await this.updateParameters();
            let observStrategy = _.cloneDeep(this.state.updatedObservStrategy);
            let newSpecificationDoc = {}
            for (const parameter of observStrategy.template.parameters) {
                for (const ref of parameter.refs) {
                    let paramPath = ref.replace(new RegExp('#/', "g"), "");
                    paramPath = paramPath.replace(new RegExp('/', "g"), '.');
                    const value = _.get(observStrategy.template, paramPath);
                    if (value !== undefined) {
                        newSpecificationDoc = _.set(newSpecificationDoc, paramPath, value);
                    }
                }
            }
            newSpecificationDoc['scheduling_constraints_doc'] = _.cloneDeep(this.state.updatedConstraintParmas).scheduling_constraints_doc;
            let schedulingUnit = this.state.schedulingUnit;
            schedulingUnit.observation_strategy_template_id = observStrategy.id;
            schedulingUnit.rank = schedulingUnit.rank === undefined || schedulingUnit.rank === '' ? 0 : schedulingUnit.rank.toFixed(4);
            schedulingUnit = await ScheduleService.saveSchedulingUnit(schedulingUnit, newSpecificationDoc);
            if (schedulingUnit.isSUUpdated) {
                if (appGrowl === null) {
                    setAppGrowl(this.growl);
                }
                appGrowl.show({
                    severity: 'success',
                    summary: 'Success',
                    detail: 'Scheduling Unit and Tasks are created successfully'
                });
                if (this.state.createAnother) {
                    this.setState({schedulingUnit: schedulingUnit.data, isDirty: false});
                    this.reset();
                } else {
                    this.setState({
                        schedulingUnit: schedulingUnit.data,
                        isDirty: false,
                        redirect: `/schedulingunit/view/draft/${schedulingUnit.data.id}`
                    });
                }
                publish('edit-dirty', false);
            } else {
                this.growl.show({
                    severity: 'error',
                    summary: 'Error Occured',
                    detail: schedulingUnit.message || 'Unable to save Scheduling Unit/Tasks'
                });
            }
        }
    
        /**
         * warn before cancel the page if any changes detected
         */
        checkIsDirty() {
            if (this.state.isDirty) {
                this.setState({showDialog: true});
            } else {
                this.cancelCreate();
            }
        }
    
        close() {
            this.setState({showDialog: false});
        }
    
        /**
         * Cancel SU creation and redirect
         */
        cancelCreate() {
            publish('edit-dirty', false);
            if (this.state.multiCreateCount > 1) {
                if (this.state.isDirty) {
                    this.props.history.push(`/schedulingunit`);
                } else {
                    this.props.history.go(this.state.multiCreateCount * -1);
                }
            } 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});
        }
    
        async setStrategyConstraint(name, version) {
            let strategyConstraint = getConstraintTemplate(this.constraintTemplates, name, version)
            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});
        }
    
        /**
         * Reset function to be called when user wants to create new SU
         */
        reset() {
            const schedulingSets = this.state.schedulingSets;
            this.nameInput.focus();
            const selectedProject = this.props.match?.params?.project;
            let multiCreateCount = this.state.multiCreateCount;
            this.setState({
                isDirty: false,
                dialog: {header: '', detail: ''},
                errors: [],
                schedulingSets: this.props.match?.params?.project ? schedulingSets : [],
                schedulingUnit: {
                    name: '',
                    description: '',
                    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
                },
                projectDisabled: (this.props.match?.params?.project ? true : false),
                observStrategy: {},
                paramsSchema: null,
                paramsOutput: null,
                validEditor: false,
                validFields: {},
                constraintSchema: null,
                constraintInitParams: null,
                selectedStations: null,
                selectedStationsOfTask: {},
                customStationsOfTask: {},
                touched: false,
                stationGroups: {},
                multiCreateCount: ++multiCreateCount
            });
    
            this.state.editorFunction();
    
        }
    
        onUpdateStations = (state, selectedStations, missing_StationFieldsErrors, customSelectedStations, taskName) => {
            let selectedStationsOfTask = this.state.selectedStationsOfTask;
            let taskStations = selectedStationsOfTask[taskName] || [];
            let customStationsOfTask = this.state.customStationsOfTask;
            let taskCustomStations = customStationsOfTask[taskName] || [];
            let missingStationsofTask = this.state.missingStationsofTask;
            let missingStnErorsofTask = this.state.missingStnErorsofTask;
            selectedStationsOfTask[taskName] = selectedStations;
            customStationsOfTask[taskName] = customSelectedStations;
            missingStationsofTask[taskName] = state;
            missingStnErorsofTask[taskName] = missing_StationFieldsErrors;
            if (!this.state.isDirty) {
                if (!_.isEqual(taskStations, selectedStations) || !_.isEqual(taskCustomStations, customSelectedStations)) {
                    this.setState({
                        missingStationsofTask,
                        selectedStationsOfTask,
                        missingStnErorsofTask,
                        customStationsOfTask
                    }, () => {
                        this.setState({validForm: this.validateForm(), isDirty: true});
                        if (!this.state.isDirty) {
                            publish('edit-dirty', true);
                        }
                    });
                } else {
                    this.setState({
                        missingStationsofTask,
                        selectedStationsOfTask,
                        missingStnErorsofTask,
                        customStationsOfTask
                    }, () => {
                        this.setState({validForm: this.validateForm()});
                    });
                }
            } else {
                this.setState({
                    missingStationsofTask,
                    selectedStationsOfTask,
                    missingStnErorsofTask,
                    customStationsOfTask
                }, () => {
                    this.setState({validForm: this.validateForm()});
                });
            }
        };
    
        async refreshSchedulingSet() {
            let tmpSU = _.cloneDeep(this.state.schedulingUnit);
            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({
                    schedulingUnit: tmpSU,
                    newSet: null
                });
            }
            this.setState({saveDialogVisible: false, showAddSet: false, schedulingSets: schedulingSets});
        }
    
        /**
         * Set newly created as current SU Set
         * @param {SU Set Name} suSet
         */
        setSUSet(suSet) {
            this.setState({newSet: suSet});
        }
    
        /**
         * Select/Unselect the create another check box
         * @param {*} e
         */
        setCreateAnother(e) {
            this.setState({'createAnother': e.target.checked})
        }
    
        render() {
            let isSaveEnabled = (  this.state.constraintValidEditor &&  this.state.validEditor  && this.state.validForm && this.state.validConstraints  && this.state.validSpecification) 
            if (this.state.redirect) {
                return <Redirect to={{pathname: this.state.redirect}}></Redirect>
            }
            const schema = this.state.paramsSchema;
            const {scheduleunit_draft} = this.state.userrole;
            let jeditor = null;
            if (schema) {
                jeditor = React.createElement(Jeditor, {
                    title: "Task Parameters",
                    schema: schema,
                    initValue: this.state.paramsOutput,
                    callback: this.setEditorOutput,
                    parentFunction: this.setEditorFunction,
                    bandPassFilter: this.state.bandPassFilter,
                    observationType: this.state.observationType,
                    theme: 'bootstrap4'
                });
            }
            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/> :
                        <>
                            <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>
                                        <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' : ''}
                                                id="name" data-testid="name"
                                                tooltip="Enter name of the Scheduling Unit"
                                                tooltipOptions={this.tooltipOptions} maxLength="128"
                                                ref={input => {
                                                    this.nameInput = input;
                                                }}
                                                value={this.state.schedulingUnit.name} autoFocus
                                                onChange={(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"}
                                            </label>
                                        </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>
                                        <div className="col-lg-3 col-md-3 col-sm-12">
                                            <InputTextarea
                                                className={(this.state.errors.description && this.state.touched.description) ? 'input-error' : ''}
                                                rows={3} cols={30}
                                                tooltip="Longer description of the scheduling unit"
                                                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)}/>
                                            <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"}
                                            </label>
                                        </div>
                                    </div>
                                    {<ProjectScheduleSetSelector
                                        selectedProject={this.state.schedulingUnit.project}
                                        projectDisabled={this.state.projectDisabled}
                                        allProjects={this.projects}
                                        projectErrors={this.state.errors.project}
                                        touchedProject={this.state.touched.project}
                                        changeProject={this.changeProject}
                                        selectedSchedulingSet={this.state.schedulingUnit.scheduling_set_id}
                                        allSchedulingSets={this.state.schedulingSets}
                                        schedulingSetErrors={this.state.errors.scheduling_set_id}
                                        touchedSchedulingSet={this.state.touched.scheduling_set_id}
                                        setSchedUnitParams={this.setSchedUnitParams}
                                        scheduleUnitDraft={scheduleunit_draft}
                                        setState={this.setState}
                                    />}
                                    <div className="p-field p-grid">
                                        <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)}/>
                                        </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"/>
    
                                        </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>
                                        </label>
                                        {<ObservationStrategySelector
                                            selectedPurpose={this.state.observStrategyFilters.purpose}
                                            allPurposes={this.templatePurposes}
                                            selectedState={this.state.observStrategyFilters.states}
                                            allStates={this.templateState}
                                            selectedObservationStrategy={this.state.observStrategy}
                                            allObservationStrategies={this.state.observStrategies}
                                            observationIdSet={this.state.observationIdSet}
                                            changeStrategy={this.changeStrategy}
                                            localStoreKey={"strategyFilterSUCreate"}
                                            setState={this.setState}
                                        />}
                                        <div className="col-lg-1 col-md-1 col-sm-12"></div>
                                        <label htmlFor="autodeletion" className="col-lg-2 col-md-2 col-sm-12">Pin
                                            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)}
                                            ></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"}}>
                                                    <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})}>
                                                        <i className={this.state.stationsCollapsed ? "fas fa-caret-right" : "fas fa-caret-down"}></i>
                                                    </button>
                                                    <label>Station specification</label>
                                                </h3>
                                                {!this.state.stationsCollapsed &&
                                                    <>
                                                        {_.keys(this.state.stationGroups).map((stnGroup) => {
                                                            return <Stations
                                                                taskName={stnGroup}
                                                                stationGroup={this.state.stationGroups[stnGroup]}
                                                                onUpdateStations={this.onUpdateStations.bind(this)}
                                                                height={'auto'}
                                                                key={stnGroup}
                                                            />
                                                        })}
                                                    </>
                                                }
                                            </fieldset>
                                        </div>
                                    }
                                </div>
                                {this.state.constraintSchema && <div className="p-fluid">
                                    <fieldset className="border-style">
                                        <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}/>
                                        </div>
                                    </fieldset>
                                    <div className="p-col-12"
                                         style={{marginLeft: '0.4em', marginTop: '-10px', paddingTop: '0px'}}>
                                        <label className={this.state.validConstraints ? "info" : "error"}>
                                            {this.state.validConstraintMessage ? this.state.validConstraintMessage : ""}
                                        </label>
                                    </div>
                                </div>}
                                <div></div>
                                {this.state.paramsSchema &&
                                    <div className="p-fluid">
                                        <fieldset className="border-style">
                                            <div style={{marginLeft: '-0.5em'}}>
                                                <div className="p-col-12" style={{width: "100%"}}>
                                                    {jeditor}
                                                </div>
                                            </div>
                                        </fieldset>
                                        <div className="p-col-12" style={{
                                            marginLeft: '0.4em',
                                            marginTop: '-10px',
                                            paddingTop: '0px',
                                            marginBottom: "2em"
                                        }}>
                                            <label className={this.state.validSpecification ? "info" : "error"} data-testid="validation-spec-msg">
                                                {this.state.validSpecificationMessage}
                                            </label>
                                        </div>
                                    </div>
                                }
                            </div>
                            <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}/>
                            </div>
                            <ReactTooltip id="reacttooltip" place={'left'} type={'dark'} effect={'solid'} multiline={true}/>
                        </>
                    }
    
                    {/* Dialog component to show messages and get input */}
                    <div className="p-grid" data-testid="confirm_dialog">
                        {this.state.showAddSet &&
                            <SchedulingSet callbackFunction={this.setSUSet} project={this.state.selectedProject[0]}
                                           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}]}
                        >
                        </CustomDialog>
                    </div>
                </React.Fragment>
            );
        }
    }
    
    SchedulingUnitCreate.propTypes = {
        match: PropTypes.object,
      history: PropTypes.object,
      location: PropTypes.oneOfType([PropTypes.object, PropTypes.string])
    }
    
    export default SchedulingUnitCreate;