Loading capif_frontend/.env +1 −0 Original line number Diff line number Diff line Loading @@ -3,3 +3,4 @@ NEXT_PUBLIC_JWT_SECRET=dd5f3089-40c3-403d-af14-d0c228b05cb4 NEXT_PUBLIC_JWT_REFRESH_TOKEN_SECRET=7c4c1c50-3230-45bf-9eae-c9b2e401c767 NEXT_PUBLIC_API_BASE_URL="https://backoffice-api.mobilesandbox.cloud:38443" NEXT_PUBLIC_GRAFANA_BASE_URL="https://grafana.5gnacar.int" NODE_ENV=development capif_frontend/src/configs/apiService.js +49 −1 Original line number Diff line number Diff line Loading @@ -7,7 +7,6 @@ export const getInvokers = async () => { return axiosInstance.get(`/resources/invokers`) } // GET /resources/invokers?page=1&page_size=10 export const getInvokersPages = async ({ page, pageSize }) => { try { const response = await axiosInstance.get(`/resources/invokersPages`, { Loading Loading @@ -64,6 +63,22 @@ export const getProviders = async () => { return axiosInstance.get(`/resources/providers`) } export const getProvidersPages = async ({ page, pageSize }) => { try { const response = await axiosInstance.get(`/resources/providersPages`, { params: { page: page, pageSize: pageSize //searchTerm: searchTerm } }); return response.data; } catch (error) { throw new Error(`Error fetching providers: ${error.message}`); } } export const getNumProviders = async () => { return axiosInstance.get(`/resources/numProviders`) } Loading @@ -73,6 +88,7 @@ export const getProviderServices = async providerId => { } export const deleteProvider = async providerId => { console.log("providerId: ", providerId) return axiosInstance.delete(`/providers/${providerId}`) } Loading @@ -89,11 +105,43 @@ export const getNumApis = async () => { return axiosInstance.get(`/apis/num`) } export const getApisPages = async ({ page, pageSize }) => { try { const response = await axiosInstance.get(`/apisPages`, { params: { page: page, pageSize: pageSize //searchTerm: searchTerm } }); return response.data; } catch (error) { throw new Error(`Error fetching apis: ${error.message}`); } } // USERS export const getUsers = async id => { return axiosInstance.get(`/users`) } export const getUsersPages = async ({ page, pageSize }) => { try { const response = await axiosInstance.get(`/resources/usersPagesRetrieve`, { params: { page: page, pageSize: pageSize //searchTerm: searchTerm } }); return response.data; } catch (error) { throw new Error(`Error fetching users: ${error.message}`); } } export const getUser = async name => { return axiosInstance.get(`/resources/users/${name}`) } Loading capif_frontend/src/context/AuthContext.js +4 −4 Original line number Diff line number Diff line Loading @@ -49,16 +49,16 @@ const AuthProvider = ({ children }) => { // useEffect -> hook de react que se ejecuta cuando el componente se monta, 1 VEZ useEffect(() => { const initAuth = async () => { console.log('Entró por initAuth') //console.log('Entró por initAuth') const storedAccessToken = getAccessToken() // obtiene el token de acceso almacenado en las cookies console.log('storedAccessToken: ', storedAccessToken) console.log('authConfig.meEndpoint: ', authConfig.meEndpoint) //console.log('storedAccessToken: ', storedAccessToken) //console.log('authConfig.meEndpoint: ', authConfig.meEndpoint) if (storedAccessToken) { // la primera vez que se ejecute no entrará por aquí logicamente pues no hay token de acceso aún setLoading(true) try { console.log("Entró por donde el token existe") //console.log("Entró por donde el token existe") // auth/me -> se le envía el token de acceso y devuelve 200 si es válido o 401 si no lo es const response = await axiosInstance.get(authConfig.meEndpoint, { // https://10.95.82.71:8085/auth/me + Authorization: Bearer token Loading capif_frontend/src/pages/apis/index.js +98 −30 Original line number Diff line number Diff line Loading @@ -16,11 +16,15 @@ import TableCell from '@mui/material/TableCell'; import TableContainer from '@mui/material/TableContainer'; import CircularProgress from '@mui/material/CircularProgress'; import Button from '@mui/material/Button'; import { getApis, getNumApis } from 'src/configs/apiService'; import { getNumApis, getApisPages } from 'src/configs/apiService'; import { useState } from 'react' import { Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material' import TextField from '@mui/material/TextField'; import { deleteProviderService } from 'src/configs/apiService'; import Pagination from '@mui/material/Pagination'; import Select from '@mui/material/Select'; import MenuItem from '@mui/material/MenuItem'; import { useEffect } from 'react'; const LinkStyled = styled(Link)(({ theme }) => ({ textDecoration: 'none', Loading @@ -33,24 +37,56 @@ const Apis = () => { const [isDeleteDialogOpen, setDeleteDialogOpen] = useState(false); const [searchTerm, setSearchTerm] = useState(''); // Define la clave única para esta consulta const queryKey = ['apis']; const [currentPage, setCurrentPage] = useState(1); const [pageSize, setPageSize] = useState(10); // Número de invocadores por página const [totalPages, setTotalPages] = useState(0); const [totalApis, setTotalApis] = useState(0); const [apis, setApis] = useState([]); // Usa useQuery para obtener los datos const { data: apisData, isLoading, isError, refetch } = useQuery({ queryKey, queryFn: getApis, }); // APIS DATA const queryKeyApis = ['apis']; // Definir la clave única para esta consulta const queryKeyNum = ['apisNum'] console.log("entra por aquí") // Utilizar useQuery para obtener los datos const { data: apisNum, isLoadingNum, isErrorNum } = useQuery({ queryKeyNum, queryFn: getNumApis, const { data: apisDataPages, isLoadingApisData, isErrorApisData, refetchApis } = useQuery({ queryKey: queryKeyApis, queryFn: () => getApisPages({ page: currentPage, pageSize }), refetchOnWindowFocus: false, refetchOnMount: false, }); console.log("2 Imprime apisDataPages", apisDataPages) useEffect(() => { // Solo establece los invocadores cuando ApisData cambie console.log("3 dentro del useEffect1 Imprime apisDataPages", apisDataPages) if (apisDataPages) { setApis(apisDataPages.data); console.log("4 Imprime apisDataPages.data dentro del if", apisDataPages.data) } }, [apisDataPages]); useEffect(() => { // Lógica para refrescar los datos aquí const fetchData = async () => { try { const response = await getApisPages({ page: currentPage, pageSize }); setApis(response.data); setTotalApis(response.total); console.log('Total apis:', response.total); setTotalPages(Math.ceil(response.total / pageSize)); } catch (error) { console.error('Error fetching apis:', error.message); } }; fetchData(); // Llama a la función fetchData directamente cuando cambien las dependencias }, [currentPage, pageSize]); console.log('5 apis, no debería existir hasta refrescar la página: ', apis) const handleDeleteClick = (apf_id, api_id) => { setSelectedApi({ apf_id, api_id }) setDeleteDialogOpen(true) Loading @@ -77,11 +113,24 @@ const Apis = () => { setSelectedApi(null) } const handlePageChange = (newPage) => { setCurrentPage(newPage); }; const handlePageSizeChange = (event) => { const newSize = event.target.value; setPageSize(newSize); // Recalcular el número total de páginas cuando cambia el tamaño de la página const newTotalPages = Math.ceil(totalApis / newSize); setTotalPages(newTotalPages); // Asegurarse de que la página actual sea válida después de cambiar el tamaño de la página setCurrentPage(1); }; return ( <Grid container spacing={6}> <Grid item xs={8}> <PageHeader title={<Typography variant='h5'>APIs: {apisNum?.data}</Typography>} /> <PageHeader title={<Typography variant='h5'>Apis: {totalApis}</Typography>} /> </Grid> {/* Grid con el campo de búsqueda en la segunda columna */} Loading @@ -103,20 +152,16 @@ const Apis = () => { <Grid item xs={12}> <Card> <CardHeader title='List of APIs' /> <CardHeader title='List of Apis' /> <TableContainer component={Paper}> <Table sx={{ minWidth: 650 }} aria-label='APIs table'> {isLoading ? ( <Table sx={{ minWidth: 650 }} aria-label='Apis table'> {isLoadingApisData ? ( <CircularProgress /> ) : isError ? ( ) : isErrorApisData ? ( <Typography variant='body1' sx={{ paddingLeft: 4, paddingBottom: 2 }}> Error loading data. </Typography> ) : !apisData || apisData.length === 0 ? ( <Typography variant='body1' sx={{ paddingLeft: 4, paddingBottom: 2 }}> There are no apis yet. </Typography> ) : ( ) : apisDataPages?.data && apisDataPages.data.length > 0 ? ( <> <TableHead> <TableRow> Loading @@ -127,9 +172,9 @@ const Apis = () => { </TableRow> </TableHead> <TableBody> {apisData.data.object.map((api) => ( {apis.map((api) => ( <TableRow key={api.username} key={api.api_id} sx={{ '&:last-of-type td, &:last-of-type th': { border: 0, Loading @@ -155,17 +200,40 @@ const Apis = () => { ))} </TableBody> </> ) : ( <Typography variant='body1' sx={{ paddingLeft: 4, paddingBottom: 2 }}> There are no apis yet. </Typography> )} </Table> </TableContainer> </Card> </Grid> <Grid item xs={12}> <Grid container spacing={3} alignItems="center" justifyContent="space-between"> <Grid item> <Pagination count={totalPages} page={currentPage} onChange={(event, value) => handlePageChange(value)} /> </Grid> <Grid item> <Select value={pageSize} onChange={handlePageSizeChange}> <MenuItem value={10}>10 per page</MenuItem> <MenuItem value={20}>20 per page</MenuItem> <MenuItem value={30}>30 per page</MenuItem> </Select> </Grid> </Grid> </Grid> {/* Confirmación de eliminación */} <Dialog open={isDeleteDialogOpen} onClose={handleDeleteCancel}> <DialogTitle>Confirm Deletion</DialogTitle> <DialogContent> Are you sure you want to delete the provider? Are you sure you want to delete the API? </DialogContent> <DialogActions> <Button onClick={handleDeleteCancel}>Cancel</Button> Loading capif_frontend/src/pages/home-dashboards/index.js +7 −7 Original line number Diff line number Diff line Loading @@ -76,10 +76,10 @@ const Homedash = () => { }); // APIS DATA const queryKeyApis= ['apis']; const queryKeyApisDataHD= ['apisDataHD']; const { data: apisData, isLoadingApis, isErrorApis, refetchApis } = useQuery({ queryKey: queryKeyApis, const { data: apisDataHD, isLoadingApisDataHD, isErrorApisDataHD, refetchApisDataHD } = useQuery({ queryKey: queryKeyApisDataHD, queryFn: getApis, }); Loading Loading @@ -256,11 +256,11 @@ const Homedash = () => { <CardContent style={{ textAlign: 'center' }}> <Typography variant='h5'>APIs:</Typography> <Typography variant='h4' sx={{ marginBottom: 6 }}>{apisNum?.data}</Typography> {!apisData?.data && <CircularProgress />} {apisData?.data && ( {!apisDataHD?.data && <CircularProgress />} {apisDataHD?.data && ( <> <List> {apisData.data.object.slice(-5).map((api) => ( {apisDataHD.data.object.slice(-5).map((api) => ( <ListItem key={api.api_id}> <ListItemText primary={ Loading @@ -275,7 +275,7 @@ const Homedash = () => { </List> <Box textAlign='center' mt={3}> <Typography variant='body2' sx={{ textDecoration: 'underline' }}> Click here to see more users. Click here to see more APIs. </Typography> </Box> </> Loading Loading
capif_frontend/.env +1 −0 Original line number Diff line number Diff line Loading @@ -3,3 +3,4 @@ NEXT_PUBLIC_JWT_SECRET=dd5f3089-40c3-403d-af14-d0c228b05cb4 NEXT_PUBLIC_JWT_REFRESH_TOKEN_SECRET=7c4c1c50-3230-45bf-9eae-c9b2e401c767 NEXT_PUBLIC_API_BASE_URL="https://backoffice-api.mobilesandbox.cloud:38443" NEXT_PUBLIC_GRAFANA_BASE_URL="https://grafana.5gnacar.int" NODE_ENV=development
capif_frontend/src/configs/apiService.js +49 −1 Original line number Diff line number Diff line Loading @@ -7,7 +7,6 @@ export const getInvokers = async () => { return axiosInstance.get(`/resources/invokers`) } // GET /resources/invokers?page=1&page_size=10 export const getInvokersPages = async ({ page, pageSize }) => { try { const response = await axiosInstance.get(`/resources/invokersPages`, { Loading Loading @@ -64,6 +63,22 @@ export const getProviders = async () => { return axiosInstance.get(`/resources/providers`) } export const getProvidersPages = async ({ page, pageSize }) => { try { const response = await axiosInstance.get(`/resources/providersPages`, { params: { page: page, pageSize: pageSize //searchTerm: searchTerm } }); return response.data; } catch (error) { throw new Error(`Error fetching providers: ${error.message}`); } } export const getNumProviders = async () => { return axiosInstance.get(`/resources/numProviders`) } Loading @@ -73,6 +88,7 @@ export const getProviderServices = async providerId => { } export const deleteProvider = async providerId => { console.log("providerId: ", providerId) return axiosInstance.delete(`/providers/${providerId}`) } Loading @@ -89,11 +105,43 @@ export const getNumApis = async () => { return axiosInstance.get(`/apis/num`) } export const getApisPages = async ({ page, pageSize }) => { try { const response = await axiosInstance.get(`/apisPages`, { params: { page: page, pageSize: pageSize //searchTerm: searchTerm } }); return response.data; } catch (error) { throw new Error(`Error fetching apis: ${error.message}`); } } // USERS export const getUsers = async id => { return axiosInstance.get(`/users`) } export const getUsersPages = async ({ page, pageSize }) => { try { const response = await axiosInstance.get(`/resources/usersPagesRetrieve`, { params: { page: page, pageSize: pageSize //searchTerm: searchTerm } }); return response.data; } catch (error) { throw new Error(`Error fetching users: ${error.message}`); } } export const getUser = async name => { return axiosInstance.get(`/resources/users/${name}`) } Loading
capif_frontend/src/context/AuthContext.js +4 −4 Original line number Diff line number Diff line Loading @@ -49,16 +49,16 @@ const AuthProvider = ({ children }) => { // useEffect -> hook de react que se ejecuta cuando el componente se monta, 1 VEZ useEffect(() => { const initAuth = async () => { console.log('Entró por initAuth') //console.log('Entró por initAuth') const storedAccessToken = getAccessToken() // obtiene el token de acceso almacenado en las cookies console.log('storedAccessToken: ', storedAccessToken) console.log('authConfig.meEndpoint: ', authConfig.meEndpoint) //console.log('storedAccessToken: ', storedAccessToken) //console.log('authConfig.meEndpoint: ', authConfig.meEndpoint) if (storedAccessToken) { // la primera vez que se ejecute no entrará por aquí logicamente pues no hay token de acceso aún setLoading(true) try { console.log("Entró por donde el token existe") //console.log("Entró por donde el token existe") // auth/me -> se le envía el token de acceso y devuelve 200 si es válido o 401 si no lo es const response = await axiosInstance.get(authConfig.meEndpoint, { // https://10.95.82.71:8085/auth/me + Authorization: Bearer token Loading
capif_frontend/src/pages/apis/index.js +98 −30 Original line number Diff line number Diff line Loading @@ -16,11 +16,15 @@ import TableCell from '@mui/material/TableCell'; import TableContainer from '@mui/material/TableContainer'; import CircularProgress from '@mui/material/CircularProgress'; import Button from '@mui/material/Button'; import { getApis, getNumApis } from 'src/configs/apiService'; import { getNumApis, getApisPages } from 'src/configs/apiService'; import { useState } from 'react' import { Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material' import TextField from '@mui/material/TextField'; import { deleteProviderService } from 'src/configs/apiService'; import Pagination from '@mui/material/Pagination'; import Select from '@mui/material/Select'; import MenuItem from '@mui/material/MenuItem'; import { useEffect } from 'react'; const LinkStyled = styled(Link)(({ theme }) => ({ textDecoration: 'none', Loading @@ -33,24 +37,56 @@ const Apis = () => { const [isDeleteDialogOpen, setDeleteDialogOpen] = useState(false); const [searchTerm, setSearchTerm] = useState(''); // Define la clave única para esta consulta const queryKey = ['apis']; const [currentPage, setCurrentPage] = useState(1); const [pageSize, setPageSize] = useState(10); // Número de invocadores por página const [totalPages, setTotalPages] = useState(0); const [totalApis, setTotalApis] = useState(0); const [apis, setApis] = useState([]); // Usa useQuery para obtener los datos const { data: apisData, isLoading, isError, refetch } = useQuery({ queryKey, queryFn: getApis, }); // APIS DATA const queryKeyApis = ['apis']; // Definir la clave única para esta consulta const queryKeyNum = ['apisNum'] console.log("entra por aquí") // Utilizar useQuery para obtener los datos const { data: apisNum, isLoadingNum, isErrorNum } = useQuery({ queryKeyNum, queryFn: getNumApis, const { data: apisDataPages, isLoadingApisData, isErrorApisData, refetchApis } = useQuery({ queryKey: queryKeyApis, queryFn: () => getApisPages({ page: currentPage, pageSize }), refetchOnWindowFocus: false, refetchOnMount: false, }); console.log("2 Imprime apisDataPages", apisDataPages) useEffect(() => { // Solo establece los invocadores cuando ApisData cambie console.log("3 dentro del useEffect1 Imprime apisDataPages", apisDataPages) if (apisDataPages) { setApis(apisDataPages.data); console.log("4 Imprime apisDataPages.data dentro del if", apisDataPages.data) } }, [apisDataPages]); useEffect(() => { // Lógica para refrescar los datos aquí const fetchData = async () => { try { const response = await getApisPages({ page: currentPage, pageSize }); setApis(response.data); setTotalApis(response.total); console.log('Total apis:', response.total); setTotalPages(Math.ceil(response.total / pageSize)); } catch (error) { console.error('Error fetching apis:', error.message); } }; fetchData(); // Llama a la función fetchData directamente cuando cambien las dependencias }, [currentPage, pageSize]); console.log('5 apis, no debería existir hasta refrescar la página: ', apis) const handleDeleteClick = (apf_id, api_id) => { setSelectedApi({ apf_id, api_id }) setDeleteDialogOpen(true) Loading @@ -77,11 +113,24 @@ const Apis = () => { setSelectedApi(null) } const handlePageChange = (newPage) => { setCurrentPage(newPage); }; const handlePageSizeChange = (event) => { const newSize = event.target.value; setPageSize(newSize); // Recalcular el número total de páginas cuando cambia el tamaño de la página const newTotalPages = Math.ceil(totalApis / newSize); setTotalPages(newTotalPages); // Asegurarse de que la página actual sea válida después de cambiar el tamaño de la página setCurrentPage(1); }; return ( <Grid container spacing={6}> <Grid item xs={8}> <PageHeader title={<Typography variant='h5'>APIs: {apisNum?.data}</Typography>} /> <PageHeader title={<Typography variant='h5'>Apis: {totalApis}</Typography>} /> </Grid> {/* Grid con el campo de búsqueda en la segunda columna */} Loading @@ -103,20 +152,16 @@ const Apis = () => { <Grid item xs={12}> <Card> <CardHeader title='List of APIs' /> <CardHeader title='List of Apis' /> <TableContainer component={Paper}> <Table sx={{ minWidth: 650 }} aria-label='APIs table'> {isLoading ? ( <Table sx={{ minWidth: 650 }} aria-label='Apis table'> {isLoadingApisData ? ( <CircularProgress /> ) : isError ? ( ) : isErrorApisData ? ( <Typography variant='body1' sx={{ paddingLeft: 4, paddingBottom: 2 }}> Error loading data. </Typography> ) : !apisData || apisData.length === 0 ? ( <Typography variant='body1' sx={{ paddingLeft: 4, paddingBottom: 2 }}> There are no apis yet. </Typography> ) : ( ) : apisDataPages?.data && apisDataPages.data.length > 0 ? ( <> <TableHead> <TableRow> Loading @@ -127,9 +172,9 @@ const Apis = () => { </TableRow> </TableHead> <TableBody> {apisData.data.object.map((api) => ( {apis.map((api) => ( <TableRow key={api.username} key={api.api_id} sx={{ '&:last-of-type td, &:last-of-type th': { border: 0, Loading @@ -155,17 +200,40 @@ const Apis = () => { ))} </TableBody> </> ) : ( <Typography variant='body1' sx={{ paddingLeft: 4, paddingBottom: 2 }}> There are no apis yet. </Typography> )} </Table> </TableContainer> </Card> </Grid> <Grid item xs={12}> <Grid container spacing={3} alignItems="center" justifyContent="space-between"> <Grid item> <Pagination count={totalPages} page={currentPage} onChange={(event, value) => handlePageChange(value)} /> </Grid> <Grid item> <Select value={pageSize} onChange={handlePageSizeChange}> <MenuItem value={10}>10 per page</MenuItem> <MenuItem value={20}>20 per page</MenuItem> <MenuItem value={30}>30 per page</MenuItem> </Select> </Grid> </Grid> </Grid> {/* Confirmación de eliminación */} <Dialog open={isDeleteDialogOpen} onClose={handleDeleteCancel}> <DialogTitle>Confirm Deletion</DialogTitle> <DialogContent> Are you sure you want to delete the provider? Are you sure you want to delete the API? </DialogContent> <DialogActions> <Button onClick={handleDeleteCancel}>Cancel</Button> Loading
capif_frontend/src/pages/home-dashboards/index.js +7 −7 Original line number Diff line number Diff line Loading @@ -76,10 +76,10 @@ const Homedash = () => { }); // APIS DATA const queryKeyApis= ['apis']; const queryKeyApisDataHD= ['apisDataHD']; const { data: apisData, isLoadingApis, isErrorApis, refetchApis } = useQuery({ queryKey: queryKeyApis, const { data: apisDataHD, isLoadingApisDataHD, isErrorApisDataHD, refetchApisDataHD } = useQuery({ queryKey: queryKeyApisDataHD, queryFn: getApis, }); Loading Loading @@ -256,11 +256,11 @@ const Homedash = () => { <CardContent style={{ textAlign: 'center' }}> <Typography variant='h5'>APIs:</Typography> <Typography variant='h4' sx={{ marginBottom: 6 }}>{apisNum?.data}</Typography> {!apisData?.data && <CircularProgress />} {apisData?.data && ( {!apisDataHD?.data && <CircularProgress />} {apisDataHD?.data && ( <> <List> {apisData.data.object.slice(-5).map((api) => ( {apisDataHD.data.object.slice(-5).map((api) => ( <ListItem key={api.api_id}> <ListItemText primary={ Loading @@ -275,7 +275,7 @@ const Homedash = () => { </List> <Box textAlign='center' mt={3}> <Typography variant='body2' sx={{ textDecoration: 'underline' }}> Click here to see more users. Click here to see more APIs. </Typography> </Box> </> Loading