Skip to content

Commit

Permalink
Merge pull request #1110 from mdhaman/fix-featured-stories
Browse files Browse the repository at this point in the history
[SDESK-3803] Modified featured stories dialog so that featured stories are created based on server timezone.
  • Loading branch information
Mayur Dhamanwala committed Jan 13, 2019
2 parents 4dabcb8 + a9e7e1e commit 84d1952
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 34 deletions.
14 changes: 10 additions & 4 deletions client/actions/planning/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,13 @@ const getCriteria = ({
excludeRescheduledAndCancelled = false,
startOfWeek = 0,
featured,
timezoneOffset = null,
}) => {
let query = {};
let mustNot = [];
let must = [];
let filter = {};
let tzOffset = timezoneOffset || getTimeZoneOffset();

[
{
Expand Down Expand Up @@ -152,7 +154,7 @@ const getCriteria = ({
range: {
'_planning_schedule.scheduled': {
gte: 'now/d',
time_zone: getTimeZoneOffset(),
time_zone: tzOffset,
},
},
},
Expand All @@ -165,7 +167,7 @@ const getCriteria = ({
let fieldName = '_planning_schedule.scheduled';
let range = {};

range[fieldName] = {time_zone: getTimeZoneOffset()};
range[fieldName] = {time_zone: tzOffset};
let rangeType = get(advancedSearch, 'dates.range');

if (rangeType === MAIN.DATE_RANGE.TODAY) {
Expand Down Expand Up @@ -348,11 +350,14 @@ const query = (
excludeRescheduledAndCancelled = false,
featured,
},
storeTotal = true
storeTotal = true,
timeZoneOffset = null

) => (
(dispatch, getState, {api}) => {
const startOfWeek = selectors.config.getStartOfWeek(getState());
let tzOffset = timeZoneOffset || getTimeZoneOffset();
// eslint-disable-next-line object-shorthand
let criteria = self.getCriteria({
spikeState,
agendas,
Expand All @@ -363,6 +368,7 @@ const query = (
excludeRescheduledAndCancelled,
startOfWeek,
featured,
timezoneOffset: tzOffset,
});

const sortField = '_planning_schedule.scheduled';
Expand All @@ -374,7 +380,7 @@ const query = (
range: {
[sortField]: {
gte: 'now/d',
time_zone: getTimeZoneOffset(),
time_zone: tzOffset,
},
},
},
Expand Down
21 changes: 15 additions & 6 deletions client/actions/planning/featuredPlanning.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import {
gettext,
getIdForFeauturedPlanning,
planningUtils,
getTimeZoneOffset,
} from '../../utils';

import * as selectors from '../../selectors';
import {MODALS, FEATURED_PLANNING, SPIKED_STATE, MAIN, TIME_COMPARISON_GRANULARITY} from '../../constants';
import {get, findIndex} from 'lodash';
import moment from 'moment';
import momentTz from 'moment-timezone';


/**
Expand Down Expand Up @@ -117,8 +119,9 @@ const receivePlannings = (plannings, append = false) => (
* @return Promise
*/
const loadFeaturedPlanningsData = (date) => (
(dispatch) => {
let startDate = date ? date : moment();
(dispatch, getState) => {
const timezone = selectors.config.defaultTimeZone(getState());
let startDate = momentTz.tz(date ? date : moment(), timezone);
const params = {
advancedSearch: {
dates: {
Expand Down Expand Up @@ -172,7 +175,11 @@ const fetchToList = (params = {}, append = false) => (
const currentItemCount = Object.keys(selectors.featuredPlanning.storedPlannings(getState())).length;

dispatch(self.requestFeaturedPlannings(params));
return dispatch(planningApi.query(params, false))
return dispatch(planningApi.query(
params,
false,
getTimeZoneOffset(momentTz.tz(moment(), selectors.config.defaultTimeZone(getState()))))
)
.then((data) => {
dispatch(self.total(data.total));
dispatch(self.receivePlannings(data._items, append));
Expand Down Expand Up @@ -326,14 +333,16 @@ const onPlanningUpdatedNotification = (planningId) => (
.then((item) => {
const currentSearchDate = selectors.featuredPlanning.currentSearchDate(getState());
const currentFeaturedPlannings = selectors.featuredPlanning.storedPlannings(getState());
const timezone = selectors.config.defaultTimeZone(getState());
const planningsForDate = get(planningUtils.getPlanningByDate([item], null,
moment(currentSearchDate.format('YYYY-MM-DD')),
moment(currentSearchDate).set({
momentTz.tz(moment(currentSearchDate.format('YYYY-MM-DD')), timezone),
momentTz.tz(moment(currentSearchDate).set({
[TIME_COMPARISON_GRANULARITY.HOUR]: 23,
[TIME_COMPARISON_GRANULARITY.MINUTE]: 59,
[TIME_COMPARISON_GRANULARITY.SECOND]: 0,
[TIME_COMPARISON_GRANULARITY.MILLISECOND]: 0,
})),
}), timezone),
selectors.config.defaultTimeZone(getState())),
'[0].events', []).map((p) => p._id);

if (!(planningId in currentFeaturedPlannings) && !planningsForDate.includes(planningId)) {
Expand Down
17 changes: 9 additions & 8 deletions client/actions/planning/tests/featuredPlanning_test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import planningApi from '../api';
import featuredPlanning from '../featuredPlanning';
import moment from 'moment';
import momentTz from 'moment-timezone';
import sinon from 'sinon';
import {getTestActionStore, restoreSinonStub} from '../../../utils/testUtils';
import {FEATURED_PLANNING, MAIN, TIME_COMPARISON_GRANULARITY} from '../../../constants';
Expand Down Expand Up @@ -55,19 +56,17 @@ describe('actions.planning.api', () => {
});

describe('loadFeaturedPlanningsData', () => {
it('calls query with required parameters', (done) => (
store.test(done, featuredPlanning.loadFeaturedPlanningsData(date))
it('calls query with required parameters', (done) => {
store.initialState.config.defaultTimezone = 'Australia/Sydney';
date = momentTz.tz(moment(data.plannings[0].planning_date), 'Australia/Sydney');
return store.test(done, featuredPlanning.loadFeaturedPlanningsData(date))
.then(() => {
expect(planningApi.query.callCount).toBe(1);
expect(planningApi.query.args[0]).toEqual([
{
advancedSearch: {
dates: {
start: moment(date).set({
[TIME_COMPARISON_GRANULARITY.HOUR]: 0,
[TIME_COMPARISON_GRANULARITY.MINUTE]: 0,
[TIME_COMPARISON_GRANULARITY.SECOND]: 0,
}),
start: date,
range: MAIN.DATE_RANGE.FOR_DATE,
},
featured: true,
Expand All @@ -77,10 +76,12 @@ describe('actions.planning.api', () => {
excludeRescheduledAndCancelled: true,
},
false,
'+11:00',
]);
done();
})
).catch(done.fail));
.catch(done.fail);
});

it('calls planning_featured end point to get the featured record for the day', (done) => (
store.test(done, featuredPlanning.getFeaturedPlanningItem(date))
Expand Down
10 changes: 8 additions & 2 deletions client/components/Main/JumpToDropdown.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,24 @@ export class JumpToDropdown extends React.Component {

this.togglePopup = this.togglePopup.bind(this);
this.onChange = this.onChange.bind(this);
this.getTimeZone = this.getTimeZone.bind(this);
}

togglePopup() {
this.setState({popupOpened: !this.state.popupOpened});
}

getTimeZone() {
return get(this.props, 'defaultTimeZone', timeUtils.localTimeZone());
}

onChange(value) {
// If the user has selected 'Today', then set the startFilter to null
// Otherwise set the startFilter to the supplied day
const newMoment = momentTz.tz(value.clone(), get(this.props, 'defaultTimeZone', timeUtils.localTimeZone()));
const newMoment = momentTz.tz(value.clone(), this.getTimeZone());
const currentMoment = momentTz.tz(moment(), this.getTimeZone());

moment(newMoment).isSame(moment(), 'day') ?
moment(newMoment).isSame(currentMoment, 'day') ?
this.props.setStartFilter(null) :
this.props.setStartFilter(newMoment);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ export class FeaturedPlanningModalComponent extends React.Component {
}

isReadOnly() {
return this.props.currentSearchDate.isBefore(moment(), 'day');
return this.props.currentSearchDate.isBefore(moment().tz(this.props.defaultTimeZone), 'day');
}

onCloseModal() {
Expand Down Expand Up @@ -343,7 +343,7 @@ export class FeaturedPlanningModalComponent extends React.Component {
{<a className="close" onClick={this.onCloseModal}>
<i className="icon-close-small" />
</a>}
<h3>{gettext('Featured Stories')}</h3>
<h3>{gettext('Featured Stories based on timezone: {{tz}}', {tz: gettext(defaultTimeZone)})}</h3>
</Modal.Header>
<Modal.Body noPadding fullHeight noScroll>
<SubNav className="grid">
Expand All @@ -360,6 +360,7 @@ export class FeaturedPlanningModalComponent extends React.Component {
defaultTimeZone={defaultTimeZone}
dateFormat="dddd LL"
noBorderNoPadding />

</div>
{this.props.loading && <div className="loading-indicator">{gettext('Loading')}</div>}
{itemUpdatedAfterPosting &&
Expand Down
14 changes: 9 additions & 5 deletions client/selectors/featuredPlanning.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ export const featuredPlanIdsInList = (state) => get(state, 'featuredPlanning.pla
export const featuredPlanningItem = (state) => get(state, 'featuredPlanning.item', null);
export const previousFilter = (state) => get(state, 'featuredPlanning.previousFilter', false);
export const currentSearchDate = (state) =>
get(state, 'featuredPlanning.currentSearch.advancedSearch.dates.start', momentTz.tz(moment(), defaultTimeZone()));
get(
state,
'featuredPlanning.currentSearch.advancedSearch.dates.start',
momentTz.tz(moment(), defaultTimeZone(state))
);
export const total = (state) => get(state, 'featuredPlanning.total', false);
export const loading = (state) => get(state, 'featuredPlanning.loading', false);
export const unsavedItems = (state) => get(state, 'featuredPlanning.unsavedItems', null);
Expand All @@ -27,8 +31,8 @@ export const featuredPlansInList = createSelector(
);

export const orderedFeaturedPlanningList = createSelector(
[featuredPlansInList, currentSearchDate, getStartOfWeek],
(plansInList, date, startOfWeek) => {
[featuredPlansInList, currentSearchDate, getStartOfWeek, defaultTimeZone],
(plansInList, date, startOfWeek, timezone) => {
const search = {
advancedSearch: {
dates: {
Expand All @@ -50,13 +54,13 @@ export const orderedFeaturedPlanningList = createSelector(
const dateRange = getSearchDateRange(search, startOfWeek);

const group = planningUtils.getPlanningByDate(
plansInList, null, dateRange.startDate, dateRange.endDate
plansInList, null, dateRange.startDate, dateRange.endDate, timezone
);

if (group.length > 0) {
const featuredPlansForDate = group.find((g) => g.date === date.format('YYYY-MM-DD'));

return featuredPlansForDate.events || [];
return get(featuredPlansForDate, 'events', []);
}

return group;
Expand Down
6 changes: 3 additions & 3 deletions client/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -528,11 +528,11 @@ export const shouldUnLockItem = (item, session, currentWorkspace) =>
(currentWorkspace !== WORKSPACE.AUTHORING && lockUtils.isItemLockedInThisSession(item, session)));

/**
* Get the timezone offset
* @param {Array} coverages
* If date is provided get timezone offset from date else browser the timezone offset
* @param {moment} date
* @returns {Array}
*/
export const getTimeZoneOffset = () => (moment().format('Z'));
export const getTimeZoneOffset = (date = null) => (moment.isMoment(date) ? date.format('Z') : moment().format('Z'));

export const getPostedState = (item) => get(item, 'pubstatus', null);

Expand Down
15 changes: 11 additions & 4 deletions client/utils/planning.js
Original file line number Diff line number Diff line change
Expand Up @@ -646,19 +646,26 @@ const getCoverageReadOnlyFields = (
}
};

const getPlanningByDate = (plansInList, events, startDate, endDate) => {
const getPlanningByDate = (plansInList, events, startDate, endDate, timezone = null) => {
if (!plansInList) return [];

const days = {};
const getGroupDate = (date) => {
const groupDate = date.clone();

if (timezone) {
groupDate.tz(timezone);
}
return groupDate;
};

plansInList.forEach((plan) => {
const dates = {};
let groupDate = null;

plan.event = get(events, get(plan, 'event_item'));
plan.coverages.forEach((coverage) => {
groupDate = moment(get(coverage, 'planning.scheduled', plan.planning_date));

groupDate = getGroupDate(moment(get(coverage, 'planning.scheduled', plan.planning_date)).clone());
if (!isDateInRange(groupDate, startDate, endDate)) {
return;
}
Expand All @@ -669,7 +676,7 @@ const getPlanningByDate = (plansInList, events, startDate, endDate) => {
});

if (isEmpty(dates)) {
groupDate = moment(plan.planning_date);
groupDate = getGroupDate(moment(plan.planning_date).clone());
if (isDateInRange(groupDate, startDate, endDate)) {
dates[groupDate.format('YYYY-MM-DD')] = groupDate;
}
Expand Down

0 comments on commit 84d1952

Please sign in to comment.