Переглянути джерело

wip

* split out create and manage user
* started naming input boxes
* javascript to fill out and other interaction
* very very rough
abetusk 5 роки тому
батько
коміт
ece314fe2b

+ 198 - 194
main/app/__init__.py

@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/python3
 
 from flask import Flask
 from flask_restful import Resource, Api
@@ -6,207 +6,211 @@ from flask_restful import Resource, Api
 from bson import json_util
 import json
 
-import pymysql
+#import pymysql
 
 
 app = Flask(__name__)
 api = Api(app)
 
-class Database:
-  def __init__(self):
-    host = "127.0.0.1"
-    user = "bus"
-    password = ""
-    db = "busdb"
-
-    self.con = pymysql.connect(host=host, user=user, db=db, cursorclass=pymysql.cursors.DictCursor)
-    self.cur = self.con.cursor()
-
-  def ok(self):
-    self.cur.execute("select rulename from rule_class where id = %s", 1)
-    res = self.cur.fetchall()
-    return res
-
-
-
-#from app import routes
-
-class Card(Resource):
-  def get(self, cardid = None):
-
-    db = Database()
-    db.cur.execute("select logical_card_id, " \
-                   "mag_token, rfid_token, comment, " \
-                   "userid, issuetype, "\
-                   "issued, lastused, firstused, " \
-                   "active, deactivated, group_id " \
-                   "from user_card " \
-                   "where logical_card_id = %s", cardid)
-    res  = db.cur.fetchall()
-    print(res)
-    if len(res)>0:
-      s = json.dumps(res[0], default=json_util.default)
-      return json.loads(s)
-    return {"msg":"no card found", "param":cardid}
-
-  def delete(self):
-    return {"msg":"delete card not implemented"}
-  def put(self):
-    return {"msg":"put/update card not implemented"}
-  def post(self):
-    return {"msg":"post/insert card not implemented"}
-
-class Pass(Resource):
-  def get(self, passid = None):
-
-    db = Database()
-    db.cur.execute("select " \
-                   "user_pass_id, logical_card_id, " \
-                   "issued, activated, deactivated, " \
-                   "firstused, lastused, " \
-                   "nrides_orig, nrides_remain, " \
-                   "nday_orig, nday_expiration, " \
-                   " active, expired, " \
-                   "rule, queue_order, " \
-                   "comment, paytype " \
-                   "from user_pass where user_pass_id = %s",
-                   passid)
-    res  = db.cur.fetchall()
-    print(res)
-    if len(res)>0:
-      s = json.dumps(res[0], default=json_util.default)
-      return json.loads(s)
-    return {"msg":"pass not found", "param":passid}
-
-  def delete(self):
-    return {"msg":"delete pass not implemented"}
-  def put(self):
-    return {"msg":"put/update pass not implemented"}
-  def post(self):
-    return {"msg":"post/insert pass not implemented"}
-
-class User(Resource):
-  def get(self, userid = None):
-
-    db = Database()
-    db.cur.execute("select " \
-                   "username, userid, comment, " \
-                   "first_name, last_name, phone, email, " \
-                   "address, city, state, zip, created, active, " \
-                   "passwordhash, " \
-                   "shipping_address, shipping_city, shipping_state, shipping_zip, " \
-                   "shipping_country_code, shipping_country_name, " \
-                   "reset_attempts " \
-                   "from users where userid = %s",
-                   userid)
-    res  = db.cur.fetchall()
-    print(res)
-    if len(res)>0:
-      s = json.dumps(res[0], default=json_util.default)
-      return json.loads(s)
-    return {"msg":"user not found", "param":passid}
-
-
-  def delete(self):
-    return {"msg":"delete user not implemented"}
-  def put(self):
-    return {"msg":"put/update user not implemented"}
-  def post(self):
-    return {"msg":"post/insert user not implemented"}
-
-class Group(Resource):
-  def get(self):
-    return {"msg":"get group not implemented"}
-  def delete(self):
-    return {"msg":"delete group not implemented"}
-  def put(self):
-    return {"msg":"put/update group not implemented"}
-  def post(self):
-    return {"msg":"post/insert group not implemented"}
-
-class PassOption(Resource):
-  def get(self):
-    return {"msg":"get passoption not implemented"}
-  def delete(self):
-    return {"msg":"delete passoption not implemented"}
-  def put(self):
-    return {"msg":"put/update passoption not implemented"}
-  def post(self):
-    return {"msg":"post/insert passoption not implemented"}
-
-class Rule(Resource):
-  def get(self):
-    return {"msg":"get rule not implemented"}
-  def delete(self):
-    return {"msg":"delete rule not implemented"}
-  def put(self):
-    return {"msg":"put/update rule not implemented"}
-  def post(self):
-    return {"msg":"post/insert rule not implemented"}
-
-
-## Admin related
-##
-
-class AdminUser(Resource):
-  def get(self):
-    return {"msg":"get adminuser not implemented"}
-  def delete(self):
-    return {"msg":"delete adminuser not implemented"}
-  def put(self):
-    return {"msg":"put/update adminuser not implemented"}
-  def post(self):
-    return {"msg":"post/insert adminuser not implemented"}
-
-class AdminGroup(Resource):
-  def get(self):
-    return {"msg":"get admingroup not implemented"}
-  def delete(self):
-    return {"msg":"delete admingroup not implemented"}
-  def put(self):
-    return {"msg":"put/update admingroup not implemented"}
-  def post(self):
-    return {"msg":"post/insert admingroup not implemented"}
-
-class Driver(Resource):
-  def get(self):
-    return {"msg":"get driver not implemented"}
-  def delete(self):
-    return {"msg":"delete driver not implemented"}
-  def put(self):
-    return {"msg":"put/update driver not implemented"}
-  def post(self):
-    return {"msg":"post/insert driver not implemented"}
-
-class Paddle(Resource):
-  def get(self):
-    return {"msg":"get paddle not implemented"}
-  def delete(self):
-    return {"msg":"delete paddle not implemented"}
-  def put(self):
-    return {"msg":"put/update paddle not implemented"}
-  def post(self):
-    return {"msg":"post/insert paddle not implemented"}
-
-class Bus(Resource):
-  def get(self):
-    return {"msg":"get bus not implemented"}
-  def delete(self):
-    return {"msg":"delete bus not implemented"}
-  def put(self):
-    return {"msg":"put/update bus not implemented"}
-  def post(self):
-    return {"msg":"post/insert bus not implemented"}
-
+#class Database:
+#  def __init__(self):
+#    host = "127.0.0.1"
+#    user = "bus"
+#    password = ""
+#    db = "busdb"
+#
+#    #self.con = pymysql.connect(host=host, user=user, db=db, cursorclass=pymysql.cursors.DictCursor)
+#    #self.cur = self.con.cursor()
+#
+#  def ok(self):
+#    #self.cur.execute("select rulename from rule_class where id = %s", 1)
+#    #res = self.cur.fetchall()
+#    #return res
+#    return {}
+#
+#
+#
+##from app import routes
+#
+#class Card(Resource):
+#  def get(self, cardid = None):
+#
+#    db = Database()
+#    db.cur.execute("select logical_card_id, " \
+#                   "mag_token, rfid_token, comment, " \
+#                   "userid, issuetype, "\
+#                   "issued, lastused, firstused, " \
+#                   "active, deactivated, group_id " \
+#                   "from user_card " \
+#                   "where logical_card_id = %s", cardid)
+#    res  = db.cur.fetchall()
+#    print(res)
+#    if len(res)>0:
+#      s = json.dumps(res[0], default=json_util.default)
+#      return json.loads(s)
+#    return {"msg":"no card found", "param":cardid}
+#
+#  def delete(self):
+#    return {"msg":"delete card not implemented"}
+#  def put(self):
+#    return {"msg":"put/update card not implemented"}
+#  def post(self):
+#    return {"msg":"post/insert card not implemented"}
+#
+#class Pass(Resource):
+#  def get(self, passid = None):
+#
+#    db = Database()
+#    db.cur.execute("select " \
+#                   "user_pass_id, logical_card_id, " \
+#                   "issued, activated, deactivated, " \
+#                   "firstused, lastused, " \
+#                   "nrides_orig, nrides_remain, " \
+#                   "nday_orig, nday_expiration, " \
+#                   " active, expired, " \
+#                   "rule, queue_order, " \
+#                   "comment, paytype " \
+#                   "from user_pass where user_pass_id = %s",
+#                   passid)
+#    res  = db.cur.fetchall()
+#    print(res)
+#    if len(res)>0:
+#      s = json.dumps(res[0], default=json_util.default)
+#      return json.loads(s)
+#    return {"msg":"pass not found", "param":passid}
+#
+#  def delete(self):
+#    return {"msg":"delete pass not implemented"}
+#  def put(self):
+#    return {"msg":"put/update pass not implemented"}
+#  def post(self):
+#    return {"msg":"post/insert pass not implemented"}
+#
+#class User(Resource):
+#  def get(self, userid = None):
+#
+#    db = Database()
+#    db.cur.execute("select " \
+#                   "username, userid, comment, " \
+#                   "first_name, last_name, phone, email, " \
+#                   "address, city, state, zip, created, active, " \
+#                   "passwordhash, " \
+#                   "shipping_address, shipping_city, shipping_state, shipping_zip, " \
+#                   "shipping_country_code, shipping_country_name, " \
+#                   "reset_attempts " \
+#                   "from users where userid = %s",
+#                   userid)
+#    res  = db.cur.fetchall()
+#    print(res)
+#    if len(res)>0:
+#      s = json.dumps(res[0], default=json_util.default)
+#      return json.loads(s)
+#    return {"msg":"user not found", "param":passid}
+#
+#
+#  def delete(self):
+#    return {"msg":"delete user not implemented"}
+#  def put(self):
+#    return {"msg":"put/update user not implemented"}
+#  def post(self):
+#    return {"msg":"post/insert user not implemented"}
+#
+#class Group(Resource):
+#  def get(self):
+#    return {"msg":"get group not implemented"}
+#  def delete(self):
+#    return {"msg":"delete group not implemented"}
+#  def put(self):
+#    return {"msg":"put/update group not implemented"}
+#  def post(self):
+#    return {"msg":"post/insert group not implemented"}
+#
+#class PassOption(Resource):
+#  def get(self):
+#    return {"msg":"get passoption not implemented"}
+#  def delete(self):
+#    return {"msg":"delete passoption not implemented"}
+#  def put(self):
+#    return {"msg":"put/update passoption not implemented"}
+#  def post(self):
+#    return {"msg":"post/insert passoption not implemented"}
+#
+#class Rule(Resource):
+#  def get(self):
+#    return {"msg":"get rule not implemented"}
+#  def delete(self):
+#    return {"msg":"delete rule not implemented"}
+#  def put(self):
+#    return {"msg":"put/update rule not implemented"}
+#  def post(self):
+#    return {"msg":"post/insert rule not implemented"}
+#
+#
+### Admin related
+###
+#
+#class AdminUser(Resource):
+#  def get(self):
+#    return {"msg":"get adminuser not implemented"}
+#  def delete(self):
+#    return {"msg":"delete adminuser not implemented"}
+#  def put(self):
+#    return {"msg":"put/update adminuser not implemented"}
+#  def post(self):
+#    return {"msg":"post/insert adminuser not implemented"}
+#
+#class AdminGroup(Resource):
+#  def get(self):
+#    return {"msg":"get admingroup not implemented"}
+#  def delete(self):
+#    return {"msg":"delete admingroup not implemented"}
+#  def put(self):
+#    return {"msg":"put/update admingroup not implemented"}
+#  def post(self):
+#    return {"msg":"post/insert admingroup not implemented"}
+#
+#class Driver(Resource):
+#  def get(self):
+#    return {"msg":"get driver not implemented"}
+#  def delete(self):
+#    return {"msg":"delete driver not implemented"}
+#  def put(self):
+#    return {"msg":"put/update driver not implemented"}
+#  def post(self):
+#    return {"msg":"post/insert driver not implemented"}
+#
+#class Paddle(Resource):
+#  def get(self):
+#    return {"msg":"get paddle not implemented"}
+#  def delete(self):
+#    return {"msg":"delete paddle not implemented"}
+#  def put(self):
+#    return {"msg":"put/update paddle not implemented"}
+#  def post(self):
+#    return {"msg":"post/insert paddle not implemented"}
+#
+#class Bus(Resource):
+#  def get(self):
+#    return {"msg":"get bus not implemented"}
+#  def delete(self):
+#    return {"msg":"delete bus not implemented"}
+#  def put(self):
+#    return {"msg":"put/update bus not implemented"}
+#  def post(self):
+#    return {"msg":"post/insert bus not implemented"}
+#
+#
 
 from app import routes
 
