diff --git a/bemani/data/mysql/user.py b/bemani/data/mysql/user.py
index 6d82916..b4af3fc 100644
--- a/bemani/data/mysql/user.py
+++ b/bemani/data/mysql/user.py
@@ -330,7 +330,7 @@ class UserData(BaseData):
Returns:
A list of User objects representing all users.
"""
- sql = "SELECT id, username, email, admin FROM user"
+ sql = "SELECT id, username, email, admin, (SELECT COUNT(id) FROM card WHERE card.userid = user.id) AS linked_cards FROM user"
cursor = self.execute(sql)
return [
User(
@@ -338,6 +338,7 @@ class UserData(BaseData):
result["username"],
result["email"],
result["admin"] == 1,
+ result["linked_cards"],
)
for result in cursor.mappings()
]
diff --git a/bemani/data/types.py b/bemani/data/types.py
index 821eb83..83f3e86 100644
--- a/bemani/data/types.py
+++ b/bemani/data/types.py
@@ -15,7 +15,14 @@ class User:
more cards, or swap out a card for a new one.
"""
- def __init__(self, userid: UserID, username: Optional[str], email: Optional[str], admin: bool) -> None:
+ def __init__(
+ self,
+ userid: UserID,
+ username: Optional[str],
+ email: Optional[str],
+ admin: bool,
+ linked_cards: Optional[int] = None,
+ ) -> None:
"""
Initialize the user object.
@@ -25,14 +32,17 @@ class User:
the web UI.
email - An optional string, set if the user has claimed their account on the
web UI.
+ admin - Whether this user is an admin or not.
+ linked_cards - The count of cards linked to this account. Not always provided.
"""
self.id = userid
self.username = username
self.email = email
self.admin = admin
+ self.linked_cards = linked_cards
def __repr__(self) -> str:
- return f"User(userid={self.id}, username={self.username}, email={self.email}, admin={self.admin})"
+ return f"User(userid={self.id}, username={self.username}, email={self.email}, admin={self.admin}, linked_cards={self.linked_cards})"
class Achievement:
diff --git a/bemani/frontend/admin/admin.py b/bemani/frontend/admin/admin.py
index 6d947d0..3b7f123 100644
--- a/bemani/frontend/admin/admin.py
+++ b/bemani/frontend/admin/admin.py
@@ -99,6 +99,7 @@ def format_user(user: User) -> Dict[str, Any]:
"username": user.username,
"email": user.email,
"admin": user.admin,
+ "linked_cards": user.linked_cards,
}
diff --git a/bemani/frontend/static/controllers/admin/cards.react.js b/bemani/frontend/static/controllers/admin/cards.react.js
index 16d0ae4..b836104 100644
--- a/bemani/frontend/static/controllers/admin/cards.react.js
+++ b/bemani/frontend/static/controllers/admin/cards.react.js
@@ -39,7 +39,10 @@ var card_management = createReactClass({
animation: 'none',
closeAnimation: 'none',
title: 'Delete Card',
- content: 'Are you sure you want to delete this card?',
+ content: (
+ 'Are you sure you want to delete this card? Doing so will remove the card from the ' +
+ 'user account but will not delete the account itself.'
+ ),
buttons: {
Delete: {
btnClass: 'delete',
@@ -93,12 +96,12 @@ var card_management = createReactClass({
return (
<>
-
+
>
);
},
diff --git a/bemani/frontend/static/controllers/admin/users.react.js b/bemani/frontend/static/controllers/admin/users.react.js
index 1b5f5dc..9340c0d 100644
--- a/bemani/frontend/static/controllers/admin/users.react.js
+++ b/bemani/frontend/static/controllers/admin/users.react.js
@@ -41,8 +41,8 @@ var card_management = createReactClass({
},
sortUsername: function(a, b) {
- var au = a.username ? a.username : '';
- var bu = b.username ? b.username : '';
+ var au = a.username ? a.username : '\u10FFFF';
+ var bu = b.username ? b.username : '\u10FFFF';
return au.localeCompare(bu);
},
@@ -53,11 +53,23 @@ var card_management = createReactClass({
},
sortEmail: function(a, b) {
- var ae = a.email ? a.email : '';
- var be = b.email ? b.email : '';
+ var ae = a.email ? a.email : '\u10FFFF';
+ var be = b.email ? b.email : '\u10FFFF';
return ae.localeCompare(be);
},
+ renderLinkedCards: function(user) {
+ return user.linked_cards ?
+ {user.linked_cards} :
+ none;
+ },
+
+ sortLinkedCards: function(a, b) {
+ var ac = a.linked_cards ? a.linked_cards : 0;
+ var bc = b.linked_cards ? b.linked_cards : 0;
+ return ac - bc;
+ },
+
renderEditButton: function(user) {
return (