From e07aae079c62e6a4f2204ded0503308feaf5162d Mon Sep 17 00:00:00 2001
From: Ramesh Kumar <r.kumar@redkarma.eu>
Date: Wed, 30 Dec 2020 14:55:40 +0530
Subject: [PATCH] TMSS-471: Observation task items added in Timeline view

---
 .../components/Timeline/CalendarTimeline.js   |  22 ++-
 .../src/layout/sass/_timeline.scss            |   6 +-
 .../tmss_webapp/src/routes/Timeline/view.js   | 177 +++++++++++++++---
 .../src/services/schedule.service.js          |  22 ++-
 4 files changed, 184 insertions(+), 43 deletions(-)

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 b89a8f9b658..d9e2613a581 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/components/Timeline/CalendarTimeline.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/components/Timeline/CalendarTimeline.js
@@ -683,7 +683,12 @@ export class CalendarTimeline extends Component {
             }   else if (this.state.viewType === UIConstants.timeline.types.WEEKVIEW) {
                 itemContext.dimensions.top -= (this.props.rowHeight-5);
             }   else {
-                itemContext.dimensions.top += 3;
+                if (item.type === "TASK") {
+                    itemContext.dimensions.top += 6;
+                    itemContext.dimensions.height -= 10;
+                }   else {
+                    itemContext.dimensions.top += 3;
+                }
             }
             
         }
@@ -693,7 +698,7 @@ export class CalendarTimeline extends Component {
                                   fontSize: "14px",
                                   overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap",
                                   textAlign: "center"};