-api.add_resource(Card, "/api/v1/card/", "/api/v1/card/<int:cardid>")
-api.add_resource(Pass, "/api/v1/pass/", "/api/v1/pass/<int:passid>")
-api.add_resource(User, "/api/v1/user/", "/api/v1/user/<int:userid>")
-api.add_resource(Group, "/api/v1/group/", "/api/v1/group/<int:groupid>")
-api.add_resource(PassOption, "/api/v1/passoption/", "/api/v1/passoption/<int:passoptionid>")
-api.add_resource(Rule, "/api/v1/rule/", "/api/v1/rule/<int:ruleid>")
+#
+#api.add_resource(Card, "/api/v1/card/", "/api/v1/card/<int:cardid>")
+#api.add_resource(Pass, "/api/v1/pass/", "/api/v1/pass/<int:passid>")
+#api.add_resource(User, "/api/v1/user/", "/api/v1/user/<int:userid>")
+#api.add_resource(Group, "/api/v1/group/", "/api/v1/group/<int:groupid>")
+#api.add_resource(PassOption, "/api/v1/passoption/", "/api/v1/passoption/<int:passoptionid>")
+#api.add_resource(Rule, "/api/v1/rule/", "/api/v1/rule/<int:ruleid>")
+#
 
 if __name__ == '__main__':
   app.run(debug=True)

