Skip to content

Commit

Permalink
Feature: users can view and export all of their queries.
Browse files Browse the repository at this point in the history
  • Loading branch information
liffiton committed Dec 29, 2024
1 parent 6c7188d commit f18142b
Show file tree
Hide file tree
Showing 11 changed files with 137 additions and 8 deletions.
36 changes: 36 additions & 0 deletions src/codehelp/templates/profile_view_data.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{#
SPDX-FileCopyrightText: 2024 Mark Liffiton <liffiton@gmail.com>

SPDX-License-Identifier: AGPL-3.0-only
#}

{% extends "base.html" %}
{% from "tables.html" import datatable, datatable_extrahead %}

{% block extrahead %}
{{ datatable_extrahead }}
{% endblock %}

{% block body %}
<section class="section p-5">
<h1 class="title">Your Queries</h1>
{{
datatable('queries', [
('id', 'id'),
('time', 'query_time', 't'),
('context', 'context_name'),
('code', 'code'),
('error', 'error'),
('issue', 'issue'),
('response (len)', 'response_text'),
('helpful', 'helpful_emoji')
],
queries,
hidden_cols=['id'],
link_col=0,
link_template="/help/view/${value}",
csv_link=url_for("profile.get_csv", kind="queries")
)
}}
</section>
{% endblock %}
3 changes: 2 additions & 1 deletion src/codehelp/templates/recent_queries.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

{% macro recent_queries(history) -%}
<div class="p-4">
<h2 class="is-size-5">Your recent queries:</h2>
<a class="button is-info is-small is-pulled-right" href="{{ url_for('profile.view_data') }}">View all</a>
<h2 class="title is-size-5">Your recent queries:</h2>
{% for prev in history %}
<div class="box p-3">
<div class="buttons has-addons are-small is-pulled-right">
Expand Down
6 changes: 3 additions & 3 deletions src/gened/csv.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from werkzeug.wrappers.response import Response


def csv_response(class_name: str, kind: str, table: list[Row]) -> str | Response:
def csv_response(file_name: str, kind: str, table: list[Row]) -> str | Response:
if not table:
flash("There are no rows to export yet.", "warning")
return render_template("error.html")
Expand All @@ -22,9 +22,9 @@ def csv_response(class_name: str, kind: str, table: list[Row]) -> str | Response
writer.writerows(table)

output = make_response(stringio.getvalue())
class_name = class_name.replace(" ","-")
file_name = file_name.replace(" ","-")
timestamp = dt.datetime.now().strftime("%Y%m%d")
output.headers["Content-Disposition"] = f"attachment; filename={timestamp}_{class_name}_{kind}.csv"
output.headers["Content-Disposition"] = f"attachment; filename={timestamp}_{file_name}_{kind}.csv"
output.headers["Content-type"] = "text/csv"

return output
20 changes: 20 additions & 0 deletions src/gened/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from flask import (
Blueprint,
abort,
current_app,
flash,
redirect,
Expand All @@ -15,8 +16,10 @@
from werkzeug.wrappers.response import Response

from .auth import generate_anon_username, get_auth, login_required
from .csv import csv_response
from .data_deletion import delete_user_data
from .db import get_db
from .queries import get_history
from .redir import safe_redirect

bp = Blueprint('profile', __name__, template_folder='templates')
Expand Down Expand Up @@ -90,6 +93,23 @@ def main() -> str:
)


@bp.route("/data/")
def view_data() -> str:
queries = get_history(limit=-1) # -1 = no limit
return render_template("profile_view_data.html", queries=queries)

@bp.route("/data/csv/<string:kind>")
def get_csv(kind: str) -> str | Response:
if kind not in ('queries'):
return abort(404)

auth = get_auth()
assert auth.user

queries = get_history(limit=-1) # -1 = no limit
return csv_response(auth.user.display_name, kind, queries)


@bp.route("/delete_data", methods=['POST'])
def delete_data() -> Response:
# Require explicit confirmation
Expand Down
1 change: 1 addition & 0 deletions src/gened/queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def get_history(limit: int = 10) -> list[Row]:
'''Fetch current user's query history.'''
db = get_db()
auth = get_auth()
assert auth.user_id is not None

cur = db.execute("SELECT * FROM queries WHERE queries.user_id=? ORDER BY query_time DESC LIMIT ?", [auth.user_id, limit])
history = cur.fetchall()
Expand Down
5 changes: 4 additions & 1 deletion src/gened/templates/profile_view.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ <h1 class="title">Your Profile</h1>
</dd>
{% endif %}
<dt>Queries:</dt>
<dd>{{ user.num_queries }} total, {{ user.num_recent_queries }} in the past week.</dd>
<dd><a href="{{ url_for('profile.view_data') }}">{{ user.num_queries }} total</a>, {{ user.num_recent_queries }} in the past week.</dd>
{% if not auth.cur_class %}
<dt>Free Queries:</dt>
<dd>
Expand Down Expand Up @@ -109,6 +109,9 @@ <h2 class="title is-size-3">

<h2 class="title is-size-3">Your Data</h2>
<div class="buttons">
<a class="button ml-5 is-info" href="{{ url_for('profile.view_data') }}">
View &amp; export your data
</a>
{% if user.provider_name not in ['lti', 'demo', 'local'] %}
<button class="button ml-5 icon-text is-info" onclick="document.querySelector('#anonymize_dialog').showModal()">
<span class="icon">
Expand Down
32 changes: 32 additions & 0 deletions src/language/templates/profile_view_data.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{#
SPDX-FileCopyrightText: 2024 Mark Liffiton <liffiton@gmail.com>

SPDX-License-Identifier: AGPL-3.0-only
#}

{% extends "base.html" %}
{% from "tables.html" import datatable, datatable_extrahead %}

{% block extrahead %}
{{ datatable_extrahead }}
{% endblock %}

{% block body %}
<section class="section p-5">
<h1 class="title">Your Queries</h1>
{{
datatable('queries', [
('id', 'id'),
('user', 'display_name'),
('time', 'query_time', 't'),
('writing', 'writing'),
('response', 'response_text')
],
queries,
link_col=0,
link_template=url_for('helper.help_view', query_id='${value}',
csv_link=url_for("profile.get_csv", kind="queries")
)
}}
</section>
{% endblock %}
3 changes: 2 additions & 1 deletion src/language/templates/recent_queries.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

{% macro recent_queries(history) -%}
<div class="p-4">
<h2 class="is-size-5">Your recent queries:</h2>
<a class="button is-info is-small is-pulled-right" href="{{ url_for('profile.view_data') }}">View all</a>
<h2 class="title is-size-5">Your recent queries:</h2>
{% for prev in history %}
<div class="box p-3">
<div class="buttons has-addons are-small is-pulled-right">
Expand Down
34 changes: 34 additions & 0 deletions src/starburst/templates/profile_view_data.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{#
SPDX-FileCopyrightText: 2024 Mark Liffiton <liffiton@gmail.com>

SPDX-License-Identifier: AGPL-3.0-only
#}

{% extends "base.html" %}
{% from "tables.html" import datatable, datatable_extrahead %}

{% block extrahead %}
{{ datatable_extrahead }}
{% endblock %}

{% block body %}
<section class="section p-5">
<h1 class="title">Your Queries</h1>
{{
datatable('queries', [
('id', 'id'),
('user', 'display_name'),
('time', 'query_time', 't'),
('assignment', 'assignment'),
('topics', 'topics'),
('response', 'response_text'),
('helpful', 'helpful_emoji')
],
queries,
link_col=0,
link_template="/ideas/view/${value}",
csv_link=url_for("profile.get_csv", kind="queries")
)
}}
</section>
{% endblock %}
3 changes: 2 additions & 1 deletion src/starburst/templates/recent_queries.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

{% macro recent_queries(history) -%}
<div class="p-4">
<h2 class="is-size-5">Your recent queries:</h2>
<a class="button is-info is-small is-pulled-right" href="{{ url_for('profile.view_data') }}">View all</a>
<h2 class="title is-size-5">Your recent queries:</h2>
{% for prev in history %}
<div class="box p-3">
<div class="buttons has-addons are-small is-pulled-right">
Expand Down
2 changes: 1 addition & 1 deletion tests/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ def test_logout(client, auth):

@pytest.mark.parametrize(('path', 'nologin', 'withlogin', 'withadmin'), [
('/', 200, 200, 200),
('/profile/', 302, (200, "2 total, 2 in the past week"), (200, "0 total, 0 in the past week")),
('/profile/', 302, (200, "2 in the past week"), (200, "0 in the past week")),
('/help/', 302, 200, 200),
('/help/view/1', 302, (400, "Invalid id."), (200, "response1")),
('/tutor/', 404, 200, 404),
Expand Down

0 comments on commit f18142b

Please sign in to comment.