Merge pull request 'statistics' (#59) from statistics into master

Reviewed-on: http://git.plannaplan.pl/y0rune/frontend/pulls/59
Reviewed-by: Maciej <glowackimaciej97@gmail.com>
This commit is contained in:
Maciej 2021-01-23 19:05:41 +01:00
commit a5d3beddb5
6 changed files with 71 additions and 22 deletions

View File

@ -1,9 +1,12 @@
import React, { useLayoutEffect, useRef } from 'react'; import React, { useContext, useLayoutEffect, useRef } from 'react';
import { useState } from 'react'; import { useState } from 'react';
import { SchedulerEvents } from './SchedulerEvents'; import { SchedulerEvents } from './SchedulerEvents';
import { days, hours } from '../constants/index'; import { days, hours } from '../constants/index';
import styled from 'styled-components/macro'; import styled from 'styled-components/macro';
import { SchedulerEvent } from '../types'; import { SchedulerEvent } from '../types';
import { coursesContext } from '../contexts/CoursesProvider';
import Button from '@material-ui/core/Button';
import Tooltip, { TooltipProps } from '@material-ui/core/Tooltip';
const SchedulerWrapper = styled.div` const SchedulerWrapper = styled.div`
border-collapse: collapse; border-collapse: collapse;
@ -17,6 +20,7 @@ const SchedulerWrapper = styled.div`
justify-content: center; justify-content: center;
align-items: center; align-items: center;
box-shadow: 3px 3px 3px -2px rgba(0, 0, 0, 0.59); box-shadow: 3px 3px 3px -2px rgba(0, 0, 0, 0.59);
position:relative;
`; `;
const TableBody = styled.div` const TableBody = styled.div`
@ -62,6 +66,27 @@ const TableCell = styled.div<TableCellProps>`
font-weight: bold; font-weight: bold;
`; `;
const TourWrapper = styled.div`
display: flex;
justify-content:center;
align-items:center;
position:absolute;
top:8px;
right:8px;
min-width: 10px;
padding: 3px 7px;
font-size: 12px;
font-weight: 700;
color: black;
line-height: 1;
vertical-align: middle;
white-space: nowrap;
text-align: center;
background-color: #FFDC61;
border-radius: 10px;
font-size:18px;
`;
interface SchedulerProps { interface SchedulerProps {
schedulerEvents: Array<SchedulerEvent>; schedulerEvents: Array<SchedulerEvent>;
} }
@ -70,6 +95,7 @@ export const Scheduler = ({ schedulerEvents }: SchedulerProps) => {
const cellRef = useRef<HTMLDivElement>(null); const cellRef = useRef<HTMLDivElement>(null);
const [cellWidth, setCellWidth] = useState(0); const [cellWidth, setCellWidth] = useState(0);
const [cellHeight, setCellHeight] = useState(0); const [cellHeight, setCellHeight] = useState(0);
const { tour } = useContext(coursesContext)!;
useLayoutEffect(() => { useLayoutEffect(() => {
const handleResize = () => { const handleResize = () => {
@ -130,6 +156,19 @@ export const Scheduler = ({ schedulerEvents }: SchedulerProps) => {
))} ))}
<SchedulerEvents cellWidth={cellWidth} cellHeight={cellHeight} schedulerEvents={schedulerEvents} /> <SchedulerEvents cellWidth={cellWidth} cellHeight={cellHeight} schedulerEvents={schedulerEvents} />
</TableBody> </TableBody>
<TourWrapper>
<Tooltip title="Pierwsza Tura Zapisów">
<div style={{cursor: 'help'}}>{tour === 'FIRST_TOUR' && '1'}</div>
</Tooltip>
<Tooltip title="Druga Tura Zapisów">
<div style={{cursor: 'help'}}>{tour === 'SECOND_TOUR' && '2'}</div>
</Tooltip>
<Tooltip title="Zapisywanie wyłączone">
<div style={{cursor: 'help'}}>{tour === 'NO_TOUR' && 'X'}</div>
</Tooltip>
</TourWrapper>
</SchedulerWrapper> </SchedulerWrapper>
); );
}; };

View File

