Dataprovider landing page: tabs load on click, publications & datasets tabs ready | Organization landing page: export publications incomplete

git-svn-id: https://svn.driver.research-infrastructures.eu/driver/dnet40/modules/uoa-services-portal/trunk@44382 d315682c-612b-4755-9ff5-7f18f6832af3
This commit is contained in:
konstantina.galouni 2016-11-03 12:31:22 +00:00
parent 000397b0ee
commit ffecd991bc
15 changed files with 361 additions and 117 deletions

View File

@ -33,6 +33,7 @@
</dl>
<tabs [id] = "datasourceId"
[resultsBy] = "dataProviderInfo.resultsBy"
[tabs]="dataProviderInfo.tabs"
[statistics]="dataProviderInfo.statistics"
[projects]="dataProviderInfo.projects"

View File

@ -12,7 +12,8 @@ import {RefineResultsService} from '../../services/servicesUtils/refineResuts.se
template: `
<ul class="nav nav-tabs">
<li *ngIf="tabs.length>0" class="active">
<a data-toggle="tab" href="#{{tabs[0].content}}">
<a *ngIf="tabs[0].content=='publicationsTab' || tabs[0].content=='datasetsTab'"
data-toggle="tab" href="#{{tabs[0].content}}">
{{tabs[0].name}}
<span class="badge" *ngIf="tabs[0].content=='publicationsTab'">
{{searchPublicationsComponent.totalResults}}
@ -24,7 +25,8 @@ import {RefineResultsService} from '../../services/servicesUtils/refineResuts.se
</li>
<li *ngFor="let tab of tabs; let i=index" role="presentation">
<a *ngIf="i>0" data-toggle="tab" href="#{{tab.content}}">
<a *ngIf="(tab.content=='publicationsTab' || tab.content=='datasetsTab') && i>0"
(click)="search(tab.content)" data-toggle="tab" href="#{{tab.content}}">
{{tab.name}}
<span class="badge" *ngIf="tab.content=='publicationsTab'">
{{searchPublicationsComponent.totalResults}}
@ -38,6 +40,8 @@ import {RefineResultsService} from '../../services/servicesUtils/refineResuts.se
<div class="tab-content">
<div *ngIf="tabs.length>0" id="{{tabs[0].content}}" class="tab-pane fade in active panel-body">
<div *ngIf="tabs[0].content=='publicationsTab' || tabs[0].content=='datasetsTab'">
<publicationsTab *ngIf="tabs[0].content=='publicationsTab'"
[searchPublicationsComponent]="searchPublicationsComponent">
</publicationsTab>
@ -54,23 +58,28 @@ import {RefineResultsService} from '../../services/servicesUtils/refineResuts.se
[datasources]="datasources">
</datasourcesTab>
</div>
<div>
<div *ngFor="let tab of tabs; let i=index" id="{{tab.content}}" class="tab-pane fade panel-body">
<div *ngIf="tab.content=='publicationsTab' || tab.content=='datasetsTab'">
<publicationsTab *ngIf="i>0 && tab.content=='publicationsTab'"
[searchPublicationsComponent] = "searchPublicationsComponent">
</publicationsTab>
<datasetsTab *ngIf="i>0 && tab.content=='datasetsTab'"></datasetsTab>
<statisticsTab *ngIf="i>0 && tab.content=='statisticsTab'">trgfrg</statisticsTab>
<statisticsTab *ngIf="i>0 && tab.content=='statisticsTab'"></statisticsTab>
<projectsTab *ngIf="i>0 && tab.content=='projectsTab'"></projectsTab>
<datasourcesTab *ngIf="i>0 && tab.content=='datasourcesTab'"></datasourcesTab>
</div>
</div>
</div>
`
})
export class TabsComponent {
@Input() id: string;
@Input() resultsBy: string;
@Input() tabs: {"name": string, "content": string}[];
//@Input() publications;
//@Input() datasets;
@ -78,6 +87,9 @@ export class TabsComponent {
@Input() projects;
@Input() datasources;
private reloadPublications: boolean = true;
private reloadDatasets: boolean = true;
subPublications: any;
subDatasets: any;
@ -93,25 +105,43 @@ export class TabsComponent {
}
ngOnInit() {
if(this.tabs != []) {
this.search(this.tabs[0].content);
}
}
ngOnDestroy() {
if(this.subPublications != undefined) {
this.subPublications.unsubscribe();
}
if(this.subDatasets != undefined) {
this.subDatasets.unsubscribe();
}
}
private search(content: string) {
if(content=='publicationsTab') {
this.subPublications = this.route.queryParams.subscribe(params => {
this.searchPublications();
});
} else if(content=='datasetsTab') {
this.subDatasets = this.route.queryParams.subscribe(params => {
this.searchDatasets();
});
}
ngOnDestroy() {
this.subPublications.unsubscribe();
this.subDatasets.unsubscribe();
}
private searchPublications() {
this.searchPublicationsComponent.getResultsForEntity("dataprovider", this.id, 1, 10);
if(this.reloadPublications) {
this.searchPublicationsComponent.getResultsForDataproviders(this.id, this.resultsBy, 1, 10);
}
this.reloadPublications = false;
}
private searchDatasets() {
if(this.reloadDatasets) {
this.searchDatasetsComponent.getResultsForEntity("dataprovider", this.id, 1, 10);
}
this.reloadDatasets = false;
}
}

View File

@ -131,18 +131,13 @@
Share - Bookmark
</li>
<li role="separator" class="list-group-item divider"></li>
<li class="list-group-item">
<export
[linkname]="'Download projects report (CSV) for National Science Foundation'"
[filename]="'projects.csv'"
[data]="data">
</export>
<li *ngFor="let key of organizationInfo.projects.keys()" class="list-group-item">
<a (click)="exportProjects(key)">Download projects report (CSV) for {{key}}</a>
</li>
<li class="list-group-item">
<export
[linkname]="'Download publications report (CSV) for National Science Foundation'"
[filename]="'publications.csv'">
</export>
<li *ngFor="let key of organizationInfo.projects.keys()" class="list-group-item">
<a (click)="exportPublications(key)">Download publications report (CSV) for {{key}}</a>
</li>
</ul>
</div>

View File

@ -7,8 +7,11 @@ import {OrganizationInfo} from '../../utils/entities/organizationInfo';
import { SearchDataprovidersComponent } from '../../searchPages/searchDataproviders.component';
import { SearchDataprovidersService } from '../../services/searchDataproviders.service';
import {SearchResultComponent} from '../../searchPages/searchUtils/searchResult.component';
import { SearchPublicationsComponent } from '../../searchPages/searchPublications.component';
import { SearchPublicationsService } from '../../services/searchPublications.service';
import {OpenaireProperties} from '../../utils/properties/openaireProperties';
import {ExportCSVComponent} from '../../utils/exportCSV.component';
@Component({
selector: 'organization',
@ -24,7 +27,7 @@ export class OrganizationComponent {
private emptyFundersSet: boolean = true;
public warningMessage = "";
public errorMessage = "";
private data : any = { "export":[] };
private csvData: any = {};
sub: any;
subDataproviders: any;
@ -32,12 +35,15 @@ export class OrganizationComponent {
private searchDataprovidersComponent : SearchDataprovidersComponent;
private linkToSearchDataproviders = "";
private searchPublicationsComponent : SearchPublicationsComponent;
constructor (private _organizationService: OrganizationService,
private route: ActivatedRoute,
private _searchDataprovidersService: SearchDataprovidersService) {
private _searchDataprovidersService: SearchDataprovidersService,
private _searchPublicationsService: SearchPublicationsService) {
console.info('organization constructor');
this.searchDataprovidersComponent = new SearchDataprovidersComponent(this.route, this._searchDataprovidersService);
this.searchPublicationsComponent = new SearchPublicationsComponent(this.route, this._searchPublicationsService);
}
ngOnInit() {
@ -52,16 +58,20 @@ export class OrganizationComponent {
}
});
/*
this.subDataprovidersCount = this.route.queryParams.subscribe(params => {
this._searchDataprovidersService.numOfEntityDataproviders(this.organizationId, "organizations/").subscribe(
this._searchDataprovidersService.numOfDataproviders("organizations/"+this.organizationId+"/datasources/count").subscribe(
data => {
this.searchDataprovidersComponent.totalResults = data;
console.info("this.searchDataprovidersComponent.totalResults = "+this.searchDataprovidersComponent.totalResults);
},
err => {
console.error(err);
}
);
})
*/
this.searchDataprovidersComponent.getNumForEntity("organization", this.organizationId);
}
@ -70,7 +80,7 @@ export class OrganizationComponent {
if(this.subDataproviders != undefined) {
this.subDataproviders.unsubscribe();
}
this.subDataprovidersCount.unsubscribe();
//this.subDataprovidersCount.unsubscribe();
}
private getOrganizationInfo () {
@ -90,22 +100,6 @@ export class OrganizationComponent {
this.organizationInfo.projects.forEach(function (value, key, map) {
projectsNum += value.length;
this.fundersSet.add(key);
for(let project of value) {
this.data.export[this.data.export.length] =
{
'Project title': this.quote(project.name),
'Project Acronym': this.quote(project.acronym),
'Project ID': this.quote(project.code),
'Funder': this.quote(project.funder),
'Funding Stream':this.quote(project.fundingStream),
'Funding Substream level 1': this.quote(project.fundingLevel1),
'Funding Substream level 2': this.quote(project.fundingLevel2),
'SC39': this.quote(project.sc39),
'Start Date': this.quote(project.startDate),
'End Date': this.quote(project.endDate)
};
}
}.bind(this));
}
this.projectsNum = projectsNum;
@ -119,7 +113,7 @@ export class OrganizationComponent {
);
}
handleClick(funder: string) {
private handleClick(funder: string) {
if(this.emptyFundersSet) {
this.fundersSet.clear();
this.emptyFundersSet = false;
@ -141,10 +135,77 @@ export class OrganizationComponent {
}
}
quote(word: string): string {
private exportProjects(key: string) {
let projectsData : any = { "columnNames": [], "export":[] };
let projectName = "Projects"+key;
if(!(projectName in this.csvData)) {
projectsData.columnNames = ['Project title', 'Project Acronym', 'Project ID',
'Funder', 'Funding Stream',
'Funding Substream level 1', 'Funding Substream level 2',
'SC39', 'Start Date', 'End Date'];
for(let project of this.organizationInfo.projects.get(key)) {
projectsData.export[projectsData.export.length] =
/*{
'Project title': this.quote(project.name),
'Project Acronym': this.quote(project.acronym),
'Project ID': this.quote(project.code),
'Funder': this.quote(project.funder),
'Funding Stream':this.quote(project.fundingStream),
'Funding Substream level 1': this.quote(project.fundingLevel1),
'Funding Substream level 2': this.quote(project.fundingLevel2),
'SC39': this.quote(project.sc39),
'Start Date': this.quote(project.startDate),
'End Date': this.quote(project.endDate)
};
*/
[
this.quote(project.name),
this.quote(project.acronym),
this.quote(project.code),
this.quote(project.funder),
this.quote(project.fundingStream),
this.quote(project.fundingLevel1),
this.quote(project.fundingLevel2),
this.quote(project.sc39),
this.quote(project.startDate),
this.quote(project.endDate)
];
}
this.csvData[projectName] = projectsData;
}
ExportCSVComponent.downloadCSV(this.csvData[projectName], "projects "+key+".csv");
}
private exportPublications(key: string) {
let publicationsData : any = { "columnNames": [], "export":[] };
let publicationName = "Publications"+key;
if(!(publicationName in this.csvData)) {
publicationsData.columnNames = ['Title', 'Authors', 'Publication Year',
'DOI', 'Download From', 'Publication type',
'Journal', 'Funder', 'Project Name (GA Number)', 'Access'];
for(let project of this.organizationInfo.projects.get(key)) {
let result = this.searchPublicationsComponent.getCSVResultsForEntity("project", project.id);
//publicationsData.export.concat(["aaaa", "ooo"], ["iiii", "eeee"]]);
result.every(function(item) {publicationsData.export.push(item);});
//console.info("publications export: "+publicationsData.export);
//console.info("publications export: "+result);
}
this.csvData[publicationName] = publicationsData;
}
ExportCSVComponent.downloadCSV(this.csvData[publicationName], "publications "+key+".csv");
}
private quote(word: string): string {
return '"'+word+'"';
}
//private getProjectsData(key: string): any {
//return this.projectsData;
//}
private searchDataproviders() {
this.searchDataprovidersComponent.getResultsForEntity("organization", this.organizationId, 1, 10);

View File

@ -173,7 +173,7 @@ export class SearchComponent {
this.subPublicationsCount.unsubscribe();
this.subDatasetsCount.unsubscribe();
this.subProjectsCount.unsubscribe();
this.subDataprovidersCount.unsubscribe();
//this.subDataprovidersCount.unsubscribe();
this.subOrganizationsCount.unsubscribe();
this.subPeopleCount.unsubscribe();
}
@ -289,16 +289,7 @@ export class SearchComponent {
);
})
this.subDataprovidersCount = this.route.queryParams.subscribe(params => {
this._searchDataprovidersService.numOfSearchDataproviders(this.keyword).subscribe(
data => {
this.searchDataProvidersComponent.totalResults = data;
},
err => {
console.error(err);
}
);
})
this.searchDataProvidersComponent.getNumForSearch(this.keyword);
this.subOrganizationsCount = this.route.queryParams.subscribe(params => {
this._searchOrganizationsService.numOfSearchOrganizations(this.keyword).subscribe(

View File

@ -67,6 +67,54 @@ export class SearchDataprovidersComponent {
}
}
public getNumForEntity(entity: string, id:string) {
console.info("getNumForEntity : Dataproviders Component");
var parameters="";
if(entity == "organization") {
parameters = "organizations/"+id+"/datasources/count";
}
if(parameters != "") {
this._searchDataprovidersService.numOfDataproviders(parameters).subscribe(
data => {
this.totalResults = data;
},
err => {
console.error(err);
//TODO check erros (service not available, bad request)
// if( ){
// this.status = ErrorCodes.ERROR;
// }
var errorCodes:ErrorCodes = new ErrorCodes();
this.status = errorCodes.ERROR;
}
);
}
}
public getNumForSearch(keyword: string) {
var parameters="datasources/count";
if(keyword != "") {
parameters += "?q="+keyword;
}
this._searchDataprovidersService.numOfDataproviders(parameters).subscribe(
data => {
this.totalResults = data;
},
err => {
console.error(err);
//TODO check erros (service not available, bad request)
// if( ){
// this.status = ErrorCodes.ERROR;
// }
var errorCodes:ErrorCodes = new ErrorCodes();
this.status = errorCodes.ERROR;
}
);
}
public getResultsForEntity(entity:string, id:string, page: number, size: number){
var parameters = "";

View File

@ -96,8 +96,6 @@ export class SearchPublicationsComponent {
}
console.info(params);
if(params[filter.filterId] != undefined) {
let values = params[filter.filterId].split(",");
@ -147,6 +145,29 @@ export class SearchPublicationsComponent {
}
*/
public getCSVResultsForEntity(entity:string, id:string): any {
let exportPublications = [];
exportPublications.push(//[exportPublications.length] =
[
this.quote("bla"),
this.quote("bla"),
this.quote("bla"),
this.quote("bla"),
this.quote("bla"),
this.quote("bla"),
this.quote("bla"),
this.quote("bla"),
this.quote("bla"),
this.quote("blaaaaa")
]
);
return exportPublications;
}
private quote(word: string): string {
return '"'+word+'"';
}
public getResultsForEntity(entity:string, id:string, page: number, size: number){
var parameters = "";
@ -154,8 +175,6 @@ public getResultsForEntity(entity:string, id:string, page: number, size: number)
parameters = "projects/"+id;
} else if(entity == "person") {
parameters = "people/"+id;
} else if(entity == "dataprovider") {
parameters = "datasources/"+id;
}
if(parameters != "") {
@ -185,6 +204,41 @@ public getResultsForEntity(entity:string, id:string, page: number, size: number)
}
}
public getResultsForDataproviders(id:string, resultsFrom:string, page: number, size: number){
var parameters;
if(resultsFrom == "collectedFrom") {
parameters = "publications?"+resultsFrom+"="+id+"&cl=and";
} else if(resultsFrom == "hostedBy") {
parameters = "publications?"+resultsFrom+"="+id+"&hs=and";
}
if(parameters != "") {
this._searchPublicationsService.searchPublicationsForDataproviders(parameters, page, size).subscribe(
data => {
this.totalResults = data[0];
console.info("search Datasets for Dataproviders: [Parameters:"+parameters+" ] [total results:"+this.totalResults+"]");
this.results = data[1];
var errorCodes:ErrorCodes = new ErrorCodes();
this.status = errorCodes.DONE;
if(this.totalResults == 0 ){
this.status = errorCodes.NONE;
}
},
err => {
console.error(err);
//TODO check erros (service not available, bad request)
// if( ){
// this.status = ErrorCodes.ERROR;
// }
var errorCodes:ErrorCodes = new ErrorCodes();
this.status = errorCodes.ERROR;
}
);
}
}
public getResults(keyword:string,refine:boolean, page: number, size: number){
var parameters = "";
if(keyword.length > 0){

View File

@ -64,6 +64,12 @@ export class DataProviderService {
if(this.dataProviderInfo.tabsInTypes.datasourcesTab.has(data[1].classid)) {
this.dataProviderInfo.tabs.push({"name": "Datasources", "content": "datasourcesTab"});
}
if(this.dataProviderInfo.resultTypes.collectedFrom.has(data[1].classid)) {
this.dataProviderInfo.resultsBy = "collectedFrom";
} else if(this.dataProviderInfo.resultTypes.hostedBy.has(data[1].classid)) {
this.dataProviderInfo.resultsBy = "hostedBy";
}
}
if(data[2] != null) {

View File

@ -71,7 +71,7 @@ export class OrganizationService {
if(mydata['funding'].hasOwnProperty("funder")) {
if(this.organizationInfo.projects == undefined) {
this.organizationInfo.projects = new Map<string,
{ "name": string, "url": string, "code": string,
{ "name": string, "id": string, "url": string, "code": string,
"acronym": string, "funder": string, "fundingStream": string,
"fundingLevel1": string, "fundingLevel2": string,
"sc39": string, "startDate": string, "endDate": string }[]>();
@ -79,7 +79,7 @@ export class OrganizationService {
if(!this.organizationInfo.projects.has(mydata['funding']['funder'].name)) {
this.organizationInfo.projects.set(mydata['funding']['funder'].name,
new Array<{ "name": string, "url": string, "code": string,
new Array<{ "name": string, "id": string, "url": string, "code": string,
"acronym": string, "funder": string, "fundingStream": string,
"fundingLevel1": string, "fundingLevel2": string,
"sc39": string, "startDate": string, "endDate": string }>());
@ -87,13 +87,14 @@ export class OrganizationService {
counter = this.organizationInfo.projects.get(mydata['funding']['funder'].name).length;
this.organizationInfo.projects.get(mydata['funding']['funder'].name)[counter] =
{ "name": "", "url": "", "code": "",
{ "name": "", "id": "", "url": "", "code": "",
"acronym": "", "funder": "", "fundingStream": "",
"fundingLevel1": "", "fundingLevel2": "",
"sc39": "", "startDate": "", "endDate": "" };
let url = "";
if(mydata['to'].content != null && mydata['to'].content != "") {
this.organizationInfo.projects.get(mydata['funding']['funder'].name)[counter]['id'] = mydata['to'].content;
url = OpenaireProperties.getsearchLinkToProject()+mydata['to'].content;
}
this.organizationInfo.projects.get(mydata['funding']['funder'].name)[counter]['name'] = mydata.title;

View File

@ -99,22 +99,12 @@ export class SearchDataprovidersService {
return results;
}
numOfEntityDataproviders(id: string, entity: string):any {
numOfDataproviders(params: string):any {
console.info("getOfDataproviders : Dataproviders Service + params="+params);
//OpenaireProperties.getSearchAPIURL()
//"http://rudie.di.uoa.gr:8080/dnet-functionality-services-2.0.0-SNAPSHOT/rest/v2/api/"
let url = OpenaireProperties.getSearchAPIURL()+entity+id+"/datasources/count"
return this.http.get(url)
.map(res => <any> res.json())
.map(res => res.total);
}
numOfSearchDataproviders(params: string):any {
//OpenaireProperties.getSearchAPIURL()
//"http://rudie.di.uoa.gr:8080/dnet-functionality-services-2.0.0-SNAPSHOT/rest/v2/api/"
let url = OpenaireProperties.getSearchAPIURL()+"datasources/count?q="+params;
let url = OpenaireProperties.getSearchAPIURL()+params;
return this.http.get(url)
.map(res => <any> res.json())

View File

@ -40,6 +40,15 @@ export class SearchPublicationsService {
.map(res => [res['meta'].total, this.parseResults(res['results'])]);
}
searchPublicationsForDataproviders(params: string, page: number, size: number):any {
let link = OpenaireProperties.getSearchAPIURL();
let url = link+params;
return this.http.get(url)
.map(res => <any> res.json())
.map(res => [res['meta'].total, this.parseResults(res['results'])]);
}
parseResults(data: any): SearchResult[] {
let results: SearchResult[] = [];

View File

@ -40,6 +40,28 @@ export class DataProviderInfo {
"datasourcesTab": new Set<string>(["entityregistry::repositories"])
};
resultsBy: string;
resultTypes = {
"collectedFrom": new Set<string>(
[ "aggregator::datarepository",
"aggregator::pubsrepository::institutional",
"aggregator::pubsrepository::unknown",
"aggregator::pubsrepository::journals",
"entityregistry::projects",
"infospace",
"scholarcomminfra",
"pubscatalogue::unknown"
]),
"hostedBy": new Set<string>(
[ "crissystem",
"datarepository::unknown",
"pubsrepository::institutional",
"pubsrepository::journal",
"pubsrepository::unknown",
"pubsrepository::thematic"
])
};
organizations: {"name": string, "url": string}[];
//publications: any;
datasets: any;

View File

@ -3,7 +3,7 @@ export class OrganizationInfo {
name: string;
country: string;
projects: Map<string, { "name": string, "url": string, "code": string,
projects: Map<string, { "name": string, "id":string, "url": string, "code": string,
"acronym": string, "funder": string, "fundingStream": string,
"fundingLevel1": string, "fundingLevel2": string,
"sc39": string, "startDate": string, "endDate": string }[]>;

View File

@ -4,7 +4,7 @@ import {Component, Input} from '@angular/core';
selector: 'export',
template: `
<a *ngIf="data != undefined && data != null && data.export != undefined && data.export != null"
(click)="downloadCSV()">
(click)="downloadCSV(data, filename)">
{{linkname}}
</a>
@ -18,7 +18,10 @@ import {Component, Input} from '@angular/core';
export class ExportCSVComponent {
stockData : any =
{
"columnNames":
["Symbol", "Company", "Price"],
"export":
/*
[
{
Symbol: "AAPL",
@ -36,6 +39,26 @@ export class ExportCSVComponent {
Price: "554.52"
},
],
*/
[
[
"AAPL",
"Apple Inc.",
"132.54"
],
[
"INTC",
"Intel Corporation",
"33.45"
],
[
"GOOG",
"Google Inc",
"554.52"
],
],
"columnDelimiter": ',',
"lineDelimiter": '\n'
@ -52,12 +75,13 @@ export class ExportCSVComponent {
ngOnInit() {
}
convertArrayOfObjectsToCSV(args) {
public static convertArrayOfObjectsToCSV(args) {
console.info("convertArrayOfObjectsToCSV");
var result, ctr, keys, columnDelimiter, lineDelimiter, data;
data = args.export || null;
if (data == null || !data.length) {
return null;
}
@ -65,12 +89,13 @@ export class ExportCSVComponent {
columnDelimiter = args.columnDelimiter || ',';
lineDelimiter = args.lineDelimiter || '\n';
keys = Object.keys(data[0]);
//keys = Object.keys(data[0]);
keys = args.columnNames;
result = '';
result += keys.join(columnDelimiter);
result += lineDelimiter;
/*
data.forEach(function(item) {
ctr = 0;
keys.forEach(function(key) {
@ -80,28 +105,39 @@ export class ExportCSVComponent {
});
result += lineDelimiter;
});
*/
for(let line of data) {
ctr = 0;
for(let column of line) {
if (ctr > 0) result += columnDelimiter;
result += column;
ctr++;
}
result += lineDelimiter;
}
return result;
}
downloadCSV() {
public static downloadCSV(data: any, filenameArg: string) {
console.info("downloadCSV");
var data, filename, link;
var encodedData, filename, link;
var csv = this.convertArrayOfObjectsToCSV(this.data);
var csv = this.convertArrayOfObjectsToCSV(data);
if (csv == null) return;
filename = this.filename || 'export.csv';
filename = filenameArg || 'export.csv';
if (!csv.match(/^data:text\/csv/i)) {
csv = 'data:text/csv;charset=utf-8,' + csv;
}
data = encodeURI(csv);
encodedData = encodeURI(csv);
//link = document.createElement('a');
link = document.getElementsByTagName('a');
link[0].setAttribute('href', data);
link[0].setAttribute('href', encodedData);
link[0].setAttribute('download', filename);
//document.body.appendChild(link);
link[0].click();