added filter for kicked/banned cards on AdminBoard, and added check for PENDING transactions

This commit is contained in:
crowetic 2025-01-15 19:14:16 -08:00
parent 39f1d8783b
commit 7f4848342d
3 changed files with 145 additions and 36 deletions

View File

@ -12,12 +12,54 @@ let adminMemberCount = 0
let adminPublicKeys = []
let kickTransactions = []
let banTransactions = []
let adminBoardState = {
kickedCards: new Set(), // store identifiers or addresses
bannedCards: new Set(), // likewise
hiddenList: new Set(), // user-hidden
// ... we can add other things to state if needed...
}
const loadAdminBoardState = () => {
// Load from localStorage if available
const rawState = localStorage.getItem('adminBoardState')
if (rawState) {
try {
const parsed = JSON.parse(rawState);
// Make sure bannedCards and kickedCards are sets
return {
bannedCards: new Set(parsed.bannedCards ?? []),
kickedCards: new Set(parsed.kickedCards ?? []),
hiddenList: new Set(parsed.hiddenList ?? []),
// ... any other fields
};
} catch (e) {
console.warn("Failed to parse adminBoardState from storage:", e)
}
}
// If nothing found or parse error, return a default
return {
bannedCards: new Set(),
kickedCards: new Set(),
hiddenList: new Set(),
}
}
// Saving the state back into localStorage as needed:
const saveAdminBoardState = () => {
const stateToSave = {
bannedCards: Array.from(adminBoardState.bannedCards),
kickedCards: Array.from(adminBoardState.kickedCards),
hiddenList: Array.from(adminBoardState.hiddenList),
}
localStorage.setItem('adminBoardState', JSON.stringify(stateToSave))
}
console.log("Attempting to load AdminBoard.js")
const loadAdminBoardPage = async () => {
// Clear existing content on the page
const bodyChildren = document.body.children;
const bodyChildren = document.body.children
for (let i = bodyChildren.length - 1; i >= 0; i--) {
const child = bodyChildren[i];
if (!child.classList.contains("menu")) {
@ -34,6 +76,12 @@ const loadAdminBoardPage = async () => {
<p> More functionality will be added over time. One of the first features will be the ability to output the existing card data 'decisions', to a json formatted list in order to allow crowetic to run his script easily until the final Mintership proposal changes are completed, and the MINTER group is transferred to 'null'.</p>
<button id="publish-card-button" class="publish-card-button" style="margin: 20px; padding: 10px;">Publish Encrypted Card</button>
<button id="refresh-cards-button" class="refresh-cards-button" style="padding: 10px;">Refresh Cards</button>
<div class="show-card-checkbox" style="margin-top: 1em;">
<input type="checkbox" id="admin-show-hidden-checkbox" name="adminHidden" />
<label for="admin-show-hidden-checkbox">Show User-Hidden Cards?</label>
<input type="checkbox" id="admin-show-kicked-banned-checkbox" name="kickedBanned" />
<label for="admin-show-kicked-banned-checkbox">Show Kicked / Banned Cards?</label>
</div>
<div id="encrypted-cards-container" class="cards-container" style="margin-top: 20px;"></div>
<div id="publish-card-view" class="publish-card-view" style="display: none; text-align: left; padding: 20px;">
<form id="publish-card-form">
@ -61,6 +109,7 @@ const loadAdminBoardPage = async () => {
`
document.body.appendChild(mainContent)
const publishCardButton = document.getElementById("publish-card-button")
if (publishCardButton) {
publishCardButton.addEventListener("click", async () => {
const publishCardView = document.getElementById("publish-card-view")
@ -69,6 +118,7 @@ const loadAdminBoardPage = async () => {
})
}
const refreshCardsButton = document.getElementById("refresh-cards-button")
if (refreshCardsButton) {
refreshCardsButton.addEventListener("click", async () => {
const encryptedCardsContainer = document.getElementById("encrypted-cards-container")
@ -76,8 +126,8 @@ const loadAdminBoardPage = async () => {
await fetchAllEncryptedCards(true)
})
}
const cancelPublishButton = document.getElementById("cancel-publish-button")
if (cancelPublishButton) {
cancelPublishButton.addEventListener("click", async () => {
const encryptedCardsContainer = document.getElementById("encrypted-cards-container")
@ -87,6 +137,7 @@ const loadAdminBoardPage = async () => {
})
}
const addLinkButton = document.getElementById("add-link-button")
if (addLinkButton) {
addLinkButton.addEventListener("click", async () => {
const linksContainer = document.getElementById("links-container")
@ -98,12 +149,21 @@ const loadAdminBoardPage = async () => {
})
}
document.getElementById('show-kicked-banned-checkbox')?.addEventListener('change', () => {
fetchAllEncryptedCards()
})
document.getElementById('show-admin-hidden-checkbox')?.addEventListener('change', () => {
fetchAllEncryptedCards()
})
document.getElementById("publish-card-form").addEventListener("submit", async (event) => {
event.preventDefault()
const isTopicChecked = document.getElementById("topic-checkbox").checked
// Pass that boolean to publishEncryptedCard
await publishEncryptedCard(isTopicChecked)
})
createScrollToTopButton()
// await fetchAndValidateAllAdminCards()
await updateOrSaveAdminGroupsDataLocally()
@ -112,26 +172,12 @@ const loadAdminBoardPage = async () => {
}
const fetchAllKicKBanTxData = async () => {
const kickTxType = "GROUP_KICK"
const banTxType = "GROUP_BAN"
const banArray = [banTxType]
const kickArray = [kickTxType]
const kickTxType = "GROUP_KICK";
const banTxType = "GROUP_BAN";
banTransactions = await searchTransactions({
txTypes: banArray,
address: '', // or whatever address
confirmationStatus: 'CONFIRMED',
limit: 0,
reverse: true,
offset: 0,
startBlock: 1990000,
blockLimit: 0,
txGroupId: 0
});
console.warn(`banTxData`, banTransactions)
kickTransactions = await searchTransactions({
txTypes: kickArray,
// 1) Fetch ban transactions
const rawBanTransactions = await searchTransactions({
txTypes: [banTxType],
address: '',
confirmationStatus: 'CONFIRMED',
limit: 0,
@ -139,10 +185,29 @@ const fetchAllKicKBanTxData = async () => {
offset: 0,
startBlock: 1990000,
blockLimit: 0,
txGroupId: 0
txGroupId: 0,
});
console.warn(`kickTxData`, kickTransactions)
}
// Filter out 'PENDING'
banTransactions = rawBanTransactions.filter((tx) => tx.approvalStatus !== 'PENDING');
console.warn('banTxData (no PENDING):', banTransactions);
// 2) Fetch kick transactions
const rawKickTransactions = await searchTransactions({
txTypes: [kickTxType],
address: '',
confirmationStatus: 'CONFIRMED',
limit: 0,
reverse: true,
offset: 0,
startBlock: 1990000,
blockLimit: 0,
txGroupId: 0,
});
// Filter out 'PENDING'
kickTransactions = rawKickTransactions.filter((tx) => tx.approvalStatus !== 'PENDING');
console.warn('kickTxData (no PENDING):', kickTransactions);
};
// Example: fetch and save admin public keys and count
@ -155,7 +220,7 @@ const updateOrSaveAdminGroupsDataLocally = async () => {
const adminData = {
keysCount: verifiedAdminPublicKeys.length,
publicKeys: verifiedAdminPublicKeys
};
}
adminPublicKeys = verifiedAdminPublicKeys
@ -173,11 +238,12 @@ const loadOrFetchAdminGroupsData = async () => {
try {
// Pull the JSON from localStorage
const storedData = localStorage.getItem('savedAdminData')
if (!storedData && attemptLoadAdminDataCount <= 3) {
console.log('No saved admin public keys found in local storage. Fetching...')
await updateOrSaveAdminGroupsDataLocally()
attemptLoadAdminDataCount++
return null;
return null
}
// Parse the JSON, then store the global variables.
const parsedData = JSON.parse(storedData)
@ -191,7 +257,7 @@ const loadOrFetchAdminGroupsData = async () => {
console.log(`Loaded admins 'keysCount'=${adminMemberCount}, publicKeys=`, adminPublicKeys)
attemptLoadAdminDataCount = 0
return parsedData; // and return { adminMemberCount, adminKeys } to the caller
return parsedData // and return { adminMemberCount, adminKeys } to the caller
} catch (error) {
console.error('Error loading/parsing saved admin public keys:', error)
return null
@ -199,10 +265,10 @@ const loadOrFetchAdminGroupsData = async () => {
}
const extractEncryptedCardsMinterName = (cardIdentifier) => {
const parts = cardIdentifier.split('-');
const parts = cardIdentifier.split('-')
// Ensure the format has at least 3 parts
if (parts.length < 3) {
throw new Error('Invalid identifier format');
throw new Error('Invalid identifier format')
}
if (parts.slice(2, -1).join('-') === 'TOPIC') {
@ -264,7 +330,7 @@ const fetchAllEncryptedCards = async (isRefresh = false) => {
if (validCardsWithData.length === 0) {
encryptedCardsContainer.innerHTML = "<p>No valid cards found.</p>"
return;
return
}
// Combine `processCards` logic: Deduplicate cards by identifier and keep latest timestamp
@ -317,15 +383,38 @@ const fetchAllEncryptedCards = async (isRefresh = false) => {
encryptedCardsContainer.innerHTML = ""
const finalVisualFilterCards = finalCards.filter(({card}) => {
const showKickedBanned = document.getElementById('admin-show-kicked-banned-checkbox')?.checked ?? false
const showHiddenAdminCards = document.getElementById('admin-show-hidden-checkbox')?.checked ?? false
if (!showKickedBanned){
if (adminBoardState.bannedCards.has(card.identifier)) {
return false // skip
}
if (adminBoardState.kickedCards.has(card.identifier)) {
return false // skip
}
}
if (!showHiddenAdminCards) {
if (adminBoardState.hiddenList.has(card.identifier)) {
return false // skip
}
}
return true
})
console.warn(`sharing current adminBoardState...`,adminBoardState)
// Display skeleton cards immediately
finalCards.forEach(({ card }) => {
finalVisualFilterCards.forEach(({ card }) => {
const skeletonHTML = createSkeletonCardHTML(card.identifier)
encryptedCardsContainer.insertAdjacentHTML("beforeend", skeletonHTML)
})
})
// Fetch poll results and update each card
await Promise.all(
finalCards.map(async ({ card, decryptedCardData }) => {
finalVisualFilterCards.map(async ({ card, decryptedCardData }) => {
try {
// Validate poll publisher keys
const encryptedCardPollPublisherPublicKey = await getPollPublisherPublicKey(decryptedCardData.poll)
@ -355,6 +444,9 @@ const fetchAllEncryptedCards = async (isRefresh = false) => {
card.identifier,
encryptedCommentCount
)
if ((!finalCardHTML) || (finalCardHTML === '')){
removeSkeleton(card.identifier)
}
replaceSkeleton(card.identifier, finalCardHTML)
} catch (error) {
console.error(`Error finalizing card ${card.identifier}:`, error)
@ -424,7 +516,7 @@ const validateEncryptedCardIdentifier = async (card) => {
// Load existing card data passed, into the form for editing -------------------------------------
const loadEncryptedCardIntoForm = async (decryptedCardData) => {
if (decryptedCardData) {
console.log("Loading existing card data:", decryptedCardData);
console.log("Loading existing card data:", decryptedCardData)
document.getElementById("minter-name-input").value = decryptedCardData.minterName
document.getElementById("card-header").value = decryptedCardData.header
document.getElementById("card-content").value = decryptedCardData.content
@ -629,7 +721,7 @@ const postEncryptedComment = async (cardIdentifier) => {
encrypt: true,
publicKeys: adminPublicKeys
})
alert('Comment posted successfully!')
// alert('Comment posted successfully!')
commentInput.value = ''
} catch (error) {
@ -969,6 +1061,8 @@ const createEncryptedCardHTML = async (cardData, pollResults, cardIdentifier, co
${`Link ${index + 1} - ${link}`}
</button>
`).join("")
const showKickedBanned = document.getElementById('admin-show-kicked-banned-checkbox')?.checked ?? false
const showHiddenAdminCards = document.getElementById('admin-show-hidden-checkbox')?.checked ?? false
const isUndefinedUser = (minterName === 'undefined')
@ -1018,6 +1112,13 @@ const createEncryptedCardHTML = async (cardData, pollResults, cardIdentifier, co
cardColorCode = 'rgb(24, 3, 3)'
altText = `<h4 style="color:rgb(106, 2, 2); margin-bottom: 0.5em;">BANNED From MINTER Group</h4>`
showRemoveHtml = ''
if (!adminBoardState.bannedCards.has(cardIdentifier)){
adminBoardState.bannedCards.add(cardIdentifier)
}
if (!showKickedBanned){
console.warn(`kick/bank checkbox is unchecked, and card is banned, not displaying...`)
return ''
}
}
if (kickTransactions.some((kickTx) => kickTx.groupId === 694 && kickTx.member === accountAddress)){
@ -1025,6 +1126,13 @@ const createEncryptedCardHTML = async (cardData, pollResults, cardIdentifier, co
cardColorCode = 'rgb(29, 7, 4)'
altText = `<h4 style="color:rgb(143, 117, 21); margin-bottom: 0.5em;">KICKED From MINTER Group</h4>`
showRemoveHtml = ''
if (!adminBoardState.kickedCards.has(cardIdentifier)){
adminBoardState.kickedCards.add(cardIdentifier)
}
if (!showKickedBanned) {
console.warn(`kick/ban checkbox is unchecked, card is kicked, not displaying...`)
return ''
}
}
} else {

View File

@ -9,6 +9,7 @@ const GROUP_APPROVAL_FEATURE_TRIGGER_HEIGHT = 9999950 //TODO update this to corr
let featureTriggerPassed = false
let isApproved = false
const loadMinterBoardPage = async () => {
// Clear existing content on the page
const bodyChildren = document.body.children

View File

@ -99,7 +99,7 @@ document.addEventListener("DOMContentLoaded", async () => {
})
// --- ADMIN CHECK ---
await verifyUserIsAdmin();
await verifyUserIsAdmin()
if (userState.isAdmin && (localStorage.getItem('savedAdminData'))) {
console.log('saved admin data found (Q-Mintership.js), loading...')