feat(webui): edit suit invigorations #2478

Merged
Sainan merged 12 commits from nyaoouo/SpaceNinjaServer:ImplEditSuitInvigorationUpgradeController into main 2025-07-14 20:33:38 -07:00
2 changed files with 69 additions and 107 deletions
Showing only changes of commit 8d144188f7 - Show all commits

View File

@ -455,62 +455,6 @@
</div> </div>
</div> </div>
</div> </div>
<div id="editSuitInvigoration" class="modal-overlay" style="display: none;">
<div id="editSuitInvigorationOverlay" class="modal-overlay" onclick="hideSuitInvigorationForm()"></div>
<div id="editSuitInvigorationForm" class="card modal-form">
<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>
</div>
</div> </div>
<div id="detailedView-route" data-route="/webui/detailedView" data-title="Inventory | OpenWF WebUI"> <div id="detailedView-route" data-route="/webui/detailedView" data-title="Inventory | OpenWF WebUI">
<h3 id="detailedView-loading" class="mb-0" data-loc="general_loading"></h3> <h3 id="detailedView-loading" class="mb-0" data-loc="general_loading"></h3>
@ -532,6 +476,53 @@
<table class="table table-hover w-100"> <table class="table table-hover w-100">
<tbody id="crystals-list"></tbody> <tbody id="crystals-list"></tbody>
</table> </table>
<form onsubmit="submitSuitInvigorationUpgrade(event)">
Sainan marked this conversation as resolved Outdated

Why is this inside of the archon crystals card and not its own card?

Why is this inside of the archon crystals card and not its own card?

Because I didn't realize that you used path route first and then only controlled visibility based on url params...

Because I didn't realize that you used path route first and then only controlled visibility based on url params...
<input type="hidden" id="dv-invigoration-oid" />
Sainan marked this conversation as resolved Outdated

The oid is already in the query string. Be consistent.

The oid is already in the query string. Be consistent.
<div class="mb-3">
<label for="invigoration-offensive" class="form-label">Offensive Upgrade</label>
Sainan marked this conversation as resolved
Review

All your strings should be added to the translation system. And let's not lowercase a title? 😒

All your strings should be added to the translation system. And let's not lowercase a title? 😒
Review

because i just use my mobile phone to edit it =_=...

because i just use my mobile phone to edit it =_=...
Review

Try coding on a PC. :)

Try coding on a PC. :)
<select class="form-select" id="dv-invigoration-offensive">
<option value="">None</option>
Sainan marked this conversation as resolved
Review

There are a few more strings here...

There are a few more strings here...
Review

I don't know the exact translation of the attributes, so I'll just estimate it based on the key.

I don't know the exact translation of the attributes, so I'll just estimate it based on the key.
<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="dv-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="dv-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-danger" onclick="clearSuitInvigorationUpgrades()">Clear Upgrades</button>
</div>
</form>
</div> </div>
</div> </div>
<div id="modularParts-card" class="card mb-3 d-none"> <div id="modularParts-card" class="card mb-3 d-none">

View File

@ -667,21 +667,6 @@ function updateInventory() {
const td = document.createElement("td"); const td = document.createElement("td");
td.classList = "text-end text-nowrap"; 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; let maxXP = Math.pow(uniqueLevelCaps[item.ItemType] ?? 30, 2) * 1000;
if ( if (
category != "Suits" && category != "Suits" &&
@ -1245,6 +1230,12 @@ function updateInventory() {
} }
document.getElementById("crystals-list").appendChild(tr); document.getElementById("crystals-list").appendChild(tr);
}); });
const { OffensiveUpgrade, DefensiveUpgrade, UpgradesExpiry } =
suitInvigorationUpgradeData(item);
document.getElementById("dv-invigoration-oid").value = oid;
nyaoouo marked this conversation as resolved Outdated

Unused?

