Compare commits

...

10 Commits

Author SHA1 Message Date
Kiril Kovachev
3133fc1de2 Add exam to navbar 2024-10-24 11:36:09 +01:00
Kiril Kovachev
a36de8a7f4 Include all questions (not yet backend-programmed) into the exam page) 2024-10-24 11:34:00 +01:00
Kiril Kovachev
aa8da63a68 Merge remote-tracking branch 'refs/remotes/origin/master' 2024-10-24 10:13:30 +01:00
Kiril Kovachev
35dba4991b Partially implement search 2024-10-21 11:14:25 +01:00
Kiril Kovachev
f664cd1a08 Check 'includes' search method by default 2024-10-21 10:29:42 +01:00
Kiril Kovachev
e4e6bb9fb1 Add submit button to search 2024-10-21 10:28:45 +01:00
Kiril Kovachev
00b8b2109b Remove unsightly greenness from dark theme 2024-10-21 10:23:48 +01:00
Kiril Kovachev
677e0868d2 Fix old PFP removal logic 2024-10-21 10:22:30 +01:00
Kiril Kovachev
e00c9fe431 Remove old profile pictures once new ones are set 2024-10-21 10:20:35 +01:00
Kiril Kovachev
009cb6aade Separate public and logged-in user settings 2024-10-21 10:20:15 +01:00
11 changed files with 280 additions and 47 deletions

View File

@ -43,41 +43,60 @@ def create_app(test_config=None):
def update_settings(form, files):
db = get_database()
if "user_id" in session:
# Set values in the database
settings = db.execute("SELECT * FROM user_settings WHERE user_id = ?",
(session["user_id"],)
).fetchone()
if settings:
db.execute("UPDATE user_settings SET lang = ?, theme = ? WHERE user_id = ?",
(form["language"], form["theme"], session["user_id"]))
else:
db.execute("INSERT INTO user_settings (user_id, lang, theme) VALUES (?, ?, ?)",
(session["user_id"], form["language"], form["theme"]))
if "pfp" in files and files["pfp"].filename != "":
stored_filename = str(uuid.uuid4())
pfp = files["pfp"]
pfp.save(os.path.join(app.config["PFP_STORE"], stored_filename))
db.execute("UPDATE user_settings SET pfp_filename = ?", (stored_filename,))
db.commit()
# Set values in the database
settings = db.execute("SELECT * FROM user_settings WHERE user_id = ?",
(session["user_id"],)
).fetchone()
if settings:
db.execute("UPDATE user_settings SET lang = ?, theme = ? WHERE user_id = ?",
(form["language"], form["theme"], session["user_id"]))
else:
db.execute("INSERT INTO user_settings (user_id, lang, theme) VALUES (?, ?, ?)",
(session["user_id"], form["language"], form["theme"]))
if "pfp" in files and files["pfp"].filename != "":
stored_filename = str(uuid.uuid4())
pfp = files["pfp"]
pfp.save(os.path.join(app.config["PFP_STORE"], stored_filename))
# Remove old PFP
if settings and settings["pfp_filename"]:
os.remove(os.path.join(app.config["PFP_STORE"], settings["pfp_filename"]))
db.execute("UPDATE user_settings SET pfp_filename = ?", (stored_filename,))
db.commit()
update_logged_out_settings(form)
return redirect("/options")
def update_logged_out_settings(form):
# Set values directly in the session
session["language"] = form["language"]
session["theme"] = form["theme"]
return redirect("/options")
return redirect("/public_options")
@app.route("/options", methods=["GET", "POST"])
def options():
if request.method == "GET":
return render_template("options.html")
if "user_id" in session:
return render_template("options.html")
else:
return redirect("/public_options")
else:
return update_settings(request.form, request.files)
@app.route("/public_options", methods=["GET", "POST"])
def public_options():
if request.method == "GET":
if "user_id" in session:
return redirect("/public_options")
else:
return render_template("logged_out_options.html")
else:
return update_logged_out_settings(request.form)
@app.get("/user/<int:user_id>")
def user_page(user_id: int):
db = get_database()

View File

@ -123,6 +123,9 @@ class Kanji(Base):
return out
def render(self):
return self.character
@blueprint.route("/id/<int:kanji_id>")
def kanji_by_id(kanji_id: int):
session = get_jiten_db()

View File

