ng-tablekit 1.0.0

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,311 @@
1
+ :host {
2
+ display: block;
3
+ min-width: 0;
4
+ }
5
+
6
+ /* Table Page Structure */
7
+ .template-page {
8
+ display: flex;
9
+ flex-direction: column;
10
+ gap: 16px;
11
+ width: 100%;
12
+ min-width: 0;
13
+ padding: 0;
14
+ border: 0;
15
+ border-radius: 0;
16
+ background: transparent;
17
+ }
18
+
19
+ /* Toolbar */
20
+ .table-toolbar {
21
+ display: flex;
22
+ align-items: center;
23
+ justify-content: space-between;
24
+ gap: 8px;
25
+ flex-wrap: wrap;
26
+ background: transparent;
27
+ padding: 0;
28
+ }
29
+
30
+ .table-toolbar__left {
31
+ display: flex;
32
+ align-items: center;
33
+ gap: 12px;
34
+ flex-wrap: wrap;
35
+ }
36
+
37
+ .table-toolbar__right {
38
+ display: flex;
39
+ align-items: center;
40
+ justify-content: flex-end;
41
+ gap: 8px;
42
+ flex-wrap: wrap;
43
+ margin-left: auto;
44
+ }
45
+
46
+ /* Page Heading */
47
+ .page-heading {
48
+ margin: 0;
49
+ font-family: Poppins, Arial, sans-serif;
50
+ font-size: 18px;
51
+ font-weight: 600;
52
+ line-height: 24px;
53
+ color: #1f1f1f;
54
+ }
55
+
56
+ /* Back Button */
57
+ .back-btn {
58
+ display: flex;
59
+ align-items: center;
60
+ justify-content: center;
61
+ width: 32px !important;
62
+ height: 32px !important;
63
+ min-width: 32px !important;
64
+ border-radius: 50% !important;
65
+ padding: 0 !important;
66
+ border: 1px solid #d9d9d9 !important;
67
+ background: #ffffff !important;
68
+ color: #262626 !important;
69
+ font-size: 14px;
70
+ cursor: pointer;
71
+ transition: all 0.2s;
72
+ }
73
+
74
+ .back-btn:hover {
75
+ border-color: #1890ff !important;
76
+ color: #1890ff !important;
77
+ background: #ffffff !important;
78
+ }
79
+
80
+ /* Compact Buttons (Filter, Excel, Actions) */
81
+ .compact-btn {
82
+ height: 32px !important;
83
+ min-width: 32px !important;
84
+ border-radius: 6px !important;
85
+ display: inline-flex;
86
+ align-items: center;
87
+ justify-content: center;
88
+ gap: 6px;
89
+ padding: 0 12px !important;
90
+ font-size: 12px !important;
91
+ }
92
+
93
+ .compact-btn.icon-only {
94
+ padding: 0 !important;
95
+ }
96
+
97
+ /* Search Field */
98
+ .search-field {
99
+ width: 260px;
100
+ margin-bottom: 0;
101
+ }
102
+
103
+ :host ::ng-deep .search-field .ant-input {
104
+ height: 32px !important;
105
+ border-radius: 8px 0 0 8px !important;
106
+ font-size: 12px;
107
+ }
108
+
109
+ :host ::ng-deep .search-field .ant-input-group-addon .ant-btn {
110
+ height: 32px !important;
111
+ width: 40px !important;
112
+ border-radius: 0 8px 8px 0 !important;
113
+ display: flex;
114
+ align-items: center;
115
+ justify-content: center;
116
+ }
117
+
118
+ /* Filter Panel */
119
+ .filter-panel {
120
+ margin: 0 0 14px;
121
+ padding: 12px 10px;
122
+ border: 1px solid #e5e7eb;
123
+ border-radius: 6px;
124
+ background: #ffffff;
125
+ }
126
+
127
+ .filter-panel__grid {
128
+ display: grid;
129
+ grid-template-columns: repeat(3, minmax(180px, 1fr));
130
+ gap: 12px;
131
+ }
132
+
133
+ .filter-panel__field {
134
+ display: inline-block;
135
+ margin-bottom: 5px;
136
+ width: 100%;
137
+ padding: 0 10px;
138
+ }
139
+
140
+ .filter-panel__field>label {
141
+ display: block;
142
+ font-family: Poppins, Arial, sans-serif;
143
+ color: #333;
144
+ font-size: 12px;
145
+ font-weight: 500;
146
+ margin-bottom: 4px;
147
+ }
148
+
149
+ :host ::ng-deep .filter-panel__field .ant-select,
150
+ :host ::ng-deep .filter-panel__field .ant-picker,
151
+ :host ::ng-deep .filter-panel__field .ant-input {
152
+ width: 100%;
153
+ border-radius: 4px;
154
+ }
155
+
156
+ :host ::ng-deep .filter-panel__field .ant-radio-wrapper {
157
+ display: inline-flex;
158
+ align-items: center;
159
+ margin-right: 16px;
160
+ }
161
+
162
+ .filter-panel__actions {
163
+ display: flex;
164
+ justify-content: flex-end;
165
+ gap: 10px;
166
+ margin-top: 10px;
167
+ padding: 0 10px;
168
+ }
169
+
170
+ /* Table Overrides */
171
+ .data-table {
172
+ width: 100%;
173
+ }
174
+
175
+ :host ::ng-deep .ant-table {
176
+ background: #ffffff !important;
177
+ font-family: Poppins, Arial, sans-serif;
178
+ }
179
+
180
+ :host ::ng-deep .ant-table-bordered .ant-table-container {
181
+ border: 0 !important;
182
+ border-left: 1px solid #e5e7eb !important;
183
+ }
184
+
185
+ :host ::ng-deep .ant-table-thead>tr>th {
186
+ background: #fafafa !important;
187
+ color: #262626 !important;
188
+ font-family: Poppins, Arial, sans-serif;
189
+ font-size: 14px !important;
190
+ font-weight: 600 !important;
191
+ white-space: nowrap;
192
+ padding: 8px 12px !important;
193
+ border-bottom: 1px solid #e5e7eb !important;
194
+ vertical-align: middle !important;
195
+ text-align: center !important;
196
+ }
197
+
198
+ :host ::ng-deep .ant-table-thead>tr>th .ant-table-filter-column-title {
199
+ padding: 0 !important;
200
+ display: flex;
201
+ align-items: center;
202
+ }
203
+
204
+ :host ::ng-deep .ant-table-tbody>tr:not(.ant-table-measure-now)>td {
205
+ color: #333 !important;
206
+ font-size: 12px !important;
207
+ font-weight: 400 !important;
208
+ padding: 6px 12px !important;
209
+ vertical-align: middle !important;
210
+ border-bottom: 1px solid #e5e7eb !important;
211
+ }
212
+
213
+ :host ::ng-deep .ant-table-tbody>tr:not(.ant-table-measure-now):hover>td {
214
+ background: #fafcff !important;
215
+ }
216
+
217
+ :host ::ng-deep tr.ant-table-measure-now,
218
+ :host ::ng-deep tr.ant-table-measure-now>td,
219
+ :host ::ng-deep tr.ant-table-measure-now>td>div {
220
+ height: 0 !important;
221
+ padding: 0 !important;
222
+ margin: 0 !important;
223
+ border: 0 !important;
224
+ line-height: 0 !important;
225
+ font-size: 0 !important;
226
+ visibility: hidden !important;
227
+ }
228
+
229
+ /* Pagination */
230
+ :host ::ng-deep .ant-pagination {
231
+ margin-top: 12px !important;
232
+ display: flex;
233
+ justify-content: flex-end;
234
+ }
235
+
236
+ :host ::ng-deep .ant-pagination-item,
237
+ :host ::ng-deep .ant-pagination-prev,
238
+ :host ::ng-deep .ant-pagination-next,
239
+ :host ::ng-deep .ant-pagination-options {
240
+ font-size: 12px !important;
241
+ }
242
+
243
+ /* Status Tag */
244
+ .status-tag {
245
+ min-width: 80px;
246
+ text-align: center;
247
+ }
248
+
249
+ /* Action Icons */
250
+ .action-buttons {
251
+ display: flex;
252
+ align-items: center;
253
+ justify-content: center;
254
+ gap: 4px;
255
+ }
256
+
257
+ .action-icon-btn {
258
+ display: inline-flex;
259
+ align-items: center;
260
+ justify-content: center;
261
+ width: 28px;
262
+ height: 28px;
263
+ border-radius: 50%;
264
+ background: #e6f7ff;
265
+ color: #1890ff;
266
+ border: 1px solid transparent;
267
+ cursor: pointer;
268
+ transition: all 0.3s;
269
+ }
270
+
271
+ .action-icon-btn:hover {
272
+ background: #1890ff;
273
+ color: #fff;
274
+ }
275
+
276
+ .action-icon-btn.danger {
277
+ background: #fff1f0;
278
+ color: #f5222d;
279
+ }
280
+
281
+ .action-icon-btn.danger:hover {
282
+ background: #f5222d;
283
+ color: #fff;
284
+ }
285
+
286
+ /* Responsive */
287
+ @media (max-width: 900px) {
288
+ .filter-panel__grid {
289
+ grid-template-columns: repeat(2, minmax(0, 1fr));
290
+ }
291
+ }
292
+
293
+ @media (max-width: 640px) {
294
+ .filter-panel__grid {
295
+ grid-template-columns: 1fr;
296
+ }
297
+
298
+ .table-toolbar__left,
299
+ .table-toolbar__right {
300
+ width: 100%;
301
+ justify-content: flex-start;
302
+ }
303
+
304
+ .table-toolbar__right {
305
+ margin-left: 0;
306
+ }
307
+
308
+ .search-field {
309
+ width: 100%;
310
+ }
311
+ }
@@ -0,0 +1,131 @@
1
+ <div class="template-code-actions">
2
+ <app-copy-template-button [sourcePaths]="[
3
+ { name: 'Master Page', path: 'master-page/master-page' },
4
+ { name: 'Record Drawer', path: 'master-page/master-record-drawer' },
5
+ { name: 'Map Role Drawer', path: 'master-page/master-map-drawer' }
6
+ ]" />
7
+ </div>
8
+ <section class="template-page">
9
+ <div class="table-toolbar">
10
+ <div class="table-toolbar__left"><button class="back-btn" title="Back" aria-label="Go back" type="button" (click)="goBack()"><span nz-icon
11
+ nzType="arrow-left"></span></button>
12
+ <h1 class="page-heading">{{ reportTitle }}</h1>
13
+ </div>
14
+ <div class="table-toolbar__right">
15
+ @if(showFilter) { <button nz-button nzType="default" class="compact-btn" type="button" (click)="toggleFilter()"><span nz-icon
16
+ nzType="filter"></span> Filter</button> }
17
+ @if(showExcel) { <button nz-button nzType="primary" class="compact-btn" type="button"
18
+ (click)="downloadExcel()"><span nz-icon nzType="file-excel"></span>
19
+ Excel</button> }
20
+ @if(showPdf) { <button nz-button nzType="primary" class="compact-btn" type="button" (click)="downloadPdf()"><span
21
+ nz-icon nzType="file-pdf"></span> PDF</button> }
22
+ <nz-form-item class="search-field"><nz-input-group nzSearch [nzAddOnAfter]="searchButton"><input type="text"
23
+ nz-input (keydown.enter)="onSearch()" placeholder="Search Records"
24
+ [(ngModel)]="searchText" /></nz-input-group><ng-template #searchButton><button nz-button
25
+ class="compact-btn icon-only" nzType="primary" type="button" (click)="onSearch()"
26
+ aria-label="Search records"><span nz-icon nzType="search"></span></button></ng-template></nz-form-item>
27
+
28
+ @if(showAddAction) {
29
+ <button nz-button nzType="primary" class="compact-btn" type="button" (click)="openAddDrawer()">
30
+ <span nz-icon nzType="plus"></span> Add New
31
+ </button>
32
+ }
33
+ </div>
34
+ </div>
35
+ @if(filterVisible){
36
+ <form class="filter-panel" [formGroup]="filterForm">
37
+ <div class="filter-panel__grid">
38
+ @if (showCategoryFilter) {
39
+ <div class="filter-panel__field"><label>Category</label><nz-select formControlName="category" nzAllowClear
40
+ nzPlaceHolder="Select category">@for(option of categories;track
41
+ option){<nz-option [nzLabel]="option" [nzValue]="option" />}</nz-select></div>
42
+ }
43
+ @if (showMultiselectFilter) {
44
+ <div class="filter-panel__field"><label>Categories (Multi)</label><nz-select formControlName="categories" nzMode="multiple" nzAllowClear
45
+ nzPlaceHolder="Select categories">@for(option of categories;track
46
+ option){<nz-option [nzLabel]="option" [nzValue]="option" />}</nz-select></div>
47
+ }
48
+ @if (showDateFilter) {
49
+ <div class="filter-panel__field"><label>Created Date</label><nz-date-picker formControlName="date" nzPlaceHolder="Select date"></nz-date-picker></div>
50
+ }
51
+ @if (showDateRangeFilter) {
52
+ <div class="filter-panel__field"><label>Date Range</label><nz-range-picker formControlName="dateRange"></nz-range-picker></div>
53
+ }
54
+ @if (showRadioFilter) {
55
+ <div class="filter-panel__field"><label>Status</label><nz-radio-group formControlName="status">
56
+ @for(option of statuses;track option){<label nz-radio [nzValue]="option">{{option}}</label>}
57
+ </nz-radio-group></div>
58
+ }
59
+ </div>
60
+ <div class="filter-panel__actions"><button nz-button class="compact-btn" type="button"
61
+ (click)="clearFilters()">Clear</button><button nz-button nzType="primary" class="compact-btn" type="button"
62
+ (click)="applyFilters()">Apply Filters</button></div>
63
+ </form>
64
+ }
65
+ <nz-table #table nzBordered nzSize="small" [nzData]="records" [(nzPageIndex)]="pageIndex" [nzPageSize]="10"
66
+ [nzShowSizeChanger]="true" [nzPageSizeOptions]="pageSizeOptions" [nzScroll]="{ y: '55vh' }"
67
+ (nzQueryParams)="onQueryParamsChange($event)">
68
+ <thead>
69
+ <tr>
70
+ <th nzWidth="150px" nzAlign="center">Action</th>
71
+ @for(column of columns; track column.key){
72
+ @if(column.sortable === true){
73
+ <th [nzWidth]="column.width ?? null" [nzSortFn]="sortBy(column.key)">{{column.title}}</th>
74
+ } @else {
75
+ <th [nzWidth]="column.width ?? null">{{column.title}}</th>
76
+ }
77
+ }
78
+ </tr>
79
+ </thead>
80
+ <tbody>@for(record of table.data; track record.id){<tr>
81
+ <td nzAlign="center">
82
+ <div class="action-buttons">
83
+ @if(showViewAction) {
84
+ <button class="action-icon-btn" title="View" (click)="viewRecord(record)">
85
+ <span nz-icon nzType="eye"></span>
86
+ </button>
87
+ }
88
+ @if(showMapAction) {
89
+ <button class="action-icon-btn" title="Map Role" (click)="mapRecord(record)">
90
+ <span nz-icon nzType="form"></span>
91
+ </button>
92
+ }
93
+ @if(showEditAction) {
94
+ <button class="action-icon-btn" title="Edit" (click)="openEditDrawer(record)">
95
+ <span nz-icon nzType="edit"></span>
96
+ </button>
97
+ }
98
+ @if(showDeleteAction) {
99
+ <button class="action-icon-btn danger" title="Delete" nz-popconfirm nzPopconfirmTitle="Are you sure delete this record?" nzPopconfirmPlacement="left" (nzOnConfirm)="deleteRecord(record)">
100
+ <span nz-icon nzType="delete"></span>
101
+ </button>
102
+ }
103
+ </div>
104
+ </td>
105
+
106
+ @for(column of
107
+ columns; track column.key){<td [nzAlign]="column.align || 'left'">
108
+ @switch(column.type){@case('date'){ {{
109
+ formatDateValue(record[column.key]) }} }@case('status'){<nz-tag class="status-tag"
110
+ [nzColor]="getStatusColor(record.status)">{{record.status}}</nz-tag>}@case('currency'){ {{ getCurrencyValue(record[column.key]) | currency }} }@default{
111
+ {{record[column.key]}} }}
112
+ </td>}
113
+ </tr>}</tbody>
114
+ </nz-table>
115
+ </section>
116
+
117
+ <app-master-record-drawer
118
+ [visible]="isDrawerVisible"
119
+ [mode]="drawerMode"
120
+ [title]="drawerTitle"
121
+ [record]="editingRecord"
122
+ [categories]="categories"
123
+ (close)="closeDrawer()"
124
+ (save)="saveRecord($event)"
125
+ ></app-master-record-drawer>
126
+
127
+ <app-master-map-drawer
128
+ [visible]="isMapDrawerVisible"
129
+ [record]="mappingRecord"
130
+ (close)="closeMapDrawer()"
131
+ ></app-master-map-drawer>