Skip to content
Snippets Groups Projects
editView.js 3.77 KiB
Newer Older
import m from 'mithril';
import { IconButton, Toolbar, ToolbarTitle, Button } from 'polythene-mithril';
import { Form } from 'amiv-web-ui-components';
import ItemView from './itemView';
import { icons } from './elements';
import { colors } from '../style';
export default class EditView extends ItemView {
Hermann's avatar
Hermann committed
  /**
   * Extension of ItemView to edit a data item
Hermann's avatar
Hermann committed
   *
   * Requires:
   * - call constructor with vnode, resource, (valid, false by default)
Hermann's avatar
Hermann committed
   * - vnode.attrs.onfinish has to be a callback function that is called after
   *   the edit is finished
Hermann's avatar
Hermann committed
   * @param  {object} vnode   [as provided by mithril]
   * @param  {string} resource  [the API resource of this view, e.g. 'events']
   * @param  {object} embedded  [any embedding query that should be added
   *                             to API requests for this resource]
Hermann's avatar
Hermann committed
   */
Hermann's avatar
Hermann committed
  constructor(vnode) {
    // the form is valid in case that the item controller is in edit mode
    const validInitially = this.controller.modus === 'edit';
    // start a form to collect the submit data
    this.form = new Form({}, validInitially, 4, Object.assign({}, this.controller.data));
    this.form.setSchema(JSON.parse(JSON.stringify(this.handler.schema)));
Hermann's avatar
Hermann committed
  /**
   * Submit the changed version of this.data
   *
   * @param  {Boolean} true if the data should be send as FormData instead of
   *                   JSON. Necessary in cases where files are included in the
   *                   changes.
   */
  submit(data) {
Ian Boschung's avatar
Ian Boschung committed
    return new Promise((resolve, reject) => {
      let request;
      if (this.controller.modus === 'edit') {
        // this is a patch to an existing item
        request = this.controller.patch(data);
      } else {
Ian Boschung's avatar
Ian Boschung committed
        request = this.controller.post(data);
Ian Boschung's avatar
Ian Boschung committed
      request.then((response) => {
        resolve(response);
      }).catch((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;
          });
          // eslint-disable-next-line no-console
Ian Boschung's avatar
Ian Boschung committed
          console.log(this.form.errors);
          m.redraw();
          reject(error);
        } else {
          // eslint-disable-next-line no-console
Ian Boschung's avatar
Ian Boschung committed
          console.log(error);
        }
      });
    if (Object.keys(this.form.data).length > 0) {
      this.submit(this.form.data).then(() => this.controller.changeModus('view'));
    } else {
      this.controller.changeModus('view');
    }
Hermann's avatar
Hermann committed
  layout(children, buttonLabel = 'submit', wrapInContainer = true) {
    return m('div', { style: { 'background-color': 'white' } }, [
      m(Toolbar, { style: { 'background-color': colors.orange } }, [
        m(IconButton, {
          icon: { svg: { content: m.trust(icons.clear) } },
          events: { onclick: () => { this.controller.cancel(); } },
        }),
boian's avatar
boian committed
        m(ToolbarTitle, `${((this.controller.modus === 'new') ? 'New' : 'Edit')}`
          + ` ${this.resource.charAt(0).toUpperCase()}${this.resource.slice(1, -1)}`),
Hermann's avatar
Hermann committed
        m(Button, {
          className: 'blue-button-filled',
          extraWide: true,
          label: buttonLabel,
          // NOTE: Temporary fix as the `valid` flag of the `Form` instance does
          //       not work reliably. This ensures that the form can be submitted.
          // disabled: !this.form.valid,
Hermann's avatar
Hermann committed
          events: { onclick: () => { this.beforeSubmit(); } },
        }),
      ...!this.form.schema ? [''] : [
        wrapInContainer && m('div.maincontainer', {
          style: { height: 'calc(100vh - 130px)', 'overflow-y': 'scroll', padding: '10px' },
        }, children),
        !wrapInContainer && children,
      ],