Loading capif_frontend/src/configs/apiService.js +32 −0 Original line number Diff line number Diff line Loading @@ -192,3 +192,35 @@ export const searchProviders = async (searchTerm, page, pageSize) => { throw new Error(`Error searching providers: ${error.message}`); } }; export const searchApis = async (searchTerm, page, pageSize) => { try { const response = await axiosInstance.get(`/apis/search`, { params: { page: page, pageSize: pageSize, searchTerm: searchTerm } }); return response.data; } catch (error) { throw new Error(`Error searching apis: ${error.message}`); } }; export const searchUsers = async (searchTerm, page, pageSize) => { try { const response = await axiosInstance.get(`/users/search`, { params: { page: page, pageSize: pageSize, searchTerm: searchTerm } }); return response.data; } catch (error) { throw new Error(`Error searching users: ${error.message}`); } }; capif_frontend/src/pages/apis/index.js +110 −43 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ 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 { getNumApis, getApisPages } from 'src/configs/apiService'; import { getApisPages, searchApis } from 'src/configs/apiService'; import { useState } from 'react' import { Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material' import TextField from '@mui/material/TextField'; Loading Loading @@ -49,6 +49,11 @@ const Apis = () => { const [showDeleteMessage, setShowDeleteMessage] = useState(false); const [errorDeleting, setErrorDeleting] = useState(false); // Estados para la búsqueda const [searchResults, setSearchResults] = useState([]); const [totalSearchResults, setTotalSearchResults] = useState(0); const [errorSearching, setErrorSearching] = useState(0); // ApiS DATA const queryKeyApis = ['apis']; Loading Loading @@ -150,40 +155,100 @@ const Apis = () => { setCurrentPage(1); }; const handleSearch = async () => { try { setErrorSearching(false); // Realizar la búsqueda en el backend const searchData = await searchApis(searchTerm, currentPage, pageSize); // Actualizar el estado con los resultados de la búsqueda y la información de paginación setSearchResults(searchData.data); setTotalPages(1) setCurrentPage(1) } catch (error) { console.error('Error searching apis:', error.message); setErrorSearching(true); } }; return ( <Grid container spacing={3}> <Grid item xs={12}> {/* Agregar controles de búsqueda aquí si es necesario */} </Grid> <Grid item xs={8}> <PageHeader title={<Typography variant='h5'>Apis: {totalApis}</Typography>} /> <Grid container spacing={3}> <Grid item xs={4}> <Button onClick={() => window.location.reload()} style={{ textTransform: 'none' }}> <PageHeader title={<Typography variant='h5'>APIs: {totalApis}</Typography>} /> </Button> </Grid> {/* Grid con el campo de búsqueda en la segunda columna */} <Grid item xs={4}> <Grid container spacing={2}> {/* Agregar un campo de búsqueda */} <Grid item xs={12}> <Grid item xs={8}> <Grid container spacing={2} alignItems="center" justifyContent="flex-end"> <Grid item> <TextField label="Search by ..." variant="outlined" //value={searchTerm} value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)} /> </Grid> {/* Otros elementos adicionales en la segunda columna, si es necesario */} <Grid item> <Button variant="contained" color="primary" onClick={() => handleSearch(searchTerm)}> Search </Button> </Grid> </Grid> </Grid> </Grid> </Grid> <Grid item xs={12}> <Card> <CardHeader title='List of Apis' /> <CardHeader title='List of APIs' /> {searchResults.length > 0 ? ( <TableContainer component={Paper}> <Table sx={{ minWidth: 650 }} aria-label='Apis table'> {isLoadingApisData ? ( <Table sx={{ minWidth: 650 }} aria-label='APIs table'> <TableHead> <TableRow> <TableCell>API name</TableCell> <TableCell>Description</TableCell> <TableCell>AEF</TableCell> <TableCell>Delete API</TableCell> </TableRow> </TableHead> <TableBody> {searchResults.map((api) => ( <TableRow key={api.api_id} sx={{ '&:last-of-type td, &:last-of-type th': { border: 0, }, }} > <TableCell component='th' scope='row'> <LinkStyled href={`/apis/${api.api_name}`}> {api.api_name} </LinkStyled> </TableCell> <TableCell>{api.description}</TableCell> <TableCell>{api.aef_profiles[0].aef_id}</TableCell> <TableCell> <Button variant='contained' onClick={() => handleDeleteClick(api.apf_id, api.api_id)} > Delete </Button> </TableCell> </TableRow> ))} </TableBody> </Table> </TableContainer> ) : isLoadingApisData ? ( <CircularProgress /> ) : isErrorApisData ? ( <Typography variant='body1' sx={{ paddingLeft: 4, paddingBottom: 2 }}> Loading @@ -191,6 +256,8 @@ const Apis = () => { </Typography> ) : apisDataPages?.data && apisDataPages.data.length > 0 ? ( <> <TableContainer component={Paper}> <Table sx={{ minWidth: 650 }} aria-label='APIs table'> <TableHead> <TableRow> <TableCell>API name</TableCell> Loading Loading @@ -227,18 +294,19 @@ const Apis = () => { </TableRow> ))} </TableBody> </Table> </TableContainer> </> ) : ( <Typography variant='body1' sx={{ paddingLeft: 4, paddingBottom: 2 }}> There are no apis yet. 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> Loading @@ -258,7 +326,6 @@ const Apis = () => { </Grid> </Grid> <Dialog open={isDeleteDialogOpen} onClose={handleDeleteCancel}> <DialogTitle>Confirm Deletion</DialogTitle> <DialogContent> Loading capif_frontend/src/pages/users/index.js +136 −72 Original line number Diff line number Diff line Loading @@ -17,7 +17,7 @@ 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 { deleteUser, getNumUsers1, getUsersPages } from 'src/configs/apiService'; import { deleteUser, getNumUsers1, getUsersPages, searchUsers } from 'src/configs/apiService'; import { Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material' import TextField from '@mui/material/TextField'; import Pagination from '@mui/material/Pagination'; Loading Loading @@ -48,6 +48,11 @@ const Users = () => { const [showDeleteMessage, setShowDeleteMessage] = useState(false); const [errorDeleting, setErrorDeleting] = useState(false); // Estados para la búsqueda const [searchResults, setSearchResults] = useState([]); const [totalSearchResults, setTotalSearchResults] = useState(0); const [errorSearching, setErrorSearching] = useState(0); // USERS DATA const queryKeyUsers = ['users']; Loading Loading @@ -150,39 +155,100 @@ const Users = () => { setCurrentPage(1); }; const handleSearch = async () => { try { setErrorSearching(false); // Realizar la búsqueda en el backend const searchData = await searchUsers(searchTerm, currentPage, pageSize); // Actualizar el estado con los resultados de la búsqueda y la información de paginación setSearchResults(searchData.data); setTotalPages(1) setCurrentPage(1) } catch (error) { console.error('Error searching invokers:', error.message); setErrorSearching(true); } }; return ( <Grid container spacing={3}> <Grid item xs={12}> {/* Agregar controles de búsqueda aquí si es necesario */} </Grid> <Grid item xs={8}> <Grid container spacing={3}> <Grid item xs={4}> <Button onClick={() => window.location.reload()} style={{ textTransform: 'none' }}> <PageHeader title={<Typography variant='h5'>Users: {totalUsers}</Typography>} /> </Button> </Grid> {/* Grid con el campo de búsqueda en la segunda columna */} <Grid item xs={4}> <Grid container spacing={2}> {/* Agregar un campo de búsqueda */} <Grid item xs={12}> <Grid item xs={8}> <Grid container spacing={2} alignItems="center" justifyContent="flex-end"> <Grid item> <TextField label="Search by ..." variant="outlined" //value={searchTerm} value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)} /> </Grid> {/* Otros elementos adicionales en la segunda columna, si es necesario */} <Grid item> <Button variant="contained" color="primary" onClick={() => handleSearch(searchTerm)}> Search </Button> </Grid> </Grid> </Grid> </Grid> </Grid> <Grid item xs={12}> <Card> <CardHeader title='List of Users' /> {searchResults.length > 0 ? ( <TableContainer component={Paper}> <Table sx={{ minWidth: 650 }} aria-label='Users table'> {isLoadingUsersData ? ( <TableHead> <TableRow> <TableCell>ID</TableCell> <TableCell>Info</TableCell> <TableCell>User name</TableCell> <TableCell>Actions</TableCell> </TableRow> </TableHead> <TableBody> {searchResults.map((user) => ( <TableRow key={user.username} sx={{ '&:last-of-type td, &:last-of-type th': { border: 0, }, }} > <TableCell component='th' scope='row'> <LinkStyled href={`/users/${user.username}`}> {user.username} </LinkStyled> </TableCell> <TableCell>{user.role}</TableCell> <TableCell>{user.description}</TableCell> <TableCell> <Button variant='contained' onClick={() => handleDeleteClick(user.username, user.password)} > Delete </Button> </TableCell> </TableRow> ))} </TableBody> </Table> </TableContainer> ) : isLoadingUsersData ? ( <CircularProgress /> ) : isErrorUsersData ? ( <Typography variant='body1' sx={{ paddingLeft: 4, paddingBottom: 2 }}> Loading @@ -190,12 +256,14 @@ const Users = () => { </Typography> ) : usersDataPages?.data && usersDataPages.data.length > 0 ? ( <> <TableContainer component={Paper}> <Table sx={{ minWidth: 650 }} aria-label='Invokers table'> <TableHead> <TableRow> <TableCell>Users name</TableCell> <TableCell>Role</TableCell> <TableCell>Users info</TableCell> <TableCell>Delete user</TableCell> <TableCell>ID</TableCell> <TableCell>Info</TableCell> <TableCell>User name</TableCell> <TableCell>Actions</TableCell> </TableRow> </TableHead> <TableBody> Loading Loading @@ -226,21 +294,17 @@ const Users = () => { </TableRow> ))} </TableBody> </Table> </TableContainer> </> ) : ( <Typography variant='body1' sx={{ paddingLeft: 4, paddingBottom: 2 }}> There are no users yet. </Typography> )} </Table> </TableContainer> </Card> </Grid> <Grid item xs={12}> <Grid container spacing={3} alignItems="center" justifyContent="space-between"> <Grid item> Loading Loading
capif_frontend/src/configs/apiService.js +32 −0 Original line number Diff line number Diff line Loading @@ -192,3 +192,35 @@ export const searchProviders = async (searchTerm, page, pageSize) => { throw new Error(`Error searching providers: ${error.message}`); } }; export const searchApis = async (searchTerm, page, pageSize) => { try { const response = await axiosInstance.get(`/apis/search`, { params: { page: page, pageSize: pageSize, searchTerm: searchTerm } }); return response.data; } catch (error) { throw new Error(`Error searching apis: ${error.message}`); } }; export const searchUsers = async (searchTerm, page, pageSize) => { try { const response = await axiosInstance.get(`/users/search`, { params: { page: page, pageSize: pageSize, searchTerm: searchTerm } }); return response.data; } catch (error) { throw new Error(`Error searching users: ${error.message}`); } };
capif_frontend/src/pages/apis/index.js +110 −43 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ 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 { getNumApis, getApisPages } from 'src/configs/apiService'; import { getApisPages, searchApis } from 'src/configs/apiService'; import { useState } from 'react' import { Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material' import TextField from '@mui/material/TextField'; Loading Loading @@ -49,6 +49,11 @@ const Apis = () => { const [showDeleteMessage, setShowDeleteMessage] = useState(false); const [errorDeleting, setErrorDeleting] = useState(false); // Estados para la búsqueda const [searchResults, setSearchResults] = useState([]); const [totalSearchResults, setTotalSearchResults] = useState(0); const [errorSearching, setErrorSearching] = useState(0); // ApiS DATA const queryKeyApis = ['apis']; Loading Loading @@ -150,40 +155,100 @@ const Apis = () => { setCurrentPage(1); }; const handleSearch = async () => { try { setErrorSearching(false); // Realizar la búsqueda en el backend const searchData = await searchApis(searchTerm, currentPage, pageSize); // Actualizar el estado con los resultados de la búsqueda y la información de paginación setSearchResults(searchData.data); setTotalPages(1) setCurrentPage(1) } catch (error) { console.error('Error searching apis:', error.message); setErrorSearching(true); } }; return ( <Grid container spacing={3}> <Grid item xs={12}> {/* Agregar controles de búsqueda aquí si es necesario */} </Grid> <Grid item xs={8}> <PageHeader title={<Typography variant='h5'>Apis: {totalApis}</Typography>} /> <Grid container spacing={3}> <Grid item xs={4}> <Button onClick={() => window.location.reload()} style={{ textTransform: 'none' }}> <PageHeader title={<Typography variant='h5'>APIs: {totalApis}</Typography>} /> </Button> </Grid> {/* Grid con el campo de búsqueda en la segunda columna */} <Grid item xs={4}> <Grid container spacing={2}> {/* Agregar un campo de búsqueda */} <Grid item xs={12}> <Grid item xs={8}> <Grid container spacing={2} alignItems="center" justifyContent="flex-end"> <Grid item> <TextField label="Search by ..." variant="outlined" //value={searchTerm} value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)} /> </Grid> {/* Otros elementos adicionales en la segunda columna, si es necesario */} <Grid item> <Button variant="contained" color="primary" onClick={() => handleSearch(searchTerm)}> Search </Button> </Grid> </Grid> </Grid> </Grid> </Grid> <Grid item xs={12}> <Card> <CardHeader title='List of Apis' /> <CardHeader title='List of APIs' /> {searchResults.length > 0 ? ( <TableContainer component={Paper}> <Table sx={{ minWidth: 650 }} aria-label='Apis table'> {isLoadingApisData ? ( <Table sx={{ minWidth: 650 }} aria-label='APIs table'> <TableHead> <TableRow> <TableCell>API name</TableCell> <TableCell>Description</TableCell> <TableCell>AEF</TableCell> <TableCell>Delete API</TableCell> </TableRow> </TableHead> <TableBody> {searchResults.map((api) => ( <TableRow key={api.api_id} sx={{ '&:last-of-type td, &:last-of-type th': { border: 0, }, }} > <TableCell component='th' scope='row'> <LinkStyled href={`/apis/${api.api_name}`}> {api.api_name} </LinkStyled> </TableCell> <TableCell>{api.description}</TableCell> <TableCell>{api.aef_profiles[0].aef_id}</TableCell> <TableCell> <Button variant='contained' onClick={() => handleDeleteClick(api.apf_id, api.api_id)} > Delete </Button> </TableCell> </TableRow> ))} </TableBody> </Table> </TableContainer> ) : isLoadingApisData ? ( <CircularProgress /> ) : isErrorApisData ? ( <Typography variant='body1' sx={{ paddingLeft: 4, paddingBottom: 2 }}> Loading @@ -191,6 +256,8 @@ const Apis = () => { </Typography> ) : apisDataPages?.data && apisDataPages.data.length > 0 ? ( <> <TableContainer component={Paper}> <Table sx={{ minWidth: 650 }} aria-label='APIs table'> <TableHead> <TableRow> <TableCell>API name</TableCell> Loading Loading @@ -227,18 +294,19 @@ const Apis = () => { </TableRow> ))} </TableBody> </Table> </TableContainer> </> ) : ( <Typography variant='body1' sx={{ paddingLeft: 4, paddingBottom: 2 }}> There are no apis yet. 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> Loading @@ -258,7 +326,6 @@ const Apis = () => { </Grid> </Grid> <Dialog open={isDeleteDialogOpen} onClose={handleDeleteCancel}> <DialogTitle>Confirm Deletion</DialogTitle> <DialogContent> Loading
capif_frontend/src/pages/users/index.js +136 −72 Original line number Diff line number Diff line Loading @@ -17,7 +17,7 @@ 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 { deleteUser, getNumUsers1, getUsersPages } from 'src/configs/apiService'; import { deleteUser, getNumUsers1, getUsersPages, searchUsers } from 'src/configs/apiService'; import { Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material' import TextField from '@mui/material/TextField'; import Pagination from '@mui/material/Pagination'; Loading Loading @@ -48,6 +48,11 @@ const Users = () => { const [showDeleteMessage, setShowDeleteMessage] = useState(false); const [errorDeleting, setErrorDeleting] = useState(false); // Estados para la búsqueda const [searchResults, setSearchResults] = useState([]); const [totalSearchResults, setTotalSearchResults] = useState(0); const [errorSearching, setErrorSearching] = useState(0); // USERS DATA const queryKeyUsers = ['users']; Loading Loading @@ -150,39 +155,100 @@ const Users = () => { setCurrentPage(1); }; const handleSearch = async () => { try { setErrorSearching(false); // Realizar la búsqueda en el backend const searchData = await searchUsers(searchTerm, currentPage, pageSize); // Actualizar el estado con los resultados de la búsqueda y la información de paginación setSearchResults(searchData.data); setTotalPages(1) setCurrentPage(1) } catch (error) { console.error('Error searching invokers:', error.message); setErrorSearching(true); } }; return ( <Grid container spacing={3}> <Grid item xs={12}> {/* Agregar controles de búsqueda aquí si es necesario */} </Grid> <Grid item xs={8}> <Grid container spacing={3}> <Grid item xs={4}> <Button onClick={() => window.location.reload()} style={{ textTransform: 'none' }}> <PageHeader title={<Typography variant='h5'>Users: {totalUsers}</Typography>} /> </Button> </Grid> {/* Grid con el campo de búsqueda en la segunda columna */} <Grid item xs={4}> <Grid container spacing={2}> {/* Agregar un campo de búsqueda */} <Grid item xs={12}> <Grid item xs={8}> <Grid container spacing={2} alignItems="center" justifyContent="flex-end"> <Grid item> <TextField label="Search by ..." variant="outlined" //value={searchTerm} value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)} /> </Grid> {/* Otros elementos adicionales en la segunda columna, si es necesario */} <Grid item> <Button variant="contained" color="primary" onClick={() => handleSearch(searchTerm)}> Search </Button> </Grid> </Grid> </Grid> </Grid> </Grid> <Grid item xs={12}> <Card> <CardHeader title='List of Users' /> {searchResults.length > 0 ? ( <TableContainer component={Paper}> <Table sx={{ minWidth: 650 }} aria-label='Users table'> {isLoadingUsersData ? ( <TableHead> <TableRow> <TableCell>ID</TableCell> <TableCell>Info</TableCell> <TableCell>User name</TableCell> <TableCell>Actions</TableCell> </TableRow> </TableHead> <TableBody> {searchResults.map((user) => ( <TableRow key={user.username} sx={{ '&:last-of-type td, &:last-of-type th': { border: 0, }, }} > <TableCell component='th' scope='row'> <LinkStyled href={`/users/${user.username}`}> {user.username} </LinkStyled> </TableCell> <TableCell>{user.role}</TableCell> <TableCell>{user.description}</TableCell> <TableCell> <Button variant='contained' onClick={() => handleDeleteClick(user.username, user.password)} > Delete </Button> </TableCell> </TableRow> ))} </TableBody> </Table> </TableContainer> ) : isLoadingUsersData ? ( <CircularProgress /> ) : isErrorUsersData ? ( <Typography variant='body1' sx={{ paddingLeft: 4, paddingBottom: 2 }}> Loading @@ -190,12 +256,14 @@ const Users = () => { </Typography> ) : usersDataPages?.data && usersDataPages.data.length > 0 ? ( <> <TableContainer component={Paper}> <Table sx={{ minWidth: 650 }} aria-label='Invokers table'> <TableHead> <TableRow> <TableCell>Users name</TableCell> <TableCell>Role</TableCell> <TableCell>Users info</TableCell> <TableCell>Delete user</TableCell> <TableCell>ID</TableCell> <TableCell>Info</TableCell> <TableCell>User name</TableCell> <TableCell>Actions</TableCell> </TableRow> </TableHead> <TableBody> Loading Loading @@ -226,21 +294,17 @@ const Users = () => { </TableRow> ))} </TableBody> </Table> </TableContainer> </> ) : ( <Typography variant='body1' sx={{ paddingLeft: 4, paddingBottom: 2 }}> There are no users yet. </Typography> )} </Table> </TableContainer> </Card> </Grid> <Grid item xs={12}> <Grid container spacing={3} alignItems="center" justifyContent="space-between"> <Grid item> Loading