Skip to content

Lihlumise/b/96353#4539

Open
Lihlu wants to merge 4 commits intoshesha-io:mainfrom
Lihlu:lihlumise/b/96353
Open

Lihlumise/b/96353#4539
Lihlu wants to merge 4 commits intoshesha-io:mainfrom
Lihlu:lihlumise/b/96353

Conversation

@Lihlu
Copy link
Collaborator

@Lihlu Lihlu commented Feb 23, 2026

96353

Summary by CodeRabbit

  • New Features

    • Autocomplete now preserves and constructs entity references from primitives and objects for more reliable selection handling.
    • Added effectiveEntityType support to improve metadata-driven rendering and filtering.
    • Exposed a general-purpose "isRecord" guard for safer object detection.
  • Bug Fixes

    • Improved robustness for primitives, plain objects and missing fields; labels render correctly while loading.
    • Reduced unnecessary data reloads when selecting from dropdowns; safer option extraction and change handling.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 23, 2026

Walkthrough

Added defensive value handling and entity-type inference to Autocomplete: new isRecord guard and helpers, safer key/display/outcome logic for primitives and non-records, lastLoadedKeys tracking to avoid unnecessary reloads, and propagation of effectiveEntityType through metadata/DataTableProvider paths.

Changes

Cohort / File(s) Summary
Autocomplete (core)
shesha-reactjs/src/components/autocomplete/index.tsx
Added helpers (extractEntityTypeFromValue, isSelectOption), isRecord guards, hardened get/display/key/outcome accessors for primitives and missing fields, lastLoadedKeys tracking, conditional reload logic, and threaded effectiveEntityType into metadata/DataTableProvider calls.
Designer autocomplete
shesha-reactjs/src/designer-components/autocomplete/autocomplete.tsx
Expanded outcomeValueFunc to handle primitives, arrays, existing entity references, and records; changed onChangeInternal signature to (value: unknown, option?: unknown) and introduced isRecord usage for object detection.
Models / Props
shesha-reactjs/src/components/autocomplete/models.tsx
Added optional prop `effectiveEntityType?: string
Utilities
shesha-reactjs/src/utils/object.ts, shesha-reactjs/src/utils/index.ts
Added exported type guard isRecord(value: unknown): value is Record<string, unknown) and re-exported it from the utils index.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Autocomplete
  participant DataTableProvider
  participant API

  User->>Autocomplete: open dropdown / select value
  Autocomplete->>Autocomplete: compute effectiveEntityType (props or infer from value)
  Autocomplete->>DataTableProvider: request metadata/data (includes effectiveEntityType, lastLoadedKeys)
  DataTableProvider->>API: fetch rows/metadata (guarded query params)
  API-->>DataTableProvider: return rows/metadata
  DataTableProvider-->>Autocomplete: deliver rows/metadata
  Autocomplete->>Autocomplete: apply isRecord / isSelectOption -> build display/key/outcome
  Autocomplete-->>User: render labels / return selected value
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • James-Baloyi
  • AlexStepantsov

Poem

🐰 I nibble through props and values with care,
Guards at each burrow so none will despair,
Primitives, records, or options I find,
EffectiveEntityType keeps logic aligned,
Hooray — safe autocompletes hop on air! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title 'Lihlumise/b/96353' is a branch name identifier that does not describe the actual changes made. The actual work involves replacing unsafe object casts with type guards in autocomplete components, adding entity type inference logic, and improving data handling for non-record values—none of which is conveyed by the title. Replace the branch name with a descriptive title like 'Replace unsafe object casts with type guards in autocomplete component' or 'Improve autocomplete type safety and entity type handling'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@shesha-reactjs/src/components/autocomplete/index.tsx`:
- Around line 103-107: The computed effectiveEntityType is duplicated; add
effectiveEntityType?: string | IReferenceListIdentifier | null to
IAutocompleteBaseProps, compute it once in Autocomplete (reusing the existing
useMemo there) and pass it explicitly through props (or spread) into
AutocompleteInner, then remove the useMemo that computes effectiveEntityType
inside AutocompleteInner and read props.effectiveEntityType directly; update any
call sites or tests that construct props if needed.
- Around line 68-73: The displayValueFunc implementation is noisy: replace the
redundant !Boolean(value) with the simpler !value, and remove the unnecessary
optional chaining on value?.toString() after the isRecord guard (use
value.toString() or String(value.toString() ?? '') as appropriate) so the logic
in displayValueFunc (referenced props.displayValueFunc, displayPropName,
isRecord, getValueByPropertyName) remains identical but cleaner.
- Around line 109-116: The useMemo that computes keys (function named keys)
currently only depends on props.value but calls keyValueFunc(..., allData),
which can change and cause stale closures; update the dependency array to
include keyValueFunc and allData (and if keyValueFunc originates from props,
include props.keyValueFunc) so keys is recomputed whenever keyValueFunc or
allData change, ensuring downstream checks like allExist, allExistInTable, and
keysChanged use fresh key values.

