Skip to content

feat(admin): adding uniformity in cancel and back buttons present in SCIM & Jans Lock#2404

Merged
duttarnab merged 37 commits intomainfrom
admin-ui-issue-2361-scim
Nov 5, 2025
Merged

feat(admin): adding uniformity in cancel and back buttons present in SCIM & Jans Lock#2404
duttarnab merged 37 commits intomainfrom
admin-ui-issue-2361-scim

Conversation

@faisalsiddique4400
Copy link
Contributor

@faisalsiddique4400 faisalsiddique4400 commented Oct 30, 2025

feat(admin): adding uniformity in cancel and back buttons present in SCIM & Jank Lock

Summary

This update introduces consistent behavior for Cancel, Back, and Apply buttons across Admin UI forms, including correct enabling and disabling based on form state.

Improvements

Button Updated Behavior
Cancel Resets all fields to their previous values without navigating away. Disabled until a change is made.
Back Navigates to the previous page. If there is no navigation history, returns to Dashboard. Always enabled.
Apply Saves the changes without leaving the page. Enabled only when the form has unsaved changes.

Additional Enhancements

  • Buttons now correctly detect dirty form states.
  • Apply button is dynamically enabled and disabled based on whether changes exist.
  • Cancel button is disabled until a field is modified.
  • Prevents accidental navigation or state loss in multi step configuration pages.

Affected Modules

This change is applied across all forms where configuration changes are possible, including but not limited to:

  • SCIM
  • Jans Lock

Parent issue: #2268

Testing Steps

  1. Open suggested config form.
  2. Modify any field.
  3. Verify that:
    • Apply and Cancel buttons become enabled.
    • Apply saves configuration and stays on page.
    • Cancel reverts values and disables itself afterward.
  4. Back button should navigate appropriately.

Summary by CodeRabbit

  • New Features

    • Added "Back" label in English, Spanish, French, and Portuguese.
    • New standardized form footer with configurable Back, Cancel, and Apply controls.
  • Improvements

    • Enhanced typeahead with better selection and form integration.
    • Stronger validation schemas and more accurate dirty-state detection across forms.
    • Clearer submission/loading states and improved cancel behavior for form flows.
  • Bug Fixes

    • More reliable property removal and form patch handling.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 30, 2025

📝 Walkthrough

Walkthrough

Adds a missing "back" translation across locales; introduces typed storage and form utilities; strengthens GluuTypeAhead typing and Formik integration; adds a reusable GluuFormFooter and converts multiple forms to patch-based dirty/validation checks; adds SCIM schema and various component refactors (Jans Lock, Custom Script handling).

Changes

Cohort / File(s) Summary
Translations
admin-ui/app/locales/{en,es,fr,pt}/translation.json
Added "back" key under the actions section for English, Spanish, French, and Portuguese.
New utilities
admin-ui/app/utils/storageUtils.ts, admin-ui/app/utils/formUtils.ts
Added typed localStorage helpers and form comparison utilities (getStorageItem, setStorageItem, removeStorageItem, getStorageNumber, getStorageBoolean, getStorageJSON, setStorageJSON, isObjectEqual, hasFormChanges).
Utility tweaks
admin-ui/app/utils/Util.ts
Relaxed generic constraint for trimObjectStrings and adjusted recursion; mapPropertyToKeyValue now uses nullish coalescing and trimming.
TypeAhead typing + Formik
admin-ui/app/routes/Apps/Gluu/GluuTypeAhead.tsx
Added GluuTypeAheadProps, Option type, Formik integration (setFieldValue), resolved labelKey logic, memoized selected value, wrapped with React.memo.
Property manipulation
admin-ui/app/routes/Apps/Gluu/GluuProperties.tsx
Replaced delete-and-filter with in-place splice() removal in removeProperty to maintain array integrity and Formik sync.
New form footer
admin-ui/app/routes/Apps/Gluu/GluuFormFooter.tsx
New GluuFormFooter component (Back, Cancel, Apply) with configurable handlers, loading/disabled states, translation-backed labels; exported memoized component.
SCIM: schema, helpers, form refactor
admin-ui/plugins/scim/helper/schema.ts, admin-ui/plugins/scim/helper/index.ts, admin-ui/plugins/scim/components/ScimConfiguration.tsx
Added scimConfigurationSchema (Yup) including URL validation and numeric constraints; re-exported schema; swapped to GluuFormFooter, added memoized patch-based dirty/valid checks.
Jans Lock: footer + patches + isSubmitting
admin-ui/plugins/jans-lock/components/JansLockConfiguration.tsx, admin-ui/plugins/jans-lock/components/JansLock.tsx, admin-ui/plugins/jans-lock/helper/utils.ts
Added isSubmitting prop, memoized trimmed values + patches, isFormDirty/isFormValid, precomputed patches for submit, swapped to GluuFormFooter, and skip add-patches for empty arrays/objects.
Custom Script Form
admin-ui/plugins/admin/components/CustomScripts/CustomScriptForm.tsx
transformPropertyForApi preserves optional fields (hide/description); mappings cast to explicit types; removed locationType gating for moduleProperties processing.

Sequence Diagram(s)

sequenceDiagram
    participant U as User
    participant GT as GluuTypeAhead
    participant F as Formik
    participant TA as TypeaheadUI
    U->>GT: selects option
    GT->>GT: handleChange
    alt formik provided
        GT->>F: setFieldValue(name, value)
    end
    GT->>TA: update selected prop
    GT->>U: call onChange (if provided)
