From 9b713e56fe3e220c3fce857bfcaff17a5050dd11 Mon Sep 17 00:00:00 2001 From: Johnathan Date: Mon, 1 Jul 2024 13:43:21 -0600 Subject: [PATCH] Fix Data Quality Components (#678) * Add precision dropdown to date object * Refactor Date and Datetime Components Handling precision. * Update package.json version to 1.4.0-beta.16 * Update package.json version to 1.4.0-beta.16 * chore: Update package.json version to 1.5.0-beta.1 * Update package.json version to 1.5.0-beta.7 * Add "Reference" to Evaluation Procedure Also code formatting single quote to double quote * Revert to single quotes * Refactor .prettierrc.js to use single quotes for consistency * chore: Update alert styling in md-standalone-quality-report template * Refactor md-quality-report templates to use model.name for input value * feat: Update md-quality-report template to use quantitativeValue for input value * chore: Bump version to 1.5.0-beta.5 in package.json * chore: Remove console.log statement in md-datetime component * chore: Update mdcodes and mdjson-schemas dependencies to latest beta versions * chore: Bump version to 1.5.0-beta.10 in package.json * Refactor md-quality-report templates to use model.name for input value * chore: Update mdjson-schemas dependency to version 2.9.2-beta.19 * chore: Update mdjson-schemas and mdcodes dependencies to latest beta versions * Refactor md-codelist component to remove console.log statement * chore: Update mdjson-schemas and mdcodes dependencies to latest beta versions * Revert changes * chore: Bump version to 1.5.0-beta.13 in package.json * chore: Update mdcodes and mdjson-schemas dependencies to latest stable versions * chore: Update mdcodes and mdjson-schemas dependencies to latest beta versions * chore: Bump version to 1.5.0-beta.15 in package.json * chore: Bump version to 1.6.0-beta.0 in package.json * feat: Add Simple HTML option to the translator dropdown * chore: Bump version to 1.5.0-beta.16 in package.json * chore: Update mdcodes and mdjson-schemas dependencies to latest beta versions * Updates Fix Lineage Source Citation Identitfier - set simpleIdentifier to true Add identification reference to taxonomy collection Remove modifications from system preview * Require standalone quality report reference * chore: Update versions mdJson-schemas to v2.9.3-beta.3 mdCodes to v2.9.4-beta.4 * Add "on " to Taxonomy System->Citation->Other Details * Fix typo * Fix Input Codelist not string * feat: Update md-datetime component to use single quotes consistently * Update md-datetime component to use single quotes consistently * Update md-datetime component to use single quotes consistently * Remove modifications from system preview template * chore: Bump version to 1.5.0-beta.19 in package.json * Remove modifications from system preview template * Update md-datetime component to use single quotes consistently * chore: Bump version to 1.5.0-beta.20 in package.json * Update md-datetime component to use ISO 8601 format consistently * chore: Bump version to 1.5.0-beta.25 in package.json * chore: Update npm dependencies to latest versions * Add precision control to date range * chore: Bump version to 1.5.0-beta.26 in package.json * feat: Add Altitude Min/Max and Units Inputs to Bounding Box * chore: Bump version to 1.5.0-beta.27 in package.json --- .prettierrc.js | 5 + .../components/control/md-itis/component.js | 132 ++++++----- .../components/input/md-codelist/component.js | 45 ++-- .../input/md-date-range/component.js | 138 ++++++++--- .../input/md-date-range/template.hbs | 79 ++++--- .../components/input/md-datetime/component.js | 38 +-- app/pods/components/md-translate/component.js | 223 ++++++++++-------- .../components/object/md-bbox/component.js | 40 ++-- .../components/object/md-bbox/template.hbs | 133 +++++++---- .../object/md-constraint/component.js | 2 +- .../object/md-constraint/template.hbs | 13 +- .../object/md-date-array/template.hbs | 12 +- .../components/object/md-date/component.js | 78 +++++- .../components/object/md-date/template.hbs | 49 +++- .../object/md-extent/spatial/component.js | 45 ++-- .../conformance-result/template.hbs | 3 +- .../descriptive-result/template.hbs | 2 +- .../quantitative-result/template.hbs | 3 +- .../object/md-quality-report/template.hbs | 7 +- .../components/object/md-source/template.hbs | 1 + .../md-standalone-quality-report/template.hbs | 9 +- .../collection/system/preview/template.hbs | 17 +- .../collection/system/template.hbs | 39 ++- .../md-taxonomy/collection/template.hbs | 88 ++++--- package.json | 7 +- yarn.lock | 21 +- 26 files changed, 767 insertions(+), 462 deletions(-) create mode 100644 .prettierrc.js diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 000000000..f1459024d --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,5 @@ +"use strict"; + +module.exports = { + singleQuote: true, +}; diff --git a/app/pods/components/control/md-itis/component.js b/app/pods/components/control/md-itis/component.js index ddeeb04d3..b3b8ddad3 100644 --- a/app/pods/components/control/md-itis/component.js +++ b/app/pods/components/control/md-itis/component.js @@ -1,30 +1,12 @@ import Component from '@ember/component'; -import { - inject as service -} from '@ember/service'; -import { - computed, - set, - get, - getWithDefault -} from '@ember/object'; -import { - or -} from '@ember/object/computed'; -import { - isArray, - A -} from '@ember/array'; -import { - later -} from '@ember/runloop'; -import { - assert -} from '@ember/debug'; +import { inject as service } from '@ember/service'; +import { computed, set, get, getWithDefault } from '@ember/object'; +import { or } from '@ember/object/computed'; +import { isArray, A } from '@ember/array'; +import { later } from '@ember/runloop'; +import { assert } from '@ember/debug'; import moment from 'moment'; -import { - formatCitation -} from '../../object/md-citation/component'; +import { formatCitation } from '../../object/md-citation/component'; export default Component.extend({ init() { @@ -61,19 +43,20 @@ export default Component.extend({ this.set('isLoading', true); this.set('searchResult', null); - itis.sendQuery(this.searchString, this.kingdom, this.limit).then(response => { - - if(!response) { - return; - } + itis + .sendQuery(this.searchString, this.kingdom, this.limit) + .then((response) => { + if (!response) { + return; + } - let docs = response.response.docs; - let data = docs.map(doc => itis.parseDoc(doc)); + let docs = response.response.docs; + let data = docs.map((doc) => itis.parseDoc(doc)); - this.set('searchResult', data); - this.set('total', response.response.numFound); - this.set('isLoading', false); - }); + this.set('searchResult', data); + this.set('total', response.response.numFound); + this.set('isLoading', false); + }); }, actions: { search() { @@ -82,58 +65,81 @@ export default Component.extend({ selectItem(item) { item.set('animate', true); item.set('selected', true); - later(this, function () { - this.searchResult.removeObject(item); - this.selected.pushObject(item); - }, 250); + later( + this, + function () { + this.searchResult.removeObject(item); + this.selected.pushObject(item); + }, + 250 + ); }, deselectItem(item) { item.set('selected', false); - later(this, function () { - this.selected.removeObject(item); - this.searchResult.pushObject(item); - }, 250); + later( + this, + function () { + this.selected.removeObject(item); + this.searchResult.pushObject(item); + }, + 250 + ); }, importTaxa(taxa) { let taxonomy = this.taxonomy; let itisCitation = this.get('itis.citation'); - let classification = set(taxonomy, 'taxonomicClassification', getWithDefault(taxonomy, - 'taxonomicClassification', [])); - let systems= set(taxonomy, 'taxonomicSystem', getWithDefault(taxonomy, - 'taxonomicSystem', [{citation:{}}])); - let system = systems.findBy('citation.title', get(itisCitation,'title')); - - let allTaxa = taxa.reduce((acc, itm) => acc.pushObjects(itm.taxonomy), []); + let classification = set( + taxonomy, + 'taxonomicClassification', + getWithDefault(taxonomy, 'taxonomicClassification', []) + ); + let systems = set( + taxonomy, + 'taxonomicSystem', + getWithDefault(taxonomy, 'taxonomicSystem', [{ citation: {} }]) + ); + let system = systems.findBy('citation.title', get(itisCitation, 'title')); + + let allTaxa = taxa.reduce( + (acc, itm) => acc.pushObjects(itm.taxonomy), + [] + ); let today = moment().format('YYYY-MM-DD'); let dateObj = { date: today, dateType: 'transmitted', - description: 'Taxa imported from ITIS' + description: 'Taxa imported from ITIS', }; + itisCitation.otherCitationDetails = [ + `Retrieved from the Integrated Taxonomic Information System on-line database, https://www.itis.gov on ${today}.`, + ]; - allTaxa.forEach(itm => this.itis.mergeTaxa(itm, classification)); + allTaxa.forEach((itm) => this.itis.mergeTaxa(itm, classification)); - if(!system) { + if (!system) { itisCitation.get('date').pushObject(dateObj); systems.pushObject({ - citation: itisCitation + citation: itisCitation, }); } else { - let citation = set(system, 'citation', getWithDefault(system,'citation', {})); + let citation = set( + system, + 'citation', + getWithDefault(system, 'citation', {}) + ); formatCitation(citation); let date = A(get(citation, 'date')); - if(!date.findBy('date', today)) { + if (!date.findBy('date', today)) { date.pushObject(dateObj); } } - this.flashMessages - .success( - `Successfully imported ${ allTaxa.length } taxa from ITIS.` - ); - } - } + this.flashMessages.success( + `Successfully imported ${allTaxa.length} taxa from ITIS.` + ); + }, + }, }); diff --git a/app/pods/components/input/md-codelist/component.js b/app/pods/components/input/md-codelist/component.js index d3b9ff717..a8f5e82ba 100644 --- a/app/pods/components/input/md-codelist/component.js +++ b/app/pods/components/input/md-codelist/component.js @@ -40,13 +40,15 @@ export default Select.extend({ this._super(...arguments); //define cp using a dynamic dependent property - defineProperty(this, 'mdCodelist', + defineProperty( + this, + 'mdCodelist', computed(`mdCodes.${this.mdCodeName}.codelist.[]`, function () { - return this.mdCodes - .get(this.mdCodeName) - .codelist - //.uniqBy(codeName) - .sortBy(this.namePath); + const codelist = this.mdCodes.get(this.mdCodeName).codelist; + if (this.disableSort) { + return codelist; + } + return codelist.sortBy(this.namePath); }) ); }, @@ -118,7 +120,7 @@ export default Select.extend({ * @type String * @default 'Select one option' */ - placeholder: "Select one option", + placeholder: 'Select one option', /** * Form label for select list @@ -141,10 +143,9 @@ export default Select.extend({ selectedItem: computed('value', function () { let value = this.value; - return this.codelist - .find((item) => { - return item['codeId'] === value; - }); + return this.codelist.find((item) => { + return item['codeId'] === value; + }); }), // mdCodelist: computed('mdCodeName', function() { @@ -176,11 +177,12 @@ export default Select.extend({ this.mdCodelist.forEach((item) => { let newObject = { codeId: item[codeId], - codeName: this.mdCodes.get( - `codeOverrides.${this.mdCodeName}.${item[codeName]}`) || - item[codeName], + codeName: + this.mdCodes.get( + `codeOverrides.${this.mdCodeName}.${item[codeName]}` + ) || item[codeName], tooltip: item[tooltip], - icon: icons.get(item[codeName]) || icons.get(defaultIcon) + icon: icons.get(item[codeName]) || icons.get(defaultIcon), }; codelist.pushObject(newObject); }); @@ -203,10 +205,10 @@ export default Select.extend({ let create = this.create; let filter = this.filterId; - if(value) { - if(create) { + if (value) { + if (create) { let found = codelist.findBy('codeId', value); - if(found === undefined) { + if (found === undefined) { let newObject = this.createCode(value); codelist.pushObject(newObject); } @@ -227,7 +229,7 @@ export default Select.extend({ return { codeId: code, codeName: code, - description: 'Undefined' + description: 'Undefined', }; }, @@ -259,7 +261,6 @@ export default Select.extend({ let code = this.createCode(selected); this.setValue(code); - } - } - + }, + }, }); diff --git a/app/pods/components/input/md-date-range/component.js b/app/pods/components/input/md-date-range/component.js index c1d193928..cf6391256 100644 --- a/app/pods/components/input/md-date-range/component.js +++ b/app/pods/components/input/md-date-range/component.js @@ -7,36 +7,120 @@ import { notEmpty, alias } from '@ember/object/computed'; import Component from '@ember/component'; import { set, get, computed } from '@ember/object'; +import { observer } from '@ember/object'; import { once } from '@ember/runloop'; -//import moment from 'moment'; +import dayjs from 'dayjs'; -import { - validator, - buildValidations -} from 'ember-cp-validations'; +import { validator, buildValidations } from 'ember-cp-validations'; const Validations = buildValidations({ - 'start': [ + start: [ validator('presence', { presence: true, disabled: notEmpty('model.end'), - ignoreBlank: true - }) + ignoreBlank: true, + }), ], - 'end': [ + end: [ validator('date', { onOrAfter: alias('model.start'), - isWarning: true + isWarning: true, }), validator('presence', { presence: true, disabled: notEmpty('model.start'), - ignoreBlank: true - }) - ] + ignoreBlank: true, + }), + ], }); export default Component.extend(Validations, { + init() { + this._super(...arguments); + + this.set('precisionOptions', [ + { value: 'Year', name: 'Year' }, + { value: 'Month', name: 'Month' }, + { value: 'Day', name: 'Day' }, + { value: 'Time', name: 'Time' }, + ]); + + this.setPrecisionBasedOnDate(); + }, + + selectedPrecision: null, + selectedFormat: 'YYYY-MM-DDTHH:mm:ssZ', + + selectedPrecisionChanged: observer('selectedPrecision', function () { + const startDate = this.start; + const endDate = this.end; + if (!startDate || !endDate) return; + + const parsedStartDate = dayjs(startDate); + const parsedEndDate = dayjs(endDate); + let newStartDate, newEndDate; + + switch (this.selectedPrecision) { + case 'Time': + newStartDate = parsedStartDate.format('YYYY-MM-DD HH:mm:ss'); + newEndDate = parsedEndDate.format('YYYY-MM-DD HH:mm:ss'); + this.set('selectedFormat', 'YYYY-MM-DDTHH:mm:ssZ'); + break; + case 'Day': + newStartDate = parsedStartDate.format('YYYY-MM-DD'); + newEndDate = parsedEndDate.format('YYYY-MM-DD'); + this.set('selectedFormat', 'YYYY-MM-DD'); + break; + case 'Month': + newStartDate = parsedStartDate.format('YYYY-MM'); + newEndDate = parsedEndDate.format('YYYY-MM'); + this.set('selectedFormat', 'YYYY-MM'); + break; + case 'Year': + newStartDate = parsedStartDate.format('YYYY'); + newEndDate = parsedEndDate.format('YYYY'); + this.set('selectedFormat', 'YYYY'); + break; + default: + newStartDate = parsedStartDate.format('YYYY-MM-DD HH:mm:ss'); + newEndDate = parsedEndDate.format('YYYY-MM-DD HH:mm:ss'); + this.set('selectedFormat', 'YYYY-MM-DDTHH:mm:ssZ'); + break; + } + + if (newStartDate !== startDate) { + this.set('start', newStartDate); + } + if (newEndDate !== endDate) { + this.set('end', newEndDate); + } + }), + + setPrecisionBasedOnDate() { + const date = this.start; + if (!date) { + this.set('selectedPrecision', 'Year'); + this.set('selectedFormat', 'YYYY'); + return; + } + if (/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(date)) { + this.set('selectedPrecision', 'Time'); + this.set('selectedFormat', 'YYYY-MM-DDTHH:mm:ssZ'); + } else if (/\d{4}-\d{2}-\d{2}/.test(date)) { + this.set('selectedPrecision', 'Day'); + this.set('selectedFormat', 'YYYY-MM-DD'); + } else if (/\d{4}-\d{2}/.test(date)) { + this.set('selectedPrecision', 'Month'); + this.set('selectedFormat', 'YYYY-MM'); + } else if (/\d{4}/.test(date)) { + this.set('selectedPrecision', 'Year'); + this.set('selectedFormat', 'YYYY'); + } else { + this.set('selectedPrecision', 'Time'); + this.set('selectedFormat', 'YYYY-MM-DDTHH:mm:ssZ'); + } + }, + /** * Date range with start date and end date fields. * @@ -71,39 +155,37 @@ export default Component.extend(Validations, { * @default moment().hour(0).second(0).minute(0) * @required */ - //startDateTime: moment().hour(0).second(0).minute(0), - - /** - * The value for the end datetime - * - * @property endDateTime - * @type {String|Date|moment} - * @default moment().hour(0).second(0).minute(0) - * @required - */ - // endDateTime: moment().hour(0).second(0).minute(0) start: computed('startDateTime', { get() { let dt = this.startDateTime; return dt === undefined ? null : dt; }, set(key, value) { - once(this, function() { + once(this, function () { set(this, 'startDateTime', value); return value; }); - } + }, }), + + /** + * The value for the end datetime + * + * @property endDateTime + * @type {String|Date|moment} + * @default moment().hour(0).second(0).minute(0) + * @required + */ end: computed('endDateTime', { get() { let dt = this.endDateTime; return dt === undefined ? null : dt; }, set(key, value) { - once(this, function() { + once(this, function () { set(this, 'endDateTime', value); return value; }); - } + }, }), }); diff --git a/app/pods/components/input/md-date-range/template.hbs b/app/pods/components/input/md-date-range/template.hbs index a1ee989bc..5ee7ff849 100644 --- a/app/pods/components/input/md-date-range/template.hbs +++ b/app/pods/components/input/md-date-range/template.hbs @@ -1,32 +1,47 @@ - -{{input/md-datetime - class="start" - valuePath="start" - model=this - showValidations=true - forceDateOutput=true - label="Start Date" - showClear=true - format="YYYY-MM-DD HH:mm:ss" - placeholder="Enter start dateTime" - profilePath=(concat profilePath ".start") -}} -{{input/md-datetime - class="end" - valuePath="end" - model=this - showValidations=true - forceDateOutput=true - showClear=true - label="End Date" - format="YYYY-MM-DD HH:mm:ss" - placeholder="Enter end dateTime" - profilePath=(concat profilePath ".end") -}} -{{control/md-fiscalyear - start="start" - end="end" - context=this - profilePath=(concat profilePath ".fiscalyear") -}} -{{yield}} + +
+
+ {{input/md-select + showValidations=true + valuePath='value' + namePath='name' + label='Precision' + model=this + path='selectedPrecision' + objectArray=precisionOptions + searchEnabled=false + placeholder='Date Precision' + }} +
+ {{input/md-datetime + class='start' + valuePath='start' + model=this + showValidations=true + forceDateOutput=true + label='Start Date' + showClear=true + format=selectedFormat + placeholder='Enter start dateTime' + profilePath=(concat profilePath '.start') + }} + {{input/md-datetime + class='end' + valuePath='end' + model=this + showValidations=true + forceDateOutput=true + showClear=true + label='End Date' + format=selectedFormat + placeholder='Enter end dateTime' + profilePath=(concat profilePath '.end') + }} + {{control/md-fiscalyear + start='start' + end='end' + context=this + profilePath=(concat profilePath '.fiscalyear') + }} +
+{{yield}} \ No newline at end of file diff --git a/app/pods/components/input/md-datetime/component.js b/app/pods/components/input/md-datetime/component.js index 59e63f0ab..3a3f6ed88 100644 --- a/app/pods/components/input/md-datetime/component.js +++ b/app/pods/components/input/md-datetime/component.js @@ -9,6 +9,7 @@ import { get, set, computed, defineProperty } from '@ember/object'; import { once } from '@ember/runloop'; import { assert, debug } from '@ember/debug'; import moment from 'moment'; +import dayjs from 'dayjs'; export default Component.extend({ /** @@ -50,8 +51,6 @@ export default Component.extend({ }, }) ); - - // ... (other property definitions related to model and validation) } else { defineProperty( this, @@ -73,7 +72,7 @@ export default Component.extend({ classNameBindings: ['label:form-group', 'required'], date: null, - format: 'YYYY-MM-DD HH:mm:ss', // Change the format to include time + format: 'YYYY-MM-DDTHH:mm:ssZ', placeholder: 'Enter date and time', label: null, useCurrent: 'day', @@ -82,29 +81,30 @@ export default Component.extend({ formatValue(value, target) { if (isBlank(value)) { - once(this, function () { - set(this, target, null); - }); + once(this, 'setTargetToNull', target); return value; } - let mom = moment(value); - - if (this.altFormat) { - let alt = mom.format(this.altFormat); - once(this, function () { - set(this, target, alt); - }); - return alt; + let formattedDate; + if (this.precision === 'Time') { + formattedDate = dayjs(value).format('YYYY-MM-DDTHH:mm:ss[Z]'); + } else { + formattedDate = dayjs(value).format(this.format); } - if (mom && mom.toISOString() !== this.get(target)) { - once(this, function () { - set(this, target, mom.toISOString()); - }); + if (formattedDate !== this.get(target)) { + once(this, 'updateFormattedDate', formattedDate, target); } - return mom; + return formattedDate; + }, + + setTargetToNull(target) { + set(this, target, null); + }, + + updateFormattedDate(formattedDate, target) { + set(this, target, formattedDate); }, calendarIcons: computed(function () { diff --git a/app/pods/components/md-translate/component.js b/app/pods/components/md-translate/component.js index c5fd289ad..89f8b54ca 100644 --- a/app/pods/components/md-translate/component.js +++ b/app/pods/components/md-translate/component.js @@ -1,30 +1,16 @@ -import { - alias, - equal, - or -} from '@ember/object/computed'; +import { alias, equal, or } from '@ember/object/computed'; import Component from '@ember/component'; -import { - computed, - get, - set -} from '@ember/object'; -import { - inject as service -} from '@ember/service'; -import { - Promise -} from 'rsvp'; +import { computed, get, set } from '@ember/object'; +import { inject as service } from '@ember/service'; +import { Promise } from 'rsvp'; import moment from 'moment'; -import { - defaultValues -} from 'mdeditor/models/setting'; +import { defaultValues } from 'mdeditor/models/setting'; const errorLevels = { - 'OK': 0, - 'NOTICE': 1, - 'WARNING': 2, - 'ERROR': 3 + OK: 0, + NOTICE: 1, + WARNING: 2, + ERROR: 3, }; const errorClasses = ['success', 'info', 'warning', 'danger']; @@ -59,37 +45,50 @@ export default Component.extend({ writer: null, writerOptions: computed(function () { - return [{ - name: 'FGDC CSDGM', - value: 'fgdc', - type: 'application/xml', - tip: 'Federal Geographic Data Committee Content Standard for Digital Geospatial Metadata' - }, { - name: 'HTML', - value: 'html', - type: 'text/html', - tip: 'HTML "human-readable" and printable report of the metadata content' - }, { - name: 'ISO 19115-3', - value: 'iso19115_3', - type: 'application/xml', - tip: 'International Standards Organization Geographic Information - Metadata 19115-1:2014' - }, { - name: 'ISO 19115-2/19139 (deprecated)', - value: 'iso19115_2', - type: 'application/xml', - tip: 'International Standards Organization Geographic Information - Metadata 19115-2:2009' - }, { - name: 'ISO 19110', - value: 'iso19110', - type: 'application/xml', - tip: 'International Standards Organization Geographic Information - Feature Catalogue 19110:2005' - }, { - name: 'sbJSON', - value: 'sbJson', - type: 'application/json', - tip: 'USGS ScienceBase metadata format' - }]; + return [ + { + name: 'FGDC CSDGM', + value: 'fgdc', + type: 'application/xml', + tip: 'Federal Geographic Data Committee Content Standard for Digital Geospatial Metadata', + }, + { + name: 'HTML', + value: 'html', + type: 'text/html', + tip: 'HTML "human-readable" and printable report of the metadata content', + }, + { + name: 'ISO 19115-3', + value: 'iso19115_3', + type: 'application/xml', + tip: 'International Standards Organization Geographic Information - Metadata 19115-1:2014', + }, + { + name: 'ISO 19115-2/19139 (deprecated)', + value: 'iso19115_2', + type: 'application/xml', + tip: 'International Standards Organization Geographic Information - Metadata 19115-2:2009', + }, + { + name: 'ISO 19110', + value: 'iso19110', + type: 'application/xml', + tip: 'International Standards Organization Geographic Information - Feature Catalogue 19110:2005', + }, + { + name: 'sbJSON', + value: 'sbJson', + type: 'application/json', + tip: 'USGS ScienceBase metadata format', + }, + { + name: 'Simple HTML (MS Word compatible)', + value: 'simple_html', + type: 'text/html', + tip: 'HTML "human-readable" and printable report of the metadata content', + }, + ]; }), result: null, @@ -112,15 +111,14 @@ export default Component.extend({ errorSubTitle: computed('subTitle', function () { let err = this.errors; - if(err.length) { + if (err.length) { return this.errorTitle + ' ocurred during translation.'; } return null; }), writeObj: computed('writer', function () { - return this.writerOptions - .findBy('value', this.writer); + return this.writerOptions.findBy('value', this.writer); }), writerType: computed('writeObj', function () { @@ -134,8 +132,9 @@ export default Component.extend({ apiURL: or('settings.data.mdTranslatorAPI', 'defaultAPI'), isHtml: computed('writerType', function () { //IE does not supoprt srcdoc, so default to non-html display - return this.writerType === 'html' && 'srcdoc' in document.createElement( - 'iframe'); + return ( + this.writerType === 'html' && 'srcdoc' in document.createElement('iframe') + ); }), messages: alias('errors'), @@ -156,7 +155,8 @@ export default Component.extend({ this._clearResult(); set(this, 'isLoading', true); - this.ajax.request(url, { + this.ajax + .request(url, { type: 'POST', data: { //file: JSON.stringify(cleaner.clean(json)), @@ -166,41 +166,52 @@ export default Component.extend({ showAllTags: this.showAllTags, forceValid: this.forceValid, validate: 'normal', - format: 'json' + format: 'json', }, - context: this + context: this, }) - .then(function (response) { - set(cmp, 'isLoading', false); - - let level = Math.max(...[response.readerExecutionStatus, - response.readerStructureStatus, - response.readerValidationStatus, response.writerStatus - ].map(itm => errorLevels[itm])); - - set(cmp, 'errorLevel', level); - set(cmp, 'errors', response.readerExecutionMessages.concat( - response.readerStructureMessages, - response.readerValidationMessages.length ? response.readerValidationMessages[ - 0] : response.readerValidationMessages, - response.writerMessages).map(itm => itm.split(':'))); - set(cmp, 'result', response.writerOutput); - if(!response.success) { - get(cmp, 'flashMessages') - .danger('Translation error!'); - } - }, (response) => { - let error = - `mdTranslator Server error: - ${response.status}: ${response.statusText}`; + .then( + function (response) { + set(cmp, 'isLoading', false); - set(cmp, 'errorLevel', 3); - set(cmp, 'isLoading', false); - set(cmp, 'xhrError', error); - get(cmp, 'flashMessages') - .danger(error); - }); + let level = Math.max( + ...[ + response.readerExecutionStatus, + response.readerStructureStatus, + response.readerValidationStatus, + response.writerStatus, + ].map((itm) => errorLevels[itm]) + ); + set(cmp, 'errorLevel', level); + set( + cmp, + 'errors', + response.readerExecutionMessages + .concat( + response.readerStructureMessages, + response.readerValidationMessages.length + ? response.readerValidationMessages[0] + : response.readerValidationMessages, + response.writerMessages + ) + .map((itm) => itm.split(':')) + ); + set(cmp, 'result', response.writerOutput); + if (!response.success) { + get(cmp, 'flashMessages').danger('Translation error!'); + } + }, + (response) => { + let error = `mdTranslator Server error: + ${response.status}: ${response.statusText}`; + + set(cmp, 'errorLevel', 3); + set(cmp, 'isLoading', false); + set(cmp, 'xhrError', error); + get(cmp, 'flashMessages').danger(error); + } + ); }, saveResult() { let title = get(this, 'model.title'); @@ -209,7 +220,7 @@ export default Component.extend({ window.saveAs( new Blob([result], { - type: `${writer.type};charset=utf-8` + type: `${writer.type};charset=utf-8`, }), `${title}_${moment().format('YYYYMMDD')}.${this.writerType}` ); @@ -221,27 +232,31 @@ export default Component.extend({ let promise = new Promise((resolve, reject) => { let parsed = JSON.parse(this.result); - if(parsed) { + if (parsed) { resolve(parsed); } else { reject('JSON not valid'); } }); - promise.then((obj) => { - set(this, 'result', JSON.stringify(obj, null, 2)); - }).catch((error) => { - //console.log(error); - this.flashMessages.danger(error.message); - }); + promise + .then((obj) => { + set(this, 'result', JSON.stringify(obj, null, 2)); + }) + .catch((error) => { + //console.log(error); + this.flashMessages.danger(error.message); + }); }, errorClass(level) { return errorClasses[errorLevels[level]] || 'primary'; }, formatMessage(message) { - return message ? message.trim().replace(/^([A-Z]{2,})/g, match => - match.toLowerCase()) : - 'context not provided'; - } - } + return message + ? message + .trim() + .replace(/^([A-Z]{2,})/g, (match) => match.toLowerCase()) + : 'context not provided'; + }, + }, }); diff --git a/app/pods/components/object/md-bbox/component.js b/app/pods/components/object/md-bbox/component.js index 8863c299e..e0a0defe6 100644 --- a/app/pods/components/object/md-bbox/component.js +++ b/app/pods/components/object/md-bbox/component.js @@ -1,45 +1,42 @@ import Component from '@ember/component'; import { readOnly, alias } from '@ember/object/computed'; -import { - validator, - buildValidations -} from 'ember-cp-validations'; +import { validator, buildValidations } from 'ember-cp-validations'; const Validations = buildValidations({ - 'north': [ + north: [ validator('number', { allowNone: false, gte: -90, - lte: 90 - }) + lte: 90, + }), ], - 'south': [ + south: [ validator('number', { allowNone: false, gte: -90, - lte: 90 + lte: 90, }), validator('number', { - lte: readOnly('model.north') - }) + lte: readOnly('model.north'), + }), ], - 'east': [ + east: [ validator('number', { allowNone: false, gte: -180, - lte: 180 - }) + lte: 180, + }), ], - 'west': [ + west: [ validator('number', { allowNone: false, gte: -180, - lte: 180 + lte: 180, }), validator('number', { - lte: readOnly('model.east') - }) - ] + lte: readOnly('model.east'), + }), + ], }); export default Component.extend(Validations, { @@ -48,7 +45,10 @@ export default Component.extend(Validations, { north: alias('model.northLatitude'), south: alias('model.southLatitude'), east: alias('model.eastLongitude'), - west: alias('model.westLongitude') + west: alias('model.westLongitude'), + minimumAltitude: alias('model.minimumAltitude'), + maximumAltitude: alias('model.maximumAltitude'), + unitsOfAltitude: alias('model.unitsOfAltitude'), // btnText: computed('isTruelyValid', function() { // let text = this.get('validations.isTruelyValid') ? '' diff --git a/app/pods/components/object/md-bbox/template.hbs b/app/pods/components/object/md-bbox/template.hbs index dc6ff7036..2178f73ec 100644 --- a/app/pods/components/object/md-bbox/template.hbs +++ b/app/pods/components/object/md-bbox/template.hbs @@ -5,54 +5,93 @@ data-spy=false shadow=false }} -
-
- {{input/md-input - type="number" - step="0.0001" - model=this - valuePath="north" - label="North" - placeholder="Enter north latitude." - profilePath=(concat profilePath ".north") - showValidations=true - }} - {{input/md-input - type="number" - step="0.0001" - model=this - valuePath="east" - label="East" - placeholder="Enter east longitude." - profilePath=(concat profilePath ".east") - showValidations=true - }} -
-
+
+
+ {{input/md-input + type='number' + step='0.0001' + model=this + valuePath='north' + label='North' + placeholder='Enter north latitude.' + profilePath=(concat profilePath '.north') + showValidations=true + }} + {{input/md-input + type='number' + step='0.0001' + model=this + valuePath='east' + label='East' + placeholder='Enter east longitude.' + profilePath=(concat profilePath '.east') + showValidations=true + }} +
+
- {{input/md-input - type="number" - step="0.0001" - model=this - valuePath="south" - label="South" - placeholder="Enter south latitude." - profilePath=(concat profilePath ".south") - showValidations=true - }} - {{input/md-input - type="number" - step="0.0001" - model=this - valuePath="west" - label="West" - placeholder="Enter west longitude." - profilePath=(concat profilePath ".west") - showValidations=true - }} + {{input/md-input + type='number' + step='0.0001' + model=this + valuePath='south' + label='South' + placeholder='Enter south latitude.' + profilePath=(concat profilePath '.south') + showValidations=true + }} + {{input/md-input + type='number' + step='0.0001' + model=this + valuePath='west' + label='West' + placeholder='Enter west longitude.' + profilePath=(concat profilePath '.west') + showValidations=true + }} +
+
+
+
+ {{input/md-input + type='number' + step='0.01' + model=this + valuePath='minimumAltitude' + label='Minimum Altitude' + placeholder='Enter minimum' + profilePath=(concat profilePath '.geographicExtent.minimumAltitude') + showValidations=true + }} +
+
+ {{input/md-input + type='number' + step='0.01' + model=this + valuePath='maximumAltitude' + label='Maximum Altitude' + placeholder='Enter maximum' + profilePath=(concat profilePath '.geographicExtent.maximumAltitude') + showValidations=true + }} +
+
+
+
+ {{input/md-input + type='text' + model=this + valuePath='unitsOfAltitude' + label='Units of Altitude' + placeholder='Enter units' + profilePath=(concat profilePath '.geographicExtent.unitsOfAltitude') + showValidations=true + }} +
-
-{{yield}} + {{yield}} -{{/layout/md-card}} +{{/layout/md-card}} \ No newline at end of file diff --git a/app/pods/components/object/md-constraint/component.js b/app/pods/components/object/md-constraint/component.js index 30e9041e2..206a49de5 100644 --- a/app/pods/components/object/md-constraint/component.js +++ b/app/pods/components/object/md-constraint/component.js @@ -51,7 +51,7 @@ export default Component.extend(Validations, { getWithDefault(model, 'releasability', { addressee: [], statement: '', - dissemiantionConstraint: [], + disseminationConstraint: [], }) ); }); diff --git a/app/pods/components/object/md-constraint/template.hbs b/app/pods/components/object/md-constraint/template.hbs index d3fea8405..7d757e269 100644 --- a/app/pods/components/object/md-constraint/template.hbs +++ b/app/pods/components/object/md-constraint/template.hbs @@ -146,12 +146,19 @@ title='Dissemintation Constraint' plain=true value=model.releasability.disseminationConstraint + profilePath=(concat profilePath '.releasability.disseminationConstraint') as |const| }} - {{input/md-input - value=const.item.value - placeholder='Additional titles for the resource.' + {{input/md-codelist + model=const.item + create=false + mdCodeName='restriction' + profilePath=(concat + profilePath '.releasability.disseminationConstraint' + ) + placeholder='Restrictions on the release of the resource.' + path='value' }} {{/object/md-simple-array-table}} diff --git a/app/pods/components/object/md-date-array/template.hbs b/app/pods/components/object/md-date-array/template.hbs index 32dfbb5b1..d7e5ef464 100644 --- a/app/pods/components/object/md-date-array/template.hbs +++ b/app/pods/components/object/md-date-array/template.hbs @@ -1,5 +1,5 @@ {{#object/md-array-table - columns="Date,Date Type,Description" + columns="Precision,Date,Date Type,Description" required=required title="Date" value=value @@ -7,8 +7,12 @@ validation=validation profilePath=profilePath data-spy=data-spy - templateClass=templateClass as |date| + templateClass=templateClass + as |date| }} - {{object/md-date model=date.item profilePath=(concat profilePath ".dateItem")}} + {{object/md-date + model=date.item + profilePath=(concat profilePath ".dateItem") + }} {{yield}} -{{/object/md-array-table}} +{{/object/md-array-table}} \ No newline at end of file diff --git a/app/pods/components/object/md-date/component.js b/app/pods/components/object/md-date/component.js index efb1b35db..473989719 100644 --- a/app/pods/components/object/md-date/component.js +++ b/app/pods/components/object/md-date/component.js @@ -1,32 +1,86 @@ import { alias } from '@ember/object/computed'; import Component from '@ember/component'; -import { - validator, - buildValidations -} from 'ember-cp-validations'; +import { validator, buildValidations } from 'ember-cp-validations'; +import { observer } from '@ember/object'; +import dayjs from 'dayjs'; const Validations = buildValidations({ date: validator('presence', { presence: true, - ignoreBlank: true + ignoreBlank: true, }), dateType: validator('presence', { presence: true, - ignoreBlank: true - }) + ignoreBlank: true, + }), }); export default Component.extend(Validations, { init() { this._super(...arguments); - // if(isNone(get(this, 'model'))) { - // set(this, 'model', {}); - // } + this.set('precisionOptions', [ + { value: 'Year', name: 'Year' }, + { value: 'Month', name: 'Month' }, + { value: 'Day', name: 'Day' }, + { value: 'Time', name: 'Time' }, + ]); + + this.setPrecisionBasedOnDate(); }, - tagName:'', + selectedPrecision: null, + + tagName: '', date: alias('model.date'), - dateType: alias('model.dateType') + dateType: alias('model.dateType'), + + selectedPrecisionChanged: observer('selectedPrecision', function () { + const date = this.get('model.date'); + if (!date) return; + + const parsedDate = dayjs(date); + let newDate; + switch (this.get('selectedPrecision')) { + case 'Time': + newDate = parsedDate.format('YYYY-MM-DD HH:mm:ss'); + break; + case 'Day': + newDate = parsedDate.format('YYYY-MM-DD'); + break; + case 'Month': + newDate = parsedDate.format('YYYY-MM'); + break; + case 'Year': + newDate = parsedDate.format('YYYY'); + break; + default: + newDate = parsedDate.format('YYYY-MM-DD HH:mm:ss'); + break; + } + + if (newDate !== date) { + this.set('model.date', newDate); + } + }), + + setPrecisionBasedOnDate() { + const date = this.get('model.date'); + if (!date) { + this.set('selectedPrecision', 'Year'); + return; + } + if (/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(date)) { + this.set('selectedPrecision', 'Time'); + } else if (/\d{4}-\d{2}-\d{2}/.test(date)) { + this.set('selectedPrecision', 'Day'); + } else if (/\d{4}-\d{2}/.test(date)) { + this.set('selectedPrecision', 'Month'); + } else if (/\d{4}/.test(date)) { + this.set('selectedPrecision', 'Year'); + } else { + this.set('selectedPrecision', 'Time'); + } + }, }); diff --git a/app/pods/components/object/md-date/template.hbs b/app/pods/components/object/md-date/template.hbs index 197aeac63..9e3ed9cb7 100644 --- a/app/pods/components/object/md-date/template.hbs +++ b/app/pods/components/object/md-date/template.hbs @@ -1,12 +1,59 @@ + {{input/md-select + showValidations=true + valuePath="value" + namePath="name" + model=this + path="selectedPrecision" + objectArray=precisionOptions + searchEnabled=false + placeholder="Date Precision" + }} + + + {{#if (eq selectedPrecision "Time")}} + {{input/md-datetime + valuePath="date" + model=this + showValidations=true + required=true + forceDateOutput=true + profilePath=(concat profilePath ".date") + }} + {{else if (eq selectedPrecision "Day")}} + {{input/md-datetime + valuePath="date" + model=this + showValidations=true + required=true + forceDateOutput=true + format="YYYY-MM-DD" + placeholder="Enter date" + profilePath=(concat profilePath ".date") + }} + {{else if (eq selectedPrecision "Month")}} + {{input/md-datetime + valuePath="date" + model=this + showValidations=true + required=true + forceDateOutput=true + format="YYYY-MM" + placeholder="Enter Year/Month" + profilePath=(concat profilePath ".date") + }} + {{else if (eq selectedPrecision "Year")}} {{input/md-datetime valuePath="date" model=this showValidations=true required=true forceDateOutput=true + format="YYYY" + placeholder="Enter Year" profilePath=(concat profilePath ".date") }} + {{/if}} {{input/md-codelist @@ -31,4 +78,4 @@ placeholder="Describe the date." }} -{{yield}} +{{yield}} \ No newline at end of file diff --git a/app/pods/components/object/md-extent/spatial/component.js b/app/pods/components/object/md-extent/spatial/component.js index 1c01b64e3..2b1e1a7b4 100644 --- a/app/pods/components/object/md-extent/spatial/component.js +++ b/app/pods/components/object/md-extent/spatial/component.js @@ -7,14 +7,12 @@ import { getWithDefault, setProperties, observer, - computed + computed, } from '@ember/object'; import { isNone } from '@ember/utils'; import { once } from '@ember/runloop'; -const { - isNaN: isNan -} = Number; +const { isNaN: isNan } = Number; export default Component.extend({ didReceiveAttrs() { @@ -31,17 +29,21 @@ export default Component.extend({ return isNone(val) || isNan(val); }, - bboxPoly: computed('bbox', + bboxPoly: computed( + 'bbox', 'bbox.{northLatitude,southLatitude,eastLongitude,westLongitude}', function () { let bbox = this.bbox; - if(!bbox) { + if (!bbox) { return null; } - if(this.isTrulyNone(bbox.southLatitude) || this.isTrulyNone(bbox.westLongitude) || - this.isTrulyNone(bbox.northLatitude) || this.isTrulyNone(bbox.eastLongitude) + if ( + this.isTrulyNone(bbox.southLatitude) || + this.isTrulyNone(bbox.westLongitude) || + this.isTrulyNone(bbox.northLatitude) || + this.isTrulyNone(bbox.eastLongitude) ) { return null; } @@ -50,17 +52,18 @@ export default Component.extend({ [bbox.southLatitude, bbox.westLongitude], [bbox.northLatitude, bbox.westLongitude], [bbox.northLatitude, bbox.eastLongitude], - [bbox.southLatitude, bbox.eastLongitude] + [bbox.southLatitude, bbox.eastLongitude], ]; - }), + } + ), bboxPolyObserver: observer('bboxPoly', function () { let map = this.map; let bbox = this.bboxPoly; - if(map && bbox) { + if (map && bbox) { this.setupMap({ - target: map + target: map, }); } }), @@ -78,8 +81,9 @@ export default Component.extend({ let bbox = this.bboxPoly; let features; - features = bbox ? geo.concat([L.rectangle(bbox).toGeoJSON()]) : [].concat( - geo); + features = bbox + ? geo.concat([L.rectangle(bbox).toGeoJSON()]) + : [].concat(geo); let bounds = L.geoJson(features).getBounds(); @@ -95,7 +99,7 @@ export default Component.extend({ calculateBox() { let geo = this.geographicElement; - if(!(geo && geo.length)) { + if (!(geo && geo.length)) { return null; } @@ -106,7 +110,7 @@ export default Component.extend({ northLatitude: bounds.getNorth(), southLatitude: bounds.getSouth(), eastLongitude: bounds.getEast(), - westLongitude: bounds.getWest() + westLongitude: bounds.getWest(), }); }, clearBox() { @@ -114,7 +118,10 @@ export default Component.extend({ northLatitude: null, southLatitude: null, eastLongitude: null, - westLongitude: null + westLongitude: null, + minimumAltitude: null, + maximumAltitude: null, + unitsOfAltitude: null, }); }, editFeatures(index) { @@ -123,6 +130,6 @@ export default Component.extend({ deleteFeatures() { this.deleteFeatures(); - } - } + }, + }, }); diff --git a/app/pods/components/object/md-quality-report/conformance-result/template.hbs b/app/pods/components/object/md-quality-report/conformance-result/template.hbs index f9f9e55db..379860c32 100644 --- a/app/pods/components/object/md-quality-report/conformance-result/template.hbs +++ b/app/pods/components/object/md-quality-report/conformance-result/template.hbs @@ -13,7 +13,8 @@ profilePath=(concat profilePath '.scopeCode') class=(if (v-get this 'isInvalid') 'required') }} -{{input/md-input value=name label='Name' placeholder='Enter name'}} + +{{input/md-input value=model.name label='Name' placeholder='Enter name'}}
{{input/md-datetime diff --git a/app/pods/components/object/md-quality-report/descriptive-result/template.hbs b/app/pods/components/object/md-quality-report/descriptive-result/template.hbs index ca4046a88..d4f3076b0 100644 --- a/app/pods/components/object/md-quality-report/descriptive-result/template.hbs +++ b/app/pods/components/object/md-quality-report/descriptive-result/template.hbs @@ -13,7 +13,7 @@ profilePath=(concat profilePath '.scopeCode') class=(if (v-get this 'isInvalid') 'required') }} -{{input/md-input value=name label='Name' placeholder='Enter name'}} +{{input/md-input value=model.name label='Name' placeholder='Enter name'}}
{{input/md-datetime diff --git a/app/pods/components/object/md-quality-report/quantitative-result/template.hbs b/app/pods/components/object/md-quality-report/quantitative-result/template.hbs index 8762ea29f..aae40f097 100644 --- a/app/pods/components/object/md-quality-report/quantitative-result/template.hbs +++ b/app/pods/components/object/md-quality-report/quantitative-result/template.hbs @@ -13,7 +13,8 @@ profilePath=(concat profilePath '.scopeCode') class=(if (v-get this 'isInvalid') 'required') }} -{{input/md-input value=name label='Name' placeholder='Enter name'}} + +{{input/md-input value=model.name label='Name' placeholder='Enter name'}}
{{input/md-datetime diff --git a/app/pods/components/object/md-quality-report/template.hbs b/app/pods/components/object/md-quality-report/template.hbs index 0e11d2109..66cb1f64b 100644 --- a/app/pods/components/object/md-quality-report/template.hbs +++ b/app/pods/components/object/md-quality-report/template.hbs @@ -2,6 +2,7 @@ value=model.type label='Report Type' required=true + disableSort=true create=true tooltip=true icon=false @@ -130,7 +131,7 @@ }} {{#if model.evaluationMethod.evaluationProcedure}} {{#layout/md-card - title='Evaluation Procedure' + title='Evaluation Procedure Reference' required=true collapsible=true collapsed=false @@ -146,13 +147,13 @@ {{else}}
-

No Evaluation Procedure Found +

No Evaluation Procedure Reference Found

diff --git a/app/pods/components/object/md-source/template.hbs b/app/pods/components/object/md-source/template.hbs index e9851bbcf..e226055bf 100644 --- a/app/pods/components/object/md-source/template.hbs +++ b/app/pods/components/object/md-source/template.hbs @@ -44,6 +44,7 @@ model=model.sourceCitation profilePath=(concat profilePath '.sourceCitation') data-spy=false + simpleIdentifier=true }} {{/layout/md-card}} diff --git a/app/pods/components/object/md-standalone-quality-report/template.hbs b/app/pods/components/object/md-standalone-quality-report/template.hbs index 15f81de94..6913b1d56 100644 --- a/app/pods/components/object/md-standalone-quality-report/template.hbs +++ b/app/pods/components/object/md-standalone-quality-report/template.hbs @@ -39,8 +39,13 @@ {{/layout/md-card}} {{else}}
-
-

No Report Reference Found +
+

No + Report Reference + found.