Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix event date view #643

Merged
merged 36 commits into from
Feb 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
b143fa1
fix event date view
nileshgulia1 Feb 22, 2019
4e260ce
add changelog
nileshgulia1 Feb 22, 2019
44541fe
Merge branch 'master' into event_date-view
tisto Feb 23, 2019
e1c9a80
Merge branch 'master' into event_date-view
nileshgulia1 Mar 4, 2019
5bb5a81
Merge branch 'master' into event_date-view
nileshgulia1 Mar 27, 2019
26500ef
Merge branch 'master' into event_date-view
nileshgulia1 Apr 20, 2019
63ee0da
use config so that we can extend it, not used document view
nileshgulia1 Apr 24, 2019
1c42bd5
Merge branch 'master' into event_date-view
nileshgulia1 May 18, 2019
6a8d57d
Merge branch 'master' into event_date-view
pnicolli Jun 22, 2019
f82780b
Started work on the Event view with react-dates
pnicolli Jun 22, 2019
ae82474
Merge branch 'master' into event_date-view
pnicolli Jun 22, 2019
e0e43d3
Merge branch 'master' into event_date-view
pnicolli Jun 23, 2019
c93d56b
Added side segment with event info
pnicolli Jun 23, 2019
2764a05
Merge branch 'master' into event_date-view
pnicolli Jun 23, 2019
c8ec9b6
Fix event summary lists
pnicolli Jun 23, 2019
b3ad9c3
Added tests
pnicolli Jun 23, 2019
beffe2a
Merge branch 'master' into event_date-view
nileshgulia1 Sep 15, 2019
7276138
reccurence view implementation for Event occuring daily
nileshgulia1 Sep 20, 2019
732664d
added more conditionals for weekdays(reccursive view)
nileshgulia1 Sep 22, 2019
b5b64b2
master' into event_date-view
nileshgulia1 Nov 6, 2019
59e5114
Fix tests and open end bug
pnicolli Nov 6, 2019
a29da57
updated snapshots
nileshgulia1 Nov 10, 2019
4bcbc10
weekday condtional for recurrence except weekends
nileshgulia1 Nov 12, 2019
fde7b52
recurrence for particular day
nileshgulia1 Dec 10, 2019
6fec8f5
modified reccurence for weekly events
nileshgulia1 Dec 19, 2019
860b8bf
Merge branch 'master' into event_date-view
nileshgulia1 Dec 19, 2019
c3ea0b4
add react-helmet package
nileshgulia1 Dec 19, 2019
6296b29
fix tests
nileshgulia1 Dec 20, 2019
60bef03
Merge branch 'master' into event_date-view
pnicolli Jan 10, 2020
ca4d317
used forked react-helmet package
nileshgulia1 Jan 16, 2020
7829847
Merge branch 'event_date-view' of https://github.com/plone/volto into…
nileshgulia1 Jan 17, 2020
ef53e7c
Merge branch 'master' into event_date-view
nileshgulia1 Jan 17, 2020
7f38413
Merge branch 'master' into event_date-view
pnicolli Feb 10, 2020
46377d1
Added event type view
pnicolli Feb 10, 2020
755f7ba
Fixed dependencies
pnicolli Feb 10, 2020
7106f5b
Updated Event dates info naming
pnicolli Feb 14, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

### Added

- Event type view @nileshgulia1 @pnicolli

### Changes

- Include link and size info to the full size image in `ImageView` view component @sneridagh
Expand Down
5 changes: 5 additions & 0 deletions global-test-setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Fixes timezone for jest snapshots
// Seen here https://stackoverflow.com/questions/56261381/how-do-i-set-a-timezone-in-my-jest-config
module.exports = async () => {
process.env.TZ = 'UTC';
};
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
"setupFiles": [
"./test-setup.js"
],
"globalSetup": "./global-test-setup.js",
"globals": {
"__DEV__": true
}
Expand Down Expand Up @@ -317,6 +318,7 @@
"redux-mock-store": "1.5.3",
"redux-thunk": "2.3.0",
"release-it": "12.4.3",
"rrule": "2.6.4",
"semantic-ui-less": "2.4.1",
"semantic-ui-react": "0.88.1",
"semver": "5.6.0",
Expand Down
1 change: 1 addition & 0 deletions src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export DefaultView from '@plone/volto/components/theme/View/DefaultView';
export FileView from '@plone/volto/components/theme/View/FileView';
export ImageView from '@plone/volto/components/theme/View/ImageView';
export NewsItemView from '@plone/volto/components/theme/View/NewsItemView';
export EventView from '@plone/volto/components/theme/View/EventView';
export ListingView from '@plone/volto/components/theme/View/ListingView';
export Login from '@plone/volto/components/theme/Login/Login';
export Logout from '@plone/volto/components/theme/Logout/Logout';
Expand Down
123 changes: 123 additions & 0 deletions src/components/theme/View/EventDatesInfo.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import React from 'react';
import PropTypes from 'prop-types';
import { List } from 'semantic-ui-react';
import moment from 'moment';
import cx from 'classnames';
import { RRule } from 'rrule';

