From 1fb931fd625664135c65bd5bb0e0327edcdba7d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Ja=C5=A1ek?= Date: Thu, 18 Jul 2024 10:05:56 +0200 Subject: [PATCH] limit displayed days (#2030) * limit displayed days group based on the interval picker SDESK-7335 * backport test fix * filter days for planning --- client/apps/Planning/PlanningList.tsx | 12 +- client/selectors/events.ts | 13 +- client/selectors/eventsplanning.ts | 20 ++- client/selectors/planning.ts | 20 ++- client/selectors/tests/events_test.ts | 118 +++++++++++++++--- client/tests.ts | 5 +- client/utils/events.ts | 99 ++++----------- client/utils/index.ts | 80 ++++++++---- e2e/cypress/e2e/events/edit_event.cy.ts | 31 ++--- .../e2e/events/event_action_cancel.cy.ts | 11 +- .../events/event_action_create_planning.cy.ts | 13 +- .../e2e/events/event_action_duplicate.cy.ts | 9 +- .../e2e/events/event_embedded_coverage.cy.ts | 30 ++--- e2e/cypress/e2e/planning/edit_planning.cy.ts | 13 +- .../e2e/planning/planning_action_cancel.cy.ts | 5 +- e2e/cypress/e2e/search/search_combined.cy.ts | 10 +- e2e/cypress/e2e/search/search_events.cy.ts | 6 +- e2e/cypress/e2e/search/search_planning.cy.ts | 6 +- e2e/cypress/e2e/workqueue.cy.ts | 5 +- e2e/cypress/fixtures/events.ts | 32 ++--- e2e/cypress/fixtures/planning.ts | 15 +-- e2e/cypress/support/common/utils.ts | 2 + .../support/planning/advancedSearch.ts | 17 ++- e2e/server/Dockerfile | 2 + package-lock.json | 2 +- 25 files changed, 320 insertions(+), 256 deletions(-) diff --git a/client/apps/Planning/PlanningList.tsx b/client/apps/Planning/PlanningList.tsx index 331bc6db2..3a2d7e932 100644 --- a/client/apps/Planning/PlanningList.tsx +++ b/client/apps/Planning/PlanningList.tsx @@ -185,17 +185,7 @@ export class PlanningListComponent extends React.PureComponent { { - const dateFilter = currentSearch.advancedSearch?.dates?.start?.toDate() ?? new Date(); - - dateFilter.setUTCHours(0, 0, 0, 0); // group date is UTC 00:00:00 - - return groups.filter((group) => { - const groupDate = new Date(group.date); - - return groupDate >= dateFilter; - }); - })()} + groups={groups} onItemClick={openPreview} onDoubleClick={edit} agendas={agendas} diff --git a/client/selectors/events.ts b/client/selectors/events.ts index 0b848a8d5..7966a22de 100644 --- a/client/selectors/events.ts +++ b/client/selectors/events.ts @@ -2,7 +2,7 @@ import {createSelector} from 'reselect'; import {get, sortBy} from 'lodash'; import {appConfig} from 'appConfig'; -import {IEventItem, IEventState, IEventTemplate, IPlanningAppState, LIST_VIEW_TYPE} from '../interfaces'; +import {IEventItem, IEventState, IEventTemplate, IPlanningAppState, JUMP_INTERVAL, LIST_VIEW_TYPE} from '../interfaces'; import {currentPlanning, storedPlannings} from './planning'; import {agendas, userPreferences} from './general'; @@ -13,6 +13,11 @@ import {EVENTS, MAIN, SPIKED_STATE} from '../constants'; function getCurrentListViewType(state?: IPlanningAppState) { return state?.main?.listViewType ?? LIST_VIEW_TYPE.SCHEDULE; } + +function getCurrentViewInterval(state?: IPlanningAppState): JUMP_INTERVAL { + return state?.main?.search?.EVENTS?.jumpInterval ?? JUMP_INTERVAL.WEEK; +} + export const storedEvents = (state) => get(state, 'events.events', {}); export const eventIdsInList = (state) => get(state, 'events.eventsInList', []); export const eventHistory = (state) => get(state, 'events.eventHistoryItems'); @@ -36,8 +41,8 @@ export const eventsInList = createSelector( * the associated events. */ export const orderedEvents = createSelector( - [eventsInList, currentSearch, getCurrentListViewType], - (events, search, viewType) => { + [eventsInList, currentSearch, getCurrentListViewType, getCurrentViewInterval], + (events, search, viewType, viewInterval) => { if (!events?.length) { return []; } else if (viewType === LIST_VIEW_TYPE.LIST) { @@ -47,7 +52,7 @@ export const orderedEvents = createSelector( }]; } - const dateRange = getSearchDateRange(search, appConfig.start_of_week); + const dateRange = getSearchDateRange(search, appConfig.start_of_week, viewInterval); return eventUtils.getEventsByDate(events, dateRange.startDate, dateRange.endDate); } diff --git a/client/selectors/eventsplanning.ts b/client/selectors/eventsplanning.ts index 68e3d989b..04c834e09 100644 --- a/client/selectors/eventsplanning.ts +++ b/client/selectors/eventsplanning.ts @@ -2,7 +2,7 @@ import {createSelector} from 'reselect'; import {get, keyBy, sortBy, uniq} from 'lodash'; import {appConfig} from 'appConfig'; -import {IPlanningAppState, LIST_VIEW_TYPE} from '../interfaces'; +import {IPlanningAppState, JUMP_INTERVAL, LIST_VIEW_TYPE} from '../interfaces'; import {storedEvents} from './events'; import {storedPlannings} from './planning'; @@ -13,6 +13,11 @@ import {userPreferences} from './general'; function getCurrentListViewType(state?: IPlanningAppState) { return state?.main?.listViewType ?? LIST_VIEW_TYPE.SCHEDULE; } + +function getCurrentViewInterval(state?: IPlanningAppState): JUMP_INTERVAL { + return state?.main?.search?.COMBINED?.jumpInterval ?? JUMP_INTERVAL.WEEK; +} + export const getEventsPlanningList = (state) => get(state, 'eventsPlanning.eventsAndPlanningInList', []); export const getRelatedPlanningsList = (state) => get(state, 'eventsPlanning.relatedPlannings', {}); export const currentSearch = (state) => get(state, 'main.search.COMBINED.currentSearch'); @@ -44,8 +49,15 @@ export const eventsPlannignViewFilters = createSelector( * @type {Reselect.Selector} */ export const orderedEventsPlanning = createSelector( - [storedEvents, storedPlannings, getEventsPlanningList, currentSearch, getCurrentListViewType], - (events, plannings, eventPlanningList, search, viewType) => { + [ + storedEvents, + storedPlannings, + getEventsPlanningList, + currentSearch, + getCurrentListViewType, + getCurrentViewInterval, + ], + (events, plannings, eventPlanningList, search, viewType, viewInterval) => { if (!eventPlanningList?.length) { return []; } else if (viewType === LIST_VIEW_TYPE.LIST) { @@ -59,7 +71,7 @@ export const orderedEventsPlanning = createSelector( const eventsList = []; const planningList = []; - const dateRange = getSearchDateRange(search, appConfig.start_of_week); + const dateRange = getSearchDateRange(search, appConfig.start_of_week, viewInterval); eventPlanningList.forEach((_id) => { if (_id in events) { diff --git a/client/selectors/planning.ts b/client/selectors/planning.ts index ff7731ec3..96873a2b2 100644 --- a/client/selectors/planning.ts +++ b/client/selectors/planning.ts @@ -2,7 +2,7 @@ import {createSelector} from 'reselect'; import {cloneDeep, get} from 'lodash'; import {appConfig} from 'appConfig'; -import {IPlanningAppState, IPlanningItem, LIST_VIEW_TYPE} from '../interfaces'; +import {IPlanningAppState, IPlanningItem, JUMP_INTERVAL, LIST_VIEW_TYPE} from '../interfaces'; import {session, userPreferences} from './general'; import {getSearchDateRange, lockUtils, planningUtils} from '../utils'; @@ -11,6 +11,11 @@ import {AGENDA, SPIKED_STATE} from '../constants'; function getCurrentListViewType(state?: IPlanningAppState) { return state?.main?.listViewType ?? LIST_VIEW_TYPE.SCHEDULE; } + +function getCurrentViewInterval(state?: IPlanningAppState): JUMP_INTERVAL { + return state?.main?.search?.PLANNING?.jumpInterval ?? JUMP_INTERVAL.WEEK; +} + const storedEvents = (state) => get(state, 'events.events', {}); export const planningHistory = (state) => get(state, 'planning.planningHistoryItems'); @@ -71,8 +76,15 @@ export const plansInList = createSelector( ); export const orderedPlanningList = createSelector( - [currentAgenda, plansInList, storedEvents, currentSearch, getCurrentListViewType], - (currentAgenda, plansInList, events, search, viewType) => { + [ + currentAgenda, + plansInList, + storedEvents, + currentSearch, + getCurrentListViewType, + getCurrentViewInterval, + ], + (currentAgenda, plansInList, events, search, viewType, viewInterval) => { if (!plansInList?.length) { return []; } if (viewType === LIST_VIEW_TYPE.LIST) { @@ -82,7 +94,7 @@ export const orderedPlanningList = createSelector( }]; } - const dateRange = getSearchDateRange(search, appConfig.start_of_week); + const dateRange = getSearchDateRange(search, appConfig.start_of_week, viewInterval); return planningUtils.getPlanningByDate( plansInList, events, dateRange.startDate, dateRange.endDate diff --git a/client/selectors/tests/events_test.ts b/client/selectors/tests/events_test.ts index cfdd99af2..29a4352db 100644 --- a/client/selectors/tests/events_test.ts +++ b/client/selectors/tests/events_test.ts @@ -2,6 +2,7 @@ import * as selectors from '../index'; import moment from 'moment'; import {keyBy} from 'lodash'; +const ids = (day) => day.events.map((e) => e._id); describe('selectors', () => { const dateFormat = 'YYYY-MM-DDTHH:mm:ss'; @@ -32,13 +33,31 @@ describe('selectors', () => { end: moment('2017-01-17T14:00:00', dateFormat), }, }, + event4: { + _id: 'event4', + name: 'event4', + dates: { + start: moment('2024-07-16T13:00:00+0000'), + end: moment('2024-07-17T00:00:00+0000'), + no_end_time: true, + }, + }, + event5: { + _id: 'event5', + name: 'event5', + dates: { + start: moment('2024-07-15T00:00:00+0000'), + end: moment('2024-07-18T00:00:00+0000'), + all_day: true, + }, + } }, - eventsInList: ['event1', 'event2', 'event3'], + eventsInList: ['event1', 'event2', 'event3', 'event4', 'event5'], }, session: {identity: {_id: 'user1'}}, }); - const setAdvancedSearchDates = (state, startDate, endate) => { + const setAdvancedSearchDates = (state, startDate, endate?) => { state.main = { filter: 'EVENTS', search: { @@ -46,8 +65,8 @@ describe('selectors', () => { currentSearch: { advancedSearch: { dates: { - start: startDate ? moment(startDate, dateFormat) : null, - end: endate ? moment(endate, dateFormat) : null, + start: startDate ? moment(startDate) : null, + end: endate ? moment(endate) : null, }, }, }, @@ -60,7 +79,7 @@ describe('selectors', () => { it('all events', () => { const state = getState(); - setAdvancedSearchDates(state, '2017-01-10T00:00:00'); + setAdvancedSearchDates(state, '2017-01-10T00:00:00+0000'); const events = keyBy(selectors.events.orderedEvents(state), 'date'); expect(Object.keys(events)).toEqual([ @@ -87,7 +106,7 @@ describe('selectors', () => { state.events.events.event2.dates.start = moment('2017-01-17T08:00:00', dateFormat); state.events.events.event2.dates.end = moment('2017-01-17T14:00:00', dateFormat); - setAdvancedSearchDates(state, '2017-01-10T00:00:00'); + setAdvancedSearchDates(state, '2017-01-10T00:00:00+0000'); const events = keyBy(selectors.events.orderedEvents(state), 'date'); expect(Object.keys(events)).toEqual([ @@ -112,7 +131,7 @@ describe('selectors', () => { it('for today 2017-01-15', () => { const state = getState(); - setAdvancedSearchDates(state, '2017-01-15T00:00:00+0000', '2017-01-15T23:59:59+0000'); + setAdvancedSearchDates(state, '2017-01-15T00:00:00', '2017-01-15T23:59:59'); const events = keyBy(selectors.events.orderedEvents(state), 'date'); expect(Object.keys(events)).toEqual([ @@ -126,7 +145,7 @@ describe('selectors', () => { it('from 2017-01-15 11:00 to 2017-01-16T14:00:00+0000', () => { const state = getState(); - setAdvancedSearchDates(state, '2017-01-15T11:00:00+0000', '2017-01-16T14:00:00+0000'); + setAdvancedSearchDates(state, '2017-01-15T11:00:00', '2017-01-16T14:00:00'); const events = keyBy(selectors.events.orderedEvents(state), 'date'); expect(Object.keys(events)).toEqual([ @@ -145,21 +164,22 @@ describe('selectors', () => { it('from 2017-01-16T06:00:00+0000 to 2017-01-16T07:00:00+0000', () => { const state = getState(); - setAdvancedSearchDates(state, '2017-01-16T06:00:00+0000', '2017-01-16T07:00:00+0000'); + setAdvancedSearchDates(state, '2017-01-16T06:00:00', '2017-01-16T07:00:00'); const events = keyBy(selectors.events.orderedEvents(state), 'date'); expect(Object.keys(events)).toEqual([ '2017-01-16', ]); - expect(events['2017-01-16'].events.length).toBe(1); + expect(events['2017-01-16'].events.length).toBe(2); expect(events['2017-01-16'].events[0]._id).toBe('event3'); + expect(events['2017-01-16'].events[1]._id).toBe('event2'); }); it('from 2017-01-16T06:00:00+0000 to 2017-01-16T10:00:00+0000', () => { const state = getState(); - setAdvancedSearchDates(state, '2017-01-16T06:00:00+0000', '2017-01-16T10:00:00+0000'); + setAdvancedSearchDates(state, '2017-01-16T06:00:00', '2017-01-16T10:00:00'); const events = keyBy(selectors.events.orderedEvents(state), 'date'); expect(Object.keys(events)).toEqual([ @@ -171,10 +191,10 @@ describe('selectors', () => { expect(events['2017-01-16'].events[1]._id).toBe('event2'); }); - it('from 2017-01-16T13:59:59+0000 to 2017-01-17T08:00:00+0000', () => { + it('from 2017-01-16T13:59:59 to 2017-01-17T08:00:00', () => { const state = getState(); - setAdvancedSearchDates(state, '2017-01-16T13:59:59+0000', '2017-01-17T08:00:00+0000'); + setAdvancedSearchDates(state, '2017-01-16T13:59:59', '2017-01-17T08:00:00'); const events = keyBy(selectors.events.orderedEvents(state), 'date'); expect(Object.keys(events)).toEqual(['2017-01-16', '2017-01-17']); @@ -187,7 +207,7 @@ describe('selectors', () => { it('from 2017-01-17T06:00:00+0000', () => { const state = getState(); - setAdvancedSearchDates(state, '2017-01-17T06:00:00+0000'); + setAdvancedSearchDates(state, '2017-01-17T06:00:00'); const events = keyBy(selectors.events.orderedEvents(state), 'date'); expect(Object.keys(events)).toEqual([ @@ -198,13 +218,79 @@ describe('selectors', () => { expect(events['2017-01-17'].events[0]._id).toBe('event3'); }); - it('from 2017-01-17T14:00:01+0000', () => { + it('from 2017-01-18T00:00:00+0000', () => { const state = getState(); - setAdvancedSearchDates(state, '2017-01-17T14:00:01+0000'); + setAdvancedSearchDates(state, '2017-01-18T00:00:00'); const events = keyBy(selectors.events.orderedEvents(state), 'date'); expect(Object.keys(events).length).toBe(0); }); + + it('from 2024-07-14', () => { + const state = getState(); + + setAdvancedSearchDates(state, '2024-07-14T12:00:00'); + const events = keyBy(selectors.events.orderedEvents(state), 'date'); + + expect(Object.keys(events)).toEqual([ + '2024-07-15', + '2024-07-16', + '2024-07-17', + '2024-07-18', + ]); + + expect(ids(events['2024-07-15'])).toEqual(['event5']); + expect(ids(events['2024-07-16'])).toEqual(['event5', 'event4']); + expect(ids(events['2024-07-17'])).toEqual(['event5', 'event4']); + expect(ids(events['2024-07-18'])).toEqual(['event5']); + }); + + it('from 2024-07-17', () => { + const state = getState(); + + setAdvancedSearchDates(state, '2024-07-17T12:00:00'); + const events = keyBy(selectors.events.orderedEvents(state), 'date'); + + expect(Object.keys(events)).toEqual([ + '2024-07-17', + '2024-07-18', + ]); + + expect(ids(events['2024-07-17'])).toEqual(['event5', 'event4']); + }); + + it('from 2024-07-14 Toronto timezone', () => { + moment.tz.setDefault('America/Toronto'); + const state = getState(); + + setAdvancedSearchDates(state, '2024-07-14T12:00:00'); + const events = keyBy(selectors.events.orderedEvents(state), 'date'); + + expect(Object.keys(events)).toEqual([ + '2024-07-15', + '2024-07-16', + '2024-07-17', + '2024-07-18', + ]); + + expect(ids(events['2024-07-15'])).toEqual(['event5']); + expect(ids(events['2024-07-16'])).toEqual(['event5', 'event4']); + expect(ids(events['2024-07-17'])).toEqual(['event5', 'event4']); + expect(ids(events['2024-07-18'])).toEqual(['event5']); + }); + + it('from 2024-07-17 Toronto timezone', () => { + moment.tz.setDefault('America/Toronto'); + const state = getState(); + + setAdvancedSearchDates(state, '2024-07-17T05:00:00'); + const events = keyBy(selectors.events.orderedEvents(state), 'date'); + + expect(Object.keys(events)).toEqual([ + '2024-07-17', + '2024-07-18', + ]); + }); }); }); diff --git a/client/tests.ts b/client/tests.ts index 0915d57ad..2fbe12cd5 100644 --- a/client/tests.ts +++ b/client/tests.ts @@ -20,9 +20,12 @@ Object.assign(appConfig, { planning_auto_assign_to_workflow: true, }); -moment.tz.setDefault('Australia/Sydney'); updateConfigAfterLoad(); +beforeEach(() => { + moment.tz.setDefault('Australia/Sydney'); +}); + var testsContext = require.context('.', true, /_test.[j|t]sx?$/); testsContext.keys().forEach(testsContext); diff --git a/client/utils/events.ts b/client/utils/events.ts index e49bf4aab..07c27119b 100644 --- a/client/utils/events.ts +++ b/client/utils/events.ts @@ -858,7 +858,6 @@ function getFlattenedEventsByDate(events: Array, startDate: moment.M return flatten(sortBy(eventsList, [(e) => (e.date)]).map((e) => e.events.map((k) => [e.date, k._id]))); } - const getStartDate = (event: IEventItem) => ( event.dates?.all_day ? moment.utc(event.dates.start) : moment(event.dates?.start) ); @@ -867,36 +866,6 @@ const getEndDate = (event: IEventItem) => ( (event.dates?.all_day || event.dates?.no_end_time) ? moment.utc(event.dates.end) : moment(event.dates?.end) ); -const isEventInRange = ( - event: IEventItem, - eventStart: moment.Moment, - eventEnd: moment.Moment, - start: moment.Moment, - end?: moment.Moment, -) => { - let localStart = eventStart; - let localEnd = eventEnd; - let startUnit : moment.unitOfTime.StartOf = 'second'; - let endUnit : moment.unitOfTime.StartOf = 'second'; - - if (event.dates?.all_day) { - // we have only dates in utc - localStart = moment(eventStart.format('YYYY-MM-DD')); - localEnd = moment(eventEnd.format('YYYY-MM-DD')); - startUnit = 'day'; - endUnit = 'day'; - } - - if (event.dates?.no_end_time) { - // we have time for start, but only date for end - localStart = moment(eventStart); - localEnd = moment(eventEnd.format('YYYY-MM-DD')); - endUnit = 'day'; - } - - return localEnd.isSameOrAfter(start, endUnit) && (end == null || localStart.isSameOrBefore(end, startUnit)); -}; - /* * Groups the events by date */ @@ -904,9 +873,9 @@ function getEventsByDate( events: Array, startDate: moment.Moment, endDate: moment.Moment -): Array { +) { if ((events?.length ?? 0) === 0) { - return []; + return {}; } // check if search exists @@ -920,23 +889,8 @@ function getEventsByDate( const days: {[date: string]: Array} = {}; - function addEventToDate(event: IEventItem, date?: moment.Moment) { - let eventDate = date || getStartDate(event); - let eventStart = getStartDate(event); - let eventEnd = getEndDate(event); - - if (!eventStart.isSame(eventEnd, 'day') && !event.dates.all_day && !event.dates.no_end_time) { - eventStart = eventDate; - eventEnd = eventEnd.isSame(eventDate, 'day') ? - eventEnd : - moment(eventDate.format('YYYY-MM-DD'), 'YYYY-MM-DD').add(86399, 'seconds'); - } - - if (!isEventInRange(event, eventDate, eventEnd, startDate, endDate)) { - return; - } - - let eventDateFormatted = eventDate.format('YYYY-MM-DD'); + function addEventToDate(event: IEventItem, date: moment.Moment, eventStart: moment.Moment) { + const eventDateFormatted = date.format('YYYY-MM-DD'); if (!days[eventDateFormatted]) { days[eventDateFormatted] = []; @@ -949,37 +903,36 @@ function getEventsByDate( } sortedEvents.forEach((event) => { - // compute the number of days of the event - const eventEndDate = event.actioned_date ? moment(event.actioned_date) : getEndDate(event); - const eventStartDate = getStartDate(event); - - if (!eventStartDate.isSame(eventEndDate, 'day')) { - let deltaDays = Math.max(Math.ceil(eventEndDate.diff(eventStartDate, 'days', true)), 1); - // if the event happens during more than one day, add it to every day - // add the event to the other days - - for (let i = 1; i < deltaDays; i++) { - // clone the date - const newDate = moment(eventStartDate.format('YYYY-MM-DD'), 'YYYY-MM-DD', true); - - newDate.add(i, 'days'); + const eventEndDate = event.actioned_date ? moment(event.actioned_date) : getLocalEndDate(event); + const eventStartDate = getLocalStartDate(event); - if (newDate.isSameOrBefore(eventEndDate, 'day')) { - addEventToDate(event, newDate); - } - } - } + const displayStartDate = eventStartDate.isSameOrAfter(startDate) ? eventStartDate : startDate; + const displayEndDate = eventEndDate.isSameOrBefore(endDate) ? eventEndDate : endDate; - // add event to its initial starting date - // add an event only if it's not actioned or actioned after this event's start date - if (!event.actioned_date || moment(event.actioned_date).isSameOrAfter(eventStartDate, 'date')) { - addEventToDate(event); + for (const day = displayStartDate.clone(); day.isSameOrBefore(displayEndDate, 'day'); day.add(1, 'days')) { + addEventToDate(event, day, eventStartDate); } }); return sortBasedOnTBC(days); } +function getLocalStartDate(event: IEventItem): moment.Moment { + if (event.dates.all_day) { + return moment(moment.utc(event.dates.start).format('YYYY-MM-DD')); + } + + return moment(event.dates.start); +} + +function getLocalEndDate(event: IEventItem): moment.Moment { + if (event.dates.all_day || event.dates.no_end_time) { + return moment(moment.utc(event.dates.end).format('YYYY-MM-DD')).endOf('day'); + } + + return moment(event.dates.end); +} + function modifyForClient(event: Partial): Partial { sanitizeItemFields(event); diff --git a/client/utils/index.ts b/client/utils/index.ts index 6782b7bf3..38d167fd9 100644 --- a/client/utils/index.ts +++ b/client/utils/index.ts @@ -11,6 +11,9 @@ import { IPlanningCoverageItem, IIngestProvider, IFeaturedPlanningItem, + ISearchParams, + ICommonSearchParams, + JUMP_INTERVAL, } from '../interfaces'; import {IUser} from 'superdesk-api'; import {superdeskApi} from '../superdeskApi'; @@ -258,6 +261,8 @@ export const getErrorMessage = (error, defaultMessage) => { return get(error, '_issues.validator exception'); } else if (typeof error === 'string') { return error; + } else if (get(error, 'error')) { + return get(error, 'error'); } return defaultMessage; @@ -542,8 +547,9 @@ export const getItemsById = (ids, items) => ( export const getUsersForDesk = (desk, globalUserList = []) => { if (!desk) return globalUserList; - return globalUserList.filter((user) => - map(desk.members, 'user').indexOf(user._id) !== -1); + const deskMembersSet = new Set((desk.members ?? []).map((member) => member.user)); + + return globalUserList.filter(({_id}) => deskMembersSet.has(_id)); }; export const getDesksForUser = (user, desksList = []) => { @@ -685,43 +691,63 @@ export const isDateInRange = (inputDate, startDate, endDate) => { return true; }; -export const getSearchDateRange = (currentSearch, startOfWeek) => { - const dates = get(currentSearch, 'advancedSearch.dates', {}); - const dateRange = {startDate: null, endDate: null}; - - if (!get(dates, 'start') && !get(dates, 'end') && !get(dates, 'range')) { - dateRange.startDate = moment(moment().format('YYYY-MM-DD'), 'YYYY-MM-DD', true); - dateRange.endDate = moment().add(999, 'years'); - } else if (get(dates, 'range')) { - let range = get(dates, 'range'); +interface IDateRange { + startDate: moment.Moment; + endDate: moment.Moment; +} - if (range === MAIN.DATE_RANGE.TODAY) { - dateRange.startDate = moment(moment().format('YYYY-MM-DD'), 'YYYY-MM-DD', true); - dateRange.endDate = dateRange.startDate.clone().add('86399', 'seconds'); - } else if (range === MAIN.DATE_RANGE.TOMORROW) { - const tomorrow = moment().add(1, 'day'); +const INTERVAL_UNIT_MAPPING = { + [JUMP_INTERVAL.DAY]: 'day', + [JUMP_INTERVAL.WEEK]: 'week', + [JUMP_INTERVAL.MONTH]: 'month', +}; - dateRange.startDate = moment(tomorrow.format('YYYY-MM-DD'), 'YYYY-MM-DD', true); +export const getSearchDateRange = ( + currentSearch: ICommonSearchParams, + startOfWeek: number, + viewInterval?: JUMP_INTERVAL, +): IDateRange => { + const dates = currentSearch.advancedSearch.dates ?? {}; + const dateRange = {startDate: null, endDate: null}; + const jumpUnit = viewInterval ? INTERVAL_UNIT_MAPPING[viewInterval] : 'month'; + + if (dates.range) { + if (dates.range === MAIN.DATE_RANGE.TODAY) { + dateRange.startDate = moment().startOf('day'); + dateRange.endDate = dateRange.startDate.clone() + .add(1, 'day'); + } else if (dates.range === MAIN.DATE_RANGE.TOMORROW) { + const tomorrow = moment().add(1, 'day') + .startOf('day'); + + dateRange.startDate = tomorrow; dateRange.endDate = tomorrow.clone().add('86399', 'seconds'); - } else if (range === MAIN.DATE_RANGE.LAST_24) { + } else if (dates.range === MAIN.DATE_RANGE.LAST_24) { dateRange.endDate = moment(); dateRange.startDate = dateRange.endDate.clone().subtract('86400', 'seconds'); - } else if (range === MAIN.DATE_RANGE.THIS_WEEK) { + } else if (dates.range === MAIN.DATE_RANGE.THIS_WEEK) { dateRange.endDate = timeUtils.getStartOfNextWeek(null, startOfWeek); dateRange.startDate = dateRange.endDate.clone().subtract(7, 'days'); - } else if (range === MAIN.DATE_RANGE.NEXT_WEEK) { + } else if (dates.range === MAIN.DATE_RANGE.NEXT_WEEK) { dateRange.endDate = timeUtils.getStartOfNextWeek(null, startOfWeek).add(7, 'days'); dateRange.startDate = dateRange.endDate.clone().subtract(7, 'days'); } + } else if (dates.start && dates.end) { + dateRange.startDate = moment(dates.start); + dateRange.endDate = moment(dates.end); + } else if (dates.start) { + dateRange.startDate = moment(dates.start); + dateRange.endDate = dateRange.startDate.clone().add(1, jumpUnit) + .subtract(1, 'second'); // remove 1s not to display additional day + } else if (dates.end) { + dateRange.endDate = moment(dates.end); + dateRange.startDate = dateRange.endDate.clone().subtract(1, jumpUnit); } else { - if (get(dates, 'start')) { - dateRange.startDate = moment(get(dates, 'start')); - } - - if (get(dates, 'end')) { - dateRange.endDate = moment(get(dates, 'end')); - } + dateRange.startDate = moment().startOf('day'); + dateRange.endDate = dateRange.startDate.clone().add(1, jumpUnit) + .subtract(1, 'second'); // remove 1s not to display additional day } + return dateRange; }; diff --git a/e2e/cypress/e2e/events/edit_event.cy.ts b/e2e/cypress/e2e/events/edit_event.cy.ts index 0c78b9631..10737cb75 100644 --- a/e2e/cypress/e2e/events/edit_event.cy.ts +++ b/e2e/cypress/e2e/events/edit_event.cy.ts @@ -1,8 +1,9 @@ import {cloneDeep} from 'lodash'; -import {setup, login, waitForPageLoad, SubNavBar, Workqueue, Modal, addItems} from '../../support/common'; +import {setup, login, waitForPageLoad, SubNavBar, Workqueue, Modal, addItems, CLIENT_FORMAT} from '../../support/common'; import {EventEditor, PlanningList} from '../../support/planning'; -import {TEST_EVENTS} from '../../fixtures/events'; +import {createEventFor, TEST_EVENTS} from '../../fixtures/events'; +import moment from 'moment'; const list = new PlanningList(); const editor = new EventEditor(); @@ -16,7 +17,7 @@ describe('Planning.Events: edit metadata', () => { beforeEach(() => { event = { - 'dates.start.date': '12/12/2045', + 'dates.start.date': moment().format(CLIENT_FORMAT), slugline: 'slugline of the event', name: 'name of the event', definition_short: 'Desc.', @@ -34,7 +35,7 @@ describe('Planning.Events: edit metadata', () => { expectedEvent = { ...event, - 'dates.end.date': '12/12/2045', + 'dates.end.date': moment().format(CLIENT_FORMAT), }; setup({fixture_profile: 'planning_prepopulate_data'}, '/#/planning'); @@ -74,7 +75,7 @@ describe('Planning.Events: edit metadata', () => { event = { ...event, 'dates.recurring.enable': true, - 'dates.recurring.until': '13/12/2045', + 'dates.recurring.until': moment().add(1, 'day').format(CLIENT_FORMAT), 'dates.allDay': true, slugline: 'slugline of the recurring event', name: 'name of the recurring event', @@ -82,7 +83,7 @@ describe('Planning.Events: edit metadata', () => { expectedEvent = { ...expectedEvent, 'dates.recurring.enable': true, - 'dates.recurring.until': '13/12/2045', + 'dates.recurring.until': moment().add(1, 'day').format(CLIENT_FORMAT), 'dates.allDay': true, slugline: 'slugline of the recurring event', name: 'name of the recurring event', @@ -133,7 +134,7 @@ describe('Planning.Events: edit metadata', () => { // Enter minimum Event metadata editor.expectItemType(); editor.type({ - 'dates.start.date': '12/12/2045', + 'dates.start.date': moment().format(CLIENT_FORMAT), 'dates.allDay': true, slugline: 'slugline of the event', name: 'name of the event', @@ -181,20 +182,12 @@ describe('Planning.Events: edit metadata', () => { describe('Planing.Events: edit existing events', () => { beforeEach(() => { setup({fixture_profile: 'planning_prepopulate_data'}, '/#/planning'); - addItems('events', [{ + addItems('events', [createEventFor.tomorrow({ ...cloneDeep(TEST_EVENTS.date_01_02_2045), - dates: { - start: TEST_EVENTS.date_01_02_2045.dates.start, - end: TEST_EVENTS.date_01_02_2045.dates.end, - }, - }, { + }), createEventFor.tomorrow({ ...cloneDeep(TEST_EVENTS.date_02_02_2045), - dates: { - start: TEST_EVENTS.date_02_02_2045.dates.start, - end: TEST_EVENTS.date_02_02_2045.dates.end, - tz: null, - }, - }]); + }, null), + ]); login(); waitForPageLoad.planning(); diff --git a/e2e/cypress/e2e/events/event_action_cancel.cy.ts b/e2e/cypress/e2e/events/event_action_cancel.cy.ts index 762959d32..075d5adbc 100644 --- a/e2e/cypress/e2e/events/event_action_cancel.cy.ts +++ b/e2e/cypress/e2e/events/event_action_cancel.cy.ts @@ -1,7 +1,7 @@ import {setup, login, addItems, waitForPageLoad, Modal} from '../../support/common'; -import {TIME_STRINGS} from '../../support/utils/time'; import {PlanningList, EventEditor, PlanningPreview} from '../../support/planning'; import {getMenuItem} from '../../support/common/ui/actionMenu'; +import {createEventFor} from '../../fixtures/events'; describe('Planning.Events: event cancel action', () => { const editor = new EventEditor(); @@ -13,24 +13,19 @@ describe('Planning.Events: event cancel action', () => { beforeEach(() => { setup({fixture_profile: 'planning_prepopulate_data'}, '/#/planning'); - addItems('events', [{ + addItems('events', [createEventFor.today({ type: 'event', occur_status: { name: 'Planned, occurs certainly', label: 'Confirmed', qcode: 'eocstat:eos5', }, - dates: { - start: '2045-12-11' + TIME_STRINGS[0], - end: '2045-12-11' + TIME_STRINGS[1], - tz: 'Australia/Sydney', - }, calendars: [], state: 'draft', place: [], name: 'Test', slugline: 'Original', - }]); + })]); login(); diff --git a/e2e/cypress/e2e/events/event_action_create_planning.cy.ts b/e2e/cypress/e2e/events/event_action_create_planning.cy.ts index 312eaebdd..bf3652b76 100644 --- a/e2e/cypress/e2e/events/event_action_create_planning.cy.ts +++ b/e2e/cypress/e2e/events/event_action_create_planning.cy.ts @@ -1,6 +1,6 @@ import moment from 'moment-timezone'; -import {setup, login, addItems, waitForPageLoad} from '../../support/common'; +import {setup, login, addItems, waitForPageLoad, CLIENT_FORMAT} from '../../support/common'; import {TIMEZONE} from '../../support/utils/time'; import {PlanningList, PlanningPreview, EventEditor, PlanningEditor} from '../../support/planning'; @@ -14,10 +14,12 @@ describe('Planning.Events: create planning action', () => { const preview = new PlanningPreview(); let menu; + const start = moment(); + const expectedValues = { slugline: 'Original', - 'planning_date.date': '12/12/2025', - 'planning_date.time': '01:00', + 'planning_date.date': start.format(CLIENT_FORMAT), + 'planning_date.time': start.format('HH:mm'), description_text: 'Desc.', ednote: 'Ed. Note', anpa_category: ['Finance'], @@ -26,7 +28,6 @@ describe('Planning.Events: create planning action', () => { beforeEach(() => { setup({fixture_profile: 'planning_prepopulate_data'}, '/#/planning'); - const start = moment.tz("2025-12-12 01:00", TIMEZONE).utc(); addItems('events', [{ slugline: 'Original', definition_short: 'Desc.', @@ -36,8 +37,8 @@ describe('Planning.Events: create planning action', () => { qcode: 'eocstat:eos5', }, dates: { - start: start.format("YYYY-MM-DDTHH:mm:ss+0000"), - end: start.add(1, 'h').format('YYYY-MM-DDTHH:mm:ss+0000'), + start: start.utc().format("YYYY-MM-DDTHH:mm:ss+0000"), + end: start.clone().utc().add(1, 'h').format('YYYY-MM-DDTHH:mm:ss+0000'), tz: TIMEZONE, }, anpa_category: [{is_active: true, name: 'Finance', qcode: 'f', subject: '04000000'}], diff --git a/e2e/cypress/e2e/events/event_action_duplicate.cy.ts b/e2e/cypress/e2e/events/event_action_duplicate.cy.ts index 66210d4f2..c9d28bd6f 100644 --- a/e2e/cypress/e2e/events/event_action_duplicate.cy.ts +++ b/e2e/cypress/e2e/events/event_action_duplicate.cy.ts @@ -1,4 +1,5 @@ -import {setup, login, waitForPageLoad, Modal, SubNavBar} from '../../support/common'; +import moment from 'moment'; +import {setup, login, waitForPageLoad, Modal, SubNavBar, CLIENT_FORMAT} from '../../support/common'; import {PlanningList, PlanningPreview, EventEditor} from '../../support/planning'; describe('Planning.Events: duplicate event', () => { @@ -12,11 +13,13 @@ describe('Planning.Events: duplicate event', () => { const preview = new PlanningPreview(); beforeEach(() => { + const now = moment(); + event = { slugline: 'Original', name: 'Test', definition_short: 'Desc.', - 'dates.start.date': '12/12/2045', + 'dates.start.date': now.format(CLIENT_FORMAT), 'dates.start.time': '00:00', occur_status: 'Planned, occurs certainly', calendars: ['Sport'], @@ -29,7 +32,7 @@ describe('Planning.Events: duplicate event', () => { }; expectedValues = Object.assign({}, event, { - 'dates.end.date': '12/12/2045', + 'dates.end.date': now.format(CLIENT_FORMAT), 'dates.end.time': '01:00', }); diff --git a/e2e/cypress/e2e/events/event_embedded_coverage.cy.ts b/e2e/cypress/e2e/events/event_embedded_coverage.cy.ts index ac22deac5..9983d4452 100644 --- a/e2e/cypress/e2e/events/event_embedded_coverage.cy.ts +++ b/e2e/cypress/e2e/events/event_embedded_coverage.cy.ts @@ -1,7 +1,9 @@ -import {setup, login, waitForPageLoad, SubNavBar, addItems} from '../../support/common'; +import {setup, login, waitForPageLoad, SubNavBar, addItems, CLIENT_FORMAT} from '../../support/common'; import {TIME_STRINGS} from '../../support/utils/time'; import {EventEditor, PlanningList} from '../../support/planning'; import {EmbeddedCoverageEditor} from '../../support/planning/events/embeddedCoverageEditor'; +import moment from 'moment'; +import {createEventFor} from '../../fixtures/events'; describe('Planning.Events: embedded coverage', () => { const editor = new EventEditor(); @@ -21,7 +23,7 @@ describe('Planning.Events: embedded coverage', () => { // Enter required fields (so we can create the Event & Planning) editor.type({ - 'dates.start.date': '12/12/2045', + 'dates.start.date': moment().format(CLIENT_FORMAT), 'dates.allDay': true, slugline: 'slugline of the event', name: 'name of the event', @@ -119,24 +121,19 @@ describe('Planning.Events: embedded coverage', () => { }); it('can add a planning item to an existing event', () => { - addItems('events', [{ + addItems('events', [createEventFor.today({ type: 'event', occur_status: { name: 'Planned, occurs certainly', label: 'Confirmed', qcode: 'eocstat:eos5', }, - dates: { - start: '2045-12-11' + TIME_STRINGS[0], - end: '2045-12-11' + TIME_STRINGS[1], - tz: 'Australia/Sydney', - }, calendars: [], state: 'draft', place: [], name: 'Test', slugline: 'slugline of the event', - }]); + })]); list.item(0) .dblclick(); @@ -234,24 +231,19 @@ describe('Planning.Events: embedded coverage', () => { }); it('SDESK-6022: planning items should stay after post/unpost', () => { - addItems('events', [{ + addItems('events', [createEventFor.today({ type: 'event', occur_status: { name: 'Planned, occurs certainly', label: 'Confirmed', qcode: 'eocstat:eos5', }, - dates: { - start: '2045-12-11' + TIME_STRINGS[0], - end: '2045-12-11' + TIME_STRINGS[1], - tz: 'Australia/Sydney', - }, calendars: [], state: 'draft', place: [], name: 'Test', slugline: 'slugline of the event', - }]); + })]); list.item(0) .dblclick(); @@ -338,16 +330,18 @@ describe('Planning.Events: embedded coverage', () => { .should('exist') .should('be.enabled'); + const now = moment() + // Fill in the dates (which should also update the Planning/Coverage dates) editor.type({ - 'dates.start.date': '12/12/2045', + 'dates.start.date': now.format(CLIENT_FORMAT), 'dates.allDay': true, }); // Make sure the date has been updated for the Coverage embeddedCoverages.getRelatedCoverage(0, 0) .should('exist') - .should('contain.text', '12/12/2045 @ 00:00'); + .should('contain.text', `${now.format(CLIENT_FORMAT)} @ 00:00`); // Now create the Event & Planning item editor.waitForAutosave(); diff --git a/e2e/cypress/e2e/planning/edit_planning.cy.ts b/e2e/cypress/e2e/planning/edit_planning.cy.ts index a67861636..72f3c55ad 100644 --- a/e2e/cypress/e2e/planning/edit_planning.cy.ts +++ b/e2e/cypress/e2e/planning/edit_planning.cy.ts @@ -1,4 +1,5 @@ -import {setup, login, waitForPageLoad, SubNavBar, Workqueue} from '../../support/common'; +import moment from 'moment'; +import {setup, login, waitForPageLoad, SubNavBar, Workqueue, CLIENT_FORMAT} from '../../support/common'; import {PlanningList, PlanningEditor, AssignmentEditor} from '../../support/planning'; describe('Planning.Planning: edit metadata', () => { @@ -20,7 +21,7 @@ describe('Planning.Planning: edit metadata', () => { it('can create a Planning item', () => { const plan = { slugline: 'slugline of the planning', - 'planning_date.date': '12/12/2045', + 'planning_date.date': moment().format(CLIENT_FORMAT), 'planning_date.time': '12:13', description_text: 'Desc. Text', internal_note: 'Int. Note', @@ -38,7 +39,7 @@ describe('Planning.Planning: edit metadata', () => { ednote: 'something to write about', internal_note: 'internal to us', news_coverage_status: 'On merit', - 'scheduled.date': '12/12/2045', + 'scheduled.date': moment().format(CLIENT_FORMAT), 'scheduled.time': '13:15', }]; @@ -66,7 +67,7 @@ describe('Planning.Planning: edit metadata', () => { it('can add coverage to workflow', () => { editor.type({ slugline: 'Plan', - 'planning_date.date': '12/12/2045', + 'planning_date.date': moment().format(CLIENT_FORMAT), 'planning_date.time': '12:13', }); editor.addCoverage('Picture'); @@ -95,7 +96,7 @@ describe('Planning.Planning: edit metadata', () => { it('not_for_publication flag will not enable post button', () => { const plan = { slugline: 'slugline of the planning', - 'planning_date.date': '12/12/2045', + 'planning_date.date': moment().format(CLIENT_FORMAT), 'planning_date.time': '12:13', }; @@ -149,7 +150,7 @@ describe('Planning.Planning: edit metadata', () => { editor.expectItemType(); editor.type({ slugline: 'slugline of the planning', - 'planning_date.date': '12/12/2045', + 'planning_date.date': moment().format(CLIENT_FORMAT), 'planning_date.time': '12:13', }); diff --git a/e2e/cypress/e2e/planning/planning_action_cancel.cy.ts b/e2e/cypress/e2e/planning/planning_action_cancel.cy.ts index bb9eb710c..3dec21205 100644 --- a/e2e/cypress/e2e/planning/planning_action_cancel.cy.ts +++ b/e2e/cypress/e2e/planning/planning_action_cancel.cy.ts @@ -2,6 +2,7 @@ import {setup, addItems, login, waitForPageLoad, Modal} from '../../support/comm import {TIME_STRINGS} from '../../support/utils/time'; import {PlanningList, PlanningEditor, PlanningPreview} from '../../support/planning'; import {getMenuItem} from '../../support/common/ui/actionMenu'; +import moment from 'moment'; describe('Planning.Planning: cancel planning item', () => { const editor = new PlanningEditor(); @@ -14,7 +15,7 @@ describe('Planning.Planning: cancel planning item', () => { setup({fixture_profile: 'planning_prepopulate_data'}, '/#/planning'); addItems('planning', [{ slugline: 'Test Planning Item', - planning_date: '2045-12-11' + TIME_STRINGS[0], + planning_date: moment().format('yy-MM-DD') + TIME_STRINGS[0], }]); login(); @@ -60,7 +61,7 @@ describe('Planning.Planning: cancel planning item', () => { list.item(0) .click(); - getMenuItem(list.item(0), 'Cancel Planning').realClick(); + getMenuItem(list.item(0), 'Cancel Planning').click(); modal.waitTillOpen(30000); diff --git a/e2e/cypress/e2e/search/search_combined.cy.ts b/e2e/cypress/e2e/search/search_combined.cy.ts index 64aa06fbe..cd5468715 100644 --- a/e2e/cypress/e2e/search/search_combined.cy.ts +++ b/e2e/cypress/e2e/search/search_combined.cy.ts @@ -103,7 +103,7 @@ describe('Search.Combined: searching events and planning', () => { search.openAllToggleBoxes(); search.runSearchTests([{ params: {}, - expectedCount: 14, + expectedCount: 6, expectedText: [ 'Event Today', 'Plan Today', @@ -111,14 +111,6 @@ describe('Search.Combined: searching events and planning', () => { 'Plan Tomorrow', 'Event Next Week', 'Plan Next Week', - 'Event Feb 1', - 'Plan Feb 1', - 'Event Feb 2', - 'Plan Feb 2', - 'Event Feb 3', - 'Plan Feb 3', - 'Event Feb 4', - 'Plan Feb 4', ], }, { params: { diff --git a/e2e/cypress/e2e/search/search_events.cy.ts b/e2e/cypress/e2e/search/search_events.cy.ts index ae1c0cb35..08991d4dd 100644 --- a/e2e/cypress/e2e/search/search_events.cy.ts +++ b/e2e/cypress/e2e/search/search_events.cy.ts @@ -144,15 +144,11 @@ describe('Search.Events: searching events', () => { search.runSearchTests([{ params: {}, - expectedCount: 7, + expectedCount: 3, expectedText: [ 'Event Today', 'Event Tomorrow', 'Event Next Week', - 'Event Feb 1', - 'Event Feb 2', - 'Event Feb 3', - 'Event Feb 4', ] }, { params: { diff --git a/e2e/cypress/e2e/search/search_planning.cy.ts b/e2e/cypress/e2e/search/search_planning.cy.ts index e41e54445..8960385e9 100644 --- a/e2e/cypress/e2e/search/search_planning.cy.ts +++ b/e2e/cypress/e2e/search/search_planning.cy.ts @@ -115,15 +115,11 @@ describe('Search.Planning: searching planning items', () => { search.runSearchTests([{ params: {}, - expectedCount: 7, + expectedCount: 3, expectedText: [ 'Plan Today', 'Plan Tomorrow', 'Plan Next Week', - 'Plan Feb 1', - 'Plan Feb 2', - 'Plan Feb 3', - 'Plan Feb 4', ], }, { params: { diff --git a/e2e/cypress/e2e/workqueue.cy.ts b/e2e/cypress/e2e/workqueue.cy.ts index 9111c35e5..5def5122a 100644 --- a/e2e/cypress/e2e/workqueue.cy.ts +++ b/e2e/cypress/e2e/workqueue.cy.ts @@ -1,5 +1,5 @@ import {setup, login, waitForPageLoad, Workqueue, Modal, addItems} from '../support/common'; -import {EventEditor, PlanningList} from '../support/planning'; +import {AdvancedSearch, EventEditor, PlanningList} from '../support/planning'; import {TEST_EVENTS} from '../fixtures/events'; describe('Planning.Workqueue', () => { @@ -7,6 +7,7 @@ describe('Planning.Workqueue', () => { const list = new PlanningList(); const workqueue = new Workqueue(); const modal = new Modal(); + const search = new AdvancedSearch(); beforeEach(() => { setup({fixture_profile: 'planning_prepopulate_data'}, '/#/planning'); @@ -22,6 +23,8 @@ describe('Planning.Workqueue', () => { TEST_EVENTS.date_03_02_2045, ]); + search.setStartDate('01/02/2045'); + // Wait for the 3 items to appear in the list list.expectItemCount(3); workqueue.expectItemCount(0); diff --git a/e2e/cypress/fixtures/events.ts b/e2e/cypress/fixtures/events.ts index f68b297ef..353aa2c7f 100644 --- a/e2e/cypress/fixtures/events.ts +++ b/e2e/cypress/fixtures/events.ts @@ -42,13 +42,8 @@ const BASE_EVENT = { }; export const TEST_EVENTS = { - draft: { + draft: getEventForDate(getDateStringFor.today(), { ...BASE_EVENT, - dates: { - start: '2045-12-11' + TIME_STRINGS[0], - end: '2045-12-11' + TIME_STRINGS[1], - tz: TIMEZONE, - }, name: 'Test', slugline: 'Original', anpa_category: [ @@ -67,18 +62,13 @@ export const TEST_EVENTS = { name: LOCATIONS.sydney_opera_house.name, address: LOCATIONS.sydney_opera_house.address, }], - }, - spiked: { + }), + spiked: getEventForDate(getDateStringFor.today(), { ...BASE_EVENT, - dates: { - start: '2045-12-11' + TIME_STRINGS[0], - end: '2045-12-11' + TIME_STRINGS[1], - tz: TIMEZONE, - }, state: 'spiked', name: 'Spiker', slugline: 'Spiked', - }, + }), date_01_02_2045: { ...BASE_EVENT, dates: { @@ -121,21 +111,21 @@ export const TEST_EVENTS = { }, }; -function getEventForDate(dateString: string, metadata: {[key: string]: any} = {}) { +function getEventForDate(dateString: string, metadata: {[key: string]: any} = {}, timezone = TIMEZONE) { return { ...BASE_EVENT, + ...metadata, dates: { start: dateString + TIME_STRINGS[0], end: dateString + TIME_STRINGS[1], - tz: TIMEZONE, + tz: timezone, }, - ...metadata, }; } export const createEventFor = { - today: (metadata = {}) => getEventForDate(getDateStringFor.today(), metadata), - tomorrow: (metadata = {}) => getEventForDate(getDateStringFor.tomorrow(), metadata), - yesterday: (metadata = {}) => getEventForDate(getDateStringFor.yesterday(), metadata), - next_week: (metadata = {}) => getEventForDate(getDateStringFor.next_week(), metadata), + today: (metadata = {}, timezone = TIMEZONE) => getEventForDate(getDateStringFor.today(), metadata, timezone), + tomorrow: (metadata = {}, timezone = TIMEZONE) => getEventForDate(getDateStringFor.tomorrow(), metadata, timezone), + yesterday: (metadata = {}, timezone = TIMEZONE) => getEventForDate(getDateStringFor.yesterday(), metadata, timezone), + next_week: (metadata = {}, timezone = TIMEZONE) => getEventForDate(getDateStringFor.next_week(), metadata, timezone), }; diff --git a/e2e/cypress/fixtures/planning.ts b/e2e/cypress/fixtures/planning.ts index 707b257fc..fe317b55f 100644 --- a/e2e/cypress/fixtures/planning.ts +++ b/e2e/cypress/fixtures/planning.ts @@ -12,10 +12,9 @@ const BASE_PLANNING = { }; export const TEST_PLANNINGS = { - draft: { + draft: getPlanningForDate(getDateStringFor.today(), { ...BASE_PLANNING, slugline: 'Original', - planning_date: '2045-12-11T01:00:00+0000', anpa_category: [ {name: 'Overseas Sport', qcode: 's'}, {name: 'International News', qcode: 'i'}, @@ -24,19 +23,17 @@ export const TEST_PLANNINGS = { {qcode: '01001000', name: 'archaeology', parent: '01000000'}, {qcode: '01011000', name: 'music', parent: '01000000'}, ], - }, - spiked: { + }), + spiked: getPlanningForDate(getDateStringFor.today(), { ...BASE_PLANNING, slugline: 'Spiker', - planning_date: '2045-12-11T01:00:00+0000', state: 'spiked', - }, - featured: { + }), + featured: getPlanningForDate(getDateStringFor.today(), { ...BASE_PLANNING, slugline: 'Featured Planning', - planning_date: '2045-12-12T01:00:00+0000', featured: true, - }, + }), plan_date_01_02_2045: { ...BASE_PLANNING, slugline: 'Plan Feb 1', diff --git a/e2e/cypress/support/common/utils.ts b/e2e/cypress/support/common/utils.ts index ffa077b42..edd00d85f 100644 --- a/e2e/cypress/support/common/utils.ts +++ b/e2e/cypress/support/common/utils.ts @@ -7,3 +7,5 @@ export function constructUrl(base, uri) { return base.replace(/\/$/, '') + uri; } + +export const CLIENT_FORMAT = 'DD/MM/yy'; diff --git a/e2e/cypress/support/planning/advancedSearch.ts b/e2e/cypress/support/planning/advancedSearch.ts index 3e420650e..71263cb8f 100644 --- a/e2e/cypress/support/planning/advancedSearch.ts +++ b/e2e/cypress/support/planning/advancedSearch.ts @@ -216,10 +216,9 @@ export class AdvancedSearch { } expectSearchResultCount(run: ISearchTest) { - cy.log('Search: ' + JSON.stringify(run.params)); + cy.log('Search: ' + JSON.stringify(run.params) + ', expected count: ' + run.expectedCount); if (Object.keys(run.params).length > 0) { - this.enterSearchParams(run.params); - this.clickSearch(); + this.searchFor(run.params); } if (run.expectedCount != null) { @@ -252,4 +251,16 @@ export class AdvancedSearch { .should('exist') .click(); } + + searchFor(params: ISearchTest['params']) { + this.enterSearchParams(params); + this.clickSearch(); + } + + setStartDate(date: string) { + this.toggleSearchPanel(); + this.openAllToggleBoxes(); + this.searchFor({'start_date.date': date}); + this.toggleSearchPanel(); + } } diff --git a/e2e/server/Dockerfile b/e2e/server/Dockerfile index dc7feea11..b26f1ce0c 100644 --- a/e2e/server/Dockerfile +++ b/e2e/server/Dockerfile @@ -6,6 +6,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python3 python3-dev python3-pip python3-venv git gcc curl \ # lxml libxml2-dev libxslt-dev \ +# xmlsec +pkg-config libxml2-dev libxmlsec1-dev libxmlsec1-openssl \ # PIL libjpeg-dev zlib1g-dev \ # magic diff --git a/package-lock.json b/package-lock.json index a7d9edec2..3133a817a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13563,7 +13563,7 @@ "sass-loader": "6.0.6", "shortid": "2.2.8", "style-loader": "0.20.2", - "superdesk-ui-framework": "^3.1.9", + "superdesk-ui-framework": "3.1.9", "ts-loader": "3.5.0", "typescript": "4.9.5", "uuid": "8.3.1",