Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/admin access #353

Closed
wants to merge 81 commits into from
Closed
Changes from 1 commit
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
df4d9b6
chore: add route for feup exchange
tomaspalma Aug 10, 2024
5592396
add: schedule and initial sidebar on exchange page
tomaspalma Aug 10, 2024
c4539df
add: static frontend to see and create requests
tomaspalma Aug 10, 2024
f311b78
placeholder: started trying with a useSession hook
tomaspalma Aug 11, 2024
b369c8c
add: csrf token retrieval & started authentication system
tomaspalma Aug 12, 2024
b8efa14
feat: exchange and planner page share states
tomaspalma Aug 12, 2024
7d38ce4
add: list of class names as a base to the filters
tomaspalma Aug 13, 2024
12e1deb
feat: added initial mechanism to send exchange requests
tomaspalma Aug 18, 2024
e2663dd
feat: initial version of using useswrinfinite to fetch exchanges pagi…
tomaspalma Aug 21, 2024
a674013
refactor: decoupled logic of getting the classes from <Schedule>
tomaspalma Sep 7, 2024
d6cf99e
feat: expand class information about request card ucs when hovered
tomaspalma Sep 7, 2024
1347741
feat: pagination for the all requests view
tomaspalma Sep 7, 2024
96dfbfb
feat: show schedule and dynamically show course units and request cards
tomaspalma Sep 8, 2024
2f36c9a
feat: fetching request card metadata
tomaspalma Sep 12, 2024
242d41e
feat: started exchange class preview
tomaspalma Sep 15, 2024
015e5f6
chore: add network to share with backend due to oidc
tomaspalma Sep 18, 2024
c58db4f
feat: initial basic add remove functionality
jose-carlos-sousa Sep 19, 2024
3226c92
feat: added toast when user hides a request card
tomaspalma Sep 20, 2024
baac409
feat : initial multiple request at a time preview
jose-carlos-sousa Sep 20, 2024
785553a
refactor: extracted logic to obtain csrf token in cookies to a function
tomaspalma Sep 21, 2024
2416c8c
fix : fixxed remove bug
jose-carlos-sousa Sep 21, 2024
3cf2613
refactor: enrolled course units not longer appear by default in creat…
tomaspalma Sep 21, 2024
b0858e6
fix: now checkbox has to be filled to work
jose-carlos-sousa Sep 24, 2024
658b486
update: preview now depends on checkboxes instead of button
jose-carlos-sousa Sep 26, 2024
018166d
feat: avatar rework and submitting marketplace exchange
tomaspalma Sep 28, 2024
8610c97
Merge remote-tracking branch 'origin/feature/exchange' into feature/p…
jose-carlos-sousa Sep 29, 2024
bb4b35d
chore : made frontend compatible with be changes to request
jose-carlos-sousa Sep 29, 2024
42bc278
feat: common header for different types of request cards
tomaspalma Sep 30, 2024
71914e7
feature: select all working
jose-carlos-sousa Sep 30, 2024
35a24ca
refactor: add way to know if user is submitting a request
tomaspalma Sep 30, 2024
1ae18c5
feat: enrolled course units loading skeleton animation
tomaspalma Oct 1, 2024
69f6cf7
Merge pull request #316 from NIAEFEUP/feature/preview
jose-carlos-sousa Oct 1, 2024
5c78ddd
Merge branch 'feature/exchange' of github.com:NIAEFEUP/tts-fe into fe…
tomaspalma Oct 1, 2024
839871c
fix : now both classes have value of pratical one
jose-carlos-sousa Oct 1, 2024
7eaa15a
Merge pull request #317 from NIAEFEUP/fix/exchangeSchedule
tomaspalma Oct 3, 2024
21ad51f
feat: all course units selected on request card when card open
tomaspalma Oct 3, 2024
08b6f4e
refactor: simplified logic of <CreateRequest> component
tomaspalma Oct 4, 2024
dc0d01a
feat: started exchange class filters
tomaspalma Sep 30, 2024
aea47ee
feat: choose filters in frontend
tomaspalma Oct 7, 2024
4b2a88a
feat: sending base64 of classes filter to backend
tomaspalma Oct 7, 2024
d8c9a42
feat: skeleton loading animation for requests and filters
tomaspalma Oct 13, 2024
c8fdb66
feat: fetching authenticated user profile image
tomaspalma Oct 13, 2024
1432906
feat: submitting request in propor troca
tomaspalma Oct 14, 2024
864244c
fix: deselecting an option had it remaining on the schedule
tomaspalma Oct 14, 2024
a0f15dd
fix: restoring previewed changed schedule when creating a request
tomaspalma Oct 14, 2024
a8ba8ab
feat: preview destination class schedule when creating request
tomaspalma Oct 14, 2024
49a468f
fix: exchange sidebar not extending beyond screen height
tomaspalma Oct 17, 2024
d20dea1
feat: using only course units that have an eligible exchange active p…
tomaspalma Oct 19, 2024
dad86f5
Merge branch 'develop' into feature/exchange
tomaspalma Oct 19, 2024
3cf615c
refactor: created common request card with common state and methods
tomaspalma Oct 24, 2024
2d923be
refactor: changed direct exchange type attributes and more modular code
tomaspalma Oct 28, 2024
c0262d6
feat: previewing working for received requests
tomaspalma Oct 28, 2024
2344165
exchange schedule is now previewed when hovering through class options
Oct 30, 2024
51dc929
refactor: common card header in request card
tomaspalma Oct 30, 2024
1b0e37b
fix: marketplace exchange request card does not show request status
tomaspalma Oct 31, 2024
de5ea85
Merge pull request #334 from NIAEFEUP/feature/preview-schedule
Wallen-Ribeiro Nov 2, 2024
f1ef7c6
feat: receiving request pending motive from backend
tomaspalma Nov 2, 2024
7ad7a27
fix: two independent useswr calls using the same key
tomaspalma Nov 2, 2024
8287498
add: changed button colors and spinner on logout
tomaspalma Nov 2, 2024
d55fab2
feat: log out is now instantaneous
tomaspalma Nov 7, 2024
d3c01fa
Made the submitting exchange button disabled when any type of conflic…
R0drig0-P Nov 10, 2024
659619e
only disable button when conflict is severe
R0drig0-P Nov 13, 2024
5988f51
feat: sent request card history
tomaspalma Nov 17, 2024
15c6933
made requested changes
R0drig0-P Nov 20, 2024
efbc4a6
fixed origin class update bug
Nov 20, 2024
9ecc970
Merge pull request #345 from NIAEFEUP/fix-exchange-origin-class
Wallen-Ribeiro Nov 23, 2024
510a50b
Merge pull request #339 from NIAEFEUP/feature/exchange-not-allow-subm…
tomaspalma Nov 27, 2024
0896bab
refactor: changed name of tab
tomaspalma Nov 27, 2024
54cfdbd
Merge branch 'develop' into feature/exchange
tomaspalma Nov 27, 2024
517aa9c
refactor: better handling of common request components having two types
tomaspalma Nov 30, 2024
116d212
chore: enable exchange only on beta versions
tomaspalma Dec 1, 2024
eddf56a
chore: solve lint issues
tomaspalma Dec 1, 2024
033663c
fix: build issues
tomaspalma Dec 1, 2024
f89800d
chore: remove dead code and extracted methods
tomaspalma Dec 17, 2024
76667db
chore: removed dead code
tomaspalma Dec 17, 2024
80c2c6a
chore: removed unused import in header profile dropdown
tomaspalma Dec 20, 2024
08027d8
fix: build issues
tomaspalma Dec 20, 2024
2c1c803
added admin page
Dec 23, 2024
4fe676d
feat: showing schedule on admin request card
tomaspalma Dec 23, 2024
2918694
chore: added /admin and /admin/settings route
tomaspalma Dec 24, 2024
6c9744c
restreicted access to admin page
Dec 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: initial version of using useswrinfinite to fetch exchanges pagi…
…nated
  • Loading branch information
