Skip to content

Commit

Permalink
Merge branch 'frontend'
Browse files Browse the repository at this point in the history
  • Loading branch information
depocoder committed Nov 10, 2024
2 parents e4c758d + 02f1d83 commit 8a0e45a
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 42 deletions.
17 changes: 5 additions & 12 deletions backend/yet_another_calendar/web/api/bulk/integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from typing import Any, Iterable, Optional

import icalendar
import pytz
from fastapi import HTTPException
from fastapi_cache import default_key_builder, FastAPICache
from fastapi_cache.decorator import cache
Expand Down Expand Up @@ -82,9 +81,9 @@ async def refresh_events(
timezone: str,
) -> schema.RefreshedCalendarResponse:
"""Clear events cache."""
cached_json = await get_cached_calendar(body, lms_user, jwt_token, calendar_id, cookies, timezone)
cached_json = await get_cached_calendar(body, lms_user, jwt_token, calendar_id, cookies)
cached_calendar = schema.CalendarResponse.model_validate(cached_json)
calendar = await get_calendar(body, lms_user, jwt_token, calendar_id, cookies, timezone)
calendar = await get_calendar(body, lms_user, jwt_token, calendar_id, cookies)
changed = cached_calendar.get_hash() != calendar.get_hash()
try:
cache_key = default_key_builder(get_cached_calendar, args=(body, jwt_token, calendar_id, cookies), kwargs={})
Expand All @@ -99,7 +98,7 @@ async def refresh_events(
raise HTTPException(detail="Can't refresh redis", status_code=status.HTTP_500_INTERNAL_SERVER_ERROR) from None
return schema.RefreshedCalendarResponse(
**{**calendar.model_dump(by_alias=True), "changed": changed},
)
).change_timezone(timezone)


async def get_calendar(
Expand All @@ -108,12 +107,7 @@ async def get_calendar(
jwt_token: str,
calendar_id: int,
cookies: netology_schema.NetologyCookies,
timezone: str,
) -> schema.CalendarResponse:
try:
tz = pytz.timezone(timezone)
except pytz.exceptions.UnknownTimeZoneError:
raise HTTPException(detail="Wrong timezone", status_code=status.HTTP_400_BAD_REQUEST) from None
lms_response = None
async with asyncio.TaskGroup() as tg:
netology_response = tg.create_task(netology_views.get_calendar(body, calendar_id, cookies))
Expand All @@ -126,7 +120,7 @@ async def get_calendar(
"modeus_events": modeus_response.result(),
"lms_events": lms_events,
}},
).change_timezone(tz)
)


@cache(expire=settings.redis_events_time_live)
Expand All @@ -136,6 +130,5 @@ async def get_cached_calendar(
jwt_token: str,
calendar_id: int,
cookies: netology_schema.NetologyCookies,
timezone: str,
) -> schema.CalendarResponse:
return await get_calendar(body, lms_user, jwt_token, calendar_id, cookies, timezone)
return await get_calendar(body, lms_user, jwt_token, calendar_id, cookies)
9 changes: 8 additions & 1 deletion backend/yet_another_calendar/web/api/bulk/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
import hashlib
from typing import Self

import pytz
from pydantic import BaseModel, Field
from starlette import status
from starlette.exceptions import HTTPException

from ..modeus import schema as modeus_schema
from ..lms import schema as lms_schema
Expand All @@ -20,7 +23,11 @@ class BulkResponse(BaseModel):
netology: netology_schema.SerializedEvents
utmn: UtmnResponse

