Skip to content
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

feat: add support for disabling the save button while the permissions are loading #2315

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,15 @@ const CreateAPIToken = ({
invalidDescription: false,
invalidDescriptionMessage: '',
})
const { permissionType, directPermission, setDirectPermission, chartPermission, k8sPermission, userRoleGroups } =
usePermissionConfiguration()
const {
permissionType,
directPermission,
setDirectPermission,
chartPermission,
k8sPermission,
userRoleGroups,
isSaveDisabled,
} = usePermissionConfiguration()
const [customDate, setCustomDate] = useState<Moment>(null)
const validationRules = new ValidationRules()

Expand Down Expand Up @@ -307,6 +314,7 @@ const CreateAPIToken = ({
}}
onSave={handleGenerateAPIToken}
buttonText="Generate token"
disabled={isSaveDisabled}
/>
{showGenerateModal && (
<GenerateModal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,15 @@ const EditAPIToken = ({
isLoading: boolean
setEditData: (editData: EditDataType) => void
}) => {
const { permissionType, directPermission, setDirectPermission, chartPermission, k8sPermission, userRoleGroups } =
usePermissionConfiguration()
const {
permissionType,
directPermission,
setDirectPermission,
chartPermission,
k8sPermission,
userRoleGroups,
isSaveDisabled,
} = usePermissionConfiguration()

const history = useHistory()
const match = useRouteMatch()
Expand Down Expand Up @@ -281,6 +288,7 @@ const EditAPIToken = ({
onCancel={redirectToTokenList}
onSave={() => handleUpdatedToken(editData.id)}
buttonText="Update token"
disabled={isSaveDisabled}
/>
{deleteConfirmation && (
<DeleteAPITokenModal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,14 @@
import { ButtonWithLoader } from '@devtron-labs/devtron-fe-common-lib'
import { GenerateActionButtonType } from './apiToken.type'

const GenerateActionButton = ({ loader, onCancel, onSave, buttonText, regenerateButton }: GenerateActionButtonType) => (
const GenerateActionButton = ({
loader,
onCancel,
onSave,
buttonText,
regenerateButton,
disabled,
}: GenerateActionButtonType) => (
<div
className={`modal__buttons w-100 pl-16 pt-16 pr-16 flex ${
regenerateButton ? 'right ml-auto' : 'left ml-0'
Expand All @@ -35,7 +42,7 @@ const GenerateActionButton = ({ loader, onCancel, onSave, buttonText, regenerate
<ButtonWithLoader
rootClassName={`flex cta h-36 ${regenerateButton ? 'order-second' : 'mr-12 order-first'}`}
onClick={onSave}
disabled={loader}
disabled={loader || disabled}
isLoading={loader}
dataTestId={buttonText.toLowerCase().replace(' ', '-')}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ const RegeneratedModal = ({
onSave={handleRegenrateToken}
buttonText="Regenerate Token"
regenerateButton
disabled={false}
/>
</div>
</VisibleModal>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export interface GenerateActionButtonType {
onSave: () => void
buttonText: string
regenerateButton?: boolean
disabled: boolean
}

export interface GenerateTokenModalType {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const PermissionGroupForm = ({ isAddMode }: { isAddMode: boolean }) => {
k8sPermission,
currentK8sPermissionRef,
data: permissionGroup,
isSaveDisabled,
} = usePermissionConfiguration()
const _permissionGroup = permissionGroup as PermissionGroup

Expand Down Expand Up @@ -217,7 +218,7 @@ const PermissionGroupForm = ({ isAddMode }: { isAddMode: boolean }) => {
text="Save"
onClick={handleSubmit}
size={ComponentSizeType.medium}
disabled={submitting}
disabled={isSaveDisabled}
isLoading={submitting}
buttonProps={{
type: 'submit',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ const AppPermissionDetail = ({
const isAccessTypeJob = accessType === ACCESS_TYPE_MAP.JOBS
const rowClass = getPermissionDetailRowClass(accessType, showStatus)

const handleAddPermission = () => {
addNewPermissionRow(accessType)
}

return (
<>
<div className={`w-100 pt-6 pb-6 dc__gap-8 display-grid ${rowClass} fw-6 fs-12 cn-7 dc__uppercase`}>
Expand Down Expand Up @@ -86,7 +90,7 @@ const AppPermissionDetail = ({
<Button
text="Add Permission"
startIcon={<AddIcon />}
onClick={() => addNewPermissionRow(accessType)}
onClick={handleAddPermission}
dataTestId="add-new-permission"
variant={ButtonVariantType.text}
size={ComponentSizeType.medium}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ const AppPermissions = () => {
setK8sPermission,
currentK8sPermissionRef,
data,
setIsSaveDisabled,
} = usePermissionConfiguration()
const { customRoles } = useAuthorizationContext()
const { isSuperAdmin: superAdmin } = useMainContext()
Expand All @@ -102,7 +103,7 @@ const AppPermissions = () => {
>
>()

const [isDataLoading, configData, error, reload] = useAsync(() =>
const [isDataLoading, configData, configDataError, reload] = useAsync(() =>
Promise.all([
getProjectList(),
getEnvironmentListMin(),
Expand Down Expand Up @@ -874,6 +875,19 @@ const AppPermissions = () => {
setAccessTypeToErrorMap(_accessTypeToErrorMap)
}

useEffect(() => {
setIsSaveDisabled(!!configDataError || isDataLoading || isLoading)
}, [isDataLoading, isLoading, configDataError])

useEffect(
() => () => {
// Set the save to false since the component has unmounted
// This can happen when the user was already a super admin
setIsSaveDisabled(false)
},
[],
)

useEffect(() => {
if (!isDataLoading) {
if (!data) {
Expand All @@ -900,7 +914,7 @@ const AppPermissions = () => {
)
}

if (error) {
if (configDataError) {
return <GenericSectionErrorState withBorder reload={reload} />
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@

import { useState } from 'react'
import {
Button,
ButtonStyleType,
ButtonVariantType,
Drawer,
OptionType,
stopPropagation,
Expand Down Expand Up @@ -184,23 +187,15 @@ const K8sPermissionModal = ({
/>
))}
</div>
<div className="w-100 pt-16 pb-16 pl-20 pr-20 flex right bcn-0 dc__border-top">
<button
type="button"
data-testid="k8s-permission-cancel"
className="cta cancel h-36 flex mr-16"
<div className="w-100 pt-16 pb-16 pl-20 pr-20 flex right dc__gap-16 bcn-0 dc__border-top">
<Button
text="Cancel"
onClick={close}
>
Cancel
</button>
<button
type="button"
data-testid="k8s-permission-save"
className="cta h-36 flex"
onClick={savePermission}
>
Done
</button>
variant={ButtonVariantType.secondary}
style={ButtonStyleType.neutral}
dataTestId="k8s-permission-cancel"
/>
<Button text="Done" onClick={savePermission} dataTestId="k8s-permission-save" />
</div>
</div>
</Drawer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export const PermissionConfigurationFormProvider = ({
data: User | PermissionGroup
showStatus: boolean
}) => {
const [isSaveDisabled, setIsSaveDisabled] = useState(false)
const [permissionType, setPermissionType] = useState<PermissionType>(PermissionType.SPECIFIC)

const [directPermission, setDirectPermission] = useState<DirectPermissionsRoleFilter[]>([])
Expand Down Expand Up @@ -127,6 +128,8 @@ export const PermissionConfigurationFormProvider = ({
handleUserStatusUpdate,
data,
showStatus,
isSaveDisabled,
setIsSaveDisabled,
}),
[
permissionType,
Expand All @@ -145,6 +148,7 @@ export const PermissionConfigurationFormProvider = ({
handleUserStatusUpdate,
data,
showStatus,
isSaveDisabled,
],
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ export interface PermissionConfigurationFormContext {
* @default false
*/
showStatus: boolean
/**
* State to control the saving of the permissions
*
* This is required since the any of the api call for parsing the permissions could fail
*/
isSaveDisabled: boolean
setIsSaveDisabled: React.Dispatch<React.SetStateAction<boolean>>
}

export type AccessTypeToErrorMapType = Record<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
timeToLive,
handleUserStatusUpdate,
showStatus,
isSaveDisabled,
} = usePermissionConfiguration()
const _userData = userData as User

Expand Down Expand Up @@ -331,7 +332,7 @@
multiSelectProps={{
getIsOptionValid: getIsEmailInputValid,
}}
shouldHideMenu

Check failure on line 335 in src/Pages/GlobalConfigurations/Authorization/UserPermissions/AddEdit/UserForm.tsx

View workflow job for this annotation

GitHub Actions / ci

Type '{ required: true; label: string; isMulti: true; options: undefined[]; autoFocus: true; isClearable: true; placeholder: string; inputValue: string; value: OptionType<string, string>[]; ... 8 more ...; size: ComponentSizeType.large; }' is not assignable to type 'IntrinsicAttributes & Pick<SelectProps<string, true>, "value" | "options" | "autoFocus" | "onChange" | "placeholder" | "name" | "isLoading" | ... 20 more ... | "required"> & ... 4 more ... & { ...; }'.
size={ComponentSizeType.large}
/>
<div className="dc__border-top" />
Expand Down Expand Up @@ -362,7 +363,7 @@
text="Save"
onClick={handleSubmit}
size={ComponentSizeType.medium}
disabled={submitting}
disabled={isSaveDisabled}
isLoading={submitting}
buttonProps={{
type: 'submit',
Expand Down
Loading