@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.
- package/README.md +29 -0
- package/documents/ProcessExecution/fragments.ts +16 -0
- package/documents/ProcessExecution/list.ts +31 -0
- package/package.json +19 -0
- package/src/api/dashboard/queries/get-process-executions.query.ts +48 -0
- package/src/api/dashboard/queries/get-process-executions.server.ts +11 -0
- package/src/api/dashboard/queries/index.ts +1 -0
- package/src/auth/.keep +0 -0
- package/src/auth/types/.keep +0 -0
- package/src/components/breadcrumbs/breadcrumbs.tsx +42 -0
- package/src/components/breadcrumbs/index.ts +2 -0
- package/src/components/button/index.ts +1 -0
- package/src/components/button/outlined-icon-button.tsx +47 -0
- package/src/components/core/index.ts +1 -0
- package/src/components/core/loading.tsx +15 -0
- package/src/components/dashboard-list/dashboard-list-row.tsx +145 -0
- package/src/components/dashboard-list/dashboard-list.tsx +157 -0
- package/src/components/dashboard-list/index.ts +1 -0
- package/src/components/data-table/index.ts +3 -0
- package/src/components/data-table/table-header.tsx +109 -0
- package/src/components/data-table/table-pagination.tsx +36 -0
- package/src/components/data-table/table-row.tsx +27 -0
- package/src/components/data-table/table-skeleton.tsx +45 -0
- package/src/components/execution/execution-filter.ts +30 -0
- package/src/components/execution/execution-status-icon.tsx +30 -0
- package/src/components/execution/execution-tag.tsx +100 -0
- package/src/components/execution/index.ts +2 -0
- package/src/components/footer/footer.tsx +55 -0
- package/src/components/footer/index.ts +1 -0
- package/src/components/header/dashboard-list-header.tsx +88 -0
- package/src/components/header/execution-details-header.tsx +154 -0
- package/src/components/header/header.tsx +42 -0
- package/src/components/header/index.ts +3 -0
- package/src/components/icons/up-down.tsx +21 -0
- package/src/components/integration-view/edges/default-edge.tsx +23 -0
- package/src/components/integration-view/elk-layout-options.ts +39 -0
- package/src/components/integration-view/elk-types.ts +19 -0
- package/src/components/integration-view/flow-types.tsx +16 -0
- package/src/components/integration-view/index.ts +1 -0
- package/src/components/integration-view/integration-view.tsx +159 -0
- package/src/components/integration-view/nodes/connection-node.tsx +10 -0
- package/src/components/integration-view/nodes/entry-node.tsx +10 -0
- package/src/components/integration-view/nodes/group-node.tsx +10 -0
- package/src/components/integration-view/nodes/task-node.tsx +17 -0
- package/src/components/integration-view/temp-data/initialElements.ts +238 -0
- package/src/components/integration-view/types.ts +12 -0
- package/src/components/layouts/index.ts +2 -0
- package/src/components/layouts/main-layout.tsx +28 -0
- package/src/components/layouts/root-container.tsx +43 -0
- package/src/components/link-cards/index.ts +1 -0
- package/src/components/link-cards/link-card.tsx +36 -0
- package/src/components/link-cards/styles.ts +29 -0
- package/src/components/list-filter/date-filter.tsx +55 -0
- package/src/components/list-filter/date-range-filter.tsx +101 -0
- package/src/components/list-filter/index.ts +6 -0
- package/src/components/list-filter/list-filter-types.ts +70 -0
- package/src/components/list-filter/list-filter.tsx +409 -0
- package/src/components/list-filter/multi-select-filter.tsx +117 -0
- package/src/components/list-filter/select-filter.tsx +82 -0
- package/src/hooks/use-breadcrumbs.ts +45 -0
- package/src/hooks/use-timestamp.tsx +25 -0
- package/src/lib/.keep +0 -0
- package/src/pages/dashboard/dashboard-link-cards.tsx +122 -0
- package/src/pages/dashboard/dashboard-list-sections.tsx +149 -0
- package/src/pages/dashboard/dashboard.tsx +14 -0
- package/src/pages/dashboard/index.ts +1 -0
- package/src/pages/execution-details/execution-details.tsx +43 -0
- package/src/pages/execution-details/index.ts +1 -0
- package/src/pages/executions/executions-list/executions-list-row.tsx +142 -0
- package/src/pages/executions/executions-list/executions-list-table.tsx +78 -0
- package/src/pages/executions/executions-list/executions-list.tsx +265 -0
- package/src/pages/executions/executions-list/index.ts +1 -0
- package/src/pages/executions/executions.tsx +98 -0
- package/src/pages/executions/index.ts +1 -0
- package/src/pages/integrations/index.ts +1 -0
- package/src/pages/integrations/integrations.tsx +39 -0
- package/src/pages/scheduler/index.ts +1 -0
- package/src/pages/scheduler/scheduler.tsx +39 -0
- package/tsconfig.json +28 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import TableRow from "@mui/material/TableRow";
|
|
2
|
+
import TableHead from "@mui/material/TableHead";
|
|
3
|
+
import TableSortLabel from "@mui/material/TableSortLabel";
|
|
4
|
+
import TableCell, { TableCellProps } from "@mui/material/TableCell";
|
|
5
|
+
import styled from "@mui/material/styles/styled";
|
|
6
|
+
|
|
7
|
+
import { SxProps } from "@mui/material";
|
|
8
|
+
import { Theme, useTheme } from "@mui/material";
|
|
9
|
+
import { ExpandLess, ExpandMore } from "@mui/icons-material";
|
|
10
|
+
|
|
11
|
+
// STYLED COMPONENTS
|
|
12
|
+
const StyledTableCell = styled(TableCell)(({ theme }) => ({
|
|
13
|
+
fontWeight: 500,
|
|
14
|
+
padding: "16px 20px",
|
|
15
|
+
color: theme.palette.grey[900],
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
// ==============================================================
|
|
19
|
+
export type Head = {
|
|
20
|
+
id: string;
|
|
21
|
+
label: string;
|
|
22
|
+
align: string;
|
|
23
|
+
width: string;
|
|
24
|
+
sortable?: boolean;
|
|
25
|
+
};
|
|
26
|
+
interface Props {
|
|
27
|
+
heading: Head[];
|
|
28
|
+
orderBy: string;
|
|
29
|
+
order: "asc" | "desc";
|
|
30
|
+
onRequestSort?: (id: string) => void; // if provided, make list sortable by column
|
|
31
|
+
rowSx?: SxProps;
|
|
32
|
+
}
|
|
33
|
+
// ==============================================================
|
|
34
|
+
|
|
35
|
+
export default function TableHeader({
|
|
36
|
+
order,
|
|
37
|
+
heading,
|
|
38
|
+
orderBy,
|
|
39
|
+
onRequestSort,
|
|
40
|
+
rowSx,
|
|
41
|
+
}: Props) {
|
|
42
|
+
const theme = useTheme();
|
|
43
|
+
const styles = getStyles(theme);
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<TableHead sx={{ backgroundColor: "grey.200" }}>
|
|
47
|
+
<TableRow sx={rowSx}>
|
|
48
|
+
{heading.map((headCell) => (
|
|
49
|
+
<StyledTableCell
|
|
50
|
+
key={headCell.id}
|
|
51
|
+
align={headCell.align as TableCellProps["align"]}
|
|
52
|
+
sortDirection={orderBy === headCell.id ? order : false}
|
|
53
|
+
width={headCell.width}
|
|
54
|
+
>
|
|
55
|
+
{onRequestSort && headCell.sortable ? (
|
|
56
|
+
<TableSortLabel
|
|
57
|
+
active={orderBy === headCell.id}
|
|
58
|
+
onClick={() => onRequestSort(headCell.id)}
|
|
59
|
+
direction={orderBy === headCell.id ? order : "asc"}
|
|
60
|
+
sx={styles.sortLabel}
|
|
61
|
+
IconComponent={() =>
|
|
62
|
+
order === "desc" && orderBy === headCell.id ? (
|
|
63
|
+
<ExpandMore
|
|
64
|
+
sx={{
|
|
65
|
+
...styles.sortIcon,
|
|
66
|
+
visibility:
|
|
67
|
+
orderBy === headCell.id ? "visible" : "hidden",
|
|
68
|
+
}}
|
|
69
|
+
/>
|
|
70
|
+
) : (
|
|
71
|
+
<ExpandLess
|
|
72
|
+
sx={{
|
|
73
|
+
...styles.sortIcon,
|
|
74
|
+
visibility:
|
|
75
|
+
orderBy === headCell.id ? "visible" : "hidden",
|
|
76
|
+
}}
|
|
77
|
+
/>
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
>
|
|
81
|
+
{headCell.label}
|
|
82
|
+
</TableSortLabel>
|
|
83
|
+
) : (
|
|
84
|
+
headCell.label
|
|
85
|
+
)}
|
|
86
|
+
</StyledTableCell>
|
|
87
|
+
))}
|
|
88
|
+
</TableRow>
|
|
89
|
+
</TableHead>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const getStyles = (theme: Theme) => {
|
|
94
|
+
return {
|
|
95
|
+
sortLabel: {
|
|
96
|
+
"&:hover": {
|
|
97
|
+
color: "info.main",
|
|
98
|
+
"& .MuiSvgIcon-root": {
|
|
99
|
+
color: "info.main",
|
|
100
|
+
visibility: "visible",
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
sortIcon: {
|
|
105
|
+
marginLeft: theme.spacing(1),
|
|
106
|
+
color: "grey.800",
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import Pagination, { PaginationProps } from "@mui/material/Pagination";
|
|
2
|
+
import styled from "@mui/material/styles/styled";
|
|
3
|
+
|
|
4
|
+
// STYLED COMPONENT
|
|
5
|
+
const StyledPagination = styled(Pagination)(({ theme }) => ({
|
|
6
|
+
"& .MuiPaginationItem-root": {
|
|
7
|
+
fontSize: 14,
|
|
8
|
+
fontWeight: 500,
|
|
9
|
+
color: theme.palette.grey[900],
|
|
10
|
+
border: `1px solid transparent`,
|
|
11
|
+
},
|
|
12
|
+
"& .MuiPaginationItem-page:hover": {
|
|
13
|
+
borderRadius: 20,
|
|
14
|
+
backgroundColor: "transparent",
|
|
15
|
+
color: theme.palette.info.main,
|
|
16
|
+
border: `1px solid ${theme.palette.info.main}`,
|
|
17
|
+
},
|
|
18
|
+
"& .MuiPaginationItem-page.Mui-selected": {
|
|
19
|
+
borderRadius: 20,
|
|
20
|
+
backgroundColor: "transparent",
|
|
21
|
+
color: theme.palette.info.main,
|
|
22
|
+
border: `1px solid ${theme.palette.info.main}`,
|
|
23
|
+
":hover": { backgroundColor: "transparent" },
|
|
24
|
+
},
|
|
25
|
+
"& .MuiPaginationItem-previousNext": {
|
|
26
|
+
margin: 10,
|
|
27
|
+
borderRadius: 20,
|
|
28
|
+
color: theme.palette.info.main,
|
|
29
|
+
border: `1px solid ${theme.palette.info.main}`,
|
|
30
|
+
"&:hover": { backgroundColor: "transparent" },
|
|
31
|
+
},
|
|
32
|
+
}));
|
|
33
|
+
|
|
34
|
+
export default function TablePagination(props: PaginationProps) {
|
|
35
|
+
return <StyledPagination {...props} />;
|
|
36
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import styled from "@mui/material/styles/styled";
|
|
2
|
+
import { TableRow, TableCell, IconButton } from "@mui/material";
|
|
3
|
+
|
|
4
|
+
const StyledTableCell = styled(TableCell)(({ theme }) => ({
|
|
5
|
+
fontSize: 14,
|
|
6
|
+
paddingTop: 10,
|
|
7
|
+
fontWeight: 500,
|
|
8
|
+
paddingBottom: 10,
|
|
9
|
+
color: theme.palette.grey[900],
|
|
10
|
+
borderBottom: `1px solid ${theme.palette.grey[300]}`,
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
const StyledTableRow = styled(TableRow)({
|
|
14
|
+
":last-child .MuiTableCell-root": { border: 0 },
|
|
15
|
+
"&.Mui-selected": {
|
|
16
|
+
backgroundColor: "transparent",
|
|
17
|
+
":hover": { backgroundColor: "transparent" },
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const StyledIconButton = styled(IconButton)(({ theme }) => ({
|
|
22
|
+
color: theme.palette.grey[600],
|
|
23
|
+
"& .MuiSvgIcon-root": { fontSize: 19 },
|
|
24
|
+
":hover": { color: theme.palette.info.main },
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
export { StyledTableCell, StyledTableRow, StyledIconButton };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { TableContainer, Table, TableBody, Skeleton } from "@mui/material";
|
|
2
|
+
import { SxProps } from "@mui/material";
|
|
3
|
+
|
|
4
|
+
import TableHeader, { Head } from "./table-header";
|
|
5
|
+
import { StyledTableRow, StyledTableCell } from "./table-row";
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
heading: Head[];
|
|
9
|
+
perPage: number;
|
|
10
|
+
sx?: SxProps;
|
|
11
|
+
rowSx?: SxProps;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default function TableSkeleton(props: Props) {
|
|
15
|
+
const rangeArray: number[] = Array.from(
|
|
16
|
+
{ length: props.perPage },
|
|
17
|
+
(_, i) => i,
|
|
18
|
+
);
|
|
19
|
+
return (
|
|
20
|
+
<TableContainer sx={props.sx}>
|
|
21
|
+
<Table>
|
|
22
|
+
<TableHeader
|
|
23
|
+
heading={props.heading}
|
|
24
|
+
order="asc"
|
|
25
|
+
orderBy=""
|
|
26
|
+
onRequestSort={() => {
|
|
27
|
+
// do nothing
|
|
28
|
+
}}
|
|
29
|
+
rowSx={props.rowSx}
|
|
30
|
+
/>
|
|
31
|
+
<TableBody>
|
|
32
|
+
{rangeArray.map((i: number) => (
|
|
33
|
+
<StyledTableRow key={i} sx={props.rowSx}>
|
|
34
|
+
{props.heading.map((heading: Head) => (
|
|
35
|
+
<StyledTableCell key={`${i}_${heading.id}`}>
|
|
36
|
+
<Skeleton />
|
|
37
|
+
</StyledTableCell>
|
|
38
|
+
))}
|
|
39
|
+
</StyledTableRow>
|
|
40
|
+
))}
|
|
41
|
+
</TableBody>
|
|
42
|
+
</Table>
|
|
43
|
+
</TableContainer>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DateRangeFilter,
|
|
3
|
+
Filters,
|
|
4
|
+
MultiSelectFilter,
|
|
5
|
+
} from "@evenicanpm/admin-integrate/components/list-filter/list-filter-types";
|
|
6
|
+
|
|
7
|
+
export interface ExecutionsListFilters extends Filters {
|
|
8
|
+
dateRange: DateRangeFilter;
|
|
9
|
+
multiSelectFilter: MultiSelectFilter;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const executionListFilters: ExecutionsListFilters = {
|
|
13
|
+
dateRange: {
|
|
14
|
+
type: "dateRange",
|
|
15
|
+
label: "Date Range",
|
|
16
|
+
value: null,
|
|
17
|
+
},
|
|
18
|
+
multiSelectFilter: {
|
|
19
|
+
type: "multiSelect",
|
|
20
|
+
label: "Execution Status",
|
|
21
|
+
value: null,
|
|
22
|
+
options: [
|
|
23
|
+
{ id: 300, value: "Executions.inProgress" },
|
|
24
|
+
{ id: 400, value: "Executions.complete" },
|
|
25
|
+
{ id: 450, value: "Executions.warning" },
|
|
26
|
+
{ id: 500, value: "Executions.failed" },
|
|
27
|
+
{ id: 999, value: "Executions.unavailable" },
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import { Box, Typography, SxProps } from "@mui/material";
|
|
4
|
+
import {
|
|
5
|
+
RemoveRedEye,
|
|
6
|
+
Loop,
|
|
7
|
+
CheckCircleOutline,
|
|
8
|
+
WarningAmber,
|
|
9
|
+
ErrorOutline,
|
|
10
|
+
Clear,
|
|
11
|
+
} from "@mui/icons-material";
|
|
12
|
+
|
|
13
|
+
interface Props {
|
|
14
|
+
executionStatusId: string;
|
|
15
|
+
sx?: SxProps;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const ExecutionStatusIcon: React.FC<Props> = (props: Props) => {
|
|
19
|
+
const statusIconMap = {
|
|
20
|
+
300: <Loop color="info" />,
|
|
21
|
+
400: <CheckCircleOutline color="success" />,
|
|
22
|
+
450: <WarningAmber color="warning" />,
|
|
23
|
+
500: <ErrorOutline color="error" />,
|
|
24
|
+
999: <Clear sx={{ color: "grey.600" }} />,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
return statusIconMap[props.executionStatusId] || statusIconMap[999];
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default ExecutionStatusIcon;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useTranslations } from "next-intl";
|
|
3
|
+
|
|
4
|
+
import { styled } from "@mui/material/styles";
|
|
5
|
+
import { Box, Typography, SxProps } from "@mui/material";
|
|
6
|
+
|
|
7
|
+
// Styled components
|
|
8
|
+
const StyledTagBox = styled(Box)(({ theme }) => ({
|
|
9
|
+
padding: theme.spacing(0, 1.5),
|
|
10
|
+
border: "solid 1px",
|
|
11
|
+
borderRadius: 4,
|
|
12
|
+
alignContent: "center",
|
|
13
|
+
maxWidth: "fit-content",
|
|
14
|
+
}));
|
|
15
|
+
const StyledTag = styled(Typography)(({ theme }) => ({
|
|
16
|
+
fontWeight: "bold",
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
interface Props {
|
|
20
|
+
executionStatusId: string;
|
|
21
|
+
sx?: SxProps;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const ExecutionTag: React.FC<Props> = (props: Props) => {
|
|
25
|
+
const t = useTranslations("Integrate");
|
|
26
|
+
|
|
27
|
+
const statusTagMap = {
|
|
28
|
+
300: (
|
|
29
|
+
<StyledTagBox
|
|
30
|
+
sx={{
|
|
31
|
+
backgroundColor: "info.100",
|
|
32
|
+
borderColor: "info.main",
|
|
33
|
+
...props.sx,
|
|
34
|
+
}}
|
|
35
|
+
>
|
|
36
|
+
<StyledTag color="info" variant="caption">
|
|
37
|
+
{t("Executions.inProgress")}
|
|
38
|
+
</StyledTag>
|
|
39
|
+
</StyledTagBox>
|
|
40
|
+
),
|
|
41
|
+
400: (
|
|
42
|
+
<StyledTagBox
|
|
43
|
+
sx={{
|
|
44
|
+
backgroundColor: "success.100",
|
|
45
|
+
borderColor: "success.main",
|
|
46
|
+
...props.sx,
|
|
47
|
+
}}
|
|
48
|
+
>
|
|
49
|
+
<StyledTag color="success" variant="caption">
|
|
50
|
+
{t("Executions.complete")}
|
|
51
|
+
</StyledTag>
|
|
52
|
+
</StyledTagBox>
|
|
53
|
+
),
|
|
54
|
+
450: (
|
|
55
|
+
<StyledTagBox
|
|
56
|
+
sx={{
|
|
57
|
+
backgroundColor: "warning.100",
|
|
58
|
+
borderColor: "orange.700",
|
|
59
|
+
color: "orange.700",
|
|
60
|
+
...props.sx,
|
|
61
|
+
}}
|
|
62
|
+
>
|
|
63
|
+
<StyledTag color="inherit" variant="caption">
|
|
64
|
+
{t("Executions.warning")}
|
|
65
|
+
</StyledTag>
|
|
66
|
+
</StyledTagBox>
|
|
67
|
+
),
|
|
68
|
+
500: (
|
|
69
|
+
<StyledTagBox
|
|
70
|
+
sx={{
|
|
71
|
+
backgroundColor: "error.100",
|
|
72
|
+
borderColor: "error.main",
|
|
73
|
+
...props.sx,
|
|
74
|
+
}}
|
|
75
|
+
>
|
|
76
|
+
<StyledTag color="error" variant="caption">
|
|
77
|
+
{t("Executions.failed")}
|
|
78
|
+
</StyledTag>
|
|
79
|
+
</StyledTagBox>
|
|
80
|
+
),
|
|
81
|
+
999: (
|
|
82
|
+
<StyledTagBox
|
|
83
|
+
sx={{
|
|
84
|
+
backgroundColor: "grey.300",
|
|
85
|
+
borderColor: "grey.600",
|
|
86
|
+
color: "grey.600",
|
|
87
|
+
...props.sx,
|
|
88
|
+
}}
|
|
89
|
+
>
|
|
90
|
+
<StyledTag color="inherit" variant="caption">
|
|
91
|
+
{t("Executions.unavailable")}
|
|
92
|
+
</StyledTag>
|
|
93
|
+
</StyledTagBox>
|
|
94
|
+
),
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
return statusTagMap[props.executionStatusId] || statusTagMap[999];
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export default ExecutionTag;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useTranslations } from "next-intl";
|
|
3
|
+
|
|
4
|
+
// MUI
|
|
5
|
+
import { Theme, useTheme } from "@mui/material";
|
|
6
|
+
import styled from "@mui/material/styles/styled";
|
|
7
|
+
import { Typography, Box, Grid2 as Grid } from "@mui/material";
|
|
8
|
+
import { Copyright } from "@mui/icons-material";
|
|
9
|
+
|
|
10
|
+
// Styled components
|
|
11
|
+
const Footer = styled("footer")(({ theme }) => ({
|
|
12
|
+
flexShrink: 0,
|
|
13
|
+
marginTop: "auto",
|
|
14
|
+
}));
|
|
15
|
+
|
|
16
|
+
const IntegrateFooter: React.FC = () => {
|
|
17
|
+
const t = useTranslations("Integrate.Footer");
|
|
18
|
+
|
|
19
|
+
const theme = useTheme();
|
|
20
|
+
const styles = getStyles(theme);
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<Footer>
|
|
24
|
+
<Grid container spacing={0.5} sx={styles.container}>
|
|
25
|
+
<Grid>
|
|
26
|
+
<Box sx={{ ...styles.centered, color: "grey.500" }}>
|
|
27
|
+
<Copyright color="inherit" fontSize="small" />
|
|
28
|
+
</Box>
|
|
29
|
+
</Grid>
|
|
30
|
+
<Grid>
|
|
31
|
+
<Box sx={styles.centered}>
|
|
32
|
+
<Typography variant="caption" color="grey">
|
|
33
|
+
{t("copyright")}
|
|
34
|
+
</Typography>
|
|
35
|
+
</Box>
|
|
36
|
+
</Grid>
|
|
37
|
+
</Grid>
|
|
38
|
+
</Footer>
|
|
39
|
+
);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const getStyles = (theme: Theme) => {
|
|
43
|
+
return {
|
|
44
|
+
container: {
|
|
45
|
+
justifyContent: "center",
|
|
46
|
+
padding: theme.spacing(5, 0, 0),
|
|
47
|
+
},
|
|
48
|
+
centered: {
|
|
49
|
+
display: "grid",
|
|
50
|
+
alignItems: "center",
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export default IntegrateFooter;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as IntegrateFooter } from "./footer";
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { redirect, RedirectType } from "next/navigation";
|
|
3
|
+
import { useTranslations } from "next-intl";
|
|
4
|
+
|
|
5
|
+
// MUI
|
|
6
|
+
import { Theme, useTheme } from "@mui/material";
|
|
7
|
+
import { Grid2 as Grid, Box, Typography, Button } from "@mui/material";
|
|
8
|
+
import { Refresh, VisibilityOutlined } from "@mui/icons-material";
|
|
9
|
+
|
|
10
|
+
// Custom components
|
|
11
|
+
import { OutlinedIconButton } from "../button";
|
|
12
|
+
|
|
13
|
+
interface Props {
|
|
14
|
+
title: string;
|
|
15
|
+
url?: string;
|
|
16
|
+
handleRefresh?: () => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const DashboardListHeader: React.FC<Props> = (props: Props) => {
|
|
20
|
+
const t = useTranslations("Integrate.Dashboard");
|
|
21
|
+
|
|
22
|
+
const theme = useTheme();
|
|
23
|
+
const styles = getStyles(theme);
|
|
24
|
+
|
|
25
|
+
const handleViewAll = () => {
|
|
26
|
+
//Temporarily commented out until executions detail page is implemented
|
|
27
|
+
//redirect(props.url, RedirectType.push);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<Grid container spacing={0}>
|
|
32
|
+
<Grid size={8}>
|
|
33
|
+
<Box sx={styles.title}>
|
|
34
|
+
<Typography variant="h6" sx={styles.typography}>
|
|
35
|
+
{props.title}
|
|
36
|
+
</Typography>
|
|
37
|
+
</Box>
|
|
38
|
+
</Grid>
|
|
39
|
+
<Grid size={4}>
|
|
40
|
+
<Box display="flex" justifyContent="flex-end">
|
|
41
|
+
{props.url && (
|
|
42
|
+
<Button
|
|
43
|
+
sx={styles.button}
|
|
44
|
+
variant="outlined"
|
|
45
|
+
color="info"
|
|
46
|
+
startIcon={<VisibilityOutlined />}
|
|
47
|
+
onClick={handleViewAll}
|
|
48
|
+
>
|
|
49
|
+
{t("ListHeader.viewAll")}
|
|
50
|
+
</Button>
|
|
51
|
+
)}
|
|
52
|
+
{props.handleRefresh && (
|
|
53
|
+
<OutlinedIconButton
|
|
54
|
+
sx={styles.iconButton}
|
|
55
|
+
color="info"
|
|
56
|
+
onClick={props.handleRefresh}
|
|
57
|
+
>
|
|
58
|
+
<Refresh />
|
|
59
|
+
</OutlinedIconButton>
|
|
60
|
+
)}
|
|
61
|
+
</Box>
|
|
62
|
+
</Grid>
|
|
63
|
+
</Grid>
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const getStyles = (theme: Theme) => {
|
|
68
|
+
return {
|
|
69
|
+
title: {
|
|
70
|
+
display: "flex",
|
|
71
|
+
alignItems: "center",
|
|
72
|
+
height: "100%",
|
|
73
|
+
},
|
|
74
|
+
typography: {
|
|
75
|
+
fontWeight: "medium",
|
|
76
|
+
},
|
|
77
|
+
button: {
|
|
78
|
+
borderWidth: 2,
|
|
79
|
+
borderRadius: 1,
|
|
80
|
+
marginRight: theme.spacing(1),
|
|
81
|
+
},
|
|
82
|
+
iconButton: {
|
|
83
|
+
borderRadius: 1,
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export default DashboardListHeader;
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
|
|
3
|
+
// MUI
|
|
4
|
+
import { Theme, useTheme } from "@mui/material";
|
|
5
|
+
import {
|
|
6
|
+
Grid2 as Grid,
|
|
7
|
+
Box,
|
|
8
|
+
Typography,
|
|
9
|
+
Button,
|
|
10
|
+
Stack,
|
|
11
|
+
Popover,
|
|
12
|
+
} from "@mui/material";
|
|
13
|
+
import { PlayArrowOutlined } from "@mui/icons-material";
|
|
14
|
+
|
|
15
|
+
// Custom components
|
|
16
|
+
import ExecutionTag from "../execution/execution-tag";
|
|
17
|
+
|
|
18
|
+
interface Execution {
|
|
19
|
+
name: string;
|
|
20
|
+
startDate: string;
|
|
21
|
+
endDate: string;
|
|
22
|
+
executionStatus: {
|
|
23
|
+
id: string;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface Props {
|
|
28
|
+
execution: Execution;
|
|
29
|
+
handleRun?: () => void;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const ExecutionDetailsHeader: React.FC<Props> = (props: Props) => {
|
|
33
|
+
const theme = useTheme();
|
|
34
|
+
const styles = getStyles(theme);
|
|
35
|
+
|
|
36
|
+
const startDate = new Date(props.execution.startDate);
|
|
37
|
+
const endDate = new Date(props.execution.endDate);
|
|
38
|
+
const localTime = startDate.toLocaleString();
|
|
39
|
+
const duration = (endDate.getTime() - startDate.getTime()) / 1000;
|
|
40
|
+
|
|
41
|
+
const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
|
|
42
|
+
const open = Boolean(anchorEl);
|
|
43
|
+
|
|
44
|
+
const handlePopoverOpen = (event: React.MouseEvent<HTMLElement>) => {
|
|
45
|
+
setAnchorEl(event.currentTarget);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const handlePopoverClose = () => {
|
|
49
|
+
setAnchorEl(null);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<Grid container spacing={0}>
|
|
54
|
+
<Grid size={8}>
|
|
55
|
+
<Stack spacing={5} direction="row">
|
|
56
|
+
<Typography variant="h5" sx={styles.typography}>
|
|
57
|
+
{props.execution.name}
|
|
58
|
+
</Typography>
|
|
59
|
+
<ExecutionTag
|
|
60
|
+
executionStatusId={props.execution.executionStatus.id}
|
|
61
|
+
/>
|
|
62
|
+
</Stack>
|
|
63
|
+
</Grid>
|
|
64
|
+
<Grid size={4}>
|
|
65
|
+
<Box display="flex" justifyContent="flex-end">
|
|
66
|
+
{props.handleRun && (
|
|
67
|
+
<Button
|
|
68
|
+
sx={styles.button}
|
|
69
|
+
variant="contained"
|
|
70
|
+
color="info"
|
|
71
|
+
startIcon={<PlayArrowOutlined />}
|
|
72
|
+
onClick={props.handleRun}
|
|
73
|
+
>
|
|
74
|
+
Run
|
|
75
|
+
</Button>
|
|
76
|
+
)}
|
|
77
|
+
</Box>
|
|
78
|
+
</Grid>
|
|
79
|
+
<Grid size={12}>
|
|
80
|
+
<Stack
|
|
81
|
+
spacing={1}
|
|
82
|
+
direction="row"
|
|
83
|
+
onMouseEnter={handlePopoverOpen}
|
|
84
|
+
onMouseLeave={handlePopoverClose}
|
|
85
|
+
>
|
|
86
|
+
<Typography color="grey" variant="caption">
|
|
87
|
+
{localTime}
|
|
88
|
+
</Typography>
|
|
89
|
+
<Typography color="grey" variant="caption">
|
|
90
|
+
Duration: {duration}s
|
|
91
|
+
</Typography>
|
|
92
|
+
</Stack>
|
|
93
|
+
</Grid>
|
|
94
|
+
<Popover
|
|
95
|
+
sx={{ pointerEvents: "none" }}
|
|
96
|
+
open={open}
|
|
97
|
+
anchorEl={anchorEl}
|
|
98
|
+
anchorOrigin={{
|
|
99
|
+
vertical: "bottom",
|
|
100
|
+
horizontal: "left",
|
|
101
|
+
}}
|
|
102
|
+
transformOrigin={{
|
|
103
|
+
vertical: "top",
|
|
104
|
+
horizontal: "left",
|
|
105
|
+
}}
|
|
106
|
+
onClose={handlePopoverClose}
|
|
107
|
+
disableRestoreFocus
|
|
108
|
+
>
|
|
109
|
+
<Box sx={styles.popover}>
|
|
110
|
+
<Typography variant="body2">
|
|
111
|
+
Uses your browser's local timezone.
|
|
112
|
+
</Typography>
|
|
113
|
+
<Box
|
|
114
|
+
display={
|
|
115
|
+
Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
116
|
+
? "block"
|
|
117
|
+
: "none"
|
|
118
|
+
}
|
|
119
|
+
>
|
|
120
|
+
<Typography variant="body2" align="center" sx={styles.timezone}>
|
|
121
|
+
{Intl.DateTimeFormat().resolvedOptions().timeZone}
|
|
122
|
+
</Typography>
|
|
123
|
+
</Box>
|
|
124
|
+
</Box>
|
|
125
|
+
</Popover>
|
|
126
|
+
</Grid>
|
|
127
|
+
);
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const getStyles = (theme: Theme) => {
|
|
131
|
+
return {
|
|
132
|
+
title: {
|
|
133
|
+
display: "flex",
|
|
134
|
+
alignItems: "center",
|
|
135
|
+
height: "100%",
|
|
136
|
+
},
|
|
137
|
+
typography: {
|
|
138
|
+
fontWeight: "medium",
|
|
139
|
+
},
|
|
140
|
+
button: {
|
|
141
|
+
borderWidth: 2,
|
|
142
|
+
borderRadius: 1,
|
|
143
|
+
marginRight: theme.spacing(1),
|
|
144
|
+
},
|
|
145
|
+
popover: {
|
|
146
|
+
padding: theme.spacing(1),
|
|
147
|
+
},
|
|
148
|
+
timezone: {
|
|
149
|
+
color: "info.main",
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
export default ExecutionDetailsHeader;
|