In `@shesha-reactjs/src/designer-components/autocomplete/autocomplete.tsx`:
- Around line 63-94: The branch in outcomeValueFunc builds an entity reference
for any object because isRecord currently matches arrays; update the isRecord
implementation (in object.ts) to explicitly exclude arrays (use Array.isArray
check) and then add a defensive guard inside outcomeValueFunc right before the
isRecord branch: if (Array.isArray(item)) return item; so arrays are returned
unchanged instead of producing malformed {id:undefined,...}; keep the existing
isEntityReferenceId, typeof item !== 'object' checks and then use
getValueByPropertyName for id/_displayName as before for genuine records.
- Around line 86-92: The id extraction is redundant and wrongly uses || which
treats 0 as falsy; in the block inside isRecord(...) replace "item.id ||
getValueByPropertyName(item, 'id')" with a nullish-coalescing expression such as
"getValueByPropertyName(item, 'id') ?? item.id" (or simply
"getValueByPropertyName(item, 'id')" if you prefer) so that numeric ids like 0
are preserved; update the return in that function in autocomplete.tsx (the
isRecord branch) referring to getValueByPropertyName and item.id accordingly.

In `@shesha-reactjs/src/utils/object.ts`:
- Around line 10-11: The isRecord type guard incorrectly returns true for
arrays; update isRecord to exclude arrays (use Array.isArray) so it only accepts
plain objects, e.g., change the predicate in isRecord to check typeof value ===
'object' && value !== null && !Array.isArray(value); then run/adjust callers in
autocomplete/index.tsx and designer-components/autocomplete/autocomplete.tsx
(the code paths that access .id and ._displayName) to rely on the corrected
guard or add fallback checks if needed.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 887e187 and fd8bd44.

📒 Files selected for processing (4)
  • shesha-reactjs/src/components/autocomplete/index.tsx
  • shesha-reactjs/src/designer-components/autocomplete/autocomplete.tsx
  • shesha-reactjs/src/utils/index.ts
  • shesha-reactjs/src/utils/object.ts

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
shesha-reactjs/src/components/autocomplete/index.tsx (2)

121-141: 🧹 Nitpick | 🔵 Trivial

Commented-out dependencies are a stale-closure hazard and code smell.

The useEffect on line 121 reads keyValueFunc, outcomeValueFunc, allData, and source?.tableData inside the callback, but the dependency array on line 141 omits them (left as a comment). If any of these change, the effect will use stale references.

The commented-out deps suggest they were intentionally removed to avoid re-trigger loops, but this should be documented with a // NOTE: explaining the trade-off. If the functions are guaranteed stable (memoized with fixed deps), the risk is low—but removing the comment avoids confusion for future maintainers.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shesha-reactjs/src/components/autocomplete/index.tsx` around lines 121 - 141,
The effect in useEffect reads keyValueFunc, outcomeValueFunc, allData and
source?.tableData but omits them from the dependency array, creating a
stale-closure hazard; either add those dependencies (keyValueFunc,
outcomeValueFunc, allData, source?.tableData) to the array so the effect reruns
when they change, or if you intentionally want to avoid reruns, add a clear //
NOTE: explaining the trade-off and guarantee that keyValueFunc and
outcomeValueFunc are stable/memoized and source.tableData changes are handled
elsewhere; ensure selected.current and getNormalizedValues(props.value) behavior
remains correct with whichever approach you choose.

49-49: ⚠️ Potential issue | 🟠 Major

Uncomment useAvailableConstantsData() hook and add missing import — allData is stubbed as an empty object.

The hook call is commented out on line 49 and useAvailableConstantsData is not imported. As a result, allData is always {}, which breaks any expression-based callbacks (keyValueFunc, outcomeValueFunc, displayValueFunc) that reference form data or global context. Every similar component (calendar, dataList, reactTable) properly calls this hook.

