Skip to content

Commit bd9ccb0

Browse files
authored
feat: Add zodiac signs to the day & month view + refactor json data loader (#155)
* feat: Add zodiac signs to the day/month view +
1 parent 69517a7 commit bd9ccb0

30 files changed

+567
-76
lines changed

app/database/models.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,3 +157,22 @@ class Quote(Base):
157157
id = Column(Integer, primary_key=True, index=True)
158158
text = Column(String, nullable=False)
159159
author = Column(String)
160+
161+
162+
class Zodiac(Base):
163+
__tablename__ = "zodiac-signs"
164+
165+
id = Column(Integer, primary_key=True, index=True)
166+
name = Column(String, nullable=False)
167+
start_month = Column(Integer, nullable=False)
168+
start_day_in_month = Column(Integer, nullable=False)
169+
end_month = Column(Integer, nullable=False)
170+
end_day_in_month = Column(Integer, nullable=False)
171+
172+
def __repr__(self):
173+
return (
174+
f'<Zodiac '
175+
f'{self.name} '
176+
f'{self.start_day_in_month}/{self.start_month}-'
177+
f'{self.end_day_in_month}/{self.end_month}>'
178+
)

app/internal/quotes/daily_quotes.py renamed to app/internal/daily_quotes.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from datetime import date
2-
from typing import Optional
2+
from typing import Dict, Optional
33

44
from app.database.models import Quote
55

@@ -9,6 +9,15 @@
99
TOTAL_DAYS = 366
1010

1111

12+
def create_quote_object(quotes_fields: Dict[str, Optional[str]]) -> Quote:
13+
"""This function create a quote object from given fields dictionary.
14+
It is used for adding the data from the json into the db"""
15+
return Quote(
16+
text=quotes_fields['text'],
17+
author=quotes_fields['author']
18+
)
19+
20+
1221
def quote_per_day(
1322
session: Session, date: date = date.today()
1423
) -> Optional[Quote]:

app/internal/json_data_loader.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import json
2+
import os
3+
from typing import Dict, List, Callable, Union
4+
5+
from loguru import logger
6+
from sqlalchemy.orm import Session
7+
8+
from app.database.database import Base
9+
from app.database.models import Quote, Zodiac
10+
from app.internal import daily_quotes, zodiac
11+
12+
13+
def get_data_from_json(path: str) -> List[Dict[str, Union[str, int, None]]]:
14+
"""This function reads all of the data from a specific JSON file.
15+
The json file consists of list of dictionaries"""
16+
try:
17+
with open(path, 'r') as f:
18+
json_content_list = json.load(f)
19+
except (IOError, ValueError):
20+
file_name = os.path.basename(path)
21+
logger.exception(
22+
f"An error occurred during reading of json file: {file_name}")
23+
return []
24+
return json_content_list
25+
26+
27+
def is_table_empty(session: Session, table: Base) -> bool:
28+
return session.query(table).count() == 0
29+
30+
31+
def load_data(
32+
session: Session, path: str,
33+
table: Base, object_creator_function: Callable) -> None:
34+
"""This function loads the specific data to the db,
35+
if it wasn't already loaded"""
36+
if not is_table_empty(session, table):
37+
return None
38+
json_objects_list = get_data_from_json(path)
39+
objects = [
40+
object_creator_function(json_object)
41+
for json_object in json_objects_list]
42+
session.add_all(objects)
43+
session.commit()
44+
45+
46+
def load_to_db(session) -> None:
47+
"""This function loads all the data for features
48+
based on pre-defind json data"""
49+
load_data(
50+
session, 'app/resources/zodiac.json',
51+
Zodiac, zodiac.create_zodiac_object)
52+
load_data(
53+
session, 'app/resources/quotes.json',
54+
Quote, daily_quotes.create_quote_object)
55+
"""The quotes JSON file content is copied from the free API:
56+
'https://type.fit/api/quotes'. I saved the content so the API won't be
57+
called every time the app is initialized."""

app/internal/quotes/load_quotes.py

Lines changed: 0 additions & 41 deletions
This file was deleted.

app/internal/zodiac.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from datetime import date
2+
from typing import Dict, Union
3+
4+
from sqlalchemy.orm import Session
5+
from sqlalchemy import and_, or_
6+
7+
from app.database.models import Zodiac
8+
9+
10+
def create_zodiac_object(zodiac_fields: Dict[str, Union[str, int]]) -> Zodiac:
11+
"""This function create a zodiac object from given fields dictionary.
12+
It is used for adding the data from the json into the db"""
13+
return Zodiac(
14+
name=zodiac_fields['name'],
15+
start_month=zodiac_fields['start_month'],
16+
start_day_in_month=zodiac_fields['start_day_in_month'],
17+
end_month=zodiac_fields['end_month'],
18+
end_day_in_month=zodiac_fields['end_day_in_month']
19+
)
20+
21+
22+
def get_zodiac_of_day(session: Session, date: date) -> Zodiac:
23+
"""This function return a zodiac object
24+
according to the current day."""
25+
first_month_of_sign_filter = and_(
26+
Zodiac.start_month == date.month,
27+
Zodiac.start_day_in_month <= date.day)
28+
second_month_of_sign_filter = and_(
29+
Zodiac.end_month == date.month,
30+
Zodiac.end_day_in_month >= date.day)
31+
zodiac_obj = session.query(Zodiac).filter(
32+
or_(first_month_of_sign_filter, second_month_of_sign_filter)).first()
33+
return zodiac_obj
34+
35+
36+
# TODO: Call this function from the month view
37+
def get_zodiac_of_month(session: Session, date: date) -> Zodiac:
38+
"""This function return a zodiac object
39+
according to the current month."""
40+
zodiac_obj = session.query(Zodiac).filter(
41+
Zodiac.end_month == date.month).first()
42+
return zodiac_obj

app/main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from app.database import models
77
from app.database.database import engine, get_db
88
from app.dependencies import (logger, MEDIA_PATH, STATIC_PATH, templates)
9-
from app.internal.quotes import daily_quotes, load_quotes
9+
from app.internal import daily_quotes, json_data_loader
1010
from app.routers import (
1111
agenda, calendar, categories, dayview, email,
1212
event, invitation, profile, search, telegram, whatsapp
@@ -30,7 +30,7 @@ def create_tables(engine, psql_environment):
3030
app.mount("/static", StaticFiles(directory=STATIC_PATH), name="static")
3131
app.mount("/media", StaticFiles(directory=MEDIA_PATH), name="media")
3232

33-
load_quotes.load_daily_quotes(next(get_db()))
33+
json_data_loader.load_to_db(next(get_db()))
3434

3535
app.logger = logger
3636

app/resources/zodiac.json

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
[
2+
{
3+
"name": "Capricorn",
4+
"start_month": 12,
5+
"start_day_in_month": 22,
6+
"end_month": 1,
7+
"end_day_in_month": 19
8+
},
9+
{
10+
"name": "Aquarius",
11+
"start_month": 1,
12+
"start_day_in_month": 20,
13+
"end_month": 2,
14+
"end_day_in_month": 18
15+
},
16+
{
17+
"name": "Pisces",
18+
"start_month": 2,
19+
"start_day_in_month": 19,
20+
"end_month": 3,
21+
"end_day_in_month": 20
22+
},
23+
{
24+
"name": "Aries",
25+
"start_month": 3,
26+
"start_day_in_month": 21,
27+
"end_month": 4,
28+
"end_day_in_month": 19
29+
},
30+
{
31+
"name": "Taurus",
32+
"start_month": 4,
33+
"start_day_in_month": 20,
34+
"end_month": 5,
35+
"end_day_in_month": 20
36+
},
37+
{
38+
"name": "Gemini",
39+
"start_month": 5,
40+
"start_day_in_month": 21,
41+
"end_month": 6,
42+
"end_day_in_month": 20
43+
},
44+
{
45+
"name": "Cancer",
46+
"start_month": 6,
47+
"start_day_in_month": 21,
48+
"end_month": 7,
49+
"end_day_in_month": 22
50+
},
51+
{
52+
"name": "Leo",
53+
"start_month": 7,
54+
"start_day_in_month": 23,
55+
"end_month": 8,
56+
"end_day_in_month": 22
57+
},
58+
{
59+
"name": "Virgo",
60+
"start_month": 8,
61+
"start_day_in_month": 23,
62+
"end_month": 9,
63+
"end_day_in_month": 22
64+
},
65+
{
66+
"name": "Libra",
67+
"start_month": 9,
68+
"start_day_in_month": 23,
69+
"end_month": 10,
70+
"end_day_in_month": 22
71+
},
72+
{
73+
"name": "Scorpio",
74+
"start_month": 10,
75+
"start_day_in_month": 23,
76+
"end_month": 11,
77+
"end_day_in_month": 21
78+
},
79+
{
80+
"name": "Sagittarius",
81+
"start_month": 11,
82+
"start_day_in_month": 22,
83+
"end_month": 12,
84+
"end_day_in_month": 21
85+
}
86+
]

app/routers/dayview.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from app.database.database import get_db
99
from app.database.models import Event, User
1010
from app.dependencies import TEMPLATES_PATH
11+
from app.internal import zodiac
1112

1213
templates = Jinja2Templates(directory=TEMPLATES_PATH)
1314

@@ -104,9 +105,11 @@ async def dayview(request: Request, date: str, db_session=Depends(get_db)):
104105
and_(Event.end >= day, Event.end < day_end),
105106
and_(Event.start < day_end, day_end < Event.end)))
106107
events_n_attrs = [(event, DivAttributes(event, day)) for event in events]
108+
zodiac_obj = zodiac.get_zodiac_of_day(db_session, day)
107109
return templates.TemplateResponse("dayview.html", {
108110
"request": request,
109111
"events": events_n_attrs,
110112
"month": day.strftime("%B").upper(),
111-
"day": day.day
113+
"day": day.day,
114+
"zodiac": zodiac_obj
112115
})

app/static/dayview.css

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,16 @@ html {
8989
.action-continer:hover .action-icon {
9090
visibility: visible;
9191
}
92+
93+
.zodiac-sign {
94+
position: fixed;
95+
right: 1.2em;
96+
top: 1.6em;
97+
padding-right: 0.4em;
98+
padding-left: 0.4em;
99+
padding-bottom: 0.2em;
100+
border: solid 0.1px var(--primary);
101+
background-color: var(--borders-variant);
102+
border-radius:50px;
103+
box-shadow: 1px 1px 2px #999;
104+
}

app/static/images/zodiac/Aquarius.svg

Lines changed: 28 additions & 0 deletions
Loading

app/static/images/zodiac/Aries.svg

Lines changed: 28 additions & 0 deletions
Loading

app/static/images/zodiac/Cancer.svg

Lines changed: 4 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)