Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
91eb35f
add color to category
ADI-projects30 Feb 7, 2021
4eb3ca8
Feature/add color to category
ADI-projects30 Feb 8, 2021
168c619
Feature/adding color to category
ADI-projects30 Feb 8, 2021
93e25ea
categories changes
ADI-projects30 Feb 16, 2021
a91f350
fix more conflictim
ADI-projects30 Feb 16, 2021
758ef50
did some changes
ADI-projects30 Feb 16, 2021
51ec154
fix conflicts
ADI-projects30 Feb 16, 2021
c7c0b86
fixfix lint
ADI-projects30 Feb 16, 2021
c3583c7
fixfix more lint
ADI-projects30 Feb 16, 2021
fdfeb8c
need to fix line
ADI-projects30 Feb 16, 2021
81a1a7e
fix forgoted line
ADI-projects30 Feb 16, 2021
fb76b71
delete blanck line
ADI-projects30 Feb 16, 2021
a22b981
fixfix more line
ADI-projects30 Feb 16, 2021
07a88aa
some changes
ADI-projects30 Feb 16, 2021
62cbf73
another fix
ADI-projects30 Feb 17, 2021
aaa1960
fixing fixing
ADI-projects30 Feb 17, 2021
0096011
fixingfix conflicts
ADI-projects30 Feb 17, 2021
82abccb
fix lint fix lint
ADI-projects30 Feb 17, 2021
35d7b46
more fix fixing lint
ADI-projects30 Feb 17, 2021
134e4e9
change something fix
ADI-projects30 Feb 17, 2021
c447e89
fix and fix more
ADI-projects30 Feb 17, 2021
3fcbeb6
just fix
ADI-projects30 Feb 17, 2021
a6ecc5f
fix given notes
ADI-projects30 Feb 18, 2021
301b34e
fix notes and the conflicts
ADI-projects30 Feb 18, 2021
5024f01
fixfixfix lintlint
ADI-projects30 Feb 18, 2021
68d00d3
another lint fixfix
ADI-projects30 Feb 18, 2021
7b5de86
one more fix
ADI-projects30 Feb 18, 2021
1d3ac9d
fix and fix notes
ADI-projects30 Feb 18, 2021
7dd98e9
conflict fixfixfixing
ADI-projects30 Feb 18, 2021
df0f8b6
fixlint fixlint
ADI-projects30 Feb 18, 2021
2a271bc
lintlint fixfix
ADI-projects30 Feb 18, 2021
6d3f31e
conflictsconflicts
ADI-projects30 Feb 18, 2021
2002615
conflictim conflictim
ADI-projects30 Feb 18, 2021
ff9225f
conflictim and more
ADI-projects30 Feb 18, 2021
489869e
one conflict and change
ADI-projects30 Feb 20, 2021
6c89cd2
fixfix conflictconflict
ADI-projects30 Feb 20, 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
65 changes: 39 additions & 26 deletions app/routers/categories.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import re
from typing import Any, Dict, List
from typing import Dict, List

from fastapi import APIRouter, Depends, HTTPException, Request
from fastapi import APIRouter, Depends, Form, HTTPException, Request
from pydantic import BaseModel
from sqlalchemy.exc import IntegrityError, SQLAlchemyError
from sqlalchemy.orm import Session
from starlette import status
from starlette.datastructures import ImmutableMultiDict
from starlette.templating import _TemplateResponse


from app.database.models import Category
from app.dependencies import get_db
from app.dependencies import templates

HEX_COLOR_FORMAT = r"^(?:[0-9a-fA-F]{3}){1,2}$"

Expand All @@ -35,7 +38,7 @@ class Config:


# TODO(issue#29): get current user_id from session
@router.get("/", include_in_schema=False)
@router.get("/user", include_in_schema=False)
def get_categories(request: Request,
db_session: Session = Depends(get_db)) -> List[Category]:
if validate_request_params(request.query_params):
Expand All @@ -46,39 +49,39 @@ def get_categories(request: Request,
f"unallowed params.")