Loading
sequenceDiagram
    participant U as User
    participant P as Config Page
    participant F as Formik
    participant Footer as GluuFormFooter
    participant API as API
    P->>F: initialize with configuration
    P->>P: compute patches (createJsonPatchFromDifferences)
    P->>P: derive isFormDirty / isFormValid
    U->>F: edit fields
    F->>P: re-evaluate dirty/valid
    alt Click Cancel
        U->>Footer: Cancel
        Footer->>P: handleCancel -> formik.resetForm()
    else Click Apply
        U->>Footer: Apply
        Footer->>F: trigger submit
        F->>P: onSubmit -> API call (with precomputed patches)
        API->>P: response
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Points requiring attention:

  • GluuTypeAhead Formik integration, labelKey resolution and backward compatibility.
  • GluuFormFooter accessibility/layout and usage across forms.
  • Patch generation logic and new guards for empty arrays/objects (Jans Lock helper and createJsonPatchFromDifferences usage).
  • SCIM schema numeric ranges, URL validation, and sync with form validation usage.
  • storageUtils parsing/coercion and error-handling semantics.

Possibly related PRs

Suggested reviewers

  • syntrydy
  • duttarnab

Poem

🐇 A label "Back" hops into place,
Footers steady forms with tidy grace.
Typed storage hums, patches softly sung,
Typeahead finds values neatly strung.
Carrots for tests — a small celebratory race! 🥕

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly summarizes the main change: adding uniformity in cancel and back buttons in SCIM & Jans Lock components. It accurately reflects the core objective of the changeset.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch admin-ui-issue-2361-scim

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between acb2273 and c131426.

📒 Files selected for processing (1)
  • admin-ui/app/routes/Apps/Gluu/GluuFormFooter.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: faisalsiddique4400
Repo: GluuFederation/flex PR: 2404
File: admin-ui/app/routes/Apps/Gluu/Gluuformfooter.tsx:70-77
Timestamp: 2025-11-03T08:47:33.926Z
Learning: In the admin-ui forms (Gluuformfooter component), the Back button should always navigate to '/home/dashboard' rather than using history-based navigation (navigate(-1)), as clarified by faisalsiddique4400 in PR #2404.
📚 Learning: 2025-11-03T08:47:33.926Z
Learnt from: faisalsiddique4400
Repo: GluuFederation/flex PR: 2404
File: admin-ui/app/routes/Apps/Gluu/Gluuformfooter.tsx:70-77
Timestamp: 2025-11-03T08:47:33.926Z
Learning: In the admin-ui forms (Gluuformfooter component), the Back button should always navigate to '/home/dashboard' rather than using history-based navigation (navigate(-1)), as clarified by faisalsiddique4400 in PR #2404.

Applied to files:

  • admin-ui/app/routes/Apps/Gluu/GluuFormFooter.tsx
🧬 Code graph analysis (1)
admin-ui/app/routes/Apps/Gluu/GluuFormFooter.tsx (1)
admin-ui/plugins/user-management/types/CommonTypes.ts (1)
  • ThemeContext (13-17)
🔇 Additional comments (1)
admin-ui/app/routes/Apps/Gluu/GluuFormFooter.tsx (1)

32-36: Great use of a discriminated union for Apply.

This tightens the API so TypeScript enforces onApply whenever the button isn’t a submit, removing the need for runtime guards. Nice touch.


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

@mo-auto mo-auto added comp-admin-ui Component affected by issue or PR kind-feature Issue or PR is a new feature request labels Oct 30, 2025
@faisalsiddique4400 faisalsiddique4400 marked this pull request as draft October 30, 2025 15:08
@faisalsiddique4400 faisalsiddique4400 marked this pull request as ready for review October 30, 2025 15:33
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: 11

Caution

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

⚠️ Outside diff range comments (3)
admin-ui/app/routes/Apps/Gluu/GluuProperties.tsx (1)

49-71: Avoid undefined options causing runtime errors; sync once.

Default options to [] to prevent .map on undefined and keep effect resilient.

-  const [properties, setProperties] = useState(options)
+  const [properties, setProperties] = useState<Property[]>(options || [])
@@
-  useEffect(() => {
-    setProperties(options)
-  }, [options])
+  useEffect(() => {
+    setProperties(options || [])
+  }, [options])
admin-ui/plugins/admin/components/CustomScripts/CustomScriptForm.tsx (2)

43-51: Script path toggle ignores persisted locationType

scriptPath now derives solely from item.moduleProperties.location_type. Many existing scripts persist locationType only on the top-level field. In that common case this hook initializes to false, so the File path input never renders, validation no longer runs, and the user cannot review or edit the stored path. Please fall back to item.locationType (or the Formik field) when the module property is absent.


417-424: Location type select no longer reflects saved value

The select’s defaultValue now reads getModuleProperty('location_type'), ignoring item.locationType / formik.values.location_type. When the module property is missing (most existing records), the dropdown renders blank and immediately marks the form dirty on first render, enabling Cancel/Apply incorrectly. Bind the control to the actual form value (with a fallback to item.locationType) so persisted selections remain visible.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a4b296b and 94b105b.

