diff --git a/frontend/README.md b/frontend/README.md index 0b01bbaf..6bd63aab 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -1,5 +1,5 @@ -# Openshift Performance Dashbaord +# Openshift Performance Dashboard ## Dashboard directory structure diff --git a/frontend/src/App.js b/frontend/src/App.js deleted file mode 100644 index 4b8c6382..00000000 --- a/frontend/src/App.js +++ /dev/null @@ -1,58 +0,0 @@ -import React, {useEffect} from 'react'; -import '@patternfly/react-core/dist/styles/base.css'; - -import { - Page, - PageSection, - PageSectionVariants, -} from '@patternfly/react-core'; -import {fetchOCPJobsData, fetchCPTJobsData, fetchQuayJobsData, fetchTelcoJobsData} from "./store/Actions/ActionCreator"; -import {useDispatch} from "react-redux"; -import {Route, Switch, BrowserRouter as Router} from "react-router-dom"; -import {NavBar} from "./components/NavBar/NavBar"; -import {HomeView} from "./components/Home/HomeView"; -import {OCPHome} from './components/OCP/OCPHome'; -import {QuayHome} from './components/Quay/QuayHome'; -import {TelcoHome} from './components/Telco/TelcoHome'; - - -export const App = () => { - const dispatch = useDispatch() - - useEffect(() => { - const fetchData = async () =>{ - await dispatch(fetchOCPJobsData()) - await dispatch(fetchCPTJobsData()) - await dispatch(fetchQuayJobsData()) - await dispatch(fetchTelcoJobsData()) - } - fetchData() - }, [dispatch]) - - - - - return ( - - } - groupProps={{ - stickyOnBreakpoint: { default: 'top' }, - sticky: 'top' - }} - > - - - - - - - - - - - - ); -}; - -export default App diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index c5f48549..d93c960e 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -5,6 +5,7 @@ import * as APP_ROUTES from "./utils/routeConstants"; import { BrowserRouter, Route, Routes } from "react-router-dom"; import Home from "./components/templates/Home"; +import ILab from "./components/templates/ILab"; import MainLayout from "./containers/MainLayout"; import OCP from "./components/templates/OCP"; import Quay from "./components/templates/Quay"; @@ -26,6 +27,7 @@ function App() { } /> } /> } /> + } /> diff --git a/frontend/src/actions/filterActions.js b/frontend/src/actions/filterActions.js index 7f565887..f8fa5691 100644 --- a/frontend/src/actions/filterActions.js +++ b/frontend/src/actions/filterActions.js @@ -1,3 +1,4 @@ +import { fetchILabJobs, setIlabDateFilter } from "./ilabActions"; import { removeCPTAppliedFilters, setCPTAppliedFilters, @@ -76,6 +77,9 @@ export const setDateFilter = (date, key, navigation, currType) => { dispatch(setQuayDateFilter(date, key, navigation)); } else if (currType === "telco") { dispatch(setTelcoDateFilter(date, key, navigation)); + } else if (currType === "ilab") { + dispatch(setIlabDateFilter(date, key, navigation)); + dispatch(fetchILabJobs()); } }; diff --git a/frontend/src/actions/ilabActions.js b/frontend/src/actions/ilabActions.js new file mode 100644 index 00000000..1152846b --- /dev/null +++ b/frontend/src/actions/ilabActions.js @@ -0,0 +1,213 @@ +import * as API_ROUTES from "@/utils/apiConstants"; +import * as TYPES from "./types.js"; + +import API from "@/utils/axiosInstance"; +import { appendQueryString } from "@/utils/helper"; +import { cloneDeep } from "lodash"; +import { showFailureToast } from "@/actions/toastActions"; + +export const fetchILabJobs = + (shouldStartFresh = false) => + async (dispatch, getState) => { + try { + dispatch({ type: TYPES.LOADING }); + const { start_date, end_date, size, offset, results } = getState().ilab; + const response = await API.get(API_ROUTES.ILABS_JOBS_API_V1, { + params: { + ...(start_date && { start_date }), + ...(end_date && { end_date }), + ...(size && { size }), + ...(offset && { offset }), + }, + }); + if (response.status === 200 && response?.data?.results.length > 0) { + const startDate = response.data.startDate, + endDate = response.data.endDate; + dispatch({ + type: TYPES.SET_ILAB_JOBS_DATA, + payload: shouldStartFresh + ? response.data.results + : [...results, ...response.data.results], + }); + + dispatch({ + type: TYPES.SET_ILAB_DATE_FILTER, + payload: { + start_date: startDate, + end_date: endDate, + }, + }); + + dispatch({ + type: TYPES.SET_ILAB_TOTAL_ITEMS, + payload: response.data.total, + }); + dispatch({ + type: TYPES.SET_ILAB_OFFSET, + payload: response.data.next_offset, + }); + + dispatch(tableReCalcValues()); + } + } catch (error) { + dispatch(showFailureToast()); + } + dispatch({ type: TYPES.COMPLETED }); + }; +export const sliceIlabTableRows = + (startIdx, endIdx) => (dispatch, getState) => { + const results = [...getState().ilab.results]; + + dispatch({ + type: TYPES.SET_ILAB_INIT_JOBS, + payload: results.slice(startIdx, endIdx), + }); + }; +export const setIlabDateFilter = + (start_date, end_date, navigate) => (dispatch, getState) => { + const appliedFilters = getState().ilab.appliedFilters; + + dispatch({ + type: TYPES.SET_ILAB_DATE_FILTER, + payload: { + start_date, + end_date, + }, + }); + + appendQueryString({ ...appliedFilters, start_date, end_date }, navigate); + }; + +export const fetchMetricsInfo = (uid) => async (dispatch) => { + try { + dispatch({ type: TYPES.LOADING }); + const response = await API.get(`/api/v1/ilab/runs/${uid}/metrics`); + if (response.status === 200) { + if ( + response.data.constructor === Object && + Object.keys(response.data).length > 0 + ) { + dispatch({ + type: TYPES.SET_ILAB_METRICS, + payload: { uid, metrics: Object.keys(response.data) }, + }); + } + } + } catch (error) { + console.error(error); + dispatch(showFailureToast()); + } + dispatch({ type: TYPES.COMPLETED }); +}; + +export const fetchPeriods = (uid) => async (dispatch) => { + try { + dispatch({ type: TYPES.LOADING }); + const response = await API.get(`/api/v1/ilab/runs/${uid}/periods`); + if (response.status === 200) { + dispatch({ + type: TYPES.SET_ILAB_PERIODS, + payload: { uid, periods: response.data }, + }); + } + } catch (error) { + console.error( + `ERROR (${error?.response?.status}): ${JSON.stringify( + error?.response?.data + )}` + ); + dispatch(showFailureToast()); + } + dispatch({ type: TYPES.COMPLETED }); +}; + +export const fetchGraphData = + (uid, metric, primary_metric) => async (dispatch, getState) => { + try { + const periods = getState().ilab.periods.find((i) => i.uid == uid); + const graphData = cloneDeep(getState().ilab.graphData); + const filterData = graphData.filter((i) => i.uid !== uid); + dispatch({ + type: TYPES.SET_ILAB_GRAPH_DATA, + payload: filterData, + }); + const copyData = cloneDeep(filterData); + dispatch({ type: TYPES.GRAPH_LOADING }); + let graphs = []; + periods?.periods?.forEach((p) => { + graphs.push({ metric: p.primary_metric, periods: [p.id] }); + graphs.push({ + metric, + aggregate: true, + periods: [p.id], + }); + }); + const response = await API.post(`/api/v1/ilab/runs/multigraph`, { + run: uid, + name: primary_metric, + graphs, + }); + if (response.status === 200) { + copyData.push({ + uid, + data: response.data.data, + layout: response.data.layout, + }); + dispatch({ + type: TYPES.SET_ILAB_GRAPH_DATA, + payload: copyData, + }); + } + } catch (error) { + console.error( + `ERROR (${error?.response?.status}): ${JSON.stringify( + error?.response?.data + )}` + ); + dispatch(showFailureToast()); + } + dispatch({ type: TYPES.GRAPH_COMPLETED }); + }; + +export const setIlabPage = (pageNo) => ({ + type: TYPES.SET_ILAB_PAGE, + payload: pageNo, +}); + +export const setIlabPageOptions = (page, perPage) => ({ + type: TYPES.SET_ILAB_PAGE_OPTIONS, + payload: { page, perPage }, +}); + +export const checkIlabJobs = (newPage) => (dispatch, getState) => { + const results = cloneDeep(getState().ilab.results); + const { totalItems, perPage } = getState().ilab; + + const startIdx = (newPage - 1) * perPage; + const endIdx = newPage * perPage; + + if ( + (typeof results[startIdx] === "undefined" || + typeof results[endIdx] === "undefined") && + results.length < totalItems + ) { + dispatch(fetchILabJobs()); + } +}; + +export const setSelectedMetrics = (id, metrics) => (dispatch, getState) => { + const metrics_selected = cloneDeep(getState().ilab.metrics_selected); + metrics_selected[id] = metrics; + dispatch({ + type: TYPES.SET_ILAB_SELECTED_METRICS, + payload: metrics_selected, + }); +}; + +export const tableReCalcValues = () => (dispatch, getState) => { + const { page, perPage } = getState().ilab; + + const startIdx = page !== 1 ? (page - 1) * perPage : 0; + const endIdx = page !== 1 ? page * perPage - 1 : perPage; + dispatch(sliceIlabTableRows(startIdx, endIdx)); +}; diff --git a/frontend/src/actions/paginationActions.js b/frontend/src/actions/paginationActions.js index 80a7dff1..1717a82a 100644 --- a/frontend/src/actions/paginationActions.js +++ b/frontend/src/actions/paginationActions.js @@ -3,9 +3,17 @@ import { setCPTPageOptions, sliceCPTTableRows, } from "./homeActions"; +import { + setIlabPage, + setIlabPageOptions, + sliceIlabTableRows, +} from "./ilabActions"; import { setOCPPage, setOCPPageOptions, sliceOCPTableRows } from "./ocpActions"; import { setQuayPage, setQuayPageOptions } from "./quayActions"; import { setTelcoPage, setTelcoPageOptions } from "./telcoActions"; + +import { checkIlabJobs } from "./ilabActions"; + export const setPage = (newPage, currType) => (dispatch) => { if (currType === "cpt") { dispatch(setCPTPage(newPage)); @@ -15,6 +23,8 @@ export const setPage = (newPage, currType) => (dispatch) => { dispatch(setQuayPage(newPage)); } else if (currType === "telco") { dispatch(setTelcoPage(newPage)); + } else if (currType === "ilab") { + dispatch(setIlabPage(newPage)); } }; @@ -27,6 +37,8 @@ export const setPageOptions = (newPage, newPerPage, currType) => (dispatch) => { dispatch(setQuayPageOptions(newPage, newPerPage)); } else if (currType === "telco") { dispatch(setTelcoPageOptions(newPage, newPerPage)); + } else if (currType === "ilab") { + dispatch(setIlabPageOptions(newPage, newPerPage)); } }; @@ -35,5 +47,11 @@ export const sliceTableRows = (startIdx, endIdx, currType) => (dispatch) => { dispatch(sliceCPTTableRows(startIdx, endIdx)); } else if (currType === "ocp") { dispatch(sliceOCPTableRows(startIdx, endIdx)); + } else if (currType === "ilab") { + dispatch(sliceIlabTableRows(startIdx, endIdx)); } }; + +export const fetchNextJobs = (newPage) => (dispatch) => { + dispatch(checkIlabJobs(newPage)); +}; diff --git a/frontend/src/actions/types.js b/frontend/src/actions/types.js index 1804cf21..58d7506f 100644 --- a/frontend/src/actions/types.js +++ b/frontend/src/actions/types.js @@ -77,3 +77,15 @@ export const SET_TELCO_SELECTED_FILTERS = "SET_TELCO_SELECTED_FILTERS"; export const SET_TELCO_SUMMARY = "SET_TELCO_SUMMARY"; export const SET_TELCO_COLUMNS = "SET_TELCO_COLUMNS"; export const SET_TELCO_GRAPH_DATA = "SET_TELCO_GRAPH_DATA"; +/* ILAB JOBS */ +export const SET_ILAB_JOBS_DATA = "SET_ILAB_JOBS_DATA"; +export const SET_ILAB_DATE_FILTER = "SET_ILAB_DATE_FILTER"; +export const SET_ILAB_GRAPH_DATA = "SET_ILAB_GRAPH_DATA"; +export const SET_ILAB_TOTAL_ITEMS = "SET_ILAB_TOTAL_ITEMS"; +export const SET_ILAB_OFFSET = "SET_ILAB_OFFSET"; +export const SET_ILAB_PAGE = "SET_ILAB_PAGE"; +export const SET_ILAB_PAGE_OPTIONS = "SET_ILAB_PAGE_OPTIONS"; +export const SET_ILAB_METRICS = "SET_ILAB_METRICS"; +export const SET_ILAB_SELECTED_METRICS = "SET_ILAB_SELECTED_METRICS"; +export const SET_ILAB_PERIODS = "SET_ILAB_PERIODS"; +export const SET_ILAB_INIT_JOBS = "SET_ILAB_INIT_JOBS"; diff --git a/frontend/src/assets/constants/SidemenuConstants.js b/frontend/src/assets/constants/SidemenuConstants.js index bc04fd52..e65a2103 100644 --- a/frontend/src/assets/constants/SidemenuConstants.js +++ b/frontend/src/assets/constants/SidemenuConstants.js @@ -2,3 +2,4 @@ export const HOME_NAV = "home"; export const QUAY_NAV = "quay"; export const OCP_NAV = "ocp"; export const TELCO_NAV = "telco"; +export const ILAB_NAV = "ilab"; diff --git a/frontend/src/components/molecules/ExpandedRow/index.jsx b/frontend/src/components/molecules/ExpandedRow/index.jsx index 981d5660..8fcc2d48 100644 --- a/frontend/src/components/molecules/ExpandedRow/index.jsx +++ b/frontend/src/components/molecules/ExpandedRow/index.jsx @@ -42,7 +42,7 @@ const RowContent = (props) => { }, []); return ( - + {content.map((unit) => ( diff --git a/frontend/src/components/molecules/SideMenuOptions/index.jsx b/frontend/src/components/molecules/SideMenuOptions/index.jsx index 48bed8de..17a00160 100644 --- a/frontend/src/components/molecules/SideMenuOptions/index.jsx +++ b/frontend/src/components/molecules/SideMenuOptions/index.jsx @@ -28,6 +28,11 @@ const sideMenuOptions = [ key: "telco", displayName: "Telco", }, + { + id: CONSTANTS.ILAB_NAV, + key: "ilab", + displayName: "ILAB", + }, ]; const MenuOptions = () => { diff --git a/frontend/src/components/organisms/Pagination/index.jsx b/frontend/src/components/organisms/Pagination/index.jsx index 7b316a21..deb8d8fe 100644 --- a/frontend/src/components/organisms/Pagination/index.jsx +++ b/frontend/src/components/organisms/Pagination/index.jsx @@ -1,5 +1,6 @@ import { Pagination, PaginationVariant } from "@patternfly/react-core"; import { + fetchNextJobs, setPage, setPageOptions, sliceTableRows, @@ -13,6 +14,7 @@ const RenderPagination = (props) => { const dispatch = useDispatch(); const perPageOptions = [ + { title: "10", value: 10 }, { title: "25", value: 25 }, { title: "50", value: 50 }, { title: "100", value: 100 }, @@ -21,6 +23,7 @@ const RenderPagination = (props) => { const onSetPage = useCallback( (_evt, newPage, _perPage, startIdx, endIdx) => { dispatch(setPage(newPage, props.type)); + dispatch(sliceTableRows(startIdx, endIdx, props.type)); }, [dispatch, props.type] @@ -28,11 +31,17 @@ const RenderPagination = (props) => { const onPerPageSelect = useCallback( (_evt, newPerPage, newPage, startIdx, endIdx) => { dispatch(setPageOptions(newPage, newPerPage, props.type)); + dispatch(sliceTableRows(startIdx, endIdx, props.type)); }, [dispatch, props.type] ); + const checkAndFetch = (_evt, newPage) => { + if (props.type === "ilab") { + dispatch(fetchNextJobs(newPage)); + } + }; return ( { perPage={props.perPage} page={props.page} variant={PaginationVariant.bottom} + onNextClick={checkAndFetch} perPageOptions={perPageOptions} onSetPage={onSetPage} onPerPageSelect={onPerPageSelect} + onPageInput={checkAndFetch} /> ); }; diff --git a/frontend/src/components/organisms/TableFilters/index.jsx b/frontend/src/components/organisms/TableFilters/index.jsx index c5f5ae62..0dd5885d 100644 --- a/frontend/src/components/organisms/TableFilters/index.jsx +++ b/frontend/src/components/organisms/TableFilters/index.jsx @@ -124,7 +124,8 @@ const TableFilter = (props) => { )} - {Object.keys(appliedFilters).length > 0 && + {appliedFilters && + Object.keys(appliedFilters).length > 0 && Object.keys(appliedFilters).map((key) => ( {getFilterName(key)} : diff --git a/frontend/src/components/templates/ILab/ILabGraph.jsx b/frontend/src/components/templates/ILab/ILabGraph.jsx new file mode 100644 index 00000000..c41300ba --- /dev/null +++ b/frontend/src/components/templates/ILab/ILabGraph.jsx @@ -0,0 +1,44 @@ +import Plot from "react-plotly.js"; +import PropType from "prop-types"; +import { cloneDeep } from "lodash"; +import { uid } from "@/utils/helper"; +import { useSelector } from "react-redux"; + +const ILabGraph = (props) => { + const { item } = props; + const isGraphLoading = useSelector((state) => state.loading.isGraphLoading); + const { graphData } = useSelector((state) => state.ilab); + + const graphDataCopy = cloneDeep(graphData); + + const getGraphData = (id) => { + const data = graphDataCopy?.filter((a) => a.uid === id); + return data; + }; + const hasGraphData = (uuid) => { + const hasData = getGraphData(uuid).length > 0; + + return hasData; + }; + + return ( + <> + {hasGraphData(item.id) ? ( + + ) : isGraphLoading && !hasGraphData(item.id) ? ( +
+ ) : ( + <> + )} + + ); +}; + +ILabGraph.propTypes = { + item: PropType.object, +}; +export default ILabGraph; diff --git a/frontend/src/components/templates/ILab/MetaRow.jsx b/frontend/src/components/templates/ILab/MetaRow.jsx new file mode 100644 index 00000000..c196e79f --- /dev/null +++ b/frontend/src/components/templates/ILab/MetaRow.jsx @@ -0,0 +1,40 @@ +import { Table, Tbody, Th, Thead, Tr } from "@patternfly/react-table"; + +import Proptypes from "prop-types"; +import { Title } from "@patternfly/react-core"; +import { uid } from "@/utils/helper"; + +const MetaRow = (props) => { + const { metadata, heading } = props; + return ( + <> + + {heading} + + + + + + + + + + {metadata.map((item) => ( + + + + + ))} + +
+ Key + Value
{item[0]}{item[1]}
+ + ); +}; + +MetaRow.propTypes = { + heading: Proptypes.string, + metadata: Proptypes.array, +}; +export default MetaRow; diff --git a/frontend/src/components/templates/ILab/MetricsDropdown.jsx b/frontend/src/components/templates/ILab/MetricsDropdown.jsx new file mode 100644 index 00000000..f301953d --- /dev/null +++ b/frontend/src/components/templates/ILab/MetricsDropdown.jsx @@ -0,0 +1,86 @@ +import { + MenuToggle, + Select, + SelectList, + SelectOption, +} from "@patternfly/react-core"; +import { fetchGraphData, setSelectedMetrics } from "@/actions/ilabActions"; +import { useDispatch, useSelector } from "react-redux"; + +import { cloneDeep } from "lodash"; +import { uid } from "@/utils/helper"; +import { useState } from "react"; + +const MetricsSelect = (props) => { + const { metrics, metrics_selected } = useSelector((state) => state.ilab); + const { item } = props; + /* Metrics select */ + const [isOpen, setIsOpen] = useState(false); + const dispatch = useDispatch(); + // const [selected, setSelected] = useState("Select a value"); + + const toggle1 = (toggleRef, selected) => ( + + {selected} + + ); + + const onToggleClick = () => { + setIsOpen(!isOpen); + }; + const onSelect = (_event, value) => { + console.log("selected", value); + const run = value.split("*"); + //setSelected(run[1].trim()); + dispatch(setSelectedMetrics(run[0].trim(), run[1].trim())); + setIsOpen(false); + dispatch(fetchGraphData(run[0].trim(), run[1].trim(), run[2].trim())); + }; + const metricsDataCopy = cloneDeep(metrics); + + const getMetricsData = (id) => { + const data = metricsDataCopy?.filter((a) => a.uid === id); + return data; + }; + const hasMetricsData = (uuid) => { + const hasData = getMetricsData(uuid).length > 0; + + return hasData; + }; + /* Metrics select */ + return ( + <> + {hasMetricsData(item.id) && ( + + )} + + ); +}; + +export default MetricsSelect; diff --git a/frontend/src/components/templates/ILab/StatusCell.jsx b/frontend/src/components/templates/ILab/StatusCell.jsx new file mode 100644 index 00000000..a4bd208f --- /dev/null +++ b/frontend/src/components/templates/ILab/StatusCell.jsx @@ -0,0 +1,24 @@ +import { + CheckCircleIcon, + ExclamationCircleIcon, +} from "@patternfly/react-icons"; + +import { Label } from "@patternfly/react-core"; +import Proptype from "prop-types"; + +const StatusCell = (props) => { + return props.value?.toLowerCase() === "pass" ? ( + + ) : ( + + ); +}; +StatusCell.propTypes = { + value: Proptype.string, +}; + +export default StatusCell; diff --git a/frontend/src/components/templates/ILab/index.jsx b/frontend/src/components/templates/ILab/index.jsx new file mode 100644 index 00000000..d1eb5d62 --- /dev/null +++ b/frontend/src/components/templates/ILab/index.jsx @@ -0,0 +1,241 @@ +import "./index.less"; + +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionToggle, + Card, + CardBody, +} from "@patternfly/react-core"; +import { + ExpandableRowContent, + Table, + Tbody, + Td, + Th, + Thead, + Tr, +} from "@patternfly/react-table"; +import { + fetchILabJobs, + fetchMetricsInfo, + fetchPeriods, + setIlabDateFilter, +} from "@/actions/ilabActions"; +import { formatDateTime, uid } from "@/utils/helper"; +import { useDispatch, useSelector } from "react-redux"; +import { useEffect, useState } from "react"; +import { useNavigate, useSearchParams } from "react-router-dom"; + +import ILabGraph from "./ILabGraph"; +import MetaRow from "./MetaRow"; +import MetricsSelect from "./MetricsDropdown"; +import RenderPagination from "@/components/organisms/Pagination"; +import StatusCell from "./StatusCell"; +import TableFilter from "@/components/organisms/TableFilters"; + +const ILab = () => { + const dispatch = useDispatch(); + const navigate = useNavigate(); + const [searchParams] = useSearchParams(); + + const { start_date, end_date } = useSelector((state) => state.ilab); + const [expandedResult, setExpandedResult] = useState([]); + const [expanded, setAccExpanded] = useState(["bordered-toggle1"]); + + const onToggle = (id) => { + const index = expanded.indexOf(id); + const newExpanded = + index >= 0 + ? [ + ...expanded.slice(0, index), + ...expanded.slice(index + 1, expanded.length), + ] + : [...expanded, id]; + setAccExpanded(newExpanded); + }; + const isResultExpanded = (res) => expandedResult?.includes(res); + const setExpanded = async (run, isExpanding = true) => { + setExpandedResult((prevExpanded) => { + const otherExpandedRunNames = prevExpanded.filter((r) => r !== run.id); + return isExpanding + ? [...otherExpandedRunNames, run.id] + : otherExpandedRunNames; + }); + if (isExpanding) { + dispatch(fetchPeriods(run.id)); + dispatch(fetchMetricsInfo(run.id)); + } + }; + + const { totalItems, page, perPage, tableData } = useSelector( + (state) => state.ilab + ); + + useEffect(() => { + if (searchParams.size > 0) { + // date filter is set apart + const startDate = searchParams.get("start_date"); + const endDate = searchParams.get("end_date"); + + searchParams.delete("start_date"); + searchParams.delete("end_date"); + const params = Object.fromEntries(searchParams); + const obj = {}; + for (const key in params) { + obj[key] = params[key].split(","); + } + dispatch(setIlabDateFilter(startDate, endDate, navigate)); + } + }, []); + + useEffect(() => { + dispatch(fetchILabJobs()); + }, [dispatch]); + + const columnNames = { + benchmark: "Benchmark", + email: "Email", + name: "Name", + source: "Source", + metric: "Metric", + begin_date: "Start Date", + end_date: "End Date", + status: "Status", + }; + + return ( + <> + + + + + + + + + + + + {tableData.map((item, rowIndex) => ( + <> + + + + + + + + + + + ))} + +
+ {columnNames.metric}{columnNames.begin_date}{columnNames.end_date}{columnNames.status}
+ setExpanded(item, !isResultExpanded(item.id)), + expandId: `expandId-${uid()}`, + }} + /> + + {item.primary_metrics[0]}{formatDateTime(item.begin_date)}{formatDateTime(item.end_date)} + +
+ + + + { + onToggle("bordered-toggle1"); + }} + isExpanded={expanded.includes("bordered-toggle1")} + id="bordered-toggle1" + > + Metadata + + + +
+ + + + + + + + + + + + + + + +
+
+
+ + { + onToggle("bordered-toggle2"); + }} + isExpanded={expanded.includes("bordered-toggle2")} + id="bordered-toggle2" + > + Metrics & Graph + + + Metrics: +
+ +
+
+
+
+
+
+ + + ); +}; + +export default ILab; diff --git a/frontend/src/components/templates/ILab/index.less b/frontend/src/components/templates/ILab/index.less new file mode 100644 index 00000000..02cd02cb --- /dev/null +++ b/frontend/src/components/templates/ILab/index.less @@ -0,0 +1,13 @@ +.pf-v5-c-accordion__expandable-content-body { + display: block; +} +.metadata-wrapper { + display: flex; + flex-direction: row; + margin-bottom: 1vw; + .metadata-card { + flex: 1; /* additionally, equal width */ + padding: 1em; + margin-right: 1.5vw; + } +} diff --git a/frontend/src/reducers/ilabReducer.js b/frontend/src/reducers/ilabReducer.js new file mode 100644 index 00000000..2f1bcd91 --- /dev/null +++ b/frontend/src/reducers/ilabReducer.js @@ -0,0 +1,61 @@ +import * as TYPES from "@/actions/types"; + +const initialState = { + results: [], + start_date: "", + end_date: "", + graphData: [], + totalItems: 0, + page: 1, + perPage: 10, + size: 10, + offset: 0, + metrics: [], + periods: [], + metrics_selected: {}, + tableData: [], +}; +const ILabReducer = (state = initialState, action = {}) => { + const { type, payload } = action; + switch (type) { + case TYPES.SET_ILAB_JOBS_DATA: + return { + ...state, + results: payload, + }; + case TYPES.SET_ILAB_DATE_FILTER: + return { + ...state, + start_date: payload.start_date, + end_date: payload.end_date, + }; + case TYPES.SET_ILAB_TOTAL_ITEMS: + return { + ...state, + totalItems: payload, + }; + case TYPES.SET_ILAB_OFFSET: + return { ...state, offset: payload }; + case TYPES.SET_ILAB_PAGE: + return { ...state, page: payload }; + case TYPES.SET_ILAB_PAGE_OPTIONS: + return { ...state, page: payload.page, perPage: payload.perPage }; + case TYPES.SET_ILAB_METRICS: + return { ...state, metrics: [...state.metrics, payload] }; + case TYPES.SET_ILAB_PERIODS: + return { ...state, periods: [...state.periods, payload] }; + case TYPES.SET_ILAB_SELECTED_METRICS: + return { + ...state, + metrics_selected: payload, + }; + case TYPES.SET_ILAB_GRAPH_DATA: + return { ...state, graphData: payload }; + case TYPES.SET_ILAB_INIT_JOBS: + return { ...state, tableData: payload }; + default: + return state; + } +}; + +export default ILabReducer; diff --git a/frontend/src/reducers/index.js b/frontend/src/reducers/index.js index 1fb4c555..43970170 100644 --- a/frontend/src/reducers/index.js +++ b/frontend/src/reducers/index.js @@ -1,4 +1,5 @@ import HomeReducer from "./homeReducer"; +import ILabReducer from "./ilabReducer"; import LoadingReducer from "./loadingReducer"; import OCPReducer from "./ocpReducer"; import QuayReducer from "./quayReducer"; @@ -15,4 +16,5 @@ export default combineReducers({ ocp: OCPReducer, quay: QuayReducer, telco: TelcoReducer, + ilab: ILabReducer, }); diff --git a/frontend/src/reducers/loadingReducer.js b/frontend/src/reducers/loadingReducer.js index 496a4e65..52f0c732 100644 --- a/frontend/src/reducers/loadingReducer.js +++ b/frontend/src/reducers/loadingReducer.js @@ -7,7 +7,7 @@ import { const initialState = { isLoading: false, - isGraphLoading: true, + isGraphLoading: false, }; const LoadingReducer = (state = initialState, action = {}) => { diff --git a/frontend/src/store/Actions/ActionCreator.js b/frontend/src/store/Actions/ActionCreator.js deleted file mode 100644 index 00adabc9..00000000 --- a/frontend/src/store/Actions/ActionCreator.js +++ /dev/null @@ -1,360 +0,0 @@ - -import {BASE_URL, OCP_GRAPH_API_V1, OCP_JOBS_API_V1, CPT_JOBS_API_V1, QUAY_JOBS_API_V1, QUAY_GRAPH_API_V1, TELCO_JOBS_API_V1, TELCO_GRAPH_API_V1} from "../Shared"; -import axios from "axios"; -import { - errorOCPCall, - getOCPJobsData, - setWaitForOCPUpdate, - updateOCPMetaData -} from "../reducers/OCPJobsReducer"; -import { - errorCPTCall, - getCPTJobsData, - setWaitForCPTUpdate, - updateCPTMetaData -} from "../reducers/CPTJobsReducer"; -import { - errorQuayCall, - getQuayJobsData, - setWaitForQuayUpdate, - updateQuayMetaData -} from "../reducers/QuayJobsReducer"; -import { - errorTelcoCall, - getTelcoJobsData, - setWaitForTelcoUpdate, - updateTelcoMetaData -} from "../reducers/TelcoJobsReducer"; -import {getUuidResults, setGraphError} from "../reducers/GraphReducer"; -import {getQuayUuidResults, setQuayGraphError} from "../reducers/QuayGraphReducer"; -import {getTelcoUuidResults, setTelcoGraphError} from "../reducers/TelcoGraphReducer"; - -export const fetchAPI = async (url, requestOptions = {}) => { - const response = await axios(url, requestOptions) - return response.data -} - -export const fetchGraphData = (uuid) => async dispatch =>{ - try { - let buildUrl = `${BASE_URL}${OCP_GRAPH_API_V1}/${uuid}` - const api_data = await fetchAPI(buildUrl) - if(api_data) dispatch(getUuidResults({ [uuid]: api_data })) - } - catch (error){ - if (axios.isAxiosError(error)) { - console.error('Axios Error:', error); - console.error('Request:', error.request); - console.error('Response:', error.response); - } else { - console.error('Axios Error:', error); - dispatch(setGraphError({error: error.response.data.details})) - } - } -} - -export const fetchQuayGraphData = (uuid) => async dispatch =>{ - try { - let buildUrl = `${BASE_URL}${QUAY_GRAPH_API_V1}/${uuid}` - const api_data = await fetchAPI(buildUrl) - if(api_data) dispatch(getQuayUuidResults({ [uuid]: api_data })) - } - catch (error){ - if (axios.isAxiosError(error)) { - console.error('Axios Error:', error); - console.error('Request:', error.request); - console.error('Response:', error.response); - } else { - console.error('Axios Error:', error); - dispatch(setQuayGraphError({error: error.response.data.details})) - } - } -} - -export const fetchTelcoGraphData = (uuid, encryptedData) => async dispatch =>{ - try { - let buildUrl = `${BASE_URL}${TELCO_GRAPH_API_V1}/${uuid}/${encryptedData}` - const api_data = await fetchAPI(buildUrl) - if(api_data) dispatch(getTelcoUuidResults({ [uuid]: api_data })) - } - catch (error){ - if (axios.isAxiosError(error)) { - console.error('Axios Error:', error); - console.error('Request:', error.request); - console.error('Response:', error.response); - } else { - console.error('Axios Error:', error); - dispatch(setTelcoGraphError({error: error.response.data.details})) - } - } -} - -export const fetchOCPJobsData = (startDate = '', endDate='') => async dispatch => { - let buildUrl = `${BASE_URL}${OCP_JOBS_API_V1}` - dispatch(setWaitForOCPUpdate({waitForUpdate:true})) - if(startDate !== '' && endDate !== '') { - buildUrl += `?start_date=${startDate}&end_date=${endDate}` - } - try{ - let api_data = await fetchAPI(buildUrl) - dispatch(setWaitForOCPUpdate({waitForUpdate:false})) - api_data = JSON.parse(api_data) - if(api_data){ - const results = api_data.results - if(results){ - const benchmarks = GetBenchmarks(results) - const versions = GetVersions(results) - const platforms = GetPlatforms(results) - const workers = GetWorkers(results) - const networkTypes = GetNetworkTypes(results) - const ciSystems = GetCiSystems(results) - const jobTypes = GetJobType(results) - const rehearses = ["TRUE", "FALSE"] - const allIpsec = ["TRUE", "FALSE"] - const allFips = ["TRUE", "FALSE"] - const allEncrypted = ["TRUE", "FALSE"] - const encryptionTypes = GetEncryptionTypes(results) - const allPublish = GetPublish(results) - const computeArchs = GetComputeArchs(results) - const controlPlaneArchs = GetControlPlaneArchs(results) - const jobStatuses = GetStatuses(results) - const updatedTime = new Date().toLocaleString().replace(', ', ' ').toString(); - await dispatch(getOCPJobsData({ - data: results, benchmarks, versions, waitForUpdate: false, platforms, workers, networkTypes, - updatedTime, ciSystems, jobTypes, rehearses, allIpsec, allFips, allEncrypted, encryptionTypes, - allPublish, computeArchs, controlPlaneArchs, jobStatuses, startDate: api_data.startDate, endDate: api_data.endDate - })) - await dispatch(updateOCPMetaData({data: results})) - } - } - } - catch (e) { - const error = e - if(error.response){ - await dispatch(errorOCPCall({error: error.response.data.error})) - alert(error.response.data.error) - } - else{ - console.log(error) - } - dispatch(setWaitForOCPUpdate({waitForUpdate:false})) - } -} - -export const fetchQuayJobsData = (startDate = '', endDate='') => async dispatch => { - let buildUrl = `${BASE_URL}${QUAY_JOBS_API_V1}` - dispatch(setWaitForQuayUpdate({waitForUpdate:true})) - if(startDate !== '' && endDate !== '') { - buildUrl += `?start_date=${startDate}&end_date=${endDate}` - } - try{ - let api_data = await fetchAPI(buildUrl) - dispatch(setWaitForQuayUpdate({waitForUpdate:false})) - api_data = JSON.parse(api_data) - if(api_data){ - const results = api_data.results - if(results){ - const benchmarks = GetBenchmarks(results) - const releaseStreams = GetReleaseStreams(results) - const platforms = GetPlatforms(results) - const workers = GetWorkers(results) - const hitSizes = GetHitSizes(results) - const concurrencies = GetConcurrencies(results) - const imagePushPulls = GetImagePushPulls(results) - const ciSystems = GetCiSystems(results) - const updatedTime = new Date().toLocaleString().replace(', ', ' ').toString(); - await dispatch(getQuayJobsData({ - data: results, benchmarks, releaseStreams, waitForUpdate: false, platforms, workers, - hitSizes, concurrencies, imagePushPulls, updatedTime, ciSystems, startDate: api_data.startDate, - endDate: api_data.endDate - })) - await dispatch(updateQuayMetaData({data: results})) - } - } - } - catch (e) { - const error = e - if(error.response){ - await dispatch(errorQuayCall({error: error.response.data.error})) - alert(error.response.data.error) - } - else{ - console.log(error) - } - dispatch(setWaitForQuayUpdate({waitForUpdate:false})) - } -} - -export const fetchTelcoJobsData = (startDate = '', endDate='') => async dispatch => { - let buildUrl = `${BASE_URL}${TELCO_JOBS_API_V1}` - dispatch(setWaitForTelcoUpdate({waitForUpdate:true})) - if(startDate !== '' && endDate !== '') { - buildUrl += `?start_date=${startDate}&end_date=${endDate}` - } - try{ - let api_data = await fetchAPI(buildUrl) - dispatch(setWaitForTelcoUpdate({waitForUpdate:false})) - api_data = JSON.parse(api_data) - if(api_data){ - const results = api_data.results - if(results){ - const benchmarks = GetBenchmarks(results) - const versions = GetVersions(results) - const releaseStreams = GetReleaseStreams(results) - const ciSystems = GetCiSystems(results) - const formals = GetFormals(results) - const nodeNames = GetNodeNames(results) - const cpus = GetCpus(results) - const updatedTime = new Date().toLocaleString().replace(', ', ' ').toString(); - await dispatch(getTelcoJobsData({ - data: results, benchmarks, versions, releaseStreams, waitForUpdate: false, formals, nodeNames, cpus, - updatedTime, ciSystems, startDate: api_data.startDate, endDate: api_data.endDate - })) - await dispatch(updateTelcoMetaData({data: results})) - } - } - } - catch (e) { - const error = e - if(error.response){ - await dispatch(errorTelcoCall({error: error.response.data.error})) - alert(error.response.data.error) - } - else{ - console.log(error) - } - dispatch(setWaitForTelcoUpdate({waitForUpdate:false})) - } -} - -export const fetchCPTJobsData = (startDate = '', endDate='') => async dispatch => { - let buildUrl = `${BASE_URL}${CPT_JOBS_API_V1}` - dispatch(setWaitForCPTUpdate({waitForUpdate:true})) - if(startDate !== '' && endDate !== '') { - buildUrl += `?start_date=${startDate}&end_date=${endDate}` - } - try{ - let api_data = await fetchAPI(buildUrl) - dispatch(setWaitForCPTUpdate({waitForUpdate:false})) - api_data = JSON.parse(api_data) - if(api_data){ - const results = api_data.results - if(results){ - const testNames = GetTestNames(results) - const products = GetProducts(results) - const ciSystems = GetCiSystems(results) - const jobStatuses = GetStatuses(results) - const releaseStreams = GetReleaseStreams(results) - const updatedTime = new Date().toLocaleString().replace(', ', ' ').toString(); - await dispatch(getCPTJobsData({ - data: results, testNames, products, waitForUpdate: false, - jobStatuses, releaseStreams, updatedTime, ciSystems, startDate: api_data.startDate, endDate: api_data.endDate - })) - await dispatch(updateCPTMetaData({data: results})) - } - } - } - catch (e) { - const error = e - if(error.response){ - await dispatch(errorCPTCall({error: error.response.data.error})) - alert(error.response.data.error) - } - else{ - console.log(error) - } - dispatch(setWaitForCPTUpdate({waitForUpdate:false})) - } -} - -const GetCiSystems = (api_data) => { - return Array.from(new Set(api_data.map(item => { - if(item.ciSystem === null) return '' - else return item.ciSystem.toUpperCase().trim() - }))).sort() -} - -export const GetVersions = (api_data) => { - return Array.from(new Set(api_data.map(item => item.shortVersion).filter(shortVersion => shortVersion !== null && shortVersion !== "").map(shortVersion => shortVersion.toUpperCase().trim()))).sort(); -} - -export const GetBenchmarks = (api_data) => { - return Array.from(new Set(api_data.map(item => { - if(item.benchmark === null) return '' - else return item.benchmark.toLowerCase().trim() - }))).sort() -} - -const GetPlatforms = (api_data) => { - return Array.from(new Set(api_data.map(item => item.platform.toUpperCase().trim()))).sort() -} - -const GetWorkers = (api_data) => { - return Array.from(new Set(api_data.map(item => parseInt(item.workerNodesCount)))).sort((a, b) => a-b) -} - -const GetHitSizes = (api_data) => { - return Array.from(new Set(api_data.map(item => parseInt(item.hitSize)))).sort((a, b) => a-b) -} - -const GetConcurrencies = (api_data) => { - return Array.from(new Set(api_data.map(item => parseInt(item.concurrency)))).sort((a, b) => a-b) -} - -const GetImagePushPulls = (api_data) => { - return Array.from(new Set(api_data.map(item => parseInt(item.imagePushPulls)))).sort((a, b) => a-b) -} - -const GetNetworkTypes = (api_data) => { - return Array.from(new Set(api_data.map(item => item.networkType.toUpperCase().trim()))).sort() -} - -const GetProducts = (api_data) => { - return Array.from(new Set(api_data.map(item => item.product.toUpperCase().trim()))).sort() -} - -const GetStatuses = (api_data) => { - return Array.from(new Set(api_data.map(item => item.jobStatus.toUpperCase().trim()))).sort() -} - -const GetReleaseStreams = (api_data) => { - return Array.from(new Set(api_data.map(item => item.releaseStream).filter(releaseStream => releaseStream !== null && releaseStream !== "").map(releaseStream => releaseStream.toUpperCase().trim()))).sort(); -} - -const GetFormals = (api_data) => { - return Array.from(new Set(api_data.map(item => item.formal).filter(formal => formal !== null && formal !== "").map(formal => formal.toUpperCase().trim()))).sort(); -} - -const GetNodeNames = (api_data) => { - return Array.from(new Set(api_data.map(item => item.nodeName).filter(nodeName => nodeName !== null && nodeName !== "").map(nodeName => nodeName.toUpperCase().trim()))).sort(); -} - -const GetCpus = (api_data) => { - return Array.from(new Set(api_data.map(item => item.cpu).filter(cpu => cpu !== null && cpu !== "").map(cpu => cpu.toUpperCase().trim()))).sort(); -} - -const GetTestNames = (api_data) => { - return Array.from(new Set(api_data.map(item => { - if(item.testName === null) return '' - else return item.testName.toLowerCase().trim() - }))).sort() -} - -const GetJobType = (api_data) => { - return Array.from(new Set(api_data.map(item => item.jobType.toUpperCase().trim()))).sort() -} - -const GetEncryptionTypes = (api_data) => { - return Array.from(new Set(api_data.map(item => item.encryptionType.toUpperCase().trim()))).sort() -} - -const GetPublish = (api_data) => { - return Array.from(new Set(api_data.map(item => item.publish.toUpperCase().trim()))).sort() -} - -const GetComputeArchs = (api_data) => { - return Array.from(new Set(api_data.map(item => item.computeArch.toUpperCase().trim()))).sort() -} - -const GetControlPlaneArchs = (api_data) => { - return Array.from(new Set(api_data.map(item => item.controlPlaneArch.toUpperCase().trim()))).sort() -} \ No newline at end of file diff --git a/frontend/src/store/Shared.js b/frontend/src/store/Shared.js deleted file mode 100644 index cff99f6a..00000000 --- a/frontend/src/store/Shared.js +++ /dev/null @@ -1,19 +0,0 @@ - - -export const getUrl = () => { - const {hostname, protocol} = window.location - return (hostname === "localhost") ? "http://localhost:8000":`${protocol}//${hostname}` -} - -export const BASE_URL = getUrl() - -export const OCP_JOBS_API_V1 = "/api/v1/ocp/jobs" -export const OCP_GRAPH_API_V1 = "/api/v1/ocp/graph" - -export const CPT_JOBS_API_V1 = "/api/v1/cpt/jobs" - -export const QUAY_JOBS_API_V1 = "/api/v1/quay/jobs" -export const QUAY_GRAPH_API_V1 = "/api/v1/quay/graph" - -export const TELCO_JOBS_API_V1 = "/api/v1/telco/jobs" -export const TELCO_GRAPH_API_V1 = "/api/v1/telco/graph" \ No newline at end of file diff --git a/frontend/src/store/reducers/InitialData.js b/frontend/src/store/reducers/InitialData.js deleted file mode 100644 index 80503b3c..00000000 --- a/frontend/src/store/reducers/InitialData.js +++ /dev/null @@ -1,181 +0,0 @@ - -export const OCP_INITIAL_DATA = { - initialState: true, - success: 0, - failure: 0, - total: 0, - others: 0, - duration:0, - benchmarks: ["All"], - versions: ["All"], - workers: ["All"], - ciSystems: ["All"], - networkTypes: ["All"], - jobTypes: ["All"], - rehearses: ["All"], - allIpsec: ["All"], - allFips: ["All"], - allEncrypted: ["All"], - encryptionTypes: ["All"], - allPublish: ["All"], - computeArchs: ["All"], - controlPlaneArchs: ["All"], - jobStatuses: ["All"], - selectedBenchmark: "All", - selectedVersion: "All", - selectedPlatform: "All", - selectedWorkerCount: "All", - selectedNetworkType: "All", - selectedCiSystem: "All", - selectedJobType: "All", - selectedRehearse: "All", - selectedIpsec: "All", - selectedFips: "All", - selectedEncrypted: "All", - selectedEncryptionType: "All", - selectedPublish: "All", - selectedComputeArch: "All", - selectedControlPlaneArch: "All", - selectedJobStatus: "All", - waitForUpdate: false, - platforms: ["All"], - copyData: [], - data: [], - updatedTime: 'Loading', - error: null, - startDate: '', - endDate: '', - tableData : [{ name: "Benchmark", value: "benchmark" }, - {name:"Release Stream", value: "releaseStream"}, - {name:"Build", value: "build"}, - {name: "Worker Count", value: "workerNodesCount"}, - {name: "Start Date", value: "startDate"}, - {name: "End Date", value: "endDate"}, - {name: "Status", value: "jobStatus"}], -} - -export const QUAY_INITIAL_DATA = { - initialState: true, - success: 0, - failure: 0, - total: 0, - others: 0, - duration:0, - ciSystems: ["All"], - platforms: ["All"], - benchmarks: ["All"], - releaseStreams: ["All"], - workers: ["All"], - hitSizes: ["All"], - concurrencies: ["All"], - imagePushPulls: ["All"], - selectedCiSystem: "All", - selectedPlatform: "All", - selectedBenchmark: "All", - selectedReleaseStream: "All", - selectedWorkerCount: "All", - selectedHitSize: "All", - selectedConcurrency: "All", - selectedImagePushPulls: "All", - waitForUpdate: false, - copyData: [], - data: [], - updatedTime: 'Loading', - error: null, - startDate: '', - endDate: '', - tableData : [{ name: "Benchmark", value: "benchmark" }, - {name:"Release Stream", value: "releaseStream"}, - {name:"Platform", value: "platform"}, - {name: "Worker Count", value: "workerNodesCount"}, - {name: "Start Date", value: "startDate"}, - {name: "End Date", value: "endDate"}, - {name: "Status", value: "jobStatus"}], -} - -export const TELCO_INITIAL_DATA = { - initialState: true, - success: 0, - failure: 0, - total: 0, - others: 0, - duration:0, - ciSystems: ["All"], - benchmarks: ["All"], - versions: ["All"], - releaseStreams: ["All"], - formals: ["All"], - nodeNames: ["All"], - cpus: ["All"], - selectedCiSystem: "All", - selectedBenchmark: "All", - selectedVersion: "All", - selectedReleaseStream: "All", - selectedFormal: "All", - selectedCpu: "All", - selectedNodeName: "All", - waitForUpdate: false, - copyData: [], - data: [], - updatedTime: 'Loading', - error: null, - startDate: '', - endDate: '', - tableData : [{ name: "Benchmark", value: "benchmark" }, - {name:"Release Stream", value: "releaseStream"}, - {name:"Build", value: "ocpVersion"}, - {name:"CPU", value: "cpu"}, - {name:"Node Name", value: "nodeName"}, - {name: "Start Date", value: "startDate"}, - {name: "End Date", value: "endDate"}, - {name: "Status", value: "jobStatus"}], -} - -export const CPT_INITIAL_DATA = { - initialState: true, - success: 0, - failure: 0, - total: 0, - others: 0, - testNames: ["All"], - products: ["All"], - ciSystems: ["All"], - statuses: ["All"], - releaseStreams: ["All"], - selectedCiSystem: "All", - selectedProduct: "All", - selectedTestName: "All", - selectedJobStatus: "All", - selectedReleaseStream: "All", - waitForUpdate: false, - copyData: [], - data: [], - updatedTime: 'Loading', - error: null, - startDate: '', - endDate: '', - tableData : [{name:"Product", value: "product"}, - { name: "CI System", value: "ciSystem" }, - {name: "Test Name", value: "testName"}, - {name: "Version", value: "version"}, - {name: "Release Stream", value: "releaseStream"}, - {name: "Start Date", value: "startDate"}, - {name: "End Date", value: "endDate"}, - {name: "Build URL", value: "buildUrl"}, - {name: "Status", value: "jobStatus"},], -} - -export const GRAPH_INITIAL_DATA = { - uuid_results: {}, - graphError: false, -} - -export const QUAY_GRAPH_INITIAL_DATA = { - uuid_results: {}, - graphError: false, -} - -export const TELCO_GRAPH_INITIAL_DATA = { - uuid_results: {}, - graphError: false, -} diff --git a/frontend/src/store/reducers/index.js b/frontend/src/store/reducers/index.js deleted file mode 100644 index fe4fddad..00000000 --- a/frontend/src/store/reducers/index.js +++ /dev/null @@ -1,18 +0,0 @@ -import ocpJobsReducer from "./OCPJobsReducer"; -import cptJobsReducer from "./CPTJobsReducer"; -import quayJobsReducer from "./QuayJobsReducer"; -import telcoJobsReducer from "./TelcoJobsReducer"; -import graphReducer from "./GraphReducer"; -import quayGraphReducer from "./QuayGraphReducer"; -import telcoGraphReducer from "./TelcoGraphReducer"; - - -export const rootReducer = { - 'ocpJobs': ocpJobsReducer, - 'cptJobs': cptJobsReducer, - 'quayJobs': quayJobsReducer, - 'telcoJobs': telcoJobsReducer, - 'graph': graphReducer, - 'quayGraph': quayGraphReducer, - 'telcoGraph': telcoGraphReducer, -} diff --git a/frontend/src/utils/apiConstants.js b/frontend/src/utils/apiConstants.js index 52576b4a..33fe0ccd 100644 --- a/frontend/src/utils/apiConstants.js +++ b/frontend/src/utils/apiConstants.js @@ -1,7 +1,7 @@ export const getUrl = () => { const { hostname, protocol } = window.location; return hostname === "localhost" - ? "http://localhost:8000" + ? "http://0.0.0.0:8000" : `${protocol}//${hostname}`; }; @@ -17,3 +17,6 @@ export const QUAY_GRAPH_API_V1 = "/api/v1/quay/graph"; export const TELCO_JOBS_API_V1 = "/api/v1/telco/jobs"; export const TELCO_GRAPH_API_V1 = "/api/v1/telco/graph"; + +export const ILABS_JOBS_API_V1 = "/api/v1/ilab/runs"; +export const ILAB_GRAPH_API_V1 = "/api/v1/ilab/runs/"; diff --git a/frontend/src/utils/routeConstants.js b/frontend/src/utils/routeConstants.js index 53f271fa..c46bab55 100644 --- a/frontend/src/utils/routeConstants.js +++ b/frontend/src/utils/routeConstants.js @@ -2,3 +2,4 @@ export const HOME = "Home"; export const OCP = "OCP"; export const QUAY = "QUAY"; export const TELCO = "TELCO"; +export const ILAB = "ILAB";