Merged PR 2395: helpers for dashboard domain layer
Related work items: #23754
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
# Dashboard Policy Boundary
|
||||
|
||||
## Current ownership
|
||||
|
||||
This boundary currently owns:
|
||||
|
||||
```js
|
||||
splitWatchedCasesBySubmissionState(records);
|
||||
```
|
||||
|
||||
Purpose:
|
||||
|
||||
```text
|
||||
watched-case records
|
||||
↓
|
||||
classification by submission state
|
||||
↓
|
||||
watched bucket
|
||||
submitted bucket
|
||||
```
|
||||
|
||||
## Current contract
|
||||
|
||||
`splitWatchedCasesBySubmissionState(records)` intentionally preserves:
|
||||
|
||||
- loose-null semantics
|
||||
- null handling
|
||||
- undefined handling
|
||||
- truthy submitted markers
|
||||
- date-string submitted markers
|
||||
- input-order preservation
|
||||
- watched bucket count calculation
|
||||
|
||||
In current behaviour, `pinswg_representationsubmitted == null` means a record remains in the watched bucket, so both `null` and `undefined` are treated as “not submitted”. Any non-null submitted marker, including booleans and date strings, is classified into the submitted bucket.
|
||||
|
||||
## Output contract
|
||||
|
||||
Current return shape:
|
||||
|
||||
```js
|
||||
{
|
||||
watchedCases: {
|
||||
"@odata.count": number,
|
||||
value: [...]
|
||||
},
|
||||
|
||||
submittedRepresentations: [...]
|
||||
}
|
||||
```
|
||||
|
||||
The asymmetry of this shape is intentional and must be preserved until an explicit contract-change initiative occurs.
|
||||
|
||||
## Explicit non-goals
|
||||
|
||||
This boundary does **not** own:
|
||||
|
||||
- sorting
|
||||
- ordering rules
|
||||
- createdon sorting
|
||||
- createdDate sorting
|
||||
- ticketnumber sorting
|
||||
- top-three truncation
|
||||
- detail merging
|
||||
- hydration
|
||||
- watch/unwatch orchestration
|
||||
- setState behaviour
|
||||
- React rendering
|
||||
- dashboard cards
|
||||
- search result rendering
|
||||
- CRM queries
|
||||
- API routes
|
||||
- authentication
|
||||
- authorization
|
||||
|
||||
## Caller-owned behaviour
|
||||
|
||||
Current pattern:
|
||||
|
||||
```text
|
||||
classification belongs to dashboard-policy
|
||||
ordering belongs to the caller
|
||||
refresh orchestration belongs to the caller
|
||||
rendering belongs to the caller
|
||||
```
|
||||
|
||||
Current examples:
|
||||
|
||||
- `pages/myportal/index.js`
|
||||
- uses `splitWatchedCasesBySubmissionState(watchedCases.value)` to derive watched and submitted buckets for store hydration.
|
||||
- caller remains responsible for page-level orchestration and dispatch behaviour.
|
||||
|
||||
- `components/myportal/viewall.js`
|
||||
- uses helper classification for watched-case membership.
|
||||
- caller still owns descending `createdon` sorting in the refresh path, current view refresh flow, and rendering.
|
||||
|
||||
- `components/myportal/topthree.js`
|
||||
- uses helper classification for watched-case membership.
|
||||
- caller still owns created-date derivation, `createdDate` sorting, `ticketnumber` sorting, detail merging, final `createdon` ordering, and top-three truncation.
|
||||
|
||||
- `components/search/searchresults.js`
|
||||
- uses helper classification only for the watched-case delete refresh path.
|
||||
- caller still owns descending `createdon` sorting after classification, watch/unwatch refresh orchestration, state updates, detail hydration, and result rendering.
|
||||
|
||||
## Adopted consumers
|
||||
|
||||
Current known adopters:
|
||||
|
||||
- `pages/myportal/index.js`
|
||||
- `components/myportal/viewall.js`
|
||||
- `components/myportal/topthree.js`
|
||||
- `components/search/searchresults.js`
|
||||
|
||||
## Remaining consumers
|
||||
|
||||
Likely future adoption candidates:
|
||||
|
||||
- `components/search/addresssearchresults.js`
|
||||
- `components/search/dnssearchresults.js`
|
||||
- `components/case/summary.js`
|
||||
|
||||
These consumers require characterization before adoption.
|
||||
|
||||
## Testing expectations
|
||||
|
||||
Current characterization safety net:
|
||||
|
||||
```bash
|
||||
node tests/phase22/dashboard-watched-case-classification.test.cjs
|
||||
node tests/phase22/dashboard-viewall-classification.test.cjs
|
||||
node tests/phase22/dashboard-topthree-classification.test.cjs
|
||||
node tests/phase22/dashboard-searchresults-classification.test.cjs
|
||||
npm run lint
|
||||
```
|
||||
|
||||
## Future evolution
|
||||
|
||||
Future work may:
|
||||
|
||||
```text
|
||||
increase helper adoption
|
||||
```
|
||||
|
||||
Future work should not:
|
||||
|
||||
```text
|
||||
move sorting into the helper
|
||||
move rendering into the helper
|
||||
move refresh orchestration into the helper
|
||||
```
|
||||
|
||||
without a separate domain-boundary decision.
|
||||
@@ -0,0 +1 @@
|
||||
export { splitWatchedCasesBySubmissionState } from "./splitWatchedCasesBySubmissionState";
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* This helper owns watched-case classification by representation submission state.
|
||||
*
|
||||
* It intentionally preserves loose-null semantics because existing dashboard
|
||||
* behaviour treats both null and undefined as "not submitted".
|
||||
*/
|
||||
export function splitWatchedCasesBySubmissionState(records = []) {
|
||||
const watchedCases = {
|
||||
"@odata.count": records.filter(
|
||||
(record) => record.pinswg_representationsubmitted == null
|
||||
).length,
|
||||
value: records.filter(
|
||||
(record) => record.pinswg_representationsubmitted == null
|
||||
)
|
||||
};
|
||||
|
||||
const submittedRepresentations = records.filter(
|
||||
(record) => record.pinswg_representationsubmitted != null
|
||||
);
|
||||
|
||||
return {
|
||||
watchedCases,
|
||||
submittedRepresentations
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user