impl editSuitInvigorationUpgradeController in web ui
All checks were successful
Build / build (pull_request) Successful in 56s

This commit is contained in:
nyaoouo 2025-07-12 23:20:48 +08:00
parent 987b5b98ff
commit 8c2b4f2c48
4 changed files with 219 additions and 0 deletions

View File

@ -0,0 +1,34 @@
import { getAccountIdForRequest } from "@/src/services/loginService";
import { getInventory } from "@/src/services/inventoryService";
import { RequestHandler } from "express";
const DEFAULT_UPGRADE_EXPIRY_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
export const editSuitInvigorationUpgradeController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
const { oid, data } = req.body as {
oid: string;
data?: {
DefensiveUpgrade: string;
OffensiveUpgrade: string;
UpgradesExpiry?: number;
};
};
const inventory = await getInventory(accountId);
const suit = inventory.Suits.id(oid)!;
if (data) {
suit.DefensiveUpgrade = data.DefensiveUpgrade;
suit.OffensiveUpgrade = data.OffensiveUpgrade;
if (data.UpgradesExpiry) {
suit.UpgradesExpiry = new Date(data.UpgradesExpiry);
} else {
suit.UpgradesExpiry = new Date(Date.now() + DEFAULT_UPGRADE_EXPIRY_MS);
}
} else {
suit.DefensiveUpgrade = undefined;
suit.OffensiveUpgrade = undefined;
suit.UpgradesExpiry = undefined;
}
await inventory.save();
res.end();
};

View File

@ -14,6 +14,7 @@ import { addMissingMaxRankModsController } from "@/src/controllers/custom/addMis
import { webuiFileChangeDetectedController } from "@/src/controllers/custom/webuiFileChangeDetectedController";
import { completeAllMissionsController } from "@/src/controllers/custom/completeAllMissionsController";
import { addMissingHelminthBlueprintsController } from "@/src/controllers/custom/addMissingHelminthBlueprintsController";
import { editSuitInvigorationUpgradeController } from "@/src/controllers/custom/editSuitInvigorationUpgradeController";
import { createAccountController } from "@/src/controllers/custom/createAccountController";
import { createMessageController } from "@/src/controllers/custom/createMessageController";
@ -45,6 +46,7 @@ customRouter.get("/addMissingMaxRankMods", addMissingMaxRankModsController);
customRouter.get("/webuiFileChangeDetected", webuiFileChangeDetectedController);
customRouter.get("/completeAllMissions", completeAllMissionsController);
customRouter.get("/addMissingHelminthBlueprints", addMissingHelminthBlueprintsController);
customRouter.post("/editSuitInvigorationUpgrade", editSuitInvigorationUpgradeController);
customRouter.post("/createAccount", createAccountController);
customRouter.post("/createMessage", createMessageController);

View File