📒 Files selected for processing (24)
  • admin-ui/app/locales/en/translation.json (1 hunks)
  • admin-ui/app/locales/es/translation.json (1 hunks)
  • admin-ui/app/locales/fr/translation.json (1 hunks)
  • admin-ui/app/locales/pt/translation.json (1 hunks)
  • admin-ui/app/routes/Apps/Gluu/GluuCommitFooter.tsx (2 hunks)
  • admin-ui/app/routes/Apps/Gluu/GluuDialog.tsx (2 hunks)
  • admin-ui/app/routes/Apps/Gluu/GluuProperties.tsx (3 hunks)
  • admin-ui/app/routes/Apps/Gluu/GluuTypeAhead.tsx (5 hunks)
  • admin-ui/app/utils/Util.ts (1 hunks)
  • admin-ui/app/utils/formUtils.ts (1 hunks)
  • admin-ui/app/utils/storageUtils.ts (1 hunks)
  • admin-ui/package.json (1 hunks)
  • admin-ui/plugins/admin/components/CustomScripts/CustomScriptAddPage.tsx (1 hunks)
  • admin-ui/plugins/admin/components/CustomScripts/CustomScriptEditPage.tsx (1 hunks)
  • admin-ui/plugins/admin/components/CustomScripts/CustomScriptForm.tsx (10 hunks)
  • admin-ui/plugins/admin/components/CustomScripts/types/forms.ts (1 hunks)
  • admin-ui/plugins/admin/components/Mapping/MappingItem.js (1 hunks)
  • admin-ui/plugins/admin/redux/features/customScriptSlice.ts (2 hunks)
  • admin-ui/plugins/fido/components/DynamicConfiguration.tsx (1 hunks)
  • admin-ui/plugins/fido/components/StaticConfiguration.tsx (1 hunks)
  • admin-ui/plugins/scim/components/ScimConfiguration.tsx (4 hunks)
  • admin-ui/plugins/scim/helper/index.ts (1 hunks)
  • admin-ui/plugins/scim/helper/schema.ts (1 hunks)
  • admin-ui/plugins/scim/helper/validations.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (7)
admin-ui/plugins/fido/components/DynamicConfiguration.tsx (1)
admin-ui/plugins/auth-server/components/Ssa/SsaAddPage.js (1)
  • isSubmitting (48-48)
admin-ui/plugins/admin/components/Mapping/MappingItem.js (3)
admin-ui/plugins/admin/components/Settings/SettingsPage.js (1)
  • initialValues (84-87)
admin-ui/plugins/auth-server/components/Configuration/Defaults/LoggingPage.js (1)
  • initialValues (55-64)
admin-ui/plugins/auth-server/components/AuthN/AuthNForm.js (1)
  • initialValues (21-42)
admin-ui/plugins/scim/helper/schema.ts (2)
admin-ui/plugins/scim/helper/validations.ts (1)
  • scimConfigurationSchema (1-1)
admin-ui/plugins/scim/helper/constants.ts (1)
  • PROTECTION_MODES (3-3)
admin-ui/plugins/admin/components/CustomScripts/types/forms.ts (2)
admin-ui/plugins/admin/redux/features/types/customScript.ts (2)
  • ModuleProperty (3-8)
  • ConfigurationProperty (10-16)
admin-ui/plugins/admin/components/CustomScripts/types/customScript.ts (2)
  • ModuleProperty (3-10)
  • ConfigurationProperty (12-18)
admin-ui/plugins/scim/components/ScimConfiguration.tsx (3)
admin-ui/plugins/scim/helper/schema.ts (1)
  • scimConfigurationSchema (19-66)
admin-ui/plugins/scim/helper/utils.ts (1)
  • createJsonPatchFromDifferences (45-142)
admin-ui/plugins/scim/types/index.ts (1)
  • ScimFormValues (3-24)
admin-ui/app/routes/Apps/Gluu/GluuCommitFooter.tsx (3)
admin-ui/plugins/admin/components/Settings/SettingsPage.js (3)
  • useTranslation (36-36)
  • theme (38-38)
  • selectedTheme (39-39)
admin-ui/plugins/services/Components/Configuration/SqlListPage.js (4)
  • useTranslation (54-54)
  • theme (66-66)
  • selectedTheme (67-67)
  • navigate (57-57)
admin-ui/plugins/user-management/types/CommonTypes.ts (1)
  • ThemeContext (13-17)
admin-ui/plugins/admin/components/CustomScripts/CustomScriptForm.tsx (3)
admin-ui/plugins/admin/components/CustomScripts/types/customScript.ts (3)
  • ModuleProperty (3-10)
  • ConfigurationProperty (12-18)
  • CustomScriptItem (29-49)
admin-ui/app/utils/Util.ts (2)
  • filterEmptyObjects (80-82)
  • mapPropertyToKeyValue (84-94)
admin-ui/plugins/admin/components/CustomScripts/types/forms.ts (1)
  • FormValues (15-29)
🔇 Additional comments (27)
admin-ui/plugins/admin/components/CustomScripts/CustomScriptAddPage.tsx (1)

9-9: LGTM! Clean removal of unused imports.

The import cleanup successfully removes applicationStyle and CustomScriptReducerState which are not referenced in this file. All remaining type imports (CustomScriptItem, RootState, UserAction, SubmitData) are actively used throughout the component.

admin-ui/package.json (1)

