Skip to content
Snippets Groups Projects
Commit b0487a0f authored by Sandro Lutz's avatar Sandro Lutz
Browse files

Merge remote-tracking branch 'origin/master' into studydocs-autocomplete

parent 1454ec67
No related branches found
No related tags found
1 merge request!30Studydocs autocomplete
import m from 'mithril'; import m from 'mithril';
import { apiUrl } from './config'; import { apiUrl } from './config';
import { getToken, getUserId, isLoggedIn } from './auth'; import { getToken, getUserId, isLoggedIn } from './auth';
import { log } from './log';
const lang = 'de'; const lang = 'de';
const date = `${new Date().toISOString().split('.')[0]}Z`; const date = `${new Date().toISOString().split('.')[0]}Z`;
...@@ -15,23 +14,23 @@ export function getList() { ...@@ -15,23 +14,23 @@ export function getList() {
return this.list; return this.list;
} }
export function getCurrent() { export function getSelectedEvent() {
return this.current; return this.selectedEvent;
} }
export function getCurrentSignup() { export function getSignupForSelectedEvent() {
return this.currentSignup; return this.selectedEventSignup;
} }
export function currentSignupHasLoaded() { export function signupForSelectedEventHasLoaded() {
return this.currentSignupLoaded; return this.selectedEventSignupLoaded;
} }
export function checkCurrentSignup() { export function loadSignupForSelectedEvent() {
const queryString = m.buildQueryString({ const queryString = m.buildQueryString({
where: JSON.stringify({ where: JSON.stringify({
user: getUserId(), user: getUserId(),
event: this.getCurrent()._id, event: this.getSelectedEvent()._id,
}), }),
}); });
...@@ -42,14 +41,58 @@ export function checkCurrentSignup() { ...@@ -42,14 +41,58 @@ export function checkCurrentSignup() {
Authorization: `Token ${getToken()}`, Authorization: `Token ${getToken()}`,
} : {}, } : {},
}).then((result) => { }).then((result) => {
[this.currentSignup] = result._items; [this.selectedEventSignup] = result._items;
this.currentSignupLoaded = true; this.selectedEventSignupLoaded = true;
}); });
} }
export function signupCurrent(additionalFields, email = '') { export function _signupUserForSelectedEvent(additionalFieldsString) {
if (typeof this.selectedEventSignup !== 'undefined') {
return m.request({
method: 'PATCH',
url: `${apiUrl}/eventsignups/${this.selectedEventSignup._id}`,
data: {
additional_fields: additionalFieldsString,
},
headers: getToken() ? {
Authorization: `Token ${getToken()}`,
'If-Match': this.selectedEventSignup._etag,
} : { 'If-Match': this.selectedEventSignup._etag },
}).then(() => { this.loadSignupForSelectedEvent(); });
}
return m.request({
method: 'POST',
url: `${apiUrl}/eventsignups`,
data: {
event: this.selectedEvent._id,
additional_fields: additionalFieldsString,
user: getUserId(),
},
headers: getToken() ? {
Authorization: `Token ${getToken()}`,
} : {},
}).then(() => { this.loadSignupForSelectedEvent(); });
}
export function _signupEmailForSelectedEvent(additionalFieldsString, email) {
return m.request({
method: 'POST',
url: `${apiUrl}/eventsignups`,
data: {
event: this.selectedEvent._id,
additional_fields: additionalFieldsString,
email,
},
headers: getToken() ? {
Authorization: `Token ${getToken()}`,
} : {},
}).then(() => { this.loadSignupForSelectedEvent(); });
}
export function signupForSelectedEvent(additionalFields, email = '') {
let additionalFieldsString; let additionalFieldsString;
if (this.current.additional_fields === undefined || if (this.selectedEvent.additional_fields === undefined ||
additionalFields === null || typeof additionalFields !== 'object') { additionalFields === null || typeof additionalFields !== 'object') {
additionalFieldsString = undefined; additionalFieldsString = undefined;
} else { } else {
...@@ -57,33 +100,23 @@ export function signupCurrent(additionalFields, email = '') { ...@@ -57,33 +100,23 @@ export function signupCurrent(additionalFields, email = '') {
} }
if (isLoggedIn()) { if (isLoggedIn()) {
log(`UserId: ${getUserId()}`); return this._signupUserForSelectedEvent(additionalFieldsString);
m.request({ } else if (this.selectedEvent.allow_email_signup) {
method: 'POST', return this._signupEmailForSelectedEvent(additionalFieldsString, email);
url: `${apiUrl}/eventsignups`, }
data: { return Promise.reject(new Error('Signup not allowed'));
event: this.current._id, }
additional_fields: additionalFieldsString,
user: getUserId(), export function signoffForSelectedEvent() {
}, if (isLoggedIn() && typeof this.selectedEventSignup !== 'undefined') {
headers: getToken() ? {
Authorization: `Token ${getToken()}`,
} : {},
}).then(() => { this.checkCurrentSignup(); });
} else if (this.current.allow_email_signup) {
log(`Email: ${email}`);
m.request({ m.request({
method: 'POST', method: 'DELETE',
url: `${apiUrl}/eventsignups`, url: `${apiUrl}/eventsignups/${this.selectedEventSignup._id}`,
data: {
event: this.current._id,
additional_fields: additionalFieldsString,
email,
},
headers: getToken() ? { headers: getToken() ? {
Authorization: `Token ${getToken()}`, Authorization: `Token ${getToken()}`,
} : {}, 'If-Match': this.selectedEventSignup._etag,
}).then(() => { this.checkCurrentSignup(); }); } : { 'If-Match': this.selectedEventSignup._etag },
}).then(() => { this.loadSignupForSelectedEvent(); });
} }
} }
...@@ -113,9 +146,9 @@ export function load(query = {}) { ...@@ -113,9 +146,9 @@ export function load(query = {}) {
}); });
} }
export function loadCurrent(eventId) { export function selectEvent(eventId) {
this.current = this.getList().find(item => item._id === eventId); this.selectedEvent = this.getList().find(item => item._id === eventId);
if (typeof this.current === 'undefined') { if (typeof this.selectedEvent === 'undefined') {
this.load({ this.load({
where: { where: {
time_advertising_start: { $lte: date }, time_advertising_start: { $lte: date },
...@@ -124,7 +157,7 @@ export function loadCurrent(eventId) { ...@@ -124,7 +157,7 @@ export function loadCurrent(eventId) {
}, },
sort: ['-priority', 'time_advertising_start'], sort: ['-priority', 'time_advertising_start'],
}).then(() => { }).then(() => {
this.current = this.getList().find(item => item._id === eventId); this.selectedEvent = this.getList().find(item => item._id === eventId);
}); });
} }
} }
......
...@@ -10,112 +10,145 @@ import JSONSchemaForm from './form/jsonSchemaForm'; ...@@ -10,112 +10,145 @@ import JSONSchemaForm from './form/jsonSchemaForm';
class EventSignupForm extends JSONSchemaForm { class EventSignupForm extends JSONSchemaForm {
oninit(vnode) { oninit(vnode) {
super.oninit(vnode); super.oninit(vnode);
this.email = '';
this.emailErrors = []; this.emailErrors = [];
this.emailValid = false; this.emailValid = false;
if (isLoggedIn()) { if (isLoggedIn()) {
events.checkCurrentSignup(); events.loadSignupForSelectedEvent()
.then(() => {
if (typeof events.getSignupForSelectedEvent() !== 'undefined') {
this.data = JSON.parse(events.getSignupForSelectedEvent().additional_fields) || {};
}
});
} }
} }
submit() { signup() {
if (isLoggedIn()) { events.signupForSelectedEvent(super.getValue(), this.email)
events.signupCurrent(super.getValue()); .then(() => log('Successfully signed up for the event!'))
} else { .catch(() => log('Could not sign up of the event!'));
events.signupCurrent(super.getValue(), this.email); }
}
signoff() {
events.signoffForSelectedEvent();
this.validate();
} }
view() { view() {
// do not render anything if there is no data yet // do not render anything if there is no data yet
if (typeof events.getCurrent() === 'undefined') return m(); if (typeof events.getSelectedEvent() === 'undefined') return m('');
if (isLoggedIn()) { if (isLoggedIn()) {
// do not render form if there is no signup data of the current user // do not render form if there is no signup data of the current user
if (!events.currentSignupHasLoaded()) return m('span', 'Loading...'); if (!events.signupForSelectedEventHasLoaded()) return m('span', 'Loading...');
if (typeof events.getCurrentSignup() === 'undefined') {
const elements = this.renderFormElements(); const elements = this.renderFormElements();
elements.push(m(button, { elements.push(this._renderSignupButton());
active: super.isValid(), if (typeof events.getSignupForSelectedEvent() !== 'undefined') {
args: { elements.unshift(m('div', 'You have already signed up. Update your data below.'));
onclick: () => this.submit(), elements.push(this._renderSignoffButton());
},
text: 'Signup',
}));
return m('form', elements);
} }
return m('div', 'You have already signed up for this event.'); return m('form', elements);
} else if (events.getCurrent().allow_email_signup) { } else if (events.getSelectedEvent().allow_email_signup) {
const elements = this.renderFormElements(); const elements = this.renderFormElements();
elements.push(m(inputGroup, { elements.push(this._renderEmailField());
name: 'email', elements.push(this._renderSignupButton());
title: 'Email',
args: {
type: 'text',
},
oninput: (e) => {
// bind changed data
this.email = e.target.value;
// validate if email address has the right structure
if (EmailValidator.validate(this.email)) {
this.emailValid = true;
this.emailErrors = [];
} else {
this.emailValid = false;
this.emailErrors = ['Not a valid email address'];
}
},
getErrors: () => this.emailErrors,
value: this.email,
}));
elements.push(m(button, {
active: this.emailValid && super.isValid(),
args: {
onclick: () => this.submit(),
},
text: 'Signup',
}));
return m('form', elements); return m('form', elements);
} }
return m('div', 'This event is for AMIV members only.'); return m('div', 'This event is for AMIV members only.');
} }
isValid() {
if (!isLoggedIn()) {
return super.isValid() && this.emailValid;
}
return super.isValid();
}
_renderEmailField() {
return m(inputGroup, {
name: 'email',
title: 'Email',
args: {
type: 'text',
},
oninput: (e) => {
// bind changed data
this.email = e.target.value;
// validate if email address has the right structure
if (EmailValidator.validate(this.email)) {
this.emailValid = true;
this.emailErrors = [];
} else {
this.emailValid = false;
this.emailErrors = ['Not a valid email address'];
}
},
getErrors: () => this.emailErrors,
value: this.email,
});
}
_renderSignupButton() {
return m(button, {
name: 'signup',
title: 'Signup',
active: super.isValid(),
args: {
onclick: () => this.signup(),
},
});
}
_renderSignoffButton() {
return m(button, {
name: 'signoff',
title: 'Delete signup',
active: true,
args: {
onclick: () => this.signoff(),
},
});
}
} }
export default class EventDetails { export default class EventDetails {
static oninit(vnode) { static oninit(vnode) {
events.loadCurrent(vnode.attrs.eventId); events.selectEvent(vnode.attrs.eventId);
} }
static view() { static view() {
if (typeof events.getCurrent() === 'undefined') { if (typeof events.getSelectedEvent() === 'undefined') {
return m(); return m('');
} }
log(events.getCurrent());
let eventSignupForm; let eventSignupForm;
const now = new Date(); const now = new Date();
const registerStart = new Date(events.getCurrent().time_register_start); const registerStart = new Date(events.getSelectedEvent().time_register_start);
const registerEnd = new Date(events.getCurrent().time_register_end); const registerEnd = new Date(events.getSelectedEvent().time_register_end);
log(`Now: ${now}`);
log(`Start: ${registerStart}`);
log(`End: ${registerEnd}`);
if (registerStart <= now) { if (registerStart <= now) {
if (registerEnd >= now) { if (registerEnd >= now) {
eventSignupForm = m(EventSignupForm, { eventSignupForm = m(EventSignupForm, {
schema: events.getCurrent().additional_fields === undefined ? schema: events.getSelectedEvent().additional_fields === undefined ?
undefined : JSON.parse(events.getCurrent().additional_fields), undefined : JSON.parse(events.getSelectedEvent().additional_fields),
}); });
} else { } else {
eventSignupForm = m('div', 'The registration period is over.'); let participantNotice = '';
if (events.getSignupForSelectedEvent() !== 'undefined') {
participantNotice = m('You signed up for this event.');
}
eventSignupForm = m('div', ['The registration period is over.', participantNotice]);
} }
} else { } else {
eventSignupForm = m('div', `The registration starts at ${registerStart}`); eventSignupForm = m('div', `The registration starts at ${registerStart}`);
} }
return m('div', [ return m('div', [
m('h1', events.getCurrent().title_de), m('h1', events.getSelectedEvent().title_de),
m('span', events.getCurrent().time_start), m('span', events.getSelectedEvent().time_start),
m('span', events.getCurrent().signup_count), m('span', events.getSelectedEvent().signup_count),
m('span', events.getCurrent().spots), m('span', events.getSelectedEvent().spots),
m('p', events.getCurrent().description_de), m('p', events.getSelectedEvent().description_de),
eventSignupForm, eventSignupForm,
]); ]);
} }
......
...@@ -77,6 +77,12 @@ export default class JSONSchemaForm { ...@@ -77,6 +77,12 @@ export default class JSONSchemaForm {
return this.schema === undefined || this.valid; return this.schema === undefined || this.valid;
} }
validate() {
// validate the new data against the schema
const validate = this.ajv.getSchema('schema');
this.valid = validate(this.data);
}
getValue() { getValue() {
return this.data; return this.data;
} }
...@@ -104,9 +110,9 @@ export default class JSONSchemaForm { ...@@ -104,9 +110,9 @@ export default class JSONSchemaForm {
return m(selectGroup, this.bind({ return m(selectGroup, this.bind({
name: key, name: key,
title: item.description, title: item.description,
type: item.items.enum.length > 8 ? 'select' : 'buttons',
options: item.items.enum,
args: { args: {
options: item.items.enum,
type: item.items.enum.length > 8 ? 'select' : 'buttons',
multipleSelect: true, multipleSelect: true,
}, },
})); }));
...@@ -123,9 +129,9 @@ export default class JSONSchemaForm { ...@@ -123,9 +129,9 @@ export default class JSONSchemaForm {
return m(selectGroup, this.bind({ return m(selectGroup, this.bind({
name: key, name: key,
title: item.description, title: item.description,
options: item.enum,
type: 'select',
args: { args: {
options: item.enum,
type: 'select',
multipleSelect: false, multipleSelect: false,
}, },
})); }));
......
...@@ -16,12 +16,19 @@ export default class SelectGroup { ...@@ -16,12 +16,19 @@ export default class SelectGroup {
args.onchange = vnode.attrs.onchange; args.onchange = vnode.attrs.onchange;
args.oninput = vnode.attrs.oninput; args.oninput = vnode.attrs.oninput;
const options = vnode.attrs.options.map((option) => {
if (typeof option === 'object') {
return option;
}
return { value: option, text: option };
});
switch (vnode.attrs.type) { switch (vnode.attrs.type) {
case 'buttons': { case 'buttons': {
if (args.multipleSelect) { if (args.multipleSelect) {
return m('div', { class: vnode.attrs.classes }, [ return m('div', { class: vnode.attrs.classes }, [
m(`label[for=${vnode.attrs.name}]`, vnode.attrs.title), m(`label[for=${vnode.attrs.name}]`, vnode.attrs.title),
m('div', vnode.attrs.options.map(option => m('div', options.map(option =>
m(inputGroup, { m(inputGroup, {
name: vnode.attrs.name, name: vnode.attrs.name,
title: option.text, title: option.text,
...@@ -47,10 +54,11 @@ export default class SelectGroup { ...@@ -47,10 +54,11 @@ export default class SelectGroup {
]); ]);
} }
return m('div', { class: vnode.attrs.classes }, [ return m('div', { class: vnode.attrs.classes }, [
m('div', vnode.attrs.options.map(option => m('div', options.map(option =>
m(inputGroup, { m(inputGroup, {
name: vnode.attrs.name, name: vnode.attrs.name,
title: option, title: option.text,
value: option.value,
onchange: vnode.attrs.onchange, onchange: vnode.attrs.onchange,
args: { type: 'radio' }, args: { type: 'radio' },
}))), }))),
...@@ -89,7 +97,7 @@ export default class SelectGroup { ...@@ -89,7 +97,7 @@ export default class SelectGroup {
vnode.attrs.oninput({ target: { name: e.target.name, value } }); vnode.attrs.oninput({ target: { name: e.target.name, value } });
}, },
}, },
vnode.attrs.options.map(option => m('option', { value: option.value }, option.text)), options.map(option => m('option', { value: option.value }, option.text)),
), ),
]); ]);
} }
...@@ -98,7 +106,7 @@ export default class SelectGroup { ...@@ -98,7 +106,7 @@ export default class SelectGroup {
m( m(
`select[name=${vnode.attrs.name}][id=${vnode.attrs.name}]`, `select[name=${vnode.attrs.name}][id=${vnode.attrs.name}]`,
args, args,
vnode.attrs.options.map(option => m('option', { value: option.value }, option.text)), options.map(option => m('option', { value: option.value }, option.text)),
), ),
]); ]);
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment