axioma-material 1.0.1

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.
Files changed (34) hide show
  1. package/README.md +63 -0
  2. package/fesm2022/axioma-material.mjs +767 -0
  3. package/fesm2022/axioma-material.mjs.map +1 -0
  4. package/index.d.ts +5 -0
  5. package/lib/confirmation-dialog/confirmation-data.d.ts +13 -0
  6. package/lib/confirmation-dialog/confirmation-dialog.component.d.ts +11 -0
  7. package/lib/confirmation.service.d.ts +8 -0
  8. package/lib/detail-actions/detail-actions.component.d.ts +11 -0
  9. package/lib/email/checkUserExistsFn.d.ts +2 -0
  10. package/lib/email/email.component.d.ts +25 -0
  11. package/lib/grid/grid-config.d.ts +29 -0
  12. package/lib/grid/grid.component.d.ts +54 -0
  13. package/lib/loading.interceptor.d.ts +2 -0
  14. package/lib/snack.service.d.ts +8 -0
  15. package/package.json +25 -0
  16. package/public-api.d.ts +19 -0
  17. package/state/crud/crud.actions.d.ts +64 -0
  18. package/state/crud/crud.effects.d.ts +41 -0
  19. package/state/crud/crud.module.d.ts +7 -0
  20. package/state/crud/crud.reducer.d.ts +36 -0
  21. package/state/crud/crud.selectors.d.ts +21 -0
  22. package/state/grid/grid-setup.d.ts +6 -0
  23. package/state/grid/grid.actions.d.ts +57 -0
  24. package/state/grid/grid.effects.d.ts +44 -0
  25. package/state/grid/grid.module.d.ts +7 -0
  26. package/state/grid/grid.reducer.d.ts +20 -0
  27. package/state/grid/grid.selectors.d.ts +17 -0
  28. package/state/grid/models.d.ts +41 -0
  29. package/state/router/router.actions.d.ts +11 -0
  30. package/state/router/router.effects.d.ts +13 -0
  31. package/state/router/router.module.d.ts +7 -0
  32. package/state/router/router.selectors.d.ts +13 -0
  33. package/state/router/store-route-serializer.d.ts +10 -0
  34. package/state/shared/shared.actions.d.ts +37 -0
