diff --git a/src/eventTool.js b/src/eventTool.js index 2cdf9fa59ef35f55b9cf7a5e64c1ba79d6b3205b..92d9af899a075f1dc27822e2377ff4380d5b7028 100644 --- a/src/eventTool.js +++ b/src/eventTool.js @@ -164,14 +164,3 @@ export class EventModal { ]); } } - -export class EventTable { - view() { - return m(TableView, { - resource: 'events', - keys: config.tableKeys, - titles: config.tableKeys.map(key => config.keyDescriptors[key] || key), - onAdd: () => { m.route.set('/newevent'); }, - }); - } -} diff --git a/src/events/newEvent.js b/src/events/newEvent.js index 4a41aac85250a417438fc9a17a0bc90f3db7b558..ddc37b107ecbfee606854f10257f00fa8c477621 100644 --- a/src/events/newEvent.js +++ b/src/events/newEvent.js @@ -1,18 +1,29 @@ import m from 'mithril'; -import { TextField, Button, Checkbox, RadioGroup, IconButton, SVG } from 'polythene-mithril'; +import { Button, Checkbox, RadioGroup, IconButton, SVG, TextField } from 'polythene-mithril'; +import { styler } from 'polythene-core-css'; import EditView from '../views/editView'; -import { icons } from '../views/elements'; +import { icons, textInput, datetimeInput } from '../views/elements'; + +const style = [ + { + '.mywrapper': { + padding: '10px', + }, + }, +]; +styler.add('event-add', style); + export default class newEvent extends EditView { constructor(vnode) { - super(vnode, 'events'); + super(vnode, 'events', {}); this.currentpage = 1; } addOne() { this.currentpage = this.currentpage + 1; - if (this.currentpage === 4) { - this.currentpage = 3; + if (this.currentpage === 5) { + this.currentpage = 4; } } @@ -23,159 +34,65 @@ export default class newEvent extends EditView { } } - view(vnode) { + view() { 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 firstTableInputs = { + title_en: { + label: 'English Event Title', }, - }); - - const buttonInfoUp = m(Button, { - label: 'Select Infoscreen File', - events: { - onclick: () => console.log('click'), + catchphrase_en: { + label: 'English Catchphrase', }, - }); - - const buttonPosterUp = m(Button, { - label: 'Select Poster File', - events: { - onclick: () => console.log('click'), + description_en: { + label: 'English Description', + multiLine: true, + rows: 5, }, - }); + title_de: { + label: 'German Event Title', + }, + catchphrase_de: { + label: 'German Catchphrase', + }, + description_de: { + label: 'German Description', + multiLine: true, + rows: 5, + }, + }; - const buttonThumbUp = m(Button, { - label: 'Select Thumbnail File', - events: { - onclick: () => console.log('click'), + const thirdTableInputs = { + spots: { + label: 'Number of Spots', + help: '0 for open event', + focusHelp: true, }, - }); + price: { + label: 'Price', + }, + time_register_start: { + label: 'Start of Registration', + }, + time_register_end: { + label: 'End of Registration', + }, + }; - const buttonUploadAll = m(Button, { - label: 'Upload', - events: { - onclick: () => console.log('click'), + const forthTableInputs = { + time_advertising_start: { + label: 'Start of Advertisement', + type: 'datetime', + required: true, }, - }); + time_advertising_end: { + label: 'End of Advertisement', + required: true, + }, + priority: { + label: 'Priority', + } + }; const iconRight = m( IconButton, { events: { onclick: () => { this.addOne(); } } }, @@ -225,45 +142,69 @@ export default class newEvent extends EditView { ], }); - function layoutWith(page) { - return m('div', page); - } + const title = [ + 'Create an Event', 'When and Where?', 'Signups', 'Advertisement' + ][this.currentpage - 1]; + // checks currentPage and selects the fitting page - if (this.currentpage === 1) { - return layoutWith(m( - 'div', { style: { height: '100%', 'overflow-y': 'scroll' } } - , [ - m( - 'h1', 'Event description:', iconLeft, iconRight, m('br'), - fieldTitleEn, fieldCatchphraseEn, fieldDescriptionEn, fieldTitleDe, - fieldCatchphraseDe, fieldDescriptionDe, - ), - ], - )); - } else if (this.currentpage === 2) { - return layoutWith(m( - 'div', { style: { height: '100%', 'overflow-y': 'scroll' } } - , [ - m( - 'h1', 'Critical Information:', iconLeft, iconRight, m('br'), fieldStartDate, - fieldEndDate, fieldStartRegDate, fieldEndRegDate, fieldLocation, fieldPrice, - fieldNumberOfParticipants, - ), - ], - )); - } else if (this.currentpage === 3) { - return layoutWith(m( - 'div', { style: { height: '100%', 'overflow-y': 'scroll' } } - , [ - 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('')); + return m('div.mywrapper', [ + m('h1', title), + m('br'), + iconLeft, + iconRight, + m('br'), + m('div', { + style: { + display: (this.currentpage === 1) ? 'block' : 'none', + }, + }, Object.keys(firstTableInputs).map((key) => { + const attrs = firstTableInputs[key]; + const attributes = Object.assign({}, attrs); + attributes.name = key; + attributes.floatingLabel = true; + return m(textInput, this.bind(attributes)); + })), + m('div', { + style: { + display: (this.currentpage === 2) ? 'block' : 'none', + }, + }, [ + m(datetimeInput, this.bind({ + name: 'time_start', + label: 'Event Start Time', + })), + m(datetimeInput, this.bind({ + name: 'time_end', + label: 'Event End Time', + })), + m(textInput, this.bind({ + name: 'location', + label: 'Location', + floatingLabel: true, + })), + ]), + m('div', { + style: { + display: (this.currentpage === 3) ? 'block' : 'none', + }, + }, Object.keys(thirdTableInputs).map((key) => { + const attrs = thirdTableInputs[key]; + const attributes = Object.assign({}, attrs); + attributes.name = key; + attributes.floatingLabel = true; + return m(textInput, this.bind(attributes)); + })), + m('div', { + style: { + display: (this.currentpage === 4) ? 'block' : 'none', + }, + }, Object.keys(forthTableInputs).map((key) => { + const attrs = forthTableInputs[key]; + const attributes = Object.assign({}, attrs); + attributes.name = key; + attributes.floatingLabel = true; + return m(textInput, this.bind(attributes)); + })), + ]); } } diff --git a/src/events/viewEvent.js b/src/events/viewEvent.js index 78e8d26d66421cdea932cd41a75fbc03beb509a7..e4fd3132dc2745957b6177bb8f3a65722b27c844 100644 --- a/src/events/viewEvent.js +++ b/src/events/viewEvent.js @@ -1,13 +1,21 @@ import m from 'mithril'; -import { Switch, Button, Card, TextField, IconButton, Toolbar, ToolbarTitle, MaterialDesignSpinner as Spinner } from 'polythene-mithril'; +import { + Switch, + Button, + Card, + TextField, + IconButton, + Toolbar, + ToolbarTitle, +} from 'polythene-mithril'; +import { styler } from 'polythene-core-css'; import ItemView from '../views/itemView'; -import { events as config, eventsignups as signupConfig } from '../config.json'; +import { 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'; -import {ResourceHandler} from "../auth"; +import { ResourceHandler } from '../auth'; const viewLayout = [ { @@ -48,6 +56,22 @@ const viewLayout = [ 'margin-top': '0px', } } + { + '.eventViewContainer': { + display: 'grid', + 'grid-template-columns': '40% 60%', + 'grid-gap': '50px', + }, + '.eventViewLeft': { + 'grid-column': 1, + }, + '.eventViewRight': { + 'grid-column': 2, + }, + '.eventViewRight h4': { + 'margin-top': '2px', + }, + }, ]; styler.add('eventView', viewLayout); @@ -105,7 +129,6 @@ class ParticipantsTable { } view() { - return m(Card, { content: m(TableView, { controller: this.ctrl, @@ -123,40 +146,45 @@ class ParticipantsTable { } class EmailList { - view({ attrs: { list } }) { - const emails = list.toString().replace(/,/g, '; '); - return m(Card, { - content: m(TextField, { value: emails, label: '', multiLine: true }, ''), - }); - } + view({ attrs: { list } }) { + const emails = list.toString().replace(/,/g, '; '); + return m(Card, { + content: m(TextField, { value: emails, label: '', multiLine: true }, ''), + }); + } } export default class viewEvent extends ItemView { - constructor() { - super('events'); - this.signupHandler = new ResourceHandler('eventsignups'); - this.details = false; - this.emailAdresses = false; - + constructor() { + super('events'); + this.signupHandler = new ResourceHandler('eventsignups'); + this.details = false; + this.emailAdresses = false; + this.emaillist = ['']; + this.showAllEmails = false; + } - this.emaillist = ['']; - this.showAllEmails = false; - this.setUpEmailList(this.showAllEmails); - } + oninit() { + this.handler.getItem(this.id, this.embedded).then((item) => { + this.data = item; + m.redraw(); + }); + this.setUpEmailList(this.showAllEmails); + } - setUpEmailList(showAll) { - if (!showAll) { - this.signupHandler.get({ where: { accepted: true } }).then((data) => { - this.emaillist = (data._items.map(item => item.email)); - }); - } - else { - this.signupHandler.get({}).then((data) => { - this.emaillist = (data._items.map(item => item.email)); - }); - } + setUpEmailList(showAll) { + if (!showAll) { + this.signupHandler.get({ where: { accepted: true } }).then((data) => { + this.emaillist = (data._items.map(item => item.email)); m.redraw(); + }); + } else { + this.signupHandler.get({}).then((data) => { + this.emaillist = (data._items.map(item => item.email)); + m.redraw(); + }); } + } view() { if (!this.data) return ''; @@ -172,6 +200,8 @@ export default class viewEvent extends ItemView { m(ToolbarTitle, { text: "email adresses" }), ]); + + let displayDetails = null; let displayWaitlist = null; let displayEmailAdresses = null; @@ -205,7 +235,6 @@ export default class viewEvent extends ItemView { en: this.data.description_en, }), ] - } }, { diff --git a/src/index.js b/src/index.js index fee7d341d902bf5f349f7014387583a0e887ff09..4d9ef91d294ec4e30f2b4e9b2d9bcc33228ff3dc 100644 --- a/src/index.js +++ b/src/index.js @@ -9,12 +9,9 @@ import viewEvent from './events/viewEvent'; import eventDraft from './events/eventDraft'; import eventWithExport from './events/eventWithExport'; import Layout from './layout'; -// import AnnounceTool from './announceTool'; import './style'; -const main = document.createElement('div'); -document.body.appendChild(main); -const root = main; +const root = document.body; function layoutWith(view) { diff --git a/src/views/editView.js b/src/views/editView.js index 91db119c24d2b021f4d0a3111e0625cd4e43b6d4..4b2c4b0badfccf4ae7f8afb03279c977c30e3823 100644 --- a/src/views/editView.js +++ b/src/views/editView.js @@ -29,6 +29,7 @@ export default class EditView extends ItemView { constructor(vnode, resource, embedded, valid = true) { super(resource, embedded); this.changed = false; + this.resource = resource; // state for validation this.valid = valid; @@ -38,6 +39,7 @@ export default class EditView extends ItemView { allErrors: true, }); this.errors = {}; + this.data = {}; // callback when edit is finished this.callback = vnode.attrs.onfinish; @@ -55,6 +57,15 @@ export default class EditView extends ItemView { m.request(`${apiUrl}docs/api-docs`).then((schema) => { const objectSchema = schema.definitions[ objectNameForResource[this.resource]]; + console.log(objectSchema); + // filter out any field that is of type media and replace with type + // object + Object.keys(objectSchema.properties).forEach((property) => { + if (objectSchema.properties[property].type === 'media' || + objectSchema.properties[property].type === 'json_schema_object') { + objectSchema.properties[property].type = 'object'; + } + }); this.ajv.addSchema(objectSchema, 'schema'); }); } @@ -65,10 +76,12 @@ export default class EditView extends ItemView { if (!this.errors[attrs.name]) this.errors[attrs.name] = []; const boundFormelement = { - onchange: (e) => { + onChange: (name, value) => { this.changed = true; // bind changed data - this.data[e.target.name] = e.target.value; + this.data[name] = value; + + console.log(this.data); // validate against schema const validate = this.ajv.getSchema('schema'); diff --git a/src/views/elements.js b/src/views/elements.js index 98cd7d9e67eca4461b7f2cf728dd2bd0b9df6343..875001950f82a8a3d671ea1c4dc9ba5384afffe2 100644 --- a/src/views/elements.js +++ b/src/views/elements.js @@ -2,12 +2,14 @@ import m from 'mithril'; import { IconButton, TextField } from 'polythene-mithril'; export class textInput { - constructor({ attrs: { getErrors } }) { + constructor({ attrs: { getErrors, name, label } }) { // Link the error-getting function from the binding this.getErrors = () => []; + this.name = name; if (getErrors) { this.getErrors = getErrors; } + this.value = ''; } view({ attrs }) { @@ -15,12 +17,92 @@ export class textInput { const errors = this.getErrors(); const attributes = Object.assign({}, attrs); - attributes.valid = errors.length > 0; + attributes.valid = errors.length === 0; attributes.error = errors.join(', '); + attributes.onChange = ({ value }) => { + if (value !== this.value) { + this.value = value; + attrs.onChange(this.name, value); + } + }; return m(TextField, attributes); } } +export class datetimeInput { + constructor({ attrs: { getErrors, name, onChange } }) { + // Link the error-getting function from the binding + this.getErrors = () => []; + this.name = name; + if (getErrors) { + this.getErrors = getErrors; + } + this.value = ''; + this.date = null; + this.time = null; + this.onChangeCallback = onChange; + } + + onChange() { + if (this.date && this.time) { + const date = new Date(this.date); + const h_m = this.time.split(':'); + date.setHours(h_m[0]); + date.setMinutes(h_m[1]); + if (this.onChangeCallback) { + this.onChangeCallback(this.name, date.toISOString()); + } + } + } + + view({ attrs: { label } }) { + // set display-settings accoridng to error-state + const errors = this.getErrors(); + + const date = { + type: 'date', + style: { + width: '150px', + float: 'left', + }, + onChange: ({ value }) => { + if (value !== this.date) { + this.date = value; + this.onChange(); + } + }, + valid: errors.length === 0, + error: errors.join(', '), + }; + + const time = { + type: 'time', + style: { + width: '100px', + }, + onChange: ({ value }) => { + if (value !== this.time) { + this.time = value; + this.onChange(); + } + }, + valid: errors.length === 0, + }; + return m('div', [ + m(TextField, { + label, + disabled: true, + style: { + width: '200px', + float: 'left', + }, + }), + m(TextField, date), + m(TextField, time), + ]); + } +} + export class selectGroup { view(vnode) { return m('div.form-group', { class: vnode.attrs.classes }, [