tomaspalma committed Sep 13, 2024
commit e2663dd1c331b27169762bbbea89e2b075a1424b
15 changes: 9 additions & 6 deletions src/@types/index.d.ts
Original file line number Diff line number Diff line change
@@ -97,10 +97,11 @@ export type ImportedCourses = {
/* Exchange data types */

export type ExchangeOption = {
acronym: string,
name: string,
classNameRequesterGoesFrom: string
classNameRequesterGoesTo: string,
course_unit_acronym: string,
course_unit_name: string,
course_unit_id: number,
class_issuer_goes_from: string
class_issuer_goes_to: string,
other_student?: number // The current student will be determined by the backend depending on session data
}

@@ -119,8 +120,10 @@ export type CreateRequestData = {

export type MarketplaceRequest = {
id: number,
student: Student,
options: Array<MarketplaceExchangeOption>
issuer_name: string,
issuer_nmec: number,
date: string,
options?: Array<ExchangeOption>
}

export type Student = {
19 changes: 16 additions & 3 deletions src/api/services/exchangeRequestService.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { CreateRequestData } from "../../@types";
import { BareFetcher } from "swr";
import { SWRInfiniteConfiguration } from "swr/dist/infinite";
import { CreateRequestData, MarketplaceRequest } from "../../@types";
import api from "../backend";

const isDirectExchange = (requests: IterableIterator<CreateRequestData>) => {
@@ -17,7 +19,7 @@ const submitExchangeRequest = async (requests: Map<string, CreateRequestData>) =
}

await fetch(
`${api.BACKEND_URL}/${isDirectExchange(requests.values()) ? "direct_exchange/" : "marketplace_exchange/"}`,
`${api.BACKEND_URL}/exchange/${isDirectExchange(requests.values()) ? "direct/" : "marketplace/"}`,
{
method: "POST",
credentials: "include",
@@ -26,8 +28,19 @@ const submitExchangeRequest = async (requests: Map<string, CreateRequestData>) =
);
}

const retrieveMarketplaceRequest = async (url: string): Promise<MarketplaceRequest[]> => {
return fetch(url).then(async (res) => {
const json = await res.json();
return json.data;
}).catch((e) => {
console.error(e);
return [];
})
}

const exchangeRequestService = {
submitExchangeRequest
submitExchangeRequest,
retrieveMarketplaceRequest
}

export default exchangeRequestService;
3 changes: 1 addition & 2 deletions src/components/exchange/requests/issue/CreateRequest.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { Dispatch, SetStateAction, useState } from "react"
import { CourseInfo, CreateRequestCardMetadata, CreateRequestData, ExchangeOption } from "../../../../@types"
import { CourseInfo, CreateRequestCardMetadata, CreateRequestData } from "../../../../@types"
import exchangeRequestService from "../../../../api/services/exchangeRequestService"
import { Button } from "../../../ui/button"
import { Separator } from "../../../ui/separator"
import { CreateRequestCard } from "./cards/CreateRequestCard"

type Props = {
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { ArrowLeftIcon, ArrowRightIcon, MinusIcon } from "@heroicons/react/24/outline"
import { Dispatch, SetStateAction, useState } from "react"
import { CreateRequestCardMetadata, CreateRequestData, ExchangeOption } from "../../../../../@types"
import { CreateRequestCardMetadata, CreateRequestData } from "../../../../../@types"
import { Button } from "../../../../ui/button"
import { Card, CardContent, CardHeader, CardTitle } from "../../../../ui/card"
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "../../../../ui/dropdown-menu"
import { Select, SelectItem, SelectTrigger, SelectValue } from "../../../../ui/select"
import { Switch } from "../../../../ui/switch"

type Props = {
99 changes: 55 additions & 44 deletions src/components/exchange/requests/view/ViewRequests.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { PlusIcon } from "@heroicons/react/24/outline";
import { Dispatch, SetStateAction, useState } from "react";
import { MarketplaceRequest } from "../../../../@types";
import useMarketplaceRequests from "../../../../hooks/useMarketplaceRequests";
import { Badge } from "../../../ui/badge";
import { Button } from "../../../ui/button";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../../../ui/tabs";
@@ -17,38 +18,44 @@ export const ViewRequests = ({
const [hiddenRequests, setHiddenRequests] = useState<Set<number>>(new Set());
const [filterCourseUnitNames, setFilterCourseUnitNames] = useState<Set<string>>(new Set());

const requests: Array<MarketplaceRequest> = [
{
id: 1,
options: [
{
acronym: "IA",
name: "Inteligência Artifical",
classNameRequesterGoesFrom: "3LEIC09",
classNameRequesterGoesTo: "3LEIC05"
},
{
acronym: "CG",
name: "Computação Gráfica",
classNameRequesterGoesFrom: "3LEIC09",
classNameRequesterGoesTo: "3LEIC05"
}
],
student: { name: "Tozé Manuel", mecNumber: "202108880" }
},
{
id: 2,
options: [
{
acronym: "CPD",
name: "Computação Paralela e Distribuída",
classNameRequesterGoesFrom: "3LEIC09",
classNameRequesterGoesTo: "3LEIC05"
},
],
student: { name: "Armindo Santos", mecNumber: "202108881" }
}
]
const { data, setSize, isLoading } = useMarketplaceRequests();
const requests = data ? [].concat(...data) : [];

console.log("current requests are: ", requests);
console.log("current wanabee requests are: ", data);

// const requests: Array<MarketplaceRequest> = [
// {
// id: 1,
// options: [
// {
// acronym: "IA",
// name: "Inteligência Artifical",
// classNameRequesterGoesFrom: "3LEIC09",
// classNameRequesterGoesTo: "3LEIC05"
// },
// {
// acronym: "CG",
// name: "Computação Gráfica",
// classNameRequesterGoesFrom: "3LEIC09",
// classNameRequesterGoesTo: "3LEIC05"
// }
// ],
// student: { name: "Tozé Manuel", mecNumber: "202108880" }
// },
// {
// id: 2,
// options: [
// {
// acronym: "CPD",
// name: "Computação Paralela e Distribuída",
// classNameRequesterGoesFrom: "3LEIC09",
// classNameRequesterGoesTo: "3LEIC05"
// },
// ],
// student: { name: "Armindo Santos", mecNumber: "202108881" }
// }
// ]

return <div className="relative flex flex-row flex-wrap items-center justify-center gap-x-2 gap-y-2 lg:justify-start">
<div className="flex flex-row justify-between items-center w-full">
@@ -74,18 +81,22 @@ export const ViewRequests = ({
availableClasses={["3LEIC01", "3LEIC02", "3LEIC03"]}
filterCourseUnitsHook={[filterCourseUnitNames, setFilterCourseUnitNames]}
/>
<div className="mt-4 flex flex-col gap-y-2">
{
requests.map((request) => (
<RequestCard
key={request.id}
request={request}
hiddenRequests={hiddenRequests}
setHiddenRequests={setHiddenRequests}
/>
))
}
</div>
{
isLoading
? <></>
: <div className="mt-4 flex flex-col gap-y-2">
{
requests?.filter((request) => request !== undefined).map((request: MarketplaceRequest) => (
<RequestCard
key={request.id}
request={request}
hiddenRequests={hiddenRequests}
setHiddenRequests={setHiddenRequests}
/>
))
}
</div>
}
</TabsContent>
<TabsContent value="meus-pedidos"></TabsContent>
<TabsContent value="recebidos"></TabsContent>
19 changes: 10 additions & 9 deletions src/components/exchange/requests/view/cards/RequestCard.tsx
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle }
import { Checkbox } from "../../../../ui/checkbox"
import { Separator } from "../../../../ui/separator"
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../../../../ui/tooltip"
import RequestCardClassBadge from "./RequestCardClassBadge"

type Props = {
request: MarketplaceRequest
@@ -33,14 +34,14 @@ export const RequestCard = ({
<img className="w-10 h-10 rounded-full shadow-md" src="https://upload.wikimedia.org/wikipedia/commons/thumb/3/35/Tux.svg/1200px-Tux.svg.png"></img>
<div className="flex flex-row justify-between items-center w-full">
<div className="flex flex-col gap-y-1">
<CardTitle>{request.student.name}</CardTitle>
<CardTitle>{request.issuer_name}</CardTitle>
<CardDescription>
{open
? <p>{request.student.mecNumber}</p>
? <p>{request.issuer_nmec}</p>
:
<div className="flex flex-row space-x-1">
{request.options.map((option) => (
<Badge>{option.acronym}</Badge>
{request.options?.map((option) => (
<RequestCardClassBadge option={option} />
))}
</div>

@@ -78,14 +79,14 @@ export const RequestCard = ({
<div>
<Separator className="my-2" />
<div className="flex flex-row gap-x-4 items-center w-full mb-2">
<Checkbox id={option.acronym} className="flex-grow w-1/12 h-8" />
<label htmlFor={option.acronym} className="w-11/12">
<Checkbox id={option.course_unit_acronym} className="flex-grow w-1/12 h-8" />
<label htmlFor={option.course_unit_acronym} className="w-11/12">
<div className="flex flex-col">
<p>{option.acronym} - {option.name}</p>
<p>{option.course_unit_acronym} - {option.course_unit_name}</p>
<div className="flex flex-row gap-x-2 items-center font-bold">
<p>{option.classNameRequesterGoesFrom}</p>
<p>{option.class_issuer_goes_from}</p>
<ArrowRightIcon className="w-5 h-5" />
<p>{option.classNameRequesterGoesTo}</p>
<p>{option.class_issuer_goes_to}</p>
</div>
</div>
</label>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { useState } from "react";
import { ExchangeOption } from "../../../../../@types";
import { Badge } from "../../../../ui/badge";

type Props = {
option: ExchangeOption
}

const RequestCardClassBadge = ({ option }: Props) => {
const [showIssuerDestClass, setShowIssuerDestClass] = useState<boolean>(false);

return <div className="flex flex-row">
<Badge
className="bg-gray-100 text-black"
onMouseOver={() => setShowIssuerDestClass(true)}
onMouseLeave={() => setShowIssuerDestClass(false)}
>
{option.course_unit_acronym}
</Badge>
<Badge
className={`relative right-2 bg-gray-300 text-black ${showIssuerDestClass ? "block" : "hidden"} transition-all delay-1000`}
>
{option.class_issuer_goes_to}
</Badge>
</div >
}

export default RequestCardClassBadge;
26 changes: 26 additions & 0 deletions src/hooks/useMarketplaceRequests.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import useSWRInfinite from "swr/infinite";
import { MarketplaceRequest } from "../@types";
import api from "../api/backend";
import exchangeRequestService from "../api/services/exchangeRequestService";

export default () => {

const getKey = (pageIndex: number) => {
if (pageIndex === 0) return `${api.BACKEND_URL}/exchange/marketplace/?limit=10`;

return `${api.BACKEND_URL}/exchange/marketplace/?page=${pageIndex}&limit=10`;
}

const { data, size, setSize, isLoading } = useSWRInfinite<Promise<MarketplaceRequest[]>>(
getKey,
exchangeRequestService.retrieveMarketplaceRequest
);

return {
data,
isLoading,
size,
setSize
}
};

24 changes: 14 additions & 10 deletions src/hooks/useSession.tsx
Original file line number Diff line number Diff line change
@@ -6,24 +6,28 @@ const useSession = () => {

const trySession = async (key) => {
try {
// const res = await fetch(`${api.BACKEND_URL}/${key}`, {
// method: "POST",
// credentials: "include",
// headers: {
// "X-CSRFToken": Cookies.get('csrftoken')
// }
// });
const res = await fetch(`${api.BACKEND_URL}/${key}`, {
method: "POST",
credentials: "include",
headers: {
"X-CSRFToken": Cookies.get('csrftoken')
}
});

if (res.ok) {
return "something"
}
} catch (e) {
console.error(e);
}
}

const { data, error, mutate } = useSwr("login/federated/", trySession, {
refreshInterval: 500
const { data, error, mutate } = useSwr("login/", trySession, {
refreshInterval: 3600000000
});

return {
signedIn: false //!data
signedIn: !data
}
}