def change_timezone(self, timezone: datetime.tzinfo) -> Self:
def change_timezone(self, timezone_name: str) -> Self:
try:
timezone = pytz.timezone(timezone_name)
except pytz.exceptions.UnknownTimeZoneError:
raise HTTPException(detail="Wrong timezone", status_code=status.HTTP_400_BAD_REQUEST) from None
for homework in self.netology.homework:
if homework.deadline:
homework.deadline = homework.deadline.astimezone(timezone)
Expand Down
12 changes: 8 additions & 4 deletions backend/yet_another_calendar/web/api/bulk/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@ async def get_calendar(
Get events from Netology and Modeus, cached.
"""

cached_calendar = await integration.get_cached_calendar(body, lms_user, jwt_token, calendar_id, cookies, time_zone)
return schema.CalendarResponse.model_validate(cached_calendar)
cached_calendar = await integration.get_cached_calendar(body, lms_user, jwt_token, calendar_id, cookies)
if isinstance(cached_calendar, schema.CalendarResponse):
return cached_calendar.change_timezone(time_zone)
# else cached
return schema.CalendarResponse.model_validate(cached_calendar).change_timezone(time_zone)


@router.post("/refresh_events/")
Expand Down Expand Up @@ -61,5 +64,6 @@ async def export_ics(
"""
Export into .ics format
"""
calendar = await integration.get_calendar(body, lms_user, jwt_token, calendar_id, cookies, time_zone)
return StreamingResponse(integration.export_to_ics(calendar))
calendar = await integration.get_calendar(body, lms_user, jwt_token, calendar_id, cookies)
calendar_with_timezone = calendar.change_timezone(time_zone)
return StreamingResponse(integration.export_to_ics(calendar_with_timezone))
2 changes: 2 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ services:
container_name: calendar-frontend
env_file:
- frontend/.env
environment:
REACT_APP_BACKEND_URL: http://127.0.0.1:8000
restart: always
volumes:
- ./frontend/src:/app/src
Expand Down
17 changes: 9 additions & 8 deletions frontend/src/components/Calendar/LessonTimes.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import React, {useEffect, useState} from 'react';
import camera from "../../img/camera.png";

export function formatDateToAMPM(date) {
const hours = date.getHours().toString().padStart(2, '0');
const minutes = date.getMinutes().toString().padStart(2, '0');

return `${hours}:${minutes}`;
}

const LessonTimes = ({ events, selectedEvent, setSelectedEvent }) => {
const [weekDays, setWeekDays] = useState(Array.from({length: 7}, () => []));

Expand Down Expand Up @@ -68,14 +75,8 @@ const LessonTimes = ({ events, selectedEvent, setSelectedEvent }) => {
const lesson = lessons.find(lesson => {
const lessonStartTime = new Date(lesson.start || lesson.starts_at);
const lessonEndTime = new Date(lesson.end || lesson.ends_at);
const lessonStartFormatted = lessonStartTime.toLocaleTimeString([], {
hour: '2-digit',
minute: '2-digit'
});
const lessonEndFormatted = lessonEndTime.toLocaleTimeString([], {
hour: '2-digit',
minute: '2-digit'
});
const lessonStartFormatted = formatDateToAMPM(lessonStartTime);
const lessonEndFormatted = formatDateToAMPM(lessonEndTime);

return (
lessonStartFormatted === timeSlot.split(' - ')[0] ||
Expand Down
41 changes: 24 additions & 17 deletions frontend/src/pages/CalendarRoute.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
bulkEvents,
getTokenFromLocalStorage,
getPersonIdLocalStorage,
getCalendarIdLocalStorage,
} from '../services/api';
import Loader from "../elements/Loader";
import '../style/header.scss';
Expand Down Expand Up @@ -34,26 +35,32 @@ const CalendarRoute = () => {
setError(null);

try {
const courseData = await getNetologyCourse(getTokenFromLocalStorage());
const calendarId = courseData?.id;
localStorage.setItem('calendarId', calendarId);
var calendarId
calendarId = getCalendarIdLocalStorage();
if (!calendarId){
const courseData = await getNetologyCourse(getTokenFromLocalStorage());
calendarId = courseData?.id;
localStorage.setItem('calendarId', calendarId);
}

if (calendarId) {
const eventsResponse = await bulkEvents({
calendarId,
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
attendeePersonId: getPersonIdLocalStorage(),
timeMin: date.start,
timeMax: date.end,
sessionToken: getTokenFromLocalStorage(),
});
if (!calendarId) {
console.error('Ошибка при получении calendar id:', calendarId);
}
const eventsResponse = await bulkEvents({
calendarId,
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
attendeePersonId: getPersonIdLocalStorage(),
timeMin: date.start,
timeMax: date.end,
sessionToken: getTokenFromLocalStorage(),
});

if (eventsResponse?.data) {
setEvents(eventsResponse.data);
} else {
throw new Error('Не удалось получить события');
}
if (eventsResponse?.data) {
setEvents(eventsResponse.data);
} else {
throw new Error('Не удалось получить события');
}

} catch (error) {
console.error('Ошибка при получении данных с сервера:', error);
setError("Ошибка при получении данных с сервера. Перезагрузите страницу!");
Expand Down

0 comments on commit 8a0e45a

Please sign in to comment.