diff --git a/src/controllers/api/nameWeaponController.ts b/src/controllers/api/nameWeaponController.ts new file mode 100644 index 00000000..7543cbc4 --- /dev/null +++ b/src/controllers/api/nameWeaponController.ts @@ -0,0 +1,27 @@ +import { RequestHandler } from "express"; +import { getAccountIdForRequest } from "@/src/services/loginService"; +import { getInventory, updateCurrency } from "@/src/services/inventoryService"; +import { getJSONfromString } from "@/src/helpers/stringHelpers"; +import { TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes"; + +interface INameWeaponRequest { + ItemName: string; +} + +export const nameWeaponController: RequestHandler = async (req, res) => { + const accountId = await getAccountIdForRequest(req); + const inventory = await getInventory(accountId); + const body = getJSONfromString(req.body.toString()) as INameWeaponRequest; + const item = inventory[req.query.Category as string as TEquipmentKey].find( + item => item._id.toString() == (req.query.ItemId as string) + )!; + if (body.ItemName != "") { + item.ItemName = body.ItemName; + } else { + item.ItemName = undefined; + } + await inventory.save(); + res.json({ + InventoryChanges: await updateCurrency("webui" in req.query ? 0 : 15, true, accountId) + }); +}; diff --git a/src/controllers/api/upgradesController.ts b/src/controllers/api/upgradesController.ts index 88c01dc7..25b548e6 100644 --- a/src/controllers/api/upgradesController.ts +++ b/src/controllers/api/upgradesController.ts @@ -1,7 +1,7 @@ import { RequestHandler } from "express"; import { IUpgradesRequest } from "@/src/types/requestTypes"; import { FocusSchool, IEquipmentDatabase } from "@/src/types/inventoryTypes/commonInventoryTypes"; -import { IMiscItem, IEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes"; +import { IMiscItem, TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes"; import { getAccountIdForRequest } from "@/src/services/loginService"; import { addMiscItems, getInventory, updateCurrency } from "@/src/services/inventoryService"; @@ -28,7 +28,7 @@ export const upgradesController: RequestHandler = async (req, res) => { switch (operation.UpgradeRequirement) { case "/Lotus/Types/Items/MiscItems/OrokinReactor": case "/Lotus/Types/Items/MiscItems/OrokinCatalyst": - for (const item of inventory[payload.ItemCategory as IEquipmentKey] as IEquipmentDatabase[]) { + for (const item of inventory[payload.ItemCategory as TEquipmentKey] as IEquipmentDatabase[]) { if (item._id.toString() == payload.ItemId.$oid) { item.Features ??= 0; item.Features |= 1; @@ -38,7 +38,7 @@ export const upgradesController: RequestHandler = async (req, res) => { break; case "/Lotus/Types/Items/MiscItems/UtilityUnlocker": case "/Lotus/Types/Items/MiscItems/WeaponUtilityUnlocker": - for (const item of inventory[payload.ItemCategory as IEquipmentKey] as IEquipmentDatabase[]) { + for (const item of inventory[payload.ItemCategory as TEquipmentKey] as IEquipmentDatabase[]) { if (item._id.toString() == payload.ItemId.$oid) { item.Features ??= 0; item.Features |= 2; @@ -49,7 +49,7 @@ export const upgradesController: RequestHandler = async (req, res) => { case "/Lotus/Types/Items/MiscItems/WeaponPrimaryArcaneUnlocker": case "/Lotus/Types/Items/MiscItems/WeaponSecondaryArcaneUnlocker": case "/Lotus/Types/Items/MiscItems/WeaponMeleeArcaneUnlocker": - for (const item of inventory[payload.ItemCategory as IEquipmentKey] as IEquipmentDatabase[]) { + for (const item of inventory[payload.ItemCategory as TEquipmentKey] as IEquipmentDatabase[]) { if (item._id.toString() == payload.ItemId.$oid) { item.Features ??= 0; item.Features |= 32; @@ -61,7 +61,7 @@ export const upgradesController: RequestHandler = async (req, res) => { case "/Lotus/Types/Items/MiscItems/FormaUmbra": case "/Lotus/Types/Items/MiscItems/FormaAura": case "/Lotus/Types/Items/MiscItems/FormaStance": - for (const item of inventory[payload.ItemCategory as IEquipmentKey] as IEquipmentDatabase[]) { + for (const item of inventory[payload.ItemCategory as TEquipmentKey] as IEquipmentDatabase[]) { if (item._id.toString() == payload.ItemId.$oid) { item.XP = 0; setSlotPolarity(item, operation.PolarizeSlot, operation.PolarizeValue); @@ -72,7 +72,7 @@ export const upgradesController: RequestHandler = async (req, res) => { } break; case "/Lotus/Types/Items/MiscItems/ModSlotUnlocker": - for (const item of inventory[payload.ItemCategory as IEquipmentKey] as IEquipmentDatabase[]) { + for (const item of inventory[payload.ItemCategory as TEquipmentKey] as IEquipmentDatabase[]) { if (item._id.toString() == payload.ItemId.$oid) { item.ModSlotPurchases ??= 0; item.ModSlotPurchases += 1; @@ -87,7 +87,7 @@ export const upgradesController: RequestHandler = async (req, res) => { } break; case "/Lotus/Types/Items/MiscItems/CustomizationSlotUnlocker": - for (const item of inventory[payload.ItemCategory as IEquipmentKey] as IEquipmentDatabase[]) { + for (const item of inventory[payload.ItemCategory as TEquipmentKey] as IEquipmentDatabase[]) { if (item._id.toString() == payload.ItemId.$oid) { item.CustomizationSlotPurchases ??= 0; item.CustomizationSlotPurchases += 1; @@ -103,7 +103,7 @@ export const upgradesController: RequestHandler = async (req, res) => { break; case "": console.assert(operation.OperationType == "UOT_SWAP_POLARITY"); - for (const item of inventory[payload.ItemCategory as IEquipmentKey] as IEquipmentDatabase[]) { + for (const item of inventory[payload.ItemCategory as TEquipmentKey] as IEquipmentDatabase[]) { if (item._id.toString() == payload.ItemId.$oid) { for (let i = 0; i != operation.PolarityRemap.length; ++i) { if (operation.PolarityRemap[i].Slot != i) { diff --git a/src/routes/api.ts b/src/routes/api.ts index 2ed9bdcb..8a059bfe 100644 --- a/src/routes/api.ts +++ b/src/routes/api.ts @@ -55,6 +55,7 @@ import { getGuildDojoController } from "@/src/controllers/api/getGuildDojoContro import { syndicateSacrificeController } from "../controllers/api/syndicateSacrificeController"; import { startDojoRecipeController } from "@/src/controllers/api/startDojoRecipeController"; import { queueDojoComponentDestructionController } from "@/src/controllers/api/queueDojoComponentDestructionController"; +import { nameWeaponController } from "@/src/controllers/api/nameWeaponController"; const apiRouter = express.Router(); @@ -120,5 +121,6 @@ apiRouter.post("/upgrades.php", upgradesController); apiRouter.post("/guildTech.php", guildTechController); apiRouter.post("/syndicateSacrifice.php", syndicateSacrificeController); apiRouter.post("/startDojoRecipe.php", startDojoRecipeController); +apiRouter.post("/nameWeapon.php", nameWeaponController); export { apiRouter }; diff --git a/src/types/inventoryTypes/inventoryTypes.ts b/src/types/inventoryTypes/inventoryTypes.ts index 4b4f589a..ec492353 100644 --- a/src/types/inventoryTypes/inventoryTypes.ts +++ b/src/types/inventoryTypes/inventoryTypes.ts @@ -59,7 +59,7 @@ export interface ITypeCount { ItemCount: number; } -export type IEquipmentKey = +export type TEquipmentKey = | "Suits" | "LongGuns" | "Pistols" diff --git a/static/webui/script.js b/static/webui/script.js index 0475a730..6a9d525d 100644 --- a/static/webui/script.js +++ b/static/webui/script.js @@ -132,6 +132,9 @@ function updateInventory() { { const td = document.createElement("td"); td.textContent = itemMap[item.ItemType]?.name ?? item.ItemType; + if (item.ItemName) { + td.textContent = item.ItemName + " (" + td.textContent + ")"; + } tr.appendChild(td); } { @@ -144,12 +147,21 @@ function updateInventory() { event.preventDefault(); addGearExp("Suits", item.ItemId.$oid, 1_600_000 - item.XP); }; - a.textContent = "Make Rank 30"; + a.title = "Make Rank 30"; + a.innerHTML = ``; + td.appendChild(a); + } + { + const a = document.createElement("a"); + a.href = "#"; + a.onclick = function (event) { + event.preventDefault(); + const name = prompt("Enter new custom name:"); + renameGear("Suits", item.ItemId.$oid, name); + }; + a.title = "Rename"; + a.innerHTML = ``; td.appendChild(a); - - const span = document.createElement("span"); - span.innerHTML = " · "; - td.appendChild(span); } { const a = document.createElement("a"); @@ -158,7 +170,8 @@ function updateInventory() { event.preventDefault(); disposeOfGear("Suits", item.ItemId.$oid); }; - a.textContent = "Remove"; + a.title = "Remove"; + a.innerHTML = ``; td.appendChild(a); } tr.appendChild(td); @@ -173,6 +186,9 @@ function updateInventory() { { const td = document.createElement("td"); td.textContent = itemMap[item.ItemType]?.name ?? item.ItemType; + if (item.ItemName) { + td.textContent = item.ItemName + " (" + td.textContent + ")"; + } tr.appendChild(td); } { @@ -185,12 +201,21 @@ function updateInventory() { event.preventDefault(); addGearExp(category, item.ItemId.$oid, 800_000 - item.XP); }; - a.textContent = "Make Rank 30"; + a.title = "Make Rank 30"; + a.innerHTML = ``; + td.appendChild(a); + } + { + const a = document.createElement("a"); + a.href = "#"; + a.onclick = function (event) { + event.preventDefault(); + const name = prompt("Enter new custom name:"); + renameGear(category, item.ItemId.$oid, name); + }; + a.title = "Rename"; + a.innerHTML = ``; td.appendChild(a); - - const span = document.createElement("span"); - span.innerHTML = " · "; - td.appendChild(span); } { const a = document.createElement("a"); @@ -199,7 +224,8 @@ function updateInventory() { event.preventDefault(); disposeOfGear(category, item.ItemId.$oid); }; - a.textContent = "Remove"; + a.title = "Remove"; + a.innerHTML = ``; td.appendChild(a); } tr.appendChild(td); @@ -241,14 +267,10 @@ function updateInventory() { }) ); a.target = "_blank"; - a.textContent = "View Stats"; + a.title = "View Stats"; + a.innerHTML = ``; td.appendChild(a); } - { - const span = document.createElement("span"); - span.innerHTML = " · "; - td.appendChild(span); - } { const a = document.createElement("a"); a.href = "#"; @@ -256,7 +278,8 @@ function updateInventory() { event.preventDefault(); disposeOfGear("Upgrades", item.ItemId.$oid); }; - a.textContent = "Remove"; + a.title = "Remove"; + a.innerHTML = ``; td.appendChild(a); } tr.appendChild(td); @@ -282,12 +305,9 @@ function updateInventory() { event.preventDefault(); setFingerprint(item.ItemType, item.ItemId, { lvl: maxRank }); }; - a.textContent = "Max Rank"; + a.title = "Max Rank"; + a.innerHTML = ``; td.appendChild(a); - - const span = document.createElement("span"); - span.innerHTML = " · "; - td.appendChild(span); } { const a = document.createElement("a"); @@ -296,7 +316,8 @@ function updateInventory() { event.preventDefault(); disposeOfGear("Upgrades", item.ItemId.$oid); }; - a.textContent = "Remove"; + a.title = "Remove"; + a.innerHTML = ``; td.appendChild(a); } tr.appendChild(td); @@ -327,14 +348,10 @@ function updateInventory() { event.preventDefault(); setFingerprint(item.ItemType, item.LastAdded, { lvl: maxRank }); }; - a.textContent = "Max Rank"; + a.title = "Max Rank"; + a.innerHTML = ``; td.appendChild(a); } - { - const span = document.createElement("span"); - span.innerHTML = " · "; - td.appendChild(span); - } { const a = document.createElement("a"); a.href = "#"; @@ -342,7 +359,8 @@ function updateInventory() { event.preventDefault(); disposeOfItems("Upgrades", item.ItemType, item.ItemCount); }; - a.textContent = "Remove"; + a.title = "Remove"; + a.innerHTML = ``; td.appendChild(a); } tr.appendChild(td); @@ -432,6 +450,20 @@ function addGearExp(category, oid, xp) { }); } +function renameGear(category, oid, name) { + revalidateAuthz(() => { + $.post({ + url: "/api/nameWeapon.php?" + window.authz + "&Category=" + category + "&ItemId=" + oid + "&webui=1", + contentType: "text/plain", + data: JSON.stringify({ + ItemName: name + }) + }).done(function () { + updateInventory(); + }); + }); +} + function disposeOfGear(category, oid) { const data = { SellCurrency: "SC_RegularCredits", diff --git a/static/webui/style.css b/static/webui/style.css index 119d4fd2..341588cd 100644 --- a/static/webui/style.css +++ b/static/webui/style.css @@ -20,3 +20,10 @@ body:not(.logged-in) .nav-item.dropdown, body:not(.logged-in) #refresh-note { display: none; } + +td.text-end > a > svg { + fill: currentColor; + height: 1em; + margin-left: 0.5em; + margin-bottom: 4px; /* to centre the icon */ +}