diff --git a/src/components/layouts/AppLayout.tsx b/src/components/layouts/AppLayout.tsx index e1124ad3..69402650 100644 --- a/src/components/layouts/AppLayout.tsx +++ b/src/components/layouts/AppLayout.tsx @@ -1,6 +1,6 @@ /******************************************************************************** - * Copyright (c) 2021,2022,2023 T-Systems International GmbH - * Copyright (c) 2021,2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022,2024 T-Systems International GmbH + * Copyright (c) 2022,2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -18,9 +18,8 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ import { Box } from '@mui/material'; -import { useEffect } from 'react'; -import { fetchUserPermissions } from '../../features/app/actions'; +import { useGetPermissionsQuery, useGetUseCasesQuery } from '../../features/app/apiSlice'; import { setLoggedInUser } from '../../features/app/slice'; import { useAppDispatch } from '../../features/store'; import Nav from '../Nav'; @@ -28,12 +27,11 @@ import Sidebar from '../sidebar'; // eslint-disable-next-line @typescript-eslint/no-explicit-any export default function AppLayout(props: any) { + useGetUseCasesQuery({}); + useGetPermissionsQuery({}); + const dispatch = useAppDispatch(); - useEffect(() => { - dispatch(fetchUserPermissions()); - dispatch(setLoggedInUser(props.loggedUser)); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + dispatch(setLoggedInUser(props.loggedUser)); return ( diff --git a/src/features/app/actions.ts b/src/features/app/actions.ts deleted file mode 100644 index 60102714..00000000 --- a/src/features/app/actions.ts +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2021,2022,2023 T-Systems International GmbH - * Copyright (c) 2022,2023 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -import { createAsyncThunk } from '@reduxjs/toolkit'; - -import AppService from '../../services/appService'; - -const fetchUserPermissions = createAsyncThunk('/user/permissions', async () => { - try { - const res = await AppService.getInstance().getUserPermissions(); - return res.data; - } catch (error) { - console.log('api call error:', error); - } -}); - -const fetchUseCases = createAsyncThunk('/usecases', async () => { - try { - const res = await AppService.getInstance().getUseCases(); - return res.data; - } catch (error) { - console.log('api call error:', error); - } -}); - -export { fetchUseCases, fetchUserPermissions }; diff --git a/src/features/app/apiSlice.ts b/src/features/app/apiSlice.ts index 2ca50e38..ebaa7663 100644 --- a/src/features/app/apiSlice.ts +++ b/src/features/app/apiSlice.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ /******************************************************************************** - * Copyright (c) 2021,2022,2023 T-Systems International GmbH - * Copyright (c) 2022,2023 Contributors to the Eclipse Foundation + * Copyright (c) 2022,2024 T-Systems International GmbH + * Copyright (c) 2022,2024 Contributors to the Eclipse Foundation * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. * @@ -21,7 +21,8 @@ import { BaseQueryFn, createApi, FetchArgs, fetchBaseQuery, FetchBaseQueryError import { apiBaseQuery } from '../../services/RequestService'; import { setSnackbarMessage } from '../notifiication/slice'; -import { IExtraOptions } from './types'; +import { setPageLoading, setPermissions, setUseCases } from './slice'; +import { IExtraOptions, UseCaseSelectionModel } from './types'; const baseQuery = fetchBaseQuery(apiBaseQuery()); const baseQueryInterceptor: BaseQueryFn = async ( @@ -54,6 +55,41 @@ const baseQueryInterceptor: BaseQueryFn ({}), + endpoints: builder => ({ + getUseCases: builder.query({ + query: () => { + return { + url: '/usecases', + }; + }, + async onQueryStarted(_, { dispatch, queryFulfilled }) { + try { + dispatch(setPageLoading(true)); + const data = UseCaseSelectionModel.create((await queryFulfilled).data); + dispatch(setUseCases(data)); + } finally { + dispatch(setPageLoading(false)); + } + }, + }), + getPermissions: builder.query({ + query: () => { + return { + url: '/user/role/permissions', + }; + }, + async onQueryStarted(_, { dispatch, queryFulfilled }) { + try { + dispatch(setPageLoading(true)); + const data = (await queryFulfilled).data; + dispatch(setPermissions(data)); + } finally { + dispatch(setPageLoading(false)); + } + }, + }), + }), tagTypes: ['UploadHistory', 'DeleteContract'], }); + +export const { useGetUseCasesQuery, useGetPermissionsQuery } = apiSlice; diff --git a/src/features/app/slice.ts b/src/features/app/slice.ts index a805641f..8a33818f 100644 --- a/src/features/app/slice.ts +++ b/src/features/app/slice.ts @@ -1,6 +1,6 @@ /******************************************************************************** - * Copyright (c) 2021,2022,2023 T-Systems International GmbH - * Copyright (c) 2022,2023 Contributors to the Eclipse Foundation + * Copyright (c) 2022,2024 T-Systems International GmbH + * Copyright (c) 2022,2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -19,8 +19,8 @@ ********************************************************************************/ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; +import { filter } from 'lodash'; -import { fetchUseCases, fetchUserPermissions } from './actions'; import { IAppSlice, IUser } from './types'; const initialState: IAppSlice = { @@ -53,27 +53,15 @@ export const appSlice = createSlice({ setSidebarExpanded: state => { state.sidebarExpanded = !state.sidebarExpanded; }, - setSelectedUseCases: (state, action: PayloadAction) => { - state.selectedUseCases = action.payload; + setUseCases: (state, { payload }) => { + state.useCases = payload; + state.selectedUseCases = filter(payload, 'checked').map(e => e.id); + }, + setPermissions: (state, { payload }) => { + state.permissions = payload; }, - }, - extraReducers: builder => { - builder.addCase(fetchUserPermissions.pending, state => { - state.pageLoading = true; - }); - builder.addCase(fetchUserPermissions.fulfilled, (state, action) => { - state.permissions = action.payload; - state.pageLoading = false; - }); - builder.addCase(fetchUseCases.pending, state => { - state.pageLoading = true; - }); - builder.addCase(fetchUseCases.fulfilled, (state, action) => { - state.useCases = action.payload; - state.pageLoading = false; - }); }, }); -export const { setPageLoading, setLoggedInUser, setSelectedUseCases, setSidebarExpanded } = appSlice.actions; +export const { setPageLoading, setLoggedInUser, setUseCases, setPermissions, setSidebarExpanded } = appSlice.actions; export default appSlice.reducer; diff --git a/src/features/app/types.ts b/src/features/app/types.ts index 2dd91ae5..8fd281f4 100644 --- a/src/features/app/types.ts +++ b/src/features/app/types.ts @@ -1,6 +1,6 @@ /******************************************************************************** - * Copyright (c) 2021,2022,2023 T-Systems International GmbH - * Copyright (c) 2022,2023 Contributors to the Eclipse Foundation + * Copyright (c) 2022,2024 T-Systems International GmbH + * Copyright (c) 2022,2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -41,9 +41,18 @@ export interface IAppSlice { export interface IUseCase { id: string; title: string; + checked?: boolean; } export interface IExtraOptions { showNotification?: boolean; message?: string; type?: IAlertColors; } + +export class UseCaseSelectionModel { + static create(useCase: IUseCase[]) { + return useCase.map(item => { + return { id: item.id, title: item.title, checked: false }; + }); + } +} diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index 8bb898a6..b065c1ca 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -1,6 +1,6 @@ /******************************************************************************** - * Copyright (c) 2021,2022,2023 T-Systems International GmbH - * Copyright (c) 2022,2023 Contributors to the Eclipse Foundation + * Copyright (c) 2022,2024 T-Systems International GmbH + * Copyright (c) 2022,2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -21,49 +21,41 @@ import '../styles/home.scss'; import ArrowForwardIcon from '@mui/icons-material/ArrowForward'; -import { Avatar, Box, FormControl, Grid, Stack } from '@mui/material'; -import { Button, Tab, TabPanel, Tabs, Typography } from 'cx-portal-shared-components'; -import { SyntheticEvent, useCallback, useEffect, useState } from 'react'; +import CheckCircleIcon from '@mui/icons-material/CheckCircle'; +import { Avatar, Box, FormControlLabel, Grid } from '@mui/material'; +import { Button, Checkbox, Tab, TabPanel, Tabs, Typography } from 'cx-portal-shared-components'; +import { SyntheticEvent, useCallback, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import legalNoticeContent from '../assets/about/legal-notice.json'; import { DataExchangeStepper } from '../components/DataExchangeStepper'; -import { fetchUseCases } from '../features/app/actions'; -import { setSelectedUseCases } from '../features/app/slice'; +import { setUseCases } from '../features/app/slice'; import { IUseCase } from '../features/app/types'; import { clearRows, setSelectedSubmodel } from '../features/provider/submodels/slice'; import { ISubmodelList } from '../features/provider/submodels/types'; import { removeSelectedFiles, setUploadStatus } from '../features/provider/upload/slice'; import { useAppDispatch, useAppSelector } from '../features/store'; import { consumeDataSteps, provideDataSteps } from '../models/Home'; +import { USER_GUIDE_URL } from '../utils/constants'; import { openInNewTab } from '../utils/utils'; export default function Home() { const [activeTab, setActiveTab] = useState(0); - const { loggedInUser, useCases, selectedUseCases } = useAppSelector(state => state.appSlice); + const { loggedInUser, useCases } = useAppSelector(state => state.appSlice); const dispatch = useAppDispatch(); const { t } = useTranslation(); - useEffect(() => { - dispatch(fetchUseCases()); - }, [dispatch]); - const handleUseCaseChange = useCallback( - (event: React.ChangeEvent) => { + (usecase: IUseCase) => { // Clearing all the ongoing uploads dispatch(setSelectedSubmodel({} as ISubmodelList)); dispatch(setUploadStatus(true)); dispatch(clearRows()); dispatch(removeSelectedFiles()); - const { value, checked } = event.target; - if (checked) { - dispatch(setSelectedUseCases([...selectedUseCases, value])); - } else { - dispatch(setSelectedUseCases(selectedUseCases.filter((e: string) => e !== value))); - } + const res = useCases.map(item => (item.id === usecase.id ? { ...item, checked: !item.checked } : item)); + dispatch(setUseCases(res)); }, - [dispatch, selectedUseCases], + [dispatch, useCases], ); const handleTabChange = (_event: SyntheticEvent, newValue: number) => { @@ -85,7 +77,7 @@ export default function Home() {