-
Notifications
You must be signed in to change notification settings - Fork 52
Feature/cursor #307
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
subscorp
wants to merge
38
commits into
PythonFreeCourse:develop
Choose a base branch
from
subscorp:feature/cursor
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Feature/cursor #307
Changes from all commits
Commits
Show all changes
38 commits
Select commit
Hold shift + click to select a range
8bbca9c
feature: add cursor settings
subscorp 056adc5
fix: fixed conflicts
subscorp 914a808
fix: fixed pytest issue
subscorp 05660da
fix: fixed conflicts
subscorp 8312440
update: changed CursorSettings table to UserSettings
subscorp 0db4d2b
fix:solved conflicts
subscorp 53de34a
fix: fixed a small bug
subscorp 6dd0219
fix: another small fix
subscorp fc72d95
fix: fixed issues according to comments
subscorp 25ca2d3
fix: fixed conflicts
subscorp 4d2195e
Update: now using the new login system
subscorp 2114a33
fix: fixed conflicts
subscorp 4ce2c74
fix: fixed issues according to comments
subscorp 4f06799
fix: fixed issues according to comments
subscorp f569f3c
fix: fixed conflicts
subscorp e289578
Update: moved functions to internals
subscorp 44da8b7
fix: fixed issue in pytest
subscorp 7b616ec
Merge branch 'develop' of https://github.com/PythonFreeCourse/calenda…
subscorp 8b0cd21
fix: a small fix
subscorp dbae35d
fix: fixed issues according to comments
subscorp 03e21d1
fix: fixed conflicts
subscorp 458fb3f
fix: fixed a bug in pytest
subscorp df699f6
fix: fixed a small bug in one of the tests. now coverage is 100% on t…
subscorp c847b41
fix: fixed issues according to comments
subscorp 479f580
fix: fixed conflicts
subscorp b01c459
fix: a tiny fix
subscorp 969bcb1
fix: fixed finale comment
subscorp d0336bf
Merge branch 'develop' of https://github.com/PythonFreeCourse/calenda…
subscorp 01456c8
fix: trying to fix the same bug from favorite_quotes in pytest
subscorp 5b54d04
fix: fixed issue in pytest
subscorp 0fdce31
fix: trying to fix the bug
subscorp 7dcfc02
fix: trying to fix the bug
subscorp 021881b
fix: trying to fix the bug
subscorp 8e057c5
fix: trying to fix the bug
subscorp 2ec4a77
fix: trying to fix the bug
subscorp d050246
fix: trying to fix the bug
subscorp a1a9f66
fix: fixed the bug!
subscorp 6d2bcf5
fix: fixed conflicts
subscorp File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
from typing import List, Optional, Tuple | ||
|
||
from sqlalchemy.orm.session import Session | ||
|
||
from app.database.models import User, UserSettings | ||
|
||
|
||
def get_cursor_settings( | ||
session: Session, | ||
user_id: int, | ||
) -> Tuple[Optional[List[str]], Optional[int], Optional[str], Optional[int]]: | ||
"""Retrieves cursor settings from the database. | ||
|
||
Args: | ||
session (Session): the database. | ||
user_id (int, optional): the users' id. | ||
|
||
Returns: | ||
Tuple[str, Optional[List[str]], Optional[int], | ||
str, Optional[str], Optional[int]]: the cursor settings. | ||
""" | ||
primary_cursor, secondary_cursor = None, None | ||
cursor_settings = ( | ||
session.query(UserSettings).filter_by(user_id=user_id).first() | ||
) | ||
if cursor_settings: | ||
primary_cursor = cursor_settings.primary_cursor | ||
secondary_cursor = cursor_settings.secondary_cursor | ||
|
||
return primary_cursor, secondary_cursor | ||
|
||
|
||
def save_cursor_settings( | ||
session: Session, | ||
user: User, | ||
cursor_choices: List[str], | ||
): | ||
"""Saves cursor choices in the db. | ||
|
||
Args: | ||
session (Session): the database. | ||
user (User): current user. | ||
cursor_choices (List[str]): primary and secondary cursors. | ||
""" | ||
cursor_settings = ( | ||
session.query(UserSettings).filter_by(user_id=user.user_id).first() | ||
) | ||
if cursor_settings: | ||
session.query(UserSettings).filter_by( | ||
user_id=cursor_settings.user_id, | ||
).update(cursor_choices) | ||
else: | ||
session.merge(UserSettings(user_id=user.user_id, **cursor_choices)) | ||
session.commit() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
http://www.rw-designer.com/cursor-set/material-amber | ||
http://www.rw-designer.com/cursor-set/windows-xp-style | ||
http://www.rw-designer.com/cursor-set/material-3d | ||
http://www.rw-designer.com/cursor-set/paper-plane | ||
http://www.rw-designer.com/cursor-set/yodalighsaber | ||
http://www.rw-designer.com/cursor-set/valentine-heart | ||
http://www.rw-designer.com/cursor-set/icy-ice | ||
http://www.rw-designer.com/cursor-set/wii-hand-1 | ||
http://www.rw-designer.com/cursor-set/pen-tablet-1 | ||
http://www.rw-designer.com/cursor-set/among-us-mixed-pointer-pack- | ||
http://www.rw-designer.com/cursor-set/nes-smb-mario | ||
http://www.rw-designer.com/cursor-set/mario-world-v64 | ||
http://www.rw-designer.com/cursor-set/the-legend-of-zelda |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import json | ||
from pathlib import Path | ||
|
||
from fastapi import APIRouter, Depends, Form, Request | ||
from sqlalchemy.orm.session import Session | ||
from starlette.responses import RedirectResponse | ||
from starlette.status import HTTP_302_FOUND | ||
|
||
from app.database.models import User | ||
from app.dependencies import CURSORS_PATH, get_db, templates | ||
from app.internal.cursor import get_cursor_settings, save_cursor_settings | ||
from app.internal.security.dependencies import current_user | ||
|
||
router = APIRouter( | ||
prefix="/cursor", | ||
tags=["cursor"], | ||
responses={404: {"description": "Not found"}}, | ||
) | ||
|
||
|
||
@router.get("/settings") | ||
def cursor_settings( | ||
request: Request, | ||
user: User = Depends(current_user), | ||
session: Session = Depends(get_db), | ||
) -> templates.TemplateResponse: | ||
"""A route to the cursor settings. | ||
|
||
Args: | ||
request (Request): the http request. | ||
session (Session): the database. | ||
|
||
Returns: | ||
templates.TemplateResponse: renders the cursor_settings.html page | ||
with the relevant information. | ||
""" | ||
cursors = ["default"] + [ | ||
path.stem for path in Path(CURSORS_PATH).glob("**/*.cur") | ||
] | ||
|
||
return templates.TemplateResponse( | ||
"cursor_settings.html", | ||
{ | ||
"request": request, | ||
"cursors": cursors, | ||
}, | ||
) | ||
|
||
|
||
@router.post("/settings") | ||
async def get_cursor_choices( | ||
session: Session = Depends(get_db), | ||
user: User = Depends(current_user), | ||
primary_cursor: str = Form(...), | ||
secondary_cursor: str = Form(...), | ||
) -> RedirectResponse: | ||
"""The form in which the user choses primary and secondary | ||
cursors. | ||
|
||
Args: | ||
session (Session, optional): the database. | ||
user (User, optional): [description]. temp user. | ||
primary_cursor (str, optional): name of the primary cursor. | ||
the primary cursor. | ||
secondary_cursor (str, optional): name of the secondary cursor. | ||
|
||
Returns: | ||
RedirectResponse: redirects to the homepage. | ||
""" | ||
cursor_choices = { | ||
"primary_cursor": primary_cursor, | ||
"secondary_cursor": secondary_cursor, | ||
} | ||
save_cursor_settings(session, user, cursor_choices) | ||
|
||
return RedirectResponse("/", status_code=HTTP_302_FOUND) | ||
|
||
|
||
@router.get("/load") | ||
async def load_cursor( | ||
session: Session = Depends(get_db), | ||
user: User = Depends(current_user), | ||
) -> RedirectResponse: | ||
"""loads cursors according to cursor settings. | ||
|
||
Args: | ||
session (Session): the database. | ||
user (User): the user. | ||
|
||
Returns: | ||
RedirectResponse: redirect the user to the homepage. | ||
""" | ||
primary_cursor, secondary_cursor = get_cursor_settings( | ||
session, | ||
user.user_id, | ||
) | ||
|
||
return json.dumps( | ||
{ | ||
"primary_cursor": primary_cursor, | ||
"secondary_cursor": secondary_cursor, | ||
}, | ||
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
const CURSORS_PATH = "/media/cursors/"; | ||
|
||
// These must be global so the mutationObserver could access them. | ||
let primary_cursor; | ||
let secondary_cursor; | ||
|
||
window.addEventListener("load", init); | ||
|
||
/** | ||
* @summary In charge of initialising the customization of the cursor. | ||
*/ | ||
function init() { | ||
get_cursor_choices(); | ||
initMutationObserver(); | ||
} | ||
|
||
/** | ||
* @summary This function gets cursor choices from the db. | ||
*/ | ||
function get_cursor_choices() { | ||
const request = new XMLHttpRequest(); | ||
request.open("GET", "/cursor/load", true); | ||
request.onload = change_cursor; | ||
request.send(); | ||
} | ||
|
||
/** | ||
* @summary This function changes the primary cursor and the secondary | ||
* cursor according to users' choices. | ||
*/ | ||
function change_cursor() { | ||
const cursor_settings = JSON.parse(JSON.parse(this.response)); | ||
subscorp marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const primary_cursor_choice = cursor_settings["primary_cursor"]; | ||
const primary_cursor_path = `url(${CURSORS_PATH}${primary_cursor_choice}), auto`; | ||
const secondary_cursor_choice = cursor_settings["secondary_cursor"]; | ||
const secondary_cursor_path = `url(${CURSORS_PATH}${secondary_cursor_choice}), auto`; | ||
primary_cursor = | ||
primary_cursor_choice !== "default.cur" ? primary_cursor_path : ""; | ||
secondary_cursor = | ||
secondary_cursor_choice !== "default.cur" ? secondary_cursor_path : ""; | ||
document.body.style.cursor = primary_cursor; | ||
const links = document.querySelectorAll("a, button, input, select, label"); | ||
links.forEach((element) => { | ||
element.style.cursor = secondary_cursor; | ||
}); | ||
} | ||
|
||
/** | ||
* @summary Sets up mutation observer to follow dynamically added links | ||
*/ | ||
function initMutationObserver() { | ||
const config = { | ||
childList: true, | ||
subtree: true, | ||
}; | ||
const observer = new MutationObserver(mutate); | ||
observer.observe(document, config); | ||
} | ||
|
||
/** | ||
* @summary This function identifies a new element for the secondary cursor, | ||
* and sets it according to the users' choices. | ||
*/ | ||
function mutate(mutationList) { | ||
const links = ["a", "button", "input", "select", "label"]; | ||
for (let mutation of mutationList) { | ||
if (mutation.type == "childList") { | ||
handle_potential_links(mutation.addedNodes, links); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* @summary Helper function to the mutate function which | ||
* on creation of new nodes in the DOM, if it is a link - changes its' | ||
* style. | ||
*/ | ||
function handle_potential_links(nodes, links) { | ||
nodes.forEach((element) => { | ||
if ( | ||
typeof(element.tagName) !== "undefined" && | ||
links.includes(element.tagName.toLowerCase()) | ||
) { | ||
element.setAttribute("style", secondary_cursor); | ||
} | ||
}); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -64,6 +64,9 @@ | |
<li class="nav-item"> | ||
<a class="nav-link" href="{{ url_for('weight') }}">Weight</a> | ||
</li> | ||
</li> | ||
<a class="nav-link" href="{{ url_for('cursor_settings') }}">Cursor Settings</a> | ||
</li> | ||
<li class="nav-item"> | ||
<a class="nav-link" href="{{ url_for('about') }}">{{ gettext("About Us") }}</a> | ||
</li> | ||
|
@@ -91,6 +94,9 @@ | |
<script defer src="https://use.fontawesome.com/releases/v5.0.8/js/all.js" integrity="sha384-SlE991lGASHoBfWbelyBPLsUlwY1GwNDJo3jSJO04KZ33K2bwfV9YBauFfnzvynJ" crossorigin="anonymous"></script> | ||
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW" crossorigin="anonymous"></script> | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js" integrity="sha512-d9xgZrVZpmmQlfonhQUvTR7lMPtO7NkZMkA0ABN3PHCbKA5nqylQ/yWlFAyY6hYgdF1Qh6nYiuADWwKB4C2WSw==" crossorigin="anonymous"></script> | ||
<script type="text/javascript" src="{{ url_for('static', path='/popover.js') }}"></script> | ||
<script defer type="text/javascript" src="{{ url_for('static', path='/cursor.js') }}"></script> | ||
|
||
<!-- This bootstrap version is needed here because of the toggler bug in the beta version--> | ||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha2/js/bootstrap.bundle.min.js" integrity="sha384-BOsAfwzjNJHrJ8cZidOg56tcQWfp6y72vEJ8xQ9w6Quywb24iOsW913URv1IS4GD" crossorigin="anonymous"></script> | ||
<script src="{{ url_for('static', path='/horoscope.js') }}"></script> | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{% extends "base.html" %} | ||
{% block content %} | ||
<div class="container mt-4"> | ||
<h1>Cursor Settings</h1> | ||
<form action="{{ url_for('get_cursor_choices') }}" method="post" id="cursor-form"> | ||
<label for="primary-cusor">Select primary cursor :</label> <br> | ||
<select name="primary_cursor" id="primary-cursor" class="form-control"> | ||
{% for cursor in cursors %} | ||
<option value="{{ cursor }}.cur">{{cursor}}</option> | ||
{% endfor %} | ||
</select> | ||
<br> | ||
<label for="secondary-cusor">Select secondary cursor :</label> <br> | ||
<select name="secondary_cursor" id="secondary-cursor" class="form-control"> | ||
{% for cursor in cursors %} | ||
<option value="{{ cursor }}.cur">{{cursor}}</option> | ||
{% endfor %} | ||
</select> | ||
<br> | ||
<button id="activate-cursor" type="submit" form="cursor-form" class="btn btn-primary"> | ||
Activate | ||
</button> | ||
<br> | ||
</form> | ||
</div> | ||
|
||
{% endblock %} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure we need a route for every setting option. This should probably be routers.setting.py and the calls should be:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you mean that there shouldn't be a [setting_type].py file for each setting type?
So if I have Audio Settings and Cursor Settings, both of them should be in routers.setting.py, but the @router functions should stay the same, only in this new file instead of the old one?
Thanks for your feedback!