@evenicanpm/admin-integrate 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/README.md +29 -0
  2. package/documents/ProcessExecution/fragments.ts +16 -0
  3. package/documents/ProcessExecution/list.ts +31 -0
  4. package/package.json +19 -0
  5. package/src/api/dashboard/queries/get-process-executions.query.ts +48 -0
  6. package/src/api/dashboard/queries/get-process-executions.server.ts +11 -0
  7. package/src/api/dashboard/queries/index.ts +1 -0
  8. package/src/auth/.keep +0 -0
  9. package/src/auth/types/.keep +0 -0
  10. package/src/components/breadcrumbs/breadcrumbs.tsx +42 -0
  11. package/src/components/breadcrumbs/index.ts +2 -0
  12. package/src/components/button/index.ts +1 -0
  13. package/src/components/button/outlined-icon-button.tsx +47 -0
  14. package/src/components/core/index.ts +1 -0
  15. package/src/components/core/loading.tsx +15 -0
  16. package/src/components/dashboard-list/dashboard-list-row.tsx +145 -0
  17. package/src/components/dashboard-list/dashboard-list.tsx +157 -0
  18. package/src/components/dashboard-list/index.ts +1 -0
  19. package/src/components/data-table/index.ts +3 -0
  20. package/src/components/data-table/table-header.tsx +109 -0
  21. package/src/components/data-table/table-pagination.tsx +36 -0
  22. package/src/components/data-table/table-row.tsx +27 -0
  23. package/src/components/data-table/table-skeleton.tsx +45 -0
  24. package/src/components/execution/execution-filter.ts +30 -0
  25. package/src/components/execution/execution-status-icon.tsx +30 -0
  26. package/src/components/execution/execution-tag.tsx +100 -0
  27. package/src/components/execution/index.ts +2 -0
  28. package/src/components/footer/footer.tsx +55 -0
  29. package/src/components/footer/index.ts +1 -0
  30. package/src/components/header/dashboard-list-header.tsx +88 -0
  31. package/src/components/header/execution-details-header.tsx +154 -0
  32. package/src/components/header/header.tsx +42 -0
  33. package/src/components/header/index.ts +3 -0
  34. package/src/components/icons/up-down.tsx +21 -0
  35. package/src/components/integration-view/edges/default-edge.tsx +23 -0
  36. package/src/components/integration-view/elk-layout-options.ts +39 -0
  37. package/src/components/integration-view/elk-types.ts +19 -0
  38. package/src/components/integration-view/flow-types.tsx +16 -0
  39. package/src/components/integration-view/index.ts +1 -0
  40. package/src/components/integration-view/integration-view.tsx +159 -0
  41. package/src/components/integration-view/nodes/connection-node.tsx +10 -0
  42. package/src/components/integration-view/nodes/entry-node.tsx +10 -0
  43. package/src/components/integration-view/nodes/group-node.tsx +10 -0
  44. package/src/components/integration-view/nodes/task-node.tsx +17 -0
  45. package/src/components/integration-view/temp-data/initialElements.ts +238 -0
  46. package/src/components/integration-view/types.ts +12 -0
  47. package/src/components/layouts/index.ts +2 -0
  48. package/src/components/layouts/main-layout.tsx +28 -0
  49. package/src/components/layouts/root-container.tsx +43 -0
  50. package/src/components/link-cards/index.ts +1 -0
  51. package/src/components/link-cards/link-card.tsx +36 -0
  52. package/src/components/link-cards/styles.ts +29 -0
  53. package/src/components/list-filter/date-filter.tsx +55 -0
  54. package/src/components/list-filter/date-range-filter.tsx +101 -0
  55. package/src/components/list-filter/index.ts +6 -0
  56. package/src/components/list-filter/list-filter-types.ts +70 -0
  57. package/src/components/list-filter/list-filter.tsx +409 -0
  58. package/src/components/list-filter/multi-select-filter.tsx +117 -0
  59. package/src/components/list-filter/select-filter.tsx +82 -0
  60. package/src/hooks/use-breadcrumbs.ts +45 -0
  61. package/src/hooks/use-timestamp.tsx +25 -0
  62. package/src/lib/.keep +0 -0
  63. package/src/pages/dashboard/dashboard-link-cards.tsx +122 -0
  64. package/src/pages/dashboard/dashboard-list-sections.tsx +149 -0
  65. package/src/pages/dashboard/dashboard.tsx +14 -0
  66. package/src/pages/dashboard/index.ts +1 -0
  67. package/src/pages/execution-details/execution-details.tsx +43 -0
  68. package/src/pages/execution-details/index.ts +1 -0
  69. package/src/pages/executions/executions-list/executions-list-row.tsx +142 -0
  70. package/src/pages/executions/executions-list/executions-list-table.tsx +78 -0
  71. package/src/pages/executions/executions-list/executions-list.tsx +265 -0
  72. package/src/pages/executions/executions-list/index.ts +1 -0
  73. package/src/pages/executions/executions.tsx +98 -0
  74. package/src/pages/executions/index.ts +1 -0
  75. package/src/pages/integrations/index.ts +1 -0
  76. package/src/pages/integrations/integrations.tsx +39 -0
  77. package/src/pages/scheduler/index.ts +1 -0
  78. package/src/pages/scheduler/scheduler.tsx +39 -0
  79. package/tsconfig.json +28 -0
