From b71027dd3e844697d97d1b6427f8eab888f9aa47 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1=C5=A1?= <git@imaniti.org>
Date: Mon, 30 Jan 2023 14:49:49 +0100
Subject: [PATCH] nicer UI, loading info & disabling button when calculating

---
 .../templates/rv_voting_calc/index.html       | 20 ++++-
 rv_voting_calc/views.py                       |  3 +-
 static_src/rv_voting_calc.js                  | 76 ++++---------------
 3 files changed, 33 insertions(+), 66 deletions(-)

diff --git a/rv_voting_calc/templates/rv_voting_calc/index.html b/rv_voting_calc/templates/rv_voting_calc/index.html
index effaff1..12bb2a7 100644
--- a/rv_voting_calc/templates/rv_voting_calc/index.html
+++ b/rv_voting_calc/templates/rv_voting_calc/index.html
@@ -8,6 +8,17 @@
 
 {% block head %}
     {% render_bundle "rv_voting_calc" %}
+
+    <link
+        href="https://styleguide.pirati.cz/2.11.x/css/styles.css"
+        rel="stylesheet"
+        media="all"
+    >
+    <link
+        href="https://styleguide.pirati.cz/2.11.x/css/pattern-scaffolding.css"
+        rel="stylesheet"
+        media="all"
+    >
 {% endblock %}
 
 {% block content %}
@@ -20,9 +31,14 @@
             <div class="flex items-center gap-3 justify-between">
                 <h2 class="text-2xl font-bebas">Výsledky</h2>
                 <button
-                    class="bg-black text-white px-5 py-3 duration-100 hover:bg-gray-800"
+                    class="btn disabled:cursor-progress"
                     id="count-votes"
-                >Vypočítat</button>
+                    disabled
+                >
+                    <div class="btn__body">
+                        Vypočítat
+                    </div>
+                </button>
             </div>
         </div>
 
diff --git a/rv_voting_calc/views.py b/rv_voting_calc/views.py
index ddb2429..4810e7c 100644
--- a/rv_voting_calc/views.py
+++ b/rv_voting_calc/views.py
@@ -22,7 +22,8 @@ def get_options_by_member(source, rv_members) -> dict:
     try:
         options_by_member = json.loads(source)
 
-        if not isinstance(options_by_member, dict):
+        # The provided votes must be a dictionary with at least 1 key.
+        if not isinstance(options_by_member, dict) or len(options_by_member) == 0:
             raise ValueError
     except ValueError:
         raise HTTPExceptions.BAD_REQUEST
diff --git a/static_src/rv_voting_calc.js b/static_src/rv_voting_calc.js
index 58d6e09..136238f 100644
--- a/static_src/rv_voting_calc.js
+++ b/static_src/rv_voting_calc.js
@@ -38,39 +38,7 @@ $(window).ready(
         $(".__vote-selection").on(
             "select2:select",
             event => {
-//                 //// Sync the tag option with other selectors.
-// 
-//                 // If the tag isn't new for this selection, do nothing.
-//                 if (!event.params.data.isNew) {
-//                     return;
-//                 }
-// 
-//                 const tagName = event.params.data.id;
-// 
-//                 const addedTag = new Option(
-//                     tagName,
-//                     tagName,
-//                     false,
-//                     false
-//                 );
-// 
-//                 // Get all other selections.
-//                 const unfilteredSelections = $(".__vote-selection").not(event.target);
-//                 let filteredSelections = [];
-// 
-//                 // Check if they contain the tag. If they do, ignore them.
-//                 for (const selection of unfilteredSelections) {
-//                     if (
-//                         $(selection).
-//                         children(`option[value=${$.escapeSelector(tagName)}]`).
-//                         length === 0
-//                     ) {
-//                         filteredSelections.push(selection);
-//                     }
-//                 }
-// 
-//                 // Add the new tag to all selections that don't have it yet.
-//                 $(filteredSelections).append(addedTag).trigger("change");
+                $("#count-votes").prop("disabled", false);
 
                 // Keep user-defined ordering. This is imperative!
                 // http://github.com/select2/select2/issues/3106 - Thanks to kevin-brown!
@@ -85,41 +53,21 @@ $(window).ready(
         $(".__vote-selection").on(
             "select2:unselect",
             event => {
-                //// Remove the tag option if it's not selected anywhere.
-
-//                 const tagName = event.params.data.id;
-// 
-//                 // Get all other selections.
-//                 const selections = $(".__vote-selection");
-// 
-//                 // Check if any of them have the tag selected. If they do, end the function.
-//                 for (const selection of selections) {
-//                     for (const data of $(selection).select2("data")) {
-//                         if (data.id == tagName) {
-//                             // TODO - Don't remove the tag from this select.
-//                             // I'm not sure select2 has a good way of doing this.
-// 
-//                             return;
-//                         }
-//                     }
-//                 }
-// 
-//                 // If the function has not ended by now, we can remove the tag.
-//                 for (const selection of selections) {
-//                     (
-//                         $(selection).
-//                         children(`option[value=${$.escapeSelector(tagName)}]`).
-//                         remove()
-//                     );
-// 
-//                     $(selection).trigger("change");
-//                 }
+                for (const selection of $(".__vote-selection")) {
+                    if ($(selection).select2("data").length !== 0) {
+                        return;
+                    }
+                }
+
+                $("#count-votes").prop("disabled", true);
             }
         );
 
         $("#count-votes").on(
             "click",
             async (event) => {
+                $(event.currentTarget).addClass("btn--loading").prop("disabled", true);
+
                 let votes = {};
 
                 for (const username of Object.keys(RV_MEMBERS)) {
@@ -139,7 +87,7 @@ $(window).ready(
                 const urlParams = new URL(window.location).searchParams;
                 const rvGid = urlParams.get("rv_gid");
                 const seed = urlParams.get("seed");
-                
+
                 let response = await fetch(
                     VOTE_CALCULATION_ENDPOINT
                     + `?votes=${encodeURIComponent(JSON.stringify(votes))}`
@@ -171,6 +119,8 @@ $(window).ready(
                         + `&seed=${Cookies.get("seed")}`
                     )
                 );
+
+                $(event.currentTarget).removeClass("btn--loading").prop("disabled", false);
             }
         );
     }
-- 
GitLab