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 4dfd1a1e96fe5e7a4fc0ceb9643941fccc990edb..d611b7857cf365ed32c8eee56b0936e8eb7e5b87 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/components/Timeline/CalendarTimeline.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/components/Timeline/CalendarTimeline.js @@ -5,7 +5,8 @@ import Timeline, { SidebarHeader, DateHeader, CustomMarker, - CursorMarker + CursorMarker, + CustomHeader } from 'react-calendar-timeline'; import containerResizeDetector from 'react-calendar-timeline/lib/resize-detector/container'; import moment from 'moment'; @@ -83,7 +84,7 @@ export class CalendarTimeline extends Component { prevZoomRange: null, lineHeight: props.rowHeight || 50, // Row line height sidebarWidth: props.sidebarWidth || 200, - timeSteps: props.timeSteps || {minute: 60}, + timeSteps: props.timeSteps || {minute: 1}, canMove: props.itemsMovable || false, canResize: props.itemsResizable || false, canchangeGroup: props.itemGroupChangeable || true, @@ -126,6 +127,7 @@ export class CalendarTimeline extends Component { this.renderLSTDateHeader = this.renderLSTDateHeader.bind(this); this.renderCursor = this.renderCursor.bind(this); this.renderItem = this.renderItem.bind(this); + this.renderNormalSuntimeHeader = this.renderNormalSuntimeHeader.bind(this); //<<<<<<< Custom Renderer Functions //>>>>>> Functions of this component @@ -257,6 +259,14 @@ export class CalendarTimeline extends Component { :`Week (${this.state.timelineStartDate.week()}) / Day`}</div> <div style={{height:'30px'}}>{this.state.dayHeaderVisible?`UTC(Hr)`:`UTC(Day)`}</div> <div style={{height:'30px'}}>{this.state.dayHeaderVisible?`LST(Hr)`:`LST(Day)`}</div> + {this.state.viewType === UIConstants.timeline.types.NORMAL && + <div className="p-grid" + style={{height:this.props.showSunTimings?'30px':'0px', paddingTop:'10px', paddingLeft:'10px'}}> + <div className="col-4" style={{marginTop:'2px', paddingLeft:'5px', backgroundColor:'yellow', color: '#212529'}}>Sunrise</div> + <div className="col-4" style={{marginTop:'2px', paddingLeft:'5px', backgroundColor:'orange', color: '#212529'}}>Sunset</div> + <div className="col-4" style={{marginTop:'2px', paddingLeft:'5px', backgroundColor:'blue'}}>Night</div> + </div> + } </div> ); } @@ -345,7 +355,7 @@ export class CalendarTimeline extends Component { return <div {...getIntervalProps()} className="rct-dateHeader" style={divStyle}> { (this.state.timeHeaderLabelVisibile)? (showBorder)? - <span> + <span key={`utchead-${displayValue}`}> {displayValue} </span>: <> @@ -420,6 +430,75 @@ export class CalendarTimeline extends Component { } } + /** Custom renderer to show sunrise, sunset and night times */ + renderNormalSuntimeHeader({ + headerContext: { intervals }, + getRootProps, + getIntervalProps, + showPeriod, + data, + }) { + const sunTimeMap = this.state.sunTimeMap; + return ( + <div {...getRootProps()}> + {intervals.map(interval => { + const dayStyle = { + lineHeight: '30px', + backgroundColor: 'white', + color: 'white' + } + const nightStyle = { + lineHeight: '30px', + backgroundColor: 'blue', + color: 'blue' + } + const sunriseStyle = { + lineHeight: '30px', + backgroundColor: 'yellow', + color: 'yellow' + } + const sunsetStyle = { + lineHeight: '30px', + backgroundColor: 'orange', + color: 'orange' + } + // Get the intervals UTC date format and time + const intervalDate = interval.startTime.clone().utc().format("YYYYMMDDT12:00:00"); + const intervalTime = interval.startTime.clone().utc(); + // Get the suntime for the UTC date + const intervalDateSunTime = sunTimeMap[intervalDate]; + let intervalStyle = dayStyle; + // If suntime is available display suntime blocks + if (intervalDateSunTime) { + // Set 15 minutes duration for sunrise and sunset and create blocks accordingly + if (intervalTime.isBefore(intervalDateSunTime.sunrise) || + intervalTime.isAfter(intervalDateSunTime.sunset.clone().add(14, 'minutes'))) { + intervalStyle = nightStyle; + } else if (intervalTime.isSame(intervalDateSunTime.sunrise) || + intervalTime.isBefore(intervalDateSunTime.sunrise.clone().add(15, 'minutes'))) { + intervalStyle = sunriseStyle; + } else if (intervalTime.isSame(intervalDateSunTime.sunset) || + (intervalTime.isAfter(intervalDateSunTime.sunset) && + intervalTime.isBefore(intervalDateSunTime.sunset.clone().add(15, 'minutes')))) { + intervalStyle = sunsetStyle; + } + return ( + <div + {...getIntervalProps({ + interval, + style: intervalStyle + })} + > + </div> + ) + } else { + return (""); + } + })} + </div> + ) + } + /** * Function to render sunrise timings on the timeline view in normal view. * @param {Array} sunRiseTimings @@ -636,18 +715,22 @@ export class CalendarTimeline extends Component { * @param {moment} endTime */ setNormalSuntimings(startTime, endTime) { - let sunRiseTimings = [], sunSetTimings = []; + let sunRiseTimings = [], sunSetTimings = [], sunTimeMap={}; const noOfDays = endTime.diff(startTime, 'days'); for (const number of _.range(noOfDays+1)) { const date = startTime.clone().add(number, 'days').hours(12).minutes(0).seconds(0); - UtilService.getSunTimings(date.format("YYYYMMDDTHH:mm:ss")+"Z").then(timings => { + const formattedDate = date.format("YYYYMMDDTHH:mm:ss"); + UtilService.getSunTimings(formattedDate+"Z").then(timings => { + const sunriseTime = moment.utc(timings.sun_rise.split('.')[0]); + const sunsetTime = moment.utc(timings.sun_set.split('.')[0]); if (moment.utc(timings.sun_rise).isAfter(startTime)) { - sunRiseTimings.push(moment.utc(timings.sun_rise)); + sunRiseTimings.push(sunriseTime); } if (moment.utc(timings.sun_set).isBefore(endTime)) { - sunSetTimings.push(moment.utc(timings.sun_set)); + sunSetTimings.push(sunsetTime); } - this.setState({sunRiseTimings: sunRiseTimings, sunSetTimings: sunSetTimings}); + sunTimeMap[formattedDate] = {sunrise: sunriseTime, sunset: sunsetTime}; + this.setState({sunRiseTimings: sunRiseTimings, sunSetTimings: sunSetTimings, sunTimeMap: sunTimeMap}); }); } } @@ -718,6 +801,7 @@ export class CalendarTimeline extends Component { async changeZoomLevel(zoomLevel, isTimelineZoom) { zoomLevel = zoomLevel?zoomLevel: DEFAULT_ZOOM_LEVEL; const newZoomLevel = _.find(ZOOM_LEVELS, {'name': zoomLevel}); + this.setState({isTimelineZoom: isTimelineZoom}); let startTime = this.state.defaultStartTime; let endTime = this.state.defaultEndTime; if (zoomLevel === 'Custom') { @@ -751,7 +835,7 @@ export class CalendarTimeline extends Component { let result = await this.changeDateRange(startTime, endTime); let group = DEFAULT_GROUP.concat(result.group); this.setState({zoomLevel: zoomLevel, defaultStartTime: startTime, defaultEndTime: endTime, - isTimelineZoom: isTimelineZoom, zoomRange: null, + isTimelineZoom: true, zoomRange: null, dayHeaderVisible: true, weekHeaderVisible: false, lstDateHeaderUnit: 'hour', group: group, items: result.items}); } @@ -1011,6 +1095,13 @@ export class CalendarTimeline extends Component { // This method will render once but will not update the values after fetching from server // <DateHeader unit={this.state.lstDateHeaderUnit} intervalRenderer={this.renderLSTDateHeader}></DateHeader> } + {/* Suntime Header in normal view with sunrise, sunset and night time */} + {this.props.showSunTimings && this.state.viewType === UIConstants.timeline.types.NORMAL && this.state.sunTimeMap && + <CustomHeader height={30} unit="minute" + children={({ headerContext: { intervals }, getRootProps, getIntervalProps, showPeriod, data})=> { + return this.renderNormalSuntimeHeader({ headerContext: { intervals }, getRootProps, getIntervalProps, showPeriod, data})}}> + </CustomHeader> + } </TimelineHeaders> <TimelineMarkers> 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 953df5906117caa9ba42ad60fef84ea12934a515..25e0ca50ba4e4546260f615e0ccb3150dc01d50a 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_timeline.scss +++ b/SAS/TMSS/frontend/tmss_webapp/src/layout/sass/_timeline.scss @@ -1,3 +1,9 @@ +.sticky { + position: sticky; + top:49px; + z-index:1000; +} + .rct-sidebar-row { font-size: 14px; }