diff --git a/SAS/TMSS/frontend/tmss_webapp/package.json b/SAS/TMSS/frontend/tmss_webapp/package.json
index b5328e779ebfa77c91b24d16cf90c040bc06e3a4..aa36b24233af3cc9b0c57a2bafd5c32e3da553d7 100644
--- a/SAS/TMSS/frontend/tmss_webapp/package.json
+++ b/SAS/TMSS/frontend/tmss_webapp/package.json
@@ -3,11 +3,13 @@
   "version": "0.1.0",
   "private": true,
   "dependencies": {
+    "@fortawesome/fontawesome-free": "^5.13.1",
     "@json-editor/json-editor": "^2.3.0",
     "@testing-library/jest-dom": "^4.2.4",
     "@testing-library/react": "^9.3.2",
     "@testing-library/user-event": "^7.1.2",
     "axios": "^0.19.2",
+    "bootstrap": "^4.5.0",
     "font-awesome": "^4.7.0",
     "history": "^5.0.0",
     "node-sass": "^4.12.0",
@@ -33,6 +35,7 @@
     "test": "react-scripts test",
     "eject": "react-scripts eject"
   },
+  "proxy": "http://192.168.99.100:8008",
   "eslintConfig": {
     "extends": "react-app"
   },
diff --git a/SAS/TMSS/frontend/tmss_webapp/public/manifest.json b/SAS/TMSS/frontend/tmss_webapp/public/manifest.json
index 080d6c77ac21bb2ef88a6992b2b73ad93daaca92..1f2f141fafdeb1d31d85b008ec5132840c5e6362 100644
--- a/SAS/TMSS/frontend/tmss_webapp/public/manifest.json
+++ b/SAS/TMSS/frontend/tmss_webapp/public/manifest.json
@@ -6,16 +6,6 @@
       "src": "favicon.ico",
       "sizes": "64x64 32x32 24x24 16x16",
       "type": "image/x-icon"
-    },
-    {
-      "src": "logo192.png",
-      "type": "image/png",
-      "sizes": "192x192"
-    },
-    {
-      "src": "logo512.png",
-      "type": "image/png",
-      "sizes": "512x512"
     }
   ],
   "start_url": ".",
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/App.css b/SAS/TMSS/frontend/tmss_webapp/src/App.css
index 18ccb9475ca09cfadf5cd73e300c156090c9812f..0fd3de74678b7f14f3aadbe2bb0b246362a66830 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/App.css
+++ b/SAS/TMSS/frontend/tmss_webapp/src/App.css
@@ -29,6 +29,40 @@
   color: #61dafb;
 }
 