+ 157 - 18
main/app/routes.py

@@ -1,12 +1,137 @@
-#!/usr/bin/env python3
+#!/usr/bin/python3
 
+import sys
+import os
 from flask import render_template, url_for
 from app import app
-from flask import request, jsonify
+from flask import request, jsonify, send_from_directory
 from flask_restful import Resource, Api
 
-import pymysql
+import PopufareAPI as api
 
+@app.route('/favicon.ico')
+def favicon():
+  return send_from_directory(os.path.join(app.root_path, 'static'),
+                             'favicon.ico',
+                             mimetype='favicon.ico')
+
+@app.route("/api/v1/User")
+def api_user():
+  field_names = [ "username", "first_name", "last_name",
+                  "email", "phone", "address", "city", "state", "zip",
+                  "shipping_name", "shipping_address", "shipping_address",
+                  "shipping_zip", "password"];
+
+  args = request.args
+  res = {}
+
+  print("....", args)
+
+  if 'action' in args:
+    if args['action'] == 'add':
+      api_req = { "action":"add", "function":"User" }
+      for f in field_names:
+        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)
+
+@app.route("/api/v1/Card")
+def api_card():
+  field_names = [ "logical_card_id", "mag_token", "rfid_token", "userid" ]
+
+  args = request.args
+  res = {}
+
+  print("api.card args:", args)
+
+  if 'action' in args:
+    if args['action'] == 'add':
+      api_req = { "action":"add", "function":"Card" }
+      for f in field_names:
+        if f in args:
+          api_req[f] = args[f]
+
+      print("avpi/v1/Card send:", api_req)
+
+      res = api.Request(api_req)
+
+      print("got:...", res)
+    elif args['action'] == 'update':
+
+      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)
+
+      res = api.Request(api_req)
+
+  return jsonify(res)
+
+@app.route("/api/v1/CardInfo")
+def api_card_info():
+
+  res = {}
+
+  args = request.args
+
+  print("....", args)
+
+  if 'action' in args:
+    if args['action'] == 'search':
+      api_req = { "action":"search", "function":"CardInfo" }
+      search_fields = ["logical_card_id", "mag_token", "rfid_token"]
+      for sf in search_fields:
+        if sf in args:
+          api_req[sf] = args[sf]
+      res = api.Request(api_req)
+
+      print("got:...", res)
+
+  return jsonify(res)
+
+@app.route("/api/v1/UserInfo")
+def api_user_info():
+
+  res = {}
+
+  args = request.args
+
+  print("....", args)
+
+  userid=-1
+  if "userid" in args:
+    userid = args["userid"]
+
+  api_req = { "function":"UserInfo", "userid":userid }
+
+  print("sending...", api_req)
+
+  res = api.Request(api_req)
+
+  print("got:...", res)
+
+  return jsonify(res)
 
 @app.route("/")
 @app.route("/index")
@@ -24,6 +149,11 @@ def manage_user():
   usr = { "username":"clementine" }
   return render_template( 'manage_user.html', title='home', user=usr)
 
