- depositHandler: handleDepositInstruction + handleDepositSelectWallet use editOrSendCallback (photo-safe fallback) — fixes 'no text in the message to edit' 400 - resetUserContext deletes lastInlineMessageId (stale inline menus cleaned on Reply Keyboard nav) - showProducts/showProfile/showBalance/showPurchases store lastInlineMessageId on sendMessage - answerCallbackQuery verified before dispatch (v1.2.4) - 48 tests pass; bump v1.2.5
141 lines
7.8 KiB
Plaintext
141 lines
7.8 KiB
Plaintext
<aside class="app-sidebar d-flex flex-column">
|
|
|
|
<%- include('app-logo') %>
|
|
|
|
<%- include('app-menu-filter') %>
|
|
|
|
<nav id="js-primary-nav" class="primary-nav flex-grow-1 custom-scroll" aria-label="Primary">
|
|
|
|
<%- include('generated-navigation') %>
|
|
|
|
<div class="no-results-msg pt-3 info-container">
|
|
<h6 class="mb-1"> No menu items found.</h6>
|
|
<p class="fs-sm">Try searching with different keywords.</p>
|
|
<div class="d-flex align-items-center gap-1 fs-xs fw-500 font-style-italic">
|
|
<kbd class="kbd-key">
|
|
<svg width="15" height="15" aria-label="Escape key" role="img">
|
|
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.2">
|
|
<path d="M13.6167 8.936c-.1065.3583-.6883.962-1.4875.962-.7993 0-1.653-.9165-1.653-2.1258v-.5678c0-1.2548.7896-2.1016 1.653-2.1016.8634 0 1.3601.4778 1.4875 1.0724M9 6c-.1352-.4735-.7506-.9219-1.46-.8972-.7092.0246-1.344.57-1.344 1.2166s.4198.8812 1.3445.9805C8.465 7.3992 8.968 7.9337 9 8.5c.032.5663-.454 1.398-1.4595 1.398C6.6593 9.898 6 9 5.963 8.4851m-1.4748.5368c-.2635.5941-.8099.876-1.5443.876s-1.7073-.6248-1.7073-2.204v-.4603c0-1.0416.721-2.131 1.7073-2.131.9864 0 1.6425 1.031 1.5443 2.2492h-2.956"></path>
|
|
</g>
|
|
</svg>
|
|
</kbd> to reset
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<div class="nav-footer">
|
|
<div class="d-flex align-items-center gap-2" role="button" data-bs-toggle="modal" data-bs-target="#versionModal" style="cursor:pointer;" title="View version history">
|
|
<svg class="sa-icon sa-thin">
|
|
<use href="/icons/sprite.svg#tag"></use>
|
|
</svg>
|
|
<span class="fs-xs opacity-70">v1.2.5</span>
|
|
</div>
|
|
</div>
|
|
</aside>
|
|
|
|
<!-- Version History Modal -->
|
|
<div class="modal fade" id="versionModal" tabindex="-1" aria-labelledby="versionModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-scrollable">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="versionModalLabel">Version History</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="alert alert-info mb-3">
|
|
<strong>Current:</strong> v1.2.5 · 2026-08-05
|
|
</div>
|
|
|
|
<h6 class="fw-bold mb-2">v1.2.5 <span class="text-muted fs-sm">— 2026-08-05</span></h6>
|
|
<ul class="small mb-3">
|
|
<li><span class="badge bg-info">refactor</span> Removed deposit amount-selection step; deposit_wallet_ now goes directly to Mercuryo instructions</li>
|
|
<li><span class="badge bg-primary">feat</span> Updated Mercuryo button text to include VISA/Mastercard branding in all locales</li>
|
|
<li><span class="badge bg-primary">feat</span> Added deposit_important5 note about Mercuryo authorization limits and top-up reserve</li>
|
|
</ul>
|
|
|
|
<h6 class="fw-bold mb-2">v1.2.0 <span class="text-muted fs-sm">— 2026-07-08</span></h6>
|
|
<ul class="small mb-3">
|
|
<li><span class="badge bg-warning text-dark">fix</span> Disabled CSRF checks in admin panel for Tor / onion zone compatibility</li>
|
|
<li><span class="badge bg-warning text-dark">fix</span> Fixed "Invalid wallet type" error in Telegram bot purchase flow</li>
|
|
<li><span class="badge bg-primary">feat</span> Added version history modal in admin sidebar</li>
|
|
</ul>
|
|
|
|
<h6 class="fw-bold mb-2">v1.1.0 <span class="text-muted fs-sm">— 2026-07-02</span></h6>
|
|
<ul class="small mb-3">
|
|
<li><span class="badge bg-primary">feat</span> Mercuryo gateway, crypto QR deposit, mono products, wallet auto-refresh</li>
|
|
<li><span class="badge bg-warning text-dark">fix</span> CSRF cookie sameSite=false for Tor, auth cookie fix, async handlers</li>
|
|
<li><span class="badge bg-primary">feat</span> Draggable dashboard panels + business KPI redesign</li>
|
|
<li><span class="badge bg-primary">feat</span> SmartAdmin template redesign + security hardening</li>
|
|
</ul>
|
|
|
|
<h6 class="fw-bold mb-2">v1.0.0 <span class="text-muted fs-sm">— 2026-06-24</span></h6>
|
|
<ul class="small mb-0">
|
|
<li><span class="badge bg-primary">feat</span> Initial release — Telegram shop bot with admin panel</li>
|
|
<li><span class="badge bg-primary">feat</span> Crypto wallets (BTC, LTC, ETH, USDT, USDC)</li>
|
|
<li><span class="badge bg-primary">feat</span> Product catalog with locations, categories, subcategories</li>
|
|
<li><span class="badge bg-primary">feat</span> Purchase system with hidden content delivery</li>
|
|
<li><span class="badge bg-primary">feat</span> Admin panel with dashboard, wallets, users, purchases, audit log</li>
|
|
<li><span class="badge bg-primary">feat</span> Tor proxy support (.onion access)</li>
|
|
<li><span class="badge bg-primary">feat</span> i18n localization (en/es/de)</li>
|
|
</ul>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<span class="text-muted small">Update version in <code>VERSION.md</code> + <code>app-sidebar.ejs</code></span>
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="backdrop" data-action="toggle-swap" data-toggleclass="app-mobile-menu-open"></div>
|
|
|
|
|
|
<!-- Sidebar Link Active Script -->
|
|
<script>
|
|
const sideNavMenu = document.getElementById("js-nav-menu");
|
|
const currentUrl = window.location.href.split(/[?#]/)[0];
|
|
const allLinks = sideNavMenu.querySelectorAll("a");
|
|
const allCollapses = sideNavMenu.querySelectorAll("li [aria-expanded='true']");
|
|
|
|
sideNavMenu.querySelectorAll("li .has-ul").forEach((toggle) => { toggle.addEventListener("click", (e) => e.preventDefault()); });
|
|
|
|
allCollapses.forEach((collapse) => {
|
|
collapse.addEventListener("show.bs.collapse", (event) => {
|
|
const currentCollapse = event.target;
|
|
const ancestors = [];
|
|
let el = currentCollapse.parentElement;
|
|
while (el && el !== sideNavMenu) {
|
|
if (el.classList.contains("collapse")) {
|
|
ancestors.push(el);
|
|
}
|
|
el = el.parentElement;
|
|
}
|
|
allCollapses.forEach((other) => {
|
|
if (other !== currentCollapse && !ancestors.includes(other)) {
|
|
new bootstrap.Collapse(other, { toggle: false }).hide();
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
allLinks.forEach((link) => {
|
|
if (link.href === currentUrl) {
|
|
link.classList.add("active");
|
|
let currentElement = link.closest("li");
|
|
while (currentElement && currentElement !== sideNavMenu) {
|
|
currentElement.classList.add("active");
|
|
const parentCollapse = currentElement.closest("[role='menu']");
|
|
if (parentCollapse) {
|
|
new bootstrap.Collapse(parentCollapse, { toggle: false }).show();
|
|
const collapseParentLi = parentCollapse.closest("li");
|
|
if (collapseParentLi) {
|
|
collapseParentLi.classList.add("active");
|
|
}
|
|
currentElement = collapseParentLi;
|
|
} else {
|
|
currentElement = currentElement.parentElement;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
</script> |