Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Create, Edit, Delete for LifeCycle Policies #1004

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,628 changes: 1,088 additions & 540 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"react-hotkeys-hook": "^4.6.1",
"react-i18next": "^15.4.0",
"react-icons": "^5.3.0",
"react-js-cron": "^5.0.1",
"react-redux": "^9.2.0",
"react-router-dom": "^6.27.0",
"react-select": "^5.8.0",
Expand Down
3 changes: 3 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import Acls from "./components/users/Acls";
import About from "./components/About";
import { useAppDispatch } from "./store";
import { fetchOcVersion, fetchUserInfo } from "./slices/userInfoSlice";
import LifeCyclePolicies from "./components/events/LifeCyclePolicies";

function App() {
const dispatch = useAppDispatch();
Expand All @@ -41,6 +42,8 @@ function App() {

<Route path={"/events/series"} element={<Series />} />

<Route path={"/events/lifeCyclePolicies"} element={<LifeCyclePolicies />} />

<Route path={"/recordings/recordings"} element={<Recordings />} />

<Route path={"/systems/jobs"} element={<Jobs />} />
Expand Down
19 changes: 19 additions & 0 deletions src/components/events/Events.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import EditMetadataEventsModal from "./partials/modals/EditMetadataEventsModal";
import { eventsTemplateMap } from "../../configs/tableConfigs/eventsTableMap";
import {
loadEventsIntoTable,
loadLifeCyclePoliciesIntoTable,
loadSeriesIntoTable,
} from "../../thunks/tableThunks";
import { fetchFilters, fetchStats, editTextFilter } from "../../slices/tableFilterSlice";
Expand Down Expand Up @@ -43,6 +44,7 @@ import {
import { fetchSeries } from "../../slices/seriesSlice";
import EventDetailsModal from "./partials/modals/EventDetailsModal";
import { showModal } from "../../selectors/eventDetailsSelectors";
import { fetchLifeCyclePolicies } from "../../slices/lifeCycleSlice";

// References for detecting a click outside of the container of the dropdown menu
const containerAction = React.createRef<HTMLDivElement>();
Expand Down Expand Up @@ -99,6 +101,14 @@ const Events = () => {
dispatch(loadSeriesIntoTable());
};

const loadLifeCyclePolicies = async () => {
// Fetching policies from server
await dispatch(fetchLifeCyclePolicies());

// Load policies into table
dispatch(loadLifeCyclePoliciesIntoTable());
};

useEffect(() => {
if ("events" !== currentFilterType) {
dispatch(fetchFilters("events"))
Expand Down Expand Up @@ -230,6 +240,15 @@ const Events = () => {
{t("EVENTS.EVENTS.NAVIGATION.SERIES")}
</Link>
)}
{hasAccess("ROLE_UI_LIFECYCLEPOLICIES_VIEW", user) && (
<Link
to="/events/lifeCyclePolicies"
className={cn({ active: false })}
onClick={() => loadLifeCyclePolicies()}
>
{t("LIFECYCLE.NAVIGATION.POLICIES")}
</Link>
)}
</nav>

{/* Include status bar component*/}
Expand Down
190 changes: 190 additions & 0 deletions src/components/events/LifeCyclePolicies.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
import React, { useEffect, useState } from "react";
import MainNav from "../shared/MainNav";
import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom";
import cn from "classnames";
import TableFilters from "../shared/TableFilters";
import Table from "../shared/Table";
import Notifications from "../shared/Notifications";
import { loadEventsIntoTable, loadLifeCyclePoliciesIntoTable, loadSeriesIntoTable } from "../../thunks/tableThunks";
import { fetchFilters, editTextFilter, fetchStats } from "../../slices/tableFilterSlice";
import Header from "../Header";
import NavBar from "../NavBar";
import MainView from "../MainView";
import Footer from "../Footer";
import { getUserInformation } from "../../selectors/userInfoSelectors";
import { hasAccess } from "../../utils/utils";
import { getCurrentFilterResource } from "../../selectors/tableFilterSelectors";
import { useAppDispatch, useAppSelector } from "../../store";
import { AsyncThunk } from "@reduxjs/toolkit";
import { AsyncThunkConfig } from "@reduxjs/toolkit/dist/createAsyncThunk";

Check failure on line 20 in src/components/events/LifeCyclePolicies.tsx

View workflow job for this annotation

GitHub Actions / build

Cannot find module '@reduxjs/toolkit/dist/createAsyncThunk' or its corresponding type declarations.
import { getTotalLifeCyclePolicies } from "../../selectors/lifeCycleSelectors";
import { fetchLifeCyclePolicies } from "../../slices/lifeCycleSlice";
import { lifeCyclePoliciesTemplateMap } from "../../configs/tableConfigs/lifeCyclePoliciesTableMap";
import { fetchEvents } from "../../slices/eventSlice";
import { setOffset } from "../../slices/tableSlice";
import { fetchSeries } from "../../slices/seriesSlice";
import NewResourceModal from "../shared/NewResourceModal";
import { fetchLifeCyclePolicyActions, fetchLifeCyclePolicyTargetTypes, fetchLifeCyclePolicyTimings } from "../../slices/lifeCycleDetailsSlice";

/**
* This component renders the table view of policies
*/
const LifeCyclePolicies = () => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const [displayNavigation, setNavigation] = useState(false);
const [displayNewPolicyModal, setNewPolicyModal] = useState(false);

const user = useAppSelector(state => getUserInformation(state));
const policiesTotal = useAppSelector(state => getTotalLifeCyclePolicies(state));
const currentFilterType = useAppSelector(state => getCurrentFilterResource(state));

const loadEvents = async () => {
// Fetching stats from server
dispatch(fetchStats());

// Fetching events from server
await dispatch(fetchEvents());

// Load events into table
dispatch(loadEventsIntoTable());
};

const loadSeries = () => {
// Reset the current page to first page
dispatch(setOffset(0));

//fetching series from server
dispatch(fetchSeries());

//load series into table
dispatch(loadSeriesIntoTable());
};

const loadLifeCyclePolicies = async () => {
// Fetching policies from server
await dispatch(fetchLifeCyclePolicies());

// Load policies into table
dispatch(loadLifeCyclePoliciesIntoTable());
};

useEffect(() => {
if ("lifeCyclePolicies" !== currentFilterType) {
dispatch(fetchFilters("lifeCyclePolicies"));
}

// Reset text filter
dispatch(editTextFilter(""));

// Load policies on mount
loadLifeCyclePolicies().then((r) => console.info(r));

// Fetch policies repeatedly
let fetchInterval = setInterval(loadLifeCyclePolicies, 5000);

return () => clearInterval(fetchInterval);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

const toggleNavigation = () => {
setNavigation(!displayNavigation);
};

const showNewPolicyModal = async () => {
await dispatch(fetchLifeCyclePolicyActions());
await dispatch(fetchLifeCyclePolicyTargetTypes());
await dispatch(fetchLifeCyclePolicyTimings());

setNewPolicyModal(true);
};

const hideNewPolicyModal = () => {
setNewPolicyModal(false);
};

return (
<>
<Header />
<NavBar>
{
/* Display modal for new event if add event button is clicked */
displayNewPolicyModal && (
<NewResourceModal
handleClose={hideNewPolicyModal}
resource={"lifecyclepolicy"}
/>
)
}

{/* Include Burger-button menu*/}
<MainNav isOpen={displayNavigation} toggleMenu={toggleNavigation} />

<nav>
{hasAccess("ROLE_UI_EVENTS_VIEW", user) && (
<Link
to="/events/events"
className={cn({ active: false })}
onClick={() => loadEvents()}
>
{t("EVENTS.EVENTS.NAVIGATION.EVENTS")}
</Link>
)}
{hasAccess("ROLE_UI_SERIES_VIEW", user) && (
<Link
to="/events/series"
className={cn({ active: false })}
onClick={() => loadSeries()}
>
{t("EVENTS.EVENTS.NAVIGATION.SERIES")}
</Link>
)}
{hasAccess("ROLE_UI_LIFECYCLEPOLICIES_VIEW", user) && (
<Link
to="/events/lifeCyclePolicies"
className={cn({ active: true })}
onClick={() => loadLifeCyclePolicies()}
>
{t("LIFECYCLE.NAVIGATION.POLICIES")}
</Link>
)}
</nav>

<div className="btn-group">
{hasAccess("ROLE_UI_EVENTS_CREATE", user) && (
<button className="add" onClick={() => showNewPolicyModal()}>
<i className="fa fa-plus" />
<span>{t("LIFECYCLE.POLICIES.TABLE.ADD_POLICY")}</span>
</button>
)}
</div>
</NavBar>

<MainView open={displayNavigation}>
{/* Include notifications component */}
<Notifications />

<div className="controls-container">
{/* Include filters component */}
{/* LifeCycle policies are not indexed, can't search or filter them */}
{/* But if we don't include this component, the policies won't load on page load, because the first
fetch request we send to the backend contains invalid params >.> */}
<TableFilters
loadResource={fetchLifeCyclePolicies as AsyncThunk<any, void, AsyncThunkConfig>}
loadResourceIntoTable={loadLifeCyclePoliciesIntoTable}
resource={"lifeCyclePolicies"}
/>

<h1>{t("LIFECYCLE.POLICIES.TABLE.CAPTION")}</h1>
<h4>{t("TABLE_SUMMARY", { numberOfRows: policiesTotal })}</h4>
</div>
{/* Include table component */}
<Table templateMap={lifeCyclePoliciesTemplateMap} />
</MainView>
<Footer />
</>
);
};

export default LifeCyclePolicies;
21 changes: 20 additions & 1 deletion src/components/events/Series.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import DeleteSeriesModal from "./partials/modals/DeleteSeriesModal";
import { seriesTemplateMap } from "../../configs/tableConfigs/seriesTableMap";
import {
loadEventsIntoTable,
loadLifeCyclePoliciesIntoTable,
loadSeriesIntoTable,
} from "../../thunks/tableThunks";
import { fetchFilters, fetchStats, editTextFilter } from "../../slices/tableFilterSlice";
Expand All @@ -34,6 +35,7 @@ import {
showActionsSeries,
} from "../../slices/seriesSlice";
import { fetchSeriesDetailsTobiraNew } from "../../slices/seriesSlice";
import { fetchLifeCyclePolicies } from "../../slices/lifeCycleSlice";

// References for detecting a click outside of the container of the dropdown menu
const containerAction = React.createRef<HTMLDivElement>();
Expand Down Expand Up @@ -79,6 +81,14 @@ const Series = () => {
dispatch(loadSeriesIntoTable());
};

const loadLifeCyclePolicies = async () => {
// Fetching policies from server
await dispatch(fetchLifeCyclePolicies());

// Load policies into table
dispatch(loadLifeCyclePoliciesIntoTable());
};

useEffect(() => {
if ("series" !== currentFilterType) {
dispatch(fetchFilters("series"))
Expand Down Expand Up @@ -186,8 +196,17 @@ const Series = () => {
{t("EVENTS.EVENTS.NAVIGATION.SERIES")}
</Link>
)}
{hasAccess("ROLE_UI_LIFECYCLEPOLICIES_VIEW", user) && (
<Link
to="/events/lifeCyclePolicies"
className={cn({ active: false })}
onClick={() => loadLifeCyclePolicies()}
>
{t("LIFECYCLE.NAVIGATION.POLICIES")}
</Link>
)}
</nav>

<div className="btn-group">
{hasAccess("ROLE_UI_SERIES_CREATE", user) && (
<button className="add" onClick={() => showNewSeriesModal()}>
Expand Down
Loading
Loading