@sneat/datagrid 0.1.3 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,70 @@
1
+ import * as i0 from '@angular/core';
2
+ import { AfterViewInit, OnChanges, ElementRef, EventEmitter, SimpleChanges } from '@angular/core';
3
+ import { RowContextMenuSignature, ColumnDefinition, Options } from 'tabulator-tables';
4
+ import { IGridColumn } from '@sneat/grid';
5
+
6
+ interface IRecordsetColumn {
7
+ name: string;
8
+ title?: string;
9
+ dbType: string;
10
+ }
11
+ interface ITableRef {
12
+ name: string;
13
+ schema: string;
14
+ catalog?: string;
15
+ }
16
+ interface IForeignKey {
17
+ name: string;
18
+ columns: string[];
19
+ refTable: ITableRef;
20
+ }
21
+ declare class CellPopoverComponent {
22
+ column?: IRecordsetColumn;
23
+ value: unknown;
24
+ fk?: IForeignKey;
25
+ tab: 'rec' | 'cols' | 'refs';
26
+ static ɵfac: i0.ɵɵFactoryDeclaration<CellPopoverComponent, never>;
27
+ static ɵcmp: i0.ɵɵComponentDeclaration<CellPopoverComponent, "sneat-datatug-cell-popover", never, { "column": { "alias": "column"; "required": false; }; "value": { "alias": "value"; "required": false; }; "fk": { "alias": "fk"; "required": false; }; }, {}, never, never, true, never>;
28
+ }
29
+
30
+ /**
31
+ * This is a wrapper class for the tabulator JS library.
32
+ * For more info see http://tabulator.info
33
+ */
34
+ declare class DataGridComponent implements AfterViewInit, OnChanges {
35
+ private readonly errorLogger;
36
+ layout?: 'fitData' | 'fitColumns';
37
+ data?: unknown[];
38
+ columns?: IGridColumn[];
39
+ groupBy?: string;
40
+ height?: string;
41
+ maxHeight?: string | number;
42
+ rowContextMenu?: RowContextMenuSignature;
43
+ tabulatorDiv?: ElementRef;
44
+ rowClick?: (event: Event, row: unknown) => void;
45
+ readonly rowSelected: EventEmitter<{
46
+ row: unknown;
47
+ event?: Event;
48
+ }>;
49
+ readonly rowDeselected: EventEmitter<{
50
+ row: unknown;
51
+ event?: Event;
52
+ }>;
53
+ private tabulator?;
54
+ selectable?: boolean | number | 'highlight';
55
+ private tabulatorOptions?;
56
+ private clickEvent?;
57
+ ngOnChanges(changes: SimpleChanges): void;
58
+ ngAfterViewInit(): void;
59
+ private drawTable;
60
+ private createTabulatorGrid;
61
+ private setTabulatorOptions;
62
+ static ɵfac: i0.ɵɵFactoryDeclaration<DataGridComponent, never>;
63
+ static ɵcmp: i0.ɵɵComponentDeclaration<DataGridComponent, "sneat-datagrid", never, { "layout": { "alias": "layout"; "required": false; }; "data": { "alias": "data"; "required": false; }; "columns": { "alias": "columns"; "required": false; }; "groupBy": { "alias": "groupBy"; "required": false; }; "height": { "alias": "height"; "required": false; }; "maxHeight": { "alias": "maxHeight"; "required": false; }; "rowContextMenu": { "alias": "rowContextMenu"; "required": false; }; "rowClick": { "alias": "rowClick"; "required": false; }; "selectable": { "alias": "selectable"; "required": false; }; }, { "rowSelected": "rowSelected"; "rowDeselected": "rowDeselected"; }, never, never, true, never>;
64
+ }
65
+
66
+ type TabulatorColumn = ColumnDefinition;
67
+ type TabulatorOptions = Options;
68
+
69
+ export { CellPopoverComponent, DataGridComponent };
70
+ export type { TabulatorColumn, TabulatorOptions };
package/eslint.config.js DELETED
@@ -1,7 +0,0 @@
1
- const baseConfig = require('../../eslint.config.js');
2
- const { sneatLibConfig } = require('../../eslint.lib.config.js');
3
-
4
- module.exports = [
5
- ...baseConfig,
6
- ...sneatLibConfig(__dirname),
7
- ];
package/ng-package.json DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3
- "dest": "../../dist/libs/datagrid",
4
- "lib": {
5
- "entryFile": "src/index.ts"
6
- }
7
- }
package/project.json DELETED
@@ -1,38 +0,0 @@
1
- {
2
- "name": "datagrid",
3
- "$schema": "../../node_modules/nx/schemas/project-schema.json",
4
- "projectType": "library",
5
- "sourceRoot": "libs/datagrid/src",
6
- "prefix": "sneat",
7
- "targets": {
8
- "build": {
9
- "executor": "@nx/angular:package",
10
- "outputs": [
11
- "{workspaceRoot}/dist/libs/datagrid"
12
- ],
13
- "options": {
14
- "project": "libs/datagrid/ng-package.json",
15
- "tsConfig": "libs/datagrid/tsconfig.lib.json"
16
- },
17
- "configurations": {
18
- "production": {
19
- "tsConfig": "libs/datagrid/tsconfig.lib.prod.json"
20
- },
21
- "development": {}
22
- },
23
- "defaultConfiguration": "production"
24
- },
25
- "test": {
26
- "executor": "@nx/vitest:test",
27
- "outputs": [
28
- "{workspaceRoot}/coverage/libs/datagrid"
29
- ],
30
- "options": {
31
- "tsConfig": "libs/datagrid/tsconfig.spec.json"
32
- }
33
- },
34
- "lint": {
35
- "executor": "@nx/eslint:lint"
36
- }
37
- }
38
- }
package/src/index.ts DELETED
@@ -1,2 +0,0 @@
1
- export * from './lib/components';
2
- export * from './lib/tabulator';
@@ -1,64 +0,0 @@
1
- <ion-card-header>
2
- <ion-card-title>Field: {{ column?.name }}</ion-card-title>
3
- <ion-card-subtitle>Value: {{ value }}</ion-card-subtitle>
4
- </ion-card-header>
5
- <h3 class="ion-margin">
6
- References:
7
- @if (fk?.refTable) {
8
- <a routerLink="{{ fk?.refTable?.schema }}.{{ fk?.refTable?.name }}">
9
- {{ fk?.refTable?.schema }}.{{ fk?.refTable?.name }}
10
- </a>
11
- }
12
- </h3>
13
- <ion-segment [(ngModel)]="tab">
14
- <ion-segment-button value="rec">
15
- <ion-label>Record</ion-label>
16
- </ion-segment-button>
17
- <ion-segment-button value="cols">
18
- <ion-label>Columns</ion-label>
19
- </ion-segment-button>
20
- <ion-segment-button value="refs">
21
- <ion-label>References</ion-label>
22
- </ion-segment-button>
23
- </ion-segment>
24
-
25
- @switch (tab) {
26
- @case ("rec") {
27
- <ion-list>
28
- <ion-item>
29
- <ion-label>Id</ion-label>
30
- <ion-input
31
- type="number"
32
- style="text-align: right"
33
- value="1"
34
- readonly="true"
35
- />
36
- </ion-item>
37
- <ion-item>
38
- <ion-label>Code</ion-label>
39
- <ion-input
40
- type="text"
41
- style="text-align: right"
42
- value="Something"
43
- readonly="true"
44
- />
45
- </ion-item>
46
- </ion-list>
47
- }
48
- @case ("cols") {
49
- <ion-list>
50
- <ion-item>
51
- <ion-label>Id</ion-label>
52
- <ion-badge slot="end" color="light">
53
- <ion-text color="medium">INT</ion-text>
54
- </ion-badge>
55
- </ion-item>
56
- <ion-item>
57
- <ion-label>Code</ion-label>
58
- <ion-badge slot="end" color="light">
59
- <ion-text color="medium">NVARCHAR</ion-text>
60
- </ion-badge>
61
- </ion-item>
62
- </ion-list>
63
- }
64
- }
@@ -1,168 +0,0 @@
1
- import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
2
- import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
3
-
4
- import { CellPopoverComponent } from './cell-popover.component';
5
-
6
- describe('CellPopoverComponent', () => {
7
- let component: CellPopoverComponent;
8
- let fixture: ComponentFixture<CellPopoverComponent>;
9
-
10
- beforeEach(waitForAsync(async () => {
11
- await TestBed.configureTestingModule({
12
- imports: [CellPopoverComponent],
13
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
14
- }).compileComponents();
15
-
16
- fixture = TestBed.createComponent(CellPopoverComponent);
17
- component = fixture.componentInstance;
18
- // Don't call detectChanges here - let individual tests control when it's called
19
- }));
20
-
21
- it('should create', () => {
22
- fixture.detectChanges();
23
- expect(component).toBeTruthy();
24
- });
25
-
26
- describe('Input Properties', () => {
27
- it('should accept column input', () => {
28
- const mockColumn = {
29
- name: 'testColumn',
30
- title: 'Test Column',
31
- dbType: 'varchar',
32
- };
33
-
34
- component.column = mockColumn;
35
- expect(component.column).toEqual(mockColumn);
36
- });
37
-
38
- it('should accept value input', () => {
39
- const testValue = 'Test Value';
40
- component.value = testValue;
41
- expect(component.value).toBe(testValue);
42
- });
43
-
44
- it('should accept numeric value', () => {
45
- const testValue = 42;
46
- component.value = testValue;
47
- expect(component.value).toBe(testValue);
48
- });
49
-
50
- it('should accept null value', () => {
51
- component.value = null;
52
- expect(component.value).toBeNull();
53
- });
54
-
55
- it('should accept undefined value', () => {
56
- component.value = undefined;
57
- expect(component.value).toBeUndefined();
58
- });
59
-
60
- it('should accept foreign key input', () => {
61
- const mockFk = {
62
- name: 'fk_user_id',
63
- columns: ['user_id'],
64
- refTable: {
65
- name: 'users',
66
- schema: 'public',
67
- catalog: 'main',
68
- },
69
- };
70
-
71
- component.fk = mockFk;
72
- expect(component.fk).toEqual(mockFk);
73
- });
74
-
75
- it('should accept foreign key without catalog', () => {
76
- const mockFk = {
77
- name: 'fk_order_id',
78
- columns: ['order_id'],
79
- refTable: {
80
- name: 'orders',
81
- schema: 'public',
82
- },
83
- };
84
-
85
- component.fk = mockFk;
86
- expect(component.fk).toEqual(mockFk);
87
- });
88
- });
89
-
90
- describe('Tab Property', () => {
91
- it('should default tab to "rec"', () => {
92
- expect(component.tab).toBe('rec');
93
- });
94
-
95
- it('should allow changing tab to "cols"', () => {
96
- component.tab = 'cols';
97
- expect(component.tab).toBe('cols');
98
- });
99
-
100
- it('should allow changing tab to "refs"', () => {
101
- component.tab = 'refs';
102
- expect(component.tab).toBe('refs');
103
- });
104
-
105
- it('should allow switching between tabs', () => {
106
- expect(component.tab).toBe('rec');
107
-
108
- component.tab = 'cols';
109
- expect(component.tab).toBe('cols');
110
-
111
- component.tab = 'refs';
112
- expect(component.tab).toBe('refs');
113
-
114
- component.tab = 'rec';
115
- expect(component.tab).toBe('rec');
116
- });
117
- });
118
-
119
- describe('Complex Scenarios', () => {
120
- it('should handle column with all properties', () => {
121
- const fullColumn = {
122
- name: 'user_email',
123
- title: 'User Email Address',
124
- dbType: 'varchar(255)',
125
- };
126
-
127
- component.column = fullColumn;
128
- component.value = 'user@example.com';
129
-
130
- expect(component.column.name).toBe('user_email');
131
- expect(component.column.title).toBe('User Email Address');
132
- expect(component.column.dbType).toBe('varchar(255)');
133
- expect(component.value).toBe('user@example.com');
134
- });
135
-
136
- it('should handle column without title', () => {
137
- const columnWithoutTitle = {
138
- name: 'status',
139
- dbType: 'int',
140
- };
141
-
142
- component.column = columnWithoutTitle;
143
- component.value = 1;
144
-
145
- expect(component.column.title).toBeUndefined();
146
- expect(component.column.name).toBe('status');
147
- });
148
-
149
- it('should handle multiple foreign key columns', () => {
150
- const multiFk = {
151
- name: 'fk_composite',
152
- columns: ['user_id', 'account_id', 'tenant_id'],
153
- refTable: {
154
- name: 'user_accounts',
155
- schema: 'auth',
156
- catalog: 'main',
157
- },
158
- };
159
-
160
- component.fk = multiFk;
161
-
162
- expect(component.fk.columns.length).toBe(3);
163
- expect(component.fk.columns).toContain('user_id');
164
- expect(component.fk.columns).toContain('account_id');
165
- expect(component.fk.columns).toContain('tenant_id');
166
- });
167
- });
168
- });
@@ -1,62 +0,0 @@
1
- import { Component, Input } from '@angular/core';
2
- import { FormsModule } from '@angular/forms';
3
- import { RouterModule } from '@angular/router';
4
- import {
5
- IonBadge,
6
- IonCardHeader,
7
- IonCardSubtitle,
8
- IonCardTitle,
9
- IonInput,
10
- IonItem,
11
- IonLabel,
12
- IonList,
13
- IonSegment,
14
- IonSegmentButton,
15
- IonText,
16
- } from '@ionic/angular/standalone';
17
-
18
- // TODO: Local minimal copies to avoid dependency on @sneat/datatug-main and break circular build deps
19
- interface IRecordsetColumn {
20
- name: string;
21
- title?: string;
22
- dbType: string; // Using string here to avoid coupling to DbType type from datatug-main
23
- }
24
-
25
- interface ITableRef {
26
- name: string;
27
- schema: string;
28
- catalog?: string;
29
- }
30
-
31
- interface IForeignKey {
32
- name: string;
33
- columns: string[];
34
- refTable: ITableRef;
35
- }
36
-
37
- @Component({
38
- selector: 'sneat-datatug-cell-popover',
39
- templateUrl: './cell-popover.component.html',
40
- imports: [
41
- RouterModule,
42
- FormsModule,
43
- IonCardHeader,
44
- IonCardTitle,
45
- IonCardSubtitle,
46
- IonSegment,
47
- IonSegmentButton,
48
- IonLabel,
49
- IonList,
50
- IonItem,
51
- IonInput,
52
- IonBadge,
53
- IonText,
54
- ],
55
- })
56
- export class CellPopoverComponent {
57
- @Input() column?: IRecordsetColumn;
58
- @Input() value: unknown;
59
- @Input() fk?: IForeignKey;
60
-
61
- public tab: 'rec' | 'cols' | 'refs' = 'rec';
62
- }
@@ -1 +0,0 @@
1
- export * from './cell-popover.component';