From 577cae15878be2b8eca19c2151f6c38eeb8b5130 Mon Sep 17 00:00:00 2001
From: Muthu <rspmkn@gmail.com>
Date: Wed, 26 Aug 2020 14:58:38 +0530
Subject: [PATCH] TMSS-297 : Component for page header updated

Component for page header updated
---
 SAS/TMSS/frontend/tmss_webapp/src/App.js      |   3 +-
 .../tmss_webapp/src/layout/_overrides.scss    |  11 +
 .../src/layout/components/AppHeader.js        |  34 ++
 .../src/routes/Cycle/ResourceDisplayList.js   |  31 ++
 .../src/routes/Cycle/ResourceInputList.js     |  58 ++
 .../tmss_webapp/src/routes/Cycle/create.js    | 477 ++++++++++++++++
 .../src/routes/Cycle/create.test.js           | 346 ++++++++++++
 .../tmss_webapp/src/routes/Cycle/edit.js      | 507 ++++++++++++++++++
 .../tmss_webapp/src/routes/Cycle/index.js     |   6 +
 .../tmss_webapp/src/routes/Cycle/list.js      | 160 ++++++
 .../tmss_webapp/src/routes/Cycle/list.test.js |  69 +++
 .../tmss_webapp/src/routes/Cycle/view.js      | 143 +++++
 .../tmss_webapp/src/routes/Project/create.js  |  27 +-
 .../tmss_webapp/src/routes/Project/edit.js    |  12 +-
 .../tmss_webapp/src/routes/Project/list.js    |  11 +-
 .../tmss_webapp/src/routes/Project/view.js    |  20 +-
 .../routes/Scheduling/SchedulingUnitList.js   |  45 +-
 .../routes/Scheduling/ViewSchedulingUnit.js   |  81 +--
 .../src/routes/Scheduling/index.js            |   3 +-
 .../tmss_webapp/src/routes/Task/edit.js       |  12 +-
 .../tmss_webapp/src/routes/Task/view.js       |  15 +-
 .../frontend/tmss_webapp/src/routes/index.js  |  36 +-
 .../tmss_webapp/src/services/cycle.service.js | 123 ++++-
 .../src/services/schedule.service.js          |  12 +-
 24 files changed, 2141 insertions(+), 101 deletions(-)
 create mode 100644 SAS/TMSS/frontend/tmss_webapp/src/layout/components/AppHeader.js
 create mode 100644 SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/ResourceDisplayList.js
 create mode 100644 SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/ResourceInputList.js
 create mode 100644 SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/create.js
 create mode 100644 SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/create.test.js
 create mode 100644 SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/edit.js
 create mode 100644 SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/index.js
 create mode 100644 SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/list.js
 create mode 100644 SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/list.test.js
 create mode 100644 SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/view.js

