converted tags to the new system

This commit is contained in:
Miodec 2021-07-08 16:03:52 +01:00
parent 77d7fb0b64
commit 3bd02d3292
10 changed files with 248 additions and 135 deletions

View file

@ -1,7 +1,9 @@
const UsersDAO = require("../../dao/user");
const BotDAO = require("../../dao/bot");
const { isUsernameValid } = require("../../handlers/validation");
const {
isUsernameValid,
isTagPresetNameValid,
} = require("../../handlers/validation");
// import UsersDAO from "../../dao/user";
// import BotDAO from "../../dao/bot";
@ -31,7 +33,11 @@ class UserController {
static async updateName(req, res, next) {
try {
const { name } = req.body;
if (!isUsernameValid(name)) return res.status(400).json({message:"Username invalid. Name cannot contain special characters or contain more than 14 characters. Can include _ . and -"});
if (!isUsernameValid(name))
return res.status(400).json({
message:
"Username invalid. Name cannot contain special characters or contain more than 14 characters. Can include _ . and -",
});
await UsersDAO.updateName();
return res.sendStatus(200);
} catch (e) {
@ -42,9 +48,15 @@ class UserController {
static async checkName(req, res, next) {
try {
const { name } = req.body;
if (!isUsernameValid(name)) return next({status: 400, message: "Username invalid. Name cannot contain special characters or contain more than 14 characters. Can include _ . and -"});
if (!isUsernameValid(name))
return next({
status: 400,
message:
"Username invalid. Name cannot contain special characters or contain more than 14 characters. Can include _ . and -",
});
const available = await UsersDAO.isNameAvailable(name);
if(!available) return res.status(400).json({message:"Username unavailable"});
if (!available)
return res.status(400).json({ message: "Username unavailable" });
return res.sendStatus(200);
} catch (e) {
return next(e);
@ -61,7 +73,7 @@ class UserController {
}
}
static async linkDiscord(req, res ,next){
static async linkDiscord(req, res, next) {
try {
const { uid } = req.decodedToken;
let discordFetch = await fetch("https://discord.com/api/users/@me", {
@ -72,13 +84,15 @@ class UserController {
discordFetch = await discordFetch.json();
const did = discordFetch.id;
let user;
try{
try {
user = await UsersDAO.getUserByDiscordId(did);
} catch(e) {
} catch (e) {
user = null;
}
if (user !== null){
return next("This Discord account is already linked to a different account");
if (user !== null) {
return next(
"This Discord account is already linked to a different account"
);
}
await UsersDAO.linkDiscord(uid, did);
await BotDAO.linkDiscord(uid, did);
@ -88,6 +102,65 @@ class UserController {
}
}
static async addTag(req, res, next) {
try {
const { uid } = req.decodedToken;
const { tagName } = req.body;
if (!isTagPresetNameValid(tagName))
return res.status(400).json({
message:
"Tag name invalid. Name cannot contain special characters or more than 16 characters. Can include _ . and -",
});
let tag = await UsersDAO.addTag(uid, tagName);
return res.status(200).json(tag);
} catch (e) {
return next(e);
}
}
static async clearTagPb(req, res, next) {
try {
const { uid } = req.decodedToken;
const { tagid } = req.body;
await UsersDAO.removeTagPb(uid, tagid);
return res.sendStatus(200);
} catch (e) {
return next(e);
}
}
static async editTag(req, res, next) {
try {
const { uid } = req.decodedToken;
const { tagid, newname } = req.body;
await UsersDAO.editTag(uid, tagid, newname);
return res.sendStatus(200);
} catch (e) {
return next(e);
}
}
static async removeTag(req, res, next) {
try {
const { uid } = req.decodedToken;
const { tagid } = req.body;
await UsersDAO.removeTag(uid, tagid);
return res.sendStatus(200);
} catch (e) {
return next(e);
}
}
static async getTags(req, res, next) {
try {
const { uid } = req.decodedToken;
let tags = await UsersDAO.getTags(uid);
if (tags == undefined) tags = [];
return res.status(200).json(tags);
} catch (e) {
return next(e);
}
}
}
module.exports = UserController;

View file

@ -14,4 +14,14 @@ router.post("/updateName", authenticateRequest, UserController.updateName);
router.get("/", authenticateRequest, UserController.getUser);
router.post("/tags/add", authenticateRequest, UserController.addTag);
router.get("/tags", authenticateRequest, UserController.getTags);
router.post("/tags/clearPb", authenticateRequest, UserController.clearTagPb);
router.post("/tags/remove", authenticateRequest, UserController.removeTag);
router.post("/tags/edit", authenticateRequest, UserController.editTag);
module.exports = router;

View file

@ -2,6 +2,7 @@ const MonkeyError = require("../handlers/error");
const { mongoDB } = require("../init/mongodb");
const { checkAndUpdatePb } = require("../handlers/pb");
const { updateAuthEmail } = require("../handlers/auth");
const uuid = require("uuid");
class UsersDAO {
static async addUser(name, email, uid) {
@ -54,7 +55,7 @@ class UsersDAO {
static async addTag(uid, name) {
return await mongoDB()
.collection("users")
.updateOne({ uid }, { $push: { tags: { name } } });
.updateOne({ uid }, { $push: { tags: { id: uuid.v4(), name } } });
}
static async getTags(uid) {
@ -68,7 +69,7 @@ class UsersDAO {
if (!user) throw new MonkeyError(404, "User not found");
if (
user.tags === undefined ||
user.tags.filter((t) => t._id === id).length === 0
user.tags.filter((t) => t.id === id).length === 0
)
throw new MonkeyError(404, "Tag not found");
return await mongoDB()
@ -76,9 +77,9 @@ class UsersDAO {
.updateOne(
{
uid: uid,
"tags._id": id,
"tags.id": id,
},
{ $set: { tags: { name } } }
{ $set: { "tags.$.name": name } }
);
}
@ -87,20 +88,7 @@ class UsersDAO {
if (!user) throw new MonkeyError(404, "User not found");
if (
user.tags === undefined ||
user.tags.filter((t) => t._id === id).length === 0
)
throw new MonkeyError(404, "Tag not found");
return await mongoDB()
.collection("users")
.updateOne({ uid }, { $pull: { id } });
}
static async removeTagPb(uid, id) {
const user = await mongoDB().collection("users").findOne({ uid });
if (!user) throw new MonkeyError(404, "User not found");
if (
user.tags === undefined ||
user.tags.filter((t) => t._id === id).length === 0
user.tags.filter((t) => t.id === id).length === 0
)
throw new MonkeyError(404, "Tag not found");
return await mongoDB()
@ -108,9 +96,28 @@ class UsersDAO {
.updateOne(
{
uid: uid,
"tags._id": id,
"tags.id": id,
},
{ $pull: { tags: { personalBests: "" } } }
{ $pull: { tags: { id } } }
);
}
static async removeTagPb(uid, id) {
const user = await mongoDB().collection("users").findOne({ uid });
if (!user) throw new MonkeyError(404, "User not found");
if (
user.tags === undefined ||
user.tags.filter((t) => t.id === id).length === 0
)
throw new MonkeyError(404, "Tag not found");
return await mongoDB()
.collection("users")
.updateOne(
{
uid: uid,
"tags.id": id,
},
{ $set: { "tags.$.personalBests": {} } }
);
}
@ -174,9 +181,20 @@ class UsersDAO {
tags,
} = result;
if (mode === "quote") {
return [];
}
let tagsToCheck = [];
user.tags.forEach((tag) => {
if (tags.includes(tag.id)) {
tagsToCheck.push(tag);
}
});
let ret = [];
tags.forEach(async (tag) => {
tagsToCheck.forEach(async (tag) => {
let tagpb = checkAndUpdatePb(
tag.personalBests,
mode,
@ -190,10 +208,13 @@ class UsersDAO {
wpm
);
if (tagpb.isPb) {
ret.push(tag._id);
ret.push(tag.id);
await mongoDB()
.collection("users")
.updateOne({ uid }, { $set: { tags: { personalBests: tagpb.obj } } });
.updateOne(
{ uid, "tags.id": tag.id },
{ $set: { "tags.$.personalBests": tagpb.obj } }
);
}
});

View file

@ -242,7 +242,7 @@ function loadMoreLines(lineIndex) {
if (result.tags !== undefined && result.tags.length > 0) {
result.tags.forEach((tag) => {
DB.getSnapshot().tags.forEach((snaptag) => {
if (tag === snaptag._id) {
if (tag === snaptag.id) {
tagNames += snaptag.name + ", ";
}
});

View file

@ -99,7 +99,7 @@ export function getFilter(group, filter) {
export function loadTags(tags) {
tags.forEach((tag) => {
defaultResultFilters.tags[tag._id] = true;
defaultResultFilters.tags[tag.id] = true;
});
}
@ -305,7 +305,7 @@ export function updateTags() {
DB.getSnapshot().tags.forEach((tag) => {
$(
".pageAccount .content .filterButtons .buttonsAndTitle.tags .buttons"
).append(`<div class="button" filter="${tag._id}">${tag.name}</div>`);
).append(`<div class="button" filter="${tag.id}">${tag.name}</div>`);
});
} else {
$(".pageAccount .content .filterButtons .buttonsAndTitle.tags").addClass(
@ -412,7 +412,7 @@ $(".pageAccount .topFilters .button.currentConfigFilter").click((e) => {
DB.getSnapshot().tags.forEach((tag) => {
if (tag.active === true) {
filters["tags"]["none"] = false;
filters["tags"][tag._id] = true;
filters["tags"][tag.id] = true;
}
});

View file

@ -232,7 +232,7 @@ export function updateTagCommands() {
display: dis,
sticky: true,
exec: () => {
TagController.toggle(tag._id);
TagController.toggle(tag.id);
TestUI.updateModesNotice();
let txt = tag.name;
@ -250,7 +250,7 @@ export function updateTagCommands() {
);
} else {
$(
`#commandLine .suggestions .entry[command='toggleTag${tag._id}']`
`#commandLine .suggestions .entry[command='toggleTag${tag.id}']`
).html(txt);
}
},

View file

@ -64,7 +64,7 @@ function hide() {
}
}
function apply() {
async function apply() {
// console.log(DB.getSnapshot());
let action = $("#tagsWrapper #tagsEdit").attr("action");
let inputVal = $("#tagsWrapper #tagsEdit input").val();
@ -72,100 +72,108 @@ function apply() {
hide();
if (action === "add") {
Loader.show();
axiosInstance
.post("/addTag", {
let response;
try {
response = await axiosInstance.post("/user/tags/add", {
tagName: inputVal,
})
.then((e) => {
Loader.hide();
let status = e.data.resultCode;
if (status === 1) {
Notifications.add("Tag added", 1, 2);
DB.getSnapshot().tags.push({
name: inputVal,
_id: e.data.id,
});
ResultTagsPopup.updateButtons();
Settings.update();
ResultFilters.updateTags();
} else if (status === -1) {
Notifications.add("Invalid tag name", 0);
} else if (status < -1) {
Notifications.add("Unknown error: " + e.data.message, -1);
}
});
} catch (e) {
Loader.hide();
let msg = e?.response?.data?.message ?? e.message;
Notifications.add("Failed to add tag: " + msg, -1);
return;
}
Loader.hide();
if (response.status !== 200) {
Notifications.add(response.data.message);
} else {
Notifications.add("Tag added", 1);
DB.getSnapshot().tags.push({
name: inputVal,
_id: response.data._id,
});
ResultTagsPopup.updateButtons();
Settings.update();
ResultFilters.updateTags();
}
} else if (action === "edit") {
Loader.show();
axiosInstance
.post("/editTag", {
tagName: inputVal,
tagId: tagid,
})
.then((e) => {
Loader.hide();
let status = e.data.resultCode;
if (status === 1) {
Notifications.add("Tag updated", 1);
DB.getSnapshot().tags.forEach((tag) => {
if (tag._id === tagid) {
tag.name = inputVal;
}
});
ResultTagsPopup.updateButtons();
Settings.update();
ResultFilters.updateTags();
} else if (status === -1) {
Notifications.add("Invalid tag name", 0);
} else if (status < -1) {
Notifications.add("Unknown error: " + e.data.message, -1);
let response;
try {
response = await axiosInstance.post("/user/tags/edit", {
tagid,
newname: inputVal,
});
} catch (e) {
Loader.hide();
let msg = e?.response?.data?.message ?? e.message;
Notifications.add("Failed to edit tag: " + msg, -1);
return;
}
Loader.hide();
if (response.status !== 200) {
Notifications.add(response.data.message);
} else {
Notifications.add("Tag updated", 1);
DB.getSnapshot().tags.forEach((tag) => {
if (tag.id === tagid) {
tag.name = inputVal;
}
});
ResultTagsPopup.updateButtons();
Settings.update();
ResultFilters.updateTags();
}
} else if (action === "remove") {
Loader.show();
axiosInstance
.post("/removeTag", {
tagId: tagid,
})
.then((e) => {
Loader.hide();
let status = e.data.resultCode;
if (status === 1) {
Notifications.add("Tag removed", 1);
DB.getSnapshot().tags.forEach((tag, index) => {
if (tag._id === tagid) {
DB.getSnapshot().tags.splice(index, 1);
}
});
ResultTagsPopup.updateButtons();
Settings.update();
ResultFilters.updateTags();
} else if (status < -1) {
Notifications.add("Unknown error: " + e.data.message, -1);
let response;
try {
response = await axiosInstance.post("/user/tags/remove", { tagid });
} catch (e) {
Loader.hide();
let msg = e?.response?.data?.message ?? e.message;
Notifications.add("Failed to remove tag: " + msg, -1);
return;
}
Loader.hide();
if (response.status !== 200) {
Notifications.add(response.data.message);
} else {
Notifications.add("Tag removed", 1);
DB.getSnapshot().tags.forEach((tag, index) => {
if (tag.id === tagid) {
DB.getSnapshot().tags.splice(index, 1);
}
});
ResultTagsPopup.updateButtons();
Settings.update();
ResultFilters.updateTags();
}
} else if (action === "clearPb") {
//TODO: rewrite to axios
// Loader.show();
// CloudFunctions.clearTagPb({
// uid: firebase.auth().currentUser.uid,
// tagid: tagid,
// }).then((e) => {
// Loader.hide();
// let status = e.data.resultCode;
// if (status === 1) {
// Notifications.add("PB cleared", 1);
// DB.getSnapshot().tags.forEach((tag, index) => {
// if (tag.id === tagid) {
// tag.personalBests = {};
// }
// });
// ResultTagsPopup.updateButtons();
// Settings.update();
// ResultFilters.updateTags();
// } else if (status < -1) {
// Notifications.add("Unknown error: " + e.data.message, -1);
// }
// });
Loader.show();
let response;
try {
response = await axiosInstance.post("/user/tags/clearPb", { tagid });
} catch (e) {
Loader.hide();
let msg = e?.response?.data?.message ?? e.message;
Notifications.add("Failed to clear tag pb: " + msg, -1);
return;
}
Loader.hide();
if (response.status !== 200) {
Notifications.add(response.data.message);
} else {
Notifications.add("Tag PB cleared", 1);
DB.getSnapshot().tags.forEach((tag, index) => {
if (tag.id === tagid) {
tag.personalBests = {};
}
});
ResultTagsPopup.updateButtons();
Settings.update();
ResultFilters.updateTags();
}
}
}

View file

@ -34,7 +34,7 @@ export function updateButtons() {
$("#resultEditTagsPanel .buttons").empty();
DB.getSnapshot().tags.forEach((tag) => {
$("#resultEditTagsPanel .buttons").append(
`<div class="button tag" tagid="${tag._id}">${tag.name}</div>`
`<div class="button tag" tagid="${tag.id}">${tag.name}</div>`
);
});
}
@ -105,7 +105,7 @@ $("#resultEditTagsPanel .confirmButton").click((e) => {
if (newtags.length > 0) {
newtags.forEach((tag) => {
DB.getSnapshot().tags.forEach((snaptag) => {
if (tag === snaptag._id) {
if (tag === snaptag.id) {
tagNames += snaptag.name + ", ";
}
});

View file

@ -7,7 +7,7 @@ export function saveActiveToLocalStorage() {
try {
DB.getSnapshot().tags.forEach((tag) => {
if (tag.active === true) {
tags.push(tag._id);
tags.push(tag.id);
}
});
// let d = new Date();
@ -41,7 +41,7 @@ export function set(tagid, state, nosave = false) {
export function toggle(tagid, nosave = false) {
DB.getSnapshot().tags.forEach((tag) => {
if (tag._id === tagid) {
if (tag.id === tagid) {
if (tag.active === undefined) {
tag.active = true;
} else {

View file

@ -1437,7 +1437,7 @@ export function finish(difficultyFailed = false) {
DB.getSnapshot().tags.forEach((tag) => {
if (tag.active === true) {
activeTags.push(tag);
activeTagsIds.push(tag._id);
activeTagsIds.push(tag.id);
}
});
} catch (e) {}
@ -1605,7 +1605,7 @@ export function finish(difficultyFailed = false) {
let annotationSide = "left";
activeTags.forEach(async (tag) => {
let tpb = await DB.getLocalTagPB(
tag._id,
tag.id,
Config.mode,
mode2,
Config.punctuation,
@ -1613,13 +1613,13 @@ export function finish(difficultyFailed = false) {
Config.difficulty
);
$("#result .stats .tags .bottom").append(`
<div tagid="${tag._id}" aria-label="PB: ${tpb}" data-balloon-pos="up">${tag.name}<i class="fas fa-crown hidden"></i></div>
<div tagid="${tag.id}" aria-label="PB: ${tpb}" data-balloon-pos="up">${tag.name}<i class="fas fa-crown hidden"></i></div>
`);
if (Config.mode != "quote") {
if (tpb < stats.wpm) {
//new pb for that tag
DB.saveLocalTagPB(
tag._id,
tag.id,
Config.mode,
mode2,
Config.punctuation,
@ -1631,11 +1631,12 @@ export function finish(difficultyFailed = false) {
consistency
);
$(
`#result .stats .tags .bottom div[tagid="${tag._id}"] .fas`
`#result .stats .tags .bottom div[tagid="${tag.id}"] .fas`
).removeClass("hidden");
$(
`#result .stats .tags .bottom div[tagid="${tag._id}"]`
).attr("aria-label", "+" + Misc.roundTo2(stats.wpm - tpb));
$(`#result .stats .tags .bottom div[tagid="${tag.id}"]`).attr(
"aria-label",
"+" + Misc.roundTo2(stats.wpm - tpb)
);
// console.log("new pb for tag " + tag.name);
} else {
ChartController.result.options.annotation.annotations.push({