gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [taler-bank] branch master updated (acdef0d -> beb6279)


From: gnunet
Subject: [GNUnet-SVN] [taler-bank] branch master updated (acdef0d -> beb6279)
Date: Mon, 15 Jan 2018 17:08:00 +0100

This is an automated email from the git hooks/post-receive script.

marcello pushed a change to branch master
in repository bank.

    from acdef0d  Closing #5149.
     new 544b1f0  history extracting logic goes in one point, and /history 
calls it now.
     new 3562cf0  set the state to implement the "see next page" feature useful 
when an account's history is too long.
     new 1a22709  make /<page_number> available
     new 9d4586a  implement page numbers
     new beb6279  fixing the back-and-forth arrows to navigate multiple pages 
/public-history results.

The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 talerbank/app/static/bank.css                |  12 +++
 talerbank/app/templates/public_accounts.html |  75 ++++++++++------
 talerbank/app/urls.py                        |  36 +++++---
 talerbank/app/views.py                       | 124 ++++++++++++++++++++-------
 4 files changed, 175 insertions(+), 72 deletions(-)

diff --git a/talerbank/app/static/bank.css b/talerbank/app/static/bank.css
index 20e7586..4c16e94 100644
--- a/talerbank/app/static/bank.css
+++ b/talerbank/app/static/bank.css
@@ -3,6 +3,18 @@ h1.nav {
   display: inline-block;
 }
 
+div.pages-list {
+  margin-top: 15px;
+}
+
+a.page-number {
+  color: blue;
+}
+
+a.current-page-number {
+  color: inherit;
+}
+
 a.pure-button {
   position: absolute;
   right: 20px;
diff --git a/talerbank/app/templates/public_accounts.html 
b/talerbank/app/templates/public_accounts.html
index e92edb6..3ebe6ad 100644
--- a/talerbank/app/templates/public_accounts.html
+++ b/talerbank/app/templates/public_accounts.html
@@ -55,32 +55,55 @@
         </ul>
       </div>
 
-      {% if selected_account.history %}
-        <table class="pure-table pure-table-striped">
-          <thead>
-            <th>Date</th>
-            <th>Amount</th>
-            <th>Counterpart</th>
-            <th>Subject</th>
-          </thead>
-          <tbody>
-          {% for entry in selected_account.history %}
-          <tr>
-            <td>{{entry.date}}</td>
-            <td>
-              {{ entry.sign }} {{ entry.amount }}
-            </td>
-            <td>{% if entry.counterpart_username %} {{ 
entry.counterpart_username }} {% endif %} (account #{{ entry.counterpart 
}})</td>
-            <td {% if entry.cancelled %} class="cancelled" {% endif %}>
-              {{ entry.subject }}
-            </td>
-          </tr>
-          {% endfor %}
-          </tbody>
-        </table>
-      {% else %}
-        <p>No history for account #{{ selected_account.number }} ({{ 
selected_account.name}}) yet</p>
-      {% endif %}
+      <div class="results">
+        {% if selected_account.history %}
+          <table class="pure-table pure-table-striped">
+            <thead>
+              <th>Date</th>
+              <th>Amount</th>
+              <th>Counterpart</th>
+              <th>Subject</th>
+            </thead>
+            <tbody>
+            {% for entry in selected_account.history %}
+            <tr>
+              <td>{{entry.date}}</td>
+              <td>
+                {{ entry.sign }} {{ entry.amount }}
+              </td>
+              <td>{% if entry.counterpart_username %} {{ 
entry.counterpart_username }} {% endif %} (account #{{ entry.counterpart 
}})</td>
+              <td {% if entry.cancelled %} class="cancelled" {% endif %}>
+                {{ entry.subject }}
+              </td>
+            </tr>
+            {% endfor %}
+            </tbody>
+          </table>
+          <div class="pages-list">
+            {% if back %}
+              <a
+               class="page-number"
+               href="{{ url("public-accounts", name=selected_account.name, 
page=back) }}">&lsaquo;...</a>
+            {% endif %}
+            {% for pagej in pages %}
+              <a
+               {% if pagej == current_page%}
+                 class="current-page-number"
+               {% else %}
+                 class="page-number"
+               {% endif %}
+               href="{{ url("public-accounts", name=selected_account.name, 
page=pagej) }}">{{ pagej }}</a>
+            {% endfor %}
+            {% if forth %}
+              <a
+               class="page-number"
+               href="{{ url("public-accounts", name=selected_account.name, 
page=forth) }}">...&rsaquo;</a>
+            {% endif %}
+          </div>
+        {% else %}
+          <p>No history for account #{{ selected_account.number }} ({{ 
selected_account.name}}) yet</p>
+        {% endif %}
+      </div>
     </article>
   </section>
 {% endblock content %}