+@app.route("/create_user")
+def create_user():
+  usr = { "username":"clementine" }
+  return render_template( 'create_user.html', title='home', user=usr)
+
 @app.route("/reissue_card")
 def reissue_card():
   usr = { "username":"clementine" }
@@ -54,23 +184,32 @@ def help():
   usr = { "username":"clementine" }
   return render_template( 'help.html', title='home', user=usr)
 
-###
-
-class Database:
-  def __init__(self):
-    host = "127.0.0.1"
-    user = "bus"
-    password = ""
-    db = "busdb"
-
-    self.con = pymysql.connect(host=host, user=user, db=db, cursorclass=pymysql.cursors.DictCursor)
-    self.cur = self.con.cursor()
+@app.route("/api/v1/hello")
+def api_hello():
+  #data = { "version":"v1", "type":"hello", "data":"hello" }
+  sessid = request.cookies.get('sessionid')
+  uname = request.cookies.get('username')
+  sess_data = { "sessionid":sessid, "username":uname }
+  data = popfareapi.hello(sess_data)
+  return jsonify(data)
 
-  def ok(self):
-    self.cur.execute("select rulename from rule_class where id = %s", 1)
-    res = self.cur.fetchall()
-    return res
+###
 
+#class Database:
+#  def __init__(self):
+#    host = "127.0.0.1"
+#    user = "bus"
+#    password = ""
+#    db = "busdb"
+#
+#    self.con = pymysql.connect(host=host, user=user, db=db, cursorclass=pymysql.cursors.DictCursor)
+#    self.cur = self.con.cursor()
+#
+#  def ok(self):
+#    self.cur.execute("select rulename from rule_class where id = %s", 1)
+#    res = self.cur.fetchall()
+#    return res
+#
 
 
 #@app.route("/api/v1/card")

+ 262 - 0
main/app/static/js/popufare_admin.js