@@ -0,0 +1,767 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, Injectable, Component, ChangeDetectionStrategy, EventEmitter, booleanAttribute, Input, Output, input, effect, forwardRef, signal, computed, TemplateRef, NgModule } from '@angular/core';
3
+ import { MatSnackBar } from '@angular/material/snack-bar';
4
+ import { HttpResponse, HttpErrorResponse, HttpClient, HttpHeaders } from '@angular/common/http';
5
+ import { createActionGroup, emptyProps, props, Store, createReducer, on, createFeature, createFeatureSelector, createSelector, provideState } from '@ngrx/store';
6
+ import { catchError, map, take, of, first, filter, switchMap, tap } from 'rxjs';
7
+ import { MAT_DIALOG_DATA, MatDialogRef, MatDialogContent, MatDialogActions, MatDialogTitle, MatDialog } from '@angular/material/dialog';
8
+ import { NgTemplateOutlet, Location, CommonModule } from '@angular/common';
9
+ import * as i5 from '@angular/material/button';
10
+ import { MatButtonModule } from '@angular/material/button';
11
+ import * as i2 from '@angular/material/icon';
12
+ import { MatIconModule } from '@angular/material/icon';
13
+ import * as i1 from '@angular/material/toolbar';
14
+ import { MatToolbarModule } from '@angular/material/toolbar';
15
+ import { toSignal, toObservable } from '@angular/core/rxjs-interop';
16
+ import * as i1$1 from '@angular/forms';
17
+ import { FormControl, Validators, NG_VALUE_ACCESSOR, NG_VALIDATORS, ReactiveFormsModule } from '@angular/forms';
18
+ import * as i2$1 from '@angular/material/form-field';
19
+ import { MatFormFieldModule } from '@angular/material/form-field';
20
+ import * as i3 from '@angular/material/input';
21
+ import { MatInputModule } from '@angular/material/input';
22
+ import * as i9 from '@angular/router';
23
+ import { RouterModule, ActivatedRoute, Router } from '@angular/router';
24
+ import * as i11 from '@angular/material/paginator';
25
+ import { MatPaginatorModule } from '@angular/material/paginator';
26
+ import * as i10 from '@angular/material/sort';
27
+ import { MatSortModule } from '@angular/material/sort';
28
+ import * as i3$1 from '@angular/material/table';
29
+ import { MatTableModule } from '@angular/material/table';
30
+ import * as i7 from '@angular/material/tooltip';
31
+ import { MatTooltipModule } from '@angular/material/tooltip';
32
+ import * as i6 from '@angular/material/checkbox';
33
+ import { MatCheckboxModule } from '@angular/material/checkbox';
34
+ import { SelectionModel } from '@angular/cdk/collections';
35
+ import { Actions, ofType, createEffect, provideEffects } from '@ngrx/effects';
36
+ import { concatLatestFrom } from '@ngrx/operators';
37
+ import { map as map$1, mergeMap, filter as filter$1, concatMap, catchError as catchError$1, tap as tap$1 } from 'rxjs/operators';
38
+ import { ROUTER_NAVIGATION } from '@ngrx/router-store';
39
+
40
+ class SnackService {
41
+ snackBar = inject(MatSnackBar);
42
+ info(message, action = 'Dismiss', duration = 3000) {
43
+ this.snackBar.open(message, action, { duration });
44
+ }
45
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: SnackService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
46
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: SnackService, providedIn: 'root' });
47
+ }
48
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: SnackService, decorators: [{
49
+ type: Injectable,
50
+ args: [{
51
+ providedIn: 'root'
52
+ }]
53
+ }] });
54
+
55
+ const SharedActions = createActionGroup({
56
+ source: 'Shared',
57
+ events: {
58
+ 'Back': emptyProps(),
59
+ 'Init': emptyProps(),
60
+ 'Init Success': props(),
61
+ 'Noop': emptyProps(),
62
+ 'Start Request': emptyProps(),
63
+ 'End Request': emptyProps(),
64
+ 'Transient Error': props(),
65
+ 'Bad Error': props(),
66
+ 'Navigate': props(),
67
+ 'Access Denied': emptyProps(),
68
+ 'Login': props(),
69
+ }
70
+ });
71
+
72
+ const loadingInterceptor = (req, next) => {
73
+ let store = inject(Store);
74
+ store.dispatch(SharedActions.startRequest());
75
+ try {
76
+ return next(req)
77
+ .pipe(catchError((err) => {
78
+ store.dispatch(SharedActions.endRequest());
79
+ throw err;
80
+ }))
81
+ .pipe(map(e => {
82
+ if (e instanceof HttpResponse || e instanceof HttpErrorResponse) {
83
+ store.dispatch(SharedActions.endRequest());
84
+ }
85
+ return e;
86
+ }));
87
+ }
88
+ catch (err) {
89
+ console.log('error', err);
90
+ store.dispatch(SharedActions.endRequest());
91
+ throw err;
92
+ }
93
+ };
94
+
95
+ class ConfirmationDialogComponent {
96
+ data = inject(MAT_DIALOG_DATA);
97
+ dialogRef = inject((MatDialogRef));
98
+ constructor() {
99
+ this.data.buttons ??= [{
100
+ text: 'Yes',
101
+ value: true,
102
+ default: true,
103
+ color: 'primary'
104
+ }, {
105
+ text: 'No',
106
+ value: false,
107
+ default: false,
108
+ }];
109
+ }
110
+ clickButton(button) {
111
+ this.dialogRef.close(button.value);
112
+ }
113
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: ConfirmationDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
114
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.4", type: ConfirmationDialogComponent, isStandalone: true, selector: "x-confirmation-dialog", ngImport: i0, template: "<h2 mat-dialog-title>{{data.title}}</h2>\r\n<mat-dialog-content cdkTrapFocus class=\"mat-typography\">\r\n @if(data.message){\r\n <p>{{data.message}}</p>\r\n } @else if (data.messageRef) {\r\n <ng-container *ngTemplateOutlet=\"data.messageRef\"></ng-container>\r\n }\r\n</mat-dialog-content>\r\n<mat-dialog-actions>\r\n @for(button of data.buttons; track button){\r\n @if(button.default){\r\n <button mat-button (click)=\"clickButton(button)\" cdkFocusInitial>{{button.text}}</button>\r\n } @else {\r\n <button mat-button (click)=\"clickButton(button)\">{{button.text}}</button>\r\n }\r\n }\r\n</mat-dialog-actions>", styles: [""], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i5.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
115
+ }
116
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: ConfirmationDialogComponent, decorators: [{
117
+ type: Component,
118
+ args: [{ selector: 'x-confirmation-dialog', imports: [NgTemplateOutlet, MatButtonModule, MatDialogContent, MatDialogActions, MatDialogTitle], changeDetection: ChangeDetectionStrategy.OnPush, template: "<h2 mat-dialog-title>{{data.title}}</h2>\r\n<mat-dialog-content cdkTrapFocus class=\"mat-typography\">\r\n @if(data.message){\r\n <p>{{data.message}}</p>\r\n } @else if (data.messageRef) {\r\n <ng-container *ngTemplateOutlet=\"data.messageRef\"></ng-container>\r\n }\r\n</mat-dialog-content>\r\n<mat-dialog-actions>\r\n @for(button of data.buttons; track button){\r\n @if(button.default){\r\n <button mat-button (click)=\"clickButton(button)\" cdkFocusInitial>{{button.text}}</button>\r\n } @else {\r\n <button mat-button (click)=\"clickButton(button)\">{{button.text}}</button>\r\n }\r\n }\r\n</mat-dialog-actions>" }]
119
+ }], ctorParameters: () => [] });
120
+
121
+ class ConfirmationService {
122
+ dialog = inject(MatDialog);
123
+ confirm(message, title = 'Confirmation') {
124
+ let ref = this.dialog.open(ConfirmationDialogComponent, {
125
+ data: {
126
+ title,
127
+ message
128
+ }
129
+ });
130
+ return ref.afterClosed();
131
+ }
132
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: ConfirmationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
133
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: ConfirmationService, providedIn: 'root' });
134
+ }
135
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: ConfirmationService, decorators: [{
136
+ type: Injectable,
137
+ args: [{
138
+ providedIn: 'root'
139
+ }]
140
+ }] });
141
+
142
+ class DetailActionsComponent {
143
+ dontRoute = false;
144
+ cancel = new EventEmitter();
145
+ location = inject(Location);
146
+ constructor() {
147
+ this.cancel.pipe(take(1)).subscribe(() => this.dontRoute || this.location.back());
148
+ }
149
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: DetailActionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
150
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "19.1.4", type: DetailActionsComponent, isStandalone: true, selector: "x-detail-actions", inputs: { dontRoute: ["no-routing", "dontRoute", booleanAttribute] }, outputs: { cancel: "cancel" }, ngImport: i0, template: "<mat-toolbar class=\"flex flex-row gap-2 p-2\">\r\n <button mat-stroked-button type=\"submit\"><mat-icon>save</mat-icon> Save</button>\r\n <button mat-button type=\"button\" (click)=\"cancel.emit()\"><mat-icon>cancel</mat-icon> Cancel</button>\r\n <div class=\"flex-grow\"></div>\r\n <ng-content select=\"[right]\"></ng-content>\r\n</mat-toolbar>", styles: [""], dependencies: [{ kind: "ngmodule", type: MatToolbarModule }, { kind: "component", type: i1.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i5.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
151
+ }
152
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: DetailActionsComponent, decorators: [{
153
+ type: Component,
154
+ args: [{ selector: 'x-detail-actions', imports: [MatToolbarModule, MatIconModule, MatButtonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<mat-toolbar class=\"flex flex-row gap-2 p-2\">\r\n <button mat-stroked-button type=\"submit\"><mat-icon>save</mat-icon> Save</button>\r\n <button mat-button type=\"button\" (click)=\"cancel.emit()\"><mat-icon>cancel</mat-icon> Cancel</button>\r\n <div class=\"flex-grow\"></div>\r\n <ng-content select=\"[right]\"></ng-content>\r\n</mat-toolbar>" }]
155
+ }], ctorParameters: () => [], propDecorators: { dontRoute: [{
156
+ type: Input,
157
+ args: [{ transform: booleanAttribute, alias: 'no-routing' }]
158
+ }], cancel: [{
159
+ type: Output
160
+ }] } });
161
+
162
+ class EmailComponent {
163
+ checkUserExistsFn;
164
+ login = new EventEmitter();
165
+ label = 'Email';
166
+ exists = new EventEmitter();
167
+ $touched = input(false, { transform: booleanAttribute, alias: 'touched' });
168
+ $existing = input(false, { transform: booleanAttribute, alias: 'existing' });
169
+ control = new FormControl('', [Validators.required, Validators.email]);
170
+ onChange = (_) => { };
171
+ onTouch = (_) => { };
172
+ onValidationChange = () => { };
173
+ writeValue(obj) {
174
+ this.control.setValue(obj);
175
+ }
176
+ registerOnChange(fn) {
177
+ this.onChange = fn;
178
+ }
179
+ registerOnTouched(fn) {
180
+ this.onTouch = fn;
181
+ }
182
+ setDisabledState(isDisabled) {
183
+ isDisabled
184
+ ? this.control.disable()
185
+ : this.control.enable();
186
+ }
187
+ validate(_) {
188
+ return this.control.errors;
189
+ }
190
+ registerOnValidatorChange(fn) {
191
+ this.onValidationChange = fn;
192
+ }
193
+ constructor() {
194
+ let $valid = toSignal(this.control.statusChanges);
195
+ effect(() => {
196
+ this.onValidationChange();
197
+ });
198
+ let $value = toSignal(this.control.valueChanges);
199
+ effect(() => {
200
+ this.onChange($value());
201
+ });
202
+ this.control.setAsyncValidators(() => {
203
+ let existing = this.$existing();
204
+ let value = this.control.value;
205
+ if (!value || typeof existing === 'undefined') {
206
+ return of(null);
207
+ }
208
+ return this.checkUserExistsFn(value).pipe(map(exists => {
209
+ this.exists.emit(exists);
210
+ return exists === existing ? null : existing ? { missing: true } : { exists: true };
211
+ }), first());
212
+ });
213
+ effect(() => {
214
+ let touched = this.$touched();
215
+ if (touched) {
216
+ this.control.markAsTouched();
217
+ }
218
+ else {
219
+ this.control.markAsUntouched();
220
+ }
221
+ });
222
+ }
223
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: EmailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
224
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.4", type: EmailComponent, isStandalone: true, selector: "x-email", inputs: { checkUserExistsFn: { classPropertyName: "checkUserExistsFn", publicName: "checkUserExistsFn", isSignal: false, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: false, isRequired: false, transformFunction: null }, $touched: { classPropertyName: "$touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, $existing: { classPropertyName: "$existing", publicName: "existing", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { login: "login", exists: "exists" }, host: { listeners: { "blur": "onTouch($event)" } }, providers: [
225
+ {
226
+ provide: NG_VALUE_ACCESSOR,
227
+ multi: true,
228
+ useExisting: EmailComponent
229
+ },
230
+ {
231
+ provide: NG_VALIDATORS,
232
+ useExisting: forwardRef(() => EmailComponent),
233
+ multi: true,
234
+ },
235
+ ], ngImport: i0, template: "<mat-form-field >\r\n <mat-label>{{label}}</mat-label>\r\n <input matInput type=\"email\" [formControl]=\"control\" required>\r\n <mat-hint><ng-content></ng-content></mat-hint>\r\n @if (control.hasError('required')){\r\n <mat-error>Email is required</mat-error>\r\n } @else if (control.hasError('email')){\r\n <mat-error>Email is invalid</mat-error>\r\n } @else if (control.hasError('exists')){\r\n <mat-error>Email already exists: <a (click)=\"login.emit()\">sign in</a>.</mat-error>\r\n } @else if (control.hasError('missing')){\r\n <mat-error>Email is missing</mat-error>\r\n }\r\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i2$1.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: RouterModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
236
+ }
237
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: EmailComponent, decorators: [{
238
+ type: Component,
239
+ args: [{ selector: 'x-email', imports: [ReactiveFormsModule, MatFormFieldModule, MatInputModule, RouterModule], changeDetection: ChangeDetectionStrategy.OnPush, host: {
240
+ '(blur)': 'onTouch($event)'
241
+ }, providers: [
242
+ {
243
+ provide: NG_VALUE_ACCESSOR,
244
+ multi: true,
245
+ useExisting: EmailComponent
246
+ },
247
+ {
248
+ provide: NG_VALIDATORS,
249
+ useExisting: forwardRef(() => EmailComponent),
250
+ multi: true,
251
+ },
252
+ ], template: "<mat-form-field >\r\n <mat-label>{{label}}</mat-label>\r\n <input matInput type=\"email\" [formControl]=\"control\" required>\r\n <mat-hint><ng-content></ng-content></mat-hint>\r\n @if (control.hasError('required')){\r\n <mat-error>Email is required</mat-error>\r\n } @else if (control.hasError('email')){\r\n <mat-error>Email is invalid</mat-error>\r\n } @else if (control.hasError('exists')){\r\n <mat-error>Email already exists: <a (click)=\"login.emit()\">sign in</a>.</mat-error>\r\n } @else if (control.hasError('missing')){\r\n <mat-error>Email is missing</mat-error>\r\n }\r\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"] }]
253
+ }], ctorParameters: () => [], propDecorators: { checkUserExistsFn: [{
254
+ type: Input,
255
+ args: [{ required: true }]
256
+ }], login: [{
257
+ type: Output
258
+ }], label: [{
259
+ type: Input
260
+ }], exists: [{
261
+ type: Output
262
+ }] } });
263
+
264
+ const GridActions = createActionGroup({
265
+ source: 'Grid',
266
+ events: {
267
+ 'Refresh': emptyProps(),
268
+ 'Load': props(),
269
+ 'Load Success': props(),
270
+ 'Change Paging': props(),
271
+ 'Change Sort': props(),
272
+ 'Change Filter': props(),
273
+ 'Update Request': props(),
274
+ 'Go To': props(),
275
+ 'Bulk Delete': props(),
276
+ 'Bulk Delete Success': emptyProps(),
277
+ }
278
+ });
279
+
280
+ const gridFeatureKey = 'grid';
281
+ const initialState$1 = {
282
+ grids: {}
283
+ };
284
+ const reducer$1 = createReducer(initialState$1, on(GridActions.loadSuccess, (state, { name, data, count }) => ({
285
+ ...state,
286
+ grids: { ...state.grids, [name]: { ...state.grids[name], data, count, loading: false } }
287
+ })), on(GridActions.load, (state, { name }) => ({
288
+ ...state,
289
+ grids: { ...state.grids, [name]: { ...state.grids[name],
290
+ data: undefined,
291
+ count: undefined,
292
+ loading: true } }
293
+ })));
294
+ const gridFeature = createFeature({
295
+ name: gridFeatureKey,
296
+ reducer: reducer$1,
297
+ });
298
+
299
+ var FilterLogic;
300
+ (function (FilterLogic) {
301
+ FilterLogic[FilterLogic["Or"] = 0] = "Or";
302
+ FilterLogic[FilterLogic["And"] = 1] = "And";
303
+ })(FilterLogic || (FilterLogic = {}));
304
+ var FilterOperator;
305
+ (function (FilterOperator) {
306
+ FilterOperator[FilterOperator["Contains"] = 0] = "Contains";
307
+ FilterOperator[FilterOperator["Equals"] = 1] = "Equals";
308
+ FilterOperator[FilterOperator["Greater"] = 2] = "Greater";
309
+ FilterOperator[FilterOperator["Less"] = 3] = "Less";
310
+ FilterOperator[FilterOperator["In"] = 4] = "In";
311
+ })(FilterOperator || (FilterOperator = {}));
312
+ var SortDir;
313
+ (function (SortDir) {
314
+ SortDir[SortDir["Asc"] = 0] = "Asc";
315
+ SortDir[SortDir["Desc"] = 1] = "Desc";
316
+ })(SortDir || (SortDir = {}));
317
+
318
+ const selectRouter = createFeatureSelector('router');
319
+ const selectRouterState = createSelector(selectRouter, state => state?.state);
320
+ const selectRouteParams = createSelector(selectRouterState, state => state?.params);
321
+ const selectRouteParam = (name) => createSelector(selectRouteParams, params => (params && name) ? params[name] : undefined);
322
+ const selectUrl = createSelector(selectRouterState, state => decodeUriInternal(state?.url));
323
+ const selectSiteSlugParam = createSelector(selectRouteParam('site-slug'), selectUrl, (s, u) => s ?? (!!u ? null : undefined));
324
+ const selectQueryParams = createSelector(selectRouterState, state => state?.queryParams);
325
+ const selectQueryParam = (name) => createSelector(selectQueryParams, params => params ? params[name] : undefined);
326
+ const selectDataParam = (name) => createSelector(selectRouterState, state => state?.data[name]);
327
+ const selectUrlWithoutQuery = createSelector(selectRouterState, state => decodeUriInternal(state?.url?.split('?')[0]));
328
+ const selectUrlSegments = (count) => createSelector(selectUrlWithoutQuery, url => {
329
+ let segs = url.split('/');
330
+ return segs.slice(0, Math.min(segs.length, count)).join('/');
331
+ });
332
+ const decodeUriInternal = (source) => {
333
+ return !!source ? decodeURI(source) : source;
334
+ };
335
+
336
+ const selectGridData = (name) => createSelector(gridFeature.selectGrids, (grids) => grids ? grids[name] : undefined);
337
+ const selectPageIndex = createSelector(selectQueryParam('page'), (p) => (p ? +p : 1) - 1);
338
+ const selectPageSize = createSelector(selectQueryParam('size'), (s) => s ? +s : 25);
339
+ const selectGridFilters = (name) => createSelector(selectQueryParam(name), (params) => params ? JSON.parse(atob(params)) : undefined);
340
+ const selectTotalCount = (name) => createSelector(selectGridData(name), data => data?.count ?? 0);
341
+ const selectGridSetup = createSelector(selectRouterState, s => s?.data['grid'] ? s.data['grid'] : undefined);
342
+ const selectSortBy = createSelector(selectGridSetup, selectQueryParam('sort-by'), (s, q) => q ? q : s?.sortBy);
343
+ const selectSortDir = createSelector(selectGridSetup, selectQueryParam('sort-dir'), (s, q) => {
344
+ q = (q ?? s?.sortDir)?.toLowerCase();
345
+ return q == 'desc' ? SortDir.Desc : SortDir.Asc;
346
+ });
347
+ const selectSearchFields = createSelector(selectGridSetup, d => d?.searchFields);
348
+ const selectIsGrid = createSelector(selectGridSetup, s => !!s);
349
+ const selectGridName = createSelector(selectGridSetup, s => s?.controllerMethod);
350
+ const selectDataUrl = createSelector(selectGridSetup, s => `/api/${s?.controllerMethod}`);
351
+ const selectFilterText = createSelector(selectGridFilters('filter'), f => f?.fields?.at(0)?.values?.at(0) ?? '');
352
+ const selectDataRequest = createSelector(selectPageIndex, selectPageSize, selectSortBy, selectSortDir, selectGridFilters('base-filter'), selectGridFilters('filter'), (pageIndex, pageSize, sortBy, sortDir, baseFilters, filters) => ({
353
+ paging: { page: pageIndex + 1, pageSize },
354
+ sortBy,
355
+ sortDir,
356
+ filters: combineFilters([baseFilters, filters])
357
+ }));
358
+ function combineFilters(filters) {
359
+ let filtered = filters.filter(f => !!f);
360
+ if (filtered.length == 0) {
361
+ return undefined;
362
+ }
363
+ if (filtered.length == 1) {
364
+ return filtered[0];
365
+ }
366
+ return { logic: FilterLogic.And, groups: filtered };
367
+ }
368
+
369
+ class GridComponent {
370
+ $deleteSuccess = toSignal(inject(Actions).pipe(ofType(GridActions.bulkDeleteSuccess)));
371
+ route = inject(ActivatedRoute);
372
+ router = inject(Router);
373
+ store = inject(Store);
374
+ selection = new SelectionModel(true, [], true, (a, b) => (a.id ?? a) === (b.id ?? b));
375
+ $config = signal(undefined);
376
+ set config(val) {
377
+ this.$config.set(val);
378
+ }
379
+ ;
380
+ $sort = this.store.selectSignal(selectSortBy);
381
+ $dir;
382
+ $bulk = input(false, { alias: 'bulk', transform: booleanAttribute });
383
+ $allSelected = signal(false);
384
+ $gridName = this.store.selectSignal(selectGridName);
385
+ $columns = computed(() => this.$config()?.columns);
386
+ $buttons = computed(() => this.$config()?.buttons);
387
+ $displayedColumns = computed(() => {
388
+ let res = this.$columns()?.map(c => c.name);
389
+ if (res && this.$hasActions()) {
390
+ res.push('actions');
391
+ }
392
+ if (res && this.$bulk()) {
393
+ res.unshift('select');
394
+ }
395
+ return res;
396
+ });
397
+ $gridData = toSignal(toObservable(this.$gridName).pipe(filter(name => !!name), switchMap(name => this.store.select(selectGridData(name)))));
398
+ $filter = this.store.selectSignal(selectFilterText);
399
+ $pageIndex = this.store.selectSignal(selectPageIndex);
400
+ $pageSize = this.store.selectSignal(selectPageSize);
401
+ $dataSource = computed(() => this.$gridData()?.data ?? []);
402
+ $searchColumns = this.store.selectSignal(selectSearchFields);
403
+ $hasSearch = computed(() => this.$searchColumns()?.length ?? 0);
404
+ $actions = computed(() => this.$config()?.actions);
405
+ $hasActions = computed(() => this.$actions()?.length ?? 0);
406
+ $selectedCount;
407
+ toggleAll() {
408
+ this.selection.clear();
409
+ this.$allSelected.set(!this.$allSelected());
410
+ }
411
+ toggleOne(e, row) {
412
+ if (this.$allSelected()) {
413
+ this.selection.clear();
414
+ this.$allSelected.set(false);
415
+ this.selection.select(row);
416
+ }
417
+ else
418
+ this.selection.toggle(row);
419
+ if (e.checked != this.selection.isSelected(row))
420
+ e.source.checked = this.selection.isSelected(row);
421
+ }
422
+ deleteSelected() {
423
+ this.store.dispatch(GridActions.bulkDelete({ ids: this.selection.selected.map(s => s.id) }));
424
+ }
425
+ pageChange(e) {
426
+ this.store.dispatch(GridActions.changePaging({ pageIndex: e.pageIndex, pageSize: e.pageSize }));
427
+ }
428
+ sortChange(e) {
429
+ this.store.dispatch(GridActions.changeSort({ sort: e.active, dir: e.direction }));
430
+ }
431
+ refresh() {
432
+ this.selection.clear();
433
+ this.store.dispatch(GridActions.refresh());
434
+ }
435
+ setFilter(filter) {
436
+ this.store.dispatch(GridActions.changeFilter({ filter }));
437
+ }
438
+ filterKeyUp(event) {
439
+ this.setFilter(event.target.value);
440
+ }
441
+ getDisplayRef(col) {
442
+ if (col.display instanceof TemplateRef)
443
+ return col.display;
444
+ return null;
445
+ }
446
+ getDisplayFunc(col) {
447
+ if (col.display instanceof Function)
448
+ return col.display;
449
+ return null;
450
+ }
451
+ display(col, row) {
452
+ let func = this.getDisplayFunc(col);
453
+ if (func)
454
+ return func(row);
455
+ return row[col.name];
456
+ }
457
+ onRowClick(row) {
458
+ if (!this.$config()?.defaultAction)
459
+ return;
460
+ let action = this.$actions()?.find(a => a.name === this.$config()?.defaultAction);
461
+ if (action?.routerLink) {
462
+ let link = action.routerLink(row);
463
+ if (!Array.isArray(link))
464
+ link = [link];
465
+ this.router.navigate(link, { relativeTo: this.route });
466
+ }
467
+ else if (action?.action) {
468
+ action.action(row);
469
+ }
470
+ }
471
+ onAction(e, row, action) {
472
+ e.stopPropagation();
473
+ if (action.action)
474
+ action.action(row);
475
+ }
476
+ getStyle(col) {
477
+ return { 'max-width': col.width ?? 'auto' };
478
+ }
479
+ $request = this.store.selectSignal(selectDataRequest);
480
+ constructor() {
481
+ let $dir = this.store.selectSignal(selectSortDir);
482
+ this.$dir = computed(() => $dir() == SortDir.Desc ? 'desc' : 'asc');
483
+ effect(() => {
484
+ this.$deleteSuccess();
485
+ this.selection.clear();
486
+ this.$allSelected.set(false);
487
+ });
488
+ let $selectionChanged = toSignal(this.selection.changed);
489
+ this.$selectedCount = computed(() => {
490
+ let selection = $selectionChanged()?.source;
491
+ let total = this.$gridData()?.count;
492
+ return this.$allSelected() && !selection?.hasValue() ? total : selection?.selected.length;
493
+ });
494
+ }
495
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: GridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
496
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.4", type: GridComponent, isStandalone: true, selector: "x-grid", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: false, isRequired: false, transformFunction: null }, $bulk: { classPropertyName: "$bulk", publicName: "bulk", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<mat-toolbar class=\"flex flex-row gap-2 p-2\">\r\n @if($hasSearch()){\r\n <div class=\"h-full\">\r\n <mat-form-field>\r\n <mat-label>Search</mat-label>\r\n <mat-icon matPrefix>search</mat-icon>\r\n <input matInput type=\"text\" [value]=\"$filter()\" (keyup)=\"filterKeyUp($event)\">\r\n @if ($filter()) {\r\n <button matSuffix mat-icon-button aria-label=\"Clear\" (click)=\"setFilter('')\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n }\r\n </mat-form-field>\r\n </div>\r\n }\r\n <ng-content select=\"[toolbar]\"></ng-content>\r\n @for(button of $buttons(); track button.name){\r\n <button mat-button [routerLink]=\"button.routerLink?button.routerLink():undefined\" [matTooltip]=\"button.text\"\r\n (click)=\"onAction($event,undefined,button)\"><mat-icon>{{button.icon}}</mat-icon> {{button.text}}</button>\r\n }\r\n @if ($config()?.new){\r\n <a mat-button routerLink=\"../new\"><mat-icon>add</mat-icon> New</a>\r\n }\r\n @if($config()?.refresh)\r\n {\r\n <button mat-button (click)=\"refresh()\"><mat-icon>sync</mat-icon> Refresh</button>\r\n }\r\n @if($bulk()){\r\n <button mat-button [disabled]=\"!$selectedCount()\" (click)=\"deleteSelected()\"><mat-icon>delete</mat-icon> Delete</button>\r\n }\r\n <span class=\"flex-grow\"></span>\r\n @if ($selectedCount() || $allSelected()){\r\n <span class=\"text-sm\"> {{$selectedCount()??0}} items selected</span>\r\n }\r\n</mat-toolbar>\r\n<mat-table [dataSource]=\"$dataSource()\" matSort (matSortChange)=\"sortChange($event)\"\r\n [matSortActive]=\"$sort()\" [matSortDirection]=\"$dir()\" matSortDisableClear>\r\n @if ($bulk()){\r\n <ng-container matColumnDef=\"select\">\r\n <mat-header-cell *matHeaderCellDef class=\"select\" matTooltip=\"Select all\">\r\n <mat-checkbox (change)=\"$event ? toggleAll() : null\" [checked]=\"!selection.hasValue() && $allSelected()\"\r\n [indeterminate]=\"selection.hasValue() && !$allSelected()\">\r\n </mat-checkbox>\r\n </mat-header-cell>\r\n <mat-cell *matCellDef=\"let row\" class=\"select\">\r\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"toggleOne($event, row)\"\r\n [checked]=\"selection.isSelected(row) || $allSelected() && !selection.hasValue()\">\r\n </mat-checkbox>\r\n </mat-cell>\r\n </ng-container>\r\n }\r\n @for(column of $columns(); track column.name){\r\n <ng-container [matColumnDef]=\"column.name\">\r\n @if (column.sort){\r\n <mat-header-cell [style]=\"getStyle(column)\" *matHeaderCellDef\r\n mat-sort-header>{{column.header}}</mat-header-cell>\r\n } @else {\r\n <mat-header-cell [style]=\"getStyle(column)\" *matHeaderCellDef>{{column.header}}</mat-header-cell>\r\n }\r\n <mat-cell [style]=\"getStyle(column)\" *matCellDef=\"let row\">\r\n @if(column.href || column.routerLink){\r\n <a [routerLink]=\"column.routerLink?column.routerLink(row):undefined\"\r\n [attr.href]=\"column.href?column.href(row):undefined\"\r\n (click)=\"column.action?column.action(row):undefined\">\r\n {{ display(column,row) }}\r\n </a>\r\n } @else if (getDisplayRef(column)) {\r\n <ng-container *ngTemplateOutlet=\"getDisplayRef(column); context: { $implicit: row}\"></ng-container>\r\n } @else {\r\n {{ display(column,row)}}\r\n }\r\n </mat-cell>\r\n </ng-container>\r\n }\r\n @if($hasActions()){\r\n <ng-container matColumnDef=\"actions\">\r\n <mat-header-cell *matHeaderCellDef>Actions</mat-header-cell>\r\n <mat-cell *matCellDef=\"let row\">\r\n @for(action of $actions(); track action.name){\r\n <button type=\"button\" mat-icon-button [disabled]=\"action.disabled?action.disabled(row):undefined\"\r\n [matTooltip]=\"action.text\" (click)=\"onAction($event, row, action)\"\r\n [queryParams]=\"action.queryParams?action.queryParams(row):undefined\"\r\n [routerLink]=\"action.routerLink?action.routerLink(row):undefined\">\r\n <mat-icon>{{action.icon}}</mat-icon>\r\n </button>\r\n }\r\n </mat-cell>\r\n </ng-container>\r\n }\r\n <mat-header-row *matHeaderRowDef=\"$displayedColumns()\"></mat-header-row>\r\n <mat-row [class.clickable]=\"!!$config()?.defaultAction\" *matRowDef=\"let row; columns: $displayedColumns()\"\r\n (click)=\"onRowClick(row)\"></mat-row>\r\n</mat-table>\r\n<mat-paginator [pageIndex]=\"$pageIndex()\" [length]=\"$gridData()?.count\" [pageSize]=\"$pageSize()\"\r\n (page)=\"pageChange($event)\" aria-label=\"Select page\"></mat-paginator>", styles: ["mat-row.clickable:hover{background:#f5f5f5;cursor:pointer}.select{max-width:80px}\n"], dependencies: [{ kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i2$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i3$1.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i3$1.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i3$1.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i3$1.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i3$1.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i3$1.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i3$1.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i3$1.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i3$1.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i3$1.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: MatToolbarModule }, { kind: "component", type: i1.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i5.MatAnchor, selector: "a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i5.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i5.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i6.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i9.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: MatSortModule }, { kind: "directive", type: i10.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i10.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i11.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
497
+ }
498
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: GridComponent, decorators: [{
499
+ type: Component,
500
+ args: [{ selector: 'x-grid', imports: [MatInputModule, MatTableModule, MatToolbarModule, MatButtonModule,
501
+ MatCheckboxModule, MatTooltipModule, MatIconModule, RouterModule,
502
+ MatSortModule, MatPaginatorModule, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "<mat-toolbar class=\"flex flex-row gap-2 p-2\">\r\n @if($hasSearch()){\r\n <div class=\"h-full\">\r\n <mat-form-field>\r\n <mat-label>Search</mat-label>\r\n <mat-icon matPrefix>search</mat-icon>\r\n <input matInput type=\"text\" [value]=\"$filter()\" (keyup)=\"filterKeyUp($event)\">\r\n @if ($filter()) {\r\n <button matSuffix mat-icon-button aria-label=\"Clear\" (click)=\"setFilter('')\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n }\r\n </mat-form-field>\r\n </div>\r\n }\r\n <ng-content select=\"[toolbar]\"></ng-content>\r\n @for(button of $buttons(); track button.name){\r\n <button mat-button [routerLink]=\"button.routerLink?button.routerLink():undefined\" [matTooltip]=\"button.text\"\r\n (click)=\"onAction($event,undefined,button)\"><mat-icon>{{button.icon}}</mat-icon> {{button.text}}</button>\r\n }\r\n @if ($config()?.new){\r\n <a mat-button routerLink=\"../new\"><mat-icon>add</mat-icon> New</a>\r\n }\r\n @if($config()?.refresh)\r\n {\r\n <button mat-button (click)=\"refresh()\"><mat-icon>sync</mat-icon> Refresh</button>\r\n }\r\n @if($bulk()){\r\n <button mat-button [disabled]=\"!$selectedCount()\" (click)=\"deleteSelected()\"><mat-icon>delete</mat-icon> Delete</button>\r\n }\r\n <span class=\"flex-grow\"></span>\r\n @if ($selectedCount() || $allSelected()){\r\n <span class=\"text-sm\"> {{$selectedCount()??0}} items selected</span>\r\n }\r\n</mat-toolbar>\r\n<mat-table [dataSource]=\"$dataSource()\" matSort (matSortChange)=\"sortChange($event)\"\r\n [matSortActive]=\"$sort()\" [matSortDirection]=\"$dir()\" matSortDisableClear>\r\n @if ($bulk()){\r\n <ng-container matColumnDef=\"select\">\r\n <mat-header-cell *matHeaderCellDef class=\"select\" matTooltip=\"Select all\">\r\n <mat-checkbox (change)=\"$event ? toggleAll() : null\" [checked]=\"!selection.hasValue() && $allSelected()\"\r\n [indeterminate]=\"selection.hasValue() && !$allSelected()\">\r\n </mat-checkbox>\r\n </mat-header-cell>\r\n <mat-cell *matCellDef=\"let row\" class=\"select\">\r\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"toggleOne($event, row)\"\r\n [checked]=\"selection.isSelected(row) || $allSelected() && !selection.hasValue()\">\r\n </mat-checkbox>\r\n </mat-cell>\r\n </ng-container>\r\n }\r\n @for(column of $columns(); track column.name){\r\n <ng-container [matColumnDef]=\"column.name\">\r\n @if (column.sort){\r\n <mat-header-cell [style]=\"getStyle(column)\" *matHeaderCellDef\r\n mat-sort-header>{{column.header}}</mat-header-cell>\r\n } @else {\r\n <mat-header-cell [style]=\"getStyle(column)\" *matHeaderCellDef>{{column.header}}</mat-header-cell>\r\n }\r\n <mat-cell [style]=\"getStyle(column)\" *matCellDef=\"let row\">\r\n @if(column.href || column.routerLink){\r\n <a [routerLink]=\"column.routerLink?column.routerLink(row):undefined\"\r\n [attr.href]=\"column.href?column.href(row):undefined\"\r\n (click)=\"column.action?column.action(row):undefined\">\r\n {{ display(column,row) }}\r\n </a>\r\n } @else if (getDisplayRef(column)) {\r\n <ng-container *ngTemplateOutlet=\"getDisplayRef(column); context: { $implicit: row}\"></ng-container>\r\n } @else {\r\n {{ display(column,row)}}\r\n }\r\n </mat-cell>\r\n </ng-container>\r\n }\r\n @if($hasActions()){\r\n <ng-container matColumnDef=\"actions\">\r\n <mat-header-cell *matHeaderCellDef>Actions</mat-header-cell>\r\n <mat-cell *matCellDef=\"let row\">\r\n @for(action of $actions(); track action.name){\r\n <button type=\"button\" mat-icon-button [disabled]=\"action.disabled?action.disabled(row):undefined\"\r\n [matTooltip]=\"action.text\" (click)=\"onAction($event, row, action)\"\r\n [queryParams]=\"action.queryParams?action.queryParams(row):undefined\"\r\n [routerLink]=\"action.routerLink?action.routerLink(row):undefined\">\r\n <mat-icon>{{action.icon}}</mat-icon>\r\n </button>\r\n }\r\n </mat-cell>\r\n </ng-container>\r\n }\r\n <mat-header-row *matHeaderRowDef=\"$displayedColumns()\"></mat-header-row>\r\n <mat-row [class.clickable]=\"!!$config()?.defaultAction\" *matRowDef=\"let row; columns: $displayedColumns()\"\r\n (click)=\"onRowClick(row)\"></mat-row>\r\n</mat-table>\r\n<mat-paginator [pageIndex]=\"$pageIndex()\" [length]=\"$gridData()?.count\" [pageSize]=\"$pageSize()\"\r\n (page)=\"pageChange($event)\" aria-label=\"Select page\"></mat-paginator>", styles: ["mat-row.clickable:hover{background:#f5f5f5;cursor:pointer}.select{max-width:80px}\n"] }]
503
+ }], ctorParameters: () => [], propDecorators: { config: [{
504
+ type: Input
505
+ }] } });
506
+
507
+ const RouterActions = createActionGroup({
508
+ source: 'Router',
509
+ events: {
510
+ 'Set Query Params': props()
511
+ }
512
+ });
513
+
514
+ class RouterEffects {
515
+ store = inject(Store);
516
+ actions$ = inject(Actions);
517
+ router = inject(Router);
518
+ $set = createEffect(() => this.actions$.pipe(ofType(RouterActions.setQueryParams), concatLatestFrom(() => this.store.select(selectQueryParams)), tap(([{ queryParams }, params]) => {
519
+ this.router.navigate([], { queryParams: Object.assign({ ...params }, queryParams) });
520
+ })), { dispatch: false });
521
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: RouterEffects, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
522
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: RouterEffects });
523
+ }
524
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: RouterEffects, decorators: [{
525
+ type: Injectable
526
+ }] });
527
+
528
+ class StateRouterModule {
529
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: StateRouterModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
530
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.1.4", ngImport: i0, type: StateRouterModule, imports: [CommonModule] });
531
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: StateRouterModule, providers: [
532
+ provideEffects(RouterEffects)
533
+ ], imports: [CommonModule] });
534
+ }
535
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: StateRouterModule, decorators: [{
536
+ type: NgModule,
537
+ args: [{
538
+ declarations: [],
539
+ imports: [
540
+ CommonModule
541
+ ],
542
+ providers: [
543
+ provideEffects(RouterEffects)
544
+ ]
545
+ }]
546
+ }] });
547
+
548
+ class GridEffects {
549
+ snack = inject(SnackService);
550
+ client = inject(HttpClient);
551
+ store = inject(Store);
552
+ actions$ = inject(Actions);
553
+ confirmation = inject(ConfirmationService);
554
+ changePaging$ = createEffect(() => {
555
+ return this.actions$.pipe(ofType(GridActions.changePaging), concatLatestFrom(() => this.store.select(selectDataRequest)), map$1(([{ pageIndex, pageSize }, req]) => GridActions.updateRequest({ request: { ...req, paging: { page: pageIndex + 1, pageSize } } })));
556
+ });
557
+ changeSort$ = createEffect(() => {
558
+ return this.actions$.pipe(ofType(GridActions.changeSort), concatLatestFrom(() => this.store.select(selectDataRequest)), map$1(([{ sort, dir }, req]) => GridActions.updateRequest({ request: { ...req, sortBy: sort, sortDir: dir == "asc" ? SortDir.Asc : SortDir.Desc } })));
559
+ });
560
+ updateRequest$ = createEffect(() => {
561
+ return this.actions$.pipe(ofType(GridActions.updateRequest), concatLatestFrom(_ => [
562
+ this.store.select(selectUrl),
563
+ this.store.select(selectUrlWithoutQuery),
564
+ this.store.select(selectQueryParam('base-filter'))
565
+ ]), mergeMap(([{ request }, oldUrl, urlWithoutQuery, filter]) => {
566
+ let url = `${urlWithoutQuery}?page=${request.paging?.page}&size=${request.paging?.pageSize}&sort-by=${request.sortBy ?? ''}&sort-dir=${request.sortDir == SortDir.Desc ? 'desc' : 'asc'}&filter=${request.filters ? btoa(JSON.stringify(request.filters)) : ''}&base-filter=${filter ?? ''}`;
567
+ return oldUrl == url
568
+ ? []
569
+ : [SharedActions.navigate({ url })];
570
+ }));
571
+ });
572
+ loadFromUrl$ = createEffect(() => {
573
+ return this.actions$.pipe(ofType(ROUTER_NAVIGATION), concatLatestFrom(() => [
574
+ this.store.select(selectIsGrid)
575
+ ]), filter$1(([_, isGrid]) => !!isGrid), map$1(() => GridActions.refresh()));
576
+ });
577
+ changeFilter$ = createEffect(() => {
578
+ return this.actions$.pipe(ofType(GridActions.changeFilter), concatLatestFrom(() => [
579
+ this.store.select(selectDataRequest),
580
+ this.store.select(selectSearchFields)
581
+ ]), map$1(([{ filter }, req, fields]) => GridActions.updateRequest({
582
+ request: {
583
+ ...req, filters: filter
584
+ ? { logic: FilterLogic.And, fields: [{ names: fields, operator: FilterOperator.Contains, values: [filter] }] }
585
+ : undefined
586
+ }
587
+ })));
588
+ });
589
+ goTo$ = createEffect(() => {
590
+ return this.actions$.pipe(ofType(GridActions.goTo), map$1(({ url, filter }) => SharedActions.navigate({ url: `${url}?base-filter=${filter ? btoa(JSON.stringify(filter)) : ''}` })));
591
+ });
592
+ loadData$ = createEffect(() => {
593
+ return this.actions$.pipe(ofType(GridActions.load), concatLatestFrom(() => [
594
+ this.store.select(selectDataUrl),
595
+ this.store.select(selectDataRequest)
596
+ ]), concatMap(([{ type, name, request }, dataUrl, requestUrl]) => this.client.post(dataUrl, request ?? requestUrl).pipe(map$1(data => GridActions.loadSuccess({ name, ...data })), catchError$1(error => of(SharedActions.badError({ source: type, error }))))));
597
+ });
598
+ bulkDelete$ = createEffect(() => {
599
+ return this.actions$.pipe(ofType(GridActions.bulkDelete), concatLatestFrom(() => [
600
+ this.store.select(selectGridName),
601
+ this.store.select(selectDataUrl),
602
+ this.store.select(selectDataRequest)
603
+ ]), concatLatestFrom(([, name]) => this.store.select(selectTotalCount(name))), mergeMap(([[{ type, ids }, name, url, request], totalCount]) => this.confirmation.confirm(`Are you sure you want to delete ${ids?.length ? ids.length : totalCount} items?`, 'Delete').pipe(filter$1(c => c), concatMap(_ => {
604
+ let headers = new HttpHeaders({ 'Content-Type': 'application/json' });
605
+ let body = {
606
+ ...request,
607
+ paging: undefined,
608
+ sortBy: undefined,
609
+ sortDir: undefined,
610
+ filters: ids?.length ? {
611
+ logic: FilterLogic.And,
612
+ fields: [{
613
+ names: ['id'], operator: FilterOperator.In, values: ids.map(id => id.toString())
614
+ }]
615
+ } : request.filters
616
+ };
617
+ return this.client.delete(url, { headers, body }).pipe(map$1(() => GridActions.bulkDeleteSuccess()), catchError$1(error => of(SharedActions.badError({ source: type, error }))));
618
+ }))));
619
+ });
620
+ refresh$ = createEffect(() => {
621
+ return this.actions$.pipe(ofType(GridActions.refresh), concatLatestFrom(() => this.store.select(selectGridName)), map$1(([_, name]) => GridActions.load({ name: name })));
622
+ });
623
+ bulkDeleteSuccess$ = createEffect(() => {
624
+ return this.actions$.pipe(ofType(GridActions.bulkDeleteSuccess), tap$1(() => this.snack.info('Deleted!')), map$1(() => GridActions.refresh()));
625
+ });
626
+ constructor() { }
627
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: GridEffects, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
628
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: GridEffects });
629
+ }
630
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: GridEffects, decorators: [{
631
+ type: Injectable
632
+ }], ctorParameters: () => [] });
633
+
634
+ class GridModule {
635
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: GridModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
636
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.1.4", ngImport: i0, type: GridModule, imports: [CommonModule] });
637
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: GridModule, providers: [
638
+ provideState(gridFeature),
639
+ provideEffects([GridEffects])
640
+ ], imports: [CommonModule] });
641
+ }
642
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: GridModule, decorators: [{
643
+ type: NgModule,
644
+ args: [{
645
+ declarations: [],
646
+ imports: [
647
+ CommonModule
648
+ ],
649
+ providers: [
650
+ provideState(gridFeature),
651
+ provideEffects([GridEffects])
652
+ ]
653
+ }]
654
+ }] });
655
+
656
+ const CrudActions = createActionGroup({
657
+ source: 'Crud',
658
+ events: {
659
+ 'Load All': props(),
660
+ 'Load All Success': props(),
661
+ 'Configure': props(),
662
+ 'Delete': props(),
663
+ 'Save': props(),
664
+ 'Save Success': props(),
665
+ 'Clear Saved': props(),
666
+ 'Load': props(),
667
+ 'Load Success': props()
668
+ }
669
+ });
670
+
671
+ const crudFeatureKey = 'crud';
672
+ const initialState = {
673
+ urlPrefix: '/api',
674
+ map: {}
675
+ };
676
+ const reducer = createReducer(initialState, on(CrudActions.load, CrudActions.clearSaved, (state, { name }) => ({ ...state, map: { ...state.map, [name]: { ...state.map[name], value: undefined } } })), on(CrudActions.configure, (state, { name, param }) => ({ ...state, map: { ...state.map, [name]: { ...state.map[name], param } } })), on(CrudActions.loadSuccess, (state, { name, value }) => ({ ...state, map: { ...state.map, [name]: { ...state.map[name], value } } })), on(CrudActions.saveSuccess, (state, { name, value }) => ({ ...state, map: { ...state.map, [name]: { ...state.map[name], value } } })), on(CrudActions.loadAllSuccess, (state, { name, all }) => ({ ...state, map: { ...state.map, [name]: { ...state.map[name], all } } })));
677
+ const crudFeature = createFeature({
678
+ name: crudFeatureKey,
679
+ reducer,
680
+ });
681
+
682
+ const selectParamName = (name) => createSelector(crudFeature.selectMap, map => map[name]?.param);
683
+ const selectValue = (name) => createSelector(crudFeature.selectMap, map => map ? map[name]?.value : undefined);
684
+ const selectAll = (name) => createSelector(crudFeature.selectMap, map => map ? map[name]?.all : undefined);
685
+
686
+ class CrudEffects {
687
+ confirmation = inject(ConfirmationService);
688
+ snack = inject(SnackService);
689
+ store = inject(Store);
690
+ actions$ = inject(Actions);
691
+ client = inject(HttpClient);
692
+ location = inject(Location);
693
+ load$ = createEffect(() => {
694
+ return this.actions$.pipe(ofType(CrudActions.load), concatLatestFrom(({ name }) => this.store.select(selectParamName(name))), concatLatestFrom(([_, param]) => [
695
+ this.store.select(crudFeature.selectUrlPrefix),
696
+ this.store.select(selectRouteParam(param)),
697
+ ]), concatMap(([[{ type, name }], prefix, id]) => id ? this.client.get(`${prefix}/${name}/${id}`).pipe(map$1(value => CrudActions.loadSuccess({ name, value })), catchError$1(error => of(SharedActions.badError({ source: type, error }))))
698
+ : of(CrudActions.loadSuccess({ name, value: undefined }))));
699
+ });
700
+ loadAll$ = createEffect(() => {
701
+ return this.actions$.pipe(ofType(CrudActions.loadAll), concatLatestFrom(() => [
702
+ this.store.select(crudFeature.selectUrlPrefix)
703
+ ]), concatMap(([{ type, name }, prefix]) => this.client.get(`${prefix}/${name}/all`).pipe(map$1(all => CrudActions.loadAllSuccess({ name, all })), catchError$1(error => of(SharedActions.badError({ source: type, error }))))));
704
+ });
705
+ save$ = createEffect(() => {
706
+ return this.actions$.pipe(ofType(CrudActions.save), concatLatestFrom(() => [
707
+ this.store.select(crudFeature.selectUrlPrefix)
708
+ ]), mergeMap(([{ type, name, value, stay }, prefix]) => (value.id
709
+ ? this.client.put(`${prefix}/${name}/${value.id}`, value)
710
+ : this.client.post(`${prefix}/${name}`, value))
711
+ .pipe(map$1(value => CrudActions.saveSuccess({ name, value, stay })), catchError$1(error => of(SharedActions.badError({ source: type, error }))))));
712
+ });
713
+ saveSuccess$ = createEffect(() => {
714
+ return this.actions$.pipe(ofType(CrudActions.saveSuccess), map$1(({ stay }) => {
715
+ this.snack.info('Saved!');
716
+ if (!stay)
717
+ this.location.back();
718
+ }));
719
+ }, { dispatch: false });
720
+ delete$ = createEffect(() => {
721
+ return this.actions$.pipe(ofType(CrudActions.delete), concatLatestFrom(() => [
722
+ this.store.select(crudFeature.selectUrlPrefix)
723
+ ]), concatMap(([{ type, name, value }, prefix]) => {
724
+ let nameStr = value.name ?? `the ${name.toLowerCase()}`;
725
+ return this.confirmation.confirm(`Are you sure you want to delete ${nameStr}?`, 'Delete').pipe(filter$1(confirmed => confirmed), mergeMap(() => this.client.delete(`${prefix}/${name}/${value.id}`).pipe(map$1(() => GridActions.refresh()), tap$1(() => this.snack.info('Deleted!')), catchError$1(error => of(SharedActions.badError({ source: type, error }))))));
726
+ }));
727
+ });
728
+ constructor() { }
729
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: CrudEffects, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
730
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: CrudEffects });
731
+ }
732
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: CrudEffects, decorators: [{
733
+ type: Injectable
734
+ }], ctorParameters: () => [] });
735
+
736
+ class CrudModule {
737
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: CrudModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
738
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.1.4", ngImport: i0, type: CrudModule, imports: [CommonModule] });
739
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: CrudModule, providers: [
740
+ provideState(crudFeature),
741
+ provideEffects(CrudEffects)
742
+ ], imports: [CommonModule] });
743
+ }
744
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: CrudModule, decorators: [{
745
+ type: NgModule,
746
+ args: [{
747
+ declarations: [],
748
+ imports: [
749
+ CommonModule
750
+ ],
751
+ providers: [
752
+ provideState(crudFeature),
753
+ provideEffects(CrudEffects)
754
+ ]
755
+ }]
756
+ }] });
757
+
758
+ /*
759
+ * Public API Surface of the library
760
+ */
761
+
762
+ /**
763
+ * Generated bundle index. Do not edit.
764
+ */
765
+
766
+ export { ConfirmationDialogComponent, ConfirmationService, CrudActions, CrudModule, DetailActionsComponent, EmailComponent, GridActions, GridComponent, GridModule, RouterActions, SnackService, StateRouterModule, crudFeature, gridFeature, loadingInterceptor, selectAll, selectDataParam, selectDataRequest, selectDataUrl, selectFilterText, selectGridData, selectGridFilters, selectGridName, selectGridSetup, selectIsGrid, selectPageIndex, selectPageSize, selectParamName, selectQueryParam, selectQueryParams, selectRouteParam, selectRouteParams, selectRouter, selectRouterState, selectSearchFields, selectSiteSlugParam, selectSortBy, selectSortDir, selectTotalCount, selectUrl, selectUrlSegments, selectUrlWithoutQuery, selectValue };
767
+ //# sourceMappingURL=axioma-material.mjs.map