@praxisui/core 10.0.0-rc.32 → 10.0.0-rc.33
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/README.md +1 -1
- package/ai/component-registry.json +10 -9
- package/fesm2022/praxisui-core-schema.mjs +356 -44
- package/fesm2022/praxisui-core.mjs +2567 -137
- package/package.json +1 -1
- package/types/praxisui-core-schema.d.ts +33 -2
- package/types/praxisui-core.d.ts +330 -30
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Component, InjectionToken, Injectable, inject, Inject, Optional, SkipSelf, makeEnvironmentProviders, signal, computed, APP_INITIALIZER, DestroyRef, ENVIRONMENT_INITIALIZER, ErrorHandler, isSignal, Input, Directive, input, booleanAttribute, ChangeDetectionStrategy, EventEmitter, Output, SecurityContext, ViewContainerRef, Injector, effect, SimpleChange, ElementRef, ChangeDetectorRef, afterEveryRender, contentChild, viewChild, HostBinding, output, afterNextRender, ViewChild, ViewEncapsulation, createEnvironmentInjector, EnvironmentInjector, reflectComponentType, HostListener, ViewChildren, TemplateRef, Renderer2 } from '@angular/core';
|
|
2
|
+
import { Component, InjectionToken, Injectable, inject, Inject, Optional, SkipSelf, makeEnvironmentProviders, signal, computed, APP_INITIALIZER, DestroyRef, ENVIRONMENT_INITIALIZER, ErrorHandler, isSignal, Input, Directive, input, booleanAttribute, ChangeDetectionStrategy, EventEmitter, Output, SecurityContext, ViewContainerRef, Injector, effect, SimpleChange, ElementRef, ChangeDetectorRef, afterEveryRender, contentChild, viewChild, HostBinding, output, afterNextRender, ViewChild, ViewEncapsulation, createEnvironmentInjector, EnvironmentInjector, reflectComponentType, HostListener, ViewChildren, forwardRef, TemplateRef, Renderer2 } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/common/http';
|
|
4
4
|
import { HttpHeaders, HttpClient, HttpParams, HttpResponse, HttpContextToken, HttpErrorResponse, HTTP_INTERCEPTORS, withInterceptors } from '@angular/common/http';
|
|
5
|
-
import { of, defer, throwError, from, EMPTY, BehaviorSubject, firstValueFrom, Subject, finalize as finalize$1, shareReplay as shareReplay$1, map as map$1,
|
|
5
|
+
import { of, defer, throwError, from, EMPTY, BehaviorSubject, firstValueFrom, Subject, finalize as finalize$1, shareReplay as shareReplay$1, map as map$1, catchError as catchError$1, switchMap as switchMap$1, Observable, timer, forkJoin, isObservable, combineLatest, merge, Subscription, defaultIfEmpty, timeout as timeout$1 } from 'rxjs';
|
|
6
6
|
import { switchMap, map, take, catchError, concatMap, tap, shareReplay, takeUntil, toArray, finalize, exhaustMap, filter, timeout } from 'rxjs/operators';
|
|
7
7
|
import * as i1$3 from '@angular/common';
|
|
8
8
|
import { Location, DOCUMENT, NgTemplateOutlet, CommonModule, NgComponentOutlet } from '@angular/common';
|
|
9
9
|
import { Router, ActivatedRoute, RouterLink, RouterLinkActive } from '@angular/router';
|
|
10
10
|
import * as i1$2 from '@angular/forms';
|
|
11
|
-
import { Validators, FormGroup, FormControl, FormArray, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
11
|
+
import { Validators, FormGroup, FormControl, FormArray, FormsModule, ReactiveFormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
12
12
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
|
13
13
|
import * as i1$1 from '@angular/material/icon';
|
|
14
14
|
import { MatIconRegistry, MatIconModule } from '@angular/material/icon';
|
|
@@ -1124,6 +1124,10 @@ const VISUALIZATION_TONES = new Set([
|
|
|
1124
1124
|
'danger',
|
|
1125
1125
|
'critical',
|
|
1126
1126
|
]);
|
|
1127
|
+
const VISUALIZATION_SCALE_SCOPES = new Set([
|
|
1128
|
+
'row',
|
|
1129
|
+
'page',
|
|
1130
|
+
]);
|
|
1127
1131
|
const TABLE_SAFE_KINDS = new Set([
|
|
1128
1132
|
'line',
|
|
1129
1133
|
'area',
|
|
@@ -1231,6 +1235,7 @@ function normalizePraxisPresentationVisualization(value) {
|
|
|
1231
1235
|
}
|
|
1232
1236
|
const surface = normalizeEnum$1(value.surface, VISUALIZATION_SURFACES);
|
|
1233
1237
|
const size = normalizeEnum$1(value.size, VISUALIZATION_SIZES);
|
|
1238
|
+
const scaleScope = normalizeEnum$1(value.scaleScope, VISUALIZATION_SCALE_SCOPES);
|
|
1234
1239
|
const tone = normalizeEnum$1(value.tone, VISUALIZATION_TONES);
|
|
1235
1240
|
const ariaLabel = normalizeText$2(value.ariaLabel);
|
|
1236
1241
|
const valueSuffix = normalizeText$2(value.valueSuffix);
|
|
@@ -1241,7 +1246,10 @@ function normalizePraxisPresentationVisualization(value) {
|
|
|
1241
1246
|
let evalVal = value.value;
|
|
1242
1247
|
if (evalVal === undefined && Array.isArray(value.points) && value.points.length > 0) {
|
|
1243
1248
|
const last = value.points[value.points.length - 1];
|
|
1244
|
-
if (
|
|
1249
|
+
if (typeof last === 'number' && Number.isFinite(last)) {
|
|
1250
|
+
evalVal = last;
|
|
1251
|
+
}
|
|
1252
|
+
else if (last && typeof last === 'object' && Number.isFinite(last.value)) {
|
|
1245
1253
|
evalVal = last.value;
|
|
1246
1254
|
}
|
|
1247
1255
|
}
|
|
@@ -1264,6 +1272,7 @@ function normalizePraxisPresentationVisualization(value) {
|
|
|
1264
1272
|
fallbackText,
|
|
1265
1273
|
...(surface ? { surface } : {}),
|
|
1266
1274
|
...(size ? { size } : {}),
|
|
1275
|
+
...(scaleScope ? { scaleScope } : {}),
|
|
1267
1276
|
...(resolvedTone ? { tone: resolvedTone } : {}),
|
|
1268
1277
|
...(resolvedAriaLabel ? { ariaLabel: resolvedAriaLabel } : {}),
|
|
1269
1278
|
...(valueSuffix ? { valueSuffix } : {}),
|
|
@@ -1271,6 +1280,10 @@ function normalizePraxisPresentationVisualization(value) {
|
|
|
1271
1280
|
...(Object.prototype.hasOwnProperty.call(value, 'value') ? { value: value.value } : {}),
|
|
1272
1281
|
...(normalizeExpression(value.valueExpr, 'valueExpr') ?? {}),
|
|
1273
1282
|
...(normalizeExpression(value.valueSuffixExpr, 'valueSuffixExpr') ?? {}),
|
|
1283
|
+
...(normalizeNumber(value.min, 'min') ?? {}),
|
|
1284
|
+
...(normalizeExpression(value.minExpr, 'minExpr') ?? {}),
|
|
1285
|
+
...(normalizeNumber(value.max, 'max') ?? {}),
|
|
1286
|
+
...(normalizeExpression(value.maxExpr, 'maxExpr') ?? {}),
|
|
1274
1287
|
...(normalizeNumber(value.total, 'total') ?? {}),
|
|
1275
1288
|
...(normalizeExpression(value.totalExpr, 'totalExpr') ?? {}),
|
|
1276
1289
|
...(normalizeNumber(value.target, 'target') ?? {}),
|
|
@@ -1331,49 +1344,75 @@ function renderPraxisPresentationVisualizationHtml(value, options = {}) {
|
|
|
1331
1344
|
}
|
|
1332
1345
|
}
|
|
1333
1346
|
function renderComparisonVisualizationHtml(visualization, options) {
|
|
1334
|
-
|
|
1347
|
+
let points = visualization.points ?? [];
|
|
1348
|
+
if (points.length === 0) {
|
|
1349
|
+
const primaryValue = toFiniteNumber(visualization.value);
|
|
1350
|
+
const referenceValue = toFiniteNumber(visualization.baseline) ?? toFiniteNumber(visualization.target);
|
|
1351
|
+
if (primaryValue !== undefined) {
|
|
1352
|
+
points = [
|
|
1353
|
+
{ value: primaryValue, tone: visualization.tone ?? 'info' },
|
|
1354
|
+
...(referenceValue !== undefined
|
|
1355
|
+
? [{ value: referenceValue, tone: 'neutral' }]
|
|
1356
|
+
: []),
|
|
1357
|
+
];
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1335
1360
|
if (points.length === 0) {
|
|
1336
1361
|
return renderFallbackVisualizationHtml(visualization, visualization.tone ?? 'neutral');
|
|
1337
1362
|
}
|
|
1338
|
-
const
|
|
1363
|
+
const explicitCeiling = Math.max(toFiniteNumber(visualization.max) ?? 0, toFiniteNumber(visualization.total) ?? 0);
|
|
1364
|
+
const max = Math.max(1, explicitCeiling, ...points.map((point) => Math.max(0, point.value)));
|
|
1365
|
+
const suffix = visualization.valueSuffix ?? '';
|
|
1366
|
+
const useCompact = visualization.compactValue === true;
|
|
1339
1367
|
const rows = points
|
|
1340
1368
|
.map((point) => {
|
|
1341
1369
|
const width = percent(point.value, max);
|
|
1370
|
+
const formattedVal = `${formatMicroNumber(point.value, options.locale, useCompact)}${suffix}`;
|
|
1371
|
+
const readout = `${point.label ? `${point.label}: ` : ''}${formattedVal} (${Math.round(Number(width))}%)`;
|
|
1342
1372
|
return `
|
|
1343
|
-
<span class="pfx-micro-viz__row" data-tone="${escapeHtml$1(point.tone ?? visualization.tone ?? 'info')}">
|
|
1373
|
+
<span class="pfx-micro-viz__row" data-tone="${escapeHtml$1(point.tone ?? visualization.tone ?? 'info')}" data-micro-readout="${escapeHtml$1(readout)}">
|
|
1344
1374
|
<span class="pfx-micro-viz__label">${escapeHtml$1(point.label ?? '')}</span>
|
|
1345
1375
|
<span class="pfx-micro-viz__track">
|
|
1346
1376
|
<span class="pfx-micro-viz__bar" style="width:${width}%"></span>
|
|
1347
1377
|
</span>
|
|
1348
|
-
<span class="pfx-micro-viz__value">${escapeHtml$1(
|
|
1378
|
+
<span class="pfx-micro-viz__value">${escapeHtml$1(formattedVal)}</span>
|
|
1349
1379
|
</span>`;
|
|
1350
1380
|
})
|
|
1351
1381
|
.join('');
|
|
1352
|
-
return `<span class="pfx-micro-viz" role="img" aria-label="${escapeHtml$1(visualization.ariaLabel ?? visualization.fallbackText)}">${rows}</span>`;
|
|
1382
|
+
return `<span class="pfx-micro-viz pfx-micro-viz__comparison" role="img" aria-label="${escapeHtml$1(visualization.ariaLabel ?? visualization.fallbackText)}">${rows}</span>`;
|
|
1353
1383
|
}
|
|
1354
1384
|
function renderStackedBarVisualizationHtml(visualization, options) {
|
|
1355
|
-
const segments = visualization.segments
|
|
1385
|
+
const segments = visualization.segments?.length
|
|
1386
|
+
? visualization.segments
|
|
1387
|
+
: (visualization.items?.filter((item) => typeof item?.value === 'number' && Number.isFinite(item.value)) ?? []);
|
|
1356
1388
|
if (segments.length === 0) {
|
|
1357
1389
|
return renderFallbackVisualizationHtml(visualization, visualization.tone ?? 'neutral');
|
|
1358
1390
|
}
|
|
1359
1391
|
const total = visualization.total && visualization.total > 0
|
|
1360
1392
|
? visualization.total
|
|
1361
1393
|
: Math.max(1, segments.reduce((sum, segment) => sum + Math.max(0, segment.value), 0));
|
|
1394
|
+
const suffix = visualization.valueSuffix ?? '';
|
|
1362
1395
|
const bars = segments
|
|
1363
|
-
.map((segment) =>
|
|
1396
|
+
.map((segment) => {
|
|
1397
|
+
const pctStr = percent(segment.value, total);
|
|
1398
|
+
const formattedVal = `${formatMicroNumber(segment.value, options.locale)}${suffix}`;
|
|
1399
|
+
const readout = `${segment.label ? `${segment.label}: ` : ''}${formattedVal} (${Math.round(Number(pctStr))}%)`;
|
|
1400
|
+
return `
|
|
1364
1401
|
<span
|
|
1365
1402
|
class="pfx-micro-viz__segment"
|
|
1366
1403
|
data-tone="${escapeHtml$1(segment.tone ?? visualization.tone ?? 'info')}"
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1404
|
+
data-micro-readout="${escapeHtml$1(readout)}"
|
|
1405
|
+
style="width:${pctStr}%"
|
|
1406
|
+
title="${escapeHtml$1(`${segment.label ?? ''} ${formattedVal}`.trim())}"
|
|
1407
|
+
></span>`;
|
|
1408
|
+
})
|
|
1370
1409
|
.join('');
|
|
1371
1410
|
const meta = segments
|
|
1372
1411
|
.slice(0, 3)
|
|
1373
1412
|
.map((segment) => `<span>${escapeHtml$1(segment.label ?? '')}: ${escapeHtml$1(formatMicroNumber(segment.value, options.locale))}</span>`)
|
|
1374
1413
|
.join('');
|
|
1375
1414
|
return `
|
|
1376
|
-
<span class="pfx-micro-viz" role="img" aria-label="${escapeHtml$1(visualization.ariaLabel ?? visualization.fallbackText)}">
|
|
1415
|
+
<span class="pfx-micro-viz pfx-micro-viz__stacked" role="img" aria-label="${escapeHtml$1(visualization.ariaLabel ?? visualization.fallbackText)}">
|
|
1377
1416
|
<span class="pfx-micro-viz__segments">${bars}</span>
|
|
1378
1417
|
<span class="pfx-micro-viz__meta">${meta}</span>
|
|
1379
1418
|
</span>`;
|
|
@@ -1387,9 +1426,15 @@ function resolveBulletMax(visualization) {
|
|
|
1387
1426
|
toFiniteNumber(visualization.value) ?? 0,
|
|
1388
1427
|
visualization.target ?? 0,
|
|
1389
1428
|
visualization.total ?? 0,
|
|
1429
|
+
visualization.max ?? 0,
|
|
1390
1430
|
...thresholdValues
|
|
1391
1431
|
].filter((v) => Number.isFinite(v) && v > 0);
|
|
1392
|
-
|
|
1432
|
+
const fallbackCeiling = visualization.total && visualization.total > 0
|
|
1433
|
+
? visualization.total
|
|
1434
|
+
: visualization.max && visualization.max > 0
|
|
1435
|
+
? visualization.max
|
|
1436
|
+
: 100;
|
|
1437
|
+
return Math.max(...values, fallbackCeiling);
|
|
1393
1438
|
}
|
|
1394
1439
|
function renderBulletVisualizationHtml(visualization, options) {
|
|
1395
1440
|
const currentValue = toFiniteNumber(visualization.value);
|
|
@@ -1400,6 +1445,7 @@ function renderBulletVisualizationHtml(visualization, options) {
|
|
|
1400
1445
|
const target = toFiniteNumber(visualization.target);
|
|
1401
1446
|
const targetLeft = target === undefined ? null : percent(target, max);
|
|
1402
1447
|
const isTable = visualization.surface === 'table-cell';
|
|
1448
|
+
const suffix = visualization.valueSuffix ?? '';
|
|
1403
1449
|
// thresholds: sort ascending by boundary value so bands draw continuously regardless of declaration order
|
|
1404
1450
|
const thresholds = visualization.thresholds ?? [];
|
|
1405
1451
|
const sortedThresholds = [...thresholds].sort((a, b) => {
|
|
@@ -1431,11 +1477,19 @@ function renderBulletVisualizationHtml(visualization, options) {
|
|
|
1431
1477
|
<span>${escapeHtml$1(formatMicroNumber(max, options.locale))}</span>
|
|
1432
1478
|
</div>`;
|
|
1433
1479
|
const showCompactValue = isTable && visualization.compactValue !== false;
|
|
1480
|
+
const useCompactNotation = visualization.compactValue === true;
|
|
1434
1481
|
const compactValueHtml = showCompactValue
|
|
1435
|
-
? `<span class="pfx-micro-bullet__compact-value">${escapeHtml$1(formatMicroNumber(currentValue, options.locale))}${escapeHtml$1(
|
|
1482
|
+
? `<span class="pfx-micro-bullet__compact-value">${escapeHtml$1(formatMicroNumber(currentValue, options.locale, useCompactNotation))}${escapeHtml$1(suffix)}</span>`
|
|
1436
1483
|
: '';
|
|
1484
|
+
const currentStr = `${formatMicroNumber(currentValue, options.locale)}${suffix}`;
|
|
1485
|
+
const diff = target !== undefined ? currentValue - target : undefined;
|
|
1486
|
+
const diffSign = diff !== undefined && diff > 0 ? '+' : '';
|
|
1487
|
+
const bulletReadout = target !== undefined && diff !== undefined
|
|
1488
|
+
? `${currentStr} / Target ${formatMicroNumber(target, options.locale)}${suffix} (${diffSign}${formatMicroNumber(diff, options.locale)}${suffix})`
|
|
1489
|
+
: `${currentStr} / ${formatMicroNumber(max, options.locale)}${suffix}`;
|
|
1490
|
+
const tabIndexAttr = isTable ? '' : ' tabindex="0"';
|
|
1437
1491
|
return `
|
|
1438
|
-
<span class="pfx-micro-viz pfx-micro-viz__bullet" data-tone="${escapeHtml$1(visualization.tone ?? 'info')}" role="img" aria-label="${escapeHtml$1(visualization.ariaLabel ?? visualization.fallbackText)}">
|
|
1492
|
+
<span class="pfx-micro-viz pfx-micro-viz__bullet"${tabIndexAttr} data-tone="${escapeHtml$1(visualization.tone ?? 'info')}" data-micro-readout="${escapeHtml$1(bulletReadout)}" role="img" aria-label="${escapeHtml$1(visualization.ariaLabel ?? visualization.fallbackText)}">
|
|
1439
1493
|
${topHtml}
|
|
1440
1494
|
<span class="pfx-micro-bullet__track">
|
|
1441
1495
|
${bandsHtml}
|
|
@@ -1468,8 +1522,19 @@ function renderDeltaVisualizationHtml(visualization, options) {
|
|
|
1468
1522
|
? 'down'
|
|
1469
1523
|
: 'stable';
|
|
1470
1524
|
const aria = visualization.ariaLabel ?? `${visualization.fallbackText}: ${directionLabel} ${text}`;
|
|
1525
|
+
const target = toFiniteNumber(visualization.target);
|
|
1526
|
+
const baseline = toFiniteNumber(visualization.baseline);
|
|
1527
|
+
const isTable = visualization.surface === 'table-cell';
|
|
1528
|
+
const deltaReadout = target !== undefined
|
|
1529
|
+
? `Target ${formatMicroNumber(target, options.locale)}${valueSuffix}`
|
|
1530
|
+
: baseline !== undefined
|
|
1531
|
+
? `Base ${formatMicroNumber(baseline, options.locale)}${valueSuffix}`
|
|
1532
|
+
: null;
|
|
1533
|
+
const readoutAttr = deltaReadout
|
|
1534
|
+
? `${isTable ? '' : ' tabindex="0"'} data-micro-readout="${escapeHtml$1(deltaReadout)}"`
|
|
1535
|
+
: '';
|
|
1471
1536
|
return `
|
|
1472
|
-
<span class="pfx-micro-viz pfx-micro-viz__delta" data-tone="${escapeHtml$1(tone)}" data-direction="${escapeHtml$1(direction)}" role="img" aria-label="${escapeHtml$1(aria)}">
|
|
1537
|
+
<span class="pfx-micro-viz pfx-micro-viz__delta" data-tone="${escapeHtml$1(tone)}" data-direction="${escapeHtml$1(direction)}"${readoutAttr} role="img" aria-label="${escapeHtml$1(aria)}">
|
|
1473
1538
|
<span class="pfx-micro-viz__delta-symbol" aria-hidden="true">${symbol}</span>
|
|
1474
1539
|
<span>${escapeHtml$1(text)}</span>
|
|
1475
1540
|
</span>`;
|
|
@@ -1483,7 +1548,14 @@ function percent(value, total) {
|
|
|
1483
1548
|
function toFiniteNumber(value) {
|
|
1484
1549
|
return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
|
|
1485
1550
|
}
|
|
1486
|
-
function formatMicroNumber(value, locale) {
|
|
1551
|
+
function formatMicroNumber(value, locale, compactValue = false) {
|
|
1552
|
+
if (compactValue && Math.abs(value) >= 1000) {
|
|
1553
|
+
return new Intl.NumberFormat(locale || undefined, {
|
|
1554
|
+
notation: 'compact',
|
|
1555
|
+
compactDisplay: 'short',
|
|
1556
|
+
maximumFractionDigits: 1,
|
|
1557
|
+
}).format(value);
|
|
1558
|
+
}
|
|
1487
1559
|
return new Intl.NumberFormat(locale || undefined, {
|
|
1488
1560
|
maximumFractionDigits: Math.abs(value) < 10 ? 2 : 0,
|
|
1489
1561
|
}).format(value);
|
|
@@ -1558,6 +1630,9 @@ function normalizeNumericEntries(value) {
|
|
|
1558
1630
|
}
|
|
1559
1631
|
return value
|
|
1560
1632
|
.map((item) => {
|
|
1633
|
+
if (typeof item === 'number') {
|
|
1634
|
+
return Number.isFinite(item) ? { value: item } : null;
|
|
1635
|
+
}
|
|
1561
1636
|
if (!item || typeof item !== 'object' || !Number.isFinite(item.value)) {
|
|
1562
1637
|
return null;
|
|
1563
1638
|
}
|
|
@@ -1618,6 +1693,7 @@ function renderRadialVisualizationHtml(visualization, options) {
|
|
|
1618
1693
|
const total = visualization.total && visualization.total > 0 ? visualization.total : 100;
|
|
1619
1694
|
const pct = Math.max(0, Math.min(100, (value / total) * 100));
|
|
1620
1695
|
const tone = visualization.tone ?? 'info';
|
|
1696
|
+
const suffix = visualization.valueSuffix ?? '';
|
|
1621
1697
|
const dashArray = `${pct.toFixed(1)}, 100`;
|
|
1622
1698
|
const pctText = `${Math.round(pct)}%`;
|
|
1623
1699
|
const aria = visualization.ariaLabel ?? `${visualization.fallbackText} (${pctText})`;
|
|
@@ -1628,8 +1704,10 @@ function renderRadialVisualizationHtml(visualization, options) {
|
|
|
1628
1704
|
const externalText = isTable
|
|
1629
1705
|
? `<span class="pfx-micro-radial-value">${escapeHtml$1(pctText)}</span>`
|
|
1630
1706
|
: '';
|
|
1707
|
+
const radialReadout = `${formatMicroNumber(value, options.locale)}${suffix} / ${formatMicroNumber(total, options.locale)}${suffix} (${pctText})`;
|
|
1708
|
+
const tabIndexAttr = isTable ? '' : ' tabindex="0"';
|
|
1631
1709
|
return `
|
|
1632
|
-
<span class="pfx-micro-viz pfx-micro-viz__radial" data-tone="${escapeHtml$1(tone)}" role="img" aria-label="${escapeHtml$1(aria)}">
|
|
1710
|
+
<span class="pfx-micro-viz pfx-micro-viz__radial"${tabIndexAttr} data-tone="${escapeHtml$1(tone)}" data-micro-readout="${escapeHtml$1(radialReadout)}" role="img" aria-label="${escapeHtml$1(aria)}">
|
|
1633
1711
|
<svg class="pfx-micro-radial-svg" viewBox="0 0 36 36">
|
|
1634
1712
|
<circle class="pfx-micro-radial-svg__track" cx="18" cy="18" r="15.9155" />
|
|
1635
1713
|
<circle class="pfx-micro-radial-svg__bar" cx="18" cy="18" r="15.9155" stroke-dasharray="${dashArray}" transform="rotate(-90 18 18)" />
|
|
@@ -1646,11 +1724,14 @@ function renderHarveyBallVisualizationHtml(visualization, options) {
|
|
|
1646
1724
|
const total = visualization.total && visualization.total > 0 ? visualization.total : 100;
|
|
1647
1725
|
const pct = Math.max(0, Math.min(100, (value / total) * 100));
|
|
1648
1726
|
const tone = visualization.tone ?? 'info';
|
|
1727
|
+
const isTable = visualization.surface === 'table-cell';
|
|
1728
|
+
const tabIndexAttr = isTable ? '' : ' tabindex="0"';
|
|
1649
1729
|
const strokeLength = pct * 0.50265;
|
|
1650
1730
|
const dashArray = `${strokeLength.toFixed(3)} 50.265`;
|
|
1651
1731
|
const aria = visualization.ariaLabel ?? `${visualization.fallbackText} (${Math.round(pct)}%)`;
|
|
1732
|
+
const harveyReadout = `${formatMicroNumber(value, options.locale)}/${formatMicroNumber(total, options.locale)} (${Math.round(pct)}%)`;
|
|
1652
1733
|
return `
|
|
1653
|
-
<span class="pfx-micro-viz pfx-micro-viz__harvey" data-tone="${escapeHtml$1(tone)}" role="img" aria-label="${escapeHtml$1(aria)}">
|
|
1734
|
+
<span class="pfx-micro-viz pfx-micro-viz__harvey"${tabIndexAttr} data-tone="${escapeHtml$1(tone)}" data-micro-readout="${escapeHtml$1(harveyReadout)}" role="img" aria-label="${escapeHtml$1(aria)}">
|
|
1654
1735
|
<svg class="pfx-micro-harvey-svg" viewBox="0 0 36 36">
|
|
1655
1736
|
<circle class="pfx-micro-harvey-svg__track" cx="18" cy="18" r="16" />
|
|
1656
1737
|
<circle class="pfx-micro-harvey-svg__bar" cx="18" cy="18" r="8" stroke-dasharray="${dashArray}" transform="rotate(-90 18 18)" />
|
|
@@ -1662,19 +1743,57 @@ function renderHarveyBallVisualizationHtml(visualization, options) {
|
|
|
1662
1743
|
</span>
|
|
1663
1744
|
</span>`;
|
|
1664
1745
|
}
|
|
1665
|
-
function
|
|
1746
|
+
function resolveTrendBounds(points, visualization, anchorZero = false) {
|
|
1747
|
+
const values = points.map((p) => p.value);
|
|
1748
|
+
const refValue = toFiniteNumber(visualization?.target) ?? toFiniteNumber(visualization?.baseline);
|
|
1749
|
+
const explicitMin = toFiniteNumber(visualization?.min);
|
|
1750
|
+
const explicitMax = toFiniteNumber(visualization?.max);
|
|
1751
|
+
const baseCandidates = anchorZero ? [...values, 0] : [...values];
|
|
1752
|
+
if (refValue !== undefined) {
|
|
1753
|
+
baseCandidates.push(refValue);
|
|
1754
|
+
}
|
|
1755
|
+
const minVal = explicitMin !== undefined ? Math.min(explicitMin, ...baseCandidates) : Math.min(...baseCandidates);
|
|
1756
|
+
const maxVal = explicitMax !== undefined ? Math.max(explicitMax, ...baseCandidates) : Math.max(...baseCandidates);
|
|
1757
|
+
const valRange = maxVal - minVal === 0 ? 1 : maxVal - minVal;
|
|
1758
|
+
return { minVal, maxVal, valRange, refValue };
|
|
1759
|
+
}
|
|
1760
|
+
function getPointsCoordinates(points, width, height, padding, visualization) {
|
|
1666
1761
|
if (points.length < 2)
|
|
1667
1762
|
return [];
|
|
1668
|
-
const
|
|
1669
|
-
const minVal = Math.min(...values);
|
|
1670
|
-
const maxVal = Math.max(...values);
|
|
1671
|
-
const valRange = maxVal - minVal === 0 ? 1 : maxVal - minVal;
|
|
1763
|
+
const { minVal, valRange } = resolveTrendBounds(points, visualization, false);
|
|
1672
1764
|
return points.map((p, index) => {
|
|
1673
1765
|
const x = padding + (index / (points.length - 1)) * (width - 2 * padding);
|
|
1674
1766
|
const y = height - padding - ((p.value - minVal) / valRange) * (height - 2 * padding);
|
|
1675
1767
|
return { x, y };
|
|
1676
1768
|
});
|
|
1677
1769
|
}
|
|
1770
|
+
function renderTrendReferenceLineHtml(points, width, height, padding, visualization, anchorZero = false) {
|
|
1771
|
+
const { minVal, valRange, refValue } = resolveTrendBounds(points, visualization, anchorZero);
|
|
1772
|
+
if (refValue === undefined) {
|
|
1773
|
+
return '';
|
|
1774
|
+
}
|
|
1775
|
+
const refY = height - padding - ((refValue - minVal) / valRange) * (height - 2 * padding);
|
|
1776
|
+
return `<line class="pfx-micro-trend__ref-line" x1="${padding}" y1="${refY.toFixed(1)}" x2="${width - padding}" y2="${refY.toFixed(1)}" stroke="currentColor" stroke-opacity="0.38" stroke-width="1" stroke-dasharray="2 2" />`;
|
|
1777
|
+
}
|
|
1778
|
+
function renderTrendScrubLayerHtml(points, coords, width, height, visualization, options) {
|
|
1779
|
+
const defaultTone = visualization.tone ?? 'info';
|
|
1780
|
+
const suffix = visualization.valueSuffix ?? '';
|
|
1781
|
+
const slicesHtml = points
|
|
1782
|
+
.map((point, index) => {
|
|
1783
|
+
const coord = coords[index] ?? { x: 50, y: 15 };
|
|
1784
|
+
const xPct = ((coord.x / width) * 100).toFixed(1);
|
|
1785
|
+
const yPct = ((coord.y / height) * 100).toFixed(1);
|
|
1786
|
+
const pointTone = point.tone ??
|
|
1787
|
+
(visualization.thresholds?.length
|
|
1788
|
+
? resolvePraxisMicroVisualizationTone(point.value, visualization.thresholds)?.tone ?? defaultTone
|
|
1789
|
+
: defaultTone);
|
|
1790
|
+
const labelPrefix = point.label ? `${point.label}: ` : `#${index + 1}: `;
|
|
1791
|
+
const readout = `${labelPrefix}${formatMicroNumber(point.value, options.locale)}${suffix}`;
|
|
1792
|
+
return `<span class="pfx-micro-trend__scrub-slice" data-tone="${escapeHtml$1(pointTone)}" data-micro-readout="${escapeHtml$1(readout)}" style="--pfx-scrub-x:${xPct}%;--pfx-scrub-y:${yPct}%;"></span>`;
|
|
1793
|
+
})
|
|
1794
|
+
.join('');
|
|
1795
|
+
return `<span class="pfx-micro-trend__scrub-layer" aria-hidden="true">${slicesHtml}</span>`;
|
|
1796
|
+
}
|
|
1678
1797
|
function renderLineVisualizationHtml(visualization, options) {
|
|
1679
1798
|
const points = visualization.points ?? [];
|
|
1680
1799
|
const tone = visualization.tone ?? 'info';
|
|
@@ -1684,8 +1803,9 @@ function renderLineVisualizationHtml(visualization, options) {
|
|
|
1684
1803
|
const width = 100;
|
|
1685
1804
|
const height = 30;
|
|
1686
1805
|
const padding = 4;
|
|
1687
|
-
const coords = getPointsCoordinates(points, width, height, padding);
|
|
1806
|
+
const coords = getPointsCoordinates(points, width, height, padding, visualization);
|
|
1688
1807
|
const pathD = coords.map((c, i) => `${i === 0 ? 'M' : 'L'} ${c.x.toFixed(1)} ${c.y.toFixed(1)}`).join(' ');
|
|
1808
|
+
const refLineHtml = renderTrendReferenceLineHtml(points, width, height, padding, visualization, false);
|
|
1689
1809
|
// Highlight extreme/boundary values
|
|
1690
1810
|
let minIdx = 0;
|
|
1691
1811
|
let maxIdx = 0;
|
|
@@ -1706,6 +1826,7 @@ function renderLineVisualizationHtml(visualization, options) {
|
|
|
1706
1826
|
markers.push({ x: coords[maxIdx].x, y: coords[maxIdx].y, tone: points[maxIdx].tone ?? 'success' });
|
|
1707
1827
|
}
|
|
1708
1828
|
const circlesHtml = markers.map(c => `<circle cx="${c.x.toFixed(1)}" cy="${c.y.toFixed(1)}" r="2.5" class="pfx-micro-trend__marker" data-tone="${escapeHtml$1(c.tone)}" />`).join('');
|
|
1829
|
+
const scrubLayerHtml = renderTrendScrubLayerHtml(points, coords, width, height, visualization, options);
|
|
1709
1830
|
const isTable = visualization.surface === 'table-cell';
|
|
1710
1831
|
const firstPoint = points[0];
|
|
1711
1832
|
const lastPoint = points[points.length - 1];
|
|
@@ -1724,9 +1845,11 @@ function renderLineVisualizationHtml(visualization, options) {
|
|
|
1724
1845
|
${leftHtml}
|
|
1725
1846
|
<span class="pfx-micro-viz pfx-micro-viz__line" data-tone="${escapeHtml$1(tone)}" role="img" aria-label="${escapeHtml$1(visualization.ariaLabel ?? visualization.fallbackText)}">
|
|
1726
1847
|
<svg class="pfx-micro-line__svg" viewBox="0 0 100 30">
|
|
1848
|
+
${refLineHtml}
|
|
1727
1849
|
<path class="pfx-micro-line__path" d="${pathD}" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
|
1728
1850
|
${circlesHtml}
|
|
1729
1851
|
</svg>
|
|
1852
|
+
${scrubLayerHtml}
|
|
1730
1853
|
</span>
|
|
1731
1854
|
${rightHtml}
|
|
1732
1855
|
</span>`;
|
|
@@ -1740,8 +1863,9 @@ function renderAreaVisualizationHtml(visualization, options) {
|
|
|
1740
1863
|
const width = 100;
|
|
1741
1864
|
const height = 30;
|
|
1742
1865
|
const padding = 4;
|
|
1743
|
-
const coords = getPointsCoordinates(points, width, height, padding);
|
|
1866
|
+
const coords = getPointsCoordinates(points, width, height, padding, visualization);
|
|
1744
1867
|
const lineD = coords.map((c, i) => `${i === 0 ? 'M' : 'L'} ${c.x.toFixed(1)} ${c.y.toFixed(1)}`).join(' ');
|
|
1868
|
+
const refLineHtml = renderTrendReferenceLineHtml(points, width, height, padding, visualization, false);
|
|
1745
1869
|
const firstX = coords[0].x.toFixed(1);
|
|
1746
1870
|
const lastX = coords[coords.length - 1].x.toFixed(1);
|
|
1747
1871
|
const areaD = `${lineD} L ${lastX} ${height} L ${firstX} ${height} Z`;
|
|
@@ -1765,6 +1889,7 @@ function renderAreaVisualizationHtml(visualization, options) {
|
|
|
1765
1889
|
markers.push({ x: coords[maxIdx].x, y: coords[maxIdx].y, tone: points[maxIdx].tone ?? 'success' });
|
|
1766
1890
|
}
|
|
1767
1891
|
const circlesHtml = markers.map(c => `<circle cx="${c.x.toFixed(1)}" cy="${c.y.toFixed(1)}" r="2.5" class="pfx-micro-trend__marker" data-tone="${escapeHtml$1(c.tone)}" />`).join('');
|
|
1892
|
+
const scrubLayerHtml = renderTrendScrubLayerHtml(points, coords, width, height, visualization, options);
|
|
1768
1893
|
const isTable = visualization.surface === 'table-cell';
|
|
1769
1894
|
const firstPoint = points[0];
|
|
1770
1895
|
const lastPoint = points[points.length - 1];
|
|
@@ -1783,10 +1908,12 @@ function renderAreaVisualizationHtml(visualization, options) {
|
|
|
1783
1908
|
${leftHtml}
|
|
1784
1909
|
<span class="pfx-micro-viz pfx-micro-viz__area" data-tone="${escapeHtml$1(tone)}" role="img" aria-label="${escapeHtml$1(visualization.ariaLabel ?? visualization.fallbackText)}">
|
|
1785
1910
|
<svg class="pfx-micro-area__svg" viewBox="0 0 100 30">
|
|
1911
|
+
${refLineHtml}
|
|
1786
1912
|
<path class="pfx-micro-area__fill" d="${areaD}" fill="currentColor" fill-opacity="0.15" />
|
|
1787
1913
|
<path class="pfx-micro-area__path" d="${lineD}" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
|
1788
1914
|
${circlesHtml}
|
|
1789
1915
|
</svg>
|
|
1916
|
+
${scrubLayerHtml}
|
|
1790
1917
|
</span>
|
|
1791
1918
|
${rightHtml}
|
|
1792
1919
|
</span>`;
|
|
@@ -1800,21 +1927,22 @@ function renderColumnVisualizationHtml(visualization, options) {
|
|
|
1800
1927
|
const width = 100;
|
|
1801
1928
|
const height = 30;
|
|
1802
1929
|
const padding = 4;
|
|
1803
|
-
const
|
|
1804
|
-
const
|
|
1805
|
-
const minVal = Math.min(...values, 0);
|
|
1806
|
-
const valRange = maxVal - minVal === 0 ? 1 : maxVal - minVal;
|
|
1930
|
+
const { minVal, valRange } = resolveTrendBounds(points, visualization, true);
|
|
1931
|
+
const refLineHtml = renderTrendReferenceLineHtml(points, width, height, padding, visualization, true);
|
|
1807
1932
|
const colWidth = Math.max(2, (width - 2 * padding) / points.length - 2);
|
|
1933
|
+
const colCoords = [];
|
|
1808
1934
|
const columnsHtml = points.map((p, i) => {
|
|
1809
1935
|
const x = padding + i * ((width - 2 * padding) / points.length) + 1;
|
|
1810
1936
|
const rectHeight = Math.max(2, ((p.value - minVal) / valRange) * (height - 2 * padding));
|
|
1811
1937
|
const rectY = height - padding - rectHeight;
|
|
1938
|
+
colCoords.push({ x: x + colWidth / 2, y: rectY });
|
|
1812
1939
|
const itemTone = p.tone ??
|
|
1813
1940
|
(visualization.thresholds?.length
|
|
1814
1941
|
? resolvePraxisMicroVisualizationTone(p.value, visualization.thresholds)?.tone ?? tone
|
|
1815
1942
|
: tone);
|
|
1816
|
-
return `<rect class="pfx-micro-column__bar" x="${x.toFixed(1)}" y="${rectY.toFixed(1)}" width="${colWidth.toFixed(1)}" height="${rectHeight.toFixed(1)}" fill="currentColor" data-tone="${escapeHtml$1(itemTone)}" />`;
|
|
1943
|
+
return `<rect class="pfx-micro-column__bar" x="${x.toFixed(1)}" y="${rectY.toFixed(1)}" width="${colWidth.toFixed(1)}" height="${rectHeight.toFixed(1)}" rx="1" fill="currentColor" data-tone="${escapeHtml$1(itemTone)}" />`;
|
|
1817
1944
|
}).join('');
|
|
1945
|
+
const scrubLayerHtml = renderTrendScrubLayerHtml(points, colCoords, width, height, visualization, options);
|
|
1818
1946
|
const isTable = visualization.surface === 'table-cell';
|
|
1819
1947
|
const firstPoint = points[0];
|
|
1820
1948
|
const lastPoint = points[points.length - 1];
|
|
@@ -1834,7 +1962,9 @@ function renderColumnVisualizationHtml(visualization, options) {
|
|
|
1834
1962
|
<span class="pfx-micro-viz pfx-micro-viz__column" data-tone="${escapeHtml$1(tone)}" role="img" aria-label="${escapeHtml$1(visualization.ariaLabel ?? visualization.fallbackText)}">
|
|
1835
1963
|
<svg class="pfx-micro-column__svg" viewBox="0 0 100 30">
|
|
1836
1964
|
${columnsHtml}
|
|
1965
|
+
${refLineHtml}
|
|
1837
1966
|
</svg>
|
|
1967
|
+
${scrubLayerHtml}
|
|
1838
1968
|
</span>
|
|
1839
1969
|
${rightHtml}
|
|
1840
1970
|
</span>`;
|
|
@@ -1864,14 +1994,23 @@ function renderProcessFlowVisualizationHtml(visualization, options) {
|
|
|
1864
1994
|
const isLast = index === items.length - 1;
|
|
1865
1995
|
const itemLabel = stepLabels[index];
|
|
1866
1996
|
const label = !isTable && item.label ? `<span class="pfx-micro-step__label"${labelInlineStyle}>${escapeHtml$1(item.label)}</span>` : '';
|
|
1997
|
+
const isActiveStep = itemState === 'active' ||
|
|
1998
|
+
itemState === 'current' ||
|
|
1999
|
+
itemState === 'in_progress' ||
|
|
2000
|
+
item.icon === 'sync' ||
|
|
2001
|
+
item.icon === 'pending' ||
|
|
2002
|
+
item.icon === 'pending_actions' ||
|
|
2003
|
+
item.icon === 'schedule' ||
|
|
2004
|
+
(!itemState && itemTone === 'warning');
|
|
2005
|
+
const stepReadout = `${index + 1}/${items.length} · ${itemLabel}`;
|
|
1867
2006
|
const connector = !isLast ? `<span class="pfx-micro-step__connector" data-tone="${escapeHtml$1(itemTone)}"></span>` : '';
|
|
1868
2007
|
const stepCircle = `
|
|
1869
|
-
<span class="pfx-micro-step__node" data-tone="${escapeHtml$1(itemTone)}" aria-hidden="true">
|
|
2008
|
+
<span class="pfx-micro-step__node" data-tone="${escapeHtml$1(itemTone)}"${isActiveStep ? ' data-active="true"' : ''} aria-hidden="true">
|
|
1870
2009
|
${item.icon ? `<span class="material-icons pfx-micro-step__icon" aria-hidden="true">${escapeHtml$1(item.icon)}</span>` : `${index + 1}`}
|
|
1871
2010
|
</span>`;
|
|
1872
2011
|
return `
|
|
1873
2012
|
<div class="pfx-micro-step" data-state="${escapeHtml$1(itemState)}" data-tone="${escapeHtml$1(itemTone)}">
|
|
1874
|
-
<div class="pfx-micro-step__node-wrapper" title="${escapeHtml$1(itemLabel)}">
|
|
2013
|
+
<div class="pfx-micro-step__node-wrapper" data-micro-readout="${escapeHtml$1(stepReadout)}" title="${escapeHtml$1(itemLabel)}">
|
|
1875
2014
|
${stepCircle}
|
|
1876
2015
|
${label}
|
|
1877
2016
|
</div>
|
|
@@ -3028,10 +3167,14 @@ class SchemaNormalizationKernel {
|
|
|
3028
3167
|
out.maxLength = Number(ui.maxLength);
|
|
3029
3168
|
if (ui.maxLengthMessage !== undefined)
|
|
3030
3169
|
out.maxLengthMessage = ui.maxLengthMessage;
|
|
3031
|
-
if (ui.min !== undefined)
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3170
|
+
if (ui.min !== undefined) {
|
|
3171
|
+
const parsedMin = Number(ui.min);
|
|
3172
|
+
out.min = Number.isFinite(parsedMin) ? parsedMin : String(ui.min).trim();
|
|
3173
|
+
}
|
|
3174
|
+
if (ui.max !== undefined) {
|
|
3175
|
+
const parsedMax = Number(ui.max);
|
|
3176
|
+
out.max = Number.isFinite(parsedMax) ? parsedMax : String(ui.max).trim();
|
|
3177
|
+
}
|
|
3035
3178
|
if (ui.minMessage !== undefined)
|
|
3036
3179
|
out.minMessage = ui.minMessage;
|
|
3037
3180
|
if (ui.maxMessage !== undefined)
|
|
@@ -3168,14 +3311,18 @@ class SchemaNormalizationKernel {
|
|
|
3168
3311
|
return ['number', 'integer', 'int', 'float', 'double', 'decimal'].includes(token);
|
|
3169
3312
|
}
|
|
3170
3313
|
resolveNumericFormatToken(prop, ui, resolvedType) {
|
|
3314
|
+
if (ui?.numberFormat?.percentage === true || ui?.['numberFormat.percentage'] === true) {
|
|
3315
|
+
return 'percent';
|
|
3316
|
+
}
|
|
3317
|
+
const explicitUiFormat = this.resolveNonEmptyStringToken(ui?.numericFormat, ui?.numberFormat?.style, ui?.['numberFormat.style']);
|
|
3318
|
+
if (explicitUiFormat) {
|
|
3319
|
+
return explicitUiFormat;
|
|
3320
|
+
}
|
|
3171
3321
|
const typeToken = resolvedType ?? prop?.type;
|
|
3172
3322
|
if (!this.isNumericSchemaType(typeToken)) {
|
|
3173
3323
|
return undefined;
|
|
3174
3324
|
}
|
|
3175
|
-
|
|
3176
|
-
return 'percent';
|
|
3177
|
-
}
|
|
3178
|
-
return this.resolveNonEmptyStringToken(ui?.numericFormat, ui?.format, ui?.numberFormat?.style, ui?.['numberFormat.style'], prop?.format);
|
|
3325
|
+
return this.resolveNonEmptyStringToken(ui?.format, prop?.format);
|
|
3179
3326
|
}
|
|
3180
3327
|
/**
|
|
3181
3328
|
* Converte o schema bruto do backend (OpenAPI + x-ui) em FieldDefinition[] tipado.
|
|
@@ -3543,10 +3690,22 @@ class SchemaNormalizationKernel {
|
|
|
3543
3690
|
field.numericStep = Number(ui.numericStep);
|
|
3544
3691
|
}
|
|
3545
3692
|
if (ui.numericMin !== undefined) {
|
|
3546
|
-
|
|
3693
|
+
const parsedMin = Number(ui.numericMin);
|
|
3694
|
+
if (Number.isFinite(parsedMin)) {
|
|
3695
|
+
field.numericMin = parsedMin;
|
|
3696
|
+
}
|
|
3697
|
+
else if (field.min === undefined && String(ui.numericMin).trim().length > 0) {
|
|
3698
|
+
field.min = String(ui.numericMin).trim();
|
|
3699
|
+
}
|
|
3547
3700
|
}
|
|
3548
3701
|
if (ui.numericMax !== undefined) {
|
|
3549
|
-
|
|
3702
|
+
const parsedMax = Number(ui.numericMax);
|
|
3703
|
+
if (Number.isFinite(parsedMax)) {
|
|
3704
|
+
field.numericMax = parsedMax;
|
|
3705
|
+
}
|
|
3706
|
+
else if (field.max === undefined && String(ui.numericMax).trim().length > 0) {
|
|
3707
|
+
field.max = String(ui.numericMax).trim();
|
|
3708
|
+
}
|
|
3550
3709
|
}
|
|
3551
3710
|
if (ui.numericMaxLength !== undefined) {
|
|
3552
3711
|
field.numericMaxLength = Number(ui.numericMaxLength);
|
|
@@ -3554,6 +3713,145 @@ class SchemaNormalizationKernel {
|
|
|
3554
3713
|
if (ui.buttons !== undefined) {
|
|
3555
3714
|
field.buttons = this.parseButtons(ui.buttons);
|
|
3556
3715
|
}
|
|
3716
|
+
// -------------------------------------------------------------------
|
|
3717
|
+
// Inline filter and specialized control metadata (x-ui)
|
|
3718
|
+
// -------------------------------------------------------------------
|
|
3719
|
+
const inlinePassThroughKeys = [
|
|
3720
|
+
'prefixIcon',
|
|
3721
|
+
'suffixIcon',
|
|
3722
|
+
'prefixIconColor',
|
|
3723
|
+
'suffixIconColor',
|
|
3724
|
+
'chipLeadingIcon',
|
|
3725
|
+
'chipTrailingIcon',
|
|
3726
|
+
'chipLeadingIconColor',
|
|
3727
|
+
'chipTrailingIconColor',
|
|
3728
|
+
'clearIcon',
|
|
3729
|
+
'clearIconColor',
|
|
3730
|
+
'showQuickClear',
|
|
3731
|
+
'clearable',
|
|
3732
|
+
'inlineAutoSize',
|
|
3733
|
+
'inlineAutoSizeMaxPx',
|
|
3734
|
+
'inlineAutoSizeMaxVw',
|
|
3735
|
+
'inlineOverlay',
|
|
3736
|
+
'inlineChipDisplay',
|
|
3737
|
+
'inlineChipSummaryTemplate',
|
|
3738
|
+
'inlineChipUnitLabel',
|
|
3739
|
+
'inlinePanelTitle',
|
|
3740
|
+
'inlineQuickPresets',
|
|
3741
|
+
'inlineQuickPresetsApplyMode',
|
|
3742
|
+
'inlineTexts',
|
|
3743
|
+
'shortcuts',
|
|
3744
|
+
'showShortcuts',
|
|
3745
|
+
'quickPresets',
|
|
3746
|
+
'quickPresetsAuto',
|
|
3747
|
+
'quickPresetsLabels',
|
|
3748
|
+
'granularity',
|
|
3749
|
+
'defaultGranularity',
|
|
3750
|
+
'selectionGrid',
|
|
3751
|
+
'showSlider',
|
|
3752
|
+
'showInputs',
|
|
3753
|
+
'minPeriod',
|
|
3754
|
+
'maxPeriod',
|
|
3755
|
+
'minYear',
|
|
3756
|
+
'maxYear',
|
|
3757
|
+
'minTime',
|
|
3758
|
+
'maxTime',
|
|
3759
|
+
'stepMinutes',
|
|
3760
|
+
'startField',
|
|
3761
|
+
'endField',
|
|
3762
|
+
'startLabel',
|
|
3763
|
+
'endLabel',
|
|
3764
|
+
'startPlaceholder',
|
|
3765
|
+
'endPlaceholder',
|
|
3766
|
+
'inputMinLabel',
|
|
3767
|
+
'inputMaxLabel',
|
|
3768
|
+
'maxVisibleChips',
|
|
3769
|
+
'maxVisibleBadges',
|
|
3770
|
+
'showSelectAll',
|
|
3771
|
+
'selectAllLabel',
|
|
3772
|
+
'clearSelectionLabel',
|
|
3773
|
+
'searchPlaceholder',
|
|
3774
|
+
'noResultsText',
|
|
3775
|
+
'allowSelectAll',
|
|
3776
|
+
'governedPaletteRef',
|
|
3777
|
+
'palette',
|
|
3778
|
+
'paletteColors',
|
|
3779
|
+
'paletteSettings',
|
|
3780
|
+
'documentType',
|
|
3781
|
+
'version',
|
|
3782
|
+
'nodes',
|
|
3783
|
+
'nodeIdField',
|
|
3784
|
+
'parentIdField',
|
|
3785
|
+
'childrenField',
|
|
3786
|
+
'lazyLoad',
|
|
3787
|
+
'marks',
|
|
3788
|
+
'semanticBands',
|
|
3789
|
+
'distribution',
|
|
3790
|
+
'discrete',
|
|
3791
|
+
'showTicks',
|
|
3792
|
+
'trueLabel',
|
|
3793
|
+
'falseLabel',
|
|
3794
|
+
'currencyCode',
|
|
3795
|
+
'locale',
|
|
3796
|
+
'precision',
|
|
3797
|
+
'rangeMode',
|
|
3798
|
+
'maxRating',
|
|
3799
|
+
'allowHalf',
|
|
3800
|
+
'ratingIcon',
|
|
3801
|
+
'ratingEmptyIcon',
|
|
3802
|
+
'ratingHalfIcon',
|
|
3803
|
+
'ratingTone',
|
|
3804
|
+
'ratingToneColors',
|
|
3805
|
+
'ratingLabels',
|
|
3806
|
+
'distanceUnit',
|
|
3807
|
+
'distanceBaseUnit',
|
|
3808
|
+
'distanceUnits',
|
|
3809
|
+
'distanceAllowUnitToggle',
|
|
3810
|
+
'distanceUnitLabels',
|
|
3811
|
+
'distanceDisplayDecimals',
|
|
3812
|
+
'distanceDecimalsKm',
|
|
3813
|
+
'distanceDecimalsMi',
|
|
3814
|
+
'distancePresets',
|
|
3815
|
+
'distanceSubtitle',
|
|
3816
|
+
'distanceRadialRings',
|
|
3817
|
+
'distanceAccentColor',
|
|
3818
|
+
'distanceRingColor',
|
|
3819
|
+
'distanceTrackColor',
|
|
3820
|
+
'distanceGlowColor',
|
|
3821
|
+
'distanceGradientLowColor',
|
|
3822
|
+
'distanceGradientMidColor',
|
|
3823
|
+
'distanceGradientHighColor',
|
|
3824
|
+
'distanceRangeBandOpacity',
|
|
3825
|
+
'pipelineOptions',
|
|
3826
|
+
'pipelineColors',
|
|
3827
|
+
'pipelineTexts',
|
|
3828
|
+
'scoreBands',
|
|
3829
|
+
'priorityBands',
|
|
3830
|
+
'severityBands',
|
|
3831
|
+
'scorePalette',
|
|
3832
|
+
'scoreTexts',
|
|
3833
|
+
'relativePeriodOptions',
|
|
3834
|
+
'relativePeriodPresets',
|
|
3835
|
+
'relativePeriodTexts',
|
|
3836
|
+
'sentimentOptions',
|
|
3837
|
+
'sentimentPalette',
|
|
3838
|
+
'sentimentTexts',
|
|
3839
|
+
'colorLabelOptions',
|
|
3840
|
+
'colorLabelPalette',
|
|
3841
|
+
'colorLabelTexts',
|
|
3842
|
+
'timeOptions',
|
|
3843
|
+
'inlineTimeQuickPresets',
|
|
3844
|
+
'inlineVisualStyle',
|
|
3845
|
+
'percentPresets',
|
|
3846
|
+
'numberFormat',
|
|
3847
|
+
'valueLabelFormat',
|
|
3848
|
+
'scale',
|
|
3849
|
+
];
|
|
3850
|
+
for (const key of inlinePassThroughKeys) {
|
|
3851
|
+
if (ui[key] !== undefined && field[key] === undefined) {
|
|
3852
|
+
field[key] = ui[key];
|
|
3853
|
+
}
|
|
3854
|
+
}
|
|
3557
3855
|
fields.push(field);
|
|
3558
3856
|
}
|
|
3559
3857
|
if (fields.length === 0 &&
|
|
@@ -3600,7 +3898,21 @@ class SchemaNormalizationKernel {
|
|
|
3600
3898
|
}
|
|
3601
3899
|
// Compatibilidade para schemas de range publicados como oneOf(array|object).
|
|
3602
3900
|
const controlToken = String(ui?.controlType || '').trim().toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
3603
|
-
const isRangeControl = [
|
|
3901
|
+
const isRangeControl = [
|
|
3902
|
+
'daterange',
|
|
3903
|
+
'datetimerange',
|
|
3904
|
+
'rangeslider',
|
|
3905
|
+
'pricerange',
|
|
3906
|
+
'inlinerange',
|
|
3907
|
+
'inlinecurrencyrange',
|
|
3908
|
+
'inlinedaterange',
|
|
3909
|
+
'inlineperiodrange',
|
|
3910
|
+
'inlineyearrange',
|
|
3911
|
+
'inlinemonthrange',
|
|
3912
|
+
'inlinetimerange',
|
|
3913
|
+
'inlinedistanceradius',
|
|
3914
|
+
'inlinescorepriority',
|
|
3915
|
+
].includes(controlToken);
|
|
3604
3916
|
if (isRangeControl && nonNullTypes.includes('array')) {
|
|
3605
3917
|
return 'array';
|
|
3606
3918
|
}
|
|
@@ -12320,6 +12632,133 @@ function mapFieldDefinitionToMetadata(field) {
|
|
|
12320
12632
|
'copyIdActionLabel',
|
|
12321
12633
|
'createActionLabel',
|
|
12322
12634
|
'actions',
|
|
12635
|
+
'prefixIconColor',
|
|
12636
|
+
'suffixIconColor',
|
|
12637
|
+
'chipLeadingIcon',
|
|
12638
|
+
'chipTrailingIcon',
|
|
12639
|
+
'chipLeadingIconColor',
|
|
12640
|
+
'chipTrailingIconColor',
|
|
12641
|
+
'clearIcon',
|
|
12642
|
+
'clearIconColor',
|
|
12643
|
+
'showQuickClear',
|
|
12644
|
+
'clearable',
|
|
12645
|
+
'inlineAutoSize',
|
|
12646
|
+
'inlineAutoSizeMaxPx',
|
|
12647
|
+
'inlineAutoSizeMaxVw',
|
|
12648
|
+
'inlineOverlay',
|
|
12649
|
+
'inlineChipDisplay',
|
|
12650
|
+
'inlineChipSummaryTemplate',
|
|
12651
|
+
'inlineChipUnitLabel',
|
|
12652
|
+
'inlinePanelTitle',
|
|
12653
|
+
'inlineQuickPresets',
|
|
12654
|
+
'inlineQuickPresetsApplyMode',
|
|
12655
|
+
'inlineTexts',
|
|
12656
|
+
'shortcuts',
|
|
12657
|
+
'showShortcuts',
|
|
12658
|
+
'quickPresets',
|
|
12659
|
+
'quickPresetsAuto',
|
|
12660
|
+
'quickPresetsLabels',
|
|
12661
|
+
'granularity',
|
|
12662
|
+
'defaultGranularity',
|
|
12663
|
+
'selectionGrid',
|
|
12664
|
+
'showSlider',
|
|
12665
|
+
'showInputs',
|
|
12666
|
+
'minPeriod',
|
|
12667
|
+
'maxPeriod',
|
|
12668
|
+
'minYear',
|
|
12669
|
+
'maxYear',
|
|
12670
|
+
'minTime',
|
|
12671
|
+
'maxTime',
|
|
12672
|
+
'stepMinutes',
|
|
12673
|
+
'startField',
|
|
12674
|
+
'endField',
|
|
12675
|
+
'startLabel',
|
|
12676
|
+
'endLabel',
|
|
12677
|
+
'startPlaceholder',
|
|
12678
|
+
'endPlaceholder',
|
|
12679
|
+
'inputMinLabel',
|
|
12680
|
+
'inputMaxLabel',
|
|
12681
|
+
'maxVisibleChips',
|
|
12682
|
+
'maxVisibleBadges',
|
|
12683
|
+
'showSelectAll',
|
|
12684
|
+
'selectAllLabel',
|
|
12685
|
+
'clearSelectionLabel',
|
|
12686
|
+
'searchPlaceholder',
|
|
12687
|
+
'noResultsText',
|
|
12688
|
+
'allowSelectAll',
|
|
12689
|
+
'governedPaletteRef',
|
|
12690
|
+
'palette',
|
|
12691
|
+
'paletteColors',
|
|
12692
|
+
'paletteSettings',
|
|
12693
|
+
'documentType',
|
|
12694
|
+
'version',
|
|
12695
|
+
'nodes',
|
|
12696
|
+
'nodeIdField',
|
|
12697
|
+
'parentIdField',
|
|
12698
|
+
'childrenField',
|
|
12699
|
+
'lazyLoad',
|
|
12700
|
+
'marks',
|
|
12701
|
+
'semanticBands',
|
|
12702
|
+
'distribution',
|
|
12703
|
+
'discrete',
|
|
12704
|
+
'showTicks',
|
|
12705
|
+
'trueLabel',
|
|
12706
|
+
'falseLabel',
|
|
12707
|
+
'currencyCode',
|
|
12708
|
+
'locale',
|
|
12709
|
+
'precision',
|
|
12710
|
+
'rangeMode',
|
|
12711
|
+
'maxRating',
|
|
12712
|
+
'allowHalf',
|
|
12713
|
+
'ratingIcon',
|
|
12714
|
+
'ratingEmptyIcon',
|
|
12715
|
+
'ratingHalfIcon',
|
|
12716
|
+
'ratingTone',
|
|
12717
|
+
'ratingToneColors',
|
|
12718
|
+
'ratingLabels',
|
|
12719
|
+
'distanceUnit',
|
|
12720
|
+
'distanceBaseUnit',
|
|
12721
|
+
'distanceUnits',
|
|
12722
|
+
'distanceAllowUnitToggle',
|
|
12723
|
+
'distanceUnitLabels',
|
|
12724
|
+
'distanceDisplayDecimals',
|
|
12725
|
+
'distanceDecimalsKm',
|
|
12726
|
+
'distanceDecimalsMi',
|
|
12727
|
+
'distancePresets',
|
|
12728
|
+
'distanceSubtitle',
|
|
12729
|
+
'distanceRadialRings',
|
|
12730
|
+
'distanceAccentColor',
|
|
12731
|
+
'distanceRingColor',
|
|
12732
|
+
'distanceTrackColor',
|
|
12733
|
+
'distanceGlowColor',
|
|
12734
|
+
'distanceGradientLowColor',
|
|
12735
|
+
'distanceGradientMidColor',
|
|
12736
|
+
'distanceGradientHighColor',
|
|
12737
|
+
'distanceRangeBandOpacity',
|
|
12738
|
+
'pipelineOptions',
|
|
12739
|
+
'pipelineColors',
|
|
12740
|
+
'pipelineTexts',
|
|
12741
|
+
'scoreBands',
|
|
12742
|
+
'priorityBands',
|
|
12743
|
+
'severityBands',
|
|
12744
|
+
'scorePalette',
|
|
12745
|
+
'scoreTexts',
|
|
12746
|
+
'relativePeriodOptions',
|
|
12747
|
+
'relativePeriodPresets',
|
|
12748
|
+
'relativePeriodTexts',
|
|
12749
|
+
'sentimentOptions',
|
|
12750
|
+
'sentimentPalette',
|
|
12751
|
+
'sentimentTexts',
|
|
12752
|
+
'colorLabelOptions',
|
|
12753
|
+
'colorLabelPalette',
|
|
12754
|
+
'colorLabelTexts',
|
|
12755
|
+
'timeOptions',
|
|
12756
|
+
'inlineTimeQuickPresets',
|
|
12757
|
+
'inlineVisualStyle',
|
|
12758
|
+
'percentPresets',
|
|
12759
|
+
'numberFormat',
|
|
12760
|
+
'valueLabelFormat',
|
|
12761
|
+
'scale',
|
|
12323
12762
|
];
|
|
12324
12763
|
for (const prop of simpleProps) {
|
|
12325
12764
|
const value = field[prop];
|
|
@@ -12394,13 +12833,19 @@ function mapFieldDefinitionToMetadata(field) {
|
|
|
12394
12833
|
if (hasOptionsFilterEndpoint) {
|
|
12395
12834
|
metadata.optionsEndpoint = 'filter';
|
|
12396
12835
|
}
|
|
12397
|
-
if (field.numericMin !== undefined) {
|
|
12836
|
+
if (field.numericMin !== undefined && !Number.isNaN(field.numericMin)) {
|
|
12398
12837
|
metadata.min = field.numericMin;
|
|
12399
12838
|
}
|
|
12400
|
-
if (field.
|
|
12839
|
+
else if (field.min !== undefined && field.min !== '' && !Number.isNaN(field.min)) {
|
|
12840
|
+
metadata.min = field.min;
|
|
12841
|
+
}
|
|
12842
|
+
if (field.numericMax !== undefined && !Number.isNaN(field.numericMax)) {
|
|
12401
12843
|
metadata.max = field.numericMax;
|
|
12402
12844
|
}
|
|
12403
|
-
if (field.
|
|
12845
|
+
else if (field.max !== undefined && field.max !== '' && !Number.isNaN(field.max)) {
|
|
12846
|
+
metadata.max = field.max;
|
|
12847
|
+
}
|
|
12848
|
+
if (field.numericStep !== undefined && !Number.isNaN(field.numericStep)) {
|
|
12404
12849
|
metadata.step = field.numericStep;
|
|
12405
12850
|
}
|
|
12406
12851
|
const rawFormat = field.format;
|
|
@@ -12485,10 +12930,14 @@ function mapFieldDefinitionToMetadata(field) {
|
|
|
12485
12930
|
metadata.clearButton = field.clearButton;
|
|
12486
12931
|
}
|
|
12487
12932
|
if (field.options) {
|
|
12488
|
-
const mapped = field.options.map((opt) =>
|
|
12489
|
-
value
|
|
12490
|
-
|
|
12491
|
-
|
|
12933
|
+
const mapped = field.options.map((opt) => {
|
|
12934
|
+
const { key, value, ...rest } = opt ?? {};
|
|
12935
|
+
return {
|
|
12936
|
+
...rest,
|
|
12937
|
+
value: key,
|
|
12938
|
+
text: value,
|
|
12939
|
+
};
|
|
12940
|
+
});
|
|
12492
12941
|
metadata.options = mapped;
|
|
12493
12942
|
metadata.selectOptions = mapped;
|
|
12494
12943
|
}
|
|
@@ -14989,10 +15438,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
14989
15438
|
}], ctorParameters: () => [] });
|
|
14990
15439
|
|
|
14991
15440
|
class ResourceDiscoveryService {
|
|
14992
|
-
http = inject(HttpClient);
|
|
15441
|
+
http = inject(HttpClient, { optional: true });
|
|
14993
15442
|
schemaNormalizer = inject(SchemaNormalizerService);
|
|
14994
|
-
apiUrlConfig = inject(API_URL);
|
|
15443
|
+
apiUrlConfig = inject(API_URL, { optional: true });
|
|
14995
15444
|
surfaceCatalogInFlightByHref = new Map();
|
|
15445
|
+
schemaCatalogInFlightByUrl = new Map();
|
|
15446
|
+
schemaFieldsInFlightByUrl = new Map();
|
|
15447
|
+
/**
|
|
15448
|
+
* Indica se o serviço dispõe de transporte HTTP e configuração de API suficientes
|
|
15449
|
+
* para resolver schemas remotos (`/schemas/catalog` e `/schemas/filtered`).
|
|
15450
|
+
*/
|
|
15451
|
+
canResolveSchemas(options) {
|
|
15452
|
+
if (!this.http) {
|
|
15453
|
+
return false;
|
|
15454
|
+
}
|
|
15455
|
+
const entry = this.resolveApiEntry(options);
|
|
15456
|
+
return !!(entry && Object.keys(entry).length > 0);
|
|
15457
|
+
}
|
|
14996
15458
|
getLinks(source, rel) {
|
|
14997
15459
|
const candidate = this.extractLinks(source)?.[rel];
|
|
14998
15460
|
if (!candidate) {
|
|
@@ -15036,6 +15498,9 @@ class ResourceDiscoveryService {
|
|
|
15036
15498
|
if (!normalizedResourceKey) {
|
|
15037
15499
|
throw new Error('ResourceDiscoveryService requires a resource key for action discovery.');
|
|
15038
15500
|
}
|
|
15501
|
+
if (!this.http) {
|
|
15502
|
+
return throwError(() => new Error('ResourceDiscoveryService requires HttpClient for action discovery.'));
|
|
15503
|
+
}
|
|
15039
15504
|
return this.http.get(this.resolveHref('/schemas/actions', options), { params: new HttpParams().set('resource', normalizedResourceKey) });
|
|
15040
15505
|
}
|
|
15041
15506
|
getCapabilities(source, options) {
|
|
@@ -15045,16 +15510,591 @@ class ResourceDiscoveryService {
|
|
|
15045
15510
|
return this.fetchJson(href, options);
|
|
15046
15511
|
}
|
|
15047
15512
|
getSchemaCatalog(query = {}, options) {
|
|
15048
|
-
|
|
15513
|
+
if (!this.http) {
|
|
15514
|
+
return throwError(() => new Error('ResourceDiscoveryService requires HttpClient for schema catalog discovery.'));
|
|
15515
|
+
}
|
|
15516
|
+
const url = this.resolveHref('/schemas/catalog', options);
|
|
15517
|
+
const params = this.toSchemaCatalogParams(query);
|
|
15518
|
+
const serializedParams = params.toString();
|
|
15519
|
+
const cacheKey = serializedParams ? `${url}?${serializedParams}` : url;
|
|
15520
|
+
const existing = this.schemaCatalogInFlightByUrl.get(cacheKey);
|
|
15521
|
+
if (existing) {
|
|
15522
|
+
return existing;
|
|
15523
|
+
}
|
|
15524
|
+
let request;
|
|
15525
|
+
request = this.http
|
|
15526
|
+
.get(url, { params })
|
|
15527
|
+
.pipe(finalize$1(() => {
|
|
15528
|
+
if (this.schemaCatalogInFlightByUrl.get(cacheKey) === request) {
|
|
15529
|
+
this.schemaCatalogInFlightByUrl.delete(cacheKey);
|
|
15530
|
+
}
|
|
15531
|
+
}), shareReplay$1({ bufferSize: 1, refCount: true }));
|
|
15532
|
+
this.schemaCatalogInFlightByUrl.set(cacheKey, request);
|
|
15533
|
+
return request;
|
|
15534
|
+
}
|
|
15535
|
+
/**
|
|
15536
|
+
* Obtém a lista de recursos governados descobertos no `/schemas/catalog` do host,
|
|
15537
|
+
* projetados e filtrados pela intenção de consumo (`intent`).
|
|
15538
|
+
*/
|
|
15539
|
+
getDiscoveredResources(options) {
|
|
15540
|
+
if (!this.http || (!this.apiUrlConfig && !options?.apiUrlEntry)) {
|
|
15541
|
+
return of([]);
|
|
15542
|
+
}
|
|
15543
|
+
return this.getSchemaCatalog(options?.query ?? {}, options).pipe(map$1((catalog) => this.projectSchemaCatalogResources(catalog, options)));
|
|
15544
|
+
}
|
|
15545
|
+
/**
|
|
15546
|
+
* Versão baseada em `Promise` de `getDiscoveredResources(options)`.
|
|
15547
|
+
*/
|
|
15548
|
+
loadDiscoveredResources(options) {
|
|
15549
|
+
return firstValueFrom(this.getDiscoveredResources(options));
|
|
15550
|
+
}
|
|
15551
|
+
/**
|
|
15552
|
+
* Projeta a resposta bruta de `/schemas/catalog` em opções de recurso governadas (`DiscoveredResourceOption[]`),
|
|
15553
|
+
* inferindo capacidades operacionais (`collection`, `filter`, `stats`, `options`, `crud`),
|
|
15554
|
+
* agregando termos de busca semântica (`searchTerms`) e filtrando pelo `intent` solicitado.
|
|
15555
|
+
*/
|
|
15556
|
+
projectSchemaCatalogResources(catalog, options) {
|
|
15557
|
+
const normalizedOptions = typeof options === 'string' ? { intent: options } : options ?? {};
|
|
15558
|
+
const intent = normalizedOptions.intent ?? 'any';
|
|
15559
|
+
const endpoints = Array.isArray(catalog?.endpoints) ? catalog.endpoints : [];
|
|
15560
|
+
if (!endpoints.length) {
|
|
15561
|
+
return [];
|
|
15562
|
+
}
|
|
15563
|
+
const capabilityEntries = new Map();
|
|
15564
|
+
for (const endpoint of endpoints) {
|
|
15565
|
+
const path = String(endpoint?.path ?? '').trim();
|
|
15566
|
+
const resourceKey = String(endpoint?.resourceKey ?? '').trim();
|
|
15567
|
+
if (endpoint?.method !== 'GET' ||
|
|
15568
|
+
!resourceKey ||
|
|
15569
|
+
!path.startsWith('/') ||
|
|
15570
|
+
path.startsWith('//') ||
|
|
15571
|
+
path.includes('{') ||
|
|
15572
|
+
!path.endsWith('/capabilities')) {
|
|
15573
|
+
continue;
|
|
15574
|
+
}
|
|
15575
|
+
const explicitResourcePath = this.normalizeResourcePathValue(endpoint?.resourcePath);
|
|
15576
|
+
const basePath = explicitResourcePath || path.slice(0, -'/capabilities'.length);
|
|
15577
|
+
if (!basePath || basePath === '/') {
|
|
15578
|
+
continue;
|
|
15579
|
+
}
|
|
15580
|
+
if (!capabilityEntries.has(basePath)) {
|
|
15581
|
+
capabilityEntries.set(basePath, { basePath, resourceKey, endpoint });
|
|
15582
|
+
}
|
|
15583
|
+
}
|
|
15584
|
+
for (const endpoint of endpoints) {
|
|
15585
|
+
const resourceKey = String(endpoint?.resourceKey ?? '').trim();
|
|
15586
|
+
const explicitResourcePath = this.normalizeResourcePathValue(endpoint?.resourcePath);
|
|
15587
|
+
if (!resourceKey ||
|
|
15588
|
+
!explicitResourcePath ||
|
|
15589
|
+
explicitResourcePath === '/' ||
|
|
15590
|
+
explicitResourcePath.startsWith('//') ||
|
|
15591
|
+
explicitResourcePath.includes('{')) {
|
|
15592
|
+
continue;
|
|
15593
|
+
}
|
|
15594
|
+
if (!capabilityEntries.has(explicitResourcePath)) {
|
|
15595
|
+
capabilityEntries.set(explicitResourcePath, {
|
|
15596
|
+
basePath: explicitResourcePath,
|
|
15597
|
+
resourceKey,
|
|
15598
|
+
endpoint,
|
|
15599
|
+
});
|
|
15600
|
+
}
|
|
15601
|
+
}
|
|
15602
|
+
if (!capabilityEntries.size) {
|
|
15603
|
+
return [];
|
|
15604
|
+
}
|
|
15605
|
+
const catalogHasExplicitOptionsEndpoints = endpoints.some((ep) => {
|
|
15606
|
+
const p = String(ep?.path ?? '').trim();
|
|
15607
|
+
return (p.endsWith('/options/filter') ||
|
|
15608
|
+
p.endsWith('/options/by-ids') ||
|
|
15609
|
+
p.endsWith('/options') ||
|
|
15610
|
+
p.includes('/option-sources'));
|
|
15611
|
+
});
|
|
15612
|
+
const catalogHasExplicitItemOrMutationEndpoints = [...capabilityEntries.values()].some(({ basePath, resourceKey }) => endpoints.some((ep) => {
|
|
15613
|
+
const p = String(ep?.path ?? '').trim();
|
|
15614
|
+
const method = String(ep?.method ?? '').toUpperCase();
|
|
15615
|
+
const epKey = String(ep?.resourceKey ?? '').trim();
|
|
15616
|
+
if (epKey && epKey !== resourceKey) {
|
|
15617
|
+
return false;
|
|
15618
|
+
}
|
|
15619
|
+
if (p === basePath && method === 'POST') {
|
|
15620
|
+
return true;
|
|
15621
|
+
}
|
|
15622
|
+
return (p.startsWith(`${basePath}/{`) &&
|
|
15623
|
+
!p.endsWith('/capabilities') &&
|
|
15624
|
+
!p.endsWith('/surfaces') &&
|
|
15625
|
+
!p.endsWith('/actions') &&
|
|
15626
|
+
(method === 'GET' || method === 'PUT' || method === 'PATCH' || method === 'DELETE'));
|
|
15627
|
+
}));
|
|
15628
|
+
const apiPrefix = this.resolveConfiguredApiPathPrefix(normalizedOptions);
|
|
15629
|
+
const group = String(catalog?.group ?? '').trim() || null;
|
|
15630
|
+
const projected = [];
|
|
15631
|
+
for (const { basePath, resourceKey, endpoint } of capabilityEntries.values()) {
|
|
15632
|
+
const siblingEndpoints = endpoints.filter((candidate) => {
|
|
15633
|
+
const candidatePath = String(candidate?.path ?? '').trim();
|
|
15634
|
+
const candidateKey = String(candidate?.resourceKey ?? '').trim();
|
|
15635
|
+
const candidateResourcePath = this.normalizeResourcePathValue(candidate?.resourcePath);
|
|
15636
|
+
if (candidateKey && candidateKey !== resourceKey) {
|
|
15637
|
+
return false;
|
|
15638
|
+
}
|
|
15639
|
+
return (candidateKey === resourceKey ||
|
|
15640
|
+
candidateResourcePath === basePath ||
|
|
15641
|
+
candidatePath === basePath ||
|
|
15642
|
+
candidatePath.startsWith(`${basePath}/`));
|
|
15643
|
+
});
|
|
15644
|
+
const operationalEndpoints = siblingEndpoints.filter((candidate) => {
|
|
15645
|
+
const candidatePath = String(candidate?.path ?? '').trim();
|
|
15646
|
+
return (!candidatePath.endsWith('/capabilities') &&
|
|
15647
|
+
!candidatePath.endsWith('/surfaces') &&
|
|
15648
|
+
!candidatePath.endsWith('/actions'));
|
|
15649
|
+
});
|
|
15650
|
+
const canonicalOperations = this.extractCanonicalResourceCapabilities(endpoint, siblingEndpoints);
|
|
15651
|
+
const readOnly = this.extractCanonicalResourceReadOnly(endpoint, siblingEndpoints, canonicalOperations);
|
|
15652
|
+
const capabilities = this.resolveResourceCapabilities(basePath, operationalEndpoints, catalogHasExplicitOptionsEndpoints, catalogHasExplicitItemOrMutationEndpoints, canonicalOperations);
|
|
15653
|
+
if (!this.matchesResourceIntent(capabilities, intent)) {
|
|
15654
|
+
continue;
|
|
15655
|
+
}
|
|
15656
|
+
const canonicalPath = this.stripConfiguredApiPrefix(basePath, apiPrefix);
|
|
15657
|
+
const label = String(endpoint.resourceVisual?.title ?? '').trim() || resourceKey;
|
|
15658
|
+
const description = String(endpoint.resourceVisual?.description ??
|
|
15659
|
+
endpoint.description ??
|
|
15660
|
+
endpoint.summary ??
|
|
15661
|
+
'').trim() || null;
|
|
15662
|
+
const icon = String(endpoint.resourceVisual?.icon ?? '').trim() || null;
|
|
15663
|
+
const tone = String(endpoint.resourceVisual?.tone ?? '').trim() || null;
|
|
15664
|
+
const tagsSet = new Set();
|
|
15665
|
+
const searchTermsSet = new Set([
|
|
15666
|
+
label,
|
|
15667
|
+
resourceKey,
|
|
15668
|
+
basePath,
|
|
15669
|
+
canonicalPath,
|
|
15670
|
+
canonicalPath.replace(/^\/+/, ''),
|
|
15671
|
+
]);
|
|
15672
|
+
if (group) {
|
|
15673
|
+
searchTermsSet.add(group);
|
|
15674
|
+
}
|
|
15675
|
+
if (description) {
|
|
15676
|
+
searchTermsSet.add(description);
|
|
15677
|
+
}
|
|
15678
|
+
for (const sibling of siblingEndpoints) {
|
|
15679
|
+
for (const tag of sibling.tags ?? []) {
|
|
15680
|
+
const trimmedTag = String(tag ?? '').trim();
|
|
15681
|
+
if (trimmedTag) {
|
|
15682
|
+
tagsSet.add(trimmedTag);
|
|
15683
|
+
searchTermsSet.add(trimmedTag);
|
|
15684
|
+
}
|
|
15685
|
+
}
|
|
15686
|
+
const siblingTitle = String(sibling.resourceVisual?.title ?? '').trim();
|
|
15687
|
+
if (siblingTitle) {
|
|
15688
|
+
searchTermsSet.add(siblingTitle);
|
|
15689
|
+
}
|
|
15690
|
+
const siblingDesc = String(sibling.resourceVisual?.description ?? '').trim();
|
|
15691
|
+
if (siblingDesc) {
|
|
15692
|
+
searchTermsSet.add(siblingDesc);
|
|
15693
|
+
}
|
|
15694
|
+
const summary = String(sibling.summary ?? '').trim();
|
|
15695
|
+
if (summary) {
|
|
15696
|
+
searchTermsSet.add(summary);
|
|
15697
|
+
}
|
|
15698
|
+
const epDescription = String(sibling.description ?? '').trim();
|
|
15699
|
+
if (epDescription) {
|
|
15700
|
+
searchTermsSet.add(epDescription);
|
|
15701
|
+
}
|
|
15702
|
+
}
|
|
15703
|
+
const { responseSchemaUrl, responseFields } = this.extractResourceResponseSchema(basePath, endpoint, operationalEndpoints);
|
|
15704
|
+
const { filterSchemaUrl, filterFields } = this.extractResourceFilterSchema(basePath, endpoint, operationalEndpoints);
|
|
15705
|
+
const option = {
|
|
15706
|
+
value: basePath,
|
|
15707
|
+
label,
|
|
15708
|
+
resourceKey,
|
|
15709
|
+
path: canonicalPath,
|
|
15710
|
+
group,
|
|
15711
|
+
description,
|
|
15712
|
+
icon,
|
|
15713
|
+
tone,
|
|
15714
|
+
tags: [...tagsSet],
|
|
15715
|
+
searchTerms: [...searchTermsSet].filter(Boolean),
|
|
15716
|
+
capabilities,
|
|
15717
|
+
};
|
|
15718
|
+
if (readOnly !== null) {
|
|
15719
|
+
option.readOnly = readOnly;
|
|
15720
|
+
}
|
|
15721
|
+
if (canonicalOperations) {
|
|
15722
|
+
option.canonicalOperations = canonicalOperations;
|
|
15723
|
+
}
|
|
15724
|
+
if (responseSchemaUrl) {
|
|
15725
|
+
option.responseSchemaUrl = responseSchemaUrl;
|
|
15726
|
+
}
|
|
15727
|
+
if (responseFields.length > 0) {
|
|
15728
|
+
option.responseFields = responseFields;
|
|
15729
|
+
}
|
|
15730
|
+
if (filterSchemaUrl) {
|
|
15731
|
+
option.filterSchemaUrl = filterSchemaUrl;
|
|
15732
|
+
}
|
|
15733
|
+
if (filterFields.length > 0) {
|
|
15734
|
+
option.filterFields = filterFields;
|
|
15735
|
+
}
|
|
15736
|
+
projected.push(option);
|
|
15737
|
+
}
|
|
15738
|
+
return projected.sort((left, right) => left.label.localeCompare(right.label) ||
|
|
15739
|
+
left.value.localeCompare(right.value));
|
|
15740
|
+
}
|
|
15741
|
+
/**
|
|
15742
|
+
* Reconcilia um `resourcePath` arbitrário (relativo, com prefixo `/api`, com sufixo operacional
|
|
15743
|
+
* como `/filter` ou `/stats/group-by`, ou `resourceKey`) com o `value` canônico da opção
|
|
15744
|
+
* correspondente em `resources`. Caso não haja correspondência, retorna o caminho normalizado.
|
|
15745
|
+
*/
|
|
15746
|
+
resolveCatalogResourceOptionValue(resourcePath, resources = [], options) {
|
|
15747
|
+
const matched = this.findCatalogResourceOption(resourcePath, resources, options);
|
|
15748
|
+
if (matched) {
|
|
15749
|
+
return matched.value;
|
|
15750
|
+
}
|
|
15751
|
+
return this.normalizeResourcePathValue(resourcePath);
|
|
15752
|
+
}
|
|
15753
|
+
/**
|
|
15754
|
+
* Localiza a opção de catálogo que representa o mesmo recurso lógico que `resourcePath`,
|
|
15755
|
+
* considerando prefixos configurados em `API_URL`, prefixo `/api`, barras iniciais/finais,
|
|
15756
|
+
* sufixos operacionais (`/filter`, `/options/filter`, `/stats/*`, etc.) e `resourceKey`.
|
|
15757
|
+
*/
|
|
15758
|
+
findCatalogResourceOption(resourcePath, resources = [], options) {
|
|
15759
|
+
const raw = String(resourcePath ?? '').trim();
|
|
15760
|
+
if (!raw || !resources.length) {
|
|
15761
|
+
return null;
|
|
15762
|
+
}
|
|
15763
|
+
const candidates = this.buildPathReconciliationCandidates(raw, options);
|
|
15764
|
+
for (const resource of resources) {
|
|
15765
|
+
const resourceKey = String(resource.resourceKey ?? '').trim();
|
|
15766
|
+
if (resourceKey && resourceKey === raw) {
|
|
15767
|
+
return resource;
|
|
15768
|
+
}
|
|
15769
|
+
const optionCandidates = new Set([
|
|
15770
|
+
...this.buildPathReconciliationCandidates(resource.value, options),
|
|
15771
|
+
...(resource.path
|
|
15772
|
+
? this.buildPathReconciliationCandidates(resource.path, options)
|
|
15773
|
+
: []),
|
|
15774
|
+
]);
|
|
15775
|
+
for (const candidate of candidates) {
|
|
15776
|
+
if (optionCandidates.has(candidate)) {
|
|
15777
|
+
return resource;
|
|
15778
|
+
}
|
|
15779
|
+
}
|
|
15780
|
+
}
|
|
15781
|
+
return null;
|
|
15049
15782
|
}
|
|
15050
15783
|
fetchJson(href, options) {
|
|
15784
|
+
if (!this.http) {
|
|
15785
|
+
return throwError(() => new Error('ResourceDiscoveryService requires HttpClient to fetch JSON.'));
|
|
15786
|
+
}
|
|
15051
15787
|
return this.http.get(this.resolveHref(href, options));
|
|
15052
15788
|
}
|
|
15053
15789
|
getSchemaByUrl(schemaUrl, options) {
|
|
15054
15790
|
return this.fetchJson(schemaUrl, options);
|
|
15055
15791
|
}
|
|
15056
15792
|
getSchemaFieldsByUrl(schemaUrl, options) {
|
|
15057
|
-
|
|
15793
|
+
const normalizedUrl = String(schemaUrl ?? '').trim();
|
|
15794
|
+
if (!normalizedUrl) {
|
|
15795
|
+
return of([]);
|
|
15796
|
+
}
|
|
15797
|
+
const resolvedUrl = this.resolveHref(normalizedUrl, options);
|
|
15798
|
+
const cacheKey = `${options?.endpointKey ?? 'default'}::${this.resolveApiBaseUrl(options)}::${resolvedUrl}`;
|
|
15799
|
+
const existing = this.schemaFieldsInFlightByUrl.get(cacheKey);
|
|
15800
|
+
if (existing) {
|
|
15801
|
+
return existing;
|
|
15802
|
+
}
|
|
15803
|
+
let request$;
|
|
15804
|
+
request$ = this.getSchemaByUrl(normalizedUrl, options).pipe(map$1((schema) => this.schemaNormalizer.normalizeSchema(schema)), catchError$1((err) => {
|
|
15805
|
+
if (this.schemaFieldsInFlightByUrl.get(cacheKey) === request$) {
|
|
15806
|
+
this.schemaFieldsInFlightByUrl.delete(cacheKey);
|
|
15807
|
+
}
|
|
15808
|
+
return throwError(() => err);
|
|
15809
|
+
}), shareReplay$1({ bufferSize: 1, refCount: false }));
|
|
15810
|
+
this.schemaFieldsInFlightByUrl.set(cacheKey, request$);
|
|
15811
|
+
return request$;
|
|
15812
|
+
}
|
|
15813
|
+
/**
|
|
15814
|
+
* Resolve os campos do schema de resposta (`response`) de um recurso de catálogo a partir
|
|
15815
|
+
* do seu `resourcePath` ou `resourceKey`.
|
|
15816
|
+
*
|
|
15817
|
+
* Estratégia zero-friction:
|
|
15818
|
+
* 1. Se o endpoint no `/schemas/catalog` publicar `schemaLinks.response`, busca e normaliza
|
|
15819
|
+
* o schema completo via `getSchemaFieldsByUrl` (com fallback para `responseFields` do catálogo).
|
|
15820
|
+
* 2. Caso contrário, projeta `FieldDefinition[]` diretamente do resumo `responseSchema.fields`
|
|
15821
|
+
* já carregado em `/schemas/catalog` sem round-trip extra.
|
|
15822
|
+
* 3. Se o recurso não constar no grupo default de `/schemas/catalog` (ex.: host multi-grupo)
|
|
15823
|
+
* ou não trouxer links/campos no catálogo, consulta diretamente `/schemas/filtered` para
|
|
15824
|
+
* `POST {resourcePath}/filter` (`schemaType=response`).
|
|
15825
|
+
*/
|
|
15826
|
+
getResourceSchemaFields(resourcePath, options) {
|
|
15827
|
+
const raw = String(resourcePath ?? '').trim();
|
|
15828
|
+
if (!raw) {
|
|
15829
|
+
return of([]);
|
|
15830
|
+
}
|
|
15831
|
+
return this.getDiscoveredResources({
|
|
15832
|
+
endpointKey: options?.endpointKey,
|
|
15833
|
+
apiUrlEntry: options?.apiUrlEntry,
|
|
15834
|
+
intent: 'any',
|
|
15835
|
+
}).pipe(switchMap$1((resources) => {
|
|
15836
|
+
const matched = this.findCatalogResourceOption(raw, resources, options);
|
|
15837
|
+
if (!matched) {
|
|
15838
|
+
const fallbackUrl = this.buildFallbackFilteredResponseSchemaUrl(raw);
|
|
15839
|
+
if (fallbackUrl && this.http) {
|
|
15840
|
+
return this.getSchemaFieldsByUrl(fallbackUrl, options).pipe(catchError$1(() => of([])));
|
|
15841
|
+
}
|
|
15842
|
+
return of([]);
|
|
15843
|
+
}
|
|
15844
|
+
const fallbackFields = this.projectCatalogFieldsToFieldDefinitions(matched.responseFields ?? []);
|
|
15845
|
+
const targetSchemaUrl = matched.responseSchemaUrl ||
|
|
15846
|
+
(fallbackFields.length === 0
|
|
15847
|
+
? this.buildFallbackFilteredResponseSchemaUrl(matched.value)
|
|
15848
|
+
: null);
|
|
15849
|
+
if (targetSchemaUrl && this.http) {
|
|
15850
|
+
return this.getSchemaFieldsByUrl(targetSchemaUrl, options).pipe(map$1((fields) => (fields.length > 0 ? fields : fallbackFields)), catchError$1(() => of(fallbackFields)));
|
|
15851
|
+
}
|
|
15852
|
+
return of(fallbackFields);
|
|
15853
|
+
}), catchError$1(() => of([])));
|
|
15854
|
+
}
|
|
15855
|
+
/**
|
|
15856
|
+
* Resolve os campos do schema de filtro (`request` de `POST {resourcePath}/filter`) de um
|
|
15857
|
+
* recurso de catálogo a partir do seu `resourcePath` ou `resourceKey`.
|
|
15858
|
+
*
|
|
15859
|
+
* Estratégia zero-friction:
|
|
15860
|
+
* 1. Se o endpoint de filtro no `/schemas/catalog` publicar `schemaLinks.request`, busca e normaliza
|
|
15861
|
+
* o schema completo via `getSchemaFieldsByUrl` (com fallback para `filterFields` do catálogo).
|
|
15862
|
+
* 2. Caso contrário, projeta `FieldDefinition[]` diretamente do resumo `requestSchema.fields`
|
|
15863
|
+
* já carregado em `/schemas/catalog` sem round-trip extra.
|
|
15864
|
+
* 3. Se o recurso não constar no grupo default de `/schemas/catalog` ou não trouxer links/campos
|
|
15865
|
+
* no catálogo (e não declarar explicitamente `capabilities.filter === false`), consulta diretamente
|
|
15866
|
+
* `/schemas/filtered` para `POST {resourcePath}/filter` (`schemaType=request`).
|
|
15867
|
+
*/
|
|
15868
|
+
getResourceFilterSchemaFields(resourcePath, options) {
|
|
15869
|
+
const raw = String(resourcePath ?? '').trim();
|
|
15870
|
+
if (!raw) {
|
|
15871
|
+
return of([]);
|
|
15872
|
+
}
|
|
15873
|
+
return this.getDiscoveredResources({
|
|
15874
|
+
endpointKey: options?.endpointKey,
|
|
15875
|
+
apiUrlEntry: options?.apiUrlEntry,
|
|
15876
|
+
intent: 'any',
|
|
15877
|
+
}).pipe(switchMap$1((resources) => {
|
|
15878
|
+
const matched = this.findCatalogResourceOption(raw, resources, options);
|
|
15879
|
+
if (!matched) {
|
|
15880
|
+
const fallbackUrl = this.buildFallbackFilteredRequestSchemaUrl(raw);
|
|
15881
|
+
if (fallbackUrl && this.http) {
|
|
15882
|
+
return this.getSchemaFieldsByUrl(fallbackUrl, options).pipe(catchError$1(() => of([])));
|
|
15883
|
+
}
|
|
15884
|
+
return of([]);
|
|
15885
|
+
}
|
|
15886
|
+
const fallbackFields = this.projectCatalogFieldsToFieldDefinitions(matched.filterFields ?? []);
|
|
15887
|
+
const supportsFilter = matched.capabilities?.filter !== false;
|
|
15888
|
+
const targetSchemaUrl = matched.filterSchemaUrl ||
|
|
15889
|
+
(fallbackFields.length === 0 && supportsFilter
|
|
15890
|
+
? this.buildFallbackFilteredRequestSchemaUrl(matched.value)
|
|
15891
|
+
: null);
|
|
15892
|
+
if (targetSchemaUrl && this.http) {
|
|
15893
|
+
return this.getSchemaFieldsByUrl(targetSchemaUrl, options).pipe(map$1((fields) => (fields.length > 0 ? fields : fallbackFields)), catchError$1(() => of(fallbackFields)));
|
|
15894
|
+
}
|
|
15895
|
+
return of(fallbackFields);
|
|
15896
|
+
}), catchError$1(() => of([])));
|
|
15897
|
+
}
|
|
15898
|
+
static REST_API_ENVELOPE_FIELDS = new Set([
|
|
15899
|
+
'status',
|
|
15900
|
+
'message',
|
|
15901
|
+
'data',
|
|
15902
|
+
'links',
|
|
15903
|
+
'_links',
|
|
15904
|
+
'timestamp',
|
|
15905
|
+
'errors',
|
|
15906
|
+
]);
|
|
15907
|
+
extractResourceResponseSchema(basePath, preferredEndpoint, operationalEndpoints) {
|
|
15908
|
+
const uniqueCandidates = [];
|
|
15909
|
+
const seen = new Set();
|
|
15910
|
+
for (const ep of [...operationalEndpoints, preferredEndpoint]) {
|
|
15911
|
+
if (ep && !seen.has(ep)) {
|
|
15912
|
+
seen.add(ep);
|
|
15913
|
+
uniqueCandidates.push(ep);
|
|
15914
|
+
}
|
|
15915
|
+
}
|
|
15916
|
+
const entityCandidates = uniqueCandidates
|
|
15917
|
+
.filter((ep) => !this.isAuxiliaryCatalogEndpoint(ep, basePath))
|
|
15918
|
+
.sort((left, right) => this.scoreEntityResponseEndpoint(left, basePath) -
|
|
15919
|
+
this.scoreEntityResponseEndpoint(right, basePath));
|
|
15920
|
+
let responseSchemaUrl = null;
|
|
15921
|
+
let responseFields = [];
|
|
15922
|
+
for (const candidate of entityCandidates) {
|
|
15923
|
+
if (!responseSchemaUrl) {
|
|
15924
|
+
const link = String(candidate.schemaLinks?.response ?? '').trim();
|
|
15925
|
+
if (link) {
|
|
15926
|
+
responseSchemaUrl = link;
|
|
15927
|
+
}
|
|
15928
|
+
}
|
|
15929
|
+
if (responseFields.length === 0) {
|
|
15930
|
+
const fields = candidate.responseSchema?.fields;
|
|
15931
|
+
if (Array.isArray(fields) && fields.length > 0) {
|
|
15932
|
+
const validFields = fields.filter((field) => !!field && typeof field.name === 'string' && field.name.trim().length > 0);
|
|
15933
|
+
if (validFields.length > 0 &&
|
|
15934
|
+
!this.isPureRestApiEnvelopeFields(validFields)) {
|
|
15935
|
+
responseFields = validFields;
|
|
15936
|
+
}
|
|
15937
|
+
}
|
|
15938
|
+
}
|
|
15939
|
+
if (responseSchemaUrl && responseFields.length > 0) {
|
|
15940
|
+
break;
|
|
15941
|
+
}
|
|
15942
|
+
}
|
|
15943
|
+
return { responseSchemaUrl, responseFields };
|
|
15944
|
+
}
|
|
15945
|
+
extractResourceFilterSchema(basePath, preferredEndpoint, operationalEndpoints) {
|
|
15946
|
+
const uniqueCandidates = [];
|
|
15947
|
+
const seen = new Set();
|
|
15948
|
+
for (const ep of [...operationalEndpoints, preferredEndpoint]) {
|
|
15949
|
+
if (ep && !seen.has(ep)) {
|
|
15950
|
+
seen.add(ep);
|
|
15951
|
+
uniqueCandidates.push(ep);
|
|
15952
|
+
}
|
|
15953
|
+
}
|
|
15954
|
+
const filterCandidates = uniqueCandidates
|
|
15955
|
+
.filter((ep) => {
|
|
15956
|
+
if (this.isAuxiliaryCatalogEndpoint(ep, basePath)) {
|
|
15957
|
+
return false;
|
|
15958
|
+
}
|
|
15959
|
+
const method = String(ep.method ?? '').trim().toUpperCase();
|
|
15960
|
+
const path = this.normalizeResourcePathValue(ep.path);
|
|
15961
|
+
return (method === 'POST' &&
|
|
15962
|
+
(path === `${basePath}/filter` ||
|
|
15963
|
+
path.endsWith('/filter') ||
|
|
15964
|
+
path === `${basePath}/filter/cursor` ||
|
|
15965
|
+
path.endsWith('/filter/cursor')));
|
|
15966
|
+
})
|
|
15967
|
+
.sort((left, right) => this.scoreEntityResponseEndpoint(left, basePath) -
|
|
15968
|
+
this.scoreEntityResponseEndpoint(right, basePath));
|
|
15969
|
+
let filterSchemaUrl = null;
|
|
15970
|
+
let filterFields = [];
|
|
15971
|
+
for (const candidate of filterCandidates) {
|
|
15972
|
+
if (!filterSchemaUrl) {
|
|
15973
|
+
const link = String(candidate.schemaLinks?.request ?? '').trim();
|
|
15974
|
+
if (link) {
|
|
15975
|
+
filterSchemaUrl = link;
|
|
15976
|
+
}
|
|
15977
|
+
}
|
|
15978
|
+
if (filterFields.length === 0) {
|
|
15979
|
+
const fields = candidate.requestSchema?.fields;
|
|
15980
|
+
if (Array.isArray(fields) && fields.length > 0) {
|
|
15981
|
+
const validFields = fields.filter((field) => !!field && typeof field.name === 'string' && field.name.trim().length > 0);
|
|
15982
|
+
if (validFields.length > 0) {
|
|
15983
|
+
filterFields = validFields;
|
|
15984
|
+
}
|
|
15985
|
+
}
|
|
15986
|
+
}
|
|
15987
|
+
if (filterSchemaUrl && filterFields.length > 0) {
|
|
15988
|
+
break;
|
|
15989
|
+
}
|
|
15990
|
+
}
|
|
15991
|
+
return { filterSchemaUrl, filterFields };
|
|
15992
|
+
}
|
|
15993
|
+
isAuxiliaryCatalogEndpoint(endpoint, basePath) {
|
|
15994
|
+
const method = String(endpoint.method ?? '').trim().toUpperCase();
|
|
15995
|
+
if (method === 'DELETE') {
|
|
15996
|
+
return true;
|
|
15997
|
+
}
|
|
15998
|
+
const path = this.normalizeResourcePathValue(endpoint.path);
|
|
15999
|
+
if (!path) {
|
|
16000
|
+
return true;
|
|
16001
|
+
}
|
|
16002
|
+
const relative = basePath && path.startsWith(`${basePath}/`)
|
|
16003
|
+
? path.slice(basePath.length)
|
|
16004
|
+
: path;
|
|
16005
|
+
return (/\/(?:capabilities|schemas(?:\/filtered)?|export|locate|batch|by-ids|options(?:\/filter|\/by-ids)?|option-sources(?:\/[^/]+)*|stats\/[^/]+|surfaces)(?:\/|$)/i.test(relative) || /\/actions\//i.test(relative));
|
|
16006
|
+
}
|
|
16007
|
+
scoreEntityResponseEndpoint(endpoint, basePath) {
|
|
16008
|
+
const method = String(endpoint.method ?? '').trim().toUpperCase();
|
|
16009
|
+
const path = this.normalizeResourcePathValue(endpoint.path);
|
|
16010
|
+
if (method === 'POST' && (path === `${basePath}/filter` || path.endsWith('/filter'))) {
|
|
16011
|
+
return 1;
|
|
16012
|
+
}
|
|
16013
|
+
if (method === 'POST' &&
|
|
16014
|
+
(path === `${basePath}/filter/cursor` || path.endsWith('/filter/cursor'))) {
|
|
16015
|
+
return 2;
|
|
16016
|
+
}
|
|
16017
|
+
if (method === 'GET' && (path === `${basePath}/all` || path.endsWith('/all'))) {
|
|
16018
|
+
return 3;
|
|
16019
|
+
}
|
|
16020
|
+
if (method === 'GET' && path === basePath) {
|
|
16021
|
+
return 4;
|
|
16022
|
+
}
|
|
16023
|
+
if (method === 'GET' && path.startsWith(`${basePath}/{`)) {
|
|
16024
|
+
return 5;
|
|
16025
|
+
}
|
|
16026
|
+
if (method === 'POST' && path === basePath) {
|
|
16027
|
+
return 6;
|
|
16028
|
+
}
|
|
16029
|
+
if ((method === 'PUT' || method === 'PATCH') && path.startsWith(`${basePath}/{`)) {
|
|
16030
|
+
return 7;
|
|
16031
|
+
}
|
|
16032
|
+
return 8;
|
|
16033
|
+
}
|
|
16034
|
+
isPureRestApiEnvelopeFields(fields) {
|
|
16035
|
+
if (!fields.length) {
|
|
16036
|
+
return false;
|
|
16037
|
+
}
|
|
16038
|
+
let hasDataOrStatus = false;
|
|
16039
|
+
for (const field of fields) {
|
|
16040
|
+
const name = String(field.name ?? '').trim();
|
|
16041
|
+
if (!ResourceDiscoveryService.REST_API_ENVELOPE_FIELDS.has(name)) {
|
|
16042
|
+
return false;
|
|
16043
|
+
}
|
|
16044
|
+
if (name === 'data' || name === 'status') {
|
|
16045
|
+
hasDataOrStatus = true;
|
|
16046
|
+
}
|
|
16047
|
+
}
|
|
16048
|
+
return hasDataOrStatus;
|
|
16049
|
+
}
|
|
16050
|
+
buildFallbackFilteredResponseSchemaUrl(rawResourcePath) {
|
|
16051
|
+
return this.buildFallbackFilteredSchemaUrl(rawResourcePath, 'response');
|
|
16052
|
+
}
|
|
16053
|
+
buildFallbackFilteredRequestSchemaUrl(rawResourcePath) {
|
|
16054
|
+
return this.buildFallbackFilteredSchemaUrl(rawResourcePath, 'request');
|
|
16055
|
+
}
|
|
16056
|
+
buildFallbackFilteredSchemaUrl(rawResourcePath, schemaType) {
|
|
16057
|
+
const trimmed = String(rawResourcePath ?? '').trim();
|
|
16058
|
+
if (!trimmed || (trimmed.includes('.') && !trimmed.includes('/'))) {
|
|
16059
|
+
return null;
|
|
16060
|
+
}
|
|
16061
|
+
const normalized = this.normalizeResourcePathValue(trimmed);
|
|
16062
|
+
if (!normalized) {
|
|
16063
|
+
return null;
|
|
16064
|
+
}
|
|
16065
|
+
const basePath = normalized.replace(/\/(?:filter\/cursor|filter|all|capabilities|options\/filter|options\/by-ids|options|stats\/[a-z0-9-]+)(?:\/?$)/i, '') || normalized;
|
|
16066
|
+
const filterPath = `${basePath}/filter`;
|
|
16067
|
+
return `/schemas/filtered?path=${encodeURIComponent(filterPath)}&operation=post&schemaType=${schemaType}`;
|
|
16068
|
+
}
|
|
16069
|
+
projectCatalogFieldsToFieldDefinitions(catalogFields) {
|
|
16070
|
+
if (this.isPureRestApiEnvelopeFields(catalogFields)) {
|
|
16071
|
+
return [];
|
|
16072
|
+
}
|
|
16073
|
+
return catalogFields
|
|
16074
|
+
.filter((field) => !!field && typeof field.name === 'string' && field.name.trim().length > 0)
|
|
16075
|
+
.map((field) => {
|
|
16076
|
+
const name = field.name.trim();
|
|
16077
|
+
const label = String(field.label ?? '').trim() || name;
|
|
16078
|
+
const type = String(field.type ?? field.controlType ?? 'string').trim() || 'string';
|
|
16079
|
+
const enumValues = Array.isArray(field.enumValues)
|
|
16080
|
+
? field.enumValues
|
|
16081
|
+
.map((val) => String(val ?? '').trim())
|
|
16082
|
+
.filter((val) => val.length > 0)
|
|
16083
|
+
: [];
|
|
16084
|
+
return {
|
|
16085
|
+
name,
|
|
16086
|
+
label,
|
|
16087
|
+
type,
|
|
16088
|
+
controlType: String(field.controlType ?? '').trim() || undefined,
|
|
16089
|
+
description: String(field.description ?? '').trim() || undefined,
|
|
16090
|
+
...(typeof field.required === 'boolean' ? { required: field.required } : {}),
|
|
16091
|
+
...(enumValues.length > 0
|
|
16092
|
+
? {
|
|
16093
|
+
options: enumValues.map((val) => ({ key: val, value: val })),
|
|
16094
|
+
}
|
|
16095
|
+
: {}),
|
|
16096
|
+
};
|
|
16097
|
+
});
|
|
15058
16098
|
}
|
|
15059
16099
|
resolveHref(href, options) {
|
|
15060
16100
|
const normalizedHref = String(href || '').trim();
|
|
@@ -15205,7 +16245,7 @@ class ResourceDiscoveryService {
|
|
|
15205
16245
|
}
|
|
15206
16246
|
resolveEndpointEntry(endpointKey) {
|
|
15207
16247
|
const key = endpointKey ?? ApiEndpoint.Default;
|
|
15208
|
-
return this.apiUrlConfig[key] || this.apiUrlConfig
|
|
16248
|
+
return this.apiUrlConfig?.[key] || this.apiUrlConfig?.default || {};
|
|
15209
16249
|
}
|
|
15210
16250
|
getRuntimeOrigin() {
|
|
15211
16251
|
try {
|
|
@@ -15222,12 +16262,287 @@ class ResourceDiscoveryService {
|
|
|
15222
16262
|
isRestApiResponse(source) {
|
|
15223
16263
|
return 'data' in source;
|
|
15224
16264
|
}
|
|
16265
|
+
extractCanonicalResourceCapabilities(primaryEndpoint, siblingEndpoints) {
|
|
16266
|
+
const candidates = [primaryEndpoint, ...siblingEndpoints];
|
|
16267
|
+
for (const candidate of candidates) {
|
|
16268
|
+
const raw = candidate?.resourceCapabilities;
|
|
16269
|
+
if (!raw || typeof raw !== 'object') {
|
|
16270
|
+
continue;
|
|
16271
|
+
}
|
|
16272
|
+
const normalized = {};
|
|
16273
|
+
let hasAny = false;
|
|
16274
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
16275
|
+
if (typeof value === 'boolean') {
|
|
16276
|
+
normalized[key] = value;
|
|
16277
|
+
hasAny = true;
|
|
16278
|
+
}
|
|
16279
|
+
}
|
|
16280
|
+
if (hasAny) {
|
|
16281
|
+
return normalized;
|
|
16282
|
+
}
|
|
16283
|
+
}
|
|
16284
|
+
return null;
|
|
16285
|
+
}
|
|
16286
|
+
extractCanonicalResourceReadOnly(primaryEndpoint, siblingEndpoints, canonicalOperations) {
|
|
16287
|
+
for (const candidate of [primaryEndpoint, ...siblingEndpoints]) {
|
|
16288
|
+
if (typeof candidate?.resourceReadOnly === 'boolean') {
|
|
16289
|
+
return candidate.resourceReadOnly;
|
|
16290
|
+
}
|
|
16291
|
+
}
|
|
16292
|
+
if (canonicalOperations &&
|
|
16293
|
+
('create' in canonicalOperations ||
|
|
16294
|
+
'update' in canonicalOperations ||
|
|
16295
|
+
'delete' in canonicalOperations)) {
|
|
16296
|
+
return !(canonicalOperations.create ||
|
|
16297
|
+
canonicalOperations.update ||
|
|
16298
|
+
canonicalOperations.delete);
|
|
16299
|
+
}
|
|
16300
|
+
return null;
|
|
16301
|
+
}
|
|
16302
|
+
resolveResourceCapabilities(basePath, operationalEndpoints, catalogHasExplicitOptionsEndpoints, catalogHasExplicitItemOrMutationEndpoints, canonicalOperations = null) {
|
|
16303
|
+
const hasCanonicalFilter = !!canonicalOperations &&
|
|
16304
|
+
('filter' in canonicalOperations || 'cursor' in canonicalOperations);
|
|
16305
|
+
const hasCanonicalCollection = !!canonicalOperations &&
|
|
16306
|
+
('all' in canonicalOperations || hasCanonicalFilter);
|
|
16307
|
+
const hasCanonicalStats = !!canonicalOperations &&
|
|
16308
|
+
('statsGroupBy' in canonicalOperations ||
|
|
16309
|
+
'statsTimeSeries' in canonicalOperations ||
|
|
16310
|
+
'statsDistribution' in canonicalOperations ||
|
|
16311
|
+
'statsComparison' in canonicalOperations);
|
|
16312
|
+
const hasCanonicalOptions = !!canonicalOperations &&
|
|
16313
|
+
('options' in canonicalOperations || 'optionSources' in canonicalOperations);
|
|
16314
|
+
const hasCanonicalCrud = !!canonicalOperations &&
|
|
16315
|
+
('byId' in canonicalOperations ||
|
|
16316
|
+
'create' in canonicalOperations ||
|
|
16317
|
+
'update' in canonicalOperations ||
|
|
16318
|
+
'delete' in canonicalOperations);
|
|
16319
|
+
const canonicalFilter = hasCanonicalFilter
|
|
16320
|
+
? Boolean(canonicalOperations.filter || canonicalOperations.cursor)
|
|
16321
|
+
: null;
|
|
16322
|
+
const canonicalCollection = hasCanonicalCollection
|
|
16323
|
+
? Boolean(canonicalOperations.all ||
|
|
16324
|
+
canonicalOperations.filter ||
|
|
16325
|
+
canonicalOperations.cursor)
|
|
16326
|
+
: null;
|
|
16327
|
+
const canonicalStats = hasCanonicalStats
|
|
16328
|
+
? Boolean(canonicalOperations.statsGroupBy ||
|
|
16329
|
+
canonicalOperations.statsTimeSeries ||
|
|
16330
|
+
canonicalOperations.statsDistribution ||
|
|
16331
|
+
canonicalOperations.statsComparison)
|
|
16332
|
+
: null;
|
|
16333
|
+
const canonicalOptions = hasCanonicalOptions
|
|
16334
|
+
? Boolean(canonicalOperations.options || canonicalOperations.optionSources)
|
|
16335
|
+
: null;
|
|
16336
|
+
const canonicalCrud = hasCanonicalCrud
|
|
16337
|
+
? Boolean(canonicalOperations.byId ||
|
|
16338
|
+
canonicalOperations.create ||
|
|
16339
|
+
canonicalOperations.update ||
|
|
16340
|
+
canonicalOperations.delete)
|
|
16341
|
+
: null;
|
|
16342
|
+
if (!operationalEndpoints.length) {
|
|
16343
|
+
return {
|
|
16344
|
+
collection: canonicalCollection ?? true,
|
|
16345
|
+
filter: canonicalFilter ?? true,
|
|
16346
|
+
stats: canonicalStats ?? false,
|
|
16347
|
+
options: canonicalOptions ?? true,
|
|
16348
|
+
crud: canonicalCrud ?? true,
|
|
16349
|
+
};
|
|
16350
|
+
}
|
|
16351
|
+
const filter = canonicalFilter ??
|
|
16352
|
+
operationalEndpoints.some((endpoint) => {
|
|
16353
|
+
const method = String(endpoint.method ?? '').toUpperCase();
|
|
16354
|
+
const path = String(endpoint.path ?? '').trim();
|
|
16355
|
+
return (method === 'POST' &&
|
|
16356
|
+
(path === `${basePath}/filter` ||
|
|
16357
|
+
path === `${basePath}/filter/cursor` ||
|
|
16358
|
+
path.endsWith('/filter') ||
|
|
16359
|
+
path.endsWith('/filter/cursor')));
|
|
16360
|
+
});
|
|
16361
|
+
const collection = canonicalCollection ??
|
|
16362
|
+
(filter ||
|
|
16363
|
+
operationalEndpoints.some((endpoint) => {
|
|
16364
|
+
const method = String(endpoint.method ?? '').toUpperCase();
|
|
16365
|
+
const path = String(endpoint.path ?? '').trim();
|
|
16366
|
+
return (method === 'GET' &&
|
|
16367
|
+
!path.includes('{') &&
|
|
16368
|
+
(path === basePath || path === `${basePath}/all` || path.endsWith('/all')));
|
|
16369
|
+
}));
|
|
16370
|
+
const stats = canonicalStats ??
|
|
16371
|
+
operationalEndpoints.some((endpoint) => {
|
|
16372
|
+
const method = String(endpoint.method ?? '').toUpperCase();
|
|
16373
|
+
const path = String(endpoint.path ?? '').trim();
|
|
16374
|
+
return (method === 'POST' &&
|
|
16375
|
+
(path === `${basePath}/stats/group-by` ||
|
|
16376
|
+
path === `${basePath}/stats/timeseries` ||
|
|
16377
|
+
path === `${basePath}/stats/distribution` ||
|
|
16378
|
+
path === `${basePath}/stats/comparison` ||
|
|
16379
|
+
path.includes('/stats/')));
|
|
16380
|
+
});
|
|
16381
|
+
const explicitOptions = operationalEndpoints.some((endpoint) => {
|
|
16382
|
+
const method = String(endpoint.method ?? '').toUpperCase();
|
|
16383
|
+
const path = String(endpoint.path ?? '').trim();
|
|
16384
|
+
return (((method === 'POST' || method === 'GET') &&
|
|
16385
|
+
(path === `${basePath}/options/filter` ||
|
|
16386
|
+
path === `${basePath}/options/by-ids` ||
|
|
16387
|
+
path === `${basePath}/options` ||
|
|
16388
|
+
path.endsWith('/options/filter') ||
|
|
16389
|
+
path.endsWith('/options/by-ids') ||
|
|
16390
|
+
path.endsWith('/options'))) ||
|
|
16391
|
+
(method === 'GET' && path.includes('/option-sources')));
|
|
16392
|
+
});
|
|
16393
|
+
const explicitCrud = operationalEndpoints.some((endpoint) => {
|
|
16394
|
+
const method = String(endpoint.method ?? '').toUpperCase();
|
|
16395
|
+
const path = String(endpoint.path ?? '').trim();
|
|
16396
|
+
if (path === basePath && method === 'POST') {
|
|
16397
|
+
return true;
|
|
16398
|
+
}
|
|
16399
|
+
return (path.startsWith(`${basePath}/{`) &&
|
|
16400
|
+
(method === 'GET' ||
|
|
16401
|
+
method === 'PUT' ||
|
|
16402
|
+
method === 'PATCH' ||
|
|
16403
|
+
method === 'DELETE'));
|
|
16404
|
+
});
|
|
16405
|
+
return {
|
|
16406
|
+
collection,
|
|
16407
|
+
filter,
|
|
16408
|
+
stats,
|
|
16409
|
+
options: canonicalOptions ??
|
|
16410
|
+
(catalogHasExplicitOptionsEndpoints
|
|
16411
|
+
? explicitOptions
|
|
16412
|
+
: explicitOptions || collection),
|
|
16413
|
+
crud: canonicalCrud ??
|
|
16414
|
+
(catalogHasExplicitItemOrMutationEndpoints
|
|
16415
|
+
? explicitCrud
|
|
16416
|
+
: explicitCrud || collection),
|
|
16417
|
+
};
|
|
16418
|
+
}
|
|
16419
|
+
matchesResourceIntent(capabilities, intent) {
|
|
16420
|
+
switch (intent) {
|
|
16421
|
+
case 'collection':
|
|
16422
|
+
return capabilities.collection;
|
|
16423
|
+
case 'filter':
|
|
16424
|
+
return capabilities.filter;
|
|
16425
|
+
case 'stats':
|
|
16426
|
+
return capabilities.stats;
|
|
16427
|
+
case 'options':
|
|
16428
|
+
return capabilities.options;
|
|
16429
|
+
case 'crud':
|
|
16430
|
+
return capabilities.crud;
|
|
16431
|
+
case 'any':
|
|
16432
|
+
default:
|
|
16433
|
+
return true;
|
|
16434
|
+
}
|
|
16435
|
+
}
|
|
16436
|
+
resolveConfiguredApiPathPrefix(options) {
|
|
16437
|
+
const baseUrl = this.resolveApiBaseUrl(options);
|
|
16438
|
+
if (!baseUrl) {
|
|
16439
|
+
return '';
|
|
16440
|
+
}
|
|
16441
|
+
if (this.isAbsoluteHttpUrl(baseUrl)) {
|
|
16442
|
+
try {
|
|
16443
|
+
return this.normalizePathPrefix(new URL(baseUrl).pathname);
|
|
16444
|
+
}
|
|
16445
|
+
catch {
|
|
16446
|
+
return '';
|
|
16447
|
+
}
|
|
16448
|
+
}
|
|
16449
|
+
return this.normalizePathPrefix(baseUrl);
|
|
16450
|
+
}
|
|
16451
|
+
stripConfiguredApiPrefix(path, configuredApiPrefix) {
|
|
16452
|
+
const normalized = this.normalizeResourcePathValue(path);
|
|
16453
|
+
if (!normalized) {
|
|
16454
|
+
return '';
|
|
16455
|
+
}
|
|
16456
|
+
const prefixes = [configuredApiPrefix, '/api'].filter(Boolean);
|
|
16457
|
+
for (const prefix of prefixes) {
|
|
16458
|
+
if (normalized.startsWith(`${prefix}/`)) {
|
|
16459
|
+
return normalized.slice(prefix.length);
|
|
16460
|
+
}
|
|
16461
|
+
}
|
|
16462
|
+
return normalized;
|
|
16463
|
+
}
|
|
16464
|
+
buildPathReconciliationCandidates(rawPath, options) {
|
|
16465
|
+
const trimmed = String(rawPath ?? '').trim();
|
|
16466
|
+
if (!trimmed) {
|
|
16467
|
+
return [];
|
|
16468
|
+
}
|
|
16469
|
+
const candidates = new Set([trimmed]);
|
|
16470
|
+
const normalized = this.normalizeResourcePathValue(trimmed);
|
|
16471
|
+
if (!normalized) {
|
|
16472
|
+
return [...candidates];
|
|
16473
|
+
}
|
|
16474
|
+
const withoutActionSuffix = normalized.replace(/\/(?:filter\/cursor|filter|all|options\/filter|options\/by-ids|options|stats\/[a-z0-9-]+)(?:\/?$)/i, '') || normalized;
|
|
16475
|
+
const apiPrefix = this.resolveConfiguredApiPathPrefix(options);
|
|
16476
|
+
const prefixes = [...new Set([apiPrefix, '/api'].filter(Boolean))];
|
|
16477
|
+
for (const base of [normalized, withoutActionSuffix]) {
|
|
16478
|
+
if (!base) {
|
|
16479
|
+
continue;
|
|
16480
|
+
}
|
|
16481
|
+
candidates.add(base);
|
|
16482
|
+
candidates.add(base.replace(/^\/+/, ''));
|
|
16483
|
+
for (const prefix of prefixes) {
|
|
16484
|
+
if (base.startsWith(`${prefix}/`)) {
|
|
16485
|
+
const stripped = base.slice(prefix.length);
|
|
16486
|
+
if (stripped) {
|
|
16487
|
+
candidates.add(stripped);
|
|
16488
|
+
candidates.add(stripped.replace(/^\/+/, ''));
|
|
16489
|
+
}
|
|
16490
|
+
}
|
|
16491
|
+
else if (base.startsWith('/')) {
|
|
16492
|
+
const prefixed = `${prefix}${base}`;
|
|
16493
|
+
candidates.add(prefixed);
|
|
16494
|
+
candidates.add(prefixed.replace(/^\/+/, ''));
|
|
16495
|
+
}
|
|
16496
|
+
}
|
|
16497
|
+
}
|
|
16498
|
+
return [...candidates];
|
|
16499
|
+
}
|
|
16500
|
+
normalizeResourcePathValue(value) {
|
|
16501
|
+
const trimmed = String(value ?? '').trim();
|
|
16502
|
+
if (!trimmed) {
|
|
16503
|
+
return '';
|
|
16504
|
+
}
|
|
16505
|
+
if (/^https?:\/\//i.test(trimmed)) {
|
|
16506
|
+
return trimmed.replace(/\/+$/, '');
|
|
16507
|
+
}
|
|
16508
|
+
const stripped = trimmed.replace(/^\/+|\/+$/g, '');
|
|
16509
|
+
return stripped ? `/${stripped}` : '';
|
|
16510
|
+
}
|
|
15225
16511
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ResourceDiscoveryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
15226
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ResourceDiscoveryService, providedIn: 'any'
|
|
16512
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ResourceDiscoveryService, providedIn: 'any', useFactory: () => {
|
|
16513
|
+
const localApiUrl = inject(API_URL, { self: true, optional: true });
|
|
16514
|
+
if (localApiUrl) {
|
|
16515
|
+
return new ResourceDiscoveryService();
|
|
16516
|
+
}
|
|
16517
|
+
const inheritedApiUrl = inject(API_URL, { skipSelf: true, optional: true });
|
|
16518
|
+
if (!inheritedApiUrl) {
|
|
16519
|
+
return new ResourceDiscoveryService();
|
|
16520
|
+
}
|
|
16521
|
+
return (inject(ResourceDiscoveryService, {
|
|
16522
|
+
skipSelf: true,
|
|
16523
|
+
optional: true,
|
|
16524
|
+
}) ?? new ResourceDiscoveryService());
|
|
16525
|
+
} });
|
|
15227
16526
|
}
|
|
15228
16527
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ResourceDiscoveryService, decorators: [{
|
|
15229
16528
|
type: Injectable,
|
|
15230
|
-
args: [{
|
|
16529
|
+
args: [{
|
|
16530
|
+
providedIn: 'any',
|
|
16531
|
+
useFactory: () => {
|
|
16532
|
+
const localApiUrl = inject(API_URL, { self: true, optional: true });
|
|
16533
|
+
if (localApiUrl) {
|
|
16534
|
+
return new ResourceDiscoveryService();
|
|
16535
|
+
}
|
|
16536
|
+
const inheritedApiUrl = inject(API_URL, { skipSelf: true, optional: true });
|
|
16537
|
+
if (!inheritedApiUrl) {
|
|
16538
|
+
return new ResourceDiscoveryService();
|
|
16539
|
+
}
|
|
16540
|
+
return (inject(ResourceDiscoveryService, {
|
|
16541
|
+
skipSelf: true,
|
|
16542
|
+
optional: true,
|
|
16543
|
+
}) ?? new ResourceDiscoveryService());
|
|
16544
|
+
},
|
|
16545
|
+
}]
|
|
15231
16546
|
}] });
|
|
15232
16547
|
|
|
15233
16548
|
/** Consumes only backend-published operation references; it never constructs resource routes. */
|
|
@@ -23232,6 +24547,13 @@ const RESOURCE_DISCOVERY_I18N_CONFIG = {
|
|
|
23232
24547
|
'quickConnect.invalid': 'Informe uma rota válida da API.',
|
|
23233
24548
|
'quickConnect.retry': 'Tentar novamente',
|
|
23234
24549
|
'quickConnect.hint': 'Escolha um recurso publicado pela API.',
|
|
24550
|
+
'quickConnect.hint.collection': 'Escolha um recurso de coleção/listagem publicado pela API.',
|
|
24551
|
+
'quickConnect.hint.filter': 'Escolha um recurso filtrável publicado pela API.',
|
|
24552
|
+
'quickConnect.hint.stats': 'Escolha um recurso analítico de estatísticas publicado pela API.',
|
|
24553
|
+
'quickConnect.hint.options': 'Escolha um recurso de opções/lookup publicado pela API.',
|
|
24554
|
+
'quickConnect.hint.crud': 'Escolha um recurso de cadastro/operação publicado pela API.',
|
|
24555
|
+
'quickConnect.readOnly': 'Somente leitura',
|
|
24556
|
+
'quickConnect.searchPlaceholder': 'Buscar por nome, chave ou rota…',
|
|
23235
24557
|
'quickConnect.fields': 'Carregar campos do filtro',
|
|
23236
24558
|
'quickConnect.fieldsError': 'Não foi possível carregar os campos. Verifique o recurso e tente novamente.',
|
|
23237
24559
|
'workflow.unavailable.default': 'A\u00e7\u00e3o indispon\u00edvel no contexto atual.',
|
|
@@ -23255,6 +24577,13 @@ const RESOURCE_DISCOVERY_I18N_CONFIG = {
|
|
|
23255
24577
|
'quickConnect.invalid': 'Enter a valid API resource path.',
|
|
23256
24578
|
'quickConnect.retry': 'Retry',
|
|
23257
24579
|
'quickConnect.hint': 'Choose a resource published by the API.',
|
|
24580
|
+
'quickConnect.hint.collection': 'Choose a collection resource published by the API.',
|
|
24581
|
+
'quickConnect.hint.filter': 'Choose a filterable resource published by the API.',
|
|
24582
|
+
'quickConnect.hint.stats': 'Choose an analytics/statistics resource published by the API.',
|
|
24583
|
+
'quickConnect.hint.options': 'Choose an options/lookup resource published by the API.',
|
|
24584
|
+
'quickConnect.hint.crud': 'Choose a CRUD/record resource published by the API.',
|
|
24585
|
+
'quickConnect.readOnly': 'Read-only',
|
|
24586
|
+
'quickConnect.searchPlaceholder': 'Search by name, key, or path…',
|
|
23258
24587
|
'quickConnect.fields': 'Load filter fields',
|
|
23259
24588
|
'quickConnect.fieldsError': 'Fields could not be loaded. Check the resource and retry.',
|
|
23260
24589
|
'workflow.unavailable.default': 'Action is unavailable in the current context.',
|
|
@@ -29372,7 +30701,7 @@ class Tokenizer {
|
|
|
29372
30701
|
readOperator() {
|
|
29373
30702
|
const two = this.input.slice(this.i, this.i + 2);
|
|
29374
30703
|
const three = this.input.slice(this.i, this.i + 3);
|
|
29375
|
-
const ops = ['===', '!==', '==', '!=', '>=', '<='];
|
|
30704
|
+
const ops = ['===', '!==', '==', '!=', '>=', '<=', '&&', '||'];
|
|
29376
30705
|
if (ops.includes(three)) {
|
|
29377
30706
|
this.i += 3;
|
|
29378
30707
|
return three;
|
|
@@ -29423,7 +30752,7 @@ class Parser {
|
|
|
29423
30752
|
return expr;
|
|
29424
30753
|
}
|
|
29425
30754
|
parseTernary() {
|
|
29426
|
-
let expr = this.
|
|
30755
|
+
let expr = this.parseLogicalOr();
|
|
29427
30756
|
if (this.matchOperator('?')) {
|
|
29428
30757
|
this.enterDepth();
|
|
29429
30758
|
const whenTrue = this.parseTernary();
|
|
@@ -29435,6 +30764,24 @@ class Parser {
|
|
|
29435
30764
|
}
|
|
29436
30765
|
return expr;
|
|
29437
30766
|
}
|
|
30767
|
+
parseLogicalOr() {
|
|
30768
|
+
let expr = this.parseLogicalAnd();
|
|
30769
|
+
while (this.matchOperator('||')) {
|
|
30770
|
+
const op = this.previous().value;
|
|
30771
|
+
const right = this.parseLogicalAnd();
|
|
30772
|
+
expr = this.makeBinary(op, expr, right);
|
|
30773
|
+
}
|
|
30774
|
+
return expr;
|
|
30775
|
+
}
|
|
30776
|
+
parseLogicalAnd() {
|
|
30777
|
+
let expr = this.parseComparison();
|
|
30778
|
+
while (this.matchOperator('&&')) {
|
|
30779
|
+
const op = this.previous().value;
|
|
30780
|
+
const right = this.parseComparison();
|
|
30781
|
+
expr = this.makeBinary(op, expr, right);
|
|
30782
|
+
}
|
|
30783
|
+
return expr;
|
|
30784
|
+
}
|
|
29438
30785
|
parseComparison() {
|
|
29439
30786
|
let expr = this.parseAdditive();
|
|
29440
30787
|
while (this.matchOperator('==', '!=', '===', '!==', '>=', '<=', '>', '<')) {
|
|
@@ -29680,6 +31027,12 @@ class SafeExpressionEvaluator {
|
|
|
29680
31027
|
}
|
|
29681
31028
|
evalBinary(node, row) {
|
|
29682
31029
|
const left = this.evalNode(node.left, row);
|
|
31030
|
+
if (node.op === '||') {
|
|
31031
|
+
return Boolean(left) ? true : Boolean(this.evalNode(node.right, row));
|
|
31032
|
+
}
|
|
31033
|
+
if (node.op === '&&') {
|
|
31034
|
+
return Boolean(left) ? Boolean(this.evalNode(node.right, row)) : false;
|
|
31035
|
+
}
|
|
29683
31036
|
const right = this.evalNode(node.right, row);
|
|
29684
31037
|
switch (node.op) {
|
|
29685
31038
|
case '+':
|
|
@@ -31469,6 +32822,8 @@ const ENUMS$1 = {
|
|
|
31469
32822
|
presentationVisualizationKind: ['line', 'area', 'column', 'comparison', 'stackedBar', 'radial', 'harveyBall', 'bullet', 'delta', 'processFlow'],
|
|
31470
32823
|
presentationVisualizationSurface: ['table-cell', 'list-item', 'object-header', 'card-summary', 'form-presentation'],
|
|
31471
32824
|
presentationVisualizationSize: ['xs', 'sm', 'md', 'lg', 'responsive'],
|
|
32825
|
+
presentationVisualizationScaleScope: ['row', 'page'],
|
|
32826
|
+
presentationVisualizationTone: ['neutral', 'info', 'success', 'warning', 'danger', 'critical'],
|
|
31472
32827
|
visibleIn: ['form', 'filter', 'table', 'dialog'],
|
|
31473
32828
|
appearance: ['fill', 'outline'],
|
|
31474
32829
|
color: ['primary', 'accent', 'warn'],
|
|
@@ -31973,6 +33328,140 @@ const FIELD_METADATA_CAPABILITIES = {
|
|
|
31973
33328
|
description: 'Tamanho semantico da micro visualizacao.',
|
|
31974
33329
|
intentExamples: ['xs em tabela', 'md em header', 'responsive em card'],
|
|
31975
33330
|
},
|
|
33331
|
+
{
|
|
33332
|
+
path: 'presentation.visualization.scaleScope',
|
|
33333
|
+
category: 'layout',
|
|
33334
|
+
valueKind: 'enum',
|
|
33335
|
+
allowedValues: ENUMS$1.presentationVisualizationScaleScope,
|
|
33336
|
+
description: 'Escopo de normalizacao de escala para series e valores em colecoes: row (local por linha) ou page (sincronizado na pagina visivel).',
|
|
33337
|
+
intentExamples: ['sincronizar escala de sparklines na pagina', 'comparar amplitude entre linhas'],
|
|
33338
|
+
},
|
|
33339
|
+
{
|
|
33340
|
+
path: 'presentation.visualization.tone',
|
|
33341
|
+
category: 'appearance',
|
|
33342
|
+
valueKind: 'enum',
|
|
33343
|
+
allowedValues: ENUMS$1.presentationVisualizationTone,
|
|
33344
|
+
description: 'Tom semantico estatico da micro visualizacao.',
|
|
33345
|
+
intentExamples: ['neutral', 'success', 'warning', 'danger', 'critical'],
|
|
33346
|
+
},
|
|
33347
|
+
{
|
|
33348
|
+
path: 'presentation.visualization.toneExpr',
|
|
33349
|
+
category: 'appearance',
|
|
33350
|
+
valueKind: 'object',
|
|
33351
|
+
description: 'Expressao Json Logic ou caminho row.<campo> para resolver dinamicamente o tom semantico da micro visualizacao.',
|
|
33352
|
+
safetyNotes: 'Deve retornar apenas um dos tons permitidos em presentationVisualizationTone.',
|
|
33353
|
+
},
|
|
33354
|
+
{
|
|
33355
|
+
path: 'presentation.visualization.valueExpr',
|
|
33356
|
+
category: 'behavior',
|
|
33357
|
+
valueKind: 'object',
|
|
33358
|
+
description: 'Caminho row.<campo> ou expressao Json Logic para obter o valor principal da micro visualizacao.',
|
|
33359
|
+
intentExamples: ['row.slaValue', 'row.progresso'],
|
|
33360
|
+
},
|
|
33361
|
+
{
|
|
33362
|
+
path: 'presentation.visualization.valueSuffix',
|
|
33363
|
+
category: 'appearance',
|
|
33364
|
+
valueKind: 'string',
|
|
33365
|
+
description: 'Sufixo de unidade anexado ao valor numerico formatado (ex: "%", " pts", " ms", " d").',
|
|
33366
|
+
intentExamples: ['mostrar % no bullet', 'adicionar sufixo pts no radial'],
|
|
33367
|
+
},
|
|
33368
|
+
{
|
|
33369
|
+
path: 'presentation.visualization.compactValue',
|
|
33370
|
+
category: 'appearance',
|
|
33371
|
+
valueKind: 'boolean',
|
|
33372
|
+
description: 'Formata valores numericos em notacao compacta (ex: 1.2M, 45.3K) para celulas densas.',
|
|
33373
|
+
intentExamples: ['compactar valores financeiros grandes', 'mostrar 1.2M em comparison'],
|
|
33374
|
+
},
|
|
33375
|
+
{
|
|
33376
|
+
path: 'presentation.visualization.min',
|
|
33377
|
+
category: 'behavior',
|
|
33378
|
+
valueKind: 'number',
|
|
33379
|
+
description: 'Limite minimo explicito da escala numerica.',
|
|
33380
|
+
},
|
|
33381
|
+
{
|
|
33382
|
+
path: 'presentation.visualization.max',
|
|
33383
|
+
category: 'behavior',
|
|
33384
|
+
valueKind: 'number',
|
|
33385
|
+
description: 'Limite maximo explicito da escala numerica.',
|
|
33386
|
+
},
|
|
33387
|
+
{
|
|
33388
|
+
path: 'presentation.visualization.total',
|
|
33389
|
+
category: 'behavior',
|
|
33390
|
+
valueKind: 'number',
|
|
33391
|
+
description: 'Total explicito para proporcionalidade em stackedBar ou radial.',
|
|
33392
|
+
},
|
|
33393
|
+
{
|
|
33394
|
+
path: 'presentation.visualization.target',
|
|
33395
|
+
category: 'behavior',
|
|
33396
|
+
valueKind: 'number',
|
|
33397
|
+
description: 'Meta fixa para comparacao em bullet.',
|
|
33398
|
+
},
|
|
33399
|
+
{
|
|
33400
|
+
path: 'presentation.visualization.targetExpr',
|
|
33401
|
+
category: 'behavior',
|
|
33402
|
+
valueKind: 'object',
|
|
33403
|
+
description: 'Caminho row.<campo> ou expressao Json Logic para obter a meta por linha em bullet.',
|
|
33404
|
+
intentExamples: ['row.metaSla', 'row.target'],
|
|
33405
|
+
},
|
|
33406
|
+
{
|
|
33407
|
+
path: 'presentation.visualization.baseline',
|
|
33408
|
+
category: 'behavior',
|
|
33409
|
+
valueKind: 'number',
|
|
33410
|
+
description: 'Valor de referencia fixo para comparison ou delta.',
|
|
33411
|
+
},
|
|
33412
|
+
{
|
|
33413
|
+
path: 'presentation.visualization.baselineExpr',
|
|
33414
|
+
category: 'behavior',
|
|
33415
|
+
valueKind: 'object',
|
|
33416
|
+
description: 'Caminho row.<campo> ou expressao Json Logic para obter o valor de referencia (baseline) por linha em comparison ou delta.',
|
|
33417
|
+
intentExamples: ['row.orcamentoPrevisto', 'row.indenizacoesTotal'],
|
|
33418
|
+
},
|
|
33419
|
+
{
|
|
33420
|
+
path: 'presentation.visualization.pointsExpr',
|
|
33421
|
+
category: 'behavior',
|
|
33422
|
+
valueKind: 'object',
|
|
33423
|
+
description: 'Caminho row.<campo> ou expressao Json Logic para serie de pontos em line, area ou column.',
|
|
33424
|
+
intentExamples: ['row.trend', 'row.historicoMensal'],
|
|
33425
|
+
},
|
|
33426
|
+
{
|
|
33427
|
+
path: 'presentation.visualization.segmentsExpr',
|
|
33428
|
+
category: 'behavior',
|
|
33429
|
+
valueKind: 'object',
|
|
33430
|
+
description: 'Caminho row.<campo> ou expressao Json Logic para lista de segmentos em stackedBar.',
|
|
33431
|
+
intentExamples: ['row.capacitySegments', 'row.distribuicao'],
|
|
33432
|
+
},
|
|
33433
|
+
{
|
|
33434
|
+
path: 'presentation.visualization.itemsExpr',
|
|
33435
|
+
category: 'behavior',
|
|
33436
|
+
valueKind: 'object',
|
|
33437
|
+
description: 'Caminho row.<campo> ou expressao Json Logic para lista de etapas em processFlow.',
|
|
33438
|
+
intentExamples: ['row.flowSteps', 'row.etapasAprovacao'],
|
|
33439
|
+
},
|
|
33440
|
+
{
|
|
33441
|
+
path: 'presentation.visualization.thresholds',
|
|
33442
|
+
category: 'appearance',
|
|
33443
|
+
valueKind: 'array',
|
|
33444
|
+
description: 'Faixas e limiares semanticos declarativos ({ value, min, max, tone, label }) para coloracao automatica e faixas qualitativas de bullet.',
|
|
33445
|
+
intentExamples: ['[{ "value": 0, "tone": "danger" }, { "value": 60, "tone": "warning" }, { "value": 85, "tone": "success" }]'],
|
|
33446
|
+
},
|
|
33447
|
+
{
|
|
33448
|
+
path: 'presentation.visualization.stepLabelLineClamp',
|
|
33449
|
+
category: 'layout',
|
|
33450
|
+
valueKind: 'number',
|
|
33451
|
+
description: 'Numero maximo de linhas (1 ou 2) para rotulos de etapas em processFlow.',
|
|
33452
|
+
},
|
|
33453
|
+
{
|
|
33454
|
+
path: 'presentation.visualization.ariaLabel',
|
|
33455
|
+
category: 'accessibility',
|
|
33456
|
+
valueKind: 'string',
|
|
33457
|
+
description: 'Rotulo acessivel explicito da micro visualizacao.',
|
|
33458
|
+
},
|
|
33459
|
+
{
|
|
33460
|
+
path: 'presentation.visualization.ariaLabelExpr',
|
|
33461
|
+
category: 'accessibility',
|
|
33462
|
+
valueKind: 'object',
|
|
33463
|
+
description: 'Caminho row.<campo> ou expressao Json Logic para compor o rotulo acessivel por linha.',
|
|
33464
|
+
},
|
|
31976
33465
|
{
|
|
31977
33466
|
path: 'presentation.visualization.fallbackText',
|
|
31978
33467
|
category: 'accessibility',
|
|
@@ -31980,6 +33469,12 @@ const FIELD_METADATA_CAPABILITIES = {
|
|
|
31980
33469
|
description: 'Texto equivalente obrigatorio para fallback, exportacao e leitores de tela.',
|
|
31981
33470
|
safetyNotes: 'Deve explicar valor, unidade, meta, tendencia ou estado quando aplicavel.',
|
|
31982
33471
|
},
|
|
33472
|
+
{
|
|
33473
|
+
path: 'presentation.visualization.fallbackTextExpr',
|
|
33474
|
+
category: 'accessibility',
|
|
33475
|
+
valueKind: 'object',
|
|
33476
|
+
description: 'Caminho row.<campo> ou expressao Json Logic para gerar o fallback textual dinamico por linha.',
|
|
33477
|
+
},
|
|
31983
33478
|
{
|
|
31984
33479
|
path: 'presentationRules',
|
|
31985
33480
|
category: 'appearance',
|
|
@@ -32019,6 +33514,21 @@ const FIELD_METADATA_CAPABILITIES = {
|
|
|
32019
33514
|
description: 'Formato de exibição (ex: pipes).',
|
|
32020
33515
|
intentExamples: ['formato de data dd/mm/yyyy', 'formato de moeda', 'exibir como porcentagem'],
|
|
32021
33516
|
},
|
|
33517
|
+
{
|
|
33518
|
+
path: 'inlineVisualStyle',
|
|
33519
|
+
category: 'appearance',
|
|
33520
|
+
valueKind: 'enum',
|
|
33521
|
+
allowedValues: ['compact', 'graphic'],
|
|
33522
|
+
description: 'Estilo visual para controles numericos percentuais inline (compact: pilula liquida com micro-anel e popover; graphic: card expandido com donut, trilho graduado e presets).',
|
|
33523
|
+
intentExamples: ['usar percentual compacto na barra', 'exibir card grafico de percentual'],
|
|
33524
|
+
},
|
|
33525
|
+
{
|
|
33526
|
+
path: 'percentPresets',
|
|
33527
|
+
category: 'data',
|
|
33528
|
+
valueKind: 'array',
|
|
33529
|
+
description: 'Lista de percentuais rapidos exibidos nos botoes de preset do Percent Studio (ex.: [0, 25, 50, 75, 100]).',
|
|
33530
|
+
intentExamples: ['atalhos de percentual 10, 25, 50 e 100%', 'definir presets de porcentagem'],
|
|
33531
|
+
},
|
|
32022
33532
|
// =============================================================================
|
|
32023
33533
|
// VALIDATORS (Generic)
|
|
32024
33534
|
// =============================================================================
|
|
@@ -32888,7 +34398,7 @@ const CAPS = [
|
|
|
32888
34398
|
path: 'page.widgets[].definition.inputs',
|
|
32889
34399
|
category: 'widgets',
|
|
32890
34400
|
valueKind: 'object',
|
|
32891
|
-
description: 'Inputs iniciais do widget.',
|
|
34401
|
+
description: 'Inputs iniciais do widget. Suporta interpolação {{state.<path> | pipe}} e ${state.<path> | pipe} com pipes declarativos CSP-safe (default/coalesce, round[:N], number[:N], percent[:N], currency[:code], uppercase, lowercase), preservando tipos primitivos boolean/number em tokens únicos.',
|
|
32892
34402
|
},
|
|
32893
34403
|
{
|
|
32894
34404
|
path: 'page.widgets[].definition.inputs.hostCapabilities',
|
|
@@ -33572,6 +35082,7 @@ const DYNAMIC_PAGE_AI_CAPABILITIES = {
|
|
|
33572
35082
|
'Nested component ports usam endpoint component-port com nestedPath; o owner em ref.widget continua sendo o widget top-level.',
|
|
33573
35083
|
'Objetivo: compor widgets e relacionamentos canonicos (ex.: master-detail).',
|
|
33574
35084
|
'Link tipico de master-detail: component-port(table.rowClick) -> component-port(form.resourceId) com transform map payload.row.id.',
|
|
35085
|
+
'Templates {{state.<path> | pipe}} e ${state.<path> | pipe} em inputs de widgets suportam pipes declarativos CSP-safe (default/coalesce, round[:N], number[:N], percent[:N], currency[:BRL|USD|EUR|GBP], uppercase, lowercase) via applyDeclarativeValuePipe, tratando tokens não resolvidos e NaN como ausentes no fallback.',
|
|
33575
35086
|
],
|
|
33576
35087
|
capabilities: CAPS,
|
|
33577
35088
|
};
|
|
@@ -36413,6 +37924,7 @@ const MATERIALIZATION_METADATA_INPUTS = [
|
|
|
36413
37924
|
'schemaEvidenceUrl',
|
|
36414
37925
|
'schemaUrl',
|
|
36415
37926
|
'kpis',
|
|
37927
|
+
'context',
|
|
36416
37928
|
];
|
|
36417
37929
|
const MUTABLE_INITIAL_BINDING_INPUTS = new Set(['enableCustomization']);
|
|
36418
37930
|
/**
|
|
@@ -36439,6 +37951,7 @@ class DynamicWidgetLoaderDirective {
|
|
|
36439
37951
|
currentUsesInitialBindings = false;
|
|
36440
37952
|
currentInitialBindingSignature = null;
|
|
36441
37953
|
boundInputValues = {};
|
|
37954
|
+
resolvedWidgetLocalContext = null;
|
|
36442
37955
|
signalEffects = new Map();
|
|
36443
37956
|
inputObservableSubs = new Map();
|
|
36444
37957
|
outputSubs = [];
|
|
@@ -36471,8 +37984,10 @@ class DynamicWidgetLoaderDirective {
|
|
|
36471
37984
|
if (!this.compRef || this.destroyed || !inputPatch || typeof inputPatch !== 'object') {
|
|
36472
37985
|
return false;
|
|
36473
37986
|
}
|
|
37987
|
+
const def = this.widgetDefinition;
|
|
37988
|
+
const entries = this.orderedInputEntries(def?.id || '', inputPatch, def?.bindingOrder);
|
|
36474
37989
|
let anyChanged = false;
|
|
36475
|
-
for (const [key, value] of
|
|
37990
|
+
for (const [key, value] of entries) {
|
|
36476
37991
|
if (this.setInput(key, value)) {
|
|
36477
37992
|
anyChanged = true;
|
|
36478
37993
|
}
|
|
@@ -36593,6 +38108,8 @@ class DynamicWidgetLoaderDirective {
|
|
|
36593
38108
|
return;
|
|
36594
38109
|
const meta = this.registry.get(def.id);
|
|
36595
38110
|
const inputs = this.withInferredIdentityInputs(def.id, def.inputs || {}, def.childWidgetKey, this.ownerWidgetKey, meta || undefined);
|
|
38111
|
+
this.refreshWidgetLocalContext(inputs);
|
|
38112
|
+
const localContextSnapshot = this.resolvedWidgetLocalContext;
|
|
36596
38113
|
this.normalizeMaterializedRuntimeInputs(def.id, inputs, meta || undefined);
|
|
36597
38114
|
const outputs = def.outputs || {};
|
|
36598
38115
|
try {
|
|
@@ -36614,7 +38131,7 @@ class DynamicWidgetLoaderDirective {
|
|
|
36614
38131
|
&& initialBindingSignature !== this.currentInitialBindingSignature);
|
|
36615
38132
|
let recreated = false;
|
|
36616
38133
|
if (needsRecreate) {
|
|
36617
|
-
this.createComponent(def.id, inputs, def.bindingOrder, meta || undefined, useInitialBindings, initialBindingSignature);
|
|
38134
|
+
this.createComponent(def.id, inputs, def.bindingOrder, meta || undefined, useInitialBindings, initialBindingSignature, localContextSnapshot);
|
|
36618
38135
|
recreated = !!this.compRef;
|
|
36619
38136
|
}
|
|
36620
38137
|
if (this.compRef) {
|
|
@@ -36644,8 +38161,9 @@ class DynamicWidgetLoaderDirective {
|
|
|
36644
38161
|
}
|
|
36645
38162
|
}
|
|
36646
38163
|
}
|
|
36647
|
-
createComponent(id, inputs, bindingOrder, metaForInputs, useInitialBindings = false, initialBindingSignature = null) {
|
|
38164
|
+
createComponent(id, inputs, bindingOrder, metaForInputs, useInitialBindings = false, initialBindingSignature = null, localContextSnapshot = null) {
|
|
36648
38165
|
this.destroyCurrent();
|
|
38166
|
+
this.resolvedWidgetLocalContext = localContextSnapshot;
|
|
36649
38167
|
const meta = this.registry.get(id);
|
|
36650
38168
|
if (!meta) {
|
|
36651
38169
|
const message = `[DynamicWidgetLoader] Component meta not found for id: ${id}`;
|
|
@@ -36710,6 +38228,7 @@ class DynamicWidgetLoaderDirective {
|
|
|
36710
38228
|
this.currentUsesInitialBindings = false;
|
|
36711
38229
|
this.currentInitialBindingSignature = null;
|
|
36712
38230
|
this.boundInputValues = {};
|
|
38231
|
+
this.resolvedWidgetLocalContext = null;
|
|
36713
38232
|
}
|
|
36714
38233
|
this.vcRef.clear();
|
|
36715
38234
|
}
|
|
@@ -36820,17 +38339,27 @@ class DynamicWidgetLoaderDirective {
|
|
|
36820
38339
|
}
|
|
36821
38340
|
applyDirectInputValue(compRef, key, raw, meta, manualChanges) {
|
|
36822
38341
|
const unwrapped = isSignal(raw) ? raw() : raw;
|
|
38342
|
+
if (key === 'context') {
|
|
38343
|
+
this.resolvedWidgetLocalContext = null;
|
|
38344
|
+
}
|
|
36823
38345
|
const value = this.resolveAndCoerceValue(key, unwrapped, meta);
|
|
38346
|
+
if (key === 'context') {
|
|
38347
|
+
this.resolvedWidgetLocalContext =
|
|
38348
|
+
value && typeof value === 'object' && !Array.isArray(value)
|
|
38349
|
+
? value
|
|
38350
|
+
: null;
|
|
38351
|
+
}
|
|
36824
38352
|
const hadPreviousValue = Object.prototype.hasOwnProperty.call(this.boundInputValues, key);
|
|
36825
38353
|
const previousValue = this.boundInputValues[key];
|
|
36826
38354
|
if (hadPreviousValue && this.areInputValuesEquivalent(previousValue, value)) {
|
|
36827
38355
|
return false;
|
|
36828
38356
|
}
|
|
36829
38357
|
try {
|
|
38358
|
+
const metadataAllowsInput = !meta?.inputs?.length || meta.inputs.some((input) => input.name === key);
|
|
36830
38359
|
if (this.hasDeclaredInput(compRef, key)) {
|
|
36831
38360
|
compRef.setInput(key, value);
|
|
36832
38361
|
}
|
|
36833
|
-
else {
|
|
38362
|
+
else if (key !== 'context' || metadataAllowsInput) {
|
|
36834
38363
|
compRef.instance[key] = value;
|
|
36835
38364
|
const change = new SimpleChange(previousValue, value, !hadPreviousValue);
|
|
36836
38365
|
if (manualChanges) {
|
|
@@ -36841,6 +38370,23 @@ class DynamicWidgetLoaderDirective {
|
|
|
36841
38370
|
}
|
|
36842
38371
|
}
|
|
36843
38372
|
this.boundInputValues[key] = value;
|
|
38373
|
+
if (key === 'context' && !manualChanges) {
|
|
38374
|
+
const siblingInputs = this.widgetDefinition?.inputs;
|
|
38375
|
+
if (siblingInputs && typeof siblingInputs === 'object') {
|
|
38376
|
+
for (const [siblingKey, siblingRaw] of Object.entries(siblingInputs)) {
|
|
38377
|
+
if (siblingKey === 'context'
|
|
38378
|
+
|| isSignal(siblingRaw)
|
|
38379
|
+
|| isObservable(siblingRaw)
|
|
38380
|
+
|| isSubscribableInput(siblingRaw)) {
|
|
38381
|
+
continue;
|
|
38382
|
+
}
|
|
38383
|
+
if (!metadataAllowsInput && meta?.inputs?.length && !meta.inputs.some((i) => i.name === siblingKey)) {
|
|
38384
|
+
continue;
|
|
38385
|
+
}
|
|
38386
|
+
this.applyDirectInputValue(compRef, siblingKey, siblingRaw, meta, manualChanges);
|
|
38387
|
+
}
|
|
38388
|
+
}
|
|
38389
|
+
}
|
|
36844
38390
|
if (!manualChanges) {
|
|
36845
38391
|
compRef.changeDetectorRef.detectChanges();
|
|
36846
38392
|
}
|
|
@@ -36861,6 +38407,24 @@ class DynamicWidgetLoaderDirective {
|
|
|
36861
38407
|
.map(([key, raw]) => [key, this.resolveAndCoerceValue(key, raw, meta)]);
|
|
36862
38408
|
return this.stableStringify(resolvedEntries);
|
|
36863
38409
|
}
|
|
38410
|
+
refreshWidgetLocalContext(inputs) {
|
|
38411
|
+
this.resolvedWidgetLocalContext = null;
|
|
38412
|
+
if (!inputs || !Object.prototype.hasOwnProperty.call(inputs, 'context')) {
|
|
38413
|
+
return;
|
|
38414
|
+
}
|
|
38415
|
+
const rawContext = inputs['context'];
|
|
38416
|
+
if (isObservable(rawContext) || isSubscribableInput(rawContext)) {
|
|
38417
|
+
return;
|
|
38418
|
+
}
|
|
38419
|
+
const unwrapped = isSignal(rawContext) ? rawContext() : rawContext;
|
|
38420
|
+
if (!unwrapped || typeof unwrapped !== 'object' || Array.isArray(unwrapped)) {
|
|
38421
|
+
return;
|
|
38422
|
+
}
|
|
38423
|
+
const resolved = this.resolveValue(unwrapped, 'context', ['context']);
|
|
38424
|
+
if (resolved && typeof resolved === 'object' && !Array.isArray(resolved)) {
|
|
38425
|
+
this.resolvedWidgetLocalContext = resolved;
|
|
38426
|
+
}
|
|
38427
|
+
}
|
|
36864
38428
|
orderedInputEntries(id, inputs, bindingOrder) {
|
|
36865
38429
|
const defaultOrderMap = {
|
|
36866
38430
|
'praxis-table': ['tableId', 'componentInstanceId', 'configPersistenceStrategy', 'resourcePath', 'data', 'config'],
|
|
@@ -36889,9 +38453,12 @@ class DynamicWidgetLoaderDirective {
|
|
|
36889
38453
|
'praxis-stepper': ['stepperId', 'componentInstanceId', 'config'],
|
|
36890
38454
|
'praxis-files-upload': ['filesUploadId', 'componentInstanceId', 'config'],
|
|
36891
38455
|
};
|
|
36892
|
-
const
|
|
38456
|
+
const baseOrder = bindingOrder && bindingOrder.length
|
|
36893
38457
|
? bindingOrder
|
|
36894
38458
|
: defaultOrderMap[id] || [];
|
|
38459
|
+
const order = baseOrder.includes('context')
|
|
38460
|
+
? baseOrder
|
|
38461
|
+
: ['context', ...baseOrder];
|
|
36895
38462
|
const entries = Object.entries(inputs);
|
|
36896
38463
|
const entriesMap = new Map(entries);
|
|
36897
38464
|
const prioritized = [];
|
|
@@ -37177,7 +38744,29 @@ class DynamicWidgetLoaderDirective {
|
|
|
37177
38744
|
error,
|
|
37178
38745
|
});
|
|
37179
38746
|
}
|
|
37180
|
-
lookup(ctx,
|
|
38747
|
+
lookup(ctx, rawExpr) {
|
|
38748
|
+
const segments = rawExpr.split('|').map((s) => s.trim()).filter(Boolean);
|
|
38749
|
+
if (!segments.length)
|
|
38750
|
+
return undefined;
|
|
38751
|
+
const path = segments[0];
|
|
38752
|
+
let resolved = this.lookupRawPath(ctx, path);
|
|
38753
|
+
for (let i = 1; i < segments.length; i += 1) {
|
|
38754
|
+
resolved = this.applyDeclarativePipe(resolved, segments[i]);
|
|
38755
|
+
}
|
|
38756
|
+
return resolved;
|
|
38757
|
+
}
|
|
38758
|
+
lookupRawPath(ctx, path) {
|
|
38759
|
+
if (this.resolvedWidgetLocalContext) {
|
|
38760
|
+
const localPath = path.startsWith('context.')
|
|
38761
|
+
? path.slice('context.'.length)
|
|
38762
|
+
: path;
|
|
38763
|
+
const fromLocal = localPath
|
|
38764
|
+
.split('.')
|
|
38765
|
+
.reduce((acc, key) => acc?.[key], this.resolvedWidgetLocalContext);
|
|
38766
|
+
if (fromLocal !== undefined && !isUnresolvedTemplateToken(fromLocal)) {
|
|
38767
|
+
return fromLocal;
|
|
38768
|
+
}
|
|
38769
|
+
}
|
|
37181
38770
|
if (!ctx)
|
|
37182
38771
|
return undefined;
|
|
37183
38772
|
const direct = path
|
|
@@ -37200,6 +38789,9 @@ class DynamicWidgetLoaderDirective {
|
|
|
37200
38789
|
}
|
|
37201
38790
|
return undefined;
|
|
37202
38791
|
}
|
|
38792
|
+
applyDeclarativePipe(value, pipeSpec) {
|
|
38793
|
+
return applyDeclarativeValuePipe(value, pipeSpec);
|
|
38794
|
+
}
|
|
37203
38795
|
validateAgainstMetadata(id, inputs, outputs, meta) {
|
|
37204
38796
|
if (!meta) {
|
|
37205
38797
|
// No metadata: we can only validate output shape at runtime
|
|
@@ -37350,6 +38942,109 @@ function isRecord(value) {
|
|
|
37350
38942
|
function isSubscribableInput(value) {
|
|
37351
38943
|
return !!value && typeof value.subscribe === 'function';
|
|
37352
38944
|
}
|
|
38945
|
+
function isUnresolvedTemplateToken(value) {
|
|
38946
|
+
return typeof value === 'string' && /^(?:\$\{([^}]+)\}|\{\{\s*([^}]+?)\s*\}\})$/.test(value.trim());
|
|
38947
|
+
}
|
|
38948
|
+
function applyDeclarativeValuePipe(value, pipeSpec) {
|
|
38949
|
+
const colonIdx = pipeSpec.indexOf(':');
|
|
38950
|
+
const pipeName = (colonIdx >= 0 ? pipeSpec.slice(0, colonIdx) : pipeSpec).trim().toLowerCase();
|
|
38951
|
+
const rawArg = colonIdx >= 0 ? pipeSpec.slice(colonIdx + 1).trim() : '';
|
|
38952
|
+
const unquotedArg = rawArg.replace(/^['"]|['"]$/g, '');
|
|
38953
|
+
if (pipeName === 'default' || pipeName === 'coalesce') {
|
|
38954
|
+
if (value === undefined
|
|
38955
|
+
|| value === null
|
|
38956
|
+
|| (typeof value === 'string' && value.trim() === '')
|
|
38957
|
+
|| (typeof value === 'number' && Number.isNaN(value))
|
|
38958
|
+
|| isUnresolvedTemplateToken(value)) {
|
|
38959
|
+
if (rawArg === 'true')
|
|
38960
|
+
return true;
|
|
38961
|
+
if (rawArg === 'false')
|
|
38962
|
+
return false;
|
|
38963
|
+
if (/^-?\d+(?:\.\d+)?$/.test(rawArg)) {
|
|
38964
|
+
return Number(rawArg);
|
|
38965
|
+
}
|
|
38966
|
+
return unquotedArg;
|
|
38967
|
+
}
|
|
38968
|
+
return value;
|
|
38969
|
+
}
|
|
38970
|
+
if (value === undefined || value === null || isUnresolvedTemplateToken(value)) {
|
|
38971
|
+
return undefined;
|
|
38972
|
+
}
|
|
38973
|
+
if (pipeName === 'uppercase' || pipeName === 'upper') {
|
|
38974
|
+
return String(value).toUpperCase();
|
|
38975
|
+
}
|
|
38976
|
+
if (pipeName === 'lowercase' || pipeName === 'lower') {
|
|
38977
|
+
return String(value).toLowerCase();
|
|
38978
|
+
}
|
|
38979
|
+
const isKnownNumericPipe = pipeName === 'round'
|
|
38980
|
+
|| pipeName === 'number'
|
|
38981
|
+
|| pipeName === 'percent'
|
|
38982
|
+
|| pipeName === 'currency';
|
|
38983
|
+
if (!isKnownNumericPipe) {
|
|
38984
|
+
return value;
|
|
38985
|
+
}
|
|
38986
|
+
if (typeof value === 'string' && value.trim() === '') {
|
|
38987
|
+
return undefined;
|
|
38988
|
+
}
|
|
38989
|
+
const numeric = typeof value === 'number' ? value : Number(value);
|
|
38990
|
+
if (!Number.isFinite(numeric)) {
|
|
38991
|
+
return undefined;
|
|
38992
|
+
}
|
|
38993
|
+
if (pipeName === 'round') {
|
|
38994
|
+
const decimals = unquotedArg !== '' && Number.isFinite(Number(unquotedArg))
|
|
38995
|
+
? Math.max(0, Math.min(6, Math.trunc(Number(unquotedArg))))
|
|
38996
|
+
: 0;
|
|
38997
|
+
const factor = Math.pow(10, decimals);
|
|
38998
|
+
return Math.round(numeric * factor) / factor;
|
|
38999
|
+
}
|
|
39000
|
+
if (pipeName === 'number') {
|
|
39001
|
+
const hasDecimals = unquotedArg !== '' && Number.isFinite(Number(unquotedArg));
|
|
39002
|
+
const decimals = hasDecimals ? Math.max(0, Math.min(6, Math.trunc(Number(unquotedArg)))) : undefined;
|
|
39003
|
+
return new Intl.NumberFormat('pt-BR', {
|
|
39004
|
+
minimumFractionDigits: decimals,
|
|
39005
|
+
maximumFractionDigits: decimals ?? 2,
|
|
39006
|
+
}).format(numeric);
|
|
39007
|
+
}
|
|
39008
|
+
if (pipeName === 'percent') {
|
|
39009
|
+
const hasDecimals = unquotedArg !== '' && Number.isFinite(Number(unquotedArg));
|
|
39010
|
+
const decimals = hasDecimals ? Math.max(0, Math.min(6, Math.trunc(Number(unquotedArg)))) : undefined;
|
|
39011
|
+
const pctValue = Math.abs(numeric) > 0 && Math.abs(numeric) < 1 ? numeric * 100 : numeric;
|
|
39012
|
+
const formatted = new Intl.NumberFormat('pt-BR', {
|
|
39013
|
+
minimumFractionDigits: decimals,
|
|
39014
|
+
maximumFractionDigits: decimals ?? 2,
|
|
39015
|
+
}).format(pctValue);
|
|
39016
|
+
return `${formatted}%`;
|
|
39017
|
+
}
|
|
39018
|
+
if (pipeName === 'currency') {
|
|
39019
|
+
const rawCurrency = (unquotedArg || 'BRL').trim().toUpperCase();
|
|
39020
|
+
const aliasMap = {
|
|
39021
|
+
'R$': 'BRL',
|
|
39022
|
+
'US$': 'USD',
|
|
39023
|
+
'$': 'USD',
|
|
39024
|
+
'€': 'EUR',
|
|
39025
|
+
'£': 'GBP',
|
|
39026
|
+
};
|
|
39027
|
+
const currency = aliasMap[rawCurrency] || (/^[A-Z]{3}$/.test(rawCurrency) ? rawCurrency : 'BRL');
|
|
39028
|
+
const locale = currency === 'USD' ? 'en-US' : 'pt-BR';
|
|
39029
|
+
try {
|
|
39030
|
+
return new Intl.NumberFormat(locale, {
|
|
39031
|
+
style: 'currency',
|
|
39032
|
+
currency,
|
|
39033
|
+
})
|
|
39034
|
+
.format(numeric)
|
|
39035
|
+
.replace(/\u00A0/g, ' ');
|
|
39036
|
+
}
|
|
39037
|
+
catch {
|
|
39038
|
+
return new Intl.NumberFormat('pt-BR', {
|
|
39039
|
+
style: 'currency',
|
|
39040
|
+
currency: 'BRL',
|
|
39041
|
+
})
|
|
39042
|
+
.format(numeric)
|
|
39043
|
+
.replace(/\u00A0/g, ' ');
|
|
39044
|
+
}
|
|
39045
|
+
}
|
|
39046
|
+
return value;
|
|
39047
|
+
}
|
|
37353
39048
|
|
|
37354
39049
|
/** Private rendered geometry shared by shell recovery and canvas authoring. */
|
|
37355
39050
|
function measureWidgetShellHeight(shell) {
|
|
@@ -40281,11 +41976,23 @@ class WidgetPageDataSourceRuntimeService {
|
|
|
40281
41976
|
base = buildApiUrl(entry);
|
|
40282
41977
|
}
|
|
40283
41978
|
}
|
|
40284
|
-
|
|
41979
|
+
let cleanPath = appendOperationSuffix(trimmed.replace(/^\/+/, ''));
|
|
40285
41980
|
if (!base) {
|
|
40286
41981
|
return cleanPath.startsWith('/') ? cleanPath : `/${cleanPath}`;
|
|
40287
41982
|
}
|
|
40288
41983
|
const cleanBase = base.replace(/\/+$/, '');
|
|
41984
|
+
try {
|
|
41985
|
+
const basePath = new URL(cleanBase, 'http://praxis.local').pathname.replace(/^\/+|\/+$/g, '');
|
|
41986
|
+
if (basePath && cleanPath.startsWith(`${basePath}/`)) {
|
|
41987
|
+
cleanPath = cleanPath.slice(basePath.length + 1);
|
|
41988
|
+
}
|
|
41989
|
+
else if (/\/api(\/|$)/.test(`/${basePath}`)) {
|
|
41990
|
+
cleanPath = cleanPath.replace(/^(?:api\/)+/, '');
|
|
41991
|
+
}
|
|
41992
|
+
}
|
|
41993
|
+
catch {
|
|
41994
|
+
// ignore invalid base URLs
|
|
41995
|
+
}
|
|
40289
41996
|
return `${cleanBase}/${cleanPath}`;
|
|
40290
41997
|
}
|
|
40291
41998
|
/**
|
|
@@ -56910,95 +58617,350 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
56910
58617
|
type: Input
|
|
56911
58618
|
}] } });
|
|
56912
58619
|
|
|
58620
|
+
let nextQuickConnectInstanceId = 0;
|
|
56913
58621
|
class ResourceQuickConnectComponent {
|
|
56914
58622
|
resourcePath = '';
|
|
58623
|
+
resourcePathChange = new EventEmitter();
|
|
58624
|
+
endpointKey;
|
|
58625
|
+
apiUrlEntry;
|
|
58626
|
+
intent = 'any';
|
|
58627
|
+
resources;
|
|
58628
|
+
label;
|
|
58629
|
+
placeholder;
|
|
58630
|
+
hint;
|
|
58631
|
+
disabled = false;
|
|
56915
58632
|
selector;
|
|
56916
58633
|
registry = this.optionalInject(ComponentMetadataRegistry);
|
|
56917
58634
|
discovery = this.optionalInject(ResourceDiscoveryService);
|
|
56918
58635
|
i18n = this.optionalInject(PraxisI18nService);
|
|
56919
58636
|
cdr = this.optionalInject(ChangeDetectorRef);
|
|
56920
|
-
|
|
58637
|
+
datalistId = `pdx-quick-connect-datalist-${++nextQuickConnectInstanceId}`;
|
|
58638
|
+
get selectorType() {
|
|
58639
|
+
return this.registry?.get('pdx-material-select')?.component;
|
|
58640
|
+
}
|
|
56921
58641
|
selectorInputs;
|
|
58642
|
+
discoveredResources = [];
|
|
58643
|
+
fallbackSearchTerm = '';
|
|
56922
58644
|
catalogLoading = false;
|
|
56923
58645
|
catalogError = false;
|
|
58646
|
+
isDirty$ = new BehaviorSubject(false);
|
|
58647
|
+
isValid$ = new BehaviorSubject(false);
|
|
58648
|
+
isBusy$ = new BehaviorSubject(false);
|
|
56924
58649
|
accessor;
|
|
56925
|
-
|
|
58650
|
+
rawCatalog = null;
|
|
58651
|
+
catalogRequestId = 0;
|
|
58652
|
+
baselineResourcePath = '';
|
|
58653
|
+
suppressSelectorOnChange = false;
|
|
58654
|
+
manualInputActive = false;
|
|
58655
|
+
userForcedAdvancedOpen = false;
|
|
58656
|
+
cvaOnChange = () => { };
|
|
58657
|
+
cvaOnTouched = () => { };
|
|
58658
|
+
tx(key, fallback) {
|
|
58659
|
+
return (this.i18n?.t(`quickConnect.${key}`, undefined, fallback ?? key, 'resourceDiscovery') ??
|
|
58660
|
+
fallback ??
|
|
58661
|
+
key);
|
|
58662
|
+
}
|
|
58663
|
+
resolvedHint() {
|
|
58664
|
+
if (this.hint?.trim()) {
|
|
58665
|
+
return this.hint.trim();
|
|
58666
|
+
}
|
|
58667
|
+
const defaultHint = this.tx('hint');
|
|
58668
|
+
if (this.intent && this.intent !== 'any') {
|
|
58669
|
+
return this.tx(`hint.${this.intent}`, defaultHint);
|
|
58670
|
+
}
|
|
58671
|
+
return defaultHint;
|
|
58672
|
+
}
|
|
58673
|
+
ngOnInit() {
|
|
58674
|
+
this.baselineResourcePath = this.resourcePath ?? '';
|
|
58675
|
+
this.updateValidity();
|
|
58676
|
+
if (Array.isArray(this.resources)) {
|
|
58677
|
+
this.applyExplicitResources(this.resources);
|
|
58678
|
+
return;
|
|
58679
|
+
}
|
|
58680
|
+
void this.loadCatalog();
|
|
58681
|
+
}
|
|
58682
|
+
ngOnChanges(changes = {}) {
|
|
58683
|
+
if (changes['resourcePath'] && !this.isDirty$.value) {
|
|
58684
|
+
this.baselineResourcePath = this.resourcePath ?? '';
|
|
58685
|
+
}
|
|
58686
|
+
this.updateValidity();
|
|
58687
|
+
if (changes['resources']) {
|
|
58688
|
+
if (Array.isArray(this.resources)) {
|
|
58689
|
+
this.applyExplicitResources(this.resources);
|
|
58690
|
+
this.cdr?.markForCheck();
|
|
58691
|
+
return;
|
|
58692
|
+
}
|
|
58693
|
+
if (!changes['resources'].firstChange) {
|
|
58694
|
+
void this.loadCatalog();
|
|
58695
|
+
return;
|
|
58696
|
+
}
|
|
58697
|
+
}
|
|
58698
|
+
if ((changes['endpointKey'] && !changes['endpointKey'].firstChange) ||
|
|
58699
|
+
(changes['apiUrlEntry'] && !changes['apiUrlEntry'].firstChange)) {
|
|
58700
|
+
void this.loadCatalog();
|
|
58701
|
+
return;
|
|
58702
|
+
}
|
|
58703
|
+
if (changes['intent'] && !changes['intent'].firstChange) {
|
|
58704
|
+
if (Array.isArray(this.resources)) {
|
|
58705
|
+
this.applyExplicitResources(this.resources);
|
|
58706
|
+
this.cdr?.markForCheck();
|
|
58707
|
+
}
|
|
58708
|
+
else if (this.rawCatalog) {
|
|
58709
|
+
this.applyCatalogProjection(this.rawCatalog);
|
|
58710
|
+
this.cdr?.markForCheck();
|
|
58711
|
+
}
|
|
58712
|
+
else {
|
|
58713
|
+
void this.loadCatalog();
|
|
58714
|
+
}
|
|
58715
|
+
return;
|
|
58716
|
+
}
|
|
58717
|
+
if ((changes['label'] && !changes['label'].firstChange) ||
|
|
58718
|
+
(changes['placeholder'] && !changes['placeholder'].firstChange)) {
|
|
58719
|
+
this.rebuildSelectorInputs();
|
|
58720
|
+
}
|
|
58721
|
+
this.syncSelectorValue();
|
|
58722
|
+
this.cdr?.markForCheck();
|
|
58723
|
+
}
|
|
56926
58724
|
ngAfterViewChecked() {
|
|
56927
58725
|
const instance = this.selector?.componentInstance;
|
|
56928
|
-
if (!instance ||
|
|
58726
|
+
if (!instance ||
|
|
58727
|
+
instance === this.accessor ||
|
|
58728
|
+
!instance.registerOnChange ||
|
|
58729
|
+
!instance.writeValue) {
|
|
56929
58730
|
return;
|
|
56930
|
-
|
|
58731
|
+
}
|
|
56931
58732
|
this.accessor = instance;
|
|
56932
|
-
this.accessor.
|
|
58733
|
+
this.accessor.setInputMetadata?.(this.selectorInputs?.['metadata']);
|
|
58734
|
+
this.accessor.setDisabledState?.(this.disabled);
|
|
58735
|
+
this.syncSelectorValue();
|
|
56933
58736
|
this.accessor.registerOnChange((value) => {
|
|
56934
|
-
this.
|
|
56935
|
-
|
|
58737
|
+
if (this.suppressSelectorOnChange) {
|
|
58738
|
+
return;
|
|
58739
|
+
}
|
|
58740
|
+
const nextValue = typeof value === 'string' ? value : '';
|
|
58741
|
+
this.manualInputActive = false;
|
|
58742
|
+
this.resourcePath = nextValue;
|
|
58743
|
+
this.updateState(true);
|
|
58744
|
+
});
|
|
58745
|
+
this.accessor.registerOnTouched?.(() => {
|
|
58746
|
+
this.handleBlur();
|
|
56936
58747
|
});
|
|
56937
58748
|
}
|
|
56938
58749
|
async loadCatalog() {
|
|
56939
|
-
if (
|
|
58750
|
+
if (Array.isArray(this.resources)) {
|
|
58751
|
+
this.applyExplicitResources(this.resources);
|
|
56940
58752
|
return;
|
|
58753
|
+
}
|
|
58754
|
+
if (!this.discovery) {
|
|
58755
|
+
return;
|
|
58756
|
+
}
|
|
58757
|
+
const requestId = ++this.catalogRequestId;
|
|
56941
58758
|
this.catalogLoading = true;
|
|
56942
58759
|
this.catalogError = false;
|
|
58760
|
+
this.isBusy$.next(true);
|
|
56943
58761
|
this.cdr?.markForCheck();
|
|
56944
58762
|
try {
|
|
56945
|
-
const
|
|
56946
|
-
const
|
|
56947
|
-
|
|
56948
|
-
|
|
56949
|
-
if (endpoint.method !== 'GET' || !endpoint.resourceKey || !endpoint.path.startsWith('/')
|
|
56950
|
-
|| endpoint.path.startsWith('//') || endpoint.path.includes('{') || !endpoint.path.endsWith('/capabilities'))
|
|
56951
|
-
continue;
|
|
56952
|
-
const value = endpoint.path.slice(0, -'/capabilities'.length);
|
|
56953
|
-
resources.set(value, { value, label: endpoint.resourceVisual?.title || endpoint.resourceKey });
|
|
58763
|
+
const requestOpts = this.requestOptions();
|
|
58764
|
+
const catalog = await firstValueFrom(this.discovery.getSchemaCatalog({}, requestOpts).pipe(timeout$1(30000)));
|
|
58765
|
+
if (requestId !== this.catalogRequestId) {
|
|
58766
|
+
return;
|
|
56954
58767
|
}
|
|
56955
|
-
this.
|
|
56956
|
-
|
|
56957
|
-
selectOptions: [...resources.values()].sort((a, b) => a.label.localeCompare(b.label)),
|
|
56958
|
-
} } : undefined;
|
|
58768
|
+
this.rawCatalog = catalog;
|
|
58769
|
+
this.applyCatalogProjection(catalog);
|
|
56959
58770
|
}
|
|
56960
58771
|
catch {
|
|
58772
|
+
if (requestId !== this.catalogRequestId) {
|
|
58773
|
+
return;
|
|
58774
|
+
}
|
|
58775
|
+
this.rawCatalog = null;
|
|
56961
58776
|
this.catalogError = true;
|
|
58777
|
+
this.discoveredResources = [];
|
|
58778
|
+
this.selectorInputs = undefined;
|
|
56962
58779
|
}
|
|
56963
58780
|
finally {
|
|
56964
|
-
this.
|
|
56965
|
-
|
|
56966
|
-
|
|
58781
|
+
if (requestId === this.catalogRequestId) {
|
|
58782
|
+
this.catalogLoading = false;
|
|
58783
|
+
this.isBusy$.next(false);
|
|
58784
|
+
this.cdr?.markForCheck();
|
|
58785
|
+
}
|
|
58786
|
+
}
|
|
58787
|
+
}
|
|
58788
|
+
filteredFallbackResources() {
|
|
58789
|
+
const query = this.normalizeSearchText(this.fallbackSearchTerm);
|
|
58790
|
+
if (!query) {
|
|
58791
|
+
return this.discoveredResources;
|
|
58792
|
+
}
|
|
58793
|
+
return this.discoveredResources.filter((option) => {
|
|
58794
|
+
const haystack = this.normalizeSearchText([
|
|
58795
|
+
option.label,
|
|
58796
|
+
option.value,
|
|
58797
|
+
option.path,
|
|
58798
|
+
option.resourceKey,
|
|
58799
|
+
option.group,
|
|
58800
|
+
option.description,
|
|
58801
|
+
...(option.tags ?? []),
|
|
58802
|
+
...(option.searchTerms ?? []),
|
|
58803
|
+
].join(' '));
|
|
58804
|
+
return haystack.includes(query);
|
|
58805
|
+
});
|
|
56967
58806
|
}
|
|
56968
|
-
|
|
56969
|
-
|
|
56970
|
-
|
|
58807
|
+
isResourceSelected(option) {
|
|
58808
|
+
const selected = this.selectedResource();
|
|
58809
|
+
return Boolean(selected && selected.value === option.value);
|
|
58810
|
+
}
|
|
58811
|
+
selectDiscoveredResource(option) {
|
|
58812
|
+
if (this.disabled) {
|
|
58813
|
+
return;
|
|
56971
58814
|
}
|
|
56972
|
-
|
|
58815
|
+
this.manualInputActive = false;
|
|
58816
|
+
this.resourcePath = option.value;
|
|
58817
|
+
this.updateState(true);
|
|
58818
|
+
this.syncSelectorValue();
|
|
58819
|
+
}
|
|
58820
|
+
selectedResource() {
|
|
58821
|
+
const trimmed = this.resourcePath?.trim() || '';
|
|
58822
|
+
if (!trimmed || !this.discoveredResources.length) {
|
|
56973
58823
|
return null;
|
|
56974
58824
|
}
|
|
58825
|
+
if (typeof this.discovery?.findCatalogResourceOption === 'function') {
|
|
58826
|
+
return this.discovery.findCatalogResourceOption(trimmed, this.discoveredResources, this.requestOptions());
|
|
58827
|
+
}
|
|
58828
|
+
return this.findMatchingResourceFallback(trimmed);
|
|
56975
58829
|
}
|
|
56976
|
-
|
|
56977
|
-
|
|
56978
|
-
|
|
56979
|
-
|
|
56980
|
-
|
|
56981
|
-
|
|
56982
|
-
|
|
56983
|
-
|
|
58830
|
+
applyExplicitResources(resources) {
|
|
58831
|
+
this.catalogLoading = false;
|
|
58832
|
+
this.catalogError = false;
|
|
58833
|
+
this.discoveredResources = Array.isArray(resources) ? [...resources] : [];
|
|
58834
|
+
this.rebuildSelectorInputs(true);
|
|
58835
|
+
if (this.resourcePath?.trim() && this.discoveredResources.length) {
|
|
58836
|
+
const resolved = this.resolvedSelectorValue();
|
|
58837
|
+
if (resolved &&
|
|
58838
|
+
resolved !== this.resourcePath &&
|
|
58839
|
+
this.matchesDiscoveredResource(this.resourcePath)) {
|
|
58840
|
+
this.resourcePath = resolved;
|
|
58841
|
+
}
|
|
58842
|
+
}
|
|
58843
|
+
this.syncSelectorValue();
|
|
58844
|
+
}
|
|
58845
|
+
applyCatalogProjection(catalog) {
|
|
58846
|
+
const requestOpts = this.requestOptions();
|
|
58847
|
+
const hasCanonicalProjector = typeof this.discovery?.projectSchemaCatalogResources === 'function';
|
|
58848
|
+
const projected = hasCanonicalProjector && this.discovery
|
|
58849
|
+
? this.discovery.projectSchemaCatalogResources(catalog, {
|
|
58850
|
+
...requestOpts,
|
|
58851
|
+
intent: this.intent,
|
|
58852
|
+
})
|
|
58853
|
+
: this.projectLegacyCatalogFallback(catalog);
|
|
58854
|
+
this.discoveredResources = projected;
|
|
58855
|
+
this.rebuildSelectorInputs(hasCanonicalProjector);
|
|
58856
|
+
if (this.resourcePath?.trim() && this.discoveredResources.length) {
|
|
58857
|
+
const resolved = this.resolvedSelectorValue();
|
|
58858
|
+
if (resolved &&
|
|
58859
|
+
resolved !== this.resourcePath &&
|
|
58860
|
+
this.matchesDiscoveredResource(this.resourcePath)) {
|
|
58861
|
+
this.resourcePath = resolved;
|
|
58862
|
+
}
|
|
58863
|
+
}
|
|
58864
|
+
this.syncSelectorValue();
|
|
56984
58865
|
}
|
|
56985
|
-
|
|
58866
|
+
writeValue(value) {
|
|
58867
|
+
this.resourcePath = typeof value === 'string' ? value : '';
|
|
58868
|
+
if (!this.isDirty$.value) {
|
|
58869
|
+
this.baselineResourcePath = this.resourcePath;
|
|
58870
|
+
}
|
|
56986
58871
|
this.updateValidity();
|
|
56987
|
-
this.
|
|
58872
|
+
this.syncSelectorValue();
|
|
58873
|
+
this.cdr?.markForCheck();
|
|
58874
|
+
}
|
|
58875
|
+
registerOnChange(fn) {
|
|
58876
|
+
this.cvaOnChange = fn ?? (() => { });
|
|
58877
|
+
}
|
|
58878
|
+
registerOnTouched(fn) {
|
|
58879
|
+
this.cvaOnTouched = fn ?? (() => { });
|
|
56988
58880
|
}
|
|
56989
|
-
|
|
58881
|
+
setDisabledState(isDisabled) {
|
|
58882
|
+
this.disabled = Boolean(isDisabled);
|
|
58883
|
+
this.accessor?.setDisabledState?.(this.disabled);
|
|
58884
|
+
this.cdr?.markForCheck();
|
|
58885
|
+
}
|
|
58886
|
+
onManualResourcePathChange(value) {
|
|
58887
|
+
this.manualInputActive = true;
|
|
58888
|
+
this.resourcePath = typeof value === 'string' ? value : '';
|
|
58889
|
+
this.updateState(true);
|
|
58890
|
+
this.syncSelectorValue();
|
|
58891
|
+
}
|
|
58892
|
+
onAdvancedToggle(event) {
|
|
58893
|
+
const details = event.target;
|
|
58894
|
+
if (details) {
|
|
58895
|
+
this.userForcedAdvancedOpen = details.open;
|
|
58896
|
+
}
|
|
58897
|
+
}
|
|
58898
|
+
handleBlur() {
|
|
58899
|
+
this.cvaOnTouched();
|
|
58900
|
+
}
|
|
58901
|
+
shouldOpenAdvanced() {
|
|
58902
|
+
if ((!this.selectorType && !this.discoveredResources.length) ||
|
|
58903
|
+
this.catalogError ||
|
|
58904
|
+
this.manualInputActive ||
|
|
58905
|
+
this.userForcedAdvancedOpen) {
|
|
58906
|
+
return true;
|
|
58907
|
+
}
|
|
58908
|
+
if (!this.catalogLoading && !this.selectorInputs && !this.discoveredResources.length) {
|
|
58909
|
+
return true;
|
|
58910
|
+
}
|
|
58911
|
+
const trimmed = this.resourcePath?.trim() || '';
|
|
58912
|
+
if (!trimmed) {
|
|
58913
|
+
return false;
|
|
58914
|
+
}
|
|
58915
|
+
if (!this.discoveredResources.length) {
|
|
58916
|
+
return false;
|
|
58917
|
+
}
|
|
58918
|
+
return !this.matchesDiscoveredResource(trimmed);
|
|
58919
|
+
}
|
|
58920
|
+
updateState(emitChanges = false) {
|
|
56990
58921
|
this.isDirty$.next(true);
|
|
56991
58922
|
this.updateValidity();
|
|
58923
|
+
if (emitChanges) {
|
|
58924
|
+
const emitted = this.resourcePath;
|
|
58925
|
+
this.cvaOnChange(emitted);
|
|
58926
|
+
this.resourcePathChange.emit(emitted);
|
|
58927
|
+
}
|
|
58928
|
+
this.cdr?.markForCheck();
|
|
56992
58929
|
}
|
|
56993
|
-
|
|
56994
|
-
|
|
56995
|
-
this.
|
|
58930
|
+
reset() {
|
|
58931
|
+
this.manualInputActive = false;
|
|
58932
|
+
this.resourcePath = this.baselineResourcePath;
|
|
58933
|
+
this.isDirty$.next(false);
|
|
58934
|
+
this.updateValidity();
|
|
58935
|
+
this.syncSelectorValue();
|
|
58936
|
+
this.cvaOnChange(this.resourcePath);
|
|
58937
|
+
this.resourcePathChange.emit(this.resourcePath);
|
|
58938
|
+
this.cdr?.markForCheck();
|
|
58939
|
+
}
|
|
58940
|
+
acceptAppliedValue(value) {
|
|
58941
|
+
if (typeof value === 'string') {
|
|
58942
|
+
this.resourcePath = value;
|
|
58943
|
+
}
|
|
58944
|
+
else if (value && typeof value.resourcePath === 'string') {
|
|
58945
|
+
this.resourcePath = value.resourcePath;
|
|
58946
|
+
}
|
|
58947
|
+
else {
|
|
58948
|
+
this.resourcePath = this.normalizedPath();
|
|
58949
|
+
}
|
|
58950
|
+
this.baselineResourcePath = this.resourcePath;
|
|
58951
|
+
this.manualInputActive = false;
|
|
58952
|
+
this.isDirty$.next(false);
|
|
58953
|
+
this.updateValidity();
|
|
58954
|
+
this.syncSelectorValue();
|
|
58955
|
+
this.cdr?.markForCheck();
|
|
56996
58956
|
}
|
|
56997
58957
|
getSettingsValue() {
|
|
56998
58958
|
return { resourcePath: this.normalizedPath() };
|
|
56999
58959
|
}
|
|
57000
58960
|
onSave() {
|
|
57001
|
-
|
|
58961
|
+
const saved = this.getSettingsValue();
|
|
58962
|
+
this.acceptAppliedValue(saved);
|
|
58963
|
+
return saved;
|
|
57002
58964
|
}
|
|
57003
58965
|
showInvalid() {
|
|
57004
58966
|
const trimmed = this.resourcePath?.trim() || '';
|
|
@@ -57014,57 +58976,525 @@ class ResourceQuickConnectComponent {
|
|
|
57014
58976
|
return trimmed;
|
|
57015
58977
|
return `/${trimmed}`;
|
|
57016
58978
|
}
|
|
58979
|
+
resolvedSelectorValue() {
|
|
58980
|
+
const trimmed = this.resourcePath?.trim() || '';
|
|
58981
|
+
if (!trimmed) {
|
|
58982
|
+
return '';
|
|
58983
|
+
}
|
|
58984
|
+
if (this.discoveredResources.length) {
|
|
58985
|
+
if (typeof this.discovery?.resolveCatalogResourceOptionValue === 'function') {
|
|
58986
|
+
return this.discovery.resolveCatalogResourceOptionValue(trimmed, this.discoveredResources, this.requestOptions());
|
|
58987
|
+
}
|
|
58988
|
+
const matched = this.findMatchingResourceFallback(trimmed);
|
|
58989
|
+
if (matched) {
|
|
58990
|
+
return matched.value;
|
|
58991
|
+
}
|
|
58992
|
+
}
|
|
58993
|
+
return this.normalizedPath();
|
|
58994
|
+
}
|
|
58995
|
+
matchesDiscoveredResource(rawPath) {
|
|
58996
|
+
if (typeof this.discovery?.findCatalogResourceOption === 'function') {
|
|
58997
|
+
return Boolean(this.discovery.findCatalogResourceOption(rawPath, this.discoveredResources, this.requestOptions()));
|
|
58998
|
+
}
|
|
58999
|
+
return Boolean(this.findMatchingResourceFallback(rawPath));
|
|
59000
|
+
}
|
|
59001
|
+
findMatchingResourceFallback(rawPath) {
|
|
59002
|
+
const normalized = this.normalizedPath();
|
|
59003
|
+
const strippedApi = normalized.startsWith('/api/')
|
|
59004
|
+
? normalized.slice('/api'.length)
|
|
59005
|
+
: normalized;
|
|
59006
|
+
const withApi = normalized.startsWith('/api/')
|
|
59007
|
+
? normalized
|
|
59008
|
+
: `/api${normalized}`;
|
|
59009
|
+
for (const option of this.discoveredResources) {
|
|
59010
|
+
if (option.value === rawPath ||
|
|
59011
|
+
option.value === normalized ||
|
|
59012
|
+
option.value === strippedApi ||
|
|
59013
|
+
option.value === withApi ||
|
|
59014
|
+
option.path === normalized ||
|
|
59015
|
+
option.path === strippedApi ||
|
|
59016
|
+
option.resourceKey === rawPath) {
|
|
59017
|
+
return option;
|
|
59018
|
+
}
|
|
59019
|
+
}
|
|
59020
|
+
return null;
|
|
59021
|
+
}
|
|
59022
|
+
syncSelectorValue() {
|
|
59023
|
+
if (!this.accessor?.writeValue) {
|
|
59024
|
+
return;
|
|
59025
|
+
}
|
|
59026
|
+
this.suppressSelectorOnChange = true;
|
|
59027
|
+
try {
|
|
59028
|
+
this.accessor.writeValue(this.resolvedSelectorValue());
|
|
59029
|
+
}
|
|
59030
|
+
finally {
|
|
59031
|
+
this.suppressSelectorOnChange = false;
|
|
59032
|
+
}
|
|
59033
|
+
}
|
|
59034
|
+
rebuildSelectorInputs(includeRichMetadata = true) {
|
|
59035
|
+
if (!this.discoveredResources.length) {
|
|
59036
|
+
this.selectorInputs = undefined;
|
|
59037
|
+
return;
|
|
59038
|
+
}
|
|
59039
|
+
const readOnlyLabel = this.tx('readOnly', 'Somente leitura');
|
|
59040
|
+
const selectOptions = this.discoveredResources.map((resource) => {
|
|
59041
|
+
if (!includeRichMetadata && !resource.description && !resource.tags.length) {
|
|
59042
|
+
return {
|
|
59043
|
+
value: resource.value,
|
|
59044
|
+
label: resource.label,
|
|
59045
|
+
};
|
|
59046
|
+
}
|
|
59047
|
+
const code = resource.path && resource.path !== resource.label
|
|
59048
|
+
? resource.path
|
|
59049
|
+
: resource.value !== resource.label
|
|
59050
|
+
? resource.value
|
|
59051
|
+
: undefined;
|
|
59052
|
+
const badgeParts = [
|
|
59053
|
+
resource.group?.trim() || null,
|
|
59054
|
+
includeRichMetadata && resource.readOnly === true ? readOnlyLabel : null,
|
|
59055
|
+
].filter((part) => Boolean(part));
|
|
59056
|
+
const badge = badgeParts.length ? badgeParts.join(' · ') : undefined;
|
|
59057
|
+
const description = resource.description?.trim() || undefined;
|
|
59058
|
+
const icon = includeRichMetadata
|
|
59059
|
+
? resource.icon?.trim() || 'api'
|
|
59060
|
+
: resource.icon?.trim() || undefined;
|
|
59061
|
+
const searchTerms = includeRichMetadata && resource.readOnly === true
|
|
59062
|
+
? Array.from(new Set([...(resource.searchTerms ?? []), readOnlyLabel]))
|
|
59063
|
+
: resource.searchTerms;
|
|
59064
|
+
return {
|
|
59065
|
+
value: resource.value,
|
|
59066
|
+
label: resource.label,
|
|
59067
|
+
...(icon ? { icon } : {}),
|
|
59068
|
+
...(code ? { code } : {}),
|
|
59069
|
+
...(badge ? { badge } : {}),
|
|
59070
|
+
...(description ? { description } : {}),
|
|
59071
|
+
...(searchTerms?.length
|
|
59072
|
+
? { searchTerms }
|
|
59073
|
+
: {}),
|
|
59074
|
+
};
|
|
59075
|
+
});
|
|
59076
|
+
this.selectorInputs = {
|
|
59077
|
+
metadata: {
|
|
59078
|
+
name: 'resourcePath',
|
|
59079
|
+
label: this.label?.trim() || this.tx('resource'),
|
|
59080
|
+
placeholder: this.placeholder?.trim() || undefined,
|
|
59081
|
+
searchPlaceholder: this.tx('searchPlaceholder'),
|
|
59082
|
+
type: 'string',
|
|
59083
|
+
controlType: 'select',
|
|
59084
|
+
searchable: true,
|
|
59085
|
+
selectOptions,
|
|
59086
|
+
},
|
|
59087
|
+
};
|
|
59088
|
+
this.accessor?.setInputMetadata?.(this.selectorInputs['metadata']);
|
|
59089
|
+
}
|
|
59090
|
+
normalizeSearchText(value) {
|
|
59091
|
+
return String(value ?? '')
|
|
59092
|
+
.normalize('NFD')
|
|
59093
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
59094
|
+
.toLowerCase()
|
|
59095
|
+
.trim();
|
|
59096
|
+
}
|
|
59097
|
+
projectLegacyCatalogFallback(catalog) {
|
|
59098
|
+
const resources = new Map();
|
|
59099
|
+
for (const endpoint of catalog?.endpoints ?? []) {
|
|
59100
|
+
if (endpoint.method !== 'GET' ||
|
|
59101
|
+
!endpoint.resourceKey ||
|
|
59102
|
+
!endpoint.path.startsWith('/') ||
|
|
59103
|
+
endpoint.path.startsWith('//') ||
|
|
59104
|
+
endpoint.path.includes('{') ||
|
|
59105
|
+
!endpoint.path.endsWith('/capabilities')) {
|
|
59106
|
+
continue;
|
|
59107
|
+
}
|
|
59108
|
+
const value = endpoint.resourcePath?.trim() || endpoint.path.slice(0, -'/capabilities'.length);
|
|
59109
|
+
const label = endpoint.resourceVisual?.title || endpoint.resourceKey;
|
|
59110
|
+
const description = endpoint.resourceVisual?.description || endpoint.description || null;
|
|
59111
|
+
const path = value.startsWith('/api/') ? value.slice('/api'.length) : value;
|
|
59112
|
+
resources.set(value, {
|
|
59113
|
+
value,
|
|
59114
|
+
label,
|
|
59115
|
+
resourceKey: endpoint.resourceKey,
|
|
59116
|
+
path,
|
|
59117
|
+
group: catalog?.group || null,
|
|
59118
|
+
description,
|
|
59119
|
+
icon: endpoint.resourceVisual?.icon || null,
|
|
59120
|
+
tone: endpoint.resourceVisual?.tone || null,
|
|
59121
|
+
readOnly: typeof endpoint.resourceReadOnly === 'boolean' ? endpoint.resourceReadOnly : null,
|
|
59122
|
+
tags: endpoint.tags ?? [],
|
|
59123
|
+
searchTerms: [label, endpoint.resourceKey, value, path].filter(Boolean),
|
|
59124
|
+
capabilities: {
|
|
59125
|
+
collection: true,
|
|
59126
|
+
filter: true,
|
|
59127
|
+
stats: false,
|
|
59128
|
+
options: true,
|
|
59129
|
+
crud: true,
|
|
59130
|
+
},
|
|
59131
|
+
...(endpoint.resourceCapabilities ? { canonicalOperations: endpoint.resourceCapabilities } : {}),
|
|
59132
|
+
});
|
|
59133
|
+
}
|
|
59134
|
+
return [...resources.values()].sort((a, b) => a.label.localeCompare(b.label));
|
|
59135
|
+
}
|
|
59136
|
+
requestOptions() {
|
|
59137
|
+
const options = {};
|
|
59138
|
+
if (this.endpointKey !== undefined) {
|
|
59139
|
+
options.endpointKey = this.endpointKey;
|
|
59140
|
+
}
|
|
59141
|
+
if (this.apiUrlEntry !== undefined) {
|
|
59142
|
+
options.apiUrlEntry = this.apiUrlEntry;
|
|
59143
|
+
}
|
|
59144
|
+
return options;
|
|
59145
|
+
}
|
|
59146
|
+
optionalInject(token) {
|
|
59147
|
+
try {
|
|
59148
|
+
return inject(token, { optional: true });
|
|
59149
|
+
}
|
|
59150
|
+
catch {
|
|
59151
|
+
return null;
|
|
59152
|
+
}
|
|
59153
|
+
}
|
|
59154
|
+
updateValidity() {
|
|
59155
|
+
const trimmed = this.resourcePath?.trim() || '';
|
|
59156
|
+
this.isValid$.next(!!trimmed && this.isValidPath(trimmed));
|
|
59157
|
+
}
|
|
57017
59158
|
isValidPath(value) {
|
|
57018
59159
|
if (value.startsWith('http://') || value.startsWith('https://'))
|
|
57019
59160
|
return true;
|
|
57020
59161
|
return /^\/?[a-zA-Z0-9][a-zA-Z0-9/_-]*$/.test(value);
|
|
57021
59162
|
}
|
|
57022
59163
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ResourceQuickConnectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
57023
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: ResourceQuickConnectComponent, isStandalone: true, selector: "praxis-resource-quick-connect", inputs: { resourcePath: "resourcePath"
|
|
57024
|
-
|
|
57025
|
-
|
|
57026
|
-
|
|
59164
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: ResourceQuickConnectComponent, isStandalone: true, selector: "praxis-resource-quick-connect", inputs: { resourcePath: "resourcePath", endpointKey: "endpointKey", apiUrlEntry: "apiUrlEntry", intent: "intent", resources: "resources", label: "label", placeholder: "placeholder", hint: "hint", disabled: "disabled" }, outputs: { resourcePathChange: "resourcePathChange" }, providers: [
|
|
59165
|
+
providePraxisI18nConfig(RESOURCE_DISCOVERY_I18N_CONFIG),
|
|
59166
|
+
{
|
|
59167
|
+
provide: NG_VALUE_ACCESSOR,
|
|
59168
|
+
useExisting: forwardRef(() => ResourceQuickConnectComponent),
|
|
59169
|
+
multi: true,
|
|
59170
|
+
},
|
|
59171
|
+
], viewQueries: [{ propertyName: "selector", first: true, predicate: NgComponentOutlet, descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
59172
|
+
<div class="pdx-quick-connect" [class.is-disabled]="disabled">
|
|
59173
|
+
@if (catalogLoading) {
|
|
59174
|
+
<p class="pdx-quick-connect__status" role="status">{{ tx('loading') }}</p>
|
|
59175
|
+
}
|
|
59176
|
+
@if (catalogError) {
|
|
59177
|
+
<div class="pdx-quick-connect__error-row">
|
|
59178
|
+
<p class="pdx-quick-connect__status pdx-quick-connect__status--error" role="status">
|
|
59179
|
+
{{ tx('unavailable') }}
|
|
59180
|
+
</p>
|
|
59181
|
+
<button
|
|
59182
|
+
type="button"
|
|
59183
|
+
class="pdx-quick-connect__retry"
|
|
59184
|
+
[disabled]="disabled"
|
|
59185
|
+
(click)="loadCatalog()"
|
|
59186
|
+
>
|
|
59187
|
+
{{ tx('retry') }}
|
|
59188
|
+
</button>
|
|
59189
|
+
</div>
|
|
59190
|
+
}
|
|
57027
59191
|
@if (selectorType && selectorInputs) {
|
|
57028
59192
|
<ng-container *ngComponentOutlet="selectorType" />
|
|
57029
|
-
|
|
59193
|
+
} @else if (!selectorType && discoveredResources.length) {
|
|
59194
|
+
<div class="pdx-quick-connect__fallback" data-testid="quick-connect-rich-fallback">
|
|
59195
|
+
<mat-form-field appearance="outline" class="pdx-quick-connect__search-field" subscriptSizing="dynamic">
|
|
59196
|
+
<mat-label>{{ label || tx('resource') }}</mat-label>
|
|
59197
|
+
<mat-icon matPrefix [praxisIcon]="'search'"></mat-icon>
|
|
59198
|
+
<input
|
|
59199
|
+
matInput
|
|
59200
|
+
type="search"
|
|
59201
|
+
[disabled]="disabled"
|
|
59202
|
+
[placeholder]="tx('searchPlaceholder')"
|
|
59203
|
+
[(ngModel)]="fallbackSearchTerm"
|
|
59204
|
+
data-testid="quick-connect-search-input"
|
|
59205
|
+
/>
|
|
59206
|
+
</mat-form-field>
|
|
59207
|
+
<div class="pdx-quick-connect__option-list" role="listbox" [attr.aria-label]="label || tx('resource')">
|
|
59208
|
+
@for (option of filteredFallbackResources(); track option.value) {
|
|
59209
|
+
<button
|
|
59210
|
+
type="button"
|
|
59211
|
+
role="option"
|
|
59212
|
+
class="pdx-quick-connect__option-item"
|
|
59213
|
+
[class.is-selected]="isResourceSelected(option)"
|
|
59214
|
+
[attr.aria-selected]="isResourceSelected(option)"
|
|
59215
|
+
[disabled]="disabled"
|
|
59216
|
+
(click)="selectDiscoveredResource(option)"
|
|
59217
|
+
>
|
|
59218
|
+
<span class="pdx-quick-connect__option-icon" aria-hidden="true">
|
|
59219
|
+
<mat-icon [praxisIcon]="option.icon || 'api'"></mat-icon>
|
|
59220
|
+
</span>
|
|
59221
|
+
<span class="pdx-quick-connect__option-body">
|
|
59222
|
+
<span class="pdx-quick-connect__option-header">
|
|
59223
|
+
<span class="pdx-quick-connect__option-label">{{ option.label }}</span>
|
|
59224
|
+
@if (option.group) {
|
|
59225
|
+
<span class="pdx-quick-connect__option-badge">{{ option.group }}</span>
|
|
59226
|
+
}
|
|
59227
|
+
@if (option.readOnly) {
|
|
59228
|
+
<span class="pdx-quick-connect__option-badge pdx-quick-connect__option-badge--readonly">
|
|
59229
|
+
{{ tx('readOnly', 'Somente leitura') }}
|
|
59230
|
+
</span>
|
|
59231
|
+
}
|
|
59232
|
+
</span>
|
|
59233
|
+
<span class="pdx-quick-connect__option-code">{{ option.path || option.value }}</span>
|
|
59234
|
+
@if (option.description) {
|
|
59235
|
+
<span class="pdx-quick-connect__option-description">{{ option.description }}</span>
|
|
59236
|
+
}
|
|
59237
|
+
</span>
|
|
59238
|
+
@if (isResourceSelected(option)) {
|
|
59239
|
+
<mat-icon class="pdx-quick-connect__option-check" aria-hidden="true">check</mat-icon>
|
|
59240
|
+
}
|
|
59241
|
+
</button>
|
|
59242
|
+
} @empty {
|
|
59243
|
+
<p class="pdx-quick-connect__status" role="status">{{ tx('empty') }}</p>
|
|
59244
|
+
}
|
|
59245
|
+
</div>
|
|
59246
|
+
</div>
|
|
59247
|
+
}
|
|
59248
|
+
@if (!catalogLoading && !catalogError && !selectorInputs && !discoveredResources.length) {
|
|
59249
|
+
<p class="pdx-quick-connect__status" role="status">{{ tx('empty') }}</p>
|
|
57030
59250
|
}
|
|
57031
|
-
@if (
|
|
57032
|
-
|
|
59251
|
+
@if (selectedResource(); as selected) {
|
|
59252
|
+
<div class="pdx-quick-connect__selected-card" data-testid="quick-connect-selected-card">
|
|
59253
|
+
<span class="pdx-quick-connect__selected-icon" aria-hidden="true">
|
|
59254
|
+
<mat-icon [praxisIcon]="selected.icon || 'api'"></mat-icon>
|
|
59255
|
+
</span>
|
|
59256
|
+
<div class="pdx-quick-connect__selected-content">
|
|
59257
|
+
<div class="pdx-quick-connect__selected-header">
|
|
59258
|
+
<strong class="pdx-quick-connect__selected-title">{{ selected.label }}</strong>
|
|
59259
|
+
@if (selected.group) {
|
|
59260
|
+
<span class="pdx-quick-connect__option-badge">{{ selected.group }}</span>
|
|
59261
|
+
}
|
|
59262
|
+
@if (selected.readOnly) {
|
|
59263
|
+
<span class="pdx-quick-connect__option-badge pdx-quick-connect__option-badge--readonly">
|
|
59264
|
+
{{ tx('readOnly', 'Somente leitura') }}
|
|
59265
|
+
</span>
|
|
59266
|
+
}
|
|
59267
|
+
</div>
|
|
59268
|
+
<div class="pdx-quick-connect__selected-paths">
|
|
59269
|
+
<code class="pdx-quick-connect__selected-path">{{ selected.value }}</code>
|
|
59270
|
+
@if (selected.resourceKey && selected.resourceKey !== selected.value && selected.resourceKey !== selected.label) {
|
|
59271
|
+
<span class="pdx-quick-connect__selected-key">{{ selected.resourceKey }}</span>
|
|
59272
|
+
}
|
|
59273
|
+
</div>
|
|
59274
|
+
@if (selected.description) {
|
|
59275
|
+
<p class="pdx-quick-connect__selected-description">{{ selected.description }}</p>
|
|
59276
|
+
}
|
|
59277
|
+
</div>
|
|
59278
|
+
</div>
|
|
59279
|
+
}
|
|
59280
|
+
<small class="pdx-quick-connect__hint">{{ resolvedHint() }}</small>
|
|
59281
|
+
<details
|
|
59282
|
+
class="pdx-quick-connect__advanced"
|
|
59283
|
+
[open]="shouldOpenAdvanced()"
|
|
59284
|
+
(toggle)="onAdvancedToggle($event)"
|
|
59285
|
+
>
|
|
57033
59286
|
<summary>{{ tx('advanced') }}</summary>
|
|
57034
|
-
<mat-form-field appearance="outline">
|
|
59287
|
+
<mat-form-field appearance="outline" class="pdx-quick-connect__path-field">
|
|
57035
59288
|
<mat-label>{{ tx('path') }}</mat-label>
|
|
57036
|
-
<input
|
|
59289
|
+
<input
|
|
59290
|
+
matInput
|
|
59291
|
+
[disabled]="disabled"
|
|
59292
|
+
[placeholder]="placeholder || ''"
|
|
59293
|
+
[attr.list]="discoveredResources.length ? datalistId : null"
|
|
59294
|
+
[(ngModel)]="resourcePath"
|
|
59295
|
+
(ngModelChange)="onManualResourcePathChange($event)"
|
|
59296
|
+
(blur)="handleBlur()"
|
|
59297
|
+
/>
|
|
57037
59298
|
<mat-icon matSuffix [praxisIcon]="'link'"></mat-icon>
|
|
57038
|
-
@if (showInvalid()) {
|
|
59299
|
+
@if (showInvalid()) {
|
|
59300
|
+
<mat-error>{{ tx('invalid') }}</mat-error>
|
|
59301
|
+
}
|
|
57039
59302
|
</mat-form-field>
|
|
59303
|
+
@if (discoveredResources.length) {
|
|
59304
|
+
<datalist [id]="datalistId">
|
|
59305
|
+
@for (option of discoveredResources; track option.value) {
|
|
59306
|
+
<option [value]="option.value" [label]="option.label"></option>
|
|
59307
|
+
@if (option.path && option.path !== option.value) {
|
|
59308
|
+
<option [value]="option.path" [label]="option.label"></option>
|
|
59309
|
+
}
|
|
59310
|
+
}
|
|
59311
|
+
</datalist>
|
|
59312
|
+
}
|
|
57040
59313
|
</details>
|
|
57041
59314
|
</div>
|
|
57042
|
-
|
|
59315
|
+
`, isInline: true, styles: [".pdx-quick-connect{display:grid;gap:10px;padding:12px;border-radius:12px;border:1px solid var(--md-sys-color-outline-variant, rgba(148, 163, 184, .28));background:var(--md-sys-color-surface, transparent);color:var(--md-sys-color-on-surface, inherit)}.pdx-quick-connect.is-disabled{opacity:.68}.pdx-quick-connect__status{margin:0;font-size:.85rem;color:var(--md-sys-color-on-surface-variant, inherit)}.pdx-quick-connect__error-row{display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap}.pdx-quick-connect__retry{appearance:none;border:1px solid var(--md-sys-color-outline, rgba(148, 163, 184, .45));background:transparent;color:var(--md-sys-color-primary, inherit);border-radius:8px;padding:4px 10px;font-size:.8rem;font-weight:600;cursor:pointer}.pdx-quick-connect__fallback{display:grid;gap:8px}.pdx-quick-connect__search-field{width:100%}.pdx-quick-connect__option-list{display:flex;flex-direction:column;gap:4px;max-height:240px;overflow-y:auto;padding:4px;border-radius:10px;border:1px solid var(--md-sys-color-outline-variant, rgba(148, 163, 184, .24));background:var(--md-sys-color-surface-container-low, rgba(148, 163, 184, .04))}.pdx-quick-connect__option-item{display:flex;align-items:flex-start;gap:10px;width:100%;padding:8px 10px;border:1px solid transparent;border-radius:8px;background:transparent;color:inherit;font:inherit;text-align:start;cursor:pointer;transition:background .12s ease,border-color .12s ease}.pdx-quick-connect__option-item:hover:not(:disabled),.pdx-quick-connect__option-item.is-selected{background:color-mix(in srgb,var(--md-sys-color-primary, currentColor) 10%,transparent);border-color:color-mix(in srgb,var(--md-sys-color-primary, currentColor) 24%,transparent)}.pdx-quick-connect__option-icon,.pdx-quick-connect__selected-icon{width:28px;height:28px;border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-primary, currentColor) 12%,transparent);color:var(--md-sys-color-primary, inherit);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:1px}.pdx-quick-connect__option-icon mat-icon,.pdx-quick-connect__selected-icon mat-icon{width:16px;height:16px;font-size:16px}.pdx-quick-connect__option-body{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1 1 auto}.pdx-quick-connect__option-header,.pdx-quick-connect__selected-header{display:flex;align-items:center;gap:6px;flex-wrap:wrap;min-width:0}.pdx-quick-connect__option-label,.pdx-quick-connect__selected-title{font-size:.86rem;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pdx-quick-connect__option-badge{display:inline-flex;align-items:center;padding:1px 6px;border-radius:999px;font-size:.68rem;font-weight:600;background:color-mix(in srgb,currentColor 10%,transparent);color:color-mix(in srgb,currentColor 78%,transparent);white-space:nowrap}.pdx-quick-connect__option-code,.pdx-quick-connect__selected-path{font-family:var(--pdx-font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace);font-size:.72rem;color:var(--md-sys-color-primary, inherit);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pdx-quick-connect__option-description,.pdx-quick-connect__selected-description{margin:0;font-size:.75rem;line-height:1.3;color:var(--md-sys-color-on-surface-variant, inherit)}.pdx-quick-connect__option-check{width:18px;height:18px;font-size:18px;color:var(--md-sys-color-primary, inherit);flex-shrink:0}.pdx-quick-connect__selected-card{display:flex;align-items:flex-start;gap:10px;padding:8px 10px;border-radius:10px;background:color-mix(in srgb,var(--md-sys-color-primary, currentColor) 6%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-primary, currentColor) 18%,transparent)}.pdx-quick-connect__selected-content{display:grid;gap:2px;min-width:0;flex:1 1 auto}.pdx-quick-connect__selected-paths{display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-width:0}.pdx-quick-connect__selected-key{font-size:.7rem;color:var(--md-sys-color-on-surface-variant, inherit)}.pdx-quick-connect__hint{color:var(--md-sys-color-on-surface-variant, inherit);font-size:.82rem;line-height:1.35}.pdx-quick-connect__advanced{font-size:.85rem}.pdx-quick-connect__advanced>summary{cursor:pointer;-webkit-user-select:none;user-select:none;color:var(--md-sys-color-on-surface-variant, inherit);font-weight:500;margin-bottom:8px}.pdx-quick-connect__path-field{width:100%}\n"], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { 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: MatFormFieldModule }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i3.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i3.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.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: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
57043
59316
|
}
|
|
57044
59317
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ResourceQuickConnectComponent, decorators: [{
|
|
57045
59318
|
type: Component,
|
|
57046
|
-
args: [{ selector: 'praxis-resource-quick-connect', changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
57047
|
-
|
|
57048
|
-
|
|
57049
|
-
|
|
59319
|
+
args: [{ selector: 'praxis-resource-quick-connect', changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
59320
|
+
providePraxisI18nConfig(RESOURCE_DISCOVERY_I18N_CONFIG),
|
|
59321
|
+
{
|
|
59322
|
+
provide: NG_VALUE_ACCESSOR,
|
|
59323
|
+
useExisting: forwardRef(() => ResourceQuickConnectComponent),
|
|
59324
|
+
multi: true,
|
|
59325
|
+
},
|
|
59326
|
+
], imports: [
|
|
59327
|
+
NgComponentOutlet,
|
|
59328
|
+
FormsModule,
|
|
59329
|
+
MatFormFieldModule,
|
|
59330
|
+
MatInputModule,
|
|
59331
|
+
MatIconModule,
|
|
59332
|
+
PraxisIconDirective,
|
|
59333
|
+
], template: `
|
|
59334
|
+
<div class="pdx-quick-connect" [class.is-disabled]="disabled">
|
|
59335
|
+
@if (catalogLoading) {
|
|
59336
|
+
<p class="pdx-quick-connect__status" role="status">{{ tx('loading') }}</p>
|
|
59337
|
+
}
|
|
59338
|
+
@if (catalogError) {
|
|
59339
|
+
<div class="pdx-quick-connect__error-row">
|
|
59340
|
+
<p class="pdx-quick-connect__status pdx-quick-connect__status--error" role="status">
|
|
59341
|
+
{{ tx('unavailable') }}
|
|
59342
|
+
</p>
|
|
59343
|
+
<button
|
|
59344
|
+
type="button"
|
|
59345
|
+
class="pdx-quick-connect__retry"
|
|
59346
|
+
[disabled]="disabled"
|
|
59347
|
+
(click)="loadCatalog()"
|
|
59348
|
+
>
|
|
59349
|
+
{{ tx('retry') }}
|
|
59350
|
+
</button>
|
|
59351
|
+
</div>
|
|
59352
|
+
}
|
|
57050
59353
|
@if (selectorType && selectorInputs) {
|
|
57051
59354
|
<ng-container *ngComponentOutlet="selectorType" />
|
|
57052
|
-
|
|
59355
|
+
} @else if (!selectorType && discoveredResources.length) {
|
|
59356
|
+
<div class="pdx-quick-connect__fallback" data-testid="quick-connect-rich-fallback">
|
|
59357
|
+
<mat-form-field appearance="outline" class="pdx-quick-connect__search-field" subscriptSizing="dynamic">
|
|
59358
|
+
<mat-label>{{ label || tx('resource') }}</mat-label>
|
|
59359
|
+
<mat-icon matPrefix [praxisIcon]="'search'"></mat-icon>
|
|
59360
|
+
<input
|
|
59361
|
+
matInput
|
|
59362
|
+
type="search"
|
|
59363
|
+
[disabled]="disabled"
|
|
59364
|
+
[placeholder]="tx('searchPlaceholder')"
|
|
59365
|
+
[(ngModel)]="fallbackSearchTerm"
|
|
59366
|
+
data-testid="quick-connect-search-input"
|
|
59367
|
+
/>
|
|
59368
|
+
</mat-form-field>
|
|
59369
|
+
<div class="pdx-quick-connect__option-list" role="listbox" [attr.aria-label]="label || tx('resource')">
|
|
59370
|
+
@for (option of filteredFallbackResources(); track option.value) {
|
|
59371
|
+
<button
|
|
59372
|
+
type="button"
|
|
59373
|
+
role="option"
|
|
59374
|
+
class="pdx-quick-connect__option-item"
|
|
59375
|
+
[class.is-selected]="isResourceSelected(option)"
|
|
59376
|
+
[attr.aria-selected]="isResourceSelected(option)"
|
|
59377
|
+
[disabled]="disabled"
|
|
59378
|
+
(click)="selectDiscoveredResource(option)"
|
|
59379
|
+
>
|
|
59380
|
+
<span class="pdx-quick-connect__option-icon" aria-hidden="true">
|
|
59381
|
+
<mat-icon [praxisIcon]="option.icon || 'api'"></mat-icon>
|
|
59382
|
+
</span>
|
|
59383
|
+
<span class="pdx-quick-connect__option-body">
|
|
59384
|
+
<span class="pdx-quick-connect__option-header">
|
|
59385
|
+
<span class="pdx-quick-connect__option-label">{{ option.label }}</span>
|
|
59386
|
+
@if (option.group) {
|
|
59387
|
+
<span class="pdx-quick-connect__option-badge">{{ option.group }}</span>
|
|
59388
|
+
}
|
|
59389
|
+
@if (option.readOnly) {
|
|
59390
|
+
<span class="pdx-quick-connect__option-badge pdx-quick-connect__option-badge--readonly">
|
|
59391
|
+
{{ tx('readOnly', 'Somente leitura') }}
|
|
59392
|
+
</span>
|
|
59393
|
+
}
|
|
59394
|
+
</span>
|
|
59395
|
+
<span class="pdx-quick-connect__option-code">{{ option.path || option.value }}</span>
|
|
59396
|
+
@if (option.description) {
|
|
59397
|
+
<span class="pdx-quick-connect__option-description">{{ option.description }}</span>
|
|
59398
|
+
}
|
|
59399
|
+
</span>
|
|
59400
|
+
@if (isResourceSelected(option)) {
|
|
59401
|
+
<mat-icon class="pdx-quick-connect__option-check" aria-hidden="true">check</mat-icon>
|
|
59402
|
+
}
|
|
59403
|
+
</button>
|
|
59404
|
+
} @empty {
|
|
59405
|
+
<p class="pdx-quick-connect__status" role="status">{{ tx('empty') }}</p>
|
|
59406
|
+
}
|
|
59407
|
+
</div>
|
|
59408
|
+
</div>
|
|
59409
|
+
}
|
|
59410
|
+
@if (!catalogLoading && !catalogError && !selectorInputs && !discoveredResources.length) {
|
|
59411
|
+
<p class="pdx-quick-connect__status" role="status">{{ tx('empty') }}</p>
|
|
59412
|
+
}
|
|
59413
|
+
@if (selectedResource(); as selected) {
|
|
59414
|
+
<div class="pdx-quick-connect__selected-card" data-testid="quick-connect-selected-card">
|
|
59415
|
+
<span class="pdx-quick-connect__selected-icon" aria-hidden="true">
|
|
59416
|
+
<mat-icon [praxisIcon]="selected.icon || 'api'"></mat-icon>
|
|
59417
|
+
</span>
|
|
59418
|
+
<div class="pdx-quick-connect__selected-content">
|
|
59419
|
+
<div class="pdx-quick-connect__selected-header">
|
|
59420
|
+
<strong class="pdx-quick-connect__selected-title">{{ selected.label }}</strong>
|
|
59421
|
+
@if (selected.group) {
|
|
59422
|
+
<span class="pdx-quick-connect__option-badge">{{ selected.group }}</span>
|
|
59423
|
+
}
|
|
59424
|
+
@if (selected.readOnly) {
|
|
59425
|
+
<span class="pdx-quick-connect__option-badge pdx-quick-connect__option-badge--readonly">
|
|
59426
|
+
{{ tx('readOnly', 'Somente leitura') }}
|
|
59427
|
+
</span>
|
|
59428
|
+
}
|
|
59429
|
+
</div>
|
|
59430
|
+
<div class="pdx-quick-connect__selected-paths">
|
|
59431
|
+
<code class="pdx-quick-connect__selected-path">{{ selected.value }}</code>
|
|
59432
|
+
@if (selected.resourceKey && selected.resourceKey !== selected.value && selected.resourceKey !== selected.label) {
|
|
59433
|
+
<span class="pdx-quick-connect__selected-key">{{ selected.resourceKey }}</span>
|
|
59434
|
+
}
|
|
59435
|
+
</div>
|
|
59436
|
+
@if (selected.description) {
|
|
59437
|
+
<p class="pdx-quick-connect__selected-description">{{ selected.description }}</p>
|
|
59438
|
+
}
|
|
59439
|
+
</div>
|
|
59440
|
+
</div>
|
|
57053
59441
|
}
|
|
57054
|
-
|
|
57055
|
-
<details
|
|
59442
|
+
<small class="pdx-quick-connect__hint">{{ resolvedHint() }}</small>
|
|
59443
|
+
<details
|
|
59444
|
+
class="pdx-quick-connect__advanced"
|
|
59445
|
+
[open]="shouldOpenAdvanced()"
|
|
59446
|
+
(toggle)="onAdvancedToggle($event)"
|
|
59447
|
+
>
|
|
57056
59448
|
<summary>{{ tx('advanced') }}</summary>
|
|
57057
|
-
<mat-form-field appearance="outline">
|
|
59449
|
+
<mat-form-field appearance="outline" class="pdx-quick-connect__path-field">
|
|
57058
59450
|
<mat-label>{{ tx('path') }}</mat-label>
|
|
57059
|
-
<input
|
|
59451
|
+
<input
|
|
59452
|
+
matInput
|
|
59453
|
+
[disabled]="disabled"
|
|
59454
|
+
[placeholder]="placeholder || ''"
|
|
59455
|
+
[attr.list]="discoveredResources.length ? datalistId : null"
|
|
59456
|
+
[(ngModel)]="resourcePath"
|
|
59457
|
+
(ngModelChange)="onManualResourcePathChange($event)"
|
|
59458
|
+
(blur)="handleBlur()"
|
|
59459
|
+
/>
|
|
57060
59460
|
<mat-icon matSuffix [praxisIcon]="'link'"></mat-icon>
|
|
57061
|
-
@if (showInvalid()) {
|
|
59461
|
+
@if (showInvalid()) {
|
|
59462
|
+
<mat-error>{{ tx('invalid') }}</mat-error>
|
|
59463
|
+
}
|
|
57062
59464
|
</mat-form-field>
|
|
59465
|
+
@if (discoveredResources.length) {
|
|
59466
|
+
<datalist [id]="datalistId">
|
|
59467
|
+
@for (option of discoveredResources; track option.value) {
|
|
59468
|
+
<option [value]="option.value" [label]="option.label"></option>
|
|
59469
|
+
@if (option.path && option.path !== option.value) {
|
|
59470
|
+
<option [value]="option.path" [label]="option.label"></option>
|
|
59471
|
+
}
|
|
59472
|
+
}
|
|
59473
|
+
</datalist>
|
|
59474
|
+
}
|
|
57063
59475
|
</details>
|
|
57064
59476
|
</div>
|
|
57065
|
-
|
|
59477
|
+
`, styles: [".pdx-quick-connect{display:grid;gap:10px;padding:12px;border-radius:12px;border:1px solid var(--md-sys-color-outline-variant, rgba(148, 163, 184, .28));background:var(--md-sys-color-surface, transparent);color:var(--md-sys-color-on-surface, inherit)}.pdx-quick-connect.is-disabled{opacity:.68}.pdx-quick-connect__status{margin:0;font-size:.85rem;color:var(--md-sys-color-on-surface-variant, inherit)}.pdx-quick-connect__error-row{display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap}.pdx-quick-connect__retry{appearance:none;border:1px solid var(--md-sys-color-outline, rgba(148, 163, 184, .45));background:transparent;color:var(--md-sys-color-primary, inherit);border-radius:8px;padding:4px 10px;font-size:.8rem;font-weight:600;cursor:pointer}.pdx-quick-connect__fallback{display:grid;gap:8px}.pdx-quick-connect__search-field{width:100%}.pdx-quick-connect__option-list{display:flex;flex-direction:column;gap:4px;max-height:240px;overflow-y:auto;padding:4px;border-radius:10px;border:1px solid var(--md-sys-color-outline-variant, rgba(148, 163, 184, .24));background:var(--md-sys-color-surface-container-low, rgba(148, 163, 184, .04))}.pdx-quick-connect__option-item{display:flex;align-items:flex-start;gap:10px;width:100%;padding:8px 10px;border:1px solid transparent;border-radius:8px;background:transparent;color:inherit;font:inherit;text-align:start;cursor:pointer;transition:background .12s ease,border-color .12s ease}.pdx-quick-connect__option-item:hover:not(:disabled),.pdx-quick-connect__option-item.is-selected{background:color-mix(in srgb,var(--md-sys-color-primary, currentColor) 10%,transparent);border-color:color-mix(in srgb,var(--md-sys-color-primary, currentColor) 24%,transparent)}.pdx-quick-connect__option-icon,.pdx-quick-connect__selected-icon{width:28px;height:28px;border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-primary, currentColor) 12%,transparent);color:var(--md-sys-color-primary, inherit);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:1px}.pdx-quick-connect__option-icon mat-icon,.pdx-quick-connect__selected-icon mat-icon{width:16px;height:16px;font-size:16px}.pdx-quick-connect__option-body{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1 1 auto}.pdx-quick-connect__option-header,.pdx-quick-connect__selected-header{display:flex;align-items:center;gap:6px;flex-wrap:wrap;min-width:0}.pdx-quick-connect__option-label,.pdx-quick-connect__selected-title{font-size:.86rem;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pdx-quick-connect__option-badge{display:inline-flex;align-items:center;padding:1px 6px;border-radius:999px;font-size:.68rem;font-weight:600;background:color-mix(in srgb,currentColor 10%,transparent);color:color-mix(in srgb,currentColor 78%,transparent);white-space:nowrap}.pdx-quick-connect__option-code,.pdx-quick-connect__selected-path{font-family:var(--pdx-font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace);font-size:.72rem;color:var(--md-sys-color-primary, inherit);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pdx-quick-connect__option-description,.pdx-quick-connect__selected-description{margin:0;font-size:.75rem;line-height:1.3;color:var(--md-sys-color-on-surface-variant, inherit)}.pdx-quick-connect__option-check{width:18px;height:18px;font-size:18px;color:var(--md-sys-color-primary, inherit);flex-shrink:0}.pdx-quick-connect__selected-card{display:flex;align-items:flex-start;gap:10px;padding:8px 10px;border-radius:10px;background:color-mix(in srgb,var(--md-sys-color-primary, currentColor) 6%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-primary, currentColor) 18%,transparent)}.pdx-quick-connect__selected-content{display:grid;gap:2px;min-width:0;flex:1 1 auto}.pdx-quick-connect__selected-paths{display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-width:0}.pdx-quick-connect__selected-key{font-size:.7rem;color:var(--md-sys-color-on-surface-variant, inherit)}.pdx-quick-connect__hint{color:var(--md-sys-color-on-surface-variant, inherit);font-size:.82rem;line-height:1.35}.pdx-quick-connect__advanced{font-size:.85rem}.pdx-quick-connect__advanced>summary{cursor:pointer;-webkit-user-select:none;user-select:none;color:var(--md-sys-color-on-surface-variant, inherit);font-weight:500;margin-bottom:8px}.pdx-quick-connect__path-field{width:100%}\n"] }]
|
|
57066
59478
|
}], propDecorators: { resourcePath: [{
|
|
57067
59479
|
type: Input
|
|
59480
|
+
}], resourcePathChange: [{
|
|
59481
|
+
type: Output
|
|
59482
|
+
}], endpointKey: [{
|
|
59483
|
+
type: Input
|
|
59484
|
+
}], apiUrlEntry: [{
|
|
59485
|
+
type: Input
|
|
59486
|
+
}], intent: [{
|
|
59487
|
+
type: Input
|
|
59488
|
+
}], resources: [{
|
|
59489
|
+
type: Input
|
|
59490
|
+
}], label: [{
|
|
59491
|
+
type: Input
|
|
59492
|
+
}], placeholder: [{
|
|
59493
|
+
type: Input
|
|
59494
|
+
}], hint: [{
|
|
59495
|
+
type: Input
|
|
59496
|
+
}], disabled: [{
|
|
59497
|
+
type: Input
|
|
57068
59498
|
}], selector: [{
|
|
57069
59499
|
type: ViewChild,
|
|
57070
59500
|
args: [NgComponentOutlet]
|
|
@@ -59111,4 +61541,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
59111
61541
|
* Generated bundle index. Do not edit.
|
|
59112
61542
|
*/
|
|
59113
61543
|
|
|
59114
|
-
export { API_CONFIG_STORAGE_OPTIONS, API_URL, ASYNC_CONFIG_STORAGE, AllowedFileTypes, AnalyticsPresentationResolver, AnalyticsSchemaContractService, AnalyticsStatsRequestBuilderService, ApiConfigStorage, ApiEndpoint, BUILTIN_PAGE_LAYOUT_PRESETS, BUILTIN_PAGE_THEME_PRESETS, BUILTIN_SHELL_PRESETS, BUILTIN_WIDGET_SHELL_PRESETS, BulkOperationClientService, BulkSyncSession, BulkSyncStateService, COMPONENT_METADATA_REGISTRY_I18N_CONFIG, COMPONENT_METADATA_REGISTRY_I18N_NAMESPACE, CONFIG_STORAGE, CONNECTION_STORAGE, ComponentAuthoringManifestProjectionError, ComponentKeyService, ComponentMetadataRegistry, ComponentRuntimeProfileService, CompositionRuntimeFacade, CompositionValidatorService, ConsoleLoggerSink, CrudOperationResolutionService, DEFAULT_DYNAMIC_FORM_SCHEMA_CACHE_MAX_ENTRIES, DEFAULT_DYNAMIC_FORM_SCHEMA_CACHE_TTL_MS, DEFAULT_FIELD_SELECTOR_CONTROL_TYPE_MAP, DEFAULT_JSON_LOGIC_OPERATORS, DEFAULT_SCHEMA_REQUEST_TIMEOUT_MS, DEFAULT_TABLE_CONFIG, DOMAIN_CATALOG_COMPONENT_CONTEXT_PACK, DOMAIN_CATALOG_CONTEXT_HINT_SCHEMA_VERSION, DYNAMIC_PAGE_AI_CAPABILITIES, DYNAMIC_PAGE_COMPONENT_CONTEXT_PACK, DYNAMIC_PAGE_CONFIG_EDITOR, DYNAMIC_PAGE_SHELL_EDITOR, DefaultLoadingRenderer, DeferredAsyncConfigStorage, DomainCatalogService, DomainKnowledgeService, DomainRuleService, DynamicFormService, DynamicWidgetLoaderDirective, DynamicWidgetPageComponent, EDITORIAL_ALLOWED_CONTENT_FORMATS, EDITORIAL_COMPLIANCE_PRESETS, EDITORIAL_EXTERNAL_LINK_REL, EDITORIAL_FORM_TEMPLATE_CATALOG, EDITORIAL_HTML_ENABLED, EDITORIAL_MARKDOWN_IMAGES_ENABLED, EDITORIAL_SOLUTION_CATALOG, EDITORIAL_SOLUTION_PRESETS, EDITORIAL_THEME_PRESETS, EDITORIAL_WIDGET_CONVENTION_INPUTS, EDITORIAL_WIDGET_TAG, EFFECTIVE_UI_LAYOUT_COMPOSITION_SCHEMA_VERSION, EMPLOYEE_ONBOARDING_EDITORIAL_SOLUTION, EMPLOYEE_ONBOARDING_EDITORIAL_TEMPLATE, EMPLOYEE_ONBOARDING_GUIDED_EDITORIAL_SOLUTION, EMPLOYEE_ONBOARDING_GUIDED_EDITORIAL_TEMPLATE, EVENT_REGISTRATION_EDITORIAL_SOLUTION, EVENT_REGISTRATION_EDITORIAL_TEMPLATE, EffectiveUiLayoutContractError, EffectiveUiLayoutHttpError, EffectiveUiLayoutService, EmptyStateCardComponent, EnterpriseRuntimeContextObsoleteError, EnterpriseRuntimeContextService, ErrorMessageService, FIELD_METADATA_CAPABILITIES, FIELD_SELECTOR_REGISTRY_BASE, FIELD_SELECTOR_REGISTRY_DISABLE_DEFAULTS, FIELD_SELECTOR_REGISTRY_OVERRIDES, FORM_HOOKS, FORM_HOOKS_PRESETS, FORM_HOOKS_WHITELIST, FORM_HOOK_RESOLVERS, FieldControlType, FieldDataType, FieldSelectorRegistry, FormHooksRegistry, GLOBAL_ACTION_CATALOG, GLOBAL_ACTION_HANDLERS, GLOBAL_ACTION_UI_SCHEMAS, GLOBAL_ANALYTICS_SERVICE, GLOBAL_API_CLIENT, GLOBAL_CONFIG, GLOBAL_DIALOG_SERVICE, GLOBAL_ROUTE_GUARD_RESOLVER, GLOBAL_SURFACE_SERVICE, GLOBAL_TOAST_SERVICE, GOVERNED_COLOR_PALETTE_OPTIONS, GenericCrudService, GlobalActionService, GlobalConfigService, GovernedColorPaletteService, INLINE_FILTER_ALIAS_TOKENS, INLINE_FILTER_CONTROL_TYPES, INLINE_FILTER_CONTROL_TYPE_SET, INLINE_FILTER_CONTROL_TYPE_VALUES, INLINE_FILTER_TOKEN_TO_BASE_CONTROL_TYPE, INLINE_FILTER_TOKEN_TO_CONTROL_TYPE, IconPickerService, IconPosition, IconSize, LOGGER_LEVEL_BY_ENV, LOGGER_LEVEL_PRIORITY, LoadingOrchestrator, LocalConnectionStorage, LocalStorageAsyncAdapter, LocalStorageCacheAdapter, LocalStorageConfigService, LoggerService, LoggerThrottleTracker, LoggerWarnOnceTracker, MemoryCacheAdapter, NestedPortCatalogService, NestedWidgetConfigAccessor, NumericFormat, OVERLAY_DECIDER_DEBUG, OVERLAY_DECISION_MATRIX, ObservabilityDashboardService, OverlayDeciderService, PRAXIS_ACTION_CONTROL_DEFAULTS, PRAXIS_ACTION_CONTROL_VARS, PRAXIS_COLLECTION_EXPORT_HTTP_OPTIONS, PRAXIS_COLLECTION_EXPORT_PROVIDER, PRAXIS_COLLECTION_SEARCH_DEFAULTS, PRAXIS_COLLECTION_SEARCH_VARS, PRAXIS_CORPORATE_SENSITIVE_KEYS, PRAXIS_DEFAULT_EXPORT_SECURITY_POLICY, PRAXIS_DEFAULT_OBSERVABILITY_ALERT_RULES, PRAXIS_DYNAMIC_PAGE_COMPONENT_METADATA, PRAXIS_EFFECTIVE_UI_LAYOUT_OPTIONS, PRAXIS_ENTERPRISE_RUNTIME_CONTEXT_OPTIONS, PRAXIS_ENTERPRISE_RUNTIME_CONTEXT_READY, PRAXIS_EXPORT_FORMULA_PREFIXES, PRAXIS_EXPORT_SECURITY_POLICY, PRAXIS_FOOTER_LINKS_METADATA, PRAXIS_GLOBAL_ACTION_CATALOG, PRAXIS_GLOBAL_CONFIG_BOOTSTRAP_OPTIONS, PRAXIS_GLOBAL_CONFIG_BOOTSTRAP_READY, PRAXIS_GLOBAL_CONFIG_TENANT_RESOLVER, PRAXIS_HERO_BANNER_METADATA, PRAXIS_I18N_CONFIG, PRAXIS_I18N_TRANSLATOR, PRAXIS_JSON_LOGIC_OPERATORS, PRAXIS_LAYER_SCALE_DEFAULTS, PRAXIS_LAYER_SCALE_VARS, PRAXIS_LEGAL_NOTICE_METADATA, PRAXIS_LOADING_CTX, PRAXIS_LOADING_RENDERER, PRAXIS_LOGGER_CONFIG, PRAXIS_LOGGER_SINKS, PRAXIS_OBSERVABILITY_DASHBOARD_OPTIONS, PRAXIS_QUERY_FILTER_EXPRESSION_SCHEMA_VERSION, PRAXIS_RELATED_RESOURCE_OUTLET_AUTHORING_MANIFEST, PRAXIS_RELATED_RESOURCE_OUTLET_COMPONENT_METADATA, PRAXIS_RELATED_RESOURCE_OUTLET_PORTS, PRAXIS_RICH_TEXT_BLOCK_METADATA, PRAXIS_TABLE_DETAIL_INLINE_NODE_RESOLVERS, PRAXIS_TABLE_DETAIL_INLINE_RENDERERS, PRAXIS_TABLE_DETAIL_RESOURCE_RESOLVER, PRAXIS_TELEMETRY_TRANSPORT, PRAXIS_THEME_SURFACE_DEFAULTS, PRAXIS_THEME_SURFACE_VARS, PRAXIS_USER_CONTEXT_SUMMARY_METADATA, PRIVACY_CONSENT_EDITORIAL_SOLUTION, PRIVACY_CONSENT_EDITORIAL_TEMPLATE, PraxisAppShellComponent, PraxisBulkClientService, PraxisCollectionExportService, PraxisCore, PraxisCustomizationModeService, PraxisFooterLinksComponent, PraxisGlobalErrorHandler, PraxisHeroBannerComponent, PraxisHttpCollectionExportProvider, PraxisI18nService, PraxisIconButtonComponent, PraxisIconDirective, PraxisIconPickerComponent, PraxisJsonLogicError, PraxisJsonLogicService, PraxisKeepAliveTabDirective, PraxisLayerScaleStyleService, PraxisLegalNoticeComponent, PraxisLoadingInterceptor, PraxisRelatedResourceOutletComponent, PraxisRelatedResourceOutletConfigEditorComponent, PraxisResourceIdentityComponent, PraxisRichTextBlockComponent, PraxisRuntimeComponentObservationRegistryService, PraxisSurfaceHostComponent, PraxisUserContextSummaryComponent, PraxisWidgetEventBus, RESOURCE_DISCOVERY_I18N_CONFIG, RESOURCE_DISCOVERY_I18N_NAMESPACE, RULE_PROPERTY_SCHEMA, RelatedResourceSurfaceResolverService, RemoteConfigStorage, ResourceActionOpenAdapterService, ResourceDiscoveryService, ResourceQuickConnectComponent, ResourceRecordOpenError, ResourceRecordOpenService, ResourceSurfaceOpenAdapterService, SCHEMA_METADATA_CLIENT_OPTIONS, SCHEMA_VIEWER_CONTEXT, SETTINGS_EDITOR_SECTIONS_HOSTED, SETTINGS_PANEL_BRIDGE, SETTINGS_PANEL_DATA, STEPPER_CONFIG_EDITOR, SURFACE_DRAWER_BRIDGE, SURFACE_DRAWER_CONTENT_DATA, SURFACE_DRAWER_REF, SURFACE_NAVIGATION_I18N_CONFIG, SURFACE_NAVIGATION_I18N_NAMESPACE, SURFACE_OPEN_I18N_CONFIG, SURFACE_OPEN_I18N_NAMESPACE, SURFACE_OPEN_PRESETS, SafeExpressionEvaluator, SchemaMetadataClient, SchemaNormalizerService, SchemaViewerComponent, SettingsSectionTabsComponent, SurfaceBindingRuntimeService, SurfaceNavigationError, SurfaceOpenActionEditorComponent, SurfaceOpenMaterializerService, SurfaceOutletRegistryService, TABLE_CONFIG_EDITOR, TableConfigService, TelemetryLoggerSink, TelemetryService, UiLayoutLifecycleContractError, UiLayoutLifecycleHttpError, UiLayoutLifecycleService, ValidationPattern, WidgetPageCompositionFactory, WidgetPageDataSourceRuntimeService, WidgetPageStateRuntimeService, WidgetShellComponent, applyLocalCustomizations$2 as applyLocalCustomizations, applyLocalCustomizations$1 as applyLocalFormCustomizations, assertPraxisCollectionExportArtifact, assertPraxisRuntimeComponentObservationSerializable, buildAngularValidators, buildApiUrl, buildBaseColumnFromDef, buildBaseFormField, buildFormConfigFromEditorialTemplate, buildHeaders, buildPageKey, buildPraxisActionControlCss, buildPraxisCollectionSearchCss, buildPraxisEffectDistinctKey, buildPraxisLayerScaleCss, buildPraxisThemeSurfaceCss, buildSchemaId, buildSchemaIdStorageKeySegment, buildValidatorsFromValidatorOptions, cancelIfCpfInvalidHook, canonicalJsonSha256, canonicalJsonStringify, clampRange, classifyEntityLookupResult, clonePraxisRuntimeComponentObservation, cloneTableConfig, cloneUiLayoutJsonDocument, cnpjAlphaValidator, collapseWhitespace, composeHeadersWithVersion, conditionalAsyncValidator, convertFormLayoutToConfig, createCorporateLoggerConfig, createCorporateObservabilityOptions, createCpfCnpjValidator, createDefaultFormConfig, createDefaultTableConfig, createDynamicRecord, createEmptyFormConfig, createEmptyRichContentDocument, createFieldLayoutItem, createPersistedPage, customAsyncValidatorFn, customValidatorFn, debounceAsyncValidator, deepMerge, domainKnowledgeTimelineToRichContentDocument, domainRuleTimelineToRichContentDocument, ensureIds, ensureNoConflictsHookFactory, ensurePageIds, escapePraxisExportCell, evaluateFieldAccess, extractNormalizedError, extractRecordId, fetchWithETag, fileTypeValidator, fillUndefined, findBuiltinWidgetShellPreset, formIdentityIssues, generateBulkIdempotencyKey, generateId, getDefaultFormHints, getEditorialCompliancePresetById, getEditorialFormTemplateById, getEditorialFormTemplateCatalog, getEditorialSolutionById, getEditorialSolutionCatalog, getEditorialSolutionPresetById, getEditorialThemePresetById, getEssentialConfig, getFieldMetadataCapabilities, getFormColumnFieldNames, getFormLayoutFieldNames, getGlobalActionCatalog, getGlobalActionPayloadActualType, getGlobalActionPayloadTypeIssue, getGlobalActionProviderEvidence, getGlobalActionUiSchema, getMissingGlobalActionPayloadKeys, getPraxisTableCellVisualizationConstraint, getPraxisTableCellVisualizationGuidance, getReferencedFieldMetadata, getRequiredGlobalActionPayloadKeys, getTextTransformer, getWidgetShellActionIdError, hasMeaningfulGlobalActionPayloadValue, hasPraxisCollectionExportArtifact, interpolatePraxisTranslation, isAllowedEditorialContentFormat, isAllowedEditorialHref, isBulkExecutionTerminal, isCssTextTransform, isDomainRuleSnapshotProblemResponse, isDynamicDataRecord, isEditorialComponentMeta, isEntityLookupMultiplePayloadMode, isEntityLookupPayloadMode, isEntityLookupPayloadModeCompatible, isEntityLookupResultSelectable, isEntityLookupSinglePayloadMode, isFormLayoutItem, isGlobalActionProviderOperational, isGlobalActionRef, isInlineFilterControlType, isLookupDialogSize, isLookupFilterFieldType, isLookupFilterOperator, isPraxisI18nMessageDescriptor, isPraxisPresentationVisualizationTableSafe, isPraxisRuntimeGlobalActionEffect, isProgrammaticDateRangePreset, isRangeValidForFilter, isRequiredGlobalActionParamPayloadMissing, isRequiredGlobalActionPayloadMissing, isStaticDateRangePreset, isSurfaceNavigationError, isTableConfigV2, isValidFormConfig, isValidTableConfig, legacyCnpjValidator, legacyCpfValidator, logOnErrorHook, mapFieldDefinitionToMetadata, mapFieldDefinitionsToMetadata, markGlobalActionProviderOperational, matchFieldValidator, materializeFormLayoutFromMetadata, materializeGovernedPaletteColors, materializeGovernedPaletteEntries, materializeResourceIdentity, maxFileSizeValidator, mergeFieldMetadata, mergePraxisI18nConfigs, mergeTableConfigs, migrateFormLayoutRule, migrateLegacyCompositionLink, migrateLegacyCompositionLinks, minWordsValidator, nestedPortPathIdentity, normalizeCardMediaAspectRatio, normalizeControlTypeKey, normalizeControlTypeToken, normalizeEditorialLink, normalizeEnd, normalizeFieldAccessMetadata, normalizeFieldConstraints, normalizeFieldPresentation, normalizeFormConfig, normalizeFormLayoutItems, normalizeFormMetadata, normalizeGlobalActionRef$1 as normalizeGlobalActionRef, normalizeLayoutPolicy, normalizeLookupFilterRequest, normalizePath, normalizePraxisDataQueryContext, normalizePraxisEffectPolicy, normalizePraxisPresentationVisualization, normalizePraxisQueryFilterExpression, normalizePraxisQueryFilterNode, normalizeReactiveDeterminations, normalizeResourceAvailabilityReasonCode, normalizeResourceIdentityContract, normalizeStart, normalizeSurfaceOperationContext, normalizeUnknownError, normalizeWidgetEventPath, notifySuccessHook, parseJsonResponseOrEmpty, praxisLoadingInterceptorFn, prefillFromContextHook, prepareCanvasArrangement, projectComponentAuthoringManifest, projectGroupedCommandPartialRows, provideDefaultFormHooks, provideFieldSelectorRegistryBase, provideFieldSelectorRegistryOverride, provideFieldSelectorRegistryRuntime, provideFormHookPresets, provideFormHooks, provideGlobalActionCatalog, provideGlobalActionHandler, provideGlobalConfig, provideGlobalConfigReady, provideGlobalConfigSeed, provideGlobalConfigTenant, provideHookResolvers, provideHookWhitelist, provideOverlayDecisionMatrix, providePraxisAnalyticsGlobalActions, providePraxisCollectionExportProvider, providePraxisDynamicPageMetadata, providePraxisEnterpriseRuntimeContext, providePraxisFooterLinksMetadata, providePraxisGlobalActionCatalog, providePraxisGlobalActions, providePraxisGlobalConfigBootstrap, providePraxisHeroBannerMetadata, providePraxisHttpCollectionExportProvider, providePraxisHttpLoading, providePraxisI18n, providePraxisI18nConfig, providePraxisI18nTranslator, providePraxisIconDefaults, providePraxisJsonLogicOperator, providePraxisJsonLogicOperatorOverride, providePraxisLegalNoticeMetadata, providePraxisLoadingDefaults, providePraxisLogging, providePraxisRelatedResourceOutletMetadata, providePraxisRichTextBlockMetadata, providePraxisTelemetry, providePraxisToastGlobalActions, providePraxisUserContextSummaryMetadata, provideRemoteGlobalConfig, readPraxisExportValue, readStrongResourceEtag, reconcileFilterConfig, reconcileFormConfig, reconcileTableConfig, registerPraxisRuntimeComponentObservation, removeDiacritics, renderPraxisPresentationVisualizationHtml, reportTelemetryHookFactory, requiredCheckedValidator, requiredPresenceValidator, resolveBuiltinPresets, resolveBuiltinWidgetShellAppearance, resolveColumnTypeFromFieldDefinition, resolveControlTypeAlias, resolveDataField, resolveDateRangeShortcutPreset, resolveDateRangeShortcutPresets, resolveDefaultValuePresentationFormat, resolveEntityLookupPayloadMode, resolveFieldPresentation, resolveGroupedCommandPartialRowSpans, resolveHidden, resolveInlineFilterControlType, resolveInlineFilterControlTypeToBaseControlType, resolveLoggerConfig, resolveObservabilityOptions, resolveOffset, resolveOrder, resolvePraxisCollectionExportItems, resolvePraxisExportFields, resolvePraxisExportScope, resolvePraxisFilterCriteria, resolvePraxisI18nDocument, resolvePraxisMicroVisualizationTone, resolveResourceAvailabilityReasonKey, resolveResourceIdentityContract, resolveSpan, resolveTextMaskFormat, resolveTextMaskFormatFromFieldDefinition, resolveValuePresentation, resolveValuePresentationLocale, resolveWidgetPageLayoutPreset, serializeEntityLookupValueForPayload, serializeOptionSourceFilterRequest, serializePraxisCollectionToCsv, serializePraxisCollectionToExcel, serializePraxisCollectionToJson, slugify, staticDateRangePresetToPreset, stripMasksHook, supportsConfigDocuments, supportsImplicitValuePresentation, syncWithServerMetadata, textSha256, toCamel, toCapitalize, toKebab, toPascal, toSentenceCase, toSnake, toTitleCase, translateResourceAvailabilityReason, translateResourceDiscoveryText, translateSurfaceNavigationRejected, translateSurfaceOpenFailed, translateUnavailableWorkflowMessage, trim, uiLayoutJsonIdentity, uniqueAsyncValidator, urlValidator, validateCanvasArrangement, validateGlobalActionRef, validateGlobalActionRefs, withFormConfigSections, withMessage, withPraxisHttpLoading };
|
|
61544
|
+
export { API_CONFIG_STORAGE_OPTIONS, API_URL, ASYNC_CONFIG_STORAGE, AllowedFileTypes, AnalyticsPresentationResolver, AnalyticsSchemaContractService, AnalyticsStatsRequestBuilderService, ApiConfigStorage, ApiEndpoint, BUILTIN_PAGE_LAYOUT_PRESETS, BUILTIN_PAGE_THEME_PRESETS, BUILTIN_SHELL_PRESETS, BUILTIN_WIDGET_SHELL_PRESETS, BulkOperationClientService, BulkSyncSession, BulkSyncStateService, COMPONENT_METADATA_REGISTRY_I18N_CONFIG, COMPONENT_METADATA_REGISTRY_I18N_NAMESPACE, CONFIG_STORAGE, CONNECTION_STORAGE, ComponentAuthoringManifestProjectionError, ComponentKeyService, ComponentMetadataRegistry, ComponentRuntimeProfileService, CompositionRuntimeFacade, CompositionValidatorService, ConsoleLoggerSink, CrudOperationResolutionService, DEFAULT_DYNAMIC_FORM_SCHEMA_CACHE_MAX_ENTRIES, DEFAULT_DYNAMIC_FORM_SCHEMA_CACHE_TTL_MS, DEFAULT_FIELD_SELECTOR_CONTROL_TYPE_MAP, DEFAULT_JSON_LOGIC_OPERATORS, DEFAULT_SCHEMA_REQUEST_TIMEOUT_MS, DEFAULT_TABLE_CONFIG, DOMAIN_CATALOG_COMPONENT_CONTEXT_PACK, DOMAIN_CATALOG_CONTEXT_HINT_SCHEMA_VERSION, DYNAMIC_PAGE_AI_CAPABILITIES, DYNAMIC_PAGE_COMPONENT_CONTEXT_PACK, DYNAMIC_PAGE_CONFIG_EDITOR, DYNAMIC_PAGE_SHELL_EDITOR, DefaultLoadingRenderer, DeferredAsyncConfigStorage, DomainCatalogService, DomainKnowledgeService, DomainRuleService, DynamicFormService, DynamicWidgetLoaderDirective, DynamicWidgetPageComponent, EDITORIAL_ALLOWED_CONTENT_FORMATS, EDITORIAL_COMPLIANCE_PRESETS, EDITORIAL_EXTERNAL_LINK_REL, EDITORIAL_FORM_TEMPLATE_CATALOG, EDITORIAL_HTML_ENABLED, EDITORIAL_MARKDOWN_IMAGES_ENABLED, EDITORIAL_SOLUTION_CATALOG, EDITORIAL_SOLUTION_PRESETS, EDITORIAL_THEME_PRESETS, EDITORIAL_WIDGET_CONVENTION_INPUTS, EDITORIAL_WIDGET_TAG, EFFECTIVE_UI_LAYOUT_COMPOSITION_SCHEMA_VERSION, EMPLOYEE_ONBOARDING_EDITORIAL_SOLUTION, EMPLOYEE_ONBOARDING_EDITORIAL_TEMPLATE, EMPLOYEE_ONBOARDING_GUIDED_EDITORIAL_SOLUTION, EMPLOYEE_ONBOARDING_GUIDED_EDITORIAL_TEMPLATE, EVENT_REGISTRATION_EDITORIAL_SOLUTION, EVENT_REGISTRATION_EDITORIAL_TEMPLATE, EffectiveUiLayoutContractError, EffectiveUiLayoutHttpError, EffectiveUiLayoutService, EmptyStateCardComponent, EnterpriseRuntimeContextObsoleteError, EnterpriseRuntimeContextService, ErrorMessageService, FIELD_METADATA_CAPABILITIES, FIELD_SELECTOR_REGISTRY_BASE, FIELD_SELECTOR_REGISTRY_DISABLE_DEFAULTS, FIELD_SELECTOR_REGISTRY_OVERRIDES, FORM_HOOKS, FORM_HOOKS_PRESETS, FORM_HOOKS_WHITELIST, FORM_HOOK_RESOLVERS, FieldControlType, FieldDataType, FieldSelectorRegistry, FormHooksRegistry, GLOBAL_ACTION_CATALOG, GLOBAL_ACTION_HANDLERS, GLOBAL_ACTION_UI_SCHEMAS, GLOBAL_ANALYTICS_SERVICE, GLOBAL_API_CLIENT, GLOBAL_CONFIG, GLOBAL_DIALOG_SERVICE, GLOBAL_ROUTE_GUARD_RESOLVER, GLOBAL_SURFACE_SERVICE, GLOBAL_TOAST_SERVICE, GOVERNED_COLOR_PALETTE_OPTIONS, GenericCrudService, GlobalActionService, GlobalConfigService, GovernedColorPaletteService, INLINE_FILTER_ALIAS_TOKENS, INLINE_FILTER_CONTROL_TYPES, INLINE_FILTER_CONTROL_TYPE_SET, INLINE_FILTER_CONTROL_TYPE_VALUES, INLINE_FILTER_TOKEN_TO_BASE_CONTROL_TYPE, INLINE_FILTER_TOKEN_TO_CONTROL_TYPE, IconPickerService, IconPosition, IconSize, LOGGER_LEVEL_BY_ENV, LOGGER_LEVEL_PRIORITY, LoadingOrchestrator, LocalConnectionStorage, LocalStorageAsyncAdapter, LocalStorageCacheAdapter, LocalStorageConfigService, LoggerService, LoggerThrottleTracker, LoggerWarnOnceTracker, MemoryCacheAdapter, NestedPortCatalogService, NestedWidgetConfigAccessor, NumericFormat, OVERLAY_DECIDER_DEBUG, OVERLAY_DECISION_MATRIX, ObservabilityDashboardService, OverlayDeciderService, PRAXIS_ACTION_CONTROL_DEFAULTS, PRAXIS_ACTION_CONTROL_VARS, PRAXIS_COLLECTION_EXPORT_HTTP_OPTIONS, PRAXIS_COLLECTION_EXPORT_PROVIDER, PRAXIS_COLLECTION_SEARCH_DEFAULTS, PRAXIS_COLLECTION_SEARCH_VARS, PRAXIS_CORPORATE_SENSITIVE_KEYS, PRAXIS_DEFAULT_EXPORT_SECURITY_POLICY, PRAXIS_DEFAULT_OBSERVABILITY_ALERT_RULES, PRAXIS_DYNAMIC_PAGE_COMPONENT_METADATA, PRAXIS_EFFECTIVE_UI_LAYOUT_OPTIONS, PRAXIS_ENTERPRISE_RUNTIME_CONTEXT_OPTIONS, PRAXIS_ENTERPRISE_RUNTIME_CONTEXT_READY, PRAXIS_EXPORT_FORMULA_PREFIXES, PRAXIS_EXPORT_SECURITY_POLICY, PRAXIS_FOOTER_LINKS_METADATA, PRAXIS_GLOBAL_ACTION_CATALOG, PRAXIS_GLOBAL_CONFIG_BOOTSTRAP_OPTIONS, PRAXIS_GLOBAL_CONFIG_BOOTSTRAP_READY, PRAXIS_GLOBAL_CONFIG_TENANT_RESOLVER, PRAXIS_HERO_BANNER_METADATA, PRAXIS_I18N_CONFIG, PRAXIS_I18N_TRANSLATOR, PRAXIS_JSON_LOGIC_OPERATORS, PRAXIS_LAYER_SCALE_DEFAULTS, PRAXIS_LAYER_SCALE_VARS, PRAXIS_LEGAL_NOTICE_METADATA, PRAXIS_LOADING_CTX, PRAXIS_LOADING_RENDERER, PRAXIS_LOGGER_CONFIG, PRAXIS_LOGGER_SINKS, PRAXIS_OBSERVABILITY_DASHBOARD_OPTIONS, PRAXIS_QUERY_FILTER_EXPRESSION_SCHEMA_VERSION, PRAXIS_RELATED_RESOURCE_OUTLET_AUTHORING_MANIFEST, PRAXIS_RELATED_RESOURCE_OUTLET_COMPONENT_METADATA, PRAXIS_RELATED_RESOURCE_OUTLET_PORTS, PRAXIS_RICH_TEXT_BLOCK_METADATA, PRAXIS_TABLE_DETAIL_INLINE_NODE_RESOLVERS, PRAXIS_TABLE_DETAIL_INLINE_RENDERERS, PRAXIS_TABLE_DETAIL_RESOURCE_RESOLVER, PRAXIS_TELEMETRY_TRANSPORT, PRAXIS_THEME_SURFACE_DEFAULTS, PRAXIS_THEME_SURFACE_VARS, PRAXIS_USER_CONTEXT_SUMMARY_METADATA, PRIVACY_CONSENT_EDITORIAL_SOLUTION, PRIVACY_CONSENT_EDITORIAL_TEMPLATE, PraxisAppShellComponent, PraxisBulkClientService, PraxisCollectionExportService, PraxisCore, PraxisCustomizationModeService, PraxisFooterLinksComponent, PraxisGlobalErrorHandler, PraxisHeroBannerComponent, PraxisHttpCollectionExportProvider, PraxisI18nService, PraxisIconButtonComponent, PraxisIconDirective, PraxisIconPickerComponent, PraxisJsonLogicError, PraxisJsonLogicService, PraxisKeepAliveTabDirective, PraxisLayerScaleStyleService, PraxisLegalNoticeComponent, PraxisLoadingInterceptor, PraxisRelatedResourceOutletComponent, PraxisRelatedResourceOutletConfigEditorComponent, PraxisResourceIdentityComponent, PraxisRichTextBlockComponent, PraxisRuntimeComponentObservationRegistryService, PraxisSurfaceHostComponent, PraxisUserContextSummaryComponent, PraxisWidgetEventBus, RESOURCE_DISCOVERY_I18N_CONFIG, RESOURCE_DISCOVERY_I18N_NAMESPACE, RULE_PROPERTY_SCHEMA, RelatedResourceSurfaceResolverService, RemoteConfigStorage, ResourceActionOpenAdapterService, ResourceDiscoveryService, ResourceQuickConnectComponent, ResourceRecordOpenError, ResourceRecordOpenService, ResourceSurfaceOpenAdapterService, SCHEMA_METADATA_CLIENT_OPTIONS, SCHEMA_VIEWER_CONTEXT, SETTINGS_EDITOR_SECTIONS_HOSTED, SETTINGS_PANEL_BRIDGE, SETTINGS_PANEL_DATA, STEPPER_CONFIG_EDITOR, SURFACE_DRAWER_BRIDGE, SURFACE_DRAWER_CONTENT_DATA, SURFACE_DRAWER_REF, SURFACE_NAVIGATION_I18N_CONFIG, SURFACE_NAVIGATION_I18N_NAMESPACE, SURFACE_OPEN_I18N_CONFIG, SURFACE_OPEN_I18N_NAMESPACE, SURFACE_OPEN_PRESETS, SafeExpressionEvaluator, SchemaMetadataClient, SchemaNormalizerService, SchemaViewerComponent, SettingsSectionTabsComponent, SurfaceBindingRuntimeService, SurfaceNavigationError, SurfaceOpenActionEditorComponent, SurfaceOpenMaterializerService, SurfaceOutletRegistryService, TABLE_CONFIG_EDITOR, TableConfigService, TelemetryLoggerSink, TelemetryService, UiLayoutLifecycleContractError, UiLayoutLifecycleHttpError, UiLayoutLifecycleService, ValidationPattern, WidgetPageCompositionFactory, WidgetPageDataSourceRuntimeService, WidgetPageStateRuntimeService, WidgetShellComponent, applyDeclarativeValuePipe, applyLocalCustomizations$2 as applyLocalCustomizations, applyLocalCustomizations$1 as applyLocalFormCustomizations, assertPraxisCollectionExportArtifact, assertPraxisRuntimeComponentObservationSerializable, buildAngularValidators, buildApiUrl, buildBaseColumnFromDef, buildBaseFormField, buildFormConfigFromEditorialTemplate, buildHeaders, buildPageKey, buildPraxisActionControlCss, buildPraxisCollectionSearchCss, buildPraxisEffectDistinctKey, buildPraxisLayerScaleCss, buildPraxisThemeSurfaceCss, buildSchemaId, buildSchemaIdStorageKeySegment, buildValidatorsFromValidatorOptions, cancelIfCpfInvalidHook, canonicalJsonSha256, canonicalJsonStringify, clampRange, classifyEntityLookupResult, clonePraxisRuntimeComponentObservation, cloneTableConfig, cloneUiLayoutJsonDocument, cnpjAlphaValidator, collapseWhitespace, composeHeadersWithVersion, conditionalAsyncValidator, convertFormLayoutToConfig, createCorporateLoggerConfig, createCorporateObservabilityOptions, createCpfCnpjValidator, createDefaultFormConfig, createDefaultTableConfig, createDynamicRecord, createEmptyFormConfig, createEmptyRichContentDocument, createFieldLayoutItem, createPersistedPage, customAsyncValidatorFn, customValidatorFn, debounceAsyncValidator, deepMerge, domainKnowledgeTimelineToRichContentDocument, domainRuleTimelineToRichContentDocument, ensureIds, ensureNoConflictsHookFactory, ensurePageIds, escapePraxisExportCell, evaluateFieldAccess, extractNormalizedError, extractRecordId, fetchWithETag, fileTypeValidator, fillUndefined, findBuiltinWidgetShellPreset, formIdentityIssues, generateBulkIdempotencyKey, generateId, getDefaultFormHints, getEditorialCompliancePresetById, getEditorialFormTemplateById, getEditorialFormTemplateCatalog, getEditorialSolutionById, getEditorialSolutionCatalog, getEditorialSolutionPresetById, getEditorialThemePresetById, getEssentialConfig, getFieldMetadataCapabilities, getFormColumnFieldNames, getFormLayoutFieldNames, getGlobalActionCatalog, getGlobalActionPayloadActualType, getGlobalActionPayloadTypeIssue, getGlobalActionProviderEvidence, getGlobalActionUiSchema, getMissingGlobalActionPayloadKeys, getPraxisTableCellVisualizationConstraint, getPraxisTableCellVisualizationGuidance, getReferencedFieldMetadata, getRequiredGlobalActionPayloadKeys, getTextTransformer, getWidgetShellActionIdError, hasMeaningfulGlobalActionPayloadValue, hasPraxisCollectionExportArtifact, interpolatePraxisTranslation, isAllowedEditorialContentFormat, isAllowedEditorialHref, isBulkExecutionTerminal, isCssTextTransform, isDomainRuleSnapshotProblemResponse, isDynamicDataRecord, isEditorialComponentMeta, isEntityLookupMultiplePayloadMode, isEntityLookupPayloadMode, isEntityLookupPayloadModeCompatible, isEntityLookupResultSelectable, isEntityLookupSinglePayloadMode, isFormLayoutItem, isGlobalActionProviderOperational, isGlobalActionRef, isInlineFilterControlType, isLookupDialogSize, isLookupFilterFieldType, isLookupFilterOperator, isPraxisI18nMessageDescriptor, isPraxisPresentationVisualizationTableSafe, isPraxisRuntimeGlobalActionEffect, isProgrammaticDateRangePreset, isRangeValidForFilter, isRequiredGlobalActionParamPayloadMissing, isRequiredGlobalActionPayloadMissing, isStaticDateRangePreset, isSurfaceNavigationError, isTableConfigV2, isUnresolvedTemplateToken, isValidFormConfig, isValidTableConfig, legacyCnpjValidator, legacyCpfValidator, logOnErrorHook, mapFieldDefinitionToMetadata, mapFieldDefinitionsToMetadata, markGlobalActionProviderOperational, matchFieldValidator, materializeFormLayoutFromMetadata, materializeGovernedPaletteColors, materializeGovernedPaletteEntries, materializeResourceIdentity, maxFileSizeValidator, mergeFieldMetadata, mergePraxisI18nConfigs, mergeTableConfigs, migrateFormLayoutRule, migrateLegacyCompositionLink, migrateLegacyCompositionLinks, minWordsValidator, nestedPortPathIdentity, normalizeCardMediaAspectRatio, normalizeControlTypeKey, normalizeControlTypeToken, normalizeEditorialLink, normalizeEnd, normalizeFieldAccessMetadata, normalizeFieldConstraints, normalizeFieldPresentation, normalizeFormConfig, normalizeFormLayoutItems, normalizeFormMetadata, normalizeGlobalActionRef$1 as normalizeGlobalActionRef, normalizeLayoutPolicy, normalizeLookupFilterRequest, normalizePath, normalizePraxisDataQueryContext, normalizePraxisEffectPolicy, normalizePraxisPresentationVisualization, normalizePraxisQueryFilterExpression, normalizePraxisQueryFilterNode, normalizeReactiveDeterminations, normalizeResourceAvailabilityReasonCode, normalizeResourceIdentityContract, normalizeStart, normalizeSurfaceOperationContext, normalizeUnknownError, normalizeWidgetEventPath, notifySuccessHook, parseJsonResponseOrEmpty, praxisLoadingInterceptorFn, prefillFromContextHook, prepareCanvasArrangement, projectComponentAuthoringManifest, projectGroupedCommandPartialRows, provideDefaultFormHooks, provideFieldSelectorRegistryBase, provideFieldSelectorRegistryOverride, provideFieldSelectorRegistryRuntime, provideFormHookPresets, provideFormHooks, provideGlobalActionCatalog, provideGlobalActionHandler, provideGlobalConfig, provideGlobalConfigReady, provideGlobalConfigSeed, provideGlobalConfigTenant, provideHookResolvers, provideHookWhitelist, provideOverlayDecisionMatrix, providePraxisAnalyticsGlobalActions, providePraxisCollectionExportProvider, providePraxisDynamicPageMetadata, providePraxisEnterpriseRuntimeContext, providePraxisFooterLinksMetadata, providePraxisGlobalActionCatalog, providePraxisGlobalActions, providePraxisGlobalConfigBootstrap, providePraxisHeroBannerMetadata, providePraxisHttpCollectionExportProvider, providePraxisHttpLoading, providePraxisI18n, providePraxisI18nConfig, providePraxisI18nTranslator, providePraxisIconDefaults, providePraxisJsonLogicOperator, providePraxisJsonLogicOperatorOverride, providePraxisLegalNoticeMetadata, providePraxisLoadingDefaults, providePraxisLogging, providePraxisRelatedResourceOutletMetadata, providePraxisRichTextBlockMetadata, providePraxisTelemetry, providePraxisToastGlobalActions, providePraxisUserContextSummaryMetadata, provideRemoteGlobalConfig, readPraxisExportValue, readStrongResourceEtag, reconcileFilterConfig, reconcileFormConfig, reconcileTableConfig, registerPraxisRuntimeComponentObservation, removeDiacritics, renderPraxisPresentationVisualizationHtml, reportTelemetryHookFactory, requiredCheckedValidator, requiredPresenceValidator, resolveBuiltinPresets, resolveBuiltinWidgetShellAppearance, resolveColumnTypeFromFieldDefinition, resolveControlTypeAlias, resolveDataField, resolveDateRangeShortcutPreset, resolveDateRangeShortcutPresets, resolveDefaultValuePresentationFormat, resolveEntityLookupPayloadMode, resolveFieldPresentation, resolveGroupedCommandPartialRowSpans, resolveHidden, resolveInlineFilterControlType, resolveInlineFilterControlTypeToBaseControlType, resolveLoggerConfig, resolveObservabilityOptions, resolveOffset, resolveOrder, resolvePraxisCollectionExportItems, resolvePraxisExportFields, resolvePraxisExportScope, resolvePraxisFilterCriteria, resolvePraxisI18nDocument, resolvePraxisMicroVisualizationTone, resolveResourceAvailabilityReasonKey, resolveResourceIdentityContract, resolveSpan, resolveTextMaskFormat, resolveTextMaskFormatFromFieldDefinition, resolveValuePresentation, resolveValuePresentationLocale, resolveWidgetPageLayoutPreset, serializeEntityLookupValueForPayload, serializeOptionSourceFilterRequest, serializePraxisCollectionToCsv, serializePraxisCollectionToExcel, serializePraxisCollectionToJson, slugify, staticDateRangePresetToPreset, stripMasksHook, supportsConfigDocuments, supportsImplicitValuePresentation, syncWithServerMetadata, textSha256, toCamel, toCapitalize, toKebab, toPascal, toSentenceCase, toSnake, toTitleCase, translateResourceAvailabilityReason, translateResourceDiscoveryText, translateSurfaceNavigationRejected, translateSurfaceOpenFailed, translateUnavailableWorkflowMessage, trim, uiLayoutJsonIdentity, uniqueAsyncValidator, urlValidator, validateCanvasArrangement, validateGlobalActionRef, validateGlobalActionRefs, withFormConfigSections, withMessage, withPraxisHttpLoading };
|