@@ -0,0 +1,262 @@
+
+function _param2hash(p) {
+  var h = {};
+  p = p.substring(1);
+  var tokval = p.split("&");
+  for (var idx=0; idx<tokval.length; idx++) {
+    pv = tokval[idx].split("=");
+    h[pv[0]] = pv[1];
+  }
+
+  return h;
+}
+
+function _attach_button(btn_id, cb) {
+  ele = document.getElementById(btn_id);
+  if (ele) { ele.onclick = cb; }
+}
+
+function _redirect(rel_str) {
+  console.log("redirect", rel_str);
+  window.location.href = rel_str;
+}
+
+function _fill_input_field(fid, fdata) {
+  var ele = document.getElementById(fid);
+  if (ele) { ele.value = fdata; }
+}
+
+function _get_input_field(fid) {
+  var ele = document.getElementById(fid);
+  if (ele) { return ele.value; }
+  return null;
+}
+
+function manage_card_find_fill(data) {
+  var fields = [ "logical_card_id", "group", "mag_token", "rfid_token"];
+
+  for (var idx=0; idx<fields.length; idx++) {
+    if (fields[idx] in data) {
+      _fill_input_field("manage_card:" + fields[idx], data[fields[idx]])
+    }
+  }
+
+}
+
+function manage_user_find_fill(data) {
+  var fields = [ "userid", "username", "first_name", "last_name",
+                 "email", "phone", "address", "city", "state", "zip",
+                 "shipping_name", "shipping_city", "shipping_address",
+                 "shipping_zip", "password"];
+
+  if ("user" in data) {
+    var user_data = data["user"];
+    for (var idx=0; idx<fields.length; idx++) {
+      if (fields[idx] in user_data) {
+        _fill_input_field("manage_user:" + fields[idx], user_data[fields[idx]])
+      }
+    }
+  }
+
+  if ("card" in data) {
+    var card_table = document.getElementById("manage_user:list_cards");
+
+    while (card_table.firstChild) {
+      card_table.removeChild(card_table.lastChild);
+    }
+
+    var row   = document.createElement("div");
+    row.classList.add("row");
+    row.classList.add("rowpop");
+    row.classList.add("row-shade");
+
+    var cell  = document.createElement("div");
+    cell.innerHTML = "Card Id";
+    cell.classList.add("col-4");
+    row.appendChild(cell);
+
+    cell  = document.createElement("div");
+    cell.innerHTML = "Mag Stripe";
+    cell.classList.add("col-4");
+    row.appendChild(cell);
+
+    cell  = document.createElement("div");
+    cell.innerHTML = "RFID";
+    cell.classList.add("col-4");
+    row.appendChild(cell);
+    card_table.appendChild(row);
+
+
+    var card_data = data["card"];
+    for (var idx=0; idx<card_data.length; idx++) {
+      var cardid = card_data[idx]["logical_card_id"];
+      var magid = card_data[idx]["mag_token"];
+      var rfid  = card_data[idx]["rfid_token"];
+
+      row = document.createElement("div");
+      row.classList.add("row");
+      row.classList.add("rowpop");
+      if ((idx % 2) == 1) {
+        row.classList.add("row-shade");
+      }
+
+      cell = document.createElement("div");
+      cell.innerHTML = "<a href='/manage_card?logical_card_id=" + cardid + "'>" + cardid + "</a>";
+      cell.classList.add("col-4");
+      row.appendChild(cell);
+
+      cell = document.createElement("div");
+      cell.innerHTML = "<a href='/manage_card?logical_card_id=" + cardid + "'>" + magid + "</a>";
+      cell.classList.add("col-4");
+      row.appendChild(cell);
+
+      cell = document.createElement("div");
+      cell.innerHTML = "<a href='/manage_card?logical_card_id=" + cardid + "'>" + rfid + "</a>";
+      cell.classList.add("col-4");
+      row.appendChild(cell);
+
+      card_table.appendChild(row);
+
+      console.log("card", idx,
+          card_data[idx]["logical_card_id"],
+          card_data[idx]["mag_token"],
+          card_data[idx]["rfid_token"] );
+    }
+  }
+
+  window.history.replaceState({}, document.title, "/manage_user");
+}
+
+function api_resp(xhr,extra) {
+  if (xhr.readyState === XMLHttpRequest.DONE) {
+    if (xhr.status === 200) {
+
+      var dat = JSON.parse(xhr.responseText);
+
+      if (extra["ui_function"] === "manage_card.find") {
+        if (("cards"in dat) &&
+            (dat.cards.length>0)) {
+          manage_card_find_fill(dat.cards[0]);
+        }
+      }
+
+      else if (extra["ui_function"] === "create_user.finish") {
+        _redirect( "manage_user?" + "action=get&userid=" + dat["userid"])
+      }
+
+      else if (extra["ui_function"] === "manage_user.find") {
+        console.log("manage_user.find:", dat);
+        manage_user_find_fill(dat);
+      }
+      else if (extra["ui_function"] === "manage_user.update") {
+        console.log("manage_user.update resp:", dat)
+      }
+
+    }
+    else {
+      console.log("xhr error:", xhr);
+    }
+  }
+}
+
+// example usage:
+//
+// api_req({"ui_function":"manage_card.find", "api_function":"CardInfo", "data":[ ["action","search"],["mag_token","370000000007015"]]})
+//
+function api_req(ctx) {
+  var xhr;
+  xhr = new XMLHttpRequest();
+  if (!xhr) { return false; }
+
+  var param_val = [];
+  for (var idx=0; idx<ctx.data.length; idx++) {
+    param_val.push(ctx.data[idx][0] + '=' + ctx.data[idx][1]);
+  }
+
+  var api_func = "nop";
+  if ("api_function" in ctx) { api_func = ctx["api_function"]; }
+
+  var req_str = "api/v1/" + api_func + "?" + param_val.join("&");
+
+  xhr.onreadystatechange = (function(_x,_f) {
+    return function(v) { api_resp(_x, {"ui_function":_f}); }
+  })(xhr, ctx["ui_function"])
+  xhr.open("GET", req_str);
+  xhr.send()
+
+}
+
+function manage_user_find_userid() {
+  var ele = document.getElementById("manage_user:userid");
+  var userid = ele.value;
+  api_req({"api_function":"UserInfo", "ui_function":"manage_user.find", "data": [ ["userid",userid] ] });
+}
+
+function manage_user_find_username() {
+  var ele = document.getElementById("manage_user:username");
+  var username = ele.value;
+  api_req({"api_function":"UserInfo", "ui_function":"manage_user.find", "data":[["username",username]]});
+}
+
+function manage_user_associate_card(data) {
+  var ele = document.getElementById("manage_user:userid");
+  var userid = ele.value;
+
+  var ele = document.getElementById("manage_user:logical_card_id");
+  var cardid = ele.value;
+
+  var req_dat = { "api_function":"Card", "ui_function":"create_user.update",
+                  "data": [
+                    ["action","update"],
+                    ["userid", userid],
+                    ["logical_card_id",cardid]
+                  ] };
+
+  api_req(req_dat);
+  
+}
+
+
+
+function create_user_process_button() {
+  var val_names = ["username", "first_name", "last_name",
+                   "email", "phone", "address", "city", "state", "zip",
+                   "shipping_name", "shipping_city", "shipping_address",
+                   "shipping_zip", "password"];
+  var req_dat = { "api_function":"User", "ui_function":"create_user.finish",
+                  "data":[ ["action","add"]] };
+  for (var idx=0; idx<val_names.length; idx++) {
+    var v = _get_input_field("create_user:" + val_names[idx]);
+    if (v) {
+      req_dat.data.push([val_names[idx],v]);
+    }
+  }
+
+  api_req(req_dat);
+}
+
+function admin_api_init() {
+  var ele;
+
+  var _func = location.pathname.substring(1);
+
+  if (_func === "creat_user") {
+    ele = document.getElementById("create_user:button_create");
+    if (ele) { ele.onclick = create_user_process_button; }
+  }
+
+  else if (_func === "manage_user") {
+    _attach_button( "manage_user:button_lookup_userid", manage_user_find_userid);
+    _attach_button( "manage_user:button_lookup_username", manage_user_find_username);
+    _attach_button( "manage_user:button_associate_card", manage_user_associate_card);
+
+    console.log(window.location.search);
+    var _h = _param2hash(window.location.search);
+    if ("userid" in _h) {
+      api_req({"api_function":"User", "ui_function":"manage_user.find", "data":[["action","get"],["userid",_h["userid"]]]});
+    }
+  }
+
+}
+
+admin_api_init();

+ 2 - 0
main/app/templates/base.html

@@ -25,6 +25,7 @@
       <div class="list-group list-group-flush">
         <a href="/manage_card" class="list-group-item list-group-item-action bg-light">Manage Card</a>
         <a href="/manage_user" class="list-group-item list-group-item-action bg-light">Manage User</a>
+        <a href="/create_user" class="list-group-item list-group-item-action bg-light">Create User</a>
         <a href="/reissue_card" class="list-group-item list-group-item-action bg-light">Re-Issue</a>
         <a href="/recycle_card" class="list-group-item list-group-item-action bg-light">Recycle Card</a>
         <a href="/add_card_block" class="list-group-item list-group-item-action bg-light">Add Card Block</a>
@@ -90,6 +91,7 @@
 
   <script src="/static/js/jquery.min.js"></script>
   <script src="/static/js/bootstrap.bundle.min.js"></script>
+  <script src="/static/js/popufare_admin.js"></script>
 
 </body>
 

+ 151 - 0
main/app/templates/create_user.html