The commented-out dependencies on line 141 suggest an incomplete fix. Restore the hook call, add the import, and include allData in the dependency arrays where functions use it, as shown in other components.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shesha-reactjs/src/components/autocomplete/index.tsx` at line 49, Restore the
real data hook by replacing the stubbed const allData = {} with a call to
useAvailableConstantsData() and add the missing import for
useAvailableConstantsData at the top of the file; then update the dependency
arrays for the callbacks that reference it (keyValueFunc, outcomeValueFunc,
displayValueFunc and any similar functions) to include allData so those memoized
callbacks react to changes in global/form constants. Ensure you reference the
existing symbols allData, useAvailableConstantsData, keyValueFunc,
outcomeValueFunc, displayValueFunc when making the changes.
♻️ Duplicate comments (1)
shesha-reactjs/src/designer-components/autocomplete/autocomplete.tsx (1)

93-93: 🧹 Nitpick | 🔵 Trivial

getValueByPropertyName(item, 'id') ?? item.id is still redundant — both access the same top-level key.

The switch from || to ?? fixes the falsy-id concern from the prior review, but the fallback item.id is functionally identical to getValueByPropertyName(item, 'id') for a plain 'id' key. Simplify to just one access.

♻️ Proposed fix
-            id: getValueByPropertyName(item, 'id') ?? item.id,
+            id: item.id,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shesha-reactjs/src/designer-components/autocomplete/autocomplete.tsx` at line
93, Remove the redundant fallback for the id field: replace the expression using
both getValueByPropertyName(item, 'id') and item.id with a single access. Locate
the assignment setting id (the line containing id: getValueByPropertyName(item,
'id') ?? item.id) and simplify it to use only getValueByPropertyName(item, 'id')
or only item.id depending on whether you need the property-name lookup; ensure
the chosen single access preserves the original null/undefined semantics that
the code expects.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@shesha-reactjs/src/components/autocomplete/index.tsx`:
- Around line 39-40: The type guard isSelectOption is too permissive because it
only checks for 'data'; update it to verify the presence and expected shapes of
all required ISelectOption members (check that 'value' and 'label' keys exist
and that label is a string and data is an object/record) so the guard
confidently narrows to ISelectOption; locate and modify the isSelectOption
function and ensure it still uses isRecord(value) as the first check and then
`in` checks and lightweight typeof/object checks for 'label' and 'data'.

In `@shesha-reactjs/src/designer-components/autocomplete/autocomplete.tsx`:
- Around line 129-132: onChangeInternal currently force-casts value to object
when calling customEvent.onChange, which bypasses type safety; add a type guard
in onChangeInternal (e.g., check typeof value === 'object' && value !== null)
before calling customEvent.onChange(value) and handle non-object values by
either calling customEvent.onChange with an appropriately typed wrapper or by
calling the original onChange(value) path; alternatively, if primitives are
valid inputs, update the customEvent.onChange signature to accept string |
number | object so no cast is necessary. Ensure references: onChangeInternal,
customEvent.onChange, and onChange are the points to modify.

---

Outside diff comments:
In `@shesha-reactjs/src/components/autocomplete/index.tsx`:
- Around line 121-141: The effect in useEffect reads keyValueFunc,
outcomeValueFunc, allData and source?.tableData but omits them from the
dependency array, creating a stale-closure hazard; either add those dependencies
(keyValueFunc, outcomeValueFunc, allData, source?.tableData) to the array so the
effect reruns when they change, or if you intentionally want to avoid reruns,
add a clear // NOTE: explaining the trade-off and guarantee that keyValueFunc
and outcomeValueFunc are stable/memoized and source.tableData changes are
handled elsewhere; ensure selected.current and getNormalizedValues(props.value)
behavior remains correct with whichever approach you choose.
- Line 49: Restore the real data hook by replacing the stubbed const allData =
{} with a call to useAvailableConstantsData() and add the missing import for
useAvailableConstantsData at the top of the file; then update the dependency
arrays for the callbacks that reference it (keyValueFunc, outcomeValueFunc,
displayValueFunc and any similar functions) to include allData so those memoized
callbacks react to changes in global/form constants. Ensure you reference the
existing symbols allData, useAvailableConstantsData, keyValueFunc,
outcomeValueFunc, displayValueFunc when making the changes.

---

Duplicate comments:
In `@shesha-reactjs/src/designer-components/autocomplete/autocomplete.tsx`:
- Line 93: Remove the redundant fallback for the id field: replace the
expression using both getValueByPropertyName(item, 'id') and item.id with a
single access. Locate the assignment setting id (the line containing id:
getValueByPropertyName(item, 'id') ?? item.id) and simplify it to use only
getValueByPropertyName(item, 'id') or only item.id depending on whether you need
the property-name lookup; ensure the chosen single access preserves the original
null/undefined semantics that the code expects.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fd8bd44 and 1b7aba0.

📒 Files selected for processing (4)
  • shesha-reactjs/src/components/autocomplete/index.tsx
  • shesha-reactjs/src/components/autocomplete/models.tsx
  • shesha-reactjs/src/designer-components/autocomplete/autocomplete.tsx
  • shesha-reactjs/src/utils/object.ts

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@shesha-reactjs/src/designer-components/autocomplete/autocomplete.tsx`:
- Around line 129-134: The onChangeInternal currently only calls
customEvent.onChange when value is an object, which skips custom handling for
primitive/free-text selections; update the guard to detect AntD runtime shape by
checking for the presence of the runtime property (use "'data' in value" or
"'data' in option") instead of only typeof/object checks so customEvent.onChange
is invoked for AntD option objects while primitives still call onChange(value);
adjust the conditional(s) in onChangeInternal accordingly so both
customEvent.onChange(customValue, optionValue) and onChange(value) are called in
the correct scenarios.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1b7aba0 and 0402116.

📒 Files selected for processing (1)
  • shesha-reactjs/src/designer-components/autocomplete/autocomplete.tsx

@Lihlu Lihlu marked this pull request as ready for review February 26, 2026 08:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant