@openg2p/registry-widgets 1.1.0-dev.0 → 1.1.0-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -25
- package/dist/index.d.ts +3 -16
- package/dist/index.esm.js +127 -168
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +127 -168
- package/dist/index.js.map +1 -1
- package/dist/widgets/ScoresDisplayWidget.d.ts +11 -17
- package/dist/widgets/ScoresDisplayWidget.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -258,16 +258,16 @@ A full-width header card designed for registry record views. Displays a profile
|
|
|
258
258
|
|
|
259
259
|
### ScoresDisplay Widget
|
|
260
260
|
|
|
261
|
-
A full-width, view-only widget for showing a
|
|
261
|
+
A full-width, view-only widget for showing **a list** of computed score records (e.g. PMT, Food Security Score). It renders, for each score:
|
|
262
262
|
|
|
263
263
|
- **Score Type**
|
|
264
264
|
- **Score**
|
|
265
265
|
- **Computed at**
|
|
266
266
|
|
|
267
|
-
**
|
|
267
|
+
**Data binding**
|
|
268
268
|
|
|
269
|
-
- The widget reads
|
|
270
|
-
-
|
|
269
|
+
- The widget reads an array of score records from `widget-data-path` (a dot-path into `schemaData` / store values).
|
|
270
|
+
- `widget-data-path` may point either directly to an array, or to an object containing `{ "scores": [...] }`.
|
|
271
271
|
|
|
272
272
|
```json
|
|
273
273
|
{
|
|
@@ -275,37 +275,27 @@ A full-width, view-only widget for showing a single computed score record (e.g.
|
|
|
275
275
|
"widget-type": "group",
|
|
276
276
|
"widget-id": "record-scores",
|
|
277
277
|
"widget-readonly": true,
|
|
278
|
-
"widget-data-
|
|
279
|
-
"type": "api",
|
|
280
|
-
"service": "staff-portal-api",
|
|
281
|
-
"endpoint": "get_scores",
|
|
282
|
-
"method": "POST",
|
|
283
|
-
"params": {
|
|
284
|
-
"internal_record_id_path": "internal_record_id"
|
|
285
|
-
}
|
|
286
|
-
}
|
|
278
|
+
"widget-data-path": "scores"
|
|
287
279
|
}
|
|
288
280
|
```
|
|
289
281
|
|
|
290
|
-
**Expected
|
|
282
|
+
**Expected record shape (ideal)**
|
|
291
283
|
|
|
292
284
|
```json
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
]
|
|
302
|
-
}
|
|
285
|
+
[
|
|
286
|
+
{
|
|
287
|
+
"score_type": "PMT",
|
|
288
|
+
"computed_score": 42,
|
|
289
|
+
"computed_at": "2026-04-16T10:12:00Z",
|
|
290
|
+
"triggered_by_cr_id": "CR-001"
|
|
291
|
+
}
|
|
292
|
+
]
|
|
303
293
|
```
|
|
304
294
|
|
|
305
295
|
**Notes**
|
|
306
296
|
|
|
307
|
-
- The widget displays a single score record. If multiple scores are returned, it selects the most recent by `computed_at` (falls back to the first item if dates are missing).
|
|
308
297
|
- There is no edit mode for this widget.
|
|
298
|
+
- If multiple scores are provided, the widget sorts them by `computed_at` (most recent first). If dates are missing/invalid, original order is preserved for those items.
|
|
309
299
|
|
|
310
300
|
## Section Modes
|
|
311
301
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1454,33 +1454,20 @@ declare const HeaderSectionWidget: ({ config }: HeaderSectionWidgetProps) => rea
|
|
|
1454
1454
|
|
|
1455
1455
|
interface ScoresDisplayWidgetProps {
|
|
1456
1456
|
config: BaseWidgetConfig;
|
|
1457
|
-
dataSourceRequestHandler?: DataSourceRequestHandler;
|
|
1458
1457
|
schemaData?: Record<string, unknown>;
|
|
1459
1458
|
}
|
|
1460
1459
|
/**
|
|
1461
|
-
* Scores Display Widget - full-width, view-only widget
|
|
1460
|
+
* Scores Display Widget - full-width, view-only widget (list)
|
|
1462
1461
|
*
|
|
1463
1462
|
* Expected config (reference):
|
|
1464
1463
|
* {
|
|
1465
1464
|
* "widget": "scores-display",
|
|
1466
1465
|
* "widget-type": "group",
|
|
1467
1466
|
* "widget-id": "record-scores",
|
|
1468
|
-
* "widget-data-
|
|
1469
|
-
* "type": "api",
|
|
1470
|
-
* "service": "staff-portal-api",
|
|
1471
|
-
* "endpoint": "get_scores",
|
|
1472
|
-
* "method": "POST",
|
|
1473
|
-
* "params": { "internal_record_id_path": "internal_record_id" }
|
|
1474
|
-
* }
|
|
1467
|
+
* "widget-data-path": "scores"
|
|
1475
1468
|
* }
|
|
1476
|
-
*
|
|
1477
|
-
* The host's `dataSourceRequestHandler` is invoked with:
|
|
1478
|
-
* - service: config.widget-data-source.service
|
|
1479
|
-
* - endpoint: config.widget-data-source.endpoint
|
|
1480
|
-
* - method: config.widget-data-source.method (default POST)
|
|
1481
|
-
* - params: { internal_record_id: <resolved from internal_record_id_path> }
|
|
1482
1469
|
*/
|
|
1483
|
-
declare const ScoresDisplayWidget: ({ config,
|
|
1470
|
+
declare const ScoresDisplayWidget: ({ config, schemaData: propSchemaData, }: ScoresDisplayWidgetProps) => react_jsx_runtime.JSX.Element;
|
|
1484
1471
|
|
|
1485
1472
|
/**
|
|
1486
1473
|
* Get value from object using dot notation path
|
package/dist/index.esm.js
CHANGED
|
@@ -9526,6 +9526,13 @@ const HeaderSectionWidget = ({ config }) => {
|
|
|
9526
9526
|
} })) : null, jsxRuntimeExports.jsx("div", { className: "hdr-avatar-placeholder", style: { display: imageUrl ? 'none' : 'flex' }, children: jsxRuntimeExports.jsx("img", { src: img$f, alt: "Profile Placeholder" }) })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-info", children: [displayName && jsxRuntimeExports.jsx("div", { className: "hdr-name", children: displayName }), jsxRuntimeExports.jsxs("div", { className: "hdr-field-row", children: [jsxRuntimeExports.jsx(Dot, { color: "#9CA3AF" }), jsxRuntimeExports.jsxs("span", { className: "hdr-field-label", children: [getLabel('functionalId'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-field-value", children: functionalId || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-field-row", children: [jsxRuntimeExports.jsx(Dot, { color: isReadonly ? statusColor : '#F59E0B' }), jsxRuntimeExports.jsx("span", { className: "hdr-field-label", children: getLabel('status') }), isReadonly ? (statusLabel ? (jsxRuntimeExports.jsx("span", { className: "hdr-status-badge", style: { backgroundColor: statusColor }, children: statusLabel })) : (jsxRuntimeExports.jsx("span", { className: "hdr-field-value", children: "-" }))) : (jsxRuntimeExports.jsxs("select", { className: "hdr-select", value: statusValue, onChange: (e) => updateFieldValue('status', e.target.value), children: [jsxRuntimeExports.jsx("option", { value: "", children: getLabel('select') }), statusOptions.map((opt) => (jsxRuntimeExports.jsx("option", { value: opt.value, children: opt.label }, opt.value)))] }))] }), jsxRuntimeExports.jsxs("div", { className: "hdr-field-row", children: [jsxRuntimeExports.jsx(Dot, { color: isReadonly ? '#9CA3AF' : '#F59E0B' }), jsxRuntimeExports.jsxs("span", { className: "hdr-field-label", children: [getLabel('statusReason'), " :"] }), isReadonly ? (jsxRuntimeExports.jsx("span", { className: "hdr-field-value", children: statusReason || '-' })) : (jsxRuntimeExports.jsx("input", { type: "text", className: "hdr-input", value: statusReason, placeholder: getLabel('enterReason'), onChange: (e) => updateFieldValue('statusReason', e.target.value) }))] })] })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-right", children: [jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [getLabel('createdBy'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: createdBy || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [getLabel('createdAt'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: createdAt || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [getLabel('lastApprovedBy'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: lastApprovedBy || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [getLabel('lastApprovedAt'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: lastApprovedAt || '-' })] })] })] })] }));
|
|
9527
9527
|
};
|
|
9528
9528
|
|
|
9529
|
+
function getValueByPathOrKey(obj, path) {
|
|
9530
|
+
if (!obj || !path)
|
|
9531
|
+
return undefined;
|
|
9532
|
+
if (Object.prototype.hasOwnProperty.call(obj, path))
|
|
9533
|
+
return obj[path];
|
|
9534
|
+
return getValueByPath(obj, path);
|
|
9535
|
+
}
|
|
9529
9536
|
function tryFormatDateTime(value) {
|
|
9530
9537
|
if (typeof value !== 'string' || !value)
|
|
9531
9538
|
return value ? String(value) : '-';
|
|
@@ -9545,157 +9552,80 @@ function tryFormatDateTime(value) {
|
|
|
9545
9552
|
return value;
|
|
9546
9553
|
}
|
|
9547
9554
|
}
|
|
9548
|
-
function
|
|
9549
|
-
if (!scores || scores.length === 0)
|
|
9550
|
-
return null;
|
|
9555
|
+
function sortScores(scores) {
|
|
9551
9556
|
const withTime = scores
|
|
9552
|
-
.map((s) => {
|
|
9557
|
+
.map((s, idx) => {
|
|
9553
9558
|
const t = typeof s?.computed_at === 'string' ? new Date(s.computed_at).getTime() : NaN;
|
|
9554
|
-
return { s, t };
|
|
9559
|
+
return { s, t, idx };
|
|
9555
9560
|
})
|
|
9556
|
-
.
|
|
9557
|
-
|
|
9558
|
-
|
|
9559
|
-
|
|
9560
|
-
|
|
9561
|
+
.sort((a, b) => {
|
|
9562
|
+
const aHas = !Number.isNaN(a.t);
|
|
9563
|
+
const bHas = !Number.isNaN(b.t);
|
|
9564
|
+
if (aHas && bHas)
|
|
9565
|
+
return b.t - a.t;
|
|
9566
|
+
if (aHas)
|
|
9567
|
+
return -1;
|
|
9568
|
+
if (bHas)
|
|
9569
|
+
return 1;
|
|
9570
|
+
return a.idx - b.idx;
|
|
9571
|
+
});
|
|
9572
|
+
return withTime.map((x) => x.s);
|
|
9561
9573
|
}
|
|
9562
9574
|
/**
|
|
9563
|
-
* Scores Display Widget - full-width, view-only widget
|
|
9575
|
+
* Scores Display Widget - full-width, view-only widget (list)
|
|
9564
9576
|
*
|
|
9565
9577
|
* Expected config (reference):
|
|
9566
9578
|
* {
|
|
9567
9579
|
* "widget": "scores-display",
|
|
9568
9580
|
* "widget-type": "group",
|
|
9569
9581
|
* "widget-id": "record-scores",
|
|
9570
|
-
* "widget-data-
|
|
9571
|
-
* "type": "api",
|
|
9572
|
-
* "service": "staff-portal-api",
|
|
9573
|
-
* "endpoint": "get_scores",
|
|
9574
|
-
* "method": "POST",
|
|
9575
|
-
* "params": { "internal_record_id_path": "internal_record_id" }
|
|
9576
|
-
* }
|
|
9582
|
+
* "widget-data-path": "scores"
|
|
9577
9583
|
* }
|
|
9578
|
-
*
|
|
9579
|
-
* The host's `dataSourceRequestHandler` is invoked with:
|
|
9580
|
-
* - service: config.widget-data-source.service
|
|
9581
|
-
* - endpoint: config.widget-data-source.endpoint
|
|
9582
|
-
* - method: config.widget-data-source.method (default POST)
|
|
9583
|
-
* - params: { internal_record_id: <resolved from internal_record_id_path> }
|
|
9584
9584
|
*/
|
|
9585
|
-
const ScoresDisplayWidget = ({ config,
|
|
9586
|
-
const {
|
|
9587
|
-
const
|
|
9588
|
-
const schemaData = propSchemaData || ctxSchemaData || {};
|
|
9585
|
+
const ScoresDisplayWidget = ({ config, schemaData: propSchemaData, }) => {
|
|
9586
|
+
const { schemaData: ctxSchemaData } = useWidgetContext();
|
|
9587
|
+
const schemaData = (propSchemaData || ctxSchemaData || {});
|
|
9589
9588
|
const values = useSelector((state) => state.widget.values);
|
|
9590
|
-
const
|
|
9591
|
-
const
|
|
9592
|
-
|
|
9593
|
-
const internalIdPath = useMemo(() => {
|
|
9594
|
-
if (!apiDs)
|
|
9595
|
-
return undefined;
|
|
9596
|
-
const p = apiDs.params || {};
|
|
9597
|
-
const fromParams = p.internal_record_id_path || p.internalRecordIdPath;
|
|
9598
|
-
const fromConfig = typeof config.internal_record_id_path === 'string'
|
|
9599
|
-
? config.internal_record_id_path
|
|
9600
|
-
: undefined;
|
|
9601
|
-
return fromParams || fromConfig;
|
|
9602
|
-
}, [apiDs, config]);
|
|
9603
|
-
const internalRecordId = useMemo(() => {
|
|
9604
|
-
if (!internalIdPath)
|
|
9589
|
+
const dataPath = config['widget-data-path'];
|
|
9590
|
+
const rawScores = useMemo(() => {
|
|
9591
|
+
if (!dataPath || typeof dataPath !== 'string')
|
|
9605
9592
|
return undefined;
|
|
9606
|
-
const
|
|
9607
|
-
|
|
9608
|
-
|
|
9609
|
-
|
|
9610
|
-
|
|
9611
|
-
|
|
9612
|
-
|
|
9593
|
+
const valuesObj = values;
|
|
9594
|
+
const tryResolve = (path) => {
|
|
9595
|
+
const fromValues = getValueByPathOrKey(valuesObj, path);
|
|
9596
|
+
if (fromValues !== undefined)
|
|
9597
|
+
return fromValues;
|
|
9598
|
+
return getValueByPathOrKey(schemaData, path);
|
|
9599
|
+
};
|
|
9600
|
+
// 1) Try exact path (works when schema/store is already namespaced)
|
|
9601
|
+
const direct = tryResolve(dataPath);
|
|
9602
|
+
if (direct !== undefined)
|
|
9603
|
+
return direct;
|
|
9604
|
+
// 2) If section/widget config has been namespaced (e.g. "rv-section-0.scores"),
|
|
9605
|
+
// fall back to the original path ("scores") so examples still work even when
|
|
9606
|
+
// schemaData/store are not namespaced.
|
|
9607
|
+
if (dataPath.includes('.')) {
|
|
9608
|
+
const unNamespaced = dataPath.split('.').slice(1).join('.');
|
|
9609
|
+
const fallback = tryResolve(unNamespaced);
|
|
9610
|
+
if (fallback !== undefined)
|
|
9611
|
+
return fallback;
|
|
9613
9612
|
}
|
|
9614
9613
|
return undefined;
|
|
9615
|
-
}, [
|
|
9616
|
-
const
|
|
9617
|
-
|
|
9618
|
-
|
|
9619
|
-
|
|
9620
|
-
|
|
9621
|
-
|
|
9622
|
-
|
|
9623
|
-
|
|
9624
|
-
|
|
9625
|
-
|
|
9626
|
-
|
|
9627
|
-
|
|
9628
|
-
|
|
9629
|
-
setResponse(null);
|
|
9630
|
-
return;
|
|
9631
|
-
}
|
|
9632
|
-
const service = apiDs.service;
|
|
9633
|
-
const endpoint = apiDs.endpoint;
|
|
9634
|
-
const method = apiDs.method || 'POST';
|
|
9635
|
-
if (!service || !endpoint) {
|
|
9636
|
-
setError('Scores widget API data source is missing service/endpoint.');
|
|
9637
|
-
setResponse(null);
|
|
9638
|
-
return;
|
|
9639
|
-
}
|
|
9640
|
-
if (!internalRecordId) {
|
|
9641
|
-
setError(null);
|
|
9642
|
-
setResponse(null);
|
|
9643
|
-
return;
|
|
9644
|
-
}
|
|
9645
|
-
try {
|
|
9646
|
-
setLoading(true);
|
|
9647
|
-
setError(null);
|
|
9648
|
-
const rawParams = apiDs.params || {};
|
|
9649
|
-
// Never pass the path helper through to the API.
|
|
9650
|
-
const { internal_record_id_path, internalRecordIdPath, ...rest } = rawParams;
|
|
9651
|
-
void internal_record_id_path;
|
|
9652
|
-
void internalRecordIdPath;
|
|
9653
|
-
const params = {
|
|
9654
|
-
...rest,
|
|
9655
|
-
internal_record_id: internalRecordId,
|
|
9656
|
-
};
|
|
9657
|
-
const res = await handler(service, endpoint, method, params, {
|
|
9658
|
-
headers: apiDs.headers,
|
|
9659
|
-
});
|
|
9660
|
-
if (cancelled)
|
|
9661
|
-
return;
|
|
9662
|
-
// Accept either direct payload or OpenG2P wrapper objects.
|
|
9663
|
-
const envelope = res && typeof res === 'object' ? res : null;
|
|
9664
|
-
const payload = envelope?.response_body?.response_payload ?? envelope?.data ?? res;
|
|
9665
|
-
if (payload && typeof payload === 'object' && !Array.isArray(payload)) {
|
|
9666
|
-
setResponse(payload);
|
|
9667
|
-
}
|
|
9668
|
-
else {
|
|
9669
|
-
setResponse({ scores: Array.isArray(payload) ? payload : [] });
|
|
9670
|
-
}
|
|
9671
|
-
}
|
|
9672
|
-
catch (e) {
|
|
9673
|
-
if (cancelled)
|
|
9674
|
-
return;
|
|
9675
|
-
const maybeErr = e;
|
|
9676
|
-
const msg = maybeErr && typeof maybeErr === 'object' && typeof maybeErr.message === 'string'
|
|
9677
|
-
? maybeErr.message
|
|
9678
|
-
: 'Failed to load scores.';
|
|
9679
|
-
setError(msg);
|
|
9680
|
-
setResponse(null);
|
|
9681
|
-
}
|
|
9682
|
-
finally {
|
|
9683
|
-
if (!cancelled)
|
|
9684
|
-
setLoading(false);
|
|
9685
|
-
}
|
|
9686
|
-
};
|
|
9687
|
-
load();
|
|
9688
|
-
return () => {
|
|
9689
|
-
cancelled = true;
|
|
9690
|
-
};
|
|
9691
|
-
}, [apiDs, handler, internalRecordId]);
|
|
9692
|
-
const latest = useMemo(() => pickLatestScore(response?.scores), [response]);
|
|
9614
|
+
}, [dataPath, values, schemaData]);
|
|
9615
|
+
const scores = useMemo(() => {
|
|
9616
|
+
if (!rawScores)
|
|
9617
|
+
return [];
|
|
9618
|
+
if (Array.isArray(rawScores))
|
|
9619
|
+
return rawScores;
|
|
9620
|
+
if (typeof rawScores === 'object') {
|
|
9621
|
+
const maybe = rawScores.scores;
|
|
9622
|
+
if (Array.isArray(maybe))
|
|
9623
|
+
return maybe;
|
|
9624
|
+
}
|
|
9625
|
+
return [];
|
|
9626
|
+
}, [rawScores]);
|
|
9627
|
+
const sortedScores = useMemo(() => sortScores(scores), [scores]);
|
|
9693
9628
|
const cls = `scores-display-widget-${config['widget-id']}`;
|
|
9694
|
-
const scoreType = latest?.score_type ? String(latest.score_type) : '-';
|
|
9695
|
-
const scoreValue = latest?.computed_score !== undefined && latest?.computed_score !== null && String(latest.computed_score) !== ''
|
|
9696
|
-
? String(latest.computed_score)
|
|
9697
|
-
: '-';
|
|
9698
|
-
const computedAt = tryFormatDateTime(latest?.computed_at);
|
|
9699
9629
|
return (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("style", { children: `
|
|
9700
9630
|
.${cls} {
|
|
9701
9631
|
width: 100%;
|
|
@@ -9712,66 +9642,95 @@ const ScoresDisplayWidget = ({ config, dataSourceRequestHandler: propHandler, sc
|
|
|
9712
9642
|
font-weight: 400;
|
|
9713
9643
|
}
|
|
9714
9644
|
|
|
9715
|
-
.${cls} .scores-
|
|
9645
|
+
.${cls} .scores-grid {
|
|
9716
9646
|
width: 100%;
|
|
9717
|
-
border: none;
|
|
9718
|
-
border-radius: 0;
|
|
9719
|
-
background: transparent;
|
|
9720
|
-
padding: 0;
|
|
9721
9647
|
display: grid;
|
|
9722
|
-
grid-template-columns:
|
|
9648
|
+
grid-template-columns: repeat(3, minmax(220px, 1fr));
|
|
9723
9649
|
gap: 16px;
|
|
9724
|
-
align-items: center;
|
|
9725
9650
|
}
|
|
9726
9651
|
|
|
9727
|
-
.${cls} .scores-
|
|
9728
|
-
|
|
9652
|
+
.${cls} .scores-card {
|
|
9653
|
+
border: 1px solid var(--owt-color-border-light, #E4E4E4);
|
|
9654
|
+
border-radius: 10px;
|
|
9655
|
+
background: var(--owt-color-bg, #FFFFFF);
|
|
9656
|
+
padding: 14px 14px;
|
|
9729
9657
|
display: flex;
|
|
9730
9658
|
flex-direction: column;
|
|
9731
|
-
gap:
|
|
9659
|
+
gap: 10px;
|
|
9660
|
+
min-width: 0;
|
|
9661
|
+
box-shadow: 0 1px 2px rgba(1, 22, 39, 0.06), 0 6px 16px rgba(1, 22, 39, 0.06);
|
|
9732
9662
|
}
|
|
9733
9663
|
|
|
9734
|
-
.${cls} .scores-
|
|
9735
|
-
font-size:
|
|
9736
|
-
|
|
9737
|
-
|
|
9738
|
-
|
|
9739
|
-
|
|
9664
|
+
.${cls} .scores-type {
|
|
9665
|
+
font-size: 16px;
|
|
9666
|
+
font-weight: 800;
|
|
9667
|
+
color: var(--owt-color-primary-dark, #F07B1A);
|
|
9668
|
+
line-height: 1.2;
|
|
9669
|
+
word-break: break-word;
|
|
9740
9670
|
}
|
|
9741
9671
|
|
|
9742
9672
|
.${cls} .scores-value {
|
|
9743
|
-
font-size:
|
|
9744
|
-
font-weight:
|
|
9673
|
+
font-size: 34px;
|
|
9674
|
+
font-weight: 800;
|
|
9745
9675
|
color: var(--owt-color-text, #011627);
|
|
9746
|
-
line-height: 1.
|
|
9747
|
-
|
|
9676
|
+
line-height: 1.05;
|
|
9677
|
+
letter-spacing: -0.25px;
|
|
9748
9678
|
}
|
|
9749
9679
|
|
|
9750
|
-
.${cls} .scores-
|
|
9751
|
-
|
|
9752
|
-
|
|
9680
|
+
.${cls} .scores-separator {
|
|
9681
|
+
height: 1px;
|
|
9682
|
+
width: 100%;
|
|
9683
|
+
background-color: var(--owt-color-border-light, #E4E4E4);
|
|
9684
|
+
border: none;
|
|
9685
|
+
margin: 2px 0;
|
|
9753
9686
|
}
|
|
9754
9687
|
|
|
9755
|
-
.${cls} .scores-value-
|
|
9756
|
-
|
|
9757
|
-
|
|
9758
|
-
|
|
9759
|
-
|
|
9688
|
+
.${cls} .scores-value .scores-muted {
|
|
9689
|
+
font-size: 18px;
|
|
9690
|
+
font-weight: 600;
|
|
9691
|
+
color: var(--owt-color-text-muted, #727474);
|
|
9692
|
+
margin-left: 6px;
|
|
9760
9693
|
}
|
|
9761
9694
|
|
|
9762
|
-
.${cls} .scores-
|
|
9695
|
+
.${cls} .scores-meta {
|
|
9696
|
+
display: flex;
|
|
9697
|
+
flex-direction: column;
|
|
9698
|
+
gap: 4px;
|
|
9699
|
+
}
|
|
9763
9700
|
|
|
9764
|
-
.${cls} .scores-
|
|
9765
|
-
|
|
9766
|
-
|
|
9701
|
+
.${cls} .scores-meta-line {
|
|
9702
|
+
font-size: 13px;
|
|
9703
|
+
color: var(--owt-color-text-muted, #727474);
|
|
9704
|
+
font-weight: 500;
|
|
9767
9705
|
}
|
|
9768
9706
|
|
|
9769
|
-
|
|
9770
|
-
|
|
9707
|
+
.${cls} .scores-meta-line strong {
|
|
9708
|
+
color: var(--owt-color-text, #011627);
|
|
9709
|
+
font-weight: 700;
|
|
9710
|
+
}
|
|
9711
|
+
|
|
9712
|
+
@media (max-width: 1024px) {
|
|
9713
|
+
.${cls} .scores-grid {
|
|
9714
|
+
grid-template-columns: repeat(2, minmax(220px, 1fr));
|
|
9715
|
+
}
|
|
9716
|
+
}
|
|
9717
|
+
|
|
9718
|
+
@media (max-width: 640px) {
|
|
9719
|
+
.${cls} .scores-grid {
|
|
9771
9720
|
grid-template-columns: 1fr;
|
|
9772
9721
|
}
|
|
9773
9722
|
}
|
|
9774
|
-
` }), jsxRuntimeExports.jsx("div", { className: cls, children:
|
|
9723
|
+
` }), jsxRuntimeExports.jsx("div", { className: cls, children: sortedScores.length === 0 ? (jsxRuntimeExports.jsx("div", { className: "scores-subtle", children: "No scores available." })) : (jsxRuntimeExports.jsx("div", { className: "scores-grid", children: sortedScores.map((s, idx) => {
|
|
9724
|
+
const scoreType = s?.score_type ? String(s.score_type) : '-';
|
|
9725
|
+
const scoreValue = s?.computed_score !== undefined &&
|
|
9726
|
+
s?.computed_score !== null &&
|
|
9727
|
+
String(s.computed_score) !== ''
|
|
9728
|
+
? String(s.computed_score)
|
|
9729
|
+
: '-';
|
|
9730
|
+
const computedAt = tryFormatDateTime(s?.computed_at);
|
|
9731
|
+
const key = `${scoreType}-${String(s?.computed_at || '')}-${idx}`;
|
|
9732
|
+
return (jsxRuntimeExports.jsxs("div", { className: "scores-card", "aria-live": idx === 0 ? 'polite' : undefined, children: [jsxRuntimeExports.jsx("div", { className: "scores-type", children: scoreType }), jsxRuntimeExports.jsx("div", { className: "scores-value", children: scoreValue }), jsxRuntimeExports.jsx("hr", { className: "scores-separator" }), jsxRuntimeExports.jsx("div", { className: "scores-meta", children: jsxRuntimeExports.jsxs("div", { className: "scores-meta-line", children: ["Computed at: ", jsxRuntimeExports.jsx("strong", { children: computedAt })] }) })] }, key));
|
|
9733
|
+
}) })) })] }));
|
|
9775
9734
|
};
|
|
9776
9735
|
|
|
9777
9736
|
/**
|