diff --git a/class/GameMgr.php b/class/GameMgr.php index 9ea39da..cc436a1 100644 --- a/class/GameMgr.php +++ b/class/GameMgr.php @@ -430,5 +430,34 @@ class GameMgr return $games; } + // Sanitize games and return game IDs. + function sanitizeGames(array $games) : array { + $sanitized = []; + foreach ($games as $game) { + // explode game identifier + [$name, $id] = explode("#", $game); + + // fetch game + if ($id !== null) { + $records = $this->db->findBy([["name", "=", $name], "AND", ["_id", "=", (int)$id]]); + } else { + $records = $this->db->findBy(["name", "=", $name]); + } + + // put game ID into sanitized list only if identifier is not ambiguous + if (count($records) === 1) { + $sanitized[] = $records[0]["_id"]; + } + } + + return $sanitized; + } + + // Resolve group IDs to full group identifiers. + function resolveGames(array &$gameIds): void { + $a = $this->db->findBy([["_id", "IN", $gameIds]]); // no caching here... + $gameIds = array_map(fn($r) => $r["name"] . "#" . $r["_id"] ,$a); + } + // ------- } diff --git a/class/GroupMgr.php b/class/GroupMgr.php index 89b25ac..a557dea 100644 --- a/class/GroupMgr.php +++ b/class/GroupMgr.php @@ -192,7 +192,7 @@ class Group extends AutoStoring alter_array_contents($this->games, $gameid, null); } foreach ($gameids_remove as $gameid) { // remove games - alter_array_contents($this->members, null, $gameid); + alter_array_contents($this->games, null, $gameid); } $this->storeMods(); // store changes diff --git a/group_manager_frame.php b/group_manager_frame.php index 763fb88..2eebfaf 100644 --- a/group_manager_frame.php +++ b/group_manager_frame.php @@ -67,13 +67,23 @@ if (!get_autologin_state() || ($user_data["privilege"] !== PRIVILEGE_QUIZMASTER)
- - + + + + +
+ + + + + + +
@@ -82,13 +92,13 @@ if (!get_autologin_state() || ($user_data["privilege"] !== PRIVILEGE_QUIZMASTER)
-
+
-
+
-
- - +
+ +
diff --git a/interface.php b/interface.php index 00638cf..9b4920c 100644 --- a/interface.php +++ b/interface.php @@ -721,10 +721,14 @@ function delete_groups(ReqHandler &$rh, array $params): string function get_all_groups(ReqHandler &$rh, array $params): array { global $groupMgr; + global $gameMgr; + $groups = $groupMgr->getAllGroups(); $a = []; foreach ($groups as $g) { - $a[] = $g->toArray(); + $r = $g->toArray(); + $gameMgr->resolveGames($r["games"]); + $a[] = $r; } return $a; } @@ -825,7 +829,7 @@ function change_group_members(ReqHandler &$rh, array $params): string $group = $groupMgr->getGroup($params["groupid"]); if ($group !== null) { - if ($group->isUserContributor($user->getNickname())) { + if ($group->isUserContributor($user->getNickname()) || $user->hasQuizmasterPrivilege()) { $add = explode_list(trim($params["add"])); $add = $userMgr->sanitizeNicknames($add); $remove = explode_list(trim($params["remove"])); @@ -838,6 +842,27 @@ function change_group_members(ReqHandler &$rh, array $params): string return "FAIL"; } +function change_group_games(ReqHandler &$rh, array $params): string +{ + global $groupMgr; + global $user; + global $gameMgr; + + $group = $groupMgr->getGroup($params["groupid"]); + if ($group !== null) { + if ($group->isUserContributor($user->getNickname()) || $user->hasQuizmasterPrivilege()) { + $add = explode_list(trim($params["add"])); + $add = $gameMgr->sanitizeGames($add); + $remove = explode_list(trim($params["remove"])); + $remove = $gameMgr->sanitizeGames($remove); + $group->changeGames($add, $remove); + return "OK"; + } + } + + return "FAIL"; +} + function import_users_from_csv(ReqHandler &$rh, array $params): string { if (!isset($_FILES["users_table"])) { @@ -852,6 +877,7 @@ $rh->add("delete_groups", ["ids"], PRIVILEGE_QUIZMASTER, "delete_groups", RESP_P $rh->add("get_all_groups", [], PRIVILEGE_QUIZMASTER, "get_all_groups", RESP_JSON, "Get all player groups."); $rh->add("search_groups", ["needle"], PRIVILEGE_QUIZMASTER, "search_groups", RESP_JSON, "Serach and fetch player groups."); $rh->add("change_group_members", ["groupid", "add", "remove"], PRIVILEGE_QUIZMASTER, "change_group_members", RESP_PLAIN, "Change group members."); +$rh->add("change_group_games", ["groupid", "add", "remove"], PRIVILEGE_QUIZMASTER, "change_group_games", RESP_PLAIN, "Change group games."); $rh->add(["create_user", "update_user"], ["nickname", "password", "realname", "privilege"], PRIVILEGE_QUIZMASTER, "create_update_user", RESP_PLAIN, "Create or update user."); $rh->add("delete_users", ["users"], PRIVILEGE_QUIZMASTER, "delete_users", RESP_PLAIN, "Delete users."); diff --git a/js/gamemgr.js b/js/gamemgr.js index 1b5ba95..037acde 100644 --- a/js/gamemgr.js +++ b/js/gamemgr.js @@ -26,7 +26,7 @@ function list_all_games() { let tdChkBox = document.createElement("td"); tdChkBox.appendChild(chkbox); tdChkBox.classList.add("checkbox"); - let tdGameName = create_table_cell(g["name"]); + let tdGameName = create_table_cell(g["name"] + "#" + g["_id"] + ""); let tdGameDescription = create_table_cell(g["description"]); let tdOwner = create_table_cell(g["owner"]); row.append(tdChkBox, tdGameName, tdGameDescription, tdOwner); diff --git a/js/groupmgr.js b/js/groupmgr.js index 67d8b15..8e5dc9a 100644 --- a/js/groupmgr.js +++ b/js/groupmgr.js @@ -44,6 +44,7 @@ function create_edit_group(group = null) { let group_ownerF = document.getElementById("group_owner"); let group_editorsF = document.getElementById("group_editors"); let group_membersF = document.getElementById("group_members"); + let group_gamesF = document.getElementById("group_games"); if (!update) { // create a new group groupnameF.value = ""; @@ -53,6 +54,7 @@ function create_edit_group(group = null) { group_ownerF.readOnly = true; group_editorsF.value = ""; group_membersF.value = ""; + group_gamesF.value = ""; hide("group_editor_additional_fields"); } else { // update and existing one groupnameF.value = group["groupname"]; @@ -62,6 +64,7 @@ function create_edit_group(group = null) { group_ownerF.readOnly = false; group_editorsF.value = group["editors"].join(", "); group_membersF.value = group["users"].join(", "); + group_gamesF.value = group["games"].join(", "); show("group_editor_additional_fields"); } @@ -123,47 +126,48 @@ function delete_groups() { function print_group_name(group_data) { let record = group_data["groupname"]; - if (!group_data["unique"]) { - record += "#" + group_data["_id"]; - } + let seqNumStyle = (group_data["unique"]) ? "style='color:lightgray'" : ""; + record += `#` + group_data["_id"] + ``; return record; } -let MEMBER_ACTION = ""; +let ACTION = ""; +let TYPE = "" -function open_member_change_window(action) { - MEMBER_ACTION = action; - let winCap = document.getElementById("member_manager_window_title"); +function open_element_change_window(action, type) { + ACTION = action; + TYPE = type; + + let winCap = document.getElementById("element_manager_window_title"); + + let typeStr = (type === "member") ? "Tagok" : "Játékok"; + let opStr = (action === "add") ? "hozzáadása" : "eltávolítása"; // print window title - if (action === "add") { - winCap.innerText = "Tagok hozzáadása"; - } else if (action === "remove") { - winCap.innerText = "Tagok eltávolítása"; - } + winCap.innerText = typeStr + " " + opStr; - show("member_manager_window"); + show("element_manager_window"); } -function change_group_members() { - let userListTA = document.getElementById("add_remove_member_area"); +function change_group_elements() { + let elementListTA = document.getElementById("add_remove_element_area"); let req = { - action: "change_group_members", + action: `change_group_${TYPE}s`, groupid: EDITED_GROUP["_id"], add: [], remove: [] }; - if (MEMBER_ACTION === "add") { - req["add"] = userListTA.value; - } else if (MEMBER_ACTION === "remove") { - req["remove"] = userListTA.value; + if (ACTION === "add") { + req["add"] = elementListTA.value; + } else if (ACTION === "remove") { + req["remove"] = elementListTA.value; } request(req).then(resp => { - userListTA.value = ""; - hide("member_manager_window"); + elementListTA.value = ""; + hide("element_manager_window"); hide("group_editor_window"); list_all_groups(); }); diff --git a/report/template/report.tex b/report/template/report.tex index b3b764f..d05595b 100644 --- a/report/template/report.tex +++ b/report/template/report.tex @@ -134,7 +134,7 @@ % An environment to create a quiz containing questions. The parameter is either the title of the quiz, or the name of the course \newenvironment{quiz}[2]{ -% Create highlighted group title + % Create highlighted group title \begin{mdframed}[backgroundcolor=colsbg] { \color{colsfg}