Skip to content

Commit

Permalink
feat(module:upload): support Observable in nzFilter (#2590)
Browse files Browse the repository at this point in the history
* feat(module:upload): support Observable in nzFilter

* chore: fix test

* fix(module:list): fix missing :host

close #2389
  • Loading branch information
cipchk authored and hsuanxyz committed Dec 11, 2018
1 parent 40efae1 commit c664c6f
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 25 deletions.
6 changes: 1 addition & 5 deletions components/list/nz-list.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,7 @@ import { NzListGrid } from './interface';
encapsulation : ViewEncapsulation.None,
changeDetection : ChangeDetectionStrategy.OnPush,
styles : [ `
:host {
display: block;
}
nz-spin {
nz-list, nz-list nz-spin {
display: block;
}
` ]
Expand Down
52 changes: 41 additions & 11 deletions components/upload/demo/avatar.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Component } from '@angular/core';
import { NzMessageService, UploadFile } from 'ng-zorro-antd';
import { Observable, Observer } from 'rxjs';

@Component({
selector: 'nz-demo-upload-avatar',
Expand All @@ -20,7 +21,7 @@ import { NzMessageService, UploadFile } from 'ng-zorro-antd';
`,
styles: [
`
:host ::ng-deep .avatar-uploader > .ant-upload {
:host ::ng-deep .avatar-uploader > .ant-upload, :host ::ng-deep .avatar {
width: 128px;
height: 128px;
}
Expand All @@ -39,18 +40,34 @@ export class NzDemoUploadAvatarComponent {
loading = false;
avatarUrl: string;

constructor(private msg: NzMessageService) {}
constructor(private msg: NzMessageService) { }

beforeUpload = (file: File) => {
const isJPG = file.type === 'image/jpeg';
if (!isJPG) {
this.msg.error('You can only upload JPG file!');
}
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
this.msg.error('Image must smaller than 2MB!');
}
return isJPG && isLt2M;
return new Observable((observer: Observer<boolean>) => {
const isJPG = file.type === 'image/jpeg';
if (!isJPG) {
this.msg.error('You can only upload JPG file!');
observer.complete();
return;
}
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
this.msg.error('Image must smaller than 2MB!');
observer.complete();
return;
}
// check height
this.checkImageDimension(file).then(dimensionRes => {
if (!dimensionRes) {
this.msg.error('Image only 300x300 above');
observer.complete();
return;
}

observer.next(isJPG && isLt2M && dimensionRes);
observer.complete();
});
});
}

private getBase64(img: File, callback: (img: string) => void): void {
Expand All @@ -59,6 +76,19 @@ export class NzDemoUploadAvatarComponent {
reader.readAsDataURL(img);
}

private checkImageDimension(file: File): Promise<boolean> {
return new Promise(resolve => {
const img = new Image(); // create image
img.src = window.URL.createObjectURL(file);
img.onload = () => {
const width = img.naturalWidth;
const height = img.naturalHeight;
window.URL.revokeObjectURL(img.src);
resolve(width === height && width >= 300);
};
});
}

handleChange(info: { file: UploadFile }): void {
if (info.file.status === 'uploading') {
this.loading = true;
Expand Down
13 changes: 12 additions & 1 deletion components/upload/demo/filter.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Component } from '@angular/core';
import { UploadFile, UploadFilter, NzMessageService } from 'ng-zorro-antd';
import { NzMessageService, UploadFile, UploadFilter } from 'ng-zorro-antd';
import { Observable, Observer } from 'rxjs';

@Component({
selector: 'nz-demo-upload-filter',
Expand Down Expand Up @@ -32,6 +33,16 @@ export class NzDemoUploadFilterComponent {
}
return fileList;
}
},
{
name: 'async',
fn: (fileList: UploadFile[]) => {
return new Observable((observer: Observer<UploadFile[]>) => {
// doing
observer.next(fileList);
observer.complete();
});
}
}
];

Expand Down
2 changes: 1 addition & 1 deletion components/upload/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export interface ZipButtonOptions {

export interface UploadFilter {
name: string;
fn: (fileList: UploadFile[]) => UploadFile[];
fn: (fileList: UploadFile[]) => UploadFile[] | Observable<UploadFile[]>;
}

export interface UploadXHRArgs {
Expand Down
24 changes: 18 additions & 6 deletions components/upload/nz-upload-btn.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import {
ViewChild,
ViewEncapsulation
} from '@angular/core';
import { Observable, Subscription } from 'rxjs';
import { of, Observable, Subscription } from 'rxjs';
import { switchMap } from 'rxjs/operators';

import { NzUpdateHostClassService } from '../core/services/update-host-class.service';

Expand Down Expand Up @@ -143,11 +144,20 @@ export class NzUploadBtnComponent implements OnInit, OnChanges, OnDestroy {
}

uploadFiles(fileList: FileList | File[]): void {
let postFiles: UploadFile[] = Array.prototype.slice.call(fileList);
this.options.filters.forEach(f => postFiles = f.fn(postFiles));
postFiles.forEach((file: UploadFile) => {
this.attachUid(file);
this.upload(file, postFiles);
let filters$: Observable<UploadFile[]> = of(Array.prototype.slice.call(fileList));
this.options.filters.forEach(f => {
filters$ = filters$.pipe(switchMap(list => {
const fnRes = f.fn(list);
return fnRes instanceof Observable ? fnRes : of(fnRes);
}));
});
filters$.subscribe(list => {
list.forEach((file: UploadFile) => {
this.attachUid(file);
this.upload(file, list);
});
}, e => {
console.warn(`Unhandled upload filter error`, e);
});
}

Expand All @@ -165,6 +175,8 @@ export class NzUploadBtnComponent implements OnInit, OnChanges, OnDestroy {
} else if (typeof processedFile === 'boolean' && processedFile !== false) {
this.post(file);
}
}, e => {
console.warn(`Unhandled upload beforeUpload error`, e);
});
} else if (before !== false) {
return this.post(file);
Expand Down
62 changes: 61 additions & 1 deletion components/upload/upload.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { fakeAsync, tick, ComponentFixture, TestBed } from '@angular/core/testin
import { FormsModule } from '@angular/forms';
import { By } from '@angular/platform-browser';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { of, Observable } from 'rxjs';
import { of, throwError, Observable, Observer } from 'rxjs';
import { delay } from 'rxjs/operators';

import { NzI18nModule, NzI18nService } from '../i18n';
Expand Down Expand Up @@ -332,6 +332,17 @@ describe('upload', () => {
pageObject.postSmall();
expect(instance._nzChange).toBeUndefined();
});
it('should be console.warn error', () => {
let warnMsg = '';
console.warn = jasmine.createSpy().and.callFake(res => warnMsg = res);
expect(instance._nzChange).toBeUndefined();
instance.beforeUpload = (file: UploadFile, fileList: UploadFile[]): Observable<any> => {
return throwError('');
};
fixture.detectChanges();
pageObject.postSmall();
expect(warnMsg).toContain(`Unhandled upload beforeUpload error`);
});
});
});

Expand Down Expand Up @@ -380,6 +391,55 @@ describe('upload', () => {
pageObject.postFile(JPGSMALL.target.files);
expect(instance._beforeUploadList.length).toBe(0);
});
describe('with Observable', () => {
it('shoule working', () => {
instance.nzFilter = [
{
name: 'f1',
fn: (fileList: UploadFile[]) => {
return new Observable((observer: Observer<UploadFile[]>) => {
observer.next(fileList.slice(1));
observer.complete();
});
}
},
{
name: 'f2',
fn: (fileList: UploadFile[]) => {
return new Observable((observer: Observer<UploadFile[]>) => {
observer.next(fileList.slice(1));
observer.complete();
});
}
}
];
fixture.detectChanges();
expect(instance._beforeUploadList.length).toBe(0);
pageObject.postFile([
...PNGSMALL.target.files,
...PNGSMALL.target.files,
...PNGSMALL.target.files
]);
expect(instance._beforeUploadList.length).toBe(1);
});
it('should be console.warn error', () => {
let warnMsg = '';
console.warn = jasmine.createSpy().and.callFake(res => warnMsg = res);
instance.nzFilter = [
{
name: 'f1',
fn: (fileList: UploadFile[]) => {
return new Observable((observer: Observer<UploadFile[]>) => {
observer.error('filter error');
});
}
}
];
fixture.detectChanges();
pageObject.postFile(PNGSMALL.target.files);
expect(warnMsg).toContain(`Unhandled upload filter error`);
});
});
});

it('#nzFileList, should be allow empty', () => {
Expand Down

0 comments on commit c664c6f

Please sign in to comment.