From a867e9388a5b34b82abb7de1c2a85f8d8035b477 Mon Sep 17 00:00:00 2001
From: Ramesh Kumar <r.kumar@redkarma.eu>
Date: Tue, 15 Dec 2020 18:52:54 +0530
Subject: [PATCH] TMSS-485: Added colors to SU blocks as per the status
 definitions and legends for SU & Reservation blocks.

---
 .../components/Timeline/CalendarTimeline.js   |  75 ++++++++---
 .../src/layout/sass/_timeline.scss            | 120 +++++++++++++++++-
 .../tmss_webapp/src/routes/Timeline/view.js   |  10 +-
 .../src/routes/Timeline/week.view.js          |   9 +-
 .../tmss_webapp/src/services/util.service.js  |   1 +
 5 files changed, 183 insertions(+), 32 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 0088a24ce7a..0bf15377272 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/components/Timeline/CalendarTimeline.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/components/Timeline/CalendarTimeline.js
@@ -675,12 +675,13 @@ export class CalendarTimeline extends Component {
             itemContext.dimensions.height -= 3;
             if (!this.props.showSunTimings && this.state.viewType === UIConstants.timeline.types.NORMAL) {
                 if (item.type === "RESERVATION") {
-                    itemContext.dimensions.top -= 5;
-                    itemContext.dimensions.height += 8;
+                    itemContext.dimensions.top -= 13;
+                    itemContext.dimensions.height -= 2;
                 }   else {
                     itemContext.dimensions.top -= 15;
-                    itemContext.dimensions.height += 12;
                 }
+            }   else if (this.state.viewType === UIConstants.timeline.types.WEEKVIEW) {
+                itemContext.dimensions.top -= (this.props.rowHeight-10);
             }   else {
                 itemContext.dimensions.top += 3;
             }
@@ -699,8 +700,9 @@ export class CalendarTimeline extends Component {
                                   textAlign: "center"};
         }
         return (
-          <div
+          <div 
             {...getItemProps({
+              className: `rct-item su-${item.status}`,
               style: {
                 background: backgroundColor,
                 color: item.color,
@@ -734,7 +736,8 @@ export class CalendarTimeline extends Component {
               }}
             >
               { this.state.viewType===UIConstants.timeline.types.WEEKVIEW && item.type !== "SUNTIME" &&
-                <><div style={itemContentStyle}><i style={{fontSize:"12px"}} className="fa fa-user" title="Friend"></i><span>{item.project}</span></div>
+                <><div style={itemContentStyle}>
+                    <i style={{fontSize:"12px"}} className={`fa fa-user su-${item.status}-icon`} title="Friend"></i><span>{item.project}</span></div>
                     <div style={itemContentStyle}><span>{item.duration}</span></div>
                     <div style={itemContentStyle}><span>{item.band}</span></div> </>}
               {this.state.viewType===UIConstants.timeline.types.NORMAL &&
@@ -834,20 +837,22 @@ export class CalendarTimeline extends Component {
             const date = startTime.clone().add(number, 'days').hours(12).minutes(0).seconds(0);
             const formattedDate = date.format("YYYY-MM-DD");
             UtilService.getSunTimings(formattedDate).then(timings => {
-                const sunriseStartTime = moment.utc(timings.sun_rise.start.split('.')[0]);
-                const sunriseEndTime = moment.utc(timings.sun_rise.end.split('.')[0]);
-                const sunsetStartTime = moment.utc(timings.sun_set.start.split('.')[0]);
-                const sunsetEndTime = moment.utc(timings.sun_set.end.split('.')[0]);
-                const sunriseTime = {start: sunriseStartTime, end: sunriseEndTime};
-                const sunsetTime = {start: sunsetStartTime, end: sunsetEndTime};
-                if (moment.utc(timings.sunriseEndTime).isAfter(startTime)) {
-                    sunRiseTimings.push(sunriseTime);
-                }
-                if (moment.utc(timings.sunsetStartTime).isBefore(endTime)) {
-                    sunSetTimings.push(sunsetTime);
+                if (timings) {
+                    const sunriseStartTime = moment.utc(timings.sun_rise.start.split('.')[0]);
+                    const sunriseEndTime = moment.utc(timings.sun_rise.end.split('.')[0]);
+                    const sunsetStartTime = moment.utc(timings.sun_set.start.split('.')[0]);
+                    const sunsetEndTime = moment.utc(timings.sun_set.end.split('.')[0]);
+                    const sunriseTime = {start: sunriseStartTime, end: sunriseEndTime};
+                    const sunsetTime = {start: sunsetStartTime, end: sunsetEndTime};
+                    if (moment.utc(timings.sunriseEndTime).isAfter(startTime)) {
+                        sunRiseTimings.push(sunriseTime);
+                    }
+                    if (moment.utc(timings.sunsetStartTime).isBefore(endTime)) {
+                        sunSetTimings.push(sunsetTime);
+                    }
+                    sunTimeMap[formattedDate] = {sunrise: sunriseTime, sunset: sunsetTime};
+                    this.setState({sunRiseTimings: sunRiseTimings, sunSetTimings: sunSetTimings, sunTimeMap: sunTimeMap});
                 }
-                sunTimeMap[formattedDate] = {sunrise: sunriseTime, sunset: sunsetTime};
-                this.setState({sunRiseTimings: sunRiseTimings, sunSetTimings: sunSetTimings, sunTimeMap: sunTimeMap});
             });
         }
     }
@@ -987,7 +992,7 @@ export class CalendarTimeline extends Component {
             }
         }
         if (this.state.viewType === UIConstants.timeline.types.WEEKVIEW) {
-            items = sunItems;
+            items = _.orderBy(sunItems, ['type'], ['desc']);
         }
         return items;
     }
@@ -1101,7 +1106,7 @@ export class CalendarTimeline extends Component {
             newVisibleTimeEnd = this.state.timelineEndDate.clone().hours(23).minutes(59).minutes(59);
             newVisibleTimeStart = newVisibleTimeEnd.clone().add((-1 * visibleTimeDiff/1000), 'seconds');
         }
-        let result = await this.changeDateRange(visibleTimeStart, visibleTimeEnd);
+        let result = await this.changeDateRange(newVisibleTimeStart, newVisibleTimeEnd);
         this.loadLSTDateHeaderMap(newVisibleTimeStart, newVisibleTimeEnd, 'hour');
         let group = DEFAULT_GROUP.concat(result.group);
         this.setState({defaultStartTime: newVisibleTimeStart,
@@ -1187,7 +1192,6 @@ export class CalendarTimeline extends Component {
         weekHeaderVisible = rangeDays > 35?true: false; 
         lstDateHeaderUnit = rangeDays > 35?"day":"hour";
         const items = await this.addWeekSunTimes(timelineStart, timelineEnd, group, result.items);
-        console.log(items);
         this.setState({defaultStartTime: timelineStart, defaultEndTime: timelineEnd,
                         timelineStartDate: timelineStart, timelineEndDate: timelineEnd,
                         zoomLevel: this.ZOOM_LEVELS[this.ZOOM_LEVELS.length-1].name, isTimelineZoom: false,
@@ -1280,6 +1284,35 @@ export class CalendarTimeline extends Component {
                         <button className="p-link" title="Move Right" onClick={e=> { this.moveRight() }}><i className="pi pi-angle-right"></i></button>
                     </div>
                 </div>
+                <div className="p-grid legendbar">
+                    <div className="col-9">
+                        <div style={{fontWeight:'500', height: '25px'}}>Scheduling Unit 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-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>
+                            <div className='col-1 su-legend su-processed' title="Processed">Processed</div>
+                            <div className='col-1 su-legend su-ingesting' title="Ingesting">Ingesting</div>
+                            <div className='col-1 su-legend su-finished' title="Finished">Finished</div>
+                        </div>
+                    </div>
+                    {!this.props.showSunTimings && this.state.viewType===UIConstants.timeline.types.NORMAL &&
+                    <div className="col-3">
+                        <div style={{fontWeight:'500', height: '25px'}}>Station Reservation</div>
+                        <div className="p-grid">
+                            <div className="col-3 su-legend reserve-not-available" title="Not Available">NA</div>
+                            <div className="col-3 su-legend reserve-available" title="Available">Available</div>
+                            <div className="col-3 su-legend reserve-manual" title="Manual">Manual</div>
+                            <div className="col-3 su-legend reserve-dynamic" title="Dynamic">Dynamic</div>
+                        </div>
+                    </div>
+                    }
+                </div>
                 <Timeline
                     groups={this.state.group}
                     items={this.state.items}
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 51b2e71b3a4..1c97ef47ffd 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_timeline.scss
+++ b/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_timeline.scss
@@ -1,6 +1,6 @@
 .sticky {
     position: sticky;
-    top:49px;
+    top:67px;
     z-index:999;
 }
 
@@ -221,6 +221,118 @@
     cursor: not-allowed;
     color: #928f8f !important;
 }
-// .float-button:hover {
-//     right: -7px;//hide it by pushing it off the screen
-// }
\ No newline at end of file
+
+.reserve-not-available {
+    background-color: black;
+    color: white;
+}
+
+.reserve-available {
+    background-color: lightgrey;
+    color: #585859;
+}
+
+.reserve-manual {
+    background-color: #585859;
+    color: white;
+}
+
+.reserve.dynamic {
+    background-color: #9b9999;
+    color: white;
+}
+
+.su-error {
+    background-color: red !important;
+    color: white !important;
+}
+
+.su-cancelled {
+    background-color: orange !important;
+    color: black !important;
+}
+
+.su-defined {
+    background-color: white !important;
+    color: black !important;
+}
+
+.su-schedulable {
+    background-color: lightblue !important;
+    color: black !important;
+}
+
+.su-scheduled {
+    background-color: blue !important;
+    color: white !important;
+}
+
+.su-observing {
+    background-color: yellow !important;
+    color: black !important;
+}
+
+.su-observed {
+    background-color: green !important;
+    color: white !important;
+}
+
+.su-processing {
+    background: repeating-linear-gradient(
+                -45deg,
+                #f3f708,
+                #f3f708 5px,
+                #dcdf26 5px,
+                #dcdf26 10px
+                ) !important;
+}
+
+.su-processed {
+    background: repeating-linear-gradient(
+                -45deg,
+                #38f708,
+                #38f708 5px,
+                #2ad32a 5px,
+                #2ad32a 10px
+                ) !important;
+}
+
+.su-ingesting {
+    background-color: #c8a2c8 !important;
+    color: black !important;
+}
+
+.su-finished {
+    background-color: #1ff811 !important;
+    color: black !important;
+}
+
+.su-error-icon,.su-scheduled-icon,.su-observed-icon {
+    color: white !important;
+}
+
+.su-cancelled-icon,.su-defined-icon,.su-schedulable-icon,
+.su-observing-icon,.su-processing-icon,
+.su-processed-icon,.su-ingesting-icon,.su-finished-icon {
+    color: black !important;
+}
+
+.su-legend {
+    padding-left:6px !important;
+    border: 1px solid grey;
+    cursor: default;
+    overflow: hidden;
+    // text-overflow: ellipsis;
+    // white-space: nowrap;
+    text-align: center;
+}
+
+.legendbar {
+    // height: 20px;
+    font-size: 10px !important;
+    position: sticky;
+    top: 33px;
+    z-index: 999;
+    margin-top: 5px;
+    // margin-left: 8px;
+}
\ 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 546a132430b..f1324c0fca7 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/view.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/view.js
@@ -153,7 +153,9 @@ export class TimelineView extends Component {
             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"}; 
+            // selectedBgColor: suBlueprint.status? STATUS_COLORS[suBlueprint.status.toUpperCase()]:"#2196f3"}; 
+            selectedBgColor: "none",
+            status: suBlueprint.status.toLowerCase()};
         return item;
     }
 
@@ -235,7 +237,9 @@ export class TimelineView extends Component {
             group = this.state.group;
             items = this.state.items;
         }
-        this.setState({suBlueprintList: _.filter(suBlueprintList, (suBlueprint) => {return suBlueprint.start_time!=null})});
+        
+        this.setState({suBlueprintList: _.filter(suBlueprintList, (suBlueprint) => {return suBlueprint.start_time!=null}),
+                        currentStartTime: startTime, currentEndTime: endTime});
         // On range change close the Details pane
         // this.closeSUDets();
         return {group: this.stationView?this.allStationsGroup:_.sortBy(group,'id'), items: items};
@@ -482,7 +486,7 @@ export class TimelineView extends Component {
                                         group={this.state.group} 
                                         items={this.state.items}
                                         currentUTC={this.state.currentUTC}
-                                        rowHeight={this.state.stationView?20:30} itemClickCallback={this.onItemClick}
+                                        rowHeight={this.state.stationView?30:30} itemClickCallback={this.onItemClick}
                                         dateRangeCallback={this.dateRangeCallback}
                                         showSunTimings={!this.state.stationView}
                                         stackItems ={this.state.stationView}
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/week.view.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/week.view.js
index 67e9ef5c7e7..dfa2a14c18e 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/week.view.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/week.view.js
@@ -127,9 +127,6 @@ export class WeekTimelineView extends Component {
      * @param {Object} suBlueprint 
      */
     async getTimelineItem(suBlueprint, displayDate) {
-        // Temporary for testing
-        const diffOfCurrAndStart = moment().diff(moment(suBlueprint.stop_time), 'seconds');
-        suBlueprint.status = diffOfCurrAndStart>=0?"FINISHED":"DEFINED";
         let antennaSet = "";
         const taskList = await ScheduleService.getTaskBlueprintsBySchedulingUnit(suBlueprint, true);
         for (let task of taskList) {
@@ -148,7 +145,10 @@ export class WeekTimelineView extends Component {
             start_time: moment.utc(`${displayDate.format('YYYY-MM-DD')} ${suBlueprint.start_time.split('T')[1]}`),
             end_time: moment.utc(`${displayDate.format('YYYY-MM-DD')} ${suBlueprint.stop_time.split('T')[1]}`),
             bgColor: suBlueprint.status? STATUS_COLORS[suBlueprint.status.toUpperCase()]:"#2196f3",
-            selectedBgColor: suBlueprint.status? STATUS_COLORS[suBlueprint.status.toUpperCase()]:"#2196f3"}; 
+            // selectedBgColor: suBlueprint.status? STATUS_COLORS[suBlueprint.status.toUpperCase()]:"#2196f3"}
+            selectedBgColor: 'none',
+            type: 'SCHEDULE',
+            status: suBlueprint.status.toLowerCase()};
         return item;
     }
 
@@ -364,6 +364,7 @@ export class WeekTimelineView extends Component {
                                         currentUTC={this.state.currentUTC}
                                         rowHeight={50} itemClickCallback={this.onItemClick}
                                         sidebarWidth={150}
+                                        stackItems={true}
                                         startTime={moment.utc(this.state.currentUTC).hour(0).minutes(0).seconds(0)}
                                         endTime={moment.utc(this.state.currentUTC).hour(23).minutes(59).seconds(59)}
                                         zoomLevel="1 Day"
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/services/util.service.js b/SAS/TMSS/frontend/tmss_webapp/src/services/util.service.js
index 1f4d794901c..2ece93bd41a 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/services/util.service.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/services/util.service.js
@@ -61,6 +61,7 @@ const UtilService = {
         return sunTimings;
       } catch(error) {
         console.error(error);
+        return  null;
       }
     },
     /** Gets all reservations in the system */
-- 
GitLab