Verified Commit 0012d193 authored by Hermann's avatar Hermann Committed by Sandro Lutz
Browse files

breaking changes in FormData submit

so far, FormData submit did not support multiple values per key. We need this for studydocuments.
Therefore, submit now simple takes a FormData or Object as input and patches it to the resource.
parent 8cb718eb
...@@ -289,26 +289,24 @@ export class ResourceHandler { ...@@ -289,26 +289,24 @@ export class ResourceHandler {
}); });
} }
patch(item, formData = false) { patch(item) {
const isFormData = item instanceof FormData;
let patchInfo = {};
if (isFormData) patchInfo = { id: item.get('_id'), etag: item.get('_etag') };
else patchInfo = { id: item._id, etag: item._etag };
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
getSession().then((api) => { getSession().then((api) => {
let submitData = item;
if (!isFormData) submitData = Object.assign({}, item);
// not all fields in the item can be patched. We filter out the fields // not all fields in the item can be patched. We filter out the fields
// we are allowed to send // we are allowed to send
let submitData; this.noPatchKeys.forEach((key) => {
if (formData) { if (isFormData) submitData.delete(key);
submitData = new FormData(); else delete submitData[key];
Object.keys(item).forEach((key) => { });
if (!this.noPatchKeys.includes(key)) { api.patch(`${this.resource}/${patchInfo.id}`, submitData, {
submitData.append(key, item[key]); headers: { 'If-Match': patchInfo.etag },
}
});
} else {
submitData = Object.assign({}, item);
this.noPatchKeys.forEach((key) => { delete submitData[key]; });
}
api.patch(`${this.resource}/${item._id}`, submitData, {
headers: { 'If-Match': item._etag },
}).then((response) => { }).then((response) => {
if (response.status === 422) { if (response.status === 422) {
this.error422(response.data); this.error422(response.data);
......
...@@ -63,9 +63,7 @@ export default class newEvent extends EditView { ...@@ -63,9 +63,7 @@ export default class newEvent extends EditView {
images[`img_${key}`] = this.form.data[`new_${key}`]; images[`img_${key}`] = this.form.data[`new_${key}`];
delete this.form.data[`new_${key}`]; delete this.form.data[`new_${key}`];
} }
if (this.form.data[`img_${key}`]) { if (this.form.data[`img_${key}`]) delete this.form.data[`img_${key}`];
delete this.form.data[`img_${key}`];
}
}); });
// Merge Options for additional fields // Merge Options for additional fields
...@@ -106,7 +104,6 @@ export default class newEvent extends EditView { ...@@ -106,7 +104,6 @@ export default class newEvent extends EditView {
this.form.data.additional_fields = null; this.form.data.additional_fields = null;
} }
// if spots is not set, also remove 'allow_email_signup' // if spots is not set, also remove 'allow_email_signup'
if (!('spots' in this.form.data) && 'allow_email_signup' in this.form.data if (!('spots' in this.form.data) && 'allow_email_signup' in this.form.data
&& !this.form.data.allow_email_signup) { && !this.form.data.allow_email_signup) {
...@@ -117,16 +114,15 @@ export default class newEvent extends EditView { ...@@ -117,16 +114,15 @@ export default class newEvent extends EditView {
if (this.rightSubmit) { if (this.rightSubmit) {
// Submition tool // Submition tool
if (Object.keys(images).length > 0) { if (Object.keys(images).length > 0) {
images._id = this.form.data._id; const imageForm = new FormData();
images._etag = this.form.data._etag; Object.keys(images).forEach(key => imageForm.append(key, images[key]));
imageForm.append('_id', this.form.data._id);
imageForm.append('_etag', this.form.data._etag);
// first upload the images as formData, then the rest as JSON // first upload the images as formData, then the rest as JSON
this.controller.handler.patch(images, true).then(({ _etag }) => { this.controller.handler.patch(imageForm).then(({ _etag }) => {
this.form.data._etag = _etag; this.submit({ ...this.form.data, _etag });
this.submit();
}); });
} else { } else this.submit(this.form.data);
this.submit();
}
} else { } else {
// Propose tool // Propose tool
Dialog.show({ Dialog.show({
......
...@@ -84,10 +84,9 @@ export default class NewGroup extends EditView { ...@@ -84,10 +84,9 @@ export default class NewGroup extends EditView {
} }
beforeSubmit() { beforeSubmit() {
const data = this.form.data;
// exchange moderator object with string of id // exchange moderator object with string of id
const { moderator } = this.form.data; this.submit({ ...data, moderator: data.moderator ? data.moderator._id : undefined });
if (moderator) { this.form.data.moderator = `${moderator._id}`; }
this.submit();
} }
view() { view() {
......
...@@ -125,6 +125,7 @@ ...@@ -125,6 +125,7 @@
"professor", "professor",
"author", "author",
"uploader" "uploader"
] ],
"notPatchableKeys": ["uploader"]
} }
} }
import m from 'mithril'; import m from 'mithril';
import { FileInput } from 'amiv-web-ui-components'; import { FileInput } from 'amiv-web-ui-components';
import { RadioGroup, Button, List, ListTile } from 'polythene-mithril'; import { RadioGroup, Button, List, ListTile, Snackbar } from 'polythene-mithril';
// eslint-disable-next-line import/extensions
import { apiUrl } from 'networkConfig';
import EditView from '../views/editView'; import EditView from '../views/editView';
...@@ -13,6 +15,40 @@ export default class editDoc extends EditView { ...@@ -13,6 +15,40 @@ export default class editDoc extends EditView {
} }
} }
oninit() {
// load schema
m.request(`${apiUrl}/docs/api-docs`).then((schema) => {
// remove the files list as it is impossible to validate
const docSchema = schema.definitions.Studydocument;
delete docSchema.properties.files;
this.form.setSchema(docSchema);
}).catch((error) => { console.log(error); });
}
beforeSubmit() {
// check if there are files uploaded
const files = [];
Object.keys(this.form.data).forEach((key) => {
if (key.startsWith('new_file_') && this.form.data[key]) {
files.push(this.form.data[key]);
delete this.form.data[key];
}
});
// in case that there are no files, eject an error
if (this.controller.modus === 'new' && files.length === 0) {
Snackbar.show({ title: 'You need to upload at least one file.' });
this.form.valid = false;
return;
}
// now post all together as FormData
const submitData = new FormData();
Object.keys(this.form.data).forEach((key) => {
if (key !== 'files') submitData.append(key, this.form.data[key]);
});
files.forEach((file) => { submitData.append('files', file); });
this.submit(submitData);
}
view() { view() {
return this.layout([ return this.layout([
m('h3', 'Add a New Studydocument'), m('h3', 'Add a New Studydocument'),
...@@ -62,17 +98,16 @@ export default class editDoc extends EditView { ...@@ -62,17 +98,16 @@ export default class editDoc extends EditView {
// file upload: unfinished // file upload: unfinished
m('div', [ m('div', [
m(List, { m(List, {
tiles: this.form.data.files.map(file => m(ListTile, { tiles: [...this.form.data.files.entries()].map(numAndFile => m(ListTile, {
content: [ content: [
m(FileInput, this.form.bind({ m(FileInput, this.form.bind({
name: 'new_file', name: `new_file_${numAndFile[0]}`,
label: `${file.name}`, label: numAndFile[1].name,
})), })),
], ],
})), })),
}), }),
// additional file // additional file
m(Button, { m(Button, {
label: 'Additional File', label: 'Additional File',
......
...@@ -14,6 +14,7 @@ const objectNameForResource = { ...@@ -14,6 +14,7 @@ const objectNameForResource = {
groups: 'Group', groups: 'Group',
eventsignups: 'Eventsignup', eventsignups: 'Eventsignup',
events: 'Event', events: 'Event',
studydocuments: 'Studydocument',
}; };
export default class EditView extends ItemView { export default class EditView extends ItemView {
...@@ -51,37 +52,37 @@ export default class EditView extends ItemView { ...@@ -51,37 +52,37 @@ export default class EditView extends ItemView {
* JSON. Necessary in cases where files are included in the * JSON. Necessary in cases where files are included in the
* changes. * changes.
*/ */
submit(formData = false) { submit(data) {
if (Object.keys(this.form.data).length > 0) { let request;
let request; if (this.controller.modus === 'edit') {
if (this.controller.modus === 'edit') { // if id is known, this is a patch to an existing item
// if id is known, this is a patch to an existing item request = this.controller.patch(data);
request = this.controller.patch(this.form.data, formData);
} else {
request = this.controller.post(this.form.data);
}
request.catch((error) => {
console.log(error);
// Process the API error
if ('_issues' in error) {
// there are problems with some fields, display them
Object.keys(error._issues).forEach((field) => {
this.form.errors[field] = [error._issues[field]];
this.form.valid = false;
});
console.log(this.form.errors);
m.redraw();
} else {
console.log(error);
}
});
} else { } else {
this.controller.changeModus('view'); request = this.controller.post(data);
} }
request.catch((error) => {
console.log(error);
// Process the API error
if ('_issues' in error) {
// there are problems with some fields, display them
Object.keys(error._issues).forEach((field) => {
this.form.errors[field] = [error._issues[field]];
this.form.valid = false;
});
console.log(this.form.errors);
m.redraw();
} else {
console.log(error);
}
});
} }
beforeSubmit() { beforeSubmit() {
this.submit(); if (Object.keys(this.form.data).length > 0) {
this.submit(this.form.data);
} else {
this.controller.changeModus('view');
}
} }
layout(children, buttonLabel = 'submit', wrapInContainer = true) { layout(children, buttonLabel = 'submit', wrapInContainer = true) {
......
Markdown is supported
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