Ver Fonte

still a wip

* too many fixes to enumerate here
* see `Testing-Notes.md`
abetusk há 5 anos atrás
pai
commit
9583c893da

+ 107 - 0
Testing-Notes.md

@@ -0,0 +1,107 @@
+# Popufare-Admin-Web-UI Testing
+
+A reference Admin Web UI to interface with the Popufare system
+
+**NOTE: THIS IS UNDER DEVELOPMENT AND IS NOT READY FOR USAGE**
+
+Current Testing
+---
+
+
+#### Starting test Database
+
+To get a test environment set up, go to the `popufare` repository and navigate to the `server/docker` directory.
+
+Run:
+
+```
+./run_daemon.sh
+```
+
+This should run a Popufare Docker image with the appropriate ports mapped.
+
+To `ssh` in for user `bus`, password `bus` (setup in the [Dockerfile](https://tree.clementinecomputing.com/clementinecomputing/popufare/src/release/server/docker/Dockerfile)):
+
+```
+ssh -p 6055 bus@localhost
+```
+
+Once in, you can access the database with user `busapi`, password `bus` (in [setup-testdb](https://tree.clementinecomputing.com/clementinecomputing/popufare/src/release/server/docker/setup-testdb)):
+
+```
+mysql -u busapi -p busdb
+```
+
+---
+
+You can also connect to the SQL database directly through port `5506` and making sure to specify the host name of `127.0.0.1`:
+
+```
+mysql -u busapi -p busdb -h 127.0.0.1 -P 5506
+```
+
+#### Staring test Web server
+
+You might need to fiddle with the port.
+Right now it's set to `8182`.
+
+Go into the [Popufare-Admin-Web-UI](https://tree.clementinecomputing.com/clementinecomputing/Popufare-Admin-Web-UI) repository.
+
+```
+cd Popufare-Admin-Web-UI
+cd main
+./main.py
+```
+
+You should have a test web server running on `8182` that you can connect to now.
+
+
+#### TODO
+
+* Manage Cards
+  - ~Fill in `Active Pass`, `Comment`, `Other ID` when looking up by (`cardid`/`magstripe`/`rfid`)~
+  - ~Fill in User information when looking up card~
+  - ~Add Multi Ride Pass~
+  - ~Add Multi Day Pass~
+  - ~Add Other Pass~
+  - ~Update pass list after pass addition~
+  - ~Fix date display issue in pass list~
+  - ~Correctly redirect to `Manage User` and grey out if no user available~
+  - Correctly redirect to `Re-Issue Card`
+  - ~Add checkboxes to passes and add functionality to delete entries~
+  - Correctly fill in 'group' (maybe don't make it a drop down?)
+* Manage Users
+  - ~Lookup by `User Id`~
+  - ~Lookup by `User Name`~
+  - Reset Password
+  - Add Card to user
+    * ~Associate by mag stripe~
+    * ~Associate by rfid~
+    * ~Associate by cardid~
+    * Group (?)
+    * Grey out by preference (cardid -> mag -> rfid)
+  - ~List user owned cards~
+    * ~Redirect to manage card for listed user cards~
+* ~Create User~
+* Re-Issue Card
+* Recycle Card
+  - Add drop down for card group
+* Add Card Block
+  - Magstripe
+  - RFID
+  - None pass type
+  - Multi-Ride pass type
+  - Multi-Day pass type
+  - Other pass type
+* Process Pending Card
+  - ???
+* Search
+  - Search cards
+  - Search Users
+  - Search Admins
+  - Give option for number of results per page
+  - Paginate options
+
+| Item | Completed | Description |
+|---|---|---|
+

+ 1 - 1
main/app/__init__.py

@@ -213,4 +213,4 @@ from app import routes
 #
 
 if __name__ == '__main__':
-  app.run(debug=True)
+  app.run(debug=True, port=8181)

+ 88 - 31
main/app/routes.py

@@ -9,6 +9,34 @@ from flask_restful import Resource, Api
 
 import PopufareAPI as api
 
+cache = {}
+
+def _cache_get_group():
+  if "group" not in cache:
+    res = api.Request({"action":"get","function":"Group"})
+    cache["group"] = res["group"]
+
+  return cache["group"]
+
+def _cache_get_other_pass():
+  if "ruleclass" not in cache:
+    res = api.Request({"action":"search","function":"Ruleclass"})
+    cache["ruleclass"] = res["ruleclass"]
+
+    cache["other_pass"] = []
+    for r in cache["ruleclass"]:
+      if r["ruleclass"] != "OTHER": continue
+      cache["other_pass"].append(r)
+
+  return cache["other_pass"]
+
+
+def _cache():
+  _cache_get_group()
+  _cache_get_other_pass()
+
+  return cache
+
 @app.route('/favicon.ico')
 def favicon():
   return send_from_directory(os.path.join(app.root_path, 'static'),
@@ -26,8 +54,6 @@ def api_user():
   args = request.args
   res = {}
 
-  print("....", args)
-
   if 'action' in args:
     if args['action'] == 'add':
       api_req = { "action":"add", "function":"User" }
@@ -35,21 +61,14 @@ def api_user():
         if f in args:
           api_req[f] = args[f]
 
-      print("avpi/v1/User send:", api_req)
-
       res = api.Request(api_req)
 
-      print("got:...", res)
     elif args['action'] == 'get':
 
-      print(">>>cp")
-
       api_req = { "action":"get", "function":"User" }
       if "userid" in args:
         api_req["userid"] = args["userid"]
 
-      print("avpi/v1/User.get send:", api_req)
-
       res = api.Request(api_req)
 
   return jsonify(res)
@@ -77,13 +96,27 @@ def api_card():
       print("got:...", res)
     elif args['action'] == 'update':
 
+      cardid = -1
+      if ("logical_card_id" in args) and (args["logical_card_id"] != ''):
+        cardid = args["logical_card_id"]
+      else:
+        subreq = {"action":"search", "function":"Card"}
+        if ("mag_token" in args) and ("mag_token" != ""):
+          subreq["mag_token"] = args["mag_token"]
+        elif ("rfid_token" in args) and ("rfid_token" != ""):
+          subreq["rfid_token"] = args["rfid_token"]
+
+        x = api.Request(subreq)
+
+        if ("logical_card_ids" in x) and (len(x["logical_card_ids"]) > 0):
+          cardid = x["logical_card_ids"][0]
+
+
+
       api_req = { "action":"update", "function":"Card" }
       if "userid" in args:
         api_req["userid"] = args["userid"]
-      if "logical_card_id" in args:
-        api_req["logical_card_id"] = args["logical_card_id"]
-
-      print("avpi/v1/Card.update send:", api_req)
+      api_req["logical_card_id"] = cardid
 
       res = api.Request(api_req)
 
@@ -123,6 +156,20 @@ def api_pass():
 
       res = api.Request(api_req)
 
+    elif args["action"] == "deactivate":
+
+      api_req = { "action":"deactivate", "function":"Pass" }
+      if "user_pass_id" in args:
+        api_req["user_pass_id"] = args["user_pass_id"]
+
+      print("avpi/v1/Pass.deactivate send:", api_req)
+
+      res = api.Request(api_req)
+
+    elif args["action"] == "search":
+      api_req = {"action":"search", "function":"Pass" }
+
+
   return jsonify(res)
 
 @app.route("/api/v1/CardInfo")
@@ -158,26 +205,31 @@ def api_card_info():
 
 @app.route("/api/v1/UserInfo")
 def api_user_info():
-
   res = {}
-
   args = request.args
 
-  print("....", args)
-
-  userid=-1
-  if "userid" in args:
+  userid = -1
+  if "username" in args:
+    res = api.Request({"action":"search", "function":"User", "username":args["username"]})
+    if ("userids" in res) and (len(res["userids"]) > 0):
+      userid = res["userids"][0]
+    else:
+      return jsonify({"error":"error", "message":"user not found"})
+  elif "userid" in args:
     userid = args["userid"]
+  else:
+    return jsonify({"error":"error", "message":"no userid"})
 
   api_req = { "function":"UserInfo", "userid":userid }
+  res = api.Request(api_req)
 
-  print("sending...", api_req)
+  return jsonify(res)
 
-  res = api.Request(api_req)
+@app.route("/api/v1/Group")
+def api_group_info():
 
-  print("got:...", res)
+  return jsonify(_cache_get_group())
 
-  return jsonify(res)
 
 @app.route("/")
 @app.route("/index")
@@ -188,37 +240,42 @@ def index():
 @app.route("/manage_card")
 def manage_card():
   usr = { "username":"clementine" }
-  return render_template( 'manage_card.html', title='home', user=usr)
+  x = _cache_get_group()
+  print(x)
+
+  x = _cache()
+  print(x)
+  return render_template( 'manage_card.html', title='home', user=usr, groups=_cache_get_group(), cache=_cache())
 
 @app.route("/manage_user")
 def manage_user():
   usr = { "username":"clementine" }
-  return render_template( 'manage_user.html', title='home', user=usr)
+  return render_template( 'manage_user.html', title='home', user=usr, groups=_cache_get_group(), cache=_cache())
 
 @app.route("/create_user")
 def create_user():
   usr = { "username":"clementine" }
-  return render_template( 'create_user.html', title='home', user=usr)
+  return render_template( 'create_user.html', title='home', user=usr, groups=_cache_get_group(), cache=_cache())
 
 @app.route("/reissue_card")
 def reissue_card():
   usr = { "username":"clementine" }
-  return render_template( 'reissue_card.html', title='home', user=usr)
+  return render_template( 'reissue_card.html', title='home', user=usr, groups=_cache_get_group(), cache=_cache())
 
 @app.route("/recycle_card")
 def recycle_card():
   usr = { "username":"clementine" }
-  return render_template( 'recycle_card.html', title='home', user=usr)
+  return render_template( 'recycle_card.html', title='home', user=usr, groups=_cache_get_group(), cache=_cache())
 
 @app.route("/add_card_block")
 def add_card_block():
   usr = { "username":"clementine" }
-  return render_template( 'add_card_block.html', title='home', user=usr)
+  return render_template( 'add_card_block.html', title='home', user=usr, groups=_cache_get_group(), cache=_cache())
 
 @app.route("/process_pending_card")
 def process_pending_card():
   usr = { "username":"clementine" }
-  return render_template( 'process_pending_card.html', title='home', user=usr)
+  return render_template( 'process_pending_card.html', title='home', user=usr, groups=_cache_get_group(), cache=_cache())
 
 @app.route("/search")
 def search():
@@ -228,7 +285,7 @@ def search():
 @app.route("/help")
 def help():
   usr = { "username":"clementine" }
-  return render_template( 'help.html', title='home', user=usr)
+  return render_template( 'help.html', title='home', user=usr, groups=_cache_get_group())
 
 @app.route("/api/v1/hello")
 def api_hello():

+ 10 - 0
main/app/static/css/custom.css

@@ -27,4 +27,14 @@
   align-items: center;
   justify-content: center;
   vertical-align: middle;
+
+  height: 8vh;
+}
+
+.custom-select {
+  margin-top: 1vh;
+}
+
+.custom-h {
+  margin-top: 1vh;
 }

+ 131 - 20
main/app/static/js/popufare_admin.js

@@ -43,9 +43,19 @@ function _get_select(fid) {
   return null;
 }
 
+function _date_only(s) {
+  if (!s) { return s; }
+  if (s.length > 0) {
+    return s.split(" ")[0];
+  }
+  return s;
+}
+
 function _create_pass_row(dat) {
   var pass_table = document.getElementById("manage_card:list_passes");
 
+  var _cb = "<input type='checkbox' id='xxx' name='xxx'>";
+
   while (pass_table.firstChild) {
     pass_table.removeChild(pass_table.lastChild);
   }
@@ -56,7 +66,8 @@ function _create_pass_row(dat) {
   row.classList.add("row-shade");
 
   var fields_width = [1,1,1,1,2,2,2,2];
-  var fields = ["x", "Type", "Original", "Remain", "Exp.", "Issued", "First Used", "Last Used"];
+  //var fields = ["x", "Type", "Original", "Remain", "Exp.", "Issued", "First Used", "Last Used"];
+  var fields = ['', "Type", "Original", "Remain", "Exp.", "Issued", "First Used", "Last Used"];
   for (var idx=0; idx<fields.length; idx++) {
     var cell = document.createElement("div");
     cell.innerHTML = fields[idx];
@@ -68,6 +79,8 @@ function _create_pass_row(dat) {
   for (var idx=0; idx<dat["pass"].length; idx++) {
     var pass_data = dat["pass"][idx];
 
+    var passid = pass_data["user_pass_id"];
+
     var pass_type = "unk";
     var pass_rule = pass_data["rule"];
     var pass_orig = "";
@@ -108,11 +121,21 @@ function _create_pass_row(dat) {
       row.classList.add("row-shade");
     }
 
-    var cell = document.createElement("div");
-    cell.innerHTML = "x";
+    //var cell = document.createElement("div");
+    //cell.innerHTML = "x";
+
+    var cell = document.createElement("input");
+
+    cell.setAttribute('type', 'checkbox');
+    cell.setAttribute('value', '');
+    cell.setAttribute('id', "manage_card:cb_" + idx + "_pass");
     cell.classList.add("col-" + fields_width[0]);
     row.appendChild(cell);
 
+
+    //cell.classList.add("col-" + fields_width[0]);
+    //row.appendChild(cell);
+
     cell = document.createElement("div");
     cell.innerHTML = pass_type;
     cell.classList.add("col-" + fields_width[1]);
@@ -129,17 +152,20 @@ function _create_pass_row(dat) {
     row.appendChild(cell);
 
     cell = document.createElement("div");
-    cell.innerHTML = pass_exp;
+    //cell.innerHTML = pass_exp;
+    cell.innerHTML = _date_only(pass_exp);
     cell.classList.add("col-" + fields_width[4]);
     row.appendChild(cell);
 
     cell = document.createElement("div");
-    cell.innerHTML = pass_data["issued"];
+    //cell.innerHTML = pass_data["issued"];
+    cell.innerHTML = _date_only(pass_data["issued"]);
     cell.classList.add("col-" + fields_width[5]);
     row.appendChild(cell);
 
     cell = document.createElement("div");
-    cell.innerHTML = pass_firstused;
+    //cell.innerHTML = pass_firstused;
+    cell.innerHTML = _date_only(pass_firstused);
     cell.classList.add("col-" + fields_width[6]);
     row.appendChild(cell);
 
@@ -148,6 +174,12 @@ function _create_pass_row(dat) {
     cell.classList.add("col-" + fields_width[7]);
     row.appendChild(cell);
 
+    cell = document.createElement("div");
+    cell.innerHTML = passid;
+    cell.setAttribute('id', "manage_card:row_" + idx + "_pass");
+    cell.style.display = "none";
+    row.appendChild(cell);
+
     pass_table.appendChild(row);
 
   }
@@ -170,6 +202,8 @@ function manage_card_find_fill(data) {
     }
   }
 
+  console.log("cp0");
+
   if ("pass" in data) {
     _create_pass_row(data);
   }
@@ -287,6 +321,8 @@ function api_resp(xhr,extra) {
 
       var dat = JSON.parse(xhr.responseText);
 
+      console.log(dat);
+
       if (extra["ui_function"] === "manage_card.find") {
 
         console.log("manage_card.find", dat);
@@ -295,10 +331,20 @@ function api_resp(xhr,extra) {
             (dat.cards.length>0)) {
           manage_card_find_fill(dat.cards[0]);
         }
+
+      }
+      else if (extra["ui_function"] === "manage_card.findone") {
+
+        console.log("... manage_card.findone", dat);
+
+        manage_card_find_fill(dat);
       }
       else if (extra["ui_function"] === "manage_card.update") {
+
+        console.log("issuing 'manage_card.update'");
+
         var cardid = _get_input_field("manage_card:logical_card_id");
-        api_req({"api_function":"CardInfo", "ui_function":"manage_card.find", "data":[["logical_card_id",cardid]]});
+        api_req({"api_function":"CardInfo", "ui_function":"manage_card.findone", "data":[["logical_card_id",cardid]]});
       }
 
       else if (extra["ui_function"] === "create_user.finish") {
@@ -320,6 +366,9 @@ function api_resp(xhr,extra) {
         api_req({"api_function":"UserInfo", "ui_function":"manage_user.find", "data":[["userid",userid]]});
       }
 
+      else if (extra["ui_function"] === "group") {
+      }
+
       //else if (extra["ui_function"] === "manage_card.find") { manage_card_find_fill(dat); }
 
     }
@@ -369,7 +418,7 @@ function manage_card_redirect_manage_user() {
 
 function manage_card_reissue() {
   var cardid = _get_input_field("manage_card:logical_card_id");
-  _redirect( "reissue?" + "action=get&logical_card_id=" + userid);
+  _redirect( "reissue_card?" + "action=get&logical_card_id=" + cardid);
 }
 
 function manage_card_add_pass(pass_type) {
@@ -413,7 +462,9 @@ function manage_card_add_pass_nride() {
     ]
   };
 
+  //DEBUG
   console.log(">>nride++", api_data);
+
   api_req(api_data);
 }
 
@@ -440,27 +491,79 @@ function manage_card_add_pass_nday() {
     ]
   };
 
+  //DEBUG
   console.log(">>nday++", api_data);
+
   api_req(api_data);
 }
 
 function manage_card_add_pass_other() {
-}
-
-function manage_card_delete_pass(passid) {
   var cardid = _get_input_field("manage_card:logical_card_id");
+  var ui_ele = document.getElementById("manage_card:pass_other");
 
-  var dat = {
+  var rule = ui_ele.options[ui_ele.selectedIndex].id;
+
+  var api_data = {
     "api_function":"Pass",
     "ui_function":"manage_card.update",
-    "data": [
-      ["action", "deactivate"],
-      ["logical_card_id",cardid],
-      ["user_pass_id", passid]
-    ]};
-  api_req(dat);
+    "data" : [
+      ["action","add"],
+      ["logical_card_id" , cardid],
+      ["rule" , rule]
+    ]
+  };
+
+  //DEBUG
+  console.log(">>other++", api_data);
+
+  api_req(api_data);
+}
+
+function manage_card_delete_pass() {
+  var cardid = _get_input_field("manage_card:logical_card_id");
+
+  var ele = document.getElementById("manage_card:list_passes");
+  var n = ele.children.length;
+  n-=1;
+
+  for (var ii=0; ii<n; ii++)  {
+    var cb = document.getElementById("manage_card:cb_" + ii + "_pass");
+    if (!cb.checked) { continue; }
+
+    var v = document.getElementById("manage_card:row_"+ ii + "_pass");
+    var passid = v.innerHTML;
+
+    console.log("deleting pass", passid, "(card:", cardid,")");
+
+    if (cb.checked) {
+      var dat = {
+        "api_function":"Pass",
+        "ui_function":"manage_card.update",
+        "data": [
+          ["action", "deactivate"],
+          ["logical_card_id",cardid],
+          ["user_pass_id", passid]
+        ]};
+      api_req(dat);
+
+    }
+
+  }
+
+}
+
+function manage_card_toggle_pass_select() {
+  var ele = document.getElementById("manage_card:list_passes");
+  var n = ele.children.length;
+  n-=1;
+  for (var ii=0; ii<n; ii++)  {
+    var cb = document.getElementById("manage_card:cb_" + ii + "_pass");
+    if (cb.checked) { cb.checked = false; }
+    else { cb.checked = true; }
+  }
 }
 
+
 // --------------------------------------
 // --------------------------------------
 
@@ -483,11 +586,19 @@ function manage_user_associate_card(data) {
   var ele = document.getElementById("manage_user:logical_card_id");
   var cardid = ele.value;
 
+  ele = document.getElementById("manage_user:mag_token");
+  var mag = ele.value;
+
+  ele = document.getElementById("manage_user:rfid_token");
+  var rfid = ele.value;
+
   var req_dat = { "api_function":"Card", "ui_function":"manage_user.update",
                   "data": [
                     ["action","update"],
                     ["userid", userid],
-                    ["logical_card_id",cardid]
+                    ["logical_card_id",cardid],
+                    ["mag_token",mag],
+                    ["rfid_token",rfid]
                   ] };
 
   api_req(req_dat);
@@ -559,7 +670,7 @@ function admin_api_init() {
     _attach_button( "manage_card:button_add_pass_nday", manage_card_add_pass_nday);
     _attach_button( "manage_card:button_add_pass_other", manage_card_add_pass_other);
     _attach_button( "manage_card:button_delete_pass", manage_card_delete_pass);
-
+    _attach_button( "manage_card:button_toggle_pass_all", manage_card_toggle_pass_select);
 
     if ("logical_card_id" in _h) {
       console.log("sending manage_card.find request");

+ 7 - 6
main/app/templates/add_card_block.html

@@ -37,11 +37,12 @@
               <div class='col-5'>Group</div>
               <div class='col-7'>
 
+
                 <div class='input-group input-group-sm mb-3'>
                   <select class='custom-select'>
-                    <option>Org A</option>
-                    <option>Org B</option>
-                    <option>Org C</option>
+                    {% for g in groups %}
+                    <option id='{{ g.group_id }}'>{{ g.group_name }}</option>
+                    {% endfor %}
                   </select>
                 </div>
 
@@ -232,9 +233,9 @@
 
                 <div class='input-group input-group-sm mb-3'>
                   <select class='custom-select'>
-                    <option>Custom Pass 0</option>
-                    <option>Custom Pass 1</option>
-                    <option>Custom Pass 2</option>
+                    {% for rc in cache["other_pass"] %}
+                      <option id='{{ rc.rulename }}'>{{ rc.rulename }}</option>
+                    {% endfor %}
                   </select>
                 </div>
 

+ 3 - 3
main/app/templates/create_user.html

@@ -126,9 +126,9 @@
               <div class='col-6'>
                 <div class='input-group input-group-sm mb-3'>
                   <select class='custom-select'>
-                    <option>Org A</option>
-                    <option>Org B</option>
-                    <option>Org C</option>
+                    {% for g in groups %}
+                    <option id='{{ g.group_id }}'>{{ g.group_name }}</option>
+                    {% endfor %}
                   </select>
                 </div>
               </div>

+ 22 - 20
main/app/templates/manage_card.html

@@ -33,9 +33,9 @@
               <div class='col-6'>
                 <div class='input-group input-group-sm mb-3'>
                   <select class='custom-select'>
-                    <option>Org A</option>
-                    <option>Org B</option>
-                    <option>Org C</option>
+                    {% for g in groups %}
+                    <option id='{{ g.group_id }}'>{{ g.group_name }}</option>
+                    {% endfor %}
                   </select>
                 </div>
               </div>
@@ -103,53 +103,53 @@
 
             <div class='row row-shade rowpop'>
               <div class='col-5'> Username </div>
-              <div id='manage_card:username' class='col-7'> jdoey112 </div>
+              <div id='manage_card:username' class='col-7'> </div>
             </div>
 
             <div class='row rowpop'>
               <div class='col-5'> First Name </div>
-              <div id='manage_card:first_name' class='col-7'> J </div>
+              <div id='manage_card:first_name' class='col-7'> </div>
             </div>
 
 
             <div class='row row-shade rowpop'>
               <div class='col-5'> Last Name </div>
-              <div id='manage_card:last_name' class='col-7'> Doey </div>
+              <div id='manage_card:last_name' class='col-7'> </div>
             </div>
 
             <div class='row rowpop'>
               <div class='col-5'> E-Mail </div>
-              <div id='manage_card:email' class='col-7'> jdoey112@example.com </div>
+              <div id='manage_card:email' class='col-7'> </div>
             </div>
 
             <div class='row row-shade rowpop'>
               <div class='col-5'> Phone </div>
-              <div id='manage_card:phone' class='col-7'> (607) 555-1212</div>
+              <div id='manage_card:phone' class='col-7'> </div>
             </div>
 
             <div class='row rowpop'>
               <div class='col-5'> Address </div>
-              <div id='manage_card:address' class='col-7'> 15 Lane </div>
+              <div id='manage_card:address' class='col-7'> </div>
             </div>
 
             <div class='row row-shade rowpop'>
               <div class='col-5'> City </div>
-              <div id='manage_card:city' class='col-7'> Ithaca </div>
+              <div id='manage_card:city' class='col-7'> </div>
             </div>
 
             <div class='row rowpop'>
               <div class='col-5'> State </div>
-              <div id='manage_card:state' class='col-7'> NY </div>
+              <div id='manage_card:state' class='col-7'> </div>
             </div>
 
             <div class='row row-shade rowpop'>
               <div class='col-5'> ZIP </div>
-              <div id='manage_card:zip' class='col-7'> 14850 </div>
+              <div id='manage_card:zip' class='col-7'> </div>
             </div>
 
             <div class='row rowpop'>
               <div class='col-5'> Group </div>
-              <div id='manage_card:group' class='col-7'> General </div>
+              <div id='manage_card:group' class='col-7'> </div>
             </div>
 
             <div class='row'>
@@ -222,7 +222,7 @@
           </div>
 
           <div class='col-3'>
-            <div class='input-group input-group-sm mb-3'>
+            <div class='input-group input-group-sm mb-3 custom-h'>
               <div class='input-group-prepend'>
                 <span class='input-group-text'>Other</span>
               </div>
@@ -275,7 +275,7 @@
           </div>
 
           <div class='col-3'>
-            <div class='input-group input-group-sm mb-3'>
+            <div class='input-group input-group-sm mb-3 custom-h'>
               <div class='input-group-prepend'>
                 <span class='input-group-text'>Other</span>
               </div>
@@ -296,9 +296,9 @@
 
             <div class='input-group input-group-sm mb-3'>
               <select id='manage_card:pass_other' class='custom-select'>
-                <option id='TEST-ORG-OTHER'>Custom Pass 0</option>
-                <option id='TEST-ORG-OTHER1'>Custom Pass 1</option>
-                <option id='TEST-ORG-OTHER2'>Custom Pass 2</option>
+                {% for rc in cache["other_pass"] %}
+                  <option id='{{ rc.rulename }}'>{{ rc.rulename }}</option>
+                {% endfor %}
               </select>
             </div>
 
@@ -323,10 +323,10 @@
           <div id='manage_card:list_passes_buttons' class='col-12'>
             <div class='row row-shade rowpop'>
               <div class='col-3'>
-                <button type='button' class='btn btn-secondary btn-sm'>check / uncheck all</button>
+                <button type='button' class='btn btn-secondary btn-sm' id='manage_card:button_toggle_pass_all'>check / uncheck all</button>
               </div>
               <div class='col-7'> </div>
-              <div class='col-2'> <button type='button' class='btn btn-secondary btn-sm'>delete</button> </div>
+              <div class='col-2'> <button type='button' class='btn btn-secondary btn-sm' id='manage_card:button_delete_pass'>delete</button> </div>
             </div>
           </div>
 
@@ -342,6 +342,7 @@
               <div class='col-3'> Last Used </div>
             </div>
 
+            <!--
             <div class='row rowpop' >
               <div class='col-1'> NRide </div>
               <div class='col-1'> 5 </div>
@@ -361,6 +362,7 @@
               <div class='col-2'> 2020-01-20 </div>
               <div class='col-3'> 2020-01-25 13:10 </div>
             </div>
+            -->
 
           </div>
 

+ 17 - 12
main/app/templates/manage_user.html

@@ -126,9 +126,9 @@
               <div class='col-6'>
                 <div class='input-group input-group-sm mb-3'>
                   <select class='custom-select'>
-                    <option>Org A</option>
-                    <option>Org B</option>
-                    <option>Org C</option>
+                    {% for g in groups %}
+                    <option id='{{ g.group_id }}'>{{ g.group_name }}</option>
+                    {% endfor %}
                   </select>
                 </div>
               </div>
@@ -187,30 +187,33 @@
         <div class='row'>
           <div class='col-8'>
 
-            <div class='row rowpop'>
+            <div class='row rowpop' style='height:10vh;'>
               <div class='col-6'> <h3> Add Card to User </h3> </div>
-              <div class='col-6'></div>
+              <div class='col-6'> <small>Fill out only one field to associate <br> a card to a user</small></div>
             </div>
 
             <div class='row rowpop row-shade'>
+              <div class='col-4'> CardId </div>
+              <div class='col-6'> <input id='manage_user:logical_card_id' type='text' class='form-control form-control-sm' placeholder=''> </div>
+            </div>
+
+
+            <div class='row rowpop row'>
               <div class='col-4'> Mag Stripe </div>
               <div class='col-6'> <input id='manage_user:mag_token' type='text' class='form-control form-control-sm' placeholder=''> </div>
             </div>
 
-            <div class='row rowpop'>
+            <div class='row rowpop row-shade'>
               <div class='col-4'> RFID </div>
               <div class='col-6'> <input id='manage_user:rfid_token' type='text' class='form-control form-control-sm' placeholder=''> </div>
             </div>
 
-            <div class='row rowpop row-shade'>
-              <div class='col-4'> CardId </div>
-              <div class='col-6'> <input id='manage_user:logical_card_id' type='text' class='form-control form-control-sm' placeholder=''> </div>
-            </div>
-
-            <div class='row rowpop'>
+            <!--
+            <div class='row rowpop row'>
               <div class='col-4'> Group </div>
               <div class='col-6'> <input id='manage_user:group_id' type='text' class='form-control form-control-sm' placeholder=''> </div>
             </div>
+            -->
 
             <div class='row rowpop'>
               <div class='col-4'>
@@ -244,12 +247,14 @@
               <div class='col-2'> RFID </div>
             </div>
 
+            <!--
             <div class='row rowpop'>
               <div class='col-4'> 1234 </div>
               <div class='col-4'> 12300000000000001 </div>
               <div class='col-2'> 35 </div>
               <div class='col-2'> 60535 </div>
             </div>
+            -->
 
           </div>
 

+ 5 - 3
main/app/templates/process_pending_card.html

@@ -118,13 +118,15 @@
             <div class='row rowpop'>
               <div class='col-4'> Group </div>
               <div class='col-8'>
+
                 <div class='input-group input-group-sm mb-3'>
                   <select class='custom-select'>
-                    <option>Org A</option>
-                    <option>Org B</option>
-                    <option>Org C</option>
+                    {% for g in groups %}
+                    <option id='{{ g.group_id }}'>{{ g.group_name }}</option>
+                    {% endfor %}
                   </select>
                 </div>
+
               </div>
             </div>
 

+ 23 - 5
main/app/templates/recycle_card.html

@@ -36,14 +36,32 @@
             <div class='row rowpop row-shade'>
               <div class='col-6'>Source Group</div>
               <div class='col-6'>
-                <input type='text' class='form-control form-control-sm' placeholder=''>
+
+                <div class='input-group input-group-sm mb-3'>
+                  <select class='custom-select'>
+                    {% for g in groups %}
+                    <option id='{{ g.group_id }}'>{{ g.group_name }}</option>
+                    {% endfor %}
+                  </select>
+                </div>
+
+
               </div>
             </div>
 
             <div class='row rowpop'>
               <div class='col-6'>Destination Group</div>
               <div class='col-6'>
-                <input type='text' class='form-control form-control-sm' placeholder=''>
+
+                <div class='input-group input-group-sm mb-3'>
+                  <select class='custom-select'>
+                    {% for g in groups %}
+                    <option id='{{ g.group_id }}'>{{ g.group_name }}</option>
+                    {% endfor %}
+                  </select>
+                </div>
+
+
               </div>
             </div>
 
@@ -211,9 +229,9 @@
 
                 <div class='input-group input-group-sm mb-3'>
                   <select class='custom-select'>
-                    <option>Custom Pass 0</option>
-                    <option>Custom Pass 1</option>
-                    <option>Custom Pass 2</option>
+                    {% for rc in cache["other_pass"] %}
+                      <option id='{{ rc.rulename }}'>{{ rc.rulename }}</option>
+                    {% endfor %}
                   </select>
                 </div>
 

+ 21 - 2
main/app/templates/reissue_card.html

@@ -35,7 +35,16 @@
             <div class='row rowpop row-shade'>
               <div class='col-6'>Source Group</div>
               <div class='col-6'>
-                <input type='text' class='form-control form-control-sm' placeholder=''>
+                <!-- <input type='text' class='form-control form-control-sm' placeholder=''> -->
+
+                <div class='input-group input-group-sm mb-3'>
+                  <select class='custom-select'>
+                    {% for g in groups %}
+                    <option id='{{ g.group_id }}'>{{ g.group_name }}</option>
+                    {% endfor %}
+                  </select>
+                </div>
+
               </div>
             </div>
 
@@ -65,7 +74,17 @@
             <div class='row rowpop row-shade'>
               <div class='col-6'>Destination Group</div>
               <div class='col-6'>
-                <input type='text' class='form-control form-control-sm' placeholder=''>
+                <!-- <input type='text' class='form-control form-control-sm' placeholder=''> -->
+
+                <div class='input-group input-group-sm mb-3'>
+                  <select class='custom-select'>
+                    {% for g in groups %}
+                    <option id='{{ g.group_id }}'>{{ g.group_name }}</option>
+                    {% endfor %}
+                  </select>
+                </div>
+
+
               </div>
             </div>
 

+ 1 - 1
main/main.py

@@ -6,4 +6,4 @@ import logging
 logging.basicConfig(level=logging.DEBUG)
 
 if __name__ == '__main__':
-  app.run()
+  app.run(port=8182)

+ 3 - 0
main/run

@@ -1,4 +1,7 @@
 #!/bin/bash
 
+which python
+python --version
+
 export FLASK_APP=main.py
 flask run --host 0.0.0.0