From ce5197173236c695dffdff925fa9bd001277e7e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20L=C3=A1szl=C3=B3?= <rlacko99@gmail.com> Date: Thu, 10 Dec 2020 16:07:12 +0100 Subject: [PATCH] List Groups --- client/src/components/Content.tsx | 3 +- client/src/components/group/Groups.tsx | 13 ++++ client/src/components/group/GroupsTable.tsx | 61 +++++++++++++++++++ client/src/components/home/OwnGroupsTable.tsx | 34 ++--------- .../utils/convertResponseToTable.tsx | 6 ++ .../components/utils/getMemberStateString.tsx | 24 ++++++++ .../graphql/queries/group/getGroupById.tsx | 2 +- .../src/graphql/queries/group/listGroups.tsx | 24 ++++++++ client/src/graphql/queries/user/ownUser.tsx | 2 +- server/src/entity/Group.ts | 2 - 10 files changed, 138 insertions(+), 33 deletions(-) create mode 100644 client/src/components/group/Groups.tsx create mode 100644 client/src/components/group/GroupsTable.tsx create mode 100644 client/src/components/utils/convertResponseToTable.tsx create mode 100644 client/src/components/utils/getMemberStateString.tsx create mode 100644 client/src/graphql/queries/group/listGroups.tsx diff --git a/client/src/components/Content.tsx b/client/src/components/Content.tsx index 1b0a23b..ce445e7 100644 --- a/client/src/components/Content.tsx +++ b/client/src/components/Content.tsx @@ -8,6 +8,7 @@ import { GroupItems } from './admin/GroupItems'; import { GroupMembers } from './admin/GroupMembers'; import { GroupRentals } from './admin/GroupRentals'; import { GroupStorages } from './admin/GroupStorages'; +import { Groups } from './group/Groups'; import { LoggedInHome } from './home/LoggedInHome'; import { LoggedOutHome } from './home/LoggedOutHome'; import { NotAuthorized } from './utils/NotAuthorized'; @@ -20,7 +21,7 @@ export const Content: React.FC = () => { <Container maxWidth="lg"> <Box py={2}> <Switch> - <Route path="/groups">groups</Route> + <Route path="/groups" component={Groups} /> <Route path="/gyik">gyik</Route> <Route path="/admin">Admin</Route> <Route path="/qr">qr</Route> diff --git a/client/src/components/group/Groups.tsx b/client/src/components/group/Groups.tsx new file mode 100644 index 0000000..05e0806 --- /dev/null +++ b/client/src/components/group/Groups.tsx @@ -0,0 +1,13 @@ +import { Grid } from '@material-ui/core'; +import { GroupsTable } from './GroupsTable'; +import React from 'react'; + +export const Groups: React.FC = () => { + return ( + <Grid container spacing={1}> + <Grid item xs={12} md={12}> + <GroupsTable /> + </Grid> + </Grid> + ); +}; diff --git a/client/src/components/group/GroupsTable.tsx b/client/src/components/group/GroupsTable.tsx new file mode 100644 index 0000000..8c8eb38 --- /dev/null +++ b/client/src/components/group/GroupsTable.tsx @@ -0,0 +1,61 @@ +import { Box, Typography } from '@material-ui/core'; +import { IListGroups, listGroups } from '../../graphql/queries/group/listGroups'; + +import { CardTable } from '../utils/CardTable'; +import { Group } from '../../types/graphqlSchema'; +import GroupIcon from '@material-ui/icons/Group'; +import React from 'react'; +import { StyledLink } from '../utils/StyledLink'; +import { convertResponseToTable } from '../utils/convertResponseToTable'; +import { getMemberStateString } from '../utils/getMemberStateString'; +import { useQuery } from '@apollo/client'; + +export const GroupsTable: React.FC = () => { + const { loading: groupsIsLoading, data: groups } = useQuery<IListGroups>(listGroups()); + + return ( + <CardTable<Partial<Group>> + columns={[ + { title: 'ID', field: 'id', type: 'numeric', hidden: true }, + { + title: 'Név', + field: 'name', + render: function renderName(rowData) { + return <StyledLink to={`/group/${rowData.id}/info`}>{rowData.name}</StyledLink>; + }, + }, + { + title: 'Tagság', + field: 'ownMemberShip', + align: 'right', + render: function renderMembership(rowData) { + if (!rowData.ownMemberShip) { + return 'Jelentkezés'; + } + return getMemberStateString(rowData.ownMemberShip); + }, + customSort: (rowData1, rowData2) => { + if (!rowData1.ownMemberShip || !rowData2.ownMemberShip) { + return 0; + } + const str1 = getMemberStateString(rowData1.ownMemberShip); + const str2 = getMemberStateString(rowData2.ownMemberShip); + if (str1 < str2) return -1; + if (str1 > str2) return 1; + return 0; + }, + }, + ]} + data={convertResponseToTable(groups?.groups)} + isLoading={groupsIsLoading} + title={ + <Box display="flex" alignItems="center"> + <GroupIcon /> + <Typography variant="h5" style={{ marginLeft: '0.8rem' }}> + Csoportok + </Typography> + </Box> + } + /> + ); +}; diff --git a/client/src/components/home/OwnGroupsTable.tsx b/client/src/components/home/OwnGroupsTable.tsx index e6e8b21..f74ec6b 100644 --- a/client/src/components/home/OwnGroupsTable.tsx +++ b/client/src/components/home/OwnGroupsTable.tsx @@ -1,5 +1,5 @@ import { Box, IconButton, Tooltip, Typography } from '@material-ui/core'; -import { Group, GroupRole, Member, MemberState } from '../../types/graphqlSchema'; +import { Group, Member, MemberState } from '../../types/graphqlSchema'; import { IOwnGroupMemberships, ownGroupMemberships } from '../../graphql/queries/group/ownGroupMemberships'; import { CardTable } from '../utils/CardTable'; @@ -7,39 +7,17 @@ import GroupIcon from '@material-ui/icons/Group'; import React from 'react'; import SettingsIcon from '@material-ui/icons/Settings'; import { StyledLink } from '../utils/StyledLink'; +import { getMemberStateString } from '../utils/getMemberStateString'; import { useHistory } from 'react-router-dom'; import { useQuery } from '@apollo/client'; -interface ITableRow extends Group { - membership: { memberState: MemberState; groupRole: GroupRole }; +interface ITableRow extends Partial<Group> { + membership: Partial<Member>; } -const isApplicantString = 'Elbírálás alatt'; -const isBannedString = 'Kitíltott'; -const isAdminString = 'Admin'; -const isMemberString = 'Tag'; - -const getMemberStateString = ({ memberState, groupRole }: ITableRow['membership']): string => { - switch (memberState) { - case MemberState.Applied: - return isApplicantString; - case MemberState.Banned: - return isBannedString; - case MemberState.Accepted: - switch (groupRole) { - case GroupRole.Admin: - return isAdminString; - case GroupRole.Normal: - return isMemberString; - } - default: - return ''; - } -}; - const convertToTableRow = (props: Member): ITableRow => { const { group, groupRole, memberState } = props; - const membership = { memberState, groupRole }; + const membership: Partial<Member> = { memberState, groupRole }; return { ...group, membership }; }; @@ -84,7 +62,7 @@ export const OwnGroupsTable: React.FC = () => { field: 'membership', align: 'left', render: function renderMembership(rowData) { - if (rowData.membership.memberState !== MemberState.Accepted) return; + if (rowData?.membership?.memberState !== MemberState.Accepted) return; return ( <Tooltip title="Adminisztráció" aria-label="group-administration"> <IconButton diff --git a/client/src/components/utils/convertResponseToTable.tsx b/client/src/components/utils/convertResponseToTable.tsx new file mode 100644 index 0000000..4fb2997 --- /dev/null +++ b/client/src/components/utils/convertResponseToTable.tsx @@ -0,0 +1,6 @@ +import { Group } from '../../types/graphqlSchema'; + +export const convertResponseToTable = (rows: Partial<Group>[] | undefined): Partial<Group>[] => { + if (!rows) return []; + return rows.map((o) => ({ ...o })); +}; diff --git a/client/src/components/utils/getMemberStateString.tsx b/client/src/components/utils/getMemberStateString.tsx new file mode 100644 index 0000000..2926042 --- /dev/null +++ b/client/src/components/utils/getMemberStateString.tsx @@ -0,0 +1,24 @@ +import { GroupRole, Member, MemberState } from '../../types/graphqlSchema'; + +const isApplicantString = 'Elbírálás alatt'; +const isBannedString = 'Kitíltott'; +const isAdminString = 'Admin'; +const isMemberString = 'Tag'; + +export const getMemberStateString = ({ memberState, groupRole }: Partial<Member>): string => { + switch (memberState) { + case MemberState.Applied: + return isApplicantString; + case MemberState.Banned: + return isBannedString; + case MemberState.Accepted: + switch (groupRole) { + case GroupRole.Admin: + return isAdminString; + case GroupRole.Normal: + return isMemberString; + } + default: + return ''; + } +}; diff --git a/client/src/graphql/queries/group/getGroupById.tsx b/client/src/graphql/queries/group/getGroupById.tsx index e5834b0..64fe8d0 100644 --- a/client/src/graphql/queries/group/getGroupById.tsx +++ b/client/src/graphql/queries/group/getGroupById.tsx @@ -19,5 +19,5 @@ export const getGroupById = (fields: string): DocumentNode => { // Returned data export interface IgetGroupById { - group: Group; + group: Partial<Group>; } diff --git a/client/src/graphql/queries/group/listGroups.tsx b/client/src/graphql/queries/group/listGroups.tsx new file mode 100644 index 0000000..0faee73 --- /dev/null +++ b/client/src/graphql/queries/group/listGroups.tsx @@ -0,0 +1,24 @@ +import { DocumentNode } from 'graphql'; +import { Group } from '../../../types/graphqlSchema'; +import gql from 'graphql-tag'; + +// Query +export const listGroups = (): DocumentNode => { + return gql` + query listGroups { + groups { + id + name + ownMemberShip { + memberState + groupRole + } + } + } + `; +}; + +// Returned data +export interface IListGroups { + groups: Partial<Group>[]; +} diff --git a/client/src/graphql/queries/user/ownUser.tsx b/client/src/graphql/queries/user/ownUser.tsx index c13cb5b..80778d8 100644 --- a/client/src/graphql/queries/user/ownUser.tsx +++ b/client/src/graphql/queries/user/ownUser.tsx @@ -16,5 +16,5 @@ export const ownUserGQL = gql` // Returned data export interface IOwnUserGQL { - me: User; + me: Partial<User>; } diff --git a/server/src/entity/Group.ts b/server/src/entity/Group.ts index b49bb40..31dabbe 100644 --- a/server/src/entity/Group.ts +++ b/server/src/entity/Group.ts @@ -134,14 +134,12 @@ export class Group extends BaseEntity { rentalConnection!: Promise<Rental[]>; @Authorized() - @UseMiddleware(isMemberOfGroupField) @Field((returns) => Int) async storageNum() { return (await this.storageConnection).length; } @Authorized() - @UseMiddleware(isMemberOfGroupField) @Field((returns) => Int) async itemNum() { return (await this.itemConnection).length; -- GitLab