diff --git a/app/controllers/providers/show/repositories/new.js b/app/controllers/providers/show/repositories/new.js index a2a8399ef..00da84419 100644 --- a/app/controllers/providers/show/repositories/new.js +++ b/app/controllers/providers/show/repositories/new.js @@ -1,231 +1,238 @@ -import classic from 'ember-classic-decorator'; -import { action, computed } from '@ember/object'; -import { inject as service } from '@ember/service'; -import Controller from '@ember/controller'; -import { isBlank } from '@ember/utils'; -import { capitalize } from '@ember/string'; -import langs from 'langs'; -import { A } from '@ember/array'; -import { clientTypeList, softwareList } from 'bracco/models/repository'; - -@classic -export default class NewController extends Controller { - @service - store; - - @service - router; - - @service - flashMessages; - - re3data = null; - softwareList = softwareList; - softwares = softwareList; - clientTypeList = clientTypeList; - clientTypes = clientTypeList; - - @computed('clientTypeList', 'model.repository.clientType') - get clientType() { - return this.clientTypeList.find( - (item) => item.value === this.get('model.repository.clientType') - ); - } - - init(...args) { - super.init(...args); - - this.repositories = this.repositories || []; - } - - @action - searchRe3DataAction(query) { - let self = this; - this.store - .query('re3data', { query, 'page[size]': 25 }) - .then(function (repositories) { - self.set('repositories', repositories); - }) - .catch(function (reason) { - console.debug(reason); - self.set('repositories', []); - }); - } - - @action - selectRe3DataAction(re3data) { - if (re3data) { - let self = this; - this.store - .findRecord('re3data', re3data.id) - .then(function (repo) { - self.set('re3data', repo); - self.model.repository.set('clientType', 'repository'); - self.model.repository.set( - 're3data', - 'https://doi.org/' + repo.get('id') - ); - self.model.repository.set('name', repo.get('repositoryName')); - self.model.repository.set('description', repo.get('description')); - if (repo.get('additionalNames').length > 0) { - self.model.repository.set( - 'alternateName', - A(repo.get('additionalNames')).get('firstObject').text - ); - } else { - self.model.repository.set('alternateName', null); - } - self.model.repository.set('url', repo.get('repositoryUrl')); - if (repo.get('software').length > 0) { - let software = repo.get('software')[0].name; - if (software === 'DataVerse') { - software = 'Dataverse'; - } else if (software === 'unknown') { - software = 'Other'; - } - self.model.repository.set('software', capitalize(software)); - } - if (repo.get('repositoryLanguages').length > 0) { - self.model.repository.set( - 'language', - A(repo.get('repositoryLanguages')).map(function (l) { - return langs.where('2', l.text)['1']; - }) - ); - } - if (repo.get('types').length > 0) { - self.model.repository.set( - 'repositoryType', - A(repo.get('types')).mapBy('text') - ); - } - if (repo.get('certificates').length > 0) { - self.model.repository.set( - 'certificate', - A(repo.get('certificates')).mapBy('text') - ); - } - }) - .catch(function (reason) { - console.debug(reason); - }); - } else { - this.model.repository.set('re3data', null); - } - } - - @action - searchClientTypeAction(query) { - let clientTypes = this.clientTypeList.filter(function (clientType) { - return clientType.label.toLowerCase().startsWith(query.toLowerCase()); - }); - this.set('clientTypes', clientTypes); - } - - @action - selectClientTypeAction(clientType) { - this.model.repository.set('clientType', clientType.value); - this.set('clientTypes', this.clientTypeList); - } - - @action - searchSoftwareAction(query) { - let softwares = softwareList.filter(function (software) { - return software.toLowerCase().startsWith(query.toLowerCase()); - }); - this.set('softwares', softwares); - } - - @action - selectSoftwareAction(software) { - this.model.repository.set('software', software); - this.set('softwares', softwareList); - } - - @action - addLanguageAction() { - this.model.repository.get('language').pushObject(null); - } - - @action - addCertificateAction() { - this.model.repository.get('certificate').pushObject(null); - } - - @action - addRepositoryTypeAction() { - this.model.repository.get('repositoryType').pushObject(null); - } - - @action - submitAction(repository) { - let self = this; - - // Remove all whitespace on domains. - if (this.model.repository.get('domains')) { - let domains = this.model.repository.get('domains'); - this.model.repository.set('domains', domains.replace(/\s/g, '')); - } - - repository.set( - 'language', - repository.get('language').filter(function (language) { - return !isBlank(language); - }) - ); - - repository.set( - 'repositoryType', - repository.get('repositoryType').filter(function (repositoryType) { - return !isBlank(repositoryType); - }) - ); - - repository.set( - 'certificate', - repository.get('certificate').filter(function (certificate) { - return !isBlank(certificate); - }) - ); - - repository - .save() - .then(function (repository) { - repository.prefixes.then(function (prefixes) { - self.router.transitionTo( - 'repositories.show.settings', - self.model.repository.id, - { - queryParams: { - assignedPrefix: - prefixes.length > 0 ? prefixes.firstObject.id : null - } - } - ); - }); - }) - .catch(function (reason) { - console.debug(reason); - let msg = reason?.errors[0]?.title - ? reason.errors[0].title - : reason?.title - ? reason.title - : 'Cause is unknown. Please contact support.'; - - self - .get('flashMessages') - .danger( - 'An error occurred and while saving this repository.' + ' ' + msg - ); - }); - } - - @action - cancelAction() { - this.model.repository.rollbackAttributes(); - this.router.transitionTo( - 'providers.show.repositories', - this.get('model.provider.id') - ); - } -} +import classic from 'ember-classic-decorator'; +import { action, computed } from '@ember/object'; +import { inject as service } from '@ember/service'; +import Controller from '@ember/controller'; +import { isBlank } from '@ember/utils'; +import { capitalize } from '@ember/string'; +import langs from 'langs'; +import { A } from '@ember/array'; +import { clientTypeList, softwareList } from 'bracco/models/repository'; + +@classic +export default class NewController extends Controller { + @service + store; + + @service + router; + + @service + flashMessages; + + re3data = null; + softwareList = softwareList; + softwares = softwareList; + isSoftwareFieldActive = false; + clientTypeList = clientTypeList; + clientTypes = clientTypeList; + + @computed('clientTypeList', 'model.repository.clientType') + get clientType() { + return this.clientTypeList.find( + (item) => item.value === this.get('model.repository.clientType') + ); + } + + init(...args) { + super.init(...args); + + this.repositories = this.repositories || []; + } + + @action + searchRe3DataAction(query) { + let self = this; + this.store + .query('re3data', { query, 'page[size]': 25 }) + .then(function (repositories) { + self.set('repositories', repositories); + }) + .catch(function (reason) { + console.debug(reason); + self.set('repositories', []); + }); + } + + @action + selectRe3DataAction(re3data) { + if (re3data) { + let self = this; + this.store + .findRecord('re3data', re3data.id) + .then(function (repo) { + self.set('re3data', repo); + self.model.repository.set('clientType', 'repository'); + self.model.repository.set( + 're3data', + 'https://doi.org/' + repo.get('id') + ); + self.model.repository.set('name', repo.get('repositoryName')); + self.model.repository.set('description', repo.get('description')); + if (repo.get('additionalNames').length > 0) { + self.model.repository.set( + 'alternateName', + A(repo.get('additionalNames')).get('firstObject').text + ); + } else { + self.model.repository.set('alternateName', null); + } + self.model.repository.set('url', repo.get('repositoryUrl')); + if (repo.get('software').length > 0) { + let software = repo.get('software')[0].name; + if (software === 'DataVerse') { + software = 'Dataverse'; + } else if (software === 'unknown') { + software = 'Other'; + } + self.model.repository.set('software', capitalize(software)); + } + if (repo.get('repositoryLanguages').length > 0) { + self.model.repository.set( + 'language', + A(repo.get('repositoryLanguages')).map(function (l) { + return langs.where('2', l.text)['1']; + }) + ); + } + if (repo.get('types').length > 0) { + self.model.repository.set( + 'repositoryType', + A(repo.get('types')).mapBy('text') + ); + } + if (repo.get('certificates').length > 0) { + self.model.repository.set( + 'certificate', + A(repo.get('certificates')).mapBy('text') + ); + } + }) + .catch(function (reason) { + console.debug(reason); + }); + } else { + this.model.repository.set('re3data', null); + } + } + + @action + searchClientTypeAction(query) { + let clientTypes = this.clientTypeList.filter(function (clientType) { + return clientType.label.toLowerCase().startsWith(query.toLowerCase()); + }); + this.set('clientTypes', clientTypes); + } + + @action + selectClientTypeAction(clientType) { + this.model.repository.set('clientType', clientType.value); + this.set('clientTypes', this.clientTypeList); + } + + @action + searchSoftwareAction(query) { + let softwares = softwareList.filter(function (software) { + return software.toLowerCase().startsWith(query.toLowerCase()); + }); + this.set('softwares', softwares); + } + + @action + selectSoftwareAction(software) { + this.model.repository.set('software', software); + this.set('softwares', softwareList); + } + + @action + addLanguageAction() { + this.model.repository.get('language').pushObject(null); + } + + @action + addCertificateAction() { + this.model.repository.get('certificate').pushObject(null); + } + + @action + addRepositoryTypeAction() { + this.model.repository.get('repositoryType').pushObject(null); + } + + @action + submitAction(repository) { + let self = this; + + // Remove all whitespace on domains. + if (this.model.repository.get('domains')) { + let domains = this.model.repository.get('domains'); + this.model.repository.set('domains', domains.replace(/\s/g, '')); + } + + repository.set( + 'language', + repository.get('language').filter(function (language) { + return !isBlank(language); + }) + ); + + repository.set( + 'repositoryType', + repository.get('repositoryType').filter(function (repositoryType) { + return !isBlank(repositoryType); + }) + ); + + repository.set( + 'certificate', + repository.get('certificate').filter(function (certificate) { + return !isBlank(certificate); + }) + ); + + repository + .save() + .then(function (repository) { + repository.prefixes.then(function (prefixes) { + self.router.transitionTo( + 'repositories.show.settings', + self.model.repository.id, + { + queryParams: { + assignedPrefix: + prefixes.length > 0 ? prefixes.firstObject.id : null + } + } + ); + }); + }) + .catch(function (reason) { + console.debug(reason); + let msg = reason?.errors[0]?.title + ? reason.errors[0].title + : reason?.title + ? reason.title + : 'Cause is unknown. Please contact support.'; + + self + .get('flashMessages') + .danger( + 'An error occurred and while saving this repository.' + ' ' + msg + ); + }); + } + + @action + cancelAction() { + this.model.repository.rollbackAttributes(); + this.router.transitionTo( + 'providers.show.repositories', + this.get('model.provider.id') + ); + } + + // This helps to manage the validation state of the software field. The field is required, but we don't want to show it as invalid until the user has interacted with it. + @action + activateSoftwareField() { + return this.set('isSoftwareFieldActive', true); + } +} diff --git a/app/controllers/repositories/show/edit.js b/app/controllers/repositories/show/edit.js index 50b3b1850..c3362bcd7 100644 --- a/app/controllers/repositories/show/edit.js +++ b/app/controllers/repositories/show/edit.js @@ -29,6 +29,7 @@ export default class EditController extends Controller { re3data = null; softwareList = softwareList; softwares = softwareList; + isSoftwareFieldActive = false; clientTypeList = clientTypeList; clientTypes = clientTypeList; @@ -185,4 +186,10 @@ export default class EditController extends Controller { this.model.rollbackAttributes(); this.router.transitionTo('repositories.show', this.model); } + + // This helps to manage the validation state of the software field. The field is required, but we don't want to show it as invalid until the user has interacted with it. + @action + activateSoftwareField() { + return this.set('isSoftwareFieldActive', true); + } } diff --git a/app/models/repository.js b/app/models/repository.js index 35c4bfc3b..605dac095 100644 --- a/app/models/repository.js +++ b/app/models/repository.js @@ -156,6 +156,9 @@ const Validations = buildValidations({ allowBlank: true, message: 'ISSN (print) is in the wrong format.' }) + ], + software: [ + validator('presence', true) ] }); diff --git a/app/routes/providers/show/repositories/new.js b/app/routes/providers/show/repositories/new.js index f09ee530b..7290f62f9 100644 --- a/app/routes/providers/show/repositories/new.js +++ b/app/routes/providers/show/repositories/new.js @@ -37,4 +37,22 @@ export default class NewRoute extends Route { }) }); } + + setupController(controller, model) { + // Call _super to maintain default behavior (controller.set('model', model)) + super.setupController(controller, model); + + // Custom setup: Set additional properties + controller.set('isSoftwareFieldActive', false); + } + + resetController(controller, isExiting, transition) { + // If the user is exiting the route entirely, reset the transient properties + if (isExiting) { + controller.set('isSoftwareFieldActive', false); + } + + // Calls the default resetController behavior (important for query params) + super.resetController(controller, isExiting, transition); + } } diff --git a/app/routes/repositories/show/edit.js b/app/routes/repositories/show/edit.js index fa6c5c4ca..48a47b325 100644 --- a/app/routes/repositories/show/edit.js +++ b/app/routes/repositories/show/edit.js @@ -39,5 +39,16 @@ export default class EditRoute extends Route { controller.set('clientTypeList', filteredClientTypeList); controller.set('clientTypes', filteredClientTypeList); + controller.set('isSoftwareFieldActive', false); + } + + resetController(controller, isExiting, transition) { + // If the user is exiting the route entirely, reset the transient properties + if (isExiting) { + controller.set('isSoftwareFieldActive', false); + } + + // Calls the default resetController behavior (important for query params) + super.resetController(controller, isExiting, transition); } } diff --git a/app/styles/local.css b/app/styles/local.css index eef6441af..e62f8aea4 100755 --- a/app/styles/local.css +++ b/app/styles/local.css @@ -147,7 +147,6 @@ div[doi-format].power-select-fragment .ember-basic-dropdown-trigger div.ember-vi /* VALIDATION - FORM-GROUPS */ .form-group .form-text { - font-size: 16px; display: block; margin-top: 5px; margin-bottom: 10px; @@ -555,7 +554,6 @@ div[doi-publisher] > div { .form-group input.is-valid + div.form-text { color: #2ecc71; } -*/ /* VALIDATION - text areas (Mostly in doi form upload.) */ diff --git a/app/templates/providers/show/repositories/new.hbs b/app/templates/providers/show/repositories/new.hbs index 36e7b5977..c350dc0fe 100644 --- a/app/templates/providers/show/repositories/new.hbs +++ b/app/templates/providers/show/repositories/new.hbs @@ -1,159 +1,158 @@ -
* to allow all domains, specify an exact domain (e.g., example.org or www.example.org), or use *. before a domain to allow only its subdomains (e.g., *.example.org). You can also separate multiple entries with commas (e.g., example.org,*.example.org,www.secondexample.org). Learn more...* to allow all domains, specify an exact domain (e.g., example.org or www.example.org), or use *. before a domain to allow only its subdomains (e.g., *.example.org). You can also separate multiple entries with commas (e.g., example.org,*.example.org,www.secondexample.org). Learn more...* to allow all domains, specify an exact domain (e.g., example.org or www.example.org), or use *. before a domain to allow only its subdomains (e.g., *.example.org). You can also separate multiple entries with commas (e.g., example.org,*.example.org,www.secondexample.org). Learn more...* to allow all domains, specify an exact domain (e.g., example.org or www.example.org), or use *. before a domain to allow only its subdomains (e.g., *.example.org). You can also separate multiple entries with commas (e.g., example.org,*.example.org,www.secondexample.org). Learn more...