This commit is contained in:
parent
2b555a6456
commit
7c3ebad987
@ -3,6 +3,7 @@ import { getDict, getItemName, getString } from "@/src/services/itemDataService"
|
||||
import {
|
||||
ExportArcanes,
|
||||
ExportAvionics,
|
||||
ExportBoosters,
|
||||
ExportCustoms,
|
||||
ExportDrones,
|
||||
ExportGear,
|
||||
@ -55,6 +56,7 @@ interface ItemLists {
|
||||
KubrowPets: ListedItem[];
|
||||
EvolutionProgress: ListedItem[];
|
||||
mods: ListedItem[];
|
||||
Boosters: ListedItem[];
|
||||
}
|
||||
|
||||
const relicQualitySuffixes: Record<TRelicQuality, string> = {
|
||||
@ -86,7 +88,8 @@ const getItemListsController: RequestHandler = (req, response) => {
|
||||
QuestKeys: [],
|
||||
KubrowPets: [],
|
||||
EvolutionProgress: [],
|
||||
mods: []
|
||||
mods: [],
|
||||
Boosters: []
|
||||
};
|
||||
for (const [uniqueName, item] of Object.entries(ExportWarframes)) {
|
||||
res[item.productCategory].push({
|
||||
@ -296,6 +299,13 @@ const getItemListsController: RequestHandler = (req, response) => {
|
||||
});
|
||||
}
|
||||
|
||||
for (const item of Object.values(ExportBoosters)) {
|
||||
res.Boosters.push({
|
||||
uniqueName: item.typeName,
|
||||
name: getString(item.name, lang)
|
||||
});
|
||||
}
|
||||
|
||||
response.json(res);
|
||||
};
|
||||
|
||||
|
37
src/controllers/custom/setBoosterController.ts
Normal file
37
src/controllers/custom/setBoosterController.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
import { RequestHandler } from "express";
|
||||
import { ExportBoosters } from "warframe-public-export-plus";
|
||||
|
||||
const I32_MAX = 0x7fffffff;
|
||||
|
||||
export const setBoosterController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const requests = req.body as { ItemType: string; ExpiryDate: number }[];
|
||||
const inventory = await getInventory(accountId);
|
||||
const boosters = inventory.Boosters;
|
||||
if (
|
||||
requests.some(request => {
|
||||
if (typeof request.ItemType !== "string") return true;
|
||||
if (Object.entries(ExportBoosters).find(([_, item]) => item.typeName === request.ItemType) === undefined)
|
||||
return true;
|
||||
if (typeof request.ExpiryDate !== "number") return true;
|
||||
if (request.ExpiryDate < 0 || request.ExpiryDate > I32_MAX) return true;
|
||||
return false;
|
||||
})
|
||||
) {
|
||||
res.status(400).send("Invalid ItemType provided.");
|
||||
return;
|
||||
}
|
||||
// Remove if ExpiryDate lower than current time?
|
||||
for (const { ItemType, ExpiryDate } of requests) {
|
||||
const boosterItem = boosters.find(item => item.ItemType === ItemType);
|
||||
if (boosterItem) {
|
||||
boosterItem.ExpiryDate = ExpiryDate;
|
||||
} else {
|
||||
boosters.push({ ItemType, ExpiryDate });
|
||||
}
|
||||
}
|
||||
await inventory.save();
|
||||
res.end();
|
||||
};
|
@ -23,6 +23,7 @@ import { setEvolutionProgressController } from "@/src/controllers/custom/setEvol
|
||||
|
||||
import { getConfigDataController } from "@/src/controllers/custom/getConfigDataController";
|
||||
import { updateConfigDataController } from "@/src/controllers/custom/updateConfigDataController";
|
||||
import { setBoosterController } from "../controllers/custom/setBoosterController";
|
||||
|
||||
const customRouter = express.Router();
|
||||
|
||||
@ -46,6 +47,7 @@ customRouter.post("/addXp", addXpController);
|
||||
customRouter.post("/import", importController);
|
||||
customRouter.post("/manageQuests", manageQuestsController);
|
||||
customRouter.post("/setEvolutionProgress", setEvolutionProgressController);
|
||||
customRouter.post("/setBooster", setBoosterController);
|
||||
|
||||
customRouter.get("/config", getConfigDataController);
|
||||
customRouter.post("/config", updateConfigDataController);
|
||||
|
@ -416,6 +416,20 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="card mb-3" style="height: 400px;">
|
||||
<h5 class="card-header" data-loc="inventory_Boosters"></h5>
|
||||
<div class="card-body overflow-auto">
|
||||
<form class="input-group mb-3" onsubmit="doAcquireBoosters();return false;">
|
||||
<input class="form-control" id="acquire-type-Boosters" list="datalist-Boosters" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
<table class="table table-hover w-100">
|
||||
<tbody id="Boosters-list"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mb-3">
|
||||
<h5 class="card-header" data-loc="general_bulkActions"></h5>
|
||||
@ -804,6 +818,7 @@
|
||||
<datalist id="datalist-ModularParts-CATBROW_MUTAGEN"></datalist>
|
||||
<datalist id="datalist-ModularParts-KUBROW_ANTIGEN"></datalist>
|
||||
<datalist id="datalist-ModularParts-KUBROW_MUTAGEN"></datalist>
|
||||
<datalist id="datalist-Boosters"></datalist>
|
||||
<script src="/webui/libs/jquery-3.6.0.min.js"></script>
|
||||
<script src="/webui/libs/whirlpool-js.min.js"></script>
|
||||
<script src="/webui/libs/single.js"></script>
|
||||
|
@ -1011,6 +1011,78 @@ function updateInventory() {
|
||||
}
|
||||
}
|
||||
document.getElementById("changeSyndicate").value = data.SupportedSyndicate ?? "";
|
||||
|
||||
|
||||
document.getElementById("Boosters-list").innerHTML = "";
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
data.Boosters.forEach(({ItemType, ExpiryDate}) => {
|
||||
if (ExpiryDate < now) {
|
||||
// Booster has expired, skip it
|
||||
return;
|
||||
}
|
||||
const tr = document.createElement("tr");
|
||||
{
|
||||
const td = document.createElement("td");
|
||||
td.textContent = itemMap[ItemType]?.name ?? ItemType;
|
||||
tr.appendChild(td);
|
||||
}
|
||||
{
|
||||
const td = document.createElement("td");
|
||||
td.classList = "text-end text-nowrap";
|
||||
const timeString = formatDatetime("%Y-%m-%d %H:%M:%s", ExpiryDate * 1000);
|
||||
const inlineForm = document.createElement("form");
|
||||
const input = document.createElement("input");
|
||||
const a = document.createElement("a");
|
||||
|
||||
a.href = "#";
|
||||
a.onclick = (event)=>{
|
||||
event.preventDefault();
|
||||
if (inlineForm.style.display === "none") {
|
||||
inlineForm.style.display = "inline";
|
||||
input.value = timeString;
|
||||
a.style.display = "none";
|
||||
input.focus();
|
||||
} else {
|
||||
inlineForm.style.display = "none";
|
||||
a.style.display = "inline";
|
||||
input.value = "";
|
||||
}
|
||||
};
|
||||
a.textContent = timeString;
|
||||
a.title = loc("code_changeExpiry");
|
||||
a.classList.add("text-decoration-none");
|
||||
td.appendChild(a);
|
||||
|
||||
const submit = ()=>{
|
||||
if (doChangeBoosterExpiry(ItemType, input.value)){
|
||||
inlineForm.style.display = "none";
|
||||
input.value = "";
|
||||
a.style.display = "inline";
|
||||
}
|
||||
};
|
||||
|
||||
inlineForm.style.display = "none";
|
||||
inlineForm.onsubmit = function (event) {
|
||||
event.preventDefault();
|
||||
submit();
|
||||
};
|
||||
input.type = "datetime-local";
|
||||
input.classList.add("form-control");
|
||||
input.classList.add("form-control-sm");
|
||||
input.value = timeString;
|
||||
input.onblur = function () {
|
||||
if (inlineForm.style.display === "inline") {
|
||||
submit();
|
||||
}
|
||||
}
|
||||
inlineForm.appendChild(input);
|
||||
|
||||
td.appendChild(inlineForm);
|
||||
|
||||
tr.appendChild(td);
|
||||
}
|
||||
document.getElementById("Boosters-list").appendChild(tr);
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -2027,3 +2099,71 @@ function handleModularSelection(category) {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function setBooster(ItemType, ExpiryDate) {
|
||||
revalidateAuthz(() => {
|
||||
$.post({
|
||||
url: "/custom/setBooster?" + window.authz,
|
||||
contentType: "application/json",
|
||||
data: JSON.stringify([{
|
||||
ItemType,
|
||||
ExpiryDate
|
||||
}])
|
||||
}).done(function () {
|
||||
updateInventory();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function doAcquireBoosters() {
|
||||
const uniqueName = getKey(document.getElementById("acquire-type-Boosters"));
|
||||
if (!uniqueName) {
|
||||
$("#acquire-type-Boosters").addClass("is-invalid").focus();
|
||||
return;
|
||||
}
|
||||
const ExpiryDate = (Date.now() / 1000) + 3 * 24 * 60 * 60; // default 3 days
|
||||
setBooster(uniqueName, ExpiryDate);
|
||||
}
|
||||
|
||||
function doChangeBoosterExpiry(ItemType, ExpiryDateInput) {
|
||||
console.log("Changing booster expiry for", ItemType, "to", ExpiryDateInput);
|
||||
// cast local datetime string to unix timestamp
|
||||
const ExpiryDate = new Date(ExpiryDateInput).getTime() / 1000;
|
||||
if (isNaN(ExpiryDate)) {
|
||||
$("#expiry-date-" + ItemType).addClass("is-invalid").focus();
|
||||
return false;
|
||||
}
|
||||
setBooster(ItemType, ExpiryDate);
|
||||
return true;
|
||||
}
|
||||
|
||||
function formatDatetime(fmt, date) {
|
||||
if (typeof date === 'number') date = new Date(date);
|
||||
return fmt.replace(/(%[yY]|%m|%[Dd]|%H|%h|%M|%[Ss]|%[Pp])/g, match => {
|
||||
switch (match) {
|
||||
case '%Y':
|
||||
return date.getFullYear().toString();
|
||||
case '%y':
|
||||
return date.getFullYear().toString().slice(-2);
|
||||
case '%m':
|
||||
return (date.getMonth() + 1).toString().padStart(2, '0');
|
||||
case '%D':
|
||||
case '%d':
|
||||
return date.getDate().toString().padStart(2, '0');
|
||||
case '%H':
|
||||
return date.getHours().toString().padStart(2, '0');
|
||||
case '%h':
|
||||
return (date.getHours() % 12).toString().padStart(2, '0');
|
||||
case '%M':
|
||||
return date.getMinutes().toString().padStart(2, '0');
|
||||
case '%S':
|
||||
case '%s':
|
||||
return date.getSeconds().toString().padStart(2, '0');
|
||||
case '%P':
|
||||
case '%p':
|
||||
return date.getHours() < 12 ? 'am' : 'pm';
|
||||
default:
|
||||
return match;
|
||||
}
|
||||
})
|
||||
}
|
@ -98,6 +98,7 @@ dict = {
|
||||
inventory_bulkRankUpSentinels: `Alle Wächter auf Max. Rang`,
|
||||
inventory_bulkRankUpSentinelWeapons: `Alle Wächter-Waffen auf Max. Rang`,
|
||||
inventory_bulkRankUpEvolutionProgress: `Alle Incarnon-Entwicklungsfortschritte auf Max. Rang`,
|
||||
inventory_Boosters: `[UNTRANSLATED] Boosters`,
|
||||
|
||||
quests_list: `Quests`,
|
||||
quests_completeAll: `Alle Quests abschließen`,
|
||||
|
@ -97,6 +97,7 @@ dict = {
|
||||
inventory_bulkRankUpSentinels: `Max Rank All Sentinels`,
|
||||
inventory_bulkRankUpSentinelWeapons: `Max Rank All Sentinel Weapons`,
|
||||
inventory_bulkRankUpEvolutionProgress: `Max Rank All Incarnon Evolution Progress`,
|
||||
inventory_Boosters: `Boosters`,
|
||||
|
||||
quests_list: `Quests`,
|
||||
quests_completeAll: `Complete All Quests`,
|
||||
|
@ -98,6 +98,7 @@ dict = {
|
||||
inventory_bulkRankUpSentinels: `Maximizar rango de todos los centinelas`,
|
||||
inventory_bulkRankUpSentinelWeapons: `Maximizar rango de todas las armas de centinela`,
|
||||
inventory_bulkRankUpEvolutionProgress: `Maximizar todo el progreso de evolución Incarnon`,
|
||||
inventory_Boosters: `[UNTRANSLATED] Boosters`,
|
||||
|
||||
quests_list: `Misiones`,
|
||||
quests_completeAll: `Completar todas las misiones`,
|
||||
|
@ -98,6 +98,7 @@ dict = {
|
||||
inventory_bulkRankUpSentinels: `Toutes les Sentinelles au rang max`,
|
||||
inventory_bulkRankUpSentinelWeapons: `Toutes les armes de Sentinelles au rang max`,
|
||||
inventory_bulkRankUpEvolutionProgress: `Toutes les évolutions Incarnon au rang max`,
|
||||
inventory_Boosters: `[UNTRANSLATED] Boosters`,
|
||||
|
||||
quests_list: `Quêtes`,
|
||||
quests_completeAll: `Compléter toutes les quêtes`,
|
||||
|
@ -98,6 +98,7 @@ dict = {
|
||||
inventory_bulkRankUpSentinels: `Максимальный ранг всех стражей`,
|
||||
inventory_bulkRankUpSentinelWeapons: `Максимальный ранг всего оружия стражей`,
|
||||
inventory_bulkRankUpEvolutionProgress: `Максимальный ранг всех эволюций Инкарнонов`,
|
||||
inventory_Boosters: `[UNTRANSLATED] Boosters`,
|
||||
|
||||
quests_list: `Квесты`,
|
||||
quests_completeAll: `Завершить все квесты`,
|
||||
|
@ -98,6 +98,7 @@ dict = {
|
||||
inventory_bulkRankUpSentinels: `所有守护升满级`,
|
||||
inventory_bulkRankUpSentinelWeapons: `所有守护武器升满级`,
|
||||
inventory_bulkRankUpEvolutionProgress: `所有灵化之源最大等级`,
|
||||
inventory_Boosters: `加成器`,
|
||||
|
||||
quests_list: `任务`,
|
||||
quests_completeAll: `完成所有任务`,
|
||||
|
Loading…
x
Reference in New Issue
Block a user