diff --git a/README.md b/README.md index a0a0801b06df38aa916adeafdc01229af107e47e..af39bdd8638b16ce087db2a4ed635a6e16bcafe5 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This app is currently under development ## Docs -You can generate from `docs/readme.md` using `markdown-pp`. +You can generate from `docs/main.md` using `markdown-pp`. ## Setup diff --git a/docs/.gitignore b/docs/.gitignore index 8f47d6aeddec9be5a590df9790e0f0cf22aecea3..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -1 +0,0 @@ -output.md \ No newline at end of file diff --git a/docs/frontend/components.md b/docs/frontend/components.md new file mode 100644 index 0000000000000000000000000000000000000000..5f6fd4ec79b6653cc598cb809897acbc24830f2b --- /dev/null +++ b/docs/frontend/components.md @@ -0,0 +1,129 @@ +`Material UI` könyvtár elemeit használja fel az oldal, továbbá a +`Material Table`-t, hogy jobb Material táblázatok legyenek. + +A komponensek felelőségüktől függően megfelelő alkönyvtárakba vannak +felosztva. Könyvtár struktúra: + +> src/components +> ├── admin +> │ ├── group +> │ │ ├── GroupAdminPanel.tsx +> │ │ ├── GroupDocuments.tsx +> │ │ ├── GroupItems.tsx +> │ │ ├── GroupMembers.tsx +> │ │ └── GroupStorages.tsx +> │ └── GroupAdminContent.tsx +> ├── group +> │ ├── GroupInfo.tsx +> │ ├── GroupsTable.tsx +> │ └── Groups.tsx +> ├── [header](#Header) +> │ ├── DrawerMenu.tsx +> │ ├── Header.tsx +> │ └── UserButton.tsx +> ├── home +> │ ├── BasicStatistics.tsx +> │ ├── GroupHomeDetails.tsx +> │ ├── LoggedInHome.tsx +> │ ├── LoggedOutHome.tsx +> │ └── OwnGroupsTable.tsx +> ├── user +> │ └── OwnProfile.tsx +> ├── utils +> │ ├── CardTable.tsx +> │ ├── GroupNotExists.tsx +> │ ├── Loader.tsx +> │ ├── Loading.tsx +> │ ├── NotAdminOfGroup.tsx +> │ ├── NotAuthorized.tsx +> │ ├── NumberCard.tsx +> │ ├── ShowOnUser.tsx +> │ ├── StyledLink.tsx +> │ └── SwitchComponentByAuth.tsx +> ├── [Content.tsx](#Content) +> ├── Faq.tsx +> └── [Footer.tsx](#Footer) + +Eggyel kintebb látható az `App.tsx`, ez az melyet megnyit az alkalmazás +és itt vannak a fő context-ek beállítva. +Innen tovább érünk a `Main.tsx`-re, mely 3 részre osztja az oldalt, +Header, fő tartalom és footer-re, továbbá biztosítja, +hogy a footer mindig az oldal alján legyen flex-t használva. + +#### Header + +> src/components/header +> ├── DrawerMenu.tsx +> ├── Header.tsx +> └── UserButton.tsx + +Két megjelenítést különböztet meg a képernyő méretétől függően. +Material UI által definiált alacsony méretben a `SmallScreen` komponens, +míg nagy méretben a `LargeScreen` jelenik meg. +Menüikonra kattintva megjelenítésre kerül a `DrawerMenu`. +Ide és a header-be statikusan kell felvenni az egyes menü elemeket, alapvetően +nincs olyan sok elem, de a későbbiekben akár valamilyen ciklussal is +lehet generálni őket. + +A felhasználó saját progiljához és kilépéshez egy külön gomb van a Header +jobb oldali részén, ehhez külön egy `UserButton` komponens kerül használatra. +Ez a komponens a kapott `children`-t jeleníti meg, mint a felhasználó neve. + +#### Footer + +Pár szociális elérhetőség ikon van itt, melyek a nézettől függően pozíciót +változtatnak. + +#### Content + +Ebben kerül megoldásra első lépésben a `Routing`. +Ennek tartalma változik az URL-től függően. + +`/groups` - Csoportok listázása +`/gyik` - Oldal használati utasítás (Még nem készült el) +`/profile/me` - Saját profil +`/group/:id/info` - Egy csoport információi +`/group/:id/admin` - Admin oldalt kezelő komponens, itt újabb Routing történik +`/` - Főoldal +`*` -> `/` - Ami nem illeszkedik egyikre sem, az átirányításra +kerül a főoldalra + +##### Főoldal + +`LoggedInHome` és `LoggedOutHome` komponensek közt van megosztva, +hogy mi jelenik meg. +Ezeken belül dől el, hogy mely statisztikák jelennek meg. + +##### Listázó oldalak + +Egy jó példa a `components/group/Groups.tsx`, melyben csak a Grid beállítás +látható, innen a mellette lévő `GroupsTable` komponensre hivatkozik. +Innen pedig a megfelelő TypeGraphQL API hívás eredményét átadva a [CardTable](CardTable) komponensnek, megjelenít egy táblát. + +Ugyanezt a logikát követi a többi listát megjelenítő komponens is az Admin +résznél, melyek a: `GroupDocuments`, `GroupItems`, +`GroupMembers`, `GroupStorages` + +##### CardTable + +`/components/utils/CardTable.tsx` + +Material Table felüldefiniált verziója, mely benne van egy Material Card-ban, +továbbá magyarosított. + +#### Admin oldalak + +Ehhez a `/components/admin/GroupAdminContent.tsx` -ben történik a legtöbb dolog. +Itt kerül ellenőrzésre, hogy a felhasználó adminja-e a csoportnak, +továbbá innen kerül tovább adásra a jelenlegi csoport a többi alkomponensének. + +Ezen belül is van Routing a `members`, `items`, `storages`, `documents` részre. + +Ezek mind 1-1 listázó komponensek, melyek képesek szűrési vagy rendezési +beállításokat átvenni. + +#### Utils komponensek + +Itt találhatóak a gyakran használt komponenseink, mint a `CardTable`, `Loader`, +hozzáférési üzenet oldalak, `NumberCard`, stb. +Ide érdemes újakat felvenni. diff --git a/docs/frontend/context.md b/docs/frontend/context.md new file mode 100644 index 0000000000000000000000000000000000000000..66b232f948a220f2b24d2dac2ee2928e985fd51f --- /dev/null +++ b/docs/frontend/context.md @@ -0,0 +1,8 @@ +Kontextusba le van tárolva a jelenlegi felhasználó és +annak az adataival dolgozik az alkalmazás onnantól, ezáltal +megspórolva az API hívásokat. + +`src/context` látható ennek a definíciója, továbbá +a hozzá tartozó interfész a `types/IContextUser` -ben. + +Ennek a beállítása a `Main.tsx` -ben történik. diff --git a/docs/frontend/graphql.md b/docs/frontend/graphql.md new file mode 100644 index 0000000000000000000000000000000000000000..f035d7ea823c41e9ea7f75ca6432ce21c012f808 --- /dev/null +++ b/docs/frontend/graphql.md @@ -0,0 +1,21 @@ +#### Típusok + +`/src/types` mappa + +Az alkalmazásban használt típusok a backend-el szinkronban állnak, +ugyanis az ott legenerált sémát kilehet exportálni, majd egy +átalakítás során az összes TypeScript interfészt legenerálni. +Ehhez csak a `types` mappában a `codegen.yml` -t kell felhasználni. +Ugyanebben a mappában találhatóak a `graphqlSchema` fájlban a +legenerált TypeScript típusok. + +#### Lekérések + +`/src/graphql` mappa + +Minden API lekérésnek külön GraphQL definíció található meg. +A nevek követik, hogy mit csinálnak ezek a definíciók. + +Mindegyikből a query-n túl egy interfész is exportálva van azzal, hogy mivel +fog visszatérni a query, így később már csak ezt kell +importálni, mikor használjuk. diff --git a/docs/frontend/req_conf.md b/docs/frontend/req_conf.md new file mode 100644 index 0000000000000000000000000000000000000000..e4b44114d6ff42cb9d359db04673a920fbc39b03 --- /dev/null +++ b/docs/frontend/req_conf.md @@ -0,0 +1,29 @@ +``` +/client/* = Frontend fájljai +``` + +#### Telepítés + +Összes követelmény telepíthető egy `npm install` parancs kiadásával + +#### TypeScript, Eslint, Babel és Webpack + +Az alkalmazás `webpack`-et használ a futtatáshoz és a production fájlok +létrehozására. Ennek konfigurációja a `webpack.config.js`-ben elérhető. +A `TypeScript` konfigurációja a `tsconfig.json` -ben elérhető, továbbá +`eslint`-et használ a kód validálására és ennek konfigurációs +fájljában `.eslintrc.js` több szabály is be van állítva. +Ami kiemelnék az a `Prettier` és a `sort-imports`. Ezeket +külön a megfelelő IDE-hez fel kell telepíteni, hogy automatikusan működjenek. +A Prettier egy kódformásért, míg a másik a be importált +könyvtárak megfelelő sorrendbe helyezéséért felel. + +#### Elindítás Dev és Prod környezetben + +`npm run dev` parancs elérhető a fejlesztői környezetben indításhoz. +Ez a helyi gép `1234` -es portjára fogja kihelyezni. + +Production-be pedig az `npm run build` paranccsal tudjuk előkészíteni a +fájlokat, majd a létrejövő build mappa tartalmát egy `nginx`-el vagy +bármi erre alkalmas alkalmazással kitudjuk hosztolni. +Ehhez elérhető egy `Dockerfile`. diff --git a/docs/main.md b/docs/main.md new file mode 100644 index 0000000000000000000000000000000000000000..635a756522e8f99c6102db0f6e9563c40e4afec5 --- /dev/null +++ b/docs/main.md @@ -0,0 +1,45 @@ +# InvControl Raktározó webalkalmazás - fejlesztői dokumentáció + +## Rövid Összefoglaló + +Az alkalmazás raktározó csoportok, tagok, raktárak, tárgyak és dokumentumok +kezelésére ad lehetőséget. Háttérben egy `Typescript`, `Express` alapú +`TypeGraphql`-ben írt alkalmazás nyújtja a logikát. +A felhasználóknak pedig egy szintén `Typescript`-ben írt, `React` keretrendszert +használó Single Page Application áll rendelkezésre. + +## Backend + +### Követelmények és konfiguráció + +!INCLUDE "backend/req_conf.md" + +### Adatstruktúrák + +!INCLUDE "backend/models.md" + +### API és ahhoz kapcsolódó Resolverek + +!INCLUDE "backend/api.md" + +### Authentikáció + +!INCLUDE "backend/auth.md" + +## Frontend + +### Követelmények és konfiguráció + +!INCLUDE "frontend/req_conf.md" + +### Komponensek + +!INCLUDE "frontend/components.md" + +### GraphQL + +!INCLUDE "frontend/graphql.md" + +### Context + +!INCLUDE "frontend/context.md" diff --git a/docs/readme.md b/docs/readme.md index 6d9ba4e4ff9734418dbaa10617b9b29b67da99ba..2111e8766dab694e4de2ca013891de618c8a91e9 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -12,19 +12,586 @@ használó Single Page Application áll rendelkezésre. ### Követelmények és konfiguráció -!INCLUDE "backend/req_conf.md" +``` +/server/* = Backend fájljai +``` + +#### Telepítés + +Összes követelmény telepíthető egy `npm install` parancs kiadásával + +#### Környezeti változók, Postgres és oAuth + +Konfigurációhoz a `/server/.env` fájlt lehet használni, melyre egy példát ad +a `.env.example` fájl. Ennek tartalma: + +```.env +TYPEORM_HOST=<Postgres host címe> +TYPEORM_USERNAME=<Postgres felhasználó név> +TYPEORM_PASSWORD=<Postgres jelszó> +TYPEORM_DATABASE=<Postgres adatbázis> +TYPEORM_PORT=<Postgres port> +CLIENT_ID=<Google-től kapott oAuth Client ID> +CLIENT_SECRET=<Google-től kapott oAuth Secret> +REDIRECT_URI=<Teljes URL cím a vissza irányításra> +LOGOUT_CALLBACK_URL=<Teljes URL cím a vissza irányításra kilépéskor> +``` + +Látható, hogy az alkalmazás `Postgres` adatbázist használ. +Az adatbázis-t nem hozza létre automatikusan, nekünk kell kézileg. +Docker-ben Postgres indítása: +`docker run -d --name invControl-pg -p 127.0.0.1:5432:5432 -e POSTGRES_PASSWORD=postgres -d postgres` + +Továbbá authentikálni OpenID oAuth -al lehet és az alkalmazás jelenleg +Google oAuth-ra van bekonfigurálva. +oAuth konfigurációhoz van pár Redirect URL, melyek: + +- REDIRECT_URI: `/auth/callback` +- LOGOUT_CALLBACK_URL: `/logout/callback"` + +#### TypeScript + +A `tsconfig.json` használható a szabályok beállítására. + +#### Elindítás Dev és Prod környezetben + +`npm run dev` parancs elérhető a fejlesztői környezetben indításhoz. +Ez a helyi gép `4000` -es portjára fogja kihelyezni. + +Production-be pedig az `npm run build` paranccsal tudjuk előkészíteni a +fájlokat a dist mappába, majd ebbe bele lépve a `node src/server.js` -el +indíthatjuk el. +Ehhez elérhető egy `Dockerfile`. ### Adatstruktúrák -!INCLUDE "backend/models.md" +Az `src/entity`-ben elérhetőek TypeScript osztályokban a használt modellek. + +> entity +> ├── [ContainerKind.ts](#ContainerKind) +> ├── [ContainerUnion.ts](#ContainerUnion) +> ├── [Document.ts](#Document) +> ├── [GroupRole.ts](#GroupRole) +> ├── [Group.ts](#Group) +> ├── [ItemDocument.ts](#ItemDocument) +> ├── [Item.ts](#Item) +> ├── [MemberState.ts](#MemberState) +> ├── [Member.ts](#Member) +> ├── [Rental.ts](#Rental) +> ├── [Storage.ts](#Storage) +> ├── [UserRole.ts](#UserRole) +> └── [User.ts](#User) + +Ezek közül az Enum-ok: + +- `ContainerKind` +- `UserRole` +- `GroupRole` +- `MemberState` + +Union pedig: + +- `ContainerUnion` + +#### User + +Egy felhasználó modellje. + +`users` táblára képződik le és egy felhasználót adatait tartalmazza + +##### Adatbázis Mezői: + +- `id`: Autó inkrementált Egész típusú azonosító szám +- `given_name`: Keresztnév +- `family_name`: Családnév +- `google_id`: Google-nél tárolt felhasználót egyedien azonosító szám +- `google_email`: Google Email cím +- `role`: Globális jogkört meghatározó enum [[UserRole](#UserRole)] + +##### Metódusok: + +- `memberships`: `memberConnection` mezőt használva visszatér a jelenlegi + tagságaival a felhasználónak + +##### További mezők: + +- `memberConnection`: Tagságai a felhasználónak [[Member](#Member)] +- `rentalsFromMeConnection`: Kiadott kölcsönzések a felhasználó által + [[Rental](#Rental)] +- `rentedByMeConnection`: Kölcsönzések a felhasználó által +- `rentalRecipientIsMeConnection`: Kölcsönzések, melyet a felhasználó vett át + +#### UserRole + +Egy enum, mely egy felhasználó globális jogkörét reprezentálja. +Adatbázisban szövegként képződik le. + +##### Mezői, és azok értékei az adatbázisban: + +- `ADMIN`, `"admin"` : Teljes hozzáférése van mindenhez +- `NORMAL`, `"normal"` : Korlátozottak a hozzáférései + +#### Group + +Egy csoport modellje. + +`groups` táblára képződik le és egy csoport adatait tartalmazza + +##### Adatbázis Mezői: + +- `id`: Autó inkrementált Egész típusú azonosító szám +- `name`: Csoport neve +- `description`: Csoport leírása + +##### Metódusok: + +- `ownMemberShip`: Saját tagság lekérése. [[Member](#Member)] -el tér vissza + ha van tagsága, különben null-al +- `parentStorages`: Azon tárolók, melyek közveteln a csoportban vannak. Tehát + a tároló `parentType` mezője `ContainerKind.Group` típusú. [[Storage](#Storage)] +- `warranties(from, to)`: Azon dokumentumok, melyek `endOfWarranty` + mezője a kapott `from` és `to` dátum típusú mezők közé esik. + [[Document](#Document)] +- `itemsLastSeen(from, to)`: Azon tárgyak, melyek `lastSeenDate` + mezője a kapott `from` és `to` dátum típusú mezők közé esik [[Item](#Item)] +- `storageNum`: Csoportban lévő raktárak száma. [[Storage](#Storage)] +- `itemNum`: Csoportban lévő tárgyak száma. [[Item](#Item)] +- `memberNum`: Csoport azon tagjainak száma, akiket felvettek. + [[Member](#Member)] +- `applicantNum`: Csoportba jelentkezők száma. + [[Member](#Member)] +- `allRentalNum`: Összes kölcsönzés száma [[Rental](#Rental)] +- `activeRentals`: Aktív még nem átvett kölcsönzések [[Rental](#Rental)] +- `activeRentalNum`: Aktív kölcsönzések száma [[Rental](#Rental)] + +##### További mezők: + +- `userConnection`: Jelenlegi tagok [[Member](#Member)] +- `storageConnection`: Csoportban lévő tárolók [[Storage](#Storage)] +- `documentConnection`: Csoportban lévő dokumentumok [[Document](#Document)] +- `itemConnection`: Csoportban lévő tárgyak [[Item](#Item)] +- `rentalConnection`: Csoportban lévő kölcsönzések [[Rental](#Rental)] + +##### Segéd funkciók: + +- `getAllRentalsByGroupId(groupId)`: Vissza adja a csoport összes kölcsönzését +- `getActiveRentalsByGroupId(groupId)`: Vissza adja a csoport összes + aktív kölcsönzését + +##### Fejlesztési lehetőség: + +- Két segédfunkció kiváltása a már felvett `rentalConnection` mező + felhasználásával + +#### Member + +Egy csoport modellje. + +`groups` táblára képződik le és egy csoport adatait tartalmazza + +##### Adatbázis Mezői: + +- `id`: Autó inkrementált Egész típusú azonosító szám +- `name`: Csoport neve +- `description`: Csoport leírása + +##### Metódusok: + +- `ownMemberShip`: Saját tagság lekérése. [[Member](#Member)] -el tér vissza + ha van tagsága, különben null-al +- `parentStorages`: Azon tárolók, melyek közveteln a csoportban vannak. Tehát + a tároló `parentType` mezője `ContainerKind.Group` típusú. [[Storage](#Storage)] +- `warranties(from, to)`: Azon dokumentumok, melyek `endOfWarranty` + mezője a kapott `from` és `to` dátum típusú mezők közé esik. + [[Document](#Document)] +- `itemsLastSeen(from, to)`: Azon tárgyak, melyek `lastSeenDate` + mezője a kapott `from` és `to` dátum típusú mezők közé esik [[Item](#Item)] +- `storageNum`: Csoportban lévő raktárak száma. [[Storage](#Storage)] +- `itemNum`: Csoportban lévő tárgyak száma. [[Item](#Item)] +- `memberNum`: Csoport azon tagjainak száma, akiket felvettek. + [[Member](#Member)] +- `applicantNum`: Csoportba jelentkezők száma. + [[Member](#Member)] +- `allRentalNum`: Összes kölcsönzés száma [[Rental](#Rental)] +- `activeRentals`: Aktív még nem átvett kölcsönzések [[Rental](#Rental)] +- `activeRentalNum`: Aktív kölcsönzések száma [[Rental](#Rental)] + +##### További mezők: + +- `userConnection`: Jelenlegi tagok [[Member](#Member)] +- `storageConnection`: Csoportban lévő tárolók [[Storage](#Storage)] +- `documentConnection`: Csoportban lévő dokumentumok [[Document](#Document)] +- `itemConnection`: Csoportban lévő tárgyak [[Item](#Item)] +- `rentalConnection`: Csoportban lévő kölcsönzések [[Rental](#Rental)] + +##### Segéd funkciók: + +- `getAllRentalsByGroupId(groupId)`: Vissza adja a csoport összes kölcsönzését +- `getActiveRentalsByGroupId(groupId)`: Vissza adja a csoport összes + aktív kölcsönzését + +##### Fejlesztési lehetőség: + +- Két segédfunkció kiváltása a már felvett `rentalConnection` mező + felhasználásával + +#### MemberState + +Egy enum, mely egy felhasználó státuszát reprezentálja egy csoportban. +Adatbázisban szövegként képződik le. + +##### Mezői, és azok értékei az adatbázisban: + +- `APPLIED`, `"applied"` : Jelentkezett +- `BANNED`, `"banned"` : Kitiltott +- `ACCEPTED`, `"accepted"` : Felvett + +#### GroupRole + +Egy enum, mely egy felhasználó jogkörét reprezentálja. +Adatbázisban szövegként képződik le. + +##### Mezői, és azok értékei az adatbázisban: + +- `ADMIN`, `"admin"` : Teljes jogköre van a csoportban +- `NORMAL`, `"normal"` : Minimális hozzáférése van a csoporthoz + +#### Storage + +Egy Tároló modellje. Egy csoportban több tároló is lehet, továbbá +tárolóban is lehetnek tárolók. Ahhoz, hogy egy tárolóról eldönthessük, +hogy mely csoportban van, anélkül, hogy bejárnánk az összes őt +tartalmazó tárolót, letároljuk, hogy mely csoporthoz tartozik. + +Ez azt jelenti, hogy tároló másik csoportba helyezésekor be kell járni az +összes benne lévő tárolót, tárgyat, dokumentumot, kölcsönzést, +hogy frissítsük a csoportjukat. +Ez a lekérdezéshez képest sokkal ritkábban fordul elő és gyorsabb lekéréseket +érhetünk el. + +`storage` táblára képződik le és tároló adatait, benne lévő dolgokra mutató +idegen kulcsokat tartalmaz + +##### Adatbázis Mezői: + +- `id`: Autó inkrementált Egész típusú azonosító szám +- `name`: Tároló neve +- `description`: Leírás +- `location`: Helyzetét meghatározó szöveg +- `parent_id`: Adott tárolót tároló objektum ID-ja +- `parent_type`: Adott tárolót tároló objektum típusa + [[ContainerKind](#ContainerKind)] +- `items`: Tárolóban lévő tárgyak. [[Item](#Item)] +- `group_id`: Csoport ID-ja, amiben benne van + +##### Metódusok: + +- `container`: Adott tárolót tartalmazó tároló vagy csoport. Visszatérési + értéke egy a GraphQL-ben használt Union típusú. + [[ContainerUnion](#ContainerUnion)] +- `contains`: Adott tárolóban lévő tárolók + +##### További mezők: + +- `group`: Visszatér a csoporttal, amelyikhez tartozik + +#### ContainerKind + +Egy enum, mely egy tároló típusát jelöli. +Tárolók tárolóinak jelöléséhez használatos. +Adatbázisban szövegként képződik le. + +##### Mezői, és azok értékei az adatbázisban: + +- `Group`, `"group"` : Csoport +- `Storage`, `"storage"` : Tároló + +##### Fejlesztési lehetőség: + +Group és Storage mező átfaktorálása GROUP és STORAGE-re. + +#### ContainerUnion + +Egy Union, mely lehetővé teszi, hogy [[Storage](#Storage)]-el vagy +[[Group](#Group)]-al térjünk vissza mikor a tárolót tároló objektumot +kérjük le. +Adatbázisban szövegként képződik le. + +#### Item + +Egy tárgy modellje. + +`items` táblára képződik le és egy csoport adatait tartalmazza + +##### Adatbázis Mezői: + +- `id`: Autó inkrementált Egész típusú azonosító szám +- `name`: Tárgy neve +- `description`: Tárgy leírása +- `is_lost`: Elveszett-e a tárgy +- `last_seen_date`: Utoljára mikor látták +- `added_date`: Mikor került hozzáadásra +- `container_id`: Tartalmazó tároló id-ja +- `groupId`: Csoport ID-ja, melyhez tartozik + +##### Metódusok: + +- `activeRental`: Aktív kölcsönzés [[Rental](#Rental)] +- `isRented`: Jelenleg kölcsönzött-e? +- `documents`: Kapcsolódó dokumentumok + +##### További mezők: + +- `container`: Tártalmazó tároló [[Storage](#Storage)] +- `rentalConnection`: Kapcsolódó kölcsönzések [[Rental](#Rental)] +- `documentConnection`: Kapcsolódó dokumentumokkal való kapcsolat +- `group`: Csoport melyhez tartozik + +#### Document + +Egy dokumentum modellje. + +`documents` táblára képződik le és egy csoport adatait tartalmazza + +##### Adatbázis Mezői: + +- `id`: Autó inkrementált Egész típusú azonosító szám +- `description`: Leírás +- `location`: Egy szöveg, melyből azonosítható a hely ahol van +- `purchase_date`: Vásárlási dátum +- `end_of_warranty`: Garancia vége +- `group_id`: Csoport ID-ja, melyhez tartozik + +##### Metódusok: + +- `items`: Kapcsolódó tárgyak [[Item](#Item)] + +##### További mezők: + +- `itemConnection`: Kapcsolódó [[ItemDocument](#ItemDocument)] -ek +- `group`: Csoport, melyhez tartozik + +#### ItemDocument + +[[Item](#Item)] és [[Document](#Document)] közti kapcsoló tábla. +Azért kell külön kapcsoló tábla, mert egy dokumentumhoz +több tárgy és több tárgyhoz egy dokumentum is kapcsolódhat. + +`item_documents` táblára képződik le. Kapcsolódó tárgy és dokumentum együtt +az egyedi kulcs + +##### Adatbázis Mezői: + +- `item_id`: Tárgy id-ja +- `document_id`: Dokumentum id-ja + +##### További mezők: + +- `item`: Tárgy amire az ID mutat +- `document`: Dokumentum amire az ID mutat + +#### Rental + +Egy kölcsönzés modellje. + +`rentals` táblára képződik le és egy kölcsönzés adatait tartalmazza + +##### Adatbázis Mezői: + +- `id`: Autó inkrementált Egész típusú azonosító szám +- `reposession_date`: Mikor került visszavételre +- `reposession_comment`: Megjegyzés a visszavételhez +- `rent_date`: Kölcsönzés dátuma +- `rent_comment`: Megjegyzés a kölcsönzéshez +- `rented_from_id`: Felhasználó ID-ja, akitől kölcsönözték +- `renter_id`: Kölcsönző felhasználó ID-ja +- `deadline`: Határidő amíg vissza kell hoznia +- `item_id`: Tárgy ID-ja ami kölcsönzésre került +- `recipient_id`: Átvevő felhasználó ID-ja +- `group_id`: Csoport ID, melyhez tartozik + +##### Metódusok: + +- `isRented`: Jelenleg kölcsönzés alatt van-e + +##### További mezők: + +- `renter`: Kölcsönző felhasználó [[User](#User)] +- `item`: Kölcsönzőtt tárgy [[Item](#Item)] +- `recipient`: Átvevő felhasználó [[User](#Group)] +- `group`: Csoport, melyhez tartozik [[User](#Group)] ### API és ahhoz kapcsolódó Resolverek -!INCLUDE "backend/api.md" +GraphQL-t használ az alkalmazás és indítás után `/graphql` +-en el is érhető + +A lekérések és kapcsolódó mutációk és ezek leírása elérhető `/graphql` címen. +Nem mindenhez van Resolver, ugyanis graphQL-ben egy lekérésből tovább +lehet menni a többi objektumra. Például egy felhasználóhoz, hogy +lekérjem az összes tagságát nem kell egy `Tárgyak(felhasználóID)` Resolver, +hanem elég egy `user(id) { items { id, name, ... }}` lekérés. + +Resolverek és mutációk `src/modules/*` alatt érhetőek el külön mappákba +rendezve. +Ezek listája: + +> modules +> ├── group +> │ └── [GroupResolver.ts](#GroupResolver) +> ├── item +> │ └── [ItemResolver.ts](#ItemResolver) +> ├── itemDocument +> │ └── [ItemDocumentResolver.ts](#ItemDocumentResolver) +> ├── member +> │ └── [MemberResolver.ts](#MemberResolver) +> ├── rental +> │ └── [RentalResolver.ts](#RentalResolver) +> ├── storage +> │ └── [StorageResolver.ts](#StorageResolver) +> └── user +> . └── [UserResolver.ts](#UserResolver) + +#### GroupResolver + +Minden a csoportokhoz tartozó lekérésért felel. + +##### Lekérés + +- `group(id)`: Csoport lekérése ID alapján +- `groups`: Összes csoport lekérése +- `groupNum`: Összes csoport számának lekérése + +##### Módosítás + +- `createGroup(name, description)`: Csoport létrehozása +- `updateGroup(groupId, name, description)`: Csoport adatok frissítése + +#### ItemResolver + +Minden a tárgyakhoz tartozó lekérésért felel. + +##### Lekérés + +- `item(id)`: Adott tárgy lekérése +- `items`: Összes tárgy listázása + +##### Módosítás + +- `updateItemLastSeen(itemId)`: Adott tárgy utoljára látott dátumának + frissítése a jelenlegire +- `createItem(name, containerId)`: Tárgy létrehozása adott tárolóba +- `deleteItem(id)`: Tárgy törlése +- `updateItem(itemId, name, description, isLost, lastSeenDate)`: + Tárgy adatainak frissítése. A mezők nem kötelezőek + +#### ItemDocumentResolver + +Minden a dokumentumokhoz tartozó lekérésért felel. + +##### Lekérés + +- `itemDocuments(groupId)`: Csoporthoz tartozó dokumentumok + +##### Módosítás + +- `createItemDocument(description, location, itemId)`: Dokumentum létrehozása +- `deleteItemDocument(documentId)`: Dokumentum törlése + +#### MemberResolver + +Minden a Csoport tagokhoz tartozó lekérésért felel. + +##### Lekérés + +- `members`: Összes csoport tagság listázása +- `member(userId)`: Felhasználóhoz tartozó csoport tagság. + +##### Módosítás + +- `createMember(userId, groupId, memberState, groupRole)`: Új tagság létrehozása +- `updateMemberState(userId, groupId, memberState)`: Tagság státusz frissítése +- `updateMemberRole(userId, groupId, groupRole)`: Jogkör frissítése + +##### Lehetséges fejlesztés + +`member(userId)` - Erre a függvényre nincs szükség. Sőt nem is tér vissza minden +csoport tagsággal. + +`updateMemberState` és `updateMemberRole` összevonása + +#### RentalResolver + +Minden a kölcsönzésekhez tartozó lekérésért felel. + +##### Lekérés + +- `allRentals`: Összes kölcsönzés kilistázása + +##### Módosítás + +- `createRental(rentedFromId, renterId, deadline, itemId)`: + Kölcsönzés létrehozása + +#### StorageResolver + +Minden a tárolókhoz tartozó lekérésért felel. + +##### Lekérés + +- `storage(id)`: Tároló lekérése ID alapján +- `storages`: Összes tároló listázása +- `storageNum`: Összes tároló száma + +##### Módosítás + +- `createStorage(name, description, location, parentType, parentId)`: + Új tároló létrehozása +- `updateStorage(storageId, name, description, location)`: + Tároló frissítése +- `deleteStorage(storageId)`: + Tároló törlése + +#### UserResolver + +Minden a felhasználókhoz tartozó lekérésért felel. + +##### Lekérés + +- `user(id)`: Felhasználó lekérése ID alapján +- `isLoggedIn`: Aki lekérdezett az be van-e lépve +- `me`: Saját felhasználó lekérése +- `users`: Összes felhasználó lekérése + +##### Módosítás + +- `updateUserRole(id, role)`: Felhasználó globális jogkörének frissítése ### Authentikáció -!INCLUDE "backend/auth.md" +Authentikációhoz a `TypeGraphQL` beépített annotiációi vannak használva. +Egy-egy modellnél mezőnként specifikálva van, hogy mikor lehet lekérni. + +Egyes esetekben `middleware`-ek vannak definiálva, melyek: + +> middleware +> ├── field +> │ ├── isMemberOfGroupField.ts +> │ └── isOwnUserField.ts +> └── resolver +> . ├── isAdminOfGroup.ts +> . ├── isAdmin.ts +> . └── isMemberOfGroup.ts + +Ezek Mező és Resolver szintűek lehetnek. +Itt lehet újabbat felvenni. + +Azért vannak ezek külön választva, mivel míg egy Resolver-nél átadásra kerül +egy groupId és az alapján meg lehet állapítani, hogy van-e joga +a felhasználónak, egy field-nél már a jelenlegi modellből kell lekérni. +Például egy `isMemberOfGroupField` -et egy `Rental` mezőre rárakáskor +megállapítja a middleware, hogy milyen típusú a mező és az alapján lekéri +a hozzá kapcsolódó csoportot. ## Frontend @@ -59,3 +626,170 @@ Production-be pedig az `npm run build` paranccsal tudjuk előkészíteni a fájlokat, majd a létrejövő build mappa tartalmát egy `nginx`-el vagy bármi erre alkalmas alkalmazással kitudjuk hosztolni. Ehhez elérhető egy `Dockerfile`. + +### Komponensek + +`Material UI` könyvtár elemeit használja fel az oldal, továbbá a +`Material Table`-t, hogy jobb Material táblázatok legyenek. + +A komponensek felelőségüktől függően megfelelő alkönyvtárakba vannak +felosztva. Könyvtár struktúra: + +> src/components +> ├── admin +> │ ├── group +> │ │ ├── GroupAdminPanel.tsx +> │ │ ├── GroupDocuments.tsx +> │ │ ├── GroupItems.tsx +> │ │ ├── GroupMembers.tsx +> │ │ └── GroupStorages.tsx +> │ └── GroupAdminContent.tsx +> ├── group +> │ ├── GroupInfo.tsx +> │ ├── GroupsTable.tsx +> │ └── Groups.tsx +> ├── [header](#Header) +> │ ├── DrawerMenu.tsx +> │ ├── Header.tsx +> │ └── UserButton.tsx +> ├── home +> │ ├── BasicStatistics.tsx +> │ ├── GroupHomeDetails.tsx +> │ ├── LoggedInHome.tsx +> │ ├── LoggedOutHome.tsx +> │ └── OwnGroupsTable.tsx +> ├── user +> │ └── OwnProfile.tsx +> ├── utils +> │ ├── CardTable.tsx +> │ ├── GroupNotExists.tsx +> │ ├── Loader.tsx +> │ ├── Loading.tsx +> │ ├── NotAdminOfGroup.tsx +> │ ├── NotAuthorized.tsx +> │ ├── NumberCard.tsx +> │ ├── ShowOnUser.tsx +> │ ├── StyledLink.tsx +> │ └── SwitchComponentByAuth.tsx +> ├── [Content.tsx](#Content) +> ├── Faq.tsx +> └── [Footer.tsx](#Footer) + +Eggyel kintebb látható az `App.tsx`, ez az melyet megnyit az alkalmazás +és itt vannak a fő context-ek beállítva. +Innen tovább érünk a `Main.tsx`-re, mely 3 részre osztja az oldalt, +Header, fő tartalom és footer-re, továbbá biztosítja, +hogy a footer mindig az oldal alján legyen flex-t használva. + +#### Header + +> src/components/header +> ├── DrawerMenu.tsx +> ├── Header.tsx +> └── UserButton.tsx + +Két megjelenítést különböztet meg a képernyő méretétől függően. +Material UI által definiált alacsony méretben a `SmallScreen` komponens, +míg nagy méretben a `LargeScreen` jelenik meg. +Menüikonra kattintva megjelenítésre kerül a `DrawerMenu`. +Ide és a header-be statikusan kell felvenni az egyes menü elemeket, alapvetően +nincs olyan sok elem, de a későbbiekben akár valamilyen ciklussal is +lehet generálni őket. + +A felhasználó saját progiljához és kilépéshez egy külön gomb van a Header +jobb oldali részén, ehhez külön egy `UserButton` komponens kerül használatra. +Ez a komponens a kapott `children`-t jeleníti meg, mint a felhasználó neve. + +#### Footer + +Pár szociális elérhetőség ikon van itt, melyek a nézettől függően pozíciót +változtatnak. + +#### Content + +Ebben kerül megoldásra első lépésben a `Routing`. +Ennek tartalma változik az URL-től függően. + +`/groups` - Csoportok listázása +`/gyik` - Oldal használati utasítás (Még nem készült el) +`/profile/me` - Saját profil +`/group/:id/info` - Egy csoport információi +`/group/:id/admin` - Admin oldalt kezelő komponens, itt újabb Routing történik +`/` - Főoldal +`*` -> `/` - Ami nem illeszkedik egyikre sem, az átirányításra +kerül a főoldalra + +##### Főoldal + +`LoggedInHome` és `LoggedOutHome` komponensek közt van megosztva, +hogy mi jelenik meg. +Ezeken belül dől el, hogy mely statisztikák jelennek meg. + +##### Listázó oldalak + +Egy jó példa a `components/group/Groups.tsx`, melyben csak a Grid beállítás +látható, innen a mellette lévő `GroupsTable` komponensre hivatkozik. +Innen pedig a megfelelő TypeGraphQL API hívás eredményét átadva a [CardTable](CardTable) komponensnek, megjelenít egy táblát. + +Ugyanezt a logikát követi a többi listát megjelenítő komponens is az Admin +résznél, melyek a: `GroupDocuments`, `GroupItems`, +`GroupMembers`, `GroupStorages` + +##### CardTable + +`/components/utils/CardTable.tsx` + +Material Table felüldefiniált verziója, mely benne van egy Material Card-ban, +továbbá magyarosított. + +#### Admin oldalak + +Ehhez a `/components/admin/GroupAdminContent.tsx` -ben történik a legtöbb dolog. +Itt kerül ellenőrzésre, hogy a felhasználó adminja-e a csoportnak, +továbbá innen kerül tovább adásra a jelenlegi csoport a többi alkomponensének. + +Ezen belül is van Routing a `members`, `items`, `storages`, `documents` részre. + +Ezek mind 1-1 listázó komponensek, melyek képesek szűrési vagy rendezési +beállításokat átvenni. + +#### Utils komponensek + +Itt találhatóak a gyakran használt komponenseink, mint a `CardTable`, `Loader`, +hozzáférési üzenet oldalak, `NumberCard`, stb. +Ide érdemes újakat felvenni. + +### GraphQL + +#### Típusok + +`/src/types` mappa + +Az alkalmazásban használt típusok a backend-el szinkronban állnak, +ugyanis az ott legenerált sémát kilehet exportálni, majd egy +átalakítás során az összes TypeScript interfészt legenerálni. +Ehhez csak a `types` mappában a `codegen.yml` -t kell felhasználni. +Ugyanebben a mappában találhatóak a `graphqlSchema` fájlban a +legenerált TypeScript típusok. + +#### Lekérések + +`/src/graphql` mappa + +Minden API lekérésnek külön GraphQL definíció található meg. +A nevek követik, hogy mit csinálnak ezek a definíciók. + +Mindegyikből a query-n túl egy interfész is exportálva van azzal, hogy mivel +fog visszatérni a query, így később már csak ezt kell +importálni, mikor használjuk. + +### Context + +Kontextusba le van tárolva a jelenlegi felhasználó és +annak az adataival dolgozik az alkalmazás onnantól, ezáltal +megspórolva az API hívásokat. + +`src/context` látható ennek a definíciója, továbbá +a hozzá tartozó interfész a `types/IContextUser` -ben. + +Ennek a beállítása a `Main.tsx` -ben történik.