@@ -0,0 +1,151 @@
+{% extends "base.html" %}
+
+{% block content %}
+
+  <h1 class="mt-4">Create User</h1>
+
+  <div class='container'>
+
+
+    <!-- container row -->
+    <div class='row'>
+
+      <!-- col-10 to give a padding on the side -->
+      <div class='col-10'>
+
+            <div class='row rowpop row-shade'>
+              <div class='col-4'> User Name </div>
+              <div class='col-6'> <input id='create_user:username' type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-2'> </div>
+            </div>
+
+            <div class='row rowpop '>
+              <div class='col-4'> First Name </div>
+              <div class='col-6'> <input id='create_user:first_name' type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-2'> </div>
+            </div>
+
+            <div class='row rowpop row-shade'>
+              <div class='col-4'> Last Name </div>
+              <div class='col-6'> <input id='create_user:last_name' type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-2'> </div>
+            </div>
+
+            <div class='row rowpop '>
+              <div class='col-4'> E-Mail </div>
+              <div class='col-6'> <input id='create_user:email' type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-2'> </div>
+            </div>
+
+            <div class='row rowpop row-shade'>
+              <div class='col-4'> Phone </div>
+              <div class='col-6'> <input id='create_user:phone' type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-2'> </div>
+            </div>
+
+            <div class='row rowpop '>
+              <div class='col-4'> Address </div>
+              <div class='col-6'> <input id='create_user:address' type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-2'> </div>
+            </div>
+
+            <div class='row rowpop row-shade'>
+              <div class='col-4'> City </div>
+              <div class='col-6'> <input id='create_user:city' type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-2'> </div>
+            </div>
+
+            <div class='row rowpop '>
+              <div class='col-4'> State </div>
+              <div class='col-6'> <input id='create_user:state' type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-2'> </div>
+            </div>
+
+            <div class='row rowpop row-shade'>
+              <div class='col-4'> ZIP </div>
+              <div class='col-6'> <input id='create_user:zip' type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-2'> </div>
+            </div>
+
+            <div class='row rowpop '>
+              <div class='col-4'> Shipping Name </div>
+              <div class='col-6'> <input id='create_user:shipping_name' type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-2'> </div>
+            </div>
+
+            <div class='row rowpop row-shade'>
+              <div class='col-4'> Shipping Address </div>
+              <div class='col-6'> <input id='create_user:shipping_address' type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-2'> </div>
+            </div>
+
+            <div class='row rowpop '>
+              <div class='col-4'> Shipping City </div>
+              <div class='col-6'> <input id='create_user:shipping_city' type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-2'> </div>
+            </div>
+
+            <div class='row rowpop row-shade'>
+              <div class='col-4'> Shipping State </div>
+              <div class='col-6'> <input id='create_user:shipping_state' type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-2'> </div>
+            </div>
+
+            <div class='row rowpop '>
+              <div class='col-4'> Shipping ZIP </div>
+              <div class='col-6'> <input id='create_user:shipping_zip' type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-2'> </div>
+            </div>
+
+            <div class='row rowpop row-shade'>
+              <div class='col-4'> Password </div>
+              <div class='col-6'> <input id='create_user:password' type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-2'> </div>
+            </div>
+
+            <div class='row rowpop '>
+              <div class='col-4'> Confirm Password </div>
+              <div class='col-6'> <input id='create_user:password_confirm' type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-2'> </div>
+            </div>
+
+            <div class='row rowpop row-shade'>
+              <div class='col-4'> Group </div>
+              <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>
+                  </select>
+                </div>
+              </div>
+              <div class='col-2'> </div>
+            </div>
+
+          </div>
+
+        <!-- row -->
+        </div>
+
+
+        <br>
+        <br>
+
+        <div class='row rowpop'>
+          <div class='col-4'>
+            <button id='create_user:button_create' type='button' class='btn btn-secondary btn-sm'>Create New User</button>
+          </div>
+          <div class='col-8'></div>
+        </div>
+
+      <!-- col-10 -->
+      </div>
+
+    <!-- container row -->
+    </div>
+
+  <!-- container -->
+  </div>
+
+{% endblock %}

+ 18 - 19
main/app/templates/manage_card.html

@@ -21,11 +21,10 @@
             <div class='row row-shade rowpop'>
               <div class='col-4'> CardId </div>
               <div class='col-6'>
-                <input type='text' class='form-control form-control-sm' placeholder=''>
+                <input id='manage_card:logical_card_id' type='text' class='form-control form-control-sm' placeholder=''>
               </div>
               <div class='col-2'> 
-                <!-- <button type='button' class='btn btn-secondary btn-sm justify-content-end'>Find</button> -->
-                <button type='button' class='btn btn-secondary btn-sm'>Find</button>
+                <button id='manage_card:button_find_logical_card_id' type='button' class='btn btn-secondary btn-sm'>Find</button>
               </div>
             </div>
 
@@ -46,7 +45,7 @@
             <div class='row row-shade rowpop'>
               <div class='col-4'> MagStripe </div>
               <div class='col-6'>
-                <input type='text' class='form-control form-control-sm' placeholder=''>
+                <input id='manage_card:mag_token' type='text' class='form-control form-control-sm' placeholder=''>
               </div>
               <div class='col-2' >
                 <button type='button' class='btn btn-secondary btn-sm '>Find</button>
@@ -56,7 +55,7 @@
             <div class='row rowpop'>
               <div class='col-4'> RFID </div>
               <div class='col-6'>
-                <input type='text' class='form-control form-control-sm' placeholder=''>
+                <input id='manage_card:rfid_token' type='text' class='form-control form-control-sm' placeholder=''>
               </div>
               <div class='col-2 '>
                 <button type='button' class='btn btn-secondary btn-sm'>Find</button>