@ -977,6 +977,59 @@
</div>
<div class="toast-container position-fixed bottom-0 end-0 p-3"></div>
</div>
<div id="editSuitInvigorationForm" class="card" style="display: none;">
<h5 class="card-header">Edit Suit Invigoration Upgrades</h5>
<div class="card-body">
<form onsubmit="submitSuitInvigorationUpgrade(event)">
<input type="hidden" id="invigoration-oid" />
<div class="mb-3">
<label for="invigoration-offensive" class="form-label">Offensive Upgrade</label>
<select class="form-select" id="invigoration-offensive">
<option value="">None</option>
<option value="/Lotus/Upgrades/Invigorations/Offensive/OffensiveInvigorationPowerStrength">Power Strength</option>
<option value="/Lotus/Upgrades/Invigorations/Offensive/OffensiveInvigorationPowerRange">Power Range</option>
<option value="/Lotus/Upgrades/Invigorations/Offensive/OffensiveInvigorationPowerDuration">Power Duration</option>
<option value="/Lotus/Upgrades/Invigorations/Offensive/OffensiveInvigorationMeleeDamage">Melee Damage</option>
<option value="/Lotus/Upgrades/Invigorations/Offensive/OffensiveInvigorationPrimaryDamage">Primary Damage</option>
<option value="/Lotus/Upgrades/Invigorations/Offensive/OffensiveInvigorationSecondaryDamage">Secondary Damage</option>
<option value="/Lotus/Upgrades/Invigorations/Offensive/OffensiveInvigorationPrimaryCritChance">Primary Crit Chance</option>
<option value="/Lotus/Upgrades/Invigorations/Offensive/OffensiveInvigorationSecondaryCritChance">Secondary Crit Chance</option>
<option value="/Lotus/Upgrades/Invigorations/Offensive/OffensiveInvigorationMeleeCritChance">Melee Crit Chance</option>
</select>
</div>
<div class="mb-3">
<label for="invigoration-defensive" class="form-label">Defensive Upgrade</label>
<select class="form-select" id="invigoration-defensive">
<option value="">None</option>
<option value="/Lotus/Upgrades/Invigorations/Utility/UtilityInvigorationPowerEfficiency">Power Efficiency</option>
<option value="/Lotus/Upgrades/Invigorations/Utility/UtilityInvigorationMovementSpeed">Movement Speed</option>
<option value="/Lotus/Upgrades/Invigorations/Utility/UtilityInvigorationParkourSpeed">Parkour Speed</option>
<option value="/Lotus/Upgrades/Invigorations/Utility/UtilityInvigorationHealth">Health</option>
<option value="/Lotus/Upgrades/Invigorations/Utility/UtilityInvigorationEnergy">Energy</option>
<option value="/Lotus/Upgrades/Invigorations/Utility/UtilityInvigorationStatusResistance">Status Resistance</option>
<option value="/Lotus/Upgrades/Invigorations/Utility/UtilityInvigorationReloadSpeed">Reload Speed</option>
<option value="/Lotus/Upgrades/Invigorations/Utility/UtilityInvigorationHealthRegen">Health Regen</option>
<option value="/Lotus/Upgrades/Invigorations/Utility/UtilityInvigorationArmor">Armor</option>
<option value="/Lotus/Upgrades/Invigorations/Utility/UtilityInvigorationJumps">Jumps</option>
<option value="/Lotus/Upgrades/Invigorations/Utility/UtilityInvigorationEnergyRegen">Energy Regen</option>
</select>
</div>
<div class="mb-3">
<label for="invigoration-expiry" class="form-label">Upgrades Expiry (optional)</label>
<input type="datetime-local" class="form-control" id="invigoration-expiry" />
</div>
<div class="d-flex gap-2">
<button type="submit" class="btn btn-primary">Apply Upgrades</button>
<button type="button" class="btn btn-secondary" onclick="hideSuitInvigorationForm()">Cancel</button>
<button type="button" class="btn btn-danger" onclick="clearSuitInvigorationUpgrades()">Clear Upgrades</button>
</div>
</form>
</div>
</div>
<datalist id="datalist-Suits"></datalist>
<datalist id="datalist-SpaceSuits"></datalist>
<datalist id="datalist-LongGuns"></datalist>

View File

