Skip to content

Commit

Permalink
build: bump to angualr 19 (#62)
Browse files Browse the repository at this point in the history
  • Loading branch information
cipchk authored Nov 23, 2024
1 parent 28f9eb8 commit 2d5110a
Show file tree
Hide file tree
Showing 11 changed files with 5,056 additions and 5,184 deletions.
7 changes: 7 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.fixAll.stylelint": "explicit"
}
}
893 changes: 0 additions & 893 deletions .yarn/releases/yarn-4.0.1.cjs

This file was deleted.

934 changes: 934 additions & 0 deletions .yarn/releases/yarn-4.5.2.cjs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .yarnrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ enableImmutableInstalls: false

nodeLinker: node-modules

yarnPath: .yarn/releases/yarn-4.0.1.cjs
yarnPath: .yarn/releases/yarn-4.5.2.cjs
2 changes: 1 addition & 1 deletion lib/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ngx-filesaver",
"version": "18.0.0",
"version": "19.0.0",
"description": "Simple file save with FileSaver.js",
"keywords": [
"angular",
Expand Down
22 changes: 13 additions & 9 deletions lib/spec/filesaver.directive.spec.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { ApplicationRef, Component, DebugElement, Injector } from '@angular/core';
import { By } from '@angular/platform-browser';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { HttpHeaders } from '@angular/common/http';
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
import { HttpHeaders, provideHttpClient } from '@angular/common/http';
import * as fs from 'file-saver';

import { FileSaverModule } from '../src/filesaver.module';
import { FileSaverDirective } from '../src/filesaver.directive';
import { FileSaverService } from '../src/filesaver.service';

function genFile(ext: string, isRealFile = true): Blob {
function genFile(_: string, isRealFile = true): Blob {
const blob = new Blob([
isRealFile ? `iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==` : '',
]);
Expand All @@ -25,8 +24,8 @@ describe('ngx-filesaver:', () => {

beforeEach(() => {
injector = TestBed.configureTestingModule({
imports: [HttpClientTestingModule, FileSaverModule],
declarations: [TestComponent],
providers: [provideHttpClient(), provideHttpClientTesting()],
imports: [TestComponent],
});

fixture = TestBed.createComponent(TestComponent);
Expand Down Expand Up @@ -143,8 +142,8 @@ describe('change detection', () => {

beforeEach(() => {
injector = TestBed.configureTestingModule({
imports: [HttpClientTestingModule, FileSaverModule],
declarations: [TestNoListenersComponent],
providers: [provideHttpClient(), provideHttpClientTesting()],
imports: [TestNoListenersComponent],
});

fixture = TestBed.createComponent(TestNoListenersComponent);
Expand All @@ -166,8 +165,8 @@ describe('change detection', () => {

@Component({
template: `
@for (i of fileTypes; track $index) {
<button
*ngFor="let i of fileTypes"
id="down-{{ i }}"
class="mr-sm"
fileSaver
Expand All @@ -180,7 +179,10 @@ describe('change detection', () => {
>
{{ i }}
</button>
}
`,
standalone: true,
imports: [FileSaverDirective],
})
class TestComponent {
fileTypes = ['xlsx', 'docx', 'pptx', 'pdf'];
Expand All @@ -199,6 +201,8 @@ class TestComponent {

@Component({
template: '<button id="down-xlsx" fileSaver query="data" method="get" url="/demo.xlsx" [fileName]="fileName">xlsx</button>',
standalone: true,
imports: [FileSaverDirective],
})
class TestNoListenersComponent {
fileName = 'demo中文';
Expand Down
70 changes: 27 additions & 43 deletions lib/src/filesaver.directive.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
/* eslint-disable @angular-eslint/no-output-native */
import { Directive, ElementRef, Input, EventEmitter, Output, NgZone, OnDestroy, OnInit } from '@angular/core';
import { Directive, ElementRef, NgZone, OnInit, inject, DestroyRef, input } from '@angular/core';
import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http';
import { filter, fromEvent, Observable, Subject, takeUntil } from 'rxjs';
import { filter, fromEvent, Observable, Subject } from 'rxjs';
import { FileSaverOptions } from 'file-saver';
import { FileSaverService } from './filesaver.service';
import { outputFromObservable, takeUntilDestroyed } from '@angular/core/rxjs-interop';

@Directive({
selector: '[fileSaver]',
exportAs: 'fileSaver',
standalone: true,
})
export class FileSaverDirective implements OnInit, OnDestroy {
@Input() method = 'GET';
@Input() http?: Observable<HttpResponse<Blob>>;
@Input() query: any;
@Input() header: any;
@Input({ required: true }) url!: string;
@Input() fileName?: string;
@Input() fsOptions?: FileSaverOptions;
@Output() readonly success = new EventEmitter<HttpResponse<Blob>>();
@Output() readonly error = new EventEmitter<any>();
export class FileSaverDirective implements OnInit {
readonly method = input('GET');
readonly http = input<Observable<HttpResponse<Blob>>>();
readonly query = input<any>();
readonly header = input<any>();
readonly url = input.required<string>();
readonly fileName = input<string>();
readonly fsOptions = input<FileSaverOptions>();
private successEmitter = new Subject<HttpResponse<Blob>>();
readonly success = outputFromObservable(this.successEmitter);
private errorEmitter = new Subject<any>();
readonly error = outputFromObservable(this.errorEmitter);

private readonly destroy$ = new Subject<void>();
private readonly d$ = inject(DestroyRef);

constructor(
private ngZone: NgZone,
Expand All @@ -38,12 +40,8 @@ export class FileSaverDirective implements OnInit, OnDestroy {
this.ngZone.runOutsideAngular(() => this.setupClickListener());
}

ngOnDestroy(): void {
this.destroy$.next();
}

private getName(res: HttpResponse<Blob>) {
return decodeURI(this.fileName || res.headers.get('filename') || res.headers.get('x-filename') || '');
return decodeURI(this.fileName() || res.headers.get('filename') || res.headers.get('x-filename') || '');
}

setDisabled(status: boolean): void {
Expand All @@ -56,54 +54,40 @@ export class FileSaverDirective implements OnInit, OnDestroy {
fromEvent(this.el.nativeElement, 'click')
.pipe(
filter(() => this.fss.isFileSaverSupported),
takeUntil(this.destroy$),
takeUntilDestroyed(this.d$),
)
.subscribe(() => {
let req = this.http;
let req = this.http();

if (!req) {
let params = new HttpParams();
const query = this.query || {};
const query = this.query() || {};
for (const item in query) {
params = params.set(item, query[item]);
}

req = this.httpClient.request(this.method, this.url, {
req = this.httpClient.request(this.method(), this.url(), {
observe: 'response',
responseType: 'blob',
headers: this.header,
headers: this.header(),
params,
});
}

this.setDisabled(true);

req.pipe(takeUntil(this.destroy$)).subscribe({
req.pipe(takeUntilDestroyed(this.d$)).subscribe({
next: (response) => {
if (response.status !== 200 || response.body!.size <= 0) {
this.emitIfHasObservers(this.error, response);
this.errorEmitter.next(response);
return;
}
this.fss.save(response.body, this.getName(response), undefined, this.fsOptions);
this.emitIfHasObservers(this.success, response);
this.fss.save(response.body, this.getName(response), undefined, this.fsOptions());
this.successEmitter.next(response);
},
error: (error) => this.emitIfHasObservers(this.error, error),
error: (error) => this.errorEmitter.next(error),
complete: () => this.setDisabled(false),
});
});
}

private emitIfHasObservers<T>(emitter: EventEmitter<T>, value: T): void {
if (hasObservers(emitter)) {
// Re-enter the Angular zone only if there're any `error` or `success` listeners
// on the directive, for instance, `(success)="..."`.
this.ngZone.run(() => emitter.emit(value));
}
}
}

function hasObservers<T>(subject: Subject<T>): boolean {
// Note: The `observed` property is available only in [email protected], which means it's
// not available for users running the lower version.
return subject.observed ?? subject.observers.length > 0;
}
51 changes: 26 additions & 25 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ngx-filesaver",
"version": "18.0.0",
"version": "19.0.0",
"description": "Simple file save with FileSaver.js",
"repository": {
"type": "git",
Expand Down Expand Up @@ -29,40 +29,41 @@
"release:next": "npm run build && cd publish && npm publish --access public --tag next"
},
"dependencies": {
"@angular/animations": "^18.0.0",
"@angular/common": "^18.0.0",
"@angular/compiler": "^18.0.0",
"@angular/core": "^18.0.0",
"@angular/forms": "^18.0.0",
"@angular/platform-browser": "^18.0.0",
"@angular/platform-browser-dynamic": "^18.0.0",
"@angular/router": "^18.0.0",
"@angular/animations": "^19.0.0",
"@angular/common": "^19.0.0",
"@angular/compiler": "^19.0.0",
"@angular/core": "^19.0.0",
"@angular/forms": "^19.0.0",
"@angular/platform-browser": "^19.0.0",
"@angular/platform-browser-dynamic": "^19.0.0",
"@angular/router": "^19.0.0",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.3"
"zone.js": "~0.15.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "^18.0.4",
"@angular-eslint/builder": "^18.0.0",
"@angular-eslint/eslint-plugin": "^18.0.0",
"@angular-eslint/eslint-plugin-template": "^18.0.0",
"@angular-eslint/schematics": "^18.0.0",
"@angular-eslint/template-parser": "^18.0.0",
"@angular/cli": "^18.0.4",
"@angular/compiler-cli": "^18.0.0",
"@types/file-saver": "^2.0.5",
"@angular-devkit/build-angular": "^19.0.1",
"@angular-eslint/builder": "^18.4.1",
"@angular-eslint/eslint-plugin": "^18.4.1",
"@angular-eslint/eslint-plugin-template": "^18.4.1",
"@angular-eslint/schematics": "^18.4.1",
"@angular-eslint/template-parser": "^18.4.1",
"@angular/cli": "^19.0.1",
"@angular/compiler-cli": "^19.0.0",
"@types/file-saver": "^2.0.7",
"@types/jasmine": "~5.1.0",
"@typescript-eslint/eslint-plugin": "^7.13.0",
"@typescript-eslint/parser": "^7.13.0",
"@typescript-eslint/eslint-plugin": "^8.15.0",
"@typescript-eslint/parser": "^8.15.0",
"eslint": "^8.53.0",
"file-saver": "^2.0.5",
"jasmine-core": "~5.1.0",
"jasmine-core": "~5.4.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "~2.2.0",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"ng-packagr": "^18.0.0",
"typescript": "~5.4.2"
}
"ng-packagr": "^19.0.1",
"typescript": "~5.6.2"
},
"packageManager": "[email protected]"
}
3 changes: 1 addition & 2 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ import { FileSaverDirective, FileSaverService } from 'ngx-filesaver';
<button type="button" fileSaver url="assets/files/demo.docx">Save Word</button>
`,
encapsulation: ViewEncapsulation.None,
standalone: true,
imports: [CommonModule, FormsModule, FileSaverDirective],
imports: [CommonModule, FormsModule, FileSaverDirective],
})
export class AppComponent {
text = `{ "text": "This is text file!中文" }`;
Expand Down
Loading

0 comments on commit 2d5110a

Please sign in to comment.