Skip to content

Commit a6ba367

Browse files
committed
refactor: filter lined progress
wip: hooked up wip: dimming wip: more wip: more refactors chore: lots of widgets
1 parent 2a0574f commit a6ba367

File tree

27 files changed

+559
-403
lines changed

27 files changed

+559
-403
lines changed

clients/admin-ui/cypress/e2e/action-center/assets-results.cy.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ import {
77
} from "cypress/support/stubs";
88

99
import { ACTION_CENTER_ROUTE } from "~/features/common/nav/routes";
10-
import { MONITOR_TYPES } from "~/features/data-discovery-and-detection/action-center/utils/getMonitorType";
10+
import { APIMonitorType } from "~/types/api/models/APIMonitorType";
1111

12-
const WEB_MONITOR_ROUTE = `${ACTION_CENTER_ROUTE}/${MONITOR_TYPES.WEBSITE}`;
12+
const WEB_MONITOR_ROUTE = `${ACTION_CENTER_ROUTE}/${APIMonitorType.WEBSITE}`;
1313

1414
describe("Action center Asset Results", () => {
1515
beforeEach(() => {

clients/admin-ui/src/features/common/api.slice.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ export const baseApi = createApi({
113113
"Access Policy Control Groups",
114114
"Access Control",
115115
"Fides Dashboard",
116+
"Monitor Statistics",
117+
"Connection Type"
116118
],
117119
endpoints: () => ({}),
118120
});

clients/admin-ui/src/features/data-discovery-and-detection/action-center/ActionCenterLayout.tsx

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import useActionCenterNavigation, {
2020
} from "~/features/data-discovery-and-detection/action-center/hooks/useActionCenterNavigation";
2121

2222
import MonitorStats from "./MonitorStats";
23+
import { APIMonitorType } from "~/types/api/models/APIMonitorType";
2324

2425
export interface ActionCenterLayoutProps {
2526
monitorId?: string;
@@ -28,13 +29,17 @@ export interface ActionCenterLayoutProps {
2829
dropdownProps?: DropdownProps;
2930
badgeProps?: BadgeProps;
3031
};
32+
refresh?: () => void
33+
monitorType?: APIMonitorType
3134
}
3235

3336
const ActionCenterLayout = ({
3437
children,
3538
monitorId,
39+
monitorType,
3640
routeConfig,
3741
pageSettings,
42+
refresh
3843
}: PropsWithChildren<ActionCenterLayoutProps>) => {
3944
const {
4045
items: menuItems,
@@ -56,21 +61,31 @@ const ActionCenterLayout = ({
5661
]}
5762
isSticky={false}
5863
rightContent={
59-
pageSettings && (
60-
<Flex>
61-
<Badge {...pageSettings.badgeProps}>
62-
<Dropdown {...pageSettings.dropdownProps}>
63-
<Button
64-
aria-label="Page settings"
65-
icon={<Icons.SettingsView />}
66-
/>
67-
</Dropdown>
68-
</Badge>
69-
</Flex>
70-
)
64+
<Flex gap="small">
65+
{pageSettings && (
66+
<Flex>
67+
<Badge {...pageSettings.badgeProps}>
68+
<Dropdown {...pageSettings.dropdownProps}>
69+
<Button
70+
aria-label="Page settings"
71+
icon={<Icons.SettingsView />}
72+
/>
73+
</Dropdown>
74+
</Badge>
75+
</Flex>
76+
)
77+
}
78+
{refresh &&
79+
<Button
80+
aria-label="Page refresh"
81+
icon={<Icons.Renew />}
82+
onClick={refresh}
83+
/>
84+
}
85+
</Flex>
7186
}
7287
/>
73-
<MonitorStats monitorId={monitorId} />
88+
{monitorId && <MonitorStats monitorId={monitorId} monitorType={monitorType} />}
7489
<Menu
7590
aria-label="Action center tabs"
7691
mode="horizontal"
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { Descriptions, Flex, Text } from "fidesui";
2+
3+
import { useFlags } from "~/features/common/features";
4+
import { useGetConnectionQuery, useGetMonitorConfigQuery } from "./action-center.slice";
5+
import { APIMonitorType } from "~/types/api/models/APIMonitorType";
6+
import { skipToken } from "@reduxjs/toolkit/query";
7+
8+
export interface MonitorDetailsWidgetProps {
9+
monitorId: string;
10+
monitorType: APIMonitorType
11+
disabled?: boolean
12+
}
13+
14+
const MonitorDetailsWidget = ({ monitorId }: MonitorDetailsWidgetProps) => {
15+
const {
16+
flags: { heliosInsights },
17+
} = useFlags();
18+
const { data: configData } = useGetMonitorConfigQuery({ monitor_config_id: monitorId })
19+
const connectionKey = configData?.connection_config_key
20+
const { data: connectionData } = useGetConnectionQuery(connectionKey ? { connection_key: connectionKey } : skipToken)
21+
22+
return (
23+
heliosInsights && (
24+
<Flex
25+
className="w-full"
26+
gap="middle"
27+
vertical
28+
>
29+
<Text strong>Details</Text>
30+
<Descriptions
31+
size="small"
32+
items={[{
33+
label: "System",
34+
children: connectionData?.system_key,
35+
span: "filled"
36+
},
37+
{
38+
label: "Integration",
39+
children: connectionKey,
40+
41+
span: "filled"
42+
}
43+
]}>
44+
</Descriptions>
45+
</Flex>
46+
)
47+
);
48+
};
49+
50+
export default MonitorDetailsWidget;

clients/admin-ui/src/features/data-discovery-and-detection/action-center/MonitorList.const.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ import {
66
} from "nuqs";
77
import * as v from "valibot";
88

9-
import { MONITOR_TYPES } from "./utils/getMonitorType";
9+
import { APIMonitorType } from "~/types/api/models/APIMonitorType";
1010

1111
export const MonitorSearchFormQuerySchema = (
12-
availableMonitors: Array<MONITOR_TYPES>,
12+
availableMonitors: Array<APIMonitorType>,
1313
) =>
1414
v.object({
1515
search: v.nullish(v.string(), null),
@@ -18,7 +18,7 @@ export const MonitorSearchFormQuerySchema = (
1818
});
1919

2020
export const SearchFormQueryState = (
21-
availableMonitors: Array<MONITOR_TYPES>,
21+
availableMonitors: Array<APIMonitorType>,
2222
id?: string,
2323
) =>
2424
({

clients/admin-ui/src/features/data-discovery-and-detection/action-center/MonitorList.tsx

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import { useGetAggregateMonitorResultsQuery } from "~/features/data-discovery-an
1111
import { EmptyMonitorsResult } from "~/features/data-discovery-and-detection/action-center/EmptyMonitorsResult";
1212
import useSearchForm from "~/features/data-discovery-and-detection/action-center/hooks/useSearchForm";
1313
import { MonitorResult } from "~/features/data-discovery-and-detection/action-center/MonitorResult";
14-
import { MONITOR_TYPES } from "~/features/data-discovery-and-detection/action-center/utils/getMonitorType";
1514
import { useGetUserMonitorsQuery } from "~/features/user-management";
1615

1716
import MonitorListSearchForm from "./forms/MonitorListSearchForm";
@@ -20,6 +19,8 @@ import {
2019
MonitorSearchFormQuerySchema,
2120
SearchFormQueryState,
2221
} from "./MonitorList.const";
22+
import { APIMonitorType } from "~/types/api/models/APIMonitorType";
23+
import MonitorStats from "./MonitorStats";
2324

2425
const MonitorList = () => {
2526
const message = useMessage();
@@ -30,25 +31,28 @@ const MonitorList = () => {
3031
useAntPagination();
3132

3233
const availableMonitorTypes = [
33-
...(webMonitorEnabled ? [MONITOR_TYPES.WEBSITE] : []),
34-
MONITOR_TYPES.DATASTORE,
35-
MONITOR_TYPES.INFRASTRUCTURE,
34+
...(webMonitorEnabled ? [APIMonitorType.WEBSITE] : []),
35+
APIMonitorType.DATASTORE,
36+
APIMonitorType.INFRASTRUCTURE,
3637
] as const;
3738

3839
const currentUser = useAppSelector(selectUser);
3940

4041
const { data: userMonitors } = useGetUserMonitorsQuery(
4142
currentUser?.id
4243
? {
43-
id: currentUser.id,
44-
}
44+
id: currentUser.id,
45+
}
4546
: skipToken,
4647
);
4748

4849
const defaultStewardFilter =
4950
(userMonitors ?? []).length > 0 ? currentUser?.id : undefined;
5051

51-
const { requestData, ...formProps } = useSearchForm<any, MonitorSearchForm>({
52+
const { requestData, ...formProps } = useSearchForm<
53+
Partial<Parameters<typeof useGetAggregateMonitorResultsQuery>[0]>,
54+
MonitorSearchForm
55+
>({
5256
schema: MonitorSearchFormQuerySchema([...availableMonitorTypes]),
5357
queryState: SearchFormQueryState(
5458
[...availableMonitorTypes],
@@ -64,7 +68,7 @@ const MonitorList = () => {
6468
search: search || undefined,
6569
monitor_type: monitor_type
6670
? [monitor_type]
67-
: availableMonitorTypes /** this should be handled via ant binding ideally. * */,
71+
: [...availableMonitorTypes] /** this should be handled via ant binding ideally. * */,
6872
steward_user_id:
6973
typeof steward_key === "undefined" || !steward_key
7074
? []
@@ -100,6 +104,7 @@ const MonitorList = () => {
100104
}}
101105
availableMonitorTypes={availableMonitorTypes}
102106
/>
107+
<MonitorStats />
103108
<List
104109
loading={isLoading}
105110
dataSource={results}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
2+
import classNames from "classnames";
3+
import { Button, Card, Divider, Flex, Icons, Text } from "fidesui";
4+
import Link from "next/link";
5+
6+
import { useFlags } from "~/features/common/features";
7+
import { INTEGRATION_MANAGEMENT_ROUTE } from "~/features/common/nav/routes";
8+
9+
import { useGetAggregateStatisticsQuery } from "./action-center.slice";
10+
import { ProgressCard } from "./ProgressCard/ProgressCard";
11+
import {
12+
buildWidgetProps,
13+
MONITOR_TYPE_TO_EMPTY_TEXT,
14+
MONITOR_TYPE_TO_ICON,
15+
MONITOR_TYPE_TO_LABEL,
16+
transformStatisticsResponseToCardProps,
17+
} from "./ProgressCard/utils";
18+
import { useQueryStates } from "nuqs";
19+
import { SearchFormQueryState } from "./MonitorList.const";
20+
import { APIMonitorType } from "~/types/api/models/APIMonitorType";
21+
22+
export interface MonitorProgressWidgetProps {
23+
monitorId?: string;
24+
monitorType: APIMonitorType
25+
disabled?: boolean
26+
}
27+
28+
const renderIcon = (icon: Icons.CarbonIconType) => {
29+
const Icon = icon;
30+
return <Icon size={33} />;
31+
};
32+
33+
const MonitorProgressWidget = ({ monitorId, monitorType }: MonitorProgressWidgetProps) => {
34+
const {
35+
flags: { heliosInsights },
36+
} = useFlags();
37+
const [filters] = useQueryStates(SearchFormQueryState(Object.values(APIMonitorType
38+
)))
39+
40+
const { data } = useGetAggregateStatisticsQuery(
41+
{
42+
monitor_type: monitorType,
43+
monitor_config_id: monitorId,
44+
steward_user_id: filters.steward_key ? [filters.steward_key] : undefined
45+
},
46+
{
47+
refetchOnMountOrArgChange: true,
48+
},
49+
);
50+
51+
const { total_monitors = 0 } = data ?? { total_monitors: 0 }
52+
53+
return (
54+
heliosInsights && (
55+
<Flex
56+
className="w-full"
57+
gap="middle"
58+
>
59+
{data && total_monitors > 0 || !!filters.steward_key ? (
60+
<ProgressCard
61+
{...buildWidgetProps({
62+
monitor_type: monitorType,
63+
total_monitors,
64+
...data,
65+
})}
66+
compact={!!monitorId}
67+
disabled={(!!filters.monitor_type && monitorType !== filters.monitor_type) || (!!filters.steward_key && total_monitors <= 0)}
68+
/>
69+
) : (
70+
<div
71+
>
72+
<Flex vertical gap="middle" align="center" justify="center">
73+
<span>{MONITOR_TYPE_TO_LABEL[monitorType]}</span>
74+
<Text>{renderIcon(MONITOR_TYPE_TO_ICON[monitorType])}</Text>
75+
<Text type="secondary" className="text-center">
76+
{MONITOR_TYPE_TO_EMPTY_TEXT[monitorType]}
77+
</Text>
78+
<Link href={INTEGRATION_MANAGEMENT_ROUTE}>
79+
<Button type="primary">Create</Button>
80+
</Link>
81+
</Flex>
82+
</div>
83+
)
84+
}
85+
</Flex>
86+
)
87+
);
88+
};
89+
90+
export default MonitorProgressWidget;

clients/admin-ui/src/features/data-discovery-and-detection/action-center/MonitorResult.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@ import { DiscoveryStatusIcon } from "./DiscoveryStatusIcon";
3333
import styles from "./MonitorResult.module.scss";
3434
import { MonitorResultDescription } from "./MonitorResultDescription";
3535
import { MonitorAggregatedResults } from "./types";
36-
import { MONITOR_TYPES } from "./utils/getMonitorType";
36+
import { APIMonitorType } from "~/types/api/models/APIMonitorType";
3737

3838
const { Text } = Typography;
3939

4040
const MONITOR_RESULT_COUNT_TYPES = {
41-
[MONITOR_TYPES.WEBSITE]: ["asset", "assets"],
42-
[MONITOR_TYPES.DATASTORE]: ["field", "fields"],
43-
[MONITOR_TYPES.INFRASTRUCTURE]: ["system", "systems"],
41+
[APIMonitorType.WEBSITE]: ["asset", "assets"],
42+
[APIMonitorType.DATASTORE]: ["field", "fields"],
43+
[APIMonitorType.INFRASTRUCTURE]: ["system", "systems"],
4444
} as const;
4545

4646
interface MonitorResultProps extends ListItemProps {
@@ -69,7 +69,7 @@ export const MonitorResult = ({
6969
} = monitorSummary;
7070

7171
let confidenceCounts;
72-
if (monitorType === MONITOR_TYPES.DATASTORE) {
72+
if (monitorType === APIMonitorType.DATASTORE) {
7373
const datastoreUpdates = updates as DatastoreMonitorUpdates | undefined;
7474
confidenceCounts = {
7575
highConfidenceCount: datastoreUpdates?.classified_high_confidence ?? 0,
@@ -87,7 +87,7 @@ export const MonitorResult = ({
8787
confidenceCounts.lowConfidenceCount > 0);
8888

8989
const showConfidenceRow =
90-
monitorType === MONITOR_TYPES.DATASTORE && hasConfidenceCounts && !!key;
90+
monitorType === APIMonitorType.DATASTORE && hasConfidenceCounts && !!key;
9191

9292
const formattedLastMonitored = lastMonitored
9393
? formatDate(new Date(lastMonitored))
@@ -201,7 +201,7 @@ export const MonitorResult = ({
201201
!!updates && (
202202
<MonitorResultDescription
203203
updates={updates}
204-
isAssetList={monitorType === MONITOR_TYPES.WEBSITE}
204+
isAssetList={monitorType === APIMonitorType.WEBSITE}
205205
/>
206206
)
207207
}

0 commit comments

Comments
 (0)