diff --git a/SAS/TMSS/frontend/tmss_webapp/src/App.js b/SAS/TMSS/frontend/tmss_webapp/src/App.js
index c35c53eb523..5bce851b911 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/App.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/App.js
@@ -36,6 +36,7 @@ class App extends Component {
   
       this.menu = [
       {label: 'Dashboard', icon: 'pi pi-fw pi-home', to:'/dashboard'},
+      {label: 'Cycle', icon:'pi pi-fw pi-spinner', to:'/cycle'},
       {label: 'Scheduling Units', icon: 'pi pi-fw pi-calendar', to:'/schedulingunit'},
       {label: 'Tasks', icon: 'pi pi-fw pi-check-square', to:'/task'},
       {label: 'Project', icon: 'fa fa-fw fa-binoculars', to:'/project'}
@@ -117,8 +118,6 @@ class App extends Component {
               <AppMenu model={this.menu} onMenuItemClick={this.onMenuItemClick} />
               <div className="layout-main">
 			  <AppBreadCrumbWithRouter setPageTitle={this.setPageTitle} />
-              {/* Display current pagename */}
-             <h2>{this.state.PageTitle}</h2> 
               <RoutedContent />
               </div>
             </Router>
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/layout/_overrides.scss b/SAS/TMSS/frontend/tmss_webapp/src/layout/_overrides.scss
index ddf77d3e4b2..87a69cd8d25 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/layout/_overrides.scss
+++ b/SAS/TMSS/frontend/tmss_webapp/src/layout/_overrides.scss
@@ -22,4 +22,15 @@
    .layout-sidebar-dark .layout-menu li a    {
     border-top: none;
    }
+}
+.app-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: baseline;
+}
+.app-header .app-header-name {
+    margin-bottom: 0;
+}
+.app-header .app-header-actions i {
+    margin-left: 20px;
 }
\ No newline at end of file
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/layout/components/AppHeader.js b/SAS/TMSS/frontend/tmss_webapp/src/layout/components/AppHeader.js
new file mode 100644
index 00000000000..12c866148bf
--- /dev/null
+++ b/SAS/TMSS/frontend/tmss_webapp/src/layout/components/AppHeader.js
@@ -0,0 +1,34 @@
+import React, { useEffect, useState } from 'react';
+import { routes } from '../../routes';
+import {matchPath, Link} from 'react-router-dom';
+
+export default (props) => {
+    const [PageTitle, setPageTitle] = useState({});
+
+    useEffect(() => {
+        const currentRoute = routes.find(route => matchPath(props.location.pathname, {path: route.path, exact: true, strict: true}));
+		//for intial route ,there wont be any route object so it failed 
+		if(!currentRoute){
+			return;
+        }
+        setPageTitle(currentRoute);
+    }, []);
+
+    return (
+        <div className="app-header">
+            <div className="title">
+                <h2 className="app-header-name">{PageTitle.name}</h2>
+                {PageTitle.subtitle && <h6 className="app-header-subtitle">{PageTitle.subtitle}</h6>}
+            </div>
+            <div className="app-header-actions">
+                {(props.actions || []).map(action => {
+                    console.log(action.props);
+                    return (
+                        <Link to={{ ...action.props }}>
+                        <i className={`fa ${action.name}`}></i>
+                    </Link>
+                )})}
+            </div>
+        </div>
+    );
+}
\ No newline at end of file
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/ResourceDisplayList.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/ResourceDisplayList.js
new file mode 100644
index 00000000000..c1a00381eeb
--- /dev/null
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/ResourceDisplayList.js
@@ -0,0 +1,31 @@
+import React, {Component} from 'react';
+
+/**
+ * Component to get input for Resource allocation while creating and editing Cycle
+ */
+class ResourceDisplayList extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            cycleQuota: props.cycleQuota
+        }
+    }
+
+    render(){
+        return (
+            <>
+                {this.props.cycleQuota.length>0 && this.props.cycleQuota.map((item, index) => (
+                    <React.Fragment key={index+10}>
+                    <label key={'label1-'+ index} className="col-lg-3 col-md-3 col-sm-12">{item.resource.name}</label>
+                    <span key={'div1-'+ index} className="col-lg-3 col-md-3 col-sm-12">
+                        {item.value/(this.props.unitMap[item.resource.quantity_value]?this.props.unitMap[item.resource.quantity_value].conversionFactor:1)}
+                        {` ${this.props.unitMap[item.resource.quantity_value]?this.props.unitMap[item.resource.quantity_value].display:''}`}
+                    </span>
+                    </React.Fragment>
+                ))}
+            </>
+        );
+    }
+}
+
+export default ResourceDisplayList;
\ No newline at end of file
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/ResourceInputList.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/ResourceInputList.js
new file mode 100644
index 00000000000..a188d348b29
--- /dev/null
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/ResourceInputList.js
@@ -0,0 +1,58 @@
+import React, {Component} from 'react';
+import {InputNumber} from 'primereact/inputnumber';
+
+/**
+ * Component to get input for Resource allocation while creating and editing Cycle
+ */
+export class ResourceInputList extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            list: props.list,
+            cycleQuota: props.cycleQuota
+        }
+        this.updateEnabled = this.props.list.length===0?true:false;
+        this.onInputChange = this.onInputChange.bind(this);
+    }
+
+    shouldComponentUpdate() {
+        return true;
+    }
+
+    onInputChange(field, event) {
+        if (this.props.callback) {
+            this.props.callback(field, event);
+        }
+    }
+
+    removeInput(field) {
+        if (this.props.removeInputCallback) {
+            this.props.removeInputCallback(field);
+        }
+    }
+
+    render(){
+        return (
+            <>
+                {this.props.list.length>0 && this.props.list.map((item, index) => (
+                    <React.Fragment key={index+10}>
+                    <label key={'label1-'+ index} className="col-lg-2 col-md-2 col-sm-12">{item.name}</label>
+                    <div key={'div1-'+ index} className="col-lg-3 col-md-3 col-sm-12">
+                        <InputNumber key={'item1-'+ index} id={'item1-'+ index} name={'item1-'+ index}
+                            suffix={` ${this.props.unitMap[item.quantity_value]?this.props.unitMap[item.quantity_value].display:''}`}
+                            placeholder={` ${this.props.unitMap[item.quantity_value]?this.props.unitMap[item.quantity_value].display:item.name}`} min={0} useGrouping={false}
+                            value={this.props.cycleQuota[item.name]} 
+                            onChange={(e) => this.onInputChange(item.name, e)}
+                            onBlur={(e) => this.onInputChange(item.name, e)}
+                            style={{width:"90%", marginRight: "5px"}}
+                        />
+                        <button className="p-link" data-testid={`${item.name}-btn`} onClick={(e) => this.removeInput(item.name)}>
+                            <i className="fa fa-trash pi-error"></i></button>
+                    </div>
+                    <div className="col-lg-1 col-md-1 col-sm-12"></div>
+                    </React.Fragment>
+                ))}
+            </>
+        );
+    }
+}
\ No newline at end of file
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/create.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/create.js
new file mode 100644
index 00000000000..be4206019f9
--- /dev/null
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/create.js
@@ -0,0 +1,477 @@
+import React, {Component} from 'react';
+import { Link, Redirect } from 'react-router-dom';
+import {InputText} from 'primereact/inputtext';
+import {Calendar} from 'primereact/calendar';
+import {InputTextarea} from 'primereact/inputtextarea';
+import {Dropdown} from 'primereact/dropdown';
+import {Button} from 'primereact/button';
+import {Dialog} from 'primereact/components/dialog/Dialog';
+import {Growl} from 'primereact/components/growl/Growl';
+import {ResourceInputList} from './ResourceInputList';
+import moment from 'moment'
+import _ from 'lodash';
+
+import AppLoader from '../../layout/components/AppLoader';
+import AppHeader from '../../layout/components/AppHeader';
+import CycleService from '../../services/cycle.service';
+import UnitConverter from '../../utils/unit.converter';
+import UIConstants from '../../utils/ui.constants';
+
+/**
+ * Component to create a new Cycle
+ */
+export class CycleCreate extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            isLoading: true,
+            dialog: { header: '', detail: ''},      
+            cycle: {
+                projects: [],
+                quota: [],  
+                start: "",
+                stop: "",
+            },
+            cycleQuota: {},                       // Resource Allocations
+            validFields: {},                        // For Validation
+            validForm: false,                       // To enable Save Button
+            errors: {},                             // Validation Errors
+            resources: [],                          // Selected Resources for Allocation
+            resourceList: [],                       // Available Resources for Allocation
+        }
+        // Validateion Rules
+        this.formRules = {
+            name: {required: true, message: "Name can not be empty"},
+            description: {required: true, message: "Description can not be empty"},
+            start: {required: true, message: "Start Date can not be empty"},
+            stop: {required: true, message: "Stop Date can not be empty"} 
+        };
+        this.defaultResourcesEnabled = true;        // This property and functionality to be concluded based on PO input
+        this.defaultResources = [
+                        {name:'LOFAR Observing Time'}, 
+                        {name:'LOFAR Observing Time prio A'}, 
+                        {name:'LOFAR Observing Time prio B'},
+                        {name:'CEP Processing Time'}, 
+                        {name:'LTA Storage'}, 
+                        {name:'LOFAR LTA resources SARA'}, 
+                        {name:'LOFAR LTA resources Jülich'}, 
+                        {name:'LOFAR LTA resources Poznan'}, 
+                        {name:'LOFAR Observing time DDT/Commissioning'}, 
+                        {name:'LOFAR Support Time'}];
+        this.cycleResourceDefaults = {};          // Default values for default resources
+        this.resourceUnitMap = UnitConverter.resourceUnitMap;       // Resource unit conversion factor and constraints
+        this.tooltipOptions = UIConstants.tooltipOptions;
+        this.setCycleQuotaDefaults = this.setCycleQuotaDefaults.bind(this);
+        this.addNewResource = this.addNewResource.bind(this);
+        this.removeResource = this.removeResource.bind(this);
+        this.setCycleQuotaParams = this.setCycleQuotaParams.bind(this);
+        this.saveCycle = this.saveCycle.bind(this);
+        this.cancelCreate = this.cancelCreate.bind(this);
+        this.reset = this.reset.bind(this);
+    }
+
+    componentDidMount() {
+        CycleService.getResources()
+            .then(resourceList => {
+                const defaultResources = this.defaultResources;
+                resourceList = _.sortBy(resourceList, "name");
+                const resources = _.remove(resourceList, function(resource) { return _.find(defaultResources, {'name': resource.name})!=null });
+                const cycleQuota = this.setCycleQuotaDefaults(resources);
+                this.setState({resourceList: resourceList, resources: resources, cycleQuota: cycleQuota, isLoading: false});
+        });
+    }
+
+    /**
+     * Cycle option sub-component with cycle object
+     */
+    cycleOptionTemplate(option) {
+        return (
+            <div className="p-clearfix">
+                <span style={{fontSize:'1em',float:'right',margin:'1em .5em 0 0'}}>{option.name}</span>
+            </div>
+        );
+    }
+
+    /**
+     * Function to set cycle resource allocation
+     * @param {Array} resources 
+     */
+    setCycleQuotaDefaults(resources) {
+        let cycleQuota = this.state.cycleQuota;
+        for (const resource of resources) {
+            // const conversionFactor = this.resourceUnitMap[resource.quantity_value]?this.resourceUnitMap[resource.quantity_value].conversionFactor:1;
+            // cycleQuota[resource['name']] = this.cycleResourceDefaults[resource.name]/conversionFactor;
+            cycleQuota[resource['name']] = 0;
+        }
+        return cycleQuota;
+    }
+
+    /**
+     * Function to add new resource to Cycle
+     */
+    addNewResource(){
+        if (this.state.newResource) {
+            let resourceList = this.state.resourceList;
+            const newResource = _.remove(resourceList, {'name': this.state.newResource});
+            let resources = this.state.resources;
+            resources.push(newResource[0]);
+            this.setState({resources: resources, resourceList: resourceList, newResource: null});
+        }
+    }
+
+        /**
+     * Callback function to be called from ResourceInpulList when a resource is removed from it
+     * @param {string} name - resource_type_id
+     */
+    removeResource(name) {
+        let resources = this.state.resources;
+        let resourceList = this.state.resourceList;
+        let cycleQuota = this.state.cycleQuota;
+        const removedResource = _.remove(resources, (resource) => { return resource.name === name });
+        resourceList.push(removedResource[0]);
+        resourceList = _.sortBy(resourceList, 'name');
+        delete cycleQuota[name];
+        this.setState({resourceList: resourceList, resources: resources, cycleQuota: cycleQuota});
+    }
+
+    /**
+     * Function to call on change and blur events from input components
+     * @param {string} key 
+     * @param {any} value 
+     */
+    setCycleParams(key, value, type) {
+        let cycle = this.state.cycle;
+        switch(type) {
+            case 'NUMBER': {
+                cycle[key] = value?parseInt(value):0;
+                break;
+            }
+            default: {
+                cycle[key] = value;                
+                break;
+            }
+           
+        }
+        this.setState({cycle: cycle, validForm: this.validateForm(key)});
+    }
+
+    /**
+     * Callback Function to call from ResourceInputList on change and blur events
+     * @param {string} key 
+     * @param {InputEvent} event 
+     */
+    setCycleQuotaParams(key, event) {
+        let cycleQuota = this.state.cycleQuota;
+        if (event.target.value) {
+            let resource = _.find(this.state.resources, {'name': key});
+            
+            let newValue = 0;
+            if (this.resourceUnitMap[resource.quantity_value] && 
+                event.target.value.toString().indexOf(this.resourceUnitMap[resource.quantity_value].display)>=0) {
+                newValue = event.target.value.replace(this.resourceUnitMap[resource.quantity_value].display,'');
+            }   else {
+                newValue = event.target.value;
+            }
+            cycleQuota[key] = (newValue==="NaN" || isNaN(newValue))?0:newValue;
+        }   else {
+            let cycleQuota = this.state.cycleQuota;
+            cycleQuota[key] = 0;
+        }
+        this.setState({cycleQuota: cycleQuota});
+    }
+
+    /**
+     * 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.cycle[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.cycle[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;
+        }
+
+        if(this.state.cycle['start'] && this.state.cycle['stop']){
+            var isSameOrAfter = moment(this.state.cycle['stop']).isSameOrAfter(this.state.cycle['start']);
+            if(!isSameOrAfter){
+                errors['stop'] = ` Stop date can not be before Start date`;
+                validForm = false;
+            }else{
+                validForm = true;
+            }
+        }
+        return validForm;
+    }
+    
+    /**
+     * Function to call when 'Save' button is clicked to save the Cycle.
+     */
+    saveCycle() {
+        if (this.validateForm) {
+            let cycleQuota = [];
+            let cycle = this.state.cycle;
+            let stoptime =  _.replace(this.state.cycle['stop'],'00:00:00', '23:59:59');
+            cycle['start'] = moment(cycle['start']).format("YYYY-MM-DDTHH:mm:ss");
+            cycle['stop'] = moment(stoptime).format("YYYY-MM-DDTHH:mm:ss");
+            this.setState({cycle: cycle});
+            for (const resource in this.state.cycleQuota) {
+                let resourceType = _.find(this.state.resources, {'name': resource});
+                if(resourceType){
+                    let quota = { cycle: this.state.cycle.name,
+                        resource_type: resourceType['url'],
+                        value: this.state.cycleQuota[resource] * (this.resourceUnitMap[resourceType.quantity_value]?this.resourceUnitMap[resourceType.quantity_value].conversionFactor:1)};
+                    cycleQuota.push(quota);
+                }
+               
+            }
+            
+        CycleService.saveCycle(this.state.cycle, this.defaultResourcesEnabled?cycleQuota:[])
+            .then(cycle => {
+                if (cycle.url) {
+                    let dialog = {};
+                    if (this.defaultResourcesEnabled) {
+                        dialog = {header: 'Success', detail: 'Cycle saved successfully. Do you want to create another Cycle?'};
+                    }   else {
+                        dialog = {header: 'Success', detail: 'Cycle saved successfully with default Resource allocations. Do you want to view and edit them?'};
+                    }
+                    this.setState({cycle:cycle, dialogVisible: true, dialog: dialog})
+                }   else {
+                    this.growl.show({severity: 'error', summary: 'Error Occured', detail: 'Unable to save Cycle'});
+                    this.setState({errors: cycle});
+                }
+            });
+        }
+    }
+
+    /**
+     * Function to cancel form creation and navigate to other page/component
+     */
+    cancelCreate() {
+        this.setState({redirect: '/cycle'});
+    }
+
+    /**
+     * Reset function to be called to reset the form fields
+     */
+    reset() {
+        if (this.defaultResourcesEnabled) {
+            let prevResources = this.state.resources;
+            let resourceList = [];
+            let resources = [];
+            if (resources) {
+                const defaultResources = this.defaultResources;
+                resourceList = _.sortBy(prevResources.concat(this.state.resourceList), "name");
+                resources = _.remove(resourceList, function(resource) { return _.find(defaultResources, {'name': resource.name})!=null });
+            }
+            const cycleQuota = this.setCycleQuotaDefaults(resources);
+            this.setState({
+                dialog: { header: '', detail: ''},
+                cycle: {
+                    name: '',
+                    description: '',
+                    start: '',
+                    stop: '',
+                    projects: [],
+                    quota: [],  
+                },
+                cycleQuota: cycleQuota,
+                validFields: {},
+                validForm: false,
+                errors: {},
+                dialogVisible: false,
+                resources: resources,
+                resourceList: resourceList
+            });
+        }   else {
+            this.setState({redirect: `/cycle/edit/${this.state.cycle.name}`})
+        }
+    }
+
+    render() {
+        if (this.state.redirect) {
+            return <Redirect to={ {pathname: this.state.redirect} }></Redirect>
+        }
+        
+        return (
+            <React.Fragment>
+               { /*<div className="p-grid">
+                    <Growl ref={(el) => this.growl = el} />
+                
+                    <div className="p-col-10 p-lg-10 p-md-10">
+                        <h2>Cycle - Add</h2>
+                    </div>
+                    <div className="p-col-2 p-lg-2 p-md-2">
+                        <Link to={{ pathname: '/cycle'}} tite="Close Edit" style={{float: "right"}}>
+                            <i className="fa fa-window-close" style={{marginTop: "10px"}}></i>
+                        </Link>
+                    </div>
+                </div> */ }
+                <AppHeader location={this.props.location} actions={[{name: 'fa-window-close', props:{pathname: '/cycle' }}]}/>
+                { this.state.isLoading ? <AppLoader /> :
+                <>
+                <div>
+                    <div className="p-fluid">
+                        <div className="p-field p-grid" style={{display: 'none'}}>
+                            <label htmlFor="cycleId" className="col-lg-2 col-md-2 col-sm-12">URL </label>
+                            <div className="col-lg-4 col-md-4 col-sm-12">
+                                <input id="cycleId" data-testid="cycleId" value={this.state.cycle.url} />
+                            </div>
+                        </div>
+                        <div className="p-field p-grid">
+                            <label htmlFor="cycleName" 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 ?'input-error':''} id="cycleName" data-testid="name" 
+                                            tooltip="Enter name of the cycle" tooltipOptions={this.tooltipOptions} maxLength="128"
+                                            value={this.state.cycle.name} 
+                                            onChange={(e) => this.setCycleParams('name', e.target.value)}
+                                            onBlur={(e) => this.setCycleParams('name', e.target.value)}/>
+                                <label className={this.state.errors.name?"error":"info"}>
+                                    {this.state.errors.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 ?'input-error':''} rows={3} cols={30} 
+                                            tooltip="Short description of the cycle" tooltipOptions={this.tooltipOptions} maxLength="128"
+                                            data-testid="description" value={this.state.cycle.description} 
+                                            onChange={(e) => this.setCycleParams('description', e.target.value)}
+                                            onBlur={(e) => this.setCycleParams('description', e.target.value)}/>
+                                <label className={this.state.errors.description ?"error":"info"}>
+                                    {this.state.errors.description ? this.state.errors.description : "Max 255 characters"}
+                                </label>
+                            </div>
+                        </div>
+                         
+                        <div className="p-field p-grid">
+                            <label htmlFor="cycleName" className="col-lg-2 col-md-2 col-sm-12">Start Date <span style={{color:'red'}}>*</span></label>
+                            <div className="col-lg-3 col-md-3 col-sm-12">
+                                <Calendar
+ 				    d dateFormat="dd-M-yy"
+                                    value= {this.state.cycle.start}
+                                    onChange= {e => this.setCycleParams('start',e.value)}
+                                    onBlur= {e => this.setCycleParams('start',e.value)}
+                                    data-testid="start"
+                                    tooltip="Moment at which the cycle starts, that is, when its projects can run." tooltipOptions={this.tooltipOptions}
+				                    showIcon={true}
+                                />
+                               
+                                <label className={this.state.errors.start?"error":"info"}>
+                                    {this.state.errors.start ? this.state.errors.start : ""}
+                                </label>
+                            </div>
+                            <div className="col-lg-1 col-md-1 col-sm-12"></div>
+                            <label htmlFor="cycleName" className="col-lg-2 col-md-2 col-sm-12">Stop Date <span style={{color:'red'}}>*</span></label>
+                             <div className="col-lg-3 col-md-3 col-sm-12">
+                                <Calendar
+                                    d dateFormat="dd-M-yy"
+                                    value= {this.state.cycle.stop}
+                                    onChange= {e => this.setCycleParams('stop', e.value)}
+                                    onBlur= {e => this.setCycleParams('stop',e.value)}
+                                    data-testid="stop"
+                                    tooltip="Moment at which the cycle officially ends." tooltipOptions={this.tooltipOptions}
+                                    showIcon={true}
+                                />
+                                
+                                <label className={this.state.errors.stop?"error":"info"}>
+                                    {this.state.errors.stop ? this.state.errors.stop : ""}
+                                </label>
+                            </div>
+                        </div>
+
+                        {this.defaultResourcesEnabled && this.state.resourceList &&
+                            <div className="p-fluid">
+                                <div className="p-field p-grid">
+                                    <div className="col-lg-2 col-md-2 col-sm-12">
+                                        <h5 data-testid="resource_alloc">Resource Allocations</h5>
+                                    </div>
+                                    <div className="col-lg-3 col-md-3 col-sm-10">
+                                        <Dropdown optionLabel="name" optionValue="name" 
+                                            tooltip="Resources to be allotted for the cycle" 
+                                            tooltipOptions={this.tooltipOptions}
+                                            value={this.state.newResource} 
+                                            options={this.state.resourceList} 
+                                            onChange={(e) => {this.setState({'newResource': e.value})}}
+                                            placeholder="Add Resources" />
+                                    </div>
+                                    <div className="col-lg-2 col-md-2 col-sm-2">
+                                         <Button label="" className="p-button-primary" icon="pi pi-plus" onClick={this.addNewResource} data-testid="add_res_btn" />
+                                    </div>
+                                </div>
+                                <div className="p-field p-grid resource-input-grid">
+                                    <ResourceInputList list={this.state.resources} unitMap={this.resourceUnitMap} 
+                                                      cycleQuota={this.state.cycleQuota} callback={this.setCycleQuotaParams} 
+                                                      removeInputCallback={this.removeResource} />
+                                </div>
+                            </div>
+                        }
+                    </div>
+                </div>
+                <div className="p-grid p-justify-start act-btn-grp">
+                    <div className="p-col-1">
+                        <Button label="Save" className="p-button-primary" id="save-btn" data-testid="save-btn" icon="pi pi-check" onClick={this.saveCycle} disabled={!this.state.validForm} />
+                    </div>
+                     <div className="p-col-1">
+                        <Button label="Cancel" className="p-button-danger" icon="pi pi-times" onClick={this.cancelCreate}  />
+                    </div>
+                </div>
+                </>
+                }
+
+                {/* Dialog component to show messages and get input */}
+                <div className="p-grid" data-testid="confirm_dialog">
+                    <Dialog header={this.state.dialog.header} visible={this.state.dialogVisible} style={{width: '25vw'}} inputId="confirm_dialog"
+                            modal={true}  onHide={() => {this.setState({dialogVisible: false})}} 
+                            footer={<div>
+                                <Button key="back" onClick={() => {this.setState({dialogVisible: false}); this.cancelCreate();}} label="No" />
+                                <Button key="submit" type="primary" onClick={this.reset} label="Yes" />
+                                </div>
+                            } >
+                            <div className="p-grid">
+                                <div className="col-lg-2 col-md-2 col-sm-2">
+                                    <i className="pi pi-check-circle pi-large pi-success"></i>
+                                </div>
+                                <div className="col-lg-10 col-md-10 col-sm-10">
+                                    <span style={{marginTop:"5px"}}>{this.state.dialog.detail}</span>
+                                </div>
+                            </div>
+                    </Dialog>
+                </div>
+                
+            </React.Fragment>
+        );
+    }
+}
\ No newline at end of file
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/create.test.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/create.test.js
new file mode 100644
index 00000000000..d738a4a909a
--- /dev/null
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/create.test.js
@@ -0,0 +1,346 @@
+import React from 'react';
+import { BrowserRouter as Router } from 'react-router-dom';
+import { act } from "react-dom/test-utils";
+import { render, cleanup, fireEvent } from '@testing-library/react';
+import '@testing-library/jest-dom/extend-expect';
+
+import {CycleCreate} from './create';
+import CycleService from '../../services/cycle.service';
+
+import CycleServiceMock from '../../__mocks__/cycle.service.data';
+
+let saveCycleSpy, resourcesSpy, cycleResourceDefaultsSpy;
+
+beforeEach(() => {
+  setMockSpy();
+});
+
+afterEach(() => {
+  // cleanup on exiting
+  clearMockSpy();
+  cleanup();
+});
+
+/**
+ * To set mock spy for Services that have API calls to the back end to fetch data
+ */
+const setMockSpy = (() => {
+    
+    resourcesSpy = jest.spyOn(CycleService, 'getResources');
+    resourcesSpy.mockImplementation(() => {
+        return Promise.resolve(CycleServiceMock.resources);
+    });
+    
+    
+    saveCycleSpy = jest.spyOn(CycleService, 'saveCycle');
+    saveCycleSpy.mockImplementation((cycle, cycleQuota) => { 
+       cycle.url = `http://localhost:3000/api/cycle/${cycle.name}`;
+        return Promise.resolve(cycle)
+    });
+});
+
+const clearMockSpy = (() => {
+    saveCycleSpy.mockRestore();
+});
+
+it("renders without crashing with all back-end data loaded", async () => {
+    console.log("renders without crashing with all back-end data loaded ------------------------");
+    
+    let content;
+    await act(async () => {
+        content = render(<Router><CycleCreate /></Router>);
+    });
+    
+    expect(content.queryByText('Cycle - Add')).not.toBe(null);        // Page loaded successfully
+    expect(content.queryAllByText('Add Resources').length).toBe(2);     // Resource Dropdown loaded successfully
+    expect(content.queryByText('Support hours')).toBeInTheDocument();         // Resources other than Default Resources listed in dropdown
+    expect(content.queryByPlaceholderText('Support Hours')).toBe(null);       // No resources other than Default Resources listed to get input
+    expect(content.queryByPlaceholderText('LOFAR Observing Time').value).toBe('1 Hours');         // Default Resource Listed with default value
+});
+
+it("Save button disabled initially when no data entered", async () => {
+    console.log("Save button disabled initially when no data entered -----------------------");
+    let content;
+    await act(async () => {
+        content = render(<Router><CycleCreate /></Router>);
+    });
+    expect(content.queryByTestId('save-btn')).toHaveAttribute("disabled");
+});
+
+it("Save button enabled when mandatory data entered", async () => {
+    console.log("Save button enabled when mandatory data entered -----------------------");
+    let content;
+    await act(async () => {
+        content = render(<Router><CycleCreate /></Router>);
+    });
+    const nameInput = content.queryByTestId('name');
+    const descInput = content.queryByTestId('description');
+    const startInput = content.queryByTestId('start');
+    const stopInput = content.queryByTestId('stop');
+     
+    fireEvent.change(nameInput, { target: { value: 'Cycle-12' } });
+    expect(nameInput.value).toBe("Cycle-12");
+    
+    fireEvent.change(descInput, { target: { value: 'Cycle-12' } });
+    expect(descInput.value).toBe("Cycle-12");
+    
+    fireEvent.change(startInput, { target: { value: '2020-07-29 11:12:15' } });
+    expect(startInput.value).toBe("2020-07-29 11:12:15");
+    
+    fireEvent.change(stopInput, { target: { value: '2020-07-30 11:12:15' } });
+    expect(stopInput.value).toBe("2020-07-30 11:12:15");
+    expect(content.queryByTestId('save-btn').hasAttribute("disabled")).toBeFalsy();
+});
+
+it("renders Save button enabled when all data entered", async () => {
+    console.log("renders Save button enabled when all data entered -----------------------");
+    let content;
+    await act(async () => {
+        content = render(<Router><CycleCreate /></Router>);
+    });
+
+    const nameInput = content.queryByTestId('name');
+    const descInput = content.queryByTestId('description');
+    const startInput = content.queryByTestId('start');
+    const stopInput = content.queryByTestId('stop');
+     
+    fireEvent.change(nameInput, { target: { value: 'Cycle-12' } });
+    expect(nameInput.value).toBe("Cycle-12");
+    
+    fireEvent.change(descInput, { target: { value: 'Cycle-12' } });
+    expect(descInput.value).toBe("Cycle-12");
+    
+    fireEvent.change(startInput, { target: { value: '2020-07-29 11:12:15' } });
+    expect(startInput.value).toBe("2020-07-29 11:12:15");
+    
+    fireEvent.change(stopInput, { target: { value: '2020-07-30 11:12:15' } });
+    expect(stopInput.value).toBe("2020-07-30 11:12:15");
+    
+    expect(content.queryByTestId('save-btn').hasAttribute("disabled")).toBeFalsy();    
+    
+});
+
+it("save cycle with mandatory fields", async () => {
+    console.log("save cycle -----------------------");
+    let content;
+    await act(async () => {
+        content = render(<Router><CycleCreate /></Router>);
+    });
+
+    const nameInput = content.queryByTestId('name');
+    const descInput = content.queryByTestId('description');
+    const startInput = content.queryByTestId('start');
+    const stopInput = content.queryByTestId('stop');
+    
+    fireEvent.change(nameInput, { target: { value: 'Cycle-12' } });
+    expect(nameInput.value).toBe("Cycle-12");
+    fireEvent.change(descInput, { target: { value: 'Cycle-12' } });
+    expect(descInput.value).toBe("Cycle-12");
+
+    fireEvent.change(startInput, { target: { value: '2020-07-29 11:12:15' } });
+    expect(startInput.value).toBe("2020-07-29 11:12:15");
+    
+    fireEvent.change(stopInput, { target: { value: '2020-07-30 11:12:15' } });
+    expect(stopInput.value).toBe("2020-07-30 11:12:15");
+     
+    expect(content.queryByTestId('save-btn').hasAttribute("disabled")).toBeFalsy();
+    expect(content.queryByTestId('cycleId').value).toBe("");
+    expect(content.queryByText("Success")).toBe(null);
+    
+    await act(async () => {
+        fireEvent.click(content.queryByTestId('save-btn'));
+    });
+    
+    // After saving cycle, URL should be available and Success dialog should be displayed
+    expect(content.queryByTestId('cycleId').value).toBe("http://localhost:3000/api/cycle/Cycle-12");
+    expect(content.queryByText("Success")).not.toBe(null);
+});
+
+it("save cycle with default resources", async () => {
+    console.log("save cycle with default resources -----------------------");
+    let content;
+    await act(async () => {
+        content = render(<Router><CycleCreate /></Router>);
+    });
+
+    const nameInput = content.queryByTestId('name');
+    const descInput = content.queryByTestId('description');
+    const startInput = content.queryByTestId('start');
+    const stopInput = content.queryByTestId('stop');
+    
+    fireEvent.change(nameInput, { target: { value: 'Cycle-12' } });
+    expect(nameInput.value).toBe("Cycle-12");
+    fireEvent.change(descInput, { target: { value: 'Cycle-12' } });
+    expect(descInput.value).toBe("Cycle-12");
+
+    fireEvent.change(startInput, { target: { value: '2020-07-29 11:12:15' } });
+    expect(startInput.value).toBe("2020-07-29 11:12:15");
+    
+    fireEvent.change(stopInput, { target: { value: '2020-07-30 11:12:15' } });
+    expect(stopInput.value).toBe("2020-07-30 11:12:15");
+
+    expect(content.queryByTestId('save-btn').hasAttribute("disabled")).toBeFalsy();
+    expect(content.queryByTestId('cycleId').value).toBe("");
+    expect(content.queryByText("Success")).toBe(null);
+    
+    const lofarObsTimeInput = content.queryByPlaceholderText('LOFAR Observing Time');
+    fireEvent.change(lofarObsTimeInput, { target: { value: 10 } });
+    expect(lofarObsTimeInput.value).toBe('10');
+    
+    const lofarObsTimeAInput = content.queryByPlaceholderText('LOFAR Observing Time prio A');
+    fireEvent.change(lofarObsTimeAInput, { target: { value: 15 } });
+    expect(lofarObsTimeAInput.value).toBe('15');
+    
+    const lofarObsTimeBInput = content.queryByPlaceholderText('LOFAR Observing Time prio B');
+    fireEvent.change(lofarObsTimeBInput, { target: { value: 20 } });
+    expect(lofarObsTimeBInput.value).toBe('20');
+    
+    const cepProcTimeInput = content.queryByPlaceholderText('CEP Processing Time');
+    fireEvent.change(cepProcTimeInput, { target: { value: 5 } });
+    expect(cepProcTimeInput.value).toBe('5');
+    
+    const ltaStorageInput = content.queryByPlaceholderText('LTA Storage');
+    fireEvent.change(ltaStorageInput, { target: { value: 2 } });
+    expect(ltaStorageInput.value).toBe('2');
+    
+    const noOfTriggerInput = content.queryByPlaceholderText('Number of triggers');
+    fireEvent.change(noOfTriggerInput, { target: { value: 3 } });
+    expect(noOfTriggerInput.value).toBe('3');
+    
+    const lofarSupTimeInput = content.queryByPlaceholderText('LOFAR Support Time');
+    fireEvent.change(lofarSupTimeInput, { target: { value: 25 } });
+    expect(lofarSupTimeInput.value).toBe('25');
+    
+    await act(async () => {
+        fireEvent.click(content.queryByTestId('save-btn'));
+    });
+    
+    // After saving cycle, URL should be available and Success dialog should be displayed
+    expect(content.queryByTestId('cycleId').value).toBe("http://localhost:3000/api/cycle/Cycle-12");
+    expect(content.queryByText("Success")).not.toBe(null);
+});
+
+it("save cycle with added resources", async () => {
+    console.log("save cycle with added resources -----------------------");
+    let content;
+    await act(async () => {
+        content = render(<Router><CycleCreate /></Router>);
+    });
+
+    const nameInput = content.queryByTestId('name');
+    const descInput = content.queryByTestId('description');
+    const startInput = content.queryByTestId('start');
+    const stopInput = content.queryByTestId('stop');
+    
+    fireEvent.change(nameInput, { target: { value: 'Cycle-12' } });
+    expect(nameInput.value).toBe("Cycle-12");
+    fireEvent.change(descInput, { target: { value: 'Cycle-12' } });
+    expect(descInput.value).toBe("Cycle-12");
+
+    fireEvent.change(startInput, { target: { value: '2020-07-29 11:12:15' } });
+    expect(startInput.value).toBe("2020-07-29 11:12:15");
+    
+    fireEvent.change(stopInput, { target: { value: '2020-07-30 11:12:15' } });
+    expect(stopInput.value).toBe("2020-07-30 11:12:15");
+
+    expect(content.queryByTestId('save-btn').hasAttribute("disabled")).toBeFalsy();
+    expect(content.queryByTestId('cycleId').value).toBe("");
+    expect(content.queryByText("Success")).toBe(null);
+    
+    const lofarObsTimeInput = content.queryByPlaceholderText('LOFAR Observing Time');
+    fireEvent.change(lofarObsTimeInput, { target: { value: 10 } });
+    expect(lofarObsTimeInput.value).toBe('10');
+    
+    const lofarObsTimeAInput = content.queryByPlaceholderText('LOFAR Observing Time prio A');
+    fireEvent.change(lofarObsTimeAInput, { target: { value: 15 } });
+    expect(lofarObsTimeAInput.value).toBe('15');
+    
+    const lofarObsTimeBInput = content.queryByPlaceholderText('LOFAR Observing Time prio B');
+    fireEvent.change(lofarObsTimeBInput, { target: { value: 20 } });
+    expect(lofarObsTimeBInput.value).toBe('20');
+    
+    const cepProcTimeInput = content.queryByPlaceholderText('CEP Processing Time');
+    fireEvent.change(cepProcTimeInput, { target: { value: 5 } });
+    expect(cepProcTimeInput.value).toBe('5');
+    
+    const ltaStorageInput = content.queryByPlaceholderText('LTA Storage');
+    fireEvent.change(ltaStorageInput, { target: { value: 2 } });
+    expect(ltaStorageInput.value).toBe('2');
+    
+    const noOfTriggerInput = content.queryByPlaceholderText('Number of triggers');
+    fireEvent.change(noOfTriggerInput, { target: { value: 3 } });
+    expect(noOfTriggerInput.value).toBe('3');
+    
+    const lofarSupTimeInput = content.queryByPlaceholderText('LOFAR Support Time');
+    fireEvent.change(lofarSupTimeInput, { target: { value: 25 } });
+    expect(lofarSupTimeInput.value).toBe('25');
+    
+    // Before selecting New Resource
+    expect(content.queryAllByText('Add Resources').length).toBe(2);
+    expect(content.queryAllByText('Support hours').length).toBe(1);
+    expect(content.getAllByRole("listbox")[3].children.length).toBe(2);
+    expect(content.queryByPlaceholderText('Support hours')).toBe(null);
+    const addResourceInput = content.getAllByRole("listbox")[3].children[1] ;
+    fireEvent.click(addResourceInput);
+    // After selecting New Resource
+    expect(content.queryAllByText('Add Resources').length).toBe(1);
+    expect(content.queryAllByText('Support hours').length).toBe(3);
+
+    const addResourceBtn = content.queryByTestId('add_res_btn');
+    fireEvent.click(addResourceBtn);
+    expect(content.queryAllByText('Add Resources').length).toBe(2);
+    expect(content.queryByPlaceholderText('Support hours')).not.toBe(null);
+
+    const newResourceInput = content.queryByPlaceholderText('Support hours');
+    fireEvent.change(newResourceInput, { target: { value: 30 } });
+    expect(newResourceInput.value).toBe('30');
+    
+    
+    await act(async () => {
+        fireEvent.click(content.queryByTestId('save-btn'));
+    });
+    
+    // After saving cycle, URL should be available and Success dialog should be displayed
+    expect(content.queryByTestId('cycleId').value).toBe("http://localhost:3000/api/cycle/Cycle-12");
+    expect(content.queryByText("Success")).not.toBe(null);
+});
+
+it("remove default resource and added resource", async () => {
+    console.log("remove default resource and added resource -----------------------");
+    let content;
+    await act(async () => {
+        content = render(<Router><CycleCreate /></Router>);
+    });
+
+    // Before selecting New Resource
+    expect(content.queryAllByText('Add Resources').length).toBe(2);
+    expect(content.queryAllByText('Support hours').length).toBe(1);
+    expect(content.getAllByRole("listbox")[3].children.length).toBe(2);
+    expect(content.queryByPlaceholderText('Support hours')).toBe(null);
+    const addResourceInput = content.getAllByRole("listbox")[3].children[1] ;
+    fireEvent.click(addResourceInput);
+    // After selecting New Resource
+    expect(content.queryAllByText('Add Resources').length).toBe(1);
+    expect(content.queryAllByText('Support hours').length).toBe(3);
+
+    const addResourceBtn = content.queryByTestId('add_res_btn');
+    fireEvent.click(addResourceBtn);
+    expect(content.queryAllByText('Add Resources').length).toBe(2);
+    expect(content.queryByPlaceholderText('Support hours')).not.toBe(null);
+
+    expect(content.queryByPlaceholderText('CEP Processing Time')).not.toBe(null);
+    expect(content.queryByTestId('CEP Processing Time-btn')).not.toBe(null);
+    const removeDefResBtn = content.queryByTestId('CEP Processing Time-btn');
+    await act(async () => {
+        fireEvent.click(content.queryByTestId('CEP Processing Time-btn'));
+    });
+    expect(content.queryByPlaceholderText('CEP Processing Time')).toBe(null);
+    expect(content.queryByTestId('CEP Processing Time-btn')).toBe(null);
+
+    const removeResourceBtn = content.queryByTestId('Support hours-btn');
+    fireEvent.click(removeResourceBtn);
+    expect(content.queryAllByText('Add Resources').length).toBe(2);
+    expect(content.queryAllByText('Support hours').length).toBe(1);
+    expect(content.getAllByRole("listbox")[3].children.length).toBe(3);
+    
+});
\ No newline at end of file
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/edit.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/edit.js
new file mode 100644
index 00000000000..66e9b157cd3
--- /dev/null
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/edit.js
@@ -0,0 +1,507 @@
+import React, {Component} from 'react';
+import { Link, Redirect } from 'react-router-dom';
+import _ from 'lodash';
+import moment from 'moment'
+
+import {InputText} from 'primereact/inputtext';
+import {Calendar} from 'primereact/calendar';
+import {InputTextarea} from 'primereact/inputtextarea';
+import {Dropdown} from 'primereact/dropdown';
+import { Button } from 'primereact/button';
+import {Dialog} from 'primereact/components/dialog/Dialog';
+import {Growl} from 'primereact/components/growl/Growl';
+
+import {ResourceInputList} from './ResourceInputList';
+
+import AppLoader from '../../layout/components/AppLoader';
+import AppHeader from '../../layout/components/AppHeader';
+import CycleService from '../../services/cycle.service';
+import UnitConverter from '../../utils/unit.converter';
+import UIConstants from '../../utils/ui.constants';
+
+export class CycleEdit extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            isLoading: true,
+            dialog: { header: '', detail: ''},
+            cycle: {
+                projects: [],
+                quota: [],                         // Mandatory Field in the back end
+            },
+            cycleQuota: {},                       // Holds the value of resources selected with resource_type_id as key
+            validFields: {},                        // Holds the list of valid fields based on the form rules
+            validForm: false,                       // To enable Save Button
+            errors: {},
+            resources: [],                          // Selected resources for the cycle
+            resourceList: [],                       // Available resources to select for the cycle
+            redirect: this.props.match.params.id?"":'/cycle/list'     //If no cycle name passed redirect to Cycle list page
+        }
+        this.cycleQuota = []                      // Holds the old list of cycle_quota saved for the cycle
+        // Validation Rules
+        this.formRules = {
+            name: {required: true, message: "Name can not be empty"},
+            description: {required: true, message: "Description can not be empty"},
+            start: {required: true, message: "Start Date can not be empty"},
+            stop: {required: true, message: "Stop Date can not be empty"},
+        };
+        this.defaultResources = [
+            {name:'LOFAR Observing Time'}, 
+            {name:'LOFAR Observing Time prio A'}, 
+            {name:'LOFAR Observing Time prio B'},
+            {name:'LOFAR Processing time '}, 
+            {name:'LOFAR LTA resources'}, 
+            {name:'LOFAR LTA resources SARA'}, 
+            {name:'LOFAR LTA resources Jülich'}, 
+            {name:'LOFAR LTA resources Poznan'}, 
+            {name:'LOFAR Observing time DDT/Commissioning'}, 
+            {name:'LOFAR Support'}];
+        this.cycleResourceDefaults = {};
+        this.resourceUnitMap = UnitConverter.resourceUnitMap;
+        this.tooltipOptions = UIConstants.tooltipOptions;
+
+        this.getCycleDetails = this.getCycleDetails.bind(this);
+        this.cycleOptionTemplate = this.cycleOptionTemplate.bind(this);
+        this.setCycleQuotaDefaults = this.setCycleQuotaDefaults.bind(this);
+        this.setCycleParams = this.setCycleParams.bind(this);
+        this.addNewResource = this.addNewResource.bind(this);
+        this.removeResource = this.removeResource.bind(this);
+        this.setCycleQuotaParams = this.setCycleQuotaParams.bind(this);
+        this.saveCycle = this.saveCycle.bind(this);
+        this.saveCycleQuota = this.saveCycleQuota.bind(this);
+        this.cancelEdit = this.cancelEdit.bind(this);
+    }
+
+    componentDidMount() {
+        CycleService.getCycle(this.props.match.params.id)
+        .then(result =>{
+            this.setState({
+                cycle: result.data,
+                isLoading : false, 
+            })
+        })
+        .then(()=>{
+            CycleService.getResources()
+            .then(resourceList => {
+                this.setState({resourceList: resourceList});
+            })
+            .then((resourceList, resources) => {
+                this.getCycleDetails();
+            });
+        })
+    }
+
+    /**
+     * Function retrieve cycle details and resource allocations(cycle_quota) and assign to appropriate varaibles
+     */
+    async getCycleDetails() {
+        let cycle = this.state.cycle;
+        let resourceList = this.state.resourceList;
+        let cycleQuota = {};
+        if (cycle) {
+            // Get cycle_quota for the cycle and asssign to the component variable
+            for (const id of cycle.quota_ids) {
+                let quota = await CycleService.getCycleQuota(id);
+                let resource = _.find(resourceList, ['name', quota.resource_type_id]);
+                quota.resource = resource;
+                this.cycleQuota.push(quota);
+                const conversionFactor = this.resourceUnitMap[resource.quantity_value]?this.resourceUnitMap[resource.quantity_value].conversionFactor:1;
+                cycleQuota[quota.resource_type_id] = quota.value / conversionFactor;
+            };
+            // Remove the already assigned resources from the resoureList
+            const resources = _.remove(resourceList, (resource) => { return _.find(this.cycleQuota, {'resource_type_id': resource.name})!=null });
+            this.setState({cycle: cycle, resourceList: resourceList, resources: resources, 
+                            cycleQuota: cycleQuota, isLoading: false});
+
+            // Validate form if all values are as per the form rules and enable Save button
+            this.validateForm();
+        }   else {
+            this.setState({redirect: '../../not-found'});
+        }
+    }
+
+    /**
+     * Cycle option sub-component with cycle object
+     */
+    cycleOptionTemplate(option) {
+        return (
+            <div className="p-clearfix">
+                <span style={{fontSize:'1em',float:'right',margin:'1em .5em 0 0'}}>{option.name}</span>
+            </div>
+        );
+    }
+
+    /**
+     * Function to set cycle resource allocation
+     * @param {Array} resources 
+     */
+    setCycleQuotaDefaults(resources) {
+        let cycleQuota = this.state.cycleQuota;
+        for (const resource of resources) {
+            const conversionFactor = this.resourceUnitMap[resource.quantity_value]?this.resourceUnitMap[resource.quantity_value].conversionFactor:1;
+            cycleQuota[resource['name']] = this.cycleResourceDefaults[resource.name]/conversionFactor;
+        }
+        return cycleQuota;
+    }
+
+    /**
+     * Function to add new resource to cycle
+     */
+    addNewResource(){
+        if (this.state.newResource) {
+            let resourceList = this.state.resourceList;
+            const newResource = _.remove(resourceList, {'name': this.state.newResource});
+            let resources = this.state.resources?this.state.resources:[];
+            resources.push(newResource[0]);
+            this.setState({resources: resources, resourceList: resourceList, newResource: null});
+        }
+    }
+
+    /**
+     * Callback function to be called from ResourceInpulList when a resource is removed from it
+     * @param {string} name - resource_type_id
+     */
+    removeResource(name) {
+        let resources = this.state.resources;
+        let resourceList = this.state.resourceList;
+        let cycleQuota = this.state.cycleQuota;
+        const removedResource = _.remove(resources, (resource) => { return resource.name === name });
+        resourceList.push(removedResource[0]);
+        delete cycleQuota[name];
+        this.setState({resourceList: resourceList, resources: resources, cycleQuota: cycleQuota});
+    }
+
+    /**
+     * Function to call on change and blur events from input components
+     * @param {string} key 
+     * @param {any} value 
+     */
+    setCycleParams(key, value, type) {
+        let cycle = this.state.cycle;
+        switch(type) {
+            case 'NUMBER': {
+                cycle[key] = value?parseInt(value):0;
+                break;
+            }
+            default: {
+                cycle[key] = value;
+                break;
+            }
+        }
+        this.setState({cycle: cycle, validForm: this.validateForm(key)});
+    }
+
+    /**
+     * Callback Function to call from ResourceInputList on change and blur events
+     * @param {string} key 
+     * @param {InputEvent} event 
+     */
+    setCycleQuotaParams(key, event) {
+        let cycleQuota = this.state.cycleQuota;
+        if (event.target.value) {
+            let resource = _.find(this.state.resources, {'name': key});
+            let newValue = 0;
+            if (this.resourceUnitMap[resource.quantity_value] && 
+                event.target.value.toString().indexOf(this.resourceUnitMap[resource.quantity_value].display)>=0) {
+                newValue = event.target.value.replace(this.resourceUnitMap[resource.quantity_value].display,'');
+            }   else {
+                newValue = event.target.value;
+            }
+            cycleQuota[key] = (newValue==="NaN" || isNaN(newValue))?0:newValue;
+        }   else {
+            let cycleQuota = this.state.cycleQuota;
+            cycleQuota[key] = 0;
+        }
+        this.setState({cycleQuota: cycleQuota});
+    }
+
+    /**
+     * 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.cycle[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.cycle[fieldName];
+                if (rule.required) {
+                    if (!fieldValue) {
+                        errors[fieldName] = rule.message?rule.message:`${fieldName} is required`;
+                    }   else {
+                        validFields[fieldName] = true;
+                    }
+                }
+            }
+        }
+        
+        if (Object.keys(validFields).length === Object.keys(this.formRules).length) {
+            validForm = true;
+        }
+
+        if(this.state.cycle['start'] && this.state.cycle['stop']){
+            var isSameOrAfter = moment(this.state.cycle['stop']).isSameOrAfter(this.state.cycle['start']);
+            if(!isSameOrAfter){
+                errors['stop'] = ` Stop date should be after Start date`;
+                validForm = false;
+            }else{
+                validForm = true;
+            }
+        }
+
+        this.setState({errors: errors, validFields: validFields, validForm: validForm});
+        return validForm;
+    }
+    
+    /**
+     * Function to call when 'Save' button is clicked to update the cycle.
+     */
+    saveCycle() {
+        if (this.validateForm) {
+            let cycle = this.state.cycle;
+            let stoptime =  _.replace(this.state.cycle['stop'],'00:00:00', '23:59:59');
+            cycle['start'] = moment(this.state.cycle['start']).format("YYYY-MM-DDTHH:mm:ss");
+            cycle['stop'] = moment(stoptime).format("YYYY-MM-DDTHH:mm:ss");
+            this.setState({cycle: cycle});
+            CycleService.updateCycle(this.props.match.params.id, this.state.cycle)
+                .then(async (cycle) => { 
+                    if (cycle && this.state.cycle.updated_at !== cycle.updated_at) {
+                        this.saveCycleQuota(cycle);
+                    }   else {
+                        this.growl.show({severity: 'error', summary: 'Error Occured', detail: 'Unable to update Cycle'});
+                        this.setState({errors: cycle});
+                    }
+                });
+        }
+    }
+
+    /**
+     * Function to Create, Update & Delete cycle_quota for the cycle
+     */
+    async saveCycleQuota(cycle) {
+        let dialog = {};
+        let quotaError = {};
+        let updatingCycleQuota = [];
+        let newCycleQuota = [];
+        let deletingCycleQuota = [];
+        for (const resource in this.state.cycleQuota) {
+            const resourceType = _.find(this.state.resources, {'name': resource});
+            const conversionFactor = this.resourceUnitMap[resourceType.quantity_value]?this.resourceUnitMap[resourceType.quantity_value].conversionFactor:1
+            let quotaValue = this.state.cycleQuota[resource] * conversionFactor;
+            let existingQuota = _.find(this.cycleQuota, {'resource_type_id': resource});
+            if (!existingQuota) {
+                let quota = { cycle: cycle.url,
+                                resource_type: resourceType['url'],
+                                value: quotaValue };
+                newCycleQuota.push(quota);
+            } else if (existingQuota && existingQuota.value !== quotaValue) {
+                existingQuota.cycle = cycle.url;
+                existingQuota.value = quotaValue;
+                updatingCycleQuota.push(existingQuota);
+            }
+        }
+        let cycleQuota = this.state.cycleQuota;
+        deletingCycleQuota = _.filter(this.cycleQuota, function(quota) { return !cycleQuota[quota.resource_type_id]});
+        
+        for (const cycleQuota of deletingCycleQuota) {
+            const deletedCycleQuota = await CycleService.deleteCycleQuota(cycleQuota);
+            if (!deletedCycleQuota) {
+                quotaError[cycleQuota.resource_type_id] = true;
+            }
+        }
+        for (const cycleQuota of updatingCycleQuota) {
+            const updatedCycleQuota = await CycleService.updateCycleQuota(cycleQuota);
+            if (!updatedCycleQuota) {
+                quotaError[cycleQuota.resource_type_id] = true;
+            }
+        }
+        for (const cycleQuota of newCycleQuota) {
+            const createdCycleQuota = await CycleService.saveCycleQuota(cycleQuota);
+            if (!createdCycleQuota) {
+                quotaError[cycleQuota.resource_type_id] = true;
+            }
+        }
+        if (_.keys(quotaError).length === 0) {
+            dialog = {header: 'Success', detail: 'Cycle updated successfully.'};
+        }   else {
+            dialog = {header: 'Error', detail: 'Cycle updated successfully but resource allocation not updated properly. Try again!'};
+        }
+        this.setState({dialogVisible: true, dialog: dialog});
+    }
+
+    /**
+     * Cancel edit and redirect to Cycle View page
+     */
+    cancelEdit() {
+        this.setState({redirect: `/cycle/view/${this.state.cycle.name}`});
+    }
+
+    render() {
+        if (this.state.redirect) {
+            return <Redirect to={ {pathname: this.state.redirect} }></Redirect>
+        }
+        return (
+            <React.Fragment>
+                {/*} <div className="p-grid">
+                    <Growl ref={(el) => this.growl = el} />
+                
+                    <div className="p-col-10 p-lg-10 p-md-10">
+                        <h2>Cycle - Edit</h2>
+                    </div>
+                    <div className="p-col-2 p-lg-2 p-md-2">
+                        <Link to={{ pathname: `/cycle/view/${this.state.cycle.name}`}} title="Close Edit" style={{float: "right"}}>
+                            <i className="fa fa-window-close" style={{marginTop: "10px"}}></i>
+                        </Link>
+                    </div>
+                </div> */}
+                <AppHeader location={this.props.location} actions={[{name: 'fa-window-close', props:{ pathname: `/cycle/view/${this.state.cycle.name}`}}]}/>
+
+                { this.state.isLoading ? <AppLoader/> :
+                <>
+                <div>
+                    <div className="p-fluid">
+                        <div className="p-field p-grid">
+                            <label htmlFor="cycleName" 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 ?'input-error':''} id="cycleName" data-testid="name"
+                                            tooltip="Enter name of the cycle" tooltipOptions={this.tooltipOptions} maxLength="128"
+                                            value={this.state.cycle.name} 
+                                            onChange={(e) => this.setCycleParams('name', e.target.value)}
+                                            onBlur={(e) => this.setCycleParams('name', e.target.value)}/>
+                                <label className={this.state.errors.name?"error":"info"}>
+                                    {this.state.errors.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 ?'input-error':''} rows={3} cols={30} 
+                                            tooltip="Short description of the cycle" tooltipOptions={this.tooltipOptions} maxLength="128"
+                                            data-testid="description" value={this.state.cycle.description} 
+                                            onChange={(e) => this.setCycleParams('description', e.target.value)}
+                                            onBlur={(e) => this.setCycleParams('description', e.target.value)}/>
+                                <label className={this.state.errors.description ?"error":"info"}>
+                                    {this.state.errors.description ? this.state.errors.description : "Max 255 characters"}
+                                </label>
+                            </div>
+                        </div>
+                        
+                        <div className="p-field p-grid"> 
+                            <label htmlFor="cycleName" className="col-lg-2 col-md-2 col-sm-12">Start Date <span style={{color:'red'}}>*</span></label>
+                            <div className="col-lg-3 col-md-3 col-sm-12">
+                                <Calendar  
+                                    d dateFormat="dd-M-yy"
+                                    inputId="start"
+                                    value= {new Date(this.state.cycle.start)}
+                                    onChange= {e => this.setCycleParams('start',e.value)}
+                                    onBlur= {e => this.setCycleParams('start',e.value)}
+                                    data-testid="start" 
+                                    tooltip="Moment at which the cycle starts, that is, when its projects can run." tooltipOptions={this.tooltipOptions}
+                                    showIcon={true} 
+                                />
+                                <label className={this.state.errors.start?"error":"info"}>
+                                    {this.state.errors.start ? this.state.errors.start : ""}
+                                </label>
+                            </div>
+                            <div className="col-lg-1 col-md-1 col-sm-12"></div>
+                            <label htmlFor="cycleName" className="col-lg-2 col-md-2 col-sm-12">Stop Date <span style={{color:'red'}}>*</span></label>
+                            <div className="col-lg-3 col-md-3 col-sm-12">
+                                <Calendar
+                                    d dateFormat="dd-M-yy"
+                                    value= {new Date(this.state.cycle.stop)}
+                                    onChange= {e => this.setCycleParams('stop', e.value)}
+                                    onBlur= {e => this.setCycleParams('stop',e.value)}
+                                    inputId="stop"
+                                    data-testid="stop"
+                                    tooltip="Moment at which the cycle officially ends." tooltipOptions={this.tooltipOptions}
+                                    showIcon={true}
+                                />
+                                <label className={this.state.errors.stop?"error":"info"}>
+                                    {this.state.errors.stop ? this.state.errors.stop : ""}
+                                </label>
+                            </div>
+                        </div>
+
+                        {this.state.resourceList &&
+                            <div className="p-fluid">
+                                <div className="p-field p-grid">
+                                    <div className="col-lg-2 col-md-2 col-sm-12">
+                                        <h5>Resource Allocations:</h5>
+                                    </div>
+                                    <div className="col-lg-3 col-md-3 col-sm-10">
+                                        <Dropdown optionLabel="name" optionValue="name" 
+                                            tooltip="Resources to be allotted for the cycle" 
+                                            tooltipOptions={this.tooltipOptions}
+                                            value={this.state.newResource} 
+                                            options={_.sortBy(this.state.resourceList, ['name'])} 
+                                            onChange={(e) => {this.setState({'newResource': e.value})}}
+                                            placeholder="Add Resources" />
+                                    </div>
+                                    <div className="col-lg-2 col-md-2 col-sm-2">
+                                    <Button label="" className="p-button-primary" icon="pi pi-plus" onClick={this.addNewResource} disabled={!this.state.newResource} data-testid="add_res_btn" />
+                                    </div>
+                                </div>
+                                 {/* {_.keys(this.state.cycleQuota).length>0 &&  */}
+                                    <div className="p-field p-grid resource-input-grid">
+                                        <ResourceInputList list={this.state.resources} unitMap={this.resourceUnitMap} 
+                                                        cycleQuota={this.state.cycleQuota} callback={this.setCycleQuotaParams} 
+                                                        removeInputCallback={this.removeResource} />
+                                    </div>
+                                 {/* } */}
+                            </div>
+                        }
+                    </div>
+                </div>
+                <div className="p-grid p-justify-start act-btn-grp">
+                    <div className="p-col-1">
+                        <Button label="Save" className="p-button-primary" id="save-btn" data-testid="save-btn" icon="pi pi-check" onClick={this.saveCycle} disabled={!this.state.validForm} />
+                    </div>
+                    <div className="p-col-1">
+                        <Button label="Cancel" className="p-button-danger" icon="pi pi-times" onClick={this.cancelEdit}  />
+                    </div>
+                </div>
+
+                </>
+                }
+                {/* Dialog component to show messages and get input */}
+                <div className="p-grid" data-testid="confirm_dialog">
+                    <Dialog header={this.state.dialog.header} visible={this.state.dialogVisible} style={{width: '30vw'}} inputId="confirm_dialog"
+                            modal={true}  onHide={() => {this.setState({dialogVisible: false})}} 
+                            footer={<div>
+                                <Button key="back" onClick={() => {this.setState({dialogVisible: false}); this.cancelEdit();}} label="Ok" />
+                                {/* <Button key="submit" type="primary" onClick={this.reset} label="Yes" /> */}
+                                </div>
+                            } >
+                            <div className="p-grid">
+                                <div className="col-lg-2 col-md-2 col-sm-2">
+                                    <i className="pi pi-check-circle pi-large pi-success"></i>
+                                </div>
+                                <div className="col-lg-10 col-md-10 col-sm-10">
+                                    <span style={{marginTop:"5px"}}>{this.state.dialog.detail}</span>
+                                </div>
+                            </div>
+                    </Dialog>
+                </div>
+            </React.Fragment>
+        );
+    }
+}
\ No newline at end of file
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/index.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/index.js
new file mode 100644
index 00000000000..a52436177a7
--- /dev/null
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/index.js
@@ -0,0 +1,6 @@
+import CycleList from './list';
+import {CycleCreate} from './create';
+import {CycleView} from './view';
+import {CycleEdit} from './edit';
+
+export {CycleList, CycleCreate, CycleView, CycleEdit};
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/list.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/list.js
new file mode 100644
index 00000000000..71705d8f70c
--- /dev/null
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/list.js
@@ -0,0 +1,160 @@
+import React, { Component } from 'react'
+import 'primeflex/primeflex.css';
+import { Link } from 'react-router-dom/cjs/react-router-dom.min';
+import _ from 'lodash';
+
+import ViewTable from '../../components/ViewTable';
+import CycleService from '../../services/cycle.service';
+import UnitConversion from '../../utils/unit.converter';
+import AppLoader from '../../layout/components/AppLoader';
+import AppHeader from '../../layout/components/AppHeader';
+
+class CycleList extends Component{
+	 constructor(props){
+        super(props)
+        this.state = {
+            cyclelist: [],
+            paths: [{
+                "View": "/cycle/view",
+            }],
+            isLoading: true
+        }
+        this.projectCategory = ['regular', 'user_shared_support'];
+        this.periodCategory = ['long_term'];
+        this.defaultcolumns = [ {   id:"Cycle Code",
+                                    start:"Start Date",
+                                    stop: "End Date",
+                                    duration: "Duration (Days)",
+                                    totalProjects: 'No.of Projects',
+                                    observingTime: 'Lofar Observing Time (Hrs)',
+                                    processingTime: 'Lofar Processing Time (Hrs)',
+                                    ltaResources: 'Lofar LTA Resources(TB)',
+                                    support: 'Lofar Support (Hrs)',
+                                    longterm : 'Long Term Projects' } ];
+        this.optionalcolumns = [{   regularProjects: 'No.of Regular Projects',
+                                    observingTimeDDT: 'Lofar Observing Time Commissioning (Hrs)',
+                                    observingTimePrioA: 'Lofar Observing Time Prio A (Hrs)',
+                                    observingTimePrioB: 'Lofar Observing Time Prio B (Hrs)',
+                                    actionpath: "actionpath", }];
+
+        this.columnclassname = [{   "Cycle Code":"filter-input-75",
+                                    "Duration (Days)" : "filter-input-50",
+                                    "No.of Projects" : "filter-input-50",
+                                    "Lofar Observing Time (Hrs)" : "filter-input-75",
+                                    "Lofar Processing Time (Hrs)" : "filter-input-75",
+                                    "Lofar LTA Resources(TB)" : "filter-input-75",
+                                    "Lofar Support (Hrs)" : "filter-input-50",
+                                    "Long Term Projects" : "filter-input-50",
+                                    "No.of Regular Projects" : "filter-input-50",
+                                    "Lofar Observing Time Commissioning (Hrs)" : "filter-input-75",
+                                    "Lofar Observing Time Prio A (Hrs)" : "filter-input-75",
+                                    "Lofar Observing Time Prio B (Hrs)" : "filter-input-75" }];
+    }
+
+    getUnitConvertedQuotaValue(cycle, cycleQuota, resourceName) {
+        const quota = _.find(cycleQuota, {'cycle_id': cycle.name, 'resource_type_id': resourceName});
+        let ref = this.state.resources.find(i => i.name === resourceName)
+        const unitQuantity =(ref)?ref.quantity_value:0
+        return UnitConversion.getUIResourceUnit(unitQuantity, quota?quota.value:0);
+    }
+
+    getCycles(cycles = [], cycleQuota) {
+        const promises = [];
+        cycles.map(cycle => promises.push(CycleService.getCycleById(cycle.name)));
+        Promise.all(promises).then(responses => {
+            const results = cycles;
+            results.map(async (cycle, index) => {
+                const projects = responses[index];
+                const regularProjects = projects.filter(project => this.projectCategory.includes(project.project_category_value));
+                const longterm = projects.filter(project => this.periodCategory.includes(project.period_category_value));
+                cycle.duration = UnitConversion.getUIResourceUnit('days', cycle.duration);
+                cycle.totalProjects = cycle.projects ? cycle.projects.length : 0;
+                cycle.id = cycle.name ;
+                cycle.regularProjects = regularProjects.length;
+                cycle.longterm = longterm.length;
+                // cycle.observingTime = this.getUnitConvertedQuotaValue(cycle, cycleQuota, 'observing_time');
+                // cycle.processingTime = this.getUnitConvertedQuotaValue(cycle, cycleQuota, 'cep_processing_time');
+                // cycle.ltaResources = this.getUnitConvertedQuotaValue(cycle, cycleQuota, 'lta_storage');
+                // cycle.support = this.getUnitConvertedQuotaValue(cycle, cycleQuota, 'support_time');
+                // cycle.observingTimeDDT = this.getUnitConvertedQuotaValue(cycle, cycleQuota, 'observing_time_commissioning');
+                // cycle.observingTimePrioA = this.getUnitConvertedQuotaValue(cycle, cycleQuota, 'observing_time_prio_a');
+                // cycle.observingTimePrioB = this.getUnitConvertedQuotaValue(cycle, cycleQuota, 'observing_time_prio_b');
+                cycle.observingTime = this.getUnitConvertedQuotaValue(cycle, cycleQuota, 'LOFAR Observing Time');
+                cycle.processingTime = this.getUnitConvertedQuotaValue(cycle, cycleQuota, 'CEP Processing Time');
+                cycle.ltaResources = this.getUnitConvertedQuotaValue(cycle, cycleQuota, 'LTA Storage');
+                cycle.support = this.getUnitConvertedQuotaValue(cycle, cycleQuota, 'LOFAR Support Time');
+                cycle.observingTimeDDT = this.getUnitConvertedQuotaValue(cycle, cycleQuota, 'LOFAR Observing Time Commissioning');
+                cycle.observingTimePrioA = this.getUnitConvertedQuotaValue(cycle, cycleQuota, 'LOFAR Observing Time prio A');
+                cycle.observingTimePrioB = this.getUnitConvertedQuotaValue(cycle, cycleQuota, 'LOFAR Observing Time prio B');
+                
+                cycle['actionpath'] = `/cycle/view/${cycle.id}`;
+                return cycle;
+            });
+            this.setState({
+                cyclelist : results,
+                isLoading: false
+            });
+        });
+    }
+
+    componentDidMount(){ 
+        const promises = [CycleService.getAllCycleQuotas(), CycleService.getResources()]
+        Promise.all(promises).then(responses => {
+            const cycleQuota = responses[0];
+            this.setState({ resources: responses[1] });
+            CycleService.getAllCycles().then(cyclelist => {
+                this.getCycles(cyclelist, cycleQuota)
+            });
+        });  
+    }
+	
+	render(){
+        return (
+            <>
+           { /*<div className="p-grid">
+                    <div className="p-col-10 p-lg-10 p-md-10">
+                        <h2>Cycle - List </h2>
+                    </div>
+                    <div className="p-col-2 p-lg-2 p-md-2">
+                        <Link to={{ pathname: '/cycle/create'}} title="Add New Cycle" style={{float: "right"}}>
+                            <i className="fa fa-plus-square" style={{marginTop: "10px"}}></i>
+                        </Link>
+                    </div>
+                </div> */}
+                {/*
+                    * Call View table to show table data, the parameters are,
+                    data - Pass API data
+                    defaultcolumns - This colum will be populate by default in table with header mentioned
+                    showaction - {true/false} -> to show the action column
+                    paths - specify the path for navigation - Table will set "id" value for each row in action button
+                */}
+                <AppHeader location={this.props.location} actions={[{name: 'fa-plus-square', props:{ pathname: '/cycle/create'}}]}/>
+                {/*
+                    * Call View table to show table data, the parameters are,
+                    data - Pass API data
+                    defaultcolumns - This colum will be populate by default in table with header mentioned
+                    showaction - {true/false} -> to show the action column
+                    paths - specify the path for navigation - Table will set "id" value for each row in action button
+                */}
+                 
+                {this.state.isLoading? <AppLoader /> : (this.state.cyclelist && this.state.cyclelist.length) ?
+                
+                    <ViewTable 
+                        data={this.state.cyclelist} 
+                        defaultcolumns={this.defaultcolumns} 
+                        optionalcolumns={this.optionalcolumns}
+                        columnclassname = {this.columnclassname}
+                        showaction="true"
+                        paths={this.state.paths}
+                 />  : <></>
+                 } 
+                
+
+                
+            </>
+        )
+    }
+}
+
+export default CycleList
+
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/list.test.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/list.test.js
new file mode 100644
index 00000000000..36858e8cacf
--- /dev/null
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/list.test.js
@@ -0,0 +1,69 @@
+import "babel-polyfill";
+import React from 'react';
+import { MemoryRouter } from 'react-router-dom';
+import { render, fireEvent } from '@testing-library/react';
+import CycleList from './list';
+import UnitConversion from '../../utils/unit.converter';
+import CycleServiceMock from '../../__mocks__/cycle.service.data';
+
+jest.mock('../../services/cycle.service', () => {
+    return {
+        getProjects: () => Promise.resolve({ data: CycleServiceMock.getProjects }),
+        getCycleQuota: () => Promise.resolve({ data: CycleServiceMock.getCycleQuota }),
+        getAllCycles: () => Promise.resolve(CycleServiceMock.getAllCycle.results ),
+        getResources: () => Promise.resolve({ data: CycleServiceMock.getresources })
+    }
+});
+
+const flushPromises = () => new Promise(setImmediate);
+
+describe('<CycleList />', () => {
+    test('render table in the cycle list', async () => {
+        const { container } = render(<MemoryRouter><CycleList /></MemoryRouter>);
+        await flushPromises();
+        expect(container.querySelector('table')).toBeInTheDocument();
+    });
+
+    test('render cycle list in row', async () => {
+        const { container } = render(<MemoryRouter><CycleList /></MemoryRouter>);
+        await flushPromises();
+        expect(container.querySelectorAll('tr').length).toBe(4);
+    });
+
+    test('render columns in the cycle list', async () => {
+        const { container } = render(<MemoryRouter><CycleList /></MemoryRouter>);
+        await flushPromises();
+        expect(container.querySelectorAll('th').length).toBe(11);
+    });
+
+    test('render cycleId - cycle name conversion', async () => {
+        const { container } = render(<MemoryRouter><CycleList /></MemoryRouter>);
+        await flushPromises();
+        expect(container.querySelectorAll('tr')[1].innerHTML.includes('Cycle00')).toBeTruthy();
+    });
+
+    test('render observing time in hours', async () => {
+        const { container } = render(<MemoryRouter><CycleList /></MemoryRouter>);
+        await flushPromises();
+        const observing_time = Math.floor(Number(CycleServiceMock.getCycleQuota.results[0].value) / 3600);
+        expect(container.querySelectorAll('tr')[1].innerHTML.includes(observing_time)).toBeTruthy();
+    });
+
+    test('render commissioning time in hours', async () => {
+        const { container } = render(<MemoryRouter><CycleList /></MemoryRouter>);
+        await flushPromises();
+        const commissioning_time = UnitConversion.getUIResourceUnit('bytes',Number(CycleServiceMock.getCycleQuota.results[1].value));
+        expect(container.querySelectorAll('tr')[1].innerHTML.includes(commissioning_time)).toBeTruthy();
+    });
+
+    test('toggle columns in table', async () => {
+        const { container } = render(<MemoryRouter><CycleList /></MemoryRouter>);
+        await flushPromises();
+        const panel = container.querySelector('#overlay_panel');
+        expect(panel).toHaveStyle('display: block');
+        fireEvent.click(container.querySelector('.col-filter-btn'));
+        await flushPromises();
+        expect(panel).toHaveStyle('display: none');
+        expect(container.querySelectorAll("input[type=checkbox]:checked").length).toBe(container.querySelectorAll('th').length)
+    });
+});
\ No newline at end of file
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/view.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/view.js
new file mode 100644
index 00000000000..ef1c35cd5cd
--- /dev/null
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/view.js
@@ -0,0 +1,143 @@
+import React, {Component} from 'react';
+import {Link, Redirect} from 'react-router-dom'
+import moment from 'moment';
+import _ from 'lodash';
+
+import { Chips } from 'primereact/chips';
+
+import ResourceDisplayList from './ResourceDisplayList';
+
+import AppLoader from '../../layout/components/AppLoader';
+import AppHeader from '../../layout/components/AppHeader';
+import CycleService from '../../services/cycle.service';
+import UnitConverter from '../../utils/unit.converter';
+
+/**
+ * Component to view the details of a cycle
+ */
+export class CycleView extends Component {
+    DATE_FORMAT = 'YYYY-MMM-DD HH:mm:ss';
+    constructor(props) {
+        super(props);
+        this.state = {
+            isLoading: true,
+            cycle:'',
+        };
+        if (this.props.match.params.id) {
+            this.state.cycleId  = this.props.match.params.id;
+        }   else if (this.props.location.state && this.props.location.state.id) {
+            this.state.cycleId = this.props.location.state.id;
+        }
+        this.state.redirect = this.state.cycleId?"":'/cycle'         // If no cycle id is passed, redirect to cycle list page
+        this.resourceUnitMap = UnitConverter.resourceUnitMap;       // Resource unit conversion factor and constraints
+    }
+
+    componentDidMount() {
+        const cycleId = this.state.cycleId;
+        if (cycleId) {
+            this.getCycleDetails();
+        }   else {
+            this.setState({redirect: "/not-found"});
+        }
+    }
+
+    /**
+     * To get the cycle details from the backend using the service
+     * 
+     */
+    async getCycleDetails() {
+        let cycle = await CycleService.getCycleDetails(this.state.cycleId);
+        let cycleQuota = [];
+        let resources = [];
+
+        if (cycle) {
+            // If resources are allocated for the cycle quota fetch the resources master from the API
+            if (cycle.quota) {
+                resources = await CycleService.getResources();
+            }
+
+            // For every cycle quota, get the resource type & assign to the resource variable of the quota object
+            for (const id of cycle.quota_ids) {
+                let quota = await CycleService.getCycleQuota(id);
+                let resource = _.find(resources, ['name', quota.resource_type_id]);
+                quota.resource = resource;
+                cycleQuota.push(quota);
+            };
+            this.setState({cycle: cycle, cycleQuota: cycleQuota, isLoading: false});
+        }   else {
+            this.setState({redirect: "../../not-found"})
+        }
+        
+    }
+
+    render() {
+        if (this.state.redirect) {
+            return <Redirect to={ {pathname: this.state.redirect} }></Redirect>
+        }
+        
+        return (
+            <React.Fragment>
+               {/* <div className="p-grid">
+                    <div className="p-col-10 p-lg-10 p-md-10">
+                        <h2>Cycle - Details </h2>
+                    </div>
+                    { this.state.cycle &&
+                    <div className="p-col-2 p-lg-2 p-md-2">
+                        <Link to={{ pathname: `/cycle`}} title="Close View" style={{float: "right"}}>
+                            <i className="fa fa-times" style={{marginTop: "10px", marginLeft: "5px"}}></i>
+                        </Link>
+                        <Link to={{ pathname: `/cycle/edit/${this.state.cycle.name}`, state: {id: this.state.cycle?this.state.cycle.name:''}}} title="Edit Cycle" 
+                                 style={{float: "right"}}>
+                            <i className="fa fa-edit" style={{marginTop: "10px"}}></i>
+                        </Link>
+                    </div>
+                    }
+                </div> */ }
+                <AppHeader location={this.props.location} actions={[{name: 'fa-edit', props:{ pathname: `/cycle/edit/${this.state.cycle.name}`, state: {id: this.state.cycle?this.state.cycle.name:''}}},{name: 'fa-times',props:{ pathname: `/cycle`}}]}/>
+                { this.state.isLoading && <AppLoader /> }
+                { this.state.cycle &&
+                    <React.Fragment>
+                        <div className="main-content">
+                            <div className="p-grid">
+                                <label className="col-lg-2 col-md-2 col-sm-12">Name</label>
+                                <span className="col-lg-4 col-md-4 col-sm-12">{this.state.cycle.name}</span>
+                                <label className="col-lg-2 col-md-2 col-sm-12">Description</label>
+                                <span className="col-lg-4 col-md-4 col-sm-12">{this.state.cycle.description}</span>
+                            </div>
+                            <div className="p-grid">
+                                <label className="col-lg-2 col-md-2 col-sm-12">Created At</label>
+                                <span className="col-lg-4 col-md-4 col-sm-12">{moment.utc(this.state.cycle.created_at).format(this.DATE_FORMAT)}</span>
+                                <label className="col-lg-2 col-md-2 col-sm-12">Updated At</label>
+                                <span className="col-lg-4 col-md-4 col-sm-12">{moment.utc(this.state.cycle.updated_at).format(this.DATE_FORMAT)}</span>
+                            </div>
+                            
+                            <div className="p-grid">
+                                <label className="col-lg-2 col-md-2 col-sm-12">Projects</label>
+                                <Chips className="col-lg-4 col-md-4 col-sm-12 chips-readonly" disabled value={this.state.cycle.projects_ids}></Chips>
+                            </div>
+                            <div className="p-fluid">
+                                <div className="p-field p-grid">
+                                    <div className="col-lg-3 col-md-3 col-sm-12">
+                                        <h5 data-testid="resource_alloc">Resource Allocations</h5>
+                                    </div>
+                                </div>
+                            </div>
+                            {this.state.cycleQuota.length===0 && 
+                                <div className="p-field p-grid">
+                                    <div className="col-lg-12 col-md-12 col-sm-12">
+                                        <span>Reosurces not yet allocated. 
+                                            <Link to={{ pathname: `/cycle/edit/${this.state.cycle.name}`, state: {id: this.state.cycle?this.state.cycle.name:''}}} title="Edit Cycle" > Click</Link> to add.
+                                        </span>
+                                    </div>
+                                </div>
+                            }
+                            <div className="p-field p-grid resource-input-grid">
+                                <ResourceDisplayList cycleQuota={this.state.cycleQuota}  unitMap={this.resourceUnitMap} />
+                            </div>
+                        </div>
+                    </React.Fragment>
+                }
+            </React.Fragment>
+        );
+    }
+}
\ No newline at end of file
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/create.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/create.js
index e400bf2f3d5..bfa99e4d328 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/create.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/create.js
@@ -15,6 +15,7 @@ import {Growl} from 'primereact/components/growl/Growl';
 import {ResourceInputList} from './ResourceInputList';
 
 import AppLoader from '../../layout/components/AppLoader';
