Skip to content

Commit

Permalink
Add an ilab UI tab
Browse files Browse the repository at this point in the history
This relies on the ilab API in cloud-bulldozer#123, which in turn builds on the crucible
service in cloud-bulldozer#122.
  • Loading branch information
MVarshini authored and dbutenhof committed Oct 17, 2024
1 parent 956d9c3 commit 021ca1f
Show file tree
Hide file tree
Showing 25 changed files with 794 additions and 269 deletions.
16 changes: 8 additions & 8 deletions frontend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,21 @@ The `utils` directory has all helper/utility scripts.

#### [`src/reducers`](src/reducers)

Contains functions that manage store via actions
Contains functions that manage store via actions

## Cloning and Running the Application Locally
## Cloning and Running the Application Locally

- Install [Node.js](https://nodejs.org)
- Install [Node.js](https://nodejs.org)
- Clone the [CPT Dashboard code](https://github.com/cloud-bulldozer/cpt-dashboard) to a local file system
- Install all the npm packages

Type the following command to install all npm packages
Type the following command to install all npm packages

```bash
$ npm install
```

In order to run the application use the following command
In order to run the application use the following command

```bash
$ npm run dev
Expand All @@ -56,12 +56,12 @@ Then, copy the `build` folder to the proper place on the server for deployment.

## Template

This application is based on v5 of PatternFly which is a production-ready UI solution for admin interfaces. For more information regarding the foundation and template of the application, please visit [PatternFly](https://www.patternfly.org/get-started/develop)
This application is based on v5 of PatternFly which is a production-ready UI solution for admin interfaces. For more information regarding the foundation and template of the application, please visit [PatternFly](https://www.patternfly.org/get-started/develop)

## Resources

- [Vite](https://vitejs.dev/guide/)
- [Vite](https://vitejs.dev/guide/)

- [ReactJS](https://reactjs.org/)
- [ReactJS](https://reactjs.org/)

- [React-Redux](https://github.com/reduxjs/react-redux)
58 changes: 0 additions & 58 deletions frontend/src/App.js

This file was deleted.

2 changes: 2 additions & 0 deletions frontend/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -26,6 +27,7 @@ function App() {
<Route path={APP_ROUTES.OCP} element={<OCP />} />
<Route path={APP_ROUTES.QUAY} element={<Quay />} />
<Route path={APP_ROUTES.TELCO} element={<Telco />} />
<Route path={APP_ROUTES.ILAB} element={<ILab />} />
</Route>
</Routes>
</BrowserRouter>
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/actions/filterActions.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { fetchILabJobs, setIlabDateFilter } from "./ilabActions";
import {
removeCPTAppliedFilters,
setCPTAppliedFilters,
Expand Down Expand Up @@ -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());
}
};

Expand Down
213 changes: 213 additions & 0 deletions frontend/src/actions/ilabActions.js
Original file line number Diff line number Diff line change
@@ -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));
};
18 changes: 18 additions & 0 deletions frontend/src/actions/paginationActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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));
}
};

Expand All @@ -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));
}
};

Expand All @@ -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));
};
Loading

0 comments on commit 021ca1f

Please sign in to comment.