Version 1.05b - see release notes published on Q-Mintership forum in General room for details. Many fixes and new features added.

This commit is contained in:
2025-01-29 19:12:30 -08:00
parent 5a35fb0d07
commit 021c99c119
8 changed files with 586 additions and 384 deletions

View File

@@ -1,121 +1,134 @@
let currentMinterToolPage = 'overview'; // Track the current page
// Load latest state for admin verification
async function verifyMinterAdminState() {
const minterGroupAdmins = await fetchMinterGroupAdmins();
return minterGroupAdmins.members.some(admin => admin.member === userState.accountAddress && admin.isAdmin);
}
async function loadMinterAdminToolsPage() {
const loadMinterAdminToolsPage = async () => {
// Remove all body content except for menu elements
const bodyChildren = document.body.children;
for (let i = bodyChildren.length - 1; i >= 0; i--) {
const child = bodyChildren[i];
if (!child.classList.contains('menu')) {
child.remove();
child.remove()
}
}
const avatarUrl = `/arbitrary/THUMBNAIL/${userState.accountName}/qortal_avatar`;
const avatarUrl = `/arbitrary/THUMBNAIL/${userState.accountName}/qortal_avatar`
// Set the background image directly from a file
const mainContent = document.createElement('div');
const mainContent = document.createElement('div')
// In your 'AdminTools' code
mainContent.innerHTML = `
<div class="tools-main mbr-parallax-background cid-ttRnlSkg2R">
<div class="tools-header" style="color: white; display: flex; flex-direction: column; justify-content: center; align-items: center; padding: 10px;">
<div> <h1 style="font-size: 50px; margin: 0;">MINTER ADMIN TOOLS </h1><a style="color: red;">Under Construction...</a></div>
<div class="user-info" style="border: 1px solid lightblue; padding: 5px; color: lightblue; display: flex; align-items: center; justify-content: center; ">
<img src="${avatarUrl}" alt="User Avatar" class="user-avatar" style="width: 50px; height: 50px; border-radius: 50%; margin-right: 10px;">
<span>${userState.accountName || 'Guest'}</span>
</div>
<div><h2>COMING SOON...</h2></div>
<div>
<p>This page will have functionality to assist the Minter Admins in performing their duties. It will display all pending transactions (of any kind they can approve/deny) along with that ability. It can also be utilized to obtain more in-depth information about existing accounts.</p>
<p> The page will be getting a significant overhaul in the near(ish) future, as the MINTER group is now owned by null, and we are past the 'temporary state' we were in for much longer than planned.</p>
</div>
<div class="tools-main mbr-parallax-background cid-ttRnlSkg2R">
<div class="tools-header" style="color: white; display: flex; flex-direction: column; justify-content: center; align-items: center; padding: 10px;">
<div><h1 style="font-size: 50px; margin: 0;">Admin Tools</h1></div>
<div class="user-info" style="border: 1px solid lightblue; padding: 5px; color: lightblue; display: flex; align-items: center; justify-content: center;">
<img src="${avatarUrl}" alt="User Avatar" class="user-avatar" style="width: 50px; height: 50px; border-radius: 50%; margin-right: 10px;">
<span>${userState.accountName || 'Guest'}</span>
</div>
<div id="tools-submenu" class="tools-submenu">
<div class="tools-buttons">
<button id="display-pending" class="tools-button">Display Pending Approval Transactions</button>
<button id="create-group-invite" class="tools-button">Create Pending Group Invite</button>
<button id="create-promotion" class="tools-button">Create Pending Promotion</button>
</div>
<div id="tools-window" class="tools-window"></div>
<div><h2>Welcome to Admin Tools</h2></div>
<div>
<p>On this page you will find admin functionality for the Q-Mintership App. Including the 'blockList' for blocking comments from certain names, and manual creation of invite transactions.</p>
<p>More features will be added as time goes on. This is the start of the functionality here.</p>
</div>
</div>
`;
document.body.appendChild(mainContent);
<div id="tools-submenu" class="tools-submenu">
<div class="tools-buttons" style="display: flex; gap: 1em; justify-content: center;">
<button id="toggle-blocklist-button" class="publish-card-button">Add/Remove blockedUsers</button>
<button id="create-group-invite" class="publish-card-button">Create Pending Group Invite</button>
</div>
<div id="tools-window" class="tools-window" style="margin-top: 2em;">
<div id="blocklist-container" class="blocklist-form" style="display: none;">
<h3 style="margin-top: 0;">Comment Block List</h3>
<div id="blocklist-display" class="blocklist-display" style="margin-bottom: 1em;"></div>
<input
type="text"
id="blocklist-input"
class="blocklist-input"
placeholder="Enter name to block/unblock"
style="margin-bottom: 1em;"
/>
<div class="blocklist-button-container publish-card-form">
<button id="blocklist-add-button" class="publish-card-button">Add</button>
<button id="blocklist-remove-button" class="publish-card-button">Remove</button>
</div>
</div>
</div>
</div>
</div>
`
document.body.appendChild(mainContent)
addToolsPageEventListeners();
addToolsPageEventListeners()
}
function addToolsPageEventListeners() {
document.getElementById("display-pending").addEventListener("click", async () => {
await displayPendingApprovals();
});
document.getElementById("toggle-blocklist-button").addEventListener("click", async () => {
const container = document.getElementById("blocklist-container")
// toggle show/hide
container.style.display = (container.style.display === "none" ? "flex" : "none")
// if showing, load the block list
if (container.style.display === "flex") {
const currentBlockList = await fetchBlockList()
displayBlockList(currentBlockList)
}
})
document.getElementById("create-group-invite").addEventListener("click", async () => {
createPendingGroupInvite();
});
document.getElementById("blocklist-add-button").addEventListener("click", async () => {
const blocklistInput = document.getElementById("blocklist-input")
const nameToAdd = blocklistInput.value.trim()
if (!nameToAdd) return
// fetch existing
const currentBlockList = await fetchBlockList()
// add if not already in list
if (!currentBlockList.includes(nameToAdd)) {
currentBlockList.push(nameToAdd)
}
// publish updated
await publishBlockList(currentBlockList)
displayBlockList(currentBlockList)
blocklistInput.value = ""
alert(`"${nameToAdd}" added to the block list!`)
})
// Remove
document.getElementById("blocklist-remove-button").addEventListener("click", async () => {
const blocklistInput = document.getElementById("blocklist-input")
const nameToRemove = blocklistInput.value.trim()
if (!nameToRemove) return
// fetch existing
let currentBlockList = await fetchBlockList()
// remove if present
currentBlockList = currentBlockList.filter(name => name !== nameToRemove)
// publish updated
await publishBlockList(currentBlockList)
displayBlockList(currentBlockList)
blocklistInput.value = ""
alert(`"${nameToRemove}" removed from the block list (if it was present).`)
})
document.getElementById("create-promotion").addEventListener("click", async () => {
createPendingPromotion();
});
}
// Fetch and display pending approvals
async function displayPendingApprovals() {
console.log("Fetching pending approval transactions...");
const response = await qortalRequest({
action: "SEARCH_TRANSACTIONS",
txGroupId: 694,
txType: [
"ADD_GROUP_ADMIN",
"GROUP_INVITE"
],
confirmationStatus: "UNCONFIRMED",
limit: 0,
offset: 0,
reverse: false
});
console.log("Fetched pending approvals: ", response);
const toolsWindow = document.getElementById('tools-window');
if (response && response.length > 0) {
toolsWindow.innerHTML = response.map(tx => `
<div class="message-item" style="border: 1px solid lightblue; padding: 10px; margin-bottom: 10px;">
<p><strong>Transaction Type:</strong> ${tx.type}</p>
<p><strong>Amount:</strong> ${tx.amount}</p>
<p><strong>Creator Address:</strong> ${tx.creatorAddress}</p>
<p><strong>Recipient:</strong> ${tx.recipient}</p>
<p><strong>Timestamp:</strong> ${new Date(tx.timestamp).toLocaleString()}</p>
<button onclick="approveTransaction('${tx.signature}')">Approve</button>
</div>
`).join('');
} else {
toolsWindow.innerHTML = '<div class="message-item" style="border: 1px solid lightblue; padding: 10px; margin-bottom: 10px;"><p>No pending approvals found.</p></div>';
const displayBlockList = (blockedNames) => {
const blocklistDisplay = document.getElementById("blocklist-display")
if (!blockedNames || blockedNames.length === 0) {
blocklistDisplay.innerHTML = "<p>No blocked users currently.</p>"
return
}
blocklistDisplay.innerHTML = `
<ul>
${blockedNames.map(name => `<li>${name}</li>`).join("")}
</ul>
`
}
// Placeholder function to create a pending group invite
async function createPendingGroupInvite() {
console.log("Creating a pending group invite...");
// Placeholder code for creating a pending group invite
alert('Pending group invite created (placeholder).');
}
// Placeholder function to create a pending promotion
async function createPendingPromotion() {
console.log("Creating a pending promotion...");
// Placeholder code for creating a pending promotion
alert('Pending promotion created (placeholder).');
}
// Placeholder function for approving a transaction
function approveTransaction(signature) {
console.log("Approving transaction with signature: ", signature);
// Placeholder code for approving transaction
alert(`Transaction with signature ${signature} approved (placeholder).`);
}