@ -1,4 +1,8 @@
from flask import Blueprint, render_template, request
from sqlalchemy import select
from kanken_online.api import Goon, Kanji, Kanon, Kanyoon, Kun, Soon, Toon
from kanken_online.database import get_jiten_db
blueprint = Blueprint("search", __name__, url_prefix="/search")
@ -7,6 +11,58 @@ def search_results(args: dict):
def render(self):
return "ok"
results = [renderable(), renderable()] # Do something with args
jiten = get_jiten_db()
query = select(Kanji).where(
Kanji.character == args["keywords"]
).where(
Kanji.stroke_count.between((args["stroke_min"] or 0), (args["stroke_max"] or 100))
)
if args["radical"]:
query = query.where(
Kanji.radical == args["radical"]
)
if args["kanon"]:
query = query.where(
Kanji.kanon.any(Kanon.reading.in_([args["kanon"]]))
)
if args["goon"]:
query = query.where(
Kanji.goon.any(Goon.reading.in_([args["goon"]]))
)
if args["soon"]:
query = query.where(
Kanji.soon.any(Soon.reading.in_([args["soon"]]))
)
if args["toon"]:
query = query.where(
Kanji.toon.any(Toon.reading.in_([args["toon"]]))
)
if args["kanyoon"]:
query = query.where(
Kanji.kanyoon.any(Kanyoon.reading.in_([args["kanyoon"]]))
)
if args["kun"]:
query = query.where(
Kanji.kun.any(Kun.reading.in_([args["kun"]]))
)
# if args["onkun"]:
# query = query.where(
# Kanji.kun.any(Kun.reading.in_([args["kun"]]))
# )
results = [row[0] for row in jiten.execute(query).all()]
# print(list(map(Kanji.to_json, results)))
return render_template("search/search_results.html", results=results, value=args["keywords"])
@blueprint.route("/")

View File

@ -1,3 +1,8 @@
body {
background: green;
background: black;
color: aliceblue;
}
html {
background-color: black;
}

View File

@ -44,5 +44,6 @@
"success_new_post": "Successfully created new post",
"user_introduction": "User",
"pfp": "Profile picture",
"level_1_exam": "Level 1 exam"
"level_1_exam": "Level 1 exam",
"exam": "Exam"
}

View File

@ -44,5 +44,6 @@
"success_new_post": "無事に新しい投稿を作りました",
"user_introduction": "利用者の",
"pfp": "利用者アイコン",
"level_1_exam": "一級試験"
"level_1_exam": "一級試験",
"exam": "試験"
}

View File

@ -28,6 +28,7 @@
<li><a href="{{ url_for('about_page') }}">{{ localize("about") }}</a></li>
<li><a href="{{ url_for('indices.indices_page') }}">{{ localize("indices") }}</a></li>
<li><a href="{{ url_for('search.search_page') }}">{{ localize("search") }}</a></li>
<li><a href="{{ url_for('exam') }}">{{ localize("exam") }}</a></li>
<li><a href="{{ url_for('forum.index') }}">{{ localize("forum") }}</a></li>
<li><a href="{{ url_for('data_page') }}">{{ localize("data") }}</a></li>
</ul>

View File

