Skip to content

Commit a1f2998

Browse files
authored
Style/grid (#106)
* Hello Wrold * Creating Html Template * Calendar dates calculation intigrating with html, HTML\CSS improvments. * Tests for calender_grid.py, changing function according to currections, fixing bugs * linting bug fixing * before merge with develop * Creating a Day object and days subclasses, changing all function and tests according to the new objects, Changing front to get information from Day objects, Re-arranging calendar.html grid stracture to be render by weeks, adding js functionality for day view section, adding css effects on daily event display * fix lintings * fix lintings * tests next week scroll * js updates * Calendar Scrolling with javascript * Fix lintings * Fix lintings * Calendar infinit scrolling ducplicates weeks bug fixed * seetings global parameters for calendar.py * Js - changing to fetch, removing jquery, fixing hint tpying, adding Week object, changing tests * Front end bug fixing * Fix linting * Fix lintings * Fix lintings * fixing syntax * Get user local date and time when enter calendar. * Fix lintings * Fix lintings * Fix lintings * Bugs fixing * Bugs fixing * Bugs fixing * Bugs fixing * JS alerts removal * Fix Lintings * Js syntext fixing * Bugs fixing * Bugs fixing * Js fixing varibales and adding div element to request. * Develop Update * Js - eliminate global parameters * Linting fixing * Fix Lintings * Fix flake8 * syntac fixing
1 parent b8e0992 commit a1f2998

File tree

13 files changed

+853
-16
lines changed

13 files changed

+853
-16
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ __pycache__/
1313
# Distribution / packaging
1414
.Python
1515
build/
16+
Scripts/
17+
include/
1618
develop-eggs/
1719
dist/
1820
downloads/
@@ -30,6 +32,8 @@ share/python-wheels/
3032
.installed.cfg
3133
*.egg
3234
MANIFEST
35+
pyvenv.cfg
36+
3337

3438
# PyInstaller
3539
# Usually these files are written by a python script from a template
@@ -116,6 +120,7 @@ venv/
116120
ENV/
117121
env.bak/
118122
venv.bak/
123+
.vscode/
119124
Scripts/*
120125
pyvenv.cfg
121126

app/main.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
from app.dependencies import (logger, MEDIA_PATH, STATIC_PATH, templates)
99
from app.internal.quotes import daily_quotes, load_quotes
1010
from app.routers import (
11-
agenda, categories, dayview, email, event, invitation, profile, search,
12-
telegram, whatsapp
11+
agenda, calendar, categories, dayview, email,
12+
event, invitation, profile, search, telegram, whatsapp
1313
)
1414
from app.telegram.bot import telegram_bot
1515

@@ -36,6 +36,7 @@ def create_tables(engine, psql_environment):
3636

3737
routers_to_include = [
3838
agenda.router,
39+
calendar.router,
3940
categories.router,
4041
dayview.router,
4142
email.router,

app/routers/calendar.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from http import HTTPStatus
2+
3+
from app.dependencies import templates
4+
from app.routers import calendar_grid as cg
5+
from fastapi import APIRouter, Request
6+
from fastapi.responses import HTMLResponse
7+
from starlette.responses import Response
8+
9+
router = APIRouter(
10+
prefix="/calendar/month",
11+
tags=["calendar"],
12+
responses={404: {"description": "Not found"}},
13+
)
14+
15+
ADD_DAYS_ON_SCROLL: int = 42
16+
17+
18+
@router.get("/")
19+
async def calendar(request: Request) -> Response:
20+
user_local_time = cg.Day.get_user_local_time()
21+
day = cg.create_day(user_local_time)
22+
return templates.TemplateResponse(
23+
"calendar/calendar.html",
24+
{
25+
"request": request,
26+
"day": day,
27+
"week_days": cg.Week.DAYS_OF_THE_WEEK,
28+
"weeks_block": cg.get_month_block(day)
29+
}
30+
)
31+
32+
33+
@router.get("/{date}")
34+
async def update_calendar(request: Request, date: str) -> HTMLResponse:
35+
last_day = cg.Day.convert_str_to_date(date)
36+
next_weeks = cg.create_weeks(cg.get_n_days(last_day, ADD_DAYS_ON_SCROLL))
37+
template = templates.get_template('calendar/add_week.html')
38+
content = template.render(weeks_block=next_weeks)
39+
return HTMLResponse(content=content, status_code=HTTPStatus.OK)

app/routers/calendar_grid.py

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
import calendar
2+
import itertools
3+
import locale
4+
from datetime import date, datetime, timedelta
5+
from typing import Dict, Iterator, List, Tuple
6+
7+
import pytz
8+
9+
MONTH_BLOCK: int = 6
10+
11+
locale.setlocale(locale.LC_TIME, ("en", "UTF-8"))
12+
13+
14+
class Day:
15+
"""A Day class.
16+
17+
Args:
18+
date (datetime): A single datetime date.
19+
Arguments:
20+
date (datetime): A single datetime date.
21+
sday (str): The day name.
22+
dailyevents (List): List of tuples represent daily event information.
23+
events (List): List of tuples represent time event name.
24+
EX: [("09AP", "Meeting with yam")]
25+
css (Dict): All css classes represent day.
26+
"""
27+
28+
def __init__(self, date: datetime):
29+
self.date: datetime = date
30+
self.sday: str = self.date.strftime("%A")
31+
self.dailyevents: List[Tuple] = []
32+
self.events: List[Tuple] = []
33+
self.css: Dict[str, str] = {
34+
'day_container': 'day',
35+
'date': 'day-number',
36+
'daily_event': 'month-event',
37+
'daily_event_front': ' '.join([
38+
'daily',
39+
'front',
40+
'background-warmyellow'
41+
]),
42+
'daily_event_back': ' '.join([
43+
'daily',
44+
'back',
45+
'text-darkblue',
46+
'background-lightgray'
47+
]),
48+
'event': 'event',
49+
}
50+
51+
def __str__(self) -> str:
52+
return self.date.strftime("%d")
53+
54+
def display(self) -> str:
55+
"""Returns day date inf the format of 00 MONTH 00"""
56+
return self.date.strftime("%d %B %y").upper()
57+
58+
def set_id(self) -> str:
59+
"""Returns day date inf the format of 00-mon-0000"""
60+
return self.date.strftime("%d-%b-%Y")
61+
62+
@classmethod
63+
def get_user_local_time(cls) -> datetime:
64+
greenwich = pytz.timezone('GB')
65+
return greenwich.localize(datetime.now())
66+
67+
@classmethod
68+
def convert_str_to_date(cls, date_string: str) -> datetime:
69+
return datetime.strptime(date_string, '%d-%b-%Y')
70+
71+
@classmethod
72+
def is_weekend(cls, date: date) -> bool:
73+
"""Returns true if this day is represent a weekend."""
74+
return date.strftime("%A") in Week.DAYS_OF_THE_WEEK[-2:]
75+
76+
77+
class DayWeekend(Day):
78+
def __init__(self, date: datetime):
79+
super().__init__(date)
80+
self.css = {
81+
'day_container': 'day ',
82+
'date': ' '.join(['day-number', 'text-gray']),
83+
'daily_event': 'month-event',
84+
'daily_event_front': ' '.join([
85+
'daily',
86+
'front',
87+
'background-warmyellow'
88+
]),
89+
'daily_event_back': ' '.join([
90+
'daily',
91+
'back',
92+
'text-darkblue',
93+
'background-lightgray'
94+
]),
95+
'event': 'event',
96+
}
97+
98+
99+
class Today(Day):
100+
def __init__(self, date: datetime):
101+
super().__init__(date)
102+
self.css = {
103+
'day_container': ' '.join([
104+
'day',
105+
'text-darkblue',
106+
'background-yellow'
107+
]),
108+
'date': 'day-number',
109+
'daily_event': 'month-event',
110+
'daily_event_front': ' '.join([
111+
'daily',
112+
'front',
113+
'text-lightgray',
114+
'background-darkblue'
115+
]),
116+
'daily_event_back': ' '.join([
117+
'daily',
118+
'back',
119+
'text-darkblue',
120+
'background-lightgray'
121+
]),
122+
'event': 'event',
123+
}
124+
125+
126+
class FirstDayMonth(Day):
127+
def __init__(self, date: datetime):
128+
super().__init__(date)
129+
self.css = {
130+
'day_container': ' '.join([
131+
'day',
132+
'text-darkblue',
133+
'background-lightgray'
134+
]),
135+
'date': 'day-number',
136+
'daily_event': 'month-event',
137+
'daily_event_front': ' '.join([
138+
'daily front',
139+
'text-lightgray',
140+
'background-red'
141+
]),
142+
'daily_event_back': ' '.join([
143+
'daily',
144+
'back',
145+
'text-darkblue',
146+
'background-lightgray'
147+
]),
148+
'event': 'event',
149+
}
150+
151+
def __str__(self) -> str:
152+
return self.date.strftime("%d %b %y").upper()
153+
154+
155+
class Week:
156+
WEEK_DAYS: int = 7
157+
DAYS_OF_THE_WEEK: List[str] = calendar.day_name
158+
159+
def __init__(self, days: List[Day]):
160+
self.days: List[Day] = days
161+
162+
163+
def create_day(day: datetime) -> Day:
164+
"""Return the currect day object according to given date."""
165+
if day == date.today():
166+
return Today(day)
167+
if int(day.day) == 1:
168+
return FirstDayMonth(day)
169+
if Day.is_weekend(day):
170+
return DayWeekend(day)
171+
return Day(day)
172+
173+
174+
def get_next_date(date: datetime) -> Iterator[Day]:
175+
"""Generate date objects from a starting given date."""
176+
yield from (
177+
create_day(date + timedelta(days=i))
178+
for i in itertools.count(start=1)
179+
)
180+
181+
182+
def get_date_before_n_days(date: datetime, n: int) -> datetime:
183+
"""Returns the date before n days."""
184+
return date - timedelta(days=n)
185+
186+
187+
def get_first_day_month_block(date: datetime) -> datetime:
188+
"""Returns the first date in a month block of given date."""
189+
return list(calendar.Calendar().itermonthdates(date.year, date.month))[0]
190+
191+
192+
def get_n_days(date: datetime, n: int) -> Iterator[Day]:
193+
"""Generate n dates from a starting given date."""
194+
next_date_gen = get_next_date(date)
195+
yield from itertools.islice(next_date_gen, n)
196+
197+
198+
def create_weeks(
199+
days: Iterator[Day],
200+
length: int = Week.WEEK_DAYS
201+
) -> List[Week]:
202+
"""Return lists of Weeks objects."""
203+
ndays: List[Day] = list(days)
204+
num_days: int = len(ndays)
205+
return [Week(ndays[i:i + length]) for i in range(0, num_days, length)]
206+
207+
208+
def get_month_block(day: Day, n: int = MONTH_BLOCK) -> List[Week]:
209+
"""Returns a 2D list represent a n days calendar from current month."""
210+
current = get_first_day_month_block(day.date) - timedelta(days=1)
211+
num_of_days = Week.WEEK_DAYS * n
212+
return create_weeks(get_n_days(current, num_of_days))

0 commit comments

Comments
 (0)