ui/forms/bagit_profile_form.js

const _ = require('lodash');
const { BagItProfile } = require('../../bagit/bagit_profile');
const { Choice } = require('./choice');
const { Constants } = require('../../core/constants');
const { Context } = require('../../core/context')
const { Field } = require('./field');
const { Form } = require('./form');

const infoFields = {
    'infoContactEmail': 'contactEmail',
    'infoContactName': 'contactName',
    'infoExternalDescription': 'externalDescription',
    'infoIdentifier': 'bagItProfileIdentifier',
    'infoSourceOrganization': 'sourceOrganization',
    'infoVersion': 'version'
};

/**
 * This is the form for editing BagItProfiles.
 *
 * @param {BagItProfile} bagItProfile
 */
class BagItProfileForm extends Form {

    constructor(bagItProfile) {
        let exclude = [
            "bagItProfileInfo",
            "baseProfileId",
            "errors",
            "help",
            "isBuiltIn",
            "required",
            "tags",
            "type",
            "userCanDelete",
        ];
        super('BagItProfile', bagItProfile, exclude);
        this._init();
    }

    /**
     * This calls internal methods to customize the form.
     *
     * @private
     */
    _init() {
        if (!this.obj.userCanDelete) {
            this.fields['name'].attrs['disabled'] = true;
        }
        this._setBasicFields();
        this._setProfileInfoFields();
    }

    /**
     * This sets up the editable fields that are part of the
     * {@link BagItProfile} but not part of the {@link BagItProfileInfo}
     * or tags properties.
     *
     * @private
     */
    _setBasicFields() {
        // Accept-BagIt-Version
        this.fields['acceptBagItVersion'].attrs['multiple'] = true;
        this.fields['acceptBagItVersion'].attrs['required'] = true;
        this.fields['acceptBagItVersion'].choices = Choice.makeList(
            Constants.BAGIT_VERSIONS,
            this.obj.acceptBagItVersion,
            false);

        // Accept-Serialization
        this.fields['acceptSerialization'].attrs['multiple'] = true;
        this.fields['acceptSerialization'].choices = Choice.makeList(
            Object.keys(Constants.SERIALIZATION_FORMATS),
            this.obj.acceptSerialization,
            false);

        // Serialization
        this.fields['serialization'].choices = Choice.makeList(
            Constants.REQUIREMENT_OPTIONS,
            this.obj.serialization,
            false);

        // Tar dir must match name
        this.fields['tarDirMustMatchName'].choices = Choice.makeList(
            Constants.YES_NO,
            this.obj.tarDirMustMatchName,
            false);

        // Allow-Fetch.txt
        this.fields['allowFetchTxt'].choices = Choice.makeList(
            Constants.YES_NO,
            this.obj.allowFetchTxt,
            false);

        // Manifests required
        this.fields['manifestsRequired'].attrs['multiple'] = true;
        this.fields['manifestsRequired'].choices = Choice.makeList(
            Constants.DIGEST_ALGORITHMS,
            this.obj.manifestsRequired,
            false);

        // Manifests allowed
        this.fields['manifestsAllowed'].attrs['multiple'] = true;
        this.fields['manifestsAllowed'].attrs['required'] = true;
        this.fields['manifestsAllowed'].choices = Choice.makeList(
            Constants.DIGEST_ALGORITHMS,
            this.obj.manifestsAllowed,
            false);

        // Tag manifests required
        this.fields['tagManifestsRequired'].attrs['multiple'] = true;
        this.fields['tagManifestsRequired'].choices = Choice.makeList(
            Constants.DIGEST_ALGORITHMS,
            this.obj.tagManifestsRequired,
            false);

        // Tag manifests allowed
        this.fields['tagManifestsAllowed'].attrs['multiple'] = true;
        this.fields['tagManifestsAllowed'].choices = Choice.makeList(
            Constants.DIGEST_ALGORITHMS,
            this.obj.tagManifestsAllowed,
            false);

        // Tag files allowed
        if (Array.isArray(this.obj.tagFilesAllowed) && this.obj.tagFilesAllowed.length > 0) {
            this.fields['tagFilesAllowed'].value = this.obj.tagFilesAllowed.join("\n").trim();
            window.field = this.fields['tagFilesAllowed'];
        }
    }

    /**
     * This sets up the form fields for the {@link BagItProfileInfo}
     * sub-object.
     *
     */
    _setProfileInfoFields() {
        // BagItProfileInfo
        for (let [fieldName, propName] of Object.entries(infoFields)) {
            this._initField(fieldName, this.obj.bagItProfileInfo[propName]);
        }
    }

    /**
     * This updates all of the values of Form.obj based on what the
     * user entered in the HTML form. After calling the super method
     * in the Form class, this hacks some values from the form into
     * the BagItProfileInfo subobjects, and cleans up some extraneous
     * properties on the BagItProfile object.
     */
    parseFromDOM() {
        if ($ === undefined) {
            var $ = require('jquery');
        }
        super.parseFromDOM();
        for (let [fakeName, actualName] of Object.entries(infoFields)) {
            this.obj.bagItProfileInfo[actualName] = this.obj[fakeName];
            delete(this.obj[fakeName]);
        }
        let fieldId = '#' + this.fields['tagFilesAllowed'].id
        let tagFilesAllowed = $(fieldId).val();
        if (tagFilesAllowed) {
            let values = tagFilesAllowed.split("\n");
            this.obj.tagFilesAllowed = values.map(val => val.trim());
        }
    }

    /**
     * Converts the form field name for a {@link BagItProfileInfo} property
     * back to the name of the actual property. For example, input
     * 'infoContactEmail' returns 'contactEmail'.
     *
     * @param {string} The name of a field on the BagItProfile form.
     *
     * @returns {string} The name of the property on the BagItProfileInfo
     * object, or undefined if the field name does not map to any property.
     *
     * @private
     */
    toObjectPropertyName(name) {
        return infoFields[name];
    }

    /**
     * Converts the name of a {@link BagItProfileInfo} property
     * to the name of a form field. For example, input
     * 'contactEmail' returns 'infoContactEmail'.
     *
     * @param {string} The name of a BagItProfileInfo property.
     *
     * @returns {string} The name of the field on the BagItProfile
     * form, or undefined if the field name does not map to any form
     * field.
     *
     * @private
     */
    toFormFieldName(name) {
        let invertedMap = _.invert(infoFields);
        return invertedMap[name];
    }
}

module.exports.BagItProfileForm = BagItProfileForm;