@router.get("/list")
def get_all_categories(
db_session: Session = Depends(get_db)) -> List[Category]:
return db_session.query(Category).all()


@router.get("/")
def get_categories_by_user_id(
user_id: int, db_session: Session = Depends(get_db)
) -> List[Category]:
return get_user_categories(db_session, user_id)
def category_color_insert(request: Request) -> _TemplateResponse:
return templates.TemplateResponse("categories.html", {
"request": request
})


# TODO(issue#29): get current user_id from session
@router.post("/")
async def set_category(category: CategoryModel,
db_sess: Session = Depends(get_db)) -> Dict[str, Any]:
if not validate_color_format(category.color):
async def set_category(request: Request,
name: str = Form(None),
color: str = Form(None),
db_sess: Session = Depends(get_db)):

message = ""
user_id = 1 # until issue#29 will get current user_id from session
color = color.replace('#', '')
if not validate_color_format(color):
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Color {category.color} if not from "
detail=f"Color {color} if not from "
f"expected format.")
try:
cat = Category.create(db_sess,
name=category.name,
color=category.color,
user_id=category.user_id)
Category.create(db_sess, name=name, color=color, user_id=user_id)
except IntegrityError:
db_sess.rollback()
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST,
detail=f"category is already exists for "
f"user {category.user_id}.")
else:
return {"category": cat.to_dict()}
message = "Category already exists"
return templates.TemplateResponse("categories.html",
dictionary_req(request, message,
name, color))
message = f"Congratulation! You have created a new category: {name}"
return templates.TemplateResponse("categories.html",
dictionary_req(request, message,
name, color))


def validate_request_params(query_params: ImmutableMultiDict) -> bool:
Expand Down Expand Up @@ -120,3 +123,13 @@ def get_user_categories(db_session: Session,
return []
else:
return categories


def dictionary_req(request, message, name, color) -> Dict:
dictionary_tamplates = {
"request": request,
"message": message,
"name": name,
"color": color,
}
return dictionary_tamplates
11 changes: 9 additions & 2 deletions app/routers/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from app.internal import comment as cmt
from app.internal.emotion import get_emotion
from app.internal.utils import create_model, get_current_user
from app.routers.categories import get_user_categories


EVENT_DATA = Tuple[Event, List[Dict[str, str]], str]
Expand All @@ -41,6 +42,7 @@
"category_id": (int, type(None)),
}