+label {
+  font-size: 14px;
+  font-weight: 600;
+  align-items: flex-start !important;
+}
+
+.chips-readonly > ul {
+  border: none;
+}
+
+p {
+  font-size: 14px;
+}
+
+.card {
+  border: none;
+}
+
+.card-title {
+  margin-bottom: 0.5rem;
+}
+
+.card-body {
+  padding: 0.25rem;
+}
+
+.task-list {
+  padding-inline-start: 0px;
+}
+
+.task-list > li {
+  list-style: none;
+}
+
 @keyframes App-logo-spin {
   from {
     transform: rotate(0deg);
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/App.js b/SAS/TMSS/frontend/tmss_webapp/src/App.js
index 0d607d738c330273f30c7f9dc5a6421c4a0069c7..6f95be3abbc5ed817fbc4a46e5dc0a26604facb7 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/App.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/App.js
@@ -8,9 +8,12 @@ import {RoutedContent} from './routes';
 
 // import {Dashboard} from './routes/dashboard/dashboard';
 
+import 'primeicons/primeicons.css';
+import 'primereact/resources/themes/nova-light/theme.css';
+import 'primereact/resources/primereact.css';
 import './layout/layout.scss';
-// import './App.css';
-
+import './App.scss';
+import './App.css';
 
 class App extends Component {
 
@@ -23,14 +26,14 @@ class App extends Component {
     this.onMenuItemClick = this.onMenuItemClick.bind(this)
     this.menu = [
       {label: 'Dashboard', icon: 'pi pi-fw pi-home', to:'/dashboard'},
-      {label: 'Scheduling Units', icon: 'pi pi-fw pi-calendar', to:'/scheduling'}
+      {label: 'Scheduling Units', icon: 'pi pi-fw pi-calendar', to:'/scheduling'},
+      {label: 'Tasks', icon: 'pi pi-fw pi-check-square', to:'/task'}
     ];
 
     // this.menuComponent = {'Dashboard': Dashboard}
   }
 
   onMenuItemClick(event) {
-    console.log(event);
     this.setState({currentMenu:event.item.label, currentPath: event.item.path});
   }
 
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/App.scss b/SAS/TMSS/frontend/tmss_webapp/src/App.scss
new file mode 100644
index 0000000000000000000000000000000000000000..93c4b1c7a72602ac2fa3e7d2a16fd445736e30e9
--- /dev/null
+++ b/SAS/TMSS/frontend/tmss_webapp/src/App.scss
@@ -0,0 +1 @@
+@import "~bootstrap/scss/bootstrap";
\ No newline at end of file
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/components/JSONEditor/JEditor.js b/SAS/TMSS/frontend/tmss_webapp/src/components/JSONEditor/JEditor.js
new file mode 100644
index 0000000000000000000000000000000000000000..106e5c7f23a34a53d5f8c69abc04819883d108fd
--- /dev/null
+++ b/SAS/TMSS/frontend/tmss_webapp/src/components/JSONEditor/JEditor.js
@@ -0,0 +1,326 @@
+/**
+ * This is the custom component to use "@json-editor/json-editor"
+ * to create form using JSON Schema and get JSON output
+ */
+import React, {useEffect, useRef} from 'react';
+import _ from 'lodash';
+
+// Sample JSON schema. The same can be received from an API call
+// import SchemaDB from './task.observation.schema';
+
+ import "@fortawesome/fontawesome-free/css/all.css";
+// import '../../styles/components/fa_all.scss';
+const JSONEditor = require("@json-editor/json-editor").JSONEditor;
+
+function Jeditor(props) {
+    // console.log("In JEditor");
+    // State object to hold the editor reference to get output
+    // const [stateEditor, setStateEditor] = useState({editor:null});
+    const editorRef = useRef(null);
+    let editor = null;
+    useEffect(() => {
+        const element = document.getElementById('editor_holder');
+        let schema = {};
+        Object.assign(schema, props.schema?props.schema:{});
+        
+        for (const definitionKey in schema.definitions) {
+            if (definitionKey === 'pointing') {
+                const defintion = schema.definitions[definitionKey];
+                let defProperties = defintion.properties;
+                if (defProperties) {
+                    for (const propName in defProperties) {
+                        if (propName === 'angle1' || propName === 'angle2') {
+                            let defProperty = getAngleProperty(defProperties[propName], propName === 'angle2');
+                            defProperties[propName] = defProperty; 
+                        }
+                    }
+                }
+            }
+        }
+        
+        getCustomProperties(schema.properties);
+
+        schema.title = props.title;
+        const validator = validateSubbandOutput;
+        JSONEditor.defaults.custom_validators.push((schema, value, path) => {
+            const errors = [];
+            if (schema.customType === "subband_list") {
+                if (!validator(value)) {
+                    errors.push({
+                        path: path,
+                        property: 'customType',
+                        message: 'Not a valid input for Subband List'
+                    });
+                }
+            }
+            return errors;
+        });
+
+        const editorOptions = {
+            form_name_root: "specification",
+            schema: schema,
+            // display_required_only: true, // circular references will blow up without this
+            theme: 'bootstrap4',
+            iconlib: 'fontawesome5',
+            // theme: 'tailwind',
+            // iconlib: 'spectre',
+            display_required_only: false,
+            // startval: props.initValue,
+            remove_button_labels: true,
+            disable_edit_json: true,
+            disable_properties: true,
+            disable_collapse: true,
+            compact: true
+        };
+        if (props.initValue) {
+            editorOptions.startval = updateInput(_.cloneDeep(props.initValue));
+        }
+        editor = new JSONEditor(element, editorOptions);
+        // editor.setValue(props.initValue);
+        // editor.getEditor('root').disable();
+        if (props.disabled) {
+            editor.disable();
+        }
+        if (!props.initValue) {
+            // editor.setValue(updateInput(editor.getValue()));
+        }
+        // setStateEditor({editor: editor});
+        if (props.parentFunc) {
+            props.parentFunc(childFunc);
+        }
+        editorRef.current = editor;
+        editor.on('change', () => {setEditorOutput()});
+    }, [props.schema]);
+
+    /**
+     * Function to call on button click and send the output back to parent through callback
+     * 
+     */
+    function setEditorOutput(){
+        const editorOutput = editorRef.current.getValue();
+        const formattedOutput = updateOutput(_.cloneDeep(editorOutput));
+        const editorValidationErrors = editorRef.current.validate();
+        if (props.callback) {
+            props.callback(formattedOutput, editorValidationErrors);
+        }
+    }
+
+    function childFunc() {
+        editorRef.current.destroy();
+    }
+
+    function getAngleProperty(defProperty, isDegree) {
+        let newProperty = {
+            "type": "object",
+            "additionalProperties": false,
+            "format": "grid",
+            "title": defProperty.title,
+            "description": defProperty.description};
+        let subProperties = {};
+        if (isDegree) {
+            subProperties["dd"] = {  "type": "number",
+                                      "title": "DD",
+                                      "description": "Degrees",
+                                      "default": 0,
+                                      "minimum": 0,
+                                      "maximum": 90 };
+        }   else {
+            subProperties["hh"] = {  "type": "number",
+                                      "title": "HH",
+                                      "description": "Hours",
+                                      "default": 0,
+                                      "minimum": 0,
+                                      "maximum": 23 };
+            
+        }
+        subProperties["mm"] = {  "type": "number",
+                                      "title": "MM",
+                                      "description": "Minutes",
+                                      "default": 0,
+                                      "minimum": 0,
+                                      "maximum": 59 };
+        subProperties["ss"] = {  "type": "number",
+                                      "title": "SS",
+                                      "description": "Seconds",
+                                      "default": 0,
+                                      "minimum": 0,
+                                      "maximum": 59 };
+
+        newProperty.properties = subProperties;
+        newProperty.required = isDegree?["dd", "mm", "ss"]:["hh", "mm", "ss"];
+        return newProperty;
+    }
+
+    function getCustomProperties(properties) {
+        for (const propertyKey in properties) {
+            const propertyValue = properties[propertyKey];
+            if (propertyKey === 'subbands') {
+                let newProperty = {};
+                newProperty.additionalItems = false;
+                newProperty.title = propertyValue.title;
+                newProperty.type = 'string';
+                newProperty.default = '';
+                newProperty.description = "For Range enter Start and End seperated by 2 dots. Mulitple ranges can be separated by comma. Minimum should be 0 and maximum should be 511. For exmaple 11..20, 30..50";
+                newProperty.customType = 'subband_list';
+                properties[propertyKey] = newProperty;
+            }   else if (propertyKey.toLowerCase() === 'duration') {
+                propertyValue.title = "Duration (minutes)";
+                propertyValue.default = 1;
+            }   else if (propertyValue instanceof Object) {
+                getCustomProperties(propertyValue);
+            }
+        }
+    }
+
+    function updateInput(editorInput) {
+        for (const inputKey in editorInput) {
+            const inputValue = editorInput[inputKey];
+            if (inputValue instanceof Object) {
+                if (inputKey.endsWith('pointing')) {
+                    inputValue.angle1 = getAngleInput(inputValue.angle1);
+                    inputValue.angle2 = getAngleInput(inputValue.angle2, true);
+                }  else if (inputKey === 'subbands') {
+                    editorInput[inputKey] = getSubbandInput(inputValue);
+                }  else {
+                    updateInput(inputValue);
+                }
+            }  else if (inputKey.toLowerCase() === 'duration') {
+                editorInput[inputKey] = inputValue/60;
+            }
+        }
+        return editorInput;
+    }
+
+    function updateOutput(editorOutput) {
+        for (const outputKey in editorOutput) {
+            let outputValue = editorOutput[outputKey];
+            if (outputValue instanceof Object) {
+                if (outputKey.endsWith('pointing')) {
+                    outputValue.angle1 = getAngleOutput(outputValue.angle1);
+                    outputValue.angle2 = getAngleOutput(outputValue.angle2);
+                } else {
+                    updateOutput(outputValue);
+                }
+            } else if (outputKey === 'subbands') {
+                editorOutput[outputKey] = getSubbandOutput(outputValue);
+            } else if (outputKey.toLowerCase() === 'duration') {
+                editorOutput[outputKey] = outputValue * 60;
+            }
+        }
+        return editorOutput;
+    }
+
+    function getAngleInput(prpInput, isDegree) {
+        const degrees = prpInput * 180 / Math.PI;
+        if (isDegree) {
+            const dd = Math.floor(prpInput * 180 / Math.PI);
+            const mm = Math.floor((degrees-dd) * 60);
+            const ss = +((degrees-dd-(mm/60)) * 3600).toFixed(0);
+            return {
+                dd: dd,
+                mm: mm,
+                ss: ss
+            }
+        }   else {
+            const hh = Math.floor(degrees/15);
+            const mm = Math.floor((degrees - (hh*15))/15 * 60 );
+            const ss = +((degrees -(hh*15)-(mm*15/60))/15 * 3600).toFixed(0);
+            return {
+                hh: hh,
+                mm: mm,
+                ss: ss
+            }
+        }
+    }
+
+    function getSubbandInput(prpInput) {
+        let subbandString = "";
+        for (let index=0; index < prpInput.length; index++) {
+            if (subbandString.length > 0) {
+                subbandString += ",";
+            }
+            let firstVal = prpInput[index]
+            let nextVal = prpInput[index];
+            if (prpInput[index+1] - nextVal === 1) {
+                subbandString += firstVal + "..";
+                while( prpInput[index+1] - nextVal === 1) {
+                    index++;
+                    nextVal = prpInput[index];
+                }
+                subbandString += nextVal;
+            }   else {
+                subbandString += firstVal;
+            }
+        }
+        return subbandString;
+    }
+
+    function getAngleOutput(prpOutput) {
+        if ('dd' in prpOutput) {
+            return ((prpOutput.dd + prpOutput.mm/60 + prpOutput.ss/3600)*Math.PI/180);
+        }   else {
+            return ((prpOutput.hh*15 + prpOutput.mm/4  + prpOutput.ss/240)*Math.PI/180);
+        }
+    }
+
+    function validateSubbandOutput(prpOutput){
+        try {
+            if (prpOutput) {
+                const subbandArray = prpOutput.split(",");
+                for (const subband of subbandArray ) {
+                    const subbandRange = subband.split('..');
+                    if (subbandRange.length > 1) {
+                        const firstVal = parseInt(subbandRange[0]);
+                        const nextVal = parseInt(subbandRange[1]) + 1;
+                        if (isNaN(firstVal * nextVal) || firstVal < 0 || firstVal > 510
+                            || nextVal < 0 || nextVal > 511
+                            || firstVal >nextVal) {
+                                return false;
+                            }
+                    }   else {
+                        if (isNaN(parseInt(subbandRange[0]))) {
+                            return false;
+                        }
+                        if (parseInt(subbandRange[0]) < 0 || parseInt(subbandRange[0]) > 511) {
+                            return false;
+                        }
+                    }
+                }
+            }   else {
+                return false
+            }
+        }   catch(exception) {
+            return false;
+        }
+        return true;
+    }
+
+    function getSubbandOutput(prpOutput) {
+        // if (validateSubbandOutput(prpOutput)) {
+            const subbandArray = prpOutput.split(",");
+            let subbandList = [];
+            for (const subband of subbandArray ) {
+                const subbandRange = subband.split('..');
+                if (subbandRange.length > 1) {
+                    subbandList = subbandList.concat( _.range(subbandRange[0], (parseInt(subbandRange[1])+1)));
+                }   else {
+                    subbandList = subbandList.concat(parseInt(subbandRange[0]));
+                }
+            }
+            prpOutput = subbandList;
+        // }   else {
+        //     alert("Subband list values are not valid!");
+        //     prpOutput = [];
+        // }
+        return prpOutput;
+    }
+
+    return (
+        <React.Fragment>
+            <div id='editor_holder'></div>
+            {/* <div><input type="button" onClick={setEditorOutput} value="Show Output" /></div> */}
+        </React.Fragment>
+    );
+};
+
+export default Jeditor;
\ No newline at end of file
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/components/JSONEditor/JViewer.js b/SAS/TMSS/frontend/tmss_webapp/src/components/JSONEditor/JViewer.js
new file mode 100644
index 0000000000000000000000000000000000000000..220a6cfa73cf42d7dc933eb253cb382ebba4acfb
--- /dev/null
+++ b/SAS/TMSS/frontend/tmss_webapp/src/components/JSONEditor/JViewer.js
@@ -0,0 +1,31 @@
+/**
+ * Component to view the JSON data using 'react-json-view' package
+ */
+import React, {Component} from 'react';
+import ReactJson from 'react-json-view';
+
+export default class JViewer extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            outputJSON: props.outputJSON
+        }
+        this.updateOutput = this.updateOutput.bind(this);
+    }
+    
+    /**
+     * Function to be called by the parent to update the JSON content of the viewer
+     * @param {JSON} outputJSON 
+     */
+    updateOutput(outputJSON) {
+        this.state.outputJSON = outputJSON;
+    }
+    
+    render() {
+        return (
+            <React.Fragment>
+                <ReactJson src={this.state.outputJSON} />
+            </React.Fragment>
+        );
+    }
+}
\ No newline at end of file
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/components/JSONEditor/index.js b/SAS/TMSS/frontend/tmss_webapp/src/components/JSONEditor/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..60bb36fd1b4c5645a2dead54172db7fc3c9f0e1f
--- /dev/null
+++ b/SAS/TMSS/frontend/tmss_webapp/src/components/JSONEditor/index.js
@@ -0,0 +1,3 @@
+import { JSONEditor } from './jsonEditor';
+
+export default JSONEditor; 
\ No newline at end of file
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/index.js b/SAS/TMSS/frontend/tmss_webapp/src/index.js
index f5185c1ec7a5dccf30b55a8e3f89afc3eca764a1..76fb92e2e220af22b7f1a3afe63e967fbae4a8bd 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/index.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/index.js
@@ -5,9 +5,9 @@ import App from './App';
 import * as serviceWorker from './serviceWorker';
 
 ReactDOM.render(
-  <React.StrictMode>
-    <App />
-  </React.StrictMode>,
+  // <React.StrictMode>
+    <App />,
+  // </React.StrictMode>,
   document.getElementById('root')
 );
 
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/layout/components/AppMenu.js b/SAS/TMSS/frontend/tmss_webapp/src/layout/components/AppMenu.js
index 7f0e4e18c1ee09448b7ed7f2330702f7b3d875dc..51e3e785c404eb0517378faafebd259825e057df 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/layout/components/AppMenu.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/layout/components/AppMenu.js
@@ -92,11 +92,6 @@ class AppSubmenu extends Component {
             let active = this.state.activeIndex === i;
             // let styleClass = classNames(item.badgeStyleClass, {'active-menuitem': active && !item.to});
             let styleClass = classNames(item.badgeStyleClass, {'active-menuitem': active && item.to});
-            console.log(item.badgeStyleClass);
-            console.log(i);
-            console.log(this.state.activeIndex);
-            console.log(active);
-            console.log(styleClass);
             return (
                 <li className={styleClass} key={i}>
                     {item.items && this.props.root===true && <div className='arrow'></div>}
@@ -124,7 +119,6 @@ export class AppMenu extends Component {
     }
 
     render() {
-        // console.log(authenticationService.currentUserValue);
         return (
             <div className={'layout-sidebar layout-sidebar-light'} >
                 <div className="layout-menu-container">
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/edit.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/edit.js
new file mode 100644
index 0000000000000000000000000000000000000000..ca9ecd6b48f36e4879c177d3241637548956cf3d
--- /dev/null
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/edit.js
@@ -0,0 +1,198 @@
+import React, {Component} from 'react';
+import { Link, Redirect } from 'react-router-dom';
+import moment from 'moment';
+import _ from 'lodash';
+
+import {InputText} from 'primereact/inputtext';
+import {InputTextarea} from 'primereact/inputtextarea';
+import { Calendar } from 'primereact/calendar';
+import {Chips} from 'primereact/chips';
+import {Checkbox} from 'primereact/checkbox';
+import {Dropdown} from 'primereact/dropdown';
+import { Button } from 'primereact/button';
+
+import Jeditor from '../../components/JSONEditor/JEditor';
+
+import TaskService from '../../services/task.services';
+
+export class TaskEdit extends Component {
+    templateOutput = {};
+    
+    constructor(props) {
+        super(props);
+        this.state = {
+            task: {
+                name: "",
+                created_at: null,
+                updated_at: null,
+                tags:[],
+                do_cancel: false
+            },
+            redirect: null,
+            taskTemplates:[],
+            validEditor: false
+            // templateOutput:{},       // id: selectedTemplateId, output: values enetered in the editor form
+        };
+        this.setEditorOutput = this.setEditorOutput.bind(this);
+        this.setTaskParams = this.setTaskParams.bind(this);
+        this.changeTaskTemplate = this.changeTaskTemplate.bind(this);
+        this.setEditorFunc = this.setEditorFunc.bind(this);
+        this.saveTask = this.saveTask.bind(this);
+        this.cancelEdit = this.cancelEdit.bind(this);
+    }
+
+    setEditorOutput(jsonOutput, errors) {
+        this.templateOutput[this.state.task.specifications_template_id] = jsonOutput;
+        if (errors.length === 0 && !this.state.validEditor) {
+            this.setState({validEditor: true});
+        }   else if (errors.length > 0 && this.state.validEditor) {
+            this.setState({validEditor: false});
+        }
+    }
+
+    setTaskParams(key, value) {
+        let task = this.state.task;
+        task[key] = value;
+        this.setState({task: task});
+    }
+
+    setEditorFunc(editorFunc) {
+        this.setState({editorFunc: editorFunc});
+    }
+
+    changeTaskTemplate(templateId) {
+        const template = _.find(this.state.taskTemplates, {'id': templateId});
+        let task = this.state.task;
+        task.specifications_template_id = templateId;
+        task.specifications_template = template.url;
+        this.setState({taskSchema: null});
+        this.setState({task: task, taskSchema: template.schema});
+        this.state.editorFunc();
+    }
+
+    saveTask() {
+        let task = this.state.task;
+        task.specifications_doc = this.templateOutput[task.specifications_template_id];
+        TaskService.updateTask("draft", task)
+        .then( (taskDraft) => {
+            if (taskDraft) {
+                this.setState({redirect: '/task/view'});
+            }
+        });
+    }
+
+    cancelEdit() {
+        this.setState({redirect: '/task/view'});
+    }
+
+    componentDidMount() {
+        TaskService.getTaskTemplates()
+        .then((templates) => {
+            this.setState({taskTemplates: templates});
+        });
+        TaskService.getTaskDetails("draft", this.props.taskId?this.props.taskId:this.props.location.state.taskId)
+        .then((task) => {
+            if (task) {
+                TaskService.getSchedulingUnit("draft", task.scheduling_unit_draft_id)
+                .then((schedulingUnit) => {
+                    this.setState({schedulingUnit: schedulingUnit});
+                });
+                
+                this.templateOutput[task.specifications_template_id] = task.specifications_doc;
+                TaskService.getTaskTemplate(task.specifications_template_id)
+                .then((taskTemplate) => {
+                    this.setState({task: task, taskSchema: taskTemplate.schema});
+                });
+            }
+        });
+    }
+
+    render() {
+        if (this.state.redirect) {
+            return <Redirect to={ {pathname: this.state.redirect, 
+                                    state: {taskId: this.state.task.id}} }></Redirect>
+        }
+        const taskSchema = this.state.taskSchema;
+        let jeditor, created_at, updated_at = null;
+        if (this.state.taskSchema) {
+            jeditor = React.createElement(Jeditor, {title: "Specification", 
+                                                        schema: taskSchema,
+                                                        //initValue: this.state.templateOutput[this.state.task.specifications_template_id], 
+                                                        initValue: this.templateOutput[this.state.task.specifications_template_id], 
+                                                        callback: this.setEditorOutput,
+                                                        parentFunc: this.setEditorFunc
+                                                    });
+            created_at = moment(this.state.task.created_at).toDate();
+            updated_at = moment(this.state.task.created_at).toDate();
+        }
+        
+        return (
+            <React.Fragment>
+                <div style={{marginBottom: "10px"}}>
+                    <h2>Task - Edit</h2>
+                </div>
+                <div>
+                    <div className="p-fluid">
+                        <div className="p-field p-grid">
+                            <label htmlFor="taskName" className="p-col-2">Name</label>
+                            <div className="p-col-4">
+                                <InputText id="taskName" type="text" value={this.state.task.name} onChange={(e) => this.setTaskParams('name', e.target.value)}/>
+                            </div>
+                            <label htmlFor="description" className="p-col-2">Description</label>
+                            <div className="p-col-4">
+                                <InputTextarea rows={3} cols={30} value={this.state.task.description} onChange={(e) => this.setTaskParams('description', e.target.value)}/>
+                            </div>
+                        </div>
+                        {/* <div className="p-field p-grid">
+                            <label htmlFor="createdAt" className="p-col-2">Created At</label>
+                            <div className="p-col-4">
+                                <Calendar showTime={true} hourFormat="24" value={created_at} onChange={(e) => this.setState({date2: e.value})}></Calendar>
+                            </div>
+                            <label htmlFor="updatedAt" className="p-col-2">Updated At</label>
+                            <div className="p-col-4">
+                                <Calendar showTime={true} hourFormat="24" value={updated_at} onChange={(e) => this.setState({date2: e.value})}></Calendar>
+                            </div>
+                        </div> */}
+                        <div className="p-field p-grid">
+                            <label htmlFor="tags" className="p-col-2">Tags</label>
+                            <div className="p-col-4">
+                                <Chips value={this.state.task.tags?this.state.task.tags:[]} onChange={(e) => this.setTaskParams('tags', e.value)}></Chips>
+                            </div>
+                            {/* <label htmlFor="doCancel" className="p-col-2">Do Cancel</label>
+                            <div className="p-col-4">
+                                <Checkbox onChange={e => this.setTaskParams('do_cancel', e.checked)} checked={this.state.task.do_cancel}></Checkbox>
+                            </div> */}
+                            <label className="p-col-2">Scheduling Unit</label>
+                            <Link className="p-col-4" to={ { pathname:'/scheduling'}}>{this.state.schedulingUnit?this.state.schedulingUnit.name:''}</Link>
+                        </div>
+                        <div className="p-field p-grid">
+                            <label htmlFor="tags" className="p-col-2">Template</label>
+                            <div className="p-col-4">
+                                <Dropdown optionLabel="name" optionValue="id" 
+                                        value={this.state.task.specifications_template_id} 
+                                        options={this.state.taskTemplates} 
+                                        onChange={(e) => {this.changeTaskTemplate(e.value)}} 
+                                        placeholder="Select Task Template"/>
+                            </div>
+                            
+                        </div>
+
+                    </div>
+                </div>
+                <div className="p-fluid">
+                    <div className="p-grid"><div className="p-col-12">
+                        {this.state.taskSchema?jeditor:""}
+                    </div></div>
+                </div>
+                <div className="p-grid p-justify-start">
+                    <div className="p-col-1">
+                        <Button label="Save" className="p-button-primary" icon="pi pi-check" onClick={this.saveTask} disabled={!this.state.validEditor} />
+                    </div>
+                    <div className="p-col-1">
+                        <Button label="Cancel" className="p-button-danger" icon="pi pi-times" onClick={this.cancelEdit}  />
+                    </div>
+                </div>
+            </React.Fragment>
+        );
+    }
+}
\ No newline at end of file
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/index.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..7ab687e3398c9015f5b074cdaedbafeeb81f92d0
--- /dev/null
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/index.js
@@ -0,0 +1,4 @@
+import {TaskEdit} from './edit';
+import {TaskView} from './view';
+
+export {TaskEdit, TaskView} ;
\ No newline at end of file
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/view.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/view.js
new file mode 100644
index 0000000000000000000000000000000000000000..d44828e1edaed7803433d54c11b986db984c069c
--- /dev/null
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/view.js
@@ -0,0 +1,149 @@
+import React, {Component} from 'react';
+import {Link} from 'react-router-dom'
+import moment from 'moment';
+
+import Jeditor from '../../components/JSONEditor/JEditor';
+
+import TaskService from '../../services/task.services';
+import { Chips } from 'primereact/chips';
+
+export class TaskView extends Component {
+    DATE_FORMAT = 'YYYY-MMM-DD HH:mm:ss';
+    constructor(props) {
+        super(props);
+        this.state = {
+        };
+        this.setEditorOutput = this.setEditorOutput.bind(this);
+        this.setEditorFunc = this.setEditorFunc.bind(this);
+    }
+
+    setEditorOutput(outputJson) {}
+
+    setEditorFunc(editorFunc) {
+        this.setState({editorFunc: editorFunc});
+    }
+
+    static getDerivedStateFromProps(nextProps, prevstate){
+        if (prevstate.task && nextProps.location.state && 
+             nextProps.location.state.taskId === prevstate.task.id) {
+            return {taskId: prevstate.task.id}
+        }
+        return null;
+    }
+
+    componentDidUpdate(prevProps, prevState) {
+        if (this.state.task && this.props.location.state &&
+             this.state.task.id !== this.props.location.state.taskId) {
+             this.getTaskDetails(this.props.location.state.taskId);
+        }
+    }
+
+    componentDidMount() {
+        const taskId = this.props.taskId?this.props.taskId:1;
+        this.getTaskDetails(taskId);
+    }
+
+    getTaskDetails(taskId) {
+        TaskService.getTaskDetails("draft", taskId)
+        .then((task) => {
+            if (task) {
+               TaskService.getSchedulingUnit("draft", task.scheduling_unit_draft_id)
+                .then((schedulingUnit) => {
+                    this.setState({schedulingUnit: schedulingUnit});
+                });
+                TaskService.getTaskTemplate(task.specifications_template_id)
+                .then((taskTemplate) => {
+                    if (this.state.editorFunc) {
+                        this.state.editorFunc();
+                    }
+                    this.setState({task: task, taskTemplate: taskTemplate});
+                });
+                
+            }
+        });
+    }
+
+    render() {
+        let jeditor = null
+        if (this.state.taskTemplate) {
+            jeditor = React.createElement(Jeditor, {title: "Specification", 
+                                                        schema: this.state.taskTemplate.schema,
+                                                        initValue: this.state.task.specifications_doc,
+                                                        disabled: true,
+                                                        // callback: this.setEditorOutput,
+                                                        parentFunc: this.setEditorFunc
+                                                    });
+        }
+
+        const TaskRelationList = ({ list }) => (
+            <ul className="task-list">
+              {list.map(item => (
+                <li key={item.id}>
+                    <Link to={ { pathname:'/task', state: {taskId: item.id}}}>{item.name}</Link>
+                </li>
+              ))}
+            </ul>
+          );
+
+        return (
+            <React.Fragment>
+                {/* <div style={{marginBottom: "10px"}}> */}
+                <div className="p-grid">
+                    <div className="p-col-2">
+                        <h2>Task - View </h2>
+                    </div>
+                    <div className="p-col-1">
+                        <Link to={{ pathname: '/task/edit', state: {taskId: this.state.task?this.state.task.id:''}}} tooltip="Edit Task" >
+                            <i className="pi pi-pencil" style={{marginTop: "10px"}}></i>
+                        </Link>
+                    </div>
+                </div>
+                { this.state.task &&
+                    <React.Fragment>
+                        <div className="p-grid">
+                            <label className="p-col-2">Name</label>
+                            <span className="p-col-4">{this.state.task.name}</span>
+                            <label className="p-col-2">Description</label>
+                            <span className="p-col-4">{this.state.task.description}</span>
+                        </div>
+                        <div className="p-grid">
+                            <label className="p-col-2">Created At</label>
+                            <span className="p-col-4">{moment.utc(this.state.task.created_at).format(this.DATE_FORMAT)}</span>
+                            <label className="p-col-2">Updated At</label>
+                            <span className="p-col-4">{moment.utc(this.state.task.updated_at).format(this.DATE_FORMAT)}</span>
+                            {/* <span className="p-col-4">{moment(this.state.task.updated_at).format()}</span> */}
+                        </div>
+                        <div className="p-grid">
+                            <label className="p-col-2">Tags</label>
+                            <Chips className="p-col-4 chips-readonly" disabled value={this.state.task.tags}></Chips>
+                            {/* <label className="p-col-2">Do Cancel?</label>
+                            <span className="p-col-4">{this.state.task.do_cancel}</span> */}
+                            <label className="p-col-2">Scheduling Unit</label>
+                            <Link className="p-col-4" to={ { pathname:'/scheduling'}}>{this.state.schedulingUnit?this.state.schedulingUnit.name:''}</Link>
+                        </div>
+                        <div className="p-grid">
+                            <label className="p-col-2">Predecessors</label>
+                            <div className="p-col-4">
+                                <TaskRelationList list={this.state.task.predecessors} />
+                            </div>
+                            <label className="p-col-2">Successors</label>
+                            <div className="p-col-4">
+                                <TaskRelationList list={this.state.task.successors} />
+                            </div>
+                        </div>
+                        <div className="p-grid">
+                            <label className="p-col-2">Template</label>
+                            <span className="p-col-4">{this.state.taskTemplate.name}</span>
+                            
+                        </div>
+                        <div className="p-fluid">
+                            <div className="p-grid"><div className="p-col-12">
+                                {this.state.taskTemplate?jeditor:""}
+                            </div></div>
+                        </div>
+                    </React.Fragment>
+                }
+            </React.Fragment>
+        );
+    }
+}
\ No newline at end of file
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/index.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/index.js
index 323019846cfc267c7874b64bee9ed4bd8a795f10..42a57b784c881506b9d8a72c382fd12d04feddca 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/routes/index.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/index.js
@@ -7,6 +7,7 @@ import {
 
 import {Dashboard} from './Dashboard';
 import {Scheduling} from './Scheduling';
+import {TaskEdit, TaskView} from './Task';
 
 export const RoutedContent = () => {
     return (
@@ -14,6 +15,9 @@ export const RoutedContent = () => {
             <Redirect from="/" to="/" exact />
             <Route path="/dashboard" exact component={Dashboard} />
             <Route path="/scheduling" exact component={Scheduling} />
+            <Route path="/task" exact component={TaskView} />
+            <Route path="/task/view" exact component={TaskView} />
+            <Route path="/task/edit" exact component={TaskEdit} />
         </Switch>
     );
 }
\ No newline at end of file
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/services/task.services.js b/SAS/TMSS/frontend/tmss_webapp/src/services/task.services.js
new file mode 100644
index 0000000000000000000000000000000000000000..e41791aa60fceb8fd2ab52c5dfe07d43a449c7a2
--- /dev/null
+++ b/SAS/TMSS/frontend/tmss_webapp/src/services/task.services.js
@@ -0,0 +1,103 @@
+const axios = require('axios');
+
+//axios.defaults.baseURL = 'http://192.168.99.100:8008/api';
+axios.defaults.headers.common['Authorization'] = 'Basic dGVzdDp0ZXN0';
+
+const TaskService = {
+    getTaskDetails: async function (taskType, taskId) {
+        try {
+          const url = taskType === 'blueprint'? '/api/task_blueprint/': '/api/task_draft/';
+          const response = await axios.get(url + taskId);
+          response.data.predecessors = [];
+          response.data.successors = [];
+          return this.getTaskRelations('draft', response.data.id)
+                  .then(relations => {
+                    response.data.predecessors = relations.predecessors;
+                    response.data.successors = relations.successors;
+                    return response.data;
+                  });
+          
+        } catch (error) {
+          console.error(error);
+        }
+    },
+    getTaskTemplate: async function(templateId) {
+      try {
+        const response = await axios.get('/api/task_template/' + templateId);
+        return response.data;
+      } catch (error) {
+        console.log(error);
+      }
+    },
+    getTaskTemplates: async function() {
+      try {
+        const response = await axios.get('/api/task_template/');
+        return response.data.results;
+      } catch (error) {
+        console.log(error);
+      }
+    },
+    getSchedulingUnit: async function(type, id) {
+      try {
+        const response = await axios.get('/api/scheduling_unit_draft/' + id);
+        return response.data;
+      } catch (error) {
+        console.error(error);
+      }
+    },
+    updateTask: async function(type, task) {
+      try {
+        const response = await axios.put(('/api/task_draft/' + task.id + "/"), task);
+        return response.data;
+      } catch (error) {
+        console.error(error);
+        return null;
+      }
+    },
+    getTaskRelation: async function(type, id) {
+      try {
+        const url = type === 'blueprint'? '/api/task_blueprint/': `/api/task_draft/${id}/task_relation_draft/`;
+        const response = await axios.get(url);
+        return response.data;
+      } catch (error) {
+        console.error(error);
+      }
+    },
+    getTaskRelations: async function(type, id) {
+      try {
+        let relations = {};
+        return this.getTaskPredecessors(type, id)
+        .then( predecessors => {
+          relations.predecessors = predecessors;
+          return this.getTaskSuccessors(type, id);
+        })
+        .then( successors => {
+          relations.successors = successors;
+          return relations;
+        });
+      } catch (error) {
+        console.log(error);
+      }
+    },
+    getTaskPredecessors: async function(type, id) {
+      try {
+        const url = type === 'blueprint'? `/api/task_blueprint/${id}/predecessors`: `/api/task_draft/${id}/predecessors/`;
+        const response = await axios.get(url);
+        return response.data;
+      } catch (error) {
+        console.error(error);
+      }
+    },
+    getTaskSuccessors: async function(type, id) {
+      try {
+        const url = type === 'blueprint'? `/api/task_blueprint/${id}/successors`: `/api/task_draft/${id}/successors/`;
+        const response = await axios.get(url);
+        return response.data;
+      } catch (error) {
+        console.error(error);
+      }
+    }
+    
+}
+
+export default TaskService;
\ No newline at end of file