36-38: New npm scripts are production-ready and properly configured.

The three new scripts follow npm conventions and integrate seamlessly with the existing codebase:

  • lint:check: read-only ESLint validation paired with the existing lint script's --fix
  • type-check: TypeScript type validation using the well-configured admin-ui/tsconfig.json
  • check:all: sequential composition for comprehensive validation

All required dependencies (eslint, typescript, TypeScript ESLint plugins, and typescript-plugin-css-modules) are present, and tsconfig.json properly supports the lint and type-check targets. The scripts align with the PR's emphasis on code quality and form control consistency.

admin-ui/plugins/scim/helper/validations.ts (1)

1-1: LGTM!

Clean refactor that maintains backward compatibility while consolidating schema definitions.

admin-ui/plugins/scim/helper/index.ts (1)

3-4: LGTM!

Appropriate expansion of the public API to include schema and validation exports.

admin-ui/plugins/scim/components/ScimConfiguration.tsx (2)

31-49: LGTM!

The form dirty and validity tracking logic is well-implemented with proper memoization. The dirty check correctly excludes action_message and uses JSON patch differences to detect changes.


59-61: LGTM!

Cancel handler correctly resets the form to initial values.

admin-ui/plugins/admin/components/CustomScripts/types/forms.ts (2)

31-34: LGTM! Clean utility type definition.

The PropertyOptionMap type provides a clear contract for transforming property arrays into option arrays. The signature correctly allows for undefined input while guaranteeing an array output (implementations should return an empty array for undefined).


21-21: No verification issues found - the optional field changes are correctly implemented.

Making script and locationPath optional is not a breaking change because:

  1. Localized scope: FormValues is only used internally in CustomScriptForm.tsx — no external code depends on these fields.

  2. Proper handling: The code already safely manages these optional fields:

    • Conditional rendering at line 519 prevents the script editor from displaying when inappropriate
    • Error handling includes proper guards (line 532: formik.errors.script && formik.touched.script)
    • Business logic explicitly sets one field to undefined based on locationType (lines 127-131)
  3. Intentional design: The optionality reflects the actual runtime behavior — either script or locationPath is used depending on whether the script source is database-driven or file-based, not both.

All existing accesses already include appropriate safeguards.

admin-ui/app/locales/fr/translation.json (1)

134-134: LGTM! Translation is correct.

The French translation "Retour" for "back" is accurate and properly placed under the actions section.

admin-ui/plugins/fido/components/StaticConfiguration.tsx (1)

351-351: Good UX improvement!

Changing from disabled to isLoading provides better visual feedback to users during form submission by showing a loading indicator instead of just disabling the button.

admin-ui/app/locales/es/translation.json (1)

23-23: LGTM! Translation is correct.

The Spanish translation "Atrás" for "back" is accurate and properly placed under the actions section.

admin-ui/plugins/admin/redux/features/customScriptSlice.ts (2)

57-57: Good state management improvement.

Incrementing totalItems when a script is successfully added keeps the count accurate and in sync with the actual data.


97-97: Good defensive programming.

Using Math.max(0, state.totalItems - 1) ensures the count never goes negative, which is a good safeguard.

admin-ui/plugins/admin/components/CustomScripts/CustomScriptEditPage.tsx (1)

11-11: Good code cleanup.

Removing unused imports keeps the dependencies minimal and the code cleaner.

admin-ui/app/locales/pt/translation.json (1)

132-132: PT actions.back added — OK.

Label “Voltar” is appropriate and consistent with EN.

admin-ui/plugins/admin/components/Mapping/MappingItem.js (2)

103-103: Formik initialValues for Typeahead — correct.

Initializing mappingAddPermissions as [] aligns with GluuTypeAhead’s Formik sync and multiple selection.


191-207: Removed forced value prop — good integration with Formik.

Letting GluuTypeAhead derive selected from formik is correct. The explicit ref clear after resetForm may be redundant but harmless.

Confirm the addPermissionsToRole API accepts an array of strings; if objects are ever used as options, pass labelKey and onChange mappers accordingly.

admin-ui/app/routes/Apps/Gluu/GluuDialog.tsx (2)

44-50: Reset message on open — good UX.

Prevents stale text when confirming different items.


75-75: Deletion header fallback — robust.

Prefers row.name and appends inum/id when present; reads well.

admin-ui/app/utils/Util.ts (1)

80-82: filterEmptyObjects — concise and safe.

Correctly drops nullish/empty objects.

admin-ui/app/routes/Apps/Gluu/GluuTypeAhead.tsx (3)

73-91: Formik synchronization and controlled selected — solid.

selected derives from value or formik; onChange updates formik then invokes onChange. This is the right pattern.

Also applies to: 118-126


66-70: Confirm or change multiple default to preserve single-select behavior for existing callers.

The default multiple = true is a breaking change. Of the many GluuTypeAhead usages across the codebase, only one explicitly sets multiple={false} (AssetForm.tsx:190), while at least 10+ usages in SqlForm.js, LdapForm.js, WebhookForm.js, MappingAddDialogForm.js, StaticConfiguration.tsx, and JansLockConfiguration.tsx don't pass the prop at all. This pattern indicates the original default was likely false (single-select), and existing callers depend on that behavior. Changing it to true will unexpectedly return arrays for fields that should remain single-select, breaking data handling in these forms.