router = APIRouter(
prefix="/event",
tags=["event"],
Expand Down Expand Up @@ -80,8 +82,13 @@ async def create_event_api(event: EventModel, session=Depends(get_db)):

@router.get("/edit", include_in_schema=False)
@router.get("/edit")
async def eventedit(request: Request) -> Response:
return templates.TemplateResponse("eventedit.html", {"request": request})
async def eventedit(request: Request,
db_session: Session = Depends(get_db)) -> Response:
user_id = 1 # until issue#29 will get current user_id from session
categories_list = get_user_categories(db_session, user_id)
return templates.TemplateResponse("eventedit.html",
{"request": request,
"categories_list": categories_list})


@router.post("/edit", include_in_schema=False)
Expand Down
32 changes: 32 additions & 0 deletions app/static/categories_style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@


body {
color: #333;
margin: auto;
font: 1.2em / 1.2 Arial, Helvetica, sans-serif;
}

h1 {
color: black;
font-size: 150%;
text-align: center;
}

form {
text-align: center;
}

input {
border-radius: 0.5em;
color: plum;
padding: 0.5em;
}

input[type="color"].custom {
padding: 0;
border: none;
height: 1.875em;
width: 9.375em;
vertical-align: middle;
border-radius: 0.5em;
}
6 changes: 4 additions & 2 deletions app/static/event/eventedit.css
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@ form {

.form_row,
.form_row_start,
.form_row_end {
.form_row_end,
.user_categories {
display: flex
}

.form_row_start,
.form_row_end {
.form_row_end,
.user_categories {
flex: 1;
}

Expand Down
3 changes: 3 additions & 0 deletions app/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@
<li class="nav-item">
<button id="a-joke" class="btn btn-link">Make me Laugh</button>
</li>
<li class="nav-item"></li>
<a class="nav-link" href="{{ url_for('category_color_insert') }}">Create Categories</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('about') }}">{{ gettext("About Us") }}</a>
</li>
Expand Down
30 changes: 30 additions & 0 deletions app/templates/categories.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{% extends "base.html" %}

{% block head %}
{{ super() }}
<link href="{{ url_for('static', path='/categories_style.css') }}" rel="stylesheet">
<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">
{% endblock %}

{% block content %}
<div class="container mt-4">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add indentation please

<h1>It's time to make some decisions</h1>
<h1>
Here you can create your unique categories and choose your favorite color
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add . or : in the end of the sentence

</h1>

<form action="/categories" method="POST" required>
<label for="category_name">Name your category:</label>
<p><input type="text" id ="name" name="name"></p>
<label for="category_color">Choose your favorite color:</label>
<p><input type="color" class="custom" id ="color", name="color"></p>
<p><button type="submit" class="btn btn-success" value="submit">Submit</button></p>
</form>
</div>
{% if message %}
<div class="container mt-4">
<p>{{ message }}</p>
</div>
{% endif %}

{% endblock %}
12 changes: 12 additions & 0 deletions app/templates/partials/calendar/event/edit_event_details_tab.html
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,18 @@
<option value="public" selected>Public</option>
</select>

<label for="user_categories">Category</label>
<select id="categories" name="the_categories">
{% if categories_list[0] is defined %}
<option style="color:#{{categories_list[0]['color'] |safe }}" value="{{categories_list[0]['name'] |safe }}" selected>{{categories_list[0]['name'] |safe }}</option>
{% endif %}
{% if categories_list[1] is defined %}
{% for category in categories_list[1:] %}
<option style="color:#{{category['color'] |safe }}" value="{{category['name'] |safe }}" selected>{{category['name'] |safe }}</option>
{% endfor %}
{% endif %}
</select>

<label for="is_google_event">Google event:</label>
<select id="is_google_event" name="is_google_event">
<option value="True">Yes</option>
Expand Down
3 changes: 3 additions & 0 deletions app/templates/partials/index/navigation.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
<li class="nav-item">
<a class="nav-link" href="/search">Search</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('categories') }}">Categories</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('about') }}">{{ gettext("About Us") }}</a>
</li>
Expand Down
8 changes: 7 additions & 1 deletion tests/client_fixture.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
from app import main
from app.database.models import Base, User
from app.routers import (
agenda, event, friendview, google_connect, invitation, profile
agenda, categories, event, friendview, google_connect,
invitation, profile
)
from app.routers.salary import routes as salary
from tests import security_testing_routes
Expand Down Expand Up @@ -68,6 +69,11 @@ def invitation_test_client() -> Generator[TestClient, None, None]:
yield from create_test_client(invitation.get_db)


@pytest.fixture(scope="session")
def categories_test_client() -> Generator[TestClient, None, None]:
yield from create_test_client(categories.get_db)


@pytest.fixture(scope="session")
def profile_test_client() -> Generator[Session, None, None]:
Base.metadata.create_all(bind=test_engine)
Expand Down
52 changes: 32 additions & 20 deletions tests/test_categories.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pytest
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.testing import mock

from starlette import status
from starlette.datastructures import ImmutableMultiDict

Expand All @@ -11,7 +12,8 @@


class TestCategories:
CATEGORY_ALREADY_EXISTS_MSG = "category is already exists for"
CATEGORY_ALREADY_EXISTS_MSG = b"Category already exists"
CREATE_CATEGORY = b"You have created"
UNALLOWED_PARAMS = "contains unallowed params"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you add b in the prefix of other string...maybe this one needs too?