-        if (item.type === "SCHEDULE") {
+        if (item.type === "SCHEDULE" || item.type === "TASK") {
             itemContentStyle = {lineHeight: `${Math.floor(itemContext.dimensions.height/3)}px`, 
                                 maxHeight: itemContext.dimensions.height,
                                   fontSize: "12px", fontWeight: "600",
@@ -728,11 +733,15 @@ export class CalendarTimeline extends Component {
           >
             {itemContext.useResizeHandle ? <div {...leftResizeProps} /> : null}
     
-              { item.type === "SCHEDULE" &&
+                { item.type === "SCHEDULE" &&
                     <div style={itemContentStyle}>
                     <i style={{fontSize:"12px"}} className={`fa fa-user su-${item.status}-icon`} ></i>
                     <span>{`${item.project} - ${item.suId?item.suId:item.id} - ${item.name} - ${item.band} - ${item.duration}`}</span></div>
                 }
+                { item.type === "TASK" &&
+                    <div style={itemContentStyle}>
+                    <span>{`${item.project} - ${item.suId} - ${item.taskId} - ${item.name} - ${item.controlId} - ${item.typeValue} ${item.band?'- '+ item.band:''} - ${item.duration}`}</span></div>
+                }
 
               { (item.type === "SUNTIME" || item.type === "RESERVATION") &&
                 <div style={itemContentStyle}><span>{item.title}</span>
@@ -808,7 +817,7 @@ export class CalendarTimeline extends Component {
      * @param {Object} item 
      */
     onItemMouseOver(evt, item) {
-        if (item.type==="SCHEDULE" && this.props.itemMouseOverCallback) {
+        if ((item.type==="SCHEDULE" || item.type==="TASK") && this.props.itemMouseOverCallback) {
             this.props.itemMouseOverCallback(evt, item);
         }
     }
@@ -818,7 +827,7 @@ export class CalendarTimeline extends Component {
      * @param {Object} item 
      */
     onItemMouseOut(evt, item) {
-        if (item.type==="SCHEDULE" && this.props.itemMouseOutCallback) {
+        if ((item.type==="SCHEDULE" || item.type==="TASK") && this.props.itemMouseOutCallback) {
             this.props.itemMouseOutCallback(evt);
         }
     }
@@ -1317,13 +1326,14 @@ export class CalendarTimeline extends Component {
                 </div>
                 <div className="p-grid legendbar">
                     <div className="col-9">
-                        <div style={{fontWeight:'500', height: '25px'}}>Scheduling Unit Status</div>
+                        <div style={{fontWeight:'500', height: '25px'}}>Scheduling Unit / Task Status</div>
                         <div className="p-grid">
                             <div className="col-1 su-legend su-error" title="Error">Error</div>
                             <div className='col-1 su-legend su-cancelled' title="Cancelled">Cancelled</div>
                             <div className='col-1 su-legend su-defined' title="Defined">Defined</div>
                             <div className='col-1 su-legend su-schedulable' title="Schedulable">Schedulable</div>
                             <div className='col-1 su-legend su-scheduled' title="Scheduled">Scheduled</div>
+                            <div className='col-1 su-legend su-started' title="Started">Started</div>
                             <div className='col-1 su-legend su-observing' title="Observing">Observing</div>
                             <div className='col-1 su-legend su-observed' title="Observed">Observed</div>
                             <div className='col-1 su-legend su-processing' title="Processing">Processing</div>
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 4ab3f51872d..f7f598d34e1 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_timeline.scss
+++ b/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_timeline.scss
@@ -26,6 +26,10 @@
     margin-right: 10px;
 }
 
+.timeline-view-toolbar .p-radiobutton {
+    margin-top: -18px;
+}
+
 .timeline-toolbar-margin-top-0 {
     margin-top: 0px !important;
 }
@@ -267,7 +271,7 @@
     color: white !important;
 }
 
-.su-observing {
+.su-observing,.su-started  {
     background-color: yellow !important;
     color: black !important;
 }
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 4da1e5ee8d9..4c1ef42c262 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/view.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/view.js
@@ -19,12 +19,18 @@ import UnitConverter from '../../utils/unit.converter';
 import SchedulingUnitSummary from '../Scheduling/summary';
 import { Dropdown } from 'primereact/dropdown';
 import { OverlayPanel } from 'primereact/overlaypanel';
+import { RadioButton } from 'primereact/radiobutton';
 
-// Color constant for status
-const STATUS_COLORS = { "ERROR": "FF0000", "CANCELLED": "#00FF00", "DEFINED": "#00BCD4", 
-                        "SCHEDULABLE":"#0000FF", "SCHEDULED": "#abc", "OBSERVING": "#bcd",
-                        "OBSERVED": "#cde", "PROCESSING": "#cddc39", "PROCESSED": "#fed",
-                        "INGESTING": "#edc", "FINISHED": "#47d53d"};
+// Color constant for SU status
+const SU_STATUS_COLORS = { "ERROR": "FF0000", "CANCELLED": "#00FF00", "DEFINED": "#00BCD4", 
+                            "SCHEDULABLE":"#0000FF", "SCHEDULED": "#abc", "OBSERVING": "#bcd",
+                            "OBSERVED": "#cde", "PROCESSING": "#cddc39", "PROCESSED": "#fed",
+                            "INGESTING": "#edc", "FINISHED": "#47d53d"};
+
+// Color constant for Task status
+const TASK_STATUS_COLORS = { "ERROR": "FF0000", "CANCELLED": "#00FF00", "DEFINED": "#00BCD4", 
+                            "SCHEDULABLE":"#0000FF", "SCHEDULED": "#abc", "STARTED": "#bcd",
+                            "OBSERVED": "#cde", "FINISHED": "#47d53d"};
 
 const RESERVATION_COLORS = {"true-true":{bgColor:"lightgrey", color:"#585859"}, "true-false":{bgColor:'#585859', color:"white"},
                             "false-true":{bgColor:"#9b9999", color:"white"}, "false-false":{bgColor:"black", color:"white"}};
@@ -52,6 +58,8 @@ export class TimelineView extends Component {
             isSummaryLoading: false,
             stationGroup: [],
             reservationFilter: null,
+            showSUs: true,
+            showTasks: false
         }
         this.STATUS_BEFORE_SCHEDULED = ['defining', 'defined', 'schedulable'];  // Statuses before scheduled to get station_group
         this.allStationsGroup = [];
@@ -99,21 +107,22 @@ export class TimelineView extends Component {
                         suBlueprint.suSet = suSet;
                         suBlueprint.durationInSec = suBlueprint.duration;
                         suBlueprint.duration = UnitConverter.getSecsToHHmmss(suBlueprint.duration);
-                        // Load subtasks also to get stations from subtask if status is before scheduled
-                        const loadSubtasks = this.STATUS_BEFORE_SCHEDULED.indexOf(suBlueprint.status.toLowerCase()) < 0 ;
+                        // Load subtasks also to get stations & control ID from subtask if status is before scheduled
+                        //const loadSubtasks = this.STATUS_BEFORE_SCHEDULED.indexOf(suBlueprint.status.toLowerCase()) < 0 || this.state.showTasks;
+                        const loadSubtasks = true;
                         // Select only blueprints with start_time and stop_time in the default time limit
                         if (suBlueprint.start_time && 
                             (moment.utc(suBlueprint.start_time).isBetween(defaultStartTime, defaultEndTime) ||
                              moment.utc(suBlueprint.stop_time).isBetween(defaultStartTime, defaultEndTime))) {
                             // suBlueprint.tasks = await ScheduleService.getTaskBlueprintsBySchedulingUnit(suBlueprint, true);
-                            suBlueprint.tasks = await ScheduleService.getTaskBlueprintsBySchedulingUnit(suBlueprint, true, loadSubtasks);
+                            suBlueprint.tasks = await ScheduleService.getTaskBlueprintsBySchedulingUnit(suBlueprint, true, loadSubtasks, loadSubtasks);
                             items.push(this.getTimelineItem(suBlueprint));
                             if (!_.find(group, {'id': suDraft.id})) {
                                 group.push({'id': suDraft.id, title: suDraft.name});
                             }
                             suList.push(suBlueprint);
                         }   else if (suBlueprint.start_time) {  // For other SUs with start_time load details asynchronously
-                            ScheduleService.getTaskBlueprintsBySchedulingUnit(suBlueprint, true, loadSubtasks)
+                            ScheduleService.getTaskBlueprintsBySchedulingUnit(suBlueprint, true, loadSubtasks, loadSubtasks)
                                 .then(tasks => {
                                     suBlueprint.tasks = tasks;
                             })
@@ -169,13 +178,65 @@ export class TimelineView extends Component {
             duration: suBlueprint.durationInSec?`${(suBlueprint.durationInSec/3600).toFixed(2)}Hrs`:"",
             start_time: moment.utc(suBlueprint.start_time),
             end_time: moment.utc(suBlueprint.stop_time),
-            bgColor: suBlueprint.status? STATUS_COLORS[suBlueprint.status.toUpperCase()]:"#2196f3",
-            // selectedBgColor: suBlueprint.status? STATUS_COLORS[suBlueprint.status.toUpperCase()]:"#2196f3"}; 
+            bgColor: suBlueprint.status? SU_STATUS_COLORS[suBlueprint.status.toUpperCase()]:"#2196f3",
+            // selectedBgColor: suBlueprint.status? SU_STATUS_COLORS[suBlueprint.status.toUpperCase()]:"#2196f3"}; 
             selectedBgColor: "none",
             status: suBlueprint.status.toLowerCase()};
         return item;
     }
 
+    /**
+     * Get Timeline items for obsercation tasks of the SU Bluprint. Task Items are grouped to the SU draft and Task draft IDs
+     * @param {Object} suBlueprint 
+     */
+    getTaskItems(suBlueprint) {
+        let taskItems = {};
+        if (suBlueprint.tasks) {
+            let items = [], itemGroup = [];
+            for (let task of suBlueprint.tasks) {
+                if (task.template.type_value.toLowerCase() === "observation" && task.start_time && task.stop_time) {
+                    const antennaSet = task.specifications_doc.antenna_set;
+                    const start_time = moment.utc(task.start_time);
+                    const end_time = moment.utc(task.stop_time);
+                    const subTaskIds = task.subTasks.filter(subtask => subtask.template.name.indexOf('control') > 0);
+                    const controlId = subTaskIds.length>0 ? subTaskIds[0].id : ''; 
+                    let item = { id: `${suBlueprint.id}_${task.id}`, 
+                                suId: suBlueprint.id,
+                                taskId: task.id,
+                                controlId: controlId,
+                                group: `${suBlueprint.suDraft.id}_${task.draft_id}`,
+                                // group: `${suBlueprint.suDraft.id}_Tasks`,    // For single row task grouping
+                                title: '',
+                                project: suBlueprint.project, type: 'TASK',
+                                name: task.name,
+                                typeValue:task.template.type_value,
+                                band: antennaSet?antennaSet.split("_")[0]:"",
+                                antennaSet: antennaSet?antennaSet:"",
+                                duration: `${(end_time.diff(start_time, 'seconds')/3600).toFixed(2)}Hrs`,
+                                start_time: start_time,
+                                end_time: end_time,
+                                bgColor: task.status? TASK_STATUS_COLORS[task.status.toUpperCase()]:"#2196f3",
+                                selectedBgColor: "none",
+                                status: task.status.toLowerCase()};
+                    items.push(item);
+                    if (!_.find(itemGroup, ['id', `${suBlueprint.suDraft.id}_${task.draft_id}`])) {
+                        itemGroup.push({'id': `${suBlueprint.suDraft.id}_${task.draft_id}`, parent: suBlueprint.suDraft.id, 
+                                        start: start_time, title: `${!this.state.showSUs?suBlueprint.suDraft.name:""} -- ${task.name}`});
+                    }
+                    /* >>>>>> If all tasks should be shown in single row remove the above 2 lines and uncomment these lines
+                    if (!_.find(itemGroup, ['id', `${suBlueprint.suDraft.id}_Tasks`])) {
+                        itemGroup.push({'id': `${suBlueprint.suDraft.id}_Tasks`, parent: suBlueprint.suDraft.id, 
+                                        start_time: start_time, title: `${!this.state.showSUs?suBlueprint.suDraft.name:""} -- Tasks`});
+                    }
+                    <<<<<<*/
+                }
+            }
+            taskItems['items'] = items;
+            taskItems['group'] = itemGroup
+        }
+        return taskItems;
+    }
+
     /**
      * Callback function to pass to Timeline component for item click.
      * @param {Object} item 
@@ -201,7 +262,7 @@ export class TimelineView extends Component {
                             for (let task of taskList) {
                                 //Control Task Id
                                 const subTaskIds = (task.subTasks || []).filter(sTask => sTask.subTaskTemplate.name.indexOf('control') > 1);
-                                task. subTaskID = subTaskIds.length ? subTaskIds[0].id : ''; 
+                                task.subTaskID = subTaskIds.length ? subTaskIds[0].id : ''; 
                                 if (task.template.type_value.toLowerCase() === "observation") {
                                     task.antenna_set = task.specifications_doc.antenna_set;
                                     task.band = task.specifications_doc.filter;
@@ -241,10 +302,11 @@ export class TimelineView extends Component {
      * @param {Object} item
      */
     onItemMouseOver(evt, item) {
-        const itemSU = _.find(this.state.suBlueprints, {id: (this.state.stationView?item.suId:item.id)});
+        const itemSU = _.find(this.state.suBlueprints, {id: (item.suId?item.suId:item.id)});
         const itemStations = this.getSUStations(itemSU);
         const itemStationGroups = this.groupSUStations(itemStations);
         item.stations = {groups: "", counts: ""};
+        item.suName = itemSU.name;
         for (const stationgroup of _.keys(itemStationGroups)) {
             let groups = item.stations.groups;
             let counts = item.stations.counts;
@@ -285,15 +347,27 @@ export class TimelineView extends Component {
             for (const suBlueprint of this.state.suBlueprints) {
                 if (moment.utc(suBlueprint.start_time).isBetween(startTime, endTime) 
                         || moment.utc(suBlueprint.stop_time).isBetween(startTime, endTime)) {
-                    let timelineItem = this.getTimelineItem(suBlueprint);
+                    // Get timeline item for station view noramlly and in timeline view only if SU to be shown
+                    let timelineItem = (this.state.showSUs || this.state.stationView)?this.getTimelineItem(suBlueprint):null;
                     if (this.state.stationView) {
-                        const loadSubtasks = this.STATUS_BEFORE_SCHEDULED.indexOf(suBlueprint.status.toLowerCase()) < 0 ;
-                        suBlueprint.tasks = await ScheduleService.getTaskBlueprintsBySchedulingUnit(suBlueprint, true, loadSubtasks);
+                        const loadSubtasks = (this.STATUS_BEFORE_SCHEDULED.indexOf(suBlueprint.status.toLowerCase()) < 0 || this.state.showTasks);
+                        suBlueprint.tasks = await ScheduleService.getTaskBlueprintsBySchedulingUnit(suBlueprint, true, loadSubtasks, loadSubtasks);
                         this.getStationItemGroups(suBlueprint, timelineItem, this.allStationsGroup, items);
                     }   else {
-                        items.push(timelineItem);
-                        if (!_.find(group, {'id': suBlueprint.suDraft.id})) {
-                            group.push({'id': suBlueprint.suDraft.id, title: suBlueprint.suDraft.name});
+                        // Add timeline SU item
+                        if (timelineItem) {
+                            items.push(timelineItem);
+                            if (!_.find(group, {'id': suBlueprint.suDraft.id})) {
+                                /* parent and start properties are added to order and display task rows below the corresponding SU row */
+                                group.push({'id': suBlueprint.suDraft.id, parent: suBlueprint.suDraft.id, 
+                                            start: moment.utc("1900-01-01", "YYYY-MM-DD"), title: suBlueprint.suDraft.name});
+                            }
+                        }
+                        // Add task item only in timeline view and when show task is enabled
+                        if (this.state.showTasks && !this.state.stationView) {
+                            const taskItems = this.getTaskItems(suBlueprint);
+                            items = items.concat(taskItems.items);
+                            group = group.concat(taskItems.group);
                         }
                     }
                     suBlueprintList.push(suBlueprint);
@@ -312,7 +386,7 @@ export class TimelineView extends Component {
                         currentStartTime: startTime, currentEndTime: endTime});
         // On range change close the Details pane
         // this.closeSUDets();
-        return {group: this.stationView?this.allStationsGroup:_.sortBy(group,'id'), items: items};
+        return {group: this.stationView?this.allStationsGroup:_.orderBy(group,["parent", "id"], ['asc', 'desc']), items: items};
     }
 
     /**
@@ -438,6 +512,15 @@ export class TimelineView extends Component {
         this.setState({reservationFilter: filter});
     }
 
+    /**
+     * To enable displaying SU or Task or Both items in timeline.
+     * @param {String} value 
+     */
+    showTimelineItems(value) {
+        this.setState({showSUs: value==='su' || value==="suTask",
+                        showTasks: value==='task' || value==="suTask"});
+    }
+
     /**
      * Function called to shrink or expand the SU list section width
      * @param {number} step - (-1) to shrink and (+1) to expand
@@ -466,13 +549,22 @@ export class TimelineView extends Component {
         const suBlueprints = this.state.suBlueprints;
         for (const data of filteredData) {
             const suBlueprint = _.find(suBlueprints, {actionpath: data.actionpath});
-            let timelineItem = this.getTimelineItem(suBlueprint);
+            let timelineItem = (this.state.showSUs || this.state.stationView)?this.getTimelineItem(suBlueprint):null;
             if (this.state.stationView) {
                 this.getStationItemGroups(suBlueprint, timelineItem, this.allStationsGroup, items);
             }   else {
-                items.push(timelineItem);
-                if (!_.find(group, {'id': suBlueprint.suDraft.id})) {
-                    group.push({'id': suBlueprint.suDraft.id, title: suBlueprint.suDraft.name});
+                if (timelineItem) {
+                    items.push(timelineItem);
+                    if (!_.find(group, {'id': suBlueprint.suDraft.id})) {
+                        /* parent and start properties are added to order and list task rows below the SU row */
+                        group.push({'id': suBlueprint.suDraft.id, parent: suBlueprint.suDraft.id, 
+                                    start: moment.utc("1900-01-01", "YYYY-MM-DD"), title: suBlueprint.suDraft.name});
+                    }
+                }
+                if (this.state.showTasks && !this.state.stationView) {
+                    const taskItems = this.getTaskItems(suBlueprint);
+                    items = items.concat(taskItems.items);
+                    group = group.concat(taskItems.group);
                 }
             }
         }
@@ -480,7 +572,7 @@ export class TimelineView extends Component {
             items = this.addStationReservations(items, this.state.currentStartTime, this.state.currentEndTime);
         }
         if (this.timeline) {
-            this.timeline.updateTimeline({group: this.state.stationView?this.allStationsGroup:_.sortBy(group,"id"), items: items});
+            this.timeline.updateTimeline({group: this.state.stationView?this.allStationsGroup:_.orderBy(group,["parent", "start"], ['asc', 'asc']), items: items});
         }
     }
 
@@ -554,6 +646,17 @@ export class TimelineView extends Component {
                                                     placeholder="Reason"/>
                                     </>
                                     }
+                                    {!this.state.stationView &&
+                                    <>
+                                        <label style={{marginLeft: '10px'}}>Show :</label>
+                                        <RadioButton value="su" name="Only SUs" inputId="suOnly" onChange={(e) => this.showTimelineItems(e.value)} checked={this.state.showSUs && !this.state.showTasks} />
+                                        <label htmlFor="suOnly">Only SU</label>
+                                        <RadioButton value="task" name="Only Tasks" inputId="taskOnly" onChange={(e) => this.showTimelineItems(e.value)} checked={!this.state.showSUs && this.state.showTasks} />
+                                        <label htmlFor="suOnly">Only Task</label>
+                                        <RadioButton value="suTask" name="Both" inputId="bothSuTask" onChange={(e) => this.showTimelineItems(e.value)} checked={this.state.showSUs && this.state.showTasks} />
+                                        <label htmlFor="suOnly">Both</label>
+                                    </>
+                                    }
                                 </div>
                                 <Timeline ref={(tl)=>{this.timeline=tl}} 
                                         group={this.state.group} 
@@ -565,7 +668,8 @@ export class TimelineView extends Component {
                                         itemMouseOutCallback={this.onItemMouseOut}
                                         dateRangeCallback={this.dateRangeCallback}
                                         showSunTimings={!this.state.stationView}
-                                        stackItems ={this.state.stationView}
+                                        // stackItems ={this.state.stationView}
+                                        stackItems
                                         className="timeline-toolbar-margin-top-0"></Timeline>
                             </div>
                             {/* Details Panel */}
@@ -591,15 +695,26 @@ export class TimelineView extends Component {
                         <label className={`col-5 su-${mouseOverItem.status}-icon`}>Project:</label>
                         <div className="col-7">{mouseOverItem.project}</div>
                         <label className={`col-5 su-${mouseOverItem.status}-icon`}>Scheduling Unit:</label>
-                        <div className="col-7">{mouseOverItem.name}</div>
-                        <label className={`col-5 su-${mouseOverItem.status}-icon`}>Friends:</label>
-                        <div className="col-7">{mouseOverItem.friends?mouseOverItem.friends:"-"}</div>
+                        <div className="col-7">{mouseOverItem.suName}</div>
+                        {mouseOverItem.type==='SCHEDULE' &&
+                        <>
+                            <label className={`col-5 su-${mouseOverItem.status}-icon`}>Friends:</label>
+                            <div className="col-7">{mouseOverItem.friends?mouseOverItem.friends:"-"}</div>
+                        </>}
+                        {mouseOverItem.type==='TASK' &&
+                        <>
+                            <label className={`col-5 su-${mouseOverItem.status}-icon`}>Task Name:</label>
+                            <div className="col-7">{mouseOverItem.name}</div>
+                        </>}
                         <label className={`col-5 su-${mouseOverItem.status}-icon`}>Start Time:</label>
                         <div className="col-7">{mouseOverItem.start_time.format("YYYY-MM-DD HH:mm:ss")}</div>
                         <label className={`col-5 su-${mouseOverItem.status}-icon`}>End Time:</label>
                         <div className="col-7">{mouseOverItem.end_time.format("YYYY-MM-DD HH:mm:ss")}</div>
-                        <label className={`col-5 su-${mouseOverItem.status}-icon`}>Antenna Set:</label>
-                        <div className="col-7">{mouseOverItem.antennaSet}</div>
+                        {mouseOverItem.type==='SCHEDULE' &&
+                        <>
+                            <label className={`col-5 su-${mouseOverItem.status}-icon`}>Antenna Set:</label>
+                            <div className="col-7">{mouseOverItem.antennaSet}</div>
+                        </>}
                         <label className={`col-5 su-${mouseOverItem.status}-icon`}>Stations:</label>
                         <div className="col-7">{mouseOverItem.stations.groups}:{mouseOverItem.stations.counts}</div>
                         <label className={`col-5 su-${mouseOverItem.status}-icon`}>Status:</label>
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 c4361162f4c..edc85678a25 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/services/schedule.service.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/services/schedule.service.js
@@ -97,7 +97,7 @@ const ScheduleService = {
             return null;
         }
     },
-    getTaskBlueprintById: async function(id, loadTemplate, loadSubtasks){
+    getTaskBlueprintById: async function(id, loadTemplate, loadSubtasks, loadSubtaskTemplate){
         let result;
         try {
             result = await axios.get('/api/task_blueprint/'+id);
@@ -105,9 +105,21 @@ const ScheduleService = {
                 result.data.template = await TaskService.getTaskTemplate(result.data.specifications_template_id);
             }
             if (result.data && loadSubtasks) {
-                let subTasks = [];
+                let subTasks = [], subtaskemplates = {};
                 for (const subtaskId of result.data.subtasks_ids) {
-                    subTasks.push((await TaskService.getSubtaskDetails(subtaskId)));
+                    let subtask = await TaskService.getSubtaskDetails(subtaskId);
+                    if (loadSubtaskTemplate) {
+                        //To avoid repeated api call for template if it has already loaded
+                        if (subtaskemplates[subtask.specifications_template_id]) {
+                            subtask.template = subtaskemplates[subtask.specifications_template_id];
+                        } else {
+                            const subtaskTemplate = await TaskService.getSubtaskTemplate(subtask.specifications_template_id);
+                            subtask.template = subtaskTemplate;
+                            subtaskemplates[subtask.specifications_template_id] = subtaskTemplate;
+                        }
+                    }
+                    subTasks.push((subtask));
+                    // subTasks.push((await TaskService.getSubtaskDetails(subtaskId)));
                 }
                 result.data.subTasks = subTasks;
             }
@@ -116,12 +128,12 @@ const ScheduleService = {
         }
         return result;
     },
-    getTaskBlueprintsBySchedulingUnit: async function(scheduleunit, loadTemplate, loadSubtasks){
+    getTaskBlueprintsBySchedulingUnit: async function(scheduleunit, loadTemplate, loadSubtasks, loadSubtaskTemplate){
         // 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, loadTemplate, loadSubtasks).then(response =>{
+               await this.getTaskBlueprintById(id, loadTemplate, loadSubtasks, loadSubtaskTemplate).then(response =>{
                     let taskblueprint = response.data;
                     taskblueprint['tasktype'] = 'Blueprint';
                     taskblueprint['actionpath'] = '/task/view/blueprint/'+taskblueprint['id'];
-- 
GitLab