@@ -0,0 +1,122 @@
1
+ import React from "react";
2
+ import { useTranslations } from "next-intl";
3
+
4
+ // MUI
5
+ import { Theme, useTheme } from "@mui/material";
6
+ import { Box, Grid2 as Grid } from "@mui/material";
7
+ import {
8
+ RocketLaunchOutlined,
9
+ IntegrationInstructionsOutlined,
10
+ PlaylistPlayOutlined,
11
+ AccessTimeOutlined,
12
+ } from "@mui/icons-material";
13
+
14
+ // Custom components
15
+ import LinkCard from "@evenicanpm/admin-integrate/components/link-cards";
16
+
17
+ const breakpoints = {
18
+ xs: 6,
19
+ md: 3,
20
+ };
21
+
22
+ export default function DashboardLinkCards() {
23
+ const t = useTranslations("Integrate.Dashboard.LinkCard");
24
+
25
+ const theme = useTheme();
26
+ const styles = getStyles(theme);
27
+
28
+ const linkcardProps = {
29
+ quickstart: {
30
+ title: t("quickstart"),
31
+ description: t("quickstartDescription"),
32
+ url: "/e4integrate",
33
+ children: (
34
+ <Box
35
+ sx={{
36
+ ...styles.iconSquare,
37
+ backgroundColor: "paste.600",
38
+ }}
39
+ >
40
+ <RocketLaunchOutlined sx={styles.icon} />
41
+ </Box>
42
+ ),
43
+ },
44
+ integrations: {
45
+ title: t("integrations"),
46
+ description: t("integrationsDescription"),
47
+ url: "/e4integrate/integrations",
48
+ children: (
49
+ <Box
50
+ sx={{
51
+ ...styles.iconSquare,
52
+ backgroundColor: "orange.400",
53
+ }}
54
+ >
55
+ <IntegrationInstructionsOutlined sx={styles.icon} />
56
+ </Box>
57
+ ),
58
+ },
59
+ scheduler: {
60
+ title: t("scheduler"),
61
+ description: t("schedulerDescription"),
62
+ url: "/e4integrate/scheduler",
63
+ children: (
64
+ <Box
65
+ sx={{
66
+ ...styles.iconSquare,
67
+ backgroundColor: "marron.600",
68
+ }}
69
+ >
70
+ <AccessTimeOutlined sx={styles.icon} />
71
+ </Box>
72
+ ),
73
+ },
74
+ executions: {
75
+ title: t("executions"),
76
+ description: t("executionsDescription"),
77
+ url: "/e4integrate/executions",
78
+ children: (
79
+ <Box
80
+ sx={{
81
+ ...styles.iconSquare,
82
+ backgroundColor: "info.500",
83
+ }}
84
+ >
85
+ <PlaylistPlayOutlined sx={styles.icon} />
86
+ </Box>
87
+ ),
88
+ },
89
+ };
90
+
91
+ return (
92
+ <Grid container spacing={4}>
93
+ <Grid size={breakpoints}>
94
+ <LinkCard {...linkcardProps.quickstart} />
95
+ </Grid>
96
+ <Grid size={breakpoints}>
97
+ <LinkCard {...linkcardProps.integrations} />
98
+ </Grid>
99
+ <Grid size={breakpoints}>
100
+ <LinkCard {...linkcardProps.executions} />
101
+ </Grid>
102
+ <Grid size={breakpoints}>
103
+ <LinkCard {...linkcardProps.scheduler} />
104
+ </Grid>
105
+ </Grid>
106
+ );
107
+ }
108
+
109
+ const getStyles = (theme: Theme) => {
110
+ return {
111
+ iconSquare: {
112
+ padding: theme.spacing(1),
113
+ paddingBottom: theme.spacing(0.5),
114
+ marginBottom: theme.spacing(1),
115
+ color: "grey.200",
116
+ borderRadius: 1,
117
+ },
118
+ icon: {
119
+ fontSize: "h4.fontSize",
120
+ },
121
+ };
122
+ };
@@ -0,0 +1,149 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import { useTranslations } from "next-intl";
3
+
4
+ // API
5
+ import { getProcessExecutions } from "@evenicanpm/admin-integrate/api/dashboard/queries";
6
+ import { ProcessExecutionInput } from "@evenicanpm/admin-core/api/e4/graphqlRequestSdk";
7
+
8
+ // Custom components
9
+ import SnackbarAlert, {
10
+ iSnackbarAlert,
11
+ } from "@evenicanpm/admin-core/components/snackbar-alert";
12
+
13
+ import DashboardList from "@evenicanpm/admin-integrate/components/dashboard-list";
14
+
15
+ const defaultInput: ProcessExecutionInput = {
16
+ sort: "startDate",
17
+ sortDesc: true,
18
+ top: 5,
19
+ skip: 0,
20
+ };
21
+
22
+ export default function DashboardListSections() {
23
+ const t = useTranslations("Integrate.Dashboard");
24
+ const m = useTranslations("Integrate.Message");
25
+
26
+ const [refreshed, setRefreshed] = useState<boolean>(false);
27
+ const [message, setMessage] = useState<iSnackbarAlert>({ open: false });
28
+
29
+ const {
30
+ data: recent,
31
+ isLoading: recentLoading,
32
+ refetch: recentRefetch,
33
+ isRefetchError: recentRefetchError,
34
+ isRefetching: recentRefetching,
35
+ } = getProcessExecutions.useData({ input: defaultInput });
36
+
37
+ const {
38
+ data: notifications,
39
+ isLoading: notificationsLoading,
40
+ refetch: notificationsRefetch,
41
+ isRefetchError: notificationsRefetchError,
42
+ isRefetching: notificationsRefetching,
43
+ } = getProcessExecutions.useData({
44
+ input: { ...defaultInput, executionStatusIds: [450, 500, 999] },
45
+ });
46
+
47
+ useEffect(() => {
48
+ if (refreshed && !recentRefetching && !notificationsRefetching) {
49
+ if (recentRefetchError || notificationsRefetchError) {
50
+ setMessage({
51
+ open: true,
52
+ severity: "error",
53
+ message: m("Refresh.error"),
54
+ });
55
+ } else {
56
+ setMessage({
57
+ open: true,
58
+ severity: "success",
59
+ message: m("Refresh.success"),
60
+ });
61
+ }
62
+ setRefreshed(false);
63
+ }
64
+ }, [
65
+ refreshed,
66
+ recentRefetchError,
67
+ notificationsRefetchError,
68
+ recentRefetching,
69
+ notificationsRefetching,
70
+ ]);
71
+
72
+ const handleRecentRefresh = () => {
73
+ setRefreshed(true);
74
+ recentRefetch();
75
+ };
76
+ const handleNotifRefresh = () => {
77
+ setRefreshed(true);
78
+ notificationsRefetch();
79
+ };
80
+
81
+ const recentExecutionsHeading = [
82
+ {
83
+ id: "name",
84
+ label: t("ListHeader.integration"),
85
+ align: "left",
86
+ width: "70%",
87
+ },
88
+ {
89
+ id: "startDate",
90
+ label: t("ListHeader.lastRun"),
91
+ align: "center",
92
+ width: "15%",
93
+ },
94
+ {
95
+ id: "view",
96
+ label: t("ListHeader.actions"),
97
+ align: "center",
98
+ width: "5%",
99
+ },
100
+ ];
101
+ const notificationsHeading = [
102
+ {
103
+ id: "name",
104
+ label: t("ListHeader.message"),
105
+ align: "left",
106
+ width: "70%",
107
+ },
108
+ {
109
+ id: "startDate",
110
+ label: t("ListHeader.time"),
111
+ align: "center",
112
+ width: "15%",
113
+ },
114
+ {
115
+ id: "view",
116
+ label: t("ListHeader.actions"),
117
+ align: "center",
118
+ width: "5%",
119
+ },
120
+ ];
121
+
122
+ return (
123
+ <>
124
+ <DashboardList
125
+ title={t("recentExecutions")}
126
+ heading={recentExecutionsHeading}
127
+ data={recent}
128
+ loading={recentLoading || recentRefetching}
129
+ url="/e4integrate/executions"
130
+ handleRefresh={handleRecentRefresh}
131
+ />
132
+ <DashboardList
133
+ title={t("notifications")}
134
+ heading={notificationsHeading}
135
+ data={notifications}
136
+ loading={notificationsLoading || notificationsRefetching}
137
+ url="/e4Integrate/executions?$filter=executionStatusId%20eq%20450%20or%20executionStatusId%20eq%20500%20or%20executionStatusId%20eq%20999"
138
+ handleRefresh={handleNotifRefresh}
139
+ enableBgColor
140
+ />
141
+ <SnackbarAlert
142
+ open={message.open}
143
+ severity={message.severity}
144
+ message={message.message}
145
+ handleClose={() => setMessage({ ...message, open: false })}
146
+ />
147
+ </>
148
+ );
149
+ }
@@ -0,0 +1,14 @@
1
+ import React from "react";
2
+
3
+ // Local page components
4
+ import DashboardLinkCards from "@evenicanpm/admin-integrate/pages/dashboard/dashboard-link-cards";
5
+ import DashboardListSections from "@evenicanpm/admin-integrate/pages/dashboard/dashboard-list-sections";
6
+
7
+ export default function IntegrateDashboard() {
8
+ return (
9
+ <>
10
+ <DashboardLinkCards />
11
+ <DashboardListSections />
12
+ </>
13
+ );
14
+ }
@@ -0,0 +1 @@
1
+ export { default } from "./dashboard";
@@ -0,0 +1,43 @@
1
+ import React from "react";
2
+ import { useTranslations } from "next-intl";
3
+
4
+ // MUI
5
+ import { Theme, useTheme } from "@mui/material";
6
+ import { Box } from "@mui/material";
7
+
8
+ // Custom components
9
+ import {
10
+ IntegrateBreadcrumbs,
11
+ Crumb,
12
+ } from "@evenicanpm/admin-integrate/components/breadcrumbs";
13
+
14
+ export default function ExecutionDetails() {
15
+ const t = useTranslations("Integrate");
16
+
17
+ const theme = useTheme();
18
+ const styles = getStyles(theme);
19
+
20
+ const breadcrumbs: Crumb[] = [
21
+ {
22
+ name: t("Header.dashboard"),
23
+ url: "/e4integrate",
24
+ },
25
+ {
26
+ name: t("Header.executions"),
27
+ url: "/e4integrate/executions",
28
+ },
29
+ {
30
+ name: "TODO: dynamic title",
31
+ },
32
+ ];
33
+
34
+ return (
35
+ <Box>
36
+ <IntegrateBreadcrumbs breadcrumbs={breadcrumbs} />
37
+ </Box>
38
+ );
39
+ }
40
+
41
+ const getStyles = (theme: Theme) => {
42
+ return {};
43
+ };
@@ -0,0 +1 @@
1
+ export { default } from "./execution-details";
@@ -0,0 +1,142 @@
1
+ import React, { useState } from "react";
2
+ import { redirect, RedirectType } from "next/navigation";
3
+
4
+ // MUI
5
+ import { Theme, useTheme } from "@mui/material";
6
+ import { Box, Stack, Typography, Popover } from "@mui/material";
7
+ import { RemoveRedEye } from "@mui/icons-material";
8
+ import { SxProps } from "@mui/material";
9
+
10
+ // Custom components
11
+ import {
12
+ StyledTableCell,
13
+ StyledTableRow,
14
+ StyledIconButton,
15
+ } from "@evenicanpm/admin-integrate/components/data-table/table-row";
16
+ import {
17
+ ExecutionTag,
18
+ ExecutionStatusIcon,
19
+ } from "@evenicanpm/admin-integrate/components/execution";
20
+
21
+ // Hooks
22
+ import useTimestamp from "@evenicanpm/admin-integrate/hooks/use-timestamp";
23
+
24
+ // Types
25
+ import { Item } from "./executions-list";
26
+ import { Head } from "@evenicanpm/admin-integrate/components/data-table/table-header";
27
+ import { TableCellProps } from "@mui/material";
28
+
29
+ interface Props {
30
+ item: Item;
31
+ heading: Head[]; // for alignment
32
+ sx?: SxProps;
33
+ }
34
+
35
+ const ExecutionsListRow: React.FC<Props> = (props: Props) => {
36
+ const theme = useTheme();
37
+ const styles = getStyles(theme);
38
+
39
+ // e.g. "xx days ago"
40
+ const time = useTimestamp(props.item.startDate);
41
+ const localTime = new Date(props.item.startDate).toString();
42
+
43
+ const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
44
+ const open = Boolean(anchorEl);
45
+
46
+ const handlePopoverOpen = (event: React.MouseEvent<HTMLElement>) => {
47
+ setAnchorEl(event.currentTarget);
48
+ };
49
+
50
+ const handlePopoverClose = () => {
51
+ setAnchorEl(null);
52
+ };
53
+
54
+ const handleRedirect = () => {
55
+ //Temporarily commented out until executions detail page is implemented
56
+ // redirect(
57
+ // `/e4integrate/executions/${props.item.process.id}?ExecutionId=${props.item.id}`,
58
+ // RedirectType.push,
59
+ // );
60
+ };
61
+
62
+ return (
63
+ <StyledTableRow sx={props.sx}>
64
+ <StyledTableCell
65
+ align={props.heading[0].align as TableCellProps["align"]}
66
+ width={props.heading[0].width}
67
+ >
68
+ <Stack spacing={1} direction="row">
69
+ <Box display="flex" justifyContent="flex-end" alignItems="center">
70
+ <ExecutionStatusIcon
71
+ executionStatusId={props.item.executionStatus.id}
72
+ />
73
+ </Box>
74
+ <Box display="flex" justifyContent="flex-end" alignItems="center">
75
+ <Typography>{props.item.name}</Typography>
76
+ </Box>
77
+ </Stack>
78
+ </StyledTableCell>
79
+ <StyledTableCell
80
+ align={props.heading[1].align as TableCellProps["align"]}
81
+ width={props.heading[1].width}
82
+ >
83
+ <ExecutionTag
84
+ executionStatusId={props.item.executionStatus.id}
85
+ sx={{ margin: "auto" }}
86
+ />
87
+ </StyledTableCell>
88
+ <StyledTableCell
89
+ align={props.heading[2].align as TableCellProps["align"]}
90
+ width={props.heading[2].width}
91
+ sx={styles.timeCell}
92
+ >
93
+ <Typography
94
+ onMouseEnter={handlePopoverOpen}
95
+ onMouseLeave={handlePopoverClose}
96
+ >
97
+ {time}
98
+ </Typography>
99
+ <Popover
100
+ sx={{ pointerEvents: "none" }}
101
+ open={open}
102
+ anchorEl={anchorEl}
103
+ anchorOrigin={{
104
+ vertical: "bottom",
105
+ horizontal: "center",
106
+ }}
107
+ transformOrigin={{
108
+ vertical: "top",
109
+ horizontal: "center",
110
+ }}
111
+ onClose={handlePopoverClose}
112
+ disableRestoreFocus
113
+ >
114
+ <Box sx={styles.popover}>
115
+ <Typography>{localTime}</Typography>
116
+ </Box>
117
+ </Popover>
118
+ </StyledTableCell>
119
+ <StyledTableCell
120
+ align={props.heading[3].align as TableCellProps["align"]}
121
+ width={props.heading[3].width}
122
+ >
123
+ <StyledIconButton onClick={handleRedirect}>
124
+ <RemoveRedEye />
125
+ </StyledIconButton>
126
+ </StyledTableCell>
127
+ </StyledTableRow>
128
+ );
129
+ };
130
+
131
+ const getStyles = (theme: Theme) => {
132
+ return {
133
+ timeCell: {
134
+ cursor: "default",
135
+ },
136
+ popover: {
137
+ padding: theme.spacing(1),
138
+ },
139
+ };
140
+ };
141
+
142
+ export default ExecutionsListRow;
@@ -0,0 +1,78 @@
1
+ import React from "react";
2
+
3
+ // Types
4
+ import { Head } from "@evenicanpm/admin-integrate/components/data-table/table-header";
5
+ import { Item } from "./executions-list";
6
+
7
+ // API
8
+ import { ProcessExecutionInput } from "@evenicanpm/admin-core/api/e4/graphqlRequestSdk";
9
+
10
+ // MUI
11
+ import { Theme, useTheme } from "@mui/material";
12
+ import { TableContainer, Table, TableBody } from "@mui/material";
13
+ import { SxProps } from "@mui/material";
14
+
15
+ // Custom components
16
+ import { TableHeader } from "@evenicanpm/admin-integrate/components/data-table";
17
+
18
+ // Local components
19
+ import ExecutionsListRow from "./executions-list-row";
20
+
21
+ interface Props {
22
+ heading: Head[];
23
+ items: Item[];
24
+ input: ProcessExecutionInput;
25
+ setInput: (newInput: ProcessExecutionInput) => void;
26
+ rowSx?: SxProps;
27
+ }
28
+
29
+ export default function ExecutionsListTable(props: Props) {
30
+ const theme = useTheme();
31
+ const styles = getStyles(theme);
32
+
33
+ const handleRequestSort = (property: string) => {
34
+ const current = props.input.sort;
35
+ if (property === current) {
36
+ props.setInput({
37
+ ...props.input,
38
+ sortDesc: !props.input.sortDesc,
39
+ });
40
+ } else {
41
+ props.setInput({
42
+ ...props.input,
43
+ sort: property,
44
+ sortDesc: false,
45
+ });
46
+ }
47
+ };
48
+
49
+ return (
50
+ <>
51
+ <TableContainer>
52
+ <Table>
53
+ <TableHeader
54
+ heading={props.heading}
55
+ orderBy={props.input.sort}
56
+ order={props.input.sortDesc ? "desc" : "asc"}
57
+ onRequestSort={handleRequestSort}
58
+ rowSx={props.rowSx}
59
+ />
60
+ <TableBody>
61
+ {props.items.map((item, index) => (
62
+ <ExecutionsListRow
63
+ key={index}
64
+ item={item}
65
+ heading={props.heading}
66
+ sx={props.rowSx}
67
+ />
68
+ ))}
69
+ </TableBody>
70
+ </Table>
71
+ </TableContainer>
72
+ </>
73
+ );
74
+ }
75
+
76
+ const getStyles = (theme: Theme) => {
77
+ return {};
78
+ };