diff --git a/.gitignore b/.gitignore index 91affb2268228030f769aa536aa4111733cd4df1..49bb99df82599fdf65aa796d6bdff59299d8b849 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ .ftpconfig node_modules/ package-lock.json + +.idea/ diff --git a/src/config.json b/src/config.json index 91e740875945e126e5b51c791d31a56674c99ca2..511510749233da02e7452d8e86f14f17544617da 100644 --- a/src/config.json +++ b/src/config.json @@ -83,6 +83,15 @@ "patchableKeys": ["user", "group"] }, "eventsignups": { - "patchableKeys": ["event"] + "patchableKeys": ["event"], + "tableKeys": [ + "_created", + "user.lastname", + "user.firstname", + "email" + ], + "searchKeys": [ + "email" + ] } } diff --git a/src/events/eventWithExport.js b/src/events/eventWithExport.js index 77a1ba41251f6ecb8ad251b8707c6c614a5f92f1..0c9ac713803e1907df7b386af96b809e7853d5bd 100644 --- a/src/events/eventWithExport.js +++ b/src/events/eventWithExport.js @@ -5,10 +5,27 @@ import { Card } from 'polythene-mithril'; import EditView from '../views/editView'; +import {styler} from 'polythene-core-css'; + +const draftStyle = [ + { + '.footer': { + position: 'fixed', + left: 0, + bottom: 0, + width: '100%', + 'background-color': '#E8462B', + 'text-align': 'right', + } + } +] + +styler.add('eventDraft', draftStyle); export default class eventWithExport extends EditView { constructor(vnode) { super(vnode, 'events'); + this.performedEdits = 0; } view() { @@ -18,6 +35,8 @@ export default class eventWithExport extends EditView { required: true, floatingLabel: true, dense: true, + onChange : (newState) => {this.title_en = this.title_en;}, + value: this.title_en, }); const fieldDescriptionEn = m(TextField, { label: 'Description [EN]', @@ -25,21 +44,26 @@ export default class eventWithExport extends EditView { floatingLabel: true, dense: true, multiLine: true, - rows: 6, - }); - const creatorButton = m(Button, { - label: 'EXPORT' - // label: 'Create a hyperlink string describing your project.' + rows: 6, + onChange : (newState) => {this.fieldDescriptionEn = this.fieldDescriptionEn;}, + value: this.fieldDescriptionEn, }); // Needs administrator (Kulturi). const fieldLocation = m(TextField, { label: 'Location:', floatingLabel: true, required: true, + onChange : (newState) => {this.fieldLocation = this.fieldLocation;}, + value: this.fieldLocation, + }); + const buttonMaker = m(Button, { + label: "Submit Request!", + onClick: () => alert("You did not finish the editing of the fields.") }); return m('div', [ - m('h1', 'For the event creator:', fieldTitleEn, fieldDescriptionEn, 'For the AMIV administrator:', fieldLocation, creatorButton), + m('h1', 'For the event creator:', fieldTitleEn , fieldDescriptionEn, 'For the AMIV administrator:', fieldLocation), + m('div.footer', buttonMaker), ]); } } \ No newline at end of file diff --git a/src/events/newEvent.js b/src/events/newEvent.js index 015adc1615b48e14216a15cb99f3f3af2079ef3a..3cff68aa1d0a4391bd6e61ca577ec273ace06f9c 100644 --- a/src/events/newEvent.js +++ b/src/events/newEvent.js @@ -1,13 +1,248 @@ import m from 'mithril'; +import { TextField, Button, Checkbox, RadioGroup, IconButton, SVG } from 'polythene-mithril'; import EditView from '../views/editView'; - +import { icons } from '../views/elements'; export default class newEvent extends EditView { constructor(vnode) { super(vnode, 'events'); + this.currentpage = 1; + } + + addOne() { + this.currentpage = this.currentpage + 1; + if (this.currentpage === 4) { + this.currentpage = 3; + } } - view() { - return m('h1', 'Hello World'); + subOne() { + this.currentpage = this.currentpage - 1; + if (this.currentpage === 0) { + this.currentpage = 1; + } + } + + view(vnode) { + if (!this.currentpage) return ''; + // German and English Information + const fieldTitleEn = m(TextField, { + label: 'Event Title [EN]', + required: true, + floatingLabel: true, + dense: true, + onChange: (newState) => { this.title_en = newState.value; console.log(this.title_en); }, + value: vnode.state.title_en, + }); + + const fieldCatchphraseEn = m(TextField, { + label: 'Catchphrase [EN]', + floatingLabel: true, + dense: true, + help: 'Fun description to make your event look more interesting than it is', + focusHelp: true, + }); + + const fieldDescriptionEn = m(TextField, { + label: 'Description [EN]', + required: true, + floatingLabel: true, + dense: true, + multiLine: true, + rows: 6, + }); + + const fieldTitleDe = m(TextField, { + label: 'Event Title [DE]', + floatingLabel: true, + dense: true, + }); + + const fieldCatchphraseDe = m(TextField, { + label: 'Catchphrase [DE]', + floatingLabel: true, + dense: true, + help: 'Fun description to make your event look more interesting than it is', + focusHelp: true, + }); + + const fieldDescriptionDe = m(TextField, { + label: 'Description [DE]', + floatingLabel: true, + dense: true, + multiLine: true, + rows: 6, + }); + + // Start of relevant data + + const fieldPrice = m(TextField, { + label: 'Price:', + type: 'number', + help: 'In Rappen/Cents', + focusHelp: true, + floatingLabel: true, + required: true, + }); + const fieldStartDate = m(TextField, { + label: 'Event Start[Date and Time]:', + help: 'Format: 01.01.1970-18:00', + focusHelp: true, + floatingLabel: true, + required: true, + }); + const fieldEndDate = m(TextField, { + label: 'Event End[Date and Time]:', + help: 'Format: 01.01.1970-1800', + focusHelp: true, + floatingLabel: true, + required: true, + }); + const fieldStartRegDate = m(TextField, { + label: 'Registration Start[Date and Time]:', + help: 'Format: 01.01.1970-18:00', + focusHelp: true, + floatingLabel: true, + required: true, + }); + const fieldEndRegDate = m(TextField, { + label: 'Registration End[Date and Time]:', + help: 'Format: 01.01.1970-1800', + focusHelp: true, + floatingLabel: true, + required: true, + }); + const fieldLocation = m(TextField, { + label: 'Location:', + floatingLabel: true, + required: true, + }); + const fieldNumberOfParticipants = m(TextField, { + label: 'Number of open spots:', + type: 'number', + floatingLabel: true, + required: true, + }); + + // Everything above is working fine atm. (13:35) + + const fieldAdvStart = m(TextField, { + label: 'Registration Start[Date and Time]:', + type: 'datetime', + help: 'Format: 01.01.1970-18:00', + focusHelp: true, + floatingLabel: true, + required: true, + }); + const fieldAdvEnd = m(TextField, { + label: 'Registration End[Date and Time]:', + help: 'Format: 01.01.1970-1800', + focusHelp: true, + floatingLabel: true, + required: true, + }); + + const buttonBannerUp = m(Button, { + label: 'Select Banner File', + events: { + onclick: () => console.log('click'), + }, + }); + + const buttonInfoUp = m(Button, { + label: 'Select Infoscreen File', + events: { + onclick: () => console.log('click'), + }, + }); + + const buttonPosterUp = m(Button, { + label: 'Select Poster File', + events: { + onclick: () => console.log('click'), + }, + }); + + const buttonThumbUp = m(Button, { + label: 'Select Thumbnail File', + events: { + onclick: () => console.log('click'), + }, + }); + + const buttonUploadAll = m(Button, { + label: 'Upload', + events: { + onclick: () => console.log('click'), + }, + }); + + const iconRight = m( + IconButton, { events: { onclick: () => { this.addOne(); } } }, + m(SVG, m.trust(icons.ArrowRight)), + ); + + const iconLeft = m( + IconButton, { events: { onclick: () => { this.subOne(); } } }, + m(SVG, m.trust(icons.ArrowLeft)), + ); + + const checkboxAnnounce = m(Checkbox, { + defaultChecked: false, + label: 'Advertise in Announce?', + value: '100', + }); + + const checkboxWebsite = m(Checkbox, { + defaultChecked: false, + label: 'Advertise on Website?', + value: '100', + }); + + const checkboxInfoScreen = m(Checkbox, { + defaultChecked: false, + label: 'Advertise on Infoscreen?', + value: '100', + }); + + const checkboxAllowMail = m(Checkbox, { + defaultChecked: false, + label: 'Allow non AMIV Members?', + value: '100', + }); + + const radioButtonSelectionMode = m(RadioGroup, { + name: 'Selection Mode', + buttons: [ + { + value: 'fcfs', + label: 'First come, first serve', + }, + { + value: 'manual', + label: 'Selection made by organizer', + }, + ], + }); + + function layoutWith(page) { + return m('div', page); + } + // checks currentPage and selects the fitting page + if (this.currentpage === 1) { + return layoutWith(m('h1', 'Event description:', iconLeft, iconRight, m('br'), fieldTitleEn, fieldCatchphraseEn, fieldDescriptionEn, fieldTitleDe, fieldCatchphraseDe, fieldDescriptionDe)); + } else if (this.currentpage === 2) { + return layoutWith(m( + 'h1', 'Critical Information:', iconLeft, iconRight, m('br'), fieldStartDate, fieldEndDate, fieldStartRegDate, + fieldEndRegDate, fieldLocation, fieldPrice, fieldNumberOfParticipants, + )); + } else if (this.currentpage === 3) { + return layoutWith(m( + 'h1', 'Advertise Information', iconLeft, iconRight, m('br'), fieldAdvStart, fieldAdvEnd, checkboxWebsite, + checkboxAnnounce, checkboxInfoScreen, buttonBannerUp, buttonInfoUp, buttonPosterUp, + buttonThumbUp, m('br'), buttonUploadAll, m('br'), checkboxAllowMail, radioButtonSelectionMode, + )); + } + return layoutWith(m('')); } } diff --git a/src/events/table.js b/src/events/table.js index 9b3d2247f4b679ab6f9c5820a1b10bb755fb3338..c913134220052a60762e7fd8b6547ad730c66d23 100644 --- a/src/events/table.js +++ b/src/events/table.js @@ -2,6 +2,7 @@ import m from 'mithril'; import { events as config } from '../config.json'; import TableView from '../views/tableView'; import DatalistController from '../listcontroller'; +import { dateFormatter } from '../utils'; /* Table of all Events @@ -10,20 +11,6 @@ import DatalistController from '../listcontroller'; */ -function dateFormatter(datestring) { - // converts an API datestring into the standard format 01.01.1990, 10:21 - if (!datestring) return ''; - const date = new Date(datestring); - return date.toLocaleString('de-DE', { - day: '2-digit', - month: '2-digit', - year: '2-digit', - hour: '2-digit', - minute: '2-digit', - }); -} - - export default class EventTable { constructor() { this.ctrl = new DatalistController('events', {}, config.tableKeys); diff --git a/src/events/viewEvent.js b/src/events/viewEvent.js index d1d82681634822af8e2cfc4f4609be3de8675939..fece3982ed3b26f8aa780e9ad93dbe527a30b2a1 100644 --- a/src/events/viewEvent.js +++ b/src/events/viewEvent.js @@ -1,13 +1,72 @@ import m from 'mithril'; +import { Checkbox, Button, Card, TextField, IconButton, Toolbar, ToolbarTitle } from 'polythene-mithril'; import ItemView from '../views/itemView'; -import {Button, Card, IconButton, Toolbar, ToolbarTitle } from "polythene-mithril" +import { events as config, eventsignups as signupConfig } from '../config.json'; +import TableView from '../views/tableView'; +import DatalistController from '../listcontroller'; +import { dateFormatter } from '../utils'; import { icons } from '../views/elements'; +import { styler } from 'polythene-core-css'; + +const viewLayout = [ + { + '.eventViewContainer': { + display: 'grid', + 'grid-template-columns': '50% 50%', + 'grid-gap': '50px', + }, + '.eventViewLeft': { + 'grid-column': 1, + }, + '.eventViewRight': { + 'grid-column': 2, + }, + '.eventViewRight h4': { + 'margin-top': '0px', + } + } +]; +styler.add('eventView', viewLayout); + + +class ParticipantsTable { + constructor({ attrs: { where } }) { + this.ctrl = new DatalistController('eventsignups', { + embedded: { user: 1 }, + where, + }, signupConfig.tableKeys); + } + + getItemData(data) { + return [ + m('div', { style: { width: '9em' } }, dateFormatter(data._created)), + m('div', { style: { width: '9em' } }, data.user.lastname), + m('div', { style: { width: '9em' } }, data.user.firstname), + m('div', { style: { width: '9em' } }, data.email), + ]; + } + + view() { + return m(Card, { + content: m(TableView, { + controller: this.ctrl, + keys: signupConfig.tableKeys, + tileContent: this.getItemData, + titles: [ + { text: 'Date of Signup', width: '9em' }, + { text: 'Name', width: '9em' }, + { text: 'First Name', width: '9em' }, + { text: 'Email', width: '9em' }, + ], + }), + }); + } +} export default class viewEvent extends ItemView { constructor() { super('events'); this.details = false; - this.participants = false; this.waitlist = false; this.emailAdresses = false; } @@ -17,26 +76,32 @@ export default class viewEvent extends ItemView { console.log(Object.keys(this)); console.log(this['data']); - let displayCatchphraseDe = null; - let displayCatchphraseEn = null; - let displayDescriptionDe = null; - let displayDescriptionEn = null; + let displayCatchphrase = null; + let displayDescription = null; let displayPriority = null; - if(this.data.catchphrase_de) { - displayCatchphraseDe = m("t3", {class: "text"}, this.data.catchphrase_de); + /*if(this.data.catchphrase_de) { + displayCatchphraseDe = m("t3", {class: "text"}, "de: " + this.data.catchphrase_de); } if(this.data.catchphrase_en) { - displayCatchphraseEn = m("t3", {class: "text"}, this.data.catchphrase_en); - } + displayCatchphraseEn = m("t3", {class: "text"}, "en: " + this.data.catchphrase_en); + }*/ - if(this.data.description_de) { - displayDescriptionDe = m("t3", {class: "text"}, this.data.description_de); + if(this.data.catchphrase_de && this.data.catchphrase_en) { + displayCatchphrase = m("t3", {class: "text"}, "de: " + this.data.catchphrase_de + " / en: " + this.data.catchphrase_en); + } else if(this.data.catchphrase_de) { + displayCatchphrase = m("t3", {class: "text"}, "de: " + this.data.catchphrase_de); + } else if(this.data.catchphrase_en) { + displayCatchphrase = m("t3", {class: "text"}, "en: " + this.data.catchphrase_en); } - if(this.data.description_en) { - displayDescriptionEn = m("t3", {class: "text"}, this.data.description_en); + if(this.data.description_de && this.data.description_en) { + displayDescription = m("t3", {class: "text"}, "de: " + this.data.description_de + " / en: " + this.data.description_en); + } else if(this.data.catchphrase_de) { + displayDescription = m("t3", {class: "text"}, "de: " + this.data.description_de); + } else if(this.data.catchphrase_en) { + displayDescription = m("t3", {class: "text"}, "en: " + this.data.description_en); } if(this.data.priority) { @@ -47,10 +112,6 @@ export default class viewEvent extends ItemView { m(IconButton, { icon: { svg: m.trust(icons.ArrowRight) } }), m(ToolbarTitle, { text: "details" }), ]); - let displayParticipantsButton = m(Toolbar, { compact: true, events: { onclick: () => this.participants = !this.participants } }, [ - m(IconButton, { icon: { svg: m.trust(icons.ArrowRight) } }), - m(ToolbarTitle, { text: "participants" }), - ]); let displayWaitlistButton = m(Toolbar, { compact: true, events: { onclick: () => this.waitlist = !this.waitlist } }, [ m(IconButton, { icon: { svg: m.trust(icons.ArrowRight) } }), m(ToolbarTitle, { text: "waitlist" }), @@ -63,7 +124,6 @@ export default class viewEvent extends ItemView { let displayDetails = null; - let displayParticipants = null; let displayWaitlist = null; let displayEmailAdresses = null; @@ -76,26 +136,24 @@ export default class viewEvent extends ItemView { content: [ { primary: { - title: "Catchphrase DE", - subtitle: displayCatchphraseDe + title: "Catchphrase", + subtitle: displayCatchphrase, } }, { - primary: { - title: "Catchphrase EN", - subtitle: displayCatchphraseEn - } + any: { + content: this.data.time_start ? m('p', m('strong', `when: from ${dateFormatter(this.data.time_start)} to ${dateFormatter(this.data.time_end)}`)) : '', + }, }, { - primary: { - title: "Description DE", - subtitle: displayDescriptionDe + any: { + content: this.data.location ? m('p', m('strong', `where: ${this.data.location}`)) : '', } }, { primary: { - title: "Description EN", - subtitle: displayDescriptionEn + title: "Description", + subtitle: displayDescription } }, { @@ -126,41 +184,6 @@ export default class viewEvent extends ItemView { }) } - if (this.participants) { - displayParticipantsButton = m(Toolbar, { compact: true, events: { onclick: () => this.participants = !this.participants } }, [ - m(IconButton, { icon: { svg: m.trust(icons.ArrowDown) } }), - m(ToolbarTitle, { text: "participants" }), - ]); - displayParticipants = m(Card, { - content: [ - { - primary: { - title: "Primary title", - subtitle: "Subtitle" - } - }, - { - actions: { - content: [ - m(Button, { - label: "Action 1" - }), - m(Button, { - label: "Action 2" - }) - ] - } - }, - { - text: { - content: "More text" - } - } - ] - - }) - } - if (this.waitlist) { displayWaitlistButton = m(Toolbar, { compact: true, events: { onclick: () => this.waitlist = !this.waitlist } }, [ m(IconButton, { icon: { svg: m.trust(icons.ArrowDown) } }), @@ -238,20 +261,26 @@ export default class viewEvent extends ItemView { m("h1", {class: "title"}, this.data.title_de), m(Button, {element: 'div', label: "Update Event"}), - displayDetailsButton, - displayDetails, + m('div.eventViewContainer', [ + m('div.eventViewLeft', [ + displayDetailsButton, + displayDetails, - displayParticipantsButton, - displayParticipants, + displayWaitlistButton, + displayWaitlist, - displayWaitlistButton, - displayWaitlist, - - displayEmailAdressesButton, - displayEmailAdresses, + displayEmailAdressesButton, + displayEmailAdresses, + ]), + m('div.eventViewRight', [ + m('h4', 'Accepted Participants'), + m(ParticipantsTable, { where: { accepted: true } }), + m('p', ''), + m('h4', 'Participants on Waiting List'), + m(ParticipantsTable, { where: { accepted: false } }), + ]) + ]), ]) } - - } diff --git a/src/utils.js b/src/utils.js index 0844554c3394f8eb10130d35cd701c4dcd8d49c3..577facb26af4ab08eb5dfffa3f45f25e0a02d5dc 100644 --- a/src/utils.js +++ b/src/utils.js @@ -17,3 +17,16 @@ export function debounce(func, wait, immediate) { if (callNow) func.apply(context, args); }; } + +export function dateFormatter(datestring) { + // converts an API datestring into the standard format 01.01.1990, 10:21 + if (!datestring) return ''; + const date = new Date(datestring); + return date.toLocaleString('de-DE', { + day: '2-digit', + month: '2-digit', + year: '2-digit', + hour: '2-digit', + minute: '2-digit', + }); +} \ No newline at end of file diff --git a/src/views/elements.js b/src/views/elements.js index 3e60b74ddf111fe15266b3f55fb5b2f42e566ab0..98cd7d9e67eca4461b7f2cf728dd2bd0b9df6343 100644 --- a/src/views/elements.js +++ b/src/views/elements.js @@ -52,6 +52,7 @@ export const icons = { ArrowDown: '<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M7.41 7.84L12 12.42l4.59-4.58L18 9.25l-6 6-6-6z"/><path d="M0-.75h24v24H0z" fill="none"/></svg>', iconUsersSVG: '<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M3 5v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2H5c-1.11 0-2 .9-2 2zm12 4c0 1.66-1.34 3-3 3s-3-1.34-3-3 1.34-3 3-3 3 1.34 3 3zm-9 8c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6v-1z"/><path d="M0 0h24v24H0z" fill="none"/></svg>', iconEventSVG: '<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M9 11H7v2h2v-2zm4 0h-2v2h2v-2zm4 0h-2v2h2v-2zm2-7h-1V2h-2v2H8V2H6v2H5c-1.11 0-1.99.9-1.99 2L3 20c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 16H5V9h14v11z"/><path d="M0 0h24v24H0z" fill="none"/></svg>', + ArrowLeft: '<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M15.41 16.09l-4.58-4.59 4.58-4.59L14 5.5l-6 6 6 6z"/><path d="M0-.5h24v24H0z" fill="none"/></svg>', }; export const BackButton = { diff --git a/src/views/tableView.js b/src/views/tableView.js index a7ef8ef525c36d4d1d633a10491ed64ba8bfe016..5b7584f9d48a1ae5625c44f6abc84ad44ed00899 100644 --- a/src/views/tableView.js +++ b/src/views/tableView.js @@ -61,18 +61,25 @@ export default class TableView { } item() { - return (data, opts) => m(ListTile, { - className: 'themed-list-tile', - hoverable: true, - compactFront: true, - content: m('div', { - onclick() { m.route.set(`/${data._links.self.href}`); }, - className: 'tableTile', - style: { width: '100%', display: 'flex' }, - }, this.tileContent ? this.tileContent(data) : this.getItemData(data)), - }); + return (data, opts) => { + console.log(data); + console.log(this.tileContent); + return m(ListTile, { + className: 'themed-list-tile', + hoverable: true, + compactFront: true, + content: m('div', { + onclick() { + m.route.set(`/${data._links.self.href}`); + }, + className: 'tableTile', + style: { width: '100%', display: 'flex' }, + }, this.tileContent ? this.tileContent(data) : this.getItemData(data)), + }); + }; } + view({ attrs: { controller,