Unused?
document.getElementById("dv-invigoration-offensive").value = OffensiveUpgrade;
document.getElementById("dv-invigoration-defensive").value = DefensiveUpgrade;
document.getElementById("dv-invigoration-expiry").value = UpgradesExpiry;
} else if (["LongGuns", "Pistols", "Melee", "SpaceGuns", "SpaceMelee"].includes(category)) { } else if (["LongGuns", "Pistols", "Melee", "SpaceGuns", "SpaceMelee"].includes(category)) {
document.getElementById("valenceBonus-card").classList.remove("d-none"); document.getElementById("valenceBonus-card").classList.remove("d-none");
document.getElementById("valenceBonus-innateDamage").value = ""; document.getElementById("valenceBonus-innateDamage").value = "";
@ -2877,58 +2868,41 @@ function handleModularPartsChange(event) {
}); });
} }
} }
function suitInvigorationUpgradeData(suitData) {
function showSuitInvigorationForm(suitData) { let expiryDate = "";
document.getElementById("invigoration-oid").value = suitData.ItemId.$oid; if (suitData.UpgradesExpiry) {
// 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) { if (suitData.UpgradesExpiry.$date) {
// MongoDB format: { "$date": { "$numberLong": "1752933467151" } }
expiryDate = new Date(parseInt(suitData.UpgradesExpiry.$date.$numberLong)); expiryDate = new Date(parseInt(suitData.UpgradesExpiry.$date.$numberLong));
} else if (typeof suitData.UpgradesExpiry === "number") { } else if (typeof suitData.UpgradesExpiry === "number") {
// Timestamp format
expiryDate = new Date(suitData.UpgradesExpiry); expiryDate = new Date(suitData.UpgradesExpiry);
} else if (suitData.UpgradesExpiry instanceof Date) { } else if (suitData.UpgradesExpiry instanceof Date) {
// Date object
expiryDate = suitData.UpgradesExpiry; expiryDate = suitData.UpgradesExpiry;
} }
if (expiryDate && !isNaN(expiryDate.getTime())) { if (expiryDate && !isNaN(expiryDate.getTime())) {
// Format for datetime-local input (YYYY-MM-DDTHH:mm)
const year = expiryDate.getFullYear(); const year = expiryDate.getFullYear();
const month = String(expiryDate.getMonth() + 1).padStart(2, "0"); const month = String(expiryDate.getMonth() + 1).padStart(2, "0");
const day = String(expiryDate.getDate()).padStart(2, "0"); const day = String(expiryDate.getDate()).padStart(2, "0");
const hours = String(expiryDate.getHours()).padStart(2, "0"); const hours = String(expiryDate.getHours()).padStart(2, "0");
const minutes = String(expiryDate.getMinutes()).padStart(2, "0"); const minutes = String(expiryDate.getMinutes()).padStart(2, "0");
expiryDate = `${year}-${month}-${day}T${hours}:${minutes}`;
document.getElementById("invigoration-expiry").value = `${year}-${month}-${day}T${hours}:${minutes}`;
} else { } else {
document.getElementById("invigoration-expiry").value = ""; expiryDate = "";
} }
} else {
document.getElementById("invigoration-expiry").value = "";
} }
return {
document.getElementById("editSuitInvigoration").style.display = "block"; oid: suitData.ItemId.$oid,
} OffensiveUpgrade: suitData.OffensiveUpgrade || "",
DefensiveUpgrade: suitData.DefensiveUpgrade || "",
function hideSuitInvigorationForm() { UpgradesExpiry: expiryDate
document.getElementById("editSuitInvigoration").style.display = "none"; };
} }
function submitSuitInvigorationUpgrade(event) { function submitSuitInvigorationUpgrade(event) {
event.preventDefault(); event.preventDefault();
const oid = new URLSearchParams(window.location.search).get("itemId");
const oid = document.getElementById("invigoration-oid").value; const offensiveUpgrade = document.getElementById("dv-invigoration-offensive").value;
const offensiveUpgrade = document.getElementById("invigoration-offensive").value; const defensiveUpgrade = document.getElementById("dv-invigoration-defensive").value;
const defensiveUpgrade = document.getElementById("invigoration-defensive").value; const expiry = document.getElementById("dv-invigoration-expiry").value;
const expiry = document.getElementById("invigoration-expiry").value;
if (!offensiveUpgrade && !defensiveUpgrade) { if (!offensiveUpgrade && !defensiveUpgrade) {
alert("Please select at least one upgrade type."); alert("Please select at least one upgrade type.");
@ -2945,13 +2919,10 @@ function submitSuitInvigorationUpgrade(event) {
} }
editSuitInvigorationUpgrade(oid, data); editSuitInvigorationUpgrade(oid, data);
hideSuitInvigorationForm();
} }
function clearSuitInvigorationUpgrades() { function clearSuitInvigorationUpgrades() {
const oid = document.getElementById("invigoration-oid").value; editSuitInvigorationUpgrade(new URLSearchParams(window.location.search).get("itemId"), null);
Sainan marked this conversation as resolved Outdated

If you need godawful custom CSS, put it in the CSS file.

If you need godawful custom CSS, put it in the CSS file.
editSuitInvigorationUpgrade(oid, null);
hideSuitInvigorationForm();
} }
async function editSuitInvigorationUpgrade(oid, data) { async function editSuitInvigorationUpgrade(oid, data) {