aboutsummaryrefslogtreecommitdiffstats
path: root/browser
diff options
context:
space:
mode:
authorJan Tuomi <jan@jantuomi.fi>2025-02-17 19:32:08 +0200
committerJan Tuomi <jan@jantuomi.fi>2025-02-17 19:32:08 +0200
commit371bbe0390113ecbf032ae9bcfc6a93470ffad67 (patch)
treeb0d7ea8afdd57d75fe4a2cd21bab208f2f0b9461 /browser
parent9a83e5f1d5f851137f82720c35fc18b52a454aa8 (diff)
Implement range query
Diffstat (limited to 'browser')
-rw-r--r--browser/app.py71
-rw-r--r--browser/templates/frag_form_delete.html.j27
-rw-r--r--browser/templates/frag_form_find.html.j22
-rw-r--r--browser/templates/frag_form_range.html.j220
-rw-r--r--browser/templates/frag_form_upsert.html.j25
5 files changed, 96 insertions, 9 deletions
diff --git a/browser/app.py b/browser/app.py
index 92fcbbf..659e7a5 100644
--- a/browser/app.py
+++ b/browser/app.py
@@ -5,6 +5,7 @@ import os
import sys
import traceback
import tempfile
+from typing import cast
from flask import Flask, render_template, request
from flask_compress import Compress # type: ignore
@@ -105,13 +106,73 @@ def query_find():
rows = rows,
)
-@app.get("/range")
-def page_range():
- rows = db.range_by("id", Bound.unbounded(), Bound.unbounded(), limit=100)
+@app.post("/range")
+def query_range():
+ field = request.form.get("field")
+ if not field: raise ValueError("Field is required")
+
+ from_type = request.form.get("from_type")
+ if not from_type: raise ValueError("From type is required")
+
+ to_type = request.form.get("to_type")
+ if not to_type: raise ValueError("To type is required")
+
+ field_index = db_fields.index(field)
+ if field_index == -1: raise ValueError(f"Field '{field}' not found")
+
+ match from_type:
+ case "unbounded":
+ bound_lower = Bound.unbounded()
+ case "included":
+ from_value = request.form.get("from_value")
+ try:
+ if not from_value: raise ValueError("From value is required")
+ from_value = cast_to_value(field, from_value)
+ except ValueError as e:
+ return error(str(e), 400)
+ bound_lower = Bound.included(cast(Value, from_value))
+ case "excluded":
+ from_value = request.form.get("from_value")
+ try:
+ if not from_value: raise ValueError("From value is required")
+ from_value = cast_to_value(field, from_value)
+ except ValueError as e:
+ return error(str(e), 400)
+ bound_lower = Bound.excluded(cast(Value, from_value))
+ case _:
+ return error("Invalid from type", 400)
+
+ match to_type:
+ case "unbounded":
+ bound_upper = Bound.unbounded()
+ case "included":
+ to_value = request.form.get("to_value")
+ try:
+ if not to_value: raise ValueError("To value is required")
+ to_value = cast_to_value(field, to_value)
+ except ValueError as e:
+ return error(str(e), 400)
+ bound_upper = Bound.included(cast(Value, to_value))
+ case "excluded":
+ to_value = request.form.get("to_value")
+ try:
+ if not to_value: raise ValueError("To value is required")
+ to_value = cast_to_value(field, to_value)
+ except ValueError as e:
+ return error(str(e), 400)
+ bound_upper = Bound.excluded(cast(Value, to_value))
+ case _:
+ return error("Invalid to type", 400)
+
+ tagged_rows = db.range_by(field, bound_lower, bound_upper, limit=100)
+ rows = [[value_to_str(v) for v in row] for row in tagged_rows]
htmp_target = request.form.get("htmp") or request.args.get("htmp")
if htmp_target:
- return render_template("frag_form_range.html.j2")
+ return render_template("frag_results.html.j2",
+ field_names = ["id", "name"],
+ rows = rows,
+ )
else:
return render_template('page_main.html.j2',
selected_form = "frag_form_range.html.j2",
@@ -119,6 +180,8 @@ def page_range():
rows = rows,
)
+# Utils
+
def cast_to_value(field: str, str_value: str) -> Value | None:
str_value = str_value.strip()
if str_value == "": return None
diff --git a/browser/templates/frag_form_delete.html.j2 b/browser/templates/frag_form_delete.html.j2
new file mode 100644
index 0000000..a362075
--- /dev/null
+++ b/browser/templates/frag_form_delete.html.j2
@@ -0,0 +1,7 @@
+<form id="form_query" action="/delete" method="post" htmp replace=results>
+ <label for="field">Field</label>
+ <input type="text" name="field" id="field" required>
+ <label for="values">Values (one per line)</label>
+ <textarea name="values" id="values" required></textarea>
+ <button type="submit">Run query</button>
+</form>
diff --git a/browser/templates/frag_form_find.html.j2 b/browser/templates/frag_form_find.html.j2
index f527b45..cadd44b 100644
--- a/browser/templates/frag_form_find.html.j2
+++ b/browser/templates/frag_form_find.html.j2
@@ -1,4 +1,4 @@
-<form id="form_query" action="/find" method="get" htmp replace=results>
+<form id="form_query" action="/find" method="post" htmp replace=results>
<label for="field">Field</label>
<input type="text" name="field" id="field" required>
<label for="values">Values (one per line)</label>
diff --git a/browser/templates/frag_form_range.html.j2 b/browser/templates/frag_form_range.html.j2
index 96fe8a8..84b8024 100644
--- a/browser/templates/frag_form_range.html.j2
+++ b/browser/templates/frag_form_range.html.j2
@@ -1,9 +1,21 @@
<form id="form_query" action="/range" method="post" htmp replace=results>
<label for="field">Field</label>
<input type="text" name="field" id="field" required>
- <label for="values">From...</label>
- <input type="text" name="from" id="from" required>
- <label for="values">...To</label>
- <input type="text" name="to" id="to" required>
+ <label for="from_type">Lower bound type</label>
+ <select id="from_type" name="from_type" required>
+ <option value="unbounded">Unbounded</option>
+ <option value="included">Inclusive</option>
+ <option value="excluded">Exclusive</option>
+ </select>
+ <label for="values">Lower bound value</label>
+ <input type="text" name="from_value" id="from_value">
+ <label for="to_type">Upper bound type</label>
+ <select id="to_type" name="to_type" required>
+ <option value="unbounded">Unbounded</option>
+ <option value="included">Inclusive</option>
+ <option value="excluded">Exclusive</option>
+ </select>
+ <label for="values">Upper bound value</label>
+ <input type="text" name="to_value" id="to_value">
<button type="submit">Run query</button>
</form>
diff --git a/browser/templates/frag_form_upsert.html.j2 b/browser/templates/frag_form_upsert.html.j2
new file mode 100644
index 0000000..68820f5
--- /dev/null
+++ b/browser/templates/frag_form_upsert.html.j2
@@ -0,0 +1,5 @@
+<form id="form_query" action="/upsert" method="post" htmp replace=results>
+ <label for="values">Values (one per line)</label>
+ <textarea name="values" id="values" required></textarea>
+ <button type="submit">Run query</button>
+</form>