Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
ee88405
set up commit
sagizaidor Jan 16, 2021
1e3b912
working day view with jinja2 template
sagizaidor Jan 17, 2021
8de8f90
Merge branch 'main' of https://github.com/PythonFreeCourse/calendar i…
sagizaidor Jan 17, 2021
43c57ce
with tests for pytest
sagizaidor Jan 17, 2021
b0a8cc4
first functioning day-view html, css and router
sagizaidor Jan 18, 2021
f61c9e4
feat: Basic responsive calender day view page
sagizaidor Jan 18, 2021
3c32513
feat: Basic responsive calender day view page
sagizaidor Jan 19, 2021
41abd94
Merge branch 'develop' into style/dayview
sagizaidor Jan 19, 2021
1cbda2e
fix lint now for sure
sagizaidor Jan 19, 2021
7b7bfd4
Merge branch 'style/dayview' of https://github.com/sagizaidor/calenda…
sagizaidor Jan 19, 2021
15baa62
more lint
sagizaidor Jan 19, 2021
f1463a4
sagizaidor Jan 21, 2021
40628f8
after all notes and started use the orm
sagizaidor Jan 21, 2021
c1b3a12
fixed: changed "size" var in html and and more acuurate typing
sagizaidor Jan 22, 2021
8131ab7
deleted some testing lines
sagizaidor Jan 22, 2021
02f9cb0
Merge branch 'develop' into style/dayview
sagizaidor Jan 22, 2021
253993a
add requirements missing
sagizaidor Jan 22, 2021
813c764
Merge branch 'style/dayview' of https://github.com/sagizaidor/calenda…
sagizaidor Jan 22, 2021
42e6dea
fixed: statements of event select more accurate
sagizaidor Jan 23, 2021
b0f4cf6
new test and lint fix
sagizaidor Jan 23, 2021
f23cac8
added more contants abd more notes taken
sagizaidor Jan 23, 2021
3abd828
Delete Scripts directory
sagizaidor Jan 23, 2021
80d2408
Merge branch 'develop' into style/dayview
sagizaidor Jan 23, 2021
df189bb
update constants
sagizaidor Jan 24, 2021
e7ef9bd
Merge branch 'style/dayview' of https://github.com/sagizaidor/calenda…
sagizaidor Jan 24, 2021
266793b
more notes
sagizaidor Jan 24, 2021
7a64596
forgot white space
sagizaidor Jan 24, 2021
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
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
dev.db
test.db
config.py
.vscode/settings.json