Revert to multiple = false unless the change was intentional to update all dependent forms.


92-93: The labelKey fallback is safe and properly implemented.

Verification confirms all object-based options in the codebase include a name property when constructed (e.g., postScripts, updateTokenScriptDns, consentScripts, all map to { dn: item.dn, name: item.name }). String array options require no labelKey and render directly. No usage violations found.

admin-ui/app/routes/Apps/Gluu/GluuProperties.tsx (2)

43-47: State reset on options change — good.

Keeps internal state aligned with Formik resets.


72-87: Formik sync paths — clear and correct.

Updating valuesOnly when !isKeys && !multiProperties and full array otherwise matches expected payload shapes.

admin-ui/plugins/fido/components/DynamicConfiguration.tsx (1)

311-312: GluuCommitFooter isLoading adoption confirmed — no action needed.

Verification shows: (1) the component interface includes isLoading as an optional prop, (2) no other GluuCommitFooter usages have a disabled prop, and (3) the DynamicConfiguration.tsx change correctly uses isLoading={isSubmitting}. The adoption is complete and correct.

admin-ui/app/locales/en/translation.json (1)

23-23: Locale coverage verified — all supported locales include actions.back.

Verification confirms "actions.back" is present in all 4 supported locales (en, pt, fr, es) with proper translations. Code correctly uses t('actions.back') in GluuCommitFooter.tsx. No gaps found.

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: 5

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 94b105b and b9fd682.

📒 Files selected for processing (9)
  • admin-ui/app/routes/Apps/Gluu/GluuCommitFooter.tsx (2 hunks)
  • admin-ui/app/routes/Apps/Gluu/GluuProperties.tsx (1 hunks)
  • admin-ui/app/routes/Apps/Gluu/GluuTypeAhead.tsx (5 hunks)
  • admin-ui/app/utils/Util.ts (1 hunks)
  • admin-ui/app/utils/formUtils.ts (1 hunks)
  • admin-ui/app/utils/storageUtils.ts (1 hunks)
  • admin-ui/plugins/admin/components/CustomScripts/CustomScriptForm.tsx (2 hunks)
  • admin-ui/plugins/scim/components/ScimConfiguration.tsx (4 hunks)
  • admin-ui/plugins/scim/helper/schema.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (5)
admin-ui/plugins/scim/components/ScimConfiguration.tsx (3)
admin-ui/plugins/scim/helper/schema.ts (1)
  • scimConfigurationSchema (14-61)
admin-ui/plugins/scim/helper/utils.ts (1)
  • createJsonPatchFromDifferences (45-142)
admin-ui/plugins/scim/types/index.ts (1)
  • ScimFormValues (3-24)
admin-ui/app/routes/Apps/Gluu/GluuProperties.tsx (1)
admin-ui/plugins/auth-server/components/Configuration/ConfigPage.js (1)
  • properties (45-45)
admin-ui/plugins/scim/helper/schema.ts (2)
admin-ui/plugins/scim/helper/validations.ts (1)
  • scimConfigurationSchema (1-1)
admin-ui/plugins/scim/helper/constants.ts (1)
  • PROTECTION_MODES (3-3)
admin-ui/plugins/admin/components/CustomScripts/CustomScriptForm.tsx (3)
admin-ui/plugins/admin/redux/features/types/customScript.ts (2)
  • ModuleProperty (3-8)
  • ConfigurationProperty (10-16)
admin-ui/plugins/admin/components/CustomScripts/types/customScript.ts (2)
  • ModuleProperty (3-10)
  • ConfigurationProperty (12-18)
admin-ui/app/utils/Util.ts (1)
  • filterEmptyObjects (80-82)
admin-ui/app/routes/Apps/Gluu/GluuCommitFooter.tsx (3)
admin-ui/plugins/admin/components/Settings/SettingsPage.js (2)
  • theme (38-38)
  • selectedTheme (39-39)
admin-ui/plugins/services/Components/Configuration/LdapListPage.js (3)
  • theme (57-57)
  • selectedTheme (58-58)
  • navigate (42-42)
admin-ui/plugins/user-management/types/CommonTypes.ts (1)
  • ThemeContext (13-17)
🔇 Additional comments (3)
admin-ui/plugins/admin/components/CustomScripts/CustomScriptForm.tsx (1)

74-85: Based on the Jans API documentation, moduleProperties examples show only value1, value2, and description fields, with no hide field. In contrast, configurationProperties includes a hide field with boolean values (e.g., "hide": true).

The transformPropertyForApi function applies the same logic to both property types, which creates a problem: it defaults hide to false for moduleProperties, but the API schema shows hide should never appear in moduleProperties.

Omit hide for moduleProperties and conditionally include it only for configurationProperties.

Update the function to distinguish between the two property types:

  • For configurationProperties: conditionally include hide only when defined
  • For moduleProperties: never include hide

The description handling should also preserve empty strings if valid.

admin-ui/plugins/scim/helper/schema.ts (1)

1-61: LGTM! Schema implementation is solid.

The validation schema is well-structured with appropriate validations for each field:

  • URL validation correctly checks for HTTP/HTTPS protocols while treating empty values as valid (optional field)
  • Numeric fields have proper type checking, range limits, and user-friendly error messages
  • The isSecureUrl function is correctly used directly in the Yup test at line 19, as Yup passes the value as the first parameter to the test function

