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