--- html_meta: "description": "" "property=og:description": "" "property=og:title": "" "keywords": "" --- (events-label)= # Turning Talks into Events ````{sidebar} Plone Frontend Chapter ```{figure} _static/plone-training-logo-for-frontend.svg :alt: Plone frontend :align: left :class: logo ``` Solve the same tasks in Plone Classic UI in chapter {doc}`events_classic` --- Get the code! ({doc}`More info `) Code for the beginning of this chapter: ```shell # frontend git checkout talklist ``` ```shell # backend git checkout talklist ``` Code for the end of this chapter: ```shell # frontend git checkout event ``` ```shell # backend git checkout event ``` ```` We forgot something: a list of talks is great, especially if you can sort it according to your preferences. But if a visitor decides she wants to actually go to see a talk she needs to know when it will take place. We need a schedule and for this we need to store the information when a talk will happen. Luckily the default type _Event_ is based on reusable behaviors from the package {py:mod}`plone.app.event` that we can reuse. In this chapter you will - enable this behavior for talks - display the date in the talkview and talklistview ```{note} This chapter uses Volto to change displaying the dates in talkview and talklistview. To meet the same requirements in classic Plone see the chapter {doc}`events_classic`. ``` ## Add date fields Instead of adding Datetime-fields to the talk schema we will use the behavior `plone.eventbasic`. Enable the behavior `plone.eventbasic` for talks in {file}`profiles/default/types/talk.xml`. ```{code-block} xml :emphasize-lines: 6 :linenos: ``` After you activate the behavior by hand or you reinstalled the add-on you will now have some additional fields for `start`, `end`, `open_end` and `whole_day`. ````{note} While we're editing behaviors we can also add our own featured-behavior to News Items. Add {file}`profiles/default/types/News_Item.xml`: ``` ``` ```` ## Display the dates Now we need to update the event view to show this information. Unfortuanely displaying dates and times is not as simple as it might sound since we'd have to account for different use cases that all look different: Here are some examples how dates might be displayed if they are full-day events, open-ended events or events with a defined end-time. - Apr 22, 2020 from 3:00 PM to 5:00 PM - Apr 22, 2020 - Apr 22, 2020 7:00 PM - Apr 22, 2020 to Apr 24, 2020 - Apr 22, 2020 7:00 PM to Apr 29, 2020 8:00 PM Now consider that dates are displayed different in other languages and it really gets complicated. So it would be a good idea to reuse a component that already deals with these use-cases. Since we use the same behavior as the default content type Event in Plone, the default event-view might have what we need. Add an event und use the React Developer Tools to inspect the component displaying the date. The component is called `When` and is defined in `frontend/node_modules/@plone/volto/src/components/theme/View/EventDatesInfo.jsx`. ```jsx ``` We'll reuse it in {file}`frontend/src/components/Views/Talk.jsx`. We'll let us inspire by the event-view and add a `` that will contain the date and also the room and the audience. In this box we will also use `
` (from [seamantic-ui](https://react.semantic-ui.com/elements/header/#types-subheaders) to separate the data. {file}`frontend/src/components/Views/Talk.jsx`: ```{code-block} jsx :emphasize-lines: 4,20-48 import React from 'react'; import { flattenToAppURL } from '@plone/volto/helpers'; import { Container, Header, Image, Label, Segment } from 'semantic-ui-react'; import { When } from '@plone/volto/components/theme/View/EventDatesInfo'; const TalkView = ({ content }) => { const color_mapping = { Beginner: 'green', Advanced: 'yellow', Professional: 'purple', }; return (

{content.type_of_talk.title || content.type_of_talk.token}:{' '} {content.title}

{content.start && !content.hide_date && ( <>
When
)} {content.audience && (
Audience
)} {content.audience?.map(item => { let audience = item.title || item.token; let color = color_mapping[audience] || 'green'; return ( ); })}
{content.description && (

{content.description}

)} {content.details && (
)} {content.speaker && (
{content.speaker}
{content.website ? (

{content.company}

) : (

{content.company}

)} {content.email && (

{content.email}

)} {content.twitter && (

{' '} {content.twitter.startsWith('@') ? content.twitter : '@' + content.twitter}

)} {content.github && (

{content.github}

)} {content.image && ( {content.image_caption} )} {content.speaker_biography && (
)} )} ); }; export default TalkView; ``` The result should look like this: ```{figure} _static/event_view_volto.png ``` ## Hiding fields from certain users ```{note} This chapter is about displaying, not editing. So setting values is not the topic here. ``` The problem now appears that speakers submitting their talks should not be able to set a time and day for their talks. Sadly it is not easy to modify permissions of fields provided by behaviors unless you write the behavior yourself. At least in this case we can take the easy way out since the field does not contain secret information: We can simply hide the fields from contributors using css and show them for reviewers. ```{warning} This trick does not yet work in Volto because some css-classes are still missing from the body-tag (see ). Skip ahead! ``` Modify {file}`frontend/theme/extras/custom.overrides` and add: ```less // Hide date fields from contributors body.userrole-contributor { #default-start.field, #default-end.field, #default-whole_day.field, #default-open_end.field { display: none; } } body.userrole-reviewer { #default-start.field, #default-end.field, #default-whole_day.field, #default-open_end.field { display: block; } } ``` ## Display the date in the listing ```{eval-rst} .. todo:: Adapt ``TalkListView`` to handle the date and time. ``` ### Exercise Find out where the event behavior is defined and which fields it offers. ````{admonition} Solution :class: toggle The name you used to enable the behavior {file}`Talk.xml` is registered in zcml. So `name="plone.eventbasic"` should be easy to find. You will find it in {file}`backend/packages/plone/app/event/dx/configure.zcml` and it points to `IEventBasic` in {file}`packages/plone.app.event/plone/app/event/dx/behaviors.py` ```python class IEventBasic(model.Schema, IDXEvent): """ Basic event schema. """ start = schema.Datetime( title=_( u'label_event_start', default=u'Event Starts' ), description=_( u'help_event_start', default=u'Date and Time, when the event begins.' ), required=True, defaultFactory=default_start ) directives.widget( 'start', DatetimeFieldWidget, default_timezone=default_timezone, klass=u'event_start' ) end = schema.Datetime( title=_( u'label_event_end', default=u'Event Ends' ), description=_( u'help_event_end', default=u'Date and Time, when the event ends.' ), required=True, defaultFactory=default_end ) directives.widget( 'end', DatetimeFieldWidget, default_timezone=default_timezone, klass=u'event_end' ) whole_day = schema.Bool( title=_( u'label_event_whole_day', default=u'Whole Day' ), description=_( u'help_event_whole_day', default=u'Event lasts whole day.' ), required=False, default=False ) directives.widget( 'whole_day', SingleCheckBoxFieldWidget, klass=u'event_whole_day' ) open_end = schema.Bool( title=_( u'label_event_open_end', default=u'Open End' ), description=_( u'help_event_open_end', default=u"This event is open ended." ), required=False, default=False ) directives.widget( 'open_end', SingleCheckBoxFieldWidget, klass=u'event_open_end' ) ``` Note how it uses `defaultFactory` to set an initial value. ```` ## Summary - You reused a existing behavior to add new fields - You reused a existing component to display the date - You did not have to write your own datetime fields and indexers o/ ```{note} To meet the same requirements in classic Plone see the chapter {doc}`events_classic` ```