diff --git a/src/js/views/metadata/EML211EditorView.js b/src/js/views/metadata/EML211EditorView.js index 30e4e66e7..99b855bdf 100644 --- a/src/js/views/metadata/EML211EditorView.js +++ b/src/js/views/metadata/EML211EditorView.js @@ -12,11 +12,10 @@ define([ "views/DataPackageView", "views/metadata/EML211View", "views/metadata/EMLEntityView", - "views/SignInView", "text!templates/editor.html", "collections/ObjectFormats", "text!templates/editorSubmitMessage.html", -], function ( +], ( _, $, Backbone, @@ -30,20 +29,19 @@ define([ DataPackageView, EMLView, EMLEntityView, - SignInView, EditorTemplate, ObjectFormats, EditorSubmitMessageTemplate, -) { +) => { /** * @class EML211EditorView * @classdesc A view of a form for creating and editing EML 2.1.1 documents * @classcategory Views/Metadata * @name EML211EditorView - * @extends EditorView + * @augments EditorView * @constructs */ - var EML211EditorView = EditorView.extend( + const EML211EditorView = EditorView.extend( /** @lends EML211EditorView.prototype */ { type: "EML211Editor", @@ -58,9 +56,9 @@ define([ submitButtonText: MetacatUI.appModel.get("editorSaveButtonText"), /** - * The events this view will listen to and the associated function to call. - * This view will inherit events from the parent class, EditorView. - * @type {Object} + * The events this view will listen to and the associated function to + * call. This view will inherit events from the parent class, EditorView. + * @type {object} */ events: _.extend(EditorView.prototype.events, { change: "saveDraft", @@ -69,8 +67,8 @@ define([ /** The identifier of the root package EML being rendered - * @type {string} - */ + * @type {string} + */ pid: null, /** @@ -85,10 +83,8 @@ define([ */ dataPackageView: null, - /** - * Initialize a new EML211EditorView - called post constructor - */ - initialize: function (options) { + /** @inheritdoc */ + initialize() { // Ensure the object formats are cached for the editor's use if (typeof MetacatUI.objectFormats === "undefined") { MetacatUI.objectFormats = new ObjectFormats(); @@ -100,19 +96,22 @@ define([ /** * Create a new EML model for this view */ - createModel: function () { - //If no pid is given, create a new EML model - if (!this.pid) var model = new EML({ synced: true }); - //Otherwise create a generic metadata model until we find out the formatId - else var model = new ScienceMetadata({ id: this.pid }); - - // Once the ScienceMetadata is populated, populate the associated package + createModel() { + let model = null; + // If no pid is given, create a new EML model + if (!this.pid) model = new EML({ synced: true }); + // Otherwise create a generic metadata model until we find out the + // formatId + else model = new ScienceMetadata({ id: this.pid }); + + // Once the ScienceMetadata is populated, populate the associated + // package this.model = model; - //Listen for the replace event on this model - var view = this; - this.listenTo(this.model, "replace", function (newModel) { - if (view.model.get("id") == newModel.get("id")) { + // Listen for the replace event on this model + const view = this; + this.listenTo(this.model, "replace", (newModel) => { + if (view.model.get("id") === newModel.get("id")) { view.model = newModel; view.setListeners(); } @@ -121,21 +120,20 @@ define([ this.setListeners(); }, - /** - * Render the view - */ - render: function () { - var view = this; + /** @inheritdoc */ + render() { + const view = this; - //Execute the superclass render() function, which will add some basic Editor functionality + // Execute the superclass render() function, which will add some basic + // Editor functionality EditorView.prototype.render.call(this); MetacatUI.appModel.set("headerType", "default"); - //Empty the view element first + // Empty the view element first this.$el.empty(); - //Inert the basic template on the page + // Inert the basic template on the page this.$el.html( this.template({ loading: MetacatUI.appView.loadingTemplate({ @@ -145,7 +143,7 @@ define([ }), ); - //If we don't have a model at this point, create one + // If we don't have a model at this point, create one if (!this.model) this.createModel(); // Before rendering the editor, we must: @@ -155,29 +153,26 @@ define([ // 4. Make sure the user has write permission on the metadata // 5. Make sure the user has write permission on the resource map - // As soon as we have all of the metadata information (STEP 2 complete)... - this.listenToOnce(this.model, "sync", function () { + // As soon as we have all of the metadata information (STEP 2 + // complete)... + this.listenToOnce(this.model, "sync", () => { // Skip the remaining steps the metadata doesn't exist. - if (this.model.get("notFound") == true) { + if (this.model.get("notFound") === true) { this.showNotFound(); return; } - // STEP 3 - // Listen for a trigger from the getDataPackage function that indicates - // The data package (resource map) has been retrieved. - this.listenToOnce(this, "dataPackageFound", function () { - var resourceMap = MetacatUI.rootDataPackage.packageModel; + // STEP 3 Listen for a trigger from the getDataPackage function that + // indicates The data package (resource map) has been retrieved. + this.listenToOnce(this, "dataPackageFound", () => { + const resourceMap = MetacatUI.rootDataPackage.packageModel; - // STEP 5 - // Once we have the resource map, then check that the user is authorized to edit this package. + // STEP 5 Once we have the resource map, then check that the user is + // authorized to edit this package. this.listenToOnce( resourceMap, "change:isAuthorized_write", - function (model, authorization) { - // Render if authorized (will show not authorized if not) - this.renderEditorComponents(); - }, + this.renderEditorComponents, ); // No need to check authorization for a new resource map if (resourceMap.isNew()) { @@ -190,15 +185,11 @@ define([ this.getDataPackage(); - // STEP 4 - // Check the authority of this user to edit the metadata + // STEP 4 Check the authority of this user to edit the metadata this.listenToOnce( this.model, "change:isAuthorized_write", - function (model, authorization) { - // Render if authorized (will show not authorized if not) - this.renderEditorComponents(); - }, + this.renderEditorComponents, ); // If the model is new, no need to check for authorization. if (this.model.isNew()) { @@ -209,15 +200,13 @@ define([ } }); - // STEP 1 - // Check that the user is signed in - var afterAccountChecked = function () { - if (MetacatUI.appUserModel.get("loggedIn") == false) { + // STEP 1 Check that the user is signed in + const afterAccountChecked = () => { + if (MetacatUI.appUserModel.get("loggedIn") === false) { // If they are not signed in, then show the sign-in view view.showSignIn(); } else { - // STEP 2 - // If signed in, then fetch model + // STEP 2 If signed in, then fetch model view.fetchModel(); } }; @@ -225,26 +214,22 @@ define([ if (MetacatUI.appUserModel.get("checked")) { afterAccountChecked(); } - // If we haven't checked for authentication yet, - // wait until the user info is loaded before we request the Metadata + // If we haven't checked for authentication yet, wait until the user + // info is loaded before we request the Metadata else { this.listenToOnce( MetacatUI.appUserModel, "change:checked", - function () { - afterAccountChecked(); - }, + afterAccountChecked, ); } - // When the user mistakenly drops a file into an area in the window - // that isn't a proper drop-target, prevent navigating away from the - // page. Without this, the user will lose their progress in the - // editor. + // When the user mistakenly drops a file into an area in the window that + // isn't a proper drop-target, prevent navigating away from the page. + // Without this, the user will lose their progress in the editor. window.addEventListener( "dragover", - function (e) { - e = e || event; + (e) => { e.preventDefault(); }, false, @@ -252,8 +237,7 @@ define([ window.addEventListener( "drop", - function (e) { - e = e || event; + (e) => { e.preventDefault(); }, false, @@ -263,36 +247,35 @@ define([ }, /** - * Render the editor components (data package view and metadata view), - * or, if not authorized, render the not authorized message. + * Render the editor components (data package view and metadata view), or, + * if not authorized, render the not authorized message. */ - renderEditorComponents: function () { + renderEditorComponents() { if (!MetacatUI.rootDataPackage.packageModel) { return; } - var resMapPermission = - MetacatUI.rootDataPackage.packageModel.get("isAuthorized_write"), - metadataPermission = this.model.get("isAuthorized_write"); + const resMapPermission = + MetacatUI.rootDataPackage.packageModel.get("isAuthorized_write"); + const metadataPermission = this.model.get("isAuthorized_write"); if (resMapPermission === true && metadataPermission === true) { - var view = this; - // Render the Data Package table. - // This function will also render metadata. + const view = this; + // Render the Data Package table. This function will also render + // metadata. view.renderDataPackage(); } else if (resMapPermission === false || metadataPermission === false) { this.notAuthorized(); } }, - /** - * Fetch the metadata model - */ - fetchModel: function () { - //If the user hasn't provided an id, then don't check the authority and mark as synced already + /** Fetch the metadata model */ + fetchModel() { + // If the user hasn't provided an id, then don't check the authority and + // mark as synced already if (!this.pid) { this.model.trigger("sync"); } else { - //Fetch the model + // Fetch the model this.model.fetch(); } }, @@ -300,7 +283,7 @@ define([ /** * @inheritdoc */ - isAccessPolicyEditEnabled: function () { + isAccessPolicyEditEnabled() { if (!MetacatUI.appModel.get("allowAccessPolicyChanges")) { return false; } @@ -309,7 +292,7 @@ define([ return false; } - let limitedTo = MetacatUI.appModel.get( + const limitedTo = MetacatUI.appModel.get( "allowAccessPolicyChangesDatasetsForSubjects", ); if (Array.isArray(limitedTo) && limitedTo.length) { @@ -319,44 +302,34 @@ define([ MetacatUI.appUserModel.get("allIdentitiesAndGroups"), ).length > 0 ); - } else { - return true; } + return true; }, /** - * Update the text that is shown below the spinner while the editor is loading - * - * @param {string} message - The message to display + * Update the text that is shown below the spinner while the editor is + * loading + * @param {string} message - The message to display. If not provided, the + * message will not be updated. */ - updateLoadingText: function (message) { - try { - if (!message || typeof message != "string") { - console.log( - "Was not able to update the loading message, left it as-is. A message must be provided to the updateLoadingText function", - ); - return; - } - var loadingPara = this.$el.find(".loading > p"); - if (loadingPara) { - loadingPara.text(message); - } - } catch (error) { - console.log( - "Was not able to update the loading message, left it as-is. Error details: " + - error, - ); + updateLoadingText(message) { + if (!message || typeof message !== "string") return; + const loadingPara = this.$el.find(".loading > p"); + if (loadingPara) { + loadingPara.text(message); } }, /** - * Get the data package (resource map) associated with the EML. Save it to MetacatUI.rootDataPackage. - * The metadata model must already be synced, and the user must be authorized to edit the EML before this function + * Get the data package (resource map) associated with the EML. Save it to + * MetacatUI.rootDataPackage. The metadata model must already be synced, + * and the user must be authorized to edit the EML before this function * can run. - * @param {Model} scimetaModel - The science metadata model for which to find the associated data package + * @param {Model} model - The science metadata model for which to find the + * associated data package */ - getDataPackage: function (scimetaModel) { - if (!scimetaModel) var scimetaModel = this.model; + getDataPackage(model) { + const scimetaModel = model || this.model; // Check if this package is obsoleted if (this.model.get("obsoletedBy")) { @@ -364,7 +337,7 @@ define([ return; } - var resourceMapIds = scimetaModel.get("resourceMap"); + const resourceMapIds = scimetaModel.get("resourceMap"); // Case 1: No resource map PID found in the metadata if ( @@ -372,9 +345,10 @@ define([ resourceMapIds === null || resourceMapIds.length <= 0 ) { - // 1A: Check if the rootDataPackage contains the metadata document the user is trying to edit. - // Ensure the resource map is not new. If it's a previously unsaved map, then getLatestVersion - // will result in a 404. + // 1A: Check if the rootDataPackage contains the metadata document the + // user is trying to edit. Ensure the resource map is not new. If it's + // a previously unsaved map, then getLatestVersion will result in a + // 404. if ( MetacatUI.rootDataPackage && MetacatUI.rootDataPackage.pluck && @@ -389,13 +363,14 @@ define([ this.getLatestResourceMap(); } - // 1B. If the root data package does not contain the metadata the user is trying to edit, - // then create a new data package. + // 1B. If the root data package does not contain the metadata the user + // is trying to edit, then create a new data package. else { + // this is a helpful message for debugging submission errors for + // now. + // eslint-disable-next-line no-console console.log( - "Resource map ids could not be found for " + - scimetaModel.id + - ", creating a new resource map.", + `Resource map ids could not be found for ${scimetaModel.id}, creating a new resource map.`, ); // Create a new DataPackage collection for this view @@ -410,16 +385,17 @@ define([ // Create a new data package with this id this.createRootDataPackage([this.model], { id: resourceMapIds[0] }); - //Handle the add of the metadata model + // Handle the add of the metadata model MetacatUI.rootDataPackage.saveReference(this.model); - // 2A. If there is more than one resource map, we need to make sure we fetch the most recent one + // 2A. If there is more than one resource map, we need to make sure we + // fetch the most recent one if (resourceMapIds.length > 1) { this.getLatestResourceMap(); // 2B. Just one resource map found } else { - this.listenToOnce(MetacatUI.rootDataPackage, "sync", function () { + this.listenToOnce(MetacatUI.rootDataPackage, "sync", () => { this.trigger("dataPackageFound"); }); // Fetch the data package @@ -429,93 +405,81 @@ define([ }, /** - * Get the latest version of the resource map model stored in MetacatUI.rootDataPackage.packageModel. - * When the newest resource map is synced, the "dataPackageFound" event will be triggered. + * Get the latest version of the resource map model stored in + * MetacatUI.rootDataPackage.packageModel. When the newest resource map is + * synced, the "dataPackageFound" event will be triggered. */ - getLatestResourceMap: function () { - try { - if ( - !MetacatUI.rootDataPackage || - !MetacatUI.rootDataPackage.packageModel - ) { - console.log( - "Could not get the latest verion of the resource map because no resource map is saved.", - ); - return; - } - // Make sure we have the latest version of the resource map before we allow editing - this.listenToOnce( - MetacatUI.rootDataPackage.packageModel, - "latestVersionFound", - function (model) { - //Create a new data package for the latest version package - this.createRootDataPackage([this.model], { - id: model.get("latestVersion"), - }); - //Handle the add of the metadata model - MetacatUI.rootDataPackage.saveReference(this.model); - this.listenToOnce(MetacatUI.rootDataPackage, "sync", function () { - this.trigger("dataPackageFound"); - }); - // Fetch the data package - MetacatUI.rootDataPackage.fetch(); - }, - ); - - //Find the latest version of the resource map - MetacatUI.rootDataPackage.packageModel.findLatestVersion(); - } catch (error) { - console.log( - "Error attempting to find the latest version of the resource map. Error details: " + - error, - ); + getLatestResourceMap() { + if ( + !MetacatUI.rootDataPackage || + !MetacatUI.rootDataPackage.packageModel + ) { + // "Could not get the latest verion of the resource map because no resource map is saved.", + return; } + // Make sure we have the latest version of the resource map before we + // allow editing + this.listenToOnce( + MetacatUI.rootDataPackage.packageModel, + "latestVersionFound", + (model) => { + // Create a new data package for the latest version package + this.createRootDataPackage([this.model], { + id: model.get("latestVersion"), + }); + // Handle the add of the metadata model + MetacatUI.rootDataPackage.saveReference(this.model); + this.listenToOnce(MetacatUI.rootDataPackage, "sync", () => { + this.trigger("dataPackageFound"); + }); + // Fetch the data package + MetacatUI.rootDataPackage.fetch(); + }, + ); + + // Find the latest version of the resource map + MetacatUI.rootDataPackage.packageModel.findLatestVersion(); }, /** - * Creates a DataPackage collection for this EML211EditorView and sets it on the MetacatUI - * global object (as `rootDataPackage`) + * Creates a DataPackage collection for this EML211EditorView and sets it + * on the MetacatUI global object (as `rootDataPackage`) */ - createDataPackage: function () { + createDataPackage() { // Create a new Data packages this.createRootDataPackage([this.model], { packageModelAttrs: { synced: true }, }); - try { - //Inherit the access policy of the metadata document, if the metadata document is not `new` - if (!this.model.isNew()) { - let metadataAccPolicy = this.model.get("accessPolicy"); - let accPolicy = - MetacatUI.rootDataPackage.packageModel.get("accessPolicy"); - - //If there is no access policy, it hasn't been fetched yet, so wait - if (!metadataAccPolicy.length) { - //If the model is of ScienceMetadata class, we need to wait for the "replace" function, - // which happens when the model is fetched and an EML211 model is created to replace it. - if (this.model.type == "ScienceMetadata") { - this.listenTo(this.model, "replace", function () { - this.listenToOnce(this.model, "sysMetaUpdated", function () { - accPolicy.copyAccessPolicy(this.model.get("accessPolicy")); - MetacatUI.rootDataPackage.packageModel.set( - "rightsHolder", - this.model.get("rightsHolder"), - ); - }); + // Inherit the access policy of the metadata document, if the metadata + // document is not `new` + if (!this.model.isNew()) { + const metadataAccPolicy = this.model.get("accessPolicy"); + const accPolicy = + MetacatUI.rootDataPackage.packageModel.get("accessPolicy"); + + // If there is no access policy, it hasn't been fetched yet, so wait + if (!metadataAccPolicy.length) { + // If the model is of ScienceMetadata class, we need to wait for + // the "replace" function, which happens when the model is fetched + // and an EML211 model is created to replace it. + if (this.model.type === "ScienceMetadata") { + this.listenTo(this.model, "replace", () => { + this.listenToOnce(this.model, "sysMetaUpdated", () => { + accPolicy.copyAccessPolicy(this.model.get("accessPolicy")); + MetacatUI.rootDataPackage.packageModel.set( + "rightsHolder", + this.model.get("rightsHolder"), + ); }); - } - } else { - accPolicy.copyAccessPolicy(this.model.get("accessPolicy")); + }); } + } else { + accPolicy.copyAccessPolicy(this.model.get("accessPolicy")); } - } catch (e) { - console.error( - "Could not copy the access policy from the metadata to the resource map: ", - e, - ); } - //Handle the add of the metadata model + // Handle the add of the metadata model MetacatUI.rootDataPackage.handleAdd(this.model); // Associate the science metadata with the resource map @@ -538,13 +502,17 @@ define([ }, /** - * Creates a {@link DataPackage} collection for this Editor view, and saves it as the Root Data Package of the app. - * This centralizes the DataPackage creation so listeners and other functionality is always performed - * @param {(DataONEObject[]|ScienceMetadata[]|EML211[])} models - An array of models to add to the collection - * @param {object} [attributes] A literal object of attributes to pass to the DataPackage.initialize() function + * Creates a {@link DataPackage} collection for this Editor view, and + * saves it as the Root Data Package of the app. This centralizes the + * DataPackage creation so listeners and other functionality is always + * performed + * @param {(DataONEObject[]|ScienceMetadata[]|EML211[])} models - An array + * of models to add to the collection + * @param {object} [attributes] A literal object of attributes to pass to + * the DataPackage.initialize() function * @since 2.17.1 */ - createRootDataPackage: function (models, attributes) { + createRootDataPackage(models, attributes) { MetacatUI.rootDataPackage = new DataPackage(models, attributes); this.listenTo( @@ -554,41 +522,41 @@ define([ ); }, - renderChildren: function (model, options) {}, + renderChildren() {}, /** * Render the Data Package View and insert it into this view */ - renderDataPackage: function () { - var view = this; + renderDataPackage() { + const view = this; if (MetacatUI.rootDataPackage.packageModel.isNew()) { view.renderMember(this.model); } // As the root collection is updated with models, render the UI - this.listenTo(MetacatUI.rootDataPackage, "add", function (model) { + this.listenTo(MetacatUI.rootDataPackage, "add", (model) => { if (!model.get("synced") && model.get("id")) this.listenTo(model, "sync", view.renderMember); else if (model.get("synced")) view.renderMember(model); - //Listen for changes on this member + // Listen for changes on this member model.on("change:fileName", model.addToUploadQueue); }); - //Render the Data Package view + // Render the Data Package view this.dataPackageView = new DataPackageView({ edit: true, dataPackage: MetacatUI.rootDataPackage, parentEditorView: this, }); - //Render the view - var $packageTableContainer = this.$("#data-package-container"); + // Render the view + const $packageTableContainer = this.$("#data-package-container"); $packageTableContainer.html(this.dataPackageView.render().el); - //Make the view resizable on the bottom - var handle = $(document.createElement("div")) + // Make the view resizable on the bottom + const handle = $(document.createElement("div")) .addClass("ui-resizable-handle ui-resizable-s") .attr("title", "Drag to resize") .append( @@ -599,16 +567,16 @@ define([ handles: { s: handle }, minHeight: 100, maxHeight: 900, - resize: function () { + resize() { view.emlView.resizeTOC(); }, }); - var tableHeight = ($(window).height() - $("#Navbar").height()) * 0.4; - $packageTableContainer.css("height", tableHeight + "px"); + const tableHeight = ($(window).height() - $("#Navbar").height()) * 0.4; + $packageTableContainer.css("height", `${tableHeight}px`); - var table = this.dataPackageView.$el; - this.listenTo(this.dataPackageView, "addOne", function () { + const table = this.dataPackageView.$el; + this.listenTo(this.dataPackageView, "addOne", () => { if ( table.outerHeight() > $packageTableContainer.outerHeight() && table.outerHeight() < 220 @@ -623,7 +591,7 @@ define([ if (this.emlView) this.emlView.resizeTOC(); - //Save the view as a subview + // Save the view as a subview this.subviews.push(this.dataPackageView); this.listenTo( @@ -635,42 +603,40 @@ define([ /** * Calls the appropriate render method depending on the model type + * @param {Backbone.Model} model The model to render */ - renderMember: function (model, collection, options) { + renderMember(model) { // Render metadata or package information, based on the type - if (typeof model.attributes === "undefined") { - return; - } else { - switch (model.get("type")) { - case "DataPackage": - // Do recursive rendering here for sub packages - break; - - case "Metadata": - // this.renderDataPackageItem(model, collection, options); - this.renderMetadata(model, collection, options); - break; - - case "Data": - //this.renderDataPackageItem(model, collection, options); - break; - - default: - console.log("model.type is not set correctly"); - } + if (typeof model.attributes === "undefined") return; + + switch (model.get("type")) { + case "DataPackage": + // Do recursive rendering here for sub packages + break; + + case "Metadata": + this.renderMetadata(model); + break; + + case "Data": + // TODO: this.renderDataPackageItem? + break; + + default: + break; } }, /** * Renders the metadata section of the EML211EditorView + * @param {Backbone.Model} modelToRender - The model to render */ - renderMetadata: function (model, collection, options) { - if (!model && this.model) var model = this.model; + renderMetadata(modelToRender) { + const model = modelToRender || this.model; if (!model) return; - var emlView, dataPackageView; - - // render metadata as the collection is updated, but only EML passed from the event + // render metadata as the collection is updated, but only EML passed + // from the event if ( typeof model.get === "undefined" || !( @@ -678,45 +644,45 @@ define([ model.get("formatId") === "https://eml.ecoinformatics.org/eml-2.2.0" ) ) { - console.log("Not EML. TODO: Render generic ScienceMetadata."); + // TODO: Render generic ScienceMetadata return; } - //Create an EML model - if (model.type != "EML") { - //Create a new EML model from the ScienceMetadata model - var EMLmodel = new EML(model.toJSON()); - //Replace the old ScienceMetadata model in the collection + // Create an EML model + if (model.type !== "EML") { + // Create a new EML model from the ScienceMetadata model + const EMLmodel = new EML(model.toJSON()); + // Replace the old ScienceMetadata model in the collection MetacatUI.rootDataPackage.remove(model); MetacatUI.rootDataPackage.add(EMLmodel, { silent: true }); MetacatUI.rootDataPackage.handleAdd(EMLmodel); model.trigger("replace", EMLmodel); - //Fetch the EML and render it + // Fetch the EML and render it this.listenToOnce(EMLmodel, "sync", this.renderMetadata); EMLmodel.fetch(); return; } - //Create an EML211 View and render it - emlView = new EMLView({ - model: model, + // Create an EML211 View and render it + const emlView = new EMLView({ + model, edit: true, }); this.subviews.push(emlView); this.emlView = emlView; emlView.render(); - //Show the required fields for this editor + // Show the required fields for this editor this.renderRequiredIcons(this.getRequiredFields()); - this.listenTo(emlView, "editorInputsAdded", function () { + this.listenTo(emlView, "editorInputsAdded", () => { this.trigger("editorInputsAdded"); }); // Create a citation view and render it - var citationView = new CitationView({ - model: model, + const citationView = new CitationView({ + model, defaultTitle: "Untitled dataset", createLink: false, createTitleLink: !model.isNew(), @@ -725,7 +691,7 @@ define([ this.subviews.push(citationView); $("#citation-container").html(citationView.render().$el); - //Remove the rendering class from the body element + // Remove the rendering class from the body element $("body").removeClass("rendering"); // Focus the folder name field once loaded but only if this is a new @@ -737,13 +703,12 @@ define([ /** * Renders the data package section of the EML211EditorView + * @param {Backbone.Model} model - The model to render */ - renderDataPackageItem: function (model, collection, options) { - var hasPackageSubView = _.find( + renderDataPackageItem(model) { + const hasPackageSubView = _.find( this.subviews, - function (subview) { - return subview.id === "data-package-table"; - }, + (subview) => subview.id === "data-package-table", model, ); @@ -755,15 +720,16 @@ define([ parentEditorView: this, }); this.subviews.push(this.dataPackageView); - dataPackageView.render(); + this.dataPackageView.render(); } }, /** - * Set listeners on the view's model for various reasons. - * This function centralizes all the listeners so that when/if the view's model is replaced, the listeners would be reset. + * Set listeners on the view's model for various reasons. This function + * centralizes all the listeners so that when/if the view's model is + * replaced, the listeners would be reset. */ - setListeners: function () { + setListeners() { this.listenTo(this.model, "change:uploadStatus", this.showControls); // Register a listener for any attribute change @@ -772,7 +738,8 @@ define([ // Register a listener to save drafts on change this.model.on("change", this.model.saveDraft, this.model); - // If any attributes have changed (including nested objects), show the controls + // If any attributes have changed (including nested objects), show the + // controls if (typeof MetacatUI.rootDataPackage.packageModel !== "undefined") { this.stopListening( MetacatUI.rootDataPackage.packageModel, @@ -786,11 +753,12 @@ define([ this.listenTo( MetacatUI.rootDataPackage.packageModel, "change:changed", - function (event) { + () => { if (MetacatUI.rootDataPackage.packageModel.get("changed")) { - // Put this metadata model in the queue when the package has been changed - // Don't put it in the queue if it's in the process of saving already - if (this.model.get("uploadStatus") != "p") + // Put this metadata model in the queue when the package has + // been changed Don't put it in the queue if it's in the process + // of saving already + if (this.model.get("uploadStatus") !== "p") this.model.set("uploadStatus", "q"); } }, @@ -799,7 +767,7 @@ define([ if ( MetacatUI.rootDataPackage && - DataPackage.prototype.isPrototypeOf(MetacatUI.rootDataPackage) + MetacatUI.rootDataPackage instanceof DataPackage ) { // If the Data Package failed saving, display an error message this.listenTo( @@ -815,7 +783,7 @@ define([ this.saveSuccess, ); - //When the Data Package cancels saving, hide the saving styling + // When the Data Package cancels saving, hide the saving styling this.listenTo( MetacatUI.rootDataPackage, "cancelSave", @@ -828,7 +796,7 @@ define([ ); } - //When the model is invalid, show the required fields + // When the model is invalid, show the required fields this.listenTo(this.model, "invalid", this.showValidation); this.listenTo(this.model, "valid", this.showValidation); @@ -839,25 +807,26 @@ define([ this.handleFileLoadError, ); - // When a data package member fails to be read, remove it and warn the user + // When a data package member fails to be read, remove it and warn the + // user this.listenTo( MetacatUI.eventDispatcher, "fileReadError", this.handleFileReadError, ); - //Set a beforeunload event only if there isn't one already + // Set a beforeunload event only if there isn't one already if (!this.beforeunloadCallback) { - var view = this; - //When the Window is about to be closed, show a confirmation message - this.beforeunloadCallback = function (e) { + const view = this; + // When the Window is about to be closed, show a confirmation message + this.beforeunloadCallback = (e) => { if (!view.canClose()) { - //Browsers don't support custom confirmation messages anymore, - // so preventDefault() needs to be called or the return value has to be set + // Browsers don't support custom confirmation messages anymore, so + // preventDefault() needs to be called or the return value has to + // be set e.preventDefault(); e.returnValue = ""; } - return; }; window.addEventListener("beforeunload", this.beforeunloadCallback); } @@ -867,41 +836,41 @@ define([ * Saves all edits in the collection * @param {Event} e - The DOM Event that triggerd this function */ - save: function (e) { - var btn = e && e.target ? $(e.target) : this.$("#save-editor"); + save(e) { + const btn = e && e.target ? $(e.target) : this.$("#save-editor"); - //If the save button is disabled, then we don't want to save right now + // If the save button is disabled, then we don't want to save right now if (btn.is(".btn-disabled")) return; this.showSaving(); - //Save the package! + // Save the package! MetacatUI.rootDataPackage.save(); }, /** * When the data package collection saves successfully, tell the user - * @param {DataPackage|DataONEObject} savedObject - The model or collection that was just saved + * @param {DataPackage|DataONEObject} savedObject - The model or + * collection that was just saved */ - saveSuccess: function (savedObject) { - //We only want to perform these actions after the package saves - if (savedObject.type != "DataPackage") return; + saveSuccess(savedObject) { + // We only want to perform these actions after the package saves + if (savedObject.type !== "DataPackage") return; - //Change the URL to the new id + // Change the URL to the new id MetacatUI.uiRouter.navigate( - "submit/" + encodeURIComponent(this.model.get("id")), + `submit/${encodeURIComponent(this.model.get("id"))}`, { trigger: false, replace: true }, ); this.toggleControls(); // Construct the save message - var message = this.editorSubmitMessageTemplate({ + const message = this.editorSubmitMessageTemplate({ messageText: "Your changes have been submitted.", - viewURL: - MetacatUI.root + - "/view/" + - encodeURIComponent(this.model.get("id")), + viewURL: `${MetacatUI.root}/view/${encodeURIComponent( + this.model.get("id"), + )}`, buttonText: "View your dataset", }); @@ -909,8 +878,8 @@ define([ remove: true, }); - //Rerender the CitationView - var citationView = _.where(this.subviews, { type: "Citation" }); + // Rerender the CitationView + const citationView = _.where(this.subviews, { type: "Citation" }); if (citationView.length) { citationView[0].createTitleLink = true; citationView[0].render(); @@ -925,39 +894,40 @@ define([ /** * When the data package collection fails to save, tell the user - * @param {string} errorMsg - The error message from the failed save() function + * @param {string} errorMsg - The error message from the failed save() + * function */ - saveError: function (errorMsg) { - var errorId = "error" + Math.round(Math.random() * 100), - messageContainer = $(document.createElement("div")).append( - document.createElement("p"), - ), - messageParagraph = messageContainer.find("p"), - messageClasses = "alert-error"; - - //Get all the models that have an error - var failedModels = MetacatUI.rootDataPackage.where({ + saveError(errorMsg) { + const errorId = `error${Math.round(Math.random() * 100)}`; + const messageContainer = $(document.createElement("div")).append( + document.createElement("p"), + ); + const messageParagraph = messageContainer.find("p"); + let messageClasses = "alert-error"; + + // Get all the models that have an error + const failedModels = MetacatUI.rootDataPackage.where({ uploadStatus: "e", }); - //If every failed model is a DataONEObject data file that failed - // because of a slow network, construct a specific error message that - // is more informative than the usual message + // If every failed model is a DataONEObject data file that failed + // because of a slow network, construct a specific error message that is + // more informative than the usual message if ( failedModels.length && - _.every(failedModels, function (m) { - return ( - m.get("type") == "Data" && - m.get("errorMessage").indexOf("network issue") > -1 - ); - }) + _.every( + failedModels, + (m) => + m.get("type") === "Data" && + m.get("errorMessage").indexOf("network issue") > -1, + ) ) { - //Create a list of file names for the files that failed to upload - var failedFileList = $(document.createElement("ul")); + // Create a list of file names for the files that failed to upload + const failedFileList = $(document.createElement("ul")); _.each( failedModels, - function (failedModel) { + (failedModel) => { failedFileList.append( $(document.createElement("li")).text( failedModel.get("fileName"), @@ -967,25 +937,25 @@ define([ this, ); - //Make the error message + // Make the error message messageParagraph.text( "The following files could not be uploaded due to a network issue. Make sure you are connected to a reliable internet connection. ", ); messageParagraph.after(failedFileList); } - //If one of the failed models is this package's metadata model or the + // If one of the failed models is this package's metadata model or the // resource map model and it failed to upload due to a network issue, // show a more specific error message else if ( _.find( failedModels, - function (m) { - var errorMsg = m.get("errorMessage") || ""; - return m == this.model && errorMsg.indexOf("network issue") > -1; + (m) => { + const msg = m.get("errorMessage") || ""; + return m === this.model && msg.indexOf("network issue") > -1; }, this, ) || - (MetacatUI.rootDataPackage.packageModel.get("uploadStatus") == "e" && + (MetacatUI.rootDataPackage.packageModel.get("uploadStatus") === "e" && MetacatUI.rootDataPackage.packageModel .get("errorMessage") .indexOf("network issue") > -1) @@ -1017,7 +987,7 @@ define([ $(document.createElement("a")) .text("See technical details") .attr("data-toggle", "collapse") - .attr("data-target", "#" + errorId) + .attr("data-target", `#${errorId}`) .addClass("pointer"), ), $(document.createElement("div")) @@ -1033,42 +1003,39 @@ define([ this.$el, null, { - emailBody: "Error message: Data Package save error: " + errorMsg, + emailBody: `Error message: Data Package save error: ${errorMsg}`, remove: true, }, ); - //Reset the Saving styling + // Reset the Saving styling this.hideSaving(); }, /** * Find the most recently updated version of the metadata */ - showLatestVersion: function () { - var view = this; - - //When the latest version is found, - this.listenToOnce(this.model, "change:latestVersion", function () { - //Make sure it has a newer version, and if so, - if (view.model.get("latestVersion") != view.model.get("id")) { - //Get the obsoleted id - var oldID = view.model.get("id"); - - //Reset the current model + showLatestVersion() { + const view = this; + + // When the latest version is found, + this.listenToOnce(this.model, "change:latestVersion", () => { + // Make sure it has a newer version, and if so, + if (view.model.get("latestVersion") !== view.model.get("id")) { + // Reset the current model view.pid = view.model.get("latestVersion"); view.model = null; - //Update the URL + // Update the URL MetacatUI.uiRouter.navigate( - "submit/" + encodeURIComponent(view.pid), + `submit/${encodeURIComponent(view.pid)}`, { trigger: false, replace: true }, ); - //Render the new model + // Render the new model view.render(); - //Show a warning that the user was trying to edit old content + // Show a warning that the user was trying to edit old content MetacatUI.appView.showAlert( "You've been forwarded to the newest version of your dataset for editing.", "alert-warning", @@ -1081,7 +1048,7 @@ define([ } }); - //Find the latest version of this metadata object + // Find the latest version of this metadata object this.model.findLatestVersion(); }, @@ -1089,29 +1056,29 @@ define([ * Show the entity editor * @param {Event} e - The DOM Event that triggerd this function */ - showEntity: function (e) { + showEntity(e) { if (!e || !e.target) return; - //For EML metadata docs - if (this.model.type == "EML") { - //Get the Entity View - var row = $(e.target).parents(".data-package-item"), - entityView = row.data("entityView"), - dataONEObject = row.data("model"); + // For EML metadata docs + if (this.model.type === "EML") { + // Get the Entity View + const row = $(e.target).parents(".data-package-item"); + let entityView = row.data("entityView"); + const dataONEObject = row.data("model"); if ( - dataONEObject.get("uploadStatus") == "p" || - dataONEObject.get("uploadStatus") == "l" || - dataONEObject.get("uploadStatus") == "e" + dataONEObject.get("uploadStatus") === "p" || + dataONEObject.get("uploadStatus") === "l" || + dataONEObject.get("uploadStatus") === "e" ) return; - //If there isn't a view yet, create one + // If there isn't a view yet, create one if (!entityView) { - //Get the entity model for this data package item - var entityModel = this.model.getEntity(row.data("model")); + // Get the entity model for this data package item + let entityModel = this.model.getEntity(row.data("model")); - //Create a new EMLOtherEntity if it doesn't exist + // Create a new EMLOtherEntity if it doesn't exist if (!entityModel) { entityModel = new EMLOtherEntity({ entityName: dataONEObject.get("fileName"), @@ -1123,18 +1090,19 @@ define([ }); if (!dataONEObject.get("fileName")) { - //Listen to changes to required fields on the otherEntity models - this.listenTo(entityModel, "change:entityName", function () { + // Listen to changes to required fields on the otherEntity + // models + this.listenTo(entityModel, "change:entityName", () => { if (!entityModel.isValid()) return; - //Get the position this entity will be in - var position = $(".data-package-item.data").index(row); + // Get the position this entity will be in + const position = $(".data-package-item.data").index(row); this.model.addEntity(entityModel, position); }); } else { - //Get the position this entity will be in - var position = $(".data-package-item.data").index(row); + // Get the position this entity will be in + const position = $(".data-package-item.data").index(row); this.model.addEntity(entityModel, position); } @@ -1146,14 +1114,14 @@ define([ }); } - //Attach the view to the edit button so we can access it again + // Attach the view to the edit button so we can access it again row.data("entityView", entityView); - //Render the view + // Render the view entityView.render(); } - //Show the modal window editor for this entity + // Show the modal window editor for this entity if (entityView) entityView.show(); } }, @@ -1161,8 +1129,9 @@ define([ /** * Shows a message if the user is not authorized to edit this package */ - notAuthorized: function () { - // Don't show the not authorized message if the user is authorized to edit the EML and the resource map + notAuthorized() { + // Don't show the not authorized message if the user is authorized to + // edit the EML and the resource map if ( MetacatUI.rootDataPackage && MetacatUI.rootDataPackage.packageModel @@ -1175,10 +1144,8 @@ define([ ) { return; } - } else { - if (this.model.get("isAuthorized")) { - return; - } + } else if (this.model.get("isAuthorized")) { + return; } this.$("#editor-body").empty(); @@ -1188,7 +1155,7 @@ define([ "#editor-body", ); - //Stop listening to any further events + // Stop listening to any further events this.stopListening(); this.model.off(); }, @@ -1196,7 +1163,7 @@ define([ /** * Toggle the editor footer controls (Save bar) */ - toggleControls: function () { + toggleControls() { if ( MetacatUI.rootDataPackage && MetacatUI.rootDataPackage.packageModel && @@ -1209,20 +1176,20 @@ define([ }, /** - * Toggles whether the Save controls for the Editor are enabled or disabled based on various attributes of the DataPackage and its models. + * Toggles whether the Save controls for the Editor are enabled or + * disabled based on various attributes of the DataPackage and its models. * @since 2.17.1 */ - toggleEnableControls: function () { + toggleEnableControls() { if (MetacatUI.rootDataPackage.packageModel.get("isLoadingFiles")) { - let noun = + const noun = MetacatUI.rootDataPackage.packageModel.get("numLoadingFiles") > 1 ? " files" : " file"; this.disableControls( - "Waiting for " + - MetacatUI.rootDataPackage.packageModel.get("numLoadingFiles") + - noun + - " to upload...", + `Waiting for ${MetacatUI.rootDataPackage.packageModel.get( + "numLoadingFiles", + )}${noun} to upload...`, ); } else { this.enableControls(); @@ -1232,81 +1199,81 @@ define([ /** * Show any errors that occured when trying to save changes */ - showValidation: function () { - //First clear all the error messaging + showValidation() { + // First clear all the error messaging this.$(".notification.error").empty(); this.$(".side-nav-item .icon").hide(); this.$("#metadata-container .error").removeClass("error"); $(".alert-container:not(:has(.temporary-message))").remove(); - var errors = this.model.validationError; + const errors = this.model.validationError; _.each( errors, - function (errorMsg, category) { - var categoryEls = this.$("[data-category='" + category + "']"), - dataItemRow = categoryEls.parents(".data-package-item"); + (errorMsg, category) => { + const categoryEls = this.$(`[data-category='${category}']`); + const dataItemRow = categoryEls.parents(".data-package-item"); - //If this field is in a DataItemView, then delegate to that view + // If this field is in a DataItemView, then delegate to that view if (dataItemRow.length && dataItemRow.data("view")) { dataItemRow.data("view").showValidation(category, errorMsg); return; - } else { - var elsWithViews = _.filter(categoryEls, function (el) { - return ( - $(el).data("view") && - $(el).data("view").showValidation && - !$(el).data("view").isNew - ); - }); + } + const elsWithViews = _.filter( + categoryEls, + (el) => + $(el).data("view") && + $(el).data("view").showValidation && + !$(el).data("view").isNew, + ); - if (elsWithViews.length) { - _.each(elsWithViews, function (el) { - $(el).data("view").showValidation(); - }); - } else if (categoryEls.length) { - //Show the error message - categoryEls - .filter(".notification") - .addClass("error") - .text(errorMsg); - - //Add the error message to inputs - categoryEls.filter("textarea, input").addClass("error"); - } + if (elsWithViews.length) { + _.each(elsWithViews, (el) => { + $(el).data("view").showValidation(); + }); + } else if (categoryEls.length) { + // Show the error message + categoryEls + .filter(".notification") + .addClass("error") + .text(errorMsg); + + // Add the error message to inputs + categoryEls.filter("textarea, input").addClass("error"); } - //Get the link in the table of contents navigation - var navigationLink = this.$( - ".side-nav-item[data-category='" + category + "']", + // Get the link in the table of contents navigation + let navigationLink = this.$( + `.side-nav-item[data-category='${category}']`, ); if (!navigationLink.length) { - var section = categoryEls.parents("[data-section]"); + const section = categoryEls.parents("[data-section]"); navigationLink = this.$( - ".side-nav-item." + $(section).attr("data-section"), + `.side-nav-item.${$(section).attr("data-section")}`, ); } - //Show the error icon in the table of contents + // Show the error icon in the table of contents navigationLink .addClass("error") .find(".icon") .addClass("error") .show(); - this.model.off("change:" + category, this.model.checkValidity); - this.model.once("change:" + category, this.model.checkValidity); + this.model.off(`change:${category}`, this.model.checkValidity); + this.model.once(`change:${category}`, this.model.checkValidity); }, this, ); if (errors) { - //Create a list of errors to display in the error message shown to the user - let errorList = ""; + // Create a list of errors to display in the error message shown to + // the user + const errorList = ``; MetacatUI.appView.showAlert( - "Fix the errors flagged below before submitting: " + errorList, + `Fix the errors flagged below before submitting: ${errorList}`, "alert-error", this.$el, null, @@ -1320,38 +1287,40 @@ define([ /** * @inheritdoc */ - hasUnsavedChanges: function () { - //If the form hasn't been edited, we can close this view without confirmation + hasUnsavedChanges() { + // If the form hasn't been edited, we can close this view without + // confirmation if ( - typeof MetacatUI.rootDataPackage.getQueue != "function" || + typeof MetacatUI.rootDataPackage.getQueue !== "function" || MetacatUI.rootDataPackage.getQueue().length ) return true; - else return false; + return false; }, /** * @inheritdoc */ - onClose: function () { - //Execute the parent class onClose() function - //EditorView.prototype.onClose.call(this); + onClose() { + // Execute the parent class onClose() function + // EditorView.prototype.onClose.call(this); - //Remove the listener on the Window + // Remove the listener on the Window if (this.beforeunloadCallback) { window.removeEventListener("beforeunload", this.beforeunloadCallback); delete this.beforeunloadCallback; } - //Stop listening to the "add" event so that new package members aren't rendered. - //Check first if the DataPackage has been intialized. An easy check is to see is - // the 'models' attribute is undefined. If the DataPackage collection has been intialized, - // then it would be an empty array. + // Stop listening to the "add" event so that new package members aren't + // rendered. Check first if the DataPackage has been intialized. An easy + // check is to see is the 'models' attribute is undefined. If the + // DataPackage collection has been intialized, then it would be an empty + // array. if (typeof MetacatUI.rootDataPackage.models !== "undefined") { this.stopListening(MetacatUI.rootDataPackage, "add"); } - //Remove all the other events + // Remove all the other events this.off(); // remove callbacks, prevent zombies this.model.off(); @@ -1361,7 +1330,7 @@ define([ this.model = null; // Close each subview - _.each(this.subviews, function (subview) { + _.each(this.subviews, (subview) => { if (subview.onClose) subview.onClose(); }); @@ -1371,13 +1340,14 @@ define([ }, /** - * Handle "fileLoadError" events by alerting the user - * and removing the row from the data package table. - * @param {DataONEObject} item The model item passed by the fileLoadError event + * Handle "fileLoadError" events by alerting the user and removing the + * row from the data package table. + * @param {DataONEObject} item The model item passed by the fileLoadError + * event */ - handleFileLoadError: function (item) { - var message; - var fileName; + handleFileLoadError(item) { + let message; + let fileName; /* Remove the data package table row */ this.dataPackageView.removeOne(item); /* Then inform the user */ @@ -1388,10 +1358,7 @@ define([ item.get("fileName") !== null) ) { fileName = item.get("fileName"); - message = - "The file " + - fileName + - " is already included in this dataset. The duplicate file has not been added."; + message = `The file ${fileName} is already included in this dataset. The duplicate file has not been added.`; } else { message = "The chosen file is already included in this dataset. " + @@ -1403,13 +1370,14 @@ define([ }, /** - * Handle "fileReadError" events by alerting the user - * and removing the row from the data package table. - * @param {DataONEObject} item The model item passed by the fileReadError event + * Handle "fileReadError" events by alerting the user and removing the row + * from the data package table. + * @param {DataONEObject} item The model item passed by the fileReadError + * event */ - handleFileReadError: function (item) { - var message; - var fileName; + handleFileReadError(item) { + let message; + let fileName; /* Remove the data package table row */ this.dataPackageView.removeOne(item); /* Then inform the user */ @@ -1421,11 +1389,9 @@ define([ ) { fileName = item.get("fileName"); message = - "The file " + - fileName + - " could not be read. You may not have permission to read the file," + - " or the file was too large for your browser to upload. " + - "The file has not been added."; + `The file ${fileName} could not be read. You may not have permission to read the file,` + + ` or the file was too large for your browser to upload. ` + + `The file has not been added.`; } else { message = "The chosen file " + @@ -1441,73 +1407,65 @@ define([ /** * Save a draft of the parent EML model */ - saveDraft: function () { - var view = this; - - try { - var title = this.model.get("title") || "No title"; - // Create a clone of the model that we will use for serialization. - // Don't serialize the model that is currently being edited, - // since serialize may make changes to the model that should not - // happen until the user is ready to save - // (e.g. - create a contact if there is not one) - var draftModel = this.model.clone(); - - LocalForage.setItem(this.model.get("id"), { - id: this.model.get("id"), - datetime: new Date().toISOString(), - title: Array.isArray(title) ? title[0] : title, - draft: draftModel.serialize(), - }).then(function () { - view.clearOldDrafts(); - }); - } catch (ex) { - console.log("Error saving draft:", ex); - } + saveDraft() { + const view = this; + + const title = this.model.get("title") || "No title"; + // Create a clone of the model that we will use for serialization. + // Don't serialize the model that is currently being edited, since + // serialize may make changes to the model that should not happen + // until the user is ready to save (e.g. - create a contact if there + // is not one) + const draftModel = this.model.clone(); + + LocalForage.setItem(this.model.get("id"), { + id: this.model.get("id"), + datetime: new Date().toISOString(), + title: Array.isArray(title) ? title[0] : title, + draft: draftModel.serialize(), + }).then(() => { + view.clearOldDrafts(); + }); }, /** - * Clear older drafts by iterating over the sorted list of drafts - * stored by LocalForage and removing any beyond a hardcoded limit. + * Clear older drafts by iterating over the sorted list of drafts stored + * by LocalForage and removing any beyond a hardcoded limit. */ - clearOldDrafts: function () { - var drafts = []; - - try { - LocalForage.iterate(function (value, key, iterationNumber) { - // Extract each draft - drafts.push({ - key: key, - value: value, - }); + clearOldDrafts() { + let drafts = []; + + LocalForage.iterate((value, key) => { + // Extract each draft + drafts.push({ + key, + value, + }); + }) + .then(() => { + // Sort by datetime + drafts = _.sortBy(drafts, (draft) => + draft.value.datetime.toString(), + ).reverse(); }) - .then(function () { - // Sort by datetime - drafts = _.sortBy(drafts, function (draft) { - return draft.value.datetime.toString(); - }).reverse(); - }) - .then(function () { - _.each(drafts, function (draft, i) { - var age = new Date() - new Date(draft.value.datetime); - var isOld = age / 2678400000 > 1; // ~31days - - // Delete this draft is not in the most recent 100 or - // if older than 31 days - var shouldDelete = i > 100 || isOld; - - if (!shouldDelete) { - return; - } - - LocalForage.removeItem(draft.key).then(function () { - // Item should be removed - }); + .then(() => { + _.each(drafts, (draft, i) => { + const age = new Date() - new Date(draft.value.datetime); + const isOld = age / 2678400000 > 1; // ~31days + + // Delete this draft is not in the most recent 100 or if older + // than 31 days + const shouldDelete = i > 100 || isOld; + + if (!shouldDelete) { + return; + } + + LocalForage.removeItem(draft.key).then(() => { + // Item should be removed }); }); - } catch (ex) { - console.log("Failed to clear old drafts: ", ex); - } + }); }, /** @@ -1516,43 +1474,37 @@ define([ * This method calls the superclass method, feeding it the identifier * associated with the row in the package table that was clicked. The * reason for this is so the AccessPolicyView can be used for single - * objects (like in the Portal editor) or an entire Collection of - * objects, like in the EML editor: The superclass impelements the - * generic behavior and the subclass tweaks it. - * - * @param {EventHandler} e: The click event + * objects (like in the Portal editor) or an entire Collection of objects, + * like in the EML editor: The superclass impelements the generic behavior + * and the subclass tweaks it. + * @param {EventHandler} e The click event that triggered this method */ - showAccessPolicyModal: function (e) { - var id = null; - - try { - id = $(e.target).parents("tr").data("id"); - } catch (e) { - console.log( - "Error determining the identifier to show an AccessPolicyView for:", - e, - ); - } + showAccessPolicyModal(e) { + const id = $(e.target)?.parents("tr")?.data("id"); + if (!id) return; - var model = MetacatUI.rootDataPackage.find(function (model) { - return model.get("id") === id; - }); + const model = MetacatUI.rootDataPackage.find((m) => m.get("id") === id); EditorView.prototype.showAccessPolicyModal.call(this, e, model); }, /** - * Gets the EML required fields, as configured in the {@link AppConfig#emlEditorRequiredFields}, and adds - * possible other special fields that may be configured elsewhere. (e.g. the {@link AppConfig#customEMLMethods}) - * @extends EditorView.getRequiredFields + * Gets the EML required fields, as configured in the + * {@link AppConfig#emlEditorRequiredFields}, and adds possible other + * special fields that may be configured elsewhere. (e.g. the + * {@link AppConfig#customEMLMethods}) + * @augments EditorView.getRequiredFields + * @returns {object} An object literal of the required fields for this EML + * editor */ - getRequiredFields: function () { - let requiredFields = _.clone( + getRequiredFields() { + const requiredFields = _.clone( MetacatUI.appModel.get("emlEditorRequiredFields"), ); - //Add required fields for Custom Methods, which are configured in a different property of the AppConfig - let customMethodOptions = MetacatUI.appModel.get("customEMLMethods"); + // Add required fields for Custom Methods, which are configured in a + // different property of the AppConfig + const customMethodOptions = MetacatUI.appModel.get("customEMLMethods"); if (customMethodOptions) { customMethodOptions.forEach((options) => { if (options.required && !requiredFields[options.id]) {