export const datesForDisplay = (start, end) => {
const mStart = moment(start);
const mEnd = moment(end);
if (!mStart.isValid() || !mEnd.isValid()) {
return null;
}
const sameDay = mStart.isSame(mEnd, 'day');
const sameTime = mStart.isSame(mEnd, 'minute');
return {
sameDay,
sameTime,
startDate: mStart.format('ll'),
startTime: mStart.format('LT'),
endDate: mEnd.format('ll'),
endTime: mEnd.format('LT'),
};
};

export const When = ({ start, end, whole_day, open_end }) => {
const datesInfo = datesForDisplay(start, end);
if (!datesInfo) {
console.warn('EventWhen: Received invalid start or end date.');
return;
}
// TODO I18N INTL
return (
<p
className={cx('event-when', {
'same-day': datesInfo.sameDay,
'same-time': datesInfo.sameTime,
'whole-day': whole_day,
'open-end': open_end,
})}
>
{!datesInfo.sameDay ? (
<>
<span className="start">
<span className="start-date">{datesInfo.startDate}</span>
{!whole_day && (
<>
{/* Plone has an optional word based on locale here */}
<span> </span>
<span className="start-time">{datesInfo.startTime}</span>
</>
)}
</span>
{!open_end && (
<>
&nbsp;to&nbsp;
<span className="end">
<span className="end-date">{datesInfo.endDate}</span>
{!whole_day && (
<>
{/* Plone has an optional word based on locale here */}
<span> </span>
<span className="end-time">{datesInfo.endTime}</span>
</>
)}
</span>
</>
)}
</>
) : (
<>
{whole_day && (
<span className="start-date">{datesInfo.startDate}</span>
)}
{open_end && !whole_day && (
<>
<span className="start-date">{datesInfo.startDate}</span>
&nbsp;from&nbsp;
<span className="start-time">{datesInfo.startTime}</span>
</>
)}
{!(whole_day || open_end) && (
<>
<span className="start-date">{datesInfo.startDate}</span>
&nbsp;from&nbsp;
<span className="start-time">{datesInfo.startTime}</span>
&nbsp;to&nbsp;
<span className="end-time">{datesInfo.endTime}</span>
</>
)}
</>
)}
</p>
);
};

When.propTypes = {
start: PropTypes.string.isRequired,
end: PropTypes.string,
whole_day: PropTypes.bool,
open_end: PropTypes.bool,
};

export const Recurrence = ({ recurrence, start }) => {
const rrule = new RRule({
...RRule.parseString(recurrence),
dtstart: new Date(start),
});

return (
<List
items={rrule
.all()
.map(date => datesForDisplay(date))
.map(date => date.startDate)}
/>
);
};

Recurrence.propTypes = {
recurrence: PropTypes.string.isRequired,
start: PropTypes.string.isRequired,
};
69 changes: 69 additions & 0 deletions src/components/theme/View/EventDatesInfo.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React from 'react';
import renderer from 'react-test-renderer';

import { When } from './EventDatesInfo';

test('different day, whole day', () => {
const component = renderer.create(
<When
start="2019-06-23T11:55:00+00:00"
end="2019-06-24T15:20:00+00:00"
whole_day={true}
open_end={false}
/>,
);
const json = component.toJSON();
expect(json).toMatchSnapshot();
});

