Skip to content

Commit

Permalink
✨ Extract IconWithLabel component (#1878)
Browse files Browse the repository at this point in the history
Resolves: #1873

---------

Signed-off-by: Radoslaw Szwajkowski <[email protected]>
  • Loading branch information
rszwajko authored Apr 25, 2024
1 parent 8715dbe commit 312b8b8
Show file tree
Hide file tree
Showing 14 changed files with 88 additions and 69 deletions.
36 changes: 36 additions & 0 deletions client/src/app/components/Icons/IconWithLabel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React, { FC, ReactElement, ReactNode } from "react";
import { Flex, FlexItem } from "@patternfly/react-core";
import { OptionalTooltip } from "./OptionalTooltip";

export const IconWithLabel: FC<{
iconTooltipMessage?: string;
icon: ReactElement;
label: ReactNode;
trailingItem?: ReactElement;
trailingItemTooltipMessage?: string;
}> = ({
iconTooltipMessage,
icon,
label,
trailingItem,
trailingItemTooltipMessage,
}) => (
<Flex
flexWrap={{ default: "nowrap" }}
spaceItems={{ default: "spaceItemsSm" }}
>
<FlexItem>
<OptionalTooltip tooltipMessage={iconTooltipMessage}>
{icon}
</OptionalTooltip>
</FlexItem>
<FlexItem>{label}</FlexItem>
{!!trailingItem && (
<FlexItem>
<OptionalTooltip tooltipMessage={trailingItemTooltipMessage}>
{trailingItem}
</OptionalTooltip>
</FlexItem>
)}
</Flex>
);
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import React from "react";
import { Flex, FlexItem, Icon, Tooltip } from "@patternfly/react-core";
import { Icon } from "@patternfly/react-core";
import { useTranslation } from "react-i18next";
import CheckCircleIcon from "@patternfly/react-icons/dist/esm/icons/check-circle-icon";
import TimesCircleIcon from "@patternfly/react-icons/dist/esm/icons/times-circle-icon";
import InProgressIcon from "@patternfly/react-icons/dist/esm/icons/in-progress-icon";
import ExclamationCircleIcon from "@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon";
import UnknownIcon from "@patternfly/react-icons/dist/esm/icons/unknown-icon";
import TopologyIcon from "@patternfly/react-icons/dist/esm/icons/topology-icon";
import { IconWithLabel } from "./IconWithLabel";
import { ReactElement } from "react-markdown/lib/react-markdown";

export type IconedStatusPreset =
| "InheritedReviews"
Expand All @@ -31,7 +33,9 @@ export type IconedStatusStatusType =
| "danger";

type IconedStatusPresetType = {
[key in IconedStatusPreset]: Omit<IIconedStatusProps, "preset">;
[key in IconedStatusPreset]: Omit<IIconedStatusProps, "preset"> & {
topologyIcon?: ReactElement;
};
};

export interface IIconedStatusProps {
Expand Down Expand Up @@ -61,6 +65,7 @@ export const IconedStatus: React.FC<IIconedStatusProps> = ({
tooltipMessage: t("message.inheritedReviewTooltip", {
count: tooltipCount,
}),
topologyIcon: <TopologyIcon />,
},
InProgressInheritedAssessments: {
icon: <InProgressIcon />,
Expand All @@ -69,6 +74,7 @@ export const IconedStatus: React.FC<IIconedStatusProps> = ({
tooltipMessage: t("message.inheritedAssessmentTooltip", {
count: tooltipCount,
}),
topologyIcon: <TopologyIcon />,
},
InheritedReviews: {
icon: <CheckCircleIcon />,
Expand All @@ -77,6 +83,7 @@ export const IconedStatus: React.FC<IIconedStatusProps> = ({
tooltipMessage: t("message.inheritedReviewTooltip", {
count: tooltipCount,
}),
topologyIcon: <TopologyIcon />,
},
InheritedAssessments: {
icon: <CheckCircleIcon />,
Expand All @@ -85,6 +92,7 @@ export const IconedStatus: React.FC<IIconedStatusProps> = ({
tooltipMessage: t("message.inheritedAssessmentTooltip", {
count: tooltipCount,
}),
topologyIcon: <TopologyIcon />,
},
Canceled: {
icon: <TimesCircleIcon />,
Expand Down Expand Up @@ -129,63 +137,18 @@ export const IconedStatus: React.FC<IIconedStatusProps> = ({
},
};
const presetProps = preset && presets[preset];
const IconWithOptionalTooltip: React.FC<{ children: React.ReactElement }> = ({
children,
}) =>
presetProps?.tooltipMessage ? (
<Tooltip content={presetProps?.tooltipMessage}>{children}</Tooltip>
) : (
<>{children}</>
);

const getTooltipContent = () => {
switch (preset) {
case "InheritedReviews":
return t("message.inheritedReviewTooltip", {
count: tooltipCount,
});

case "InheritedAssessments":
return t("message.inheritedAssessmentTooltip", {
count: tooltipCount,
});
case "InProgressInheritedReviews":
return t("message.inheritedReviewTooltip", {
count: tooltipCount,
});
case "InProgressInheritedAssessments":
return t("message.inheritedAssessmentTooltip", {
count: tooltipCount,
});

default:
return "";
}
};

return (
<Flex
flexWrap={{ default: "nowrap" }}
spaceItems={{ default: "spaceItemsSm" }}
>
<FlexItem>
<IconWithOptionalTooltip>
<Icon status={status || presetProps?.status} className={className}>
{icon || presetProps?.icon || <UnknownIcon />}
</Icon>
</IconWithOptionalTooltip>
</FlexItem>
<FlexItem>{label || presetProps?.label}</FlexItem>
{(preset === "InheritedReviews" ||
preset === "InheritedAssessments" ||
preset === "InProgressInheritedAssessments" ||
preset === "InProgressInheritedReviews") && (
<FlexItem>
<Tooltip content={getTooltipContent()}>
<TopologyIcon />
</Tooltip>
</FlexItem>
)}
</Flex>
<IconWithLabel
iconTooltipMessage={presetProps?.tooltipMessage}
icon={
<Icon status={status || presetProps?.status} className={className}>
{icon || presetProps?.icon || <UnknownIcon />}
</Icon>
}
label={label || presetProps?.label}
trailingItemTooltipMessage={presetProps?.tooltipMessage}
trailingItem={presetProps?.topologyIcon}
/>
);
};
12 changes: 12 additions & 0 deletions client/src/app/components/Icons/OptionalTooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from "react";
import { Tooltip } from "@patternfly/react-core";

export const OptionalTooltip: React.FC<{
tooltipMessage?: string;
children: React.ReactElement;
}> = ({ children, tooltipMessage }) =>
tooltipMessage ? (
<Tooltip content={tooltipMessage}>{children}</Tooltip>
) : (
<>{children}</>
);
3 changes: 3 additions & 0 deletions client/src/app/components/Icons/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "./OptionalTooltip";
export * from "./IconedStatus";
export * from "./IconWithLabel";
2 changes: 1 addition & 1 deletion client/src/app/components/answer-table/answer-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { NoDataEmptyState } from "@app/components/NoDataEmptyState";
import { Answer } from "@app/api/models";
import { Label, Text, Tooltip } from "@patternfly/react-core";
import spacing from "@patternfly/react-styles/css/utilities/Spacing/spacing";
import { IconedStatus } from "@app/components/IconedStatus";
import { IconedStatus } from "@app/components/Icons";
import { TimesCircleIcon } from "@patternfly/react-icons";
import { WarningTriangleIcon } from "@patternfly/react-icons";
import { List, ListItem } from "@patternfly/react-core";
Expand Down
2 changes: 1 addition & 1 deletion client/src/app/components/risk-icon/risk-icon.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";
import { TimesCircleIcon, WarningTriangleIcon } from "@patternfly/react-icons";
import { IconedStatus } from "@app/components/IconedStatus";
import { IconedStatus } from "@app/components/Icons";

interface RiskIconProps {
risk: string;
Expand Down
2 changes: 1 addition & 1 deletion client/src/app/components/tests/StatusIcon.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { render } from "@app/test-config/test-utils";
import React from "react";
import { IconedStatus } from "../IconedStatus";
import { IconedStatus } from "../Icons";

describe("StatusIcon", () => {
it("Renders without crashing", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ import { useFetchArchetypes } from "@app/queries/archetypes";
import { ApplicationFormModal } from "../components/application-form";
import { ManageColumnsToolbar } from "./components/manage-columns-toolbar";
import dayjs from "dayjs";
import { IconWithLabel } from "@app/components/Icons";

export const ApplicationsTable: React.FC = () => {
const { t } = useTranslation();
Expand Down Expand Up @@ -950,8 +951,12 @@ export const ApplicationsTable: React.FC = () => {
modifier="truncate"
{...getTdProps({ columnKey: "tags" })}
>
<TagIcon />
{application.tags ? application.tags.length : 0}
<IconWithLabel
icon={<TagIcon />}
label={
application.tags ? application.tags.length : 0
}
/>
</Td>
)}
{getColumnVisibility("effort") && (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";

import { TaskState } from "@app/api/models";
import { IconedStatus } from "@app/components/IconedStatus";
import { IconedStatus } from "@app/components/Icons";

export interface ApplicationAnalysisStatusProps {
state: TaskState;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";
import { Application } from "@app/api/models";
import { IconedStatus, IconedStatusPreset } from "@app/components/IconedStatus";
import { IconedStatus, IconedStatusPreset } from "@app/components/Icons";
import { Spinner } from "@patternfly/react-core";
import { useAssessmentStatus } from "@app/hooks/useAssessmentStatus";
interface ApplicationAssessmentStatusProps {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";
import { Application } from "@app/api/models";
import { IconedStatus, IconedStatusPreset } from "@app/components/IconedStatus";
import { IconedStatus, IconedStatusPreset } from "@app/components/Icons";
import { Spinner } from "@patternfly/react-core";
import { EmptyTextMessage } from "@app/components/EmptyTextMessage";
import { useTranslation } from "react-i18next";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { AppPlaceholder } from "@app/components/AppPlaceholder";
import { ConditionalRender } from "@app/components/ConditionalRender";
import { ConfirmDialog } from "@app/components/ConfirmDialog";
import { FilterType, FilterToolbar } from "@app/components/FilterToolbar";
import { IconedStatus } from "@app/components/IconedStatus";
import { IconedStatus } from "@app/components/Icons";
import { KebabDropdown } from "@app/components/KebabDropdown";
import { NotificationsContext } from "@app/components/NotificationsContext";
import { SimplePagination } from "@app/components/SimplePagination";
Expand Down
2 changes: 1 addition & 1 deletion client/src/app/pages/archetypes/archetypes-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ import {
} from "@app/rbac";
import { checkAccess } from "@app/utils/rbac-utils";
import keycloak from "@app/keycloak";
import { IconedStatus } from "@app/components/IconedStatus";
import { IconedStatus } from "@app/components/Icons";
import { useQueryClient } from "@tanstack/react-query";

const Archetypes: React.FC = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
Spinner,
} from "@patternfly/react-core";
import ExclamationCircleIcon from "@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon";
import { IconedStatus } from "@app/components/IconedStatus";
import { IconedStatus } from "@app/components/Icons";

interface ITrackerStatusProps {
name: string;
Expand Down

0 comments on commit 312b8b8

Please sign in to comment.