@@ -67,7 +66,7 @@
               <div class='col-4'> Active Pass </div>
               <div class='col-6'> ...  </div>
               <div class='col-2'>
-                <button type='button' class='btn btn-secondary btn-sm'>Find</button>
+                <button id='manage_card:button_lookup_pass' type='button' class='btn btn-secondary btn-sm'>Find</button>
               </div>
             </div>
 
@@ -80,10 +79,10 @@
             <div class='row row-shade rowpop'>
               <div class='col-4'> Other ID </div>
               <div class='col-6'>
-                <input type='text' class='form-control form-control-sm' placeholder=''>
+                <input id='manage_card:other_id' type='text' class='form-control form-control-sm' placeholder=''>
               </div>
               <div class='col-2'>
-                <button type='button' class='btn btn-secondary btn-sm'>Find</button>
+                <button id='manage_card:button_other_find' type='button' class='btn btn-secondary btn-sm'>Find</button>
               </div>
             </div>
 
@@ -102,53 +101,53 @@
 
             <div class='row row-shade rowpop'>
               <div class='col-5'> Username </div>
-              <div class='col-7'> jdoey112 </div>
+              <div id='manage_card:username' class='col-7'> jdoey112 </div>
             </div>
 
             <div class='row rowpop'>
               <div class='col-5'> First Name </div>
-              <div class='col-7'> J </div>
+              <div id='manage_card:first_name' class='col-7'> J </div>
             </div>
 
 
             <div class='row row-shade rowpop'>
               <div class='col-5'> Last Name </div>
-              <div class='col-7'> Doey </div>
+              <div id='manage_card:last_name' class='col-7'> Doey </div>
             </div>
 
             <div class='row rowpop'>
               <div class='col-5'> E-Mail </div>
-              <div class='col-7'> jdoey112@example.com </div>
+              <div id='manage_card:email' class='col-7'> jdoey112@example.com </div>
             </div>
 
             <div class='row row-shade rowpop'>
               <div class='col-5'> Phone </div>
-              <div class='col-7'> (607) 555-1212</div>
+              <div id='manage_card:phone' class='col-7'> (607) 555-1212</div>
             </div>
 
             <div class='row rowpop'>
               <div class='col-5'> Address </div>
-              <div class='col-7'> 15 Lane </div>
+              <div id='manage_card:address' class='col-7'> 15 Lane </div>
             </div>
 
             <div class='row row-shade rowpop'>
               <div class='col-5'> City </div>
-              <div class='col-7'> Ithaca </div>
+              <div id='manage_card:city' class='col-7'> Ithaca </div>
             </div>
 
             <div class='row rowpop'>
               <div class='col-5'> State </div>
-              <div class='col-7'> NY </div>
+              <div id='manage_card:state' class='col-7'> NY </div>
             </div>
 
             <div class='row row-shade rowpop'>
               <div class='col-5'> ZIP </div>
-              <div class='col-7'> 14850 </div>
+              <div id='manage_card:zip' class='col-7'> 14850 </div>
             </div>
 
             <div class='row rowpop'>
               <div class='col-5'> Group </div>
-              <div class='col-7'> General </div>
+              <div id='manage_card:group' class='col-7'> General </div>
             </div>
 
           </div>
@@ -168,7 +167,7 @@
           <div class='col-6'></div>
 
           <div class='col-3'>
-            <button type='button' class='btn btn-secondary btn-sm'>Re-Issue Card</button>
+            <button id='manage_card:button_reissue' type='button' class='btn btn-secondary btn-sm'>Re-Issue Card</button>
           </div>
 
         </div>

+ 24 - 135
main/app/templates/manage_user.html

@@ -17,95 +17,95 @@
         <div class='row'>
 
           <!-- half of the row is devoted to card specific operations -->
-          <div class='col-6'>
+          <div class='col-10'>
 
             <div class='row row-shade rowpop'>
               <div class='col-4'> User Id </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
-              <div class='col-2'> <button type='button' class='btn btn-secondary btn-sm'>Lookup</button> </div>
+              <div class='col-6'> <input id='manage_user:userid' type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-2'> <button id='manage_user:button_lookup_userid' type='button' class='btn btn-secondary btn-sm'>Lookup</button> </div>
             </div>
 
             <div class='row rowpop'>
               <div class='col-4'> User Name </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