@ -239,10 +239,10 @@ export const SchedulerRow = ({ groups, indexRow, rowTop, cellWidth, cellHeight }
<PopoverSpan>Sala zajęć</PopoverSpan>: {groups[index].room} <PopoverSpan>Sala zajęć</PopoverSpan>: {groups[index].room}
</p> </p>
<p style={{ margin: '2px 0 2px 0' }}> <p style={{ margin: '2px 0 2px 0' }}>
<PopoverSpan>Kod przedmiotu: </PopoverSpan>ACB129 <PopoverSpan>Kod przedmiotu: </PopoverSpan> {groups[index].symbol}
</p> </p>
<p style={{ margin: '2px 0 2px 0' }}> <p style={{ margin: '2px 0 2px 0' }}>
<PopoverSpan>Kod grupy: </PopoverSpan>FVJ753 <PopoverSpan>Numer grupy: </PopoverSpan> {groups[index].grNr}
</p> </p>
<p style={{ margin: '2px 0 2px 0', color:"green"}}> <p style={{ margin: '2px 0 2px 0', color:"green"}}>
<b>{groups[index].isAccepted===true && "Przedmiot został zaakceptowany"}</b> <b>{groups[index].isAccepted===true && "Przedmiot został zaakceptowany"}</b>

View File

@ -10,6 +10,7 @@ import { SelectMenu } from './SelectMenu';
import { studentsContext } from '../contexts/StudentsProvider'; import { studentsContext } from '../contexts/StudentsProvider';
import { CASContext } from '../contexts/CASProvider'; import { CASContext } from '../contexts/CASProvider';
import { render } from 'react-dom'; import { render } from 'react-dom';
import { coursesContext } from '../contexts/CoursesProvider';
const Topbar = styled.div` const Topbar = styled.div`
background-color: #e3e5ed; background-color: #e3e5ed;
@ -112,6 +113,8 @@ const IconWrapper = styled.div`
margin-right: 10px; margin-right: 10px;
`; `;
const Icon = styled.img` const Icon = styled.img`
width: 40px; width: 40px;
margin-left: 40px; margin-left: 40px;
@ -215,9 +218,8 @@ export default function ({ handleTransfer }: TopbarProps) {
</FlexboxColumn> </FlexboxColumn>
<IconWrapper> <IconWrapper>
<SelectedStudent>{selectedStudent?.email.replace(/@st.amu.edu.pl/, '')}</SelectedStudent> <SelectedStudent>{selectedStudent?.email.replace(/@st.amu.edu.pl/, '')}</SelectedStudent>
{/* <Text>Maciej Głowacki</Text> */} {/* <Text>Maciej Głowacki</Text> */}
{userPrivilige==="STUDENT" && <Icon alt="transfer" src={TransferIcon} onClick={handleTransfer} />} {userPrivilige === 'STUDENT' && <Icon alt="transfer" src={TransferIcon} onClick={handleTransfer} />}
{/* <Icon alt="change_language" src={isPolish ? EnglishIcon : PolishIcon} onClick={onLangChange} /> */} {/* <Icon alt="change_language" src={isPolish ? EnglishIcon : PolishIcon} onClick={onLangChange} /> */}
<Icon alt="logout" src={LogoutIcon} onClick={logout} /> <Icon alt="logout" src={LogoutIcon} onClick={logout} />
{/* <Profile anchorEl={anchorEl} handleClose={handleCloseProfile} /> */} {/* <Profile anchorEl={anchorEl} handleClose={handleCloseProfile} /> */}

View File

@ -180,7 +180,7 @@ const ExchangeParagraph = styled.p`
`; `;
export const Transfer = ({ handleClose, isTransferOpen }: TransferProps) => { export const Transfer = ({ handleClose, isTransferOpen }: TransferProps) => {
const { basket, selectBasketCourses } = useContext(coursesContext)!; const { basket, tour, selectBasketCourses } = useContext(coursesContext)!;
// const basketCourseGroups = useMemo(() => selectBasketCourseGroups(course.name), []); // const basketCourseGroups = useMemo(() => selectBasketCourseGroups(course.name), []);
const basketCourses = selectBasketCourses(); const basketCourses = selectBasketCourses();
@ -195,7 +195,6 @@ export const Transfer = ({ handleClose, isTransferOpen }: TransferProps) => {
const [groups, setGroups] = useState<any>([]); const [groups, setGroups] = useState<any>([]);
const [exchanges, setExchanges] = useState<any>(null); const [exchanges, setExchanges] = useState<any>(null);
const [save, setSave] = useState(false); const [save, setSave] = useState(false);
const [tour, setTour] = useState<any>(null);
// const allGroups // const allGroups
const handleSelectedAssignmentsGroupChange = (event: React.ChangeEvent<{ value: unknown }>) => { const handleSelectedAssignmentsGroupChange = (event: React.ChangeEvent<{ value: unknown }>) => {
setSelectedAssignmentsClasses(event.target.value as any); setSelectedAssignmentsClasses(event.target.value as any);
@ -243,7 +242,6 @@ export const Transfer = ({ handleClose, isTransferOpen }: TransferProps) => {
} }
}; };
getExchanges(); getExchanges();
getCurrentTour();
getAssignmentsGroups(); getAssignmentsGroups();
}, [isTransferOpen, save]); }, [isTransferOpen, save]);
@ -261,15 +259,6 @@ export const Transfer = ({ handleClose, isTransferOpen }: TransferProps) => {
setSave(!save); setSave(!save);
}; };
const getCurrentTour = async () => {
try {
const { data } = await axiosInstance.get(`${process.env.REACT_APP_API_URL}/api/v1/configurator/config/tour`);
setTour(data.currentTour);
} catch (e) {
console.log(e);
}
};
const deleteExchange = async (id: number) => { const deleteExchange = async (id: number) => {
try { try {
const response = await axiosInstance.delete(`${process.env.REACT_APP_API_URL}/api/v1/exchanges/exchange/${id}`); const response = await axiosInstance.delete(`${process.env.REACT_APP_API_URL}/api/v1/exchanges/exchange/${id}`);

View File

@ -21,6 +21,8 @@ interface CourseContext {
userID: string; userID: string;
isDataLoading: boolean; isDataLoading: boolean;
historyBasket: Array<Basket>; historyBasket: Array<Basket>;
tour: string;
getCurrentTour: () => void;
addCourseToBasket: (courses: Course) => void; addCourseToBasket: (courses: Course) => void;
changeHoveredGroup: (group: Group | null) => void; changeHoveredGroup: (group: Group | null) => void;
changeGroupInBasket: (group: any, courseId: number) => void; changeGroupInBasket: (group: any, courseId: number) => void;
@ -57,6 +59,7 @@ export const CoursesProvider = ({ children }: CoursesProviderProps) => {
const [userID, setUserID] = useState(''); const [userID, setUserID] = useState('');
const [hoveredGroup, setHoveredGroup] = useState<Group | undefined | null>(null); const [hoveredGroup, setHoveredGroup] = useState<Group | undefined | null>(null);
const [isDataLoading, setIsDataLoading] = useState(false); const [isDataLoading, setIsDataLoading] = useState(false);
const [tour, setTour] = useState('');
const selectBasketIds = () => { const selectBasketIds = () => {
const classesIds = basket.map((course) => course?.classes?.id).filter((course) => course !== undefined); const classesIds = basket.map((course) => course?.classes?.id).filter((course) => course !== undefined);
@ -76,12 +79,12 @@ export const CoursesProvider = ({ children }: CoursesProviderProps) => {
const selectSchedulerEvents = () => { const selectSchedulerEvents = () => {
return basket.reduce((res, el) => { return basket.reduce((res, el) => {
const { name } = el; const { name, symbol } = el;
if (el.classes) { if (el.classes) {
res.push({ ...el.classes, name }); res.push({ ...el.classes, name, symbol});
} }
if (el.lecture) { if (el.lecture) {
res.push({ ...el.lecture, name }); res.push({ ...el.lecture, name, symbol });
} }
return res; return res;
}, [] as Array<SchedulerEvent>); }, [] as Array<SchedulerEvent>);
@ -161,7 +164,7 @@ export const CoursesProvider = ({ children }: CoursesProviderProps) => {
}); });
} catch (e) { } catch (e) {
console.log('error: ', e); console.log('error: ', e);
enqueueSnackbar('Zapisywanie planu nie powiodło się', { enqueueSnackbar('Zapisywanie niemożliwe w czasie bezturowym', {
variant: 'error', variant: 'error',
action, action,
}); });
@ -274,9 +277,19 @@ export const CoursesProvider = ({ children }: CoursesProviderProps) => {
setHistoryBasket(basket); setHistoryBasket(basket);
}; };
const getCurrentTour = async () => {
try {
const { data } = await axiosInstance.get(`${process.env.REACT_APP_API_URL}/api/v1/configurator/config/tour`);
setTour(data.currentTour);
} catch (e) {
console.log(e);
}
};
useEffect(() => { useEffect(() => {
setIsDataLoading(true); setIsDataLoading(true);
setTimeout(() => { setTimeout(() => {
getCurrentTour();
fetchCourses(); fetchCourses();
getNewestTimetable(); getNewestTimetable();
setIsDataLoading(false); setIsDataLoading(false);
@ -293,6 +306,8 @@ export const CoursesProvider = ({ children }: CoursesProviderProps) => {
timetableHistory, timetableHistory,
isDataLoading, isDataLoading,
historyBasket, historyBasket,
tour,
getCurrentTour,
addCourseToBasket, addCourseToBasket,
changeHoveredGroup, changeHoveredGroup,
changeGroupInBasket, changeGroupInBasket,

View File

@ -6,6 +6,7 @@ export enum GroupType {
export interface Basket { export interface Basket {
id: number; id: number;
name: string; name: string;
symbol?:string;
lecture?: Group; lecture?: Group;
classes?: Group; classes?: Group;
} }
@ -21,6 +22,7 @@ export interface Group {
capacity?: number; capacity?: number;
takenPlaces: number; takenPlaces: number;
isAccepted:boolean; isAccepted:boolean;
grNr: number;
} }
export interface Course { export interface Course {
@ -55,6 +57,8 @@ export interface SchedulerEvent {
takenPlaces: number; takenPlaces: number;
name: string; name: string;
isAccepted:boolean; isAccepted:boolean;
grNr?: number;
symbol?:string;
} }
export interface TimetableHistory { export interface TimetableHistory {