@ -667,6 +667,21 @@ function updateInventory() {
const td = document.createElement("td");
td.classList = "text-end text-nowrap";
if (category == "Suits") {
const a = document.createElement("a");
a.href = "#";
a.onclick = () => showSuitInvigorationForm(item);
a.innerHTML = `<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 24 24">
<path d="M15.907 11.998 10.332 9.23a.9.9 0 0 1-.16-.037l-.018-.007v6.554c0 .017.008.034.01.051l2.388-2.974 3.355-.82Z"/>
<path d="m11.463 4.054 5.579 3.323A4.02 4.02 0 0 1 18.525 9c.332.668.47 1.414.398 2.155a3.07 3.07 0 0 1-.745 1.65 3.108 3.108 0 0 1-1.55.951c-.022.007-.045.005-.07.01-.062.03-.126.057-.191.08l-2.72.667-1.992 2.48c-.18.227-.41.409-.67.534.047.034.085.077.137.107a2.05 2.05 0 0 0 1.995.035c.592-.33 2.15-1.201 4.636-2.892l.28-.19c1.328-.895 3.616-2.442 3.967-4.215a9.94 9.94 0 0 0-1.713-4.154 10.027 10.027 0 0 0-3.375-2.989 10.107 10.107 0 0 0-8.802-.418c1.162.287 2.287.704 3.354 1.243Z"/>
<path d="M5.382 17.082v-6.457a3.7 3.7 0 0 1 .45-1.761 3.733 3.733 0 0 1 1.238-1.34 3.915 3.915 0 0 1 3.433-.245c.176.03.347.084.508.161l5.753 2.856c.082.05.161.105.236.165a2.128 2.128 0 0 0-.953-1.455l-5.51-3.284c-1.74-.857-3.906-1.523-5.244-1.097a9.96 9.96 0 0 0-2.5 3.496 9.895 9.895 0 0 0 .283 8.368 9.973 9.973 0 0 0 2.73 3.322 17.161 17.161 0 0 1-.424-2.729Z"/>
<path d="m19.102 16.163-.272.183c-2.557 1.74-4.169 2.64-4.698 2.935a4.083 4.083 0 0 1-2 .53 3.946 3.946 0 0 1-1.983-.535 3.788 3.788 0 0 1-1.36-1.361 3.752 3.752 0 0 1-.51-1.85 1.812 1.812 0 0 1-.043-.26V9.143c0-.024.009-.046.01-.07-.056.02-.11.043-.162.07a1.796 1.796 0 0 0-.787 1.516v6.377a10.67 10.67 0 0 0 1.113 4.27 10.11 10.11 0 0 0 8.505-.53 10.022 10.022 0 0 0 3.282-2.858 9.936 9.936 0 0 0 1.75-3.97 19.615 19.615 0 0 1-2.845 2.216Z"/>
</svg>`;
a.style.textDecoration = "none";
a.title = "";
td.appendChild(a);
}
let maxXP = Math.pow(uniqueLevelCaps[item.ItemType] ?? 30, 2) * 1000;
if (
category != "Suits" &&
@ -2862,3 +2877,118 @@ function handleModularPartsChange(event) {
});
}
}
function showSuitInvigorationForm(suitData) {
document.getElementById("invigoration-oid").value = suitData.ItemId.$oid;
// Auto-fill form with existing data
document.getElementById("invigoration-offensive").value = suitData?.OffensiveUpgrade || "";
document.getElementById("invigoration-defensive").value = suitData?.DefensiveUpgrade || "";
// Handle expiry date
if (suitData?.UpgradesExpiry) {
let expiryDate;
if (suitData.UpgradesExpiry.$date) {
// MongoDB format: { "$date": { "$numberLong": "1752933467151" } }
expiryDate = new Date(parseInt(suitData.UpgradesExpiry.$date.$numberLong));
} else if (typeof suitData.UpgradesExpiry === "number") {
// Timestamp format
expiryDate = new Date(suitData.UpgradesExpiry);
} else if (suitData.UpgradesExpiry instanceof Date) {
// Date object
expiryDate = suitData.UpgradesExpiry;
}
if (expiryDate && !isNaN(expiryDate.getTime())) {
// Format for datetime-local input (YYYY-MM-DDTHH:mm)
const year = expiryDate.getFullYear();
const month = String(expiryDate.getMonth() + 1).padStart(2, "0");
const day = String(expiryDate.getDate()).padStart(2, "0");
const hours = String(expiryDate.getHours()).padStart(2, "0");
const minutes = String(expiryDate.getMinutes()).padStart(2, "0");
document.getElementById("invigoration-expiry").value = `${year}-${month}-${day}T${hours}:${minutes}`;
} else {
document.getElementById("invigoration-expiry").value = "";
}
} else {
document.getElementById("invigoration-expiry").value = "";
}
const form = document.getElementById("editSuitInvigorationForm");
form.style.display = "block";
form.style.position = "fixed";
form.style.top = "50%";
form.style.left = "50%";
form.style.transform = "translate(-50%, -50%)";
form.style.zIndex = "1050";
form.style.width = "400px";
// Add backdrop
const backdrop = document.createElement("div");
backdrop.id = "invigoration-backdrop";
backdrop.style.position = "fixed";
backdrop.style.top = "0";
backdrop.style.left = "0";
backdrop.style.width = "100%";
backdrop.style.height = "100%";
backdrop.style.backgroundColor = "rgba(0, 0, 0, 0.5)";
backdrop.style.zIndex = "1040";
backdrop.onclick = hideSuitInvigorationForm;
document.body.appendChild(backdrop);
}
function hideSuitInvigorationForm() {
document.getElementById("editSuitInvigorationForm").style.display = "none";
const backdrop = document.getElementById("invigoration-backdrop");
if (backdrop) {
backdrop.remove();
}
}
function submitSuitInvigorationUpgrade(event) {
event.preventDefault();
const oid = document.getElementById("invigoration-oid").value;
const offensiveUpgrade = document.getElementById("invigoration-offensive").value;
const defensiveUpgrade = document.getElementById("invigoration-defensive").value;
const expiry = document.getElementById("invigoration-expiry").value;
if (!offensiveUpgrade && !defensiveUpgrade) {
alert("Please select at least one upgrade type.");
return;
}
const data = {
OffensiveUpgrade: offensiveUpgrade,
DefensiveUpgrade: defensiveUpgrade
};
if (expiry) {
data.UpgradesExpiry = new Date(expiry).getTime();
}
editSuitInvigorationUpgrade(oid, data);
hideSuitInvigorationForm();
}
function clearSuitInvigorationUpgrades() {
const oid = document.getElementById("invigoration-oid").value;
editSuitInvigorationUpgrade(oid, null);
hideSuitInvigorationForm();
}
async function editSuitInvigorationUpgrade(oid, data) {
/* data?: {
DefensiveUpgrade: string;
OffensiveUpgrade: string;
UpgradesExpiry?: number;
}*/
$.post({
url: "/custom/editSuitInvigorationUpgrade?" + window.authz,
contentType: "application/json",
data: JSON.stringify({ oid, data })
}).done(function () {
updateInventory();
});
}