diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e8e336c5fc789a9bc47574134599f41dea94eef5..7f96632c36e9b1caa7887e0fb323adc3fcf69678 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -265,6 +265,7 @@ integration_test_TMSS:
     RABBITMQ_DEFAULT_PASS: guest
     LOFAR_DEFAULT_BROKER: 'rabbitmq' # override default 'localhost' which does not work for CI service rabbitmq.
   needs:
+    - build_TMSS
     - unit_test_TMSS
   artifacts:
     name: integration-test-report
@@ -289,6 +290,7 @@ integration_test_RAServices:
     - cd build/gnucxx11_opt
     - SKIP_INTEGRATION_TESTS=false SKIP_UNIT_TESTS=true ctest
   needs:
+    - build_RAServices
     - unit_test_RAServices
   artifacts:
     name: integration-test-report
@@ -313,6 +315,7 @@ integration_test_LTAIngest:
     RABBITMQ_DEFAULT_PASS: guest
     LOFAR_DEFAULT_BROKER: 'rabbitmq' # override default 'localhost' which does not work for CI service rabbitmq.
   needs:
+    - build_LTAIngest
     - unit_test_LTAIngest
   artifacts:
     name: integration-test-report
diff --git a/Docker/lofar-ci/Dockerfile_ci_sas b/Docker/lofar-ci/Dockerfile_ci_sas
index 527639e256c50c98b1ef0550b41a7cbf69b3e1c3..1aa8f6689b56f7529d3a0a17e0022128a9ab2bbc 100644
--- a/Docker/lofar-ci/Dockerfile_ci_sas
+++ b/Docker/lofar-ci/Dockerfile_ci_sas
@@ -16,7 +16,7 @@ RUN yum erase -y postgresql postgresql-server postgresql-devel && \
     cd /bin && ln -s /usr/pgsql-9.6/bin/initdb && ln -s /usr/pgsql-9.6/bin/postgres
 ENV PATH /usr/pgsql-9.6/bin:$PATH 
 
-RUN pip3 install cython kombu lxml requests pygcn xmljson mysql-connector-python python-dateutil Django==3.0.9 djangorestframework==3.11.1 djangorestframework-xml ldap==1.0.2 flask fabric coverage python-qpid-proton PyGreSQL numpy h5py psycopg2 testing.postgresql Flask-Testing scipy Markdown django-filter python-ldap python-ldap-test ldap3 django-jsonforms django-json-widget django-jsoneditor drf-yasg flex swagger-spec-validator django-auth-ldap mozilla-django-oidc jsonschema comet pyxb==1.2.5 graphviz isodate astropy packaging
+RUN pip3 install cython kombu lxml requests pygcn xmljson mysql-connector-python python-dateutil Django==3.0.9 djangorestframework==3.11.1 djangorestframework-xml ldap==1.0.2 flask fabric coverage python-qpid-proton PyGreSQL numpy h5py psycopg2 testing.postgresql Flask-Testing scipy Markdown django-filter python-ldap python-ldap-test ldap3 django-jsonforms django-json-widget django-jsoneditor drf-yasg flex swagger-spec-validator django-auth-ldap mozilla-django-oidc jsonschema comet pyxb==1.2.5 graphviz isodate astropy packaging django-debug-toolbar 
 
 #Viewflow package 
 RUN pip3 install django-material django-viewflow
diff --git a/RTCP/Cobalt/GPUProc/etc/parset-additions.d/default/PVSS-feedback.parset b/RTCP/Cobalt/GPUProc/etc/parset-additions.d/default/PVSS-feedback.parset
index 4e062233e380cd0bc57b388f0ecec42bf1ccfe33..3f8654919634d6601b5d6c9bb635a067058ed53f 100644
--- a/RTCP/Cobalt/GPUProc/etc/parset-additions.d/default/PVSS-feedback.parset
+++ b/RTCP/Cobalt/GPUProc/etc/parset-additions.d/default/PVSS-feedback.parset
@@ -4,4 +4,4 @@
 # If empty, data points are never sent.
 # One can also start a PVSSGateway_Stub
 #   on localhost, which writes to a file.
-Cobalt.PVSSGateway.host = ccu001
+Cobalt.PVSSGateway.host = 
diff --git a/SAS/TMSS/docker-compose-ua.yml b/SAS/TMSS/docker-compose-ua.yml
index 74752f8596f9daa35763a85b7f5e355288b38cbd..73b699d14c94f2d0606c3242d4b964f593d05b68 100644
--- a/SAS/TMSS/docker-compose-ua.yml
+++ b/SAS/TMSS/docker-compose-ua.yml
@@ -17,9 +17,10 @@ services:
       - "8088:8088"
   web:
     image: nexus.cep4.control.lofar:18080/tmss_django:latest
+    hostname: tmss-ua
     restart: on-failure
     env_file:
       - ./.env
-    command: bash -c 'source /opt/lofar/lofarinit.sh && python3 lib64/python3.6/site-packages/lofar/sas/tmss/manage.py runserver 0.0.0.0:8008'
+    command: bash -c 'source /opt/lofar/lofarinit.sh && ALLOWED_HOSTS=* tmss_test_environment -H 0.0.0.0 -P tmss-ua -p 8008 --data'
     ports:
       - "8008:8008"
diff --git a/SAS/TMSS/frontend/tmss_webapp/debug.log b/SAS/TMSS/frontend/tmss_webapp/debug.log
new file mode 100644
index 0000000000000000000000000000000000000000..2d8c637aed6551186839ffb67b3120ab5e4487b9
--- /dev/null
+++ b/SAS/TMSS/frontend/tmss_webapp/debug.log
@@ -0,0 +1,2 @@
+[1013/111617.035:ERROR:directory_reader_win.cc(43)] FindFirstFile: The system cannot find the path specified. (0x3)
+[1015/122332.151:ERROR:directory_reader_win.cc(43)] FindFirstFile: The system cannot find the path specified. (0x3)
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/components/Timeline/CalendarTimeline.js b/SAS/TMSS/frontend/tmss_webapp/src/components/Timeline/CalendarTimeline.js
index 1825ef55a1a8191016e852cba1b9206e0b884c2b..ba27d387d396ba1292a334e6907d58f0f6f91561 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/components/Timeline/CalendarTimeline.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/components/Timeline/CalendarTimeline.js
@@ -18,6 +18,7 @@ import UtilService from '../../services/util.service';
 
 import 'react-calendar-timeline/lib/Timeline.css';
 import { Calendar } from 'primereact/calendar';