diff --git a/talerbank/app/urls.py b/talerbank/app/urls.py
index c44c7c3..19c0169 100644
--- a/talerbank/app/urls.py
+++ b/talerbank/app/urls.py
@@ -1,16 +1,19 @@
 #  This file is part of TALER
 #  (C) 2014, 2015, 2016 INRIA
 #
-#  TALER is free software; you can redistribute it and/or modify it under the
-#  terms of the GNU Affero General Public License as published by the Free 
Software
-#  Foundation; either version 3, or (at your option) any later version.
+#  TALER is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation; either version 3, or
+# (at your option) any later version.
 #
-#  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
-#  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
FOR
-#  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#  TALER is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
 #
-#  You should have received a copy of the GNU General Public License along with
-#  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+#  You should have received a copy of the GNU General Public
+# License along with TALER; see the file COPYING.  If not, see
+# <http://www.gnu.org/licenses/>.
 #
 #  @author Marcello Stanisci
 
@@ -20,9 +23,11 @@ from . import views
 
 urlpatterns = [
     url(r'^', include('talerbank.urls')),
-    url(r'^$', RedirectView.as_view(pattern_name="profile"), name="index"),
+    url(r'^$', RedirectView.as_view(pattern_name="profile"),
+        name="index"),
     url(r'^favicon\.ico$', views.ignore),
-    url(r'^admin/add/incoming$', views.add_incoming, name="add-incoming"),
+    url(r'^admin/add/incoming$', views.add_incoming,
+        name="add-incoming"),
     url(r'^login/$', views.login_view, name="login"),
     url(r'^logout/$', views.logout_view, name="logout"),
     url(r'^accounts/register/$', views.register, name="register"),
@@ -30,10 +35,15 @@ urlpatterns = [
     url(r'^history$', views.serve_history, name="history"),
     url(r'^reject$', views.reject, name="reject"),
     url(r'^withdraw$', views.withdraw_nojs, name="withdraw-nojs"),
-    url(r'^public-accounts$', views.serve_public_accounts, 
name="public-accounts"),
-    url(r'^public-accounts/(?P<name>[a-zA-Z0-9 ]+)$',
+    url(r'^public-accounts$', views.serve_public_accounts,
+        name="public-accounts"),
+    url(r'^public-accounts/(?P<name>[a-zA-Z0-9]+)$',
+        views.serve_public_accounts,
+        name="public-accounts"),
+    url(r'^public-accounts/(?P<name>[a-zA-Z0-9]+)/(?P<page>[0-9]+)$',
         views.serve_public_accounts,
         name="public-accounts"),
-    url(r'^pin/question$', views.pin_tan_question, name="pin-question"),
+    url(r'^pin/question$', views.pin_tan_question,
+        name="pin-question"),
     url(r'^pin/verify$', views.pin_tan_verify, name="pin-verify"),
     ]
diff --git a/talerbank/app/views.py b/talerbank/app/views.py
index 6383a68..fa6efa4 100644
--- a/talerbank/app/views.py
+++ b/talerbank/app/views.py
@@ -18,6 +18,7 @@
 #  @author Florian Dold
 
 from functools import wraps
+import math
 import json
 import logging
 import hashlib
@@ -320,11 +321,10 @@ def logout_view(request):
     return redirect("index")
 
 
-def extract_history(account):
+def extract_history(account, delta=None, start=-1, sign="+"):
     history = []
-    related_transactions = BankTransaction.objects.filter(
-        Q(debit_account=account) | Q(credit_account=account))
-    for item in related_transactions:
+    qs = query_history(account, "both", delta, start, sign)
+    for item in qs:
         if item.credit_account == account:
             counterpart = item.debit_account
             sign = ""
@@ -345,18 +345,53 @@ def extract_history(account):
     return history
 
 
-def serve_public_accounts(request, name=None):
+def serve_public_accounts(request, name=None, page=None):
+    
+    try:
+        page = int(page)
+    except Exception:
+        page = 1
+
     if not name:
         name = settings.TALER_PREDEFINED_ACCOUNTS[0]
     user = User.objects.get(username=name)
+
+    if "public_history_count" not in request.session:
+        qs = extract_history(user.bankaccount, sign="-")
+        youngest = -1
+        if qs:
+            youngest = qs[0]["row_id"]
+        request.session["public_history_account"] = \
+            len(qs), youngest
+
+    DELTA = 30
+    youngest = request.session["public_history_account"][1]
+    # normalize page
+    if not page or page in [0, 1]:
+        page = 1
+    # page 0 and 1 give both the youngest 100 records.
+    if page > 1:
+        youngest = youngest - (DELTA * (page - 1)) # goes backwards.
     if not user.bankaccount.is_public:
         request.session["public_accounts_hint"] = \
             True, False, "Could not query private accounts!"
     fail_message, success_message, hint = \
         get_session_hint(request, "public_accounts_hint")
     public_accounts = BankAccount.objects.filter(is_public=True)
-    history = extract_history(user.bankaccount)
+
+    # Retrieve DELTA records older than 'start'.
+    history = extract_history(
+        user.bankaccount, DELTA,
+        -1 if youngest < 2 else youngest, "-")
+
+    num_pages = request.session["public_history_account"][0] / DELTA
+    pages = list(
+        range(max(1, page - 3),
+              min(page + 4, math.ceil(num_pages))))
     context = dict(
+        current_page=page,
+        back = page - 1 if pages[0] > 1 else None,
+        forth = page + 1 if pages[-1] < num_pages else None,
         public_accounts=public_accounts,
         selected_account=dict(
             fail_message=fail_message,
@@ -365,7 +400,8 @@ def serve_public_accounts(request, name=None):
             name=name,
             number=user.bankaccount.account_no,
             history=history,
-        )
+        ),
+        pages=pages
     )
     return render(request, "public_accounts.html", context)
 
@@ -378,6 +414,49 @@ def login_via_headers(view_func):
         return view_func(request, user_account, *args, **kwargs)
     return wraps(view_func)(_decorator)
 
+# Internal function used by /history and /public-accounts.  It
+# offers abstraction against the query string definition and DB
+# querying.
+#
+# 'bank_account': whose history is going to be retrieved.
+# 'direction': (both|credit|debit|cancel+|cancel-).
+# 'delta': how many results are going to be extracted.  If 'None'
+#   is given, no filter of this kind will be applied.
+# 'start': a "id" indicating the first record to be returned.
+#   If -1 is given, then the first record will be the youngest.
+# 'sign': (+|-) indicating that we want records younger|older
+#   than 'start'.
+
+def query_history(bank_account, direction, delta, start, sign):
+    direction_switch = {
+        "both": Q(debit_account=bank_account) \
+                | Q(credit_account=bank_account),
+        "credit": Q(credit_account=bank_account),
+        "debit": Q(debit_account=bank_account),
+        "cancel+": Q(credit_account=bank_account) \
+                      & Q(cancelled=True),
+        "cancel-": Q(debit_account=bank_account) \
+                      & Q(cancelled=True)}
+
+    sign_filter = {
+        "+": Q(id__gt=start),
+        "-": Q(id__lt=start),
+        "*": Q(),
+        "x": not Q(),
+    }
+
+    # Handle special case.
+    if start == -1: # can only retrieve older records.
+        sign = "*"
+        if sign == "+": # no result is younger than the youngest.
+            sign = "x"
+
+    return BankTransaction.objects.filter(
+        direction_switch.get(direction),
+        sign_filter.get(sign)).order_by(
+            # '-id' does descending ordering.
+            "-id" if sign in ["-", "*"] else "id")[:delta]
+
 @require_GET
 @login_via_headers
 def serve_history(request, user_account):
@@ -390,36 +469,15 @@ def serve_history(request, user_account):
     parsed_delta = re.search(r"([\+-])?([0-9]+)",
                              request.GET.get("delta"))
     sign = parsed_delta.group(1)
-    # start
-    start = int(request.GET.get("start", -1))
-
-    # translating delta's sign into query object
-    sign_filter = Q()
-    if start >= 0:
-        sign_filter = Q(id__gt=start)
-        if sign == "-":
-            sign_filter = Q(id__lt=start)
 
+    qs = query_history(user_account.bankaccount,
+                       request.GET.get("direction"),
+                       int(parsed_delta.group(2)),
+                       int(request.GET.get("start", -1)),
+                       sign if sign else "+")
 
-    direction_switch = {
-        "both": Q(debit_account=user_account.bankaccount) \
-                | Q(credit_account=user_account.bankaccount),
-        "credit": Q(credit_account=user_account.bankaccount),
-        "debit": Q(debit_account=user_account.bankaccount),
-        "cancel+": Q(credit_account=user_account.bankaccount) \
-                      & Q(cancelled=True),
-        "cancel-": Q(debit_account=user_account.bankaccount) \
-                      & Q(cancelled=True)
-    }
-    # Sanity checks are done at the beginning, so 'direction' key
-    # (and its value as switch's key) does exist here.
-    query_string = direction_switch[request.GET["direction"]]
     history = []
     cancelled = request.GET.get("cancelled", "show")
-    qs = BankTransaction.objects.filter(
-        query_string, sign_filter).order_by(
-            "-id" if sign == "-" else "id") \
-            [:int(parsed_delta.group(2))]
     for entry in qs:
         counterpart = entry.credit_account.account_no
         sign_ = "-"

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]