1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-04-01 01:18:10 +02:00

feat: add disabled state handling on slow network (#6165)

This commit is contained in:
Mateusz Kwasniewski 2024-02-08 10:27:51 +01:00 committed by GitHub
parent bc7d4b8edb
commit 7e66a79f9f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 91 additions and 26 deletions

View File

@ -13,10 +13,12 @@ interface IChangeRequestDialogueProps {
environment?: string;
showBanner?: boolean;
messageComponent: JSX.Element;
disabled?: boolean;
}
export const ChangeRequestDialogue: FC<IChangeRequestDialogueProps> = ({
isOpen,
disabled = false,
onConfirm,
onClose,
showBanner,
@ -40,6 +42,7 @@ export const ChangeRequestDialogue: FC<IChangeRequestDialogueProps> = ({
open={isOpen}
primaryButtonText={primaryButtonText}
secondaryButtonText='Cancel'
disabledPrimaryButton={disabled}
onClick={onConfirm}
onClose={onClose}
title='Request changes'

View File

@ -97,13 +97,14 @@ export const ChangeRequestOverview: FC = () => {
projectId,
id,
);
const { changeState, addComment, loading } = useChangeRequestApi();
const { changeState, addComment } = useChangeRequestApi();
const { refetch: refetchChangeRequestOpen } =
usePendingChangeRequests(projectId);
const { setToastData, setToastApiError } = useToast();
const { isChangeRequestConfiguredForReview } =
useChangeRequestsEnabled(projectId);
const scheduleChangeRequests = useUiFlag('scheduledConfigurationChanges');
const [disabled, setDisabled] = useState(false);
if (!changeRequest) {
return null;
@ -124,11 +125,12 @@ export const ChangeRequestOverview: FC = () => {
const onApplyChanges = async () => {
try {
setDisabled(true);
await changeState(projectId, Number(id), getCurrentState(), {
state: 'Applied',
});
setShowApplyScheduledDialog(false);
refetchChangeRequest();
await refetchChangeRequest();
refetchChangeRequestOpen();
setToastData({
type: 'success',
@ -137,11 +139,14 @@ export const ChangeRequestOverview: FC = () => {
});
} catch (error: unknown) {
setToastApiError(formatUnknownError(error));
} finally {
setDisabled(false);
}
};
const onScheduleChangeRequest = async (scheduledDate: Date) => {
try {
setDisabled(true);
await changeState(projectId, Number(id), getCurrentState(), {
state: 'Scheduled',
scheduledAt: scheduledDate.toISOString(),
@ -156,14 +161,17 @@ export const ChangeRequestOverview: FC = () => {
});
} catch (error: unknown) {
setToastApiError(formatUnknownError(error));
} finally {
setDisabled(false);
}
};
const onAddComment = async () => {
try {
setDisabled(true);
await addComment(projectId, id, commentText);
setCommentText('');
refetchChangeRequest();
await refetchChangeRequest();
setToastData({
type: 'success',
title: 'Success',
@ -171,16 +179,19 @@ export const ChangeRequestOverview: FC = () => {
});
} catch (error: unknown) {
setToastApiError(formatUnknownError(error));
} finally {
setDisabled(false);
}
};
const onCancelChanges = async () => {
try {
setDisabled(true);
await changeState(projectId, Number(id), getCurrentState(), {
state: 'Cancelled',
});
setShowCancelDialog(false);
refetchChangeRequest();
await refetchChangeRequest();
refetchChangeRequestOpen();
setToastData({
type: 'success',
@ -189,34 +200,41 @@ export const ChangeRequestOverview: FC = () => {
});
} catch (error: unknown) {
setToastApiError(formatUnknownError(error));
} finally {
setDisabled(false);
}
};
const onReject = async (comment?: string) => {
try {
setDisabled(true);
await changeState(projectId, Number(id), getCurrentState(), {
state: 'Rejected',
comment,
});
setShowRejectDialog(false);
await refetchChangeRequest();
setToastData({
type: 'success',
title: 'Success',
text: 'Changes rejected',
});
refetchChangeRequest();
refetchChangeRequestOpen();
} catch (error: unknown) {
setToastApiError(formatUnknownError(error));
} finally {
setDisabled(false);
}
};
const onApprove = async () => {
try {
setDisabled(true);
await changeState(projectId, Number(id), getCurrentState(), {
state: 'Approved',
});
refetchChangeRequest();
await refetchChangeRequest();
refetchChangeRequestOpen();
setToastData({
type: 'success',
@ -225,6 +243,8 @@ export const ChangeRequestOverview: FC = () => {
});
} catch (error: unknown) {
setToastApiError(formatUnknownError(error));
} finally {
setDisabled(false);
}
};
@ -313,7 +333,8 @@ export const ChangeRequestOverview: FC = () => {
disabled={
!allowChangeRequestActions ||
commentText.trim().length === 0 ||
commentText.trim().length > 1000
commentText.trim().length > 1000 ||
disabled
}
>
Comment
@ -350,7 +371,10 @@ export const ChangeRequestOverview: FC = () => {
setShowRejectDialog(true)
}
onApprove={onApprove}
disabled={!allowChangeRequestActions}
disabled={
!allowChangeRequestActions ||
disabled
}
>
Review changes ({countOfChanges})
</ReviewButton>
@ -366,7 +390,7 @@ export const ChangeRequestOverview: FC = () => {
onApply={onApplyChanges}
disabled={
!allowChangeRequestActions ||
loading
disabled
}
onSchedule={() =>
setShowScheduleChangeDialog(
@ -390,7 +414,7 @@ export const ChangeRequestOverview: FC = () => {
}
disabled={
!allowChangeRequestActions ||
loading
disabled
}
>
Apply changes
@ -411,7 +435,7 @@ export const ChangeRequestOverview: FC = () => {
}
disabled={
!allowChangeRequestActions ||
loading
disabled
}
onSchedule={() =>
setShowScheduleChangeDialog(true)
@ -445,6 +469,7 @@ export const ChangeRequestOverview: FC = () => {
true,
)
}
disabled={disabled}
>
Reject changes
</StyledButton>
@ -453,6 +478,7 @@ export const ChangeRequestOverview: FC = () => {
<StyledButton
variant='outlined'
onClick={onCancel}
disabled={disabled}
>
Cancel changes
</StyledButton>
@ -485,6 +511,7 @@ export const ChangeRequestOverview: FC = () => {
open={showRejectDialog}
onConfirm={onReject}
onClose={onCancelReject}
disabled={disabled}
/>
<ConditionallyRender
condition={scheduleChangeRequests}
@ -494,7 +521,9 @@ export const ChangeRequestOverview: FC = () => {
open={showScheduleChangesDialog}
onConfirm={onScheduleChangeRequest}
onClose={onScheduleChangeAbort}
disabled={!allowChangeRequestActions || loading}
disabled={
!allowChangeRequestActions || disabled
}
projectId={projectId}
environment={changeRequest.environment}
primaryButtonText={
@ -514,7 +543,9 @@ export const ChangeRequestOverview: FC = () => {
onConfirm={onApplyChanges}
onClose={onApplyScheduledAbort}
scheduledTime={scheduledAt}
disabled={!allowChangeRequestActions || loading}
disabled={
!allowChangeRequestActions || disabled
}
projectId={projectId}
environment={changeRequest.environment}
/>
@ -523,6 +554,7 @@ export const ChangeRequestOverview: FC = () => {
onConfirm={onReject}
onClose={onRejectScheduledAbort}
scheduledTime={scheduledAt}
disabled={disabled}
/>
</>
}

View File

@ -6,12 +6,14 @@ interface IChangeRequestDialogueProps {
open: boolean;
onConfirm: (comment?: string) => void;
onClose: () => void;
disabled?: boolean;
}
export const ChangeRequestRejectDialogue: FC<IChangeRequestDialogueProps> = ({
open,
onConfirm,
onClose,
disabled = false,
}) => {
const [commentText, setCommentText] = useState('');
@ -21,6 +23,7 @@ export const ChangeRequestRejectDialogue: FC<IChangeRequestDialogueProps> = ({
primaryButtonText='Reject changes'
secondaryButtonText='Cancel'
onClick={() => onConfirm(commentText)}
disabledPrimaryButton={disabled}
onClose={onClose}
title='Reject changes'
fullWidth

View File

@ -29,6 +29,7 @@ export const ChangeRequestScheduledDialog: FC<
onClose,
title,
primaryButtonText,
disabled,
message,
scheduledTime,
permissionButton,
@ -39,6 +40,7 @@ export const ChangeRequestScheduledDialog: FC<
<Dialogue
title={title}
primaryButtonText={primaryButtonText}
disabledPrimaryButton={disabled}
secondaryButtonText='Cancel'
open={open}
onClose={onClose}

View File

@ -48,6 +48,7 @@ export const ScheduleChangeRequestDialog: FC<ScheduleChangeRequestDialogProps> =
<Dialogue
title={title}
primaryButtonText={primaryButtonText}
disabledPrimaryButton={disabled}
secondaryButtonText='Cancel'
open={open}
onClose={() => onClose()}

View File

@ -102,6 +102,7 @@ export const MultiActionButton: FC<{
{actions.map(
({ label, onSelect, icon }) => (
<MenuItem
disabled={disabled}
onClick={onSelect}
key={`MenuItem-${label}`}
>

View File

@ -25,11 +25,17 @@ import { ChangeRequestTitle } from './ChangeRequestTitle';
import { UpdateCount } from 'component/changeRequest/UpdateCount';
import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useChangeRequestApi';
const SubmitChangeRequestButton: FC<{ onClick: () => void; count: number }> = ({
onClick,
count,
}) => (
<Button sx={{ ml: 'auto' }} variant='contained' onClick={onClick}>
const SubmitChangeRequestButton: FC<{
onClick: () => void;
count: number;
disabled?: boolean;
}> = ({ onClick, count, disabled = false }) => (
<Button
sx={{ ml: 'auto' }}
variant='contained'
onClick={onClick}
disabled={disabled}
>
Submit change request ({count})
</Button>
);
@ -66,11 +72,18 @@ export const EnvironmentChangeRequest: FC<{
const { user } = useAuthUser();
const [title, setTitle] = useState(environmentChangeRequest.title);
const { changeState } = useChangeRequestApi();
const sendToReview = async (project: string) =>
changeState(project, environmentChangeRequest.id, 'Draft', {
state: 'In review',
comment: commentText,
});
const [disabled, setDisabled] = useState(false);
const sendToReview = async (project: string) => {
setDisabled(true);
try {
await changeState(project, environmentChangeRequest.id, 'Draft', {
state: 'In review',
comment: commentText,
});
} catch (e) {
setDisabled(false);
}
};
return (
<Box key={environmentChangeRequest.id}>
@ -152,14 +165,17 @@ export const EnvironmentChangeRequest: FC<{
count={changesCount(
environmentChangeRequest,
)}
disabled={disabled}
/>
<Button
sx={{ ml: 2 }}
variant='outlined'
onClick={() =>
onDiscard(environmentChangeRequest.id)
}
disabled={disabled}
onClick={() => {
setDisabled(true);
onDiscard(environmentChangeRequest.id);
}}
>
Discard changes
</Button>

View File

@ -53,6 +53,7 @@ export const useFeatureToggleSwitch: UseFeatureToggleSwitchType = (
onAddDefaultStrategy: () => {},
});
const {
pending,
onChangeRequestToggle,
onChangeRequestToggleClose,
onChangeRequestToggleConfirm,
@ -233,6 +234,7 @@ export const useFeatureToggleSwitch: UseFeatureToggleSwitchType = (
onChangeRequestToggleClose();
}}
environment={changeRequestDialogDetails?.environment}
disabled={pending}
onConfirm={() => {
changeRequestDialogCallback?.();
onChangeRequestToggleConfirm();

View File

@ -9,6 +9,7 @@ export const useChangeRequestToggle = (project: string) => {
const { addChange } = useChangeRequestApi();
const { refetch: refetchChangeRequests } =
usePendingChangeRequests(project);
const [pending, setPending] = useState(false);
const [changeRequestDialogDetails, setChangeRequestDialogDetails] =
useState<{
@ -43,6 +44,7 @@ export const useChangeRequestToggle = (project: string) => {
const onChangeRequestToggleConfirm = useCallback(async () => {
try {
setPending(true);
await addChange(project, changeRequestDialogDetails.environment!, {
feature: changeRequestDialogDetails.featureName!,
action: 'updateEnabled',
@ -68,10 +70,13 @@ export const useChangeRequestToggle = (project: string) => {
...prev,
isOpen: false,
}));
} finally {
setPending(false);
}
}, [addChange]);
return {
pending,
onChangeRequestToggle,
onChangeRequestToggleClose,
onChangeRequestToggleConfirm,