The schema provides comprehensive validation coverage for the SCIM configuration form.

admin-ui/plugins/scim/components/ScimConfiguration.tsx (1)

81-92: LGTM! Button states correctly implement PR objectives.

The button behavior perfectly aligns with the PR requirements:

  • Back (line 87): Always enabled (disableBack={false}) ✓
  • Cancel (line 88): Disabled until form is modified (disableCancel={!isFormDirty}) ✓
  • Apply (line 89): Enabled only when form is valid and has unsaved changes (disableApply={!isFormValid || !isFormDirty}) ✓

The implementation provides clear user feedback about form state and prevents invalid submissions while allowing users to navigate away or reset changes as needed.

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: 5

Caution

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

⚠️ Outside diff range comments (1)
admin-ui/plugins/admin/components/CustomScripts/CustomScriptForm.tsx (1)

147-151: Inconsistent data source causes filtered properties to be ignored.

The filtering at lines 128-133 modifies item.moduleProperties to remove location_path, but lines 147-151 build submitValues.moduleProperties from values.moduleProperties. When Object.assign(item, submitValues) executes at line 159, the unfiltered values.moduleProperties overwrites the filtered item.moduleProperties, causing location_path to be sent to the API even when locationType === 'db'.

Additionally, since the GluuProperties component (line 517) updates formik.values.moduleProperties, using item.moduleProperties for filtering means user edits are ignored.

