diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml
index 4b00749f..92f6d86b 100644
--- a/.github/workflows/analysis.yml
+++ b/.github/workflows/analysis.yml
@@ -72,7 +72,7 @@ jobs:
-Dsonar.javascript.lcov.reportPaths=coverage/lcov.info
-Dsonar.typescript.tsconfigPaths=tsconfig.json
-Dsonar.sources=src/
- -Dsonar.exclusions=src/__test__/**
+ -Dsonar.exclusions=src/__test__/**,src/amplifyconfiguration.*,src/**/*.scss,src/**/*.css,src/**/*.d.*,src/setupTests.*
-Dsonar.tests=src/__test__/
-Dsonar.project.monorepo.enabled=true
sonar_token: ${{ secrets.SONAR_TOKEN_FRONTEND }}
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 9212ab8e..9724ce05 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -13,7 +13,6 @@
"@carbon/icons-react": "^11.50.1",
"@carbon/pictograms-react": "^11.49.0",
"@carbon/react": "^1.27.0",
- "@redux-devtools/extension": "^3.3.0",
"@tanstack/react-query": "^5.50.1",
"@types/node": "^22.0.0",
"@vitejs/plugin-react": "^4.0.4",
@@ -30,10 +29,7 @@
"react-esri-leaflet": "^2.0.1",
"react-hash-string": "^1.0.0",
"react-leaflet": "^4.2.1",
- "react-redux": "^9.0.0",
"react-router-dom": "^6.10.0",
- "redux": "^5.0.0",
- "redux-thunk": "^3.0.0",
"vite": "^5.0.0",
"vite-plugin-svgr": "^4.0.0",
"vite-tsconfig-paths": "^5.0.0",
@@ -3122,19 +3118,6 @@
"react-dom": "^18.0.0"
}
},
- "node_modules/@redux-devtools/extension": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/@redux-devtools/extension/-/extension-3.3.0.tgz",
- "integrity": "sha512-X34S/rC8S/M1BIrkYD1mJ5f8vlH0BDqxXrs96cvxSBo4FhMdbhU+GUGsmNYov1xjSyLMHgo8NYrUG8bNX7525g==",
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.23.2",
- "immutable": "^4.3.4"
- },
- "peerDependencies": {
- "redux": "^3.1.0 || ^4.0.0 || ^5.0.0"
- }
- },
"node_modules/@remix-run/router": {
"version": "1.20.0",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.20.0.tgz",
@@ -5226,7 +5209,7 @@
"version": "15.7.13",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz",
"integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==",
- "devOptional": true,
+ "dev": true,
"license": "MIT"
},
"node_modules/@types/qs": {
@@ -5247,7 +5230,7 @@
"version": "18.3.12",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz",
"integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==",
- "devOptional": true,
+ "dev": true,
"license": "MIT",
"dependencies": {
"@types/prop-types": "*",
@@ -5330,12 +5313,6 @@
"@types/geojson": "*"
}
},
- "node_modules/@types/use-sync-external-store": {
- "version": "0.0.3",
- "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
- "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==",
- "license": "MIT"
- },
"node_modules/@types/uuid": {
"version": "9.0.8",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz",
@@ -6657,7 +6634,7 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
- "devOptional": true,
+ "dev": true,
"license": "MIT"
},
"node_modules/d3": {
@@ -11265,29 +11242,6 @@
"react-dom": "^18.0.0"
}
},
- "node_modules/react-redux": {
- "version": "9.1.2",
- "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.2.tgz",
- "integrity": "sha512-0OA4dhM1W48l3uzmv6B7TXPCGmokUU4p1M44DGN2/D9a1FjVPukVjER1PcPX97jIg6aUeLq1XJo1IpfbgULn0w==",
- "license": "MIT",
- "dependencies": {
- "@types/use-sync-external-store": "^0.0.3",
- "use-sync-external-store": "^1.0.0"
- },
- "peerDependencies": {
- "@types/react": "^18.2.25",
- "react": "^18.0",
- "redux": "^5.0.0"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "redux": {
- "optional": true
- }
- }
- },
"node_modules/react-refresh": {
"version": "0.14.2",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
@@ -11356,21 +11310,6 @@
"node": ">=8"
}
},
- "node_modules/redux": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
- "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
- "license": "MIT"
- },
- "node_modules/redux-thunk": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz",
- "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==",
- "license": "MIT",
- "peerDependencies": {
- "redux": "^5.0.0"
- }
- },
"node_modules/reflect.getprototypeof": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz",
@@ -12756,15 +12695,6 @@
"react-dom": ">=16.8.0"
}
},
- "node_modules/use-sync-external-store": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz",
- "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==",
- "license": "MIT",
- "peerDependencies": {
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
- }
- },
"node_modules/utrie": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 276e9e7b..7772c0a6 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -9,11 +9,10 @@
"@carbon/icons-react": "^11.50.1",
"@carbon/pictograms-react": "^11.49.0",
"@carbon/react": "^1.27.0",
- "@redux-devtools/extension": "^3.3.0",
"@tanstack/react-query": "^5.50.1",
"@types/node": "^22.0.0",
"@vitejs/plugin-react": "^4.0.4",
- "@vitejs/plugin-react-swc": "^3.3.2",
+ "@vitejs/plugin-react-swc": "^3.3.2",
"aws-amplify": "^6.7.0",
"axios": "^1.6.8",
"jspdf": "^2.5.2",
@@ -26,10 +25,7 @@
"react-esri-leaflet": "^2.0.1",
"react-hash-string": "^1.0.0",
"react-leaflet": "^4.2.1",
- "react-redux": "^9.0.0",
"react-router-dom": "^6.10.0",
- "redux": "^5.0.0",
- "redux-thunk": "^3.0.0",
"vite": "^5.0.0",
"vite-plugin-svgr": "^4.0.0",
"vite-tsconfig-paths": "^5.0.0",
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 1895b049..3a618220 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -1,7 +1,6 @@
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import './custom.scss';
import Landing from "./screens/Landing";
-import Help from "./screens/Help";
import SideLayout from './layouts/SideLayout';
import ProtectedRoute from './routes/ProtectedRoute';
import Opening from './screens/Opening';
@@ -33,10 +32,6 @@ const router = createBrowserRouter([
{
path: "/silviculture-search",
element: } />
- },
- {
- path: "/help",
- element: } />
}
]
},
diff --git a/frontend/src/__test__/actions/userAction.test.ts b/frontend/src/__test__/actions/userAction.test.ts
deleted file mode 100644
index 592f409f..00000000
--- a/frontend/src/__test__/actions/userAction.test.ts
+++ /dev/null
@@ -1,86 +0,0 @@
-import { describe, it, expect, vi } from 'vitest';
-import { getUserDetails, setClientRoles } from '../../actions/userAction';
-import {
- USER_DETAILS_REQUEST,
-USER_DETAILS_SUCCESS,
-USER_DETAILS_FAIL,
-SET_CLIENT_ROLES
-} from '../../constants/userConstants';
-import { useGetAuth } from '../../contexts/AuthProvider';
-import { AppDispatch } from '../../store';
-import { UserClientRolesType } from '../../types/UserRoleType';
-
-
-
-vi.mock('../../contexts/AuthProvider', () => ({
-useGetAuth: vi.fn(),
-}));
-
-describe('userAction', () => {
-describe('getUserDetails', () => {
- it('should dispatch USER_DETAILS_REQUEST and USER_DETAILS_SUCCESS with user data when successful', async () => {
- const mockDispatch = vi.fn();
- const mockIsLoggedIn = true;
- const mockUser = { firstName: 'John', lastName: 'Doe' };
- const mockUserJSON = JSON.stringify(mockUser);
-
- (useGetAuth as vi.Mock).mockReturnValue({ isLoggedIn: mockIsLoggedIn });
- localStorage.setItem('famLoginUser', mockUserJSON);
-
- await getUserDetails()(mockDispatch as unknown as AppDispatch);
-
- expect(mockDispatch).toHaveBeenCalledWith({ type: USER_DETAILS_REQUEST });
- expect(mockDispatch).toHaveBeenCalledWith({
- type: USER_DETAILS_SUCCESS,
- payload: { ...mockUser, isLoggedIn: mockIsLoggedIn },
- });
- });
-
- it('should dispatch USER_DETAILS_FAIL with error when an error occurs', async () => {
- const mockDispatch = vi.fn();
- const mockError = new Error('Test error');
-
- (useGetAuth as vi.Mock).mockImplementation(() => {
- throw mockError;
- });
-
- await getUserDetails()(mockDispatch as unknown as AppDispatch);
-
- expect(mockDispatch).toHaveBeenCalledWith({ type: USER_DETAILS_REQUEST });
- expect(mockDispatch).toHaveBeenCalledWith({
- type: USER_DETAILS_FAIL,
- payload: { error: mockError },
- });
- });
-
- it('should handle missing user data in localStorage', async () => {
- const mockDispatch = vi.fn();
- const mockIsLoggedIn = true;
-
- (useGetAuth as vi.Mock).mockReturnValue({ isLoggedIn: mockIsLoggedIn });
- localStorage.removeItem('famLoginUser');
-
- await getUserDetails()(mockDispatch as unknown as AppDispatch);
-
- expect(mockDispatch).toHaveBeenCalledWith({ type: USER_DETAILS_REQUEST });
- expect(mockDispatch).toHaveBeenCalledWith({
- type: USER_DETAILS_SUCCESS,
- payload: { isLoggedIn: mockIsLoggedIn },
- });
- });
-});
-
-describe('setClientRoles', () => {
- it('should dispatch SET_CLIENT_ROLES with client roles', () => {
- const mockDispatch = vi.fn();
- const mockClientRoles: UserClientRolesType[] = [{ clientId: '123', roles: ['admin'] }];
-
- setClientRoles(mockClientRoles)(mockDispatch as unknown as AppDispatch);
-
- expect(mockDispatch).toHaveBeenCalledWith({
- type: SET_CLIENT_ROLES,
- payload: mockClientRoles,
- });
- });
-});
-});
\ No newline at end of file
diff --git a/frontend/src/__test__/components/BCHeaderwSide.test.tsx b/frontend/src/__test__/components/BCHeaderwSide.test.tsx
index c3a49c78..5a920686 100644
--- a/frontend/src/__test__/components/BCHeaderwSide.test.tsx
+++ b/frontend/src/__test__/components/BCHeaderwSide.test.tsx
@@ -5,9 +5,6 @@ import { BrowserRouter } from 'react-router-dom';
import BCHeaderwSide from '../../components/BCHeaderwSide';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import {leftMenu } from '../../components/BCHeaderwSide/constants';
-import * as redux from 'react-redux';
-import { Provider } from 'react-redux';
-import store from '../../store';
import { UserClientRolesType } from '../../types/UserRoleType';
import '@testing-library/jest-dom';
import { AuthProvider } from '../../contexts/AuthProvider';
@@ -31,12 +28,10 @@ const renderComponent = () => {
render(
-
-
-
-
-
-
+
+
+
+
);
@@ -65,9 +60,6 @@ const state = {
},
};
-vi.spyOn(redux, 'useSelector')
- .mockImplementation((callback) => callback(state));
-
describe('BCHeaderwSide', () => {
it('should renders the component', () => {
renderComponent();
@@ -88,12 +80,6 @@ describe('BCHeaderwSide', () => {
// expect(screen.queryByText('My Profile')).not.toBeVisible();
});
- // it('renders the correct number of top-level menu items', () => {
- // renderComponent();
- // const menuItems = screen.getAllByRole('button', { name: /.*Category.*/ });
- // expect(menuItems).toHaveLength(leftMenu.length);
- // });
-
it('renders the correct menu item names', () => {
renderComponent();
leftMenu.forEach(item => {
diff --git a/frontend/src/__test__/components/OpeningHistory.test.tsx b/frontend/src/__test__/components/OpeningHistory.test.tsx
index e65b5a08..e5be3a72 100644
--- a/frontend/src/__test__/components/OpeningHistory.test.tsx
+++ b/frontend/src/__test__/components/OpeningHistory.test.tsx
@@ -2,49 +2,32 @@ import React from 'react';
import { render, act } from '@testing-library/react';
import { describe, it, expect, vi } from 'vitest';
import OpeningHistory from '../../components/OpeningHistory';
-import History from '../../types/History';
-import { deleteOpeningFavorite } from '../../services/OpeningFavoriteService';
-
-const mockHistories: History[] = [
- {
- id: 1,
- steps: [],
- },
- {
- id: 2,
- steps: [
- { step: 1, status: 'complete', description: 'Step 1', subtitle: 'Completed' },
- { step: 2, status: 'invalid', description: 'Step 2', subtitle: 'Invalid' },
- { step: 3, status: 'disabled', description: 'Step 3', subtitle: 'Disabled' },
- ],
- },
-];
+import { NotificationProvider } from '../../contexts/NotificationProvider';
+import { deleteOpeningFavorite, fetchOpeningTrends } from '../../services/OpeningFavoriteService';
vi.mock('../../services/OpeningFavoriteService', () => ({
deleteOpeningFavorite: vi.fn(),
+ fetchOpeningTrends: vi.fn(),
}));
describe('OpeningHistory Component', () => {
it('renders correctly with given histories', async () => {
- let getByText;
+ (fetchOpeningTrends as vi.Mock).mockReturnValueOnce(Promise.resolve([1, 2]));
+ let container;
await act(async () => {
- ({ getByText } = render( ));
+ ({ container } = render());
});
// Check for the presence of Opening Ids
- expect(getByText('Opening Id 1')).toBeInTheDocument();
- expect(getByText('Opening Id 2')).toBeInTheDocument();
-
- // Check for the presence of step descriptions
- expect(getByText('Step 1')).toBeInTheDocument();
- expect(getByText('Step 2')).toBeInTheDocument();
- expect(getByText('Step 3')).toBeInTheDocument();
+ expect(container.querySelector('div[data-id="1"').innerHTML).toContain('Opening Id 1');
+ expect(container.querySelector('div[data-id="2"').innerHTML).toContain('Opening Id 2');
});
it('renders correctly with empty histories', async () => {
+ (fetchOpeningTrends as vi.Mock).mockReturnValueOnce(Promise.resolve([]));
let container;
await act(async () => {
- ({ container } = render( ));
+ ({ container } = render());
});
// Select the div with the specific class
@@ -57,13 +40,29 @@ describe('OpeningHistory Component', () => {
// check if when clicked on the FavoriteButton, the deleteOpeningFavorite function is called
it('should call deleteOpeningFavorite when FavoriteButton is clicked', async () => {
+ (fetchOpeningTrends as vi.Mock).mockReturnValueOnce(Promise.resolve([1, 2]));
let container;
await act(async () => {
- ({ container } = render( ));
+ ({ container } = render());
});
const favoriteButton = container.querySelector('.favorite-icon button')
- favoriteButton && favoriteButton.click();
+ await act(async () => favoriteButton && favoriteButton.click());
+
+ expect(deleteOpeningFavorite).toHaveBeenCalled();
+ });
+
+ it('should call deleteOpeningFavorite and handle error when FavoriteButton is clicked', async () => {
+ (fetchOpeningTrends as vi.Mock).mockReturnValueOnce(Promise.resolve([1, 2]));
+ (deleteOpeningFavorite as vi.Mock).mockRejectedValueOnce(new Error('Failed to delete favorite'));
+ let container;
+ await act(async () => {
+ ({ container } = render());
+ });
+
+ const favoriteButton = container.querySelector('.favorite-icon button')
+ await act(async () => favoriteButton && favoriteButton.click());
+
expect(deleteOpeningFavorite).toHaveBeenCalled();
});
});
diff --git a/frontend/src/__test__/components/OpeningMetricsTab.test.tsx b/frontend/src/__test__/components/OpeningMetricsTab.test.tsx
index 75a27d69..08a02b41 100644
--- a/frontend/src/__test__/components/OpeningMetricsTab.test.tsx
+++ b/frontend/src/__test__/components/OpeningMetricsTab.test.tsx
@@ -2,6 +2,7 @@ import { describe, it, expect, vi, beforeEach } from 'vitest';
import React from 'react';
import { render, act, waitFor, fireEvent, screen } from '@testing-library/react';
import OpeningMetricsTab from '../../components/OpeningMetricsTab';
+import { NotificationProvider } from '../../contexts/NotificationProvider';
import { fetchOpeningTrends } from '../../services/OpeningFavoriteService';
import { fetchFreeGrowingMilestones, fetchOpeningsPerYear, fetchRecentOpenings } from '../../services/OpeningService';
@@ -46,7 +47,7 @@ describe('OpeningMetricsTab', () => {
it('should render the OpeningMetricsTab component with all sections', async () => {
- await act(async () => render());
+ await act(async () => render());
expect(screen.getByText('Dashboard')).toBeInTheDocument();
expect(screen.getByText('Manage and track silvicultural information about openings')).toBeInTheDocument();
@@ -64,7 +65,7 @@ describe('OpeningMetricsTab', () => {
await act(async () => {
- render();
+ render();
});
await waitFor(() => {
@@ -84,7 +85,7 @@ describe('OpeningMetricsTab', () => {
delete window.location;
window.location = { search: '?scrollTo=trackOpenings' } as any;
- await act(async () => render());
+ await act(async () => render());
expect(mockScrollIntoView).toHaveBeenCalledWith({ behavior: 'smooth' });
@@ -100,7 +101,7 @@ describe('OpeningMetricsTab', () => {
delete window.location;
window.location = { search: '' } as any;
- await act(async () => render());
+ await act(async () => render());
expect(mockScrollIntoView).not.toHaveBeenCalled();
diff --git a/frontend/src/__test__/components/OpeningsTab.test.tsx b/frontend/src/__test__/components/OpeningsTab.test.tsx
index 0b5cd8d1..10bd1b32 100644
--- a/frontend/src/__test__/components/OpeningsTab.test.tsx
+++ b/frontend/src/__test__/components/OpeningsTab.test.tsx
@@ -1,99 +1,51 @@
-import React from "react";
-import { render, screen } from "@testing-library/react";
-import "@testing-library/jest-dom";
-import { describe, expect, it, vi } from "vitest";
-import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
-import OpeningsTab from "../../../src/components/OpeningsTab";
-import { Provider } from "react-redux";
-import store from "../../store";
-import {useUserRecentOpeningQuery} from "../../../src/services/queries/search/openingQueries";
-import { MemoryRouter } from "react-router-dom";
-import PaginationContext from "../../contexts/PaginationContext";
-
-// Mocking useUserRecentOpeningQuery to return the necessary functions and state
-vi.mock("../../../src/services/queries/search/openingQueries", () => ({
- useUserRecentOpeningQuery: vi.fn(),
+import { describe, it, expect, vi, beforeEach } from 'vitest';
+import React from 'react';
+import { render, act, waitFor, screen } from '@testing-library/react';
+import OpeningsTab from '../../components/OpeningsTab';
+import { AuthProvider } from '../../contexts/AuthProvider';
+import { getWmsLayersWhitelistUsers } from '../../services/SecretsService';
+import { fetchRecentOpenings } from '../../services/OpeningService';
+import { RecentOpening } from '../../types/RecentOpening';
+import PaginationProvider from '../../contexts/PaginationProvider';
+
+
+vi.mock('../../services/SecretsService', () => ({
+ getWmsLayersWhitelistUsers: vi.fn()
}));
-
-const paginationValueMock = {
- getCurrentData: () => [],
- currentPage: 0,
- totalPages: 0,
- handlePageChange: vi.fn(),
- handleItemsPerPageChange: vi.fn(),
- itemsPerPage: 5,
- totalResultItems:100,
- setTotalResultItems:vi.fn(),
- setPageData: vi.fn(),
- setInitialItemsPerPage: vi.fn(),
+vi.mock('../../services/OpeningService', async () => {
+ const actual = await vi.importActual('../../services/OpeningService');
+ return {
+ ...actual,
+ fetchRecentOpenings: vi.fn(),
};
+});
-describe("OpeningsTab", () => {
- const queryClient = new QueryClient();
- const showSpatial = false;
- const setShowSpatial = vi.fn();
-
- it("renders the component successfully", () => {
- (useUserRecentOpeningQuery as jest.Mock).mockReturnValue({ data: [], isFetching: false });
- render(
-
-
-
-
-
-
-
-
-
- );
- const searchInput = screen.getByText(/Track the history of openings you have looked at and check spatial information by selecting the openings in the table below/i);
- expect(searchInput).toBeInTheDocument();
- });
- it("shows the spatial area with Hide Spatial Button", () => {
- (useUserRecentOpeningQuery as jest.Mock).mockReturnValue({ data: [], isFetching: false });
- render(
-
-
-
-
-
-
-
-
-
- );
- const hideSpatialButton = screen.getByRole('button', { name: /Hide Spatial/i });
- expect(hideSpatialButton).toBeInTheDocument();
+const rows: RecentOpening[] = [{
+ id: '123',
+ openingId: '123',
+ fileId: '1',
+ cuttingPermit: '1',
+ timberMark: '1',
+ cutBlock: '1',
+ grossAreaHa: 1,
+ statusDesc: 'Approved',
+ categoryDesc: 'Another:Another',
+ disturbanceStart: '1',
+ entryTimestamp: '1',
+ updateTimestamp: '1',
+}];
+
+describe('Openings Tab test',() => {
+
+ it('should render properly',async () =>{
+ (getWmsLayersWhitelistUsers as vi.Mock).mockResolvedValue([{userName: 'TEST'}]);
+ (fetchRecentOpenings as vi.Mock).mockResolvedValue(rows);
+ await act(async () => {
+ render();
+ });
+ expect(screen.getByText('Recent openings')).toBeInTheDocument();
});
-
- it("shows table skeleton when the data is loading", () => {
- (useUserRecentOpeningQuery as jest.Mock).mockReturnValue({ data: [], isFetching: true });
-
- render(
-
-
-
-
-
-
-
-
-
- );
- console.log(screen.debug());
- expect.poll(() => document.querySelector('--cds-skeleton')).toBeTruthy();
- });
-
-});
+});
\ No newline at end of file
diff --git a/frontend/src/__test__/components/ThemeToggle.test.tsx b/frontend/src/__test__/components/ThemeToggle.test.tsx
new file mode 100644
index 00000000..41cdceea
--- /dev/null
+++ b/frontend/src/__test__/components/ThemeToggle.test.tsx
@@ -0,0 +1,18 @@
+import React from 'react';
+import { render } from '@testing-library/react';
+import { describe, expect, it, vi } from 'vitest';
+import ThemeToggle from '../../components/ThemeToggle';
+
+describe('Theme toggle component tests', () => {
+ it('should render correctly', () => {
+ const { container } = render();
+ expect(container).toMatchSnapshot();
+ });
+
+ it('should toggle theme when button is clicked', () => {
+ const { container } = render();
+ const button = container.querySelector('button');
+ button?.click();
+ expect(container).toMatchSnapshot();
+ });
+});
diff --git a/frontend/src/__test__/components/__snapshots__/ThemeToggle.test.tsx.snap b/frontend/src/__test__/components/__snapshots__/ThemeToggle.test.tsx.snap
new file mode 100644
index 00000000..2c112feb
--- /dev/null
+++ b/frontend/src/__test__/components/__snapshots__/ThemeToggle.test.tsx.snap
@@ -0,0 +1,61 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`Theme toggle component tests > should render correctly 1`] = `
+
+`;
+
+exports[`Theme toggle component tests > should toggle theme when button is clicked 1`] = `
+
+`;
diff --git a/frontend/src/__test__/contexts/AuthProvider.test.tsx b/frontend/src/__test__/contexts/AuthProvider.test.tsx
index 3430ccca..7106ad23 100644
--- a/frontend/src/__test__/contexts/AuthProvider.test.tsx
+++ b/frontend/src/__test__/contexts/AuthProvider.test.tsx
@@ -91,7 +91,7 @@ describe('AuthProvider', () => {
it('should handle login correctly', async () => {
setAuthCookies(sampleAuthToken);
const provider = 'idir';
- const envProvider = 'TEST-IDIR';
+ const envProvider = `${env.VITE_ZONE ?? 'DEV'}-IDIR`;
const TestComponent = () => {
const { login } = useGetAuth();
diff --git a/frontend/src/__test__/contexts/NotificationProvider.test.tsx b/frontend/src/__test__/contexts/NotificationProvider.test.tsx
new file mode 100644
index 00000000..320bda9b
--- /dev/null
+++ b/frontend/src/__test__/contexts/NotificationProvider.test.tsx
@@ -0,0 +1,128 @@
+import React from 'react';
+import { render, screen, act } from '@testing-library/react';
+import { describe, it, expect, vi } from 'vitest';
+import { NotificationProvider, useNotification } from '../../contexts/NotificationProvider';
+import { NotificationContent } from '../../types/NotificationType';
+import { ActionableNotification } from '@carbon/react';
+
+// Mock the ActionableNotification component
+vi.mock('@carbon/react', () => ({
+ ActionableNotification: ({ title, subtitle, onClose, onActionButtonClick }: any) => (
+
+
{title}
+
{subtitle}
+
+
+
+ )
+}));
+
+const onCloseMock = vi.fn();
+
+const TestComponent = () => {
+ const { displayNotification } = useNotification();
+ return (
+
+ );
+};
+
+describe('NotificationProvider', () => {
+ it('should display notification when displayNotification is called', () => {
+ render(
+
+
+
+ );
+
+ act(() => {
+ screen.getByText('Show Notification').click();
+ });
+
+ expect(screen.getByText('Test Title')).toBeInTheDocument();
+ expect(screen.getByText('Test Subtitle')).toBeInTheDocument();
+ expect(screen.getByText('Close')).toBeInTheDocument();
+ expect(screen.getByText('Action')).toBeInTheDocument();
+ });
+
+ it('should hide notification when close button is clicked', () => {
+ render(
+
+
+
+ );
+
+ act(() => {
+ screen.getByText('Show Notification').click();
+ });
+
+ act(() => {
+ screen.getByText('Close').click();
+ });
+
+ expect(screen.queryByText('Test Title')).not.toBeInTheDocument();
+ expect(screen.queryByText('Test Subtitle')).not.toBeInTheDocument();
+ });
+
+ it('should call onClose and hide notification when action button is clicked', () => {
+
+
+ render(
+
+
+
+ );
+
+ act(() => {
+ screen.getByText('Show Notification').click();
+ });
+
+ act(() => {
+ screen.getByText('Action').click();
+ });
+
+ expect(onCloseMock).toHaveBeenCalled();
+ expect(screen.queryByText('Test Title')).not.toBeInTheDocument();
+ expect(screen.queryByText('Test Subtitle')).not.toBeInTheDocument();
+ });
+
+ it('should hide notification after dismissIn time', async () => {
+ vi.useFakeTimers(); // Use fake timers
+
+ await act(async () => render(
+
+
+
+ ));
+
+ await act(async () => {
+ screen.getByText('Show Notification').click();
+ });
+
+ expect(screen.getByText('Test Title')).toBeInTheDocument();
+ expect(screen.getByText('Test Subtitle')).toBeInTheDocument();
+
+ await act(async () => vi.advanceTimersByTime(1111)); // Fast-forward time by 1 second
+
+ expect(screen.queryByText('Test Title')).not.toBeInTheDocument();
+ expect(screen.queryByText('Test Subtitle')).not.toBeInTheDocument
+
+ });
+
+
+ afterEach(() => {
+ vi.useRealTimers(); // Restore real timers after each test
+ });
+});
\ No newline at end of file
diff --git a/frontend/src/__test__/screens/Help.test.tsx b/frontend/src/__test__/screens/Help.test.tsx
deleted file mode 100644
index ff823dc2..00000000
--- a/frontend/src/__test__/screens/Help.test.tsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import React from 'react';
-import { render, screen, act } from '@testing-library/react';
-import { MemoryRouter } from 'react-router-dom';
-import Help from '../../screens/Help';
-import { describe, expect, it } from 'vitest';
-
-describe('Help component test cases', () => {
- it('should renders the help page header', () => {
- render(, { wrapper: MemoryRouter });
- const headerElement = screen.getByText('Help Page');
- expect(headerElement).not.toBeNull();
- });
-
- it('should renders the help page content', () => {
- render(, { wrapper: MemoryRouter });
- const contentElement = screen.getByText(/Welcome to the Help Page/i);
- expect(contentElement).not.toBeNull();
- });
-
- it('should navigates back to home page on button click', () => {
- act(() => {
- render(, { wrapper: MemoryRouter });
- });
-
- act(() => {
- const backButton = screen.getByRole('button', { name: /Back to Home/i });
- backButton.click();
- });
-
- // Add assertions to test if navigation to the home page occurs
- expect(location.pathname).toBe('/');
- });
-});
diff --git a/frontend/src/__test__/screens/Opening.test.tsx b/frontend/src/__test__/screens/Opening.test.tsx
index 8e4d3970..863c0d76 100644
--- a/frontend/src/__test__/screens/Opening.test.tsx
+++ b/frontend/src/__test__/screens/Opening.test.tsx
@@ -3,12 +3,13 @@ import { describe, expect, it, vi } from 'vitest';
import { render, waitFor, act } from '@testing-library/react';
import Opening from '../../screens/Opening';
import PaginationContext from '../../contexts/PaginationContext';
+import { NotificationProvider } from '../../contexts/NotificationProvider';
import { BrowserRouter } from 'react-router-dom';
-import * as redux from 'react-redux';
import { RecentOpening } from '../../types/RecentOpening';
import { getWmsLayersWhitelistUsers } from '../../services/SecretsService';
import { fetchFreeGrowingMilestones, fetchOpeningsPerYear, fetchRecentOpenings } from '../../services/OpeningService';
import { fetchOpeningTrends } from '../../services/OpeningFavoriteService';
+import { AuthProvider } from '../../contexts/AuthProvider';
const data = {
"activityType": "Update",
@@ -44,8 +45,6 @@ const state = {
}
};
-vi.spyOn(redux, 'useSelector')
- .mockImplementation((callback) => callback(state));
const rows: RecentOpening[] = [{
id: '123',
@@ -96,7 +95,11 @@ describe('Opening screen test cases', () => {
const { getByTestId } = render(
-
+
+
+
+
+
);
@@ -117,7 +120,11 @@ describe('Opening screen test cases', () => {
({ container } = render(
-
+
+
+
+
+
));
@@ -152,7 +159,11 @@ describe('Opening screen test cases', () => {
({ container, getByText } = render(
-
+
+
+
+
+
));
@@ -171,7 +182,11 @@ describe('Opening screen test cases', () => {
({ container, getByText } = render(
-
+
+
+
+
+
));
diff --git a/frontend/src/__test__/views/LoginOrgSelection.test.tsx b/frontend/src/__test__/views/LoginOrgSelection.test.tsx
deleted file mode 100644
index a003fdc7..00000000
--- a/frontend/src/__test__/views/LoginOrgSelection.test.tsx
+++ /dev/null
@@ -1,67 +0,0 @@
-import React from 'react';
-import { render, screen } from '@testing-library/react';
-import { describe, expect, it, vi } from 'vitest';
-import { Provider } from 'react-redux';
-import store from '../../store';
-import LoginOrgSelection from '../../views/LoginOrgSelection';
-import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
-import { UserClientRolesType } from '../../types/UserRoleType';
-import * as redux from 'react-redux';
-
-vi.mock('../../services/TestService', () => ({
- getForestClientByNumberOrAcronym: vi.fn(() => [
- {
- clientNumber: '00012797',
- clientName: 'MINISTRY OF FORESTS',
- legalFirstName: '',
- legalMiddleName: '',
- clientStatusCode: { code: 'ACT', description: 'Active' },
- clientTypeCode: { code: 'F', description: 'Ministry of Forests and Range' },
- acronym: 'MOF'
- },
- ]),
-}));
-
-const clientRoles: UserClientRolesType[] = [
- {
- clientId: '00012797',
- roles: ['ONE', 'TWO', 'THREE'],
- clientName: 'MINISTRY OF FORESTS'
- }
-];
-
-const state = {
- userDetails: {
- id: 1,
- name: 'User',
- user: {
- firstName: 'John',
- lastName: 'Doe',
- providerUsername: 'johndoe123',
- clientRoles: clientRoles
- },
- loading: false,
- error: null
- },
-};
-
-vi.spyOn(redux, 'useSelector')
- .mockImplementation((callback) => callback(state));
-
-describe('LoginOrgSelection', () => {
- it('renders organization selection view with user details', () => {
- const qc = new QueryClient();
-
- render(
-
-
-
-
-
- );
-
- // Check if elements are rendered correctly
- expect(screen.getByText('Organization selection')).toBeDefined();
- expect(screen.getByText('John Doe (johndoe123) select which organization you\'re representing.')).toBeDefined();
- });
-});
diff --git a/frontend/src/actions/selectedClientRolesActions.ts b/frontend/src/actions/selectedClientRolesActions.ts
deleted file mode 100644
index aa0ec954..00000000
--- a/frontend/src/actions/selectedClientRolesActions.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-// selectedClientRolesActions.js
-import { SET_SELECTED_CLIENT_ROLES } from '../constants/selectedClientRolesConstants';
-import { AppDispatch } from '../store';
-import { UserClientRolesType } from '../types/UserRoleType';
-
-export interface SetSelectedClientRolesAction {
- type: typeof SET_SELECTED_CLIENT_ROLES;
- payload: UserClientRolesType;
-}
-
-export const setSelectedClientRoles = (selectedClientRoles: UserClientRolesType) => (dispatch: AppDispatch) => {
- dispatch({
- type: SET_SELECTED_CLIENT_ROLES,
- payload: selectedClientRoles
- });
-};
diff --git a/frontend/src/actions/userAction.ts b/frontend/src/actions/userAction.ts
deleted file mode 100644
index 87d6369d..00000000
--- a/frontend/src/actions/userAction.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import {
- USER_DETAILS_REQUEST,
- USER_DETAILS_SUCCESS,
- USER_DETAILS_FAIL,
- SET_CLIENT_ROLES
-} from '../constants/userConstants';
-import { AppDispatch } from '../store';
-import { UserClientRolesType } from '../types/UserRoleType';
-import { useGetAuth } from '../contexts/AuthProvider';
-
-const FAM_LOGIN_USER = 'famLoginUser';
-
-export const getUserDetails = () => async (dispatch: AppDispatch) => {
- try {
- dispatch({
- type: USER_DETAILS_REQUEST
- });
- //first call the isCurrent and only after that extract the JSON
- const { isLoggedIn } = useGetAuth();
-
- const userJSON = localStorage.getItem(FAM_LOGIN_USER); // Retrieve the JSON string from local storage
- const user = userJSON ? JSON.parse(userJSON) : null; // Parse the JSON string to a JavaScript object
-
- dispatch({
- type: USER_DETAILS_SUCCESS,
- payload: { ...user, isLoggedIn }
- });
- } catch (error) {
- dispatch({
- type: USER_DETAILS_FAIL,
- payload: { error: error }
- });
- }
-};
-
-export const setClientRoles = (clientRoles:UserClientRolesType[]) => (dispatch: AppDispatch) => {
- dispatch({
- type: SET_CLIENT_ROLES,
- payload: clientRoles
- });
-};
diff --git a/frontend/src/amplifyconfiguration.ts b/frontend/src/amplifyconfiguration.ts
index 31a482f0..0598eda2 100644
--- a/frontend/src/amplifyconfiguration.ts
+++ b/frontend/src/amplifyconfiguration.ts
@@ -3,7 +3,8 @@ import { env } from './env';
const ZONE = env.VITE_ZONE.toLocaleLowerCase();
const redirectUri = window.location.origin;
const logoutDomain = `https://logon${ZONE === "prod"?'':'test'}7.gov.bc.ca`;
-const retUrl = `https://${ZONE === "prod" ? "loginproxy" :ZONE === "test" ? "test.loginproxy": "dev.loginproxy"}.gov.bc.ca/auth/realms/standard/protocol/openid-connect/logout`;
+const returnUrlHost = ZONE === "prod" ? "loginproxy" :ZONE === "test" ? "test.loginproxy": "dev.loginproxy";
+const retUrl = `https://${returnUrlHost}.gov.bc.ca/auth/realms/standard/protocol/openid-connect/logout`;
const redirectSignOut =
env.VITE_REDIRECT_SIGN_OUT && env.VITE_REDIRECT_SIGN_OUT.trim() !== ""
diff --git a/frontend/src/components/ActionsTable/index.tsx b/frontend/src/components/ActionsTable/index.tsx
index 30203d40..0dc84b85 100644
--- a/frontend/src/components/ActionsTable/index.tsx
+++ b/frontend/src/components/ActionsTable/index.tsx
@@ -1,4 +1,3 @@
-import React from 'react';
import {
Table,
TableHead,
@@ -14,8 +13,8 @@ import { ActivityTagFileFormatEnum, ActivityTagTypeEnum } from '../../types/Acti
import { ITableHeader } from '../../types/TableHeader';
interface IActionsTable {
- rows: RecentAction[];
- headers: ITableHeader[];
+ readonly rows: RecentAction[];
+ readonly headers: ITableHeader[];
}
/**
@@ -68,8 +67,8 @@ function ActionsTable(props: IActionsTable): JSX.Element {
- {props.rows.map((row: RecentAction, idx: number) => (
-
+ {props.rows.map((row: RecentAction) => (
+
{headerKeys.map((key: string) => (
{key === "statusCode" ? (
diff --git a/frontend/src/components/BCHeader/index.tsx b/frontend/src/components/BCHeader/index.tsx
index c54f62ad..36a68854 100644
--- a/frontend/src/components/BCHeader/index.tsx
+++ b/frontend/src/components/BCHeader/index.tsx
@@ -1,5 +1,4 @@
import React from "react";
-import { Link } from "react-router-dom";
import { useThemePreference } from "../../utils/ThemePreference";
import { toggleTheme } from "../../utils/ThemeFunction";
import {
@@ -16,7 +15,7 @@ import {
SideNavItems,
HeaderSideNavItems,
} from '@carbon/react';
-import { NavLink } from "react-router-dom";
+import { NavLink , Link} from "react-router-dom";
import * as Icons from '@carbon/icons-react';
import './BCHeader.scss'
import { HeaderContainerProps } from "./definitions";
@@ -26,78 +25,76 @@ const BCHeader: React.FC = () => {
const { theme, setTheme } = useThemePreference();
return (
- <>
- (
-
-
-
-
- SILVA
-
-
- Link 1
- Link 2
- Link 3
-
- Sub-link 1
- Sub-link 2
- Sub-link 3
-
-
-
+ (
+
+
+
+
+ SILVA
+
+
+ Link 1
+ Link 2
+ Link 3
+
+ Sub-link 1
+ Sub-link 2
+ Sub-link 3
+
+
+
- {toggleTheme(theme,setTheme)}}
- >
- {/* Must have a child component */}
- <>{theme === 'g10'?:}>
-
+ {toggleTheme(theme,setTheme)}}
+ >
+ {/* Must have a child component */}
+ <>{theme === 'g10'?:}>
+
-
-
-
-
-
-
+
-
+ aria-label="Help"
+ >
+
+
+
+
+
+
-
-
-
-
- Link 1
- Link 2
- Link 3
-
- Sub-link 1
- Sub-link 2
- Sub-link 3
-
-
-
-
-
- )}
- />
- >
+
+
+
+
+ Link 1
+ Link 2
+ Link 3
+
+ Sub-link 1
+ Sub-link 2
+ Sub-link 3
+
+
+
+
+
+ )}
+ />
);
};
diff --git a/frontend/src/components/OpeningHistory/index.tsx b/frontend/src/components/OpeningHistory/index.tsx
index cad8b441..936968d4 100644
--- a/frontend/src/components/OpeningHistory/index.tsx
+++ b/frontend/src/components/OpeningHistory/index.tsx
@@ -1,3 +1,4 @@
+import React, { useState, useEffect } from "react";
import {
ProgressIndicator,
ProgressStep
@@ -7,31 +8,55 @@ import History from '../../types/History';
import statusClass from '../../utils/HistoryStatus';
import FavoriteButton from '../FavoriteButton';
import './styles.scss';
+import { useNotification } from '../../contexts/NotificationProvider';
+import { fetchOpeningTrends, deleteOpeningFavorite } from "../../services/OpeningFavoriteService";
-import { deleteOpeningFavorite } from '../../services/OpeningFavoriteService';
-interface OpeningHistoryProps {
- histories: History[];
-}
+const OpeningHistory: React.FC = () => {
+ const { displayNotification } = useNotification();
+ const [histories, setHistories] = useState([]);
-const handleFavoriteChange = async (newStatus: boolean, openingId: number) => {
- try {
- if(!newStatus){
- await deleteOpeningFavorite(openingId);
+ const loadTrends = async () => {
+ const history = await fetchOpeningTrends();
+ setHistories(history?.map(item => ({ id: item, steps: [] })) || []);
+ };
+
+ useEffect(() => { loadTrends(); },[]);
+
+
+ const handleFavoriteChange = async (newStatus: boolean, openingId: number) => {
+ try {
+ if(!newStatus){
+ await deleteOpeningFavorite(openingId);
+ displayNotification({
+ title: 'Favorite Removed',
+ subTitle: `Opening Id ${openingId} removed from favorites`,
+ type: 'success',
+ dismissIn: 8000,
+ onClose: () => {}
+ });
+ loadTrends();
+ }
+ } catch (error) {
+ displayNotification({
+ title: 'Error',
+ subTitle: `Failed to update favorite status for ${openingId}`,
+ type: 'error',
+ dismissIn: 8000,
+ onClose: () => {}
+ });
}
- } catch (error) {
- console.error(`Failed to update favorite status for ${openingId}`);
- }
-};
+ };
+
+ return (
-const OpeningHistory = ({ histories }: OpeningHistoryProps) => (
{histories.map((history, index) => (
-
+
);
+};
export default OpeningHistory;
diff --git a/frontend/src/components/OpeningMetricsTab/index.tsx b/frontend/src/components/OpeningMetricsTab/index.tsx
index 44282295..7325af4b 100644
--- a/frontend/src/components/OpeningMetricsTab/index.tsx
+++ b/frontend/src/components/OpeningMetricsTab/index.tsx
@@ -1,18 +1,15 @@
-import React, { useRef, useEffect, useState } from "react";
+import React, { useRef, useEffect } from "react";
import './styles.scss';
import SectionTitle from "../SectionTitle";
import BarChartGrouped from "../BarChartGrouped";
import ChartContainer from "../ChartContainer";
import DoughnutChartView from "../DoughnutChartView";
import OpeningHistory from "../OpeningHistory";
-import History from "../../types/History";
import MyRecentActions from "../MyRecentActions";
-import { fetchOpeningTrends } from "../../services/OpeningFavoriteService";
const OpeningMetricsTab: React.FC = () => {
const trackOpeningRef = useRef
(null);
- const [submissionTrends, setSubmissionTrends] = useState([]);
-
+
// Optional: Scroll to "Track Openings" when this component mounts
useEffect(() => {
@@ -23,13 +20,6 @@ const OpeningMetricsTab: React.FC = () => {
trackOpeningRef.current.scrollIntoView({ behavior: "smooth" });
}
- const loadTrends = async () => {
- const response = await fetchOpeningTrends();
- setSubmissionTrends(response.map(item => ({ id: item, steps: [] })));
- };
-
- loadTrends();
-
}, []);
return (
@@ -48,10 +38,8 @@ const OpeningMetricsTab: React.FC = () => {
{/* Add ref here to scroll */}
-
-
+
+
diff --git a/frontend/src/components/OpeningsTab/index.tsx b/frontend/src/components/OpeningsTab/index.tsx
index 6b71fff0..b72bff80 100644
--- a/frontend/src/components/OpeningsTab/index.tsx
+++ b/frontend/src/components/OpeningsTab/index.tsx
@@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react';
-import { Button } from '@carbon/react';
+import { Button, InlineNotification } from '@carbon/react';
import './styles.scss'
import { Location } from '@carbon/icons-react';
import OpeningsMap from '../OpeningsMap';
@@ -7,71 +7,53 @@ import OpeningScreenDataTable from '../OpeningScreenDataTable/index';
import { columns } from '../Dashboard/Opening/RecentOpeningsDataTable/testData';
import SectionTitle from '../SectionTitle';
import TableSkeleton from '../TableSkeleton';
-import { InlineNotification } from '@carbon/react';
import { RecentOpening } from '../../types/RecentOpening';
-import { useSelector } from 'react-redux';
-import { RootState } from '../../store';
import { generateHtmlFile } from './layersGenerator';
import { getWmsLayersWhitelistUsers, WmsLayersWhitelistUser } from '../../services/SecretsService';
-import { useUserRecentOpeningQuery } from '../../services/queries/search/openingQueries';
-import RecentOpeningsDataTable from '../Dashboard/Opening/RecentOpeningsDataTable';
-import { ITableHeader } from '../../types/TableHeader';
+import { useGetAuth } from '../../contexts/AuthProvider';
interface Props {
showSpatial: boolean;
- setShowSpatial: Function;
+ setShowSpatial: (show: boolean) => void;
}
const OpeningsTab: React.FC
= ({ showSpatial, setShowSpatial }) => {
const [loadId, setLoadId] = useState(null);
const [openingPolygonNotFound, setOpeningPolygonNotFound] = useState(false);
- const [wmsUsersWhitelist, setWmsUsersWhitelist] = useState([]);
- const userDetails = useSelector((state: RootState) => state.userDetails);
- const { data, isFetching } = useUserRecentOpeningQuery(10);
- const [headers, setHeaders] = useState(columns);
+ const [wmsUsersWhitelist, setWmsUsersWhitelist] = useState([]);
+ const { user } = useGetAuth();
-
+ useEffect(() => {
+ const fetchData = async () => {
+ try {
+ const rows: RecentOpening[] = await fetchRecentOpenings();
+ setOpeningRows(rows);
+ setLoading(false);
+ setError(null);
+ } catch (error) {
+ console.error('Error fetching recent openings:', error);
+ setLoading(false);
+ setError('Failed to fetch recent openings');
+ }
+ };
- useEffect(() => {}, [loadId, openingPolygonNotFound, wmsUsersWhitelist]);
+ const fetchAllowedPeople = async () => {
+ try {
+ const usersList: WmsLayersWhitelistUser[] = await getWmsLayersWhitelistUsers();
+ setWmsUsersWhitelist(usersList);
+ } catch (error) {
+ console.error('Error fetching recent openings:', error);
+ }
+ };
- const toggleSpatial = () => {
- setShowSpatial((prevShowSpatial :boolean) => !prevShowSpatial);
- };
+ fetchData();
+ fetchAllowedPeople();
+ }, []);
- const onClickFn = () => {
- const allowed: string[] = wmsUsersWhitelist.map((user: WmsLayersWhitelistUser) => user.userName);
- const { userName } = userDetails.user;
- if (allowed.includes(userName)) {
- const newWindow = window.open();
- if (newWindow) {
- newWindow.document.body.innerHTML = generateHtmlFile();
- }
- }
- };
+ useEffect(() => {}, [loadId, openingPolygonNotFound, wmsUsersWhitelist]);
- const handleCheckboxChange = (columnKey: string) => {
- if(columnKey === "select-default"){
- //set to the deafult
- setHeaders(columns)
- }
- else if(columnKey === "select-all"){
- setHeaders((prevHeaders) =>
- prevHeaders.map((header) => ({
- ...header,
- selected: true, // Select all headers
- }))
- );
- }
- else{
- setHeaders((prevHeaders) =>
- prevHeaders.map((header) =>
- header.key === columnKey
- ? { ...header, selected: !header.selected }
- : header
- )
- );
- }
-
+ const toggleSpatial = () => {
+ setShowSpatial(!showSpatial);
};
return (
@@ -81,7 +63,6 @@ const OpeningsTab: React.FC = ({ showSpatial, setShowSpatial }) => {