+import AppHeader from '../../layout/components/AppHeader';
 import CycleService from '../../services/cycle.service';
 import ProjectService from '../../services/project.service';
 import UnitConverter from '../../utils/unit.converter';
@@ -255,10 +256,12 @@ export class ProjectCreate extends Component {
             let projectQuota = [];
             for (const resource in this.state.projectQuota) {
                 let resourceType = _.find(this.state.resources, {'name': resource});
-                let quota = { project: this.state.project.name,
-                                resource_type: resourceType['url'],
-                                value: this.state.projectQuota[resource] * (this.resourceUnitMap[resourceType.quantity_value]?this.resourceUnitMap[resourceType.quantity_value].conversionFactor:1)};
-                projectQuota.push(quota);
+                if(resourceType){
+                    let quota = { project: this.state.project.name,
+                                    resource_type: resourceType['url'],
+                                    value: this.state.projectQuota[resource] * (this.resourceUnitMap[resourceType.quantity_value]?this.resourceUnitMap[resourceType.quantity_value].conversionFactor:1)};
+                    projectQuota.push(quota);
+                }
             }
             ProjectService.saveProject(this.state.project, this.defaultResourcesEnabled?projectQuota:[])
                 .then(project => {
@@ -306,11 +309,12 @@ export class ProjectCreate extends Component {
             this.setState({
                 dialog: { header: '', detail: ''},
                 project: {
+                    url: '',
                     name: '',
                     description: '',
                     trigger_priority: 1000,
                     priority_rank: null,
-                    project_quota: []
+                    quota: []
                 },
                 projectQuota: projectQuota,
                 validFields: {},
@@ -332,14 +336,19 @@ export class ProjectCreate extends Component {
         
         return (
             <React.Fragment>
-                <div className="p-grid">
+                { /* <div className="p-grid">
                     <Growl ref={(el) => this.growl = el} />
-                       <div className="p-col-2 p-lg-2 p-md-2">
+                
+                    <div className="p-col-10 p-lg-10 p-md-10">
+                        <h2>Project - Add</h2>
+                    </div>
+                    <div className="p-col-2 p-lg-2 p-md-2">
                         <Link to={{ pathname: '/project'}} tite="Close Edit" style={{float: "right"}}>
-                            <i className="fa fa-window-close" style={{position:"absolute",top: "105px",marginLeft:"863px"}}></i>
+                            <i className="fa fa-window-close" style={{marginTop: "10px"}}></i>
                         </Link>
                     </div>
-                </div>
+                 </div> */ }
+                 <AppHeader location={this.props.location} actions={[{name: 'fa-window-close', props:{ pathname: '/project'}}]}/>
                 { this.state.isLoading ? <AppLoader /> :
                 <>
                 <div>
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/edit.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/edit.js
index 0136988f137..80ae162cb4b 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/edit.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/edit.js
@@ -15,6 +15,7 @@ import {Growl} from 'primereact/components/growl/Growl';
 import {ResourceInputList} from './ResourceInputList';
 
 import AppLoader from '../../layout/components/AppLoader';
+import AppHeader from '../../layout/components/AppHeader';
 import CycleService from '../../services/cycle.service';
 import ProjectService from '../../services/project.service';
 import UnitConverter from '../../utils/unit.converter';
@@ -356,14 +357,19 @@ export class ProjectEdit extends Component {
         
         return (
             <React.Fragment>
-                <div className="p-grid">
+                {/*} <div className="p-grid">
                     <Growl ref={(el) => this.growl = el} />
+                
+                    <div className="p-col-10 p-lg-10 p-md-10">
+                        <h2>Project - Edit</h2>
+                    </div>
                     <div className="p-col-2 p-lg-2 p-md-2">
                         <Link to={{ pathname: `/project/view/${this.state.project.name}`}} title="Close Edit" style={{float: "right"}}>
-                            <i className="fa fa-window-close" style={{position: "absolute",top: "105px",marginLeft: "875px"}}></i>
+                            <i className="fa fa-window-close" style={{marginTop: "10px"}}></i>
                         </Link>
                     </div>
-                </div>
+                  </div> */}
+                 <AppHeader location={this.props.location} actions={[{name: 'fa-window-close', props : { pathname: `/project/view/${this.state.project.name}`}}]}/>
 
                 { this.state.isLoading ? <AppLoader/> :
                 <>
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/list.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/list.js
index f47fc36beca..8a1b11ac569 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/list.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/list.js
@@ -3,6 +3,7 @@ import ProjectService from '../../services/project.service';
 import ViewTable from '../../components/ViewTable';
 import { Link } from 'react-router-dom/cjs/react-router-dom.min';
 import AppLoader from '../../layout/components/AppLoader';
+import AppHeader from '../../layout/components/AppHeader';
 
 export class ProjectList extends Component{
     constructor(props){
@@ -70,13 +71,17 @@ export class ProjectList extends Component{
     render(){
         return(
             <>
-                <div className="p-grid">
+               {/*<div className="p-grid">
+                    <div className="p-col-10 p-lg-10 p-md-10">
+                        <h2>Project - List </h2>
+                    </div>
                     <div className="p-col-2 p-lg-2 p-md-2">
                         <Link to={{ pathname: '/project/create'}} title="Add New Project" style={{float: "right"}}>
-                            <i className="fa fa-plus-square" style={{top: "105px",position: "absolute",marginLeft: "865px"}}></i>
+                            <i className="fa fa-plus-square" style={{marginTop: "10px"}}></i>
                         </Link>
                     </div>
-                </div>
+                </div> */}
+                <AppHeader location={this.props.location} actions={[{name: 'fa-plus-square', props:{pathname: '/project/create' }}]}/>
                 {this.state.isLoading? <AppLoader /> : this.state.isprocessed &&
                     <ViewTable 
                         data={this.state.projectlist} 
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/view.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/view.js
index eca8951d2d9..6fe352aee92 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/view.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/view.js
@@ -8,6 +8,7 @@ import { Chips } from 'primereact/chips';
 import ResourceDisplayList from './ResourceDisplayList';
 
 import AppLoader from '../../layout/components/AppLoader';
+import AppHeader from '../../layout/components/AppHeader';
 import ProjectService from '../../services/project.service';
 import UnitConverter from '../../utils/unit.converter';
 
@@ -20,23 +21,20 @@ export class ProjectView extends Component {
         super(props);
         this.state = {
             isLoading: true,
+            project:'',
         };
-        console.log(this.props);
         if (this.props.match.params.id) {
             this.state.projectId  = this.props.match.params.id;
         }   else if (this.props.location.state && this.props.location.state.id) {
             this.state.projectId = this.props.location.state.id;
         }
-        console.log(this.state.projectId);
         this.state.redirect = this.state.projectId?"":'/project'         // If no project id is passed, redirect to Project list page
         this.resourceUnitMap = UnitConverter.resourceUnitMap;       // Resource unit conversion factor and constraints
     }
 
     componentDidMount() {
         const projectId = this.state.projectId;
-        console.log(projectId);
         if (projectId) {
-            console.log(projectId);
             this.getProjectDetails(projectId);
         }   else {
             this.setState({redirect: "/not-found"});
@@ -79,19 +77,23 @@ export class ProjectView extends Component {
         
         return (
             <React.Fragment>
-                <div className="p-grid">
+                { /*}  <div className="p-grid">
+                    <div className="p-col-10 p-lg-10 p-md-10">
+                        <h2>Project - Details </h2>
+                    </div>
                     { this.state.project &&
                     <div className="p-col-2 p-lg-2 p-md-2">
                         <Link to={{ pathname: `/project`}} title="Close View" style={{float: "right"}}>
-                            <i className="fa fa-times" style={{position:"absolute",top:"105px",marginLeft:"870px"}}></i>
+                            <i className="fa fa-times" style={{marginTop: "10px", marginLeft: "5px"}}></i>
                         </Link>
                         <Link to={{ pathname: `/project/edit/${this.state.project.name}`, state: {id: this.state.project?this.state.project.name:''}}} title="Edit Project" 
                                  style={{float: "right"}}>
-                            <i className="fa fa-edit" style={{position:"absolute",top:"105px",marginLeft:"845px"}}></i>
+                            <i className="fa fa-edit" style={{marginTop: "10px"}}></i>
                         </Link>
                     </div>
                     }
-                </div>
+                </div> */}
+                 <AppHeader location={this.props.location} actions={[{name: 'fa-edit', props : { pathname: `/project/edit/${this.state.project.name}`, state: {id: this.state.project?this.state.project.name:''&& this.state.project}}},{name: 'fa-times', props : { pathname: `/project`}}]}/>
                 { this.state.isLoading && <AppLoader /> }
                 { this.state.project &&
                     <React.Fragment>
@@ -112,7 +114,7 @@ export class ProjectView extends Component {
                                 <label className="col-lg-2 col-md-2 col-sm-12">Trigger Priority</label>
                                 <span className="col-lg-4 col-md-4 col-sm-12">{this.state.project.trigger_priority}</span>
                                 <label className="col-lg-2 col-md-2 col-sm-12">Allows Trigger Submission</label>
-                                <span className="col-lg-4 col-md-4 col-sm-12"><i className={this.state.project.can_trigger?'fa fa-check-square':'fa fa-times'}></i></span>
+                                <span className="col-lg-4 col-md-4 col-sm-12"><i className={this.state.project.can_trigger?'fa fa-check-circle':'fa fa-times-circle'}></i></span>
                             </div>
                             <div className="p-grid">
                                 <label className="col-lg-2 col-md-2 col-sm-12">Project Category</label>
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/SchedulingUnitList.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/SchedulingUnitList.js
index 4ef6b176343..a3ec244ea83 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/SchedulingUnitList.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/SchedulingUnitList.js
@@ -1,8 +1,8 @@
 import React, { Component } from 'react'
 import 'primeflex/primeflex.css';
-
-import AppLoader from "../../layout/components/AppLoader";
-import ViewTable from '../../components/ViewTable';
+import moment from 'moment';
+import AppLoader from "./../../layout/components/AppLoader";
+import ViewTable from './../../components/ViewTable';
 
 import ScheduleService from '../../services/schedule.service';
  
@@ -18,6 +18,7 @@ class SchedulingUnitList extends Component{
             }],
             isLoading: true,
             defaultcolumns: [ {
+                "type":"Type",
                 "name":"Name",
                 "description":"Description",
                 "created_at":"Created Date",
@@ -25,7 +26,7 @@ class SchedulingUnitList extends Component{
                 "requirements_template_id": "Template",
                 "start_time":"Start Time",
                 "stop_time":"End time",
-                "duration":"Duration"
+                "duration":"Duration (HH:mm:ss)"
                 }],
             optionalcolumns:  [{
                 "actionpath":"actionpath",
@@ -33,23 +34,41 @@ class SchedulingUnitList extends Component{
             columnclassname: [{
                 "Template":"filter-input-50",
                 "Duration":"filter-input-50",
+                "Type": "filter-input-75"
             }]
         }
     }
+    
+     
 
-    componentDidMount(){ 
+    async getSchedulingUnitList () {
+        const bluePrint = await ScheduleService.getSchedulingUnitBlueprint();
         ScheduleService.getSchedulingUnitDraft().then(scheduleunit =>{
-            console.log(scheduleunit)
+            const output = [];
             var scheduleunits = scheduleunit.data.results;
-        
             for( const scheduleunit  of scheduleunits){
-                scheduleunit['actionpath']='/schedulingunit/view'
+                const blueprintdata = bluePrint.data.results.filter(i => i.draft_id === scheduleunit.id);
+                blueprintdata.map(blueP => { 
+                    blueP.duration = moment.utc(blueP.duration*1000).format('HH:mm:ss'); 
+                    blueP.type="Blueprint"; 
+                    blueP['actionpath'] = '/task/view/type/id';
+                    return blueP; 
+                });
+                output.push(...blueprintdata);
+                scheduleunit['actionpath']='/schedulingunit/view';
+                scheduleunit['type'] = 'Draft';
+                scheduleunit['duration'] = moment.utc(scheduleunit.duration*1000).format('HH:mm:ss');
+                output.push(scheduleunit);
             }
             this.setState({
-                scheduleunit : scheduleunit.data ,isLoading: false
+                scheduleunit: output, isLoading:false
             });
         })
     }
+    
+    componentDidMount(){ 
+       this.getSchedulingUnitList();
+    }
 
     render(){
         if (this.state.isLoading) {
@@ -57,9 +76,7 @@ class SchedulingUnitList extends Component{
         }
         return(
             <>
-            
-                {
-                
+               {
                 /*
                     * Call View table to show table data, the parameters are,
                     data - Pass API data
@@ -70,9 +87,9 @@ class SchedulingUnitList extends Component{
                     paths - specify the path for navigation - Table will set "id" value for each row in action button
                     
                 */}
-                {this.state.scheduleunit.results &&
+                {this.state.scheduleunit &&
                     <ViewTable 
-                        data={this.state.scheduleunit.results} 
+                        data={this.state.scheduleunit} 
                         defaultcolumns={this.state.defaultcolumns} 
                         optionalcolumns={this.state.optionalcolumns}
                         columnclassname={this.state.columnclassname}
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/ViewSchedulingUnit.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/ViewSchedulingUnit.js
index eaececbd9a8..68974a98919 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/ViewSchedulingUnit.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/ViewSchedulingUnit.js
@@ -4,6 +4,7 @@ import 'primeflex/primeflex.css';
 import { Chips } from 'primereact/chips';
 
 import AppLoader from "./../../layout/components/AppLoader";
+import AppHeader from '../../layout/components/AppHeader';
 
 import ViewTable from './../../components/ViewTable';
 import ScheduleService from '../../services/schedule.service';
@@ -21,7 +22,7 @@ class ViewSchedulingUnit extends Component{
             }],
 
             defaultcolumns: [ {
-                "tasktype":"Task Type",
+                "tasktype":"Type",
                 "id":"ID",
                 "name":"Name",
                 "description":"Description",
@@ -30,11 +31,11 @@ class ViewSchedulingUnit extends Component{
                 "do_cancel":"Cancelled",
                 "start_time":"Start Time",
                 "stop_time":"End Time",
-                "duration":"Duration",
+                "duration":"Duration (HH:mm:ss)",
             }],
             optionalcolumns:  [{
-                "relative_start_time":"Relative Start Time",
-                "relative_stop_time":"Relative End Time",
+                "relative_start_time":"Relative Start Time (HH:mm:ss)",
+                "relative_stop_time":"Relative End Time (HH:mm:ss)",
                 "tags":"Tags",
                 "blueprint_draft":"BluePrint / Task Draft link",
                 "url":"URL",
@@ -42,12 +43,14 @@ class ViewSchedulingUnit extends Component{
             }],
 
             columnclassname: [{
-                "Task Type":"filter-input-100",
+                "Type":"filter-input-75",
                 "ID":"filter-input-50",
                 "Cancelled":"filter-input-50",
-                "Duration":"filter-input-50",
+                "Duration (HH:mm:ss)":"filter-input-75",
                 "Template ID":"filter-input-50",
-                "BluePrint / Task Draft link":"filter-input-100",
+                "BluePrint / Task Draft link": "filter-input-100",
+                "Relative Start Time (HH:mm:ss)": "filter-input-75",
+                "Relative End Time (HH:mm:ss)": "filter-input-75",
             }]
         }
     }
@@ -59,6 +62,12 @@ class ViewSchedulingUnit extends Component{
             .then(scheduleunit =>{
                 ScheduleService.getScheduleTasksBySchedulingUnitId(scheduleunit.data.id)
                 .then(tasks =>{
+                    tasks.map(task => {
+                        task.duration = moment.utc(task.duration*1000).format('HH:mm:ss'); 
+                        task.relative_start_time = moment.utc(task.relative_start_time*1000).format('HH:mm:ss'); 
+                        task.relative_stop_time = moment.utc(task.relative_stop_time*1000).format('HH:mm:ss'); 
+                        return task;
+                    });
                     this.setState({
                         scheduleunit : scheduleunit.data,
                         schedule_unit_task : tasks,
@@ -72,50 +81,54 @@ class ViewSchedulingUnit extends Component{
     render(){
         return(
 		   <>   
-                <div className="p-grid">
-                <div className="p-col-2">
+                {/*}  <div className="p-grid">
+                <div className="p-col-10">
+                  <h2>Scheduling Unit - Details </h2>
+			    </div>
+				<div className="p-col-2">
                     <Link to={{ pathname: '/schedulingunit'}} title="Close" 
                                 style={{float:'right'}}>
-                        <i className="fa fa-times" style={{position:"absolute",top:"105px",marginLeft:"870px"}}></i>
+                        <i className="fa fa-times" style={{marginTop: "10px", marginLeft: '5px'}}></i>
                     </Link>
-                    <Link to={{ pathname: '/schedulingunit/edit', state: {id: this.state.scheduleunit?this.state.scheduleunit.id:''}}} title="Edit" 
+                     <Link to={{ pathname: '/schedulingunit/edit', state: {id: this.state.scheduleunit?this.state.scheduleunit.id:''}}} title="Edit" 
                             style={{float:'right'}}>
-                    <i className="fa fa-edit" style={{position:"absolute",top:"105px",marginLeft:"845px"}}></i>
-                    </Link>
-                </div>
+                    <i className="fa fa-edit" style={{marginTop: "10px"}}></i>
+                    </Link> 
                 </div>
+                </div> */}
+                <AppHeader location={this.props.location} actions={[{name: 'fa-times', props : { pathname: '/schedulingunit'}}]}/>
 				{ this.state.isLoading ? <AppLoader/> :this.state.scheduleunit &&
 			    <>
 		            <div className="p-grid">
-                        <label  className="p-col-2">Name</label>
-                        <span className="p-col-4">{this.state.scheduleunit.name}</span>
-                        <label  className="p-col-2">Description</label>
-                        <span className="p-col-4">{this.state.scheduleunit.description}</span>
+                        <label  className="col-lg-2 col-md-2 col-sm-12">Name</label>
+                        <span className="p-col-lg-4 col-md-4 col-sm-12">{this.state.scheduleunit.name}</span>
+                        <label  className="col-lg-2 col-md-2 col-sm-12">Description</label>
+                        <span className="col-lg-4 col-md-4 col-sm-12">{this.state.scheduleunit.description}</span>
                     </div>
                     <div className="p-grid">
-                        <label className="p-col-2">Created At</label>
-                        <span className="p-col-4">{moment(this.state.scheduleunit.created_at).format("YYYY-MMM-DD HH:mm:SS")}</span>
-                        <label className="p-col-2">Updated At</label>
-                        <span className="p-col-4">{moment(this.state.scheduleunit.updated_at).format("YYYY-MMM-DD HH:mm:SS")}</span>
+                        <label className="col-lg-2 col-md-2 col-sm-12">Created At</label>
+                        <span className="col-lg-4 col-md-4 col-sm-12">{moment(this.state.scheduleunit.created_at).format("YYYY-MMM-DD HH:mm:SS")}</span>
+                        <label className="col-lg-2 col-md-2 col-sm-12">Updated At</label>
+                        <span className="col-lg-4 col-md-4 col-sm-12">{moment(this.state.scheduleunit.updated_at).format("YYYY-MMM-DD HH:mm:SS")}</span>
                     </div>
                     <div className="p-grid">
-                        <label className="p-col-2">Start Time</label>
-                        <span className="p-col-4">{this.state.scheduleunit.start_time && moment(this.state.scheduleunit.start_time).format("YYYY-MMM-DD HH:mm:SS")}</span>
-                        <label className="p-col-2">End Time</label>
-                        <span className="p-col-4">{this.state.scheduleunit.stop_time && moment(this.state.scheduleunit.stop_time).format("YYYY-MMM-DD HH:mm:SS")}</span>
+                        <label className="col-lg-2 col-md-2 col-sm-12">Start Time</label>
+                        <span className="col-lg-4 col-md-4 col-sm-12">{this.state.scheduleunit.start_time && moment(this.state.scheduleunit.start_time).format("YYYY-MMM-DD HH:mm:SS")}</span>
+                        <label className="col-lg-2 col-md-2 col-sm-12">End Time</label>
+                        <span className="col-lg-4 col-md-4 col-sm-12">{this.state.scheduleunit.stop_time && moment(this.state.scheduleunit.stop_time).format("YYYY-MMM-DD HH:mm:SS")}</span>
                     </div>
                     <div className="p-grid">
-                        <label className="p-col-2">Template ID</label>
-                        <span className="p-col-4">{this.state.scheduleunit.requirements_template_id}</span>
-                        <label  className="p-col-2">Scheduling set</label>
-                        <span className="p-col-4">{this.state.scheduleunit.scheduling_set_id}</span>
+                        <label className="col-lg-2 col-md-2 col-sm-12">Template ID</label>
+                        <span className="col-lg-4 col-md-4 col-sm-12">{this.state.scheduleunit.requirements_template_id}</span>
+                        <label  className="col-lg-2 col-md-2 col-sm-12">Scheduling set</label>
+                        <span className="col-lg-4 col-md-4 col-sm-12">{this.state.scheduleunit.scheduling_set_id}</span>
                     </div>
                     <div className="p-grid">
-                        <label className="p-col-2">Duration</label>
-                        <span className="p-col-4">{this.state.scheduleunit.duration}</span>
-                        <label  className="p-col-2">Tags</label>
+                        <label className="col-lg-2 col-md-2 col-sm-12">Duration (HH:mm:ss)</label>
+                        <span className="col-lg-4 col-md-4 col-sm-12">{moment.utc(this.state.scheduleunit.duration*1000).format('HH:mm:ss')}</span>
+                        <label  className="col-lg-2 col-md-2 col-sm-12">Tags</label>
                         <Chips className="p-col-4 chips-readonly" disabled value={this.state.scheduleunit.tags}></Chips>
-                        <span className="p-col-4">{this.state.scheduleunit.tags}</span>
+                        <span className="col-lg-4 col-md-4 col-sm-12">{this.state.scheduleunit.tags}</span>
                     </div>
                 </>
 			 
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/index.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/index.js
index 81a439da72d..e4c8e9e8f8d 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/index.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/index.js
@@ -1,5 +1,6 @@
 import React, {Component} from 'react';
 import SchedulingUnitList from './SchedulingUnitList';
+import AppHeader from '../../layout/components/AppHeader';
 
 export class Scheduling extends Component {
     constructor(props){
@@ -14,7 +15,7 @@ export class Scheduling extends Component {
     render() {
 		   return (
             <>
-                
+                <AppHeader location={this.props.location} />
                 {this.state.scheduleunit && 
 				<SchedulingUnitList /> }
 		    </>
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/edit.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/edit.js
index f110d4ac421..6d40b19874e 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/edit.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/edit.js
@@ -12,6 +12,7 @@ import Jeditor from '../../components/JSONEditor/JEditor';
 
 import TaskService from '../../services/task.service';
 import AppLoader from "./../../layout/components/AppLoader";
+import AppHeader from '../../layout/components/AppHeader';
 
 
 export class TaskEdit extends Component {
@@ -187,15 +188,18 @@ export class TaskEdit extends Component {
         
         return (
             <React.Fragment>
-                <div className="p-grid">
+                {/*} <div className="p-grid">
+                    <div className="p-col-10 p-lg-10 p-md-10">
+                        <h2>Task - Edit</h2>
+                    </div>
                     <div className="p-col-2 p-lg-2 p-md-2">
                         <Link to={{ pathname: `/task/view/draft/${this.state.task?this.state.task.id:''}`}} title="Close Edit"
                                 style={{float: "right"}} >
-                            <i className="fa fa-window-close" style={{position:"absolute",top:"105px",marginLeft: "860px"}}></i>
+                            <i className="fa fa-window-close" style={{marginTop: "10px"}}></i>
                         </Link>
                     </div>
-                </div>
-				
+                    </div> */}
+				<AppHeader location={this.props.location} actions={[{name: 'fa-window-close', props : { pathname:  `/task/view/draft/${this.state.task?this.state.task.id:''}`}}]}/>
 				{isLoading ? <AppLoader/> :
                 <div>
 			        <div className="p-fluid">
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/view.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/view.js
index 812f2cc0d80..13c77c508a0 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/view.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/view.js
@@ -7,6 +7,7 @@ import Jeditor from '../../components/JSONEditor/JEditor';
 import TaskService from '../../services/task.service';
 import { Chips } from 'primereact/chips';
 import AppLoader from '../../layout/components/AppLoader';
+import AppHeader from '../../layout/components/AppHeader';
 
 export class TaskView extends Component {
     DATE_FORMAT = 'YYYY-MMM-DD HH:mm:ss';
@@ -126,25 +127,29 @@ export class TaskView extends Component {
           );
         return (
             <React.Fragment>
-                <div className="p-grid">
+                {/* <div className="p-grid">
+                    <div className="p-col-10 p-lg-10 p-md-10">
+                        <h2>Task - Details </h2>
+                    </div>
                     <div className="p-col-2 p-lg-2 p-md-2">
                         {this.state.taskType === 'draft' &&
                             <div>
                             <Link to={{ pathname: '/task'}} tooltip="Edit Task" 
                                 style={{float: 'right'}}>
-                                <i className="fa fa-times" style={{position:"absolute",top:"105px",marginLeft:"865px"}}></i>
+                                <i className="fa fa-times" style={{marginLeft:"5px", marginTop: "10px"}}></i>
                             </Link>
                             <Link to={{ pathname: '/task/edit', state: {taskId: this.state.task?this.state.task.id:''}}} tooltip="Edit Task" 
                                 style={{float: 'right'}}>
-                                <i className="fa fa-edit" style={{position:"absolute",top:"105px",marginLeft:"839px"}}></i>
+                                <i className="fa fa-edit" style={{marginTop: "10px"}}></i>
                             </Link>
                             </div>
                         }
                         {this.state.taskType === 'blueprint' &&
-                            <i className="fa fa-lock" style={{position: "absolute",top: "105px",marginLeft: "1025px"}}></i>
+                            <i className="fa fa-lock" style={{float:"right", marginTop: "10px"}}></i>
                         }
                     </div>
-                </div>
+                    </div> */}
+                <AppHeader location={this.props.location} actions={[{name: 'fa-edit', props : { pathname:'/task/edit',state: {taskId: this.state.task?this.state.task.id:''} } },{name: 'fa-times', props : { pathname:'/task' }}]}/>
                 { this.state.isLoading? <AppLoader /> : this.state.task &&
                     <React.Fragment>
                         <div className="main-content">
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/index.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/index.js
index 8efb26f988e..7b48b397c17 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/routes/index.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/index.js
@@ -11,6 +11,7 @@ import {Dashboard} from './Dashboard';
 import {Scheduling} from './Scheduling';
 import {TaskEdit, TaskView} from './Task';
 import ViewSchedulingUnit from './Scheduling/ViewSchedulingUnit'
+import { CycleList, CycleCreate, CycleView, CycleEdit } from './Cycle';
 
 export const routes = [
     {
@@ -72,18 +73,45 @@ export const routes = [
         component: ProjectView,
         name: 'Project View',
         pageTitle: 'Project - View'
-    },{
+    },
+    {
         path: "/project/edit/:id",
         component: ProjectEdit,
         name: 'Project Edit',
-        pageTitle: 'Project - Edit'
+        pageTitle: 'Project Edit'
+    },
+    {
+        path: "/cycle/edit/:id",
+        component: CycleEdit,
+        name: 'Cycle Edit',
+        pageTitle:'Cycle-Edit'
+    },{
+        path: "/cycle/view",
+        component: CycleView,
+        name: 'Cycle View',
+        pageTitle:'Cycle-View'
+    },{
+        path: "/cycle/view/:id",
+        component: CycleView,
+        name: 'Cycle View',
+        pageTitle:'Cycle-View'
+    }, {
+        path: "/cycle/create",
+        component: CycleCreate,
+        name: 'Cycle Add',
+        pageTitle:'Cycle-Add'
+    },
+    {
+        path: "/cycle",
+        component: CycleList,
+        name: 'Cycle List',
+        pageTitle:'Cycle-List'
     },
 ];
 
 export const RoutedContent = () => {
     return (
-	     
-        <Switch>
+	    <Switch>
             <Redirect from="/" to="/" exact />
 			{routes.map(routeProps => <Route {...routeProps} exact key={routeProps.path} />)}
         </Switch>
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/services/cycle.service.js b/SAS/TMSS/frontend/tmss_webapp/src/services/cycle.service.js
index e9ab9620b3a..f758c543f5a 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/services/cycle.service.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/services/cycle.service.js
@@ -4,25 +4,46 @@ const axios = require('axios');
 axios.defaults.headers.common['Authorization'] = 'Basic dGVzdDp0ZXN0';
 
 const CycleService = {
-    getAllCycles: async function() {
+    getAllCycles: async function () {
         try {
-          const url = `/api/cycle`;
-          const response = await axios.get(url);
-          return response.data.results;
+            const url = `/api/cycle`;
+            const response = await axios.get(url);
+            return response.data.results;
         } catch (error) {
-          console.error(error);
+            console.error(error);
         }
-      },
+    },
+    // Duplicate
+    getCycleById: async function (id) {
+        try {
+            const url = `/api/cycle/${id}/project`;
+            const response = await axios.get(url);
+            return response.data.results;
+        } catch (error) {
+            console.error(error);
+        }
+    },
+    getAllCycleQuotas: async function () {
+        let res = [];
+        // To be changed once the cycle_quota for cycle is available.
+        await axios.get('/api/cycle_quota/?limit=1000&offset=0')
+            .then(response => {
+                res = response.data.results;
+            }).catch(function (error) {
+                console.error('[cycle.services.cycle_quota]', error);
+            });
+        return res;
+    },
+    // Duplicate
       getCycle: async function(id) {
         try {
-          const url = `/api/cycle/${id}`;
-          const response = await axios.get(url);
-          return response.data.results;
+          const response = await axios.get((`/api/cycle/${id}`));
+          return response;
         } catch (error) {
           console.error(error);
         }
       },
-      // To be rmoved
+      // To be removed
       getAllCycle: async function (){
         let res = [];
         await axios.get('/api/cycle/')
@@ -34,7 +55,85 @@ const CycleService = {
       
         return res;
       },
-      
+      //Duplicate
+      getResources: async function() {
+        try {
+            const url = `/api/resource_type`;
+            const response = await axios.get(url);
+            return response.data.results;
+          } catch (error) {
+            console.error('[cycle.services.getResources]',error);
+          }
+    },
+    getCycleQuota: async function(id) {
+      try {
+        const response = await axios.get((`/api/cycle_quota/${id}`));
+        return response.data;
+      } catch (error) {
+        console.error(error);
+      }
+    },
+    saveCycle: async function(cycle, cycleQuota) {
+      try {
+        const response = await axios.post(('/api/cycle/'), cycle);
+        cycle = response.data
+        for (let quota of cycleQuota) {
+          quota.cycle = cycle.url;
+          this.saveCycleQuota(quota);
+        }
+        return response.data;
+      } catch (error) {
+        console.log(error.response.data);
+        return error.response.data;
+      }
+    },
+    saveCycleQuota: async function(cycleQuota) {
+      try {
+        const response = await axios.post(('/api/cycle_quota/'),cycleQuota);
+        return response.data;
+      } catch (error) {
+        console.error(error);
+        return null;
+      }
+    }, 
+    updateCycle: async function(id, cycle) {
+      try {
+        const response = await axios.put((`/api/cycle/${id}/`), cycle);
+        return response.data;
+      } catch (error) {
+        console.log(error.response.data);
+        return error.response.data;
+      }
+    },
+    deleteCycleQuota: async function(cycleQuota) {
+      try {
+        const response = await axios.delete(`/api/cycle_quota/${cycleQuota.id}/`);
+        return response.status===204?{message: 'deleted'}:null;
+      } catch (error) {
+        console.error(error);
+        return null;
+      }
+    },
+    updateCycleQuota: async function(cycleQuota) {
+      try {
+        const response = await axios.put(`/api/cycle_quota/${cycleQuota.id}/`, cycleQuota);
+        return response.data;
+      } catch (error) {
+        console.error(error);
+        return null;
+      }
+    },
+    //Duplicate
+    getCycleDetails: async function(id) {
+      try {
+        const response = await axios.get((`/api/cycle/${id}`));
+        let cycle = response.data;
+        return cycle;
+      } catch(error) {
+        console.error(error);
+        return null;
+      }
+    },
 }
 
-export default CycleService;
\ No newline at end of file
+export default CycleService;
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/services/schedule.service.js b/SAS/TMSS/frontend/tmss_webapp/src/services/schedule.service.js
index cda5342a5c6..f09e1da9e87 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/services/schedule.service.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/services/schedule.service.js
@@ -14,6 +14,16 @@ const ScheduleService = {
         });
         return res;
     },
+    getSchedulingUnitBlueprint: async function (){
+        let res = [];
+        await axios.get('/api/scheduling_unit_blueprint/?ordering=id')
+        .then(response => {
+            res= response; 
+        }).catch(function(error) {
+            console.error('[schedule.services.getSchedulingUnitBlueprint]',error);
+        });
+        return res;
+    },
     getSchedulingUnitDraftById: async function (id){
         let res = [];
         await axios.get('/api/scheduling_unit_draft/'+id)
@@ -36,7 +46,7 @@ const ScheduleService = {
         .then(response =>{
             for(const task of response.data.results){
                 let scheduletask = [];
-                scheduletask['tasktype'] = 'Task Draft';
+                scheduletask['tasktype'] = 'Draft';
                 scheduletask['actionpath'] = '/task/view/draft/'+task['id'];
                 scheduletask['blueprint_draft'] = task['task_blueprints'];
 
-- 
GitLab