diff --git a/angular-legacy/shared/fieldClasses.ts b/angular-legacy/shared/fieldClasses.ts index baee2869f1..9016c4e245 100644 --- a/angular-legacy/shared/fieldClasses.ts +++ b/angular-legacy/shared/fieldClasses.ts @@ -19,6 +19,7 @@ import { HtmlRawComponent } from './form/field-simple.component'; import { RecordMetadataRetrieverField, RecordMetadataRetrieverComponent } from './form/record-meta.component'; +import { TimerField, TimerComponent } from './form/timer.component'; import { VocabField, VocabFieldComponent } from './form/field-vocab.component'; import { RepeatableContainer, RepeatableVocab, RepeatableContributor, RepeatableVocabComponent, RepeatableContributorComponent } from './form/field-repeatable.component'; import { ContributorField, ContributorComponent } from './form/field-contributor.component'; @@ -67,6 +68,7 @@ export const fieldClasses= { 'MapField': {'meta': MapField, 'comp': MapComponent, 'lookupService': 'vocabFieldLookupService'}, 'ParameterRetriever':{ 'meta': ParameterRetrieverField, 'comp': ParameterRetrieverComponent}, 'RecordMetadataRetriever':{ 'meta': RecordMetadataRetrieverField, 'comp': RecordMetadataRetrieverComponent}, + 'Timer':{ 'meta': TimerField, 'comp': TimerComponent}, 'RelatedObjectSelector':{ 'meta': RelatedObjectSelectorField, 'comp': RelatedObjectSelectorComponent}, 'RelatedFileUpload':{ 'meta': RelatedFileUploadField, 'comp': RelatedFileUploadComponent}, 'DataLocation':{ 'meta': DataLocationField, 'comp': DataLocationComponent}, diff --git a/angular-legacy/shared/form/field-contributor.component.ts b/angular-legacy/shared/form/field-contributor.component.ts index 15f58790fd..2da7dd73ab 100644 --- a/angular-legacy/shared/form/field-contributor.component.ts +++ b/angular-legacy/shared/form/field-contributor.component.ts @@ -98,6 +98,7 @@ export class ContributorField extends FieldBase implements CustomValidation this.roles = options['roles'] || []; this.value = options['value'] || this.setEmptyValue(); + this.activeValidators = options['activeValidators']; @@ -143,6 +144,7 @@ export class ContributorField extends FieldBase implements CustomValidation this.validators['family_name'] = [Validators.required]; this.validators['given_name'] = [Validators.required]; } + // Resolves: #605 // now that we've set the default validators... we read the config to override if (!_.isEmpty(this.activeValidators)) { @@ -158,6 +160,7 @@ export class ContributorField extends FieldBase implements CustomValidation } }); } + this.findRelationshipFor = options['findRelationshipFor'] || ''; this.findRelationship = options['findRelationship'] || null; this.relationshipFor = options['relationshipFor'] || ''; @@ -214,6 +217,8 @@ export class ContributorField extends FieldBase implements CustomValidation if (this.required) { this.enableValidators(); } else { + // disable the validators otherwise they'll get enabled on show/hide + this.validators = {}; // if splitting names, attach handler to individual input form control if (this.splitNames) { const reqFields = ['family_name', 'given_name']; @@ -270,7 +275,6 @@ export class ContributorField extends FieldBase implements CustomValidation } else { this.toggleConditionalValidation(!_.isEmpty(value.text_full_name)); } - } toggleConditionalValidation(hasValue) { @@ -486,6 +490,68 @@ export class ContributorField extends FieldBase implements CustomValidation }); } } + + public setVisibility(data, eventConf:any = {}) { + let newVisible = this.visible; + if (_.isArray(this.visibilityCriteria)) { + // save the value of this data in a map, so we can run complex conditional logic that depends on one or more fields + if (!_.isEmpty(eventConf) && !_.isEmpty(eventConf.srcName)) { + this.subscriptionData[eventConf.srcName] = data; + } + // only run the function set if we have all the data... + if (_.size(this.subscriptionData) == _.size(this.visibilityCriteria)) { + newVisible = true; + _.each(this.visibilityCriteria, (visibilityCriteria) => { + const dataEntry = this.subscriptionData[visibilityCriteria.fieldName]; + newVisible = newVisible && this.execVisibilityFn(dataEntry, visibilityCriteria); + }); + + } + } else + if (_.isObject(this.visibilityCriteria) && _.get(this.visibilityCriteria, 'type') == 'function') { + newVisible = this.execVisibilityFn(data, this.visibilityCriteria); + } else { + newVisible = _.isEqual(data, this.visibilityCriteria); + } + const that = this; + setTimeout(() => { + if (!newVisible) { + if (that.visible) { + // remove validators + if (that.formModel) { + if(that['disableValidators'] != null && typeof(that['disableValidators']) == 'function') { + that['disableValidators'](); + } else { + that.formModel.clearValidators(); + } + that.formModel.updateValueAndValidity(); + + } + } + } else { + if (!that.visible) { + // restore validators + if (that.formModel) { + if(that['enableValidators'] != null && typeof(that['enableValidators']) == 'function') { + that['enableValidators'](); + } else { + that.formModel.setValidators(that.validators); + } + setTimeout(() => { + that.setValue(that.formModel.value,false,true) + }); + that.formModel.updateValueAndValidity(); + } + } + } + that.visible = newVisible; + }); + if(eventConf.returnData == true) { + return data; + } + + } + } @Component({ diff --git a/angular-legacy/shared/form/field-map.component.ts b/angular-legacy/shared/form/field-map.component.ts index 47cbab2ed1..37e1da083d 100644 --- a/angular-legacy/shared/form/field-map.component.ts +++ b/angular-legacy/shared/form/field-map.component.ts @@ -22,11 +22,11 @@ import { FieldBase } from './field-base'; import { FormGroup, FormControl, Validators } from '@angular/forms'; import * as _ from "lodash"; import { RecordsService } from './records.service'; -import { Map, GeoJSON, } from 'leaflet'; +import { Map, GeoJSON, } from 'leaflet'; declare var omnivore: any; declare var L: any; declare var jQuery: any; -declare function require(name:string); +declare function require(name: string); /** * Map Model @@ -44,7 +44,7 @@ export class MapField extends FieldBase { layerGeoJSON: any = {}; map: Map; - importFailed:boolean = false; + importFailed: boolean = false; layers = []; drawnItems: any = new L.FeatureGroup(); googleMaps = L.tileLayer('http://{s}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}', { @@ -150,10 +150,10 @@ export class MapField extends FieldBase { this.layerGeoJSON = options.value; this.mainTabId = options['mainTabId'] || null; - this.coordinatesHelp = this.getTranslated(options.coordinatesHelp, undefined); + this.coordinatesHelp = this.getTranslated(options.coordinatesHelp, undefined); this.kmlGeoJsonLabel = this.getTranslated(options.kmlGeoJsonLabel, "Enter KML or GeoJSON"); - this.importButtonLabel = this.getTranslated(options.importButtonLabel, "Import"); - this.invalidDataMessage = this.getTranslated(options.invalidDataMessage, "Entered text is not valid KML or GeoJSON"); + this.importButtonLabel = this.getTranslated(options.importButtonLabel, "Import"); + this.invalidDataMessage = this.getTranslated(options.invalidDataMessage, "Entered text is not valid KML or GeoJSON"); } onMapReady(map: Map) { @@ -167,8 +167,15 @@ export class MapField extends FieldBase { if (this.tabId === null) { - map.invalidateSize(); - map.fitBounds(this.drawnItems.getBounds()); + if (this.visible) { + map.invalidateSize(); + try { + // if there are no layers present this will throw an error + map.fitBounds(this.drawnItems.getBounds()); + } catch (e) { + + } + } } else { if (this.editMode) { // Note: this assumes the tabId is unqiue in the page, which may not be when there are multiple tab layouts. @@ -193,18 +200,18 @@ export class MapField extends FieldBase { public initMap(map, that) { map.invalidateSize(); - try { - // if there are no layers present this will throw an error - map.fitBounds(this.drawnItems.getBounds()); - } catch (e) { + try { + // if there are no layers present this will throw an error + map.fitBounds(this.drawnItems.getBounds()); + } catch (e) { - } + } } registerMapEventHandlers(map: Map) { let that = this; - map.on(L.Draw.Event.CREATED, function(e: any) { + map.on(L.Draw.Event.CREATED, function (e: any) { var type = e.layerType, layer = e.layer; that.layers.push(layer); @@ -213,12 +220,12 @@ export class MapField extends FieldBase { return false; }); - map.on('draw:edited', function(e: any) { + map.on('draw:edited', function (e: any) { let layers = e.layers; let that2 = that; - layers.eachLayer(function(layer) { - let layerIndex = _.findIndex(that2.layers, function(o) { return o._leaflet_id == layer._leaflet_id; }); - if(layerIndex == -1) { + layers.eachLayer(function (layer) { + let layerIndex = _.findIndex(that2.layers, function (o) { return o._leaflet_id == layer._leaflet_id; }); + if (layerIndex == -1) { that2.layers.push(layer); } else { that2.layers[layerIndex] = layer; @@ -227,21 +234,21 @@ export class MapField extends FieldBase { }); }); - map.on('draw:editstop', function(e: any) { + map.on('draw:editstop', function (e: any) { that.layerGeoJSON = L.featureGroup(that.layers).toGeoJSON(); that.setValue(that.layerGeoJSON); }); - map.on('draw:deletestop', function(e: any) { + map.on('draw:deletestop', function (e: any) { that.layerGeoJSON = L.featureGroup(that.layers).toGeoJSON(); that.setValue(that.layerGeoJSON); }); - map.on('draw:deleted', function(e: any) { + map.on('draw:deleted', function (e: any) { let layers = e.layers; let that2 = that; - layers.eachLayer(function(layer) { - _.remove(that2.layers, function(o) { return o._leaflet_id == layer._leaflet_id; }); + layers.eachLayer(function (layer) { + _.remove(that2.layers, function (o) { return o._leaflet_id == layer._leaflet_id; }); }); }); } @@ -257,7 +264,15 @@ export class MapField extends FieldBase { that.layers.push(layer); }); } - + public setVisibility(data, eventConf: any = {}) { + let that = this; + super.setVisibility(data, eventConf); + setTimeout(function () { + if (that.visible) { + that.initMap(that.map, that); + } + }, 100) + } postInit(value: any) { if (!_.isEmpty(value)) { @@ -283,6 +298,9 @@ export class MapField extends FieldBase { this.formModel.patchValue(this.layerGeoJSON, { emitEvent: emitEvent, emitModelToViewChange: true }); this.formModel.markAsTouched(); this.formModel.markAsDirty(); + } else { + this.setEmptyValue(); + this.drawnItems.clearLayers(); } } @@ -292,7 +310,7 @@ export class MapField extends FieldBase { } reactEvent(eventName: string, eventData: any, origData: any) { - super.reactEvent(eventName, eventData,origData); + super.reactEvent(eventName, eventData, origData); if (!_.isEmpty(this.formModel.value)) { this.layerGeoJSON = this.formModel.value; this.drawLayers(); @@ -303,43 +321,43 @@ export class MapField extends FieldBase { } importData() { - if(this.importDataString.length > 0) { + if (this.importDataString.length > 0) { try { - if(this.importDataString.indexOf("<") == 0) { - //probably KML - let parsedLayers = omnivore.kml.parse(this.importDataString); - if(parsedLayers.getLayers().length == 0) { - this.importFailed = true; - return false; + if (this.importDataString.indexOf("<") == 0) { + //probably KML + let parsedLayers = omnivore.kml.parse(this.importDataString); + if (parsedLayers.getLayers().length == 0) { + this.importFailed = true; + return false; + } + let that = this; + parsedLayers.eachLayer(layer => { + layer.addTo(that.drawnItems); + that.layers.push(layer); + that.layerGeoJSON = L.featureGroup(that.layers).toGeoJSON(); + this.drawLayers(); + that.map.fitBounds(that.drawnItems.getBounds()); + }); + this.importDataString = ""; + this.importFailed = false; + } else { + let parsedLayers = L.geoJSON(JSON.parse(this.importDataString)); + let that = this; + parsedLayers.eachLayer(layer => { + layer.addTo(that.drawnItems); + that.layers.push(layer); + that.layerGeoJSON = L.featureGroup(that.layers).toGeoJSON(); + this.drawLayers(); + that.map.fitBounds(that.drawnItems.getBounds()); + }); + this.importDataString = ""; + this.importFailed = false; } - let that = this; - parsedLayers.eachLayer(layer => { - layer.addTo(that.drawnItems); - that.layers.push(layer); - that.layerGeoJSON = L.featureGroup(that.layers).toGeoJSON(); - this.drawLayers(); - that.map.fitBounds(that.drawnItems.getBounds()); - }); - this.importDataString = ""; - this.importFailed = false; - } else { - let parsedLayers = L.geoJSON(JSON.parse(this.importDataString)); - let that = this; - parsedLayers.eachLayer(layer => { - layer.addTo(that.drawnItems); - that.layers.push(layer); - that.layerGeoJSON = L.featureGroup(that.layers).toGeoJSON(); - this.drawLayers(); - that.map.fitBounds(that.drawnItems.getBounds()); - }); - this.importDataString = ""; - this.importFailed = false; + this.layerGeoJSON = L.featureGroup(this.layers).toGeoJSON(); + this.setValue(this.layerGeoJSON); + } catch (e) { + this.importFailed = true; } - this.layerGeoJSON = L.featureGroup(this.layers).toGeoJSON(); - this.setValue(this.layerGeoJSON); - } catch (e) { - this.importFailed = true; - } } diff --git a/angular-legacy/shared/form/field-map.html b/angular-legacy/shared/form/field-map.html index 684df5c582..66436e8c36 100644 --- a/angular-legacy/shared/form/field-map.html +++ b/angular-legacy/shared/form/field-map.html @@ -1,5 +1,5 @@ - -
+ +