@praxisui/crud 10.0.0-rc.4 → 10.0.0-rc.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ai/component-registry.json +2 -2
- package/fesm2022/praxisui-crud.mjs +1211 -36
- package/package.json +7 -7
- package/types/praxisui-crud.d.ts +271 -26
|
@@ -1,31 +1,36 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import {
|
|
2
|
+
import { EventEmitter, inject, ChangeDetectorRef, DestroyRef, Output, Input, ChangeDetectionStrategy, Component, Injectable, InjectionToken, input, signal, computed, effect, output, Injector, booleanAttribute, ViewChild, Optional, Inject, ViewEncapsulation, ENVIRONMENT_INITIALIZER } from '@angular/core';
|
|
3
3
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
4
4
|
import { HttpClient } from '@angular/common/http';
|
|
5
5
|
import { Router, ActivatedRoute, RouterLink } from '@angular/router';
|
|
6
6
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
|
7
7
|
import { firstValueFrom, BehaviorSubject, Subscription } from 'rxjs';
|
|
8
|
+
import { take, filter } from 'rxjs/operators';
|
|
8
9
|
import * as i2$1 from '@praxisui/core';
|
|
9
|
-
import { ASYNC_CONFIG_STORAGE, GlobalConfigService, CrudOperationResolutionService, LoggerService, SurfaceNavigationError, fillUndefined, SETTINGS_PANEL_DATA, PraxisI18nService, PraxisIconDirective, providePraxisI18nConfig, createDefaultTableConfig, EnterpriseRuntimeContextService, GLOBAL_SURFACE_SERVICE, SurfaceOutletRegistryService, ComponentKeyService, ResourceDiscoveryService, ResourceActionOpenAdapterService, ResourceSurfaceOpenAdapterService, normalizeSurfaceOperationContext, translateUnavailableWorkflowMessage, isSurfaceNavigationError, translateSurfaceNavigationRejected, normalizeUnknownError, EmptyStateCardComponent, RESOURCE_DISCOVERY_I18N_CONFIG, SURFACE_DRAWER_REF, SURFACE_DRAWER_CONTENT_DATA, PraxisIconButtonComponent, PraxisResourceIdentityComponent, GenericCrudService, ComponentMetadataRegistry } from '@praxisui/core';
|
|
10
|
+
import { SafeExpressionEvaluator, ASYNC_CONFIG_STORAGE, GlobalConfigService, CrudOperationResolutionService, LoggerService, SurfaceNavigationError, fillUndefined, SETTINGS_PANEL_DATA, PraxisI18nService, PraxisIconDirective, providePraxisI18nConfig, createDefaultTableConfig, PraxisWidgetEventBus, EnterpriseRuntimeContextService, GLOBAL_SURFACE_SERVICE, SurfaceOutletRegistryService, ComponentKeyService, ResourceDiscoveryService, ResourceActionOpenAdapterService, ResourceSurfaceOpenAdapterService, normalizeSurfaceOperationContext, translateUnavailableWorkflowMessage, isSurfaceNavigationError, translateSurfaceNavigationRejected, normalizeUnknownError, EmptyStateCardComponent, RESOURCE_DISCOVERY_I18N_CONFIG, SURFACE_DRAWER_REF, SURFACE_DRAWER_CONTENT_DATA, PraxisIconButtonComponent, PraxisResourceIdentityComponent, GenericCrudService, ComponentMetadataRegistry } from '@praxisui/core';
|
|
11
|
+
export { createDynamicRecord, extractRecordId, isDynamicDataRecord, resolveDataField } from '@praxisui/core';
|
|
10
12
|
import { SettingsPanelService } from '@praxisui/settings-panel';
|
|
11
|
-
import { PraxisTableInlineAuthoringEditorComponent, PraxisTable } from '@praxisui/table';
|
|
13
|
+
import { PraxisTableInlineAuthoringEditorComponent, PraxisTable, PraxisScopeBarComponent } from '@praxisui/table';
|
|
12
14
|
import { ConfirmDialogComponent } from '@praxisui/dynamic-fields';
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
+
import * as i1 from '@angular/common';
|
|
16
|
+
import { CommonModule } from '@angular/common';
|
|
17
|
+
import * as i2 from '@angular/material/icon';
|
|
18
|
+
import { MatIconModule } from '@angular/material/icon';
|
|
19
|
+
import * as i3 from '@angular/material/button';
|
|
20
|
+
import { MatButtonModule } from '@angular/material/button';
|
|
21
|
+
import * as i4 from '@angular/material/tooltip';
|
|
22
|
+
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
23
|
+
import * as i1$1 from '@angular/material/dialog';
|
|
15
24
|
import { MatDialogRef, MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
|
|
16
25
|
export { MAT_DIALOG_DATA as DIALOG_DATA } from '@angular/material/dialog';
|
|
17
|
-
import * as i1$
|
|
26
|
+
import * as i1$2 from '@angular/forms';
|
|
18
27
|
import { FormsModule } from '@angular/forms';
|
|
19
|
-
import * as
|
|
20
|
-
import { MatButtonModule } from '@angular/material/button';
|
|
21
|
-
import * as i3 from '@angular/material/card';
|
|
28
|
+
import * as i3$1 from '@angular/material/card';
|
|
22
29
|
import { MatCardModule } from '@angular/material/card';
|
|
23
|
-
import * as i4 from '@angular/material/expansion';
|
|
30
|
+
import * as i4$1 from '@angular/material/expansion';
|
|
24
31
|
import { MatExpansionModule } from '@angular/material/expansion';
|
|
25
32
|
import * as i5 from '@angular/material/form-field';
|
|
26
33
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
27
|
-
import * as i6 from '@angular/material/icon';
|
|
28
|
-
import { MatIconModule } from '@angular/material/icon';
|
|
29
34
|
import * as i7 from '@angular/material/input';
|
|
30
35
|
import { MatInputModule } from '@angular/material/input';
|
|
31
36
|
import * as i8 from '@angular/material/select';
|
|
@@ -36,6 +41,382 @@ import * as i10 from '@angular/material/tabs';
|
|
|
36
41
|
import { MatTabsModule } from '@angular/material/tabs';
|
|
37
42
|
import { PraxisDynamicForm } from '@praxisui/dynamic-form';
|
|
38
43
|
|
|
44
|
+
function formatKpiValue(value, format) {
|
|
45
|
+
if (value === null || value === undefined || value === '') {
|
|
46
|
+
return '—';
|
|
47
|
+
}
|
|
48
|
+
const num = Number(value);
|
|
49
|
+
const isNum = !isNaN(num) && typeof value !== 'boolean';
|
|
50
|
+
if (format === 'currency:compactBRL' || format === 'compactBRL') {
|
|
51
|
+
if (!isNum)
|
|
52
|
+
return String(value);
|
|
53
|
+
const sign = num < 0 ? '-' : '';
|
|
54
|
+
const abs = Math.abs(num);
|
|
55
|
+
if (abs >= 1_000_000_000) {
|
|
56
|
+
return `${sign}R$ ${(abs / 1_000_000_000).toLocaleString('pt-BR', { minimumFractionDigits: 0, maximumFractionDigits: 2 })}B`;
|
|
57
|
+
}
|
|
58
|
+
if (abs >= 1_000_000) {
|
|
59
|
+
return `${sign}R$ ${(abs / 1_000_000).toLocaleString('pt-BR', { minimumFractionDigits: 0, maximumFractionDigits: 2 })}M`;
|
|
60
|
+
}
|
|
61
|
+
if (abs >= 1_000) {
|
|
62
|
+
return `${sign}R$ ${(abs / 1_000).toLocaleString('pt-BR', { minimumFractionDigits: 0, maximumFractionDigits: 1 })}K`;
|
|
63
|
+
}
|
|
64
|
+
return new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }).format(num);
|
|
65
|
+
}
|
|
66
|
+
if (format === 'currency:BRL' || format === 'currency') {
|
|
67
|
+
if (!isNum)
|
|
68
|
+
return String(value);
|
|
69
|
+
return new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }).format(num);
|
|
70
|
+
}
|
|
71
|
+
if (format === 'percent' || format === 'percentage') {
|
|
72
|
+
if (!isNum)
|
|
73
|
+
return String(value);
|
|
74
|
+
return `${num}%`;
|
|
75
|
+
}
|
|
76
|
+
if (format === 'number:compact' || format === 'compact') {
|
|
77
|
+
if (!isNum)
|
|
78
|
+
return String(value);
|
|
79
|
+
const sign = num < 0 ? '-' : '';
|
|
80
|
+
const abs = Math.abs(num);
|
|
81
|
+
if (abs >= 1_000_000_000) {
|
|
82
|
+
return `${sign}${(abs / 1_000_000_000).toLocaleString('pt-BR', { minimumFractionDigits: 0, maximumFractionDigits: 2 })}B`;
|
|
83
|
+
}
|
|
84
|
+
if (abs >= 1_000_000) {
|
|
85
|
+
return `${sign}${(abs / 1_000_000).toLocaleString('pt-BR', { minimumFractionDigits: 0, maximumFractionDigits: 2 })}M`;
|
|
86
|
+
}
|
|
87
|
+
if (abs >= 1_000) {
|
|
88
|
+
return `${sign}${(abs / 1_000).toLocaleString('pt-BR', { minimumFractionDigits: 0, maximumFractionDigits: 1 })}K`;
|
|
89
|
+
}
|
|
90
|
+
return num.toLocaleString('pt-BR');
|
|
91
|
+
}
|
|
92
|
+
if (format === 'number') {
|
|
93
|
+
if (!isNum)
|
|
94
|
+
return String(value);
|
|
95
|
+
return num.toLocaleString('pt-BR');
|
|
96
|
+
}
|
|
97
|
+
return String(value);
|
|
98
|
+
}
|
|
99
|
+
class PraxisKpiBandComponent {
|
|
100
|
+
config;
|
|
101
|
+
dataContext;
|
|
102
|
+
/**
|
|
103
|
+
* Indica se o container hospedeiro (ex.: PraxisCrudComponent) possui ouvintes ativos
|
|
104
|
+
* para cliques em cards. Quando explicitamente falso, evita a falsa affordance de botões.
|
|
105
|
+
*/
|
|
106
|
+
isInteractiveHost;
|
|
107
|
+
cardClick = new EventEmitter();
|
|
108
|
+
statsLoaded = new EventEmitter();
|
|
109
|
+
statsError = new EventEmitter();
|
|
110
|
+
refreshClick = new EventEmitter();
|
|
111
|
+
http = inject(HttpClient);
|
|
112
|
+
cdr = inject(ChangeDetectorRef);
|
|
113
|
+
destroyRef = inject(DestroyRef);
|
|
114
|
+
evaluator = new SafeExpressionEvaluator({
|
|
115
|
+
maxLength: 500,
|
|
116
|
+
maxTokens: 150,
|
|
117
|
+
});
|
|
118
|
+
isLoading = false;
|
|
119
|
+
evaluatedCards = [];
|
|
120
|
+
fetchedData = {};
|
|
121
|
+
skeletonPlaceholders = [1, 2, 3, 4];
|
|
122
|
+
get isVisible() {
|
|
123
|
+
if (!this.config || this.config.enabled === false)
|
|
124
|
+
return false;
|
|
125
|
+
return !!(this.config.cards?.length || this.config.source || this.config.document);
|
|
126
|
+
}
|
|
127
|
+
get resolvedColumns() {
|
|
128
|
+
if (this.config?.columns && this.config.columns > 0) {
|
|
129
|
+
return String(this.config.columns);
|
|
130
|
+
}
|
|
131
|
+
return 'auto-fit';
|
|
132
|
+
}
|
|
133
|
+
get resolvedGap() {
|
|
134
|
+
const gap = this.config?.gap;
|
|
135
|
+
if (gap === 'sm')
|
|
136
|
+
return '0.5rem';
|
|
137
|
+
if (gap === 'md')
|
|
138
|
+
return '1rem';
|
|
139
|
+
if (gap === 'lg')
|
|
140
|
+
return '1.5rem';
|
|
141
|
+
return gap || '1rem';
|
|
142
|
+
}
|
|
143
|
+
ngOnInit() {
|
|
144
|
+
if (this.config?.cards?.length) {
|
|
145
|
+
this.skeletonPlaceholders = Array.from({ length: this.config.cards.length }, (_, i) => i + 1);
|
|
146
|
+
}
|
|
147
|
+
this.refresh();
|
|
148
|
+
}
|
|
149
|
+
ngOnChanges(changes) {
|
|
150
|
+
if (changes['config'] || changes['dataContext']) {
|
|
151
|
+
if (changes['config'] && this.config?.source !== changes['config'].previousValue?.source) {
|
|
152
|
+
this.refresh();
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
this.recomputeCards();
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
handleRefresh() {
|
|
160
|
+
this.refreshClick.emit();
|
|
161
|
+
this.refresh();
|
|
162
|
+
}
|
|
163
|
+
refresh() {
|
|
164
|
+
if (this.config?.source) {
|
|
165
|
+
this.fetchFromSource();
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
this.recomputeCards();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
fetchFromSource() {
|
|
172
|
+
const source = this.config?.source;
|
|
173
|
+
if (!source)
|
|
174
|
+
return;
|
|
175
|
+
this.isLoading = true;
|
|
176
|
+
this.cdr.markForCheck();
|
|
177
|
+
const method = this.config?.method || 'GET';
|
|
178
|
+
const request$ = method.toUpperCase() === 'POST'
|
|
179
|
+
? this.http.post(source, this.config?.payload || {})
|
|
180
|
+
: this.http.get(source);
|
|
181
|
+
request$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
|
|
182
|
+
next: (res) => {
|
|
183
|
+
const payload = res?.data ?? res ?? {};
|
|
184
|
+
this.fetchedData = typeof payload === 'object' ? payload : { value: payload };
|
|
185
|
+
this.isLoading = false;
|
|
186
|
+
this.statsLoaded.emit(this.fetchedData);
|
|
187
|
+
this.recomputeCards();
|
|
188
|
+
this.cdr.markForCheck();
|
|
189
|
+
},
|
|
190
|
+
error: (err) => {
|
|
191
|
+
this.isLoading = false;
|
|
192
|
+
this.statsError.emit(err);
|
|
193
|
+
this.recomputeCards();
|
|
194
|
+
this.cdr.markForCheck();
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
recomputeCards() {
|
|
199
|
+
const cards = this.config?.cards;
|
|
200
|
+
if (!cards || !Array.isArray(cards) || cards.length === 0) {
|
|
201
|
+
this.evaluatedCards = [];
|
|
202
|
+
this.cdr.markForCheck();
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
const context = {
|
|
206
|
+
...(this.dataContext || {}),
|
|
207
|
+
...(this.fetchedData || {}),
|
|
208
|
+
stats: this.fetchedData,
|
|
209
|
+
data: this.fetchedData,
|
|
210
|
+
};
|
|
211
|
+
const isObserved = this.isInteractiveHost !== undefined ? this.isInteractiveHost : this.cardClick.observed;
|
|
212
|
+
this.evaluatedCards = cards.map((card) => {
|
|
213
|
+
let rawValue = card.value;
|
|
214
|
+
if (card.valueExpr) {
|
|
215
|
+
const res = this.evaluator.evaluate(card.valueExpr, context);
|
|
216
|
+
if (!res.error && res.value !== undefined) {
|
|
217
|
+
rawValue = res.value;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
let rawCaption = card.caption;
|
|
221
|
+
if (card.captionExpr) {
|
|
222
|
+
const res = this.evaluator.evaluate(card.captionExpr, context);
|
|
223
|
+
if (!res.error && res.value !== undefined) {
|
|
224
|
+
rawCaption = String(res.value);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
const displayValue = formatKpiValue(rawValue, card.format);
|
|
228
|
+
const interactive = card.interactive !== undefined
|
|
229
|
+
? card.interactive
|
|
230
|
+
: !!(card.action || card.filter || card.route || isObserved);
|
|
231
|
+
return {
|
|
232
|
+
raw: card,
|
|
233
|
+
id: card.id,
|
|
234
|
+
label: card.label,
|
|
235
|
+
displayValue,
|
|
236
|
+
displayCaption: rawCaption,
|
|
237
|
+
footnote: card.footnote,
|
|
238
|
+
icon: card.icon,
|
|
239
|
+
tone: card.tone || 'neutral',
|
|
240
|
+
interactive,
|
|
241
|
+
className: card.className,
|
|
242
|
+
tooltip: card.tooltip,
|
|
243
|
+
};
|
|
244
|
+
});
|
|
245
|
+
this.cdr.markForCheck();
|
|
246
|
+
}
|
|
247
|
+
onCardClick(card, index) {
|
|
248
|
+
if (!card.interactive)
|
|
249
|
+
return;
|
|
250
|
+
this.cardClick.emit({
|
|
251
|
+
card: card.raw,
|
|
252
|
+
index,
|
|
253
|
+
data: this.fetchedData,
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisKpiBandComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
257
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.14", type: PraxisKpiBandComponent, isStandalone: true, selector: "praxis-kpi-band", inputs: { config: "config", dataContext: "dataContext", isInteractiveHost: "isInteractiveHost" }, outputs: { cardClick: "cardClick", statsLoaded: "statsLoaded", statsError: "statsError", refreshClick: "refreshClick" }, usesOnChanges: true, ngImport: i0, template: `
|
|
258
|
+
<div
|
|
259
|
+
*ngIf="isVisible"
|
|
260
|
+
class="praxis-kpi-band"
|
|
261
|
+
[class]="config?.className || ''"
|
|
262
|
+
[style.--praxis-kpi-columns]="resolvedColumns"
|
|
263
|
+
[style.--praxis-kpi-gap]="resolvedGap"
|
|
264
|
+
>
|
|
265
|
+
<div *ngIf="config?.title || config?.showRefresh" class="praxis-kpi-band-header">
|
|
266
|
+
<div class="praxis-kpi-band-title-group">
|
|
267
|
+
<h3 *ngIf="config?.title" class="praxis-kpi-band-title">{{ config?.title }}</h3>
|
|
268
|
+
<p *ngIf="config?.subtitle" class="praxis-kpi-band-subtitle">{{ config?.subtitle }}</p>
|
|
269
|
+
</div>
|
|
270
|
+
<div *ngIf="config?.showRefresh" class="praxis-kpi-band-actions">
|
|
271
|
+
<button
|
|
272
|
+
mat-icon-button
|
|
273
|
+
type="button"
|
|
274
|
+
class="praxis-kpi-refresh-button"
|
|
275
|
+
(click)="handleRefresh()"
|
|
276
|
+
matTooltip="Atualizar indicadores"
|
|
277
|
+
>
|
|
278
|
+
<mat-icon>refresh</mat-icon>
|
|
279
|
+
</button>
|
|
280
|
+
</div>
|
|
281
|
+
</div>
|
|
282
|
+
|
|
283
|
+
<div class="praxis-kpi-band-grid">
|
|
284
|
+
<ng-container *ngIf="isLoading; else cardsTpl">
|
|
285
|
+
<div
|
|
286
|
+
*ngFor="let placeholder of skeletonPlaceholders"
|
|
287
|
+
class="praxis-kpi-card praxis-kpi-card-skeleton"
|
|
288
|
+
>
|
|
289
|
+
<div class="praxis-kpi-skeleton-line label"></div>
|
|
290
|
+
<div class="praxis-kpi-skeleton-line value"></div>
|
|
291
|
+
<div class="praxis-kpi-skeleton-line caption"></div>
|
|
292
|
+
</div>
|
|
293
|
+
</ng-container>
|
|
294
|
+
|
|
295
|
+
<ng-template #cardsTpl>
|
|
296
|
+
<div
|
|
297
|
+
*ngFor="let card of evaluatedCards; let i = index"
|
|
298
|
+
class="praxis-kpi-card"
|
|
299
|
+
[class.interactive]="card.interactive"
|
|
300
|
+
[ngClass]="[card.tone ? 'tone-' + card.tone : 'tone-neutral', card.className || '']"
|
|
301
|
+
[attr.role]="card.interactive ? 'button' : null"
|
|
302
|
+
[attr.tabindex]="card.interactive ? 0 : null"
|
|
303
|
+
[matTooltip]="card.tooltip || ''"
|
|
304
|
+
(click)="onCardClick(card, i)"
|
|
305
|
+
(keydown.enter)="onCardClick(card, i)"
|
|
306
|
+
(keydown.space)="$event.preventDefault(); onCardClick(card, i)"
|
|
307
|
+
>
|
|
308
|
+
<div class="praxis-kpi-card-top">
|
|
309
|
+
<span class="praxis-kpi-card-label">{{ card.label }}</span>
|
|
310
|
+
<div *ngIf="card.icon" class="praxis-kpi-card-icon">
|
|
311
|
+
<mat-icon>{{ card.icon }}</mat-icon>
|
|
312
|
+
</div>
|
|
313
|
+
</div>
|
|
314
|
+
|
|
315
|
+
<div class="praxis-kpi-card-value">{{ card.displayValue }}</div>
|
|
316
|
+
|
|
317
|
+
<div *ngIf="card.displayCaption" class="praxis-kpi-card-caption">
|
|
318
|
+
{{ card.displayCaption }}
|
|
319
|
+
</div>
|
|
320
|
+
|
|
321
|
+
<div *ngIf="card.footnote" class="praxis-kpi-card-footnote">
|
|
322
|
+
{{ card.footnote }}
|
|
323
|
+
</div>
|
|
324
|
+
</div>
|
|
325
|
+
</ng-template>
|
|
326
|
+
</div>
|
|
327
|
+
</div>
|
|
328
|
+
`, isInline: true, styles: [".praxis-kpi-band{display:flex;flex-direction:column;gap:.75rem;margin-bottom:1.25rem;width:100%;box-sizing:border-box}.praxis-kpi-band-header{display:flex;align-items:center;justify-content:space-between;gap:1rem}.praxis-kpi-band-title{margin:0;font-size:1rem;font-weight:600;color:var(--praxis-text-primary, #0f172a)}.praxis-kpi-band-subtitle{margin:.125rem 0 0;font-size:.8125rem;color:var(--praxis-text-muted, #64748b)}.praxis-kpi-band-grid{display:grid;grid-template-columns:repeat(var(--praxis-kpi-columns, auto-fit),minmax(200px,1fr));gap:var(--praxis-kpi-gap, 1rem);width:100%}.praxis-kpi-card{display:flex;flex-direction:column;justify-content:space-between;padding:1rem 1.25rem;border-radius:.75rem;background:var(--praxis-surface-card, #ffffff);border:1px solid var(--praxis-border-subtle, #e2e8f0);box-shadow:0 1px 3px #0000000a;transition:transform .15s ease,box-shadow .15s ease,border-color .15s ease;position:relative;overflow:hidden;min-height:5.5rem;box-sizing:border-box}.praxis-kpi-card.interactive{cursor:pointer}.praxis-kpi-card.interactive:hover{transform:translateY(-2px);box-shadow:0 4px 12px #00000014}.praxis-kpi-card.interactive:focus-visible{outline:2px solid var(--praxis-primary, #0284c7);outline-offset:2px}.praxis-kpi-card-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:.5rem}.praxis-kpi-card-label{font-size:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--praxis-text-muted, #64748b)}.praxis-kpi-card-icon{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;border-radius:.5rem}.praxis-kpi-card-icon mat-icon{font-size:1.25rem;width:1.25rem;height:1.25rem}.praxis-kpi-card-value{font-size:1.625rem;font-weight:700;line-height:1.2;letter-spacing:-.02em;font-feature-settings:\"tnum\" on,\"lnum\" on;color:var(--praxis-text-primary, #0f172a)}.praxis-kpi-card-caption{font-size:.75rem;color:var(--praxis-text-muted, #64748b);margin-top:.375rem}.praxis-kpi-card-footnote{font-size:.7rem;color:var(--praxis-text-secondary, #94a3b8);margin-top:.25rem}.tone-info{border-left:4px solid var(--praxis-info, #0284c7)}.tone-info .praxis-kpi-card-icon{background:#f0f9ff;color:#0284c7}.tone-success{border-left:4px solid var(--praxis-success, #059669)}.tone-success .praxis-kpi-card-icon{background:#ecfdf5;color:#059669}.tone-warning{border-left:4px solid var(--praxis-warning, #d97706)}.tone-warning .praxis-kpi-card-icon{background:#fffbeb;color:#d97706}.tone-error,.tone-danger{border-left:4px solid var(--praxis-error, #dc2626)}.tone-error .praxis-kpi-card-icon,.tone-danger .praxis-kpi-card-icon{background:#fef2f2;color:#dc2626}.tone-neutral{border-left:4px solid var(--praxis-neutral, #94a3b8)}.tone-neutral .praxis-kpi-card-icon{background:#f8fafc;color:#64748b}.praxis-kpi-card-skeleton{pointer-events:none}.praxis-kpi-skeleton-line{background:linear-gradient(90deg,#f1f5f9 25%,#e2e8f0,#f1f5f9 75%);background-size:200% 100%;animation:praxis-shimmer 1.5s infinite;border-radius:.25rem}.praxis-kpi-skeleton-line.label{width:40%;height:.75rem;margin-bottom:.75rem}.praxis-kpi-skeleton-line.value{width:65%;height:1.5rem;margin-bottom:.5rem}.praxis-kpi-skeleton-line.caption{width:50%;height:.65rem}@keyframes praxis-shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { 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: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
329
|
+
}
|
|
330
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisKpiBandComponent, decorators: [{
|
|
331
|
+
type: Component,
|
|
332
|
+
args: [{ selector: 'praxis-kpi-band', standalone: true, imports: [CommonModule, MatIconModule, MatButtonModule, MatTooltipModule], template: `
|
|
333
|
+
<div
|
|
334
|
+
*ngIf="isVisible"
|
|
335
|
+
class="praxis-kpi-band"
|
|
336
|
+
[class]="config?.className || ''"
|
|
337
|
+
[style.--praxis-kpi-columns]="resolvedColumns"
|
|
338
|
+
[style.--praxis-kpi-gap]="resolvedGap"
|
|
339
|
+
>
|
|
340
|
+
<div *ngIf="config?.title || config?.showRefresh" class="praxis-kpi-band-header">
|
|
341
|
+
<div class="praxis-kpi-band-title-group">
|
|
342
|
+
<h3 *ngIf="config?.title" class="praxis-kpi-band-title">{{ config?.title }}</h3>
|
|
343
|
+
<p *ngIf="config?.subtitle" class="praxis-kpi-band-subtitle">{{ config?.subtitle }}</p>
|
|
344
|
+
</div>
|
|
345
|
+
<div *ngIf="config?.showRefresh" class="praxis-kpi-band-actions">
|
|
346
|
+
<button
|
|
347
|
+
mat-icon-button
|
|
348
|
+
type="button"
|
|
349
|
+
class="praxis-kpi-refresh-button"
|
|
350
|
+
(click)="handleRefresh()"
|
|
351
|
+
matTooltip="Atualizar indicadores"
|
|
352
|
+
>
|
|
353
|
+
<mat-icon>refresh</mat-icon>
|
|
354
|
+
</button>
|
|
355
|
+
</div>
|
|
356
|
+
</div>
|
|
357
|
+
|
|
358
|
+
<div class="praxis-kpi-band-grid">
|
|
359
|
+
<ng-container *ngIf="isLoading; else cardsTpl">
|
|
360
|
+
<div
|
|
361
|
+
*ngFor="let placeholder of skeletonPlaceholders"
|
|
362
|
+
class="praxis-kpi-card praxis-kpi-card-skeleton"
|
|
363
|
+
>
|
|
364
|
+
<div class="praxis-kpi-skeleton-line label"></div>
|
|
365
|
+
<div class="praxis-kpi-skeleton-line value"></div>
|
|
366
|
+
<div class="praxis-kpi-skeleton-line caption"></div>
|
|
367
|
+
</div>
|
|
368
|
+
</ng-container>
|
|
369
|
+
|
|
370
|
+
<ng-template #cardsTpl>
|
|
371
|
+
<div
|
|
372
|
+
*ngFor="let card of evaluatedCards; let i = index"
|
|
373
|
+
class="praxis-kpi-card"
|
|
374
|
+
[class.interactive]="card.interactive"
|
|
375
|
+
[ngClass]="[card.tone ? 'tone-' + card.tone : 'tone-neutral', card.className || '']"
|
|
376
|
+
[attr.role]="card.interactive ? 'button' : null"
|
|
377
|
+
[attr.tabindex]="card.interactive ? 0 : null"
|
|
378
|
+
[matTooltip]="card.tooltip || ''"
|
|
379
|
+
(click)="onCardClick(card, i)"
|
|
380
|
+
(keydown.enter)="onCardClick(card, i)"
|
|
381
|
+
(keydown.space)="$event.preventDefault(); onCardClick(card, i)"
|
|
382
|
+
>
|
|
383
|
+
<div class="praxis-kpi-card-top">
|
|
384
|
+
<span class="praxis-kpi-card-label">{{ card.label }}</span>
|
|
385
|
+
<div *ngIf="card.icon" class="praxis-kpi-card-icon">
|
|
386
|
+
<mat-icon>{{ card.icon }}</mat-icon>
|
|
387
|
+
</div>
|
|
388
|
+
</div>
|
|
389
|
+
|
|
390
|
+
<div class="praxis-kpi-card-value">{{ card.displayValue }}</div>
|
|
391
|
+
|
|
392
|
+
<div *ngIf="card.displayCaption" class="praxis-kpi-card-caption">
|
|
393
|
+
{{ card.displayCaption }}
|
|
394
|
+
</div>
|
|
395
|
+
|
|
396
|
+
<div *ngIf="card.footnote" class="praxis-kpi-card-footnote">
|
|
397
|
+
{{ card.footnote }}
|
|
398
|
+
</div>
|
|
399
|
+
</div>
|
|
400
|
+
</ng-template>
|
|
401
|
+
</div>
|
|
402
|
+
</div>
|
|
403
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".praxis-kpi-band{display:flex;flex-direction:column;gap:.75rem;margin-bottom:1.25rem;width:100%;box-sizing:border-box}.praxis-kpi-band-header{display:flex;align-items:center;justify-content:space-between;gap:1rem}.praxis-kpi-band-title{margin:0;font-size:1rem;font-weight:600;color:var(--praxis-text-primary, #0f172a)}.praxis-kpi-band-subtitle{margin:.125rem 0 0;font-size:.8125rem;color:var(--praxis-text-muted, #64748b)}.praxis-kpi-band-grid{display:grid;grid-template-columns:repeat(var(--praxis-kpi-columns, auto-fit),minmax(200px,1fr));gap:var(--praxis-kpi-gap, 1rem);width:100%}.praxis-kpi-card{display:flex;flex-direction:column;justify-content:space-between;padding:1rem 1.25rem;border-radius:.75rem;background:var(--praxis-surface-card, #ffffff);border:1px solid var(--praxis-border-subtle, #e2e8f0);box-shadow:0 1px 3px #0000000a;transition:transform .15s ease,box-shadow .15s ease,border-color .15s ease;position:relative;overflow:hidden;min-height:5.5rem;box-sizing:border-box}.praxis-kpi-card.interactive{cursor:pointer}.praxis-kpi-card.interactive:hover{transform:translateY(-2px);box-shadow:0 4px 12px #00000014}.praxis-kpi-card.interactive:focus-visible{outline:2px solid var(--praxis-primary, #0284c7);outline-offset:2px}.praxis-kpi-card-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:.5rem}.praxis-kpi-card-label{font-size:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--praxis-text-muted, #64748b)}.praxis-kpi-card-icon{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;border-radius:.5rem}.praxis-kpi-card-icon mat-icon{font-size:1.25rem;width:1.25rem;height:1.25rem}.praxis-kpi-card-value{font-size:1.625rem;font-weight:700;line-height:1.2;letter-spacing:-.02em;font-feature-settings:\"tnum\" on,\"lnum\" on;color:var(--praxis-text-primary, #0f172a)}.praxis-kpi-card-caption{font-size:.75rem;color:var(--praxis-text-muted, #64748b);margin-top:.375rem}.praxis-kpi-card-footnote{font-size:.7rem;color:var(--praxis-text-secondary, #94a3b8);margin-top:.25rem}.tone-info{border-left:4px solid var(--praxis-info, #0284c7)}.tone-info .praxis-kpi-card-icon{background:#f0f9ff;color:#0284c7}.tone-success{border-left:4px solid var(--praxis-success, #059669)}.tone-success .praxis-kpi-card-icon{background:#ecfdf5;color:#059669}.tone-warning{border-left:4px solid var(--praxis-warning, #d97706)}.tone-warning .praxis-kpi-card-icon{background:#fffbeb;color:#d97706}.tone-error,.tone-danger{border-left:4px solid var(--praxis-error, #dc2626)}.tone-error .praxis-kpi-card-icon,.tone-danger .praxis-kpi-card-icon{background:#fef2f2;color:#dc2626}.tone-neutral{border-left:4px solid var(--praxis-neutral, #94a3b8)}.tone-neutral .praxis-kpi-card-icon{background:#f8fafc;color:#64748b}.praxis-kpi-card-skeleton{pointer-events:none}.praxis-kpi-skeleton-line{background:linear-gradient(90deg,#f1f5f9 25%,#e2e8f0,#f1f5f9 75%);background-size:200% 100%;animation:praxis-shimmer 1.5s infinite;border-radius:.25rem}.praxis-kpi-skeleton-line.label{width:40%;height:.75rem;margin-bottom:.75rem}.praxis-kpi-skeleton-line.value{width:65%;height:1.5rem;margin-bottom:.5rem}.praxis-kpi-skeleton-line.caption{width:50%;height:.65rem}@keyframes praxis-shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}\n"] }]
|
|
404
|
+
}], propDecorators: { config: [{
|
|
405
|
+
type: Input
|
|
406
|
+
}], dataContext: [{
|
|
407
|
+
type: Input
|
|
408
|
+
}], isInteractiveHost: [{
|
|
409
|
+
type: Input
|
|
410
|
+
}], cardClick: [{
|
|
411
|
+
type: Output
|
|
412
|
+
}], statsLoaded: [{
|
|
413
|
+
type: Output
|
|
414
|
+
}], statsError: [{
|
|
415
|
+
type: Output
|
|
416
|
+
}], refreshClick: [{
|
|
417
|
+
type: Output
|
|
418
|
+
}] } });
|
|
419
|
+
|
|
39
420
|
class DialogService {
|
|
40
421
|
matDialog;
|
|
41
422
|
zone;
|
|
@@ -50,13 +431,13 @@ class DialogService {
|
|
|
50
431
|
const component = await loader();
|
|
51
432
|
return this.zone.run(() => this.matDialog.open(component, config));
|
|
52
433
|
}
|
|
53
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DialogService, deps: [{ token: i1.MatDialog }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
434
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DialogService, deps: [{ token: i1$1.MatDialog }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
54
435
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DialogService, providedIn: 'root' });
|
|
55
436
|
}
|
|
56
437
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DialogService, decorators: [{
|
|
57
438
|
type: Injectable,
|
|
58
439
|
args: [{ providedIn: 'root' }]
|
|
59
|
-
}], ctorParameters: () => [{ type: i1.MatDialog }, { type: i0.NgZone }] });
|
|
440
|
+
}], ctorParameters: () => [{ type: i1$1.MatDialog }, { type: i0.NgZone }] });
|
|
60
441
|
|
|
61
442
|
function getCrudDrawerAdapterToken() {
|
|
62
443
|
const registryKey = '__PAX_CRUD_DRAWER_ADAPTER_TOKEN__';
|
|
@@ -3280,7 +3661,7 @@ class CrudMetadataEditorComponent {
|
|
|
3280
3661
|
</mat-tab>
|
|
3281
3662
|
</mat-tab-group>
|
|
3282
3663
|
</section>
|
|
3283
|
-
`, isInline: true, styles: [":host{display:block;min-width:0;color:var(--md-sys-color-on-surface,#1a1b20)}.editor-shell{display:grid;gap:16px}.editor-header{display:flex;justify-content:space-between;gap:16px;align-items:start}.editor-overview,.editor-health-map{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.editor-health-card{display:grid;gap:4px;padding:14px;border-radius:18px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high,#eef1f6) 92%,transparent)}.editor-health-card--warn{background:color-mix(in srgb,var(--md-sys-color-tertiary-container,#f8e08e) 78%,transparent)}.editor-health-card--error{background:color-mix(in srgb,var(--md-sys-color-error-container,#f9dedc) 82%,transparent);color:var(--md-sys-color-on-error-container,#410e0b)}.editor-focus{display:flex;gap:12px;align-items:start;padding:14px 16px;border-radius:18px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high,#eef1f6) 92%,transparent)}.editor-focus--success{background:color-mix(in srgb,var(--md-sys-color-secondary-container,#d7e3ff) 70%,transparent)}.editor-focus-chip{padding:6px 10px;border-radius:999px;font-size:12px;background:color-mix(in srgb,var(--md-sys-color-secondary-container,#d7e3ff) 70%,transparent);white-space:nowrap}.editor-focus-chip--warn{background:color-mix(in srgb,var(--md-sys-color-tertiary-container,#f8e08e) 78%,transparent)}.editor-focus-chip--error{background:color-mix(in srgb,var(--md-sys-color-error-container,#f9dedc) 82%,transparent);color:var(--md-sys-color-on-error-container,#410e0b)}.editor-focus-copy{display:grid;gap:4px}.editor-focus-copy p{margin:0;color:var(--md-sys-color-on-surface-variant,#5a5d67)}.editor-tabs{display:flex;flex-direction:column;min-width:0}.editor-tabs .mat-mdc-tab{min-width:118px}.editor-tabs ::ng-deep .mdc-tab__content{gap:8px}.editor-tabs ::ng-deep .mat-mdc-tab-body-wrapper,.editor-tabs ::ng-deep .mat-mdc-tab-group-container{flex:1 1 auto;min-height:0}.editor-tabs ::ng-deep .mat-mdc-tab-body-content{overflow:hidden}.tab-status-dot{width:8px;height:8px;border-radius:999px;background:var(--md-sys-color-primary,#1263b4);flex:0 0 auto}.tab-status-dot--warn{background:var(--md-sys-color-tertiary,#7d5700)}.tab-status-dot--error{background:var(--md-sys-color-error,#b3261e)}.tab-content{display:grid;gap:14px;min-width:0;padding:12px 2px 4px;box-sizing:border-box}.editor-overview-card{display:grid;gap:4px;padding:14px;border-radius:18px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high,#eef1f6) 92%,transparent)}.editor-overview-card--warn{background:color-mix(in srgb,var(--md-sys-color-tertiary-container,#f8e08e) 78%,transparent)}.editor-overview-card--error{background:color-mix(in srgb,var(--md-sys-color-error-container,#f9dedc) 82%,transparent);color:var(--md-sys-color-on-error-container,#410e0b)}.editor-overview-label{font-size:12px;color:var(--md-sys-color-on-surface-variant,#5a5d67)}.editor-overview-value{line-height:1.3;overflow-wrap:anywhere}.editor-overview-note{margin:0;font-size:12px;color:var(--md-sys-color-on-surface-variant,#5a5d67)}.editor-header h2,.editor-card h3{margin:0}.editor-header p{margin:6px 0 0;color:var(--md-sys-color-on-surface-variant,#5a5d67)}.editor-chip{padding:6px 10px;border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-primary,#1263b4) 12%,transparent);font-size:12px}.editor-card{display:grid;gap:14px;padding:16px;border-radius:20px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline,#c5c7ce) 70%,transparent)}.editor-section-header{display:flex;justify-content:space-between;gap:12px;align-items:start}.editor-grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.editor-grid--compact{grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}.editor-toggles{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.editor-actions,.action-grid{display:grid;gap:14px}.action-summary-strip{display:flex;flex-wrap:wrap;gap:8px}.action-summary-chip{padding:6px 10px;border-radius:999px;font-size:12px;background:color-mix(in srgb,var(--md-sys-color-secondary-container,#d7e3ff) 70%,transparent)}.action-summary-chip--warn{background:color-mix(in srgb,var(--md-sys-color-tertiary-container,#f8e08e) 78%,transparent)}.action-summary-chip--error{background:color-mix(in srgb,var(--md-sys-color-error-container,#f9dedc) 82%,transparent);color:var(--md-sys-color-on-error-container,#410e0b)}.action-group{display:grid;gap:10px;padding:12px;border-radius:16px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high,#eef1f6) 88%,transparent)}.action-group--advanced{background:color-mix(in srgb,var(--md-sys-color-surface-container,#f5f7fb) 90%,transparent)}.action-group__header{display:grid;gap:4px}.action-subgroup{display:grid;gap:10px;padding:10px;border-radius:14px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low,#fafbfd) 92%,transparent)}.action-subgroup__header{display:grid;gap:4px}.action-param-list{display:grid;gap:12px}.action-param-row{display:grid;gap:8px}.action-advanced-panel{border:1px solid color-mix(in srgb,var(--md-sys-color-outline,#c5c7ce) 65%,transparent);border-radius:16px}.editor-section-note{margin:0;color:var(--md-sys-color-on-surface-variant,#5a5d67)}.diagnostics-groups{display:grid;gap:12px}.diagnostics-group{display:grid;gap:10px;padding:12px;border-radius:16px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high,#eef1f6) 92%,transparent)}.diagnostics{display:grid;gap:8px;margin:0;padding-left:18px}.diagnostics .error{color:var(--md-sys-color-error,#b3261e)}pre{margin:0;overflow:auto;max-height:320px;padding:12px;border-radius:14px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high,#eef1f6) 92%,transparent)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { 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.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i3.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i4.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i4.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i4.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i4.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: MatSelectModule }, { kind: "component", type: i8.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i8.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i9.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "directive", type: i10.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "component", type: i10.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i10.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: PraxisTableInlineAuthoringEditorComponent, selector: "praxis-table-inline-authoring-editor", inputs: ["config", "readonly"], outputs: ["configChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3664
|
+
`, isInline: true, styles: [":host{display:block;min-width:0;color:var(--md-sys-color-on-surface,#1a1b20)}.editor-shell{display:grid;gap:16px}.editor-header{display:flex;justify-content:space-between;gap:16px;align-items:start}.editor-overview,.editor-health-map{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.editor-health-card{display:grid;gap:4px;padding:14px;border-radius:18px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high,#eef1f6) 92%,transparent)}.editor-health-card--warn{background:color-mix(in srgb,var(--md-sys-color-tertiary-container,#f8e08e) 78%,transparent)}.editor-health-card--error{background:color-mix(in srgb,var(--md-sys-color-error-container,#f9dedc) 82%,transparent);color:var(--md-sys-color-on-error-container,#410e0b)}.editor-focus{display:flex;gap:12px;align-items:start;padding:14px 16px;border-radius:18px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high,#eef1f6) 92%,transparent)}.editor-focus--success{background:color-mix(in srgb,var(--md-sys-color-secondary-container,#d7e3ff) 70%,transparent)}.editor-focus-chip{padding:6px 10px;border-radius:999px;font-size:12px;background:color-mix(in srgb,var(--md-sys-color-secondary-container,#d7e3ff) 70%,transparent);white-space:nowrap}.editor-focus-chip--warn{background:color-mix(in srgb,var(--md-sys-color-tertiary-container,#f8e08e) 78%,transparent)}.editor-focus-chip--error{background:color-mix(in srgb,var(--md-sys-color-error-container,#f9dedc) 82%,transparent);color:var(--md-sys-color-on-error-container,#410e0b)}.editor-focus-copy{display:grid;gap:4px}.editor-focus-copy p{margin:0;color:var(--md-sys-color-on-surface-variant,#5a5d67)}.editor-tabs{display:flex;flex-direction:column;min-width:0}.editor-tabs .mat-mdc-tab{min-width:118px}.editor-tabs ::ng-deep .mdc-tab__content{gap:8px}.editor-tabs ::ng-deep .mat-mdc-tab-body-wrapper,.editor-tabs ::ng-deep .mat-mdc-tab-group-container{flex:1 1 auto;min-height:0}.editor-tabs ::ng-deep .mat-mdc-tab-body-content{overflow:hidden}.tab-status-dot{width:8px;height:8px;border-radius:999px;background:var(--md-sys-color-primary,#1263b4);flex:0 0 auto}.tab-status-dot--warn{background:var(--md-sys-color-tertiary,#7d5700)}.tab-status-dot--error{background:var(--md-sys-color-error,#b3261e)}.tab-content{display:grid;gap:14px;min-width:0;padding:12px 2px 4px;box-sizing:border-box}.editor-overview-card{display:grid;gap:4px;padding:14px;border-radius:18px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high,#eef1f6) 92%,transparent)}.editor-overview-card--warn{background:color-mix(in srgb,var(--md-sys-color-tertiary-container,#f8e08e) 78%,transparent)}.editor-overview-card--error{background:color-mix(in srgb,var(--md-sys-color-error-container,#f9dedc) 82%,transparent);color:var(--md-sys-color-on-error-container,#410e0b)}.editor-overview-label{font-size:12px;color:var(--md-sys-color-on-surface-variant,#5a5d67)}.editor-overview-value{line-height:1.3;overflow-wrap:anywhere}.editor-overview-note{margin:0;font-size:12px;color:var(--md-sys-color-on-surface-variant,#5a5d67)}.editor-header h2,.editor-card h3{margin:0}.editor-header p{margin:6px 0 0;color:var(--md-sys-color-on-surface-variant,#5a5d67)}.editor-chip{padding:6px 10px;border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-primary,#1263b4) 12%,transparent);font-size:12px}.editor-card{display:grid;gap:14px;padding:16px;border-radius:20px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline,#c5c7ce) 70%,transparent)}.editor-section-header{display:flex;justify-content:space-between;gap:12px;align-items:start}.editor-grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.editor-grid--compact{grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}.editor-toggles{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.editor-actions,.action-grid{display:grid;gap:14px}.action-summary-strip{display:flex;flex-wrap:wrap;gap:8px}.action-summary-chip{padding:6px 10px;border-radius:999px;font-size:12px;background:color-mix(in srgb,var(--md-sys-color-secondary-container,#d7e3ff) 70%,transparent)}.action-summary-chip--warn{background:color-mix(in srgb,var(--md-sys-color-tertiary-container,#f8e08e) 78%,transparent)}.action-summary-chip--error{background:color-mix(in srgb,var(--md-sys-color-error-container,#f9dedc) 82%,transparent);color:var(--md-sys-color-on-error-container,#410e0b)}.action-group{display:grid;gap:10px;padding:12px;border-radius:16px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high,#eef1f6) 88%,transparent)}.action-group--advanced{background:color-mix(in srgb,var(--md-sys-color-surface-container,#f5f7fb) 90%,transparent)}.action-group__header{display:grid;gap:4px}.action-subgroup{display:grid;gap:10px;padding:10px;border-radius:14px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low,#fafbfd) 92%,transparent)}.action-subgroup__header{display:grid;gap:4px}.action-param-list{display:grid;gap:12px}.action-param-row{display:grid;gap:8px}.action-advanced-panel{border:1px solid color-mix(in srgb,var(--md-sys-color-outline,#c5c7ce) 65%,transparent);border-radius:16px}.editor-section-note{margin:0;color:var(--md-sys-color-on-surface-variant,#5a5d67)}.diagnostics-groups{display:grid;gap:12px}.diagnostics-group{display:grid;gap:10px;padding:12px;border-radius:16px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high,#eef1f6) 92%,transparent)}.diagnostics{display:grid;gap:8px;margin:0;padding-left:18px}.diagnostics .error{color:var(--md-sys-color-error,#b3261e)}pre{margin:0;overflow:auto;max-height:320px;padding:12px;border-radius:14px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high,#eef1f6) 92%,transparent)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i3$1.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i4$1.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i4$1.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i4$1.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i4$1.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: MatSelectModule }, { kind: "component", type: i8.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i8.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i9.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "directive", type: i10.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "component", type: i10.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i10.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: PraxisTableInlineAuthoringEditorComponent, selector: "praxis-table-inline-authoring-editor", inputs: ["config", "readonly"], outputs: ["configChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3284
3665
|
}
|
|
3285
3666
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: CrudMetadataEditorComponent, decorators: [{
|
|
3286
3667
|
type: Component,
|
|
@@ -3938,7 +4319,32 @@ function isOperationalRenderer(renderer) {
|
|
|
3938
4319
|
|
|
3939
4320
|
class PraxisCrudComponent {
|
|
3940
4321
|
metadata;
|
|
3941
|
-
crudId;
|
|
4322
|
+
crudId = 'praxis-crud';
|
|
4323
|
+
_resource;
|
|
4324
|
+
_autoGeneratedMetadata = false;
|
|
4325
|
+
/** Alias canônico para descoberta integral do recurso (Issue #38) */
|
|
4326
|
+
set resource(value) {
|
|
4327
|
+
this._resource = value;
|
|
4328
|
+
if (value && (!this.metadata || this._autoGeneratedMetadata)) {
|
|
4329
|
+
this._autoGeneratedMetadata = true;
|
|
4330
|
+
this.metadata = {
|
|
4331
|
+
component: 'praxis-crud',
|
|
4332
|
+
resource: {
|
|
4333
|
+
path: value,
|
|
4334
|
+
idField: 'id',
|
|
4335
|
+
},
|
|
4336
|
+
table: {
|
|
4337
|
+
columns: [],
|
|
4338
|
+
},
|
|
4339
|
+
};
|
|
4340
|
+
if (this.crudId === 'praxis-crud' || !this.crudId || this.crudId.startsWith('crud-')) {
|
|
4341
|
+
this.crudId = `crud-${value.replace(/\//g, '-')}`;
|
|
4342
|
+
}
|
|
4343
|
+
}
|
|
4344
|
+
}
|
|
4345
|
+
get resource() {
|
|
4346
|
+
return this._resource;
|
|
4347
|
+
}
|
|
3942
4348
|
componentInstanceId;
|
|
3943
4349
|
/** Controls whether the CRUD's internal table trusts host input or stored user configuration. */
|
|
3944
4350
|
tableConfigPersistenceStrategy = 'local-first';
|
|
@@ -3948,6 +4354,24 @@ class PraxisCrudComponent {
|
|
|
3948
4354
|
showResourceIdentityKey = true;
|
|
3949
4355
|
/** Capability publica exigida para authoring governado do CRUD e da tabela interna. */
|
|
3950
4356
|
authoringCapability = null;
|
|
4357
|
+
/** Critérios reativos de filtro aplicados à tabela interna (Issue #11) */
|
|
4358
|
+
filterCriteria;
|
|
4359
|
+
/** Habilita teleporte da barra de filtros para container externo (Issue #11) */
|
|
4360
|
+
filterTeleport = false;
|
|
4361
|
+
/** Desabilita auto-abertura da gaveta analítica no clique de linha (Issue #39) */
|
|
4362
|
+
disableAutoDrawer = false;
|
|
4363
|
+
get filterTemplate() {
|
|
4364
|
+
return this.table?.filterTemplate;
|
|
4365
|
+
}
|
|
4366
|
+
get internalTable() {
|
|
4367
|
+
return this.table;
|
|
4368
|
+
}
|
|
4369
|
+
openAnalyticalDrawer(row, tabId) {
|
|
4370
|
+
this.table?.openAnalyticalDrawer(row, tabId);
|
|
4371
|
+
}
|
|
4372
|
+
closeAnalyticalDrawer() {
|
|
4373
|
+
this.table?.closeAnalyticalDrawer();
|
|
4374
|
+
}
|
|
3951
4375
|
configureRequested = new EventEmitter();
|
|
3952
4376
|
afterOpen = new EventEmitter();
|
|
3953
4377
|
afterClose = new EventEmitter();
|
|
@@ -3965,8 +4389,39 @@ class PraxisCrudComponent {
|
|
|
3965
4389
|
/** Forwards the canonical resource interaction envelope emitted by the internal table. */
|
|
3966
4390
|
resourceEvent = output();
|
|
3967
4391
|
tableRuntimeConfigChange = new EventEmitter();
|
|
4392
|
+
drawerOpen = new EventEmitter();
|
|
4393
|
+
drawerClose = new EventEmitter();
|
|
3968
4394
|
crudAuthoringDocumentApplied = new EventEmitter();
|
|
3969
4395
|
crudAuthoringDocumentSaved = new EventEmitter();
|
|
4396
|
+
/** Evento emitido ao clicar em um card da faixa declarativa de KPIs (Issue #33) */
|
|
4397
|
+
kpiCardClick = new EventEmitter();
|
|
4398
|
+
get resolvedKpiBandConfig() {
|
|
4399
|
+
const meta = this.resolvedMetadata;
|
|
4400
|
+
const band = meta?.kpiBand || meta?.table?.kpiBand || meta?.table?.behavior?.kpiBand;
|
|
4401
|
+
if (band && band.enabled !== false && (band.cards?.length || band.source || band.document)) {
|
|
4402
|
+
return band;
|
|
4403
|
+
}
|
|
4404
|
+
return null;
|
|
4405
|
+
}
|
|
4406
|
+
get isKpiInteractiveHost() {
|
|
4407
|
+
return this.kpiCardClick.observed;
|
|
4408
|
+
}
|
|
4409
|
+
get kpiDataContext() {
|
|
4410
|
+
return {
|
|
4411
|
+
...(this.context || {}),
|
|
4412
|
+
data: this.resolvedMetadata?.data,
|
|
4413
|
+
};
|
|
4414
|
+
}
|
|
4415
|
+
onKpiCardClick(event) {
|
|
4416
|
+
this.kpiCardClick.emit(event);
|
|
4417
|
+
if (event.card.filter && typeof event.card.filter === 'object') {
|
|
4418
|
+
this.tableQueryContext = {
|
|
4419
|
+
...(this.tableQueryContext || {}),
|
|
4420
|
+
...event.card.filter,
|
|
4421
|
+
};
|
|
4422
|
+
this.cdr.markForCheck();
|
|
4423
|
+
}
|
|
4424
|
+
}
|
|
3970
4425
|
resolvedMetadata;
|
|
3971
4426
|
effectiveTableConfig;
|
|
3972
4427
|
tableConfigForBinding = createDefaultTableConfig();
|
|
@@ -3978,6 +4433,7 @@ class PraxisCrudComponent {
|
|
|
3978
4433
|
http = inject(HttpClient);
|
|
3979
4434
|
destroyRef = inject(DestroyRef);
|
|
3980
4435
|
cdr = inject(ChangeDetectorRef);
|
|
4436
|
+
widgetEventBus = inject(PraxisWidgetEventBus, { optional: true });
|
|
3981
4437
|
table;
|
|
3982
4438
|
storage = inject(ASYNC_CONFIG_STORAGE);
|
|
3983
4439
|
settingsPanel = inject(SettingsPanelService);
|
|
@@ -4030,6 +4486,25 @@ class PraxisCrudComponent {
|
|
|
4030
4486
|
}
|
|
4031
4487
|
this.cdr.markForCheck();
|
|
4032
4488
|
});
|
|
4489
|
+
if (this.widgetEventBus) {
|
|
4490
|
+
this.widgetEventBus
|
|
4491
|
+
.onFilter()
|
|
4492
|
+
.pipe(filter((evt) => {
|
|
4493
|
+
if (!evt.targetWidgetId || evt.targetWidgetId === '*') {
|
|
4494
|
+
return true;
|
|
4495
|
+
}
|
|
4496
|
+
return (evt.targetWidgetId === this.crudId ||
|
|
4497
|
+
(!!this.resource && evt.targetWidgetId === this.resource));
|
|
4498
|
+
}), takeUntilDestroyed(this.destroyRef))
|
|
4499
|
+
.subscribe((evt) => {
|
|
4500
|
+
if (evt.eventType === 'filter.apply') {
|
|
4501
|
+
this.applyFilterCriteria(evt.payload);
|
|
4502
|
+
}
|
|
4503
|
+
else if (evt.eventType === 'filter.clear') {
|
|
4504
|
+
this.clearFilterCriteria();
|
|
4505
|
+
}
|
|
4506
|
+
});
|
|
4507
|
+
}
|
|
4033
4508
|
}
|
|
4034
4509
|
collectionCapabilitiesRequestHref = null;
|
|
4035
4510
|
collectionCapabilitiesResolvedHref = null;
|
|
@@ -4091,6 +4566,12 @@ class PraxisCrudComponent {
|
|
|
4091
4566
|
}
|
|
4092
4567
|
this.resourceEvent.emit(event);
|
|
4093
4568
|
}
|
|
4569
|
+
onTableDrawerOpen(event) {
|
|
4570
|
+
this.drawerOpen.emit(event);
|
|
4571
|
+
}
|
|
4572
|
+
onTableDrawerClose() {
|
|
4573
|
+
this.drawerClose.emit();
|
|
4574
|
+
}
|
|
4094
4575
|
async onBulkAction(event) {
|
|
4095
4576
|
if (this.isInspectOnly()) {
|
|
4096
4577
|
return;
|
|
@@ -4118,16 +4599,72 @@ class PraxisCrudComponent {
|
|
|
4118
4599
|
await this.onAction(action, row ?? undefined, event);
|
|
4119
4600
|
}
|
|
4120
4601
|
ngOnChanges(changes) {
|
|
4121
|
-
if (!changes['metadata'] && !changes['context']) {
|
|
4602
|
+
if (!changes['metadata'] && !changes['context'] && !changes['resource']) {
|
|
4122
4603
|
return;
|
|
4123
4604
|
}
|
|
4605
|
+
if (changes['metadata']) {
|
|
4606
|
+
this._autoGeneratedMetadata = false;
|
|
4607
|
+
}
|
|
4608
|
+
if (changes['resource'] && !changes['metadata'] && this.resource) {
|
|
4609
|
+
this._autoGeneratedMetadata = true;
|
|
4610
|
+
this.metadata = {
|
|
4611
|
+
component: 'praxis-crud',
|
|
4612
|
+
resource: {
|
|
4613
|
+
path: this.resource,
|
|
4614
|
+
idField: 'id',
|
|
4615
|
+
},
|
|
4616
|
+
table: {
|
|
4617
|
+
columns: [],
|
|
4618
|
+
},
|
|
4619
|
+
};
|
|
4620
|
+
if (this.crudId === 'praxis-crud' || !this.crudId || this.crudId.startsWith('crud-')) {
|
|
4621
|
+
this.crudId = `crud-${this.resource.replace(/\//g, '-')}`;
|
|
4622
|
+
}
|
|
4623
|
+
}
|
|
4124
4624
|
this.materializedRefreshSequence += 1;
|
|
4125
4625
|
this.lastTableRuntimeConfigSnapshot = null;
|
|
4126
4626
|
this.lastEmittedTableRuntimeConfigJson = '';
|
|
4627
|
+
if (changes['filterCriteria'] && !changes['filterCriteria'].firstChange) {
|
|
4628
|
+
this.applyFilterCriteria(this.filterCriteria);
|
|
4629
|
+
}
|
|
4127
4630
|
try {
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4631
|
+
let parsed;
|
|
4632
|
+
if (typeof this.metadata === 'string') {
|
|
4633
|
+
const trimmed = this.metadata.trim();
|
|
4634
|
+
if (trimmed.startsWith('{')) {
|
|
4635
|
+
parsed = JSON.parse(trimmed);
|
|
4636
|
+
}
|
|
4637
|
+
else {
|
|
4638
|
+
parsed = {
|
|
4639
|
+
component: 'praxis-crud',
|
|
4640
|
+
resource: {
|
|
4641
|
+
path: trimmed,
|
|
4642
|
+
idField: 'id',
|
|
4643
|
+
},
|
|
4644
|
+
table: {
|
|
4645
|
+
columns: [],
|
|
4646
|
+
},
|
|
4647
|
+
};
|
|
4648
|
+
}
|
|
4649
|
+
}
|
|
4650
|
+
else if (this.metadata) {
|
|
4651
|
+
parsed = this.metadata;
|
|
4652
|
+
}
|
|
4653
|
+
else if (this.resource) {
|
|
4654
|
+
parsed = {
|
|
4655
|
+
component: 'praxis-crud',
|
|
4656
|
+
resource: {
|
|
4657
|
+
path: this.resource,
|
|
4658
|
+
idField: 'id',
|
|
4659
|
+
},
|
|
4660
|
+
table: {
|
|
4661
|
+
columns: [],
|
|
4662
|
+
},
|
|
4663
|
+
};
|
|
4664
|
+
}
|
|
4665
|
+
else {
|
|
4666
|
+
return;
|
|
4667
|
+
}
|
|
4131
4668
|
this.resolvedMetadata = parsed;
|
|
4132
4669
|
const externalAuthoringSeed = parsed.interactionMode !== 'inspect-only' && this.context && typeof this.context === 'object'
|
|
4133
4670
|
? (this.context['authoringDocument'] ?? this.context['authoringMetadata'])
|
|
@@ -4723,14 +5260,39 @@ class PraxisCrudComponent {
|
|
|
4723
5260
|
return this.isRecord(meta?.queryContext) ? meta.queryContext : null;
|
|
4724
5261
|
}
|
|
4725
5262
|
resolveFilterCriteria(meta) {
|
|
4726
|
-
|
|
5263
|
+
const fromInput = this.isRecord(this.filterCriteria) ? { ...this.filterCriteria } : {};
|
|
5264
|
+
const fromMeta = this.isRecord(meta?.filterCriteria) ? { ...meta.filterCriteria } : {};
|
|
5265
|
+
return { ...fromMeta, ...fromInput };
|
|
5266
|
+
}
|
|
5267
|
+
/**
|
|
5268
|
+
* Aplica critérios de busca avançada na tabela interna do CRUD (Issue #11).
|
|
5269
|
+
*/
|
|
5270
|
+
applyFilterCriteria(criteria) {
|
|
5271
|
+
this.tableFilterCriteria = {
|
|
5272
|
+
...this.resolveFilterCriteria(this.resolvedMetadata),
|
|
5273
|
+
...(criteria || {}),
|
|
5274
|
+
};
|
|
5275
|
+
if (this.table) {
|
|
5276
|
+
this.table.applyAdvancedFilterCriteria(this.tableFilterCriteria);
|
|
5277
|
+
}
|
|
5278
|
+
this.cdr.markForCheck();
|
|
5279
|
+
}
|
|
5280
|
+
/**
|
|
5281
|
+
* Limpa os filtros ativos na tabela interna do CRUD (Issue #11).
|
|
5282
|
+
*/
|
|
5283
|
+
clearFilterCriteria() {
|
|
5284
|
+
this.tableFilterCriteria = {};
|
|
5285
|
+
if (this.table) {
|
|
5286
|
+
this.table.clearAdvancedFilter();
|
|
5287
|
+
}
|
|
5288
|
+
this.cdr.markForCheck();
|
|
4727
5289
|
}
|
|
4728
5290
|
extractRowFromEvent(event) {
|
|
4729
5291
|
if (!this.isRecord(event)) {
|
|
4730
5292
|
return null;
|
|
4731
5293
|
}
|
|
4732
5294
|
const row = event['row'];
|
|
4733
|
-
return this.isRecord(row) ? row : null;
|
|
5295
|
+
return this.isRecord(row) ? row : (this.isRecord(event) ? event : null);
|
|
4734
5296
|
}
|
|
4735
5297
|
extractSelectedRowFromEvent(event) {
|
|
4736
5298
|
if (!this.isRecord(event)) {
|
|
@@ -5258,6 +5820,46 @@ class PraxisCrudComponent {
|
|
|
5258
5820
|
}
|
|
5259
5821
|
return cfg.toolbar;
|
|
5260
5822
|
};
|
|
5823
|
+
if (meta?.filterBar) {
|
|
5824
|
+
const fb = meta.filterBar;
|
|
5825
|
+
const toolbar = ensureToolbar();
|
|
5826
|
+
toolbar.visible = true;
|
|
5827
|
+
toolbar.filters = toolbar.filters || { enabled: true, showAdvancedButton: true };
|
|
5828
|
+
toolbar.filters.enabled = true;
|
|
5829
|
+
if (fb.showAdvanced !== undefined) {
|
|
5830
|
+
toolbar.filters.showAdvancedButton = fb.showAdvanced;
|
|
5831
|
+
}
|
|
5832
|
+
if (Array.isArray(fb.quickFilters)) {
|
|
5833
|
+
toolbar.filters.quickFilters = [...fb.quickFilters];
|
|
5834
|
+
}
|
|
5835
|
+
else if (fb.quickFilters === false) {
|
|
5836
|
+
toolbar.filters.quickFilters = [];
|
|
5837
|
+
}
|
|
5838
|
+
if (Array.isArray(fb.inlineFields) && fb.inlineFields.length > 0) {
|
|
5839
|
+
const behavior = (cfg.behavior = cfg.behavior || {});
|
|
5840
|
+
const filtering = (behavior.filtering = behavior.filtering || {
|
|
5841
|
+
enabled: true,
|
|
5842
|
+
strategy: 'server',
|
|
5843
|
+
debounceTime: 300,
|
|
5844
|
+
});
|
|
5845
|
+
filtering.enabled = true;
|
|
5846
|
+
const advancedFilters = (filtering.advancedFilters = filtering.advancedFilters || { enabled: true });
|
|
5847
|
+
advancedFilters.enabled = true;
|
|
5848
|
+
const settings = (advancedFilters.settings = advancedFilters.settings || {});
|
|
5849
|
+
settings.alwaysVisibleFields = [...fb.inlineFields];
|
|
5850
|
+
if (fb.showAdvanced !== undefined) {
|
|
5851
|
+
settings.showAdvanced = fb.showAdvanced;
|
|
5852
|
+
}
|
|
5853
|
+
}
|
|
5854
|
+
changed = true;
|
|
5855
|
+
}
|
|
5856
|
+
else if (this.supportsFilterCapability(capabilities) && !cfg.toolbar?.filters && !cfg.behavior?.filtering?.advancedFilters) {
|
|
5857
|
+
const toolbar = ensureToolbar();
|
|
5858
|
+
toolbar.visible = true;
|
|
5859
|
+
toolbar.filters = toolbar.filters || { enabled: true, showAdvancedButton: true };
|
|
5860
|
+
toolbar.filters.enabled = true;
|
|
5861
|
+
changed = true;
|
|
5862
|
+
}
|
|
5261
5863
|
const hasToolbarAdd = (cfg.toolbar?.actions || []).some((action) => this.shouldCanonicalizeToolbarCreateAction(action));
|
|
5262
5864
|
const addAction = this.resolveCreateToolbarAction(meta, capabilities);
|
|
5263
5865
|
if (addAction) {
|
|
@@ -5384,6 +5986,20 @@ class PraxisCrudComponent {
|
|
|
5384
5986
|
changed = true;
|
|
5385
5987
|
}
|
|
5386
5988
|
}
|
|
5989
|
+
const effectiveOpenMode = meta.defaults?.openMode;
|
|
5990
|
+
const hasDrawerAction = (meta.actions || []).some((action) => action.openMode === 'drawer');
|
|
5991
|
+
const drawerRequested = effectiveOpenMode === 'drawer' ||
|
|
5992
|
+
hasDrawerAction ||
|
|
5993
|
+
cfg.behavior?.drawer?.enabled === true;
|
|
5994
|
+
if (drawerRequested && !this.disableAutoDrawer) {
|
|
5995
|
+
cfg.behavior = cfg.behavior || {};
|
|
5996
|
+
cfg.behavior.drawer = {
|
|
5997
|
+
enabled: true,
|
|
5998
|
+
openOnRowClick: cfg.behavior.drawer?.openOnRowClick !== false,
|
|
5999
|
+
...cfg.behavior.drawer,
|
|
6000
|
+
};
|
|
6001
|
+
changed = true;
|
|
6002
|
+
}
|
|
5387
6003
|
if (!changed) {
|
|
5388
6004
|
return base ? undefined : cfg;
|
|
5389
6005
|
}
|
|
@@ -5500,7 +6116,8 @@ class PraxisCrudComponent {
|
|
|
5500
6116
|
if (!requiredCapability) {
|
|
5501
6117
|
return true;
|
|
5502
6118
|
}
|
|
5503
|
-
const capabilities = this.enterpriseRuntimeContext?.
|
|
6119
|
+
const capabilities = this.enterpriseRuntimeContext?.effectiveContext?.capabilities ??
|
|
6120
|
+
this.enterpriseRuntimeContext?.snapshot?.capabilities;
|
|
5504
6121
|
return Array.isArray(capabilities)
|
|
5505
6122
|
&& capabilities.some((capability) => capability === requiredCapability);
|
|
5506
6123
|
}
|
|
@@ -5675,7 +6292,7 @@ class PraxisCrudComponent {
|
|
|
5675
6292
|
return operationAvailability;
|
|
5676
6293
|
}
|
|
5677
6294
|
return (this.hasCanonicalOperation(snapshot, 'create') ||
|
|
5678
|
-
snapshot.surfaces.some((surface) => surface.scope === 'COLLECTION' &&
|
|
6295
|
+
(snapshot.surfaces || []).some((surface) => surface.scope === 'COLLECTION' &&
|
|
5679
6296
|
this.isWritableCrudSurface(surface) &&
|
|
5680
6297
|
surface.availability?.allowed !== false));
|
|
5681
6298
|
}
|
|
@@ -5691,6 +6308,12 @@ class PraxisCrudComponent {
|
|
|
5691
6308
|
const operationAvailability = this.resolveOperationAvailability(snapshot, 'delete');
|
|
5692
6309
|
return operationAvailability ?? this.hasCanonicalOperation(snapshot, 'delete');
|
|
5693
6310
|
}
|
|
6311
|
+
supportsFilterCapability(snapshot) {
|
|
6312
|
+
if (!snapshot)
|
|
6313
|
+
return false;
|
|
6314
|
+
const operationAvailability = this.resolveOperationAvailability(snapshot, 'filter');
|
|
6315
|
+
return operationAvailability ?? this.hasCanonicalOperation(snapshot, 'filter');
|
|
6316
|
+
}
|
|
5694
6317
|
resolveOperationAvailability(snapshot, operationId) {
|
|
5695
6318
|
const operation = snapshot.operations?.[operationId];
|
|
5696
6319
|
if (!operation) {
|
|
@@ -5838,7 +6461,7 @@ class PraxisCrudComponent {
|
|
|
5838
6461
|
return Object.entries(params).reduce((current, [name, value]) => current.split(`{${name}}`).join(value), text);
|
|
5839
6462
|
}
|
|
5840
6463
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisCrudComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5841
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisCrudComponent, isStandalone: true, selector: "praxis-crud", inputs: { metadata: "metadata", crudId: "crudId", componentInstanceId: "componentInstanceId", tableConfigPersistenceStrategy: "tableConfigPersistenceStrategy", context: "context", enableCustomization: "enableCustomization", showResourceIdentityKey: "showResourceIdentityKey", authoringCapability: "authoringCapability" }, outputs: { configureRequested: "configureRequested", afterOpen: "afterOpen", afterClose: "afterClose", afterSave: "afterSave", afterDelete: "afterDelete", reactiveDeterminationExecuted: "reactiveDeterminationExecuted", reactiveDeterminationPendingChange: "reactiveDeterminationPendingChange", reactiveDeterminationStabilityChange: "reactiveDeterminationStabilityChange", error: "error", rowClick: "rowClick", rowAction: "rowAction", selectionChange: "selectionChange", resourceEvent: "resourceEvent", tableRuntimeConfigChange: "tableRuntimeConfigChange", crudAuthoringDocumentApplied: "crudAuthoringDocumentApplied", crudAuthoringDocumentSaved: "crudAuthoringDocumentSaved" }, providers: [
|
|
6464
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisCrudComponent, isStandalone: true, selector: "praxis-crud", inputs: { metadata: "metadata", crudId: "crudId", resource: "resource", componentInstanceId: "componentInstanceId", tableConfigPersistenceStrategy: "tableConfigPersistenceStrategy", context: "context", enableCustomization: "enableCustomization", showResourceIdentityKey: "showResourceIdentityKey", authoringCapability: "authoringCapability", filterCriteria: "filterCriteria", filterTeleport: ["filterTeleport", "filterTeleport", booleanAttribute], disableAutoDrawer: ["disableAutoDrawer", "disableAutoDrawer", booleanAttribute] }, outputs: { configureRequested: "configureRequested", afterOpen: "afterOpen", afterClose: "afterClose", afterSave: "afterSave", afterDelete: "afterDelete", reactiveDeterminationExecuted: "reactiveDeterminationExecuted", reactiveDeterminationPendingChange: "reactiveDeterminationPendingChange", reactiveDeterminationStabilityChange: "reactiveDeterminationStabilityChange", error: "error", rowClick: "rowClick", rowAction: "rowAction", selectionChange: "selectionChange", resourceEvent: "resourceEvent", tableRuntimeConfigChange: "tableRuntimeConfigChange", drawerOpen: "drawerOpen", drawerClose: "drawerClose", crudAuthoringDocumentApplied: "crudAuthoringDocumentApplied", crudAuthoringDocumentSaved: "crudAuthoringDocumentSaved", kpiCardClick: "kpiCardClick" }, providers: [
|
|
5842
6465
|
providePraxisI18nConfig(RESOURCE_DISCOVERY_I18N_CONFIG),
|
|
5843
6466
|
providePraxisI18nConfig(PRAXIS_CRUD_RUNTIME_I18N_CONFIG),
|
|
5844
6467
|
], viewQueries: [{ propertyName: "table", first: true, predicate: PraxisTable, descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
@@ -5849,6 +6472,14 @@ class PraxisCrudComponent {
|
|
|
5849
6472
|
<span>{{ getOpeningActionStatus(actionLabel) }}</span>
|
|
5850
6473
|
</div>
|
|
5851
6474
|
}
|
|
6475
|
+
@if (resolvedKpiBandConfig) {
|
|
6476
|
+
<praxis-kpi-band
|
|
6477
|
+
[config]="resolvedKpiBandConfig"
|
|
6478
|
+
[dataContext]="kpiDataContext"
|
|
6479
|
+
[isInteractiveHost]="isKpiInteractiveHost"
|
|
6480
|
+
(cardClick)="onKpiCardClick($event)"
|
|
6481
|
+
/>
|
|
6482
|
+
}
|
|
5852
6483
|
@if (shouldRenderTable(resolvedMetadata)) {
|
|
5853
6484
|
<praxis-table
|
|
5854
6485
|
[config]="tableConfigForBinding"
|
|
@@ -5856,6 +6487,7 @@ class PraxisCrudComponent {
|
|
|
5856
6487
|
[data]="resolveTableData(resolvedMetadata)"
|
|
5857
6488
|
[queryContext]="tableQueryContext"
|
|
5858
6489
|
[filterCriteria]="tableFilterCriteria"
|
|
6490
|
+
[filterTeleport]="filterTeleport"
|
|
5859
6491
|
[tableId]="crudId || 'default'"
|
|
5860
6492
|
[configPersistenceStrategy]="resolvedTableConfigPersistenceStrategy"
|
|
5861
6493
|
[crudContext]="tableCrudContext"
|
|
@@ -5872,6 +6504,8 @@ class PraxisCrudComponent {
|
|
|
5872
6504
|
(configChange)="onTableConfigChange($event)"
|
|
5873
6505
|
(metadataChange)="onTableMetadataChange()"
|
|
5874
6506
|
(loadingStateChange)="onTableLoadingStateChange($event)"
|
|
6507
|
+
(drawerOpen)="onTableDrawerOpen($event)"
|
|
6508
|
+
(drawerClose)="onTableDrawerClose()"
|
|
5875
6509
|
></praxis-table>
|
|
5876
6510
|
} @else {
|
|
5877
6511
|
@if (isCustomizationAvailable()) {
|
|
@@ -5884,11 +6518,11 @@ class PraxisCrudComponent {
|
|
|
5884
6518
|
}
|
|
5885
6519
|
}
|
|
5886
6520
|
</div>
|
|
5887
|
-
`, isInline: true, styles: [":host{display:block;width:100%;min-width:0;max-width:100%}.praxis-crud-runtime{position:relative;min-width:0}.praxis-crud-opening-status{position:absolute;z-index:6;top:.7rem;right:.7rem;display:inline-flex;align-items:center;gap:.55rem;min-height:2.25rem;max-width:min(24rem,calc(100% - 1.4rem));padding:.48rem .72rem;border:1px solid color-mix(in srgb,var(--md-sys-color-primary, #3f51b5) 32%,transparent);border-radius:999px;color:var(--md-sys-color-on-surface, currentColor);background:color-mix(in srgb,var(--md-sys-color-surface-container-high, #fff) 94%,transparent);box-shadow:0 10px 28px #0f172a29;font-size:.82rem;font-weight:650;line-height:1.25;pointer-events:none}.praxis-crud-opening-status__spinner{width:.95rem;height:.95rem;flex:0 0 auto;border:2px solid color-mix(in srgb,var(--md-sys-color-primary, #3f51b5) 26%,transparent);border-top-color:var(--md-sys-color-primary, #3f51b5);border-radius:50%;animation:praxis-crud-opening-spin .72s linear infinite}@keyframes praxis-crud-opening-spin{to{transform:rotate(360deg)}}@media(prefers-reduced-motion:reduce){.praxis-crud-opening-status__spinner{animation:none;border-top-color:currentColor}}\n"], dependencies: [{ kind: "component", type: PraxisTable, selector: "praxis-table", inputs: ["config", "resourcePath", "data", "tableId", "componentInstanceId", "configPersistenceStrategy", "title", "subtitle", "icon", "autoDelete", "notifyIfOutdated", "snoozeMs", "autoOpenSettingsOnOutdated", "crudContext", "filterCriteria", "queryContext", "aiContext", "aiAssistantVoiceInputMode", "aiAssistantVoiceLanguage", "horizontalScroll", "enableCustomization", "authoringCapability", "dense"], outputs: ["rowClick", "widgetEvent", "resourceEvent", "rowDoubleClick", "rowExpansionChange", "rowAction", "toolbarAction", "bulkAction", "exportAction", "columnReorder", "columnReorderAttempt", "columnResize", "beforeDelete", "afterDelete", "deleteError", "beforeBulkDelete", "afterBulkDelete", "bulkDeleteError", "schemaStatusChange", "configChange", "metadataChange", "loadingStateChange", "collectionLinksChange", "selectionChange"] }, { kind: "component", type: EmptyStateCardComponent, selector: "praxis-empty-state-card", inputs: ["icon", "title", "description", "primaryAction", "secondaryActions", "inline", "tone", "variant", "alignment", "density", "iconContainer"] }] });
|
|
6521
|
+
`, isInline: true, styles: [":host{display:block;width:100%;min-width:0;max-width:100%}.praxis-crud-runtime{position:relative;min-width:0}.praxis-crud-opening-status{position:absolute;z-index:6;top:.7rem;right:.7rem;display:inline-flex;align-items:center;gap:.55rem;min-height:2.25rem;max-width:min(24rem,calc(100% - 1.4rem));padding:.48rem .72rem;border:1px solid color-mix(in srgb,var(--md-sys-color-primary, #3f51b5) 32%,transparent);border-radius:999px;color:var(--md-sys-color-on-surface, currentColor);background:color-mix(in srgb,var(--md-sys-color-surface-container-high, #fff) 94%,transparent);box-shadow:0 10px 28px #0f172a29;font-size:.82rem;font-weight:650;line-height:1.25;pointer-events:none}.praxis-crud-opening-status__spinner{width:.95rem;height:.95rem;flex:0 0 auto;border:2px solid color-mix(in srgb,var(--md-sys-color-primary, #3f51b5) 26%,transparent);border-top-color:var(--md-sys-color-primary, #3f51b5);border-radius:50%;animation:praxis-crud-opening-spin .72s linear infinite}@keyframes praxis-crud-opening-spin{to{transform:rotate(360deg)}}@media(prefers-reduced-motion:reduce){.praxis-crud-opening-status__spinner{animation:none;border-top-color:currentColor}}\n"], dependencies: [{ kind: "component", type: PraxisTable, selector: "praxis-table", inputs: ["config", "resourcePath", "data", "tableId", "componentInstanceId", "configPersistenceStrategy", "title", "subtitle", "icon", "autoDelete", "notifyIfOutdated", "snoozeMs", "autoOpenSettingsOnOutdated", "crudContext", "filterCriteria", "filterTeleport", "widgetId", "queryContext", "aiContext", "aiAssistantVoiceInputMode", "aiAssistantVoiceLanguage", "horizontalScroll", "enableCustomization", "authoringCapability", "dense"], outputs: ["queryContextClear", "queryContextChange", "rowClick", "widgetEvent", "resourceEvent", "rowDoubleClick", "rowExpansionChange", "rowAction", "toolbarAction", "bulkAction", "exportAction", "columnReorder", "columnReorderAttempt", "columnResize", "beforeDelete", "afterDelete", "deleteError", "beforeBulkDelete", "afterBulkDelete", "bulkDeleteError", "schemaStatusChange", "configChange", "metadataChange", "loadingStateChange", "collectionLinksChange", "selectionChange", "drawerOpen", "drawerClose", "drawerTabChange"] }, { kind: "component", type: EmptyStateCardComponent, selector: "praxis-empty-state-card", inputs: ["icon", "title", "description", "primaryAction", "secondaryActions", "inline", "tone", "variant", "alignment", "density", "iconContainer"] }, { kind: "component", type: PraxisKpiBandComponent, selector: "praxis-kpi-band", inputs: ["config", "dataContext", "isInteractiveHost"], outputs: ["cardClick", "statsLoaded", "statsError", "refreshClick"] }] });
|
|
5888
6522
|
}
|
|
5889
6523
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisCrudComponent, decorators: [{
|
|
5890
6524
|
type: Component,
|
|
5891
|
-
args: [{ selector: 'praxis-crud', standalone: true, imports: [PraxisTable, EmptyStateCardComponent], providers: [
|
|
6525
|
+
args: [{ selector: 'praxis-crud', standalone: true, imports: [PraxisTable, EmptyStateCardComponent, PraxisKpiBandComponent], providers: [
|
|
5892
6526
|
providePraxisI18nConfig(RESOURCE_DISCOVERY_I18N_CONFIG),
|
|
5893
6527
|
providePraxisI18nConfig(PRAXIS_CRUD_RUNTIME_I18N_CONFIG),
|
|
5894
6528
|
], template: `
|
|
@@ -5899,6 +6533,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
5899
6533
|
<span>{{ getOpeningActionStatus(actionLabel) }}</span>
|
|
5900
6534
|
</div>
|
|
5901
6535
|
}
|
|
6536
|
+
@if (resolvedKpiBandConfig) {
|
|
6537
|
+
<praxis-kpi-band
|
|
6538
|
+
[config]="resolvedKpiBandConfig"
|
|
6539
|
+
[dataContext]="kpiDataContext"
|
|
6540
|
+
[isInteractiveHost]="isKpiInteractiveHost"
|
|
6541
|
+
(cardClick)="onKpiCardClick($event)"
|
|
6542
|
+
/>
|
|
6543
|
+
}
|
|
5902
6544
|
@if (shouldRenderTable(resolvedMetadata)) {
|
|
5903
6545
|
<praxis-table
|
|
5904
6546
|
[config]="tableConfigForBinding"
|
|
@@ -5906,6 +6548,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
5906
6548
|
[data]="resolveTableData(resolvedMetadata)"
|
|
5907
6549
|
[queryContext]="tableQueryContext"
|
|
5908
6550
|
[filterCriteria]="tableFilterCriteria"
|
|
6551
|
+
[filterTeleport]="filterTeleport"
|
|
5909
6552
|
[tableId]="crudId || 'default'"
|
|
5910
6553
|
[configPersistenceStrategy]="resolvedTableConfigPersistenceStrategy"
|
|
5911
6554
|
[crudContext]="tableCrudContext"
|
|
@@ -5922,6 +6565,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
5922
6565
|
(configChange)="onTableConfigChange($event)"
|
|
5923
6566
|
(metadataChange)="onTableMetadataChange()"
|
|
5924
6567
|
(loadingStateChange)="onTableLoadingStateChange($event)"
|
|
6568
|
+
(drawerOpen)="onTableDrawerOpen($event)"
|
|
6569
|
+
(drawerClose)="onTableDrawerClose()"
|
|
5925
6570
|
></praxis-table>
|
|
5926
6571
|
} @else {
|
|
5927
6572
|
@if (isCustomizationAvailable()) {
|
|
@@ -5936,11 +6581,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
5936
6581
|
</div>
|
|
5937
6582
|
`, styles: [":host{display:block;width:100%;min-width:0;max-width:100%}.praxis-crud-runtime{position:relative;min-width:0}.praxis-crud-opening-status{position:absolute;z-index:6;top:.7rem;right:.7rem;display:inline-flex;align-items:center;gap:.55rem;min-height:2.25rem;max-width:min(24rem,calc(100% - 1.4rem));padding:.48rem .72rem;border:1px solid color-mix(in srgb,var(--md-sys-color-primary, #3f51b5) 32%,transparent);border-radius:999px;color:var(--md-sys-color-on-surface, currentColor);background:color-mix(in srgb,var(--md-sys-color-surface-container-high, #fff) 94%,transparent);box-shadow:0 10px 28px #0f172a29;font-size:.82rem;font-weight:650;line-height:1.25;pointer-events:none}.praxis-crud-opening-status__spinner{width:.95rem;height:.95rem;flex:0 0 auto;border:2px solid color-mix(in srgb,var(--md-sys-color-primary, #3f51b5) 26%,transparent);border-top-color:var(--md-sys-color-primary, #3f51b5);border-radius:50%;animation:praxis-crud-opening-spin .72s linear infinite}@keyframes praxis-crud-opening-spin{to{transform:rotate(360deg)}}@media(prefers-reduced-motion:reduce){.praxis-crud-opening-status__spinner{animation:none;border-top-color:currentColor}}\n"] }]
|
|
5938
6583
|
}], ctorParameters: () => [], propDecorators: { metadata: [{
|
|
5939
|
-
type: Input
|
|
5940
|
-
args: [{ required: true }]
|
|
6584
|
+
type: Input
|
|
5941
6585
|
}], crudId: [{
|
|
5942
|
-
type: Input
|
|
5943
|
-
|
|
6586
|
+
type: Input
|
|
6587
|
+
}], resource: [{
|
|
6588
|
+
type: Input
|
|
5944
6589
|
}], componentInstanceId: [{
|
|
5945
6590
|
type: Input
|
|
5946
6591
|
}], tableConfigPersistenceStrategy: [{
|
|
@@ -5953,6 +6598,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
5953
6598
|
type: Input
|
|
5954
6599
|
}], authoringCapability: [{
|
|
5955
6600
|
type: Input
|
|
6601
|
+
}], filterCriteria: [{
|
|
6602
|
+
type: Input
|
|
6603
|
+
}], filterTeleport: [{
|
|
6604
|
+
type: Input,
|
|
6605
|
+
args: [{ transform: booleanAttribute }]
|
|
6606
|
+
}], disableAutoDrawer: [{
|
|
6607
|
+
type: Input,
|
|
6608
|
+
args: [{ transform: booleanAttribute }]
|
|
5956
6609
|
}], configureRequested: [{
|
|
5957
6610
|
type: Output
|
|
5958
6611
|
}], afterOpen: [{
|
|
@@ -5979,10 +6632,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
5979
6632
|
type: Output
|
|
5980
6633
|
}], resourceEvent: [{ type: i0.Output, args: ["resourceEvent"] }], tableRuntimeConfigChange: [{
|
|
5981
6634
|
type: Output
|
|
6635
|
+
}], drawerOpen: [{
|
|
6636
|
+
type: Output
|
|
6637
|
+
}], drawerClose: [{
|
|
6638
|
+
type: Output
|
|
5982
6639
|
}], crudAuthoringDocumentApplied: [{
|
|
5983
6640
|
type: Output
|
|
5984
6641
|
}], crudAuthoringDocumentSaved: [{
|
|
5985
6642
|
type: Output
|
|
6643
|
+
}], kpiCardClick: [{
|
|
6644
|
+
type: Output
|
|
5986
6645
|
}], table: [{
|
|
5987
6646
|
type: ViewChild,
|
|
5988
6647
|
args: [PraxisTable]
|
|
@@ -6703,7 +7362,7 @@ class DynamicFormDialogHostComponent {
|
|
|
6703
7362
|
(reactiveDeterminationPendingChange)="onReactiveDeterminationPendingChange($event)"
|
|
6704
7363
|
></praxis-dynamic-form>
|
|
6705
7364
|
</mat-dialog-content>
|
|
6706
|
-
`, isInline: true, styles: ["praxis-dynamic-form-dialog-host{--dlg-header-h: 56px;--dlg-footer-h: 56px;--dlg-pad: 16px;display:flex;flex-direction:column;height:100%;overflow:hidden}praxis-dynamic-form-dialog-host[data-density=compact]{--dlg-header-h: 44px;--dlg-footer-h: 44px;--dlg-pad: 12px}praxis-dynamic-form-dialog-host .dialog-header{position:sticky;top:0;z-index:1;display:flex;align-items:center;gap:var(--dlg-pad);min-height:var(--dlg-header-h);padding:10px var(--dlg-pad);margin:0;background:var(--md-sys-color-surface-container-high);border-bottom:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface)}praxis-dynamic-form-dialog-host .dialog-title{margin:0;font:inherit;font-weight:600;color:var(--md-sys-color-on-surface)}praxis-dynamic-form-dialog-host .dialog-heading{display:grid;min-width:0;gap:2px}praxis-dynamic-form-dialog-host .dialog-title-icon{display:inline-grid;flex:0 0 auto;width:36px;height:36px;place-items:center;border-radius:10px;color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent)}praxis-dynamic-form-dialog-host .dialog-title-icon mat-icon{width:22px;height:22px;font-size:22px}praxis-dynamic-form-dialog-host .dialog-subtitle{display:-webkit-box;overflow:hidden;color:var(--md-sys-color-on-surface-variant);font-size:.82rem;font-weight:400;line-height:1.35;-webkit-box-orient:vertical;-webkit-line-clamp:2}praxis-dynamic-form-dialog-host .spacer{flex:1}praxis-dynamic-form-dialog-host .dialog-content{flex:1 1 auto;overflow:auto;padding:var(--dlg-pad);max-height:calc(100svh - var(--dlg-header-h) - 32px)}praxis-dynamic-form-dialog-host .crud-operation-context{position:sticky;top:0;z-index:1;display:grid;gap:.75rem;margin-block-end:var(--dlg-pad);padding-block:.5rem .75rem;background:var(--pfx-form-surface, var(--md-sys-color-surface));border-bottom:1px solid var(--md-sys-color-outline-variant)}praxis-dynamic-form-dialog-host .crud-resource-identity{display:grid;gap:.25rem;min-width:0}praxis-dynamic-form-dialog-host .crud-resource-identity__label{color:var(--md-sys-color-on-surface-variant);font:var(--md-sys-typescale-label-medium, 500 .75rem/1rem inherit)}praxis-dynamic-form-dialog-host.praxis-drawer{--dlg-header-h: 72px;width:100%;min-width:0;max-width:100vw;height:100dvh;background:var(--pfx-form-surface, var(--md-sys-color-surface));color:var(--md-sys-color-on-surface)}praxis-dynamic-form-dialog-host.praxis-drawer .dialog-header{background:color-mix(in srgb,var(--md-sys-color-surface-container-high, var(--md-sys-color-surface)),transparent 4%)}praxis-dynamic-form-dialog-host.praxis-drawer .dialog-content{display:flex;flex-direction:column;max-height:none;min-height:0;padding:clamp(12px,2.4vw,24px)}praxis-dynamic-form-dialog-host.praxis-drawer .dialog-content>praxis-dynamic-form{display:block;flex:1 1 auto;min-height:0}praxis-dynamic-form-dialog-host.praxis-drawer .dialog-content>praxis-dynamic-form>.praxis-dynamic-form{min-height:100%}praxis-dynamic-form-dialog-host.praxis-drawer .dialog-content>praxis-dynamic-form>.praxis-dynamic-form>praxis-form-actions[data-actions-placement=afterSections]{margin-top:auto;padding-top:var(--pfx-actions-gap-top, var(--pfx-section-gap, 20px))}praxis-dynamic-form-dialog-host.praxis-surface-frame .dialog-content{max-height:none;min-height:0;padding:clamp(12px,2.4vw,24px)}praxis-dynamic-form-dialog-host .dialog-header button.praxis-icon-button{color:var(--md-sys-color-on-surface-variant)}praxis-dynamic-form-dialog-host .dialog-header button.praxis-icon-button:hover{color:var(--md-sys-color-primary)}praxis-dynamic-form-dialog-host .dialog-footer{position:sticky;bottom:0;z-index:1;padding:var(--dlg-pad)}.pfx-blur-backdrop{background-color:var(--pfx-backdrop, rgba(15, 23, 42, .42))!important;backdrop-filter:blur(var(--pfx-backdrop-blur, 10px)) saturate(110%);-webkit-backdrop-filter:blur(var(--pfx-backdrop-blur, 10px)) saturate(110%)}.pfx-transparent-backdrop{background-color:transparent!important}.cdk-overlay-pane.pfx-dialog-pane{overflow:hidden;transition:width .2s ease,height .2s ease,margin .2s ease}.cdk-overlay-pane.pfx-dialog-pane .mat-mdc-dialog-surface,.cdk-overlay-pane.pfx-dialog-pane .mdc-dialog__surface{display:flex;flex-direction:column;width:100%;min-width:0;height:100%;max-height:inherit;overflow:hidden;background:var(--pfx-form-surface, var(--md-sys-color-surface))!important;border:1px solid var(--pfx-form-stroke, var(--md-sys-color-outline-variant))!important}.cdk-overlay-pane.pfx-dialog-pane.pfx-dialog-frosted .mat-mdc-dialog-surface,.cdk-overlay-pane.pfx-dialog-pane.pfx-dialog-frosted .mdc-dialog__surface{backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.cdk-overlay-pane.pfx-drawer-pane{margin:0!important;border-radius:0!important;box-shadow:var(--md-sys-elevation-level3, 0 24px 80px rgba(15, 23, 42, .28)),0 0 0 1px color-mix(in srgb,var(--md-sys-color-outline, #64748b) 24%,transparent)}.cdk-overlay-pane.pfx-drawer-pane.pfx-drawer-maximized{margin:var(--pfx-drawer-edge-gap, 8px)!important}.cdk-overlay-pane.pfx-drawer-pane .mat-mdc-dialog-surface,.cdk-overlay-pane.pfx-drawer-pane .mdc-dialog__surface{min-width:0!important;border-radius:0!important}\n"], dependencies: [{ kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type:
|
|
7365
|
+
`, isInline: true, styles: ["praxis-dynamic-form-dialog-host{--dlg-header-h: 56px;--dlg-footer-h: 56px;--dlg-pad: 16px;display:flex;flex-direction:column;height:100%;overflow:hidden}praxis-dynamic-form-dialog-host[data-density=compact]{--dlg-header-h: 44px;--dlg-footer-h: 44px;--dlg-pad: 12px}praxis-dynamic-form-dialog-host .dialog-header{position:sticky;top:0;z-index:1;display:flex;align-items:center;gap:var(--dlg-pad);min-height:var(--dlg-header-h);padding:10px var(--dlg-pad);margin:0;background:var(--md-sys-color-surface-container-high);border-bottom:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface)}praxis-dynamic-form-dialog-host .dialog-title{margin:0;font:inherit;font-weight:600;color:var(--md-sys-color-on-surface)}praxis-dynamic-form-dialog-host .dialog-heading{display:grid;min-width:0;gap:2px}praxis-dynamic-form-dialog-host .dialog-title-icon{display:inline-grid;flex:0 0 auto;width:36px;height:36px;place-items:center;border-radius:10px;color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent)}praxis-dynamic-form-dialog-host .dialog-title-icon mat-icon{width:22px;height:22px;font-size:22px}praxis-dynamic-form-dialog-host .dialog-subtitle{display:-webkit-box;overflow:hidden;color:var(--md-sys-color-on-surface-variant);font-size:.82rem;font-weight:400;line-height:1.35;-webkit-box-orient:vertical;-webkit-line-clamp:2}praxis-dynamic-form-dialog-host .spacer{flex:1}praxis-dynamic-form-dialog-host .dialog-content{flex:1 1 auto;overflow:auto;padding:var(--dlg-pad);max-height:calc(100svh - var(--dlg-header-h) - 32px)}praxis-dynamic-form-dialog-host .crud-operation-context{position:sticky;top:0;z-index:1;display:grid;gap:.75rem;margin-block-end:var(--dlg-pad);padding-block:.5rem .75rem;background:var(--pfx-form-surface, var(--md-sys-color-surface));border-bottom:1px solid var(--md-sys-color-outline-variant)}praxis-dynamic-form-dialog-host .crud-resource-identity{display:grid;gap:.25rem;min-width:0}praxis-dynamic-form-dialog-host .crud-resource-identity__label{color:var(--md-sys-color-on-surface-variant);font:var(--md-sys-typescale-label-medium, 500 .75rem/1rem inherit)}praxis-dynamic-form-dialog-host.praxis-drawer{--dlg-header-h: 72px;width:100%;min-width:0;max-width:100vw;height:100dvh;background:var(--pfx-form-surface, var(--md-sys-color-surface));color:var(--md-sys-color-on-surface)}praxis-dynamic-form-dialog-host.praxis-drawer .dialog-header{background:color-mix(in srgb,var(--md-sys-color-surface-container-high, var(--md-sys-color-surface)),transparent 4%)}praxis-dynamic-form-dialog-host.praxis-drawer .dialog-content{display:flex;flex-direction:column;max-height:none;min-height:0;padding:clamp(12px,2.4vw,24px)}praxis-dynamic-form-dialog-host.praxis-drawer .dialog-content>praxis-dynamic-form{display:block;flex:1 1 auto;min-height:0}praxis-dynamic-form-dialog-host.praxis-drawer .dialog-content>praxis-dynamic-form>.praxis-dynamic-form{min-height:100%}praxis-dynamic-form-dialog-host.praxis-drawer .dialog-content>praxis-dynamic-form>.praxis-dynamic-form>praxis-form-actions[data-actions-placement=afterSections]{margin-top:auto;padding-top:var(--pfx-actions-gap-top, var(--pfx-section-gap, 20px))}praxis-dynamic-form-dialog-host.praxis-surface-frame .dialog-content{max-height:none;min-height:0;padding:clamp(12px,2.4vw,24px)}praxis-dynamic-form-dialog-host .dialog-header button.praxis-icon-button{color:var(--md-sys-color-on-surface-variant)}praxis-dynamic-form-dialog-host .dialog-header button.praxis-icon-button:hover{color:var(--md-sys-color-primary)}praxis-dynamic-form-dialog-host .dialog-footer{position:sticky;bottom:0;z-index:1;padding:var(--dlg-pad)}.pfx-blur-backdrop{background-color:var(--pfx-backdrop, rgba(15, 23, 42, .42))!important;backdrop-filter:blur(var(--pfx-backdrop-blur, 10px)) saturate(110%);-webkit-backdrop-filter:blur(var(--pfx-backdrop-blur, 10px)) saturate(110%)}.pfx-transparent-backdrop{background-color:transparent!important}.cdk-overlay-pane.pfx-dialog-pane{overflow:hidden;transition:width .2s ease,height .2s ease,margin .2s ease}.cdk-overlay-pane.pfx-dialog-pane .mat-mdc-dialog-surface,.cdk-overlay-pane.pfx-dialog-pane .mdc-dialog__surface{display:flex;flex-direction:column;width:100%;min-width:0;height:100%;max-height:inherit;overflow:hidden;background:var(--pfx-form-surface, var(--md-sys-color-surface))!important;border:1px solid var(--pfx-form-stroke, var(--md-sys-color-outline-variant))!important}.cdk-overlay-pane.pfx-dialog-pane.pfx-dialog-frosted .mat-mdc-dialog-surface,.cdk-overlay-pane.pfx-dialog-pane.pfx-dialog-frosted .mdc-dialog__surface{backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.cdk-overlay-pane.pfx-drawer-pane{margin:0!important;border-radius:0!important;box-shadow:var(--md-sys-elevation-level3, 0 24px 80px rgba(15, 23, 42, .28)),0 0 0 1px color-mix(in srgb,var(--md-sys-color-outline, #64748b) 24%,transparent)}.cdk-overlay-pane.pfx-drawer-pane.pfx-drawer-maximized{margin:var(--pfx-drawer-edge-gap, 8px)!important}.cdk-overlay-pane.pfx-drawer-pane .mat-mdc-dialog-surface,.cdk-overlay-pane.pfx-drawer-pane .mdc-dialog__surface{min-width:0!important;border-radius:0!important}\n"], dependencies: [{ kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1$1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1$1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: PraxisResourceIdentityComponent, selector: "praxis-resource-identity", inputs: ["identity", "emptyTitle", "density", "showMetadataLabels", "showKey", "showKeyLabel", "ariaLabel"] }, { kind: "component", type: PraxisDynamicForm, selector: "praxis-dynamic-form", inputs: ["resourcePath", "resourceId", "initialValue", "emptyState", "editorialContext", "mode", "config", "actions", "schemaSource", "schemaUrl", "readUrl", "submitUrl", "submitMethod", "submitIdempotencyKey", "submitCorrelationId", "submitResourceVersion", "submitResourceVersionTargetResourceKey", "submitResourceVersionTargetIdField", "responseSchemaUrl", "apiEndpointKey", "apiUrlEntry", "enableCustomization", "showAiAssistant", "formId", "componentInstanceId", "configPersistenceStrategy", "layout", "layoutMode", "formLayout", "generatedLayoutPreset", "layoutPolicy", "backConfig", "hooks", "removeEmptyContainersOnSave", "reactiveValidation", "reactiveValidationDebounceMs", "notifyIfOutdated", "snoozeMs", "autoOpenSettingsOnOutdated", "readonlyModeGlobal", "disabledModeGlobal", "presentationModeGlobal", "presentation", "presentationPreset", "sectionDefaultAppearance", "sectionDivider", "visibleGlobal", "fieldIconPolicy", "domainRules", "customEndpoints"], outputs: ["formSubmit", "formCancel", "formReset", "configChange", "configPatchChange", "formReady", "valueChange", "payloadPreviewChange", "syncCompleted", "initializationError", "loadingStateChange", "enableCustomizationChange", "customAction", "actionConfirmation", "schemaStatusChange", "fieldRenderError", "ruleDiagnosticsChange", "reactiveDeterminationExecuted", "reactiveDeterminationPendingChange", "tabChange", "tabSelected"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
6707
7366
|
}
|
|
6708
7367
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicFormDialogHostComponent, decorators: [{
|
|
6709
7368
|
type: Component,
|
|
@@ -6952,8 +7611,8 @@ function lowerFirstLetter(value) {
|
|
|
6952
7611
|
}
|
|
6953
7612
|
|
|
6954
7613
|
var dynamicFormDialogHost_component = /*#__PURE__*/Object.freeze({
|
|
6955
|
-
|
|
6956
|
-
|
|
7614
|
+
__proto__: null,
|
|
7615
|
+
DynamicFormDialogHostComponent: DynamicFormDialogHostComponent
|
|
6957
7616
|
});
|
|
6958
7617
|
|
|
6959
7618
|
class PraxisCrudWidgetConfigEditor {
|
|
@@ -7638,7 +8297,7 @@ class CrudPageHeaderComponent {
|
|
|
7638
8297
|
<ng-content></ng-content>
|
|
7639
8298
|
</div>
|
|
7640
8299
|
</header>
|
|
7641
|
-
`, isInline: true, styles: [".crud-header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 0;background:var(--md-sys-color-surface)}.crud-header.sticky{position:sticky;top:0;z-index:10;-webkit-backdrop-filter:saturate(110%);backdrop-filter:saturate(110%)}.crud-header.with-divider{border-bottom:1px solid var(--md-sys-color-outline-variant)}.left{display:flex;align-items:center;gap:8px;min-width:0}.right{display:flex;align-items:center;gap:8px}.title{margin:0;font-weight:600;color:var(--md-sys-color-on-surface, currentColor);font:var(--mdc-typography-title-large, 600 20px/28px system-ui);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.back-btn{display:inline-flex;align-items:center;gap:6px;text-decoration:none}.back-btn .mat-mdc-button{padding-left:0}.back-btn mat-icon{color:var(--md-sys-color-on-surface-variant, currentColor)}.back-btn .label{color:var(--md-sys-color-on-surface-variant, currentColor)}.back-btn.ghost{border-radius:20px;padding:4px 8px}.back-btn.ghost:hover{background:var(--md-sys-color-primary-container)}.back-btn.tonal{border-radius:20px;padding:4px 10px;background:var(--md-sys-color-surface-container);box-shadow:inset 0 0 0 1px var(--md-sys-color-outline-variant)}.back-btn.tonal:hover{background:var(--md-sys-color-primary-container)}.back-btn.outlined{border-radius:20px;padding:4px 10px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface)}.back-btn.outlined:hover{border-color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container)}@media(max-width:599px){.label.hide-on-narrow{display:none}}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type:
|
|
8300
|
+
`, isInline: true, styles: [".crud-header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 0;background:var(--md-sys-color-surface)}.crud-header.sticky{position:sticky;top:0;z-index:10;-webkit-backdrop-filter:saturate(110%);backdrop-filter:saturate(110%)}.crud-header.with-divider{border-bottom:1px solid var(--md-sys-color-outline-variant)}.left{display:flex;align-items:center;gap:8px;min-width:0}.right{display:flex;align-items:center;gap:8px}.title{margin:0;font-weight:600;color:var(--md-sys-color-on-surface, currentColor);font:var(--mdc-typography-title-large, 600 20px/28px system-ui);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.back-btn{display:inline-flex;align-items:center;gap:6px;text-decoration:none}.back-btn .mat-mdc-button{padding-left:0}.back-btn mat-icon{color:var(--md-sys-color-on-surface-variant, currentColor)}.back-btn .label{color:var(--md-sys-color-on-surface-variant, currentColor)}.back-btn.ghost{border-radius:20px;padding:4px 8px}.back-btn.ghost:hover{background:var(--md-sys-color-primary-container)}.back-btn.tonal{border-radius:20px;padding:4px 10px;background:var(--md-sys-color-surface-container);box-shadow:inset 0 0 0 1px var(--md-sys-color-outline-variant)}.back-btn.tonal:hover{background:var(--md-sys-color-primary-container)}.back-btn.outlined{border-radius:20px;padding:4px 10px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface)}.back-btn.outlined:hover{border-color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container)}@media(max-width:599px){.label.hide-on-narrow{display:none}}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }] });
|
|
7642
8301
|
}
|
|
7643
8302
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: CrudPageHeaderComponent, decorators: [{
|
|
7644
8303
|
type: Component,
|
|
@@ -8241,6 +8900,522 @@ const PRAXIS_CRUD_AUTHORING_MANIFEST = {
|
|
|
8241
8900
|
],
|
|
8242
8901
|
};
|
|
8243
8902
|
|
|
8903
|
+
/**
|
|
8904
|
+
* Praxis UI Platform — Zero-Code Canonical Resource Page (Issue #38, #40)
|
|
8905
|
+
*
|
|
8906
|
+
* Componente governado de página inteira que orquestra automaticamente a experiência
|
|
8907
|
+
* completa de um recurso corporativo a partir de sua coordenada RESTful ('resource' / 'resourcePath').
|
|
8908
|
+
*
|
|
8909
|
+
* Suporta nativamente:
|
|
8910
|
+
* - Auto-Header Governado (domínio, título, subtítulo e ações)
|
|
8911
|
+
* - Auto-ScopeBar Integrado (filtros rápidos em chips conectados diretamente ao CRUD)
|
|
8912
|
+
* - Auto-KPI Band Nativo (sincronização bidirecional entre cards e escopos)
|
|
8913
|
+
* - Customização de colunas e tabela via configuração declarativa
|
|
8914
|
+
* - Isolamento multi-tenant / persona com reload seguro em trocas de identidade
|
|
8915
|
+
*
|
|
8916
|
+
* Pode ser utilizado diretamente como alvo de rotas do Angular:
|
|
8917
|
+
* ```typescript
|
|
8918
|
+
* {
|
|
8919
|
+
* path: 'missoes',
|
|
8920
|
+
* component: PraxisResourcePage,
|
|
8921
|
+
* data: {
|
|
8922
|
+
* resource: 'operations/missoes',
|
|
8923
|
+
* title: 'Centro de Missões',
|
|
8924
|
+
* subtitle: 'Planejamento e acompanhamento em campo.',
|
|
8925
|
+
* domain: { label: 'Operações Táticas', icon: 'military_tech', tone: 'operations' },
|
|
8926
|
+
* scopeBar: { ... }
|
|
8927
|
+
* }
|
|
8928
|
+
* }
|
|
8929
|
+
* ```
|
|
8930
|
+
*/
|
|
8931
|
+
class PraxisResourcePage {
|
|
8932
|
+
route = inject(ActivatedRoute, { optional: true });
|
|
8933
|
+
routeSub;
|
|
8934
|
+
resource;
|
|
8935
|
+
resourcePath;
|
|
8936
|
+
crudId;
|
|
8937
|
+
metadata;
|
|
8938
|
+
title;
|
|
8939
|
+
subtitle;
|
|
8940
|
+
domain;
|
|
8941
|
+
scopeBar;
|
|
8942
|
+
scopeItems;
|
|
8943
|
+
defaultScopeId;
|
|
8944
|
+
enableCustomization = false;
|
|
8945
|
+
tableConfigPersistenceStrategy = 'local-first';
|
|
8946
|
+
context;
|
|
8947
|
+
actions;
|
|
8948
|
+
filterCriteria;
|
|
8949
|
+
rowClick = new EventEmitter();
|
|
8950
|
+
rowAction = new EventEmitter();
|
|
8951
|
+
rowDoubleClick = new EventEmitter();
|
|
8952
|
+
selectionChange = new EventEmitter();
|
|
8953
|
+
drawerOpen = new EventEmitter();
|
|
8954
|
+
drawerClose = new EventEmitter();
|
|
8955
|
+
afterOpen = new EventEmitter();
|
|
8956
|
+
afterClose = new EventEmitter();
|
|
8957
|
+
kpiCardClick = new EventEmitter();
|
|
8958
|
+
afterSave = new EventEmitter();
|
|
8959
|
+
afterDelete = new EventEmitter();
|
|
8960
|
+
error = new EventEmitter();
|
|
8961
|
+
routeResourceSignal = signal(null, ...(ngDevMode ? [{ debugName: "routeResourceSignal" }] : /* istanbul ignore next */ []));
|
|
8962
|
+
routeMetadataSignal = signal(null, ...(ngDevMode ? [{ debugName: "routeMetadataSignal" }] : /* istanbul ignore next */ []));
|
|
8963
|
+
routeTitleSignal = signal(null, ...(ngDevMode ? [{ debugName: "routeTitleSignal" }] : /* istanbul ignore next */ []));
|
|
8964
|
+
routeSubtitleSignal = signal(null, ...(ngDevMode ? [{ debugName: "routeSubtitleSignal" }] : /* istanbul ignore next */ []));
|
|
8965
|
+
routeDomainSignal = signal(null, ...(ngDevMode ? [{ debugName: "routeDomainSignal" }] : /* istanbul ignore next */ []));
|
|
8966
|
+
routeScopeBarSignal = signal(null, ...(ngDevMode ? [{ debugName: "routeScopeBarSignal" }] : /* istanbul ignore next */ []));
|
|
8967
|
+
routeCustomizationSignal = signal(null, ...(ngDevMode ? [{ debugName: "routeCustomizationSignal" }] : /* istanbul ignore next */ []));
|
|
8968
|
+
identityRenderKey = signal(0, ...(ngDevMode ? [{ debugName: "identityRenderKey" }] : /* istanbul ignore next */ []));
|
|
8969
|
+
identityVisible = signal(true, ...(ngDevMode ? [{ debugName: "identityVisible" }] : /* istanbul ignore next */ []));
|
|
8970
|
+
activeScopeId = signal('all', ...(ngDevMode ? [{ debugName: "activeScopeId" }] : /* istanbul ignore next */ []));
|
|
8971
|
+
activeScopeFilter = signal({}, ...(ngDevMode ? [{ debugName: "activeScopeFilter" }] : /* istanbul ignore next */ []));
|
|
8972
|
+
effectiveResource = computed(() => {
|
|
8973
|
+
return this.resource || this.resourcePath || this.routeResourceSignal();
|
|
8974
|
+
}, ...(ngDevMode ? [{ debugName: "effectiveResource" }] : /* istanbul ignore next */ []));
|
|
8975
|
+
effectiveTitle = computed(() => {
|
|
8976
|
+
return this.title || this.routeTitleSignal();
|
|
8977
|
+
}, ...(ngDevMode ? [{ debugName: "effectiveTitle" }] : /* istanbul ignore next */ []));
|
|
8978
|
+
effectiveSubtitle = computed(() => {
|
|
8979
|
+
return this.subtitle || this.routeSubtitleSignal();
|
|
8980
|
+
}, ...(ngDevMode ? [{ debugName: "effectiveSubtitle" }] : /* istanbul ignore next */ []));
|
|
8981
|
+
effectiveDomain = computed(() => {
|
|
8982
|
+
return this.domain || this.routeDomainSignal();
|
|
8983
|
+
}, ...(ngDevMode ? [{ debugName: "effectiveDomain" }] : /* istanbul ignore next */ []));
|
|
8984
|
+
effectiveEnableCustomization = computed(() => {
|
|
8985
|
+
return this.enableCustomization || this.routeCustomizationSignal() || false;
|
|
8986
|
+
}, ...(ngDevMode ? [{ debugName: "effectiveEnableCustomization" }] : /* istanbul ignore next */ []));
|
|
8987
|
+
effectiveScopeBar = computed(() => {
|
|
8988
|
+
if (this.scopeBar)
|
|
8989
|
+
return this.scopeBar;
|
|
8990
|
+
if (this.scopeItems && this.scopeItems.length > 0) {
|
|
8991
|
+
return {
|
|
8992
|
+
items: this.scopeItems,
|
|
8993
|
+
leadLabel: 'Filtro:',
|
|
8994
|
+
leadIcon: 'tune',
|
|
8995
|
+
};
|
|
8996
|
+
}
|
|
8997
|
+
const fromRoute = this.routeScopeBarSignal();
|
|
8998
|
+
if (fromRoute)
|
|
8999
|
+
return fromRoute;
|
|
9000
|
+
// Auto-promoção declarativa a partir de metadata.table.toolbar.filters.quickFilters
|
|
9001
|
+
const metaSource = this.metadata || this.routeMetadataSignal();
|
|
9002
|
+
let meta = null;
|
|
9003
|
+
if (typeof metaSource === 'string' && metaSource.trim().startsWith('{')) {
|
|
9004
|
+
try {
|
|
9005
|
+
meta = JSON.parse(metaSource);
|
|
9006
|
+
}
|
|
9007
|
+
catch { }
|
|
9008
|
+
}
|
|
9009
|
+
else if (metaSource && typeof metaSource === 'object') {
|
|
9010
|
+
meta = metaSource;
|
|
9011
|
+
}
|
|
9012
|
+
const quickFilters = meta?.table?.toolbar?.filters?.quickFilters;
|
|
9013
|
+
if (Array.isArray(quickFilters) && quickFilters.length > 0) {
|
|
9014
|
+
return {
|
|
9015
|
+
items: quickFilters.map((qf) => ({
|
|
9016
|
+
id: qf.id,
|
|
9017
|
+
label: qf.label,
|
|
9018
|
+
filter: qf.filter,
|
|
9019
|
+
icon: qf.icon,
|
|
9020
|
+
tone: qf.tone,
|
|
9021
|
+
badge: qf.badge,
|
|
9022
|
+
count: qf.count,
|
|
9023
|
+
})),
|
|
9024
|
+
leadLabel: 'Filtro:',
|
|
9025
|
+
leadIcon: 'tune',
|
|
9026
|
+
};
|
|
9027
|
+
}
|
|
9028
|
+
return null;
|
|
9029
|
+
}, ...(ngDevMode ? [{ debugName: "effectiveScopeBar" }] : /* istanbul ignore next */ []));
|
|
9030
|
+
resolvedCrudId = computed(() => {
|
|
9031
|
+
if (this.crudId)
|
|
9032
|
+
return this.crudId;
|
|
9033
|
+
const res = this.effectiveResource();
|
|
9034
|
+
return res ? `crud-${res.replace(/\//g, '-')}` : 'praxis-crud-auto';
|
|
9035
|
+
}, ...(ngDevMode ? [{ debugName: "resolvedCrudId" }] : /* istanbul ignore next */ []));
|
|
9036
|
+
effectiveMetadata = computed(() => {
|
|
9037
|
+
const metaSource = this.metadata || this.routeMetadataSignal();
|
|
9038
|
+
let base;
|
|
9039
|
+
if (typeof metaSource === 'string') {
|
|
9040
|
+
const trimmed = metaSource.trim();
|
|
9041
|
+
base = trimmed.startsWith('{')
|
|
9042
|
+
? JSON.parse(trimmed)
|
|
9043
|
+
: {
|
|
9044
|
+
component: 'praxis-crud',
|
|
9045
|
+
resource: { path: trimmed, idField: 'id' },
|
|
9046
|
+
table: { columns: [] },
|
|
9047
|
+
};
|
|
9048
|
+
}
|
|
9049
|
+
else if (metaSource) {
|
|
9050
|
+
base = { ...metaSource };
|
|
9051
|
+
}
|
|
9052
|
+
else {
|
|
9053
|
+
const res = this.effectiveResource() || 'recurso-auto';
|
|
9054
|
+
base = {
|
|
9055
|
+
component: 'praxis-crud',
|
|
9056
|
+
resource: { path: res, idField: 'id' },
|
|
9057
|
+
table: { columns: [] },
|
|
9058
|
+
};
|
|
9059
|
+
}
|
|
9060
|
+
if (this.actions) {
|
|
9061
|
+
base.actions = [...(base.actions || []), ...this.actions];
|
|
9062
|
+
}
|
|
9063
|
+
// Se o ScopeBar estiver ativo no cabeçalho (seja manual ou auto-promovido),
|
|
9064
|
+
// suprimir os botões redundantes de quickFilters na toolbar interna da tabela
|
|
9065
|
+
if (this.effectiveScopeBar() && base.table?.toolbar?.filters) {
|
|
9066
|
+
base.table = {
|
|
9067
|
+
...base.table,
|
|
9068
|
+
toolbar: {
|
|
9069
|
+
...base.table.toolbar,
|
|
9070
|
+
filters: {
|
|
9071
|
+
...base.table.toolbar.filters,
|
|
9072
|
+
showQuickFilters: false,
|
|
9073
|
+
},
|
|
9074
|
+
},
|
|
9075
|
+
};
|
|
9076
|
+
}
|
|
9077
|
+
// Mesclar filterCriteria com filtro tático do ScopeBar ativo
|
|
9078
|
+
const combinedFilterCriteria = {
|
|
9079
|
+
...(base.filterCriteria || {}),
|
|
9080
|
+
...(this.filterCriteria || {}),
|
|
9081
|
+
...this.activeScopeFilter(),
|
|
9082
|
+
};
|
|
9083
|
+
base.filterCriteria = combinedFilterCriteria;
|
|
9084
|
+
return base;
|
|
9085
|
+
}, ...(ngDevMode ? [{ debugName: "effectiveMetadata" }] : /* istanbul ignore next */ []));
|
|
9086
|
+
defaultMetadata = computed(() => {
|
|
9087
|
+
return this.effectiveMetadata();
|
|
9088
|
+
}, ...(ngDevMode ? [{ debugName: "defaultMetadata" }] : /* istanbul ignore next */ []));
|
|
9089
|
+
onIdentitySwitch = () => {
|
|
9090
|
+
this.activeScopeFilter.set({});
|
|
9091
|
+
this.activeScopeId.set(this.defaultScopeId || 'all');
|
|
9092
|
+
this.identityRenderKey.update((k) => k + 1);
|
|
9093
|
+
this.identityVisible.set(false);
|
|
9094
|
+
queueMicrotask(() => this.identityVisible.set(true));
|
|
9095
|
+
};
|
|
9096
|
+
ngOnInit() {
|
|
9097
|
+
const sb = this.effectiveScopeBar();
|
|
9098
|
+
const initialId = this.defaultScopeId ||
|
|
9099
|
+
sb?.activeId ||
|
|
9100
|
+
sb?.items?.find((i) => i.isDefault)?.id ||
|
|
9101
|
+
'all';
|
|
9102
|
+
this.activeScopeId.set(initialId);
|
|
9103
|
+
const initialItem = sb?.items?.find((i) => i.id === initialId);
|
|
9104
|
+
if (initialItem) {
|
|
9105
|
+
this.applyItemFilter(initialItem);
|
|
9106
|
+
}
|
|
9107
|
+
if (typeof window !== 'undefined') {
|
|
9108
|
+
window.addEventListener('praxis:identity-switch', this.onIdentitySwitch);
|
|
9109
|
+
}
|
|
9110
|
+
if (this.route) {
|
|
9111
|
+
// 1. Extração estática síncrona
|
|
9112
|
+
const data = this.route.snapshot.data || {};
|
|
9113
|
+
const params = this.route.snapshot.params || {};
|
|
9114
|
+
const dataResource = data['resource'] || data['resourcePath'];
|
|
9115
|
+
const paramResource = this.route.snapshot.paramMap?.get('resource') || params['resource'];
|
|
9116
|
+
const initialRes = dataResource || paramResource || null;
|
|
9117
|
+
if (initialRes) {
|
|
9118
|
+
this.routeResourceSignal.set(initialRes);
|
|
9119
|
+
}
|
|
9120
|
+
this.extractRouteData(data);
|
|
9121
|
+
// 2. Assinatura reativa para mudanças dinâmicas de rota
|
|
9122
|
+
this.routeSub = new Subscription();
|
|
9123
|
+
if (this.route.params) {
|
|
9124
|
+
this.routeSub.add(this.route.params.subscribe((p) => {
|
|
9125
|
+
if (p['resource']) {
|
|
9126
|
+
this.routeResourceSignal.set(p['resource']);
|
|
9127
|
+
}
|
|
9128
|
+
}));
|
|
9129
|
+
}
|
|
9130
|
+
if (this.route.data) {
|
|
9131
|
+
this.routeSub.add(this.route.data.subscribe((d) => {
|
|
9132
|
+
const nextRes = d['resource'] || d['resourcePath'];
|
|
9133
|
+
if (nextRes) {
|
|
9134
|
+
this.routeResourceSignal.set(nextRes);
|
|
9135
|
+
}
|
|
9136
|
+
this.extractRouteData(d);
|
|
9137
|
+
}));
|
|
9138
|
+
}
|
|
9139
|
+
}
|
|
9140
|
+
}
|
|
9141
|
+
ngOnDestroy() {
|
|
9142
|
+
this.routeSub?.unsubscribe();
|
|
9143
|
+
if (typeof window !== 'undefined') {
|
|
9144
|
+
window.removeEventListener('praxis:identity-switch', this.onIdentitySwitch);
|
|
9145
|
+
}
|
|
9146
|
+
}
|
|
9147
|
+
onScopeChange(item) {
|
|
9148
|
+
this.activeScopeId.set(item.id);
|
|
9149
|
+
this.applyItemFilter(item);
|
|
9150
|
+
}
|
|
9151
|
+
onScopeClear() {
|
|
9152
|
+
const sb = this.effectiveScopeBar();
|
|
9153
|
+
const defaultItem = sb?.items?.find((item) => item.isDefault) ||
|
|
9154
|
+
sb?.items?.find((item) => item.id === 'all');
|
|
9155
|
+
if (defaultItem) {
|
|
9156
|
+
this.onScopeChange(defaultItem);
|
|
9157
|
+
}
|
|
9158
|
+
else {
|
|
9159
|
+
this.activeScopeId.set('all');
|
|
9160
|
+
this.activeScopeFilter.set({});
|
|
9161
|
+
}
|
|
9162
|
+
}
|
|
9163
|
+
handleKpiCardClick(event) {
|
|
9164
|
+
const cardFilter = event.card.filter;
|
|
9165
|
+
if (cardFilter && typeof cardFilter === 'object') {
|
|
9166
|
+
const sb = this.effectiveScopeBar();
|
|
9167
|
+
if (sb && sb.items) {
|
|
9168
|
+
const matched = sb.items.find((item) => JSON.stringify(item.filter) === JSON.stringify(cardFilter));
|
|
9169
|
+
if (matched) {
|
|
9170
|
+
this.onScopeChange(matched);
|
|
9171
|
+
}
|
|
9172
|
+
}
|
|
9173
|
+
}
|
|
9174
|
+
this.kpiCardClick.emit(event);
|
|
9175
|
+
}
|
|
9176
|
+
applyItemFilter(item) {
|
|
9177
|
+
let filterObj = {};
|
|
9178
|
+
if (item.filter && typeof item.filter === 'object') {
|
|
9179
|
+
filterObj = item.filter;
|
|
9180
|
+
}
|
|
9181
|
+
else if (typeof item.filter === 'string') {
|
|
9182
|
+
const trimmed = item.filter.trim();
|
|
9183
|
+
if (trimmed.startsWith('{')) {
|
|
9184
|
+
try {
|
|
9185
|
+
filterObj = JSON.parse(trimmed);
|
|
9186
|
+
}
|
|
9187
|
+
catch {
|
|
9188
|
+
filterObj = { query: trimmed };
|
|
9189
|
+
}
|
|
9190
|
+
}
|
|
9191
|
+
else if (trimmed) {
|
|
9192
|
+
filterObj = { query: trimmed };
|
|
9193
|
+
}
|
|
9194
|
+
}
|
|
9195
|
+
this.activeScopeFilter.set(filterObj);
|
|
9196
|
+
}
|
|
9197
|
+
extractRouteData(data) {
|
|
9198
|
+
if ('metadata' in data) {
|
|
9199
|
+
this.routeMetadataSignal.set(data['metadata'] ?? null);
|
|
9200
|
+
}
|
|
9201
|
+
if ('title' in data) {
|
|
9202
|
+
this.routeTitleSignal.set(data['title'] ?? null);
|
|
9203
|
+
}
|
|
9204
|
+
if ('subtitle' in data) {
|
|
9205
|
+
this.routeSubtitleSignal.set(data['subtitle'] ?? null);
|
|
9206
|
+
}
|
|
9207
|
+
if ('domain' in data) {
|
|
9208
|
+
this.routeDomainSignal.set(data['domain'] ?? null);
|
|
9209
|
+
}
|
|
9210
|
+
if ('scopeBar' in data) {
|
|
9211
|
+
this.routeScopeBarSignal.set(data['scopeBar'] ?? null);
|
|
9212
|
+
}
|
|
9213
|
+
if (typeof data['enableCustomization'] === 'boolean') {
|
|
9214
|
+
this.routeCustomizationSignal.set(data['enableCustomization']);
|
|
9215
|
+
}
|
|
9216
|
+
}
|
|
9217
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisResourcePage, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9218
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisResourcePage, isStandalone: true, selector: "praxis-resource-page", inputs: { resource: "resource", resourcePath: "resourcePath", crudId: "crudId", metadata: "metadata", title: "title", subtitle: "subtitle", domain: "domain", scopeBar: "scopeBar", scopeItems: "scopeItems", defaultScopeId: "defaultScopeId", enableCustomization: "enableCustomization", tableConfigPersistenceStrategy: "tableConfigPersistenceStrategy", context: "context", actions: "actions", filterCriteria: "filterCriteria" }, outputs: { rowClick: "rowClick", rowAction: "rowAction", rowDoubleClick: "rowDoubleClick", selectionChange: "selectionChange", drawerOpen: "drawerOpen", drawerClose: "drawerClose", afterOpen: "afterOpen", afterClose: "afterClose", kpiCardClick: "kpiCardClick", afterSave: "afterSave", afterDelete: "afterDelete", error: "error" }, ngImport: i0, template: `
|
|
9219
|
+
<div class="praxis-resource-page page-container">
|
|
9220
|
+
<!-- Auto-Header Governado -->
|
|
9221
|
+
@if (effectiveTitle() || effectiveDomain()) {
|
|
9222
|
+
<header class="praxis-resource-page__header section-header">
|
|
9223
|
+
<div class="praxis-resource-page__header-main">
|
|
9224
|
+
@if (effectiveDomain(); as dom) {
|
|
9225
|
+
<div
|
|
9226
|
+
class="praxis-resource-page__domain-badge domain-tag"
|
|
9227
|
+
[ngClass]="dom.tone ? 'tone-' + dom.tone : ''"
|
|
9228
|
+
>
|
|
9229
|
+
@if (dom.icon) {
|
|
9230
|
+
<span class="material-symbols-outlined">{{ dom.icon }}</span>
|
|
9231
|
+
}
|
|
9232
|
+
<span>{{ dom.label }}</span>
|
|
9233
|
+
</div>
|
|
9234
|
+
}
|
|
9235
|
+
@if (effectiveTitle(); as t) {
|
|
9236
|
+
<h1 class="praxis-resource-page__title page-title title-gradient">{{ t }}</h1>
|
|
9237
|
+
}
|
|
9238
|
+
@if (effectiveSubtitle(); as sub) {
|
|
9239
|
+
<p class="praxis-resource-page__subtitle page-subtitle">{{ sub }}</p>
|
|
9240
|
+
}
|
|
9241
|
+
</div>
|
|
9242
|
+
|
|
9243
|
+
<div class="praxis-resource-page__header-actions">
|
|
9244
|
+
<ng-content select="[page-header-actions]"></ng-content>
|
|
9245
|
+
</div>
|
|
9246
|
+
</header>
|
|
9247
|
+
}
|
|
9248
|
+
|
|
9249
|
+
<!-- Auto-ScopeBar Integrado -->
|
|
9250
|
+
@if (effectiveScopeBar(); as sb) {
|
|
9251
|
+
<praxis-scope-bar
|
|
9252
|
+
[leadLabel]="sb.leadLabel || 'Filtro:'"
|
|
9253
|
+
[leadIcon]="sb.leadIcon || 'tune'"
|
|
9254
|
+
[items]="sb.items || []"
|
|
9255
|
+
[activeId]="activeScopeId()"
|
|
9256
|
+
[showClearButton]="sb.showClearButton ?? (activeScopeId() !== 'all')"
|
|
9257
|
+
[showOmnibox]="sb.showOmnibox ?? false"
|
|
9258
|
+
(scopeChange)="onScopeChange($event)"
|
|
9259
|
+
(clear)="onScopeClear()"
|
|
9260
|
+
/>
|
|
9261
|
+
}
|
|
9262
|
+
|
|
9263
|
+
<!-- Praxis CRUD Runtime com isolamento reativo multi-tenant -->
|
|
9264
|
+
@if (effectiveResource() && identityVisible()) {
|
|
9265
|
+
<section class="praxis-resource-page__crud-surface crud-surface glass-panel">
|
|
9266
|
+
<praxis-crud
|
|
9267
|
+
[resource]="effectiveResource()!"
|
|
9268
|
+
[crudId]="resolvedCrudId()"
|
|
9269
|
+
[metadata]="effectiveMetadata()"
|
|
9270
|
+
[enableCustomization]="effectiveEnableCustomization()"
|
|
9271
|
+
[tableConfigPersistenceStrategy]="tableConfigPersistenceStrategy"
|
|
9272
|
+
[context]="context"
|
|
9273
|
+
(rowClick)="rowClick.emit($event)"
|
|
9274
|
+
(rowAction)="rowAction.emit($event)"
|
|
9275
|
+
(selectionChange)="selectionChange.emit($event)"
|
|
9276
|
+
(drawerOpen)="drawerOpen.emit($event)"
|
|
9277
|
+
(drawerClose)="drawerClose.emit()"
|
|
9278
|
+
(afterOpen)="afterOpen.emit($event)"
|
|
9279
|
+
(afterClose)="afterClose.emit()"
|
|
9280
|
+
(kpiCardClick)="handleKpiCardClick($event)"
|
|
9281
|
+
(afterSave)="afterSave.emit($event)"
|
|
9282
|
+
(afterDelete)="afterDelete.emit($event)"
|
|
9283
|
+
(error)="error.emit($event)"
|
|
9284
|
+
></praxis-crud>
|
|
9285
|
+
</section>
|
|
9286
|
+
}
|
|
9287
|
+
</div>
|
|
9288
|
+
`, isInline: true, styles: [":host{display:block;width:100%;min-height:100%;box-sizing:border-box}.praxis-resource-page{width:100%;display:flex;flex-direction:column;gap:20px;padding:var(--praxis-page-padding, 24px);box-sizing:border-box;max-width:1540px;margin:0 auto}.praxis-resource-page__header{display:flex;justify-content:space-between;align-items:flex-start;gap:16px;flex-wrap:wrap}.praxis-resource-page__header-main{min-width:0;display:flex;flex-direction:column}.praxis-resource-page__domain-badge{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:9999px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;margin-bottom:8px;align-self:flex-start;background:var(--praxis-domain-badge-bg, rgba(255, 255, 255, .08));color:var(--praxis-domain-badge-color, inherit);border:1px solid var(--praxis-domain-badge-border, rgba(255, 255, 255, .1))}.praxis-resource-page__domain-badge span.material-symbols-outlined{font-size:14px}.praxis-resource-page__title{margin:0 0 6px;font-size:var(--praxis-page-title-size, 2rem);font-weight:800;letter-spacing:-.02em;color:var(--praxis-page-title-color, var(--foreground, inherit));line-height:1.2}.praxis-resource-page__subtitle{margin:0;font-size:var(--praxis-page-subtitle-size, .9rem);color:var(--muted-foreground, #94a3b8);max-width:800px;line-height:1.5}.praxis-resource-page__crud-surface{width:100%;border-radius:var(--praxis-surface-radius, 16px);overflow:hidden}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: PraxisCrudComponent, selector: "praxis-crud", inputs: ["metadata", "crudId", "resource", "componentInstanceId", "tableConfigPersistenceStrategy", "context", "enableCustomization", "showResourceIdentityKey", "authoringCapability", "filterCriteria", "filterTeleport", "disableAutoDrawer"], outputs: ["configureRequested", "afterOpen", "afterClose", "afterSave", "afterDelete", "reactiveDeterminationExecuted", "reactiveDeterminationPendingChange", "reactiveDeterminationStabilityChange", "error", "rowClick", "rowAction", "selectionChange", "resourceEvent", "tableRuntimeConfigChange", "drawerOpen", "drawerClose", "crudAuthoringDocumentApplied", "crudAuthoringDocumentSaved", "kpiCardClick"] }, { kind: "component", type: PraxisScopeBarComponent, selector: "praxis-scope-bar", inputs: ["items", "activeId", "showOmnibox", "omniboxPlaceholder", "omniboxValue", "omniboxDebounceMs", "leadIcon", "leadLabel", "showClearButton", "clearLabel", "target", "targetWidgetId", "scopeBarId", "searchField"], outputs: ["activeIdChange", "omniboxValueChange", "scopeChange", "searchChange", "filterCriteriaChange", "clear"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
9289
|
+
}
|
|
9290
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisResourcePage, decorators: [{
|
|
9291
|
+
type: Component,
|
|
9292
|
+
args: [{ selector: 'praxis-resource-page', standalone: true, imports: [CommonModule, PraxisCrudComponent, PraxisScopeBarComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
9293
|
+
<div class="praxis-resource-page page-container">
|
|
9294
|
+
<!-- Auto-Header Governado -->
|
|
9295
|
+
@if (effectiveTitle() || effectiveDomain()) {
|
|
9296
|
+
<header class="praxis-resource-page__header section-header">
|
|
9297
|
+
<div class="praxis-resource-page__header-main">
|
|
9298
|
+
@if (effectiveDomain(); as dom) {
|
|
9299
|
+
<div
|
|
9300
|
+
class="praxis-resource-page__domain-badge domain-tag"
|
|
9301
|
+
[ngClass]="dom.tone ? 'tone-' + dom.tone : ''"
|
|
9302
|
+
>
|
|
9303
|
+
@if (dom.icon) {
|
|
9304
|
+
<span class="material-symbols-outlined">{{ dom.icon }}</span>
|
|
9305
|
+
}
|
|
9306
|
+
<span>{{ dom.label }}</span>
|
|
9307
|
+
</div>
|
|
9308
|
+
}
|
|
9309
|
+
@if (effectiveTitle(); as t) {
|
|
9310
|
+
<h1 class="praxis-resource-page__title page-title title-gradient">{{ t }}</h1>
|
|
9311
|
+
}
|
|
9312
|
+
@if (effectiveSubtitle(); as sub) {
|
|
9313
|
+
<p class="praxis-resource-page__subtitle page-subtitle">{{ sub }}</p>
|
|
9314
|
+
}
|
|
9315
|
+
</div>
|
|
9316
|
+
|
|
9317
|
+
<div class="praxis-resource-page__header-actions">
|
|
9318
|
+
<ng-content select="[page-header-actions]"></ng-content>
|
|
9319
|
+
</div>
|
|
9320
|
+
</header>
|
|
9321
|
+
}
|
|
9322
|
+
|
|
9323
|
+
<!-- Auto-ScopeBar Integrado -->
|
|
9324
|
+
@if (effectiveScopeBar(); as sb) {
|
|
9325
|
+
<praxis-scope-bar
|
|
9326
|
+
[leadLabel]="sb.leadLabel || 'Filtro:'"
|
|
9327
|
+
[leadIcon]="sb.leadIcon || 'tune'"
|
|
9328
|
+
[items]="sb.items || []"
|
|
9329
|
+
[activeId]="activeScopeId()"
|
|
9330
|
+
[showClearButton]="sb.showClearButton ?? (activeScopeId() !== 'all')"
|
|
9331
|
+
[showOmnibox]="sb.showOmnibox ?? false"
|
|
9332
|
+
(scopeChange)="onScopeChange($event)"
|
|
9333
|
+
(clear)="onScopeClear()"
|
|
9334
|
+
/>
|
|
9335
|
+
}
|
|
9336
|
+
|
|
9337
|
+
<!-- Praxis CRUD Runtime com isolamento reativo multi-tenant -->
|
|
9338
|
+
@if (effectiveResource() && identityVisible()) {
|
|
9339
|
+
<section class="praxis-resource-page__crud-surface crud-surface glass-panel">
|
|
9340
|
+
<praxis-crud
|
|
9341
|
+
[resource]="effectiveResource()!"
|
|
9342
|
+
[crudId]="resolvedCrudId()"
|
|
9343
|
+
[metadata]="effectiveMetadata()"
|
|
9344
|
+
[enableCustomization]="effectiveEnableCustomization()"
|
|
9345
|
+
[tableConfigPersistenceStrategy]="tableConfigPersistenceStrategy"
|
|
9346
|
+
[context]="context"
|
|
9347
|
+
(rowClick)="rowClick.emit($event)"
|
|
9348
|
+
(rowAction)="rowAction.emit($event)"
|
|
9349
|
+
(selectionChange)="selectionChange.emit($event)"
|
|
9350
|
+
(drawerOpen)="drawerOpen.emit($event)"
|
|
9351
|
+
(drawerClose)="drawerClose.emit()"
|
|
9352
|
+
(afterOpen)="afterOpen.emit($event)"
|
|
9353
|
+
(afterClose)="afterClose.emit()"
|
|
9354
|
+
(kpiCardClick)="handleKpiCardClick($event)"
|
|
9355
|
+
(afterSave)="afterSave.emit($event)"
|
|
9356
|
+
(afterDelete)="afterDelete.emit($event)"
|
|
9357
|
+
(error)="error.emit($event)"
|
|
9358
|
+
></praxis-crud>
|
|
9359
|
+
</section>
|
|
9360
|
+
}
|
|
9361
|
+
</div>
|
|
9362
|
+
`, styles: [":host{display:block;width:100%;min-height:100%;box-sizing:border-box}.praxis-resource-page{width:100%;display:flex;flex-direction:column;gap:20px;padding:var(--praxis-page-padding, 24px);box-sizing:border-box;max-width:1540px;margin:0 auto}.praxis-resource-page__header{display:flex;justify-content:space-between;align-items:flex-start;gap:16px;flex-wrap:wrap}.praxis-resource-page__header-main{min-width:0;display:flex;flex-direction:column}.praxis-resource-page__domain-badge{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:9999px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;margin-bottom:8px;align-self:flex-start;background:var(--praxis-domain-badge-bg, rgba(255, 255, 255, .08));color:var(--praxis-domain-badge-color, inherit);border:1px solid var(--praxis-domain-badge-border, rgba(255, 255, 255, .1))}.praxis-resource-page__domain-badge span.material-symbols-outlined{font-size:14px}.praxis-resource-page__title{margin:0 0 6px;font-size:var(--praxis-page-title-size, 2rem);font-weight:800;letter-spacing:-.02em;color:var(--praxis-page-title-color, var(--foreground, inherit));line-height:1.2}.praxis-resource-page__subtitle{margin:0;font-size:var(--praxis-page-subtitle-size, .9rem);color:var(--muted-foreground, #94a3b8);max-width:800px;line-height:1.5}.praxis-resource-page__crud-surface{width:100%;border-radius:var(--praxis-surface-radius, 16px);overflow:hidden}\n"] }]
|
|
9363
|
+
}], propDecorators: { resource: [{
|
|
9364
|
+
type: Input
|
|
9365
|
+
}], resourcePath: [{
|
|
9366
|
+
type: Input
|
|
9367
|
+
}], crudId: [{
|
|
9368
|
+
type: Input
|
|
9369
|
+
}], metadata: [{
|
|
9370
|
+
type: Input
|
|
9371
|
+
}], title: [{
|
|
9372
|
+
type: Input
|
|
9373
|
+
}], subtitle: [{
|
|
9374
|
+
type: Input
|
|
9375
|
+
}], domain: [{
|
|
9376
|
+
type: Input
|
|
9377
|
+
}], scopeBar: [{
|
|
9378
|
+
type: Input
|
|
9379
|
+
}], scopeItems: [{
|
|
9380
|
+
type: Input
|
|
9381
|
+
}], defaultScopeId: [{
|
|
9382
|
+
type: Input
|
|
9383
|
+
}], enableCustomization: [{
|
|
9384
|
+
type: Input
|
|
9385
|
+
}], tableConfigPersistenceStrategy: [{
|
|
9386
|
+
type: Input
|
|
9387
|
+
}], context: [{
|
|
9388
|
+
type: Input
|
|
9389
|
+
}], actions: [{
|
|
9390
|
+
type: Input
|
|
9391
|
+
}], filterCriteria: [{
|
|
9392
|
+
type: Input
|
|
9393
|
+
}], rowClick: [{
|
|
9394
|
+
type: Output
|
|
9395
|
+
}], rowAction: [{
|
|
9396
|
+
type: Output
|
|
9397
|
+
}], rowDoubleClick: [{
|
|
9398
|
+
type: Output
|
|
9399
|
+
}], selectionChange: [{
|
|
9400
|
+
type: Output
|
|
9401
|
+
}], drawerOpen: [{
|
|
9402
|
+
type: Output
|
|
9403
|
+
}], drawerClose: [{
|
|
9404
|
+
type: Output
|
|
9405
|
+
}], afterOpen: [{
|
|
9406
|
+
type: Output
|
|
9407
|
+
}], afterClose: [{
|
|
9408
|
+
type: Output
|
|
9409
|
+
}], kpiCardClick: [{
|
|
9410
|
+
type: Output
|
|
9411
|
+
}], afterSave: [{
|
|
9412
|
+
type: Output
|
|
9413
|
+
}], afterDelete: [{
|
|
9414
|
+
type: Output
|
|
9415
|
+
}], error: [{
|
|
9416
|
+
type: Output
|
|
9417
|
+
}] } });
|
|
9418
|
+
|
|
8244
9419
|
/*
|
|
8245
9420
|
* Public API Surface of praxis-crud
|
|
8246
9421
|
*/
|
|
@@ -8249,4 +9424,4 @@ const PRAXIS_CRUD_AUTHORING_MANIFEST = {
|
|
|
8249
9424
|
* Generated bundle index. Do not edit.
|
|
8250
9425
|
*/
|
|
8251
9426
|
|
|
8252
|
-
export { CRUD_AI_CAPABILITIES, CrudLauncherService, CrudMetadataEditorComponent, CrudPageHeaderComponent, DialogService, DynamicFormDialogHostComponent, PRAXIS_CRUD_AUTHORING_MANIFEST, PRAXIS_CRUD_COMPONENT_METADATA, PraxisCrudComponent, PraxisCrudWidgetConfigEditor, assertCrudMetadata, createCrudAuthoringDocument, findCrudAction, normalizeCrudAuthoringDocument, openCrudMetadataEditor, parseLegacyOrCrudDocument, providePraxisCrudMetadata, serializeCrudAuthoringDocument, validateCrudAuthoringDocument };
|
|
9427
|
+
export { CRUD_AI_CAPABILITIES, CrudLauncherService, CrudMetadataEditorComponent, CrudPageHeaderComponent, DialogService, DynamicFormDialogHostComponent, PRAXIS_CRUD_AUTHORING_MANIFEST, PRAXIS_CRUD_COMPONENT_METADATA, PraxisCrudComponent, PraxisCrudWidgetConfigEditor, PraxisKpiBandComponent, PraxisResourcePage, assertCrudMetadata, createCrudAuthoringDocument, findCrudAction, formatKpiValue, normalizeCrudAuthoringDocument, openCrudMetadataEditor, parseLegacyOrCrudDocument, providePraxisCrudMetadata, serializeCrudAuthoringDocument, validateCrudAuthoringDocument };
|