Gennadysht 2 éve
szülő
commit
d7eaedb9bd

+ 5 - 0
.vscode/extensions.json

@@ -0,0 +1,5 @@
+{
+    "recommendations": [
+        "formulahendry.azure-storage-explorer"
+    ]
+}

+ 1 - 1
src/App.js

@@ -95,8 +95,8 @@ function App() {
               <Route path="/order/:_id" component={COrder} />
               <Route path="/cart" component={CCart} />
               <Route path="/login" component={CLoginForm} />
-              <Route path="/user" component={CUser} />
               <Route path="/user/:_id" component={CUser} />
+              <Route path="/user" component={CUser} />
               <Route path="/logout" component={CLogout} />
 
               <Route path="*" component={NotFound} />

+ 60 - 6
src/Components/EditableUser.js

@@ -1,18 +1,32 @@
 import { useSelector } from "react-redux"
 import { useSaveUserMutation, useUserFindQuery } from "../reducers";
 import { useParams } from "react-router-dom";
-import { Button, Card, CardActions, CardContent, CardMedia, Container, Grid, InputAdornment, TextField } from "@mui/material";
+import { Button, Card, CardActions, CardContent, CardMedia, Checkbox, Container, FormControlLabel, FormGroup, Grid, InputAdornment, TextField, Typography } from "@mui/material";
 import { CSortedFileDropZone } from "./SortedFileDropZone";
 import { ModalContainer } from "./ModalContainer";
 import { useEffect, useState } from "react";
 import { getFullImageUrl, saveImage } from "../utills/utils";
 import { Input } from "@mui/icons-material";
 
-const EditableUser = ({ user: userExt, maxWidth = 'md', saveUser }) => {
-    let [user, setUser] = useState(userExt);
+const getRoleIdx = (user, role) => {
+    let res = user?.acl?.indexOf(role);
+    return res ?? -1;
+}
+const isRole = (user, role) => getRoleIdx(user, role) >= 0;
+const isAdminRole = user => isRole(user, "admin");
+const isUserRole = user => isRole(user, "user");
+
+const EditableUser = ({ user: userExt, maxWidth = 'md', saveUser, isAdminPermissions }) => {
+    const copyUser = user => ({
+        ...user,
+        acl: user.acl ? [...user.acl] : [],
+        avatar: user.avatar ? { _id: user.avatar._id, url: user.avatar.url } : undefined
+    });
+
+    let [user, setUser] = useState(copyUser(userExt));
 
     useEffect(() => {
-        setUser(userExt);
+        setUser(copyUser(userExt));
     }, [userExt]);
 
     const setUserData = (data) => {
@@ -21,7 +35,7 @@ const EditableUser = ({ user: userExt, maxWidth = 'md', saveUser }) => {
         return userData;
     }
     const saveFullUser = async () => {
-        saveUser({ user: { _id: user._id, nick: user.nick } });
+        saveUser({ user: { _id: user._id, nick: user.nick, acl: user.acl ?? [] } });
     }
 
     const uploadAvatar = async param => {
@@ -30,6 +44,24 @@ const EditableUser = ({ user: userExt, maxWidth = 'md', saveUser }) => {
         saveUser({ user: userToSave });
     }
 
+    const setRole = (user, role, isSet) => {
+        user.acl ??= [];
+        let roleIdx = getRoleIdx(user, role);
+        if (isSet) {
+            if (roleIdx < 0) {
+                user.acl.push(role);
+            }
+        }
+        else {
+            if (roleIdx >= 0) {
+                user.acl.splice(roleIdx, 1);
+            }
+        }
+        setUser({ ...user });
+    }
+    const setAdminRole = (user, isSet) => setRole(user, "admin", isSet);
+    const setUserRole = (user, isSet) => setRole(user, "user", isSet);
+    
     return user && (
         <>
             <Container maxWidth={maxWidth}>
@@ -80,6 +112,22 @@ const EditableUser = ({ user: userExt, maxWidth = 'md', saveUser }) => {
                                                     fullWidth
                                                 />
                                             </Grid>
+                                            <Grid item width="100%">
+                                                <FormGroup>
+                                                    <FormControlLabel control={(
+                                                        <Checkbox
+                                                            checked={isUserRole(user)}
+                                                            disabled={!isAdminPermissions}
+                                                            onChange={e => setUserRole(user, e.target.checked)}
+                                                        />)} label="User" />
+                                                    <FormControlLabel control={(
+                                                        <Checkbox
+                                                            checked={isAdminRole(user)}
+                                                            disabled={!isAdminPermissions}
+                                                            onChange={e => setAdminRole(user, e.target.checked)}
+                                                        />)} label="Admin" />
+                                                </FormGroup>
+                                            </Grid>
                                         </Grid>
                                     </CardContent>
                                 </Grid>
@@ -113,7 +161,13 @@ const CEditableUser = ({ maxWidth = 'md' }) => {
     user = _id ? user : currentUser;
     const [saveUserMutation, { }] = useSaveUserMutation();
 
-    return <EditableUser user={user} maxWidth={maxWidth} saveUser={saveUserMutation} />
+    let isCurrentUser = currentUser?._id === _id || !_id;
+    let isAdminPermissions = isAdminRole(currentUser);
+
+
+    return user && (isAdminPermissions || isCurrentUser) ? (
+        <EditableUser user={user} maxWidth={maxWidth} isAdminPermissions={isAdminPermissions} saveUser={saveUserMutation} />) :
+        <Typography>Permission denied</Typography>;
 }
 
 

+ 136 - 0
src/Components/UsersList.js

@@ -0,0 +1,136 @@
+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 { MyLink } from '.';
+import { useSelector } from 'react-redux';
+import { useGetOrdersCountQuery, useGetOrdersQuery } from '../reducers';
+
+const UsersList = ({ orders, fromPage, pageSize }) => {
+
+    let headCells = [
+        {
+            id: '#',
+            numeric: true,
+            disablePadding: true,
+            label: '#',
+            align: "center"
+        },
+        {
+            id: 'Date',
+            numeric: true,
+            disablePadding: true,
+            label: 'Date',
+        },
+        {
+            id: 'Order ID',
+            numeric: true,
+            disablePadding: true,
+            label: 'Order ID',
+        },
+        {
+            id: 'Total ($)',
+            numeric: true,
+            disablePadding: true,
+            label: 'Total ($)',
+            align: "right"
+        },
+        {
+            id: 'Owner',
+            numeric: true,
+            disablePadding: true,
+            label: 'Owner',
+            align: "right"
+        },
+        {
+            id: 'Note',
+            numeric: true,
+            disablePadding: true,
+            label: 'Note',
+            align: "right"
+        },
+    ]
+    return (
+        <>
+            <Container maxWidth="lg">
+                <COrdersSearchInput />
+                <TableContainer component={Paper} >
+                    <Table sx={{ overflow: 'scroll' }} >
+                        <TableHead>
+                            <TableRow>
+                                {
+                                    headCells.map(headCell => {
+                                        return <StyledTableCell key={headCell.id} align={headCell.align}>{headCell.label}</StyledTableCell>
+                                    })
+                                }
+                            </TableRow>
+                        </TableHead>
+                        {orders?.length > 0 && (
+                            <TableBody>
+                                {
+                                    orders.map((order, index) => {
+                                        return (
+                                            <StyledTableRow key={order._id}>
+                                                <StyledTableCell align="right" >
+                                                    <Typography>
+                                                        {(fromPage * pageSize) + index + 1}.
+                                                    </Typography>
+                                                </StyledTableCell>
+                                                <StyledTableCell  >
+                                                    {new Date(+order.createdAt).toLocaleString()}
+                                                </StyledTableCell>
+                                                <StyledTableCell  >
+                                                    <MyLink to={`/order/${order._id}`}>
+                                                        <Typography >
+                                                            {order._id}
+                                                        </Typography>
+                                                    </MyLink>
+                                                </StyledTableCell>
+                                                <StyledTableCell align="right" >
+                                                    <Typography >
+                                                        {order.total}
+                                                    </Typography>
+                                                </StyledTableCell>
+                                                <StyledTableCell align="right" >
+                                                    <Link href='#'>
+                                                        <Typography>
+                                                            {order.owner?.nick}
+                                                        </Typography>
+                                                    </Link>
+                                                </StyledTableCell>
+                                                <StyledTableCell align="right" >
+                                                    <Typography>
+                                                        {order.notes}
+                                                    </Typography>
+                                                </StyledTableCell>
+                                            </StyledTableRow>
+                                        )
+                                    })
+                                }
+                            </TableBody>
+                        )}
+                        <COrdersPagination />
+                    </Table>
+                </TableContainer>
+            </Container>
+        </>
+    )
+
+}
+const COrdersList = () => {
+    let state = useSelector(state => state);
+    const searchStr = state.frontend.ordersSearchStr;
+    const fromPage = state.frontend.ordersPaging.fromPage;
+    const pageSize = state.frontend.ordersPaging.pageSize;
+
+    const ordersResult = useGetOrdersQuery({ fromPage, pageSize, searchStr });
+    const ordersCountResult = useGetOrdersCountQuery({ searchStr });
+    let isLoading = ordersResult.isLoading || ordersCountResult.isLoading;
+
+    let orders = !isLoading && ordersResult.data?.OrderFind;
+    return !isLoading  && orders && <OrderList orders={orders} fromPage={fromPage} pageSize={pageSize} />
+}
+
+////export { COrdersList };

+ 1 - 1
src/reducers/authReducer.js

@@ -36,7 +36,7 @@ export const loginApi = createApi({
                 document: gql`
                     query UserFind($q: String) {
                         UserFindOne(query: $q){
-                            _id login nick avatar {_id url} createdAt
+                            _id login nick acl avatar {_id url} createdAt
                         } 
                     }
                     `,