Gennadysht il y a 2 ans
Parent
commit
9fcb4af64f

+ 4 - 3
src/App.js

@@ -4,7 +4,7 @@ import { Router, Route, Switch } from 'react-router-dom';
 import { createBrowserHistory } from "history";
 import { Provider } from 'react-redux';
 import { promiseReducer, frontEndReducer, cartReducer, actionRestoreCart, goodsApi, cartGoodsApi } from './reducers';
-import { CEditableGood, CGood, CGoodsList, CLoginForm, CMainAppBar, COrder, COrdersList, CUser } from "./Components";
+import { CEditableGood, CGood, CGoodsList, CLoginForm, CMainAppBar, COrder, COrdersList, CUser, CUsersList } from "./Components";
 import { CLogout } from './Components';
 import { CSidebar } from './Components/Sidebar';
 import { CRootCats } from './Components';
@@ -26,6 +26,7 @@ import {
 } from 'redux-persist';
 import { EditPost } from './Test/drop';
 import { FileDropZone } from './Components/FileDropZone';
+import { useEffect } from 'react';
 
 
 
@@ -77,17 +78,17 @@ const Main = () =>
 
 //<EditPost onSave={post => console.log(post)}/>
 function App() {
-
   return (
     <>
       <Router history={history}>
         <Provider store={store}>
           <div className="App">
             <CMainAppBar />
-            <CSidebar menuComponent={() => <CRootCats />} />
+            <CSidebar id="sidBar" menuComponent={() => <CRootCats />} />
             <Switch>
               <Route path="/" component={Main} exact />
               <Route path="/orders" component={COrdersList} />
+              <Route path="/users" component={CUsersList} />
               <Route path="/goods" component={CGoodsList} />
               <Route path="/good/:_id" component={CGood} />
               <Route path="/editgood/:_id" component={CEditableGood} />

+ 1 - 1
src/Components/EditableUser.js

@@ -116,7 +116,7 @@ const EditableUser = ({ user: userExt, maxWidth = 'md', saveUser, isAdminPermiss
                             Save
                         </Button>
                         <Button size='small' color='primary'
-                            onClick={() => setUser(userExt)}
+                            onClick={() => setUser(copyUser(userExt))}
                         >
                             Cancel
                         </Button>

+ 11 - 8
src/Components/MainAppBar.js

@@ -6,13 +6,15 @@ import Button from '@mui/material/Button';
 import IconButton from '@mui/material/IconButton';
 import MenuIcon from '@mui/icons-material/Menu';
 import { MyLink } from './MyLink';
-import { connect } from 'react-redux';
+import { connect, useSelector } from 'react-redux';
 import { useTheme } from '@emotion/react';
 import { actionSetSidebar } from '../reducers/frontEndReducer';
+import { UserEntity } from '../Entities';
 
 const MainAppBar = ({ token, openSidebar }) => {
     const theme = useTheme();
-
+    let currentUser = useSelector(state => new UserEntity(state.auth.currentUser ?? { _id: null }));
+    let isAdmin = currentUser.isAdminRole;
     let isLoggedIn = token && true;
     return (
         <Box sx={{ flexGrow: 1 }}>
@@ -33,19 +35,20 @@ const MainAppBar = ({ token, openSidebar }) => {
                     {
                         !isLoggedIn &&
                         <>
-                            <MyLink to="/login"><Button color="inherit">Login</Button></MyLink>
-                            <MyLink to="/register"><Button color="inherit">Register</Button></MyLink>
+                            <MyLink to="/login"><Button sx={{ color: "white" }}>Login</Button></MyLink>
+                            <MyLink to="/register"><Button sx={{ color: "white" }}>Register</Button></MyLink>
                         </>
                     }
                     {
                         isLoggedIn &&
                         <>
-                            <MyLink to="/logout"><Button color="inherit">Logout</Button></MyLink>
-                            <MyLink to="/orders"><Button color="inherit">Orders</Button></MyLink>
-                            <MyLink to="/user"><Button color="inherit">About Me</Button></MyLink>
+                            <MyLink to="/logout"><Button sx={{ color: "white" }}>Logout</Button></MyLink>
+                            <MyLink to="/orders"><Button sx={{ color: "white" }}>Orders</Button></MyLink>
+                            {isAdmin && <MyLink to="/users"><Button sx={{ color: "white" }}>Users</Button></MyLink>}
+                            <MyLink to="/user"><Button sx={{ color: "white" }}>About Me</Button></MyLink>
                         </>
                     }
-                    <MyLink to="/cart"><Button color="inherit">Cart</Button></MyLink>
+                    <MyLink to="/cart"><Button sx={{ color: "white" }}>Cart</Button></MyLink>
                 </Toolbar>
             </AppBar>
         </Box>

+ 12 - 1
src/Components/Pagination.js

@@ -1,6 +1,6 @@
 import { TablePagination } from '@mui/material';
 import { useDispatch, useSelector } from 'react-redux';
-import { getOrdersCount } from '../reducers';
+import { actionSetUsersPaging, getOrdersCount, getUsersCount } from '../reducers';
 import { actionSetGoodsPaging, actionSetOrdersPaging, getGoodsCount } from '../reducers';
 
 const Pagination = ({ allEntitiesCount, fromPage, pageSize, changePageFE, changeRowsPerPageFE }) => {
@@ -48,3 +48,14 @@ export const CGoodsPagination = () => {
     return <Pagination allEntitiesCount={allEntitiesCount} fromPage={fromPage} pageSize={pageSize} changePageFE={changePageFE} changeRowsPerPageFE={changeRowsPerPageFE} />
 }
 
+export const CUsersPagination = () => {
+    let state = useSelector(state => state);
+    let allEntitiesCount = getUsersCount(state);
+    let dispatch = useDispatch();
+    let changePageFE = (fromPage) => dispatch(actionSetUsersPaging({ fromPage }));
+    let changeRowsPerPageFE = pageSize => 
+        dispatch(actionSetUsersPaging({ fromPage: 0, pageSize }));
+    let fromPage = state.frontend.usersPaging.fromPage;
+    const pageSize = state.frontend.usersPaging.pageSize;
+    return <Pagination allEntitiesCount={allEntitiesCount} fromPage={fromPage} pageSize={pageSize} changePageFE={changePageFE} changeRowsPerPageFE={changeRowsPerPageFE} />
+}

+ 11 - 7
src/Components/SearchInput.js

@@ -6,7 +6,7 @@ import Typography from '@mui/material/Typography';
 import InputBase from '@mui/material/InputBase';
 import SearchIcon from '@mui/icons-material/Search';
 import { connect } from 'react-redux';
-import { actionSetGoodsSearch, actionSetOrderSearch } from '../reducers/frontEndReducer';
+import { actionSetGoodsSearch, actionSetOrderSearch, actionSetUsersSearch } from '../reducers/frontEndReducer';
 
 const Search = styled('div')(({ theme }) => ({
   position: 'relative',
@@ -77,17 +77,21 @@ function SearchInput({ onChange }) {
 }
 
 export const COrdersSearchInput = connect(
-  state => {
-
-  },
+  state => { },
   {
     onChange: seacrhStr => actionSetOrderSearch(seacrhStr)
   }
 )(SearchInput);
-export const CGoodsSearchInput = connect(
-  state => {
 
-  },
+export const CUsersSearchInput = connect(
+  state => { },
+  {
+    onChange: seacrhStr => actionSetUsersSearch(seacrhStr)
+  }
+)(SearchInput);
+
+export const CGoodsSearchInput = connect(
+  state => { },
   {
     onChange: seacrhStr => actionSetGoodsSearch(seacrhStr)
   }

+ 44 - 51
src/Components/UsersList.js

@@ -2,13 +2,13 @@ import React from 'react';
 import { Container, Typography, Paper, Link } from '@mui/material';
 import { Table, TableBody, TableContainer, TableHead, TableRow } from "@mui/material";
 import { StyledTableCell, StyledTableRow } from './StyledTableElements';
-import { COrdersPagination } from './Pagination';
-import { COrdersSearchInput } from './SearchInput';
+import { CUsersPagination } from './Pagination';
+import { CUsersSearchInput } from './SearchInput';
 import { MyLink } from '.';
 import { useSelector } from 'react-redux';
-import { useGetOrdersCountQuery, useGetOrdersQuery } from '../reducers';
+import { useGetUsersCountQuery, useGetUsersQuery } from '../reducers';
 
-const UsersList = ({ orders, fromPage, pageSize }) => {
+const UsersList = ({ users, fromPage, pageSize }) => {
 
     let headCells = [
         {
@@ -16,121 +16,114 @@ const UsersList = ({ orders, fromPage, pageSize }) => {
             numeric: true,
             disablePadding: true,
             label: '#',
-            align: "center"
+            align: "center",
+            xs: 1,
         },
         {
             id: 'Date',
             numeric: true,
             disablePadding: true,
             label: 'Date',
+            xs: 2,
         },
         {
-            id: 'Order ID',
+            id: 'User ID',
             numeric: true,
             disablePadding: true,
-            label: 'Order ID',
+            label: 'User ID',
+            xs: 3,
         },
         {
-            id: 'Total ($)',
+            id: 'login',
             numeric: true,
             disablePadding: true,
-            label: 'Total ($)',
-            align: "right"
+            label: 'login',
+            align: "right",
+            xs: 3,
         },
         {
-            id: 'Owner',
+            id: 'Nick',
             numeric: true,
             disablePadding: true,
-            label: 'Owner',
-            align: "right"
-        },
-        {
-            id: 'Note',
-            numeric: true,
-            disablePadding: true,
-            label: 'Note',
-            align: "right"
+            label: 'Nick',
+            align: "right",
+            xs: 3,
         },
     ]
     return (
         <>
             <Container maxWidth="lg">
-                <COrdersSearchInput />
+                <CUsersSearchInput />
                 <TableContainer component={Paper} >
                     <Table sx={{ overflow: 'scroll' }} >
                         <TableHead>
                             <TableRow>
                                 {
                                     headCells.map(headCell => {
-                                        return <StyledTableCell key={headCell.id} align={headCell.align}>{headCell.label}</StyledTableCell>
+                                        return <StyledTableCell key={headCell.id} align={headCell.align} xs={headCell.xs}>{headCell.label}</StyledTableCell>
                                     })
                                 }
                             </TableRow>
                         </TableHead>
-                        {orders?.length > 0 && (
+                        {users?.length > 0 && (
                             <TableBody>
                                 {
-                                    orders.map((order, index) => {
+                                    users.map((user, index) => {
                                         return (
-                                            <StyledTableRow key={order._id}>
-                                                <StyledTableCell align="right" >
+                                            <StyledTableRow key={user._id}>
+                                                <StyledTableCell align="right" width="10%">
                                                     <Typography>
                                                         {(fromPage * pageSize) + index + 1}.
                                                     </Typography>
                                                 </StyledTableCell>
-                                                <StyledTableCell  >
-                                                    {new Date(+order.createdAt).toLocaleString()}
+                                                <StyledTableCell width="15%">
+                                                    {new Date(+user.createdAt).toLocaleString()}
                                                 </StyledTableCell>
-                                                <StyledTableCell  >
-                                                    <MyLink to={`/order/${order._id}`}>
+                                                <StyledTableCell width="25%">
+                                                    <MyLink to={`/user/${user._id}`}>
                                                         <Typography >
-                                                            {order._id}
+                                                            {user._id}
                                                         </Typography>
                                                     </MyLink>
                                                 </StyledTableCell>
-                                                <StyledTableCell align="right" >
+                                                <StyledTableCell align="right" width="25%">
                                                     <Typography >
-                                                        {order.total}
+                                                        {user.login}
                                                     </Typography>
                                                 </StyledTableCell>
-                                                <StyledTableCell align="right" >
+                                                <StyledTableCell align="right" width="25%">
                                                     <Link href='#'>
                                                         <Typography>
-                                                            {order.owner?.nick}
+                                                            {user.nick}
                                                         </Typography>
                                                     </Link>
                                                 </StyledTableCell>
-                                                <StyledTableCell align="right" >
-                                                    <Typography>
-                                                        {order.notes}
-                                                    </Typography>
-                                                </StyledTableCell>
                                             </StyledTableRow>
                                         )
                                     })
                                 }
                             </TableBody>
                         )}
-                        <COrdersPagination />
                     </Table>
+                    <CUsersPagination />
                 </TableContainer>
             </Container>
         </>
     )
 
 }
-const COrdersList = () => {
+const CUsersList = () => {
     let state = useSelector(state => state);
-    const searchStr = state.frontend.ordersSearchStr;
-    const fromPage = state.frontend.ordersPaging.fromPage;
-    const pageSize = state.frontend.ordersPaging.pageSize;
+    const searchStr = state.frontend.usersSearchStr;
+    const fromPage = state.frontend.usersPaging.fromPage;
+    const pageSize = state.frontend.usersPaging.pageSize;
 
-    const ordersResult = useGetOrdersQuery({ fromPage, pageSize, searchStr });
-    const ordersCountResult = useGetOrdersCountQuery({ searchStr });
-    let isLoading = ordersResult.isLoading || ordersCountResult.isLoading;
+    const usersResult = useGetUsersQuery({ fromPage, pageSize, searchStr });
+    const usersCountResult = useGetUsersCountQuery({ searchStr });
+    let isLoading = usersResult.isLoading || usersCountResult.isLoading;
 
-    let orders = !isLoading && ordersResult.data?.OrderFind;
-    return !isLoading  && orders && <OrderList orders={orders} fromPage={fromPage} pageSize={pageSize} />
+    let users = !isLoading && usersResult.data?.UserFind;
+    return !isLoading && users && <UsersList users={users} fromPage={fromPage} pageSize={pageSize} />
 }
 
-////export { COrdersList };
+export { CUsersList };

+ 1 - 0
src/Components/index.js

@@ -13,3 +13,4 @@ export { CRootCats } from './RootCats';
 export { CSortedFileDropZone } from './SortedFileDropZone';
 export { CEditableGood } from './EditableGood'
 export { CEditableUser as CUser } from './EditableUser';
+export { CUsersList } from './UsersList';

+ 36 - 14
src/reducers/authReducer.js

@@ -5,8 +5,16 @@ import { jwtDecode } from "../utills";
 import { createSlice, current } from "@reduxjs/toolkit";
 import { history } from "../App";
 import { UserEntity } from "../Entities";
+import { createFullQuery } from "../gql";
 //import { prepareHeaders } from "./index";
 
+const getUsersSearchParams = (searchStr, queryExt) => (
+    {
+        searchStr: searchStr,
+        searchFieldNames: ["nick", "login"],
+        queryExt
+    });
+
 export const prepareHeaders = (headers, { getState }) => {
     const token = getState().auth.token;
     if (token) {
@@ -45,19 +53,6 @@ export const loginApi = createApi({
             }),
             providesTags: (result, error, id) => ([{ type: 'User', id }])
         }),
-        setNick: builder.mutation({
-            query: ({ _id, nick }) => ({
-                document: gql`
-                    mutation SetNick($_id:String, $nick: String){
-                        UserUpsert(user: {_id: $_id, nick: $nick}){
-                            _id, nick
-                        }
-                    }
-                `,
-                variables: { _id, nick }
-            }),
-            invalidatesTags: (result, error, arg) => ([{ type: 'User', id: arg._id }])
-        }),
         saveUser: builder.mutation({
             query: ({ user }) => ({
                 document: gql`
@@ -71,6 +66,33 @@ export const loginApi = createApi({
             }),
             invalidatesTags: (result, error, arg) => ([{ type: 'User', id: arg._id }])
         }),
+        getUsers: builder.query({
+            query: ({ fromPage, pageSize, searchStr = '' }) => {
+                let params = createFullQuery(getUsersSearchParams(searchStr), { fromPage, pageSize, sort: { _id: -1 } });
+                return {
+                    document: gql`
+                        query UserFind($q: String) {
+                            UserFind(query: $q){
+                                _id login nick acl avatar {_id url} createdAt
+                            } 
+                        }                
+                    `,
+                    variables: params
+                }
+            },
+        }),
+        getUsersCount: builder.query({
+            query: ({ searchStr = '' }) => {
+                let params = createFullQuery(getUsersSearchParams(searchStr));
+                return {
+                    document: gql`
+                            query UsersCount($q: String) { UserCount(query: $q) }
+                    `,
+                    variables: params
+                }
+            },
+        }),
+
     }),
 })
 
@@ -128,6 +150,6 @@ let authApiReducer = loginApi.reducer;
 let authReducer = authSlice.reducer;
 let authApiReducerPath = loginApi.reducerPath;
 
-export const { useLoginMutation, useUserFindQuery, useSaveUserMutation } = loginApi;
+export const { useLoginMutation, useUserFindQuery, useSaveUserMutation, useGetUsersQuery, useGetUsersCountQuery } = loginApi;
 export { authApiReducer, authReducer, authApiReducerPath, actionAuthLogout, actionAboutMe }
 

+ 33 - 3
src/reducers/frontEndReducer.js

@@ -4,12 +4,14 @@ import { actionClearCart } from "./cartReducer";
 import { categoryApi } from "./categoryReducer";
 import { goodsApi } from "./goodsReducer";
 import { ordersApi } from "./ordersReducer";
+import { loginApi } from "./authReducer";
 
 const frontEndReducerSlice = createSlice({ //promiseReducer
     name: 'frontend', //префикс типа наподобие AUTH_
     initialState: {
         sidebar: {},
         ordersPaging: { fromPage: 0, pageSize: 10 },
+        usersPaging: { fromPage: 0, pageSize: 10 },
         goodsPaging: { fromPage: 0, pageSize: 5 }
     }, //state={} в параметрах
     reducers: {
@@ -21,14 +23,24 @@ const frontEndReducerSlice = createSlice({ //promiseReducer
             let { fromPage, pageSize } = action.payload.page;
             fromPage = fromPage ?? state.ordersPaging?.fromPage;
             pageSize = pageSize ?? state.ordersPaging?.pageSize;
-            state.ordersPaging.fromPage = fromPage;
-            state.ordersPaging.pageSize = pageSize;
+            state.ordersPaging = { fromPage, pageSize };
             return state;
         },
         setOrdersSearch(state, action) {
             state.ordersSearchStr = action.payload.searchStr;
             return state;
         },
+        setUsersPaging(state, action) {
+            let { fromPage, pageSize } = action.payload.page;
+            fromPage = fromPage ?? state.usersPaging?.fromPage;
+            pageSize = pageSize ?? state.usersPaging?.pageSize;
+            state.usersPaging = { fromPage, pageSize };
+            return state;
+        },
+        setUsersSearch(state, action) {
+            state.usersSearchStr = action.payload.searchStr;
+            return state;
+        },
         setGoodsPaging(state, action) {
             let { fromPage, pageSize } = action.payload.page;
             fromPage = fromPage ?? state.goodsPaging?.fromPage;
@@ -52,6 +64,7 @@ const frontEndReducerSlice = createSlice({ //promiseReducer
             setCurrentOrder(state, action.payload._id);
             return state;
         },
+
     },
     extraReducers: builder => {
         builder.addMatcher(goodsApi.endpoints.getGoodsCount.matchFulfilled,
@@ -66,6 +79,10 @@ const frontEndReducerSlice = createSlice({ //promiseReducer
             (state, { payload }) => {
                 state.orders = { ordersCount: { payload: payload.OrderCount } }
             });
+        builder.addMatcher(loginApi.endpoints.getUsersCount.matchFulfilled,
+            (state, { payload }) => {
+                state.users = { usersCount: { payload: payload.UserCount } }
+            });
         builder.addMatcher(ordersApi.endpoints.getOrders.matchFulfilled,
             (state, data) => {
                 let a = '';
@@ -95,6 +112,11 @@ let actionSetOrderSearch = (searchStr) =>
         dispatch(frontEndReducerSlice.actions.setOrdersSearch({ searchStr }))
     }
 
+let actionSetUsersSearch = (searchStr) =>
+    async dispatch => {
+        dispatch(frontEndReducerSlice.actions.setUsersSearch({ searchStr }))
+    }
+
 let actionSetCurrentCategory = (_id) =>
     async dispatch => {
         dispatch(frontEndReducerSlice.actions.setCurrentCategory({ _id }))
@@ -155,8 +177,16 @@ const getOrdersCount = state => {
     let result = state.frontend.orders.ordersCount?.payload ?? 0;
     return result;
 }
+const getUsersCount = state => {
+    let result = state.frontend.users.usersCount?.payload ?? 0;
+    return result;
+}
+let actionSetUsersPaging = ({ fromPage, pageSize }) =>
+    async dispatch => {
+        dispatch(frontEndReducerSlice.actions.setUsersPaging({ page: { fromPage, pageSize } }))
+    }
 
 
 export { frontEndReducer, actionSetSidebar, actionSetOrdersPaging, actionSetOrderSearch, actionSetGoodsPaging, actionSetGoodsSearch };
 export { getCurrentCategory, getCurrentGood, actionSetCurrentCategory, actionSetCurrentGood, getGoodsCount, getCurrentOrder, actionSetCurrentOrder }
-export { getOrdersCount };
+export { getOrdersCount, getUsersCount, actionSetUsersPaging, actionSetUsersSearch };

+ 3 - 3
src/reducers/index.js

@@ -1,9 +1,9 @@
 export { promiseReducer, actionPromise, actionFulfilled, actionPending, actionRejected } from "./promiseReducer";
-export { authApiReducer, authReducer, authApiReducerPath, loginApi, authReducerPath, useUserFindQuery, actionAuthLogout, useSaveUserMutation } from './authReducer';
-export { cartReducer, actionAddGoodToCart, actionDeleteGoodFromCart, actionRestoreCart, actionClearCart, /*getCart,*/ } from "./cartReducer";
+export { authApiReducer, authReducer, authApiReducerPath, loginApi, authReducerPath, useUserFindQuery, actionAuthLogout, useGetUsersQuery, useGetUsersCountQuery, useSaveUserMutation } from './authReducer';
+export { cartReducer, actionAddGoodToCart, actionDeleteGoodFromCart, actionRestoreCart, actionClearCart } from "./cartReducer";
 export { cartGoodsApi, useGetCartGoodsQuery } from "./cartGoodsReducer";
 export { localStoredReducer, } from "./localStoredReducer";
-export { frontEndReducer, getCurrentCategory, actionSetGoodsPaging, actionSetOrdersPaging, getCurrentGood, getGoodsCount, getOrdersCount } from "./frontEndReducer";
+export { frontEndReducer, getCurrentCategory, actionSetGoodsPaging, actionSetOrdersPaging, getCurrentGood, getGoodsCount, getOrdersCount, getUsersCount, actionSetUsersPaging, actionSetUsersSearch } from "./frontEndReducer";
 export { useGetRootCategoriesQuery, useGetCategoryByIdQuery } from './categoryReducer';
 export { ordersApi, useGetOrderByIdQuery, useGetOrdersCountQuery, useGetOrdersQuery, useAddOrderMutation } from './ordersReducer';
 export { goodsApi, useGetGoodByIdQuery, useGetGoodsCountQuery, useGetGoodsQuery, useSaveGoodMutation } from './goodsReducer';