# Byte-compiled / optimized / DLL files
__pycache__/
Expand Down Expand Up @@ -116,6 +117,8 @@ venv/
ENV/
env.bak/
venv.bak/
Scripts/*
pyvenv.cfg

# Spyder project settings
.spyderproject
Expand All @@ -134,3 +137,5 @@ dmypy.json

# Pyre type checker
.pyre/

app/routers/stam
2 changes: 2 additions & 0 deletions app/database/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ class Event(Base):

owner = relationship("User")
owner_id = Column(Integer, ForeignKey("users.id"))
color = Column(String, nullable=True)

participants = relationship("UserEvent", back_populates="events")

def __repr__(self):
Expand Down
4 changes: 3 additions & 1 deletion app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
from app.database.database import engine
from app.dependencies import (
MEDIA_PATH, STATIC_PATH, templates)
from app.routers import agenda, event, profile, email, invitation
from app.routers import agenda, dayview, event, profile, email, invitation


models.Base.metadata.create_all(bind=engine)

Expand All @@ -16,6 +17,7 @@
app.include_router(profile.router)
app.include_router(event.router)
app.include_router(agenda.router)
app.include_router(dayview.router)
app.include_router(email.router)
app.include_router(invitation.router)

Expand Down
113 changes: 113 additions & 0 deletions app/routers/dayview.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
from datetime import datetime, timedelta
from typing import Tuple, Union

from fastapi import APIRouter, Depends, Request
from fastapi.templating import Jinja2Templates
from sqlalchemy import and_, or_

from app.database.database import get_db
from app.database.models import Event, User
from app.dependencies import TEMPLATES_PATH


templates = Jinja2Templates(directory=TEMPLATES_PATH)


router = APIRouter()


class DivAttributes:
GRID_BAR_QUARTER = 1
FULL_GRID_BAR = 4
MIN_MINUTES = 0
MAX_MINUTES = 15
BASE_GRID_BAR = 5
FIRST_GRID_BAR = 1
LAST_GRID_BAR = 101
DEFAULT_COLOR = 'grey'
DEFAULT_FORMAT = "%H:%M"
MULTIDAY_FORMAT = "%d/%m %H:%M"

def __init__(self, event: Event,
day: Union[bool, datetime] = False) -> None:
self.start_time = event.start
self.end_time = event.end
self.day = day
self.start_multiday, self.end_multiday = self._check_multiday_event()
self.color = self._check_color(event.color)
self.total_time = self._set_total_time()
self.grid_position = self._set_grid_position()

def _check_color(self, color: str) -> str:
if color is None:
return self.DEFAULT_COLOR
return color

def _minutes_position(self, minutes: int) -> Union[int, None]:
min_minutes = self.MIN_MINUTES
max_minutes = self.MAX_MINUTES
for i in range(self.GRID_BAR_QUARTER, self.FULL_GRID_BAR + 1):
if min_minutes < minutes <= max_minutes:
return i
min_minutes = max_minutes
max_minutes += 15

def _get_position(self, time: datetime) -> int:
grid_hour_position = time.hour * self.FULL_GRID_BAR
grid_minutes_modifier = self._minutes_position(time.minute)
if grid_minutes_modifier is None:
grid_minutes_modifier = 0
return grid_hour_position + grid_minutes_modifier + self.BASE_GRID_BAR

def _set_grid_position(self) -> str:
if self.start_multiday:
start = self.FIRST_GRID_BAR
else:
start = self._get_position(self.start_time)
if self.end_multiday:
end = self.LAST_GRID_BAR
else:
end = self._get_position(self.end_time)
return f'{start} / {end}'

def _get_time_format(self) -> str:
for multiday in [self.start_multiday, self.end_multiday]:
yield self.MULTIDAY_FORMAT if multiday else self.DEFAULT_FORMAT

def _set_total_time(self) -> None:
length = self.end_time - self.start_time
self.length = length.seconds / 60
format_gen = self._get_time_format()
start_time_str = self.start_time.strftime(next(format_gen))
end_time_str = self.end_time.strftime(next(format_gen))
return ' '.join([start_time_str, '-', end_time_str])

def _check_multiday_event(self) -> Tuple[bool]:
start_multiday, end_multiday = False, False
if self.day:
if self.start_time < self.day:
start_multiday = True
self.day += timedelta(hours=24)
if self.day <= self.end_time:
end_multiday = True
return (start_multiday, end_multiday)


@router.get('/day/{date}')
async def dayview(request: Request, date: str, db_session=Depends(get_db)):
# TODO: add a login session
user = db_session.query(User).filter_by(username='test1').first()
day = datetime.strptime(date, '%Y-%m-%d')
day_end = day + timedelta(hours=24)
events = db_session.query(Event).filter(
Event.owner_id == user.id).filter(
or_(and_(Event.start >= day, Event.start < day_end),
and_(Event.end >= day, Event.end < day_end),
and_(Event.start < day_end, day_end < Event.end)))
events_n_attrs = [(event, DivAttributes(event, day)) for event in events]
return templates.TemplateResponse("dayview.html", {
"request": request,
"events": events_n_attrs,
"month": day.strftime("%B").upper(),
"day": day.day
})
91 changes: 91 additions & 0 deletions app/static/dayview.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@

:root {
--primary:#30465D;
--primary-variant:#FFDE4D;
--secondary:#EF5454;
--borders:#E7E7E7;
--borders-variant:#F7F7F7;
}

html {
font-family: 'Assistant', sans-serif;
text-align: center;
}

#toptab {
background-color: var(--primary);
}

.schedule {
display: grid;
grid-template-rows: 1;
}

.times {
margin-top: 0.65em;
grid-row: 1 / -1;
grid-column: 1 / -1;
z-index: 40;
}

.baselines {
grid-row: 1 / -1;
grid-column: 1 / -1;
z-index: 38;
}

.eventgrid {
grid-row: 1 / -1;
grid-column: 1 / -1;
display: grid;
grid-template-rows: repeat(100, 0.375rem);
z-index: 39;
}

.hourbar {
margin-top: -1px;
}

.event {
font-size: 1rem;
}

.total-time {
font-size: 0.4rem;
line-height: 1rem;
}

.title_size_small {
font-size: 0.6em;
}

.title_size_Xsmall {
font-size: 0.4em;
}

.title_size_tiny {
font-size: 0.1em;
line-height: 4em;
}

.actiongrid {
grid-row: 1 / -1;
grid-column: 1 / -1;
display: grid;
grid-template-rows: repeat(100, 0.375rem);
z-index: 42;
}

.action-icon {
visibility: hidden;
}

.action-continer:hover {
border-top: 1px dashed var(--borders);
border-bottom: 1px dashed var(--borders);
transition: 0.3;
}

.action-continer:hover .action-icon {
visibility: visible;
}
1 change: 1 addition & 0 deletions app/static/images/icons/close_sidebar.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions app/static/images/icons/pencil.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions app/static/images/icons/trash-can.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
63 changes: 63 additions & 0 deletions app/templates/dayview.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
<link rel="stylesheet" href="{{ url_for('static', path='/dayview.css') }}">
<link href="https://fonts.googleapis.com/css2?family=Assistant&family=Open+Sans&family=Roboto&family=Roboto+Condensed&display=swap" rel="stylesheet">
<title>dayview</title>
</head>
<body>
<div id="toptab" class="d-flex justify-content-around sticky-top">
<a href="/closethedayview" title="close day view"><img class="pb-1" src="{{ url_for('static', path='/images/icons/close_sidebar.svg')}}" width="15em" height="15em"></a>
<span class="month fw-bold text-white">{{month}}</span>
<span class="day fw-bold text-white">{{day}}</span>
</div>
<div class="schedule">
<div class="container times bg-primeary position">
{% for i in range(24)%}
<div class="row bg-transparent hourmark">
{% set i = i|string() %}
{{i.zfill(2)}}:00
</div>
{% endfor %}
</div>
<div class="eventgrid">
{% for event, attr in events %}
{% set totaltime = 'visible'%}
{% if attr.length < 60 %}
{% set size = 'title_size_small' %}
{% set totaltime = 'invisible'%}
{% if attr.length < 45 %}
{% set size = 'title_size_Xsmall' %}
{% if attr.length < 30 %}
{% set size = 'title_size_tiny' %}
{% endif %}
{% endif %}
{% endif %}
<div id="event{{event.id}}" class="text-truncate px-5 d-flex flex-column justify-content-evenly event" style="background-color: {{attr.color}}; grid-row: {{attr.grid_position}}; max-hight:1.5rem;">
<p class="text-truncate my-0 {{size}}">{{ event.title }}</p>
{% if totaltime == 'visible' %}
<p class="total-time text-truncate fw-light my-0">{{attr.total_time}}</p>
{% endif %}
</div>
{% endfor %}
</div>
<div class="container baselines bg-transparent">
{% for i in range(25)%}
<div class="hourbar {{i}} row text-white border-bottom">---</div>
{% endfor %}
</div>
<div class="actiongrid">
{% for event, attr in events %}
<div class="d-flex flex-row justify-content-around align-items-end action-continer" style="grid-row: {{attr.grid_position}};">
<a href="/edit/{{event.id}}" title="Edit event" class="action-icon"><img class="pb-1" src="{{ url_for('static', path='/images/icons/pencil.svg')}}" width="15em" height="15em"></a>
<a href="/delete/{{event.id}}" title="Delete event" class="action-icon"><img class="pb-1" src="{{ url_for('static', path='/images/icons/trash-can.svg')}}" width="15em" height="15em"></a>
</div>
{% endfor %}
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW" crossorigin="anonymous"></script>
</body>
</html>
7 changes: 7 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
aiofiles==0.6.0
apipkg==1.5
arrow==0.17.0
atomicwrites==1.4.0
attrs==20.3.0
beautifulsoup4==4.9.3
certifi==2020.12.5
chardet==4.0.0
click==7.1.2
colorama==0.4.4
coverage==5.3.1
execnet==1.7.1
fastapi==0.63.0
fastapi_mail==0.3.3.1
faker==5.6.2
Expand All @@ -29,14 +32,18 @@ py==1.10.0
pydantic==1.7.3
pyparsing==2.4.7
pytest==6.2.1
pytest-asyncio==0.14.0
pytest-cov==2.10.1
pytest-forked==1.3.0
pytest-xdist==2.2.0
python-dateutil==2.8.1
python-dotenv==0.15.0
python-multipart==0.0.5
pytz==2020.5
PyYAML==5.3.1
requests==2.25.1
six==1.15.0
soupsieve==2.1
SQLAlchemy==1.3.22
starlette==0.13.6
toml==0.10.2
Expand Down
Loading