@sneat/datagrid 0.1.3 → 0.1.4
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.
- package/fesm2022/sneat-datagrid.mjs +326 -0
- package/fesm2022/sneat-datagrid.mjs.map +1 -0
- package/package.json +14 -2
- package/types/sneat-datagrid.d.ts +70 -0
- package/eslint.config.js +0 -7
- package/ng-package.json +0 -7
- package/project.json +0 -38
- package/src/index.ts +0 -2
- package/src/lib/components/cell-popover/cell-popover.component.html +0 -64
- package/src/lib/components/cell-popover/cell-popover.component.spec.ts +0 -168
- package/src/lib/components/cell-popover/cell-popover.component.ts +0 -62
- package/src/lib/components/cell-popover/index.ts +0 -1
- package/src/lib/components/data-grid/data-grid.component.spec.ts +0 -635
- package/src/lib/components/data-grid/data-grid.component.ts +0 -297
- package/src/lib/components/data-grid/index.ts +0 -1
- package/src/lib/components/index.ts +0 -2
- package/src/lib/tabulator/index.ts +0 -1
- package/src/lib/tabulator/tabulator-options.spec.ts +0 -142
- package/src/lib/tabulator/tabulator-options.ts +0 -37
- package/src/test-setup.ts +0 -3
- package/tsconfig.json +0 -13
- package/tsconfig.lib.json +0 -19
- package/tsconfig.lib.prod.json +0 -7
- package/tsconfig.spec.json +0 -31
- package/vite.config.mts +0 -10
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { Input, Component, inject, EventEmitter, Output, ViewChild } from '@angular/core';
|
|
3
|
+
import * as i2 from '@angular/forms';
|
|
4
|
+
import { FormsModule } from '@angular/forms';
|
|
5
|
+
import * as i1 from '@angular/router';
|
|
6
|
+
import { RouterModule } from '@angular/router';
|
|
7
|
+
import { IonCardHeader, IonCardTitle, IonCardSubtitle, IonSegment, IonSegmentButton, IonLabel, IonList, IonItem, IonInput, IonBadge, IonText } from '@ionic/angular/standalone';
|
|
8
|
+
import { ErrorLogger } from '@sneat/core';
|
|
9
|
+
import { Module, Tabulator, InteractionModule, SelectRowModule, MenuModule } from 'tabulator-tables';
|
|
10
|
+
|
|
11
|
+
class CellPopoverComponent {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.tab = 'rec';
|
|
14
|
+
}
|
|
15
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: CellPopoverComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
16
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: CellPopoverComponent, isStandalone: true, selector: "sneat-datatug-cell-popover", inputs: { column: "column", value: "value", fk: "fk" }, ngImport: i0, template: "<ion-card-header>\n <ion-card-title>Field: {{ column?.name }}</ion-card-title>\n <ion-card-subtitle>Value: {{ value }}</ion-card-subtitle>\n</ion-card-header>\n<h3 class=\"ion-margin\">\n References:\n @if (fk?.refTable) {\n <a routerLink=\"{{ fk?.refTable?.schema }}.{{ fk?.refTable?.name }}\">\n {{ fk?.refTable?.schema }}.{{ fk?.refTable?.name }}\n </a>\n }\n</h3>\n<ion-segment [(ngModel)]=\"tab\">\n <ion-segment-button value=\"rec\">\n <ion-label>Record</ion-label>\n </ion-segment-button>\n <ion-segment-button value=\"cols\">\n <ion-label>Columns</ion-label>\n </ion-segment-button>\n <ion-segment-button value=\"refs\">\n <ion-label>References</ion-label>\n </ion-segment-button>\n</ion-segment>\n\n@switch (tab) {\n @case (\"rec\") {\n <ion-list>\n <ion-item>\n <ion-label>Id</ion-label>\n <ion-input\n type=\"number\"\n style=\"text-align: right\"\n value=\"1\"\n readonly=\"true\"\n />\n </ion-item>\n <ion-item>\n <ion-label>Code</ion-label>\n <ion-input\n type=\"text\"\n style=\"text-align: right\"\n value=\"Something\"\n readonly=\"true\"\n />\n </ion-item>\n </ion-list>\n }\n @case (\"cols\") {\n <ion-list>\n <ion-item>\n <ion-label>Id</ion-label>\n <ion-badge slot=\"end\" color=\"light\">\n <ion-text color=\"medium\">INT</ion-text>\n </ion-badge>\n </ion-item>\n <ion-item>\n <ion-label>Code</ion-label>\n <ion-badge slot=\"end\" color=\"light\">\n <ion-text color=\"medium\">NVARCHAR</ion-text>\n </ion-badge>\n </ion-item>\n </ion-list>\n }\n}\n", dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: IonCardHeader, selector: "ion-card-header", inputs: ["color", "mode", "translucent"] }, { kind: "component", type: IonCardTitle, selector: "ion-card-title", inputs: ["color", "mode"] }, { kind: "component", type: IonCardSubtitle, selector: "ion-card-subtitle", inputs: ["color", "mode"] }, { kind: "component", type: IonSegment, selector: "ion-segment", inputs: ["color", "disabled", "mode", "scrollable", "selectOnFocus", "swipeGesture", "value"] }, { kind: "component", type: IonSegmentButton, selector: "ion-segment-button", inputs: ["contentId", "disabled", "layout", "mode", "type", "value"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonBadge, selector: "ion-badge", inputs: ["color", "mode"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }] }); }
|
|
17
|
+
}
|
|
18
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: CellPopoverComponent, decorators: [{
|
|
19
|
+
type: Component,
|
|
20
|
+
args: [{ selector: 'sneat-datatug-cell-popover', imports: [
|
|
21
|
+
RouterModule,
|
|
22
|
+
FormsModule,
|
|
23
|
+
IonCardHeader,
|
|
24
|
+
IonCardTitle,
|
|
25
|
+
IonCardSubtitle,
|
|
26
|
+
IonSegment,
|
|
27
|
+
IonSegmentButton,
|
|
28
|
+
IonLabel,
|
|
29
|
+
IonList,
|
|
30
|
+
IonItem,
|
|
31
|
+
IonInput,
|
|
32
|
+
IonBadge,
|
|
33
|
+
IonText,
|
|
34
|
+
], template: "<ion-card-header>\n <ion-card-title>Field: {{ column?.name }}</ion-card-title>\n <ion-card-subtitle>Value: {{ value }}</ion-card-subtitle>\n</ion-card-header>\n<h3 class=\"ion-margin\">\n References:\n @if (fk?.refTable) {\n <a routerLink=\"{{ fk?.refTable?.schema }}.{{ fk?.refTable?.name }}\">\n {{ fk?.refTable?.schema }}.{{ fk?.refTable?.name }}\n </a>\n }\n</h3>\n<ion-segment [(ngModel)]=\"tab\">\n <ion-segment-button value=\"rec\">\n <ion-label>Record</ion-label>\n </ion-segment-button>\n <ion-segment-button value=\"cols\">\n <ion-label>Columns</ion-label>\n </ion-segment-button>\n <ion-segment-button value=\"refs\">\n <ion-label>References</ion-label>\n </ion-segment-button>\n</ion-segment>\n\n@switch (tab) {\n @case (\"rec\") {\n <ion-list>\n <ion-item>\n <ion-label>Id</ion-label>\n <ion-input\n type=\"number\"\n style=\"text-align: right\"\n value=\"1\"\n readonly=\"true\"\n />\n </ion-item>\n <ion-item>\n <ion-label>Code</ion-label>\n <ion-input\n type=\"text\"\n style=\"text-align: right\"\n value=\"Something\"\n readonly=\"true\"\n />\n </ion-item>\n </ion-list>\n }\n @case (\"cols\") {\n <ion-list>\n <ion-item>\n <ion-label>Id</ion-label>\n <ion-badge slot=\"end\" color=\"light\">\n <ion-text color=\"medium\">INT</ion-text>\n </ion-badge>\n </ion-item>\n <ion-item>\n <ion-label>Code</ion-label>\n <ion-badge slot=\"end\" color=\"light\">\n <ion-text color=\"medium\">NVARCHAR</ion-text>\n </ion-badge>\n </ion-item>\n </ion-list>\n }\n}\n" }]
|
|
35
|
+
}], propDecorators: { column: [{
|
|
36
|
+
type: Input
|
|
37
|
+
}], value: [{
|
|
38
|
+
type: Input
|
|
39
|
+
}], fk: [{
|
|
40
|
+
type: Input
|
|
41
|
+
}] } });
|
|
42
|
+
|
|
43
|
+
class AdvertModule extends Module {
|
|
44
|
+
static { this.moduleName = 'advert'; }
|
|
45
|
+
initialize() {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
Tabulator.registerModule([
|
|
50
|
+
InteractionModule,
|
|
51
|
+
SelectRowModule,
|
|
52
|
+
AdvertModule,
|
|
53
|
+
MenuModule,
|
|
54
|
+
]);
|
|
55
|
+
// export interface IGridDef {
|
|
56
|
+
// columns: IGridColumn[],
|
|
57
|
+
// rows?: unknown[],
|
|
58
|
+
// groupBy?: string;
|
|
59
|
+
// }
|
|
60
|
+
//
|
|
61
|
+
// export const getTabulatorCols = (cols: IGridColumn[]): any[] => cols.map(c => {
|
|
62
|
+
// const v = {...c};
|
|
63
|
+
// delete v.dbType;
|
|
64
|
+
// return v;
|
|
65
|
+
// });
|
|
66
|
+
//
|
|
67
|
+
// export interface IGridColumn {
|
|
68
|
+
// field: string;
|
|
69
|
+
// colName?: string;
|
|
70
|
+
// dbType: string;
|
|
71
|
+
// title: string;
|
|
72
|
+
// tooltip?: (cell: any) => string;
|
|
73
|
+
// formatter?: any;
|
|
74
|
+
// hozAlign?: 'left' | 'right';
|
|
75
|
+
// widthShrink?: number;
|
|
76
|
+
// widthGrow?: number;
|
|
77
|
+
// width?: number | string;
|
|
78
|
+
// }
|
|
79
|
+
/**
|
|
80
|
+
* This is a wrapper class for the tabulator JS library.
|
|
81
|
+
* For more info see http://tabulator.info
|
|
82
|
+
*/
|
|
83
|
+
class DataGridComponent {
|
|
84
|
+
constructor() {
|
|
85
|
+
this.errorLogger = inject(ErrorLogger);
|
|
86
|
+
this.layout = 'fitColumns';
|
|
87
|
+
this.data = [];
|
|
88
|
+
this.columns = [];
|
|
89
|
+
this.rowSelected = new EventEmitter();
|
|
90
|
+
this.rowDeselected = new EventEmitter();
|
|
91
|
+
}
|
|
92
|
+
ngOnChanges(changes) {
|
|
93
|
+
try {
|
|
94
|
+
if ((changes['data'] && this.data && this.columns) ||
|
|
95
|
+
(changes['columns'] && this.columns) ||
|
|
96
|
+
(changes['rowClick'] && this.rowClick)) {
|
|
97
|
+
this.drawTable();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch (ex) {
|
|
101
|
+
this.errorLogger.logError(ex, 'Failed to process ngOnChanges in DataGridComponent');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// ngOnDestroy(): void {
|
|
105
|
+
// console.log('DataGridComponent.ngOnDestroy()', this.tabulator);
|
|
106
|
+
// try { // TODO: destroy Tabulator
|
|
107
|
+
// if (this.tabulator?.element) {
|
|
108
|
+
// // noinspection TypeScriptValidateJSTypes
|
|
109
|
+
// this.tabulator.element.tabulator('destroy');
|
|
110
|
+
// }
|
|
111
|
+
// } catch (ex) {
|
|
112
|
+
// this.errorLogger.logError(ex, 'Failed to destroy tabulator');
|
|
113
|
+
// }
|
|
114
|
+
// }
|
|
115
|
+
ngAfterViewInit() {
|
|
116
|
+
if (this.tabulator) {
|
|
117
|
+
try {
|
|
118
|
+
this.tabulator.redraw();
|
|
119
|
+
}
|
|
120
|
+
catch (e) {
|
|
121
|
+
this.errorLogger.logError(e, 'Failed to redraw tabulator', {
|
|
122
|
+
show: false,
|
|
123
|
+
report: false,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
drawTable() {
|
|
129
|
+
if (!this.data || !this.columns) {
|
|
130
|
+
console.warn('drawTable()', 'columns:', this.columns, 'data:', this.data);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
try {
|
|
134
|
+
if (!this.tabulatorDiv) {
|
|
135
|
+
this.errorLogger.logError(new Error('!this.tabulatorDiv'));
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
if (this.tabulatorOptions) {
|
|
139
|
+
this.tabulatorOptions = { ...this.tabulatorOptions, data: this.data };
|
|
140
|
+
this.tabulator
|
|
141
|
+
?.setData(this.data)
|
|
142
|
+
.catch(this.errorLogger.logErrorHandler('Failed to set data'));
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
this.createTabulatorGrid();
|
|
146
|
+
}
|
|
147
|
+
// this.tabulatorDiv.nativeElement.appendChild(this.tab);
|
|
148
|
+
// tabulator.redraw();
|
|
149
|
+
}
|
|
150
|
+
catch (e) {
|
|
151
|
+
this.errorLogger.logError(e, 'Failed to drawTable');
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
createTabulatorGrid() {
|
|
155
|
+
this.setTabulatorOptions();
|
|
156
|
+
if (!this.tabulator) {
|
|
157
|
+
this.tabulatorOptions = {
|
|
158
|
+
...this.tabulatorOptions,
|
|
159
|
+
// rowClick: function (e, row) {
|
|
160
|
+
// console.log('rowClick1', row);
|
|
161
|
+
// },
|
|
162
|
+
// rowSelect: function (row) {
|
|
163
|
+
// console.log('rowSelect', row);
|
|
164
|
+
// },
|
|
165
|
+
// rowDeselect: function (row) {
|
|
166
|
+
// console.log('rowDeselect', row);
|
|
167
|
+
// }
|
|
168
|
+
};
|
|
169
|
+
this.tabulator = new Tabulator(this.tabulatorDiv?.nativeElement, this.tabulatorOptions);
|
|
170
|
+
this.tabulator.on('rowClick', (event, row) => {
|
|
171
|
+
this.clickEvent = event;
|
|
172
|
+
if (this.rowClick) {
|
|
173
|
+
this.rowClick(event, row);
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
this.tabulator.on('rowSelected', (row) => this.rowSelected.emit({ row, event: this.clickEvent }));
|
|
177
|
+
this.tabulator.on('rowDeselected', (row) => this.rowDeselected.emit({ row, event: this.clickEvent }));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
setTabulatorOptions() {
|
|
181
|
+
this.tabulatorOptions = {
|
|
182
|
+
// tooltipsHeader: true, // enable header tooltips
|
|
183
|
+
// tooltipGenerationMode: 'hover',
|
|
184
|
+
rowContextMenu: this.rowContextMenu,
|
|
185
|
+
selectableRows: this.selectable,
|
|
186
|
+
data: this.data,
|
|
187
|
+
// reactiveData: true, // enable data reactivity
|
|
188
|
+
columns: this.columns?.map((c) => {
|
|
189
|
+
const col = {
|
|
190
|
+
// TODO(help-wanted): Use strongly typed Tabulator col def
|
|
191
|
+
field: c.field,
|
|
192
|
+
title: c.title || c.field || c.title,
|
|
193
|
+
// headerTooltip: () =>
|
|
194
|
+
// `${c.colName || c.title || c.field}: ${c.dbType}`,
|
|
195
|
+
};
|
|
196
|
+
if (c.colName !== 'Id' && c.colName?.endsWith('Id')) {
|
|
197
|
+
col.formatter = 'link';
|
|
198
|
+
col.formatterParams = {
|
|
199
|
+
url: 'test-url',
|
|
200
|
+
};
|
|
201
|
+
col.cellClick = (e, cell) => {
|
|
202
|
+
void cell;
|
|
203
|
+
e.preventDefault();
|
|
204
|
+
e.stopPropagation();
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
if (c.tooltip) {
|
|
208
|
+
col.tooltip = c.tooltip;
|
|
209
|
+
}
|
|
210
|
+
if (c.formatter) {
|
|
211
|
+
col.formatter = c.formatter;
|
|
212
|
+
}
|
|
213
|
+
if (c.hozAlign) {
|
|
214
|
+
col.hozAlign = c.hozAlign;
|
|
215
|
+
}
|
|
216
|
+
if (c.headerHozAlign) {
|
|
217
|
+
col.headerHozAlign = c.headerHozAlign;
|
|
218
|
+
}
|
|
219
|
+
if (c.widthGrow) {
|
|
220
|
+
col.widthGrow = c.widthGrow;
|
|
221
|
+
}
|
|
222
|
+
if (c.widthShrink) {
|
|
223
|
+
col.widthShrink = c.widthShrink;
|
|
224
|
+
}
|
|
225
|
+
if (c.width !== undefined) {
|
|
226
|
+
col.width = c.width;
|
|
227
|
+
}
|
|
228
|
+
// console.log('col:', col);
|
|
229
|
+
return col;
|
|
230
|
+
}),
|
|
231
|
+
layout: this.layout || 'fitColumns',
|
|
232
|
+
};
|
|
233
|
+
if (this.height) {
|
|
234
|
+
this.tabulatorOptions = {
|
|
235
|
+
...this.tabulatorOptions,
|
|
236
|
+
height: this.height,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
if (this.maxHeight) {
|
|
240
|
+
this.tabulatorOptions = {
|
|
241
|
+
...this.tabulatorOptions,
|
|
242
|
+
maxHeight: this.maxHeight,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
if (this.groupBy) {
|
|
246
|
+
this.tabulatorOptions = {
|
|
247
|
+
...this.tabulatorOptions,
|
|
248
|
+
groupBy: this.groupBy,
|
|
249
|
+
groupHeader: (value, count) => {
|
|
250
|
+
// value - the value all members of this group share
|
|
251
|
+
// count - the number of rows in this group
|
|
252
|
+
// data - an array of all the row data objects in this group
|
|
253
|
+
// group - the group component for the group
|
|
254
|
+
// console.log('groupHeader', value);
|
|
255
|
+
return `${this.groupBy}: ${value} <span class="ion-margin-start">(${count} ${count === 1 ? 'record' : 'records'})</span>`;
|
|
256
|
+
},
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DataGridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
261
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.0", type: DataGridComponent, isStandalone: true, selector: "sneat-datagrid", inputs: { layout: "layout", data: "data", columns: "columns", groupBy: "groupBy", height: "height", maxHeight: "maxHeight", rowContextMenu: "rowContextMenu", rowClick: "rowClick", selectable: "selectable" }, outputs: { rowSelected: "rowSelected", rowDeselected: "rowDeselected" }, viewQueries: [{ propertyName: "tabulatorDiv", first: true, predicate: ["tabulatorDiv"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
262
|
+
<div id="tabulator" #tabulatorDiv></div>
|
|
263
|
+
<p class="ion-margin-start">Rows: {{ data?.length }}</p>
|
|
264
|
+
`, isInline: true }); }
|
|
265
|
+
}
|
|
266
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DataGridComponent, decorators: [{
|
|
267
|
+
type: Component,
|
|
268
|
+
args: [{
|
|
269
|
+
selector: 'sneat-datagrid',
|
|
270
|
+
template: `
|
|
271
|
+
<div id="tabulator" #tabulatorDiv></div>
|
|
272
|
+
<p class="ion-margin-start">Rows: {{ data?.length }}</p>
|
|
273
|
+
`,
|
|
274
|
+
imports: [],
|
|
275
|
+
}]
|
|
276
|
+
}], propDecorators: { layout: [{
|
|
277
|
+
type: Input
|
|
278
|
+
}], data: [{
|
|
279
|
+
type: Input
|
|
280
|
+
}], columns: [{
|
|
281
|
+
type: Input
|
|
282
|
+
}], groupBy: [{
|
|
283
|
+
type: Input
|
|
284
|
+
}], height: [{
|
|
285
|
+
type: Input
|
|
286
|
+
}], maxHeight: [{
|
|
287
|
+
type: Input
|
|
288
|
+
}], rowContextMenu: [{
|
|
289
|
+
type: Input
|
|
290
|
+
}], tabulatorDiv: [{
|
|
291
|
+
type: ViewChild,
|
|
292
|
+
args: ['tabulatorDiv', { static: true }]
|
|
293
|
+
}], rowClick: [{
|
|
294
|
+
type: Input
|
|
295
|
+
}], rowSelected: [{
|
|
296
|
+
type: Output
|
|
297
|
+
}], rowDeselected: [{
|
|
298
|
+
type: Output
|
|
299
|
+
}], selectable: [{
|
|
300
|
+
type: Input
|
|
301
|
+
}] } });
|
|
302
|
+
|
|
303
|
+
// export interface TabulatorOptions {
|
|
304
|
+
// readonly tooltipsHeader?: boolean;
|
|
305
|
+
// readonly tooltipGenerationMode?: 'hover' | 'mouseover';
|
|
306
|
+
// readonly reactiveData?: boolean;
|
|
307
|
+
// readonly selectable?: boolean | number | 'highlight';
|
|
308
|
+
// readonly data?: unknown[];
|
|
309
|
+
// readonly layout?: 'fitData' | 'fitColumns';
|
|
310
|
+
// readonly columns?: TabulatorColumn[];
|
|
311
|
+
// readonly height?: string | number;
|
|
312
|
+
// readonly maxHeight?: string | number;
|
|
313
|
+
// readonly groupBy?: string;
|
|
314
|
+
// readonly groupHeader?: (value: unknown, count: number) => string;
|
|
315
|
+
// readonly rowClick?: (event: Event, row: unknown) => void;
|
|
316
|
+
// readonly rowSelect?: (row: unknown) => void;
|
|
317
|
+
// readonly rowDeselect?: (row: unknown) => void;
|
|
318
|
+
// readonly rowContextMenu?: IRowMenu[];
|
|
319
|
+
// }
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Generated bundle index. Do not edit.
|
|
323
|
+
*/
|
|
324
|
+
|
|
325
|
+
export { CellPopoverComponent, DataGridComponent };
|
|
326
|
+
//# sourceMappingURL=sneat-datagrid.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sneat-datagrid.mjs","sources":["../../../../libs/datagrid/src/lib/components/cell-popover/cell-popover.component.ts","../../../../libs/datagrid/src/lib/components/cell-popover/cell-popover.component.html","../../../../libs/datagrid/src/lib/components/data-grid/data-grid.component.ts","../../../../libs/datagrid/src/lib/tabulator/tabulator-options.ts","../../../../libs/datagrid/src/sneat-datagrid.ts"],"sourcesContent":["import { Component, Input } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { RouterModule } from '@angular/router';\nimport {\n IonBadge,\n IonCardHeader,\n IonCardSubtitle,\n IonCardTitle,\n IonInput,\n IonItem,\n IonLabel,\n IonList,\n IonSegment,\n IonSegmentButton,\n IonText,\n} from '@ionic/angular/standalone';\n\n// TODO: Local minimal copies to avoid dependency on @sneat/datatug-main and break circular build deps\ninterface IRecordsetColumn {\n name: string;\n title?: string;\n dbType: string; // Using string here to avoid coupling to DbType type from datatug-main\n}\n\ninterface ITableRef {\n name: string;\n schema: string;\n catalog?: string;\n}\n\ninterface IForeignKey {\n name: string;\n columns: string[];\n refTable: ITableRef;\n}\n\n@Component({\n selector: 'sneat-datatug-cell-popover',\n templateUrl: './cell-popover.component.html',\n imports: [\n RouterModule,\n FormsModule,\n IonCardHeader,\n IonCardTitle,\n IonCardSubtitle,\n IonSegment,\n IonSegmentButton,\n IonLabel,\n IonList,\n IonItem,\n IonInput,\n IonBadge,\n IonText,\n ],\n})\nexport class CellPopoverComponent {\n @Input() column?: IRecordsetColumn;\n @Input() value: unknown;\n @Input() fk?: IForeignKey;\n\n public tab: 'rec' | 'cols' | 'refs' = 'rec';\n}\n","<ion-card-header>\n <ion-card-title>Field: {{ column?.name }}</ion-card-title>\n <ion-card-subtitle>Value: {{ value }}</ion-card-subtitle>\n</ion-card-header>\n<h3 class=\"ion-margin\">\n References:\n @if (fk?.refTable) {\n <a routerLink=\"{{ fk?.refTable?.schema }}.{{ fk?.refTable?.name }}\">\n {{ fk?.refTable?.schema }}.{{ fk?.refTable?.name }}\n </a>\n }\n</h3>\n<ion-segment [(ngModel)]=\"tab\">\n <ion-segment-button value=\"rec\">\n <ion-label>Record</ion-label>\n </ion-segment-button>\n <ion-segment-button value=\"cols\">\n <ion-label>Columns</ion-label>\n </ion-segment-button>\n <ion-segment-button value=\"refs\">\n <ion-label>References</ion-label>\n </ion-segment-button>\n</ion-segment>\n\n@switch (tab) {\n @case (\"rec\") {\n <ion-list>\n <ion-item>\n <ion-label>Id</ion-label>\n <ion-input\n type=\"number\"\n style=\"text-align: right\"\n value=\"1\"\n readonly=\"true\"\n />\n </ion-item>\n <ion-item>\n <ion-label>Code</ion-label>\n <ion-input\n type=\"text\"\n style=\"text-align: right\"\n value=\"Something\"\n readonly=\"true\"\n />\n </ion-item>\n </ion-list>\n }\n @case (\"cols\") {\n <ion-list>\n <ion-item>\n <ion-label>Id</ion-label>\n <ion-badge slot=\"end\" color=\"light\">\n <ion-text color=\"medium\">INT</ion-text>\n </ion-badge>\n </ion-item>\n <ion-item>\n <ion-label>Code</ion-label>\n <ion-badge slot=\"end\" color=\"light\">\n <ion-text color=\"medium\">NVARCHAR</ion-text>\n </ion-badge>\n </ion-item>\n </ion-list>\n }\n}\n","import {\n AfterViewInit,\n Component,\n ElementRef,\n EventEmitter,\n Input,\n OnChanges,\n Output,\n SimpleChanges,\n ViewChild,\n inject,\n} from '@angular/core';\nimport { ErrorLogger, IErrorLogger } from '@sneat/core';\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport {\n Tabulator,\n SelectRowModule,\n MenuModule,\n InteractionModule,\n Module,\n RowContextMenuSignature,\n} from 'tabulator-tables';\nimport { IGridColumn } from '@sneat/grid';\nimport { TabulatorColumn, TabulatorOptions } from '../../tabulator';\n\nclass AdvertModule extends Module {\n public static override moduleName = 'advert';\n\n override initialize() {\n return;\n }\n}\n\nTabulator.registerModule([\n InteractionModule,\n SelectRowModule,\n AdvertModule,\n MenuModule,\n]);\n\n\n// export interface IGridDef {\n// \tcolumns: IGridColumn[],\n// \trows?: unknown[],\n// \tgroupBy?: string;\n// }\n//\n// export const getTabulatorCols = (cols: IGridColumn[]): any[] => cols.map(c => {\n// \tconst v = {...c};\n// \tdelete v.dbType;\n// \treturn v;\n// });\n//\n// export interface IGridColumn {\n// \tfield: string;\n// \tcolName?: string;\n// \tdbType: string;\n// \ttitle: string;\n// \ttooltip?: (cell: any) => string;\n// \tformatter?: any;\n// \thozAlign?: 'left' | 'right';\n// \twidthShrink?: number;\n// \twidthGrow?: number;\n// \twidth?: number | string;\n// }\n\n/**\n * This is a wrapper class for the tabulator JS library.\n * For more info see http://tabulator.info\n */\n@Component({\n selector: 'sneat-datagrid',\n template: `\n <div id=\"tabulator\" #tabulatorDiv></div>\n <p class=\"ion-margin-start\">Rows: {{ data?.length }}</p>\n `,\n imports: [],\n})\nexport class DataGridComponent implements AfterViewInit, OnChanges {\n private readonly errorLogger = inject<IErrorLogger>(ErrorLogger);\n\n @Input() layout?: 'fitData' | 'fitColumns' = 'fitColumns';\n @Input() data?: unknown[] = [];\n @Input() columns?: IGridColumn[] = [];\n @Input() groupBy?: string;\n @Input() height?: string;\n @Input() maxHeight?: string | number;\n @Input() rowContextMenu?: RowContextMenuSignature;\n @ViewChild('tabulatorDiv', { static: true }) tabulatorDiv?: ElementRef;\n\n @Input() rowClick?: (event: Event, row: unknown) => void;\n\n @Output() readonly rowSelected = new EventEmitter<{\n row: unknown;\n event?: Event;\n }>();\n\n @Output() readonly rowDeselected = new EventEmitter<{\n row: unknown;\n event?: Event;\n }>();\n\n // private tab = document.createElement('div');\n private tabulator?: Tabulator;\n\n @Input() public selectable?: boolean | number | 'highlight';\n\n private tabulatorOptions?: TabulatorOptions;\n private clickEvent?: Event;\n\n ngOnChanges(changes: SimpleChanges): void {\n try {\n if (\n (changes['data'] && this.data && this.columns) ||\n (changes['columns'] && this.columns) ||\n (changes['rowClick'] && this.rowClick)\n ) {\n this.drawTable();\n }\n } catch (ex) {\n this.errorLogger.logError(\n ex,\n 'Failed to process ngOnChanges in DataGridComponent',\n );\n }\n }\n\n // ngOnDestroy(): void {\n // console.log('DataGridComponent.ngOnDestroy()', this.tabulator);\n // try { // TODO: destroy Tabulator\n // \tif (this.tabulator?.element) {\n // \t\t// noinspection TypeScriptValidateJSTypes\n // \t\tthis.tabulator.element.tabulator('destroy');\n // \t}\n // } catch (ex) {\n // \tthis.errorLogger.logError(ex, 'Failed to destroy tabulator');\n // }\n // }\n\n ngAfterViewInit(): void /* Intentionally not ngOnInit */ {\n if (this.tabulator) {\n try {\n this.tabulator.redraw();\n } catch (e) {\n this.errorLogger.logError(e, 'Failed to redraw tabulator', {\n show: false,\n report: false,\n });\n }\n }\n }\n\n private drawTable(): void {\n if (!this.data || !this.columns) {\n console.warn('drawTable()', 'columns:', this.columns, 'data:', this.data);\n return;\n }\n try {\n if (!this.tabulatorDiv) {\n this.errorLogger.logError(new Error('!this.tabulatorDiv'));\n return;\n }\n if (this.tabulatorOptions) {\n this.tabulatorOptions = { ...this.tabulatorOptions, data: this.data };\n this.tabulator\n ?.setData(this.data)\n .catch(this.errorLogger.logErrorHandler('Failed to set data'));\n } else {\n this.createTabulatorGrid();\n }\n // this.tabulatorDiv.nativeElement.appendChild(this.tab);\n // tabulator.redraw();\n } catch (e) {\n this.errorLogger.logError(e, 'Failed to drawTable');\n }\n }\n\n private createTabulatorGrid(): void {\n this.setTabulatorOptions();\n if (!this.tabulator) {\n this.tabulatorOptions = {\n ...this.tabulatorOptions,\n // rowClick: function (e, row) {\n // \tconsole.log('rowClick1', row);\n // },\n // rowSelect: function (row) {\n // \tconsole.log('rowSelect', row);\n // },\n // rowDeselect: function (row) {\n // \tconsole.log('rowDeselect', row);\n // }\n };\n this.tabulator = new Tabulator(\n this.tabulatorDiv?.nativeElement,\n this.tabulatorOptions,\n );\n this.tabulator.on('rowClick', (event: Event, row: unknown) => {\n this.clickEvent = event;\n if (this.rowClick) {\n this.rowClick(event, row);\n }\n });\n this.tabulator.on('rowSelected', (row: unknown) =>\n this.rowSelected.emit({ row, event: this.clickEvent }),\n );\n this.tabulator.on('rowDeselected', (row: unknown) =>\n this.rowDeselected.emit({ row, event: this.clickEvent }),\n );\n }\n }\n\n private setTabulatorOptions(): void {\n this.tabulatorOptions = {\n // tooltipsHeader: true, // enable header tooltips\n // tooltipGenerationMode: 'hover',\n rowContextMenu: this.rowContextMenu,\n selectableRows: this.selectable,\n data: this.data,\n // reactiveData: true, // enable data reactivity\n columns: this.columns?.map((c) => {\n const col: TabulatorColumn = {\n // TODO(help-wanted): Use strongly typed Tabulator col def\n field: c.field,\n title: c.title || c.field || c.title,\n // headerTooltip: () =>\n // \t`${c.colName || c.title || c.field}: ${c.dbType}`,\n };\n if (c.colName !== 'Id' && c.colName?.endsWith('Id')) {\n col.formatter = 'link';\n col.formatterParams = {\n url: 'test-url',\n };\n col.cellClick = (e: Event, cell: unknown) => {\n void cell;\n e.preventDefault();\n e.stopPropagation();\n };\n }\n if (c.tooltip) {\n col.tooltip = c.tooltip;\n }\n if (c.formatter) {\n col.formatter = c.formatter;\n }\n if (c.hozAlign) {\n col.hozAlign = c.hozAlign;\n }\n if (c.headerHozAlign) {\n col.headerHozAlign = c.headerHozAlign;\n }\n if (c.widthGrow) {\n col.widthGrow = c.widthGrow;\n }\n if (c.widthShrink) {\n col.widthShrink = c.widthShrink;\n }\n if (c.width !== undefined) {\n col.width = c.width;\n }\n // console.log('col:', col);\n return col;\n }),\n layout: this.layout || 'fitColumns',\n };\n if (this.height) {\n this.tabulatorOptions = {\n ...this.tabulatorOptions,\n height: this.height,\n };\n }\n if (this.maxHeight) {\n this.tabulatorOptions = {\n ...this.tabulatorOptions,\n maxHeight: this.maxHeight,\n };\n }\n if (this.groupBy) {\n this.tabulatorOptions = {\n ...this.tabulatorOptions,\n groupBy: this.groupBy,\n groupHeader: (value: unknown, count: number) => {\n // value - the value all members of this group share\n // count - the number of rows in this group\n // data - an array of all the row data objects in this group\n // group - the group component for the group\n // console.log('groupHeader', value);\n return `${\n this.groupBy\n }: ${value} <span class=\"ion-margin-start\">(${count} ${\n count === 1 ? 'record' : 'records'\n })</span>`;\n },\n };\n }\n }\n}\n","import { ColumnDefinition, Options } from 'tabulator-tables';\n\nexport type TabulatorColumn = ColumnDefinition;\n\n// export interface TabulatorColumn {\n// \tfield: string;\n// \ttitle?: string;\n// \tformatter?: 'link' | 'progress' | 'html' | 'text' | 'number' | 'money' | 'image' | 'tickCross';\n// \tformatterParams?: unknown;\n// \tcellClick?: (e: Event, cell: unknown) => void;\n// \theaderTooltip?: () => string;\n// \ttooltip?: (cell: unknown) => string;\n// \thozAlign?: 'left' | 'right';\n// \theaderHozAlign?: 'left' | 'right';\n// \twidthShrink?: number;\n// \twidthGrow?: number;\n// \twidth?: number | string;\n// }\n\nexport type TabulatorOptions = Options;\n// export interface TabulatorOptions {\n// \treadonly tooltipsHeader?: boolean;\n// \treadonly tooltipGenerationMode?: 'hover' | 'mouseover';\n// \treadonly reactiveData?: boolean;\n// \treadonly selectable?: boolean | number | 'highlight';\n// \treadonly data?: unknown[];\n// \treadonly layout?: 'fitData' | 'fitColumns';\n// \treadonly columns?: TabulatorColumn[];\n// \treadonly height?: string | number;\n// \treadonly maxHeight?: string | number;\n// \treadonly groupBy?: string;\n// \treadonly groupHeader?: (value: unknown, count: number) => string;\n// \treadonly rowClick?: (event: Event, row: unknown) => void;\n// \treadonly rowSelect?: (row: unknown) => void;\n// \treadonly rowDeselect?: (row: unknown) => void;\n// \treadonly rowContextMenu?: IRowMenu[];\n// }\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sneat/datagrid",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -10,5 +10,17 @@
|
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"tslib": "2.8.1"
|
|
13
|
-
}
|
|
13
|
+
},
|
|
14
|
+
"module": "fesm2022/sneat-datagrid.mjs",
|
|
15
|
+
"typings": "types/sneat-datagrid.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
"./package.json": {
|
|
18
|
+
"default": "./package.json"
|
|
19
|
+
},
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./types/sneat-datagrid.d.ts",
|
|
22
|
+
"default": "./fesm2022/sneat-datagrid.mjs"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"sideEffects": false
|
|
14
26
|
}
|
|
@@ -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
package/ng-package.json
DELETED
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,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
|
-
}
|