-
+
settings_overscan
diff --git a/src/app/components/shared/cart-toggle/cart-toggle.component.html b/src/app/components/shared/cart-toggle/cart-toggle.component.html
index 46982a3cd..6c3667e07 100644
--- a/src/app/components/shared/cart-toggle/cart-toggle.component.html
+++ b/src/app/components/shared/cart-toggle/cart-toggle.component.html
@@ -1,4 +1,5 @@
add_shopping_cart
diff --git a/src/app/components/shared/copy-to-clipboard/copy-to-clipboard.component.html b/src/app/components/shared/copy-to-clipboard/copy-to-clipboard.component.html
index 735462e44..e4146c48b 100644
--- a/src/app/components/shared/copy-to-clipboard/copy-to-clipboard.component.html
+++ b/src/app/components/shared/copy-to-clipboard/copy-to-clipboard.component.html
@@ -1,7 +1,24 @@
+
+ 0"
+ (click)="$event.stopPropagation()"
+[matMenuTriggerFor]="promptMenu"
+class="clickable"
+matTooltipPosition="left"
+[icon]="copyIcon">
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/components/shared/copy-to-clipboard/copy-to-clipboard.component.ts b/src/app/components/shared/copy-to-clipboard/copy-to-clipboard.component.ts
index 2e568d6be..a050a8c71 100644
--- a/src/app/components/shared/copy-to-clipboard/copy-to-clipboard.component.ts
+++ b/src/app/components/shared/copy-to-clipboard/copy-to-clipboard.component.ts
@@ -4,9 +4,10 @@ import { SubSink } from 'subsink';
import { of } from 'rxjs';
import { tap, delay } from 'rxjs/operators';
-import { faCopy } from '@fortawesome/free-solid-svg-icons';
+import { IconDefinition } from '@fortawesome/free-solid-svg-icons';
import { ClipboardService } from 'ngx-clipboard';
import { NotificationService } from '@services/notification.service';
+import { CopyIcons } from '@models';
@Component({
selector: 'app-copy-to-clipboard',
@@ -15,13 +16,13 @@ import { NotificationService } from '@services/notification.service';
})
export class CopyToClipboardComponent implements OnDestroy {
@Input() value: string;
+ @Input({required: false}) submenu: [string, string][] = [];
@Input() prompt = 'Copy to clipboard';
@Input() notification = 'Copied';
@Input() toast = true;
-
+ @Input({required: false}) copyIcon: IconDefinition = CopyIcons.COPY;
@ViewChild('copyTooltip', { static: true }) copyTooltip: ElementRef;
- public copyIcon = faCopy;
private subs = new SubSink();
constructor(
@@ -47,6 +48,22 @@ export class CopyToClipboardComponent implements OnDestroy {
e.stopPropagation();
}
+ public onCopyFromMenu(prompt: string, value: string) {
+ this.clipboardService.copyFromContent(value);
+ if (this.toast) {
+ this.notificationService.linkCopyIcon(prompt, value.split(',').length);
+ }
+
+ this.subs.add(
+ of((' ' + prompt).slice(1)).pipe(
+ tap(() => prompt = this.notification),
+ delay(2200)
+ ).subscribe(
+ msg => prompt = msg
+ )
+ );
+ }
+
ngOnDestroy() {
this.subs.unsubscribe();
}
diff --git a/src/app/components/shared/copy-to-clipboard/copy-to-clipboard.module.ts b/src/app/components/shared/copy-to-clipboard/copy-to-clipboard.module.ts
index 61534d1e0..be1cda1bc 100644
--- a/src/app/components/shared/copy-to-clipboard/copy-to-clipboard.module.ts
+++ b/src/app/components/shared/copy-to-clipboard/copy-to-clipboard.module.ts
@@ -3,7 +3,7 @@ import { CommonModule } from '@angular/common';
import { CopyToClipboardComponent } from './copy-to-clipboard.component';
import { MatSharedModule } from '@shared';
-
+import { MatMenuModule } from '@angular/material/menu';
import { ClipboardModule } from 'ngx-clipboard';
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
@@ -14,6 +14,7 @@ import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
FontAwesomeModule,
ClipboardModule,
MatSharedModule,
+ MatMenuModule
],
exports: [CopyToClipboardComponent]
})
diff --git a/src/app/components/shared/scene-metadata/scene-metadata.component.html b/src/app/components/shared/scene-metadata/scene-metadata.component.html
index 4f0a62229..5d6ede0b6 100644
--- a/src/app/components/shared/scene-metadata/scene-metadata.component.html
+++ b/src/app/components/shared/scene-metadata/scene-metadata.component.html
@@ -70,9 +70,9 @@
- {{ 'PATH' | translate }} • {{ scene.metadata.path }}
+ {{ prop.isRelevant(p.USE_TRACK, dataset) ? ('TRACK' | translate) : ('PATH' | translate) }} • {{ scene.metadata.path }}
settings
@@ -82,13 +82,18 @@
+
+
+
+
+
- {{ 'FRAME' | translate }} • {{ scene.metadata.frame }}
+ {{ 'FRAME' | translate }} • {{ scene.metadata.frame }}
settings
@@ -115,8 +120,20 @@
+
+ {{ 'FRAME_COVERAGE' | translate }} • {{ scene.metadata.nisar.frameCoverage}}
+
+
+ settings
+
-
+
+
+
+
+
{{ 'POLARIZATION' | translate }} • {{ scene.metadata.polarization }}
{{ 'ADD_POLARIZATION_TO_SEARCH' | translate }}
+
+ {{ 'POLARIZATION_MAIN' | translate }} • {{ scene.metadata.nisar.mainBandPolarization }}
+
+
+ settings
+
+
+
+
+
+
+
+ {{ 'POLARIZATION_SIDE' | translate }} • {{ scene.metadata.nisar.sideBandPolarization }}
+
+
+ settings
+
+
+
+
+
+
+
+
+ {{ 'RANGE_BANDWIDTH' | translate }} • {{ scene.metadata.nisar.rangeBandwidth }}
+
+
+ settings
+
+
+
+
+
+
+
+
+ {{ 'JOINT_OBSERVATION_ONLY' | translate }} • {{ scene.metadata.nisar.jointObservation }}
+
+
diff --git a/src/app/components/shared/scene-metadata/scene-metadata.component.ts b/src/app/components/shared/scene-metadata/scene-metadata.component.ts
index c1f4ae8b9..d20b7feb0 100644
--- a/src/app/components/shared/scene-metadata/scene-metadata.component.ts
+++ b/src/app/components/shared/scene-metadata/scene-metadata.component.ts
@@ -89,17 +89,34 @@ export class SceneMetadataComponent implements OnInit, OnDestroy {
const action = new filtersStore.SetFlightDirections([capitalized]);
this.store$.dispatch(action);
}
+ public setFrameCoverage(): void {
+ const action = new filtersStore.setFrameCoverage([this.scene.metadata.nisar.frameCoverage]);
+ this.store$.dispatch(action);
+ }
public addPolarization(): void {
const action = new filtersStore.AddPolarization(this.scene.metadata.polarization);
this.store$.dispatch(action);
}
+ public addMainPolarization(): void {
+ const action = new filtersStore.AddPolarization(this.scene.metadata.nisar.mainBandPolarization);
+ this.store$.dispatch(action);
+ }
+ public addSidePolarization(): void {
+ const action = new filtersStore.AddSidePolarization(this.scene.metadata.nisar.sideBandPolarization);
+ this.store$.dispatch(action);
+ }
public addMission(): void {
const action = new filtersStore.SelectMission(this.scene.metadata.missionName);
this.store$.dispatch(action);
}
+ public addRangeBandwidth(): void {
+ const action = new filtersStore.addRangeBandwidth(this.scene.metadata.nisar.rangeBandwidth);
+ this.store$.dispatch(action);
+ }
+
public setTemporalStart(): void {
const action = new filtersStore.SetTemporalStart(
this.scene.metadata.temporal + this.offsets.temporal
diff --git a/src/app/components/shared/selectors/observation-panel-selector/index.ts b/src/app/components/shared/selectors/observation-panel-selector/index.ts
new file mode 100644
index 000000000..3edc7c43b
--- /dev/null
+++ b/src/app/components/shared/selectors/observation-panel-selector/index.ts
@@ -0,0 +1,2 @@
+export {ObservationPanelSelectorComponent} from './observation-panel-selector.component'
+export {ObservationPanelSelectorModule} from './observation-panel-selector.module'
\ No newline at end of file
diff --git a/src/app/components/shared/selectors/observation-panel-selector/observation-panel-selector.component.html b/src/app/components/shared/selectors/observation-panel-selector/observation-panel-selector.component.html
new file mode 100644
index 000000000..8787fef3a
--- /dev/null
+++ b/src/app/components/shared/selectors/observation-panel-selector/observation-panel-selector.component.html
@@ -0,0 +1,153 @@
+
+
+
+
+ {{pol}}
+ {{pol | polarizationCount}}
+
+
+
+ {{ polarizations?.length || 0 }}/{{ dataset.polarizations.length }}
+ {{ 'POLARIZATIONS_SELECTED' | translate }}
+
+
+ {{ 'NO_POLARIZATIONS_TO_SELECT' | translate }}
+
+
+
+
+
+
+
+ {{pol}}
+ {{pol | polarizationCount}}
+
+
+
+ {{ sidePolarizations?.length || 0 }}/{{ dataset.polarizations.length }}
+ {{ 'POLARIZATIONS_SELECTED' | translate }}
+
+
+ {{ 'NO_POLARIZATIONS_TO_SELECT' | translate }}
+
+
+
+
+
+
+
+ {{direction.toUpperCase() | translate}}
+
+
+
+
+ {{ flightDirections?.length || 0 }}/{{ flightDirectionTypes.length }}
+ {{ 'FLIGHT_DIRECTIONS_SELECTED' | translate }}
+
+
+ {{ 'NO_FLIGHT_DIRECTIONS_TO_SELECT' | translate }}
+
+
+
+
+
+
+ {{ subtype.apiValue }}
+
+
+
+
+ {{ subtypes?.length || 0 }}/{{ dataset.subtypes?.length }}
+ {{ 'SUBTYPES_SELECTED' | translate }}
+
+
+ {{ 'NO_SUBTYPES_TO_SELECT' | translate }}
+
+
+
+
+
+
+ {{instrument.displayName}}
+
+
+
+
+ {{ instruments?.length || 0 }}/{{ dataset.instruments.length }}
+ {{ 'INSTRUMENTS_SELECTED' | translate }}
+
+
+ {{ 'NO_INSTRUMENTS_TO_SELECT' | translate }}
+
+
+
+
+
+
+ {{'FULL' | translate}}
+
+
+ {{'PARTIAL' | translate}}
+
+
+
+
+ {{ frameCoverage?.length || 0 }}/2
+ {{ 'FRAMES_SELECTED' | translate }}
+
+
+ {{ 'NO_FRAMES_TO_SELECT' | translate }}
+
+
+
+
+
+ @for(parent of (dataset.bandwidth | keyvalue); track $index) {
+ @for(band of parent.value; track $index) {
+
+ ({{parent.key}}) {{band}}
+
+ }
+ }
+
+
+
+ {{ rangeBandwidth?.length || 0 }}/{{ dataset.bandwidth.length }}
+ {{ 'RANGE_BANDWITH_SELECTED' | translate }}
+
+
+ {{ 'NO_BANDWITH_TO_SELECT' | translate }}
+
+
+
+
+ {{ 'JOINT_OBSERVATION_ONLY' | translate}}
+
+
+
+
+
+
diff --git a/src/app/components/shared/selectors/observation-panel-selector/observation-panel-selector.component.scss b/src/app/components/shared/selectors/observation-panel-selector/observation-panel-selector.component.scss
new file mode 100644
index 000000000..531d9f452
--- /dev/null
+++ b/src/app/components/shared/selectors/observation-panel-selector/observation-panel-selector.component.scss
@@ -0,0 +1,44 @@
+@use 'sass:color';
+@use 'variables';
+
+mat-form-field {
+ margin-right: 10px;
+ margin-bottom: 10px;
+}
+
+.short-name-selector {
+ width: 100%;
+}
+
+.polarization-count {
+ font-size: small;
+ font-style: italic;
+ color: variables.$uaf-primary-blue;
+}
+
+.observation-panel {
+ display: flex;
+ flex-flow: row wrap;
+}
+
+.extra-wide {
+ flex-basis: 30%;
+ margin-left: 12px;
+}
+
+.half-width {
+ flex-basis: 48%;
+}
+
+.flight-direction-field {
+ min-width: 230px;
+}
+
+.polarization-select-container {
+ flex-basis: 48%;
+}
+
+.joint-observation-toggle {
+ margin: 16px 0 0 35px
+}
+
diff --git a/src/app/components/shared/selectors/observation-panel-selector/observation-panel-selector.component.ts b/src/app/components/shared/selectors/observation-panel-selector/observation-panel-selector.component.ts
new file mode 100644
index 000000000..324f50e1c
--- /dev/null
+++ b/src/app/components/shared/selectors/observation-panel-selector/observation-panel-selector.component.ts
@@ -0,0 +1,152 @@
+import { Component, OnInit, OnDestroy } from '@angular/core';
+import { Store } from '@ngrx/store';
+
+import { tap } from 'rxjs/operators';
+import { AppState } from '@store';
+import * as filtersStore from '@store/filters';
+
+import { PropertyService } from '@services';
+import { SubSink } from 'subsink';
+import * as models from '@models';
+@Component({
+ selector: 'app-observation-panel-selector',
+ templateUrl: './observation-panel-selector.component.html',
+ styleUrl: './observation-panel-selector.component.scss'
+})
+export class ObservationPanelSelectorComponent implements OnDestroy, OnInit{
+ dataset: models.Dataset;
+ productTypes: models.DatasetProductTypes;
+ flightDirections: models.FlightDirection[];
+ beamModes: models.DatasetBeamModes;
+ polarizations: models.DatasetPolarizations;
+ sidePolarizations: models.DatasetPolarizations;
+ subtypes: models.DatasetSubtypes;
+ groupID: string;
+ frameCoverage: string[];
+ rangeBandwidth: string[];
+ jointObservation: boolean;
+ instruments: string[];
+
+ public datasetProductTypes$ = this.store$.select(filtersStore.getProductTypes);
+ public flightDirections$ = this.store$.select(filtersStore.getFlightDirections);
+ public instruments$ = this.store$.select(filtersStore.getInstruments);
+ public beamModes$ = this.store$.select(filtersStore.getBeamModes);
+ public sidePolarizations$ = this.store$.select(filtersStore.getSidePolarizations);
+ public polarizations$ = this.store$.select(filtersStore.getPolarizations);
+ public selectedDataset$ = this.store$.select(filtersStore.getSelectedDataset);
+ public subtypes$ = this.store$.select(filtersStore.getSubtypes);
+ public groupID$ = this.store$.select(filtersStore.getGroupID);
+ public frameCoverage$ = this.store$.select(filtersStore.getFrameCoverage);
+ public jointObservation$ = this.store$.select(filtersStore.getJointObservation)
+ public rangeBandwidth$ = this.store$.select(filtersStore.getRangeBandwidth)
+
+
+ public flightDirectionTypes = models.flightDirections;
+ public p = models.Props;
+ private subs = new SubSink();
+
+ constructor(
+ private store$: Store,
+ public prop: PropertyService,
+ ) { }
+
+ ngOnInit() {
+ this.subs.add(
+ this.selectedDataset$.pipe(
+ tap(
+ dataset => this.flightDirectionTypes = dataset.id === models.avnir.id ?
+ models.justDescending : models.flightDirections
+ )
+ ).subscribe(dataset => this.dataset = dataset)
+ );
+ this.subs.add(
+ this.beamModes$.subscribe(modes => this.beamModes = modes)
+ );
+ this.subs.add(
+ this.flightDirections$.subscribe(directions => this.flightDirections = directions)
+ );
+ this.subs.add(
+ this.datasetProductTypes$.subscribe(types => this.productTypes = types)
+ );
+ this.subs.add(
+ this.polarizations$.subscribe(pols => this.polarizations = pols)
+ );
+ this.subs.add(
+ this.sidePolarizations$.subscribe(pols => this.sidePolarizations = pols)
+ );
+ this.subs.add(
+ this.subtypes$.subscribe(subtypes => this.subtypes = subtypes)
+ );
+ this.subs.add(
+ this.groupID$.subscribe(groupID => this.groupID = groupID)
+ );
+ this.subs.add(
+ this.frameCoverage$.subscribe(frameCoverage => this.frameCoverage = frameCoverage)
+ );
+ this.subs.add(
+ this.jointObservation$.subscribe(jointObservation => this.jointObservation = jointObservation)
+ );
+ this.subs.add(
+ this.rangeBandwidth$.subscribe(rangeBandwidth => this.rangeBandwidth = rangeBandwidth)
+ );
+ this.subs.add(
+ this.instruments$.subscribe(instruments => this.instruments = instruments)
+ );
+ }
+
+ public onNewDatasetBeamModes(beamModes: string[]): void {
+ this.store$.dispatch(new filtersStore.SetBeamModes(beamModes));
+ }
+
+ public onNewFlightDirectionsSelected(directions: models.FlightDirection[]): void {
+ this.store$.dispatch(new filtersStore.SetFlightDirections(directions));
+ }
+
+ public onNewDatasetPolarizations(polarizations: string[]): void {
+ this.store$.dispatch(new filtersStore.SetPolarizations(polarizations));
+ }
+
+ public onNewDatasetSidePolarizations(polarizations: string[]): void {
+ this.store$.dispatch(new filtersStore.SetSidePolarizations(polarizations));
+ }
+
+ public onNewProductTypes(productTypes: models.DatasetProductTypes): void {
+ this.store$.dispatch(new filtersStore.SetProductTypes(productTypes));
+ }
+
+ public onNewShortNames(shortNames: models.DatasetShortName): void {
+ this.store$.dispatch(new filtersStore.setShortNames(shortNames));
+ }
+
+ public onNewMaxResults(maxResults): void {
+ this.store$.dispatch(new filtersStore.SetMaxResults(maxResults));
+ }
+
+ public onNewSubtypeSelected(subtypes): void {
+ this.store$.dispatch(new filtersStore.SetSubtypes(subtypes));
+ }
+ public onNewFrameCoverageSelected(coverage): void {
+ this.store$.dispatch(new filtersStore.setFrameCoverage(coverage));
+ }
+ public onNewRangeBandwidthSelected(bandwidth) {
+ this.store$.dispatch(new filtersStore.setRangeBandwidth(bandwidth))
+ }
+
+ public onNewJointObservation(observation) {
+ this.store$.dispatch(new filtersStore.setJointObservation(observation))
+ }
+ public onNewInstrument(instruments) {
+ this.store$.dispatch(new filtersStore.setIntstrument(instruments))
+ }
+
+ public onNewGroupID(): void {
+ if(this.groupID.length > 29) {
+ this.groupID = this.groupID.slice(0, 29);
+ }
+ this.store$.dispatch(new filtersStore.setGroupID(this.groupID));
+ }
+
+ ngOnDestroy() {
+ this.subs.unsubscribe();
+ }
+}
diff --git a/src/app/components/shared/selectors/observation-panel-selector/observation-panel-selector.module.ts b/src/app/components/shared/selectors/observation-panel-selector/observation-panel-selector.module.ts
new file mode 100644
index 000000000..e82ce3795
--- /dev/null
+++ b/src/app/components/shared/selectors/observation-panel-selector/observation-panel-selector.module.ts
@@ -0,0 +1,39 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+
+import { MatSelectModule } from '@angular/material/select';
+import { MatButtonToggleModule } from '@angular/material/button-toggle';
+import { MatSharedModule } from '@shared';
+
+import { ProductTypeSelectorModule } from '@components/shared/selectors/product-type-selector';
+import { ShortNameSelectorModule } from '@components/shared/selectors/short-name-selector';
+
+import { ObservationPanelSelectorComponent } from './observation-panel-selector.component';
+import { BurstSelectorModule } from '../burst-selector';
+import { SharedModule } from "@shared";
+import { MatInputModule } from '@angular/material/input';
+import { OperaCalibrationDataSelectorModule } from '../opera-calibration-data-selector';
+import { MatSlideToggleModule } from '@angular/material/slide-toggle';
+import { PipesModule } from '@pipes';
+
+@NgModule({
+ declarations: [ ObservationPanelSelectorComponent ],
+ imports: [
+ CommonModule,
+ FormsModule,
+ MatSelectModule,
+ MatButtonToggleModule,
+ MatSharedModule,
+ MatSlideToggleModule,
+ ProductTypeSelectorModule,
+ ShortNameSelectorModule,
+ BurstSelectorModule,
+ SharedModule,
+ MatInputModule,
+ OperaCalibrationDataSelectorModule,
+ PipesModule
+ ],
+ exports: [ ObservationPanelSelectorComponent ],
+})
+export class ObservationPanelSelectorModule { }
diff --git a/src/app/components/shared/selectors/other-selector/other-selector.component.html b/src/app/components/shared/selectors/other-selector/other-selector.component.html
index 4fc54fb71..226b31975 100644
--- a/src/app/components/shared/selectors/other-selector/other-selector.component.html
+++ b/src/app/components/shared/selectors/other-selector/other-selector.component.html
@@ -102,5 +102,10 @@
-->
+
+
diff --git a/src/app/components/shared/selectors/other-selector/other-selector.component.scss b/src/app/components/shared/selectors/other-selector/other-selector.component.scss
index d4276533d..f41aad7d8 100644
--- a/src/app/components/shared/selectors/other-selector/other-selector.component.scss
+++ b/src/app/components/shared/selectors/other-selector/other-selector.component.scss
@@ -2,3 +2,7 @@ mat-form-field {
margin-right: 10px;
margin-bottom: 10px;
}
+
+.short-name-selector {
+ width: 100%;
+}
\ No newline at end of file
diff --git a/src/app/components/shared/selectors/other-selector/other-selector.component.ts b/src/app/components/shared/selectors/other-selector/other-selector.component.ts
index 561c33bcd..96e4b436f 100644
--- a/src/app/components/shared/selectors/other-selector/other-selector.component.ts
+++ b/src/app/components/shared/selectors/other-selector/other-selector.component.ts
@@ -85,6 +85,10 @@ export class OtherSelectorComponent implements OnInit, OnDestroy {
this.store$.dispatch(new filtersStore.SetProductTypes(productTypes));
}
+ public onNewShortNames(shortNames: models.DatasetShortName): void {
+ this.store$.dispatch(new filtersStore.setShortNames(shortNames));
+ }
+
public onNewMaxResults(maxResults): void {
this.store$.dispatch(new filtersStore.SetMaxResults(maxResults));
}
diff --git a/src/app/components/shared/selectors/other-selector/other-selector.module.ts b/src/app/components/shared/selectors/other-selector/other-selector.module.ts
index 4df09e387..e9b595310 100644
--- a/src/app/components/shared/selectors/other-selector/other-selector.module.ts
+++ b/src/app/components/shared/selectors/other-selector/other-selector.module.ts
@@ -7,6 +7,8 @@ import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { MatSharedModule } from '@shared';
import { ProductTypeSelectorModule } from '@components/shared/selectors/product-type-selector';
+import { ShortNameSelectorModule } from '@components/shared/selectors/short-name-selector';
+
import { OtherSelectorComponent } from './other-selector.component';
import { BurstSelectorModule } from '../burst-selector';
import { SharedModule } from "@shared";
@@ -22,6 +24,7 @@ import { OperaCalibrationDataSelectorModule } from '../opera-calibration-data-se
MatButtonToggleModule,
MatSharedModule,
ProductTypeSelectorModule,
+ ShortNameSelectorModule,
BurstSelectorModule,
SharedModule,
MatInputModule,
diff --git a/src/app/components/shared/selectors/path-selector/path-selector.component.html b/src/app/components/shared/selectors/path-selector/path-selector.component.html
index de614fbf4..bb257cf81 100644
--- a/src/app/components/shared/selectors/path-selector/path-selector.component.html
+++ b/src/app/components/shared/selectors/path-selector/path-selector.component.html
@@ -2,24 +2,24 @@
-
+ name="pathStart" placeholder="{{ prop.isRelevant(p.USE_TRACK) ? ('TRACK_START' | translate) : ('PATH_START' | translate)}}">
-
+ name="pathEnd" placeholder="{{ prop.isRelevant(p.USE_TRACK) ? ('TRACK_END' | translate) : ('PATH_END' | translate) }}">
@@ -31,10 +31,10 @@
type="number"
(input)="onValueChanged($event, inputTypes.FRAME_START)"
[(ngModel)]="frameStart"
- name="frameStart" placeholder="{{ 'FRAME_START' | translate }}">
+ name="frameStart" placeholder="{{ 'FRAME_START' | translate}}">
-
();
private currentError: PathFormInputType | null = null;
-
+
public inputTypes = PathFormInputType;
public pathStart: number | null;
public pathEnd: number | null;
public frameStart: number | null;
public frameEnd: number | null;
-
+ public selectedDataset: string | null = '';
+
private get pathStartControl() {
return this.pathForm.form
.controls['pathStart'];
@@ -68,6 +69,11 @@ export class PathSelectorComponent implements OnInit, OnDestroy {
ngOnInit() {
this.handlePathFrameErrors();
+ this.subs.add(
+ this.store$.select(filtersStore.getSelectedDatasetId).subscribe(
+ selected => this.selectedDataset = selected
+ )
+ );
this.subs.add(
this.store$.select(filtersStore.getPathRange).subscribe(
range => {
diff --git a/src/app/components/shared/selectors/product-science-selector/product-science-selector.component.html b/src/app/components/shared/selectors/product-science-selector/product-science-selector.component.html
new file mode 100644
index 000000000..c9d7c8110
--- /dev/null
+++ b/src/app/components/shared/selectors/product-science-selector/product-science-selector.component.html
@@ -0,0 +1,16 @@
+
+
+ {{ 'SCIENCE_PRODUCT' | translate }}
+
+
+ @for (group of sciProdGroups; track group) {
+
+ @for (sciProd of group.sciProd; track sciProd) {
+ {{sciProd.viewValue}}
+ }
+
+ }
+
+ {{ sciProdControl.value }}
+
diff --git a/src/app/components/shared/selectors/product-science-selector/product-science-selector.component.scss b/src/app/components/shared/selectors/product-science-selector/product-science-selector.component.scss
new file mode 100644
index 000000000..a52215b4d
--- /dev/null
+++ b/src/app/components/shared/selectors/product-science-selector/product-science-selector.component.scss
@@ -0,0 +1,9 @@
+div.cdk-overlay-pane:has(>.sci-prod-select) {
+ min-width: fit-content !important;
+ width: fit-content !important;
+}
+
+.sci-prod-select-container {
+ width: 49%;
+ margin-right: 17px;
+}
diff --git a/src/app/components/shared/selectors/product-science-selector/product-science-selector.component.ts b/src/app/components/shared/selectors/product-science-selector/product-science-selector.component.ts
new file mode 100644
index 000000000..f5b9e7c93
--- /dev/null
+++ b/src/app/components/shared/selectors/product-science-selector/product-science-selector.component.ts
@@ -0,0 +1,87 @@
+import {Component, OnDestroy, OnInit} from '@angular/core';
+import {FormControl, FormsModule, ReactiveFormsModule} from '@angular/forms';
+import {MatInputModule} from '@angular/material/input';
+import {MatSelectModule} from '@angular/material/select';
+import {MatFormFieldModule} from '@angular/material/form-field';
+import {SharedModule} from '@shared';
+import { SubSink } from 'subsink';
+import { Store } from '@ngrx/store';
+import { AppState } from '@store';
+import * as filtersStore from '@store/filters';
+
+interface sciProd {
+ value: string;
+ viewValue: string;
+}
+
+interface sciProdGroup {
+ disabled?: boolean;
+ name: string;
+ sciProd: sciProd[];
+}
+
+@Component({
+ selector: 'app-product-science-selector',
+ standalone: true,
+ templateUrl: './product-science-selector.component.html',
+ styleUrl: './product-science-selector.component.scss',
+ imports: [MatFormFieldModule, MatSelectModule, FormsModule, ReactiveFormsModule, MatInputModule, SharedModule],
+})
+export class ProductScienceSelectorComponent implements OnInit, OnDestroy {
+ sciProdControl: FormControl = new FormControl([]);
+ sciProdGroups: sciProdGroup[] = [
+
+ {
+ name: 'Level-3',
+ disabled: false,
+ sciProd: [
+ {value: 'SME2', viewValue: 'SME2 (Soil Moisture EASE-Grid 2.0)'},
+ ],
+ },
+
+ {
+ name: 'Level-2',
+ disabled: false,
+ sciProd: [
+ {value: 'GSLC', viewValue: 'GSLC (Geocoded Single Look Complex)'},
+ {value: 'GCOV', viewValue: 'GCOV (Geocoded Polarimetric Covariance)'},
+ {value: 'GUNW', viewValue: 'GUNW (Geocoded Unwrapped Interferogram)'},
+ {value: 'GOFF', viewValue: 'GOFF (Geocoded Pixel Offsets)'},
+ ],
+ },
+
+ {
+ name: 'Level-1',
+ disabled: false,
+ sciProd: [
+ {value: 'RSLC', viewValue: 'RSLC (Range-Doppler Single Look Complex)'},
+ {value: 'RIFG', viewValue: 'RIFG (Range-Doppler Wrapped Interferogram)'},
+ {value: 'RUNW', viewValue: 'RUNW (Range-Doppler Unwrapped Interferogram)'},
+ {value: 'ROFF', viewValue: 'ROFF (Range-Doppler Pixel Offsets)'},
+ ],
+ },
+
+ {
+ name: 'Level-0',
+ sciProd: [
+ {value: 'L0B', viewValue: 'L0B (Radar Raw Signal Data)'},
+ ],
+ },
+
+ ];
+ private subs: SubSink = new SubSink();
+
+ public constructor(private store$: Store) {}
+
+ public ngOnInit(): void {
+ this.subs.add(this.store$.select(filtersStore.getScienceProduct).subscribe(value => {
+ this.sciProdControl.setValue(value);
+ }))
+ }
+ public onSciProductSelect(value) {
+ this.store$.dispatch(new filtersStore.setScienceProduct(value));
+ }
+ public ngOnDestroy(): void {
+ this.subs.unsubscribe()
+ }
+}
diff --git a/src/app/components/shared/selectors/product-science-selector/product-science-selector.module.ts b/src/app/components/shared/selectors/product-science-selector/product-science-selector.module.ts
new file mode 100644
index 000000000..12caca764
--- /dev/null
+++ b/src/app/components/shared/selectors/product-science-selector/product-science-selector.module.ts
@@ -0,0 +1,12 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+
+
+@NgModule({
+ declarations: [],
+ imports: [
+ CommonModule
+ ]
+})
+export class ProductScienceSelectorModule { }
diff --git a/src/app/components/shared/selectors/production-config-selector/production-config-selector.component.html b/src/app/components/shared/selectors/production-config-selector/production-config-selector.component.html
new file mode 100644
index 000000000..19e1f7245
--- /dev/null
+++ b/src/app/components/shared/selectors/production-config-selector/production-config-selector.component.html
@@ -0,0 +1,15 @@
+
+ {{ 'PRODUCTION_CONFIGURATION' | translate }}
+
+ @for (prodConfig of prodConfigs; track prodConfig) {
+ {{prodConfig.viewValue | translate }}
+ }
+
+ {{ prodConfigControl.value }}
+
+
+
+
diff --git a/src/app/components/shared/selectors/production-config-selector/production-config-selector.component.scss b/src/app/components/shared/selectors/production-config-selector/production-config-selector.component.scss
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/app/components/shared/selectors/production-config-selector/production-config-selector.component.ts b/src/app/components/shared/selectors/production-config-selector/production-config-selector.component.ts
new file mode 100644
index 000000000..97bd460de
--- /dev/null
+++ b/src/app/components/shared/selectors/production-config-selector/production-config-selector.component.ts
@@ -0,0 +1,55 @@
+import {Component, OnDestroy, OnInit} from '@angular/core';
+import {FormControl, FormsModule, ReactiveFormsModule} from '@angular/forms';
+import {MatInputModule} from '@angular/material/input';
+import {MatSelectModule} from '@angular/material/select';
+import {MatFormFieldModule} from '@angular/material/form-field';
+import {SharedModule} from '@shared';
+import { SubSink } from 'subsink';
+import { AppState } from '@store';
+import { Store } from '@ngrx/store';
+import * as filtersStore from '@store/filters';
+
+interface prodConfig {
+ value: string;
+ viewValue: string;
+}
+
+@Component({
+ selector: 'app-production-config-selector',
+ standalone: true,
+ templateUrl: './production-config-selector.component.html',
+ styleUrl: './production-config-selector.component.scss',
+ imports: [MatFormFieldModule, MatSelectModule, FormsModule, ReactiveFormsModule, MatInputModule, SharedModule],
+})
+
+export class ProductionConfigSelectorComponent implements OnInit, OnDestroy {
+ prodConfigControl = new FormControl(['']);
+ public selectedConfig: string[] = ['PR']; // Default selected config
+
+ prodConfigs: prodConfig[] = [
+ {value: 'PR', viewValue: 'PRODUCTION'},
+ {value: 'UR', viewValue: 'URGENT_RESPONSE'},
+ {value: 'OD', viewValue: 'CUSTOM_VALIDATION'},
+ ];
+
+
+ private subs: SubSink = new SubSink();
+
+ public constructor(private store$: Store) {}
+
+ public ngOnInit(): void {
+ this.onProductionConfigSelect(this.selectedConfig);
+
+ this.subs.add(this.store$.select(filtersStore.getProductionConfig).subscribe(value => {
+ this.prodConfigControl.setValue(value);
+ }))
+ }
+
+ public onProductionConfigSelect(value) {
+ this.store$.dispatch(new filtersStore.setProductionConfig(value));
+ }
+
+ public ngOnDestroy(): void {
+ this.subs.unsubscribe()
+ }
+}
diff --git a/src/app/components/shared/selectors/production-config-selector/production-config-selector.module.ts b/src/app/components/shared/selectors/production-config-selector/production-config-selector.module.ts
new file mode 100644
index 000000000..e2c219900
--- /dev/null
+++ b/src/app/components/shared/selectors/production-config-selector/production-config-selector.module.ts
@@ -0,0 +1,12 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+
+
+@NgModule({
+ declarations: [],
+ imports: [
+ CommonModule
+ ]
+})
+export class ProductionConfigSelectorModule { }
diff --git a/src/app/components/shared/selectors/short-name-selector/index.ts b/src/app/components/shared/selectors/short-name-selector/index.ts
new file mode 100644
index 000000000..86de7ca12
--- /dev/null
+++ b/src/app/components/shared/selectors/short-name-selector/index.ts
@@ -0,0 +1,2 @@
+export * from './short-name-selector.component';
+export * from './short-name-selector.module';
diff --git a/src/app/components/shared/selectors/short-name-selector/short-name-selector.component.html b/src/app/components/shared/selectors/short-name-selector/short-name-selector.component.html
new file mode 100644
index 000000000..3ab922cce
--- /dev/null
+++ b/src/app/components/shared/selectors/short-name-selector/short-name-selector.component.html
@@ -0,0 +1,24 @@
+
+
+
+ {{type.displayName}}
+
+
+
+ = 1" align="start">
+ {{ shortNamesList?.length || 0 }}/{{ selectableShortNames.length }}
+ {{ 'SHORT_NAMES_SELECTED' | translate }}
+
+
+
+
\ No newline at end of file
diff --git a/src/app/components/shared/selectors/short-name-selector/short-name-selector.component.scss b/src/app/components/shared/selectors/short-name-selector/short-name-selector.component.scss
new file mode 100644
index 000000000..e3eaa3ac5
--- /dev/null
+++ b/src/app/components/shared/selectors/short-name-selector/short-name-selector.component.scss
@@ -0,0 +1,7 @@
+.short-name-form {
+ width: 100%;
+
+ .short-name-dropdown {
+ width: 100%;
+ }
+}
\ No newline at end of file
diff --git a/src/app/components/shared/selectors/short-name-selector/short-name-selector.component.ts b/src/app/components/shared/selectors/short-name-selector/short-name-selector.component.ts
new file mode 100644
index 000000000..d89faf1f0
--- /dev/null
+++ b/src/app/components/shared/selectors/short-name-selector/short-name-selector.component.ts
@@ -0,0 +1,60 @@
+import { Component, OnInit, Output, EventEmitter, OnDestroy } from '@angular/core';
+import * as models from '@models';
+import * as filtersStore from '@store/filters';
+import { Store } from '@ngrx/store';
+import { AppState } from '@store';
+import { SubSink } from 'subsink';
+import { MatSelectChange } from '@angular/material/select';
+
+@Component({
+ selector: 'app-short-name-selector',
+ templateUrl: './short-name-selector.component.html',
+ styleUrl: './short-name-selector.component.scss'
+})
+export class ShortNameSelectorComponent implements OnInit, OnDestroy {
+ @Output() shortNamesChange = new EventEmitter();
+ public dataset: models.Dataset;
+ public shortNamesList: string[] = [];
+ public selectableShortNames: models.ShortName[] = []
+
+ private dataset$ = this.store$.select(filtersStore.getSelectedDataset);
+
+
+ constructor(private store$: Store) { }
+
+ private subs = new SubSink();
+
+ ngOnInit(): void {
+ this.subs.add(
+ this.dataset$.subscribe(
+ dataset => {
+ this.dataset = dataset
+ this.selectableShortNames = dataset?.shortNames ?? []
+ }
+ )
+ )
+ this.subs.add(
+ this.store$.select(filtersStore.getShortNames).subscribe(
+ shortNamesList => this.shortNamesList = shortNamesList.map(val => val.apiValue)
+ )
+ )
+ }
+
+ ngOnDestroy(): void {
+ this.subs.unsubscribe();
+ }
+
+ public onNewShortNames(event: MatSelectChange): void {
+ const shortNameAPIValues = (event.value as string[]);
+ this.emitShortNames(shortNameAPIValues);
+ }
+
+ public emitShortNames(shortNameAPIValues: string[]): void {
+ const shortNames = this.dataset?.shortNames ?? []
+ let output = shortNameAPIValues.map(shortName => shortNames.find(datasetType => datasetType.apiValue === shortName))
+ this.shortNamesChange.emit(output);
+ }
+}
+
+
+
diff --git a/src/app/components/shared/selectors/short-name-selector/short-name-selector.module.ts b/src/app/components/shared/selectors/short-name-selector/short-name-selector.module.ts
new file mode 100644
index 000000000..e29f88cbf
--- /dev/null
+++ b/src/app/components/shared/selectors/short-name-selector/short-name-selector.module.ts
@@ -0,0 +1,27 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+
+import { MatSelectModule } from '@angular/material/select';
+import { MatSharedModule } from '@shared';
+
+import { ShortNameSelectorComponent } from './short-name-selector.component';
+import { SharedModule } from "@shared";
+
+@NgModule({
+ declarations: [
+ ShortNameSelectorComponent
+ ],
+ imports: [
+ CommonModule,
+ FormsModule,
+ MatSelectModule,
+ MatSharedModule,
+ SharedModule
+
+ ],
+ exports: [
+ ShortNameSelectorComponent
+ ]
+})
+export class ShortNameSelectorModule { }
diff --git a/src/app/models/cmr-product.model.ts b/src/app/models/cmr-product.model.ts
index 5185af945..3d9991ffc 100644
--- a/src/app/models/cmr-product.model.ts
+++ b/src/app/models/cmr-product.model.ts
@@ -60,15 +60,17 @@ export interface CMRProductMetadata {
// OPERA-S1
opera: OperaS1Metadata | null;
+ nisar: NISARMetadata | null;
fileName: string | null;
job: Hyp3Job | null;
// versioning
- pgeVersion: number | null;
+ pgeVersion: string | null;
- // BURST XML, OPERA-S1
+ // BURST XML, OPERA-S1, NISAR
subproducts: any[];
+ s3URI?: string;
parentID: string;
// ARIA S1 GUNW
@@ -92,6 +94,16 @@ export interface OperaS1Metadata {
validityStartDate?: moment.Moment | null;
}
+export interface NISARMetadata {
+ additionalUrls: string[];
+ s3Urls: string[];
+ frameCoverage: string,
+ jointObservation: string,
+ sideBandPolarization: string,
+ mainBandPolarization: string,
+ rangeBandwidth: string,
+}
+
export enum FlightDirection {
ASCENDING = 'ASCENDING',
DESCENDING = 'DESCENDING',
diff --git a/src/app/models/copy-icon.model.ts b/src/app/models/copy-icon.model.ts
new file mode 100644
index 000000000..6a403a45b
--- /dev/null
+++ b/src/app/models/copy-icon.model.ts
@@ -0,0 +1,6 @@
+import { faCopy, faLink } from '@fortawesome/free-solid-svg-icons';
+
+export const CopyIcons = {
+ COPY: faCopy,
+ LINK: faLink,
+}
\ No newline at end of file
diff --git a/src/app/models/dataset.model.ts b/src/app/models/dataset.model.ts
index f295a8eb4..ea6db0938 100644
--- a/src/app/models/dataset.model.ts
+++ b/src/app/models/dataset.model.ts
@@ -13,6 +13,7 @@ export interface Dataset {
productTypes: ProductType[];
beamModes: string[];
polarizations: string[];
+ sidepolarizations?: string[];
subtypes: DatasetSubtype[];
frequency: string;
source: {
@@ -25,6 +26,9 @@ export interface Dataset {
calibrationDatasets?: string[];
calibrationProductTypes?: ProductType[];
+ shortNames?: ShortName[]; // For NISAR shortnames
+ instruments?: {displayName: string, apiValue: string}[];
+ bandwidth?: {[band: string]: string[]};
}
export enum MissionDataset {
@@ -43,12 +47,18 @@ export interface ProductType {
apiValue: string;
}
+export interface ShortName {
+ displayName: string;
+ apiValue: string;
+}
+
export interface DatasetSubtype {
displayName: string;
apiValue: string;
}
export type DatasetProductTypes = ProductType[];
+export type DatasetShortName = ShortName[];
export type DatasetBeamModes = string[];
export type DatasetPolarizations = string[];
export type DatasetSubtypes = DatasetSubtype[];
@@ -68,8 +78,10 @@ export const ers = fromDatasets.ers;
export const jers_1 = fromDatasets.jers_1;
export const airsar = fromDatasets.airsar;
export const seasat = fromDatasets.seasat;
+export const nisar = fromDatasets.nisar;
export const datasetList: Dataset[] = [
+ fromDatasets.nisar,
fromDatasets.sentinel_1,
fromDatasets.sentinel_1_bursts,
fromDatasets.opera_s1,
diff --git a/src/app/models/datasets/index.ts b/src/app/models/datasets/index.ts
index 1e5f66525..dec04bc24 100644
--- a/src/app/models/datasets/index.ts
+++ b/src/app/models/datasets/index.ts
@@ -12,4 +12,5 @@ export * from './sirc';
export * from './avnir';
export * from './sentinel-1-burst';
export * from './opera_s1';
-export * from './alos_2';
\ No newline at end of file
+export * from './nisar';
+export * from './alos_2';
diff --git a/src/app/models/datasets/nisar.ts b/src/app/models/datasets/nisar.ts
new file mode 100644
index 000000000..d66930452
--- /dev/null
+++ b/src/app/models/datasets/nisar.ts
@@ -0,0 +1,284 @@
+import { Props } from '../filters.model';
+
+export const nisar = {
+ id: 'NISAR',
+ name: 'NISAR',
+ subName: '',
+ beta: false,
+ properties: [
+ Props.DATE,
+ // Props.BEAM_MODE,
+ Props.FLIGHT_DIRECTION,
+ Props.POLARIZATION,
+ // Props.ABSOLUTE_ORBIT,
+ // Props.BASELINE_TOOL,
+ Props.PATH,
+ Props.FRAME,
+ Props.SIDE_POLARIZATION,
+ Props.RANGE_BANDWIDTH,
+ // Props.JOINT_OBSERVATION,
+ Props.COVERAGE_ANGLE,
+ Props.USE_TRACK,
+ Props.INSTRUMENT,
+ ],
+ apiValue: { dataset: 'NISAR' },
+ date: { start: new Date('2024/01/01 03:44:43 UTC') },
+ infoUrl: 'https://nisar.jpl.nasa.gov',
+ citationUrl: 'https://asf.alaska.edu/nisar/',
+ frequency: 'L-Band',
+ source: {
+ name: 'JPL',
+ url: 'https://nisar.jpl.nasa.gov'
+ },
+ productTypes: [
+ // {
+ // apiValue: 'BURST',
+ // displayName: 'SLC Burst (BURST)'
+ // }
+ ],
+ beamModes: [
+ // 'IW', 'EW'
+ ],
+ polarizations: [
+ "HH",
+ "HH,HV",
+ "HH,VV",
+ "HH,HV,VH,VV",
+ "VV",
+ "VV,VH",
+ "RH,RV",
+ "LH,LV"
+ ],
+ sidepolarizations: [
+ "HH",
+ "HH,HV",
+ "HH,HV,VH,VV",
+ // "HH,HV,VV,VH",
+ "VV",
+ "VV,VH",
+ "RH,RV",
+ "LH,LV"
+ ],
+ bandwidth: {
+ 'L-Band': [
+ '20+5',
+ '40+5',
+ '77',
+ '5',
+ '5+5'
+ ],
+ // 'S-Band': [
+ // '10',
+ // '25',
+ // '37',
+ // '75'
+ // ],
+ },
+ instruments: [
+ {
+ displayName: 'L-Band SAR',
+ apiValue: 'L-SAR',
+ },
+ // {
+ // displayName: 'S-Band SAR',
+ // apiValue: 'S-SAR',
+ // },
+ ],
+ subtypes: [
+ // {
+ // displayName: 'Sentinel-1A',
+ // apiValue: 'SA',
+ // }, {
+ // displayName: 'Sentinel-1B',
+ // apiValue: 'SB',
+ // }
+ ],
+// shortNames: [
+// {
+// displayName: "NISAR Beta NEN Science Telemetry Data (Version 1)",
+// apiValue: "NISAR_NEN_RRST_BETA_V1"
+// },
+// {
+// displayName: "NISAR Provisional NEN Science Telemetry Data (Version 1)",
+// apiValue: "NISAR_NEN_RRST_PROVISIONAL_V1"
+// },
+// {
+// displayName: "NISAR NEN Science Telemetry Data (Version 1)",
+// apiValue: "NISAR_NEN_RRST_V1"
+// },
+// {
+// displayName: "NISAR Beta Level 0A Science Telemetry Data (Version 1)",
+// apiValue: "NISAR_L0A_RRST_BETA_V1"
+// },
+// {
+// displayName: "NISAR Provisional Level 0A Science Telemetry Data (Version 1)",
+// apiValue: "NISAR_L0A_RRST_PROVISIONAL_V1"
+// },
+// {
+// displayName: "NISAR Level 0A Science Telemetry Data (Version 1)",
+// apiValue: "NISAR_L0A_RRST_V1"
+// },
+// {
+// displayName: "NISAR Beta Radar Raw Signal Science Data (Version 1)",
+// apiValue: "NISAR_L0B_RRSD_BETA_V1"
+// },
+// {
+// displayName: "NISAR Provisional Radar Raw Signal Science Data (Version 1)",
+// apiValue: "NISAR_L0B_RRSD_PROVISIONAL_V1"
+// },
+// {
+// displayName: "NISAR Radar Raw Signal Science Data (Version 1)",
+// apiValue: "NISAR_L0B_RRSD_V1"
+// },
+// {
+// displayName: "NISAR Beta Radar Raw Signal Calibration Data (Version 1)",
+// apiValue: "NISAR_L0B_CRSD_BETA_V1"
+// },
+// {
+// displayName: "NISAR Provisional Radar Raw Signal Calibration Data (Version 1)",
+// apiValue: "NISAR_L0B_CRSD_PROVISIONAL_V1"
+// },
+// {
+// displayName: "NISAR Radar Raw Signal Calibration Data (Version 1)",
+// apiValue: "NISAR_L0B_CRSD_V1"
+// },
+// {
+// displayName: "NISAR Beta Range Doppler Single Look Complex Product (Version 1)",
+// apiValue: "NISAR_L1_RSLC_BETA_V1"
+// },
+// {
+// displayName: "NISAR Provisional Range Doppler Single Look Complex Product (Version 1)",
+// apiValue: "NISAR_L1_RSLC_PROVISIONAL_V1"
+// },
+// {
+// displayName: "NISAR Validated Range Doppler Single Look Complex Product (Version 1)",
+// apiValue: "NISAR_L1_RSLC_V1"
+// },
+// {
+// displayName: "NISAR Beta Range Doppler Wrapped Interferogram Product (Version 1)",
+// apiValue: "NISAR_L1_RIFG_BETA_V1"
+// },
+// {
+// displayName: "NISAR Provisional Range Doppler Wrapped Interferogram Product (Version 1)",
+// apiValue: "NISAR_L1_RIFG_PROVISIONAL_V1"
+// },
+// {
+// displayName: "NISAR Validated Range Doppler Wrapped Interferogram Product (Version 1)",
+// apiValue: "NISAR_L1_RIFG_V1"
+// },
+// {
+// displayName: "NISAR Beta Range Doppler Unwrapped Interferogram Product (Version 1)",
+// apiValue: "NISAR_L1_RUNW_BETA_V1"
+// },
+// {
+// displayName: "NISAR Provisional Range Doppler Unwrapped Interferogram Product (Version 1)",
+// apiValue: "NISAR_L1_RUNW_PROVISIONAL_V1"
+// },
+// {
+// displayName: "NISAR Validated Range Doppler Unwrapped Interferogram Product (Version 1)",
+// apiValue: "NISAR_L1_RUNW_V1"
+// },
+// {
+// displayName: "NISAR Beta Range Doppler Pixel Offsets (Version 1)",
+// apiValue: "NISAR_L1_ROFF_BETA_V1"
+// },
+// {
+// displayName: "NISAR Provisional Range Doppler Pixel Offsets (Version 1)",
+// apiValue: "NISAR_L1_ROFF_PROVISIONAL_V1"
+// },
+// {
+// displayName: "NISAR Validated Range Doppler Pixel Offsets (Version 1)",
+// apiValue: "NISAR_L1_ROFF_V1"
+// },
+// {
+// displayName: "NISAR Beta Geocoded Single Look Complex Product (Version 1)",
+// apiValue: "NISAR_L2_GSLC_BETA_V1"
+// },
+// {
+// displayName: "NISAR Provisional Geocoded Single Look Complex Product (Version 1)",
+// apiValue: "NISAR_L2_GSLC_PROVISIONAL_V1"
+// },
+// {
+// displayName: "NISAR Validated Geocoded Single Look Complex Product (Version 1)",
+// apiValue: "NISAR_L2_GSLC_V1"
+// },
+// {
+// displayName: "NISAR Beta Geocoded Unwrapped Interferogram Product (Version 1)",
+// apiValue: "NISAR_L2_GUNW_BETA_V1"
+// },
+// {
+// displayName: "NISAR Provisional Geocoded Unwrapped Interferogram Product (Version 1)",
+// apiValue: "NISAR_L2_GUNW_PROVISIONAL_V1"
+// },
+// {
+// displayName: "NISAR Validated Geocoded Unwrapped Interferogram Product (Version 1)",
+// apiValue: "NISAR_L2_GUNW_V1"
+// },
+// {
+// displayName: "NISAR Beta Geocoded Polarimetric Covariance Product (Version 1)",
+// apiValue: "NISAR_L2_GCOV_BETA_V1"
+// },
+// {
+// displayName: "NISAR Provisional Geocoded Polarimetric Covariance Product (Version 1)",
+// apiValue: "NISAR_L2_GCOV_PROVISIONAL_V1"
+// },
+// {
+// displayName: "NISAR Validated Geocoded Polarimetric Covariance Product (Version 1)",
+// apiValue: "NISAR_L2_GCOV_V1"
+// },
+// {
+// displayName: "NISAR Beta Geocoded Pixel Offsets (Version 1)",
+// apiValue: "NISAR_L2_GOFF_BETA_V1"
+// },
+// {
+// displayName: "NISAR Provisional Geocoded Pixel Offsets (Version 1)",
+// apiValue: "NISAR_L2_GOFF_PROVISIONAL_V1"
+// },
+// {
+// displayName: "NISAR Validated Geocoded Pixel Offsets (Version 1)",
+// apiValue: "NISAR_L2_GOFF_V1"
+// },
+// {
+// displayName: "NISAR Beta Soil Moisture (Version 1)",
+// apiValue: "NISAR_L3_SME2_BETA_V1"
+// },
+// {
+// displayName: "NISAR Provisional Soil Moisture (Version 1)",
+// apiValue: "NISAR_L3_SME2_PROVISIONAL_V1"
+// },
+// {
+// displayName: "NISAR Validated Soil Moisture (Version 1)",
+// apiValue: "NISAR_L3_SME2_V1"
+// },
+// {
+// displayName: "NISAR Provisional Custom Products",
+// apiValue: "NISAR_CUSTOM_PROVISIONAL_V1"
+// },
+// {
+// displayName: "NISAR Urgent Response Radar Raw Signal Science Data",
+// apiValue: "NISAR_UR_L0B_RRSD"
+// },
+// {
+// displayName: "NISAR Urgent Response Level 1 Product",
+// apiValue: "NISAR_UR_L1"
+// },
+// {
+// displayName: "NISAR Urgent Response Level 2 Product",
+// apiValue: "NISAR_UR_L2"
+// },
+// {
+// displayName: "NISAR Ancillary and Auxiliary Data",
+// apiValue: "NISAR_ANC_AUX"
+// },
+// {
+// displayName: "NISAR LSAR External Calibration File",
+// apiValue: "NISAR_LSAR_EXT_CAL"
+// },
+// {
+// displayName: "NISAR LSAR Internal Calibration File",
+// apiValue: "NISAR_LSAR_INT_CAL"
+// },
+// ],
+ platformDesc: 'NISAR_DESC',
+ platformIcon: '/assets/icons/satellite_alt_black_48dp.svg',
+};
diff --git a/src/app/models/filters.model.ts b/src/app/models/filters.model.ts
index abe965d7e..7eba9cc8f 100644
--- a/src/app/models/filters.model.ts
+++ b/src/app/models/filters.model.ts
@@ -13,9 +13,15 @@ export enum Props {
STACK_SIZE = 'Stack Size',
BASELINE_TOOL = 'Baseline Tool',
SUBTYPE = 'Subtype',
+ INSTRUMENT = 'Instrument',
POINTING_ANGLE = 'Pointing Angle',
+ COVERAGE_ANGLE = 'Coverage Angle',
+ JOINT_OBSERVATION = 'Joint Observation',
+ SIDE_POLARIZATION = 'Side Polarization',
+ RANGE_BANDWIDTH = 'Range Bandwidth',
USE_BEAM_MODE = 'Use Beam Mode Filter',
- USE_PROCESSING_TYPE = 'Use Processing Type'
+ USE_PROCESSING_TYPE = 'Use Processing Type',
+ USE_TRACK = 'Use Track for Path'
}
export const apiParamNames = {
diff --git a/src/app/models/index.ts b/src/app/models/index.ts
index f68878104..5f74471b9 100644
--- a/src/app/models/index.ts
+++ b/src/app/models/index.ts
@@ -28,5 +28,6 @@ export * from './download.model';
export * from './event-product-sort.model';
export * from './asf-website.model';
export * from './mapbox.model';
+export * from './copy-icon.model';
export * from './timeseries.model';
export * from './layers.model';
diff --git a/src/app/pipes/pipes.module.ts b/src/app/pipes/pipes.module.ts
index c9a711f18..179509b61 100644
--- a/src/app/pipes/pipes.module.ts
+++ b/src/app/pipes/pipes.module.ts
@@ -11,6 +11,7 @@ import { QuakePipe, VolcanoPipe } from './sarviews-event.pipe';
import { FilterExtensionPipe } from './filter-extension.pipe';
import { FloatPrecisionPipe } from './float-precision.pipe';
import { AoiIconPipe } from './aoi-icon.pipe';
+import { PolarizationCountPipe } from './polarization.pipe';
@NgModule({
declarations: [
ReadableSizeFromBytesPipe,
@@ -30,7 +31,8 @@ import { AoiIconPipe } from './aoi-icon.pipe';
VolcanoPipe,
FilterExtensionPipe,
FloatPrecisionPipe,
- AoiIconPipe
+ AoiIconPipe,
+ PolarizationCountPipe
],
imports: [
CommonModule
@@ -53,7 +55,8 @@ import { AoiIconPipe } from './aoi-icon.pipe';
VolcanoPipe,
FilterExtensionPipe,
FloatPrecisionPipe,
- AoiIconPipe
+ AoiIconPipe,
+ PolarizationCountPipe
]
})
export class PipesModule { }
diff --git a/src/app/pipes/polarization.pipe.ts b/src/app/pipes/polarization.pipe.ts
new file mode 100644
index 000000000..b4b007f40
--- /dev/null
+++ b/src/app/pipes/polarization.pipe.ts
@@ -0,0 +1,21 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+ name: 'polarizationCount'
+})
+export class PolarizationCountPipe implements PipeTransform {
+ transform(input: string): string {
+ let count = (input.match(/,/g)||[]).length;
+ let bands = {
+ 0: 'Single-Pol',
+ 1: 'Dual-Pol',
+ 3: 'Quad-Pol'
+ }
+ if(bands.hasOwnProperty(count)) {
+ return `${bands[count]}`;
+ }
+ else {
+ return '';
+ }
+ }
+}
diff --git a/src/app/services/asf-api.service.ts b/src/app/services/asf-api.service.ts
index c3d207413..b04a187b9 100644
--- a/src/app/services/asf-api.service.ts
+++ b/src/app/services/asf-api.service.ts
@@ -62,9 +62,10 @@ export class AsfApiService {
if (this.env.currentEnv.cmr_token) {
stateParamsObj['cmr_token'] = this.env.currentEnv.cmr_token;
+ } else if (this.env.currentEnv.api_maturity !== 'prod') {
+ delete stateParamsObj['cmr_token'];
}
}
-
const params = this.queryParamsFrom(stateParamsObj);
const queryParamsStr = params.toString()
diff --git a/src/app/services/browse-overlay.service.ts b/src/app/services/browse-overlay.service.ts
index 0415ff824..4a0051a08 100644
--- a/src/app/services/browse-overlay.service.ts
+++ b/src/app/services/browse-overlay.service.ts
@@ -1,13 +1,13 @@
import { Injectable } from '@angular/core';
import { WktService } from '@services';
-import { Extent } from 'ol/extent';
+import { Extent, getCenter } from 'ol/extent';
import Feature from 'ol/Feature';
import Geometry from 'ol/geom/Geometry';
import Polygon from 'ol/geom/Polygon';
import ImageLayer from 'ol/layer/Image';
import Static from 'ol/source/ImageStatic';
-
-import { Coordinate } from 'ol/coordinate';
+// import * as olExtent from 'ol/extent';
+import { Coordinate, rotate } from 'ol/coordinate';
import MultiPolygon from 'ol/geom/MultiPolygon';
import { PinnedProduct } from './browse-map.service';
import LayerGroup from 'ol/layer/Group';
@@ -23,7 +23,15 @@ import { AppState } from '@store';
import GeoTIFFSource from 'ol/source/GeoTIFF';
import TileLayer from 'ol/layer/WebGLTile.js';
import ImageSource from 'ol/source/Image';
+import VectorLayer from 'ol/layer/Vector';
+import VectorSource from 'ol/source/Vector';
+// import { Overlay } from 'ol';
+import { Icon, Stroke, Style } from 'ol/style';
+import { Point } from 'ol/geom';
+import { Projection, addCoordinateTransforms, addProjection, get as getProjection, transform} from 'ol/proj';
+// import { HttpClient } from '@angular/common/http';
+// import { CustomProjection } from './map/views';
@Injectable({
providedIn: 'root'
})
@@ -43,6 +51,7 @@ export class BrowseOverlayService {
|| datasetID === 'SENTINEL-1'
|| datasetID === 'SENTINEL-1 INTERFEROGRAM (BETA)'
|| datasetID === 'UAVSAR'
+ || datasetID === 'NISAR'
|| datasetID === 'OPERA-S1';
case models.SearchType.SARVIEWS_EVENTS:
return selectedEventProducts?.length > 0;
@@ -51,7 +60,9 @@ export class BrowseOverlayService {
|| selectedScene?.dataset === 'Sentinel-1A'
|| selectedScene?.dataset === 'Sentinel-1B'
|| selectedScene?.dataset === 'Sentinel-1 Interferogram (BETA)'
- || selectedScene?.dataset === 'UAVSAR';
+ || selectedScene?.dataset === 'UAVSAR'
+ || selectedScene?.dataset === 'NISAR'
+ ;
case models.SearchType.CUSTOM_PRODUCTS:
return true;
case models.SearchType.DISPLACEMENT:
@@ -63,8 +74,11 @@ export class BrowseOverlayService {
}),
);
- constructor(private wktService: WktService,
- private store$: Store) { }
+ constructor(
+ private wktService: WktService,
+ private store$: Store,
+ // private http: HttpClient,
+) { }
private createImageSource(url: string, extent: Extent) {
return new Static({
@@ -182,6 +196,210 @@ export class BrowseOverlayService {
}
}
+ public getKMLLayer(_product: models.CMRProduct, _png_url: string, wkt: string, className: string = 'ol-layer', _layer_id: string = '') {
+ // function _substitute_url(url: string) {
+ // console.log(url)
+ // // https://openlayers.org/en/v7.5.2/apidoc/module-ol_format_KML-KML.html
+ // // For `iconUrlFunction`, kmls are formatted without url of image
+ // return png_url
+ // // return null
+
+ // }
+
+
+ // const feature = this.wktService.wktToFeature(wkt, 'EPSG:4326');
+ const feature = this.wktService.wktToFeature(wkt, 'EPSG:3857');
+
+ // const polygon = this.getPolygonFromFeature(feature, wkt);
+ // const polygon2 = this.getPolygonFromFeature(feature2, wkt);
+ // let anchor = this.getPolygonFromFeature(feature, wkt).getCoordinates()[0][0]
+ const iconStyle = new Style({
+ image: new Icon({
+ anchorXUnits: 'pixels',
+ anchorYUnits: 'pixels',
+
+ // src: 'https://avatars.githubusercontent.com/u/1342004?s=48&v=4',
+ src: _png_url,
+ scale: 0.05,
+ // 'anchorOrigin': 'bottom-left',
+
+ }),
+
+ });
+
+
+ const lineStyle = new Style({
+ "stroke": new Stroke({
+ "color": "#00FF00",
+ "width": 10
+ })
+ })
+ feature.setStyle(
+ (_feature) => {
+ var stringCoords = this.getPolygonFromFeature(feature, wkt).getCoordinates()[0];
+ var coords = stringCoords.slice(-2);
+ if (coords[1][0] == coords[0][0] && coords[1][1] == coords[0][1] && stringCoords.length > 2) {
+ // useful for drawing
+ coords = stringCoords.slice(-3, -1);
+ }
+ // iconStyle.getImage().set
+ iconStyle.setGeometry(new Point(stringCoords[1]));
+ // iconStyle.getImage().setDisplacement(coords[0])
+ iconStyle.getImage().setRotation(
+ Math.atan2(coords[1][0] - coords[0][0], coords[1][1] - coords[0][1])
+ );
+
+ return [lineStyle, iconStyle];
+ }
+ )
+ let source = new VectorSource({
+ wrapX: models.mapOptions.wrapX,
+ features: [feature]
+ });
+ const vecLayer = new VectorLayer({
+ // "extent": polygon.getExtent(),
+ source,
+ "zIndex": 0,
+ opacity: 1.0,
+ className,
+ // style: iconStyle
+ })
+ return vecLayer
+// let proj = new CustomProjection(
+// 'EPSG:27700',
+// '+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 ' +
+// '+x_0=400000 +y_0=-100000 +ellps=airy ' +
+// '+towgs84=446.448,-125.157,542.06,0.15,0.247,0.842,-20.489 ' +
+// '+units=m +no_defs',
+// polygon.getExtent()
+// )
+ // return Imagelayer;
+ // let proj = new Projection({code: 'EPSG:4326', 'metersPerUnit': 5, "axisOrientation": 'nwu', })
+
+ // // let l = polygon.getArea()
+ // // left
+ // // bottom
+ // // right
+ // // top
+
+ // let fromLonLat = getTransform(proj, 'EPSG:3857');
+ // let extent = polygon.getExtent()
+ // // olExtent.getlef
+ // // let flatcoords = polygon.getCoordinates()[0]
+
+ // console.log(extent)
+ // console.log(polygon.getCoordinates())
+ // // let simped = polygon.getSimplifiedGeometry(0.01).getCoordinates()[0]
+ // // simped.pop()
+ // // extent[2] = extent[2] - 5/2
+
+ let polygon = this.getPolygonFromFeature(feature, wkt)
+ let img = new ImageLayer({
+ // source: static_image_source,
+ extent: polygon.getExtent(),
+
+ })
+ let rotateProjection = (projection, angle, extent) => {
+ function rotateCoordinate(coordinate, angle, anchor) {
+ var coord = rotate(
+ [coordinate[0] - anchor[0], coordinate[1] - anchor[1]],
+ angle
+ );
+ return [coord[0] + anchor[0], coord[1] + anchor[1]];
+ }
+
+ function rotateTransform(coordinate) {
+ return rotateCoordinate(coordinate, angle, getCenter(extent));
+ }
+
+ function normalTransform(coordinate) {
+ return rotateCoordinate(coordinate, -angle, getCenter(extent));
+ }
+
+ var normalProjection = getProjection(projection);
+
+ var rotatedProjection = new Projection({
+ code:
+ normalProjection.getCode() +
+ ":" +
+ angle.toString() +
+ ":" +
+ extent.toString(),
+ units: normalProjection.getUnits(),
+ extent: extent
+ });
+ addProjection(rotatedProjection);
+
+ addCoordinateTransforms(
+ "EPSG:4326",
+ rotatedProjection,
+ function(coordinate) {
+ return rotateTransform(transform(coordinate, "EPSG:4326", projection));
+ },
+ function(coordinate) {
+ return transform(normalTransform(coordinate), projection, "EPSG:4326");
+ }
+ );
+
+ addCoordinateTransforms(
+ "EPSG:3857",
+ rotatedProjection,
+ function(coordinate) {
+ return rotateTransform(transform(coordinate, "EPSG:3857", projection));
+ },
+ function(coordinate) {
+ return transform(normalTransform(coordinate), projection, "EPSG:3857");
+ }
+ );
+
+ // also set up transforms with any projections defined using proj4
+ // if (typeof proj4 !== "undefined") {
+ // var projCodes = Object.keys(proj4.defs);
+ // projCodes.forEach(function(code) {
+ // var proj4Projection = getProjection(code);
+ // if (!getTransform(proj4Projection, rotatedProjection)) {
+ // addCoordinateTransforms(
+ // proj4Projection,
+ // rotatedProjection,
+ // function(coordinate) {
+ // return rotateTransform(
+ // transform(coordinate, proj4Projection, projection)
+ // );
+ // },
+ // function(coordinate) {
+ // return transform(
+ // normalTransform(coordinate),
+ // projection,
+ // proj4Projection
+ // );
+ // }
+ // );
+ // }
+ // });
+ // }
+
+ return rotatedProjection;
+ }
+ // let coords = polygon.getCoordinates()[0]
+ // let ext = applyTransform([...coords[1], ...coords[3]], fromLonLat, undefined )
+ let static_image_source = new Static({
+ url: _png_url,
+ projection: rotateProjection("EPSG:27700", Math.PI / 4, img.getExtent()),
+ // imageExtent: img.getExtent(),
+ // imageExtent: ext,
+ // imageExtent: extent.map(f => f),
+ // imageExtent: olExtent.boundingExtent(
+ // polygon.getCoordinates()[0].reverse()
+ // ),
+ // imageSize: [2018, 1845]
+ })
+ img.setSource(static_image_source)
+ return img
+ // img.getSource().getImage()
+ // static_image_source.getImage()
+ }
+
+
public setPinnedProducts(pinnedProducts: {[product_id in string]: PinnedProduct}, productLayerGroup: LayerGroup) {
const pinnedProductIds = Object.keys(pinnedProducts);
diff --git a/src/app/services/environment.service.ts b/src/app/services/environment.service.ts
index 49a4d0397..503cd426c 100644
--- a/src/app/services/environment.service.ts
+++ b/src/app/services/environment.service.ts
@@ -1,5 +1,8 @@
import { Injectable } from '@angular/core';
import { env } from './env';
+import { Store } from '@ngrx/store';
+import { AppState } from '@store';
+import { SetSearchOutOfDate } from '@store/search';
export interface Environments {
prod: Environment;
@@ -34,7 +37,7 @@ export class EnvironmentService {
public maturity: string;
public isProd: boolean;
- constructor() {
+ constructor(private $store: Store) {
this.isProd = env.defaultEnv === 'prod';
this.envs = this.loadEnvs();
@@ -65,10 +68,12 @@ export class EnvironmentService {
public setMaturity(maturity: string): void {
this.maturity = maturity;
localStorage.setItem(this.maturityKey, this.maturity);
+ this.$store.dispatch(new SetSearchOutOfDate(true));
}
public setEnvs(envs: any): void {
this.envs = envs;
+ this.$store.dispatch(new SetSearchOutOfDate(true));
}
private loadWithCustom(): Environments {
@@ -91,5 +96,6 @@ export class EnvironmentService {
public resetToDefault(): void {
this.envs = this.loadFromEnvFile();
+ this.$store.dispatch(new SetSearchOutOfDate(true));
}
}
diff --git a/src/app/services/envs/env-test.ts b/src/app/services/envs/env-test.ts
index 1141e60af..f72130064 100644
--- a/src/app/services/envs/env-test.ts
+++ b/src/app/services/envs/env-test.ts
@@ -11,7 +11,7 @@ export const env = {
},
test: {
api: 'https://api-test.asf.alaska.edu',
- api_maturity: 'prod',
+ api_maturity: 'test',
auth: 'https://auth.asf.alaska.edu',
urs: 'https://urs.earthdata.nasa.gov',
urs_client_id: 'BO_n7nTIlMljdvU6kRRB3g',
diff --git a/src/app/services/map/map.service.ts b/src/app/services/map/map.service.ts
index 075660bc6..17f6eacba 100644
--- a/src/app/services/map/map.service.ts
+++ b/src/app/services/map/map.service.ts
@@ -45,7 +45,7 @@ import TileLayer from 'ol/layer/WebGLTile.js';
import SimpleGeometry from 'ol/geom/SimpleGeometry';
import { SetGeocode } from '@store/filters';
-import { Extent } from 'ol/extent';
+import {Extent, isEmpty} from 'ol/extent';
import { MultiPolygon } from 'ol/geom';
import GeoJSON from 'ol/format/GeoJSON.js';
import * as uiStore from '@store/ui';
@@ -434,8 +434,10 @@ export class MapService implements OnDestroy {
const extent = this.polygonLayer
.getSource()
.getExtent();
-
- this.zoomToExtent(extent);
+
+ if(!isEmpty(extent)) {
+ this.zoomToExtent(extent);
+ }
}
public zoomToScene(scene: models.CMRProduct): void {
@@ -742,7 +744,7 @@ export class MapService implements OnDestroy {
}
- public setSelectedBrowse(url: string, wkt: string) {
+ public setSelectedBrowse(url: string, wkt: string, _scene: models.CMRProduct = null) {
if (!!this.browseImageLayer) {
this.map.removeLayer(this.browseImageLayer);
}
@@ -757,7 +759,12 @@ export class MapService implements OnDestroy {
this.browseImageLayer = this.browseOverlayService.createImageLayer(url, wkt, 'ol-layer', 'current-overlay');
this.map.addLayer(this.browseImageLayer);
})
- } else {
+ }
+ // else if(url.toLowerCase().includes('nisar')) {
+ // this.browseImageLayer = this.browseOverlayService.getKMLLayer(_scene, url, wkt, 'ol-layer', 'current-overlay');
+ // this.map.addLayer(this.browseImageLayer);
+ // }
+ else {
this.browseImageLayer = this.browseOverlayService.createNormalImageLayer(url, wkt, 'ol-layer', 'current-overlay');
this.map.addLayer(this.browseImageLayer);
}
diff --git a/src/app/services/notification.service.ts b/src/app/services/notification.service.ts
index df16d22fd..a33eb3d79 100644
--- a/src/app/services/notification.service.ts
+++ b/src/app/services/notification.service.ts
@@ -116,6 +116,24 @@ export class NotificationService {
}
}
+ public linkCopyIcon(prompt: string, count: number) {
+ let contentType = prompt.includes('S3') ? 'S3 Url' : 'Download Url';
+
+ let headerText: string;
+ let infoText: string;
+
+ if (count > 1) {
+ headerText = `${contentType}s Copied`;
+ infoText = `${count} ${contentType}s copied`;
+
+ this.info(infoText, headerText);
+ } else {
+ infoText = `${contentType} Copied`;
+
+ this.info(infoText);
+ }
+ }
+
public closeFiltersPanel() {
this.info('Filters dismissed and not applied');
}
diff --git a/src/app/services/product.service.ts b/src/app/services/product.service.ts
index 2d2763046..3b428cdb6 100644
--- a/src/app/services/product.service.ts
+++ b/src/app/services/product.service.ts
@@ -9,32 +9,33 @@ import * as models from '@models';
export class ProductService {
public fromResponse = (resp: any): models.CMRProduct[] => {
const products = (resp.results || [])
- .map(
- (g: any): models.CMRProduct => {
- let browses: string[] = [];
-
- if (Array.isArray(g.b)) {
- if (g.b.length > 0) {
- browses = g.b.map(
- (b: any): string => {
- return (b.replace('{gn}', g.gn));
- });
- } else {
- browses = ['/assets/no-browse.png'];
- }
- } else {
- if (g.b) {
- browses = [g.b];
+ .map(
+ (g: any): models.CMRProduct => {
+ let browses: string[] = [];
+
+ if (Array.isArray(g.b)) {
+ if (g.b.length > 0) {
+ browses = g.b.map(
+ (b: any): string => {
+ return (b.replaceAll('{gn}', g.gn));
+ });
+ } else {
+ browses = ['/assets/no-browse.png'];
+ }
} else {
- browses = ['/assets/no-browse.png'];
+ if (g.b) {
+ browses = [g.b];
+ } else {
+ browses = ['/assets/no-browse.png'];
+ }
}
- }
- if(g.pt == 'DISP-S1') {
+
+ if(g.pt == 'DISP-S1') {
browses = [browses[0]]; // only show the first browse for displacement for now
- }
+ }
- const thumbnail = (g.t ? g.t.replace('{gn}', g.gn) : g.t) || (!browses[0].includes('no-browse') ? browses[0].replace('{gn}', g.gn) : '/assets/no-thumb.png');
- let filename = g.fn.replace('{gn}', g.gn);
+ const thumbnail = (g.t ? g.t.replaceAll('{gn}', g.gn) : g.t) || (!browses[0].includes('no-browse') ? browses[0].replaceAll('{gn}', g.gn) : '/assets/no-thumb.png');
+ let filename = g.fn.replaceAll('{gn}', g.gn);
if ( !filename.includes(g.gn)) {
filename = `${g.gn}-${filename}`;
}
@@ -42,13 +43,13 @@ export class ProductService {
name: g.gn,
productTypeDisplay: g.ptd || g.gn,
file: filename,
- id: g.pid.replace('{gn}', g.gn),
- downloadUrl: g.du.replace('{gn}', g.gn),
+ id: g.pid.replaceAll('{gn}', g.gn),
+ downloadUrl: g.du.replaceAll('{gn}', g.gn),
bytes: g.s * 1000000,
dataset: (g.d === 'STS-59' || g.d === 'STS-68') ? 'SIR-C' : g.d,
browses,
thumbnail,
- groupId: g.gid.replace('{gn}', g.gn),
+ groupId: g.gid.replaceAll('{gn}', g.gn),
isUnzippedFile: false,
isDummyProduct: false,
metadata: this.getMetadataFrom(g)
@@ -57,7 +58,7 @@ export class ProductService {
product.metadata.subproducts = this.getSubproducts(product)
return product;
- }
+ }
);
return products;
@@ -65,8 +66,8 @@ export class ProductService {
private getMetadataFrom =
(g: any): models.CMRProductMetadata => ({
- date: this.fromCMRDate(g.st),
- stopDate: this.fromCMRDate(g.stp),
+ date: this.fromCMRDate(g.st),
+ stopDate: this.fromCMRDate(g.stp),
polygon: g.wu,
productType: g.pt,
@@ -95,9 +96,11 @@ export class ProductService {
fileName: null,
burst: g.s1b ? g.s1b : null,
opera: g.s1o ? g.s1o : null,
- pgeVersion: g.pge !== null ? parseFloat(g.pge) : null,
+ nisar: g.nsr ? g.nsr : null,
+ pgeVersion: g.pge !== null ? g.pge : null,
subproducts: [],
parentID: null,
+ s3URI: null,
ariaVersion: g.ariav ? g.ariav : null
})
@@ -107,104 +110,217 @@ export class ProductService {
return moment.utc(dateString);
}
- private getSubproducts(product: models.CMRProduct): models.CMRProduct[] {
- if (product.metadata?.productType === 'BURST') {
- return [this.burstXMLFromScene(product)]
- }
+ private getSubproducts(product: models.CMRProduct): models.CMRProduct[] {
+ if (product.metadata.productType === 'BURST') {
+ return [this.burstXMLFromScene(product)]
if (!!product.metadata?.opera) {
return this.operaSubproductsFromScene(product)
}
return []
}
+ if (!!product.metadata.opera) {
+ return this.operaSubproductsFromScene(product);
+ }
+ if (product.dataset === 'NISAR') {
+ return this.nisarSubproductsFromScene(product);
+ }
+ return []
+ }
+
+ private burstXMLFromScene(product: models.CMRProduct) {
+ let p = {
+ ...product,
+ downloadUrl: product.downloadUrl.replace('tiff', 'xml'),
+ productTypeDisplay: 'XML Metadata (BURST)',
+ file: product.file.replace('tiff', 'xml'),
+ id: product.id + '-XML',
+ bytes: 0,
+ metadata: {
+ ...product.metadata,
+ productType: product.metadata.productType + '_XML',
+ subproducts: [],
+ parentID: product.id,
+ },
+ } as models.CMRProduct;
+
+ return p;
+ }
- private burstXMLFromScene(product: models.CMRProduct) {
- let p = {
+ private operaProductTypeDisplays = {
+ hh: 'HH GeoTIFF',
+ hv: 'HV GeoTIFF',
+ vv: 'VV GeoTIFF',
+ vh: 'VH GeoTIFF',
+ mask: 'Mask GeoTIFF',
+ h5: 'HDF5',
+ xml: 'Metadata XML',
+ rtc_anf_gamma0_to_sigma0: 'RTC Gamma to Sigma GeoTIFF',
+ number_of_looks: '# of Looks GeoTIFF',
+ incidence_angle: 'Incidence Angle GeoTIFF',
+ rtc_anf_gamma0_to_beta0: 'RTC Gamm to Beta GeoTIFF',
+ local_incidence_angle: 'Local Incidence Angle GeoTIFF'
+ }
+
+ private operaSubproductsFromScene(product: models.CMRProduct) {
+ if (!!product.metadata.opera?.validityStartDate) {
+ product.metadata.opera.validityStartDate = this.fromCMRDate(
+ (product.metadata.opera?.validityStartDate as unknown) as string)
+ }
+ let products = []
+
+ let reg = product.downloadUrl.split(/(_v[0-9]\.[0-9]){1}(\.(\w*)|(_(\w*(_*))*.))*/);
+ let file_suffix = !!reg[3] ? reg[3] : reg[5]
+ product.productTypeDisplay = this.operaProductTypeDisplays[file_suffix.toLowerCase()]
+
+ const thumbnail_index = product.browses.findIndex(url => url.toLowerCase().includes('thumbnail'))
+ if (thumbnail_index !== -1) {
+ product.thumbnail = product.browses.splice(thumbnail_index, 1)[0];
+ }
+ product.browses = product.browses.filter(url => !url.includes('low-res'));
+
+
+ for (const p of product.metadata.opera.additionalUrls.filter(url => url !== product.downloadUrl)) {
+ reg = p.split(/(_v[0-9]\.[0-9]){1}(\.(\w*)|(_(\w*(_*))*.))*/);
+ file_suffix = !!reg[3] ? reg[3] : reg[5]
+ const productTypeDisplay = this.operaProductTypeDisplays[file_suffix.toLowerCase()];
+
+ const fileID = p.split('/').slice(-1)[0]
+
+ let subproduct = {
...product,
- downloadUrl: product.downloadUrl.replace('tiff', 'xml'),
- productTypeDisplay: 'XML Metadata (BURST)',
- file: product.file.replace('tiff', 'xml'),
- id: product.id + '-XML',
+ downloadUrl: p,
+ productTypeDisplay: productTypeDisplay || p,
+ file: fileID,
+ id: product.id + '-' + file_suffix,
bytes: 0,
+ browses: [],
+ thumbnail: null,
metadata: {
...product.metadata,
- productType: product.metadata.productType + '_XML',
- subproducts: [],
+ productType: product.metadata.productType,
parentID: product.id,
+ subproducts: []
},
} as models.CMRProduct;
- return p;
+ products.push(subproduct)
}
- private operaProductTypeDisplays = {
- hh: 'HH GeoTIFF',
- hv: 'HV GeoTIFF',
- vv: 'VV GeoTIFF',
- vh: 'VH GeoTIFF',
- mask: 'Mask GeoTIFF',
- h5: 'HDF5',
- xml: 'Metadata XML',
- rtc_anf_gamma0_to_sigma0: 'RTC Gamma to Sigma GeoTIFF',
- number_of_looks: '# of Looks GeoTIFF',
- incidence_angle: 'Incidence Angle GeoTIFF',
- rtc_anf_gamma0_to_beta0: 'RTC Gamm to Beta GeoTIFF',
- local_incidence_angle: 'Local Incidence Angle GeoTIFF'
+ return products.sort((a, b) => {
+ if (['hh', 'vv', 'vh', 'hv'].includes(a.productTypeDisplay.slice(0, 2).toLowerCase())) {
+ return -1;
+ } else if (['hh', 'vv', 'vh', 'hv'].includes(b.productTypeDisplay.slice(0, 2).toLowerCase()))
+ return 1;
+
+ return a.productTypeDisplay < b.productTypeDisplay ? -1 : 1
}
+ )
+ }
- private operaSubproductsFromScene(product: models.CMRProduct) {
- if (!!product.metadata.opera?.validityStartDate) {
- product.metadata.opera.validityStartDate = this.fromCMRDate(
- (product.metadata.opera?.validityStartDate as unknown) as string)
+ private nisarProductTypeDisplays = {
+ yaml: 'YAML',
+ kml: 'KML',
+ png: 'Browse PNG',
+ csv: 'Metadata CSV',
+ h5: 'HDF5',
+ xml: 'Metadata XML',
+ json: 'Metadata JSON',
+ pdf: 'PDF Report',
+ log: 'Log File',
+ qa: 'Report (QA)',
+ bin: 'Bin File'
+ }
+
+ private nisarSubproductsFromScene(product: models.CMRProduct) {
+ let products = []
+ let temp = product.downloadUrl.split('.')
+ let file_extension = temp[temp.length - 1]
+ // let reg = product.downloadUrl.split(/(_v[0-9]\.[0-9]){1}(\.(\w*)|(_(\w*(_*))*.))*/);
+ // let file_suffix = !!reg[3] ? reg[3] : reg[5]
+ product.productTypeDisplay = this.nisarProductTypeDisplays[file_extension.toLowerCase()] ? this.nisarProductTypeDisplays[file_extension.toLowerCase()] : 'Missing Display'
+ if (product.productTypeDisplay === 'Missing Display') {
+ if (file_extension.includes('vc')) {
+ product.productTypeDisplay = file_extension.toUpperCase();
+ } else {
+ console.log(`Missing product type display for file extension "${file_extension}"`);
}
- let products = []
+ }
+ const thumbnail_index = product.browses.findIndex(url => url.toLowerCase().includes('thumbnail'))
+ if (thumbnail_index !== -1) {
+ product.thumbnail = product.browses.splice(thumbnail_index, 1)[0];
+ }
+ product.browses = product.browses.filter(url => !url.includes('low-res'));
+
+
+ const s3UrlsByProductID = product.metadata.nisar.s3Urls.reduce((prev, curr) => {
+ const subproductFileID = curr.split('/').at(-1);
+
+ prev[subproductFileID] = curr;
- let reg = product.downloadUrl.split(/(_v[0-9]\.[0-9]){1}(\.(\w*)|(_(\w*(_*))*.))*/);
- let file_suffix = !!reg[3] ? reg[3] : reg[5]
- product.productTypeDisplay = this.operaProductTypeDisplays[file_suffix.toLowerCase()]
+ return prev;
+ }, {})
- const thumbnail_index = product.browses.findIndex(url => url.toLowerCase().includes('thumbnail'))
- if (thumbnail_index !== -1) {
- product.thumbnail = product.browses.splice(thumbnail_index, 1)[0];
+
+ product.metadata.s3URI = s3UrlsByProductID[product.file] ?? null;
+
+ let browses = []
+ for (const p of product.metadata.nisar.additionalUrls.filter(url => url !== product.downloadUrl)) {
+ temp = p.split('.')
+ file_extension = temp[temp.length - 1]
+ let productTypeDisplay = this.nisarProductTypeDisplays[file_extension.toLowerCase()] ?? 'Missing Display';
+ if (productTypeDisplay === 'Missing Display') {
+ if (file_extension.includes('vc')) {
+ productTypeDisplay = file_extension.toUpperCase();
+ } else {
+ console.log(`Missing product type display for file extension "${file_extension}"`);
+ }
}
- product.browses = product.browses.filter(url => !url.includes('low-res'));
-
-
- for (const p of product.metadata.opera.additionalUrls.filter(url => url !== product.downloadUrl)) {
- reg = p.split(/(_v[0-9]\.[0-9]){1}(\.(\w*)|(_(\w*(_*))*.))*/);
- file_suffix = !!reg[3] ? reg[3] : reg[5]
- const productTypeDisplay = this.operaProductTypeDisplays[file_suffix.toLowerCase()];
-
- const fileID = p.split('/').slice(-1)[0]
-
- let subproduct = {
- ...product,
- downloadUrl: p,
- productTypeDisplay: productTypeDisplay || p,
- file: fileID,
- id: product.id + '-' + file_suffix,
- bytes: 0,
- browses: [],
- thumbnail: null,
- metadata: {
- ...product.metadata,
- productType: product.metadata.productType,
- parentID: product.id,
- subproducts: []
- },
- } as models.CMRProduct;
-
- products.push(subproduct)
+ if (productTypeDisplay === 'Browse PNG') {
+ browses.push(p)
+ }
+ if (p.includes('QA_')) {
+ productTypeDisplay += (' (QA)')
+ }
+ if(productTypeDisplay === 'Log File') {
+ continue;
}
- return products.sort((a, b) => {
- if(['hh', 'vv', 'vh', 'hv'].includes(a.productTypeDisplay.slice(0, 2).toLowerCase())) {
- return -1;
- } else if(['hh', 'vv', 'vh', 'hv'].includes(b.productTypeDisplay.slice(0, 2).toLowerCase()))
- return 1;
- return a.productTypeDisplay < b.productTypeDisplay ? -1 : 1
+
+ const fileID = p.split('/').slice(-1)[0]
+ const s3Url = s3UrlsByProductID[fileID] ?? null
+ let subproduct = {
+ ...product,
+ downloadUrl: p,
+ productTypeDisplay: productTypeDisplay || p,
+ file: fileID,
+ id: product.id + '-' + file_extension,
+ bytes: 0,
+ browses,
+ thumbnail: null,
+ metadata: {
+ ...product.metadata,
+ productType: product.metadata.productType,
+ parentID: product.id,
+ subproducts: [],
+ s3URI: s3Url
+ },
+
+ } as models.CMRProduct;
+
+ products.push(subproduct)
+ }
+
+ return products.sort((a, b) => {
+ if (a.productTypeDisplay.includes('Metadata') || a.productTypeDisplay.includes('QA')) {
+ return 1;
+ } else if (b.productTypeDisplay.includes('Metadata') || b.productTypeDisplay.includes('QA')) {
+ return -1;
}
- )
+
+ return a.productTypeDisplay < b.productTypeDisplay ? -1 : 1
}
-}
+ )
+ }
+}
\ No newline at end of file
diff --git a/src/app/services/property.service.ts b/src/app/services/property.service.ts
index 64928c26b..ca4bff738 100644
--- a/src/app/services/property.service.ts
+++ b/src/app/services/property.service.ts
@@ -35,8 +35,14 @@ export class PropertyService {
const [datasetName, possibleValuesStr] = this.hasDatasetId(loadStr) ?
this.oldFormat(loadStr) :
this.shortFormat(loadStr);
+ let possibleTypes = [];
- const possibleTypes = (possibleValuesStr || '').split(',');
+ if(datasetPropertyKey.includes('polarization')) {
+ possibleTypes = (possibleValuesStr || '').split(',').map(x => x.replaceAll('-',','));
+ } else {
+ possibleTypes = (possibleValuesStr || '').split(',');
+
+ }
const dataset = models.datasetList
.filter(d => datasetName === d.id)
diff --git a/src/app/services/search-params.service.ts b/src/app/services/search-params.service.ts
index efdc7364f..c23706739 100644
--- a/src/app/services/search-params.service.ts
+++ b/src/app/services/search-params.service.ts
@@ -18,6 +18,8 @@ import { RangeService } from './range.service';
import * as models from '@models';
import { DrawService } from './map/draw.service';
import { Polygon } from 'ol/geom';
+import * as userStore from '@store/user';
+
@Injectable({
providedIn: 'root'
})
@@ -26,7 +28,8 @@ export class SearchParamsService {
private store$: Store,
private mapService: MapService,
private rangeService: RangeService,
- private drawService: DrawService
+ private drawService: DrawService,
+ // private authService: AuthService
) { }
@@ -171,6 +174,15 @@ export class SearchParamsService {
map(types => ({ processinglevel: types }))
);
+ private shortNames$ = this.store$.select(filterStore.getShortNames).pipe(
+ map(types => types.map(type => type.apiValue)),
+ map(
+ shortNames => Array.from(new Set(shortNames))
+ .join(',')
+ ),
+ map(shortNames => ({ shortname: shortNames }))
+ );
+
private beamModes$ = this.store$.select(filterStore.getBeamModes).pipe(
map(
types => Array.from(new Set(types))
@@ -185,11 +197,66 @@ export class SearchParamsService {
private polarizations$ = this.store$.select(filterStore.getPolarizations).pipe(
map(
polarizations => Array.from(new Set(polarizations))
+ .map(x => x.replaceAll(',','+'))
.join(',')
),
- map(polarization => ({ polarization })),
+ withLatestFrom(this.store$.select(filterStore.getSelectedDataset)),
+ map(([polarizations, dataset]) => dataset.properties.includes(models.Props.SIDE_POLARIZATION)?
+ ({ mainbandpolarization: polarizations }) : ({ polarization: polarizations })),
+ );
+
+ private productionConfig$ = this.store$.select(filterStore.getProductionConfig).pipe(
+ map((config) => ({ productionconfiguration: config.join(',') })
+ )
+ );
+
+ private sidePolarizations$ = this.store$.select(filterStore.getSidePolarizations).pipe(
+ map(
+ polarizations => Array.from(new Set(polarizations))
+ .map(x => x.replaceAll(',','+'))
+ .join(',')
+ ),
+ map(sidePolarization => ({ sidebandpolarization: sidePolarization })),
+ );
+
+ private frameCoverage$ = this.store$.select(filterStore.getFrameCoverage).pipe(
+ map(
+ coverages => {
+ let base = Array.from(new Set(coverages))
+ if(base.length > 1) {
+ return ''
+ } else {
+ return base[0]
+ }
+ }
+ ),
+ map(frameCoverage => ({ framecoverage: frameCoverage })),
+ );
+
+ private jointObservation$ = this.store$.select(filterStore.getJointObservation).pipe(
+ map(jointObservation => ({ jointobservation: jointObservation })),
);
+ private rangeBandwidth$ = this.store$.select(filterStore.getRangeBandwidth).pipe(
+ map(
+ bandwidths => Array.from(new Set(bandwidths))
+ .join(',')
+ ),
+ map(
+ bandwidths => ({rangebandwidth: bandwidths})
+ )
+ )
+
+ private instruments$ = this.store$.select(filterStore.getInstruments).pipe(
+ map(
+ instruments => Array.from(new Set(instruments))
+ .join(',')
+ ),
+ map(
+ instruments => ({instrument: instruments})
+ )
+ )
+
private flightDirections$ = this.store$.select(filterStore.getFlightDirections).pipe(
map(dirs => dirs.length > 1 ? [] : dirs),
map(dirs => dirs.join(',')),
@@ -199,6 +266,11 @@ export class SearchParamsService {
private maxResults$ = this.store$.select(filterStore.getMaxSearchResults).pipe(
map(maxResults => ({ maxResults }))
);
+
+ private sciProducts$ = this.store$.select(filterStore.getScienceProduct).pipe(
+ map(sciProducts => ({processingLevel: sciProducts.join(',')}))
+ )
+
private filterSearchParams$ = combineLatest([
this.searchPolygon$,
this.selectedDataset$,
@@ -207,14 +279,22 @@ export class SearchParamsService {
this.pathRange$,
this.frameRange$,
this.productType$,
+ this.shortNames$,
this.flightDirections$,
this.beamModes$,
this.polarizations$,
+ this.sidePolarizations$,
+ this.productionConfig$,
+ this.frameCoverage$,
+ this.jointObservation$,
+ this.rangeBandwidth$,
+ this.instruments$,
this.maxResults$,
this.missionParam$,
this.burstParams$,
this.operaBurstParams$,
// this.operaCalibrationParam$,
+ this.sciProducts$,
this.groupID$]
).pipe(
map((params: any[]) => params
@@ -240,34 +320,35 @@ export class SearchParamsService {
public getParams = combineLatest([
this.store$.select(getSearchType),
- this.baselineSearchParams$]
+ this.baselineSearchParams$,
+ this.store$.select(userStore.getUserEDLToken)]
).pipe(
withLatestFrom(this.listParam$),
withLatestFrom(this.filterSearchParams$),
withLatestFrom(this.timeseriesParams$),
map(
- ([[[[searchType, baselineParams], listParam], filterParams], timeseriesParams]) => {
+ ([[[[searchType, baselineParams, cmr_token], listParam], filterParams], timeseriesParams]) => {
switch (searchType) {
case models.SearchType.LIST: {
- return listParam;
+ return {cmr_token, ...listParam};
}
case models.SearchType.DATASET: {
- return filterParams;
+ return {cmr_token, ...filterParams};
}
case models.SearchType.BASELINE: {
- return baselineParams;
+ return {cmr_token, ...baselineParams};
}
case models.SearchType.SBAS: {
- return baselineParams;
+ return {cmr_token, ...baselineParams};
}
case models.SearchType.CUSTOM_PRODUCTS: {
- return listParam;
+ return {cmr_token, ...listParam};
}
case models.SearchType.DISPLACEMENT: {
return timeseriesParams;
}
default: {
- return filterParams;
+ return {cmr_token, ...filterParams};
}
}
}),
@@ -277,28 +358,30 @@ export class SearchParamsService {
this.store$.select(getSearchType),
this.listParam$,
this.baselineSearchParams$,
- this.filterSearchParams$]
+ this.filterSearchParams$,
+ this.store$.select(userStore.getUserEDLToken)
+ ]
).pipe(
map(
- ([searchType, listParam, baselineParams, filterParams]) => {
+ ([searchType, listParam, baselineParams, filterParams, cmr_token]) => {
switch (searchType) {
case models.SearchType.LIST: {
- return listParam;
+ return {cmr_token, ...listParam};
}
case models.SearchType.DATASET: {
- return filterParams;
+ return {cmr_token, ...filterParams};
}
case models.SearchType.BASELINE: {
- return baselineParams;
+ return {cmr_token, ...baselineParams};
}
case models.SearchType.SBAS: {
- return baselineParams;
+ return {cmr_token, ...baselineParams};
}
case models.SearchType.CUSTOM_PRODUCTS: {
- return listParam;
+ return {cmr_token, ...listParam};
}
default: {
- return filterParams;
+ return {cmr_token, ...filterParams};
}
}
}),
diff --git a/src/app/services/url-state.service.ts b/src/app/services/url-state.service.ts
index 480ec49fb..2657bf2d2 100644
--- a/src/app/services/url-state.service.ts
+++ b/src/app/services/url-state.service.ts
@@ -267,7 +267,6 @@ export class UrlStateService {
];
}
-
private eventMonitorParameters(): models.UrlParameter[] {
return [{
name: 'eventID',
@@ -577,7 +576,11 @@ export class UrlStateService {
name: 'polarizations',
source: this.store$.select(filterStore.getPolarizations).pipe(
map(
- pols => this.prop.saveProperties(pols, 'polarizations')
+
+ pols => {
+ const param = pols.map(x=> x.replaceAll(',', '-')).join(',');
+ return { 'polarizations': param };
+ }
)
),
loader: this.loadPolarizations
@@ -595,7 +598,66 @@ export class UrlStateService {
map(useCalibrationData => ({useCalibrationData}))
),
loader: this.loadUseCalibrationData
- }
+ },
+ {
+ name: 'sidePolarizations',
+ source: this.store$.select(filterStore.getSidePolarizations).pipe(
+ map(
+ pols => {
+ const param = pols.map(x => x.replaceAll(',','-')).join(',');
+ return { 'sidePolarizations': param };
+ }
+ )
+ ),
+ loader: this.loadSidePolarizations
+ },
+ {
+ name: 'frameCoverage',
+ source: this.store$.select(filterStore.getFrameCoverage).pipe(
+ map(dirs => dirs.join(',')),
+ map(frameCoverage => ({ frameCoverage }))
+ ),
+ loader: this.loadFrameCoverage
+ },
+ {
+ name: 'jointObservation',
+ source: this.store$.select(filterStore.getJointObservation).pipe(
+ map(jointObservation => ({ jointObservation }))
+ ),
+ loader: this.loadJointObservation
+ },
+ {
+ name: 'rangeBandwidths',
+ source: this.store$.select(filterStore.getRangeBandwidth).pipe(
+ map(bandwidths => bandwidths.join(',')),
+ map(rangeBandwidths => ({ rangeBandwidths }))
+ ),
+ loader: this.loadRangeBandwidth
+ },
+ {
+ name: 'instruments',
+ source: this.store$.select(filterStore.getInstruments).pipe(
+ map(instruments => instruments.join(',')),
+ map(instruments => ({ instruments }))
+ ),
+ loader: this.loadInstruments
+ },
+ {
+ name: 'sciProducts',
+ source: this.store$.select(filterStore.getScienceProduct).pipe(
+ map(sciProducts => sciProducts.join(',')),
+ map(sciProducts => ({ sciProducts }))
+ ),
+ loader: this.loadSciProducts
+ },
+ {
+ name: 'prodConfig',
+ source: this.store$.select(filterStore.getProductionConfig).pipe(
+ map(configs => configs.join(',')),
+ map(prodConfig => ({ prodConfig }))
+ ),
+ loader: this.loadProduction
+ },
];
}
@@ -657,6 +719,14 @@ export class UrlStateService {
)),
loader: this.loadGroupId
},
+ {
+ name: 'shortNames',
+ source: this.store$.select(filterStore.getShortNames).pipe(
+ map(shortNames => ({'shortNames': shortNames.map(name => name.apiValue).join(',')}))
+ ),
+ loader: this.loadShortNames
+
+ }
];
}
@@ -823,6 +893,20 @@ export class UrlStateService {
return new filterStore.SetProductTypes(productTypes);
};
+ private loadShortNames = (shortNameStr: string): Action | undefined => {
+ const shortNames: models.DatasetShortName = this.prop.loadProperties(
+ shortNameStr,
+ 'shortNames',
+ (v: models.ShortName) => v.apiValue
+ );
+
+ if (!shortNames) {
+ return;
+ }
+
+ return new filterStore.setShortNames(shortNames);
+ };
+
private loadBeamModes = (modesStr: string): Action | undefined => {
const beamModes = this.prop.loadProperties(modesStr, 'beamModes');
@@ -843,6 +927,14 @@ export class UrlStateService {
return new filterStore.SetPolarizations(polarizations);
};
+ private loadSidePolarizations = (polarizationsStr: string): Action | undefined => {
+ const polarizations = this.prop.loadProperties(polarizationsStr, 'polarizations');
+ if (!polarizations) {
+ return;
+ }
+
+ return new filterStore.SetSidePolarizations(polarizations);
+ };
private loadSubtypes = (subtypesStr: string): Action | undefined => {
const subtypes = this.prop.loadProperties(subtypesStr, 'subtypes', v => v.apiValue);
@@ -997,6 +1089,42 @@ export class UrlStateService {
private loadUseCalibrationData = (usingCalibrationData: string): Action => {
return new filterStore.setUseCalibrationData(!!usingCalibrationData)
}
+ private loadFrameCoverage = (coverageStr: string): Action => {
+ const coverage= coverageStr
+ .split(',')
+ // TODO: Add some better checking for this by grabbing from the dataset
+ // .filter(direction => !Object.values(models.FlightDirection).includes(direction))
+ // .map(direction => direction);
+
+ return new filterStore.setFrameCoverage(coverage);
+ };
+ private loadRangeBandwidth = (bandwidthStr: string): Action => {
+ const bandwidth= bandwidthStr
+ .split(',')
+ // TODO: Add some better checking for this by grabbing from the dataset
+ // .filter(direction => !Object.values(models.FlightDirection).includes(direction))
+ // .map(direction => direction);
+
+ return new filterStore.setRangeBandwidth(bandwidth);
+ };
+ private loadInstruments = (instrumentsStr: string): Action => {
+ const instruments= instrumentsStr
+ .split(',')
+ return new filterStore.setIntstrument(instruments);
+ };
+ private loadSciProducts = (sciProductsStr: string): Action => {
+ const sciProducts= sciProductsStr
+ .split(',')
+ return new filterStore.setScienceProduct(sciProducts);
+ };
+ private loadProduction = (productionStr: string): Action => {
+ const loadProducts = productionStr
+ .split(',')
+ return new filterStore.setProductionConfig(loadProducts);
+ };
+ private loadJointObservation = (observationStr: string): Action => {
+ return new filterStore.setJointObservation(observationStr === 'true');
+ };
private loadSeriesState = (seriesState)=> {
let states: models.timeseriesChartItemState[] = [];
diff --git a/src/app/store/filters/filters.action.ts b/src/app/store/filters/filters.action.ts
index 65f54d5e3..03ded0b1e 100644
--- a/src/app/store/filters/filters.action.ts
+++ b/src/app/store/filters/filters.action.ts
@@ -42,6 +42,9 @@ export enum FiltersActionType {
ADD_POLARIZATION = '[Filters-Polarization] Add Polarization',
SET_POLARIZATIONS = '[Filters-Polarization] Set Dataset Polarizations',
+ ADD_SIDE_POLARIZATION = '[Filters-Polarization] Add Side Polarization',
+ SET_SIDE_POLARIZATIONS = '[Filters-Polarization] Set Dataset Side Polarizations',
+
SET_JOB_STATUSES = '[Filters-Job-Status] Set Job Statuses',
SET_FLIGHT_DIRECTIONS = '[Filters-Flight-Dir] Set Flight Directions',
@@ -91,10 +94,20 @@ export enum FiltersActionType {
SET_GEOCODE = '[Filters] Set geocode area name',
SET_FULL_BURST = '[Filters] Set Full Burst IDs',
-
+
SET_OPERA_BURST_ID = '[Filters] Set Full OPERA S1 Burst IDs',
SET_INCLUDE_CALIBRATION_DATA = '[Filters] Set use calbiration data in OPERA-S1 search',
- SET_GROUP_ID = '[Filters] Set Sentinel-1 Group ID'
+ SET_GROUP_ID = '[Filters] Set Sentinel-1 Group ID',
+ SET_SHORT_NAMES = '[Filters] Set Short Names',
+
+ SET_FRAME_COVERAGE = '[Filters] Set Frame Coverage',
+ SET_JOINT_OBSERVATION = '[Filters] Set Joint Observation',
+ SET_RANGE_BANDWIDTH = '[Filters] Set Range Bandwidth',
+ ADD_RANGE_BANDWIDTH = '[Filters] Add Range Bandwidth',
+ SET_INSTRUMENT = '[Filters] Set Instrument',
+ SET_SCIENCE_PRODUCT = '[Filters] Set Science Product',
+ SET_PRODUCTION_CONFIG = '[Filters] Set Production Config',
+
}
export class SetSelectedDataset implements Action {
@@ -231,6 +244,11 @@ export class SetProductTypes implements Action {
constructor(public payload: models.DatasetProductTypes) {}
}
+export class setShortNames implements Action {
+ public readonly type = FiltersActionType.SET_SHORT_NAMES;
+
+ constructor(public payload: models.DatasetShortName) {}
+}
export class SetListSearchType implements Action {
public readonly type = FiltersActionType.SET_LIST_SEARCH_TYPE;
@@ -279,6 +297,17 @@ export class SetPolarizations implements Action {
constructor(public payload: models.DatasetPolarizations) {}
}
+export class AddSidePolarization implements Action {
+ public readonly type = FiltersActionType.ADD_SIDE_POLARIZATION;
+
+ constructor(public payload: string) {}
+}
+
+export class SetSidePolarizations implements Action {
+public readonly type = FiltersActionType.SET_SIDE_POLARIZATIONS;
+
+ constructor(public payload: models.DatasetPolarizations) {}
+}
export class SetSubtypes implements Action {
public readonly type = FiltersActionType.SET_SUBTYPES;
@@ -452,9 +481,45 @@ export class setUseCalibrationData implements Action {
export class setGroupID implements Action {
public readonly type = FiltersActionType.SET_GROUP_ID;
- constructor(public payload: string) {}
+ constructor(public payload: string) {}
+}
+export class setFrameCoverage implements Action {
+ public readonly type = FiltersActionType.SET_FRAME_COVERAGE;
+
+ constructor(public payload: string[]) {}
}
+export class setJointObservation implements Action {
+ public readonly type = FiltersActionType.SET_JOINT_OBSERVATION;
+ constructor(public payload: boolean) {}
+}
+
+export class setRangeBandwidth implements Action {
+ public readonly type = FiltersActionType.SET_RANGE_BANDWIDTH;
+
+ constructor(public payload: string[]) {}
+}
+export class addRangeBandwidth implements Action {
+ public readonly type = FiltersActionType.ADD_RANGE_BANDWIDTH;
+
+ constructor(public payload: string) {}
+}
+export class setIntstrument implements Action {
+ public readonly type = FiltersActionType.SET_INSTRUMENT;
+
+ constructor(public payload: string[]) {}
+}
+export class setScienceProduct implements Action {
+ public readonly type = FiltersActionType.SET_SCIENCE_PRODUCT;
+
+ constructor(public payload: string[]) {}
+}
+
+export class setProductionConfig implements Action {
+ public readonly type = FiltersActionType.SET_PRODUCTION_CONFIG;
+
+ constructor(public payload: string[]) {}
+}
export type FiltersActions =
@@ -483,6 +548,7 @@ export type FiltersActions =
| SetFiltersSimilarTo
| ClearFrameRange
| SetProductTypes
+ | setShortNames
| SetListSearchType
| SetSearchList
| SetFlightDirections
@@ -492,6 +558,8 @@ export type FiltersActions =
| SetSubtypes
| AddPolarization
| SetPolarizations
+ | AddSidePolarization
+ | SetSidePolarizations
| ClearDatasetFilters
| ClearListFilters
| SetMissions
@@ -520,4 +588,11 @@ export type FiltersActions =
| setFullBurst
| setOperaBurstID
| setUseCalibrationData
- | setGroupID;
+ | setGroupID
+ | setFrameCoverage
+ | setRangeBandwidth
+ | addRangeBandwidth
+ | setJointObservation
+ | setIntstrument
+ | setScienceProduct
+ | setProductionConfig;
diff --git a/src/app/store/filters/filters.reducer.ts b/src/app/store/filters/filters.reducer.ts
index bfb1a1813..55403efa7 100644
--- a/src/app/store/filters/filters.reducer.ts
+++ b/src/app/store/filters/filters.reducer.ts
@@ -21,8 +21,10 @@ export interface FiltersState {
searchList: string[];
productTypes: models.DatasetProductTypes;
+ shortNames: models.DatasetShortName;
beamModes: models.DatasetBeamModes;
polarizations: models.DatasetPolarizations;
+ sidePolarizations: models.DatasetPolarizations;
flightDirections: Set;
subtypes: models.DatasetSubtypes;
jobStatuses: models.Hyp3JobStatusCode[];
@@ -51,9 +53,17 @@ export interface FiltersState {
fullBurstIDs: null | string[];
+ frameCoverage: string[];
+ jointObservation: boolean;
+ rangeBandwidth: string[];
+ instrument: string[];
+ scienceProduct: string[];
+ productionConfig: string[];
+
operaBurstIDs: null | string[];
useCalibrationData: boolean; // used to toggle OPERA-S1 Calval (calibration) datasets
+
groupID: null | string;
}
@@ -62,7 +72,7 @@ export type DateRangeState = models.Range;
export const initState: FiltersState = {
- selectedDatasetId: 'SENTINEL-1',
+ selectedDatasetId: 'NISAR',
dateRange: {
start: null,
end: null
@@ -94,6 +104,7 @@ export const initState: FiltersState = {
productTypes: [],
beamModes: [],
polarizations: [],
+ sidePolarizations: [],
subtypes: [],
flightDirections: new Set([]),
jobStatuses: [],
@@ -130,7 +141,15 @@ export const initState: FiltersState = {
operaBurstIDs: [],
useCalibrationData: false,
- groupID: null
+ frameCoverage: [],
+ jointObservation: false,
+ rangeBandwidth: [],
+ instrument: [],
+ scienceProduct: [],
+ productionConfig: [],
+
+ groupID: null,
+ shortNames: []
};
@@ -416,7 +435,16 @@ export function filtersReducer(state = initState, action: FiltersActions): Filte
fullBurstIDs: [],
operaBurstIDs: [],
useCalibrationData: false,
- groupID: null
+ groupID: null,
+ shortNames: [],
+ frameCoverage: [],
+ sidePolarizations: [],
+ jointObservation: false,
+ instrument: [],
+ rangeBandwidth: [],
+ scienceProduct: [],
+ productionConfig: [],
+
};
}
@@ -459,12 +487,25 @@ export function filtersReducer(state = initState, action: FiltersActions): Filte
};
}
+ case FiltersActionType.SET_SHORT_NAMES: {
+ return {
+ ...state,
+ shortNames: [ ...action.payload ]
+ };
+ }
+
case FiltersActionType.ADD_BEAM_MODE: {
return {
...state,
beamModes: [ ...state.beamModes, action.payload ]
};
}
+ case FiltersActionType.ADD_RANGE_BANDWIDTH: {
+ return {
+ ...state,
+ rangeBandwidth: [...new Set([...state.rangeBandwidth, action.payload])]
+ }
+ }
case FiltersActionType.SET_BEAM_MODES: {
return {
@@ -497,6 +538,23 @@ export function filtersReducer(state = initState, action: FiltersActions): Filte
polarizations: [ ...action.payload ]
};
}
+ case FiltersActionType.ADD_SIDE_POLARIZATION: {
+ const newPols = Array.from(
+ new Set([...state.sidePolarizations, action.payload])
+ );
+
+ return {
+ ...state,
+ sidePolarizations: [...newPols]
+ };
+ }
+
+ case FiltersActionType.SET_SIDE_POLARIZATIONS: {
+ return {
+ ...state,
+ sidePolarizations: [...action.payload]
+ };
+ }
case FiltersActionType.SET_SUBTYPES: {
return {
...state,
@@ -773,6 +831,42 @@ export function filtersReducer(state = initState, action: FiltersActions): Filte
groupID: action.payload
}
}
+ case FiltersActionType.SET_FRAME_COVERAGE: {
+ return {
+ ...state,
+ frameCoverage: action.payload
+ }
+ }
+ case FiltersActionType.SET_JOINT_OBSERVATION: {
+ return {
+ ...state,
+ jointObservation: action.payload
+ }
+ }
+ case FiltersActionType.SET_RANGE_BANDWIDTH: {
+ return {
+ ...state,
+ rangeBandwidth: action.payload
+ }
+ }
+ case FiltersActionType.SET_INSTRUMENT: {
+ return {
+ ...state,
+ instrument: action.payload
+ }
+ }
+ case FiltersActionType.SET_SCIENCE_PRODUCT: {
+ return {
+ ...state,
+ scienceProduct: action.payload
+ }
+ }
+ case FiltersActionType.SET_PRODUCTION_CONFIG: {
+ return {
+ ...state,
+ productionConfig: action.payload
+ }
+ }
default: {
return state;
}
@@ -881,6 +975,11 @@ export const getProductTypes = createSelector(
(state: FiltersState) => state.productTypes
);
+export const getShortNames = createSelector(
+ getFiltersState,
+ (state: FiltersState) => state.shortNames
+);
+
export const getBeamModes = createSelector(
getFiltersState,
(state: FiltersState) => state.beamModes
@@ -891,6 +990,11 @@ export const getPolarizations = createSelector(
(state: FiltersState) => state.polarizations
);
+export const getSidePolarizations = createSelector(
+ getFiltersState,
+ (state: FiltersState) => state.sidePolarizations
+);
+
export const getSubtypes = createSelector(
getFiltersState,
(state: FiltersState) => state.subtypes
@@ -946,7 +1050,8 @@ export const getGeographicSearch = createSelector(
selectedMission: state.selectedMission,
fullBurstIDs: state.fullBurstIDs,
operaBurstIDs: state.operaBurstIDs,
- useCalibrationData: state.useCalibrationData
+ useCalibrationData: state.useCalibrationData,
+ shortNames: state.shortNames
})
);
@@ -1072,3 +1177,30 @@ export const getGroupID = createSelector(
getFiltersState,
(state: FiltersState) => state.groupID
)
+
+export const getFrameCoverage = createSelector(
+ getFiltersState,
+ (state: FiltersState) => state.frameCoverage
+)
+
+export const getJointObservation = createSelector(
+ getFiltersState,
+ (state: FiltersState) => state.jointObservation
+)
+
+export const getRangeBandwidth = createSelector(
+ getFiltersState,
+ (state: FiltersState) => state.rangeBandwidth
+)
+export const getInstruments = createSelector(
+ getFiltersState,
+ (state: FiltersState) => state.instrument
+)
+export const getScienceProduct = createSelector(
+ getFiltersState,
+ (state: FiltersState) => state.scienceProduct
+)
+export const getProductionConfig = createSelector(
+ getFiltersState,
+ (state: FiltersState) => state.productionConfig
+)
diff --git a/src/app/store/map/map.effect.ts b/src/app/store/map/map.effect.ts
index 1144a0ea1..915982b5c 100644
--- a/src/app/store/map/map.effect.ts
+++ b/src/app/store/map/map.effect.ts
@@ -81,7 +81,8 @@ export class MapEffects {
|| dataset?.id === 'SENTINEL-1'
|| dataset?.id === 'SENTINEL-1 INTERFEROGRAM (BETA)'
|| dataset?.id === 'UAVSAR'
- || dataset?.id === 'OPERA-S1';
+ || dataset?.id === 'OPERA-S1'
+ || dataset?.id === 'NISAR';
}
return searchType !== SearchType.BASELINE && searchType !== SearchType.SBAS;
}),
@@ -98,7 +99,8 @@ export class MapEffects {
|| product.dataset === 'Sentinel-1A'
|| product.dataset === 'Sentinel-1B'
|| product.dataset === 'Sentinel-1 Interferogram (BETA)'
- || product.dataset === 'UAVSAR';
+ || product.dataset === 'UAVSAR'
+ || product.dataset === 'NISAR';
} else if (searchType === SearchType.CUSTOM_PRODUCTS) {
const failed = product.metadata.job?.status_code === models.Hyp3JobStatusCode.FAILED;
const running = product.metadata.job?.status_code === models.Hyp3JobStatusCode.RUNNING;
diff --git a/src/app/store/scenes/scenes.reducer.ts b/src/app/store/scenes/scenes.reducer.ts
index c34ebfe29..d1f2e9f8e 100644
--- a/src/app/store/scenes/scenes.reducer.ts
+++ b/src/app/store/scenes/scenes.reducer.ts
@@ -113,7 +113,7 @@ export function scenesReducer(state = initState, action: ScenesActions): ScenesS
if (product.metadata.subproducts.length > 0) {
groupCriteria = product.id;
- } else if(ungrouped_product_types.includes(product.metadata.productType)) {
+ } else if(ungrouped_product_types.includes(product.metadata.productType) || product.dataset === 'NISAR') {
if(isSubProduct(product)) {
groupCriteria = product.metadata.parentID;
} else {
@@ -567,7 +567,7 @@ const productsForScene = (selected, state) => {
const ungrouped_product_types = [...opera_s1.productTypes, {apiValue: 'BURST'}, {apiValue: 'BURST_XML'}].map(m => m.apiValue)
// if (Object.keys(productTypes).length <= 2 && Object.keys(productTypes)[0] === 'BURST') {
// products = state.scenes[selected.name] || [];
- if(ungrouped_product_types.includes(selected.metadata.productType)) {
+ if(ungrouped_product_types.includes(selected.metadata.productType) || selected.dataset === 'NISAR') {
products = state.scenes[selected.metadata.parentID ?? selected.id] || [];
}
else {
diff --git a/src/app/store/search/search.effect.ts b/src/app/store/search/search.effect.ts
index 306dd3471..218588f51 100644
--- a/src/app/store/search/search.effect.ts
+++ b/src/app/store/search/search.effect.ts
@@ -39,6 +39,7 @@ import { Feature } from 'ol';
import Geometry from 'ol/geom/Geometry';
import { FiltersActionType } from '@store/filters';
import { getIsFiltersMenuOpen, getIsResultsMenuOpen } from '@store/ui';
+import * as searchStore from '@store/search';
@Injectable()
export class SearchEffects {
private vectorSource = new VectorSource({
@@ -81,11 +82,45 @@ export class SearchEffects {
)
));
+ public onUpdateMaturity = createEffect(() => this.actions$.pipe(
+ ofType(SearchActionType.SET_SEARCH_OUT_OF_DATE),
+ withLatestFrom(this.searchParams$.getlatestParams),
+ map(([_, y]) => y),
+ debounceTime(200),
+ withLatestFrom(this.store$.select(getSearchType)),
+ filter(([_, searchType]) => searchType !== SearchType.SARVIEWS_EVENTS
+ && searchType !== SearchType.CUSTOM_PRODUCTS
+ && searchType !== SearchType.BASELINE
+ && searchType !== SearchType.SBAS),
+ map(([params, _]) => ({ ...params, output: 'COUNT' })),
+ tap(_ =>
+ this.store$.dispatch(new searchStore.SearchAmountLoading())
+ ),
+ switchMap(params => {
+ return this.asfApiService.query(params).pipe(
+ catchError(resp => {
+ const { error } = resp;
+ if (!resp.ok || error && error.includes('VALIDATION_ERROR')) {
+ return of(0);
+ }
+
+ return of(-1);
+ })
+ );
+ }
+ ),
+ map(searchAmount => {
+ const amount = +searchAmount;
+
+ this.store$.dispatch(new searchStore.SetSearchAmount(amount));
+ })
+ ), { dispatch: false });
+
public setEventSearchProductsOnClear = createEffect(() => this.actions$.pipe(
ofType(ScenesActionType.CLEAR),
withLatestFrom(this.store$.select(getSearchType)),
switchMap(([_, searchType]) => {
- if(searchType === SearchType.SARVIEWS_EVENTS) {
+ if (searchType === SearchType.SARVIEWS_EVENTS) {
return this.sarviewsService.getSarviewsEvents$
} else {
return of([])
@@ -149,13 +184,13 @@ export class SearchEffects {
public searchResponse = createEffect(() => this.actions$.pipe(
ofType(SearchActionType.SEARCH_RESPONSE),
switchMap(action => {
- let output : any[] = [
+ let output: any[] = [
new scenesStore.SetScenes({
products: action.payload.files,
searchType: action.payload.searchType
})
];
- if(action.payload.totalCount) {
+ if (action.payload.totalCount) {
output.push(new SetSearchAmount(action.payload.totalCount))
}
return output
@@ -191,7 +226,7 @@ export class SearchEffects {
}
}, []);
- const params = {'granule_list': (granuleNames).join(',')};
+ const params = { 'granule_list': (granuleNames).join(',') };
return this.asfApiService.query(params);
}),
@@ -277,6 +312,7 @@ export class SearchEffects {
job:null,
pgeVersion: null,
subproducts: [],
+ nisar: null,
parentID: "",
ariaVersion: null,
}
@@ -353,8 +389,8 @@ export class SearchEffects {
withLatestFrom(this.store$.select(getAreResultsLoaded)),
filter(([[[_, searchtype], outOfdate], loaded]) => !outOfdate && searchtype === models.SearchType.DATASET && loaded),
).pipe(
- map(_ => new SetSearchOutOfDate(true))
- ));
+ map(_ => new SetSearchOutOfDate(true))
+ ));
public setSearchUpToDate = createEffect(() => this.actions$.pipe(
ofType(SearchActionType.MAKE_SEARCH,
@@ -381,27 +417,27 @@ export class SearchEffects {
([params]) => forkJoin(
this.asfApiService.query(params)
).pipe(
- withLatestFrom(combineLatest([
- this.store$.select(getSearchType),
- this.store$.select(getIsCanceled)]
- )),
- map(([[response], [searchType, isCanceled]]) =>
- !isCanceled ?
- new SearchResponse({
- files: this.productService.fromResponse(response),
- searchType
- }) :
- new SearchCanceled()
- ),
- catchError(
- (err: HttpErrorResponse) => {
- if (err.status !== 400) {
- return of(new SearchError(`Unknown Error`));
- }
- return EMPTY;
+ withLatestFrom(combineLatest([
+ this.store$.select(getSearchType),
+ this.store$.select(getIsCanceled)]
+ )),
+ map(([[response], [searchType, isCanceled]]) =>
+ !isCanceled ?
+ new SearchResponse({
+ files: this.productService.fromResponse(response),
+ searchType
+ }) :
+ new SearchCanceled()
+ ),
+ catchError(
+ (err: HttpErrorResponse) => {
+ if (err.status !== 400) {
+ return of(new SearchError(`Unknown Error`));
}
- ),
- ))
+ return EMPTY;
+ }
+ ),
+ ))
);
public asfApiBaselineQuery$(): Observable {
@@ -558,32 +594,32 @@ export class SearchEffects {
job.files[0] :
{ size: -1, url: '', filename: product.name };
- const scene_keys = job.job_parameters.granules;
- job.job_parameters.scenes = [];
- for (const scene_key of scene_keys) {
- job.job_parameters.scenes.push(products[scene_key]);
- }
-
- const jobProduct = {
- ...product,
- browses: job.browse_images ? job.browse_images : ['assets/no-browse.png'],
- thumbnail: job.thumbnail_images ? job.thumbnail_images[0] : 'assets/no-thumb.png',
- productTypeDisplay: `${job.job_type}, ${product.metadata.productType} `,
- downloadUrl: jobFile.url,
- bytes: jobFile.size,
- groupId: job.job_id,
- id: job.job_id,
- isDummyProduct: true,
- metadata: {
- ...product.metadata,
- fileName: jobFile.filename || '',
- productType: job.job_type,
- job
- },
- };
+ const scene_keys = job.job_parameters.granules;
+ job.job_parameters.scenes = [];
+ for (const scene_key of scene_keys) {
+ job.job_parameters.scenes.push(products[scene_key]);
+ }
- return jobProduct
- });
+ const jobProduct = {
+ ...product,
+ browses: job.browse_images ? job.browse_images : ['assets/no-browse.png'],
+ thumbnail: job.thumbnail_images ? job.thumbnail_images[0] : 'assets/no-thumb.png',
+ productTypeDisplay: `${job.job_type}, ${product.metadata.productType} `,
+ downloadUrl: jobFile.url,
+ bytes: jobFile.size,
+ groupId: job.job_id,
+ id: job.job_id,
+ isDummyProduct: true,
+ metadata: {
+ ...product.metadata,
+ fileName: jobFile.filename || '',
+ productType: job.job_type,
+ job
+ },
+ };
+
+ return jobProduct
+ });
return virtualProducts;
}
diff --git a/src/app/store/user/user.reducer.ts b/src/app/store/user/user.reducer.ts
index bd06ea821..91a2d2a46 100644
--- a/src/app/store/user/user.reducer.ts
+++ b/src/app/store/user/user.reducer.ts
@@ -2,6 +2,7 @@ import { createFeatureSelector, createSelector } from '@ngrx/store';
import { UserActionType, UserActions } from './user.action';
import * as models from '@models';
+import jwt_decode from 'jwt-decode';
/* State */
export interface UserState {
@@ -21,7 +22,7 @@ export const initState: UserState = {
groups: []
},
profile: {
- defaultDataset: 'SENTINEL-1',
+ defaultDataset: 'NISAR',
mapLayer: models.MapLayerTypes.SATELLITE,
maxResults: 250,
defaultMaxConcurrentDownloads: 3,
@@ -250,6 +251,17 @@ export const getIsUserLoggedIn = createSelector(
(state: UserState) => !!state.auth.id
);
+export const getUserEDLToken = createSelector(
+ getUserState,
+ (state: UserState) => {
+ if (state.auth.token) {
+ const decoded = jwt_decode(state.auth.token)
+ return decoded['urs-access-token'] ?? null
+ }
+ return null;
+ }
+);
+
export const getSavedSearches = createSelector(
getUserState,
(state: UserState) => state.savedSearches.searches
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json
index 4b955ba63..ac0071a73 100644
--- a/src/assets/i18n/en.json
+++ b/src/assets/i18n/en.json
@@ -16,13 +16,14 @@
"ADD_ALL_RESULTS_TO_DOWNLOADS": "Add all results to downloads",
"ADD_ALL_RESULTS_TO_ON_DEMAND_QUEUE": "Add all results to On Demand queue",
"ADD_BEAM_MODE_TO_SEARCH": "Add beam mode to search",
+ "ADD_BY_FILE_TYPE": "Add by file type",
"ADD_BY_PRODUCT_TYPE": "Add by product type",
"ADD_FILE_TO_DOWNLOADS": "Add file to downloads",
"ADD_FILE_TO_QUEUE": "Add file to queue",
"ADD_JOB": "Add job",
"ADD_MAIN_POLARIZATION_TO_SEARCH": "Add main polarization to search",
"ADD_PAIR_TO_ON_DEMAND_QUEUE": "Add pair to On Demand queue",
- "ADD_POINTS": "Add",
+ "ADD_POINTS": "Add points",
"ADD_POLARIZATION_TO_SEARCH": "Add polarization to search",
"ADD_RANGE_BANDWIDTH_TO_SEARCH": "Add range bandwidth to search",
"ADD_SCENE_FILES_TO_DOWNLOADS": "Add scene files to downloads",
@@ -75,6 +76,7 @@
"ASF_DATA_SEARCH": "ASF Data Search",
"ASF_DATA_SEARCH_TITLE": "ASF Data Search\n",
"ASF_SEARCH_API": "ASF Search API",
+ "ASF_SEARCH_DOCS": "ASF Search Docs",
"ASF_SEARCH_PYTHON_EXPORT": "ASF Search Python Export",
"ASF_WEBSITE": "ASF Website",
"ASPECT_RATIO": "aspect_ratio",
@@ -154,6 +156,7 @@
"COPY_FILE_ID_TO_CLIPBOARD": "Copy File IDs to clipboard",
"COPY_FILE_IDS": "Copy File IDs",
"COPY_FILE_URLS_TO_CLIPBOARD": " Copy File URLs to clipboard",
+ "COPY_JOB_ID": "Copy Job ID",
"COPY_NAME": "Copy Name",
"COPY_REFERENCE_SCENE_NAMES_TO_CLIPBOARD": "Copy reference scene names to clipboard",
"COPY_SCENE_NAME": "Copy scene name",
@@ -180,9 +183,11 @@
"CUMULATIVE_LAYER": "Cumulative Layer",
"CURRENT_SARVIEWS_PRODUCT_FILES_PRODUCT_SIZE_TO_STRING": "currentSarviewsProduct.files.product_size.toString()",
"CUSTOM_PAIR": "Custom Pair",
+ "CUSTOM_VALIDATION": "Custom Validation",
"CUSTOMIZE_ENVIRONMENTS": "Customize Environments",
"DARK": "Dark",
"DATA": "Data",
+ "DATA_COURTESY": "Data courtesy of OPERA",
"DATA_COURTESY_OF": "Data courtesy of",
"DATA_DOWNLOAD": "Data Download",
"DATA_DOWNLOAD_IS_USED_TO_DOWNLOAD_MULTIPLE_PRODUCTS_WITH_EITHER_THE": "Data Download is used to download multiple products, with either the",
@@ -233,6 +238,7 @@
"DEVELOPER": "Developer",
"DIRECTION": "Direction",
"DISABLE": "Disable",
+ "DISP_DOI": "DISP DOI",
"DISPLACEMENT": "Displacement",
"DISPLACEMENT_DESCRIPTION": "Displacement products provide information on anthropogenic and natural changes of Earth's surface, covering North America.",
"DISPLACEMENT_FILTERS": "Displacement Filters",
@@ -337,6 +343,7 @@
"FRAME_COVERAGE": "Frame Coverage",
"FRAME_END": "Frame End",
"FRAME_START": "Frame Start",
+ "FRAMES_SELECTED": "frames selected",
"FREQUENCY": "Frequency",
"FULL": "Full",
"FULL_BURST_ID": "Full Burst ID",
@@ -382,6 +389,8 @@
"HTTPS_URS_EARTHDATA_NASA_GOV_USERS_NEW": "https://urs.earthdata.nasa.gov/users/new",
"HY_P3_API_URL": "HyP3 API URL",
"HY_P3_USER_GUIDE": "HyP3 User Guide",
+ "HYP3_JOB_IDS_INFO_BAR": "HYP3 Job IDs Info Bar",
+ "HYP3_SDK_DOCS": "HyP3 SDK Docs",
"I_DS": "IDs",
"IF_YOU_ARE_LOGGED_INTO_VERTEX_CLICKING_ON_THE_CART_ICON_IN_THE_HEADER_LABELED_DOWNLOADS": "If you are logged into Vertex, Clicking on the cart icon in the header, labeled Downloads,",
"IF_YOU_DO_NOT_ALREADY_HAVE_ONE_REGISTER_FOR_A_FREE_EARTHDATA_LOGIN_ACCOUNT": "If you do not already have one, register for a free Earthdata Login account.",
@@ -430,6 +439,7 @@
"JERS_DESC": "The JERS-1 (Japanese Earth Resources Satellite) SAR is a high-resolution, all-weather imaging radar. Data uses: land surveys, agriculture, forestry, fisheries, environmental...",
"JOB": "job",
"JOB_FILTERS": "Job Filters",
+ "JOB_IDS_SELECTOR": "Job IDs Selector",
"JOB_MAX": "job max",
"JOB_STATUS": "Job Status",
"JOB_SUBMITTED": "Job Submitted",
@@ -439,6 +449,7 @@
"JOBS_NOW": "jobs now",
"JOBS_PER_MONTH": "jobs per month",
"JOINT_OBSERVATION_ONLY": "Joint Observation Only",
+ "JOINT_OBSERVATION_ONLY_TOOLTIP": "Toggle on for simultaneous L- and S-band acquisitions",
"JUN_JUL_AUG": "Jun, Jul, Aug",
"KML": "kml",
"LANGUAGE": "Language",
@@ -448,10 +459,12 @@
"LEARN_MORE_ABOUT_ASF_AND_SAR": "Learn More About ASF & SAR",
"LEARN_THE_BASICS": "Learn the Basics",
"LEFTMOST_COLUMN_OF_THE_RESULTS_PANEL": "leftmost column of the results panel.",
+ "LICENSE": "License",
"LIGHT": "Light",
"LINE": "Line",
"LINE_DRAW": "Line draw",
"LINE_POLYGON_AND_BOUNDING_BOX": "line, polygon, and bounding box.",
+ "LINEAR_FIT_NOT_AVAILABLE": "Linear fit not available",
"LINK": "link",
"LIST": "List",
"LIST_OF": "List of",
@@ -470,6 +483,7 @@
"LOOKS_OTHER": "Looks Other",
"MAGNITUDE": "Magnitude",
"MAIN": "Main",
+ "MAIN_BAND_FREQ_A_POLARIZATION": "Main Band (Freq. A) Polarization",
"MAIN_POLARIZATIONS": "Main Polarizations",
"MAKE_SURE_YOU_ARE_LOGGED_INTO_VERTEX": "Make sure you are logged into Vertex.",
"MAKE_SURE_YOU_ARE_LOGGED_INTO_VERTEX_SEARCHES_CANNOT_BE_SAVED_AND_SEARCH_HISTORY_CANNOT_BE": "Make sure you are logged into Vertex. Searches cannot be saved and search history cannot be",
@@ -508,9 +522,10 @@
"NEW_DATE_GET_TIME_EVENT_GTM_JS_VAR_F_D_GET_ELEMENTS_BY_TAG_NAME_S": "new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],",
"NEW_END_DATE": "New End Date'\n",
"NEXT": "Next",
- "NISAR_DESC ": "NISAR provides L- and S-band SAR data to measure Earth's changing ecosystems, dynamic surfaces, and ice masses with 12-day regularity on ascending and descending passes.",
+ "NISAR_DESC": "NISAR provides L- and S-band SAR data to measure Earth's changing ecosystems, dynamic surfaces, and ice masses with 12-day regularity on ascending and descending passes.",
"NO OVERLAP THRESHOLD": "No Overlap Threshold",
"NO_AREA_ON_INTEREST_SPECIFIED": "No area of interest specified.",
+ "NO_BANDWITH_TO_SELECT": "no range bandwidths to select",
"NO_BEAM_MODES_TO_SELECT": "No beam modes to select",
"NO_CREDITS_LEFT_THIS_MONTH": "No credits left this month",
"NO_FILE_TYPES_TO_SELECT": "No file types to select",
@@ -518,6 +533,7 @@
"NO_FLIGHT_DIRECTION_SELECTED": "No flight directions selected",
"NO_FLIGHT_DIRECTIONS_TO_SELECT": "No flight directions to select",
"NO_FRAME_INPUT": "No frame input",
+ "NO_FRAMES_TO_SELECT": "no frames to select",
"NO_JOBS_LEFT_THIS_MONTH": "No jobs left this month",
"NO_MOBILE_DISPLACEMENT_SEARCH": "Displacement Searches are not available on small screens.",
"NO_NAME": "No Name",
@@ -532,7 +548,9 @@
"NO_SCENE_SELECTED": "No Scene Selected",
"NO_SUBTYPES_TO_SELECT": "No subtypes to select",
"NO_SUITABLE_PRODUCTS_FOR_THIS_TOOL": "No suitable products for this tool",
+ "NO_VALID_DATA_FOR_POINT": "No valid data for point.",
"NON_DISCRIMINATION": "Non-Discrimination",
+ "NONE": "None",
"NOT_ABLE_TO_SELECT_SIMILAR_SCENES_FROM_THIS_SOURCE": "Not able to select similar scenes from this source",
"NOT_ALL_FILTERS_WILL_BE_AVAILABLE_FOR": "Not all filters will be available for",
"NOTE_IN_VERTEX_A_SCENE_IS_CONSIDERED_TO_BE_A_PACKAGE_CONTAINING_ALL_FILES_OR_PRODUCTS": "Note: In Vertex, a scene is considered to be a package containing all files, or products,",
@@ -631,6 +649,8 @@
"PRODUCT_TYPE": "Product Type",
"PRODUCT_TYPES": "Product Types",
"PRODUCTION": "Production",
+ "PRODUCTION_CONFIGURATION": "Production Configuration",
+ "PRODUCTION_CONFIGURATION_FILTER": "Production Configuration Filter",
"PRODUCTS_IN_YOUR_QUEUE_MAY_REQUIRE_A_RESTRICTED_DATASET_AGREEMENT": "Products in your queue may require a restricted dataset agreement.",
"PRODUCTS_TO_DOWNLOADS_FROM_SELECTED_EVENT": "products to downloads from selected event",
"PROFILE": "Profile",
@@ -648,6 +668,7 @@
"RADIO_BUTTON_UNCHECKED": "radio_button_unchecked",
"RADIOMETRY": "Radiometry",
"RANGE_BANDWIDTH": "Range Bandwidth",
+ "RANGE_BANDWITH_SELECTED": "range bandwidths selected",
"RAW": "Raw",
"READ_OUR_ON_DEMAND_GUIDE": "Read Our On Demand Guide",
"READ_OUR_USER_GUIDE": "Read Our User Guide",
@@ -723,8 +744,11 @@
"SCENE_START_TIME": "Scene Start Time",
"SCENES": "Scenes",
"SCENES_THE_LEFT_COLUMN": "Scenes - the left column",
+ "SCIENCE_PRODUCT": "Science Product",
"SCRIPTS_FOR_ACCESSING_SAR_DATA": "scripts for accessing SAR data.",
"SCROLL_THROUGH_THE_LIST_OF_RESULTS_AND_YOU_SEE_SOME_FILES_HAVE_AN_ICON_OF_THREE_GRAY_SQUARES_NEXT": "Scroll through the list of results and you see some files have an icon of three gray squares next",
+ "SDK_PYTHON_CODE_EXPORT": "Export SDK Python Code",
+ "SDK_PYTHON_CODE_EXPORT_TOOLTIP": "SDK Python code export tooltip",
"SEA_ICE_MEASURES": "Sea Ice MEaSUREs",
"SEARCH": "Search",
"SEARCH_AREA": "Search Area",
@@ -762,6 +786,7 @@
"SENTINEL_DESC": "Sentinel-1 includes twin satellites that each carry C-band synthetic aperture radar (SAR), together providing all-weather, day-and-night imagery of Earth’s surface.",
"SEP_OCT_NOV": "Sep, Oct, Nov",
"SERIES": "Series",
+ "SERIES_UNDEFINED": "Series undefined",
"SET": "Set",
"SET_AS_BASELINE": "Set as Baseline",
"SET_AS_BOTH": "Set as both",
@@ -792,6 +817,7 @@
"SHOW_PRODUCT_FILTERS_CRITERIA": "Show product filters criteria",
"SHOW_RAW_DATA": "Show raw data",
"SIDE": "Side",
+ "SIDE_BAND_FREQ_B_POLARIZATION": "Side Band (Freq. B) Polarization",
"SIDE_POLARIZATIONS": "Side Polarizations",
"SIGMA0": "sigma0",
"SIGN_IN": "Sign In",
@@ -852,6 +878,7 @@
"TEMPORAL": "Temporal",
"TEMPORAL_CRITERIA": "Temporal Criteria:",
"TEST": "Test",
+ "TEST_1_1": "TEST 1.1",
"THAT_ARE_RELATED_TO_A_SPECIFIC_LOCATION_AND_TIME": "that are related to a specific location and time.",
"THE_BASELINE_TOOL_BUTTON_OPENS_THE_ASF_BASELINE_TOOL_WHICH_IS_USED_FOR_THE_CREATION_OF_IN_SAR_STACKS": "The 'Baseline Tool' button opens the ASF Baseline Tool, which is used for the creation of InSAR stacks.",
"THE_CART_CHANGES_APPEARANCE_WHEN_THIS_IS_DONE": "The cart changes appearance when this is done.",
@@ -884,6 +911,7 @@
"TOOLS": "Tools",
"TOOLTIP": "TOOLTIP",
"TRACK": "Track",
+ "TRACK_AND_FRAME_FILTERS": "Track and Frame Filters",
"TRACK_END": "Track End",
"TRACK_START": "Track Start",
"TRAVEL_EXPLORE": "travel_explore",
@@ -896,6 +924,7 @@
"UPLOAD_AOI_VIA_FILE": "Upload AOI via file",
"UPLOAD_GEOSPATIAL_FILE": "Upload Geospatial File",
"UR_LS": "URLs",
+ "URGENT_RESPONSE": "Urgent Response",
"USE_AN_ASF_SEARCH_API_QUERY_TO_DOWNLOAD_MORE_RESULTS_MANUALLY": "Use an ASF Search API query to download more results manually.",
"USE_THE_AREA_OF_INTEREST_BUTTONS_TO_TOGGLE_DRAWING_ON_THE_MAP_ON_AND_OFF_TO_EDIT_THE_SHAPE": "Use the 'Area of Interest' buttons to toggle drawing on the map on and off, to edit the shape",
"USE_THE_MAP_PROJECTION_BUTTONS_IN_THE_MAP_TOOLBAR_TO_TOGGLE_BETWEEN_THE_ARCTIC_EQUATORIAL": "Use the 'Map Projection' buttons in the map toolbar to toggle between the Arctic, Equatorial,",
@@ -973,6 +1002,7 @@
"YOUR_DOWNLOAD_QUEUE_IS_EMPTY": "Your download queue is empty.",
"YOUR_JOBS_QUEUE_IS_EMPTY": "Your jobs queue is empty.",
"YOUR_SEARCH_AND_REDUCE_THE_NUMBER_OF_RESULTS": "your search and reduce the number of results.",
+ "YOUR_SEARCH_AND_REDUCE_THE_NUMBER_OF_RESULTS_NOT_ALL_FILTERS_WILL_BE_AVAILABLE_FOR": "Your search and reduce the number of results. Not all filters will be available for",
"YOUR_SELECTION_TO_A_VALID_RANGE_FOR_THE_SELECTED_DATASET": "your selection to a valid range for the selected dataset.",
"ZIPPED_FILES_WILL_BE_DENOTED_BY_A_RIGHT_POINTING_CARET_TO_THE_LEFT_OF_THE_FILENAME_CLICKING_THE_CARET": "Zipped files will be denoted by a right-pointing caret to the left of the filename. Clicking the caret",
"ZOOM": "Zoom",
@@ -983,4 +1013,4 @@
"ZOOM_TO_FIT": "Zoom To Fit",
"ZOOM_TO_RESULTS": "Zoom to results",
"ZOOM_TO_SCENE": "Zoom to scene"
-}
\ No newline at end of file
+}
diff --git a/src/assets/i18n/es.json b/src/assets/i18n/es.json
index 336e8ec21..00437426d 100644
--- a/src/assets/i18n/es.json
+++ b/src/assets/i18n/es.json
@@ -16,13 +16,14 @@
"ADD_ALL_RESULTS_TO_DOWNLOADS": "Agregar todos los resultados a las descargas",
"ADD_ALL_RESULTS_TO_ON_DEMAND_QUEUE": "Agregar todos los resultados a la lista de On Demand",
"ADD_BEAM_MODE_TO_SEARCH": "Agregar modo de haz para buscar",
+ "ADD_BY_FILE_TYPE": "Agregar por tipo de archivo",
"ADD_BY_PRODUCT_TYPE": "Añadir por tipo de producto",
"ADD_FILE_TO_DOWNLOADS": "Agregar archivo a las descargas",
"ADD_FILE_TO_QUEUE": "Agregar archivo a la lista",
"ADD_JOB": "Agregar trabajo",
"ADD_MAIN_POLARIZATION_TO_SEARCH": "Agregar polarización principal a la búsqueda",
"ADD_PAIR_TO_ON_DEMAND_QUEUE": "Agregar par a la lista On Demand",
- "ADD_POINTS": "Agregar",
+ "ADD_POINTS": "Agregar puntos",
"ADD_POLARIZATION_TO_SEARCH": "Agregar polarización a la búsqueda",
"ADD_RANGE_BANDWIDTH_TO_SEARCH": "Agregar ancho de banda de rango a la búsqueda",
"ADD_SCENE_FILES_TO_DOWNLOADS": "Agregar archivos de escena a las descargas",
@@ -73,8 +74,9 @@
"ARROW_FORWARD": "flecha_adelante",
"ASCENDING": "Ascendente",
"ASF_DATA_SEARCH": "Búsqueda de datos ASF",
- "ASF_DATA_SEARCH_TITLE": "Búsqueda de datos ASF",
+ "ASF_DATA_SEARCH_TITLE": "Título de búsqueda de datos ASF",
"ASF_SEARCH_API": "API de búsqueda ASF",
+ "ASF_SEARCH_DOCS": "Documentos de búsqueda de ASF",
"ASF_SEARCH_PYTHON_EXPORT": "Exportación de Python de búsqueda ASF",
"ASF_WEBSITE": "Sitio web de la ASF",
"ASPECT_RATIO": "relación_de_aspecto",
@@ -104,7 +106,7 @@
"BROWSE_IMAGE_OPACITY": "Browse Image Opacity",
"BUILD_COMMIT": "Confirmación de compilación",
"BURST_ID_ABSOLUTE": "ID de Burst Absoluta",
- "BURST_ID_FULL": "ID de Burst Completa",
+ "BURST_ID_FULL": "ID de Burst Completo",
"BURST_ID_RELATIVE": "ID de Burst Relativa",
"BURST_INDEX": "Índice de Burst",
"BUTTONS_BASELINE_TOOL_AND_SBAS_TOOL_CLICK_THE_BASELINE_TOOL_BUTTON_TO_PERFORM_A_BASELINE_SEARCH": "Botones: 'Herramienta de Línea Base' y 'Herramienta SBAS'. Haga clic en el botón 'Herramienta de Línea Base' para realizar una búsqueda de Línea Base.",
@@ -154,6 +156,7 @@
"COPY_FILE_ID_TO_CLIPBOARD": "Copiar ID de Archivo al portapapeles",
"COPY_FILE_IDS": "Copiar ID de archivos",
"COPY_FILE_URLS_TO_CLIPBOARD": " Copiar URL de Archivo al portapapeles",
+ "COPY_JOB_ID": "Copiar ID de tarea",
"COPY_NAME": "Copiar Nombre",
"COPY_REFERENCE_SCENE_NAMES_TO_CLIPBOARD": "Copie los nombres de las escenas de referencia en el portapapeles",
"COPY_SCENE_NAME": "Copiar nombre de escena",
@@ -180,13 +183,15 @@
"CUMULATIVE_LAYER": "Capa Acumulativa",
"CURRENT_SARVIEWS_PRODUCT_FILES_PRODUCT_SIZE_TO_STRING": "currentSarviewsProduct.files.product_size.toString()",
"CUSTOM_PAIR": "Par personalizado",
+ "CUSTOM_VALIDATION": "Validación Personalizada",
"CUSTOMIZE_ENVIRONMENTS": "Personalizar Entornos",
"DARK": "Oscuro",
"DATA": "Datos",
+ "DATA_COURTESY": "Datos cortesía de OPERA",
"DATA_COURTESY_OF": "Datos Cortesía de",
"DATA_DOWNLOAD": "Descarga de Datos",
"DATA_DOWNLOAD_IS_USED_TO_DOWNLOAD_MULTIPLE_PRODUCTS_WITH_EITHER_THE": "Descarga de datos se utiliza para descargar varios productos, ya sea con el",
- "DATA_FILTERS": "Filtros de Fecha",
+ "DATA_FILTERS": "Filtros de Datos",
"DATA_TYPE": "Tipo de Dato",
"DATASET": "Conjunto de Datos",
"DATASET_INFO": "Información del conjunto de datos",
@@ -224,7 +229,7 @@
"DERIVED_DATASETS": "Set de Datos Derivados",
"DERIVED_DATASETS_1": "Set de Datos Derivados",
"DERIVED_DATASETS_CONTAIN_A_COLLECTION_OF_DATASETS_AVAILABLE_TO_VIEW_AND_DOWNLOAD": "Los conjuntos de datos derivados contienen una colección de conjuntos de datos disponibles para ver y descargar.",
- "DESCENDING": "Descendiendo",
+ "DESCENDING": "Descendente",
"DESCRIP_GLOBAL_SEASONAL_SENTINEL": "Este conjunto de datos es la primera representación espacial de este tipo de retrodispersión y coherencia interferométrica de paso repetido de SAR global y multiestacional. La cobertura mundial comprende todas las masas terrestres y capas de hielo desde los 82 grados de latitud norte hasta los 78 grados de latitud sur. El conjunto de datos se deriva del procesamiento interferométrico de paso repetido multitemporal de alta resolución de aproximadamente 205 000 datos Sentinel-1 Single-Look-Complex (SLC) adquiridos en el modo Interferometric Wide-Swath (modo Sentinel-1 IW) del 1 de diciembre al 2019 al 30-nov-2020.",
"DESCRIPTION_RADIOMETRIC_TERRAIN_CORRECTION": "La Corrección Radiométrica del Terreno (RTC) elimina las distorsiones geométricas y radiométricas en los conjuntos de datos SAR y crea datos listos para el análisis adecuados para su uso en aplicaciones GIS.",
"DETAIL": "Detalle",
@@ -233,6 +238,7 @@
"DEVELOPER": "Desarrollador",
"DIRECTION": "Dirección",
"DISABLE": "Desactivar",
+ "DISP_DOI": "DOI de desplazamiento",
"DISPLACEMENT": "Desplazamiento",
"DISPLACEMENT_DESCRIPTION": "Los productos de desplazamiento proporcionan información sobre los cambios antropogénicos y naturales en la superficie de la Tierra, cubriendo América del Norte.",
"DISPLACEMENT_FILTERS": "Filtros de desplazamiento",
@@ -325,8 +331,8 @@
"FIND_SAR_DATA_USING_ASF_API": "Encuentre datos SAR utilizando la API de ASF",
"FLIGHT_DIR": "Dirección de vuelo",
"FLIGHT_DIRECTION": "Dirección del Vuelo",
- "FLIGHT_DIRECTION_SELECTED": "Dirección de vuelo seleccionada",
- "FLIGHT_DIRECTIONS_SELECTED": "direcciones de vuelo seleccionadas",
+ "FLIGHT_DIRECTION_SELECTED": "Dirección de vuelo elegido",
+ "FLIGHT_DIRECTIONS_SELECTED": "direcciones de vuelo elegidos",
"FLIGHT_LINE": "Línea de Vuelo",
"FOR_EXAMPLE_THIS_LIST_COULD_THEN_BE_PASTED _INTO_THE ": "Por ejemplo, esta lista se podría pegar en el",
"FOR_EXAMPLE_THIS_LIST_COULD_THEN_BE_PASTED_INTO_THE_SCENE_LIST_SEARCH_WINDOW": "Por ejemplo, esta lista se podría pegar en la ventana de búsqueda de la lista de escenas.",
@@ -337,9 +343,10 @@
"FRAME_COVERAGE": "Cobertura del Marco",
"FRAME_END": "Fin del Marco",
"FRAME_START": "Inicio del Marco",
+ "FRAMES_SELECTED": "marcos coincidentes",
"FREQUENCY": "Frecuencia",
"FULL": "Completo",
- "FULL_BURST_ID": "ID de Burst Completa",
+ "FULL_BURST_ID": "ID de Burst Completo",
"GAMMA0": "gamma0",
"GAPS_DETECTED": "Brechas Detectadas",
"GEO_SEARCH": "Búsqueda Geográfica",
@@ -348,7 +355,7 @@
"Geographic Search": "Búsqueda Geográfica",
"GEOGRAPHIC_SEARCH": "Búsqueda Geográfica",
"GEOGRAPHIC_SEARCH_ALLOWS_YOU_TO_SEARCH_FOR_DATA_BASED_UPON_A_GEOGRAPHIC_LOCATION": "La búsqueda geográfica le permite buscar datos basados en una ubicación geográfica.",
- "GEOGRAPHIC_SEARCH_BASED_ON_BURST": "Búsqueda geográfica basada en el ID de ráfaga completa de este producto de ráfaga.\n\n\n\n\n\n\n\n",
+ "GEOGRAPHIC_SEARCH_BASED_ON_BURST": "Búsqueda geográfica basada en el ID de Burst completo de este producto de Burst.",
"GEOGRAPHIC_SEARCH_BASED_ON_EVENT_POLYGON": "Búsqueda geográfica basada en el polígono del evento",
"GEOGRAPHIC_SEARCH_BASED_ON_THIS_SCENE_S_PATH_FRAME": "Búsqueda geográfica basada en la ruta/marco de esta(s) escena(s)",
"GEOGRAPHIC_SEARCH_POLYGON_SCALE": "Escala poligonal de búsqueda geográfica",
@@ -382,6 +389,8 @@
"HTTPS_URS_EARTHDATA_NASA_GOV_USERS_NEW": "https://urs.earthdata.nasa.gov/users/new",
"HY_P3_API_URL": "URL de la API de HyP3",
"HY_P3_USER_GUIDE": "Guía del usuario de HyP3",
+ "HYP3_JOB_IDS_INFO_BAR": "Barra informativa de ID de tareas HYP3",
+ "HYP3_SDK_DOCS": "Documentos del SDK de HyP3",
"I_DS": "identificaciones",
"IF_YOU_ARE_LOGGED_INTO_VERTEX_CLICKING_ON_THE_CART_ICON_IN_THE_HEADER_LABELED_DOWNLOADS": "Si ha iniciado sesión en Vertex, al hacer clic en el ícono del carrito en el encabezado, denominado Descargas,",
"IF_YOU_DO_NOT_ALREADY_HAVE_ONE_REGISTER_FOR_A_FREE_EARTHDATA_LOGIN_ACCOUNT": "Si aún no tiene una, regístrese para obtener una cuenta gratuita de inicio de sesión de Earthdata.",
@@ -416,7 +425,7 @@
"INSAR_DESC": "El procesamiento del radar interferométrico de apertura sintética (InSAR) utiliza dos imágenes SAR recopiladas en la misma área para determinar las propiedades geométricas de la superficie. Las mediciones de fase de las dos imágenes adquiridas en diferentes momentos se diferencian para detectar y cuantificar cambios en la superficie.",
"INSTRUMENT": "Instrumento",
"INSTRUMENTS": "Instrumentos",
- "INSTRUMENTS_SELECTED": "instrumentos seleccionados",
+ "INSTRUMENTS_SELECTED": "instrumentos elegidos",
"INVALID_BASELINE": "Línea de base no válida",
"INVALID_END_DAY": "Día de finalización no válido",
"INVALID_START_DAY": "Día de inicio no válido",
@@ -431,6 +440,7 @@
"JERS_DESC": "El JERS-1 (Japanese Earth Resources Satellite) SAR es un radar de imágenes de alta resolución y para todo tipo de clima. Usos de los datos: estudios de tierra, agricultura, silvicultura, pesca, medio ambiente...",
"JOB": "trabajo",
"JOB_FILTERS": "Filtros de Trabajo",
+ "JOB_IDS_SELECTOR": "Selector de ID de tareas",
"JOB_MAX": "trabajos Max",
"JOB_STATUS": "Estado del Trabajo",
"JOB_SUBMITTED": "Trabajo Enviado",
@@ -440,6 +450,7 @@
"JOBS_NOW": "trabajos ahora",
"JOBS_PER_MONTH": "trabajos por mes",
"JOINT_OBSERVATION_ONLY": "Solo Observación Conjunta",
+ "JOINT_OBSERVATION_ONLY_TOOLTIP": "Activar para adquisiciones simultáneas de banda L y S",
"JUN_JUL_AUG": "Jun, Jul, Ago",
"KML": "kml",
"LANGUAGE": "Idioma",
@@ -449,10 +460,12 @@
"LEARN_MORE_ABOUT_ASF_AND_SAR": "Obtenga más información sobre ASF y SAR",
"LEARN_THE_BASICS": "Aprenda lo básico",
"LEFTMOST_COLUMN_OF_THE_RESULTS_PANEL": "columna más a la izquierda del panel de resultados.",
+ "LICENSE": "Licencia",
"LIGHT": "Claro",
"LINE": "Línea",
"LINE_DRAW": "Dibujar Línea",
"LINE_POLYGON_AND_BOUNDING_BOX": "línea, polígono y rectángulo delimitador.",
+ "LINEAR_FIT_NOT_AVAILABLE": "Ajuste lineal no disponible",
"LINK": "enlace",
"LIST": "Lista",
"LIST_OF": "Lista de",
@@ -462,13 +475,16 @@
"LOADING": "Cargando...",
"LOADING_FILES": "Cargando archivos...",
"LOGIN": "Iniciar sesión",
- "LOGIN_TO_VIEW_NUMBER_OF_CREDITS_LEFT_THIS_MONTH": "inicie sesión para ver el número de créditos que quedan este mes",
- "LOGIN_TO_VIEW_NUMBER_OF_JOBS_LEFT_THIS_MONTH": "inicie sesión para ver la cantidad de trabajos que restan este mes",
+ "LOGIN_TO_VIEW": "inicie sesión para ver",
+ "LOGIN_TO_VIEW_NUMBER_OF_CREDITS_LEFT_THIS_MONTH": "inicie sesión para ver el número de créditos que restan este mes",
+ "LOGIN_TO_VIEW_NUMBER_OF_JOBS_LEFT_THIS_MONTH": "inicie sesión para ver la cantidad de trabajos que restan este mes",
+ "LOOKING_FOR_DEMS": "Buscando DEMs",
"LOOKS TWO": "parece_dos",
"LOOKS_MANY": "parece_uno",
"LOOKS_OTHER": "parece_uno",
"MAGNITUDE": "Magnitud",
"MAIN": "Principal",
+ "MAIN_BAND_FREQ_A_POLARIZATION": "Polarización de Banda Principal (Frecuencia A)",
"MAIN_POLARIZATIONS": "Polarizaciones Principales",
"MAKE_SURE_YOU_ARE_LOGGED_INTO_VERTEX": "Asegúrese de haber iniciado sesión en Vertex.",
"MAKE_SURE_YOU_ARE_LOGGED_INTO_VERTEX_SEARCHES_CANNOT_BE_SAVED_AND_SEARCH_HISTORY_CANNOT_BE": "Asegúrese de haber iniciado sesión en Vertex. Las búsquedas no pueden guardarse y el historial de búsqueda no puede ser",
@@ -500,7 +516,6 @@
"MORE_LIKE_THIS_BUTTON_IF_THE_SCENE_IS_SUITABLE_FOR_INTERFEROMETRY_THERE_WILL_BE_TWO_ADDITIONAL": "Botón 'Más como esto'. Si la escena es adecuada para interferometría, habrá dos adicionales\n\n\n\n\n\n\n\n",
"MORE_OPTIONS": "Más opciones",
"MUST_BE_LOGGED_IN": "Debe iniciar sesión",
- "N_A_LOGIN_TO_VIEW": "N/A - inicie sesión para ver",
"NAME": "Nombre",
"NAVIGATE_TO_YOUR_AREA_OF_INTEREST": "Navegue a su área de interés",
"NAVIGATE_TO_YOUR_AREA_OF_INTEREST_BY_DRAGGING_THE_MAP_WHILE_HOLDING_DOWN_THE_LEFT_MOUSE_BUTTON": "Navegue hasta su área de interés arrastrando el mapa mientras mantiene presionado el botón izquierdo del mouse.",
@@ -508,9 +523,10 @@
"NEW_DATE_GET_TIME_EVENT_GTM_JS_VAR_F_D_GET_ELEMENTS_BY_TAG_NAME_S": "nueva Fecha().getTime(),evento:'gtm.js'});var f=d.getElementsByTagName(s)[0],",
"NEW_END_DATE": "Nueva fecha de finalización",
"NEXT": "Siguiente",
- "NISAR_DESC ": "NISAR proporciona datos SAR de banda L y S para medir los ecosistemas cambiantes, las superficies dinámicas y las masas de hielo de la Tierra con una regularidad de 12 días en pasadas ascendentes y descendentes.",
+ "NISAR_DESC": "NISAR proporciona datos SAR de banda L y S para medir los ecosistemas cambiantes, las superficies dinámicas y las masas de hielo de la Tierra con una regularidad de 12 días en pasadas ascendentes y descendentes.",
"NO OVERLAP THRESHOLD": "Sin Umbral de Superposición",
"NO_AREA_ON_INTEREST_SPECIFIED": "No se especifica el área de interés.",
+ "NO_BANDWITH_TO_SELECT": "No hay rangos de ancho de banda para seleccionar",
"NO_BEAM_MODES_TO_SELECT": "No hay modos de haz para seleccionar",
"NO_CREDITS_LEFT_THIS_MONTH": "No quedan créditos este mes",
"NO_FILE_TYPES_TO_SELECT": "No hay tipos de archivo para seleccionar",
@@ -518,6 +534,7 @@
"NO_FLIGHT_DIRECTION_SELECTED": "No se seleccionaron direcciones de vuelo",
"NO_FLIGHT_DIRECTIONS_TO_SELECT": "No hay direcciones de vuelo para seleccionar",
"NO_FRAME_INPUT": "Sin entrada del marco",
+ "NO_FRAMES_TO_SELECT": "no hay marco para seleccionar",
"NO_JOBS_LEFT_THIS_MONTH": "No quedan trabajos este mes",
"NO_MOBILE_DISPLACEMENT_SEARCH": "Las búsquedas de desplazamiento no están disponibles en pantallas pequeñas.",
"NO_NAME": "Sin Nombre",
@@ -532,8 +549,11 @@
"NO_SCENE_SELECTED": "No se seleccionó ninguna escena",
"NO_SUBTYPES_TO_SELECT": "No hay subtipos para seleccionar",
"NO_SUITABLE_PRODUCTS_FOR_THIS_TOOL": "No hay productos adecuados para esta herramienta",
+ "NO_VALID_DATA_FOR_POINT": "No hay datos válidos para el punto.",
"NON_DISCRIMINATION": "No Discriminación",
+ "NONE": "Ninguno",
"NOT_ABLE_TO_SELECT_SIMILAR_SCENES_FROM_THIS_SOURCE": "No es posible seleccionar escenas similares de esta fuente",
+ "NOT_ALL_FILTERS_WILL_BE_AVAILABLE_FOR": "No todos los filtros estarán disponibles para",
"NOTE_IN_VERTEX_A_SCENE_IS_CONSIDERED_TO_BE_A_PACKAGE_CONTAINING_ALL_FILES_OR_PRODUCTS": "Nota: En Vertex, una escena se considera un paquete que contiene todos los archivos o productos",
"NOTE_THE_NUMBER_OF_FILES_THAT_ARE_PREDICTED_TO_MATCH_THE_CURRENT_SEARCH_PARAMETERS_IS_DISPLAYED_UNDER_THE_SEARCH_BUTTON_IF_THERE_ARE_NO_PREDICTED_MATCHES_THE_SEARCH_BUTTON_WILL_BE_GREYED_OUT_AND_DISPLAY_NO_RESULTS": "Nota: El número de archivos que se predice coincidan con los parámetros de búsqueda actuales se muestra debajo del botón de BÚSQUEDA. Si no hay coincidencias predichas, el botón de búsqueda se desactivará y mostrará SIN RESULTADOS.",
"OBSERVATIONAL_FILTERS": "Filtros Observacionales",
@@ -562,7 +582,7 @@
"OPEN_LINK_TO_DOCUMENTATION": "Abrir enlace a la documentación.",
"OPEN_MANUAL": "Abrir Manual",
"OPEN_STREET_MAP_CONTRIBUTORS": "© Colaboradores de OpenStreetMap",
- "OPERA_BURST_ID": "Identificaciones de ráfaga de OPERA",
+ "OPERA_BURST_ID": "Identificaciones de Burst de OPERA",
"OPERA_S1_DESC": "Los productos RTC de retrodispersión de Sentinel-1 ofrecen cobertura casi global, y los productos CSLC cubren América del Norte.",
"OPERA_S1_SOURCE_DATA": "Escena fuente de Sentinel-1 para el producto OPERA-S1 seleccionado.",
"OPTION_OR": "opción o",
@@ -609,7 +629,7 @@
"POLARIZATION_SELECTED": "Polarización seleccionada",
"POLARIZATION_SIDE": "Polarización Lateral",
"POLARIZATIONS": "Polarizaciones",
- "POLARIZATIONS_SELECTED": "polarizaciones seleccionadas",
+ "POLARIZATIONS_SELECTED": "polarizaciones elegidas",
"POLYGON": "Polígono",
"POLYGON_DRAW": "Dibujar polígono",
"POWER": "poder",
@@ -630,6 +650,8 @@
"PRODUCT_TYPE": "Tipo de Producto",
"PRODUCT_TYPES": "Tipos de productos",
"PRODUCTION": "Producción",
+ "PRODUCTION_CONFIGURATION": "Configuración de Producción",
+ "PRODUCTION_CONFIGURATION_FILTER": "Filtro de Configuración de Producción",
"PRODUCTS_IN_YOUR_QUEUE_MAY_REQUIRE_A_RESTRICTED_DATASET_AGREEMENT": "Los productos en su lista pueden requerir un acuerdo de conjunto de datos restringido.",
"PRODUCTS_TO_DOWNLOADS_FROM_SELECTED_EVENT": "los productos a las descargas del evento seleccionado",
"PROFILE": "Perfil",
@@ -646,7 +668,8 @@
"RADARSAT_IS_AVAILABLE_THROUGH": "RADARSAT-1 está disponible gratuitamente a través de",
"RADIO_BUTTON_UNCHECKED": "botón_de_radio_sin marcar",
"RADIOMETRY": "Radiometría",
- "RANGE_BANDWIDTH": "Banda de rango",
+ "RANGE_BANDWIDTH": "Ancho de Banda de Rango",
+ "RANGE_BANDWITH_SELECTED": "Rangos de ancho de banda seleccionados",
"RAW": "Crudo",
"READ_OUR_ON_DEMAND_GUIDE": "Lea nuestra guía a On Demand ",
"READ_OUR_USER_GUIDE": "Lea nuestra guía de usuario",
@@ -659,6 +682,7 @@
"REMOVE": "Eliminar",
"REMOVE_CUSTOM_PAIR": "Eliminar par personalizado",
"REMOVE_FILE": "Remover archivo",
+ "REMOVE_FILE_FROM_DOWNLOADS": "Eliminar archivo de las descargas",
"REMOVE_FILE_FROM_QUEUE": "Eliminar archivo de la lista",
"REMOVE_JOB": "Quitar trabajo",
"REMOVE_RED_EYE": "quitar_ojo_rojo",
@@ -704,6 +728,7 @@
"SAVED_SEARCHES_AND_SEARCH_HISTORY": "Búsquedas guardadas e historial de búsqueda",
"SBAS": "SBAS",
"SBAS_CHART": "Gráfico SBAS",
+ "SBAS_COUNT_TOOLTIP": "Los filtros aplicados pueden reducir el número de pares que se enumeran a continuación",
"SBAS_FILTERS": "Filtros SBAS",
"SBAS_SEARCH": "Búsqueda de SBAS",
"SBAS_SEARCH_PROVIDES_PERPENDICULAR_AND_TEMPORAL_BASELINE_DATA_AS_WELL_AS_SCENE_PAIRS_FOR_A_CHOSEN": "La búsqueda SBAS proporciona datos de referencia perpendiculares y temporales, así como pares de escenas, para una determinada",
@@ -720,8 +745,11 @@
"SCENE_START_TIME": "Hora de inicio de la escena",
"SCENES": "Escenas",
"SCENES_THE_LEFT_COLUMN": "Escenas: la columna izquierda",
+ "SCIENCE_PRODUCT": "Producto Científico",
"SCRIPTS_FOR_ACCESSING_SAR_DATA": "scripts para acceder a los datos SAR.",
"SCROLL_THROUGH_THE_LIST_OF_RESULTS_AND_YOU_SEE_SOME_FILES_HAVE_AN_ICON_OF_THREE_GRAY_SQUARES_NEXT": "Desplácese por la lista de resultados y verá que algunos archivos tienen un icono de tres cuadrados grises junto a ellos.",
+ "SDK_PYTHON_CODE_EXPORT": "Exportar código Python del SDK",
+ "SDK_PYTHON_CODE_EXPORT_TOOLTIP": "Información sobre la exportación de código Python del SDK",
"SEA_ICE_MEASURES": "Hielo Marino MEaSUREs",
"SEARCH": "Buscar",
"SEARCH_AREA": "Área de Búsqueda",
@@ -759,6 +787,7 @@
"SENTINEL_DESC": "Sentinel-1 incluye satélites gemelos con radar SAR en banda C, que juntos ofrecen imágenes de la superficie terrestre, de día o de noche, en cualquier clima.",
"SEP_OCT_NOV": "Sep, Oct, Nov",
"SERIES": "Series",
+ "SERIES_UNDEFINED": "Series indefinidas",
"SET": "Colocar",
"SET_AS_BASELINE": "Fijar Línea base",
"SET_AS_BOTH": "Establecer como ambos",
@@ -789,6 +818,7 @@
"SHOW_PRODUCT_FILTERS_CRITERIA": "Mostrar criterios de filtros de productos",
"SHOW_RAW_DATA": "Mostrar datos sin procesar",
"SIDE": "Lateral",
+ "SIDE_BAND_FREQ_B_POLARIZATION": "Polarización de Banda Secundaria (Frecuencia B)",
"SIDE_POLARIZATIONS": "Polarizaciones laterales",
"SIGMA0": "sigma0",
"SIGN_IN": "Iniciar sesión",
@@ -849,6 +879,7 @@
"TEMPORAL": "Temporal",
"TEMPORAL_CRITERIA": "Criterios Temporales:",
"TEST": "Prueba",
+ "TEST_1_1": "PRUEBA 1.1",
"THAT_ARE_RELATED_TO_A_SPECIFIC_LOCATION_AND_TIME": "que están relacionados con un lugar y tiempo específico.",
"THE_BASELINE_TOOL_BUTTON_OPENS_THE_ASF_BASELINE_TOOL_WHICH_IS_USED_FOR_THE_CREATION_OF_IN_SAR_STACKS": "El botón 'Herramienta de línea base' abre la Herramienta de línea base ASF, que se utiliza para la creación de pilas InSAR.",
"THE_CART_CHANGES_APPEARANCE_WHEN_THIS_IS_DONE": "El carrito cambia de apariencia cuando se hace esto.",
@@ -881,7 +912,8 @@
"TOOLS": "Herramientas",
"TOOLTIP": "SUGERENCIA",
"TRACK": "Trayecto",
- "TRACK_END": "Fin de Trayecto",
+ "TRACK_AND_FRAME_FILTERS": "Filtros de Trayecto y Marco",
+ "TRACK_END": "Fin del Trayecto",
"TRACK_START": "Inicio del Trayecto",
"TRAVEL_EXPLORE": "viajar_explorar",
"TYPE": "Tipo",
@@ -893,6 +925,7 @@
"UPLOAD_AOI_VIA_FILE": "Subir AOI a través de un archivo",
"UPLOAD_GEOSPATIAL_FILE": "Subir archivo geoespacial",
"UR_LS": "URL",
+ "URGENT_RESPONSE": "Respuesta Urgente",
"USE_AN_ASF_SEARCH_API_QUERY_TO_DOWNLOAD_MORE_RESULTS_MANUALLY": "Utilice una consulta de la API de búsqueda de ASF para descargar más resultados manualmente.",
"USE_THE_AREA_OF_INTEREST_BUTTONS_TO_TOGGLE_DRAWING_ON_THE_MAP_ON_AND_OFF_TO_EDIT_THE_SHAPE": "Use los botones 'Área de interés' para activar y desactivar el dibujo en el mapa, para editar la forma",
"USE_THE_MAP_PROJECTION_BUTTONS_IN_THE_MAP_TOOLBAR_TO_TOGGLE_BETWEEN_THE_ARCTIC_EQUATORIAL": "Use los botones de 'Proyección de mapa' en la barra de herramientas del mapa para alternar entre el Ártico, Ecuatorial,",
@@ -945,6 +978,7 @@
"WHEN_YOU_SUBMIT_THE_JOB_S_YOU_CAN_ENTER_A_PROJECT_NAME_FOR_EASY_REFERENCE_WHEN_THE_PROCESSING_IS": "Cuando envíe el(los) trabajo(s), puede ingresar un nombre de proyecto para una fácil referencia cuando finalice el procesamiento.",
"WILL_BE": "será",
"WILL_CLEAR_ALL_FILES_FROM_THE_QUEUE_THE_OPTION": "borrará todos los archivos de la lista. La opción",
+ "WILL_COPY_THE_FILE_NAMES_OF_ALL_FILES_IN_THE_QUEUE_FOR_USE_ELSEWHERE": "copiará los nombres de todos los archivos de la cola para utilizarlos en otro lugar.",
"WILL_DISPLAY_THE_CONTENTS_OF_YOUR_CURRENT_DOWNLOAD_QUEUE": "mostrará el contenido de su lista de descarga actual.",
"WILL_EXPAND_THE_LIST_TO_SHOW_ALL_OF_THE_INDIVIDUAL_COMPONENTS_WITHIN_THE_ZIP_ARCHIVE_YOU_CAN": "expandirá la lista para mostrar todos los componentes individuales dentro del archivo zip. ",
"WINDOW": "Ventana.",
@@ -968,7 +1002,8 @@
"YOU_TO_SEARCH_FOR_DATA_FROM_A_COMMAND_LINE_INTERFACE_SO_YOU_CAN_WRITE_YOUR_OWN": "que busque datos desde una interfaz de línea de comandos para que pueda escribir su propia",
"YOUR_DOWNLOAD_QUEUE_IS_EMPTY": "Su lista de descarga está vacía.",
"YOUR_JOBS_QUEUE_IS_EMPTY": "Su lista de trabajos está vacía.",
- "YOUR_SEARCH_AND_REDUCE_THE_NUMBER_OF_RESULTS_NOT_ALL_FILTERS_WILL_BE_AVAILABLE_FOR": "su búsqueda y reducir el número de resultados. ",
+ "YOUR_SEARCH_AND_REDUCE_THE_NUMBER_OF_RESULTS": "su búsqueda y reducir el número de resultados.",
+ "YOUR_SEARCH_AND_REDUCE_THE_NUMBER_OF_RESULTS_NOT_ALL_FILTERS_WILL_BE_AVAILABLE_FOR": "Su búsqueda y reducir el número de resultados. No todos los filtros estarán disponibles para",
"YOUR_SELECTION_TO_A_VALID_RANGE_FOR_THE_SELECTED_DATASET": "su selección a un rango válido para el conjunto de datos seleccionado.",
"ZIPPED_FILES_WILL_BE_DENOTED_BY_A_RIGHT_POINTING_CARET_TO_THE_LEFT_OF_THE_FILENAME_CLICKING_THE_CARET": "Los archivos comprimidos se indicarán con un signo de intercalación que apunta hacia la derecha a la izquierda del nombre del archivo. ",
"ZOOM": "Acercar",
@@ -979,4 +1014,4 @@
"ZOOM_TO_FIT": "Acercar para ajustar",
"ZOOM_TO_RESULTS": "Acercar a los resultados",
"ZOOM_TO_SCENE": "Acercar a la escena"
-}
\ No newline at end of file
+}
diff --git a/src/styles.scss b/src/styles.scss
index 101b2ce60..2c3c758d0 100644
--- a/src/styles.scss
+++ b/src/styles.scss
@@ -422,7 +422,8 @@ ul {
}
.mat-mdc-select-panel {
- max-width: 340px !important;
+ max-width: fit-content !important;
+ //max-width: 340px !important;
max-height: 364px !important;
}
@@ -849,6 +850,10 @@ $d-height: 550px;
max-width: 340px !important;
}
+.short-name-selector.mat-mdc-select-panel {
+ max-width: 900px !important;
+}
+
.cdk-overlay-pane:has(.mat-mdc-select-panel) { min-width: fit-content; }
.breadcrumb-list .mat-mdc-form-field {