test('different day, not whole day', () => {
const component = renderer.create(
<When
start="2019-06-23T11:55:00+00:00"
end="2019-06-24T15:20:00+00:00"
whole_day={false}
open_end={false}
/>,
);
const json = component.toJSON();
expect(json).toMatchSnapshot();
});

test('same day, whole day', () => {
const component = renderer.create(
<When
start="2019-06-23T11:55:00+00:00"
end="2019-06-23T15:20:00+00:00"
whole_day={true}
open_end={false}
/>,
);
const json = component.toJSON();
expect(json).toMatchSnapshot();
});

test('same day, not whole day, open end', () => {
const component = renderer.create(
<When
start="2019-06-23T11:55:00+00:00"
end="2019-06-23T15:20:00+00:00"
whole_day={false}
open_end={true}
/>,
);
const json = component.toJSON();
expect(json).toMatchSnapshot();
});

test('same day, not whole day, not open end', () => {
const component = renderer.create(
<When
start="2019-06-23T11:55:00+00:00"
end="2019-06-23T15:20:00+00:00"
whole_day={false}
open_end={false}
/>,
);
const json = component.toJSON();
expect(json).toMatchSnapshot();
});
144 changes: 144 additions & 0 deletions src/components/theme/View/EventView.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/**
* EventView view component.
* @module components/theme/View/EventView
*/

import React from 'react';
import PropTypes from 'prop-types';
import { Helmet } from '@plone/volto/helpers';
import { Container, Image, Segment, Header, List } from 'semantic-ui-react';

import { When, Recurrence } from './EventDatesInfo';

/**
* EventView view component class.
* @function EventView
* @params {object} content Content object.
* @returns {string} Markup of the component.
*/
const EventView = ({ content }) => (
<Container className="view-wrapper event-view">
<Helmet title={content.title} />
{content.title && <h1 className="documentFirstHeading">{content.title}</h1>}
{content.description && (
<p className="documentDescription">{content.description}</p>
)}
{content.image && (
<Image
className="document-image"
src={content.image.scales.thumb.download}
floated="right"
/>
)}
<Segment floated="right">
{/* TODO I18N INTL */}
{content.subjects.length > 0 && (
<>
<Header dividing sub>
What
</Header>
<List items={content.subjects} />
</>
)}
<Header dividing sub>
When
</Header>
<When
start={content.start}
end={content.end}
whole_day={content.whole_day}
open_end={content.open_end}
/>
{content.recurrence && (
<>
<Header dividing sub>
All dates
</Header>
<Recurrence recurrence={content.recurrence} start={content.start} />
</>
)}
{content.location && (
<>
<Header dividing sub>
Where
</Header>
<p>{content.location}</p>
</>
)}
{content.contact_name && (
<>
<Header dividing sub>
Contact Name
</Header>
<p>
{content.contact_email ? (
<a href={`mailto:${content.contact_email}`}>
{content.contact_name}
</a>
) : (
content.contact_name
)}
</p>
</>
)}
{content.contact_phone && (
<>
<Header dividing sub>
Contact Phone
</Header>
<p>{content.contact_phone}</p>
</>
)}
{content.attendees.length > 0 && (
<>
<Header dividing sub>
Attendees
</Header>
<List items={content.attendees} />
</>
)}
{content.event_url && (
<>
<Header dividing sub>
Web
</Header>
<p>
<a href={content.event_url}>Visit external website</a>
</p>
</>
)}
</Segment>
{content.text && (
<div dangerouslySetInnerHTML={{ __html: content.text.data }} />
)}
</Container>
);

/**
* Property types.
* @property {Object} propTypes Property types.
* @static
*/
EventView.propTypes = {
content: PropTypes.shape({
title: PropTypes.string,
description: PropTypes.string,
text: PropTypes.shape({
data: PropTypes.string,
}),
attendees: PropTypes.arrayOf(PropTypes.string).isRequired,
contact_email: PropTypes.string,
contact_name: PropTypes.string,
contact_phone: PropTypes.string,
end: PropTypes.string.isRequired,
event_url: PropTypes.string,
location: PropTypes.string,
open_end: PropTypes.bool,
recurrence: PropTypes.any,
start: PropTypes.string.isRequired,
subjects: PropTypes.arrayOf(PropTypes.string).isRequired,
whole_day: PropTypes.bool,
}).isRequired,
};

export default EventView;
Loading