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

Create a shared component for Download button.

parent d0321325
Pipeline #3857 passed with stage
in 3 minutes and 5 seconds
......@@ -206,23 +206,12 @@
clip-rule="evenodd" />
</svg>
</button>
<div class="column resource-download-icon is-narrow-tablet is-5-mobile" (click)="saveFile(queryableUrl)"
[attr.data-tooltip]="downloadMessage">
<a>
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="21" fill="none" viewBox="0 0 22 21">
<path fill="#4668AB"
d="M21.323 13.961h-.338c-.339 0-.677.339-.677.677v4.57H1.692v-4.57a.667.667 0 0 0-.677-.677H.677c-.339 0-.677.339-.677.677V20.223c0 .423.338.677.677.677h20.646c.338 0 .677-.339.677-.677v-5.585a.667.667 0 0 0-.677-.677z" />
<path fill="#4668AB"
d="M10.323 15.315c.085.085.254.17.339.17.084.084.254.084.338.084.085 0 .254 0 .339-.084.17 0 .254-.085.338-.17L17.6 9.223c.17-.254.17-.592 0-.761l-.423-.424c-.169-.253-.592-.253-.761 0l-4.57 4.654V.846C11.847.338 11.509 0 11 0c-.507 0-.846.338-.846.846v11.846L5.585 8.038c-.17-.253-.508-.253-.762 0l-.423.424c-.169.253-.169.592 0 .761l5.923 6.092z" />
</svg>
</a>
<div class="resource-download-icon">
<app-download-button [url]="queryableUrl" [fileName]="getFileName()">
</app-download-button>
</div>
</div>
</div>
</ng-container>
......
......@@ -50,9 +50,9 @@
border: 1px solid $grey-super-light-color;
transition: all 0.5s ease;
word-break: break-all;
// flex-grow: 1;
flex-shrink: 1;
padding: 0.7rem 0.5rem;
min-height: 2.5rem;
// ng-deep needed because of the innerHtml breaks the styling
/* stylelint-disable-next-line */
......@@ -77,9 +77,18 @@
.button {
font-size: 0.875rem;
margin-left: 0.5rem;
height: 2.5rem;
width: 2.5rem;
position: relative;
margin-right: 0.5rem;
height: 3.5rem;
flex-grow: 1;
margin-top: 0.5rem;
@media screen and (min-width: $tablet) {
height: 2.5rem;
width: 2.5rem;
margin-top: 0;
flex-grow: 0;
}
svg {
position: absolute;
......@@ -150,26 +159,6 @@
word-break: break-all;
}
.resource-download-icon {
padding: 0.5rem 0.4rem;
border: 1px solid $grey-super-light-color;
border-radius: 4px;
a {
display: flex;
justify-content: center;
}
svg {
height: 1.5rem;
fill: $link-color;
}
&:hover a {
opacity: 0.7;
}
}
.create-request {
cursor: pointer;
display: flex;
......@@ -218,11 +207,12 @@
.tooltip {
margin-left: 0;
margin-top: 0.5rem;
width: 2.5rem;
height: 2.5rem;
height: 3.5rem;
flex-grow: 1;
@media screen and (min-width: $tablet) {
margin-left: 0.5rem;
width: 2.5rem;
height: 2.5rem;
margin-top: 0;
}
}
......
import { Component, Input, OnInit } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { saveAs } from 'file-saver';
import { communeInsee } from '../../../../../../assets/resources/commune-insee';
import { geosource, notificationMessages } from '../../../../../../i18n/traductions';
import { geosource } from '../../../../../../i18n/traductions';
import { NotificationService } from '../../../../../core/services';
import { linkFormats, Metadata } from '../../../../../shared/models';
import { Format, Projection, Resource } from '../../../../models';
......@@ -451,16 +450,20 @@ export class ResourceQueryableComponent implements OnInit {
return array;
}
saveFile(url: string) {
saveAs(url, `${this.resource.metadataLink.name}.${this.selectedFormat.fileExtension}`);
this._notificationService.notify(
{
type: 'success',
message: notificationMessages.general.startDownload,
},
);
getFileName() {
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;
}
......@@ -488,11 +491,13 @@ export class ResourceQueryableComponent implements OnInit {
this.messageClipboardRoot = geosource.mapMessages.copied;
setTimeout(() => {
this.messageClipboardRoot = geosource.mapMessages.share;
// tslint:disable-next-line: align
}, 2000);
} else {
this.messageClipboard = geosource.mapMessages.copied;
setTimeout(() => {
this.messageClipboard = geosource.mapMessages.share;
// tslint:disable-next-line: align
}, 2000);
}
......
......@@ -8,8 +8,10 @@
<span>{{downloadable.key}}</span>
</div>
<div class="resource-downloadable-files" *ngFor="let resource of downloadable.value">
<app-resource-custom-download [resource]="resource">
</app-resource-custom-download>
<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>
</ng-container>
</div>
</div>
</div>
......@@ -19,9 +21,9 @@
<div class="resource-description">
<span>{{static.key}}</span>
</div>
<div class="resource-static-files" *ngFor="let resource of static.value">
<app-resource-static [link]="resource">
</app-resource-static>
<div class="resource-static-files" *ngFor="let metadataLink of static.value">
<app-resource-download-item [link]="metadataLink" [isQueryable]="false">
</app-resource-download-item>
</div>
</div>
</div>
......
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DatasetDownloadsComponent } from './dataset-downloads.component';
describe('DatasetDownloadsComponent', () => {
let component: DatasetDownloadsComponent;
let fixture: ComponentFixture<DatasetDownloadsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ DatasetDownloadsComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(DatasetDownloadsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
......@@ -5,7 +5,7 @@ import { environment } from '../../../../environments/environment';
import { notificationMessages } from '../../../../i18n/traductions';
import { Notification } from '../../../core/models';
import { NotificationService } from '../../../core/services';
import { IMetadataLink, Metadata } from '../../../shared/models';
import { IMetadataLink, linkFormats, Metadata } from '../../../shared/models';
import { UserService } from '../../../user/services';
import { Resource } from '../../models';
import { DatasetDetailService, ResourcesService } from '../../services';
......@@ -17,6 +17,8 @@ import { DatasetDetailService, ResourcesService } from '../../services';
})
export class DatasetDownloadsComponent implements OnInit {
linkFormats = linkFormats;
metadata: Metadata;
sub: Subscription;
downloadableResources: Resource[];
......@@ -99,7 +101,7 @@ export class DatasetDownloadsComponent implements OnInit {
if (link.service === resource.type && resourceCopy.isQueryable) {
// We exclude Shapefile if from WFS. The Shapefile from WS has priority.
if (resourceCopy.type === 'WFS') {
if (resourceCopy.type === this.linkFormats.wfs) {
resourceCopy.formats = resourceCopy.formats.filter(f => f.name !== 'ShapeFile');
}
......
<div class="resource">
<ng-container *ngFor="let format of resource.formats; let i=index">
<app-resource-download-item [formatName]="format.name" [formatExtension]="format.fileExtension"
[resourceName]="resource.metadataLink.name" [isQueryable]="true" (saveEvent)="saveFile(format, i)"
(abortEvent)="abortDownload(i)"
[whichStepLoading]="whichStepLoading[i]">
</app-resource-download-item>
</ng-container>
</div>
\ No newline at end of file
<div class="resource-download">
<div class="resource-left">
<app-format-icon [formatName]="formatName">
<app-format-icon [formatName]="getFormatName()">
</app-format-icon>
<div class="resource-main">
<div class="resource-main-name">
<span>{{isQueryable ? resourceName + '.' + formatExtension : resourceName }}
<span>{{isQueryable ? resource.metadataLink.name + '.' + format.fileExtension : link.name }}
</span>
</div>
</div>
</div>
<ng-container *ngIf="isQueryable; else other">
<div class="resource-icon-download" (click)="saveResource()" *ngIf="!whichStepLoading">
<a [attr.data-tooltip]="downloadMessage">
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="21" fill="none" viewBox="0 0 22 21">
<path fill="#4668AB"
d="M21.323 13.961h-.338c-.339 0-.677.339-.677.677v4.57H1.692v-4.57a.667.667 0 0 0-.677-.677H.677c-.339 0-.677.339-.677.677V20.223c0 .423.338.677.677.677h20.646c.338 0 .677-.339.677-.677v-5.585a.667.667 0 0 0-.677-.677z" />
<path fill="#4668AB"
d="M10.323 15.315c.085.085.254.17.339.17.084.084.254.084.338.084.085 0 .254 0 .339-.084.17 0 .254-.085.338-.17L17.6 9.223c.17-.254.17-.592 0-.761l-.423-.424c-.169-.253-.592-.253-.761 0l-4.57 4.654V.846C11.847.338 11.509 0 11 0c-.507 0-.846.338-.846.846v11.846L5.585 8.038c-.17-.253-.508-.253-.762 0l-.423.424c-.169.253-.169.592 0 .761l5.923 6.092z" />
</svg>
</a>
</div>
<div class="resource-icon-cancel" *ngIf="whichStepLoading"
[attr.data-tooltip]="whichStepLoading ? abortMessage : null">
<svg width="34" height="34" viewBox="0 0 34 34" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M17 0C18.1009 0 19.0325 0.929231 19.0325 2.02741C19.0325 3.16783 18.1009 4.05483 17 4.05483C15.8567 4.05483 14.9675 3.16783 14.9675 2.02741C14.9675 0.929231 15.8567 0 17 0ZM6.37132 4.36171C7.47224 4.36171 8.40378 5.29094 8.40378 6.38912C8.40378 7.52954 7.47224 8.41653 6.37132 8.41653C5.22807 8.41653 4.33887 7.52954 4.33887 6.38912C4.33887 5.29094 5.22807 4.36171 6.37132 4.36171ZM4.06492 17.0002C4.06492 15.902 3.13337 14.9728 2.03246 14.9728C0.8892 14.9728 0 15.902 0 17.0002C0 18.1406 0.8892 19.0276 2.03246 19.0276C3.13337 19.0276 4.06492 18.1406 4.06492 17.0002ZM6.37132 25.5838C7.47224 25.5838 8.40378 26.513 8.40378 27.6112C8.40378 28.7516 7.47224 29.6386 6.37132 29.6386C5.22807 29.6386 4.33887 28.7516 4.33887 27.6112C4.33887 26.513 5.22807 25.5838 6.37132 25.5838ZM19.0327 31.9727C19.0327 30.8745 18.1011 29.9453 17.0002 29.9453C15.857 29.9453 14.9678 30.8745 14.9678 31.9727C14.9678 33.1131 15.857 34.0001 17.0002 34.0001C18.1011 34.0001 19.0327 33.1131 19.0327 31.9727ZM27.6301 25.5838C28.731 25.5838 29.6626 26.513 29.6626 27.6112C29.6626 28.7516 28.731 29.6386 27.6301 29.6386C26.4869 29.6386 25.5977 28.7516 25.5977 27.6112C25.5977 26.513 26.4869 25.5838 27.6301 25.5838ZM34.0005 17.0002C34.0005 15.902 33.0689 14.9728 31.968 14.9728C30.8247 14.9728 29.9355 15.902 29.9355 17.0002C29.9355 18.1406 30.8247 19.0276 31.968 19.0276C33.0689 19.0276 34.0005 18.1406 34.0005 17.0002Z"
fill="#242B3F" />
<animateTransform attributeName="transform" type="rotate" from="0 0 0" to="360 0 0" dur="1.2s"
repeatCount="indefinite" />
</svg>
<img src="../../../../../../assets/img/close.svg" [alt]="abortMessage" (click)=abortDownload()>
</div>
</ng-container>
<ng-template #other>
<div class="resource-icon-download">
<a [href]="resourceUrl" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="21" fill="none" viewBox="0 0 22 21">
<path fill="#4668AB"
d="M21.323 13.961h-.338c-.339 0-.677.339-.677.677v4.57H1.692v-4.57a.667.667 0 0 0-.677-.677H.677c-.339 0-.677.339-.677.677V20.223c0 .423.338.677.677.677h20.646c.338 0 .677-.339.677-.677v-5.585a.667.667 0 0 0-.677-.677z" />
<path fill="#4668AB"
d="M10.323 15.315c.085.085.254.17.339.17.084.084.254.084.338.084.085 0 .254 0 .339-.084.17 0 .254-.085.338-.17L17.6 9.223c.17-.254.17-.592 0-.761l-.423-.424c-.169-.253-.592-.253-.761 0l-4.57 4.654V.846C11.847.338 11.509 0 11 0c-.507 0-.846.338-.846.846v11.846L5.585 8.038c-.17-.253-.508-.253-.762 0l-.423.424c-.169.253-.169.592 0 .761l5.923 6.092z" />
</svg>
</a>
</div>
</ng-template>
<app-download-button [url]="getQueryableUrl()" [fileName]="getFileName()">
</app-download-button>
</div>
\ No newline at end of file
......@@ -29,63 +29,3 @@
}
}
}
.resource-icon-download {
padding: 0.4rem 0.4rem;
border: 1px solid $grey-super-light-color;
border-radius: 4px;
margin-right: 0.75rem;
width: 2.5rem;
height: 2.5rem;
a {
display: flex;
}
svg {
height: 1.5rem;
width: 1.5rem;
fill: $link-color;
}
&:hover svg {
opacity: 0.7;
}
}
.resource-icon-cancel {
padding: 0.4rem 0.4rem;
border: 1px solid $grey-super-light-color;
border-radius: 4px;
margin-right: 0.75rem;
position: relative;
width: 2.5rem;
height: 2.5rem;
a {
display: flex;
}
svg {
position: absolute;
height: 2rem;
width: 2rem;
left: calc(50% - 1rem);
top: calc(50% - 1rem);
fill: $link-color;
opacity: 0.6;
}
img {
position: absolute;
height: 0.875rem;
width: 0.875rem;
left: calc(50% - 0.4375rem);
top: calc(50% - 0.4375rem);
}
&:hover img {
opacity: 0.6;
}
}
\ No newline at end of file
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { geosource } from '../../../../../../i18n/traductions';
import { IMetadataLink, linkFormats } from '../../../../../shared/models';
import { Format, Resource } from '../../../../models';
@Component({
selector: 'app-resource-download-item',
......@@ -8,29 +10,97 @@ import { geosource } from '../../../../../../i18n/traductions';
})
export class ResourceDownloadItemComponent implements OnInit {
@Input() formatName: string;
@Input() formatExtension?: string;
@Input() resourceName: string;
@Input() resourceUrl ?: string;
linkFormats = linkFormats;
@Input() format?: Format;
@Input() resource: Resource;
@Input() link: IMetadataLink;
@Input() isQueryable: boolean;
@Input() whichStepLoading ?: string;
@Output() saveEvent = new EventEmitter();
@Output() abortEvent = new EventEmitter();
abortMessage: string = geosource.downloads.abort;
downloadMessage: string = geosource.downloads.download;
labelLayer = {
WFS: 'typename',
WMS: 'layers',
WCS: 'identifiers',
};
labelFormat = {
WFS: 'outputFormat',
WMS: 'FORMAT',
WCS: 'FORMAT',
};
constructor() { }
ngOnInit() {
}
saveResource() {
this.saveEvent.emit(null);
getFormatName() {
return this.format ? this.format.name : this.link.formats[0];
}
getQueryableUrl() {
let queryableUrl = '';
if (this.isQueryable) {
queryableUrl = this.resource.metadataLink.url;
let layer = '';
let outputFormat = '';
if (this.resource.isStandard) {
layer = `&${this.labelLayer[this.resource.type]}=${this.resource.metadataLink.name}`;
outputFormat = `&${this.labelFormat[this.resource.type]}=` +
`${this.format.mapServerType}`;
const projectionAndBbox = this.getProjectionAndBbox(this.format);
const baseParameters = this.resource.parametersUrl ? `?${this.resource.parametersUrl}` : '';
queryableUrl += baseParameters +
layer +
outputFormat +
projectionAndBbox.projection +
projectionAndBbox.bboxRequest;
} else if (this.resource.type === linkFormats.ws) {
if (this.format.name === 'JSON') {
queryableUrl += `/${this.resource.metadataLink.name}/all.json`;
} else {
queryableUrl += `/${this.resource.metadataLink.name}.shp?srsname=EPSG:3946`;
}
}
} else {
queryableUrl = this.link.url;
}
return queryableUrl;
}
abortDownload() {
this.abortEvent.emit(null);
getFileName() {
return this.resource ? `${this.resource.metadataLink.name}.${this.format.fileExtension}` : this.link.name;
}
getProjectionAndBbox(format: Format) {
let projection = '';
let bboxRequest = '';
if (this.resource.type === linkFormats.wfs) {
projection = '&SRSNAME=EPSG:3946';
} else if (this.resource.type === linkFormats.wms || this.resource.type === linkFormats.wcs) {
projection = '&CRS=EPSG:3946';
const bbox = this.resource.metadataLink.bbox_by_projection['EPSG:3946'];
bboxRequest = `&BBOX=${bbox.minx},` +
`${bbox.miny},` +
`${bbox.maxx},` +
`${bbox.maxy}`;
} else if (this.resource.type === linkFormats.ws) {
if (format.name !== 'JSON') {
projection = 'srsname=EPSG:3946';
}
}
return {
projection,
bboxRequest,
};
}
}
<div class="resource">
<app-resource-download-item [formatName]="link.formats[0]"
[resourceName]="link.name" [resourceUrl]="link.url" [isQueryable]="false">
</app-resource-download-item>
</div>
\ No newline at end of file
@import '../../../../../scss/variables.scss';
.resource {
background-color: white;
}
import { Component, Input, OnInit } from '@angular/core';
import { IMetadataLink } from '../../../../shared/models';
@Component({
selector: 'app-resource-static',
templateUrl: './resource-static.component.html',
styleUrls: ['./resource-static.component.scss'],
})
export class ResourceStaticComponent implements OnInit {
@Input() link: IMetadataLink;
constructor() { }
ngOnInit() {
}
humanFileSize(bytes: string, si: boolean) {
let sizeFilebytes = Number(bytes);
const thresh = si ? 1000 : 1024;
if (Math.abs(Number((bytes))) < thresh) {
return `${bytes} B`;
}
const units = si
? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
let u = -1;
do {
sizeFilebytes /= thresh;
u += 1;