Apply this diff to filter values.moduleProperties consistently:

       if (values.moduleProperties) {
+        let modulePropsToSubmit = values.moduleProperties
+        if (item.locationType === 'db') {
+          modulePropsToSubmit = values.moduleProperties.filter(
+            (moduleItem: ModuleProperty) => moduleItem?.value1 !== 'location_path',
+          )
+        }
-        submitValues.moduleProperties = filterEmptyObjects(values.moduleProperties).map(
+        submitValues.moduleProperties = filterEmptyObjects(modulePropsToSubmit).map(
           transformPropertyForApi,
         )
       }

You can also remove the now-redundant filtering at lines 128-133 since the filtering will happen here.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b9fd682 and 9bc53ff.

📒 Files selected for processing (5)
  • admin-ui/app/routes/Apps/Gluu/GluuTypeAhead.tsx (5 hunks)
  • admin-ui/app/utils/Util.ts (1 hunks)
  • admin-ui/app/utils/storageUtils.ts (1 hunks)
  • admin-ui/plugins/admin/components/CustomScripts/CustomScriptForm.tsx (2 hunks)
  • admin-ui/plugins/scim/components/ScimConfiguration.tsx (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
admin-ui/plugins/scim/components/ScimConfiguration.tsx (4)
admin-ui/plugins/scim/helper/schema.ts (1)
  • scimConfigurationSchema (14-61)
admin-ui/plugins/scim/helper/validations.ts (1)
  • scimConfigurationSchema (1-1)
admin-ui/plugins/scim/helper/utils.ts (1)
  • createJsonPatchFromDifferences (45-142)
admin-ui/plugins/scim/types/index.ts (1)
  • ScimFormValues (3-24)
admin-ui/plugins/admin/components/CustomScripts/CustomScriptForm.tsx (2)
admin-ui/plugins/admin/redux/features/types/customScript.ts (2)
  • ModuleProperty (3-8)
  • ConfigurationProperty (10-16)
admin-ui/plugins/admin/components/CustomScripts/types/customScript.ts (2)
  • ModuleProperty (3-10)
  • ConfigurationProperty (12-18)
🔇 Additional comments (10)
admin-ui/plugins/scim/components/ScimConfiguration.tsx (5)

2-7: LGTM! Import changes align with new form state management.

The added hooks (useMemo, useCallback) and utilities (createJsonPatchFromDifferences) are used appropriately throughout the component for optimized dirty-checking and memoized handlers.


31-42: Excellent! Dirty-checking logic is robust and addresses previous feedback.

The patch-based dirty detection correctly excludes the UI-only action_message field and efficiently compares form state. The switch to eslint-disable-next-line (line 35) properly addresses the previous review comment about the void action_message pattern.


44-49: LGTM! Form validation check is correctly implemented.

Using isValidSync for real-time validation is appropriate and efficiently determines whether the Apply button should be enabled.


59-61: LGTM! Cancel handler correctly resets form to initial values.

The implementation properly fulfills the PR objective: "Cancel resets all fields to previous values without navigating away."


81-92: Excellent implementation! Footer button behavior perfectly aligns with PR objectives.

The button states correctly implement all requirements:

  • Back is always enabled (line 87: disableBack={false}) ✓
  • Cancel is disabled until changes are made (line 88: disableCancel={!isFormDirty}) ✓
  • Apply is enabled only when form is valid and has unsaved changes (line 89) ✓

This addresses the previous review comment about Back button enablement and implements the complete feature as specified.

admin-ui/app/routes/Apps/Gluu/GluuTypeAhead.tsx (2)

92-97: LGTM! Past critical issue resolved.

The resolvedLabelKey logic correctly returns the string literal 'name' as the fallback (line 96), addressing the previous critical comment about blank typeahead labels caused by returning the variable name (which would be the form field name like "scimProperties").


22-45: Interface is well-structured.

The labelKey typing as string | ((option: Option) => string) correctly addresses the past refactoring suggestion to match the react-bootstrap-typeahead library's API. The comprehensive prop definitions provide good type safety for consumers.

admin-ui/app/utils/Util.ts (1)

90-92: LGTM! Nullish coalescing correctly preserves empty strings.

The implementation now uses ?? instead of ||, which preserves empty strings as valid values (e.g., { key: '', value1: 'fallback' } → key = ''). The .trim() call normalizes whitespace without the need for a String() wrapper.

admin-ui/app/utils/storageUtils.ts (2)

3-41: LGTM! Correctly handles empty strings and type coercion.

The implementation correctly addresses past review concerns:

  • Line 10 uses stored === null instead of !stored, allowing empty strings to round-trip properly
  • Type coercion based on defaultValue type (boolean, number, object) works correctly
  • The special handling of the literal "null" string (line 17) ensures proper round-trip for null values
  • Error handling with fallback to defaultValue is appropriate

43-60: LGTM! Correctly removes key when value is null.

The implementation correctly addresses the past review concern by removing the key (line 50) instead of stringifying null to "null". This prevents type confusion on subsequent reads.

Note: The type StorageValue excludes undefined, which prevents accidental storage of the string "undefined". This is good defensive typing.

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

♻️ Duplicate comments (1)
admin-ui/plugins/admin/components/CustomScripts/CustomScriptForm.tsx (1)

151-155: Location_path filtering is undone before API submission.

When locationType === 'db', lines 132-136 filter location_path from item.moduleProperties. However, lines 151-154 read from values.moduleProperties (which hasn't been filtered) and assign the result to submitValues.moduleProperties. Subsequently, line 163's Object.assign(item, submitValues) overwrites the filtered item.moduleProperties with the unfiltered content from submitValues.moduleProperties, so location_path is still sent to the API.

Apply this diff to filter values.moduleProperties before transformation when locationType === 'db':

       if (values.moduleProperties) {
+        let modulePropsToSubmit = values.moduleProperties
+        if (item.locationType === 'db') {
+          modulePropsToSubmit = modulePropsToSubmit.filter(
+            (moduleItem: ModuleProperty) => moduleItem?.value1 !== 'location_path',
+          )
+        }
-        submitValues.moduleProperties = filterEmptyObjects(values.moduleProperties).map(
+        submitValues.moduleProperties = filterEmptyObjects(modulePropsToSubmit).map(
           transformPropertyForApi,
         ) as ModuleProperty[]
       }

Alternatively, you can remove the redundant filtering at lines 132-136 since the filtering would now happen at lines 151-155.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9bc53ff and 847a607.

📒 Files selected for processing (3)
  • admin-ui/app/routes/Apps/Gluu/GluuTypeAhead.tsx (5 hunks)
  • admin-ui/app/utils/storageUtils.ts (1 hunks)
  • admin-ui/plugins/admin/components/CustomScripts/CustomScriptForm.tsx (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
admin-ui/plugins/admin/components/CustomScripts/CustomScriptForm.tsx (3)
admin-ui/plugins/admin/redux/features/types/customScript.ts (2)
  • ModuleProperty (3-8)
  • ConfigurationProperty (10-16)
admin-ui/plugins/admin/components/CustomScripts/types/customScript.ts (2)
  • ModuleProperty (3-10)
  • ConfigurationProperty (12-18)
admin-ui/app/utils/Util.ts (1)
  • filterEmptyObjects (80-82)
🔇 Additional comments (7)
admin-ui/plugins/admin/components/CustomScripts/CustomScriptForm.tsx (2)

75-89: LGTM: Metadata preservation now correctly implemented.

The transformPropertyForApi function now properly preserves optional fields (hide and description) when present, addressing the previous concern about forcing hide: false and dropping metadata.

One minor note: description is only included when truthy (line 85), so an empty string "" would be excluded. This is likely intentional to avoid sending empty descriptions to the API.


146-149: LGTM: Configuration properties transformation is correct.

The transformation of configurationProperties properly filters empty objects and applies the corrected transformPropertyForApi function with appropriate type casting.

admin-ui/app/routes/Apps/Gluu/GluuTypeAhead.tsx (5)

22-45: Well-structured interface with proper typing.

The interface comprehensively covers all component props with appropriate types. The labelKey typing now correctly supports both string and function forms, addressing the previous review feedback.


73-79: Properly implemented with correct dependencies and type safety.

The memo correctly addresses previous feedback:

  • Dependencies now track the actual field value (formik?.values?.[name]) instead of the stable formik reference
  • Runtime Array.isArray check before type assertion prevents unsafe casts

The implementation ensures selectedValue recomputes when the field changes and safely handles both controlled (value prop) and Formik-managed state.


81-93: Clean implementation with narrowed dependencies.

The callback correctly addresses previous feedback by depending on formik?.setFieldValue rather than the entire formik object. This makes the dependency precise and clarifies that only setFieldValue is used.

The logic properly handles both Formik-managed and standalone usage patterns.


95-100: Correctly returns the literal 'name' string.

This addresses the previous critical issue. The memo now returns the literal string 'name' (line 99) instead of the form field name variable, ensuring the typeahead properly displays each option's name property rather than rendering blank labels.


102-147: Clean integration of memoized values and callbacks.

The render logic correctly uses the memoized resolvedLabelKey, handleChange, and selectedValue, ensuring optimal performance and correct behavior. The component is properly wrapped with React.memo to prevent unnecessary re-renders.

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

♻️ Duplicate comments (1)
admin-ui/app/utils/storageUtils.ts (1)

76-81: Same empty-string issue as the base getStorageItem.

The parser uses Number(value) which converts '' and whitespace to 0 instead of falling back to defaultValue. Apply the same empty-string check suggested for lines 20-23 to keep the behavior consistent.

Apply this diff:

 export const getStorageNumber = (key: string, defaultValue: number): number => {
   return getStorageItem(key, defaultValue, (value) => {
+    const trimmed = value.trim()
+    if (trimmed === '') return defaultValue
-    const parsed = Number(value)
+    const parsed = Number(trimmed)
     return isNaN(parsed) ? defaultValue : parsed
   })
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 847a607 and 793a56a.

📒 Files selected for processing (1)
  • admin-ui/app/utils/storageUtils.ts (1 hunks)
🔇 Additional comments (5)
admin-ui/app/utils/storageUtils.ts (5)

40-64: LGTM!

The setter correctly handles all edge cases: null values remove the key, objects are JSON-serialized, and custom serializers are supported. Error handling is robust.


66-74: LGTM!

Simple, correct wrapper with appropriate error handling and boolean return.


83-85: LGTM!

Boolean parsing is consistent with the base function and uses a simple, predictable rule: only the string 'true' parses to true.


87-96: LGTM!

While getStorageItem already handles objects via JSON, this specialized helper provides a cleaner, more explicit API for JSON use cases. The error handling and type constraints are appropriate.


98-106: LGTM!

Specialized setter provides a cleaner API for JSON values. The error handling is consistent with other functions.

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: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 793a56a and 7181998.

📒 Files selected for processing (1)
  • admin-ui/app/utils/storageUtils.ts (1 hunks)
🔇 Additional comments (1)
admin-ui/app/utils/storageUtils.ts (1)

43-67: LGTM! Clean serialization logic.

The function correctly handles all the edge cases:

  • null values trigger key removal
  • Objects are JSON-serialized when no custom serializer is provided
  • Custom serializers are respected
  • Errors are caught and logged

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: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d14e1b6 and acb2273.

📒 Files selected for processing (1)
  • admin-ui/app/routes/Apps/Gluu/GluuFormFooter.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: faisalsiddique4400
Repo: GluuFederation/flex PR: 2404
File: admin-ui/app/routes/Apps/Gluu/Gluuformfooter.tsx:70-77
Timestamp: 2025-11-03T08:47:33.926Z
Learning: In the admin-ui forms (Gluuformfooter component), the Back button should always navigate to '/home/dashboard' rather than using history-based navigation (navigate(-1)), as clarified by faisalsiddique4400 in PR #2404.
📚 Learning: 2025-11-03T08:47:33.926Z
Learnt from: faisalsiddique4400
Repo: GluuFederation/flex PR: 2404
File: admin-ui/app/routes/Apps/Gluu/Gluuformfooter.tsx:70-77
Timestamp: 2025-11-03T08:47:33.926Z
Learning: In the admin-ui forms (Gluuformfooter component), the Back button should always navigate to '/home/dashboard' rather than using history-based navigation (navigate(-1)), as clarified by faisalsiddique4400 in PR #2404.

Applied to files:

  • admin-ui/app/routes/Apps/Gluu/GluuFormFooter.tsx
🧬 Code graph analysis (1)
admin-ui/app/routes/Apps/Gluu/GluuFormFooter.tsx (1)
admin-ui/plugins/user-management/types/CommonTypes.ts (1)
  • ThemeContext (13-17)
🔇 Additional comments (7)
admin-ui/app/routes/Apps/Gluu/GluuFormFooter.tsx (7)

34-44: Well-implemented memoized button label component.

The ButtonLabel component effectively handles loading states with a clean conditional icon render and proper displayName for debugging.


48-68: Solid component initialization with proper defaults.

The component setup correctly uses React hooks, provides sensible defaults, and safely handles theme context with optional chaining and fallbacks.


70-76: Back navigation correctly implements dashboard-only navigation.

The implementation properly navigates to /home/dashboard as per project requirements, avoiding history-based navigation. Clean callback structure with appropriate dependencies.

Based on learnings


146-157: Back button correctly remains enabled during form submission.

The Back button's disabled state properly excludes isLoading (line 153), allowing users to navigate away during form submission. This addresses the previous review feedback.


159-190: Apply button correctly handles both submit and button variants.

Both button types properly disable during loading and include appropriate safety checks. The button variant correctly validates onApply existence at line 180 before allowing interaction.


192-203: Cancel button consolidation successfully completed.

The Cancel button render has been properly consolidated into a single element with conditional className logic, addressing previous feedback about duplication.


209-212: Proper component memoization and export.

The component is correctly memoized with memo and includes a displayName for better debugging experience in React DevTools.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Nov 5, 2025

@faisalsiddique4400 faisalsiddique4400 requested review from moabu and removed request for syntrydy November 5, 2025 07:51
@duttarnab duttarnab merged commit d18a5f1 into main Nov 5, 2025
13 checks passed
@duttarnab duttarnab deleted the admin-ui-issue-2361-scim branch November 5, 2025 11:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp-admin-ui Component affected by issue or PR kind-feature Issue or PR is a new feature request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants