Skip to content
Snippets Groups Projects
Select Git revision
  • 2d8a2711a829e0202f6d63e33485f1aaa590198a
  • 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

reservation.edit.js

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    reservation.edit.js 33.28 KiB
    import React, { Component } from 'react';
    import { Redirect } from 'react-router-dom'
    
    import { Button } from 'primereact/button';
    import { Dropdown } from 'primereact/dropdown';
    import { InputText } from 'primereact/inputtext';
    import { InputTextarea } from 'primereact/inputtextarea';
    
    import moment from 'moment';
    import _ from 'lodash';
    import Flatpickr from "react-flatpickr";
    
    import { publish } from '../../App';
    import { CustomDialog } from '../../layout/components/CustomDialog';
    import { appGrowl } from '../../layout/components/AppGrowl';
    import AppLoader from '../../layout/components/AppLoader';
    import PageHeader from '../../layout/components/PageHeader';
    import Jeditor from '../../components/JSONEditor/JEditor';
    import UIConstants from '../../utils/ui.constants';
    import ProjectService from '../../services/project.service';
    import ReservationService from '../../services/reservation.service';
    import UtilService from '../../services/util.service';
    import { InputMask } from 'primereact/inputmask';
    import UnitConverter from '../../utils/unit.converter';
    
    export class ReservationEdit extends Component {
        constructor(props) {
            super(props);
            this.state = {
                isLoading: true,
                isDirty: false,
                errors: {},                             // Validation Errors
                validFields: {},                        // For Validation
                validForm: false,                       // To enable Save Button
                validEditor: false,
                reservationStrategy: {
                    id: null,
                },
            };
            this.hasProject = false;        // disable project column if project already
            this.projects = [];                         // All projects to load project dropdown
            this.reservationTemplates = [];
            this.reservationStrategies = [];
            this.tooltipOptions = UIConstants.tooltipOptions;
    
            this.setEditorOutput = this.setEditorOutput.bind(this);
            this.setEditorFunction = this.setEditorFunction.bind(this);
            this.checkIsDirty = this.checkIsDirty.bind(this);
            this.isValidDuration = this.isValidDuration.bind(this);
            this.saveReservation = this.saveReservation.bind(this);
            this.close = this.close.bind(this);
            this.cancelEdit = this.cancelEdit.bind(this);
    
            // Validateion Rules
            this.formRules = {
                name: { required: true, message: "Name can not be empty" },
                description: { required: true, message: "Description can not be empty" },
                start_time: { required: true, message: "Start Time can not be empty" },
            };
        }
    
        componentDidMount() {
            this.initReservation();
        }
    
        /**
         * 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 });
        }
      
        /**
         * Initialize the Reservation and related
         */
        async initReservation() {
            const reserId = this.props.match ? this.props.match.params.id : null;
            const promises = [ProjectService.getProjectList(),
            ReservationService.getReservationTemplates(),
            UtilService.getUTC(),
            ReservationService.getReservationStrategyTemplates()
            ];
            let emptyProjects = [{ url: null, name: "Select Project" }];
            Promise.all(promises).then(responses => {
                this.projects = emptyProjects.concat(responses[0]);
                this.reservationTemplates = responses[1];
                let systemTime = moment.utc(responses[2]);
                this.reservationStrategies = responses[3];
                let schema = {
                    properties: {}
                };
                if (this.state.reservationTemplate) {
                    schema = this.state.reservationTemplate.schema;
                }
                this.setState({
                    paramsSchema: schema,
                    isLoading: false,
                    systemTime: systemTime
                });
                this.getReservationDetails(reserId);
            });
    
        }
        
        /**
         * To get the reservation details from the backend using the service
         * @param {number} Reservation Id
         */
        async getReservationDetails(id) {
            if (id) {
                await ReservationService.getReservation(id)
                    .then(async (reservation) => {
                        if (reservation) {                        
                            reservation.duration = reservation.duration || 0;
                            reservation.duration = UnitConverter.getSecsToDDHHmmss(reservation.duration); //this.secondsToHms(reservation.duration);
                            let reservationTemplate = this.reservationTemplates.find(reserTemplate => reserTemplate.id === reservation.specifications_template_id);
                            if (this.state.editorFunction) {
                                this.state.editorFunction();
                            }
                            // no project then allow to select project from dropdown list
                            this.hasProject = reservation.project ? true : false;
                            let schema = {
                                properties: {}
                            };
                            if (reservationTemplate) {
                                schema = reservationTemplate.schema;
                            }
                            let project = this.projects.find(project => project.name === reservation.project_id);
                            reservation['project'] = project ? project.name : null;
                            let strategyName = reservation.specifications_doc.activity.name;
                            let reservationStrategy = null;
                            if (strategyName) {
                                reservationStrategy = this.reservationStrategies.find(strategy => strategy.name === strategyName);
                            } else {
                                reservationStrategy = {
                                    id: null,
                                }
                            }
    
                            this.setState({
                                reservationStrategy: reservationStrategy,
                                reservation: reservation,
                                reservationTemplate: reservationTemplate,
                                paramsSchema: schema,
                            });
                        } else {
                            this.setState({ redirect: "/not-found" });
                        }
                    });
            } else {
                this.setState({ redirect: "/not-found" });
            }
        }
    
        close() {
            this.setState({ showDialog: false });
        }
    
        /**
         * Cancel edit and redirect to Reservation View page
         */
        cancelEdit() {      
            const reserId = this.props.match ? this.props.match.params.id : null;
            publish('edit-dirty', false);       
            this.setState({ showDialog: false });
            this.props.history.goBack();        
        }
    
        /**
         * warn before cancel this page if any changes detected 
         */
        checkIsDirty() {
            if (this.state.isDirty) {
                this.setState({ showDialog: true });
            } else {
                this.cancelEdit();
            }
        }
    
        /**
         * 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.reservation[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.reservation[fieldName];
                    if (rule.required) {
                        if (!fieldValue) {
                            errors[fieldName] = rule.message ? rule.message : `${fieldName} is required`;
                        } else {
                            validFields[fieldName] = true;
                        }
                    }
                }
            }
            this.setState({ errors: errors, validFields: validFields });
            if (Object.keys(validFields).length === Object.keys(this.formRules).length) {
                validForm = true;
                delete errors['start_time'];
                delete errors['stop_time'];
            }
            if (!this.validateDates(this.state.reservation.start_time, this.state.reservation.stop_time)) {
                validForm = false;
                if (!fieldName || fieldName === 'start_time') {
                    errors['start_time'] = "Start Time cannot be same or after End Time";
                    delete errors['stop_time'];
                }
                if (!fieldName || fieldName === 'stop_time') {
                    errors['stop_time'] = "End Time cannot be same or before Start Time";
                    delete errors['start_time'];
                }
                this.setState({ errors: errors });
            }
            if (fieldName === 'duration' && this.state.reservation.duration) {
                var values = this.state.reservation.duration.split(' ');
                var days = values[0];
                var dValues = values[1].split(':');           
                delete errors['duration'];
                if ((days *1 )===0 && (dValues[0] * 1) === 0 && (dValues[1] * 1) === 0 && (dValues[2] * 1) === 0) {
                    validForm = false;
                    if (!fieldName || fieldName === 'duration') {
                        errors['duration'] = "Duration cannot be zero";
                    }
                    this.setState({ errors: errors });
                }
            }
            return validForm;
        }
    
        /**
         * Function to validate if stop_time is always later than start_time if exists.
         * @param {Date} fromDate 
         * @param {Date} toDate 
         * @returns boolean
         */
        validateDates(fromDate, toDate) {
            if (fromDate && toDate && moment(toDate).isSameOrBefore(moment(fromDate))) {
                return false;
            }
            return true;
        }
    
        /**
        * This function is mainly added for Unit Tests. If this function is removed Unit Tests will fail.
        */
        validateEditor() {
            return this.validEditor;
        }
    
        /**
         * Function to call on change and blur events from input components
         * @param {string} key 
         * @param {any} value 
         */
        setParams(key, value, type) {
            let reservation = this.state.reservation;
            switch (type) {
                case 'NUMBER': {
                    reservation[key] = value ? parseInt(value) : 0;
                    break;
                }
                default: {
                    reservation[key] = value;
                    break;
                }
            }
            this.setState({ reservation: reservation, validForm: this.validateForm(key), isDirty: true },
                () => {
                    this.setDurationOrEndValue(key);
                });
            publish('edit-dirty', true);
        }
    
        /**
         * Function to set the value for the dependant fields when value is set to one field.
         * When start_time or stop_time is changed, duration will be updated accordingly.
         * Similarly if duration is changed, stop_time is updated.
         * @param {String} key - property name of the reservation
         */
        setDurationOrEndValue = (key) => {
            let state = this.state;
            if ( key === 'start_time' || key === 'stop_time') {
                if (this.state.reservation.start_time && this.state.reservation.stop_time) {
                    var delta = Math.abs(new Date(this.state.reservation.start_time) - new Date(this.state.reservation.stop_time)) / 1000;
                    let tempDuration = UnitConverter.getSecsToDDHHmmss(delta);              
                    this.setDurationOrStopTime('duration', tempDuration);
                }   else if (key === 'start_time' && this.state.reservation.start_time && this.state.reservation.duration) {
                    let stopDate = UnitConverter.getEndDateFromDuration(this.state.reservation.start_time, this.state.reservation.duration);               
                    this.setDurationOrStopTime('stop_time', stopDate);
                }   else if (key === 'stop_time' && !this.state.reservation.stop_time) {
                    this.setDurationOrStopTime('duration', "");
                }
            }
            else if (key === 'duration') {            
                if (this.state.reservation.start_time) {
                    let stopDate = UnitConverter.getEndDateFromDuration(this.state.reservation.start_time, this.state.reservation.duration);               
                    this.setDurationOrStopTime('stop_time', stopDate);
                }
            }
        }
        
        /**
         * Function to set calcualted value for either duration or stop_time
         * @param {String} key - name of the field
         * @param {*} value - value to set for the field
         */
         setDurationOrStopTime(key, value) {
            let reservation = this.state.reservation;
            reservation[key] = value;
            this.setState({ reservation: reservation, validForm: this.validateForm(key), isDirty: true });
        }
    
        /**
         * Function to validate the duration field.
         * @param {String} value - Duration in format 'Days HH:mm:ss'
         * @returns boolean
         */
         isValidDuration(value) {
            let errors = this.state.errors;
            let touched = this.state.touched;
            let reservation = this.state.reservation;
            let validForm = this.state.validForm;
            if (value.length === 12 && (value === "000 00:00:00" ||
                !value.match(/^([0-1]90 00:00:00)|([0-1][0-8][0-9] ([0-1]?\d|2[0-3]):([0-5]?\d):([0-5]?\d))$/))) {
                errors.duration = "Not valid duration. Duration should be in Days Hours:minutes:seconds. Min - 000 00:00:01, Max - 190 00:00:00";
                touched.duration = true;
                validForm = false;
            }   else {
                delete errors["duration"];
                delete touched["duration"];
                validForm = this.validateForm();
            }
            reservation.duration = value;
            this.setState({errors: errors, touched: touched, reservation: reservation, validForm: validForm});
            return errors.duration?false:true;
        }
    
        /**
         * Set JEditor output
         * @param {*} jsonOutput 
         * @param {*} errors 
         */
        setEditorOutput(jsonOutput, errors) {
            this.paramsOutput = jsonOutput;
            this.validEditor = errors.length === 0;
            if (!this.state.isDirty && this.state.paramsOutput && !_.isEqual(this.state.paramsOutput, jsonOutput)) {
                this.setState({
                    paramsOutput: jsonOutput,
                    validEditor: errors.length === 0,
                    validForm: this.validateForm(),
                    isDirty: true
                });
                publish('edit-dirty', true);
            } else {
                this.setState({
                    paramsOutput: jsonOutput,
                    validEditor: errors.length === 0,
                    validForm: this.validateForm()
                });
            }
        }
    
        /**
         * Function to set form values to the Reservation object
         * @param {string} key 
         * @param {object} value 
         */
        setReservationParams(key, value) {
            let reservation = _.cloneDeep(this.state.reservation);
            reservation[key] = value;
            if (!this.state.isDirty && !_.isEqual(this.state.reservation, reservation)) {
                this.setState({
                    reservation: reservation, validForm: this.validateForm(key), validEditor: this.validateEditor(), touched: {
                        ...this.state.touched,
                        [key]: true
                    }, isDirty: true
                });
                publish('edit-dirty', true);
            } else {
                this.setState({
                    reservation: reservation, validForm: this.validateForm(key), validEditor: this.validateEditor(), touched: {
                        ...this.state.touched,
                        [key]: true
                    }
                });
            }
        }
    
        /**
         * Update reservation
         */
        async saveReservation() {
            let reservation = this.state.reservation;
            let project = this.projects.find(project => project.name === reservation.project);
            reservation['start_time'] = moment(reservation['start_time']).format(UIConstants.CALENDAR_DATETIME_FORMAT);
            reservation['stop_time'] = (reservation['stop_time'] && reservation['stop_time'] !== 'Invalid date') ? moment(reservation['stop_time']).format(UIConstants.CALENDAR_DATETIME_FORMAT) : null;
            reservation['project'] = project ? project.url : null;
            reservation['specifications_doc'] = this.paramsOutput;
            reservation = await ReservationService.updateReservation(reservation);
            if (reservation && reservation.id) {
                appGrowl.show({ severity: 'success', summary: 'Success', detail: 'Reservation updated successfully.' });
                this.props.history.push({
                    pathname: `/reservation/view/${this.props.match.params.id}`,
                });
                publish('edit-dirty', false);
            } else {
                appGrowl.show({ severity: 'error', summary: 'Error Occured', detail: 'Unable to update Reservation', showDialog: false, isDirty: false });
            }
        }
    
        render() {
            if (this.state.redirect) {
                return <Redirect to={{ pathname: this.state.redirect }}></Redirect>
            }
            let jeditor = null;
            if (this.state.reservationTemplate) {
                if (this.state.reservation.specifications_doc.$id) {
                    delete this.state.reservation.specifications_doc.$id;
                    delete this.state.reservation.specifications_doc.$schema;
                }
                jeditor = React.createElement(Jeditor, {
                    title: "Reservation Parameters",
                    schema: this.state.reservationTemplate.schema,
                    initValue: this.state.reservation.specifications_doc,
                    disabled: false,
                    callback: this.setEditorOutput,
                    parentFunction: this.setEditorFunction
                });
            }
    
            return (
                <React.Fragment>
                    <PageHeader location={this.props.location} title={'Reservation - Edit'} actions={[{
                        icon: 'fa-window-close',
                        title: 'Click to Close Reservation - Edit', type: 'button', actOn: 'click', props: { callback: this.checkIsDirty }
                    }]} />
    
                    { this.state.isLoading ? <AppLoader /> : this.state.reservation &&
                        <React.Fragment>
                            <div>
                                <div className="p-fluid">
                                    <div className="p-field p-grid">
                                        <label htmlFor="reservationname" 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">
                                            <InputText className={(this.state.errors.name && this.state.touched.name) ? 'input-error' : ''} id="reservationname" data-testid="name"
                                                tooltip="Enter name of the Reservation" tooltipOptions={this.tooltipOptions} maxLength="128"
                                                ref={input => { this.nameInput = input; }}
                                                value={this.state.reservation.name} autoFocus
                                                onChange={(e) => this.setReservationParams('name', e.target.value)}
                                                onBlur={(e) => this.setReservationParams('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 Reservation"
                                                tooltipOptions={this.tooltipOptions}
                                                maxLength="128"
                                                data-testid="description"
                                                value={this.state.reservation.description}
                                                onChange={(e) => this.setReservationParams('description', e.target.value)}
                                                onBlur={(e) => this.setReservationParams('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>
    
                                    <div className="p-field p-grid">
                                        <label htmlFor="project" className="col-lg-2 col-md-2 col-sm-12">Project</label>
                                        <div className="col-lg-3 col-md-3 col-sm-12" data-testid="project" >
                                            <Dropdown inputId="project" optionLabel="name" optionValue="name"
                                                tooltip="Project" tooltipOptions={this.tooltipOptions}
                                                value={this.state.reservation.project}
                                                options={this.projects}
                                                onChange={(e) => { this.setParams('project', e.value) }}
                                                placeholder="Select Project"
                                                disabled={this.hasProject}
                                            />
                                            <label className={(this.state.errors.project && this.state.touched.project) ? "error" : "info"}>
                                                {(this.state.errors.project && this.state.touched.project) ? this.state.errors.project : "Select Project"}
                                            </label>
                                        </div>
                                        {/*  <div className="col-lg-1 col-md-1 col-sm-12"></div>
                                        <label htmlFor="strategy" className="col-lg-2 col-md-2 col-sm-12">Reservation Strategy</label>
                                        <div className="col-lg-3 col-md-3 col-sm-12" data-testid="strategy" >
                                            {this.state.reservationStrategy.id &&
                                            <Dropdown inputId="strategy" optionLabel="name" optionValue="id" 
                                                    tooltip="Choose Reservation Strategy Template to set default values for create Reservation" tooltipOptions={this.tooltipOptions}
                                                    value={this.state.reservationStrategy.id} 
                                                    options={this.reservationStrategies} 
                                                    onChange={(e) => {this.changeStrategy(e.value)}} 
                                                    placeholder="Select Strategy"
                                                    disabled= {true} />
                                            }
                                        </div> */}
                                    </div>
    
                                    <div className="p-field p-grid">
                                        <label htmlFor="start-time" className="col-lg-2 col-md-2 col-sm-12" >Start Time<span style={{ color: 'red' }}>*</span></label>
                                        <div className="col-lg-3 col-md-3 col-sm-12">
                                            <Flatpickr data-enable-time data-input options={{
                                                "inlineHideInput": true,
                                                "wrap": true,
                                                "enableSeconds": true,
                                                "time_24hr": true,
                                                "minuteIncrement": 1,
                                                "allowInput": true,
                                                "defaultDate": this.state.systemTime.format(UIConstants.CALENDAR_DEFAULTDATE_FORMAT),
                                                "defaultHour": this.state.systemTime.hours(),
                                                "defaultMinute": this.state.systemTime.minutes()
                                            }}
                                                title="Start of this reservation"
                                                value={this.state.reservation.start_time}
                                                onChange={value => {
                                                    this.setParams('start_time', value[0] ? value[0] : this.state.reservation.start_time);
                                                    this.setReservationParams('start_time', value[0] ? value[0] : this.state.reservation.start_time)
                                                }} >
                                                <input type="text" data-input className={`p-inputtext p-component ${this.state.errors.start_time && this.state.touched.start_time ? 'input-error' : ''}`} />
                                                <i className="fa fa-calendar" data-toggle style={{ position: "absolute", marginLeft: '-25px', marginTop: '5px', cursor: 'pointer' }} ></i>
                                                <i className="fa fa-times" style={{ position: "absolute", marginLeft: '-50px', marginTop: '5px', cursor: 'pointer' }}
                                                    onClick={e => { this.setParams('start_time', ''); this.setReservationParams('start_time', '') }}></i>
                                            </Flatpickr>
                                            <label className={this.state.errors.start_time && this.state.touched.start_time ? "error" : "info"}>
                                                {this.state.errors.start_time && this.state.touched.start_time ? this.state.errors.start_time : ""}
                                            </label>
                                        </div>
                                        <div className="col-lg-1 col-md-1 col-sm-12"></div>
                                        <label className="col-lg-2 col-md-2 col-sm-12">End time</label>
                                        <div className="col-lg-3 col-md-3 col-sm-12">
                                            <Flatpickr data-enable-time data-input options={{
                                                "inlineHideInput": true,
                                                "wrap": true,
                                                "enableSeconds": true,
                                                "time_24hr": true,
                                                "minuteIncrement": 1,
                                                "allowInput": true,
                                                "minDate": this.state.reservation.stop_time ? this.state.reservation.stop_time.toDate : '',
                                                "defaultDate": this.state.systemTime.format(UIConstants.CALENDAR_DEFAULTDATE_FORMAT),
                                                "defaultHour": this.state.systemTime.hours(),
                                                "defaultMinute": this.state.systemTime.minutes()
                                            }}
                                                title="End of this reservation. If empty, then this reservation is indefinite."
                                                value={this.state.reservation.stop_time}
                                                onChange={value => {
                                                    this.setParams('stop_time', value[0] ? value[0] : this.state.reservation.stop_time);
                                                    this.setReservationParams('stop_time', value[0] ? value[0] : this.state.reservation.stop_time)
                                                }} >
                                                <input type="text" data-input className={`p-inputtext p-component ${this.state.errors.stop_time && this.state.touched.stop_time ? 'input-error' : ''}`} />
                                                <i className="fa fa-calendar" data-toggle style={{ position: "absolute", marginLeft: '-25px', marginTop: '5px', cursor: 'pointer' }} ></i>
                                                <i className="fa fa-times" style={{ position: "absolute", marginLeft: '-50px', marginTop: '5px', cursor: 'pointer' }}
                                                    onClick={e => { this.setParams('stop_time', ''); this.setReservationParams('stop_time', '') }}></i>
                                            </Flatpickr>
                                            <label className={this.state.errors.stop_time && this.state.touched.stop_time ? "error" : "info"}>
                                                {this.state.errors.stop_time && this.state.touched.stop_time ? this.state.errors.stop_time : ""}
                                            </label>
                                        </div>
                                    </div>
    
                                    <div className="p-field p-grid">
                                        <label className="col-lg-2 col-md-2 col-sm-12">Duration</label>
                                        <div className="col-lg-3 col-md-3 col-sm-12">
                                            <InputMask mask="999 99:99:99"
                                                tooltip="Enter duration in (Days HH:mm:ss) format. Min-000 00:00:01 & Max-190 00:00:00."
                                                tooltipOptions={this.tooltipOptions} 
                                                value={this.state.reservation.duration}
                                                placeholder="DDD HH:MM:SS"
                                                onChange={(e) =>{if(!e.value) {this.setDurationOrEndValue("stop_time")}}}
                                                onComplete={(e) => {
                                                    if (this.isValidDuration(e.value)) {
                                                        this.setReservationParams('duration', e.value);
                                                        this.setParams('duration', e.value ? e.value : this.state.reservation.duration);
                                                    }
                                                }}
                                                onBlur={(e) => {
                                                    this.setParams('duration', e.value ? e.value : this.state.reservation.duration);
                                                }}></InputMask>
                                            <label className={this.state.errors.duration && this.state.touched.duration ? "error" : "info"}>
                                                {this.state.errors.duration && this.state.touched.duration ? this.state.errors.duration : ""}
                                            </label>
                                        </div>
                                    </div>
    
                                    <div className="p-grid">
                                        <div className="p-col-12">
                                            {this.state.paramsSchema ? jeditor : ""}
                                        </div>
                                    </div>
                                </div>
    
                                <div className="p-grid p-justify-start">
                                    <div className="p-col-1">
                                        <Button label="Save" className="p-button-primary" icon="pi pi-check" onClick={this.saveReservation}
                                            disabled={!this.state.validEditor || !this.state.validForm} data-testid="save-btn" />
                                    </div>
                                    <div className="p-col-1">
                                        <Button label="Cancel" className="p-button-danger" icon="pi pi-times" onClick={this.checkIsDirty} />
                                    </div>
                                </div>
                            </div>
    
                        </React.Fragment>
                    }
    
                    <CustomDialog type="confirmation" visible={this.state.showDialog} width="40vw"
                        header={'Edit Reservation'} message={'Do you want to leave this page? Your changes may not be saved.'}
                        content={''} onClose={this.cancelEdit} onCancel={this.close} onSubmit={this.cancelEdit}>
                    </CustomDialog>
    
                </React.Fragment>
            );
        }
    }