Skip to content
Snippets Groups Projects
viewEvent.js 14.6 KiB
Newer Older
Hermann's avatar
Hermann committed
import m from 'mithril';
import { Button } from 'polythene-mithril';
import Stream from 'mithril/stream';
import { styler } from 'polythene-core-css';
import { DropdownCard, Chip } from 'amiv-web-ui-components';
Hermann's avatar
Hermann committed
// eslint-disable-next-line import/extensions
import { apiUrl } from 'networkConfig';
Hermann's avatar
Hermann committed
import ItemView from '../views/itemView';
import { ParticipantsController, ParticipantsTable } from './participants';
import { dateFormatter } from '../utils';
import { Property, FilterChip, icons } from '../views/elements';
import { colors } from '../style';
Hermann's avatar
Hermann committed
    '.propertyLangIndicator': {
      width: '30px',
      height: '20px',
      float: 'left',
      'background-color': 'rgb(031,045,084)',
      'border-radius': '10px',
      'text-align': 'center',
      'line-height': '20px',
      color: 'rgb(255,255,255)',
      'margin-right': '10px',
      'font-size': '11px',
Hermann's avatar
Hermann committed
    },
    '.eventViewLeft': {
    },
    '.eventViewRight': {
    },
    '.eventViewRight h4': {
// small helper class to display both German and English content together, dependent
// on which content is available.
class DuoLangProperty {
  view({ attrs: { title, de, en } }) {
Hermann's avatar
Hermann committed
    // TODO Lang indicators should be smaller and there should be less margin
    // between languages
    return m(
      Property,
      { title },
      de ? m('div', [
        m('div', { className: 'propertyLangIndicator' }, 'DE'),
        m('p', de),
      ]) : '',
      en ? m('div', [
        m('div', { className: 'propertyLangIndicator' }, 'EN'),
        m('p', en),
      ]) : '',
    );
class ParticipantsSummary {
  constructor() {
    this.onlyAccepted = true;
  }

  view({ attrs: { participants, additionalFields = "{'properties': {}}" } }) {
    // Parse the JSON from additional fields into an object
    const parsedParticipants = participants.map(signup => ({
      ...signup,
boian's avatar
boian committed
      additional_fields: signup.additional_fields
        ? JSON.parse(signup.additional_fields) : {},
    }));
    // Filter if only accepted participants should be shown
boian's avatar
boian committed
    const filteredParticipants = parsedParticipants.filter(
      participant => (this.onlyAccepted ? participant.accepted : true),
    );

    // check which additional fields should get summarized
    let hasSBB = false;
    let hasFood = false;
    if (additionalFields) {
      hasSBB = 'sbb_abo' in JSON.parse(additionalFields).properties;
      hasFood = 'food' in JSON.parse(additionalFields).properties;
    }

    return m('div', [
      m('div', {
        style: {
          height: '50px',
          'overflow-x': 'auto',
          'overflow-y': 'hidden',
          'white-space': 'nowrap',
          padding: '0px 5px',
        },
      }, [].concat(['Filters: '], ...[
        m(FilterChip, {
          selected: this.onlyAccepted,
          onclick: () => { this.onlyAccepted = !this.onlyAccepted; },
        }, 'accepted users'),
      ])),
      hasSBB ? m('div', { style: { display: 'flex' } }, [
boian's avatar
boian committed
        m(Property, { title: 'No SBB', leftAlign: false }, filteredParticipants.filter(
          signup => signup.additional_fields.sbb_abo === 'None',
        ).length),
        m(Property, { title: 'GA', leftAlign: false }, filteredParticipants.filter(
          signup => signup.additional_fields.sbb_abo === 'GA',
        ).length),
        m(Property, { title: 'Halbtax', leftAlign: false }, filteredParticipants.filter(
          signup => signup.additional_fields.sbb_abo === 'Halbtax',
        ).length),
        m(Property, { title: 'Gleis 7', leftAlign: false }, filteredParticipants.filter(
          signup => signup.additional_fields.sbb_abo === 'Gleis 7',
        ).length),
      ]) : '',
      hasFood ? m('div', { style: { display: 'flex' } }, [
boian's avatar
boian committed
        m(Property, { title: 'Omnivors', leftAlign: false }, filteredParticipants.filter(
          signup => signup.additional_fields.food === 'Omnivor',
        ).length),
        m(Property, { title: 'Vegis', leftAlign: false }, filteredParticipants.filter(
          signup => signup.additional_fields.food === 'Vegi',
        ).length),
        m(Property, { title: 'Vegans', leftAlign: false }, filteredParticipants.filter(
          signup => signup.additional_fields.food === 'Vegan',
        ).length),
      ]) : '',
      m('textarea', {
        style: { opacity: '0', width: '0px' },
        id: 'participantsemails',
      }, filteredParticipants.map(signup => signup.email).toString().replace(/,/g, '; ')),
      m(Button, {
        label: 'Copy Emails',
        events: {
          onclick: () => {
            document.getElementById('participantsemails').select();
            document.execCommand('copy');
          },
        },
      }),
    ]);
  }
}

Hermann's avatar
Hermann committed
export default class viewEvent extends ItemView {
Hermann's avatar
Hermann committed
  constructor(vnode) {
    super(vnode);
    this.participantsCtrl = new ParticipantsController();
carol's avatar
carol committed
    this.description = false;
    this.advertisement = false;
    this.registration = false;
    this.modalDisplay = Stream('none');
    this.participantsCtrl.setEventId(this.data._id);
  cloneEvent() {
    const event = Object.assign({}, this.data);

    const eventInfoToDelete = [
      '_id',
      '_created',
      '_etag',
      '_links',
      '_updated',
      'signup_count',
      'unaccepted_count',
      '__proto__',
    ];
    const now = new Date();
    if (event.time_end < `${now.toISOString().slice(0, -5)}Z`) {
      eventInfoToDelete.push(...[
        'time_advertising_end',
        'time_advertising_start',
        'time_end',
        'time_register_end',
        'time_deregister_end',
        'time_register_start',
        'time_start']);
    }
    eventInfoToDelete.forEach((key) => {
      delete event[key];
    });

    this.controller.changeModus('new');
    this.controller.data = event;
  }

Hermann's avatar
Hermann committed
  view() {
    let displaySpots = '-';
    const stdMargin = { margin: '5px' };
    // Get the image and insert it inside the modal -
    // use its "alt" text as a caption
    const modalImg = document.getElementById('modalImg');

    if (this.data.spots !== 0) {
      displaySpots = this.data.spots;
    }
carol's avatar
carol committed

Hermann's avatar
Hermann committed
    return this.layout([
Hermann's avatar
Hermann committed
      // this div is the title line
Hermann's avatar
Hermann committed
      m('div.maincontainer', [
Hermann's avatar
Hermann committed
        // event image if existing
        this.data.img_thumbnail ? m('img', {
          src: `${apiUrl}${this.data.img_thumbnail.file}`,
          style: { float: 'left', margin: '0 5px' },
Hermann's avatar
Hermann committed
        m('h1', this.data.title_de || this.data.title_en),
Hermann's avatar
Hermann committed
      // below the title, most important details are listed
Hermann's avatar
Hermann committed
      m('div.maincontainer', { style: { display: 'flex' } }, [
        this.data.type && m(Property, {
          style: stdMargin,
          title: 'Type',
        }, `${this.data.type.charAt(0).toUpperCase() + this.data.type.slice(1)}`),
        (this.data.spots !== null && 'signup_count' in this.data
boian's avatar
boian committed
         && this.data.signup_count !== null)
          ? m(Property, {
            style: stdMargin,
            title: 'Signups',
          }, `${this.data.signup_count} / ${displaySpots}`) : '',
        this.data.location && m(Property, {
          style: stdMargin,
Hermann's avatar
Hermann committed
          title: 'Location',
        }, `${this.data.location}`),
        this.data.time_start && m(Property, {
Hermann's avatar
Hermann committed
          title: 'Time',
          style: stdMargin,
        }, `${dateFormatter(this.data.time_start)} - ${dateFormatter(this.data.time_end)}`),
boian's avatar
boian committed
        this.data.moderator && m(Property, {
          title: 'Moderator',
          style: stdMargin,
        }, m.trust(`${this.data.moderator.firstname} ${this.data.moderator.lastname}
         (<a href='mailto:${this.data.moderator.email}'>${this.data.moderator.email}</a>)`)),
Hermann's avatar
Hermann committed
      ]),
Hermann's avatar
Hermann committed
      // everything else is not listed in DropdownCards, which open only on request
Hermann's avatar
Hermann committed
      m('div.viewcontainer', [
        m('div.viewcontainercolumn', [
          m(DropdownCard, { title: 'description' }, [
            m(DuoLangProperty, {
              title: 'Catchphrase',
              de: this.data.catchphrase_de,
              en: this.data.catchphrase_en,
            m(DuoLangProperty, {
              title: 'Description',
              de: this.data.description_de,
              en: this.data.description_en,
            }),
          ]),
carol's avatar
carol committed

          m(DropdownCard, { title: 'advertisement', style: { margin: '10px 0' } }, [
dporteni's avatar
dporteni committed
                svg: this.data.show_announce ? icons.checked : icons.clear,
                border: '1px #aaaaaa solid',
              }, 'announce'),
                svg: this.data.show_infoscreen ? icons.checked : icons.clear,
                border: '1px #aaaaaa solid',
                margin: '4px',
              }, 'infoscreen'),
                svg: this.data.show_website ? icons.checked : icons.clear,
                border: '1px #aaaaaa solid',
              }, 'website'),
            ],
            this.data.time_advertising_start ? m(
              Property,
Hermann's avatar
Hermann committed
              { title: 'Advertising Time' },
boian's avatar
boian committed
              `${dateFormatter(this.data.time_advertising_start)} - `
              + `${dateFormatter(this.data.time_advertising_end)}`,
            ) : '',
            this.data.priority ? m(
              Property,
              { title: 'Priority' },
              `${this.data.priority}`,
            ) : '',
          ]),

          m(DropdownCard, { title: 'Registration', style: { margin: '10px 0' } }, [
            this.data.price ? m(Property, { title: 'Price' }, `${this.data.price}`) : '',
            this.data.time_register_start ? m(
              Property,
              { title: 'Registration Time' },
boian's avatar
boian committed
              `${dateFormatter(this.data.time_register_start)} - `
              + `${dateFormatter(this.data.time_register_end)}`,
            this.data.time_deregister_end ? m(
              Property,
              { title: 'Deregistration Time' },
              `${dateFormatter(this.data.time_deregister_end)}`,
            ) : '',
            this.data.selection_strategy ? m(
              Property,
              { title: 'Selection Mode' },
              m.trust(this.data.selection_strategy),
            ) : '',
Hermann's avatar
Hermann committed
            this.data.allow_email_signup && m(Property, 'non AMIV-Members allowed'),
            this.data.additional_fields && m(
              Property,
              { title: 'Registration Form' },
              this.data.additional_fields,
            ),
            this.data.external_registration && m(
              Property,
              { title: 'External Registration' },
              m('a', { href: this.data.external_registration, target: '_blank' },
                this.data.external_registration),
            ),
Hermann's avatar
Hermann committed
          // a list of email adresses of all participants, easy to copy-paste
          this.data.spots !== null ? m(DropdownCard, {
            title: 'Participants Summary',
            style: { margin: '10px 0' },
          }, m(ParticipantsSummary, {
            participants: this.participantsCtrl.allParticipants,
            additionalFields: this.data.additional_fields,
          })) : '',
rdoerge's avatar
rdoerge committed
          m(DropdownCard, { title: 'Images' }, [
            m('div', {
              style: {
                display: 'flex',
              },
            }, [
              m('div', {
                style: {
                  width: '40%',
                  padding: '5px',
                },
              }, [
                this.data.img_poster && m('div', 'Poster'),
                this.data.img_poster && m('img', {
                  src: `${apiUrl}${this.data.img_poster.file}`,
                  width: '100%',
                    this.modalDisplay('block');
                    modalImg.src = `${apiUrl}${this.data.img_poster.file}`;
rdoerge's avatar
rdoerge committed
              m('div', {
                style: {
                  width: '52%',
                  padding: '5px',
                },
              }, [
                m('div', [
                  this.data.img_infoscreen && m('div', 'Infoscreen'),
                  this.data.img_infoscreen && m('img', {
                    src: `${apiUrl}${this.data.img_infoscreen.file}`,
                    width: '100%',
                      this.modalDisplay('block');
                      modalImg.src = `${apiUrl}${this.data.img_infoscreen.file}`;
        m('div.viewcontainercolumn', { style: { width: '50em' } }, [
Hermann's avatar
Hermann committed
          this.data.time_register_start ? m(ParticipantsTable, {
            title: 'Accepted Participants',
            filePrefix: 'accepted',
            event: this.data,
            waitingList: false,
            additional_fields_schema: this.data.additional_fields,
            participantsCtrl: this.participantsCtrl,
Hermann's avatar
Hermann committed
          }) : '',
          this.data.time_register_start ? m(ParticipantsTable, {
            title: 'Participants on Waiting List',
            filePrefix: 'waitinglist',
            event: this.data,
            waitingList: true,
            additional_fields_schema: this.data.additional_fields,
            participantsCtrl: this.participantsCtrl,
Hermann's avatar
Hermann committed
          }) : '',
      m('div', {
        id: 'imgModal',
        style: {
          display: this.modalDisplay(),
          position: 'fixed',
          'z-index': '100',
          'padding-top': '100px',
          left: 0,
          top: 0,
          width: '100vw',
          height: '100vh',
          overflow: 'auto',
          'background-color': 'rgba(0, 0, 0, 0.9)',
        },
      }, [
        m('img', {
          id: 'modalImg',
          style: {
            margin: 'auto',
            display: 'block',
            'max-width': '80vw',
            'max-heigth': '80vh',
          },
        }),
        m('div', {
          onclick: () => {
            this.modalDisplay('none');
          },
          style: {
            top: '15px',
            right: '35px',
            color: '#f1f1f1',
            transition: '0.3s',
            'z-index': 10,
            position: 'absolute',
            'font-size': '40px',
            'font-weight': 'bold',
          },
        }, 'x'),
      ]),
    ], [
      m(Button, {
        label: 'Clone Event',
        border: true,
        style: {
          color: colors.light_blue,
          'border-color': colors.light_blue,
        },
        events: {
          // opens 'new event' ,
          // coping All information but the 'event_id',  past dates and API generated properties
          onclick: () => this.cloneEvent(),
        },
      }),
Hermann's avatar
Hermann committed
}