-
Notifications
You must be signed in to change notification settings - Fork 21
feat(admin): adding uniformity in cancel and back buttons present in SCIM & Jans Lock #2408
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
+522
−83
Closed
Changes from 31 commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
69ae0e0
fix(admin-ui): unable to add Custom and Module properties in Scripts …
faisalsiddique4400 38a4851
code rabbit suggestions
faisalsiddique4400 a7c8332
code rabbit suggestions
faisalsiddique4400 5a84bf4
code rabbit suggestions
faisalsiddique4400 4809e95
pagination count issues fixed
faisalsiddique4400 eae25f9
fix(admin-ui): unable to map permission to a role using GUI (#2400)
faisalsiddique4400 94b105b
fix(admin-ui): adding uniformity in cancel and back buttons present …
faisalsiddique4400 4317ea8
Merge branch 'main' of github-faisal:GluuFederation/flex into admin-u…
faisalsiddique4400 b9fd682
Code rabbit suggestions
faisalsiddique4400 9bc53ff
Code rabbit suggestions
faisalsiddique4400 847a607
Code rabbit suggestions
faisalsiddique4400 793a56a
Code rabbit suggestions
faisalsiddique4400 7181998
Code rabbit suggestions
faisalsiddique4400 241e9c6
Code rabbit suggestions
faisalsiddique4400 5dc0919
Code rabbit suggestions
faisalsiddique4400 68f742d
buttons swapping
faisalsiddique4400 ea5aa6b
Code Rabbit fixes
faisalsiddique4400 0cd0df3
Code Rabbit fixes
faisalsiddique4400 7af2074
Code Rabbit fixes
faisalsiddique4400 4e86e97
Code Rabbit fixes
faisalsiddique4400 1bff777
Code Rabbit fixes
faisalsiddique4400 a288f10
Code Rabbit fixes
faisalsiddique4400 cb7b80e
feat(admin): adding uniformity in cancel and back buttons present in …
faisalsiddique4400 4c5e6d3
Merge branch 'main' into admin-ui-issue-2361-scim
faisalsiddique4400 89271ec
Saperating footer components
faisalsiddique4400 75b0358
Code rabbit changes
faisalsiddique4400 c90eec1
Code rabbit changes
faisalsiddique4400 b2b52b0
Code rabbit changes
faisalsiddique4400 8aba204
Code rabbit changes
faisalsiddique4400 f5fc2be
file notations fixes
faisalsiddique4400 00b2d45
file notations fixes
faisalsiddique4400 b9dad66
Rename Gluuformfooter.tsx to GluuFormFooter.tsx
faisalsiddique4400 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,226 @@ | ||
| import { useContext, useMemo, useCallback, memo } from 'react' | ||
| import { useNavigate } from 'react-router-dom' | ||
| import { Button, Divider } from 'Components' | ||
| import { useTranslation } from 'react-i18next' | ||
| import applicationStyle from 'Routes/Apps/Gluu/styles/applicationstyle' | ||
| import { ThemeContext } from 'Context/theme/themeContext' | ||
| import { Box } from '@mui/material' | ||
|
|
||
| interface ButtonLabelProps { | ||
| isLoading: boolean | ||
| iconClass: string | ||
| label: string | ||
| loadingIconClass?: string | ||
| } | ||
|
|
||
| interface GluuformfooterProps { | ||
| showBack?: boolean | ||
| backButtonLabel?: string | ||
| onBack?: () => void | ||
| disableBack?: boolean | ||
| showCancel?: boolean | ||
| cancelButtonLabel?: string | ||
| onCancel?: () => void | ||
| disableCancel?: boolean | ||
| showApply?: boolean | ||
| onApply?: () => void | ||
| disableApply?: boolean | ||
| applyButtonType?: 'button' | 'submit' | ||
| applyButtonLabel?: string | ||
| isLoading?: boolean | ||
| className?: string | ||
| } | ||
|
|
||
| const ButtonLabel = memo((props: ButtonLabelProps) => { | ||
| const { isLoading, iconClass, label, loadingIconClass = 'fa fa-spinner fa-spin' } = props | ||
| return ( | ||
| <> | ||
| <i className={`${isLoading ? loadingIconClass : iconClass} me-2`} /> | ||
| {label} | ||
| </> | ||
| ) | ||
| }) | ||
|
|
||
| ButtonLabel.displayName = 'ButtonLabel' | ||
|
|
||
| const BUTTON_STYLE = { ...applicationStyle.buttonStyle, ...applicationStyle.buttonFlexIconStyles } | ||
|
|
||
| const GluuFormFooter = ({ | ||
| showBack, | ||
| backButtonLabel, | ||
| onBack, | ||
| disableBack, | ||
| showCancel, | ||
| cancelButtonLabel, | ||
| onCancel, | ||
| disableCancel, | ||
| showApply, | ||
| onApply, | ||
| disableApply, | ||
| applyButtonType = 'submit', | ||
| applyButtonLabel, | ||
| isLoading = false, | ||
| className = '', | ||
| }: GluuformfooterProps) => { | ||
| const { t } = useTranslation() | ||
| const theme = useContext(ThemeContext) | ||
| const selectedTheme = useMemo(() => theme?.state.theme || 'darkBlack', [theme?.state.theme]) | ||
| const navigate = useNavigate() | ||
|
|
||
| const handleBackClick = useCallback(() => { | ||
| if (onBack) { | ||
| onBack() | ||
| return | ||
| } else { | ||
| navigate('/home/dashboard') | ||
| } | ||
| }, [onBack, navigate]) | ||
|
|
||
| const handleCancelClick = useCallback(() => { | ||
| if (onCancel) { | ||
| onCancel() | ||
| } | ||
| }, [onCancel]) | ||
|
|
||
| const buttonStates = useMemo(() => { | ||
| const hasAnyButton = Boolean(showBack) || Boolean(showCancel) || Boolean(showApply) | ||
| const hasAllThreeButtons = Boolean(showBack) && Boolean(showCancel) && Boolean(showApply) | ||
| const hasBackAndCancel = Boolean(showBack) && Boolean(showCancel) && !showApply | ||
|
|
||
| return { | ||
| showBack: Boolean(showBack), | ||
| showCancel: Boolean(showCancel), | ||
| showApply: Boolean(showApply), | ||
| hasAnyButton, | ||
| hasAllThreeButtons, | ||
| hasBackAndCancel, | ||
| } | ||
| }, [showBack, showCancel, showApply]) | ||
|
|
||
| const buttonColor = useMemo(() => `primary-${selectedTheme}`, [selectedTheme]) | ||
|
|
||
| const backLabel = useMemo(() => backButtonLabel || t('actions.back'), [backButtonLabel, t]) | ||
| const cancelLabel = useMemo( | ||
| () => cancelButtonLabel || t('actions.cancel'), | ||
| [cancelButtonLabel, t], | ||
| ) | ||
| const applyLabel = useMemo(() => applyButtonLabel || t('actions.apply'), [applyButtonLabel, t]) | ||
|
|
||
| const buttonLayout = useMemo(() => { | ||
| if (!buttonStates.hasAnyButton) { | ||
| return { back: '', cancel: '', apply: '' } | ||
| } | ||
|
|
||
| const layout = { | ||
| back: buttonStates.showBack ? 'd-flex' : '', | ||
| cancel: buttonStates.showCancel ? 'd-flex' : '', | ||
| apply: buttonStates.showApply ? 'd-flex' : '', | ||
| } | ||
|
|
||
| if (buttonStates.showApply) { | ||
| layout.apply += ' ms-auto' | ||
| if (buttonStates.hasAllThreeButtons) { | ||
| layout.apply += ' me-0' | ||
| } | ||
| } else if (buttonStates.showCancel) { | ||
| layout.cancel += ' ms-auto' | ||
| } | ||
|
|
||
| return layout | ||
| }, [buttonStates]) | ||
|
|
||
| if (!buttonStates.hasAnyButton) { | ||
| return null | ||
| } | ||
|
|
||
| return ( | ||
| <> | ||
| <Divider /> | ||
| <Box | ||
| display="flex" | ||
| my={2} | ||
| justifyContent="space-between" | ||
| alignItems="center" | ||
| gap={1} | ||
| className={className} | ||
| > | ||
| {buttonStates.showBack && ( | ||
| <Button | ||
| color={buttonColor} | ||
| style={BUTTON_STYLE} | ||
| type="button" | ||
| onClick={handleBackClick} | ||
| className={buttonLayout.back} | ||
| disabled={disableBack} | ||
| > | ||
| <ButtonLabel isLoading={false} iconClass="fa fa-arrow-circle-left" label={backLabel} /> | ||
| </Button> | ||
| )} | ||
|
|
||
| {buttonStates.showApply && ( | ||
| <Box className={buttonLayout.apply}> | ||
| {applyButtonType === 'submit' ? ( | ||
| <Button | ||
| type="submit" | ||
| color={buttonColor} | ||
| style={BUTTON_STYLE} | ||
| disabled={disableApply || isLoading} | ||
| > | ||
| <ButtonLabel | ||
| isLoading={isLoading} | ||
| iconClass="fa fa-check-circle" | ||
| label={applyLabel} | ||
| /> | ||
| </Button> | ||
| ) : ( | ||
| <Button | ||
| type="button" | ||
| color={buttonColor} | ||
| style={BUTTON_STYLE} | ||
| onClick={onApply} | ||
| disabled={disableApply || isLoading || !onApply} | ||
| > | ||
| <ButtonLabel | ||
| isLoading={isLoading} | ||
| iconClass="fa fa-check-circle" | ||
| label={applyLabel} | ||
| /> | ||
| </Button> | ||
| )} | ||
| </Box> | ||
| )} | ||
|
|
||
| {buttonStates.hasAllThreeButtons && ( | ||
| <Button | ||
| color={buttonColor} | ||
| style={BUTTON_STYLE} | ||
| type="button" | ||
| onClick={handleCancelClick} | ||
| className={`${buttonLayout.cancel} ms-4`} | ||
| disabled={disableCancel || isLoading} | ||
| > | ||
| <ButtonLabel isLoading={false} iconClass="fa fa-undo" label={cancelLabel} /> | ||
| </Button> | ||
| )} | ||
|
|
||
| {!buttonStates.hasAllThreeButtons && buttonStates.showCancel && ( | ||
| <Button | ||
| color={buttonColor} | ||
| style={BUTTON_STYLE} | ||
| type="button" | ||
| onClick={handleCancelClick} | ||
| className={buttonLayout.cancel} | ||
| disabled={disableCancel || isLoading} | ||
| > | ||
| <ButtonLabel isLoading={false} iconClass="fa fa-undo" label={cancelLabel} /> | ||
| </Button> | ||
| )} | ||
| </Box> | ||
| </> | ||
| ) | ||
| } | ||
|
|
||
| const GluuFormFooterMemoized = memo(GluuFormFooter) | ||
| GluuFormFooterMemoized.displayName = 'GluuFormFooter' | ||
|
|
||
| export default GluuFormFooterMemoized |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| import { isEqual } from 'lodash' | ||
|
|
||
| type Primitive = string | number | boolean | null | undefined | ||
|
|
||
| export const isObjectEqual = <T extends Record<string, Primitive | object>>( | ||
| obj1: T, | ||
| obj2: T, | ||
| ): boolean => { | ||
| if (obj1 === obj2) return true | ||
| if (obj1 == null || obj2 == null) return false | ||
| if (typeof obj1 !== 'object' || typeof obj2 !== 'object') return obj1 === obj2 | ||
|
|
||
| return isEqual(obj1, obj2) | ||
| } | ||
|
|
||
| export const hasFormChanges = < | ||
| T extends Record<string, Primitive | object | Array<Primitive | object>>, | ||
| >( | ||
| currentValues: T, | ||
| initialValues: T, | ||
| excludeKeys: Array<keyof T> = [], | ||
| ): boolean => { | ||
| const keys = (Object.keys(currentValues) as Array<keyof T>).filter( | ||
| (key) => !excludeKeys.includes(key), | ||
| ) | ||
|
|
||
| for (const key of keys) { | ||
| const current = currentValues[key] | ||
| const initial = initialValues[key] | ||
|
|
||
| if (typeof current === 'object' && typeof initial === 'object') { | ||
| if (!isEqual(current, initial)) { | ||
| return true | ||
| } | ||
| } else if (current !== initial) { | ||
| return true | ||
| } | ||
| } | ||
|
|
||
| return false | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix dependency array to ensure proper memoization.
The dependency
formik?.values?.[name]won't trigger re-computation correctly because React's dependency comparison doesn't evaluate the optional chain expression—it compares the reference toformik?.values?.[name]itself, not the value. Whenformik.valueschanges, this memo may return stale data.Apply this diff:
const selectedValue = useMemo(() => { if (value !== undefined) { return value } const fieldValue = formik?.values?.[name] return Array.isArray(fieldValue) ? (fieldValue as Option[]) : [] - }, [value, formik?.values?.[name], name]) + }, [value, formik?.values, name])📝 Committable suggestion
🤖 Prompt for AI Agents