Commit e6978d1a authored by ext.sopra.ncastejon's avatar ext.sopra.ncastejon
Browse files

Add the projection and insee for Downloads tab.

parent 7490923c
// import { async, ComponentFixture, TestBed } from '@angular/core/testing';
// import { DatasetExportComponent } from './dataset-export.component';
// import { LicenseModalComponent } from '../..';
// import { ActivatedRoute } from '@angular/router';
// import { Observable, of } from 'rxjs';
// import { DatasetDetailService, ElasticsearchService } from '../../../services';
// import { HttpClientModule } from '@angular/common/http';
// import { Metadata } from '../../../models';
// import { NotificationService, ErrorService } from '../../../../core/services';
// describe('DatasetExportComponent', () => {
// let component: DatasetExportComponent;
// let fixture: ComponentFixture<DatasetExportComponent>;
// let service: DatasetDetailService;
// beforeEach(async(() => {
// TestBed.configureTestingModule({
// imports: [
// HttpClientModule,
// ],
// declarations: [DatasetExportComponent, LicenseModalComponent],
// providers: [
// {
// provide: ActivatedRoute,
// useValue: {
// parent: {
// get paramMap(): Observable<any> {
// return of();
// },
// },
// },
// },
// DatasetDetailService,
// ElasticsearchService,
// ErrorService,
// NotificationService,
// ],
// })
// .compileComponents();
// }));
// beforeEach(() => {
// fixture = TestBed.createComponent(DatasetExportComponent);
// component = fixture.componentInstance;
// service = TestBed.get(DatasetDetailService);
// spyOn(service, 'getDatasetMetadata').and.returnValue(of(new Metadata()));
// fixture.detectChanges();
// });
// it('should create', () => {
// expect(component).toBeTruthy();
// });
// });
......@@ -86,20 +86,7 @@ export class DatasetAPIComponent implements OnInit, OnDestroy {
if (this.metadata && this.resources.length > 0 && !this.hasBeenInitialized) {
this.hasBeenInitialized = true;
if (this.metadata.link) {
this.metadata.link.forEach((link) => {
if (link.service) {
this.resources.forEach((resource) => {
const resourceCopy = Object.assign({}, resource);
resourceCopy.metadataLink = link;
if (link.service === resource.type && resourceCopy.isQueryable) {
if (!this.queryableResources[link.description]) {
this.queryableResources[link.description] = [];
}
this.queryableResources[link.description].push(resourceCopy);
}
});
}
});
this.queryableResources = this._resourcesService.getQueryableResources(this.metadata.link);
}
}
}
......
......@@ -2,7 +2,6 @@ import { Component, Input, OnInit } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { communeInsee } from '../../../../../../assets/resources/commune-insee';
import { geosource } from '../../../../../../i18n/traductions';
import { NotificationService } from '../../../../../core/services';
import { linkFormats, Metadata } from '../../../../../shared/models';
import { Format, Projection, Resource } from '../../../../models';
import { DatasetDetailService } from '../../../../services';
......@@ -95,7 +94,6 @@ export class ResourceQueryableComponent implements OnInit {
constructor(
private _datasetDetailService: DatasetDetailService,
private _notificationService: NotificationService,
private _sanitizer: DomSanitizer,
) { }
......@@ -454,16 +452,6 @@ export class ResourceQueryableComponent implements OnInit {
return `${this.resource.metadataLink.name}.${this.selectedFormat.fileExtension}`;
}
// saveFile(url: string) {
// saveAs(url, `${this.resource.metadataLink.name}.${this.selectedFormat.fileExtension}`);
// this._notificationService.notify(
// {
// type: 'success',
// message: notificationMessages.general.startDownload,
// },
// );
// }
get totalData() {
return this._datasetDetailService.dataset.totalData;
}
......
......@@ -56,7 +56,12 @@ export class DatasetDetailComponent implements OnInit, OnDestroy {
this._meta.updateTag({ name: 'description', content: this.metadata.abstract });
this.isLoading = true;
this.initDatasetInfo();
// Retrieve the first data for the dataset (if exists). It will be used in the
// Data, Downloads and API tabs.
this._datasetDetailService.retrieveDatasetData().subscribe(() => {
this.initDatasetInfo();
});
});
}
......
......@@ -9,7 +9,7 @@
</div>
<div class="resource-downloadable-files" *ngFor="let resource of downloadable.value">
<ng-container *ngFor="let format of resource.formats; let i=index">
<app-resource-download-item [format]="format" [resource]="resource" [isQueryable]="true">
<app-resource-download-item [format]="format" [resource]="resource" [projections]="projections" [isQueryable]="true">
</app-resource-download-item>
</ng-container>
</div>
......
import { Component, OnInit } from '@angular/core';
import { CookieService } from 'ngx-cookie-service';
import { Subscription } from 'rxjs';
import { forkJoin, Subscription } from 'rxjs';
import { environment } from '../../../../environments/environment';
import { notificationMessages } from '../../../../i18n/traductions';
import { Notification } from '../../../core/models';
import { NotificationService } from '../../../core/services';
import { IMetadataLink, linkFormats, Metadata } from '../../../shared/models';
import { UserService } from '../../../user/services';
import { Resource } from '../../models';
import { Projection, Resource } from '../../models';
import { DatasetDetailService, ResourcesService } from '../../services';
@Component({
......@@ -29,6 +29,7 @@ export class DatasetDownloadsComponent implements OnInit {
isSample = false;
resources: Resource[];
projections: Projection[];
hasBeenInitialized = false;
constructor(
......@@ -42,6 +43,7 @@ export class DatasetDownloadsComponent implements OnInit {
ngOnInit() {
this.resources = [];
this.projections = [];
this.downloadableResources = [];
this.staticResources = [];
this.otherResources = [];
......@@ -52,22 +54,25 @@ export class DatasetDownloadsComponent implements OnInit {
this.isSample = this._datasetDetailService.dataset.editorialMetadata.isSample;
this.initialize();
this._resourcesService.getResources().subscribe(
(results) => {
this.resources = results;
forkJoin([
this._resourcesService.getProjections(),
this._resourcesService.getResources(),
]).subscribe((response) => {
this.projections = response[0];
this.resources = response[1];
this.initialize();
this.sub = this._datasetDetailService.dataset$.subscribe(() => {
this.initialize();
this.sub = this._datasetDetailService.dataset$.subscribe(() => {
this.initialize();
});
},
(err) => {
this._notificationService.notify(new Notification({
type: 'error',
message: `${notificationMessages.resources.initializationError}`,
}));
},
);
});
// tslint:disable-next-line: align
}, (err) => {
this._notificationService.notify(new Notification({
type: 'error',
message: `${notificationMessages.resources.initializationError}`,
}));
});
}
ngOnDestroy() {
......@@ -92,43 +97,8 @@ export class DatasetDownloadsComponent implements OnInit {
if (this.metadata && this.resources.length > 0 && !this.hasBeenInitialized) {
this.hasBeenInitialized = true;
if (this.metadata.link) {
this.metadata.link.forEach((link) => {
if (link.service) {
this.resources.forEach((resource) => {
const resourceCopy = Object.assign({}, resource);
resourceCopy.metadataLink = link;
if (link.service === resource.type && resourceCopy.isQueryable) {
// We exclude Shapefile if from WFS. The Shapefile from WS has priority.
if (resourceCopy.type === this.linkFormats.wfs) {
resourceCopy.formats = resourceCopy.formats.filter(f => f.name !== 'ShapeFile');
}
// For non-geographical data, the Shapefile is not available for the WS service
if (resourceCopy.type === 'WS' && this.metadata.type === 'nonGeographicDataset') {
resourceCopy.formats = resourceCopy.formats.filter(f => f.name !== 'ShapeFile');
}
if (!this.downloadableResources[link.description]) {
this.downloadableResources[link.description] = [];
}
this.downloadableResources[link.description].push(resourceCopy);
}
});
} else if (link.service === undefined) {
if (!link.name.includes('Licence')) {
if (link.formats) {
if (!this.staticResources[link.description]) {
this.staticResources[link.description] = [];
}
this.staticResources[link.description].push(link);
} else {
this.otherResources.push(link);
}
}
}
});
[this.downloadableResources, this.staticResources, this.otherResources] =
this._resourcesService.getResourcesForDownload(this.metadata);
}
}
}
......
......@@ -10,6 +10,78 @@
</div>
</div>
<div class="division-item" *ngIf="format.isCuttable && inseeLabel">
<div class="label-dropdown title-label">
<span i18n="@@dataset.resources.divisionbycommune">
Division by municipality
</span>
</div>
<div>
<!-- Dropdown for insee when needed -->
<div class="dropdown dropdown-insee" [ngClass]="{'is-active': dropDownInseeToggle}"
(click)="dropDownInseeToggle=!dropDownInseeToggle" (clickOutside)="dropDownInseeToggle = false;">
<div class="dropdown-trigger">
<button class="button" aria-haspopup="true" aria-controls="dropdown-menu">
<span
*ngIf="selectedInsee">{{ selectedInsee ? selectedInsee.commune + ' - ' + selectedInsee.insee : ''}}</span>
<span *ngIf="!selectedInsee" i18n="@@dataset.resources.commune">Municipality</span>
<svg xmlns="http://www.w3.org/2000/svg" id="chevron" viewBox="0 0 15 9">
<path
d="M7.5 7.5c-.1 0-.3-.1-.4-.1l-6-6C1 1.1 1 .8 1.1.6s.5-.2.7 0l5.6 5.6L13 .6c.2-.2.5-.2.7 0s.2.5 0 .7l-6 6c.1.1-.1.2-.2.2z"
class="brandcolor" />
<path
d="M7.5 7.5c-.1 0-.3-.1-.4-.1l-6-6C1 1.1 1 .8 1.1.6s.5-.2.7 0l5.6 5.6L13 .6c.2-.2.5-.2.7 0s.2.5 0 .7l-6 6c.1.1-.1.2-.2.2z"
class="brandcolor" />
</svg>
</button>
</div>
<div class="dropdown-menu" id="dropdown-menu" role="menu">
<div class="dropdown-content">
<a class="dropdown-item" (click)="setInsee(null)" i18n="@@global.all.feminine">All</a>
<a class="dropdown-item" *ngFor="let zone of communeInseeList" (click)="setInsee(zone)">
{{ zone.commune }} - {{ zone.insee }}
</a>
</div>
</div>
</div>
</div>
</div>
<div class="projection-item" *ngIf="format.isProjectable">
<div class="label-dropdown title-label">
<span i18n="@@dataset.resources.projectionsystem">
Projection system
</span>
</div>
<div>
<!-- Dropdow for projections -->
<div class="dropdown" [ngClass]="{'is-active': dropDownProjectionToggle}"
(click)="dropDownProjectionToggle=!dropDownProjectionToggle"
(clickOutside)="dropDownProjectionToggle = false;">
<div class="dropdown-trigger">
<button class="button" aria-haspopup="true" aria-controls="dropdown-menu">
<span>{{ getProjectionLabel(selectedProjection.name) }}</span>
<svg xmlns="http://www.w3.org/2000/svg" id="chevron" viewBox="0 0 15 9">
<path
d="M7.5 7.5c-.1 0-.3-.1-.4-.1l-6-6C1 1.1 1 .8 1.1.6s.5-.2.7 0l5.6 5.6L13 .6c.2-.2.5-.2.7 0s.2.5 0 .7l-6 6c.1.1-.1.2-.2.2z"
class="brandcolor" />
<path
d="M7.5 7.5c-.1 0-.3-.1-.4-.1l-6-6C1 1.1 1 .8 1.1.6s.5-.2.7 0l5.6 5.6L13 .6c.2-.2.5-.2.7 0s.2.5 0 .7l-6 6c.1.1-.1.2-.2.2z"
class="brandcolor" />
</svg>
</button>
</div>
<div class="dropdown-menu" id="dropdown-menu" role="menu">
<div class="dropdown-content">
<a class="dropdown-item" *ngFor="let projection of projectionList" (click)="setProjection(projection)">
{{ getProjectionLabel(projection.name) }}
</a>
</div>
</div>
</div>
</div>
</div>
<app-download-button [url]="getQueryableUrl()" [fileName]="getFileName()">
</app-download-button>
......
......@@ -29,3 +29,26 @@
}
}
}
.dropdown-menu {
height: 2.5rem;
}
.dropdown-insee {
.dropdown-menu {
height: 200px;
max-height: 200px;
overflow-y: scroll;
overflow-x: hidden;
}
}
/* stylelint-disable-next-line */
.dropdown-trigger .button {
justify-content: space-between;
svg {
width: 1rem;
height: 0.6rem;
}
}
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { communeInsee } from '../../../../../../assets/resources/commune-insee';
import { geosource } from '../../../../../../i18n/traductions';
import { IMetadataLink, linkFormats } from '../../../../../shared/models';
import { Format, Resource } from '../../../../models';
import { Format, Projection, Resource } from '../../../../models';
import { DatasetDetailService } from '../../../../services';
@Component({
selector: 'app-resource-download-item',
......@@ -14,6 +16,7 @@ export class ResourceDownloadItemComponent implements OnInit {
@Input() format?: Format;
@Input() resource: Resource;
@Input() projections: Projection[];
@Input() link: IMetadataLink;
@Input() isQueryable: boolean;
@Output() saveEvent = new EventEmitter();
......@@ -22,6 +25,25 @@ export class ResourceDownloadItemComponent implements OnInit {
abortMessage: string = geosource.downloads.abort;
downloadMessage: string = geosource.downloads.download;
queryableUrl = '';
projectionList;
// Dropdown projection
dropDownProjectionToggle: false;
selectedProjection: {
name: '',
bbox: any,
};
inseeLabel: string;
// Dropdown insee
dropDownInseeToggle: false;
selectedInsee: {
commune: '',
insee: '',
};
communeInseeList = communeInsee;
labelLayer = {
WFS: 'typename',
WMS: 'layers',
......@@ -34,9 +56,67 @@ export class ResourceDownloadItemComponent implements OnInit {
WCS: 'FORMAT',
};
constructor() { }
shpProjections = {
'EPSG:4171': 'EPSG:4171',
'EPSG:3946': 'EPSG:3946',
'EPSG:2154': 'EPSG:2154',
'EPSG:4326': 'EPSG:4326',
'EPSG:4258': 'EPSG:4258',
};
queryableParameters = {
baseUrl: '',
baseParameters: '',
layer: '',
outputFormat: '',
outputFormatActive: false,
projection: '',
projectionActive: false,
bbox: '',
insee: '',
inseeActive: false,
numberFeatures: false,
fromFeature: false,
};
constructor(
private _datasetDetailService: DatasetDetailService,
) { }
ngOnInit() {
// Get projections and set the default one (depending on the resource)
this.projectionList = [];
if (this.resource.type === linkFormats.wms) {
this.projectionList = this.transformObjectToArray(this.resource.metadataLink.bbox_by_projection);
this.selectedProjection = this.projectionList[0];
} else if (this.resource.type === linkFormats.wfs) {
this.resource.metadataLink.projections.forEach((key) => {
this.projectionList.push({
name: key,
bbox: key,
});
});
this.selectedProjection = this.projectionList[0];
} else if (this.resource.type === linkFormats.wcs) {
this.projectionList = this.transformObjectToArray(this.resource.metadataLink.bbox_by_projection);
this.selectedProjection = this.projectionList[0];
} else if (this.resource.type === linkFormats.ws) {
this.projectionList = this.transformObjectToArray(this.shpProjections);
this.selectedProjection = this.projectionList[0];
}
// Set the insee property label for this dataset
if (this._datasetDetailService.datasetData[0]) {
const properties = Object.keys(this._datasetDetailService.datasetData[0].properties);
this.inseeLabel = properties.find((prop) => { return prop.includes('insee'); });
}
this.communeInseeList.sort((a, b) => (a.commune > b.commune) ? 1 : -1);
this.setProjection(this.selectedProjection);
console.log('selected projeciton', this.selectedProjection);
}
getFormatName() {
......@@ -79,6 +159,60 @@ export class ResourceDownloadItemComponent implements OnInit {
return this.resource ? `${this.resource.metadataLink.name}.${this.format.fileExtension}` : this.link.name;
}
getProjectionLabel(name: string) {
const projection = this.projections.find((projection) => {
return projection.name === name;
});
return projection ? `${projection.commonName} (${projection.name})` : name;
}
// Set the selected projection and set the queryable parameters
// depending on the resource
setProjection(projection) {
this.selectedProjection = projection;
if (this.resource.type === linkFormats.wfs) {
this.queryableParameters.projection = `&SRSNAME=${projection.name}`;
} else if (this.resource.type === linkFormats.wms || this.resource.type === linkFormats.wcs) {
this.queryableParameters.projection = `&CRS=${projection.name}`;
this.queryableParameters.bbox = `&BBOX=${projection.bbox.minx},` +
`${projection.bbox.miny},` +
`${projection.bbox.maxx},` +
`${projection.bbox.maxy}`;
} else if (this.resource.type === linkFormats.ws) {
if (this.format.name !== 'JSON') {
this.queryableParameters.projection = `srsname=${projection.name}`;
}
}
this.queryableParameters.projectionActive = true;
this.updateQueryableUrl();
}
// Set the selected insee and set the queryable parameters
// depending on the resource
setInsee(insee) {
this.selectedInsee = insee;
if (!this.selectedInsee || !this.inseeLabel) {
this.queryableParameters.insee = '';
} else {
if (this.resource.type === linkFormats.wfs) {
this.queryableParameters.insee = '&filter=Filter=<Filter> <PropertyIsLike wildcard="*" ' +
'singleChar=\'.\' escape=\'_\'> <PropertyName>' +
`${this.inseeLabel}</PropertyName><Literal>${this.selectedInsee.insee}` +
'</Literal></PropertyIsLike> </Filter>';
} else if (this.resource.type === linkFormats.ws) {
this.queryableParameters.baseUrl = this.resource.metadataLink.name.replace('\/all.json', '');
const match = (/\/ws\/([^\/]+)/g).exec(this.resource.metadataLink.url);
const serviceName = match[1] ? match[1] : '';
this.queryableParameters.insee = `&mask_db=${serviceName}&mask_layer=adr_voie_lieu.adrcommune` +
`&mask_field=insee&mask_value=${this.selectedInsee.insee}`;
}
this.queryableParameters.inseeActive = true;
}
this.updateQueryableUrl();
}
getProjectionAndBbox(format: Format) {
let projection = '';
let bboxRequest = '';
......@@ -103,4 +237,29 @@ export class ResourceDownloadItemComponent implements OnInit {
};
}
// When the user changes parameters (or when view init), we update the url provided
// to the <a> link
updateQueryableUrl() {
this.queryableUrl = this.queryableParameters.baseUrl +
this.queryableParameters.baseParameters;
this.queryableUrl += this.queryableParameters.layer +
this.queryableParameters.outputFormat +