chore(litmus-portal): Added date filter in workflows table and some important refactorings (#1962)

This commit has the following changes:
- Date filter in the workflows table
- Important refactoring in the Browse Workflow Section
- Minor CSS fixes

Signed-off-by: Amit Kumar Das <amitkumar.das@mayadata.io>
This commit is contained in:
Amit Kumar Das 2020-09-04 17:55:52 +05:30 committed by GitHub
parent d74c1d3898
commit 9fb8cef94f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 571 additions and 198 deletions

View File

@ -2753,6 +2753,16 @@
"csstype": "^2.2.0"
}
},
"@types/react-date-range": {
"version": "0.95.1",
"resolved": "https://registry.npmjs.org/@types/react-date-range/-/react-date-range-0.95.1.tgz",
"integrity": "sha512-jzuh7fL9F1Y3eSoeyWoS/H2zSCn9WXvlbLfOOox9bopmZjyNwp/fx08TYrgi8jAJ60F2Aap8uA2BQbe8+7mNGg==",
"dev": true,
"requires": {
"@types/react": "*",
"moment": ">=2.14.0"
}
},
"@types/react-dom": {
"version": "16.9.8",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.8.tgz",
@ -13718,6 +13728,24 @@
"gl-mat4": "^1.0.1"
}
},
"materialui-daterange-picker": {
"version": "1.1.91",
"resolved": "https://registry.npmjs.org/materialui-daterange-picker/-/materialui-daterange-picker-1.1.91.tgz",
"integrity": "sha512-vMEQlI3WrTuWEVgAhO6P5X6WfC46A1I4BwnlaEKz9Tbsw/1vj1fms5BX37yJkZZs4+Rbj1XIp34l7uy3UyuVyw==",
"requires": {
"@material-ui/core": "^4.9.4",
"@material-ui/icons": "^4.9.1",
"classnames": "^2.2.6",
"date-fns": "^1.30.1"
},
"dependencies": {
"date-fns": {
"version": "1.30.1",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz",
"integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw=="
}
}
},
"math-log2": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/math-log2/-/math-log2-1.0.1.tgz",
@ -14174,8 +14202,7 @@
"moment": {
"version": "2.27.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz",
"integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==",
"dev": true
"integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ=="
},
"monotone-convex-hull-2d": {
"version": "1.0.1",

View File

@ -27,6 +27,8 @@
"js-yaml": "^3.14.0",
"jsonwebtoken": "^8.5.1",
"localforage": "^1.7.3",
"materialui-daterange-picker": "^1.1.91",
"moment": "^2.27.0",
"plotly.js": "^1.54.6",
"prop-types": "^15.7.2",
"rc-progress": "^3.0.0",

View File

@ -12,9 +12,10 @@ import LinearProgressBar from '../../ReturningHome/ProgressBar/LinearProgressBar
import useStyles from './styles';
import timeDifferenceForDate from '../../../../utils/datesModifier';
import { history } from '../../../../redux/configureStore';
import { WorkflowRun } from '../../../../models/workflowData';
interface TableDataProps {
data: any;
data: WorkflowRun;
}
const TableData: React.FC<TableDataProps> = ({ data }) => {
@ -33,7 +34,7 @@ const TableData: React.FC<TableDataProps> = ({ data }) => {
const handleMenu = () => {};
return (
<>
<TableCell className={classes.headerStatus1}>
<TableCell className={classes.tableDataStatus}>
<CustomStatus status={JSON.parse(data.execution_data).phase} />
</TableCell>
<TableCell className={classes.workflowNameData}>

View File

@ -0,0 +1,169 @@
import React from 'react';
import {
InputBase,
InputAdornment,
FormControl,
InputLabel,
Select,
MenuItem,
Typography,
IconButton,
Popover,
} from '@material-ui/core';
import SearchIcon from '@material-ui/icons/Search';
import { DateRangePicker } from 'materialui-daterange-picker';
import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
import ChevronRightIcon from '@material-ui/icons/ChevronRight';
import useStyles from './styles';
interface HeaderSectionProps {
searchValue: string;
statusValue: string;
clusterValue: string;
isOpen: boolean;
isDateOpen: boolean;
popAnchorEl: HTMLElement | null;
displayDate: string;
changeSearch: (
event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>
) => void;
changeStatus: (
event: React.ChangeEvent<{
name?: string | undefined;
value: unknown;
}>,
child: React.ReactNode
) => void;
changeCluster: (
event: React.ChangeEvent<{
name?: string | undefined;
value: unknown;
}>,
child: React.ReactNode
) => void;
popOverClick: (
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => void;
popOverClose: (
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => void;
toggle: () => void;
selectDate: (range: any) => void;
}
const HeaderSection: React.FC<HeaderSectionProps> = ({
searchValue,
statusValue,
clusterValue,
isOpen,
popAnchorEl,
isDateOpen,
displayDate,
changeSearch,
changeStatus,
changeCluster,
popOverClick,
popOverClose,
toggle,
selectDate,
}) => {
const classes = useStyles();
return (
<div>
<div className={classes.headerSection}>
{/* Search Field */}
<InputBase
id="input-with-icon-adornment"
placeholder="Search"
className={classes.search}
value={searchValue}
onChange={changeSearch}
startAdornment={
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
}
/>
{/* Select Workflow */}
<FormControl
variant="outlined"
className={classes.formControl}
color="secondary"
focused
>
<InputLabel className={classes.selectText}>
Workflow Status
</InputLabel>
<Select
value={statusValue}
onChange={changeStatus}
label="Workflow Status"
className={classes.selectText}
>
<MenuItem value="All">All</MenuItem>
<MenuItem value="Failed">Failed</MenuItem>
<MenuItem value="Running">Running</MenuItem>
<MenuItem value="Succeeded">Succeeded</MenuItem>
</Select>
</FormControl>
{/* Select Cluster */}
<FormControl
variant="outlined"
className={classes.formControl}
color="secondary"
focused
>
<InputLabel className={classes.selectText}>Target Cluster</InputLabel>
<Select
value={clusterValue}
onChange={changeCluster}
label="Target Cluster"
className={classes.selectText}
>
<MenuItem value="All">All</MenuItem>
<MenuItem value="Predefined">Cluset pre-defined</MenuItem>
<MenuItem value="Kubernetes">Kubernetes Cluster</MenuItem>
</Select>
</FormControl>
<div className={classes.selectDate}>
<Typography className={classes.displayDate}>
{displayDate}
<IconButton
style={{ width: 10, height: 10 }}
onClick={popOverClick}
>
{isOpen ? <KeyboardArrowDownIcon /> : <ChevronRightIcon />}
</IconButton>
</Typography>
</div>
<Popover
open={isOpen}
anchorEl={popAnchorEl}
onClose={popOverClose}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'center',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'center',
}}
style={{
marginTop: 10,
}}
>
<DateRangePicker
open={isDateOpen}
toggle={toggle}
onChange={selectDate}
/>
</Popover>
</div>
</div>
);
};
export default HeaderSection;

View File

@ -1,12 +1,6 @@
import { useQuery } from '@apollo/client';
import {
FormControl,
IconButton,
InputAdornment,
InputBase,
InputLabel,
MenuItem,
Select,
Table,
TableBody,
TableCell,
@ -16,9 +10,9 @@ import {
TableRow,
Typography,
} from '@material-ui/core';
import moment from 'moment';
import ExpandLessIcon from '@material-ui/icons/ExpandLess';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import SearchIcon from '@material-ui/icons/Search';
import React, { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import { WORKFLOW_DETAILS, WORKFLOW_EVENTS } from '../../../../graphql';
@ -41,6 +35,7 @@ import {
import Loader from '../../../Loader';
import useStyles from './styles';
import TableData from './TableData';
import HeaderSection from './headerSection';
interface FilterOptions {
search: string;
@ -59,6 +54,12 @@ interface SortData {
noOfSteps: { sort: boolean; ascending: boolean };
}
interface DateData {
dateValue: string;
fromDate: Date | undefined;
toDate: Date | undefined;
}
const BrowseWorkflow = () => {
const classes = useStyles();
const userData: UserData = useSelector((state: RootState) => state.userData);
@ -72,7 +73,6 @@ const BrowseWorkflow = () => {
variables: { projectID: selectedProjectID },
fetchPolicy: 'cache-and-network',
});
// Using subscription to get realtime data
useEffect(() => {
subscribeToMore<WorkflowSubscription>({
@ -121,6 +121,29 @@ const BrowseWorkflow = () => {
rowsPerPage: 5,
});
const [popAnchorEl, setPopAnchorEl] = React.useState<null | HTMLElement>(
null
);
const isOpen = Boolean(popAnchorEl);
const [open, setOpen] = React.useState<boolean>(false);
const handlePopOverClose = () => {
setPopAnchorEl(null);
setOpen(false);
};
const handlePopOverClick = (event: React.MouseEvent<HTMLElement>) => {
setPopAnchorEl(event.currentTarget);
setOpen(true);
};
// State for start date and end date
const [dateRange, setDateRange] = React.useState<DateData>({
dateValue: 'Select a period',
fromDate: new Date(0),
toDate: new Date(new Date().valueOf() + 1000 * 3600 * 24),
});
const filteredData = data?.getWorkFlowRuns
.filter((dataRow) =>
dataRow.workflow_name.toLowerCase().includes(filters.search)
@ -137,6 +160,14 @@ const BrowseWorkflow = () => {
? true
: dataRow.cluster_name.toLowerCase().includes(filters.cluster)
)
.filter((dataRow) => {
return dateRange.fromDate && dateRange.toDate === undefined
? true
: parseInt(dataRow.last_updated, 10) * 1000 >=
new Date(moment(dateRange.fromDate).format()).getTime() &&
parseInt(dataRow.last_updated, 10) * 1000 <=
new Date(moment(dateRange.toDate).format()).getTime();
})
.sort((a: WorkflowRun, b: WorkflowRun) => {
// Sorting based on unique fields
if (sortData.name.sort) {
@ -178,94 +209,73 @@ const BrowseWorkflow = () => {
return 0;
});
// Functions passed as props in the headerSeaction
const changeSearch = (
event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>
) => {
setFilters({ ...filters, search: event.target.value as string });
setPaginationData({ ...paginationData, pageNo: 0 });
};
const changeStatus = (
event: React.ChangeEvent<{
name?: string | undefined;
value: unknown;
}>
) => {
setFilters({ ...filters, status: event.target.value as string });
setPaginationData({ ...paginationData, pageNo: 0 });
};
const changeCluster = (
event: React.ChangeEvent<{
name?: string | undefined;
value: unknown;
}>
) => {
setFilters({ ...filters, cluster: event.target.value as string });
setPaginationData({ ...paginationData, pageNo: 0 });
};
// Function to set the date range for filtering
const dateChange = (range: any) => {
setDateRange({
dateValue: `${moment(range?.startDate)
.format('DD.MM.YYYY')
.toString()}-${moment(range?.endDate).format('DD.MM.YYYY').toString()}`,
fromDate:
moment(range?.startDate).format('DD-MM-YYYY') ===
moment(new Date()).format('DD-MM-YYYY')
? new Date(new Date().setHours(0, 0, 0))
: new Date(range?.startDate.setHours(0, 0, 0)),
toDate:
moment(range?.endDate).format('DD-MM-YYYY') ===
moment(new Date()).format('DD-MM-YYYY')
? new Date(new Date().setHours(23, 59, 59))
: new Date(range?.endDate.setHours(23, 59, 59)),
});
};
return (
<div>
<section className="Heading section">
<div className={classes.headerSection}>
<InputBase
id="input-with-icon-adornment"
placeholder="Search"
className={classes.search}
value={filters.search}
onChange={(e) => {
setFilters({ ...filters, search: e.target.value as string });
setPaginationData({ ...paginationData, pageNo: 0 });
}}
startAdornment={
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
}
{/* Header Section */}
<HeaderSection
searchValue={filters.search}
changeSearch={changeSearch}
statusValue={filters.status}
changeStatus={changeStatus}
clusterValue={filters.cluster}
changeCluster={changeCluster}
popOverClick={handlePopOverClick}
popOverClose={handlePopOverClose}
isOpen={isOpen}
popAnchorEl={popAnchorEl}
isDateOpen={open}
toggle={handlePopOverClose}
displayDate={dateRange.dateValue}
selectDate={dateChange}
/>
<FormControl className={classes.select}>
<InputLabel id="demo-simple-select-outlined-label">
Workflow Status
</InputLabel>
<Select
labelId="demo-simple-select-outlined-label"
id="demo-simple-select-outlined"
value={filters.status}
onChange={(e) => {
setFilters({ ...filters, status: e.target.value as string });
setPaginationData({ ...paginationData, pageNo: 0 });
}}
disableUnderline
>
<MenuItem value="All">
<Typography className={classes.menuItem}>All</Typography>
</MenuItem>
<MenuItem value="Failed">
<Typography className={classes.menuItem}>Failed</Typography>
</MenuItem>
<MenuItem value="Running">
<Typography className={classes.menuItem}>Running</Typography>
</MenuItem>
<MenuItem value="Succeeded">
<Typography className={classes.menuItem}>Succeeded</Typography>
</MenuItem>
</Select>
</FormControl>
<FormControl className={classes.select1}>
<InputLabel id="demo-simple-select-outlined-label">
Target Cluster
</InputLabel>
<Select
labelId="demo-simple-select-outlined-label"
id="demo-simple-select-outlined"
value={filters.cluster}
onChange={(e) => {
setFilters({ ...filters, cluster: e.target.value as string });
setPaginationData({ ...paginationData, pageNo: 0 });
}}
disableUnderline
>
<MenuItem value="All">
<Typography className={classes.menuItem}>All</Typography>
</MenuItem>
<MenuItem value="Predefined">
<Typography className={classes.menuItem}>
Cluset pre-defined
</Typography>
</MenuItem>
<MenuItem value="Kubernetes">
<Typography className={classes.menuItem}>
Kubernetes Cluster
</Typography>
</MenuItem>
</Select>
</FormControl>
<FormControl className={classes.select}>
<InputLabel id="demo-simple-select-outlined-label">Date</InputLabel>
<Select
labelId="demo-simple-select-outlined-label"
id="demo-simple-select-outlined"
value=""
disableUnderline
onChange={() => {}}
/>
</FormControl>
</div>
</section>
<section className="table section">
<TableContainer className={classes.tableMain}>
@ -394,7 +404,7 @@ const BrowseWorkflow = () => {
</div>
</TableCell>
{/* Menu */}
{/* Menu Cell */}
<TableCell />
</TableRow>
</TableHead>

View File

@ -1,39 +1,60 @@
import { makeStyles } from '@material-ui/core';
const useStyles = makeStyles((theme) => ({
// Header Section Properties
headerSection: {
width: '100%',
height: '5.625rem',
display: 'flex',
flexDirection: 'row',
alignContent: 'center',
alignItems: 'center',
justifyContent: 'center',
border: '1px solid ',
borderColor: theme.palette.text.hint,
borderColor: theme.palette.customColors.black(0.07),
backgroundColor: theme.palette.common.white,
},
search: {
fontSize: 14,
marginRight: 'auto',
borderBottom: `1px solid ${theme.palette.customColors.black(0.1)}`,
marginLeft: theme.spacing(6.25),
},
select: {
width: '9.375rem',
marginLeft: theme.spacing(1.25),
paddingBottom: theme.spacing(2.5),
// Form Select Properties
formControl: {
margin: theme.spacing(0.5),
marginRight: theme.spacing(2.5),
height: '2.5rem',
minWidth: '9rem',
},
select1: {
width: '10.375rem',
marginLeft: theme.spacing(1.25),
paddingBottom: theme.spacing(2.5),
selectText: {
height: '2.5rem',
padding: theme.spacing(0.5),
},
headerText: {
marginLeft: theme.spacing(3.75),
color: theme.palette.text.disabled,
paddingBottom: theme.spacing(0.625),
selectDate: {
display: 'flex',
flexDirection: 'row',
height: '2.5rem',
minWidth: '9rem',
border: '1.7px solid',
borderRadius: 4,
borderColor: theme.palette.secondary.main,
marginRight: theme.spacing(3.75),
},
displayDate: {
marginLeft: theme.spacing(1.875),
paddingTop: theme.spacing(0.75),
width: '100%',
},
// Table and Table Data Properties
tableMain: {
marginTop: theme.spacing(6.25),
border: '1px solid rgba(0,0,0,0.1)',
border: `1px solid ${theme.palette.customColors.black(0.07)}`,
backgroundColor: theme.palette.common.white,
height: '29.219rem',
},
@ -42,10 +63,22 @@ const useStyles = makeStyles((theme) => ({
},
headerStatus: {
paddingLeft: theme.spacing(10),
color: 'rgba(0, 0, 0, 0.4)',
color: theme.palette.customColors.black(0.4),
},
headerStatus1: {
paddingLeft: theme.spacing(8),
workflowName: {
borderRight: `1px solid ${theme.palette.customColors.black(0.1)}`,
color: theme.palette.customColors.black(0.4),
},
sortDiv: {
display: 'flex',
flexDirection: 'column',
paddingLeft: theme.spacing(1.25),
},
headData: {
color: theme.palette.customColors.black(0.4),
},
tableDataStatus: {
paddingLeft: theme.spacing(8.5),
},
progressBar: {
width: '6.5rem',
@ -53,23 +86,13 @@ const useStyles = makeStyles((theme) => ({
steps: {
marginLeft: theme.spacing(5.625),
},
menuItem: {
paddingLeft: theme.spacing(1.75),
},
workflowName: {
borderRight: '1px solid rgba(0,0,0,0.1)',
color: theme.palette.customColors.black(0.4),
},
workflowNameData: {
borderRight: '1px solid rgba(0,0,0,0.1)',
borderRight: `1px solid ${theme.palette.customColors.black(0.1)}`,
},
targetCluster: {
paddingLeft: theme.spacing(3.75),
color: theme.palette.customColors.black(0.4),
},
headData: {
color: theme.palette.customColors.black(0.4),
},
clusterName: {
marginLeft: theme.spacing(3.75),
},
@ -86,11 +109,6 @@ const useStyles = makeStyles((theme) => ({
display: 'flex',
flexDirection: 'row',
},
sortDiv: {
display: 'flex',
flexDirection: 'column',
paddingLeft: theme.spacing(1.25),
},
}));
export default useStyles;

View File

@ -11,47 +11,52 @@ import {
import MoreVertIcon from '@material-ui/icons/MoreVert';
import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
import ChevronRightIcon from '@material-ui/icons/ChevronRight';
import moment from 'moment';
import useStyles from './styles';
import LinearProgressBar from '../../ReturningHome/ProgressBar/LinearProgressBar';
import { history } from '../../../../redux/configureStore';
import { WorkflowRun } from '../../../../models/workflowData';
interface TableDataProps {
data: any;
data: WorkflowRun;
deleteRow: (workflowId: string) => void;
}
const TableData: React.FC<TableDataProps> = ({ data }) => {
const TableData: React.FC<TableDataProps> = ({ data, deleteRow }) => {
const classes = useStyles();
// States for PopOver to display Experiment Weights
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const [popAnchorEl, setPopAnchorEl] = React.useState<null | HTMLElement>(
null
);
const open = Boolean(anchorEl);
const handleClick = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
};
const isOpen = Boolean(popAnchorEl);
const id = isOpen ? 'simple-popover' : undefined;
const handlePopOverClose = () => {
setPopAnchorEl(null);
};
const handlePopOverClick = (event: React.MouseEvent<HTMLElement>) => {
setPopAnchorEl(event.currentTarget);
};
const handleClick = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const handleMenu = () => {};
// Function to convert UNIX time in format of DD MMM YYY
const formatDate = (date: any) => {
const updated = new Date(date * 1000).toString();
const day = updated.slice(8, 10);
const month = updated.slice(4, 7);
const year = updated.slice(11, 15);
const resDate = `${day} ${month} ${year}`;
const resDate = moment(updated).format('DD MMM YYYY');
return resDate;
};
// Dummy Experiment Weights
const exWeight = [
{
name: 'Node add test',
@ -103,7 +108,7 @@ const TableData: React.FC<TableDataProps> = ({ data }) => {
<KeyboardArrowDownIcon className={classes.expInfo} />
</div>
) : (
<div className={classes.expDiv1}>
<div className={classes.expDiv}>
<Typography>
<strong>Show Experiment</strong>
</Typography>
@ -180,7 +185,10 @@ const TableData: React.FC<TableDataProps> = ({ data }) => {
<Typography className={classes.btnText}>Edit Schedule</Typography>
</div>
</MenuItem>
<MenuItem value="Analysis" onClick={handleMenu}>
<MenuItem
value="Analysis"
onClick={() => deleteRow(data.workflow_id)}
>
<div className={classes.expDiv}>
<img
src="/icons/deleteSchedule.svg"

View File

@ -16,13 +16,27 @@ import {
TableCell,
TableBody,
TablePagination,
IconButton,
} from '@material-ui/core';
import ExpandLessIcon from '@material-ui/icons/ExpandLess';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import { useSelector } from 'react-redux';
import useStyles from './styles';
import { WORKFLOW_DETAILS } from '../../../../graphql';
import TableData from './TableData';
import { Workflow, WorkflowDataVars } from '../../../../models/workflowData';
import {
Workflow,
WorkflowDataVars,
WorkflowRun,
ExecutionData,
} from '../../../../models/workflowData';
import Loader from '../../../Loader';
import {
sortAlphaAsc,
sortAlphaDesc,
sortNumAsc,
sortNumDesc,
} from '../../../../utils/sort';
import { UserData } from '../../../../models/user';
import { RootState } from '../../../../redux/reducers';
@ -36,6 +50,11 @@ interface PaginationData {
rowsPerPage: number;
}
interface SortData {
startDate: { sort: boolean; ascending: boolean };
name: { sort: boolean; ascending: boolean };
}
const ScheduleWorkflow = () => {
const classes = useStyles();
const userData: UserData = useSelector((state: RootState) => state.userData);
@ -59,6 +78,12 @@ const ScheduleWorkflow = () => {
rowsPerPage: 5,
});
// State for sorting
const [sortData, setSortData] = useState<SortData>({
name: { sort: false, ascending: true },
startDate: { sort: true, ascending: true },
});
const filteredData = data?.getWorkFlowRuns
.filter((dataRow) =>
dataRow.workflow_name.toLowerCase().includes(filter.search)
@ -68,12 +93,41 @@ const ScheduleWorkflow = () => {
? true
: dataRow.cluster_name.toLowerCase().includes(filter.cluster)
)
.reverse();
.sort((a: WorkflowRun, b: WorkflowRun) => {
// Sorting based on unique fields
if (sortData.name.sort) {
const x = a.workflow_name;
const y = b.workflow_name;
return sortData.name.ascending
? sortAlphaAsc(x, y)
: sortAlphaDesc(x, y);
}
if (sortData.startDate.sort) {
const x = parseInt(
(JSON.parse(a.execution_data) as ExecutionData).startedAt,
10
);
const y = parseInt(
(JSON.parse(b.execution_data) as ExecutionData).startedAt,
10
);
return sortData.startDate.ascending
? sortNumAsc(y, x)
: sortNumDesc(y, x);
}
return 0;
});
const deleteRow = () => {
// Delete Mutation Here
};
return (
<div>
<section className="Heading section">
<div className={classes.headerSection}>
{/* Search Field */}
<InputBase
id="input-with-icon-adornment"
placeholder="Search"
@ -88,59 +142,126 @@ const ScheduleWorkflow = () => {
</InputAdornment>
}
/>
<FormControl className={classes.select}>
<InputLabel id="demo-simple-select-outlined-label">
{/* Select Cluster */}
<FormControl
variant="outlined"
className={classes.formControl}
color="secondary"
focused
>
<InputLabel className={classes.selectText}>
Target Cluster
</InputLabel>
<Select
labelId="demo-simple-select-outlined-label"
id="demo-simple-select-outlined"
value={filter.cluster}
onChange={(event) =>
setFilter({ ...filter, cluster: event.target.value as string })
}
disableUnderline
label="Target Cluster"
className={classes.selectText}
>
<MenuItem value="All">
<Typography className={classes.menuItem}>All</Typography>
</MenuItem>
<MenuItem value="Predefined">
<Typography className={classes.menuItem}>
Cluset pre-defined
</Typography>
</MenuItem>
<MenuItem value="Kubernetes">
<Typography className={classes.menuItem}>
Kubernetes Cluster
</Typography>
</MenuItem>
<MenuItem value="All">All</MenuItem>
<MenuItem value="Predefined">Cluset pre-defined</MenuItem>
<MenuItem value="Kubernetes">Kubernetes Cluster</MenuItem>
</Select>
</FormControl>
</div>
</section>
<section className="table section">
{/* Table Header */}
<TableContainer className={classes.tableMain}>
<Table stickyHeader aria-label="simple table">
<TableHead>
<TableRow className={classes.tableHead}>
{/* WorkFlow Name */}
<TableCell className={classes.workflowName}>
<Typography style={{ paddingLeft: 65 }}>
<div style={{ display: 'flex', flexDirection: 'row' }}>
<Typography style={{ paddingLeft: 65, paddingTop: 10 }}>
Workflow Name
</Typography>
<div className={classes.sortDiv}>
<IconButton
aria-label="sort name ascending"
size="small"
onClick={() =>
setSortData({
...sortData,
name: { sort: true, ascending: true },
startDate: { sort: false, ascending: true },
})
}
>
<ExpandLessIcon fontSize="inherit" />
</IconButton>
<IconButton
aria-label="sort name descending"
size="small"
onClick={() =>
setSortData({
...sortData,
name: { sort: true, ascending: false },
startDate: { sort: false, ascending: false },
})
}
>
<ExpandMoreIcon fontSize="inherit" />
</IconButton>
</div>
</div>
</TableCell>
{/* Starting Date */}
<TableCell className={classes.headerStatus}>
<div style={{ display: 'flex', flexDirection: 'row' }}>
<Typography style={{ paddingTop: 10 }}>
Starting Date
</Typography>
<div className={classes.sortDiv}>
<IconButton
aria-label="sort last run ascending"
size="small"
onClick={() =>
setSortData({
...sortData,
startDate: { sort: true, ascending: true },
name: { sort: false, ascending: true },
})
}
>
<ExpandLessIcon fontSize="inherit" />
</IconButton>
<IconButton
aria-label="sort last run descending"
size="small"
onClick={() =>
setSortData({
...sortData,
startDate: { sort: true, ascending: false },
name: { sort: false, ascending: true },
})
}
>
<ExpandMoreIcon fontSize="inherit" />
</IconButton>
</div>
</div>
</TableCell>
{/* Regularity */}
<TableCell>
<Typography className={classes.regularity}>
Regularity
</Typography>
</TableCell>
{/* Cluster */}
<TableCell>
<Typography className={classes.targetCluster}>
Cluster
</Typography>
</TableCell>
{/* Show Experiments */}
<TableCell>
<Typography className={classes.showExp}>
Show Experiments
@ -169,9 +290,9 @@ const ScheduleWorkflow = () => {
paginationData.pageNo * paginationData.rowsPerPage +
paginationData.rowsPerPage
)
.map((data: any) => (
.map((data) => (
<TableRow key={data.workflow_run_id}>
<TableData data={data} />
<TableData data={data} deleteRow={deleteRow} />
</TableRow>
))
) : (
@ -184,6 +305,8 @@ const ScheduleWorkflow = () => {
</TableBody>
</Table>
</TableContainer>
{/* Pagination Section */}
<TablePagination
rowsPerPageOptions={[5, 10, 25]}
component="div"

View File

@ -1,27 +1,39 @@
import { makeStyles } from '@material-ui/core';
const useStyles = makeStyles((theme) => ({
// Header Section Properties
headerSection: {
width: '100%',
height: '5.625rem',
display: 'flex',
flexDirection: 'row',
alignContent: 'center',
alignItems: 'center',
justifyContent: 'center',
border: '1px solid ',
borderColor: theme.palette.text.hint,
borderColor: theme.palette.customColors.black(0.07),
backgroundColor: theme.palette.common.white,
},
search: {
fontSize: 14,
marginRight: 'auto',
borderBottom: `1px solid ${theme.palette.customColors.black(0.1)}`,
marginLeft: theme.spacing(6.25),
},
select: {
width: '10.375rem',
marginLeft: theme.spacing(1.25),
paddingBottom: theme.spacing(2.5),
marginRight: theme.spacing(3.75),
// Form Select Properties
formControl: {
margin: theme.spacing(0.5),
marginRight: theme.spacing(6.25),
height: '2.5rem',
minWidth: '9rem',
},
selectText: {
height: '2.5rem',
padding: theme.spacing(0.5),
},
// Table and Table Data Properties
headerText: {
marginLeft: theme.spacing(3.75),
color: theme.palette.text.disabled,
@ -29,9 +41,9 @@ const useStyles = makeStyles((theme) => ({
},
tableMain: {
marginTop: theme.spacing(6.25),
border: '1px solid rgba(0,0,0,0.1)',
border: `1px solid ${theme.palette.customColors.black(0.07)}`,
backgroundColor: theme.palette.common.white,
height: '29.180rem',
height: '29.220rem',
},
tableHead: {
opacity: 1,
@ -54,11 +66,16 @@ const useStyles = makeStyles((theme) => ({
paddingLeft: theme.spacing(1.75),
},
workflowName: {
borderRight: '1px solid rgba(0,0,0,0.1)',
borderRight: `1px solid ${theme.palette.customColors.black(0.1)}`,
color: theme.palette.customColors.black(0.4),
},
sortDiv: {
display: 'flex',
flexDirection: 'column',
marginLeft: theme.spacing(1.25),
},
workflowNameData: {
borderRight: '1px solid rgba(0,0,0,0.1)',
borderRight: `1px solid ${theme.palette.customColors.black(0.1)}`,
},
regularity: {
paddingLeft: theme.spacing(3.75),
@ -84,24 +101,6 @@ const useStyles = makeStyles((theme) => ({
paddingLeft: theme.spacing(1),
color: theme.palette.customColors.black(0.4),
},
expDiv: {
display: 'flex',
flexDirection: 'row',
},
expDiv1: {
display: 'flex',
flexDirection: 'row',
cursor: 'pointer',
},
weightDiv: {
width: 243,
padding: '25px 20px',
},
weightInfo: {
display: 'flex',
flexDirection: 'row',
paddingBottom: theme.spacing(0.625),
},
clusterData: {
paddingTop: theme.spacing(1.25),
},
@ -123,6 +122,22 @@ const useStyles = makeStyles((theme) => ({
btnText: {
paddingLeft: theme.spacing(1.625),
},
// Experiment Weights PopOver Property
weightDiv: {
width: '15.1875rem',
padding: theme.spacing(3.125, 2.6),
},
weightInfo: {
display: 'flex',
flexDirection: 'row',
paddingBottom: theme.spacing(0.625),
},
expDiv: {
display: 'flex',
flexDirection: 'row',
cursor: 'pointer',
},
}));
export default useStyles;