Commit b909a436 authored by scmoritz's avatar scmoritz Committed by Sandro Lutz
Browse files

Use the form in web-ui-components in eventsignups

parent 27f16721
......@@ -22,7 +22,6 @@
"author": "AMIV IT team",
"license": "ISC",
"dependencies": {
"ajv": "^5.5.0",
"amiv-web-ui-components": "git+https://git@gitlab.ethz.ch/amiv/web-ui-components.git#1a1f5064d46c5de4b43fcbd1cd4c8245041b8c8a",
"babel-polyfill": "^6.26.0",
"email-validator": "^2.0.4",
......
import m from 'mithril';
import Ajv from 'ajv';
import jsonSchemaDraft04 from 'ajv/lib/refs/json-schema-draft-04.json';
import { log } from '../../models/log';
import inputGroup from './inputGroup';
import selectGroup from './selectGroup';
export default class JSONSchemaForm {
constructor() {
this.data = {};
this.errors = {};
this.ajv = new Ajv({
missingRefs: 'ignore',
errorDataPath: 'property',
allErrors: false,
});
this.ajv.addMetaSchema(jsonSchemaDraft04);
}
oninit(vnode) {
this.schema = vnode.attrs.schema;
this.fieldOrder = vnode.attrs.fieldOrder;
if (this.schema === null || typeof this.schema !== 'object') {
this.schema = undefined;
} else {
this.ajv.addSchema(this.schema, 'schema');
}
if (!this.fieldOrder) {
this.fieldOrder = [];
}
}
// bind form-fields to the object data and validation
bind(attrs) {
// initialize error-list for every bound field
if (!this.errors[attrs.name]) this.errors[attrs.name] = [];
const boundFormelement = {
oninput: e => {
// bind changed data
this.data[e.target.name] = e.target.value;
// validate against schema
const validate = this.ajv.getSchema('schema');
this.valid = validate(this.data);
if (this.valid) {
Object.keys(this.errors).forEach(field => {
this.errors[field] = [];
});
} else {
// get errors for respective fields
Object.keys(this.errors).forEach(field => {
const errors = validate.errors.filter(error => `.${field}` === error.dataPath);
this.errors[field] = errors.map(error => error.message);
});
}
},
getErrors: () => this.errors[attrs.name],
value: this.data[attrs.name],
};
// add the given attributes
Object.keys(attrs).forEach(key => {
boundFormelement[key] = attrs[key];
});
return boundFormelement;
}
view() {
const elements = this.renderFormElements();
return m('form', elements);
}
isValid() {
return this.schema === undefined || this.valid;
}
validate() {
// do nothing if schema is undefined
if (!this.schema) return;
// validate the new data against the schema
const validate = this.ajv.getSchema('schema');
this.valid = validate(this.data);
}
getValue() {
return this.data;
}
// render all schema properties to an array of form-fields
renderFormElements() {
const elements = [];
if (this.schema !== undefined) {
let keys = Object.keys(this.schema.properties);
this.fieldOrder.forEach(key => {
if (key in keys) {
elements.push(this._renderProperty(key, this.schema.properties[key]));
keys = keys.filter(e => e !== key);
}
});
keys.forEach(key => {
elements.push(this._renderProperty(key, this.schema.properties[key]));
});
}
return elements;
}
_renderArrayProperty(key, item) {
if ('enum' in item) {
return m(
selectGroup,
this.bind({
name: key,
title: item.description,
type: item.items.enum.length > 8 ? 'select' : 'buttons',
options: item.items.enum,
args: {
multipleSelect: true,
},
})
);
}
log('Unknown array property type');
return m('');
}
// render schema property to form-fields
_renderProperty(key, item) {
if (item.readOnly) return m('');
if ('enum' in item) {
return m(
selectGroup,
this.bind({
name: key,
title: item.description,
options: item.enum,
type: 'select',
args: {
multipleSelect: false,
},
})
);
}
switch (item.type) {
case 'integer': {
return m(
inputGroup,
this.bind({ name: key, title: item.description, args: { type: 'number', step: 1 } })
);
}
case 'number': {
return m(
inputGroup,
this.bind({ name: key, title: item.description, args: { type: 'number' } })
);
}
case 'boolean': {
return m(
inputGroup,
this.bind({ name: key, title: item.description, args: { type: 'checkbox' } })
);
}
case 'array': {
return this._renderArrayProperty(key, item);
}
case 'string':
default: {
return m(
inputGroup,
this.bind({ name: key, title: item.description, args: { type: 'text' } })
);
}
}
}
}
......@@ -6,6 +6,5 @@ export { default as Dropdown } from './Dropdown';
export { default as TextField } from './TextField';
export { default as FilterView } from './FilterView';
export { default as InputGroupForm } from './form/inputGroup';
export { default as JSONSchemaForm } from './form/jsonSchemaForm';
export { default as SelectGroupForm } from './form/selectGroup';
export { default as FileInput } from './FileInput';
import m from 'mithril';
import marked from 'marked';
import escape from 'html-escape';
import * as EmailValidator from 'email-validator';
import { TextField } from 'polythene-mithril';
import { Form } from 'amiv-web-ui-components';
import { log } from '../../models/log';
import { isLoggedIn, login } from '../../models/auth';
import { Button, InputGroupForm, JSONSchemaForm } from '../../components';
import { Button } from '../../components';
import { i18n } from '../../models/language';
class EventSignupForm extends JSONSchemaForm {
class EventSignupForm {
oninit(vnode) {
this.event = vnode.attrs.event;
super.oninit(
Object.assign({}, vnode, {
attrs: {
schema:
this.event.additional_fields === undefined
? undefined
: JSON.parse(this.event.additional_fields),
},
})
);
this.schema =
this.event.additional_fields === undefined
? undefined
: JSON.parse(this.event.additional_fields);
this.form = new Form();
if (this.schema && this.schema.$schema) {
// ajv fails to verify the v4 schema of some resources
this.schema.$schema = 'http://json-schema.org/draft-06/schema#';
this.form.setSchema(this.schema);
}
this.email = '';
this.emailErrors = [];
this.emailValid = false;
this.emailSignup = null;
if (isLoggedIn()) {
this.event.loadSignup().then(() => {
if (this.event.signupData) {
this.data = JSON.parse(this.event.signupData.additional_fields || '{}');
this.form.data = JSON.parse(this.event.signupData.additional_fields || '{}');
}
});
}
......@@ -49,7 +48,7 @@ class EventSignupForm extends JSONSchemaForm {
} catch (err) {
log(err);
}
this.validate();
this.form.validate();
}
view() {
......@@ -57,7 +56,7 @@ class EventSignupForm extends JSONSchemaForm {
// do not render form if there is no signup data of the current user
if (!this.event.hasSignupDataLoaded) return m('span', i18n('loading'));
const elements = this.renderFormElements();
const elements = this.schema ? this.form.renderSchema() : [];
if (!this.event.signupData || (this.event.signupData && this.event.additional_fields)) {
elements.push(this._renderSignupButton());
}
......@@ -75,7 +74,7 @@ class EventSignupForm extends JSONSchemaForm {
return m('form', { onsubmit: () => false }, elements);
} else if (this.event.allow_email_signup) {
if (!this.emailSignup) {
const elements = this.renderFormElements();
const elements = this.schema ? this.form.renderSchema() : [];
elements.push(this._renderEmailField());
elements.push(this._renderSignupButton());
return m('form', { onsubmit: () => false }, elements);
......@@ -90,49 +89,31 @@ class EventSignupForm extends JSONSchemaForm {
]);
}
isValid() {
if (!isLoggedIn()) {
return super.isValid() && this.emailValid;
}
return super.isValid();
}
_renderEmailField() {
return m(InputGroupForm, {
name: 'email',
title: i18n('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 = [i18n('email_invalid')];
}
},
getErrors: () => this.emailErrors,
value: this.email,
});
}
_renderSignupButton() {
return m(Button, {
name: 'signup',
label: i18n('events.signup'),
active: super.isValid(),
active: this.form.valid,
events: {
onclick: () => this.signup(),
},
});
}
_renderEmailField() {
return m(TextField, {
name: 'email',
label: i18n('email'),
validateOnInput: true,
floatingLabel: true,
type: 'email',
onChange: (name, value) => {
this.email = value;
},
value: this.email,
});
}
_renderSignoffButton() {
return m(Button, {
name: 'signoff',
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment