Merge pull request 'Admin' (#49) from Admin into master
Reviewed-on: http://git.plannaplan.pl/y0rune/frontend/pulls/49 Reviewed-by: wrzesinski-hubert <wrzesinski.hubert@gmail.com>
This commit is contained in:
commit
72782880c0
@ -7,7 +7,6 @@ import styled, { css } from 'styled-components';
|
|||||||
import { makeStyles } from '@material-ui/core/styles';
|
import { makeStyles } from '@material-ui/core/styles';
|
||||||
import DeleteIcon from '@material-ui/icons/Delete';
|
import DeleteIcon from '@material-ui/icons/Delete';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { createClassTime } from '../utils';
|
|
||||||
import { dayMapping } from '../constants';
|
import { dayMapping } from '../constants';
|
||||||
|
|
||||||
const CourseCardWrapper = styled.div`
|
const CourseCardWrapper = styled.div`
|
||||||
@ -219,12 +218,9 @@ export const CourseCard = ({ course }: CourseCardProps) => {
|
|||||||
</FlexItem>
|
</FlexItem>
|
||||||
)}
|
)}
|
||||||
<FlexItem style={{ justifyContent: 'center', flexDirection: 'column' }}>
|
<FlexItem style={{ justifyContent: 'center', flexDirection: 'column' }}>
|
||||||
{/* <span>
|
|
||||||
{dayMapping[group.day]} {createClassTime(group.time)[0]} - {createClassTime(group.time)[1]}
|
|
||||||
</span> */}
|
|
||||||
<div>{dayMapping[group.day]}</div>
|
<div>{dayMapping[group.day]}</div>
|
||||||
<div>
|
<div>
|
||||||
{createClassTime(group.time)[0]} - {createClassTime(group.time)[1]}
|
{group.time} - {group.endTime}
|
||||||
</div>
|
</div>
|
||||||
</FlexItem>
|
</FlexItem>
|
||||||
</FlexboxWrapper>
|
</FlexboxWrapper>
|
||||||
|
@ -77,7 +77,7 @@ const StyledSchedulerEvent = styled.div<SchedulerEventProps>`
|
|||||||
`}
|
`}
|
||||||
transition: background-color ease-out 0.4s;
|
transition: background-color ease-out 0.4s;
|
||||||
box-shadow: 3px 3px 3px 0px rgba(0, 0, 0, 0.75);
|
box-shadow: 3px 3px 3px 0px rgba(0, 0, 0, 0.75);
|
||||||
cursor:pointer;
|
cursor: pointer;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const threeStyles = () => {
|
const threeStyles = () => {
|
||||||
@ -189,12 +189,16 @@ export const SchedulerRow = ({ groups, indexRow, rowTop, cellWidth, cellHeight }
|
|||||||
<BoldParagraph isThree={groupsPerDay[group.day] >= 3}>{groups[index].name}</BoldParagraph>
|
<BoldParagraph isThree={groupsPerDay[group.day] >= 3}>{groups[index].name}</BoldParagraph>
|
||||||
{groupsPerDay[group.day] < 3 ? (
|
{groupsPerDay[group.day] < 3 ? (
|
||||||
<TextWrapper>
|
<TextWrapper>
|
||||||
<div>{`${groups[index].time[0]}-${groups[index].time[1]}`}</div>
|
<div>{`${groups[index].time}-${groups[index].endTime}`}</div>
|
||||||
<div>3/{groups[index].capacity}</div>
|
<div>
|
||||||
|
{groups[index].takenPlaces}/{groups[index].capacity}
|
||||||
|
</div>
|
||||||
</TextWrapper>
|
</TextWrapper>
|
||||||
) : (
|
) : (
|
||||||
<TextWrapper style={{ flexDirection: 'column' }}>
|
<TextWrapper style={{ flexDirection: 'column' }}>
|
||||||
<div style={{ alignSelf: 'flex-end' }}>3/{groups[index].capacity}</div>
|
<div style={{ alignSelf: 'flex-end' }}>
|
||||||
|
{groups[index].takenPlaces}/{groups[index].capacity}
|
||||||
|
</div>
|
||||||
</TextWrapper>
|
</TextWrapper>
|
||||||
)}
|
)}
|
||||||
</ClassWrap>
|
</ClassWrap>
|
||||||
|
@ -6,6 +6,7 @@ export interface CASContext {
|
|||||||
user: LoggedUser | undefined;
|
user: LoggedUser | undefined;
|
||||||
logout: () => void;
|
logout: () => void;
|
||||||
token: string | undefined;
|
token: string | undefined;
|
||||||
|
refreshToken: string | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CASContext = createContext<CASContext | undefined>(undefined);
|
export const CASContext = createContext<CASContext | undefined>(undefined);
|
||||||
@ -17,6 +18,7 @@ export interface CASProviderProps {
|
|||||||
export const CASProvider = ({ children }: CASProviderProps) => {
|
export const CASProvider = ({ children }: CASProviderProps) => {
|
||||||
const [user, setUser] = useState<LoggedUser>();
|
const [user, setUser] = useState<LoggedUser>();
|
||||||
const [token, setToken] = useState<string | undefined>();
|
const [token, setToken] = useState<string | undefined>();
|
||||||
|
const [refreshToken, setRefreshToken] = useState<string | undefined>();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const login = async () => {
|
const login = async () => {
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
@ -26,15 +28,19 @@ export const CASProvider = ({ children }: CASProviderProps) => {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (!localStorage.getItem('userToken')) {
|
if (!localStorage.getItem('userToken')) {
|
||||||
const { data: user } = await axiosInstance.get<LoggedUser & { token: string }>(
|
const { data: user } = await axiosInstance.get<LoggedUser & { token: string; refreshToken: string }>(
|
||||||
`${process.env.REACT_APP_API_URL}/token?ticket=${ticket}`,
|
`${process.env.REACT_APP_API_URL}/token?ticket=${ticket}`,
|
||||||
);
|
);
|
||||||
|
console.log('token response: ', user);
|
||||||
setUser({ authorityRole: user.authorityRole, email: user.email, id: user.id });
|
setUser({ authorityRole: user.authorityRole, email: user.email, id: user.id });
|
||||||
localStorage.setItem('userToken', user.token);
|
localStorage.setItem('userToken', user.token);
|
||||||
localStorage.setItem('userPrivilige', user.authorityRole);
|
localStorage.setItem('userPrivilige', user.authorityRole);
|
||||||
|
localStorage.setItem('refreshToken', user.refreshToken);
|
||||||
}
|
}
|
||||||
const token = localStorage.getItem('userToken');
|
const token = localStorage.getItem('userToken');
|
||||||
|
const refreshToken = localStorage.getItem('refreshToken');
|
||||||
token && setToken(token);
|
token && setToken(token);
|
||||||
|
refreshToken && setRefreshToken(refreshToken);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
}
|
||||||
@ -44,6 +50,7 @@ export const CASProvider = ({ children }: CASProviderProps) => {
|
|||||||
|
|
||||||
function logout() {
|
function logout() {
|
||||||
localStorage.removeItem('userToken');
|
localStorage.removeItem('userToken');
|
||||||
|
localStorage.removeItem('refreshToken');
|
||||||
localStorage.removeItem('userPrivilige');
|
localStorage.removeItem('userPrivilige');
|
||||||
redirectToCASLogoutService();
|
redirectToCASLogoutService();
|
||||||
}
|
}
|
||||||
@ -56,5 +63,5 @@ export const CASProvider = ({ children }: CASProviderProps) => {
|
|||||||
window.location.replace(`https://cas.amu.edu.pl/cas/login?service=${window.origin}&locale=pl`);
|
window.location.replace(`https://cas.amu.edu.pl/cas/login?service=${window.origin}&locale=pl`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <CASContext.Provider value={{ user, token, logout }}>{children}</CASContext.Provider>;
|
return <CASContext.Provider value={{ user, token, refreshToken, logout }}>{children}</CASContext.Provider>;
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React, { useState, createContext, useEffect, ReactNode } from 'react';
|
import React, { useState, createContext, useEffect, ReactNode } from 'react';
|
||||||
import { Course, Group, Basket, GroupType, SchedulerEvent } from '../types';
|
import { Course, Group, Basket, GroupType, SchedulerEvent } from '../types';
|
||||||
import { useSnackbar } from 'notistack';
|
import { useSnackbar } from 'notistack';
|
||||||
import { createClassTime } from '../utils';
|
|
||||||
import { axiosInstance } from '../utils/axiosInstance';
|
import { axiosInstance } from '../utils/axiosInstance';
|
||||||
import CloseIcon from '@material-ui/icons/Close';
|
import CloseIcon from '@material-ui/icons/Close';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
@ -71,12 +70,13 @@ export const CoursesProvider = ({ children }: CoursesProviderProps) => {
|
|||||||
return basket.reduce((res, el) => {
|
return basket.reduce((res, el) => {
|
||||||
const { name } = el;
|
const { name } = el;
|
||||||
if (el.classes) {
|
if (el.classes) {
|
||||||
const { time } = el.classes;
|
console.log('element kurwa is: ', el);
|
||||||
res.push({ ...el.classes, name, time: createClassTime(time) });
|
res.push({ ...el.classes, name });
|
||||||
}
|
}
|
||||||
if (el.lecture) {
|
if (el.lecture) {
|
||||||
const { time } = el.lecture;
|
console.log('element kurwa is: ', el);
|
||||||
res.push({ ...el.lecture, name, time: createClassTime(time) });
|
|
||||||
|
res.push({ ...el.lecture, name });
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}, [] as Array<SchedulerEvent>);
|
}, [] as Array<SchedulerEvent>);
|
||||||
@ -175,8 +175,12 @@ export const CoursesProvider = ({ children }: CoursesProviderProps) => {
|
|||||||
|
|
||||||
const getNewestTimetable = async () => {
|
const getNewestTimetable = async () => {
|
||||||
try {
|
try {
|
||||||
const { data } = await axiosInstance.get(`${process.env.REACT_APP_API_URL}/api/v1/commisions/user/schedule`);
|
const { data } = await axiosInstance.get<Array<Basket> | ''>(
|
||||||
|
`${process.env.REACT_APP_API_URL}/api/v1/commisions/user/schedule`,
|
||||||
|
);
|
||||||
const basket = data === '' ? [] : data;
|
const basket = data === '' ? [] : data;
|
||||||
|
console.log('basket is: ', basket);
|
||||||
|
console.log('mordo weź');
|
||||||
setBasket(basket);
|
setBasket(basket);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
@ -189,6 +193,7 @@ export const CoursesProvider = ({ children }: CoursesProviderProps) => {
|
|||||||
`${process.env.REACT_APP_API_URL}/api/v1/commisions/user/${studentId}/schedule`,
|
`${process.env.REACT_APP_API_URL}/api/v1/commisions/user/${studentId}/schedule`,
|
||||||
);
|
);
|
||||||
const basket = data === '' ? [] : data;
|
const basket = data === '' ? [] : data;
|
||||||
|
|
||||||
setBasket(basket);
|
setBasket(basket);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
@ -198,13 +203,14 @@ export const CoursesProvider = ({ children }: CoursesProviderProps) => {
|
|||||||
const fetchCourses = async () => {
|
const fetchCourses = async () => {
|
||||||
try {
|
try {
|
||||||
const { data: courses } = await axiosInstance.get<Array<Course>>(
|
const { data: courses } = await axiosInstance.get<Array<Course>>(
|
||||||
`${process.env.REACT_APP_API_URL}/api/v1/courses/all?groups=true`,
|
`${process.env.REACT_APP_API_URL}/api/v1/courses/all?groups=true&takenPlaces=true`,
|
||||||
);
|
);
|
||||||
const sortedCourses = courses.sort((a, b) => (a.name > b.name ? 1 : -1));
|
const sortedCourses = courses.sort((a, b) => (a.name > b.name ? 1 : -1));
|
||||||
|
console.log('sortedCourses: ', sortedCourses);
|
||||||
setCourses(sortedCourses);
|
setCourses(sortedCourses);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -20,8 +20,6 @@ export const StudentsProvider = ({ children }: StudentsProviderProps) => {
|
|||||||
const [selectedStudent, setSelectedStudent] = useState<Student | null>(null);
|
const [selectedStudent, setSelectedStudent] = useState<Student | null>(null);
|
||||||
|
|
||||||
//not working currently
|
//not working currently
|
||||||
const userPrivilige = localStorage.getItem('userPrivilige');
|
|
||||||
const { user } = useContext(CASContext)!;
|
|
||||||
|
|
||||||
const getStudents = async () => {
|
const getStudents = async () => {
|
||||||
try {
|
try {
|
||||||
@ -41,8 +39,9 @@ export const StudentsProvider = ({ children }: StudentsProviderProps) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// user?.authorityRole === 'DEANERY' &&
|
const userPrivilige = localStorage.getItem('userPrivilige');
|
||||||
getStudents();
|
console.log('mordo privilidż: ', userPrivilige);
|
||||||
|
userPrivilige === 'DEANERY' && getStudents();
|
||||||
}, 500);
|
}, 500);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
@ -14,10 +14,12 @@ export interface Group {
|
|||||||
id: number;
|
id: number;
|
||||||
day: number;
|
day: number;
|
||||||
time: string;
|
time: string;
|
||||||
|
endTime: string;
|
||||||
lecturer: string;
|
lecturer: string;
|
||||||
room: string;
|
room: string;
|
||||||
type: GroupType;
|
type: GroupType;
|
||||||
capacity?: number;
|
capacity?: number;
|
||||||
|
takenPlaces: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Course {
|
export interface Course {
|
||||||
@ -43,10 +45,12 @@ export interface Student {
|
|||||||
export interface SchedulerEvent {
|
export interface SchedulerEvent {
|
||||||
id: number;
|
id: number;
|
||||||
day: number;
|
day: number;
|
||||||
time: [string, string];
|
time: string;
|
||||||
|
endTime: string;
|
||||||
lecturer: string;
|
lecturer: string;
|
||||||
room: string;
|
room: string;
|
||||||
type: GroupType;
|
type: GroupType;
|
||||||
capacity?: number;
|
capacity?: number;
|
||||||
|
takenPlaces: number;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -2,15 +2,47 @@ import axios from 'axios';
|
|||||||
|
|
||||||
export const axiosInstance = axios.create();
|
export const axiosInstance = axios.create();
|
||||||
|
|
||||||
|
//getting new tokens
|
||||||
|
const getNewTokens = async () => {
|
||||||
|
try {
|
||||||
|
const refreshToken = localStorage.getItem('refreshToken');
|
||||||
|
const { data } = await axiosInstance.get(
|
||||||
|
`${process.env.REACT_APP_API_URL}/token/refresh?refreshToken=${refreshToken}`,
|
||||||
|
);
|
||||||
|
localStorage.setItem('userToken', data.token);
|
||||||
|
localStorage.setItem('refreshToken', data.refreshToken);
|
||||||
|
return data.token;
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
axiosInstance.interceptors.request.use(
|
axiosInstance.interceptors.request.use(
|
||||||
(config) => {
|
(request) => {
|
||||||
const token = localStorage.getItem('userToken');
|
const token = localStorage.getItem('userToken');
|
||||||
|
|
||||||
config.headers['Content-Type'] = 'application/json';
|
request.headers['Content-Type'] = 'application/json';
|
||||||
config.headers['Authorization'] = token ? `Bearer ${token}` : '';
|
request.headers['Authorization'] = token ? `Bearer ${token}` : '';
|
||||||
return config;
|
return request;
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
Promise.reject(error);
|
Promise.reject(error);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Response interceptor for API calls
|
||||||
|
axiosInstance.interceptors.response.use(
|
||||||
|
(response) => {
|
||||||
|
return response;
|
||||||
|
},
|
||||||
|
async (error) => {
|
||||||
|
const originalRequest = error.config;
|
||||||
|
if (error.response.status === 403 && !originalRequest._retry) {
|
||||||
|
originalRequest._retry = true;
|
||||||
|
const access_token = await getNewTokens();
|
||||||
|
axios.defaults.headers.common['Authorization'] = `Bearer ${access_token}`;
|
||||||
|
return axiosInstance(originalRequest);
|
||||||
|
}
|
||||||
|
return Promise.reject(error);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
@ -1,21 +1,12 @@
|
|||||||
import { courseStartTimeToEventRow } from '../constants/index';
|
import { courseStartTimeToEventRow } from '../constants/index';
|
||||||
import { SchedulerEvent } from '../types';
|
import { SchedulerEvent } from '../types';
|
||||||
|
|
||||||
export const createClassTime = (startTime: string): [string, string] => {
|
|
||||||
const startTimeMapped = courseStartTimeToEventRow[startTime];
|
|
||||||
const endTime = Object.keys(courseStartTimeToEventRow).find(
|
|
||||||
(key) => courseStartTimeToEventRow[key] === startTimeMapped + 1,
|
|
||||||
)!;
|
|
||||||
return [startTime, endTime];
|
|
||||||
};
|
|
||||||
|
|
||||||
export const selectGroupsToShow = (schedulerEvents: Array<SchedulerEvent>, index: number) => {
|
export const selectGroupsToShow = (schedulerEvents: Array<SchedulerEvent>, index: number) => {
|
||||||
return schedulerEvents.filter(({ time }: { time: [string, string] }) => courseStartTimeToEventRow[time[0]] === index);
|
return schedulerEvents.filter((schedulerEvent) => courseStartTimeToEventRow[schedulerEvent.time] === index);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//debounce declaration and implementation
|
//debounce declaration and implementation
|
||||||
type Procedure = (...args: any[]) => any;
|
type Procedure = (...args: any[]) => any;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user