BAD_COLOR_FORMAT = "if not from expected format"

Expand All @@ -20,28 +22,30 @@ def test_get_categories_logic_succeeded(session, user, category):
assert get_user_categories(session, category.user_id) == [category]

@staticmethod
def test_creating_new_category(client, user):
response = client.post("/categories/",
json={"user_id": user.id, "name": "Foo",
"color": "eecc11"})
def test_creating_new_category(categories_test_client, session, user):
CORRECT_ADD_CATEGORY_DATA = {"user_id": user.id,
"name": "Foo",
"color": "eecc11"}
response = categories_test_client.post("/categories/",
data=CORRECT_ADD_CATEGORY_DATA)
assert response.ok
assert {("user_id", user.id), ("name", "Foo"),
("color", "eecc11")}.issubset(
set(response.json()['category'].items()))
assert TestCategories.CREATE_CATEGORY in response.content

@staticmethod
def test_creating_not_unique_category_failed(client, sender, category):
response = client.post("/categories/", json={"user_id": sender.id,
"name": "Guitar Lesson",
"color": "121212"})
assert response.status_code == status.HTTP_400_BAD_REQUEST
assert TestCategories.CATEGORY_ALREADY_EXISTS_MSG in \
response.json()["detail"]
def test_create_not_unique_category_failed(categories_test_client, sender,
category):
CATEGORY_ALREADY_EXISTS = {"name": "Guitar Lesson",
"color": "121212",
"user_id": sender.id}
response = categories_test_client.post("/categories/",
data=CATEGORY_ALREADY_EXISTS)
assert response.ok
assert TestCategories.CATEGORY_ALREADY_EXISTS_MSG in response.content

@staticmethod
def test_creating_new_category_bad_color_format(client, user):
response = client.post("/categories/",
json={"user_id": user.id, "name": "Foo",
data={"user_id": user.id, "name": "Foo",
"color": "bad format"})
assert response.status_code == status.HTTP_400_BAD_REQUEST
assert TestCategories.BAD_COLOR_FORMAT in response.json()["detail"]
Expand All @@ -62,7 +66,8 @@ def test_update_event_with_category(today_event, category):

@staticmethod
def test_get_user_categories(client, category):
response = client.get(f"/categories/?user_id={category.user_id}"
response = client.get(f"/categories/user/?"
f"user_id={category.user_id}"
f"&name={category.name}&color={category.color}")
assert response.ok
assert len(response.json()) == 1
Expand All @@ -72,7 +77,8 @@ def test_get_user_categories(client, category):

@staticmethod
def test_get_category_by_name(client, sender, category):
response = client.get(f"/categories/?user_id={category.user_id}"
response = client.get(f"/categories/user/?"
f"user_id={category.user_id}"
f"&name={category.name}")
assert response.ok
assert len(response.json()) == 1
Expand All @@ -82,7 +88,8 @@ def test_get_category_by_name(client, sender, category):

@staticmethod
def test_get_category_by_color(client, sender, category):
response = client.get(f"/categories/?user_id={category.user_id}&"
response = client.get(f"/categories/user/?"
f"user_id={category.user_id}&"
f"color={category.color}")
assert response.ok
assert len(response.json()) == 1
Expand All @@ -92,10 +99,15 @@ def test_get_category_by_color(client, sender, category):

@staticmethod
def test_get_category_bad_request(client):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you remove this one?

response = client.get("/categories/")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be probably /categories/user now, could you keep it?

response = client.get("/categories/user")
assert response.status_code == status.HTTP_400_BAD_REQUEST
assert TestCategories.UNALLOWED_PARAMS in response.json()["detail"]

@staticmethod
def test_get_category_ok_request(client):
response = client.get("/categories")
assert response.ok

@staticmethod
def test_repr(category):
assert category.__repr__() == \
Expand Down