Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 3 additions & 10 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
language: node_js
node_js:
- '10'
dist: xenial
sudo: required
services:
- xvfb
addons:
chrome: stable
before_script:
- export DISPLAY=:99.0
- '20'
- '22'
install:
- npm install
script:
- npm run test
- npm test
46 changes: 27 additions & 19 deletions Angular-csv.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
/* tslint:disable:no-unused-variable */

import {AngularCsv, CsvConfigConsts} from './Angular-csv';

beforeAll(() => {
global.URL.createObjectURL = jest.fn(() => 'blob:mock');
global.URL.revokeObjectURL = jest.fn();
});

describe('Component: AngularCsv', () => {


Expand Down Expand Up @@ -37,7 +40,7 @@ describe('Component: AngularCsv', () => {
let component = new AngularCsv([{name: 'test', age: 20}], 'My Report', {useBom: false, quoteStrings: '|'});
let csv = component['csv'];
let first_row = csv.split(CsvConfigConsts.EOL)[0].split(',');
expect(first_row[0]).toMatch('\\|.*\\|');
expect(first_row[0]).toMatch(/\|.*\|/);
});

it('should return csv file with correct header labels', () => {
Expand All @@ -53,32 +56,38 @@ describe('Component: AngularCsv', () => {
});

it('should return csv file with data aligned with passed header object', () => {
let component = new AngularCsv([{ name: 'test', age: 20 },{ age: 22, name: 'test22'}], 'My Report', {
useObjHeader : true,
let component = new AngularCsv([{ name: 'test', age: 20 }, { age: 22, name: 'test22'}], 'My Report', {
useObjHeader: true,
objHeader: {
name: "Name",
age: "Age"
},
useBom: false
});
let csv = component['csv'];

let labels = csv.split(CsvConfigConsts.EOL)[0].split(',');
let row1 = csv.split(CsvConfigConsts.EOL)[1].split(',');
let row2 = csv.split(CsvConfigConsts.EOL)[2].split(',');

/**
* Commented tests fail for some reason, however it works as expected
*/

// expect(labels[0]).toEqual('Name');
expect(labels[1]).toEqual('Age')

// expect(row1[0]).toEqual('test');
expect(labels[0]).toEqual('Name');
expect(labels[1]).toEqual('Age');
expect(row1[0]).toEqual('"test"');
expect(row1[1]).toEqual('20');

// expect(row2[0]).toEqual('test22');
expect(row2[0]).toEqual('"test22"');
expect(row2[1]).toEqual('22');
})
});

it('should only include header keys when useHeader is true', () => {
let component = new AngularCsv([{name: 'test', age: 20, city: 'x'}], 'My Report', {
useBom: false,
headers: ['name', 'age'],
useHeader: true
});
let csv = component['csv'];
let first_row = csv.split(CsvConfigConsts.EOL)[0].split(',');
expect(first_row.length).toBe(2);
});

it('should return nulls as empty strings if the options is selected', () => {
let component = new AngularCsv([{name: null, age: null}], 'My Report', {useBom: false, nullToEmptyString: true});
Expand All @@ -87,6 +96,5 @@ describe('Component: AngularCsv', () => {
let first_row = csv_rows[0].replace(/"/g, '').split(',');
expect(first_row[0]).toEqual('');
expect(first_row[1]).toBe('');

})
});
});
});
120 changes: 32 additions & 88 deletions Angular-csv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export interface Options {
title: string;
useBom: boolean;
headers: string[];
objHeader: any;
objHeader: Record<string, string>;
noDownload: boolean;
useObjHeader: boolean;
useHeader: boolean;
Expand Down Expand Up @@ -56,8 +56,8 @@ export const ConfigDefaults: Options = {

export class AngularCsv {

public fileName: string;
public labels: Array<String>;
public fileName: string = '';
public labels: Array<string> = [];
public data: any[];

private _options: Options;
Expand All @@ -68,11 +68,8 @@ export class AngularCsv {

this.data = typeof DataJSON != 'object' ? JSON.parse(DataJSON) : DataJSON;

this._options = objectAssign({}, ConfigDefaults, config);

if (this._options.filename) {
this._options.filename = filename;
}
this._options = Object.assign({}, ConfigDefaults, config);
this._options.filename = filename;

this.generateCsv();
}
Expand All @@ -97,49 +94,42 @@ export class AngularCsv {
this.getHeaders();
this.getBody();
}

if (this.csv == '') {
console.log("Invalid data");
return;
}

if(this._options.noDownload) {
if (this._options.noDownload) {
return this.csv;
}

let blob = new Blob([this.csv], {"type": "text/csv;charset=utf8;"});
let blob = new Blob([this.csv], { "type": "text/csv;charset=utf8;" });

if (navigator.msSaveBlob) {
let filename = this._options.filename.replace(/ /g, "_") + ".csv";
navigator.msSaveBlob(blob, filename);
} else {
let uri = 'data:attachment/csv;charset=utf-8,' + encodeURI(this.csv);
let link = document.createElement("a");
let link = document.createElement("a");

link.href = URL.createObjectURL(blob);
link.href = URL.createObjectURL(blob);

link.setAttribute('target', '_blank');
link.setAttribute('visibility', 'hidden');
link.download = this._options.filename.replace(/ /g, "_") + ".csv";
link.setAttribute('visibility', 'hidden');
link.download = this._options.filename.replace(/ /g, "_") + ".csv";

document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}

/**
* Create Headers
*/
getHeaders(): void {
if (this._options.headers.length > 0) {
const { headers } = this._options;
let row = headers.reduce((headerRow, header) => {
return headerRow + header + this._options.fieldSeparator;
}, '');
row = row.slice(0, -1);
this.csv += row + CsvConfigConsts.EOL;
}
if (this._options.headers.length > 0) {
const { headers } = this._options;
let row = headers.reduce((headerRow, header) => {
return headerRow + header + this._options.fieldSeparator;
}, '');
row = row.slice(0, -1);
this.csv += row + CsvConfigConsts.EOL;
}
}

/**
Expand Down Expand Up @@ -179,13 +169,13 @@ export class AngularCsv {
for (let i = 0; i < this.data.length; i++) {
let row = "";
if (this._options.useHeader && this._options.headers.length > 0) {
for (const index of this._options.headers) {
row += this.formatData(this.data[i][index]) + this._options.fieldSeparator;
}
for (const index of this._options.headers) {
row += this.formatData(this.data[i][index]) + this._options.fieldSeparator;
}
} else {
for (const index in this.data[i]) {
row += this.formatData(this.data[i][index]) + this._options.fieldSeparator;
}
for (const index in this.data[i]) {
row += this.formatData(this.data[i][index]) + this._options.fieldSeparator;
}
}
row = row.slice(0, -1);
this.csv += row + CsvConfigConsts.EOL;
Expand Down Expand Up @@ -215,13 +205,12 @@ export class AngularCsv {
}

if (this._options.nullToEmptyString) {
if(!data) {
if (data === null) {
return data = '';
}else{
return data;
}
return data;
}

if (typeof data === 'boolean') {
return data ? 'TRUE' : 'FALSE';
}
Expand All @@ -241,48 +230,3 @@ export class AngularCsv {
return +input === input && (!isFinite(input) || Boolean(input % 1));
}
}

let hasOwnProperty = Object.prototype.hasOwnProperty;
let propIsEnumerable = Object.prototype.propertyIsEnumerable;

/**
* Convet to Object
* @param {any} val
*/
function toObject(val: any) {
if (val === null || val === undefined) {
throw new TypeError('Object.assign cannot be called with null or undefined');
}
return Object(val);
}

/**
* Assign data to new Object
* @param {any} target
* @param {any[]} ...source
*/
function objectAssign(target: any, ...source: any[]) {
let from: any;
let to = toObject(target);
let symbols: any;

for (let s = 1; s < arguments.length; s++) {
from = Object(arguments[s]);

for (const key in from) {
if (hasOwnProperty.call(from, key)) {
to[key] = from[key];
}
}

if ((<any>Object).getOwnPropertySymbols) {
symbols = (<any>Object).getOwnPropertySymbols(from);
for (let i = 0; i < symbols.length; i++) {
if (propIsEnumerable.call(from, symbols[i])) {
to[symbols[i]] = from[symbols[i]];
}
}
}
}
return to;
}
Loading