Skip to content

Commit

Permalink
Fix build and update packages
Browse files Browse the repository at this point in the history
  • Loading branch information
salamaashoush committed Feb 16, 2024
1 parent ebe676b commit 105226f
Show file tree
Hide file tree
Showing 10 changed files with 884 additions and 2,528 deletions.
10 changes: 1 addition & 9 deletions apps/demo/src/app/app.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { TestBed } from '@angular/core/testing';
import { AppComponent } from './app.component';
import { NxWelcomeComponent } from './nx-welcome.component';
import { RouterTestingModule } from '@angular/router/testing';

describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AppComponent, NxWelcomeComponent, RouterTestingModule],
imports: [AppComponent],
}).compileComponents();
});

Expand All @@ -16,10 +14,4 @@ describe('AppComponent', () => {
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain('Welcome demo');
});

it(`should have as title 'demo'`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app.title).toEqual('demo');
});
});
12 changes: 5 additions & 7 deletions apps/demo/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,9 @@ export class AppComponent {
onRowClick = (event: any) => console.log('Grid row clicked', event);

columns = ['Name', 'Email', 'Phone Number'];
data: TData = new Array(20)
.fill(undefined)
.map(() => [
faker.person.fullName(),
faker.internet.email(),
faker.phone.number(),
]);
data: TData = Array.from({ length: 100 }).map(() => [
faker.person.fullName(),
faker.internet.email(),
faker.phone.number(),
]);
}
59 changes: 31 additions & 28 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,38 @@
"license": "MIT",
"scripts": {
"build": "nx build gridjs-angular",
"dev": "nx serve demo"
"test": "nx test gridjs-angular",
"dev": "nx serve demo",
"publish": "cd dist/packages/gridjs-angular && pnpm publish --access public",
"prepublishOnly": "pnpm run build"
},
"private": true,
"dependencies": {
"@angular/animations": "~17.1.2",
"@angular/common": "~17.1.2",
"@angular/compiler": "~17.1.2",
"@angular/core": "~17.1.2",
"@angular/forms": "~17.1.2",
"@angular/platform-browser": "~17.1.2",
"@angular/platform-browser-dynamic": "~17.1.2",
"@angular/router": "~17.1.2",
"@angular/animations": "~17.2.1",
"@angular/common": "~17.2.1",
"@angular/compiler": "~17.2.1",
"@angular/core": "~17.2.1",
"@angular/forms": "~17.2.1",
"@angular/platform-browser": "~17.2.1",
"@angular/platform-browser-dynamic": "~17.2.1",
"@angular/router": "~17.2.1",
"@nx/angular": "17.3.1",
"gridjs": "^6.1.1",
"rxjs": "~7.8.1",
"tslib": "^2.6.2",
"zone.js": "~0.14.3"
"zone.js": "~0.14.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "~17.1.2",
"@angular-devkit/core": "~17.1.2",
"@angular-devkit/schematics": "~17.1.2",
"@angular-devkit/build-angular": "~17.2.0",
"@angular-devkit/core": "~17.2.0",
"@angular-devkit/schematics": "~17.2.0",
"@angular-eslint/eslint-plugin": "~17.2.1",
"@angular-eslint/eslint-plugin-template": "~17.2.1",
"@angular-eslint/template-parser": "~17.2.1",
"@angular/cli": "~17.1.2",
"@angular/compiler-cli": "~17.1.2",
"@angular/language-service": "~17.1.2",
"@faker-js/faker": "^8.4.0",
"@angular/cli": "~17.2.0",
"@angular/compiler-cli": "~17.2.1",
"@angular/language-service": "~17.2.1",
"@faker-js/faker": "^8.4.1",
"@nx/devkit": "17.3.1",
"@nx/eslint": "17.3.1",
"@nx/eslint-plugin": "17.3.1",
Expand All @@ -41,29 +44,29 @@
"@nx/playwright": "17.3.1",
"@nx/workspace": "17.3.1",
"@playwright/test": "^1.41.2",
"@schematics/angular": "~17.1.2",
"@schematics/angular": "~17.2.0",
"@swc-node/register": "~1.8.0",
"@swc/core": "~1.3.107",
"@swc/helpers": "~0.5.3",
"@swc/core": "~1.4.1",
"@swc/helpers": "~0.5.6",
"@types/jest": "^29.5.12",
"@types/node": "18.16.9",
"@typescript-eslint/eslint-plugin": "^6.20.0",
"@typescript-eslint/parser": "^6.20.0",
"@typescript-eslint/eslint-plugin": "^7.0.1",
"@typescript-eslint/parser": "^7.0.1",
"autoprefixer": "^10.4.17",
"change-case": "^5.4.2",
"change-case": "^5.4.3",
"eslint": "~8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-playwright": "^0.22.1",
"eslint-plugin-playwright": "^1.1.2",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jest-preset-angular": "~14.0.0",
"jest-preset-angular": "~14.0.3",
"jsonc-eslint-parser": "^2.4.0",
"mustache": "^4.2.0",
"ng-packagr": "~17.1.2",
"ng-packagr": "~17.2.0",
"nx": "17.3.1",
"postcss": "^8.4.33",
"postcss": "^8.4.35",
"postcss-url": "~10.1.3",
"prettier": "^3.2.4",
"prettier": "^3.2.5",
"ts-jest": "^29.1.2",
"ts-node": "10.9.2",
"typescript": "~5.3.3"
Expand Down
17 changes: 3 additions & 14 deletions packages/gridjs-angular/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,16 @@ npm install gridjs gridjs-angular

## Usage

In your module

```ts
import { GridjsAngularModule } from 'gridjs-angular';

@NgModule({
imports: [CommonModule,GridjsAngularModule],
declarations: [...],
exports: [...],
})
export class AppModule {}
```

In your component template

```ts
import { Component } from '@angular/core';
import { GridjsAngularModule } from 'gridjs-angular';
import { Config } from 'gridjs';

@Component({
standalone: true,
imports: [GridJsAngularComponent],
template: `
<gridjs-angular
[gridConfig]="gridConfig"
Expand Down Expand Up @@ -129,4 +119,3 @@ The `gridjs-angular` repository is a monorepo that uses [Nx](https://nx.dev) and
- `pnpm install` - Install all dependencies
- `nx serve demo` - Run demo app
- `nx migrate latest` - Update Nx to the latest version, and upgrade all packages from package.json to their latest version
- `nx update-bindings gridjs-angular` - Update the input and output bindings from GridJS to the Angular component. This command should be run after updating the GridJS version.
4 changes: 3 additions & 1 deletion packages/gridjs-angular/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
},
"update-bindings": {
"executor": "nx:run-commands",
"outputs": ["{workspaceRoot}/packages/gridjs-angular/src/lib/gridjs-binding-base.ts"],
"outputs": [
"{workspaceRoot}/packages/gridjs-angular/src/lib/gridjs-binding-base.ts"
],
"options": {
"command": "node scripts/update-bindings.mjs"
}
Expand Down
2 changes: 1 addition & 1 deletion packages/gridjs-angular/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export * from './lib/gridjs-angular.component';
export { GRID_EVENTS as GRID_JS_EVENTS } from './lib/gridjs-binding-base';
export * from './lib/constants';
35 changes: 35 additions & 0 deletions packages/gridjs-angular/src/lib/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { Config } from 'gridjs';
import { GridEvents } from 'gridjs/dist/src/events';

export const GRID_JS_EVENTS: (keyof GridEvents)[] = [
'beforeLoad',
'cellClick',
'load',
'rowClick',
'ready',
];

export const GRID_JS_PROPS: (keyof Config)[] = [
'eventEmitter',
'plugin',
'data',
'server',
'header',
'from',
'storage',
'pipeline',
'autoWidth',
'width',
'height',
'translator',
'style',
'className',
'fixedHeader',
'columns',
'search',
'pagination',
'sort',
'language',
'plugins',
'processingThrottleMs',
];
126 changes: 100 additions & 26 deletions packages/gridjs-angular/src/lib/gridjs-angular.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,73 +3,147 @@ import {
Component,
ElementRef,
EventEmitter,
Input,
OnChanges,
OnDestroy,
Output,
ViewEncapsulation,
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { Config, Grid } from 'gridjs';
import { GRID_EVENTS, GridJsAngularBindingBase } from './gridjs-binding-base';
import { GRID_JS_EVENTS, GRID_JS_PROPS } from './constants';
import { GridEvents } from 'gridjs/dist/src/events';

/** only properties that exist on the Config interface (not the Config class) */
type EventName = keyof GridEvents;
type EventHandler = (...args: any[]) => void;
type GridJsAngularComponentProps = Omit<
Partial<Config>,
'instance' | 'store' | 'assign' | 'update'
>;
type GridEvent = keyof GridEvents;
type GridEventData<T extends GridEvent> = Parameters<
GridEvents[T]
>[0] extends undefined
? void
: Parameters<GridEvents[T]>[0];

type AnyFn = (...args: any[]) => any;
@Component({
selector: 'gridjs-angular',
standalone: true,
template: '',
standalone: true,
imports: [CommonModule],
encapsulation: ViewEncapsulation.None,
})
export class GridJsAngularComponent
extends GridJsAngularBindingBase
implements AfterViewInit, OnDestroy
implements AfterViewInit, OnChanges, OnDestroy, GridJsAngularComponentProps
{
private readonly listeners = new Map<EventName, EventHandler>();
private nativeElement: HTMLElement;
private instance?: Grid;
private initialized = false;
private listeners: Map<GridEvent, AnyFn> = new Map();
@Input() config?: Partial<Config>;

/** alias of `load` event due to possible conflict with native load event */
@Output() readonly gridLoad = this.load;
// props
@Input() plugins: Config['plugins'] = [];
@Input() eventEmitter?: Config['eventEmitter'];
@Input() plugin?: Config['plugin'];
@Input() data: Config['data'];
@Input() server: Config['server'];
@Input() header: Config['header'];
@Input() from?: Config['from'];
@Input() storage?: Config['storage'];
@Input() pipeline?: Config['pipeline'];
@Input() autoWidth?: Config['autoWidth'];
@Input() width?: Config['width'];
@Input() height?: Config['height'];
@Input() translator?: Config['translator'];
@Input() style: Config['style'];
@Input() className: Config['className'];
@Input() fixedHeader?: Config['fixedHeader'];
@Input() columns?: Config['columns'];
@Input() search?: Config['search'];
@Input() pagination?: Config['pagination'];
@Input() sort?: Config['sort'];
@Input() language?: Config['language'];
@Input() resizable?: Config['resizable'];
@Input() processingThrottleMs?: Config['processingThrottleMs'];

constructor(private readonly host: ElementRef) {
super();
// events
@Output() beforeLoad: EventEmitter<GridEventData<'beforeLoad'>> =
new EventEmitter(true);
// renamed load event to avoid conflict with native load event
@Output() gridLoad: EventEmitter<GridEventData<'load'>> = new EventEmitter(
true,
);
@Output() cellClick: EventEmitter<GridEventData<'cellClick'>> =
new EventEmitter(true);
@Output() rowClick: EventEmitter<GridEventData<'rowClick'>> =
new EventEmitter(true);
@Output() ready: EventEmitter<GridEventData<'ready'>> = new EventEmitter(
true,
);

constructor(private elementDef: ElementRef) {
this.nativeElement = this.elementDef.nativeElement;
}

ngAfterViewInit(): void {
const instance = new Grid(this.config());
this.instance.set(instance);
this.instance = new Grid(this.getConfig(this.config ?? {}));
this.registerEvents();
instance.render(this.host.nativeElement);
this.instance.render(this.nativeElement);
this.initialized = true;
}

ngOnDestroy(): void {
if (this.instance()) {
this.unregisterEvents();
this.instance.set(undefined);
ngOnChanges(): void {
if (this.initialized) {
this.updateConfig(this.config);
}
}

ngOnDestroy(): void {
if (this.initialized) {
if (this.instance) {
this.unregisterEvents();
this.instance = undefined;
}
}
}
// public api to interact with grid instance
getGridInstance() {
return this.instance();
return this.instance;
}

updateConfig(config: Partial<Config> = {}) {
this.gridConfig.set(config);
this.instance?.updateConfig(this.getConfig(config)).forceRender();
}

private registerEvents() {
for (const event of GRID_EVENTS) {
const emitter = (<any>this)[event] as EventEmitter<any>;
for (const event of GRID_JS_EVENTS) {
const emitter = event === 'load' ? this.gridLoad : this[event];
if (!emitter) {
continue;
}
const listener = (...args: any[]) => emitter.emit(args);
const listener: AnyFn = (args) => emitter.emit(args);
this.listeners.set(event, listener);
this.instance()?.on(event, listener);
if (emitter) {
this.instance?.on(event, listener);
}
}
}

private unregisterEvents() {
for (const [event, listener] of this.listeners.entries()) {
this.instance()?.off(event, listener);
this.instance?.off(event, listener);
}
}

private getConfig(config: Partial<Config> = {}) {
const newConfig: Record<string, unknown> = structuredClone(config);
for (const [key, value] of Object.entries(this)) {
if (GRID_JS_PROPS.includes(key as keyof Config)) {
newConfig[key] = value;
}
}
this.config = newConfig;
return newConfig;
}
}
Loading

0 comments on commit 105226f

Please sign in to comment.