+import { Checkbox } from 'primereact/checkbox';
 
 // Label formats for day headers based on the interval label width
 const DAY_HEADER_FORMATS = [{ name: "longer", minWidth: 300, maxWidth: 50000, format: "DD dddd, MMMM YYYY"},
@@ -30,7 +31,8 @@ const DAY_HEADER_FORMATS = [{ name: "longer", minWidth: 300, maxWidth: 50000, fo
                             {name: "nano", minWidth: 0, maxWidth: 0, format: ""}];
 
 //>>>>>> Constants for date/time formats, zoom level definition & defaults
-const UTC_DISPLAY_FORMAT = "YYYY-MM-DDTHH:mm:ss";
+const UTC_DATE_FORMAT = "YYYY-MM-DD";
+const UTC_TIME_FORMAT = "HH:mm:ss";
 const UTC_LST_KEY_FORMAT = "YYYY-MM-DDTHH:mm:00";
 const UTC_LST_HOUR_FORMAT = "YYYY-MM-DDTHH:00:00";
 const UTC_LST_DAY_FORMAT = "YYYY-MM-DDT00:00:00";
@@ -95,7 +97,8 @@ export class CalendarTimeline extends Component {
         lstDateHeaderUnit: 'hour',                                  // Unit to be considered for the LST axis header based on the visible duration
         isLSTDateHeaderLoading: true,
         dayHeaderVisible: true,                                     // To control the Day header visibility based on the zoom level
-        weekHeaderVisible: false                                    // To control the Week header visibility based on the zoom level
+        weekHeaderVisible: false,                                   // To control the Week header visibility based on the zoom level
+        isLive: false
       }
       this.itemClickCallback = props.itemClickCallback;             // Pass timeline item click event back to parent
       
@@ -125,6 +128,10 @@ export class CalendarTimeline extends Component {
       this.zoomOut = this.zoomOut.bind(this);
       this.setZoomRange = this.setZoomRange.bind(this);
       //<<<<<< Functions of this component
+      
+      //>>>>>> Public functions of the component
+      this.updateTimeline = this.updateTimeline.bind(this);
+      //<<<<<< Public functions of the component
     }
 
     componentDidMount() {
@@ -158,12 +165,17 @@ export class CalendarTimeline extends Component {
                     const currentUTC = moment.utc(utcString);
                     this.setState({currentUTC: currentUTC});
                     let currentLST = await UtilService.getLST(utcString);
-                    this.setState({currentLST: moment(currentUTC.format('DD-MMM-YYYY ') + currentLST)})
+                    this.setState({currentLST: moment(currentUTC.format('DD-MMM-YYYY ') + currentLST.split('.')[0], 'DD-MMM-YYYY HH:mm:ss')})
                 } );
         }   else {
             this.setState({currentUTC: this.state.currentUTC.add(1, 'second'), 
                             currentLST: this.state.currentLST?this.state.currentLST.add(1, 'second'):null});
         }
+        if (this.state.isLive) {
+            this.props.dateRangeCallback(this.state.defaultStartTime.add(1, 'second'), this.state.defaultEndTime.add(1, 'second'));
+            // const result = this.props.dateRangeCallback(this.state.defaultStartTime.add(1, 'second'), this.state.defaultEndTime.add(1, 'second'));
+            // let group = DEFAULT_GROUP.concat(result.group);
+        }
     }
 
     /**
@@ -183,7 +195,7 @@ export class CalendarTimeline extends Component {
             const formattedColUTC = colUTC.format(lstDateHeaderUnit==="hour"?UTC_LST_HOUR_FORMAT:UTC_LST_DAY_FORMAT);
             // if (!lstDateHeaderMap[formattedColUTC]) {
                 const lst = await UtilService.getLST(formattedColUTC);
-                const lstDate = moment(colUTC.format(`DD-MMM-YYYY ${lst}`)).add(30, 'minutes');
+                const lstDate = moment(colUTC.format(`MM-DD-YYYY ${lst.split('.')[0]}`), 'MM-DD-YYYY HH:mm:ss').add(30, 'minutes');
                 lstDateHeaderMap[formattedColUTC] = lstDateHeaderUnit==="hour"?lstDate.format('HH'):lstDate.format('DD');
             // }
         }
@@ -506,6 +518,7 @@ export class CalendarTimeline extends Component {
     onTimeChange(visibleTimeStart, visibleTimeEnd, updateScrollCanvas) {
         this.loadLSTDateHeaderMap(moment(visibleTimeStart).utc(), moment(visibleTimeEnd).utc(), this.state.lstDateHeaderUnit);
         updateScrollCanvas(visibleTimeStart, visibleTimeEnd);
+        this.props.dateRangeCallback(moment(visibleTimeStart).utc(), moment(visibleTimeEnd).utc());
         this.setState({defaultStartTime: moment(visibleTimeStart), defaultEndTime: moment(visibleTimeEnd)})
     }
 
@@ -570,8 +583,11 @@ export class CalendarTimeline extends Component {
         let visibleTimeEnd = this.state.defaultEndTime;
         const visibleTimeDiff = visibleTimeEnd.valueOf()-visibleTimeStart.valueOf();
         const secondsToMove = visibleTimeDiff / 1000 / 10 ;
+        const result = this.props.dateRangeCallback(visibleTimeStart, visibleTimeEnd);
+        let group = DEFAULT_GROUP.concat(result.group);
         this.setState({defaultStartTime: visibleTimeStart.add(-1 * secondsToMove, 'seconds'),
-                        defaultEndTime: visibleTimeEnd.add(-1 * secondsToMove, 'seconds')});
+                        defaultEndTime: visibleTimeEnd.add(-1 * secondsToMove, 'seconds'),
+                        group: group, items: result.items});
     }
 
     /**
@@ -582,22 +598,17 @@ export class CalendarTimeline extends Component {
         let visibleTimeEnd = this.state.defaultEndTime;
         const visibleTimeDiff = visibleTimeEnd.valueOf()-visibleTimeStart.valueOf();
         const secondsToMove = visibleTimeDiff / 1000 / 10 ;
+        const result = this.props.dateRangeCallback(visibleTimeStart, visibleTimeEnd);
+        let group = DEFAULT_GROUP.concat(result.group);
         this.setState({defaultStartTime: visibleTimeStart.add(1 * secondsToMove, 'seconds'),
-                        defaultEndTime: visibleTimeEnd.add(1 * secondsToMove, 'seconds')});
+                        defaultEndTime: visibleTimeEnd.add(1 * secondsToMove, 'seconds'),
+                        group: group, items: result.items});
     }
 
     /**
      * Zooms In to the next pre-defined zoom level
      */
     zoomIn() {
-        /*let visibleTimeStart = this.state.defaultStartTime;
-        let visibleTimeEnd = this.state.defaultEndTime;
-        const visibleTimeDiff = visibleTimeEnd.valueOf()-visibleTimeStart.valueOf();
-        if (visibleTimeDiff > this.state.minZoom) {
-            const secondsToZoom = visibleTimeDiff / 1000 / 2 / 4 * 3 ;
-            this.setState({defaultStartTime: visibleTimeStart.add(1*secondsToZoom, 'seconds'),
-                            defaultEndTime: visibleTimeEnd.add(-1*secondsToZoom, 'seconds')});
-        }*/
         let prevZoomLevel = this.state.zoomLevel;
         const prevZoomObject = _.find(ZOOM_LEVELS, {'name': prevZoomLevel});
         const prevZoomIndex = ZOOM_LEVELS.indexOf(prevZoomObject);
@@ -610,14 +621,6 @@ export class CalendarTimeline extends Component {
      * Zooms out to the next pre-defined zoom level
      */
     zoomOut() {
-        /*let visibleTimeStart = this.state.defaultStartTime;
-        let visibleTimeEnd = this.state.defaultEndTime;
-        const visibleTimeDiff = visibleTimeEnd.valueOf()-visibleTimeStart.valueOf();
-        if (visibleTimeDiff < this.state.maxZoom) {
-            const secondsToZoom = visibleTimeDiff / 1000 * 3 / 2;
-            this.setState({defaultStartTime: visibleTimeStart.add(-1*secondsToZoom, 'seconds'),
-                            defaultEndTime: visibleTimeEnd.add(1*secondsToZoom, 'seconds')});
-        }*/
         let prevZoomLevel = this.state.zoomLevel;
         const prevZoomObject = _.find(ZOOM_LEVELS, {'name': prevZoomLevel});
         const prevZoomIndex = ZOOM_LEVELS.indexOf(prevZoomObject);
@@ -663,15 +666,27 @@ export class CalendarTimeline extends Component {
         }
     }
 
+    /**
+     * Public function that can be called by its implementation class or function to pass required data and parameters
+     * as objects
+     * @param {Object} props 
+     */
+    updateTimeline(props) {
+        this.setState({group: DEFAULT_GROUP.concat(props.group), items: props.items});
+    }
+
     render() {
         return (
             <React.Fragment>
                 {/* Toolbar for the timeline */}
                 <div className="p-fluid p-grid timeline-toolbar">
                     {/* Clock Display */}
-                    <div className="p-col-3" style={{padding: '0px 0px 0px 10px'}}>
+                    <div className="p-col-2" style={{padding: '0px 0px 0px 10px'}}>
                         <div style={{marginTop: "0px"}}>
-                            <label style={{marginBottom: "0px"}}>UTC:</label><span>{this.state.currentUTC.format(UTC_DISPLAY_FORMAT)}</span>
+                            <label style={{marginBottom: "0px"}}>Date:</label><span>{this.state.currentUTC.format(UTC_DATE_FORMAT)}</span>
+                        </div>
+                        <div style={{marginTop: "0px"}}>
+                            <label style={{marginBottom: "0px"}}>UTC:</label><span>{this.state.currentUTC.format(UTC_TIME_FORMAT)}</span>
                         </div>
                         {this.state.currentLST && 
                             <div style={{marginTop: "0px"}}>
@@ -679,8 +694,12 @@ export class CalendarTimeline extends Component {
                             </div>
                         }
                     </div>
+                    <div className="p-col-1 timeline-filters">
+                        <label style={{paddingRight: "3px"}}>Live </label>
+                        <Checkbox checked={this.state.isLive} label="Live" onChange={(e) => { this.setState({'isLive': e.checked})}} ></Checkbox>
+                    </div>
                     {/* Date Range Selection */}
-                    <div className="p-col-4">
+                    <div className="p-col-4 timeline-filters">
                         {/* <span className="p-float-label"> */}
                         <Calendar id="range" placeholder="Select Date Range" selectionMode="range" showIcon={!this.state.zoomRange}
                                 value={this.state.zoomRange} onChange={(e) => this.setZoomRange( e.value )} readOnlyInput />
@@ -690,11 +709,11 @@ export class CalendarTimeline extends Component {
                                                     onClick={() => {this.setZoomRange( null)}}></i>}
                     </div>
                     {/* Reset to default zoom and current timeline */}
-                    <div className="p-col-1" style={{padding: '5px 0px'}}>
+                    <div className="p-col-1 timeline-button" >
                         <Button label="" icon="pi pi-arrow-down" className="p-button-rounded p-button-success" id="now-btn" onClick={this.resetToCurrentTime} title="Rest Zoom & Move to Current Time"/>
                     </div>
                     {/* Zoom Select */}
-                    <div className="p-col-2" style={{paddingRight: '0px'}}>
+                    <div className="p-col-2 timeline-filters" style={{paddingRight: '0px'}}>
                         <Dropdown optionLabel="name" optionValue="name" 
                                 style={{fontSize: '10px'}}
                                 value={this.state.zoomLevel} 
@@ -704,7 +723,7 @@ export class CalendarTimeline extends Component {
                                 placeholder="Zoom"/>
                     </div>
                     {/* Zoom and Move Action */}
-                    <div className="p-col-2 timeline-actionbar">
+                    <div className="p-col-2 timeline-actionbar timeline-filters">
                         <button className="p-link" title="Move Left" onClick={e=> { this.moveLeft() }}><i className="pi pi-angle-left"></i></button>
                         <button className="p-link" title="Zoom Out" onClick={e=> { this.zoomOut() }} disabled={this.state.zoomLevel.startsWith('Custom')}><i className="pi pi-minus-circle"></i></button>
                         <button className="p-link" title="Zoom In" onClick={e=> { this.zoomIn() }} disabled={this.state.zoomLevel.startsWith('Custom')}><i className="pi pi-plus-circle"></i></button>
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/components/ViewTable.js b/SAS/TMSS/frontend/tmss_webapp/src/components/ViewTable.js
index 21f9326233262c6e69a655eb877a7868d4ca4d9b..904166532404bbea9b00a73c540a276b9e8e5783 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/components/ViewTable.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/components/ViewTable.js
@@ -11,10 +11,14 @@ import {Paginator} from 'primereact/paginator';
 import { Button } from "react-bootstrap";
 import { InputNumber } from "primereact/inputnumber";
 
-let tbldata =[];
+let tbldata =[], filteredData = [] ;
 let isunittest = false;
 let showTopTotal = true;
+let showGlobalFilter = true;
+let showColumnFilter = true;
+let allowColumnSelection = true;
 let columnclassname =[];
+let parentCallbackFunction;
 
 // Define a default UI for filtering
 function GlobalFilter({
@@ -39,13 +43,13 @@ function GlobalFilter({
 
 // Define a default UI for filtering
 function DefaultColumnFilter({
-  column: { filterValue, preFilteredRows, setFilter },
+  column: { filterValue, preFilteredRows, setFilter, filteredRows },
 }) {
   return (
     <input
       value={filterValue || ''}
       onChange={e => {
-        setFilter(e.target.value || undefined) // Set undefined to remove the filter entirely
+        setFilter(e.target.value || undefined); // Set undefined to remove the filter entirely
       }}
     />
   )
@@ -291,7 +295,7 @@ function Table({ columns, data, defaultheader, optionalheader, defaultSortColumn
       useGlobalFilter,
       useSortBy,   
       usePagination
-    )
+    );
   React.useEffect(() => {
     setHiddenColumns(
       columns.filter(column => !column.isVisible).map(column => column.accessor)
@@ -345,11 +349,18 @@ function Table({ columns, data, defaultheader, optionalheader, defaultSortColumn
     })
     localStorage.setItem(tablename,JSON.stringify(lsToggleColumns))
   }
+
+  filteredData = _.map(rows, 'values');
+  if (parentCallbackFunction) {
+    parentCallbackFunction(filteredData);
+  }
+  
   return (
     <>
      <div id="block_container"> 
+     { allowColumnSelection &&
           <div   style={{textAlign:'left', marginRight:'30px'}}>
-                <i className="fa fa-columns col-filter-btn" label="Toggle Columns" onClick={(e) => op.current.toggle(e)}  />
+                <i className="fa fa-columns col-filter-btn" label="Toggle Columns" onClick={(e) => op.current.toggle(e)}  /> 
                 <OverlayPanel ref={op} id="overlay_panel" showCloseIcon={false} >
                   <div>
                       <div style={{textAlign: 'center'}}>
@@ -377,9 +388,9 @@ function Table({ columns, data, defaultheader, optionalheader, defaultSortColumn
                   </div>
                 </OverlayPanel>
             </div> 
-                
+      }
         <div  style={{textAlign:'right'}}>
-        {tbldata.length>0 && !isunittest && 
+        {tbldata.length>0 && !isunittest && showGlobalFilter &&
               <GlobalFilter
                 preGlobalFilteredRows={preGlobalFilteredRows}
                 globalFilter={state.globalFilter}
@@ -470,10 +481,14 @@ filterGreaterThan.autoRemove = val => typeof val !== 'number'
 function ViewTable(props) {
     const history = useHistory();
     // Data to show in table
-    tbldata = props.data; 
+    tbldata = props.data;
+    parentCallbackFunction = props.filterCallback; 
     isunittest = props.unittest;
     columnclassname = props.columnclassname;
-    showTopTotal = props.showTopTotal==='false'? false:true;
+    showTopTotal = props.showTopTotal===undefined?true:props.showTopTotal;
+    showGlobalFilter = props.showGlobalFilter===undefined?true:props.showGlobalFilter;
+    showColumnFilter = props.showColumnFilter===undefined?true:props.showColumnFilter;
+    allowColumnSelection = props.allowColumnSelection===undefined?true:props.allowColumnSelection;
     // Default Header to show in table and other columns header will not show until user action on UI
     let defaultheader = props.defaultcolumns;
     let optionalheader = props.optionalcolumns;
@@ -519,8 +534,8 @@ function ViewTable(props) {
       Header: isString ? defaultheader[0][header] : defaultheader[0][header].name,
       id: header,
       accessor: header,
-      filter: (!isString && defaultheader[0][header].filter=== 'date') ? 'includes' : 'fuzzyText',
-      Filter: isString ? DefaultColumnFilter : (filterTypes[defaultheader[0][header].filter] ? filterTypes[defaultheader[0][header].filter] : DefaultColumnFilter),
+      filter: (showColumnFilter?((!isString && defaultheader[0][header].filter=== 'date') ? 'includes' : 'fuzzyText'):""),
+      Filter: (showColumnFilter?(isString ? DefaultColumnFilter : (filterTypes[defaultheader[0][header].filter] ? filterTypes[defaultheader[0][header].filter] : DefaultColumnFilter)):""),
       isVisible: true,
       Cell: props => <div> {updatedCellvalue(header, props.value)} </div>,
    })
@@ -534,8 +549,8 @@ optionaldataheader.forEach(header => {
       Header: isString ? optionalheader[0][header] : optionalheader[0][header].name,
           id: isString ? header : optionalheader[0][header].name,
           accessor: header,
-          filter: (!isString && optionalheader[0][header].filter=== 'date') ? 'includes' : 'fuzzyText',
-          Filter: isString ? DefaultColumnFilter : (filterTypes[optionalheader[0][header].filter] ? filterTypes[optionalheader[0][header].filter] : DefaultColumnFilter),
+          filter: (showColumnFilter?((!isString && optionalheader[0][header].filter=== 'date') ? 'includes' : 'fuzzyText'):""),
+          Filter: (showColumnFilter?(isString ? DefaultColumnFilter : (filterTypes[optionalheader[0][header].filter] ? filterTypes[optionalheader[0][header].filter] : DefaultColumnFilter)):""),
           isVisible: false,
           Cell: props => <div> {updatedCellvalue(header, props.value)} </div>,
       })
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/layout/_overrides.scss b/SAS/TMSS/frontend/tmss_webapp/src/layout/_overrides.scss
index 03b42a5aeb25770e4dc82919a4ee85d33cec416d..ea8fa6ac620c972f2b45914a621415afda28ee3f 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/layout/_overrides.scss
+++ b/SAS/TMSS/frontend/tmss_webapp/src/layout/_overrides.scss
@@ -51,3 +51,5 @@
     }
 }
 
+
+
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_timeline.scss b/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_timeline.scss
index c2b32f1d6f45d477613e4d68d7257c3fedaff4ab..44fd846f2ef832ee7249f06e5f1d732764fb9ecf 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_timeline.scss
+++ b/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_timeline.scss
@@ -19,6 +19,7 @@
 .timeline-actionbar button {
     padding-top: 3px;
     font-size: 1.0rem;
+    padding-left: 3px;
     // float: right;
 }
 
@@ -31,8 +32,23 @@
     white-space: nowrap;
 }
 
+.timeline-filters,.timeline-bottom {
+    padding-top: 25px;
+}
+
+.timeline-button {
+    padding-bottom: 5px;
+    padding-left: 0px;
+    padding-right: 0px;
+    padding-top: 25px;
+}
+
+.timeline-details-pane {
+    font-size: 14px;
+}
+
 #now-btn {
-    margin-left: 20px;
+    margin-left: 10px;
 }
 
 .resize-div,
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_viewtable.scss b/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_viewtable.scss
index 47803d3ad81264ab7634da3e4b9194d89af2b6f8..45b581f6c23bd3bb129886a494ba5305c6ffcc76 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_viewtable.scss
+++ b/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_viewtable.scss
@@ -102,27 +102,27 @@ body .p-paginator {
   max-width: 175px;
 }
 
-.filter-input-50 input{
+.filter-input-50,.filter-input-50 input{
   width: 50px;
 }
 
-.filter-input-75 input{
+.filter-input-75,.filter-input-75 input{
   width: 75px;
 }
 
-.filter-input-100 input{
+.filter-input-100,.filter-input-100 input{
   width: 100px;
 }
 
-.filter-input-125 input{
+.filter-input-125,.filter-input-125 input{
   width: 125px;
 }
 
-.filter-input-150 input{
+.filter-input-150,.filter-input-150 input{
   width: 150px;
 }
 
-.filter-input-175 input{
+.filter-input-175,.filter-input-175 input{
   width: 175px;
 }
  
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 6cec1f3d60c3f628370e79557f3566549969dc22..2105eadd46a6b1c5e51bb5b336573d95c48a2aae 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/SchedulingUnitList.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/SchedulingUnitList.js
@@ -25,15 +25,17 @@ class SchedulingUnitList extends Component{
                 "requirements_template_id": "Template",
                 "start_time":"Start Time",
                 "stop_time":"End time",
-                "duration":"Duration (HH:mm:ss)"
+                "duration":"Duration (HH:mm:ss)",
+                "status":"Status"
                 }],
             optionalcolumns:  [{
                 "actionpath":"actionpath",
             }],
             columnclassname: [{
                 "Template":"filter-input-50",
-                "Duration":"filter-input-50",
-                "Type": "filter-input-75"
+                "Duration (HH:mm:ss)":"filter-input-75",
+                "Type": "filter-input-75",
+                "Status":"filter-input-100"
             }],
             defaultSortColumn: [{id: "Name", desc: false}],
         }
@@ -57,7 +59,7 @@ class SchedulingUnitList extends Component{
                 for( const scheduleunit  of scheduleunits){
                     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.duration = moment.utc((blueP.duration || 0)*1000).format('HH:mm:ss'); 
                         blueP.type="Blueprint"; 
                         blueP['actionpath'] ='/schedulingunit/view/blueprint/'+blueP.id;
                         return blueP; 
@@ -65,7 +67,7 @@ class SchedulingUnitList extends Component{
                     output.push(...blueprintdata);
                     scheduleunit['actionpath']='/schedulingunit/view/draft/'+scheduleunit.id;
                     scheduleunit['type'] = 'Draft';
-                    scheduleunit['duration'] = moment.utc(scheduleunit.duration*1000).format('HH:mm:ss');
+                    scheduleunit['duration'] = moment.utc((scheduleunit.duration || 0)*1000).format('HH:mm:ss');
                     output.push(scheduleunit);
                 }
                 this.setState({
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 c57445b61784420eceb8a9f538d5c113fea84909..5b35acb3ea87b6311ca3277ea549930f28e171bb 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/ViewSchedulingUnit.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/ViewSchedulingUnit.js
@@ -32,6 +32,7 @@ class ViewSchedulingUnit extends Component{
                 "start_time":"Start Time",
                 "stop_time":"End Time",
                 "duration":"Duration (HH:mm:ss)",
+                "status":"Status"
             }],
             optionalcolumns:  [{
                 "relative_start_time":"Relative Start Time (HH:mm:ss)",
@@ -50,14 +51,15 @@ class ViewSchedulingUnit extends Component{
                 "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",
+                "Status":"filter-input-100"
             }]
         }
         this.actions = [
             {icon: 'fa-window-close',title:'Click to Close Scheduling Unit View', link: this.props.history.goBack} 
         ];
         if (this.props.match.params.type === 'draft') {
-            this.actions.unshift({icon: 'fa-edit', title: 'Click to edit',  props : { pathname:`/schedulingunit/edit/${ this.props.match.params.id}`
-        } });
+            this.actions.unshift({icon: 'fa-edit', title: 'Click to edit',  props : { pathname:`/schedulingunit/edit/${ this.props.match.params.id}`}
+            });
         } else {
             this.actions.unshift({icon: 'fa-lock', title: 'Cannot edit blueprint'});
         }
@@ -67,7 +69,7 @@ class ViewSchedulingUnit extends Component{
         if (this.props.match.params.type) {
             this.state.scheduleunitType = this.props.match.params.type;
         }
-    }
+       }
 
     componentDidMount(){ 
         let schedule_id = this.state.scheduleunitId;
@@ -78,12 +80,6 @@ class ViewSchedulingUnit extends Component{
                 if (schedulingUnit) {
                     this.getScheduleUnitTasks(schedule_type, schedulingUnit)
                         .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 : schedulingUnit,
                             schedule_unit_task : tasks,
@@ -111,8 +107,8 @@ class ViewSchedulingUnit extends Component{
         else
             return ScheduleService.getSchedulingUnitBlueprintById(id)
     }
-
-    render(){
+   
+ render(){
         return(
 		   <>   
                 {/*}  <div className="p-grid">
@@ -136,36 +132,42 @@ class ViewSchedulingUnit extends Component{
 				{ this.state.isLoading ? <AppLoader/> :this.state.scheduleunit &&
 			    <>
 		            <div className="main-content">
-                    <div className="p-grid">
-                        <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="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="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="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_object.name}</span>
-                    </div>
-                    <div className="p-grid">
-                        <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>
+                        <div className="p-grid">
+                            <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="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="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="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_object.name}</span>
+                        </div>
+                        <div className="p-grid">
+                            <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?this.state.scheduleunit.duration:0)*1000).format('HH:mm:ss')}</span>
+                            {this.props.match.params.type === 'blueprint' &&
+                            <label className="col-lg-2 col-md-2 col-sm-12 ">Status</label> }
+                             {this.props.match.params.type === 'blueprint' &&
+                            <span className="col-lg-2 col-md-2 col-sm-12">{this.state.scheduleunit.status}</span>}
+                         </div>
+                     <div className="p-grid">
                         <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>
-                    </div>
+                        </div>
                     </div>
                 </>
 			 
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/summary.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/summary.js
new file mode 100644
index 0000000000000000000000000000000000000000..e5ca99a752c5d3e59b739ecb292b5658b4f65bfd
--- /dev/null
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/summary.js
@@ -0,0 +1,71 @@
+import React, {Component} from 'react';
+import { Link } from 'react-router-dom/cjs/react-router-dom.min';
+import moment from 'moment';
+import ViewTable from '../../components/ViewTable';
+
+/**
+ * Component to view summary of the scheduling unit with limited task details
+ */
+export class SchedulingUnitSummary extends Component {
+
+    constructor(props) {
+        super(props);
+        this.state = {
+            schedulingUnit: props.schedulingUnit || null
+        }
+        this.closeSUDets = this.closeSUDets.bind(this);
+    }
+
+    componentDidMount() {}
+
+    closeSUDets() {
+        if(this.props.closeCallback) {
+            this.props.closeCallback();
+        }
+    }
+
+    render() {
+        const schedulingUnit = this.props.schedulingUnit;
+        const suTaskList = this.props.suTaskList;
+        return (
+            <React.Fragment>
+            { schedulingUnit &&
+                <div className="p-grid timeline-details-pane" style={{marginTop: '10px'}}>
+                    <h6 className="col-lg-10 col-sm-10">Details</h6>
+                    <Link to={`/schedulingunit/view/blueprint/${schedulingUnit.id}`} title="View Full Details"><i className="fa fa-eye"></i></Link>
+                    <Link to={`/su/timelineview`} onClick={this.closeSUDets} title="Close Details"><i className="fa fa-times"></i></Link>
+                    <div className="col-4"><label>Name:</label></div>
+                    <div className="col-8">{schedulingUnit.name}</div>
+                    <div className="col-4"><label>Project:</label></div>
+                    <div className="col-8">{schedulingUnit.project.name}</div>
+                    <div className="col-4"><label>Start Time:</label></div>
+                    <div className="col-8">{moment.utc(schedulingUnit.start_time).format("DD-MMM-YYYY HH:mm:ss")}</div>
+                    <div className="col-4"><label>Stop Time:</label></div>
+                    <div className="col-8">{moment.utc(schedulingUnit.stop_time).format("DD-MMM-YYYY HH:mm:ss")}</div>
+                    <div className="col-4"><label>Status:</label></div>
+                    <div className="col-8">{schedulingUnit.status}</div>
+                    <div className="col-12">
+                        <ViewTable 
+                            data={suTaskList} 
+                            defaultcolumns={[{id: "ID", start_time:"Start Time", stop_time:"End Time", status: "Status", 
+                                                antenna_set: "Antenna Set", band: 'Band'}]}
+                            optionalcolumns={[{actionpath: "actionpath"}]}
+                            columnclassname={[{"ID": "filter-input-50", "Start Time": "filter-input-75", "End Time": "filter-input-75",
+                                                "Status": "filter-input-75", "Antenna Set": "filter-input-75", "Band": "filter-input-75"}]}
+                            defaultSortColumn= {[{id: "ID", desc: false}]}
+                            showaction="false"
+                            tablename="timeline_su_taskslist"
+                            showTopTotal={false}
+                            showGlobalFilter={false}
+                            showColumnFilter={false}
+                            allowColumnSelection={false}
+                        />
+                    </div>
+                </div>
+            }
+            </React.Fragment>
+        );
+    }
+}
+
+export default SchedulingUnitSummary;
\ No newline at end of file
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/view.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/view.js
index 7b1577973c9b081ff5534cb129c013846e890b5b..3d4ad6a1a31004c9c31dcb1b9f77adcf94cc15bc 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/view.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/view.js
@@ -15,6 +15,7 @@ import ScheduleService from '../../services/schedule.service';
 import UtilService from '../../services/util.service';
 
 import UnitConverter from '../../utils/unit.converter';
+import SchedulingUnitSummary from '../Scheduling/summary';
 
 // Color constant for status
 const STATUS_COLORS = { "ERROR": "FF0000", "CANCELLED": "#00FF00", "DEFINED": "#00BCD4", 
@@ -39,13 +40,16 @@ export class TimelineView extends Component {
             isSUDetsVisible: false,
             canExtendSUList: true,
             canShrinkSUList: false,
-            selectedItem: null
+            selectedItem: null,
+            suTaskList:[],
+            isSummaryLoading: false
         }
 
         this.onItemClick = this.onItemClick.bind(this);
         this.closeSUDets = this.closeSUDets.bind(this);
         this.dateRangeCallback = this.dateRangeCallback.bind(this);
         this.resizeSUList = this.resizeSUList.bind(this);
+        this.suListFilterCallback = this.suListFilterCallback.bind(this);
     }
 
     async componentDidMount() {
@@ -126,7 +130,24 @@ export class TimelineView extends Component {
         if (this.state.isSUDetsVisible && item.id===this.state.selectedItem.id) {
             this.closeSUDets();
         }   else {
-            this.setState({selectedItem: item, isSUDetsVisible: true, canExtendSUList: false, canShrinkSUList:false});
+            const fetchDetails = !this.state.selectedItem || item.id!==this.state.selectedItem.id
+            this.setState({selectedItem: item, isSUDetsVisible: true, 
+                isSummaryLoading: fetchDetails,
+                suTaskList: !fetchDetails?this.state.suTaskList:[],
+                canExtendSUList: false, canShrinkSUList:false});
+            if (fetchDetails) {
+                const suBlueprint = _.find(this.state.suBlueprints, {id: item.id});
+                ScheduleService.getTaskBlueprintsBySchedulingUnit(suBlueprint, true)
+                    .then(taskList => {
+                        for (let task of taskList) {
+                            if (task.template.type_value.toLowerCase() === "observation") {
+                                task.antenna_set = task.specifications_doc.antenna_set;
+                                task.band = task.specifications_doc.filter;
+                            }
+                        }
+                        this.setState({suTaskList: _.sortBy(taskList, "id"), isSummaryLoading: false})
+                    });
+            }
         }
     }
 
@@ -162,7 +183,7 @@ export class TimelineView extends Component {
         }
         this.setState({suBlueprintList: _.filter(suBlueprintList, (suBlueprint) => {return suBlueprint.start_time!=null})});
         // On range change close the Details pane
-        this.closeSUDets();
+        // this.closeSUDets();
         return {group: group, items: items};
     }
 
@@ -185,6 +206,25 @@ export class TimelineView extends Component {
         this.setState({canExtendSUList: canExtendSUList, canShrinkSUList: canShrinkSUList});
     }
 
+    /**
+     * Callback function to pass to the ViewTable component to pass back filtered data
+     * @param {Array} filteredData 
+     */
+    suListFilterCallback(filteredData) {
+        let group=[], items = [];
+        const suBlueprints = this.state.suBlueprints;
+        for (const data of filteredData) {
+            const suBlueprint = _.find(suBlueprints, {actionpath: data.actionpath});
+            items.push(this.getTimelineItem(suBlueprint));
+            if (!_.find(group, {'id': suBlueprint.suDraft.id})) {
+                group.push({'id': suBlueprint.suDraft.id, title: suBlueprint.suDraft.name});
+            }
+        }
+        if (this.timeline) {
+            this.timeline.updateTimeline({group: group, items: items});
+        }
+    }
+
     render() {
         if (this.state.redirect) {
             return <Redirect to={ {pathname: this.state.redirect} }></Redirect>
@@ -192,21 +232,15 @@ export class TimelineView extends Component {
         const isSUDetsVisible = this.state.isSUDetsVisible;
         const canExtendSUList = this.state.canExtendSUList;
         const canShrinkSUList = this.state.canShrinkSUList;
+        let suBlueprint = null;
+        if (isSUDetsVisible) {
+            suBlueprint = _.find(this.state.suBlueprints, {id: this.state.selectedItem.id});
+        }
         return (
             <React.Fragment>
                 <PageHeader location={this.props.location} title={'Scheduling Units - Timeline View'} />
                 { this.state.isLoading ? <AppLoader /> :
                         <div className="p-grid">
-                        {/* <SplitPane split="vertical" defaultSize={600} style={{height: 'auto'}} primary="second"> */}
-                            {/* <div className={isSUDetsVisible || (canExtendSUList && !canShrinkSUList)?"resize-div-min col-lg-4 col-md-4 col-sm-12":((canExtendSUList && canShrinkSUList)?"resize-div-avg col-lg-5 col-md-5 col-sm-12":"resize-div-max col-lg-6 col-md-6 col-sm-12")}>
-                                    <button className="p-link resize-btn" disabled={!this.state.canExtendSUList} 
-                                        onClick={(e)=> { this.resizeSUList(1)}}>
-                                        <i className="pi pi-step-forward"></i>
-                                    </button>
-                                    <button className="p-link resize-btn" disabled={!this.state.canShrinkSUList} 
-                                            onClick={(e)=> { this.resizeSUList(-1)}}>
-                                        <i className="pi pi-step-backward"></i>
-                                    </button></div>  */}
                             {/* SU List Panel */}
                             <div className={isSUDetsVisible || (canExtendSUList && !canShrinkSUList)?"col-lg-4 col-md-4 col-sm-12":((canExtendSUList && canShrinkSUList)?"col-lg-5 col-md-5 col-sm-12":"col-lg-6 col-md-6 col-sm-12")}
                                  style={{position: "inherit", borderRight: "5px solid #efefef", paddingTop: "10px"}}>
@@ -221,10 +255,11 @@ export class TimelineView extends Component {
                                     showaction="true"
                                     tablename="timeline_scheduleunit_list"
                                     showTopTotal="false"
+                                    filterCallback={this.suListFilterCallback}
                                 />
                             </div>
                             {/* Timeline Panel */}
-                            <div className={isSUDetsVisible || (!canExtendSUList && canShrinkSUList)?"col-lg-6 col-md-6 col-sm-12":((canExtendSUList && canShrinkSUList)?"col-lg-7 col-md-7 col-sm-12":"col-lg-8 col-md-8 col-sm-12")}>
+                            <div className={isSUDetsVisible || (!canExtendSUList && canShrinkSUList)?"col-lg-5 col-md-5 col-sm-12":((canExtendSUList && canShrinkSUList)?"col-lg-7 col-md-7 col-sm-12":"col-lg-8 col-md-8 col-sm-12")}>
                                 {/* Panel Resize buttons */}
                                 <div className="resize-div">
                                     <button className="p-link resize-btn" disabled={!this.state.canShrinkSUList} 
@@ -245,21 +280,14 @@ export class TimelineView extends Component {
                                         rowHeight={30} itemClickCallback={this.onItemClick}
                                         dateRangeCallback={this.dateRangeCallback}></Timeline>
                             </div>
-                        {/* </SplitPane> */}
                             {/* Details Panel */}
                             {this.state.isSUDetsVisible &&
-                                <div className="col-lg-2 col-md-2 col-sm-12" 
+                                <div className="col-lg-3 col-md-3 col-sm-12" 
                                      style={{borderLeft: "1px solid #efefef", marginTop: "0px", backgroundColor: "#f2f2f2"}}>
-                                    <div className="p-grid" style={{marginTop: '10px'}}>
-                                        <h6 className="col-lg-10 col-sm-10">Details</h6>
-                                        <button className="p-link" onClick={this.closeSUDets}><i className="fa fa-times"></i></button>
-                                    
-                                        <div className="col-12">
-                                            {this.state.selectedItem.title}
-                                        </div>
-
-                                        <div className="col-12">Still In Development</div>
-                                    </div>
+                                    {this.state.isSummaryLoading?<AppLoader /> :
+                                        <SchedulingUnitSummary schedulingUnit={suBlueprint} suTaskList={this.state.suTaskList}
+                                                closeCallback={this.closeSUDets}></SchedulingUnitSummary>
+                                    }
                                 </div>
                             }  
                         
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 30a2c0db09bf506a44b47f156ba4f8b26ec2c3f6..f8d5b8bdb035b4812b683f863ff01bdd0a778d52 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/services/schedule.service.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/services/schedule.service.js
@@ -52,29 +52,31 @@ const ScheduleService = {
             return null;
         }
     },
-    getTaskBlueprintById: async function(id){
-        let res = [];
-        await axios.get('/api/task_blueprint/'+id)
-        .then(response => {
-            res= response; 
-        }).catch(function(error) {
+    getTaskBlueprintById: async function(id, loadTemplate){
+        let result;
+        try {
+            result = await axios.get('/api/task_blueprint/'+id);
+            if (result.data && loadTemplate) {
+                result.data.template = await TaskService.getTaskTemplate(result.data.specifications_template_id);
+            }
+        }   catch(error) {
             console.error('[schedule.services.getTaskBlueprintById]',error);
-        });
-        return res;
+        }
+        return result;
     },
-    getTaskBlueprintsBySchedulingUnit: async function(scheduleunit){
+    getTaskBlueprintsBySchedulingUnit: async function(scheduleunit, loadTemplate){
         // there no single api to fetch associated task_blueprint, so iteare the task_blueprint id to fetch associated task_blueprint
         let taskblueprintsList = [];
         if(scheduleunit.task_blueprints_ids){
             for(const id of scheduleunit.task_blueprints_ids){
-               await this.getTaskBlueprintById(id).then(response =>{
+               await this.getTaskBlueprintById(id, loadTemplate).then(response =>{
                     let taskblueprint = response.data;
                     taskblueprint['tasktype'] = 'Blueprint';
                     taskblueprint['actionpath'] = '/task/view/blueprint/'+taskblueprint['id'];
                     taskblueprint['blueprint_draft'] = taskblueprint['draft'];
                     taskblueprint['relative_start_time'] = 0;
                     taskblueprint['relative_stop_time'] = 0;
-                    taskblueprint.duration = moment.utc(taskblueprint.duration*1000).format('HH:mm:ss'); 
+                    taskblueprint.duration = moment.utc((taskblueprint.duration || 0)*1000).format('HH:mm:ss');
                     taskblueprintsList.push(taskblueprint);
                 })
             }
@@ -85,9 +87,9 @@ const ScheduleService = {
         let scheduletasklist=[];
         // let taskblueprints = [];
         // Common keys for Task and Blueprint
-        let commonkeys = ['id','created_at','description','name','tags','updated_at','url','do_cancel','relative_start_time','relative_stop_time','start_time','stop_time','duration'];
+        let commonkeys = ['id','created_at','description','name','tags','updated_at','url','do_cancel','relative_start_time','relative_stop_time','start_time','stop_time','duration','status'];
         // await this.getTaskBlueprints().then( blueprints =>{
-        //     taskblueprints = blueprints.data.results;
+        //     taskblueprints = blueprints.data.results;'
         // });
         await this.getTasksDraftBySchedulingUnitId(id)
         .then(async(response) =>{
@@ -96,12 +98,13 @@ const ScheduleService = {
                 scheduletask['tasktype'] = 'Draft';
                 scheduletask['actionpath'] = '/task/view/draft/'+task['id'];
                 scheduletask['blueprint_draft'] = task['task_blueprints'];
+                scheduletask['status'] = task['status'];
 
                 //fetch task draft details
                 for(const key of commonkeys){
                     scheduletask[key] = task[key];
                 }
-                scheduletask.duration = moment.utc(scheduletask.duration*1000).format('HH:mm:ss'); 
+                scheduletask.duration = moment.utc((scheduletask.duration || 0)*1000).format('HH:mm:ss'); 
                 scheduletask.relative_start_time = moment.utc(scheduletask.relative_start_time*1000).format('HH:mm:ss'); 
                 scheduletask.relative_stop_time = moment.utc(scheduletask.relative_stop_time*1000).format('HH:mm:ss'); 
                //Fetch blueprint details for Task Draft
@@ -115,10 +118,12 @@ const ScheduleService = {
                     taskblueprint['tasktype'] = 'Blueprint';
                     taskblueprint['actionpath'] = '/task/view/blueprint/'+blueprint['id'];
                     taskblueprint['blueprint_draft'] = blueprint['draft'];
+                    taskblueprint['status'] = blueprint['status'];
+                    
                     for(const key of commonkeys){
                         taskblueprint[key] = blueprint[key];
                     }
-                    taskblueprint.duration = moment.utc(taskblueprint.duration*1000).format('HH:mm:ss'); 
+                    taskblueprint.duration = moment.utc((taskblueprint.duration || 0)*1000).format('HH:mm:ss'); 
                     taskblueprint.relative_start_time = moment.utc(taskblueprint.relative_start_time*1000).format('HH:mm:ss'); 
                     taskblueprint.relative_stop_time = moment.utc(taskblueprint.relative_stop_time*1000).format('HH:mm:ss'); 
 
@@ -272,12 +277,12 @@ const ScheduleService = {
                     for(const suDraft of suDraftList){
                         suDraft['actionpath']='/schedulingunit/view/draft/'+suDraft.id;
                         suDraft['type'] = 'Draft';
-                        suDraft['duration'] = moment.utc(suDraft.duration*1000).format('HH:mm:ss');
+                        suDraft['duration'] = moment.utc((suDraft.duration || 0)*1000).format('HH:mm:ss');
                         schedulingunitlist = schedulingunitlist.concat(suDraft);
                         //Fetch SU Blue prints for the SU Draft
                         await this.getBlueprintsByschedulingUnitId(suDraft.id).then(suBlueprintList =>{
                             for(const suBlueprint of suBlueprintList.data.results){
-                                suBlueprint.duration = moment.utc(suBlueprint.duration*1000).format('HH:mm:ss'); 
+                                suBlueprint.duration = moment.utc((suBlueprint.duration || 0)*1000).format('HH:mm:ss'); 
                                 suBlueprint.type="Blueprint"; 
                                 suBlueprint['actionpath'] = '/schedulingunit/view/blueprint/'+suBlueprint.id;
                                 schedulingunitlist = schedulingunitlist.concat(suBlueprint);
diff --git a/SAS/TMSS/src/tmss/CMakeLists.txt b/SAS/TMSS/src/tmss/CMakeLists.txt
index a38c2b149ed20a69a4ae3376365d869db9c1990e..3e7754777f2f6d34a58352c9d78765303dd9cfa4 100644
--- a/SAS/TMSS/src/tmss/CMakeLists.txt
+++ b/SAS/TMSS/src/tmss/CMakeLists.txt
@@ -13,3 +13,4 @@ python_install(${_py_files}
     DESTINATION lofar/sas/tmss/tmss)
 
 add_subdirectory(tmssapp)
+add_subdirectory(workflowapp)
diff --git a/SAS/TMSS/src/tmss/settings.py b/SAS/TMSS/src/tmss/settings.py
index 3fcb6ea5e997dfabaa0357e8d62c9da6b4a54cac..97b14e0609ec957a3553493dec1a668033b7a841 100644
--- a/SAS/TMSS/src/tmss/settings.py
+++ b/SAS/TMSS/src/tmss/settings.py
@@ -120,8 +120,17 @@ INSTALLED_APPS = [
     'material.frontend',
     'viewflow',
     'viewflow.frontend',
+    'lofar.sas.tmss.tmss.workflowapp',
+    'debug_toolbar',
 ]
 
+def show_debug_toolbar(*args, **kwargs):
+    return os.environ.get('SHOW_DJANGO_DEBUG_TOOLBAR', False)
+
+DEBUG_TOOLBAR_CONFIG = {
+    'SHOW_TOOLBAR_CALLBACK': show_debug_toolbar
+}
+
 MIDDLEWARE = [
     'django.middleware.gzip.GZipMiddleware',
     'django.middleware.security.SecurityMiddleware',
@@ -133,6 +142,7 @@ MIDDLEWARE = [
     'django.middleware.clickjacking.XFrameOptionsMiddleware'
 ]
 
+
 ROOT_URLCONF = 'lofar.sas.tmss.tmss.urls'
 
 TEMPLATES = [
diff --git a/SAS/TMSS/src/tmss/tmssapp/CMakeLists.txt b/SAS/TMSS/src/tmss/tmssapp/CMakeLists.txt
index e24af6998d0ad9240a454cd41fdb389a38cb4208..58c545f7ed434d8c05064e1fad48ebf0c93d821a 100644
--- a/SAS/TMSS/src/tmss/tmssapp/CMakeLists.txt
+++ b/SAS/TMSS/src/tmss/tmssapp/CMakeLists.txt
@@ -23,5 +23,3 @@ add_subdirectory(serializers)
 add_subdirectory(viewsets)
 add_subdirectory(adapters)
 add_subdirectory(schemas)
-add_subdirectory(workflows)
-
diff --git a/SAS/TMSS/src/tmss/tmssapp/migrations/0001_initial.py b/SAS/TMSS/src/tmss/tmssapp/migrations/0001_initial.py
index daa63f9369488f5e160485fbfec01af9cdb5121b..45b53b6b1f17acc72ba81dedbfe5036d1b420889 100644
--- a/SAS/TMSS/src/tmss/tmssapp/migrations/0001_initial.py
+++ b/SAS/TMSS/src/tmss/tmssapp/migrations/0001_initial.py
@@ -1,4 +1,4 @@
-# Generated by Django 3.0.9 on 2020-09-24 15:47
+# Generated by Django 3.0.9 on 2020-09-30 09:15
 
 from django.conf import settings
 import django.contrib.postgres.fields
@@ -14,7 +14,6 @@ class Migration(migrations.Migration):
 
     dependencies = [
         migrations.swappable_dependency(settings.AUTH_USER_MODEL),
-        ('viewflow', '0008_jsonfield_and_artifact'),
     ]
 
     operations = [
@@ -492,26 +491,6 @@ class Migration(migrations.Migration):
                 'abstract': False,
             },
         ),
-        migrations.CreateModel(
-            name='SchedulingUnitDemo',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
-                ('name', models.CharField(max_length=50)),
-                ('state', models.IntegerField()),
-            ],
-        ),
-        migrations.CreateModel(
-            name='SchedulingUnitDemoProcess',
-            fields=[
-                ('process_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='viewflow.Process')),
-                ('text', models.CharField(max_length=150)),
-                ('approved', models.BooleanField(default=False)),
-            ],
-            options={
-                'abstract': False,
-            },
-            bases=('viewflow.process',),
-        ),
         migrations.CreateModel(
             name='SchedulingUnitDraft',
             fields=[
@@ -764,19 +743,6 @@ class Migration(migrations.Migration):
                 'abstract': False,
             },
         ),
-        migrations.CreateModel(
-            name='HelloWorldProcess',
-            fields=[
-            ],
-            options={
-                'verbose_name': 'World Request',
-                'verbose_name_plural': 'World Requests',
-                'proxy': True,
-                'indexes': [],
-                'constraints': [],
-            },
-            bases=('viewflow.process',),
-        ),
         migrations.CreateModel(
             name='Setting',
             fields=[
@@ -1093,11 +1059,6 @@ class Migration(migrations.Migration):
             name='scheduling_set',
             field=models.ForeignKey(help_text='Set to which this scheduling unit draft belongs.', on_delete=django.db.models.deletion.CASCADE, related_name='scheduling_unit_drafts', to='tmssapp.SchedulingSet'),
         ),
-        migrations.AddField(
-            model_name='schedulingunitdemoprocess',
-            name='su',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='tmssapp.SchedulingUnitDemo'),
-        ),
         migrations.AddField(
             model_name='schedulingunitblueprint',
             name='draft',
diff --git a/SAS/TMSS/src/tmss/tmssapp/models/CMakeLists.txt b/SAS/TMSS/src/tmss/tmssapp/models/CMakeLists.txt
index 2ac64b115ecf2f4bc700c614a3ba9572f3af6aa6..7598bc12c79161c19b95275e001a28adb92d3b56 100644
--- a/SAS/TMSS/src/tmss/tmssapp/models/CMakeLists.txt
+++ b/SAS/TMSS/src/tmss/tmssapp/models/CMakeLists.txt
@@ -5,8 +5,6 @@ set(_py_files
     __init__.py
     specification.py
     scheduling.py
-    helloworldflow.py
-    schedulingunitdemoflow.py
     )
 
 python_install(${_py_files}
diff --git a/SAS/TMSS/src/tmss/tmssapp/models/__init__.py b/SAS/TMSS/src/tmss/tmssapp/models/__init__.py
index be7a174d740d60b255c47117cb8abfc657cc9bde..93f3c7e6d54f95c40d6d9484aad802b13f9991ba 100644
--- a/SAS/TMSS/src/tmss/tmssapp/models/__init__.py
+++ b/SAS/TMSS/src/tmss/tmssapp/models/__init__.py
@@ -1,4 +1,2 @@
 from .specification import *
-from .scheduling import *
-from .helloworldflow import *
-from .schedulingunitdemoflow import *
\ No newline at end of file
+from .scheduling import *
\ No newline at end of file
diff --git a/SAS/TMSS/src/tmss/tmssapp/models/scheduling.py b/SAS/TMSS/src/tmss/tmssapp/models/scheduling.py
index a3ebd865de710e9df320248e1614f9ba4f5344da..0ca0fd3810e9afb9ceeb5ad0249f0673e9557f40 100644
--- a/SAS/TMSS/src/tmss/tmssapp/models/scheduling.py
+++ b/SAS/TMSS/src/tmss/tmssapp/models/scheduling.py
@@ -149,7 +149,7 @@ class Subtask(BasicCommon):
         super().__init__(*args, **kwargs)
 
         # keep original state for logging
-        self.__original_state = self.state
+        self.__original_state_id = self.state_id
 
     @staticmethod
     def _send_state_change_event_message(subtask_id:int, old_state: str, new_state: str):
@@ -189,7 +189,7 @@ class Subtask(BasicCommon):
 
         annotate_validate_add_defaults_to_doc_using_template(self, 'specifications_doc', 'specifications_template')
 
-        if self.state.value == SubtaskState.Choices.SCHEDULED.value and self.__original_state.value == SubtaskState.Choices.SCHEDULING.value:
+        if self.state.value == SubtaskState.Choices.SCHEDULED.value and self.__original_state_id == SubtaskState.Choices.SCHEDULING.value:
             if self.start_time is None:
                 if self.predecessors.all().count() == 0:
                     raise SubtaskSchedulingException("Cannot schedule subtask id=%s when start time is 'None'." % (self.pk, ))
@@ -202,12 +202,12 @@ class Subtask(BasicCommon):
         super().save(force_insert, force_update, using, update_fields)
 
         # log if either state update or new entry:
-        if self.state != self.__original_state or creating == True:
+        if self.state_id != self.__original_state_id or creating == True:
             if self.created_or_updated_by_user is None:
                 identifier = None
             else:
                 identifier = self.created_or_updated_by_user.email
-            log_entry = SubtaskStateLog(subtask=self, old_state=self.__original_state, new_state=self.state,
+            log_entry = SubtaskStateLog(subtask=self, old_state=SubtaskState.objects.get(value=self.__original_state_id), new_state=self.state,
                                            user=self.created_or_updated_by_user, user_identifier=identifier)
             log_entry.save()
 
@@ -217,7 +217,7 @@ class Subtask(BasicCommon):
                 logger.error("Could not send state change to messagebus: %s", e)
 
             # update the previous state value
-            self.__original_state = self.state
+            self.__original_state_id = self.state_id
 
 class SubtaskStateLog(BasicCommon):
     """
diff --git a/SAS/TMSS/src/tmss/tmssapp/models/specification.py b/SAS/TMSS/src/tmss/tmssapp/models/specification.py
index f6665e3da24db201901f135fc5708efe6e8f0caa..3caf5c6a31395acee91640096b4c8438ca496eaf 100644
--- a/SAS/TMSS/src/tmss/tmssapp/models/specification.py
+++ b/SAS/TMSS/src/tmss/tmssapp/models/specification.py
@@ -19,7 +19,7 @@ import json
 import jsonschema
 from django.urls import reverse as revese_url
 from collections import Counter
-
+from django.utils.functional import cached_property
 
 #
 # Common
@@ -41,7 +41,7 @@ class BasicCommon(Model):
 
 class NamedCommon(BasicCommon):
     name = CharField(max_length=128, help_text='Human-readable name of this object.', null=False) # todo: check if we want to have this primary_key=True
-    description = CharField(max_length=255, help_text='A longer description of this object.')
+    description = CharField(max_length=255, help_text='A longer description of this object.', blank=True)
 
     def __str__(self):
         return self.name
@@ -412,7 +412,7 @@ class Cycle(NamedCommonPK):
     start = DateTimeField(help_text='Moment at which the cycle starts, that is, when its projects can run.')
     stop = DateTimeField(help_text='Moment at which the cycle officially ends.')
 
-    @property
+    @cached_property
     def duration(self) -> datetime.timedelta:
         '''the duration of the cycle (stop-start date)'''
         return self.stop - self.start
@@ -553,19 +553,19 @@ class SchedulingUnitDraft(NamedCommon):
                 validate_json_against_schema(self.observation_strategy_template.template, self.requirements_template.schema)
 
         if self.scheduling_constraints_doc is not None and self.scheduling_constraints_template_id and self.scheduling_constraints_template.schema is not None:
-                validate_json_against_schema(self.scheduling_constraints_doc, self.scheduling_constraints_template.schema)
+            validate_json_against_schema(self.scheduling_constraints_doc, self.scheduling_constraints_template.schema)
 
         annotate_validate_add_defaults_to_doc_using_template(self, 'requirements_doc', 'requirements_template')
         annotate_validate_add_defaults_to_doc_using_template(self, 'scheduling_constraints_doc', 'scheduling_constraints_template')
         super().save(force_insert, force_update, using, update_fields)
 
-    @property
+    @cached_property
     def duration(self) -> datetime.timedelta:
         '''return the overall duration of all tasks of this scheduling unit
         '''
         return self.relative_stop_time - self.relative_start_time
 
-    @property
+    @cached_property
     def relative_start_time(self) -> datetime.timedelta:
         '''return the earliest relative start time of all tasks of this scheduling unit
         '''
@@ -575,7 +575,7 @@ class SchedulingUnitDraft(NamedCommon):
         else:
             return datetime.timedelta(seconds=0)
 
-    @property
+    @cached_property
     def relative_stop_time(self) -> datetime.timedelta:
         '''return the latest relative stop time of all tasks of this scheduling unit
         '''
@@ -597,7 +597,7 @@ class SchedulingUnitBlueprint(NamedCommon):
 
         super().save(force_insert, force_update, using, update_fields)
 
-    @property
+    @cached_property
     def duration(self) -> datetime.timedelta:
         '''return the overall duration of all tasks of this scheduling unit
         '''
@@ -606,7 +606,7 @@ class SchedulingUnitBlueprint(NamedCommon):
         else:
             return self.stop_time - self.start_time   # <- todo: do we ever want this?
 
-    @property
+    @cached_property
     def relative_start_time(self) -> datetime.timedelta:
         '''return the earliest relative start time of all tasks of this scheduling unit
         '''
@@ -616,7 +616,7 @@ class SchedulingUnitBlueprint(NamedCommon):
         else:
             return datetime.timedelta(seconds=0)
 
-    @property
+    @cached_property
     def relative_stop_time(self) -> datetime.timedelta:
         '''return the latest relative stop time of all tasks of this scheduling unit
         '''
@@ -626,7 +626,7 @@ class SchedulingUnitBlueprint(NamedCommon):
         else:
             return datetime.timedelta(seconds=0)
 
-    @property
+    @cached_property
     def start_time(self) -> datetime or None:
         '''return the earliest start time of all tasks of this scheduling unit
         '''
@@ -636,7 +636,7 @@ class SchedulingUnitBlueprint(NamedCommon):
         else:
             return None
 
-    @property
+    @cached_property
     def stop_time(self) -> datetime or None:
         '''return the latest stop time of all tasks of this scheduling unit
         '''
@@ -758,7 +758,7 @@ class TaskDraft(NamedCommon):
         annotate_validate_add_defaults_to_doc_using_template(self, 'specifications_doc', 'specifications_template')
         super().save(force_insert, force_update, using, update_fields)
 
-    @property
+    @cached_property
     def successors(self) -> QuerySet:
         '''return the connect successor taskdraft(s) as queryset (over which you can perform extended queries, or return via the serializers/viewsets)
            If you want the result, add .all() like so: my_taskdraft.successors.all()
@@ -768,7 +768,7 @@ class TaskDraft(NamedCommon):
                                                       "INNER JOIN tmssapp_taskrelationdraft as task_rel on task_rel.consumer_id = successor_task.id\n"
                                                       "WHERE task_rel.producer_id = %s", params=[self.id]))
 
-    @property
+    @cached_property
     def predecessors(self) -> QuerySet:
         '''return the connect predecessor taskdraft(s) as queryset (over which you can perform extended queries, or return via the serializers/viewsets)
         If you want the result, add .all() like so: my_taskdraft.predecessors.all()
@@ -778,26 +778,26 @@ class TaskDraft(NamedCommon):
                                                       "INNER JOIN tmssapp_taskrelationdraft as task_rel on task_rel.producer_id = successor_task.id\n"
                                                       "WHERE task_rel.consumer_id = %s", params=[self.id]))
 
-    @property
+    @cached_property
     def duration(self) -> datetime.timedelta:
          '''returns the overall duration of this task
          '''
          return self.relative_stop_time - self.relative_start_time
 
-    @property
+    @cached_property
     def relative_start_time(self) -> datetime.timedelta:
         '''return the earliest relative start time of all subtasks of this task
         '''
         scheduling_relations = list(self.first_to_connect.all()) + list(self.second_to_connect.all())
         for scheduling_relation in scheduling_relations:
-            if scheduling_relation.first.id == self.id and scheduling_relation.placement.value == "after":
+            if scheduling_relation.first.id == self._id and scheduling_relation.placement_id == "after":
                 previous_related_task_draft = TaskDraft.objects.get(id=scheduling_relation.second.id)
                 time_offset = scheduling_relation.time_offset
                 # todo: max of several relations
                 if previous_related_task_draft.relative_stop_time:
                     return previous_related_task_draft.relative_stop_time + datetime.timedelta(seconds=time_offset)
 
-            if scheduling_relation.second.id == self.id and scheduling_relation.placement.value == "before":
+            if scheduling_relation.second.id == self._id and scheduling_relation.placement_id == "before":
                 previous_related_task_draft = TaskDraft.objects.get(id=scheduling_relation.first.id)
                 time_offset = scheduling_relation.time_offset
                 # todo: max of several relations
@@ -805,7 +805,7 @@ class TaskDraft(NamedCommon):
                     return previous_related_task_draft.relative_stop_time + datetime.timedelta(seconds=time_offset)
         return datetime.timedelta(seconds=0)
 
-    @property
+    @cached_property
     def relative_stop_time(self) -> datetime.timedelta:
         '''return the latest relative stop time of all subtasks of this task
         '''
@@ -825,7 +825,7 @@ class TaskDraft(NamedCommon):
     #  Only on the blueprints, we also aggregate start_stop times as they are in the system
     #  I'll leave these code bits here for now, until we made up our minds about this, but this can probably be removed
     #
-    # @property
+    # @cached_property
     # def duration(self) -> datetime.timedelta:
     #     '''returns the overall duration in seconds of all blueprints of this task
     #     # todo: is this the wanted behavior? Do you want to consider all the blueprints created from your draft or do you want to preview a new blueprint?
@@ -836,7 +836,7 @@ class TaskDraft(NamedCommon):
     #     else:
     #         return self.stop_time - self.start_time
     #
-    # @property
+    # @cached_property
     # def start_time(self) -> datetime or None:
     #     '''return the earliest start time of all blueprints of this task
     #     # todo: is this the wanted behavior? Do you want to consider all the blueprints created from your draft or do you want to preview a new blueprint?
@@ -848,7 +848,7 @@ class TaskDraft(NamedCommon):
     #         # todo: calculate?
     #         return None
     #
-    # @property
+    # @cached_property
     # def stop_time(self) -> datetime or None:
     #     '''return the latest stop time of all blueprints of this task
     #     # todo: is this the wanted behavior? Do you want to consider all the blueprints created from your draft or do you want to preview a new blueprint?
@@ -872,7 +872,7 @@ class TaskBlueprint(NamedCommon):
         annotate_validate_add_defaults_to_doc_using_template(self, 'specifications_doc', 'specifications_template')
         super().save(force_insert, force_update, using, update_fields)
 
-    @property
+    @cached_property
     def successors(self) -> QuerySet:
         '''return the connect successor taskblueprint(s) as queryset (over which you can perform extended queries, or return via the serializers/viewsets)
            If you want the result, add .all() like so: my_taskblueprint.successors.all()
@@ -882,7 +882,7 @@ class TaskBlueprint(NamedCommon):
                                                           "INNER JOIN tmssapp_taskrelationblueprint as task_rel on task_rel.consumer_id = successor_task.id\n"
                                                           "WHERE task_rel.producer_id = %s", params=[self.id]))
 
-    @property
+    @cached_property
     def predecessors(self) -> QuerySet:
         '''return the connect predecessor taskblueprint(s) as queryset (over which you can perform extended queries, or return via the serializers/viewsets)
         If you want the result, add .all() like so: my_taskblueprint.predecessors.all()
@@ -892,7 +892,7 @@ class TaskBlueprint(NamedCommon):
                                                           "INNER JOIN tmssapp_taskrelationblueprint as task_rel on task_rel.producer_id = predecessor_task.id\n"
                                                           "WHERE task_rel.consumer_id = %s", params=[self.id]))
 
-    @property
+    @cached_property
     def duration(self) -> datetime.timedelta:
         '''return the overall duration of this task
         '''
@@ -901,20 +901,20 @@ class TaskBlueprint(NamedCommon):
         else:
             return self.stop_time - self.start_time
 
-    @property
+    @cached_property
     def relative_start_time(self) -> datetime.timedelta:
         '''return the earliest relative start time of all subtasks of this task
         '''
         scheduling_relations = list(self.first_to_connect.all()) + list(self.second_to_connect.all())
         for scheduling_relation in scheduling_relations:
-                if scheduling_relation.first.id == self.id and scheduling_relation.placement.value == "after":
+            if scheduling_relation.first.id == self._id and scheduling_relation.placement_id == "after":   # self.id and placement.value will hit the db, this does not
                     previous_related_task_blueprint = TaskBlueprint.objects.get(id=scheduling_relation.second.id)
                     time_offset = scheduling_relation.time_offset
                     # todo: max of several relations
                     if previous_related_task_blueprint.relative_stop_time:
                         return previous_related_task_blueprint.relative_stop_time + datetime.timedelta(seconds=time_offset)
 
-                if scheduling_relation.second.id == self.id and scheduling_relation.placement.value == "before":
+            if scheduling_relation.second.id == self._id and scheduling_relation.placement_id == "before":   # self.id and placement.value will hit the db, this does not
                     previous_related_task_blueprint = TaskBlueprint.objects.get(id=scheduling_relation.first.id)
                     time_offset = scheduling_relation.time_offset
                     # todo: max of several relations
@@ -922,7 +922,7 @@ class TaskBlueprint(NamedCommon):
                         return previous_related_task_blueprint.relative_stop_time + datetime.timedelta(seconds=time_offset)
         return datetime.timedelta(seconds=666660)
 
-    @property
+    @cached_property
     def relative_stop_time(self) -> datetime.timedelta:
         '''return the latest relative stop time of all subtasks of this task
         '''
@@ -934,7 +934,7 @@ class TaskBlueprint(NamedCommon):
             pass
         return self.relative_start_time
 
-    @property
+    @cached_property
     def start_time(self) -> datetime or None:
         '''return the earliest start time of all subtasks of this task
         '''
@@ -944,7 +944,7 @@ class TaskBlueprint(NamedCommon):
         else:
             return None
 
-    @property
+    @cached_property
     def stop_time(self) -> datetime or None:
         '''return the latest stop time of all subtasks of this task
         '''
diff --git a/SAS/TMSS/src/tmss/tmssapp/populate.py b/SAS/TMSS/src/tmss/tmssapp/populate.py
index d9f964aae6c3d0b9ac70e02c653edcce27eb4c2a..b786248f34773046434364d3ddc887ecd6d59e3a 100644
--- a/SAS/TMSS/src/tmss/tmssapp/populate.py
+++ b/SAS/TMSS/src/tmss/tmssapp/populate.py
@@ -55,6 +55,12 @@ def populate_test_data():
             from lofar.sas.tmss.test.tmss_test_data_django_models import SchedulingSet_test_data, SchedulingUnitDraft_test_data
             from lofar.sas.tmss.tmss.tmssapp.tasks import create_task_blueprints_and_subtasks_from_scheduling_unit_draft, create_task_blueprints_and_subtasks_and_schedule_subtasks_from_scheduling_unit_draft
             from lofar.sas.tmss.tmss.tmssapp.subtasks import schedule_subtask
+            from lofar.common.json_utils import get_default_json_object_for_schema
+
+            constraints_template = models.SchedulingConstraintsTemplate.objects.get(name="constraints")
+            constraints_spec = get_default_json_object_for_schema(constraints_template.schema)
+
+            strategy_template = models.SchedulingUnitObservingStrategyTemplate.objects.get(name="UC1 CTC+pipelines")
 
             # create a Test Scheduling Set UC1 under project TMSS-Commissioning
             tmss_project = models.Project.objects.get(name="TMSS-Commissioning")
@@ -67,8 +73,6 @@ def populate_test_data():
                 logger.info('created test scheduling_set: %s', scheduling_set.name)
 
                 for unit_nr in range(5):
-                    strategy_template = models.SchedulingUnitObservingStrategyTemplate.objects.get(name="UC1 CTC+pipelines")
-
 
                     # the 'template' in the strategy_template is a predefined json-data blob which validates against the given scheduling_unit_template
                     # a user might 'upload' a partial json-data blob, so add all the known defaults
@@ -79,7 +83,9 @@ def populate_test_data():
                                                                                       scheduling_set=scheduling_set,
                                                                                       requirements_template=strategy_template.scheduling_unit_template,
                                                                                       requirements_doc=scheduling_unit_spec,
-                                                                                      observation_strategy_template=strategy_template)
+                                                                                      observation_strategy_template=strategy_template,
+                                                                                      scheduling_constraints_doc=constraints_spec,
+                                                                                      scheduling_constraints_template=constraints_template)
                     scheduling_unit_draft.tags = ["TEST", "UC1"]
                     scheduling_unit_draft.save()
 
diff --git a/SAS/TMSS/src/tmss/tmssapp/schemas/scheduling_constraints_template-constraints-1.json b/SAS/TMSS/src/tmss/tmssapp/schemas/scheduling_constraints_template-constraints-1.json
index 04bb208f0b4deff2d4a7d0491ef4108afe335922..77a916705c8df50c069f5929e11fc03d5586acf7 100644
--- a/SAS/TMSS/src/tmss/tmssapp/schemas/scheduling_constraints_template-constraints-1.json
+++ b/SAS/TMSS/src/tmss/tmssapp/schemas/scheduling_constraints_template-constraints-1.json
@@ -1,13 +1,32 @@
 {
+  "$id":"http://tmss.lofar.org/api/schemas/schedulingconstraintstemplate/constraints/1#",
   "$schema": "http://json-schema.org/draft-06/schema#",
-  "title": "Constraints",
-  "description": "This schema defines the constraints for a scheduling unit",
+  "title": "constraints",
+  "description": "This schema defines the scheduling constraints for a scheduling unit",
   "version": 1,
   "definitions": {
     "timestamp": {
+      "description": "A timestamp defined in UTC",
       "type": "string",
-      "pattern": "\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+Z",
-      "format": "datetime"
+      "pattern": "\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d(\\.\\d+)?Z",
+      "format": "date-time"
+    },
+    "timewindow": {
+      "type": "object",
+      "description": "A timewindow interval: [from, to)",
+      "properties": {
+        "from": {
+          "$ref": "#/definitions/timestamp"
+        },
+        "to": {
+          "$ref": "#/definitions/timestamp"
+        }
+      },
+      "additionalProperties": false,
+      "required": [
+        "from",
+        "to"
+      ]
     },
     "distance_on_sky": {
       "type": "number",
@@ -24,7 +43,7 @@
   "properties": {
     "scheduler": {
       "name": "Scheduler",
-      "description": "Which scheduling system wiil schedule this",
+      "description": "Which scheduling system will schedule this",
       "type": "string",
       "enum": [
         "manual",
@@ -34,6 +53,7 @@
     },
     "time": {
       "type": "object",
+      "default": {},
       "properties": {
         "at": {
           "description": "Start at this moment",
@@ -51,41 +71,28 @@
           "description": "Run within one of these time windows",
           "type": "array",
           "items": {
-            "from": {
-              "$ref": "#/definitions/timestamp"
-            },
-            "to": {
-              "$ref": "#/definitions/timestamp"
-            },
-            "required": [
-              "from",
-              "to"
-            ]
+            "$ref": "#/definitions/timewindow"
           },
-          "additionalItems": false
+          "minItems":0,
+          "uniqueItems":true,
+          "default": []
         },
         "not_between": {
-          "description": "NOT run within one of these time windows",
+          "description": "Do NOT run within any of these time windows",
           "type": "array",
           "items": {
-            "from": {
-              "$ref": "#/definitions/timestamp"
-            },
-            "to": {
-              "$ref": "#/definitions/timestamp"
-            },
-            "required": [
-              "from",
-              "to"
-            ]
+            "$ref": "#/definitions/timewindow"
           },
-          "additionalItems": false
+          "minItems":0,
+          "uniqueItems":true,
+          "default": []
         }
       },
       "additionalProperties": false
     },
     "daily": {
       "type": "object",
+      "default": {},
       "properties": {
         "require_night": {
           "description": "Must run at night",
@@ -107,6 +114,7 @@
     },
     "sky": {
       "type": "object",
+      "default": {},
       "properties": {
         "min_calibrator_elevation": {
           "description": "Minimum elevation for all calibrator sources",
@@ -123,14 +131,14 @@
           "type": "object",
           "properties": {
             "from": {
-              "type": "integer",
-              "minimum": -43200,
-              "maximum": 43200
+              "type": "number",
+              "minimum": -0.20943951,
+              "maximum": 0.20943951
             },
             "to": {
-              "type": "integer",
-              "minimum": -43200,
-              "maximum": 43200
+              "type": "number",
+              "minimum": -0.20943951,
+              "maximum": 0.20943951
             }
           },
           "additionalProperties": false
@@ -157,7 +165,6 @@
       "additionalProperties": false
     }
   },
-  "additionalProperties": false,
   "required": [
     "scheduler"
   ]
diff --git a/SAS/TMSS/src/tmss/tmssapp/serializers/specification.py b/SAS/TMSS/src/tmss/tmssapp/serializers/specification.py
index dc0f28d734c988f0343ccd657564d789ca62e9ee..bf250c5a51a2781970924e9ec30eb415d147b9fe 100644
--- a/SAS/TMSS/src/tmss/tmssapp/serializers/specification.py
+++ b/SAS/TMSS/src/tmss/tmssapp/serializers/specification.py
@@ -288,6 +288,7 @@ class SchedulingSetSerializer(RelationalHyperlinkedModelSerializer):
 
 class SchedulingUnitDraftSerializer(RelationalHyperlinkedModelSerializer):
     requirements_doc = JSONEditorField(schema_source="requirements_template.schema")
+    scheduling_constraints_doc = JSONEditorField(schema_source="scheduling_constraints_template.schema")
     duration = FloatDurationField(read_only=True)
 
     class Meta:
diff --git a/SAS/TMSS/src/tmss/tmssapp/viewsets/CMakeLists.txt b/SAS/TMSS/src/tmss/tmssapp/viewsets/CMakeLists.txt
index 445e0bbe4672e5cdad3a5a41be8575dbf2169ff0..fc0325a523508e371b2456d96b3467274dae748d 100644
--- a/SAS/TMSS/src/tmss/tmssapp/viewsets/CMakeLists.txt
+++ b/SAS/TMSS/src/tmss/tmssapp/viewsets/CMakeLists.txt
@@ -6,8 +6,6 @@ set(_py_files
     lofar_viewset.py
     specification.py
     scheduling.py
-    helloworldflow.py
-    schedulingunitdemoflow.py
     )
 
 python_install(${_py_files}
diff --git a/SAS/TMSS/src/tmss/tmssapp/viewsets/__init__.py b/SAS/TMSS/src/tmss/tmssapp/viewsets/__init__.py
index 882458975ee4be50507620471ed1026433ddf589..93f3c7e6d54f95c40d6d9484aad802b13f9991ba 100644
--- a/SAS/TMSS/src/tmss/tmssapp/viewsets/__init__.py
+++ b/SAS/TMSS/src/tmss/tmssapp/viewsets/__init__.py
@@ -1,3 +1,2 @@
 from .specification import *
-from .scheduling import *
-from .schedulingunitdemoflow import *
\ No newline at end of file
+from .scheduling import *
\ No newline at end of file
diff --git a/SAS/TMSS/src/tmss/tmssapp/viewsets/scheduling.py b/SAS/TMSS/src/tmss/tmssapp/viewsets/scheduling.py
index af49948d1615bac654f06ea03f55f8b09f679d6a..731dea891e03bf199867741111d93e58a53910ed 100644
--- a/SAS/TMSS/src/tmss/tmssapp/viewsets/scheduling.py
+++ b/SAS/TMSS/src/tmss/tmssapp/viewsets/scheduling.py
@@ -144,6 +144,8 @@ class SubtaskViewSet(LOFARViewSet):
     filter_class = SubTaskFilter
     ordering = ('start_time',)
 
+    queryset = queryset.prefetch_related('state')
+
     @swagger_auto_schema(auto_schema=TextPlainAutoSchema,
                          responses={200: 'A LOFAR parset for this subtask (as plain text)',
                                     403: 'forbidden',
diff --git a/SAS/TMSS/src/tmss/tmssapp/viewsets/specification.py b/SAS/TMSS/src/tmss/tmssapp/viewsets/specification.py
index ce3fa163142398bbaf6ae6bf7e197b33b6311cd2..242f06d05a6084ad6f0aa64a46eec8ce75ac164d 100644
--- a/SAS/TMSS/src/tmss/tmssapp/viewsets/specification.py
+++ b/SAS/TMSS/src/tmss/tmssapp/viewsets/specification.py
@@ -307,6 +307,16 @@ class SchedulingUnitDraftViewSet(LOFARViewSet):
     queryset = models.SchedulingUnitDraft.objects.all()
     serializer_class = serializers.SchedulingUnitDraftSerializer
 
+    # prefetch all reverse related references from other models on their related_name to avoid a ton of duplicate queries
+    queryset = queryset.prefetch_related('copied_from') \
+                       .prefetch_related('scheduling_unit_blueprints')\
+                       .prefetch_related('task_drafts')
+
+    # preselect all references to other models to avoid even more duplicate queries
+    queryset = queryset.select_related('copies') \
+                       .select_related('copy_reason') \
+                       .select_related('scheduling_set')
+
     @swagger_auto_schema(responses={201: 'The Created SchedulingUnitBlueprint, see Location in Response header',
                                     403: 'forbidden'},
                          operation_description="Carve SchedulingUnitDraft in stone, and make an (uneditable) blueprint out of it.")
@@ -580,6 +590,9 @@ class SchedulingUnitBlueprintViewSet(LOFARViewSet):
     queryset = models.SchedulingUnitBlueprint.objects.all()
     serializer_class = serializers.SchedulingUnitBlueprintSerializer
 
+    # prefetch all reverse related references from other models on their related_name to avoid a ton of duplicate queries
+    queryset = queryset.prefetch_related('task_blueprints')
+
     @swagger_auto_schema(responses={201: "This SchedulingUnitBlueprint, with references to its created TaskBlueprints and (scheduled) Subtasks.",
                                     403: 'forbidden'},
                          operation_description="Create TaskBlueprint(s) for this scheduling unit, create subtasks, and schedule the ones that are not dependend on predecessors.")
@@ -633,6 +646,22 @@ class TaskDraftViewSet(LOFARViewSet):
     queryset = models.TaskDraft.objects.all()
     serializer_class = serializers.TaskDraftSerializer
 
+    # prefetch all reverse related references from other models on their related_name to avoid a ton of duplicate queries
+    queryset = queryset.prefetch_related('first_to_connect') \
+                       .prefetch_related('second_to_connect')\
+                       .prefetch_related('produced_by')\
+                       .prefetch_related('consumed_by')\
+                       .prefetch_related('task_blueprints')\
+                       .prefetch_related('copied_from')
+
+    # prefetch nested references in reverse models to avoid duplicate lookup queries
+    queryset = queryset.prefetch_related('first_to_connect__placement') \
+                       .prefetch_related('second_to_connect__placement')
+
+    # select all references to other models to avoid even more duplicate queries
+    queryset = queryset.select_related('copies') \
+                       .select_related('copy_reason')
+
     @swagger_auto_schema(responses={201: 'The created task blueprint, see Location in Response header',
                                     403: 'forbidden'},
                          operation_description="Carve this draft task specification in stone, and make an (uneditable) blueprint out of it.")
@@ -726,6 +755,17 @@ class TaskBlueprintViewSet(LOFARViewSet):
     queryset = models.TaskBlueprint.objects.all()
     serializer_class = serializers.TaskBlueprintSerializer
 
+    # prefetch all reverse related references from other models on their related_name to avoid a ton of duplicate queries
+    queryset = queryset.prefetch_related('first_to_connect')\
+                       .prefetch_related('second_to_connect')\
+                       .prefetch_related('produced_by')\
+                       .prefetch_related('consumed_by')\
+                       .prefetch_related('subtasks')
+
+    # prefetch nested references in reverse models to avoid duplicate lookup queries
+    queryset = queryset.prefetch_related('first_to_connect__placement') \
+                       .prefetch_related('second_to_connect__placement')
+
     @swagger_auto_schema(responses={201: "This TaskBlueprint, with it is created subtasks",
                                     403: 'forbidden'},
                          operation_description="Create subtasks.")
diff --git a/SAS/TMSS/src/tmss/urls.py b/SAS/TMSS/src/tmss/urls.py
index 37d9d081a3a3ecbee61e876ea3ee365b7c111ace..0776702860d8c041eb193e83f2ba72b78d1d8031 100644
--- a/SAS/TMSS/src/tmss/urls.py
+++ b/SAS/TMSS/src/tmss/urls.py
@@ -23,7 +23,7 @@ from django.views.generic.base import TemplateView, RedirectView
 
 from collections import OrderedDict
 from rest_framework import routers, permissions
-from .tmssapp import viewsets, models, serializers, views, workflows
+from .tmssapp import viewsets, models, serializers, views
 from rest_framework.documentation import include_docs_urls
 from drf_yasg.views import get_schema_view
 from drf_yasg import openapi
@@ -33,6 +33,8 @@ from datetime import datetime
 from material.frontend import urls as frontend_urls
 from viewflow.flow.viewset import FlowViewSet
 
+import debug_toolbar
+
 #
 # Django style patterns
 #
@@ -63,7 +65,8 @@ urlpatterns = [
     path('schemas/<str:template>/<str:name>/<str:version>', views.get_template_json_schema, name='get_template_json_schema'), #TODO: how to make trailing slash optional?
     path('schemas/<str:template>/<str:name>/<str:version>/', views.get_template_json_schema, name='get_template_json_schema'),
     path(r'util/utc', views.utc, name="system-utc"),
-    path(r'util/lst', views.lst, name="conversion-lst")
+    path(r'util/lst', views.lst, name="conversion-lst"),
+    path('__debug__/', include(debug_toolbar.urls)),
 ]
 
 
diff --git a/SAS/TMSS/src/tmss/workflowapp/CMakeLists.txt b/SAS/TMSS/src/tmss/workflowapp/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..94b72e83e35a77ab9b16f84b7647f8ab0c8af94a
--- /dev/null
+++ b/SAS/TMSS/src/tmss/workflowapp/CMakeLists.txt
@@ -0,0 +1,17 @@
+
+include(PythonInstall)
+
+set(_py_files
+    __init__.py
+    admin.py
+    apps.py
+    tests.py
+    )
+
+python_install(${_py_files}
+    DESTINATION lofar/sas/tmss/tmss/workflowapp)
+
+add_subdirectory(migrations)
+add_subdirectory(models)
+add_subdirectory(flows)
+add_subdirectory(viewsets)
diff --git a/SAS/TMSS/src/tmss/tmssapp/viewsets/helloworldflow.py b/SAS/TMSS/src/tmss/workflowapp/__init__.py
similarity index 100%
rename from SAS/TMSS/src/tmss/tmssapp/viewsets/helloworldflow.py
rename to SAS/TMSS/src/tmss/workflowapp/__init__.py
diff --git a/SAS/TMSS/src/tmss/workflowapp/admin.py b/SAS/TMSS/src/tmss/workflowapp/admin.py
new file mode 100644
index 0000000000000000000000000000000000000000..8c38f3f3dad51e4585f3984282c2a4bec5349c1e
--- /dev/null
+++ b/SAS/TMSS/src/tmss/workflowapp/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/SAS/TMSS/src/tmss/workflowapp/apps.py b/SAS/TMSS/src/tmss/workflowapp/apps.py
new file mode 100644
index 0000000000000000000000000000000000000000..d70dc7921a32145aa2a76285c3362041e091a358
--- /dev/null
+++ b/SAS/TMSS/src/tmss/workflowapp/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class WorkflowappConfig(AppConfig):
+    name = 'workflowapp'
diff --git a/SAS/TMSS/src/tmss/tmssapp/workflows/CMakeLists.txt b/SAS/TMSS/src/tmss/workflowapp/flows/CMakeLists.txt
similarity index 72%
rename from SAS/TMSS/src/tmss/tmssapp/workflows/CMakeLists.txt
rename to SAS/TMSS/src/tmss/workflowapp/flows/CMakeLists.txt
index 474aada33041160e598ac2b1a126d68971d75afd..769f922e4781a912f1c0488c3655f6ab61363d3a 100644
--- a/SAS/TMSS/src/tmss/tmssapp/workflows/CMakeLists.txt
+++ b/SAS/TMSS/src/tmss/workflowapp/flows/CMakeLists.txt
@@ -8,4 +8,4 @@ set(_py_files
     )
 
 python_install(${_py_files}
-    DESTINATION lofar/sas/tmss/tmss/tmssapp/workflows)
+    DESTINATION lofar/sas/tmss/tmss/workflowapp/flows)
diff --git a/SAS/TMSS/src/tmss/tmssapp/workflows/__init__.py b/SAS/TMSS/src/tmss/workflowapp/flows/__init__.py
similarity index 100%
rename from SAS/TMSS/src/tmss/tmssapp/workflows/__init__.py
rename to SAS/TMSS/src/tmss/workflowapp/flows/__init__.py
diff --git a/SAS/TMSS/src/tmss/tmssapp/workflows/helloworldflow.py b/SAS/TMSS/src/tmss/workflowapp/flows/helloworldflow.py
similarity index 97%
rename from SAS/TMSS/src/tmss/tmssapp/workflows/helloworldflow.py
rename to SAS/TMSS/src/tmss/workflowapp/flows/helloworldflow.py
index d3307efe5f773359de58c89bea4a8728fa809c05..cd7ee660823074d4a00e5dca9e87e240098442c9 100644
--- a/SAS/TMSS/src/tmss/tmssapp/workflows/helloworldflow.py
+++ b/SAS/TMSS/src/tmss/workflowapp/flows/helloworldflow.py
@@ -5,9 +5,7 @@ from viewflow.base import this, Flow
 from viewflow.compat import _
 from viewflow.flow import views as flow_views
 
-
-from lofar.sas.tmss.tmss.tmssapp import models
-
+from .. import models
 
 
 @frontend.register
diff --git a/SAS/TMSS/src/tmss/tmssapp/workflows/schedulingunitdemoflow.py b/SAS/TMSS/src/tmss/workflowapp/flows/schedulingunitdemoflow.py
similarity index 99%
rename from SAS/TMSS/src/tmss/tmssapp/workflows/schedulingunitdemoflow.py
rename to SAS/TMSS/src/tmss/workflowapp/flows/schedulingunitdemoflow.py
index a35c72db8e9430b929e9ada4f424bbf6a58527c9..0a2882d7a4550ef3ff8e60b190c4074f60356795 100644
--- a/SAS/TMSS/src/tmss/tmssapp/workflows/schedulingunitdemoflow.py
+++ b/SAS/TMSS/src/tmss/workflowapp/flows/schedulingunitdemoflow.py
@@ -8,7 +8,7 @@ from viewflow.activation import FuncActivation, ViewActivation
 from viewflow.flow.nodes import Signal
 from viewflow import mixins
 
-from lofar.sas.tmss.tmss.tmssapp import models
+from .. import models
 
 from viewflow import frontend, ThisObject
 from viewflow.activation import STATUS
diff --git a/SAS/TMSS/src/tmss/workflowapp/migrations/0001_initial.py b/SAS/TMSS/src/tmss/workflowapp/migrations/0001_initial.py
new file mode 100644
index 0000000000000000000000000000000000000000..2e95b97379265e5eb14cfd44e85357218eb63948
--- /dev/null
+++ b/SAS/TMSS/src/tmss/workflowapp/migrations/0001_initial.py
@@ -0,0 +1,50 @@
+# Generated by Django 3.0.9 on 2020-10-01 12:30
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        ('viewflow', '0008_jsonfield_and_artifact'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='SchedulingUnitDemo',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name', models.CharField(max_length=50)),
+                ('state', models.IntegerField()),
+            ],
+        ),
+        migrations.CreateModel(
+            name='HelloWorldProcess',
+            fields=[
+            ],
+            options={
+                'verbose_name': 'World Request',
+                'verbose_name_plural': 'World Requests',
+                'proxy': True,
+                'indexes': [],
+                'constraints': [],
+            },
+            bases=('viewflow.process',),
+        ),
+        migrations.CreateModel(
+            name='SchedulingUnitDemoProcess',
+            fields=[
+                ('process_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='viewflow.Process')),
+                ('text', models.CharField(max_length=150)),
+                ('approved', models.BooleanField(default=False)),
+                ('su', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='workflowapp.SchedulingUnitDemo')),
+            ],
+            options={
+                'abstract': False,
+            },
+            bases=('viewflow.process',),
+        ),
+    ]
diff --git a/SAS/TMSS/src/tmss/workflowapp/migrations/CMakeLists.txt b/SAS/TMSS/src/tmss/workflowapp/migrations/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..158ea7946445fcee8e52b00447df80a873e98ec2
--- /dev/null
+++ b/SAS/TMSS/src/tmss/workflowapp/migrations/CMakeLists.txt
@@ -0,0 +1,8 @@
+
+include(PythonInstall)
+
+
+FILE(GLOB _py_files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.py)
+
+python_install(${_py_files}
+    DESTINATION lofar/sas/tmss/tmss/workflowapp/migrations)
\ No newline at end of file
diff --git a/SAS/TMSS/src/tmss/workflowapp/migrations/__init__.py b/SAS/TMSS/src/tmss/workflowapp/migrations/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/SAS/TMSS/src/tmss/workflowapp/models/CMakeLists.txt b/SAS/TMSS/src/tmss/workflowapp/models/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1c94f0a15d5ade684111945ce5bb79dfe25f7a91
--- /dev/null
+++ b/SAS/TMSS/src/tmss/workflowapp/models/CMakeLists.txt
@@ -0,0 +1,11 @@
+
+include(PythonInstall)
+
+set(_py_files
+    __init__.py
+    helloworldflow.py
+    schedulingunitdemoflow.py
+    )
+
+python_install(${_py_files}
+    DESTINATION lofar/sas/tmss/tmss/workflowapp/models)
diff --git a/SAS/TMSS/src/tmss/workflowapp/models/__init__.py b/SAS/TMSS/src/tmss/workflowapp/models/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..45516795a25730483ebfa40c1fbdb5f533df8ebe
--- /dev/null
+++ b/SAS/TMSS/src/tmss/workflowapp/models/__init__.py
@@ -0,0 +1,2 @@
+from .helloworldflow import *
+from .schedulingunitdemoflow import *
\ No newline at end of file
diff --git a/SAS/TMSS/src/tmss/tmssapp/models/helloworldflow.py b/SAS/TMSS/src/tmss/workflowapp/models/helloworldflow.py
similarity index 100%
rename from SAS/TMSS/src/tmss/tmssapp/models/helloworldflow.py
rename to SAS/TMSS/src/tmss/workflowapp/models/helloworldflow.py
diff --git a/SAS/TMSS/src/tmss/tmssapp/models/schedulingunitdemoflow.py b/SAS/TMSS/src/tmss/workflowapp/models/schedulingunitdemoflow.py
similarity index 100%
rename from SAS/TMSS/src/tmss/tmssapp/models/schedulingunitdemoflow.py
rename to SAS/TMSS/src/tmss/workflowapp/models/schedulingunitdemoflow.py
diff --git a/SAS/TMSS/src/tmss/workflowapp/tests.py b/SAS/TMSS/src/tmss/workflowapp/tests.py
new file mode 100644
index 0000000000000000000000000000000000000000..7ce503c2dd97ba78597f6ff6e4393132753573f6
--- /dev/null
+++ b/SAS/TMSS/src/tmss/workflowapp/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/SAS/TMSS/src/tmss/workflowapp/viewsets/CMakeLists.txt b/SAS/TMSS/src/tmss/workflowapp/viewsets/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7adc12fcf7a85912784409d17f37177986c94298
--- /dev/null
+++ b/SAS/TMSS/src/tmss/workflowapp/viewsets/CMakeLists.txt
@@ -0,0 +1,10 @@
+
+include(PythonInstall)
+
+set(_py_files
+    __init__.py
+    schedulingunitdemoflow.py
+    )
+
+python_install(${_py_files}
+    DESTINATION lofar/sas/tmss/tmss/workflowapp/viewsets)
diff --git a/SAS/TMSS/src/tmss/workflowapp/viewsets/__init__.py b/SAS/TMSS/src/tmss/workflowapp/viewsets/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..b77c70aeb959e9d4f63c395fd1079cfbbe3bc078
--- /dev/null
+++ b/SAS/TMSS/src/tmss/workflowapp/viewsets/__init__.py
@@ -0,0 +1 @@
+from .schedulingunitdemoflow import *
\ No newline at end of file
diff --git a/SAS/TMSS/src/tmss/tmssapp/viewsets/schedulingunitdemoflow.py b/SAS/TMSS/src/tmss/workflowapp/viewsets/schedulingunitdemoflow.py
similarity index 92%
rename from SAS/TMSS/src/tmss/tmssapp/viewsets/schedulingunitdemoflow.py
rename to SAS/TMSS/src/tmss/workflowapp/viewsets/schedulingunitdemoflow.py
index ea117c0f9c27a4324fe76c77fe1256e1b1eca446..da3dc24e15ff6f3bd93da9037101a718f4ebed66 100644
--- a/SAS/TMSS/src/tmss/tmssapp/viewsets/schedulingunitdemoflow.py
+++ b/SAS/TMSS/src/tmss/workflowapp/viewsets/schedulingunitdemoflow.py
@@ -3,7 +3,7 @@ from rest_framework import viewsets
 from rest_framework.response import Response
 from rest_framework.decorators import action
 from rest_framework.serializers import ModelSerializer
-from lofar.sas.tmss.tmss.tmssapp import models
+from lofar.sas.tmss.tmss.workflowapp import models
 
 # Create your views here.
 
diff --git a/SAS/TMSS/test/t_tmssapp_specification_REST_API.py b/SAS/TMSS/test/t_tmssapp_specification_REST_API.py
index 5bb9e175d4324f9ecdaa40176243dde8fa0da040..018c985f4b69f7b626564bda91f076dcc49591b9 100755
--- a/SAS/TMSS/test/t_tmssapp_specification_REST_API.py
+++ b/SAS/TMSS/test/t_tmssapp_specification_REST_API.py
@@ -1335,11 +1335,10 @@ class SchedulingUnitDraftTestCase(unittest.TestCase):
         GET_OK_and_assert_equal_expected_response(self, url, test_data)
 
     def test_GET_SchedulingUnitDraft_list_view_shows_entry(self):
-
         test_data_1 = SchedulingUnitDraft_test_data("scheduler unit draft one")
-        models.SchedulingUnitDraft.objects.create(**test_data_1)
+        obj = models.SchedulingUnitDraft.objects.create(**test_data_1)
         nbr_results = models.SchedulingUnitDraft.objects.count()
-        GET_and_assert_in_expected_response_result_list(self, BASE_URL + '/scheduling_unit_draft/', test_data_1, nbr_results)
+        GET_and_assert_in_expected_response_result_list(self, BASE_URL + '/scheduling_unit_draft/', test_data_1, nbr_results, obj.id)
 
     def test_GET_SchedulingUnitDraft_view_returns_correct_entry(self):
 
@@ -1385,8 +1384,8 @@ class SchedulingUnitDraftTestCase(unittest.TestCase):
 
         # setup
         test_data_1 = SchedulingUnitDraft_test_data("scheduler unit draft one")
-        tdt_test_data_1 = TaskDraft_test_data("task draft one")
-        tdt_test_data_2 = TaskDraft_test_data("task draft two")
+        tdt_test_data_1 = TaskDraft_test_data("task draft one of su1")
+        tdt_test_data_2 = TaskDraft_test_data("task draft two of su2 ")
         scheduling_unit_draft = models.SchedulingUnitDraft.objects.create(**test_data_1)
         task_draft_1 = models.TaskDraft.objects.create(**tdt_test_data_1)
         task_draft_1.scheduling_unit_draft = scheduling_unit_draft
@@ -1522,9 +1521,9 @@ class TaskDraftTestCase(unittest.TestCase):
     def test_GET_TaskDraft_list_view_shows_entry(self):
 
         test_data_1 = TaskDraft_test_data("task draft")
-        models.TaskDraft.objects.create(**test_data_1)
+        obj = models.TaskDraft.objects.create(**test_data_1)
         nbr_results = models.TaskDraft.objects.count()
-        GET_and_assert_in_expected_response_result_list(self, BASE_URL + '/task_draft/', test_data_1, nbr_results)
+        GET_and_assert_in_expected_response_result_list(self, BASE_URL + '/task_draft/', test_data_1, nbr_results, obj.id)
 
     def test_GET_TaskDraft_view_returns_correct_entry(self):
 
@@ -1540,7 +1539,7 @@ class TaskDraftTestCase(unittest.TestCase):
     def test_nested_TaskDraft_are_filtered_according_to_SchedulingUnitDraft(self):
 
         # setup
-        test_data_1 = TaskDraft_test_data("task draft one")
+        test_data_1 = TaskDraft_test_data("task draft three")
         sudt_test_data_1 = SchedulingUnitDraft_test_data("scheduling unit draft one")
         scheduling_unit_draft_1 = models.SchedulingUnitDraft.objects.create(**sudt_test_data_1)
         test_data_1 = dict(test_data_1)
@@ -1552,7 +1551,7 @@ class TaskDraftTestCase(unittest.TestCase):
     def test_TaskDraft_contains_list_of_related_TaskBlueprint(self):
 
         # setup
-        test_data_1 = TaskDraft_test_data("task draft one")
+        test_data_1 = TaskDraft_test_data("task draft four")
         tbt_test_data_1 = TaskBlueprint_test_data()
         tbt_test_data_2 = TaskBlueprint_test_data()
         task_draft = models.TaskDraft.objects.create(**test_data_1)
@@ -1569,7 +1568,7 @@ class TaskDraftTestCase(unittest.TestCase):
     def test_TaskDraft_contains_lists_of_related_TaskRelationDraft(self):
 
         # setup
-        test_data_1 = TaskDraft_test_data("task draft one")
+        test_data_1 = TaskDraft_test_data("task draft five")
         task_draft = models.TaskDraft.objects.create(**test_data_1)
 
         trdt_test_data_1 = TaskRelationDraft_test_data()
diff --git a/SAS/TMSS/test/test_utils.py b/SAS/TMSS/test/test_utils.py
index 52e18d0a8a10191285b7daaf6266fdd00768a4bc..2edeaae66b24887a9491527b23bbe6518f4456ae 100644
--- a/SAS/TMSS/test/test_utils.py
+++ b/SAS/TMSS/test/test_utils.py
@@ -214,7 +214,7 @@ class TMSSDjangoServerInstance():
 
         # wait for server to be up and running....
         # or exit via TimeoutError
-        self.check_running_server(timeout=30)
+        self.check_running_server(timeout=60)
 
     def stop(self):
         '''
diff --git a/SAS/TMSS/test/tmss_test_environment_unittest_setup.py b/SAS/TMSS/test/tmss_test_environment_unittest_setup.py
index dc4f72644bf2b40058a6eb6571218f7cf6fd3d89..04b9882454838c474e06523d8017ebc9320aca07 100644
--- a/SAS/TMSS/test/tmss_test_environment_unittest_setup.py
+++ b/SAS/TMSS/test/tmss_test_environment_unittest_setup.py
@@ -134,7 +134,7 @@ def GET_and_assert_equal_expected_code(test_instance, url, expected_code):
     return r_dict
 
 
-def GET_and_assert_in_expected_response_result_list(test_instance, url, expected_content, expected_nbr_results):
+def GET_and_assert_in_expected_response_result_list(test_instance, url, expected_content, expected_nbr_results, expected_id=None):
     """
     GET from url and assert the expected code is returned and the expected content is in the response content
     Use this check when multiple results (list) are returned
@@ -159,7 +159,17 @@ def GET_and_assert_in_expected_response_result_list(test_instance, url, expected
             test_instance.assertIn(key, item.keys())
 
     if url_check:
-        assertDataWithUrls(test_instance, r_dict['results'][expected_nbr_results-1], expected_content)
+        # Find the expected id in result list if parameter is given (of curse for just one it does not make sense)
+        # There was an 'old' assumption that the last one should taken, but that is not reliable
+        if expected_id is not None:
+            for idx in range(0, expected_nbr_results):
+                if r_dict['results'][idx]['id'] == expected_id:
+                    expected_idx = idx
+                    break
+        else:
+            # this is the 'old' assumption that last object added will also be the last one in the result dict
+            expected_idx = expected_nbr_results-1
+        assertDataWithUrls(test_instance, r_dict['results'][expected_idx], expected_content)
     return r_dict