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

Update D&D action button loading behavior #5201

Merged
merged 5 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ The types of changes are:

### Changed
- Visual updates to badges in D&D result tables [#5212](https://github.com/ethyca/fides/pull/5212)
- Tweaked behavior of loading state on D&D table actions buttons [#5201](https://github.com/ethyca/fides/pull/5201)


## [2.43.0](https://github.com/ethyca/fides/compare/2.42.1...2.43.0)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,26 @@
import { Button, ButtonProps, Text } from "fidesui";
import { Button, ButtonProps } from "fidesui";
import { ReactElement } from "react";

interface ActionButtonProps extends ButtonProps {
title: string;
icon?: ReactElement;
}

const ActionButton = ({
title,
icon,
onClick,
disabled,
variant = "outline",
colorScheme = undefined,
}: {
title: string;
icon?: ReactElement;
onClick: () => void;
disabled?: boolean;
} & Pick<ButtonProps, "variant" | "colorScheme">) => (
...props
}: ActionButtonProps) => (
<Button
size="xs"
onClick={onClick}
isDisabled={disabled}
variant={variant}
colorScheme={colorScheme}
data-testid={`action-${title}`}
loadingText={title}
leftIcon={icon}
{...props}
>
{icon}
<Text marginLeft={icon && 1} fontWeight="semibold" fontSize={12}>
{title}
</Text>
{title}
</Button>
);
export default ActionButton;
Copy link
Contributor

Choose a reason for hiding this comment

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

Since you are extending all ButtonProps in the interface now, you should be able to simplify this quite a bit just by passing all of those props along to the Button. A good best-practice for making custom components a true extension of the original.

const ActionButton = ({
  title,
  icon,
  variant = "outline",
  ...props
}: ActionButtonProps) => (
  <Button
    size="xs"
    variant={variant}
    data-testid={`action-${title}`}
    loadingText={title}
    leftIcon={icon}
    {...props}
  >
    {title}
  </Button>
);

Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
import {
ButtonSpinner,
CheckIcon,
HStack,
ViewIcon,
ViewOffIcon,
} from "fidesui";
import { useState } from "react";
import { CheckIcon, HStack, ViewIcon, ViewOffIcon } from "fidesui";

import { useAlert } from "~/features/common/hooks";
import { DiffStatus, StagedResource } from "~/types/api";
Expand All @@ -27,12 +20,16 @@ interface DetectionItemActionProps {

const DetectionItemAction = ({ resource }: DetectionItemActionProps) => {
const resourceType = findResourceType(resource);
const [confirmResourceMutation] = useConfirmResourceMutation();
const [muteResourceMutation] = useMuteResourceMutation();
const [unmuteResourceMutation] = useUnmuteResourceMutation();
const [confirmResourceMutation, { isLoading: confirmIsLoading }] =
useConfirmResourceMutation();
const [muteResourceMutation, { isLoading: muteIsLoading }] =
useMuteResourceMutation();
const [unmuteResourceMutation, { isLoading: unmuteIsLoading }] =
useUnmuteResourceMutation();
const { successAlert } = useAlert();

const [isProcessingAction, setIsProcessingAction] = useState(false);
const anyActionIsLoading =
confirmIsLoading || muteIsLoading || unmuteIsLoading;

const { diff_status: diffStatus, child_diff_statuses: childDiffStatus } =
resource;
Expand Down Expand Up @@ -60,7 +57,6 @@ const DetectionItemAction = ({ resource }: DetectionItemActionProps) => {
title="Monitor"
icon={<MonitorOnIcon />}
onClick={async () => {
setIsProcessingAction(true);
await confirmResourceMutation({
staged_resource_urn: resource.urn,
monitor_config_id: resource.monitor_config_id!,
Expand All @@ -69,35 +65,33 @@ const DetectionItemAction = ({ resource }: DetectionItemActionProps) => {
"Data discovery has started. The results may take some time to appear in the “Data discovery“ tab.",
`${resource.name || "The resource"} is now being monitored.`,
);
setIsProcessingAction(false);
}}
disabled={isProcessingAction}
isDisabled={anyActionIsLoading}
isLoading={confirmIsLoading}
/>
)}
{showUnmuteAction && (
<ActionButton
title="Monitor"
icon={isSchemaType ? <MonitorOnIcon /> : <ViewIcon />}
onClick={async () => {
setIsProcessingAction(true);
await unmuteResourceMutation({
staged_resource_urn: resource.urn,
});
successAlert(
"Data discovery has started. The results may take some time to appear in the “Data discovery“ tab.",
`${resource.name || "The resource"} is now being monitored.`,
);
setIsProcessingAction(false);
}}
disabled={isProcessingAction}
isDisabled={anyActionIsLoading}
isLoading={unmuteIsLoading}
/>
)}
{showConfirmAction && (
<ActionButton
title="Confirm"
icon={<CheckIcon />}
onClick={async () => {
setIsProcessingAction(true);
await confirmResourceMutation({
staged_resource_urn: resource.urn,
monitor_config_id: resource.monitor_config_id!,
Expand All @@ -106,9 +100,9 @@ const DetectionItemAction = ({ resource }: DetectionItemActionProps) => {
`These changes have been added to a Fides dataset. To view, navigate to "Manage datasets".`,
`Table changes confirmed`,
);
setIsProcessingAction(false);
}}
disabled={isProcessingAction}
isDisabled={anyActionIsLoading}
isLoading={confirmIsLoading}
/>
)}
{/* Positive Actions (Monitor, Confirm) goes first. Negative actions such as ignore should be last */}
Expand All @@ -117,21 +111,18 @@ const DetectionItemAction = ({ resource }: DetectionItemActionProps) => {
title="Ignore"
icon={isSchemaType ? <MonitorOffIcon /> : <ViewOffIcon />}
onClick={async () => {
setIsProcessingAction(true);
await muteResourceMutation({
staged_resource_urn: resource.urn,
});
successAlert(
`Ignored data will not be monitored for changes or added to Fides datasets.`,
`${resource.name || "Resource"} ignored`,
);
setIsProcessingAction(false);
}}
disabled={isProcessingAction}
isDisabled={anyActionIsLoading}
isLoading={muteIsLoading}
/>
)}

{isProcessingAction ? <ButtonSpinner position="static" /> : null}
</HStack>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { ButtonSpinner, CheckIcon, HStack, ViewOffIcon } from "fidesui";
import { useState } from "react";
import { CheckIcon, HStack, ViewOffIcon } from "fidesui";

import { useAlert } from "~/features/common/hooks";
import { DiscoveryMonitorItem } from "~/features/data-discovery-and-detection/types/DiscoveryMonitorItem";
Expand All @@ -16,10 +15,12 @@ interface DiscoveryItemActionsProps {
}

const DiscoveryItemActions = ({ resource }: DiscoveryItemActionsProps) => {
const [promoteResourceMutation] = usePromoteResourceMutation();
const [muteResourceMutation] = useMuteResourceMutation();
const [promoteResourceMutation, { isLoading: promoteIsLoading }] =
usePromoteResourceMutation();
const [muteResourceMutation, { isLoading: muteIsLoading }] =
useMuteResourceMutation();

const [isProcessingAction, setIsProcessingAction] = useState(false);
const anyActionIsLoading = promoteIsLoading || muteIsLoading;

const {
diff_status: diffStatus,
Expand Down Expand Up @@ -55,39 +56,35 @@ const DiscoveryItemActions = ({ resource }: DiscoveryItemActionsProps) => {
title="Confirm"
icon={<CheckIcon />}
onClick={async () => {
setIsProcessingAction(true);
await promoteResourceMutation({
staged_resource_urn: resource.urn,
});
successAlert(
`These changes have been added to a Fides dataset. To view, navigate to "Manage datasets".`,
`Table changes confirmed`,
);
setIsProcessingAction(false);
}}
disabled={isProcessingAction}
isDisabled={anyActionIsLoading}
isLoading={promoteIsLoading}
/>
)}
{showMuteAction && (
<ActionButton
title="Ignore"
icon={<ViewOffIcon />}
onClick={async () => {
setIsProcessingAction(true);
await muteResourceMutation({
staged_resource_urn: resource.urn,
});
successAlert(
`Ignored changes will not be added to a Fides dataset.`,
`${resource.name || "Changes"} ignored`,
);
setIsProcessingAction(false);
}}
disabled={isProcessingAction}
isDisabled={anyActionIsLoading}
isLoading={muteIsLoading}
/>
)}

{isProcessingAction ? <ButtonSpinner position="static" /> : null}
</HStack>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const DiscoveryFieldBulkActions = ({
const [muteResourceMutationTrigger, { isLoading: isMuteLoading }] =
useMuteResourcesMutation();

const isLoading = isPromoteLoading || isMuteLoading;
const anyActionIsLoading = isPromoteLoading || isMuteLoading;

const handleIgnoreClicked = async (urns: string[]) => {
await muteResourceMutationTrigger({
Expand All @@ -42,15 +42,17 @@ const DiscoveryFieldBulkActions = ({
title="Confirm all"
icon={<CheckIcon />}
onClick={() => handleConfirmClicked([resourceUrn])}
disabled={isLoading}
isDisabled={anyActionIsLoading}
isLoading={isPromoteLoading}
variant="solid"
colorScheme="primary"
/>
<ActionButton
title="Ignore all"
icon={<ViewOffIcon />}
disabled={isLoading}
onClick={() => handleIgnoreClicked([resourceUrn])}
isDisabled={anyActionIsLoading}
isLoading={isMuteLoading}
/>
</ButtonGroup>
</Flex>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const DiscoveryTableBulkActions = ({
const [muteResourcesMutationTrigger, { isLoading: isMuteLoading }] =
useMuteResourcesMutation();

const isLoading = isPromoteLoading || isMuteLoading;
const anyActionIsLoading = isPromoteLoading || isMuteLoading;

const handleConfirmClicked = async (urns: string[]) => {
await promoteResourcesMutationTrigger({
Expand Down Expand Up @@ -52,14 +52,16 @@ const DiscoveryTableBulkActions = ({
title="Confirm"
icon={<CheckIcon />}
onClick={() => handleConfirmClicked(selectedUrns)}
disabled={isLoading}
isDisabled={anyActionIsLoading}
isLoading={isPromoteLoading}
variant="solid"
colorScheme="primary"
/>
<ActionButton
title="Ignore"
icon={<ViewOffIcon />}
disabled={isLoading}
isDisabled={anyActionIsLoading}
isLoading={isMuteLoading}
onClick={() => handleIgnoreClicked(selectedUrns)}
/>
</ButtonGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ const MonitorConfigActionsCell = ({
defaultSuccessMsg: "Monitor deleted successfully",
});

const [executeMonitor] = useExecuteDiscoveryMonitorMutation();
const [executeMonitor, { isLoading: executeIsLoading }] =
useExecuteDiscoveryMonitorMutation();
const { toastResult: toastExecuteResult } = useQueryResultToast({
defaultErrorMsg: "A problem occurred initiating monitor execution",
defaultSuccessMsg: "Monitor execution successfully started",
Expand Down Expand Up @@ -78,7 +79,11 @@ const MonitorConfigActionsCell = ({
data-testid="delete-monitor-btn"
/>
</Tooltip>
<ActionButton onClick={handleExecute} title="Scan" />
<ActionButton
onClick={handleExecute}
title="Scan"
isLoading={executeIsLoading}
/>
</ButtonGroup>
</>
);
Expand Down
Loading