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

Display LifeCyclePolicies in UI (read-only) #943

Open
wants to merge 7 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
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
150 changes: 150 additions & 0 deletions src/components/events/LifeCyclePolicies.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import React, { useEffect, useState } from "react";
import MainNav from "../shared/MainNav";
import { useTranslation } from "react-i18next";
import { Link } from "react-router";
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 { 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";

/**
* This component renders the table view of policies
*/
const LifeCyclePolicies = () => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const [displayNavigation, setNavigation] = 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));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

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

return (
<>
<Header />
<NavBar>

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

View workflow job for this annotation

GitHub Actions / build

Type '{ children: Element[]; }' is missing the following properties from type '{ children?: ReactNode; navAriaLabel?: string | undefined; displayNavigation: boolean; setNavigation: Dispatch<SetStateAction<boolean>>; links: LinkType[]; create?: CreateType | undefined; }': displayNavigation, setNavigation, links
{/* 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>
</NavBar>

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

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

View workflow job for this annotation

GitHub Actions / build

Property 'context' is missing in type '{}' but required in type '{ context: Context; }'.

<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, any>}
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;
17 changes: 16 additions & 1 deletion src/components/events/partials/EventsNavigation.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { fetchEvents } from "../../../slices/eventSlice";
import { fetchLifeCyclePolicies } from "../../../slices/lifeCycleSlice";
import { fetchSeries } from "../../../slices/seriesSlice";
import { fetchStats } from "../../../slices/tableFilterSlice";
import { AppDispatch } from "../../../store";
import { loadEventsIntoTable, loadSeriesIntoTable } from "../../../thunks/tableThunks";
import { loadEventsIntoTable, loadLifeCyclePoliciesIntoTable, loadSeriesIntoTable } from "../../../thunks/tableThunks";

/**
* Utility file for the navigation bar
Expand All @@ -27,6 +28,14 @@ export const loadSeries = (dispatch: AppDispatch) => {
dispatch(loadSeriesIntoTable());
};

export const loadLifeCyclePolicies = (dispatch: AppDispatch) => {
// Fetching policies from server
dispatch(fetchLifeCyclePolicies());

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

export const eventsLinks = [
{
path: "/events/events",
Expand All @@ -39,5 +48,11 @@ export const eventsLinks = [
accessRole: "ROLE_UI_SERIES_VIEW",
loadFn: loadSeries,
text: "EVENTS.EVENTS.NAVIGATION.SERIES"
},
{
path: "/events/lifeCyclePolicies",
accessRole: "ROLE_UI_LIFECYCLEPOLICIES_VIEW",
loadFn: loadLifeCyclePolicies,
text: "LIFECYCLE.NAVIGATION.POLICIES"
}
];
62 changes: 62 additions & 0 deletions src/components/events/partials/LifeCyclePolicyActionCell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { useAppDispatch, useAppSelector } from "../../../store";
import { Tooltip } from "../../shared/Tooltip";
import { LifeCyclePolicy } from "../../../slices/lifeCycleSlice";
import DetailsModal from "../../shared/modals/DetailsModal";
import LifeCyclePolicyDetails from "./modals/LifeCyclePolicyDetails";
import { hasAccess } from "../../../utils/utils";
import { getUserInformation } from "../../../selectors/userInfoSelectors";
import { fetchLifeCyclePolicyDetails } from "../../../slices/lifeCycleDetailsSlice";

/**
* This component renders the title cells of series in the table view
*/
const LifeCyclePolicyActionCell = ({
row,
}: {
row: LifeCyclePolicy
}) => {
const { t } = useTranslation();
const dispatch = useAppDispatch();

const [displayLifeCyclePolicyDetails, setLifeCyclePolicyDetails] = useState(false);

const user = useAppSelector(state => getUserInformation(state));

const showLifeCyclePolicyDetails = async () => {
await dispatch(fetchLifeCyclePolicyDetails(row.id));

setLifeCyclePolicyDetails(true);
};

const hideLifeCyclePolicyDetails = () => {
setLifeCyclePolicyDetails(false);
};

return (
<>
{/* view details location/recording */}
{hasAccess("ROLE_UI_LIFECYCLEPOLICY_DETAILS_VIEW", user) && (
<Tooltip title={t("LIFECYCLE.POLICIES.TABLE.TOOLTIP.DETAILS")}>
<button
className="button-like-anchor more"
onClick={() => showLifeCyclePolicyDetails()}
/>
</Tooltip>
)}

{displayLifeCyclePolicyDetails && (
<DetailsModal
handleClose={hideLifeCyclePolicyDetails}
title={row.title}
prefix={"LIFECYCLE.POLICIES.DETAILS.HEADER"}
>
<LifeCyclePolicyDetails />
</DetailsModal>
)}
</>
);
};

export default LifeCyclePolicyActionCell;
22 changes: 22 additions & 0 deletions src/components/events/partials/LifeCyclePolicyIsActiveCell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from "react";
import { LifeCyclePolicy } from "../../../slices/lifeCycleSlice";

/**
* This component renders the maintenance cells of servers in the table view
*/
const LifeCyclePolicyIsActiveCell = ({
row,
}: {
row: LifeCyclePolicy
}) => {

return (
<input
type="checkbox"
checked={row.isActive}
disabled={true}
/>
);
};

export default LifeCyclePolicyIsActiveCell;
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React, { useEffect } from "react";
import { useTranslation } from "react-i18next";
import ResourceDetailsAccessPolicyTab from "../../../shared/modals/ResourceDetailsAccessPolicyTab";
import { removeNotificationWizardForm } from "../../../../slices/notificationSlice";
import { useAppDispatch, useAppSelector } from "../../../../store";
import { getLifeCyclePolicyDetailsAcl } from "../../../../selectors/lifeCycleDetailsSelectors";
import { fetchLifeCyclePolicyDetailsAcls, updateLifeCyclePolicyAccess } from "../../../../slices/lifeCycleDetailsSlice";

/**
* This component manages the access policy tab of the series details modal
*/
const LifeCyclePolicyDetailsAccessTab = ({
seriesId,
header,
policyChanged,
setPolicyChanged,
}: {
seriesId: string,
header: string,
policyChanged: boolean,
setPolicyChanged: (value: boolean) => void,
}) => {
const { t } = useTranslation();
const dispatch = useAppDispatch();

const acl = useAppSelector(state => getLifeCyclePolicyDetailsAcl(state));

useEffect(() => {
dispatch(removeNotificationWizardForm());
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return (
<ResourceDetailsAccessPolicyTab
resourceId={seriesId}
header={header}
buttonText={"LIFECYCLE.POLICIES.DETAILS.ACCESS.LABEL"}
saveButtonText={"SAVE"}

Check failure on line 38 in src/components/events/partials/ModalTabsAndPages/LifeCyclePolicyAccessTab.tsx

View workflow job for this annotation

GitHub Actions / build

Type '{ resourceId: string; header: string; buttonText: string; saveButtonText: string; descriptionText: string; policies: TransformedAcl[]; fetchAccessPolicies: AsyncThunk<TransformedAcl[], string, { ...; }>; saveNewAccessPolicies: AsyncThunk<...>; editAccessRole: string; policyChanged: boolean; setPolicyChanged: (value:...' is not assignable to type 'IntrinsicAttributes & { resourceId: string; header: string; policies: TransformedAcl[]; fetchHasActiveTransactions?: AsyncThunk<any, string, any> | undefined; ... 6 more ...; setPolicyChanged: (value: boolean) => void; }'.
descriptionText={t("LIFECYCLE.POLICIES.DETAILS.ACCESS.DESCRIPTION")}
policies={acl}
fetchAccessPolicies={fetchLifeCyclePolicyDetailsAcls}
saveNewAccessPolicies={updateLifeCyclePolicyAccess}
editAccessRole={"ROLE_UI_LIFECYCLEPOLICY_DETAILS_ACL_EDIT"}
policyChanged={policyChanged}
setPolicyChanged={setPolicyChanged}
/>
);
};

export default LifeCyclePolicyDetailsAccessTab;
Loading
Loading