-              <div class='col-2'> <button type='button' class='btn btn-secondary btn-sm'>Lookup</button> </div>
+              <div class='col-6'> <input id='manage_user:username' type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-2'> <button id='manage_user:button_lookup_username' type='button' class='btn btn-secondary btn-sm'>Lookup</button> </div>
             </div>
 
             <div class='row rowpop row-shade'>
               <div class='col-4'> First Name </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-6'> <input id='manage_user:first_name' type='text' class='form-control form-control-sm' placeholder=''> </div>
               <div class='col-2'> </div>
             </div>
 
             <div class='row rowpop'>
               <div class='col-4'> Last Name </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-6'> <input id='manage_user:last_name' type='text' class='form-control form-control-sm' placeholder=''> </div>
               <div class='col-2'> </div>
             </div>
 
             <div class='row rowpop row-shade'>
               <div class='col-4'> E-Mail </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-6'> <input id='manage_user:email' type='text' class='form-control form-control-sm' placeholder=''> </div>
               <div class='col-2'> </div>
             </div>
 
             <div class='row rowpop'>
               <div class='col-4'> Phone </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-6'> <input id='manage_user:phone' type='text' class='form-control form-control-sm' placeholder=''> </div>
               <div class='col-2'> </div>
             </div>
 
             <div class='row rowpop row-shade'>
               <div class='col-4'> Address </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-6'> <input id='manage_user:address' type='text' class='form-control form-control-sm' placeholder=''> </div>
               <div class='col-2'> </div>
             </div>
 
             <div class='row rowpop'>
               <div class='col-4'> City </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-6'> <input id='manage_user:city' type='text' class='form-control form-control-sm' placeholder=''> </div>
               <div class='col-2'> </div>
             </div>
 
             <div class='row rowpop row-shade'>
               <div class='col-4'> State </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-6'> <input id='manage_user:state' type='text' class='form-control form-control-sm' placeholder=''> </div>
               <div class='col-2'> </div>
             </div>
 
             <div class='row rowpop'>
               <div class='col-4'> ZIP </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-6'> <input id='manage_user:zip' type='text' class='form-control form-control-sm' placeholder=''> </div>
               <div class='col-2'> </div>
             </div>
 
             <div class='row rowpop row-shade'>
               <div class='col-4'> Shipping Name </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-6'> <input id='manage_user:shipping_name' type='text' class='form-control form-control-sm' placeholder=''> </div>
               <div class='col-2'> </div>
             </div>
 
             <div class='row rowpop'>
               <div class='col-4'> Shipping Address </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-6'> <input id='manage_user:shipping_address' type='text' class='form-control form-control-sm' placeholder=''> </div>
               <div class='col-2'> </div>
             </div>
 
             <div class='row rowpop row-shade'>
               <div class='col-4'> Shipping City </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-6'> <input id='manage_user:shipping_city' type='text' class='form-control form-control-sm' placeholder=''> </div>
               <div class='col-2'> </div>
             </div>
 
             <div class='row rowpop'>
               <div class='col-4'> Shipping State </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-6'> <input id='manage_user:shipping_state' type='text' class='form-control form-control-sm' placeholder=''> </div>
               <div class='col-2'> </div>
             </div>
 
             <div class='row rowpop row-shade'>
               <div class='col-4'> Shipping ZIP </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
+              <div class='col-6'> <input id='manage_user:shipping_zip' type='text' class='form-control form-control-sm' placeholder=''> </div>
               <div class='col-2'> </div>
             </div>
 
@@ -126,117 +126,6 @@
           </div>
 
           <div class='col-6'>
-
-            <div class='row rowpop row-shade'>
-              <div class='col-4'> User Name </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
-              <div class='col-2'> </div>
-            </div>
-
-            <div class='row rowpop '>
-              <div class='col-4'> First Name </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
-              <div class='col-2'> </div>
-            </div>
-
-            <div class='row rowpop row-shade'>
-              <div class='col-4'> Last Name </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
-              <div class='col-2'> </div>
-            </div>
-
-            <div class='row rowpop '>
-              <div class='col-4'> E-Mail </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
-              <div class='col-2'> </div>
-            </div>
-
-            <div class='row rowpop row-shade'>
-              <div class='col-4'> Phone </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
-              <div class='col-2'> </div>
-            </div>
-
-            <div class='row rowpop '>
-              <div class='col-4'> Address </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
-              <div class='col-2'> </div>
-            </div>
-
-            <div class='row rowpop row-shade'>
-              <div class='col-4'> City </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
-              <div class='col-2'> </div>
-            </div>
-
-            <div class='row rowpop '>
-              <div class='col-4'> State </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
-              <div class='col-2'> </div>
-            </div>
-
-            <div class='row rowpop row-shade'>
-              <div class='col-4'> ZIP </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
-              <div class='col-2'> </div>
-            </div>
-
-            <div class='row rowpop '>
-              <div class='col-4'> Shipping Name </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
-              <div class='col-2'> </div>
-            </div>
-
-            <div class='row rowpop row-shade'>
-              <div class='col-4'> Shipping Address </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
-              <div class='col-2'> </div>
-            </div>
-
-            <div class='row rowpop '>
-              <div class='col-4'> Shipping City </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
-              <div class='col-2'> </div>
-            </div>
-
-            <div class='row rowpop row-shade'>
-              <div class='col-4'> Shipping State </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
-              <div class='col-2'> </div>
-            </div>
-
-            <div class='row rowpop '>
-              <div class='col-4'> Shipping ZIP </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
-              <div class='col-2'> </div>
-            </div>
-
-            <div class='row rowpop row-shade'>
-              <div class='col-4'> Password </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
-              <div class='col-2'> </div>
-            </div>
-
-            <div class='row rowpop '>
-              <div class='col-4'> Confirm Password </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </div>
-              <div class='col-2'> </div>
-            </div>
-
-            <div class='row rowpop row-shade'>
-              <div class='col-4'> Group </div>
-              <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>
-                  </select>
-                </div>
-              </div>
-              <div class='col-2'> </div>
-            </div>
-
           </div>
 
         <!-- row -->
@@ -293,27 +182,27 @@
 
             <div class='row rowpop row-shade'>
               <div class='col-4'> Mag Stripe </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </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='col-4'> RFID </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </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 type='text' class='form-control form-control-sm' placeholder=''> </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='col-4'> Group </div>
-              <div class='col-6'> <input type='text' class='form-control form-control-sm' placeholder=''> </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'>
-                <button type='button' class='btn btn-secondary btn-sm'>Reset Password</button>
+                <button id='manage_user:button_associate_card' type='button' class='btn btn-secondary btn-sm'>Associate Card to User</button>
               </div>
               <div class='col-8'></div>
             </div>
@@ -329,7 +218,7 @@
 
         <!-- user managed cards block -->
         <div class='row'>
-          <div class='col-10'>
+          <div id='manage_user:list_cards' class='col-10'>
 
             <div class='row rowpop'>
               <div class='col-6'> <h3> User Owned Cards </h3> </div>

+ 5 - 1
main/main.py

@@ -1,3 +1,7 @@
-#!/usr/bin/python
+#!/usr/bin/python3
+#
 
 from app import app
+
+if __name__ == '__main__':
+  app.run()