@ -9,6 +9,7 @@
{% endblock %}
{% block content %}
<div lang="ja">
<h1>日本漢字能力検定試験問題</h1>
<div id="q1">
<h2>(一)</h2>
@ -57,4 +58,141 @@
</ol>
</div>
<div id="q3">
<h2>(三)</h2>
<p>次の1~5の意味を的確に表す語を、左の「」から選び、<b>漢字</b>で記せ。</p>
<ol id="q3-definitions">
</ol>
<div id="q3-word-box">
<ul id="q3-words">
{% for i in range(8) %}
<li class="wordbox-word">Definition</li>
{% endfor %}
</ul>
</div>
</div>
<div id="q4">
<h2>(四)</h2>
<p>次の<span class="mondai">問1</span><span class="mondai">問2</span>の四字熟語について答えよ。</p>
<div id="q4-mon-ichi">
<p><span class="mondai">問1</span> 次の四字熟語の(1~10)に入る適切な語を左の「」から選び<b>漢字二字</b>で記せ。</p>
<div id="q4-mon-ichi-questions">
<ol id="q4-mon-ichi-top">
{% for i in range(5) %}
<li>bottom two characters</li>
{% endfor %}
</ol>
<ol id="q4-mon-ichi-bottom" start="6">
{% for i in range(5) %}
<li>top two characters</li> <!--Q: Will this work with just CSS, or will it need extra HTML formatting...? -->
{% endfor %}
</ol>
</div>
<div id="q4-mon-ichi-wordbox">
<ul id="q4-mon-ichi-words">
{% for i in range(10) %}
<li class="wordbox-word">Definition</li>
{% endfor %}
</ul>
</div>
</div>
<div id="q4-mon-ni">
<p>次の1~5の<b>解説・意味</b>にあてはまる四字熟語を後の「」から選び、その<b>傍線部分だけの読み</b><b>ひらがな</b>で記せ。</p>
<ol id="q4-mon-ni-questions">
{% for i in range(5) %}
<li>Test</li>
{% endfor %}
</ol>
<div id="q4-mon-ni-wordbox">
<ul id="q4-mon-ni-words">
{% for i in range(8) %}
<li>Test</li>
{% endfor %}
</ul>
</div>
</div>
</div>
<div id="q5">
<h2>(五)</h2>
<p>次の<b>熟字訓・当て字</b>の読みを記せ。</p>
{% for i in range(5) %}
<li>Test</li>
{% endfor %}
</div>
<div id="q6">
<h2>(六)</h2>
<p>次の<b>熟語</b><b>読み</b><b>音読み</b>)とその<b>語義</b>にふさわしい<b>訓読み</b>を(送りがなに注意して)<b>ひらがな</b>で記せ。</p>
<div id="q6-example">
<p>〈例〉健勝……勝れる→けんしょう・すぐ</p>
</div>
<div id="q6-questions">
<ol class="katakana-list">
{% for i in range(5) %}
<li>
<ol start="{{2*i + 1}}">
<li>On</li>
……
<li>Kun</li>
</ol>
</li>
{% endfor %}
</ol>
</div>
</div>
<div id="q7">
<h2>(七)</h2>
<p>次の1~5の<b>対義語</b>、6~10の<b>類義語</b>を後の「」の中から選び、<b>漢字</b>で記せ。「」の中の語は一度だけ使うこと。</p>
<div id="q7-antonyms">
<span><b>対義語</b></span>
<ol>
{% for i in range(5) %}
<li>Test</li>
{% endfor %}
</ol>
</div>
<hr>
<div id="q7-synonyms">
<span><b>対義語</b></span>
<ol start="6">
{% for i in range(5) %}
<li>Test</li>
{% endfor %}
</ol>
</div>
<div id="q7-wordbox">
<ul>
{% for i in range(10) %}
<li>Test</li>
{% endfor %}
</ul>
</div>
</div>
<div id="q8">
<h2>(八)</h2>
<p>次の故事・成語・諺の<b>カタカナ</b>の部分を<b>漢字</b>で記せ。</p>
<ol>
{% for i in range(10) %}
<li>Test</li>
{% endfor %}
</ol>
</div>
<div id="q9">
<h2>(九)</h2>
<p>文章の中の傍線(1~10)の<b>カタカナ</b><b>漢字</b>に直し、波線(ア~コ)の<b>漢字</b>の読みを<b>ひらがな</b>で記せ。</p>
<ol id="q9-texts">
{% for text in range(3) %}
<li>The quick brown fox jumps over the lazy dog.</li>
{% endfor %}
</ol>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,25 @@
{% extends 'base.html' %}
{% block header %}
<h1>{% block title %}{{ localize("options") }}{% endblock %}</h1>
{% endblock %}
{% block content %}
<form method="post" enctype=multipart/form-data>
<label for="language-select">{{ localize("language") }}</label>
<select name="language" id="language-select">
<option value="ja">日本語</option>
<option value="en">English</option>
</select>
<label for="theme-select">{{ localize("theme") }}</label>
<select name="theme" id="theme-select">
<option value="dark">{{ localize("dark_theme") }}</option>
<option value="light">{{ localize("light_theme") }}</option>
</select>
{% block logged_in_options %}{% endblock %}
<hr>
<button type="submit">Okay</button>
</form>
{% endblock %}

View File

@ -1,27 +1,10 @@
{% extends 'base.html' %}
{% extends 'logged_out_options.html' %}
{% block header %}
<h1>{% block title %}{{ localize("options") }}{% endblock %}</h1>
{% endblock %}
{% block content %}
<form method="post" enctype=multipart/form-data>
<label for="language-select">{{ localize("language") }}</label>
<select name="language" id="language-select">
<option value="ja">日本語</option>
<option value="en">English</option>
</select>
<label for="theme-select">{{ localize("theme") }}</label>
<select name="theme" id="theme-select">
<option value="dark">{{ localize("dark_theme") }}</option>
<option value="light">{{ localize("light_theme") }}</option>
</select>
{% block logged_in_options %}
<label for="pfp">{{ localize("pfp") }}</label>
<input type="file" id="pfp" name="pfp">
<hr>
<button type="submit">Okay</button>
</form>
{% endblock %}

View File

@ -11,7 +11,7 @@
<fieldset>
<label for="search_method_includes">Includes</label>
<input type="radio" id="search_method_includes" name="search_method" value="includes">
<input type="radio" id="search_method_includes" name="search_method" value="includes" checked>
<label for="search_method_includes">Matches</label>
<input type="radio" id="search_method_matches" name="search_method" value="matches">
<label for="search_method_includes">Starts with</label>
@ -40,6 +40,7 @@
<option value="include">include</option>
<option value="exclude">exclude</option>
</select>
<button type="submit">Submit</button>
</form>
{% block results %}
{% endblock %}