diff --git a/assets/js/ARBoard.js b/assets/js/ARBoard.js
index 05e7fed..e19b702 100644
--- a/assets/js/ARBoard.js
+++ b/assets/js/ARBoard.js
@@ -59,6 +59,13 @@ const loadAddRemoveAdminPage = async () => {
@@ -80,8 +87,8 @@ const loadAddRemoveAdminPage = async () => {
// proposeButton.style.display === 'flex' ? 'none' : 'flex'
} catch (error) {
- console.error("Error checking for existing card:", error)
- alert("Failed to check for existing card. Please try again.")
+ console.error("Error opening propose form", error)
+ alert("Failed to open proposal form. Please try again.")
}
})
@@ -126,79 +133,79 @@ const toggleProposeButton = () => {
proposeButton.style.display === 'flex' ? 'none' : 'flex'
}
-let addAdminTxs
-let remAdminTxs
-
const fetchAllARTxData = async () => {
const addAdmTx = "ADD_GROUP_ADMIN"
const remAdmTx = "REMOVE_GROUP_ADMIN"
- const filterAddTransactions = (rawTransactions) => {
- // Group transactions by member
- const memberTxMap = rawTransactions.reduce((map, tx) => {
- if (!map[tx.member]) {
- map[tx.member] = []
- }
- map[tx.member].push(tx)
- return map
- }, {})
-
- // Filter out members with both pending and non-pending transactions
- return Object.values(memberTxMap)
- .filter(txs => txs.every(tx => tx.approvalStatus !== 'PENDING'))
- .flat()
- // .filter((txs) => !(txs.some(tx => tx.approvalStatus === 'PENDING') &&
- // txs.some(tx => tx.approvalStatus !== 'PENDING')))
- // .flat()
- }
-
- const filterRemoveTransactions = (rawTransactions) => {
- // Group transactions by member
- const adminTxMap = rawTransactions.reduce((map, tx) => {
- if (!map[tx.admin]) {
- map[tx.admin] = []
- }
- map[tx.admin].push(tx)
- return map
- }, {})
-
- // Filter out members with both pending and non-pending transactions
- return Object.values(adminTxMap)
- .filter((txs) => !(txs.some(tx => tx.approvalStatus === 'PENDING') &&
- txs.some(tx => tx.approvalStatus !== 'PENDING')))
- .flat()
- }
-
- // Fetch ban transactions
const allAddTxs = await searchTransactions({
- txTypes: [addAdmTx],
- confirmationStatus: 'CONFIRMED',
- limit: 0,
- reverse: true,
- offset: 0,
- startBlock: 1990000,
- blockLimit: 0,
- txGroupId: 694,
- })
- // Filter out 'PENDING'
- addAdminTxs = filterAddTransactions(allAddTxs)
- console.warn('addAdminTxData (no PENDING nor past+PENDING):', addAdminTxs)
+ txTypes: [addAdmTx],
+ confirmationStatus: 'CONFIRMED',
+ limit: 0,
+ reverse: true,
+ offset: 0,
+ startBlock: 1990000,
+ blockLimit: 0,
+ txGroupId: 694,
+ })
+
+ const allRemTxs = await searchTransactions({
+ txTypes: [remAdmTx],
+ confirmationStatus: 'CONFIRMED',
+ limit: 0,
+ reverse: true,
+ offset: 0,
+ startBlock: 1990000,
+ blockLimit: 0,
+ txGroupId: 694,
+ })
+
+ const { finalAddTxs, pendingAddTxs } = partitionAddTransactions(allAddTxs)
+ const { finalRemTxs, pendingRemTxs } = partitionRemoveTransactions(allRemTxs)
+
+ // We are going to keep all transactions in order to filter more accurately for display purposes.
+ console.log('Final addAdminTxs:', finalAddTxs);
+ console.log('Pending addAdminTxs:', pendingAddTxs);
+ console.log('Final remAdminTxs:', finalRemTxs);
+ console.log('Pending remAdminTxs:', pendingRemTxs);
+
+ return {
+ finalAddTxs,
+ pendingAddTxs,
+ finalRemTxs,
+ pendingRemTxs,
+ }
+}
+
+function partitionAddTransactions(rawTransactions) {
+ const finalAddTxs = []
+ const pendingAddTxs = []
+
+ for (const tx of rawTransactions) {
+ if (tx.approvalStatus === 'PENDING') {
+ pendingAddTxs.push(tx)
+ } else {
+ finalAddTxs.push(tx)
+ }
+ }
+
+ return { finalAddTxs, pendingAddTxs };
+}
+
+function partitionRemoveTransactions(rawTransactions) {
+ const finalRemTxs = []
+ const pendingRemTxs = []
+
+ for (const tx of rawTransactions) {
+ if (tx.approvalStatus === 'PENDING') {
+ pendingRemTxs.push(tx)
+ } else {
+ finalRemTxs.push(tx)
+ }
+ }
+
+ return { finalRemTxs, pendingRemTxs }
+}
- // Fetch kick transactions
- const allRemTxs = await searchTransactions({
- txTypes: [remAdmTx],
- confirmationStatus: 'CONFIRMED',
- limit: 0,
- reverse: true,
- offset: 0,
- startBlock: 1990000,
- blockLimit: 0,
- txGroupId: 694,
- })
- // Filter out 'PENDING'
- remAdminTxs = filterRemoveTransactions(allRemTxs)
- console.warn('remAdminTxData (no PENDING nor past+PENDING):', remAdminTxs)
- }
const displayExistingMinterAdmins = async () => {
const adminListContainer = document.getElementById("admin-list-container")
@@ -309,9 +316,10 @@ const handleProposeDemotion = async (adminName, adminAddress) => {
// Notify the user to fill out the rest
alert(`Admin "${adminName}" has been selected for demotion. Please fill out the rest of the form.`)
- }
+}
+
- const fetchExistingARCard = async (cardIdentifierPrefix, minterName) => {
+const fetchExistingARCard = async (cardIdentifierPrefix, minterName) => {
try {
const response = await searchSimple(
'BLOG_POST',
@@ -381,7 +389,7 @@ const handleProposeDemotion = async (adminName, adminAddress) => {
console.error("Error fetching existing AR card:", error)
return null
}
- }
+}
const publishARCard = async (cardIdentifierPrefix) => {
@@ -726,8 +734,8 @@ const fallbackMinterCheck = async (minterName, minterGroupMembers, minterAdmins)
}
-const createARCardHTML = async (cardData, pollResults, cardIdentifier, commentCount) => {
- const { minterName, header, content, links, creator, timestamp, poll, promotionCard } = cardData
+const createARCardHTML = async (cardData, pollResults, cardIdentifier, commentCount, cardUpdatedTime, bgColor, cardPublisherAddress, illegalDuplicate) => {
+ const { minterName, minterAddress='priorToAddition', header, content, links, creator, timestamp, poll, promotionCard } = cardData
const formattedDate = new Date(timestamp).toLocaleString()
const minterAvatar = await getMinterAvatar(minterName)
const creatorAvatar = await getMinterAvatar(creator)
@@ -744,7 +752,7 @@ const createARCardHTML = async (cardData, pollResults, cardIdentifier, commentCo
// showPromotionCard = await fallbackMinterCheck(minterName, minterGroupMembers, minterAdmins)
if (typeof promotionCard === 'boolean') {
- showPromotionCard = promotionCard;
+ showPromotionCard = promotionCard
} else if (typeof promotionCard === 'string') {
// Could be "true" or "false" or something else
const lower = promotionCard.trim().toLowerCase()
@@ -790,41 +798,63 @@ const createARCardHTML = async (cardData, pollResults, cardIdentifier, commentCo
let altText = ''
const verifiedName = await validateMinterName(minterName)
- if (verifiedName) {
+ if (verifiedName && !illegalDuplicate) {
const accountInfo = await getNameInfo(verifiedName)
const accountAddress = accountInfo.owner
+ const minterGroupAddresses = minterGroupMembers.map(m => m.member)
+ const adminAddresses = minterAdmins.map(m => m.member)
+ const existingAdmin = adminAddresses.includes(accountAddress)
+ const existingMinter = minterGroupAddresses.includes(accountAddress)
console.log(`name is validated, utilizing for removal features...${verifiedName}`)
const actionsHtmlCheck = await checkAndDisplayActions(adminYes, verifiedName, cardIdentifier)
actionsHtml = actionsHtmlCheck
- if (!addAdminTxs || !remAdminTxs) {
- await fetchAllARTxData()
- }
+ const { finalAddTxs, pendingAddTxs, finalRemTxs, pendingRemTxs } = await fetchAllARTxData()
- if (addAdminTxs.some((addTx) => addTx.groupId === 694 && addTx.member === accountAddress)){
- console.warn(`account was already adminified(PROMOTED), displaying as such...`)
+ const confirmedAdd = finalAddTxs.some(
+ (tx) => tx.groupId === 694 && tx.member === accountAddress
+ )
+ const userPendingAdd = pendingAddTxs.some(
+ (tx) => tx.groupId === 694 && tx.member === accountAddress
+ )
+ const confirmedRemove = finalRemTxs.some(
+ (tx) => tx.groupId === 694 && tx.admin === accountAddress
+ )
+ const userPendingRemove = pendingRemTxs.some(
+ (tx) => tx.groupId === 694 && tx.admin === accountAddress
+ )
+
+ // If user is definitely admin (finalAdd) and not pending removal
+ if (confirmedAdd && !userPendingRemove && existingAdmin) {
+ console.warn(`account was already admin, final. no add/remove pending.`);
cardColorCode = 'rgb(3, 11, 24)'
- altText = `
PROMOTED to ADMIN `
+ altText = `
PROMOTED to ADMIN `;
actionsHtml = ''
- // =============================================================== if 'showPromotedDemoted' is wanted to be added.
- // if (!showPromotedDemoted){
- // console.warn(`promoted/demoted show checkbox is unchecked, and card is promoted, not displaying...`)
- // return ''
- // }
+ }
+
+ if (confirmedAdd && userPendingRemove && existingAdmin) {
+ console.warn(`user is a previously approved an admin, but now has pending removals. Keeping html`)
}
- if (remAdminTxs.some((remTx) => remTx.groupId === 694 && remTx.admin === accountAddress)){
- console.warn(`account was already UNadminified(DEMOTED), displaying as such...`)
+ // If user has a final "remove" and no pending additions or removals
+ if (confirmedRemove && !userPendingAdd && existingMinter) {
+ console.warn(`account was demoted, final. no add pending, existingMinter.`);
cardColorCode = 'rgb(29, 4, 6)'
altText = `
DEMOTED from ADMIN `
actionsHtml = ''
-
- // if (!showPromotedDemoted) {
- // console.warn(`promoted/demoted show checkbox is unchecked, card is demoted, not displaying...`)
- // return ''
- // }
}
+ // If user has both final remove and pending add, do something else
+ if (confirmedRemove && userPendingAdd && existingMinter) {
+ console.warn(`account was previously demoted, but also a pending re-add, allowing actions to show...`)
+ // Possibly show "DEMOTED but re-add in progress" or something
+ }
+
+ } else if ( verifiedName && illegalDuplicate) {
+ console.warn(`illegalDuplicate detected (this card was somehow allowed to be published twice, keeping newest as active to prevent issues with old cards and updates, but displaying without actions...)`)
+ cardColorCode = 'rgb(82, 81, 81)'
+ altText = `
DUPLICATE (diplayed for data only) `
+ actionsHtml = ''
} else {
console.warn(`name could not be validated, not setting actionsHtml`)
actionsHtml = ''
diff --git a/assets/js/AdminBoard.js b/assets/js/AdminBoard.js
index cc82ffa..375d83a 100644
--- a/assets/js/AdminBoard.js
+++ b/assets/js/AdminBoard.js
@@ -83,6 +83,13 @@ const loadAdminBoardPage = async () => {
Least Votes
Most Votes
+
+ Show All
+ Last 1 day
+ Last 7 days
+ Last 30 days
+ Last 90 days
+
Show User-Hidden Cards?
@@ -327,8 +334,20 @@ const fetchAllEncryptedCards = async (isRefresh = false) => {
const encryptedCardsContainer = document.getElementById("encrypted-cards-container")
encryptedCardsContainer.innerHTML = "
Loading cards...
"
+ let afterTime = null
+ const timeRangeSelect = document.getElementById("time-range-select")
+ if (timeRangeSelect) {
+ const days = parseInt(timeRangeSelect.value, 10)
+ if (days > 0) {
+ const now = Date.now()
+ const dayMs = 24 * 60 * 60 * 1000
+ afterTime = now - days * dayMs // e.g. last X days
+ console.log(`afterTime for last ${days} days = ${new Date(afterTime).toLocaleString()}`)
+ }
+ }
+
try {
- const response = await searchSimple('MAIL_PRIVATE', `${encryptedCardIdentifierPrefix}`, '', 0)
+ const response = await searchSimple('MAIL_PRIVATE', `${encryptedCardIdentifierPrefix}`, '', 0, 0, '', false, true, afterTime)
if (!response || !Array.isArray(response) || response.length === 0) {
encryptedCardsContainer.innerHTML = "
No cards found.
"
@@ -379,12 +398,13 @@ const fetchAllEncryptedCards = async (isRefresh = false) => {
const latestCardsMap = new Map()
validCardsWithData.forEach(({ card, decryptedCardData }) => {
- const timestamp = card.updated || card.created || 0
+ const timestamp = card.created || 0
const existingCard = latestCardsMap.get(card.identifier)
- if (!existingCard || timestamp > (existingCard.card.updated || existingCard.card.created || 0)) {
+ if (!existingCard || timestamp < (existingCard.card.updated || existingCard.card.created || 0)) {
latestCardsMap.set(card.identifier, { card, decryptedCardData })
- }
+ }
+
})
const uniqueValidCards = Array.from(latestCardsMap.values())
@@ -396,13 +416,11 @@ const fetchAllEncryptedCards = async (isRefresh = false) => {
const obtainedMinterName = decryptedCardData.minterName
// Only check for cards that are NOT topic-based cards
if ((!decryptedCardData.isTopic) || decryptedCardData.isTopic === 'false') {
- const cardTimestamp = card.updated || card.created || 0
if (obtainedMinterName) {
const existingEntry = mostRecentCardsMap.get(obtainedMinterName)
- // Replace only if the current card is more recent
- if (!existingEntry || cardTimestamp > (existingEntry.card.updated || existingEntry.card.created || 0)) {
+ if (!existingEntry) {
mostRecentCardsMap.set(obtainedMinterName, { card, decryptedCardData })
}
}
@@ -414,7 +432,7 @@ const fetchAllEncryptedCards = async (isRefresh = false) => {
})
// Convert the map into an array of final cards
- const finalCards = Array.from(mostRecentCardsMap.values());
+ const finalCards = Array.from(mostRecentCardsMap.values())
let selectedSort = 'newest'
const sortSelect = document.getElementById('sort-select')
@@ -1037,7 +1055,7 @@ const processQortalLinkForRendering = async (link) => {
return link
}
-const checkAndDisplayRemoveActions = async (adminYes, name, cardIdentifier) => {
+const checkAndDisplayRemoveActions = async (adminYes, name, cardIdentifier, nameIsActuallyAddress = false) => {
const latestBlockInfo = await getLatestBlockInfo()
const isBlockPassed = latestBlockInfo.height >= GROUP_APPROVAL_FEATURE_TRIGGER_HEIGHT
let minAdminCount
@@ -1052,10 +1070,15 @@ const checkAndDisplayRemoveActions = async (adminYes, name, cardIdentifier) => {
minAdminCount = Math.round(fortyPercent)
console.warn(`this is another check to ensure minterAdmin group has more than 1 admin. IF so we will calculate the 40% needed for GROUP_APPROVAL, that number is: ${minAdminCount}`)
}
- if (isBlockPassed && userState.isMinterAdmin) {
+ if (isBlockPassed && (userState.isMinterAdmin || userState.isAdmin)) {
console.warn(`feature trigger has passed, checking for approval requirements`)
- const addressInfo = await getNameInfo(name)
- const address = addressInfo.owner
+ let address
+ if (!nameIsActuallyAddress){
+ const nameInfo = await getNameInfo(name)
+ address = nameInfo.owner
+ } else {
+ address = name
+ }
const kickApprovalHtml = await checkGroupApprovalAndCreateButton(address, cardIdentifier, "GROUP_KICK")
const banApprovalHtml = await checkGroupApprovalAndCreateButton(address, cardIdentifier, "GROUP_BAN")
@@ -1068,7 +1091,7 @@ const checkAndDisplayRemoveActions = async (adminYes, name, cardIdentifier) => {
}
}
- if (adminYes >= minAdminCount && userState.isMinterAdmin) {
+ if (adminYes >= minAdminCount && (userState.isMinterAdmin || userState.isAdmin)) {
const removeButtonHtml = createRemoveButtonHtml(name, cardIdentifier)
return removeButtonHtml
} else{
@@ -1098,6 +1121,8 @@ const createRemoveButtonHtml = (name, cardIdentifier) => {
const handleKickMinter = async (minterName) => {
try {
+ isAddress = await getAddressInfo(minterName)
+
// Optional block check
let txGroupId = 0
// const { height: currentHeight } = await getLatestBlockInfo()
@@ -1108,8 +1133,14 @@ const handleKickMinter = async (minterName) => {
}
// Get the minter address from name info
- const minterNameInfo = await getNameInfo(minterName)
- const minterAddress = minterNameInfo?.owner
+ let minterAddress
+ if (!isAddress){
+ const minterNameInfo = await getNameInfo(minterName)
+ minterAddress = minterNameInfo?.owner
+ } else {
+ minterAddress = minterName
+ }
+
if (!minterAddress) {
alert(`No valid address found for minter name: ${minterName}, this should NOT have happened, please report to developers...`)
return
@@ -1150,6 +1181,7 @@ const handleKickMinter = async (minterName) => {
}
const handleBanMinter = async (minterName) => {
+ isAddress = await getAddressInfo(minterName)
try {
let txGroupId = 0
// const { height: currentHeight } = await getLatestBlockInfo()
@@ -1161,9 +1193,13 @@ const handleBanMinter = async (minterName) => {
console.log(`featureTrigger block is passed, using txGroupId 694`)
txGroupId = 694
}
-
- const minterNameInfo = await getNameInfo(minterName)
- const minterAddress = minterNameInfo?.owner
+ let minterAddress
+ if (!isAddress) {
+ const minterNameInfo = await getNameInfo(minterName)
+ const minterAddress = minterNameInfo?.owner
+ } else {
+ minterAddress = minterName
+ }
if (!minterAddress) {
alert(`No valid address found for minter name: ${minterName}, this should NOT have happened, please report to developers...`)
@@ -1236,7 +1272,7 @@ const createEncryptedCardHTML = async (cardData, pollResults, cardIdentifier, co
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')
+ const isUndefinedUser = (minterName === 'undefined' || minterName === 'null')
const hasTopicMode = Object.prototype.hasOwnProperty.call(cardData, 'topicMode')
@@ -1254,7 +1290,7 @@ const createEncryptedCardHTML = async (cardData, pollResults, cardIdentifier, co
let cardColorCode = showTopic ? '#0e1b15' : '#151f28'
const minterOrTopicHtml = ((showTopic) || (isUndefinedUser)) ? `
-
+
${minterName}` :
`
@@ -1274,16 +1310,23 @@ const createEncryptedCardHTML = async (cardData, pollResults, cardIdentifier, co
let adjustmentText = ''
const verifiedName = await validateMinterName(minterName)
let levelText = ' '
+ const addressVerification = await getAddressInfo(minterName)
+ const verifiedAddress = addressVerification.address
- if (verifiedName) {
- const accountInfo = await getNameInfo(verifiedName)
- const accountAddress = accountInfo.owner
- const addressInfo = await getAddressInfo(accountAddress)
+ if (verifiedName || verifiedAddress) {
+ let accountInfo
+ if (!verifiedAddress){
+ accountInfo = await getNameInfo(verifiedName)
+ }
+
+ const accountAddress = verifiedAddress ? addressVerification.address : accountInfo.owner
+ const addressInfo = verifiedAddress ? addressVerification : await getAddressInfo(accountAddress)
+
levelText = ` - Level ${addressInfo.level}`
console.log(`name is validated, utilizing for removal features...${verifiedName}`)
penaltyText = addressInfo.blocksMintedPenalty == 0 ? '' : '
(has Blocks Penalty)
'
adjustmentText = addressInfo.blocksMintedAdjustment == 0 ? '' : '
(has Blocks Adjustment)
'
- const removeActionsHtml = await checkAndDisplayRemoveActions(adminYes, verifiedName, cardIdentifier)
+ const removeActionsHtml = verifiedAddress ? await checkAndDisplayRemoveActions(adminYes, verifiedAddress, cardIdentifier) : await checkAndDisplayRemoveActions(adminYes, verifiedName, cardIdentifier)
showRemoveHtml = removeActionsHtml
if (userVote === 0) {
cardColorCode = "rgba(1, 65, 39, 0.41)"; // or any green you want
diff --git a/assets/js/AdminTools.js b/assets/js/AdminTools.js
index f5c3907..0a0177e 100644
--- a/assets/js/AdminTools.js
+++ b/assets/js/AdminTools.js
@@ -28,10 +28,10 @@ async function loadMinterAdminToolsPage() {
${userState.accountName || 'Guest'}
-
No Functionality Here Yet
+
COMING SOON...
-
This page is still under development. Until the final Mintership proposal modifications are made, and the MINTER group is transferred to null, there is no need for this page's functionality. The page will be updated when the final modifications are made.
-
This page until then is simply a placeholder.
+
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.
+
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.
diff --git a/assets/js/MinterBoard.js b/assets/js/MinterBoard.js
index 788b8b5..5e635d5 100644
--- a/assets/js/MinterBoard.js
+++ b/assets/js/MinterBoard.js
@@ -37,6 +37,13 @@ const loadMinterBoardPage = async () => {