Resolved multiple publish issues on ARA Board, not allowing duplicate names to be published, and only allowing original publisher to update a published card. Resolved promotion cards being displayed as such regardless. Removed 'alert' for successful comment publish, etc.

This commit is contained in:
crowetic 2025-01-22 15:40:19 -08:00
parent 8ade0b60aa
commit 10f8230619
4 changed files with 100 additions and 103 deletions

View File

@ -3,6 +3,7 @@ let minterGroupAddresses
let minterAdminAddresses let minterAdminAddresses
let isTest = false let isTest = false
let isAddRemoveBoard = true let isAddRemoveBoard = true
let otherPublisher = false
const addRemoveIdentifierPrefix = "QM-AR-card" const addRemoveIdentifierPrefix = "QM-AR-card"
const loadAddRemoveAdminPage = async () => { const loadAddRemoveAdminPage = async () => {
console.log("Loading Add/Remove Admin page...") console.log("Loading Add/Remove Admin page...")
@ -69,35 +70,6 @@ const loadAddRemoveAdminPage = async () => {
document.getElementById("propose-promotion-button").addEventListener("click", async () => { document.getElementById("propose-promotion-button").addEventListener("click", async () => {
try { try {
const fetchedCard = await fetchExistingARCard(addRemoveIdentifierPrefix)
if (fetchedCard) {
// An existing card is found
if (isTest) {
const updateCard = confirm("You have already published a promotion card, would you like to update that one or publish a new one?")
if (updateCard) {
isExistingCard = true
await loadCardIntoForm(existingCardData)
alert("Edit your existing card and publish.")
} else {
alert("New Card Selected: You can now create a new promotion card.")
isExistingCard = false
existingCardData = {}
document.getElementById("publish-card-form").reset()
}
} else {
// Not in test mode, force editing
alert("A card already exists. Publishing of multiple cards is not allowed. Please update your card.")
isExistingCard = true
await loadCardIntoForm(existingCardData)
}
} else {
// No existing card found
console.log("No existing card found. Creating a new card.")
isExistingCard = false
}
// Show the form // Show the form
const publishCardView = document.getElementById("promotion-form-container") const publishCardView = document.getElementById("promotion-form-container")
publishCardView.style.display = 'flex' publishCardView.style.display = 'flex'
@ -317,13 +289,12 @@ const handleProposeDemotion = async (adminName, adminAddress) => {
const proposeButton = document.getElementById('propose-promotion-button') const proposeButton = document.getElementById('propose-promotion-button')
proposeButton.style.display = 'none' proposeButton.style.display = 'none'
const fetchedCard = await fetchExistingARCard(addRemoveIdentifierPrefix, adminName) const fetchedCard = await fetchExistingARCard(addRemoveIdentifierPrefix, adminName)
if (fetchedCard) { if (fetchedCard) {
alert("A card already exists. Publishing of multiple cards is not allowed. Please update your card.") alert("A card already exists. Publishing of multiple cards is not allowed. Please update your card.")
isExistingCard = true isExistingCard = true
await loadCardIntoForm(fetchedCard) await loadCardIntoForm(fetchedCard)
} }
// Populate the form with the admin's name // Populate the form with the admin's name
const nameInput = document.getElementById("minter-name-input") const nameInput = document.getElementById("minter-name-input")
nameInput.value = adminName nameInput.value = adminName
@ -342,37 +313,29 @@ const handleProposeDemotion = async (adminName, adminAddress) => {
const fetchExistingARCard = async (cardIdentifierPrefix, minterName) => { const fetchExistingARCard = async (cardIdentifierPrefix, minterName) => {
try { try {
// 1. Fetch all cards with the specified prefix
const response = await searchSimple( const response = await searchSimple(
'BLOG_POST', 'BLOG_POST',
`${cardIdentifierPrefix}`, `${cardIdentifierPrefix}`,
'', // Empty name to fetch all cards '',
0, 0,
0, 0,
'', '',
false,
true true
) )
console.log(`SEARCH_QDN_RESOURCES response: ${JSON.stringify(response, null, 2)}`) console.log(`fetchExistingCard searchSimple response: ${JSON.stringify(response, null, 2)}`)
if (!response || !Array.isArray(response) || response.length === 0) { if (!response || !Array.isArray(response) || response.length === 0) {
console.log("No cards found.") console.log("No cards found.")
return null return null
} }
// 2. Fetch minterGroupAddresses if not already fetched
if (!minterGroupAddresses) {
const groupData = await fetchMinterGroupMembers()
minterGroupAddresses = groupData.map((m) => m.member)
}
// 3. Validate all fetched cards and check for duplicate `minterName`
const validatedCards = await Promise.all( const validatedCards = await Promise.all(
response.map(async (card) => { response.map(async (card) => {
const isValid = await validateCardStructure(card) const isValid = await validateCardStructure(card)
if (!isValid) return null if (!isValid) return null
// Fetch full card data for validation // Fetch full card data for validation
const cardDataResponse = await qortalRequest({ const cardDataResponse = await qortalRequest({
action: "FETCH_QDN_RESOURCE", action: "FETCH_QDN_RESOURCE",
@ -381,30 +344,28 @@ const handleProposeDemotion = async (adminName, adminAddress) => {
identifier: card.identifier, identifier: card.identifier,
}) })
// Check if `minterName` matches the input or is a duplicate
if (cardDataResponse.minterName === minterName) { if (cardDataResponse.minterName === minterName) {
console.log(`Card with the same minterName found: ${minterName}`) console.log(`Card with the same minterName found: ${minterName}`)
return { if (cardDataResponse.creator === userState.accountName) {
card, console.log(`The user is the publisher, adding card...`)
cardData: cardDataResponse, return {
card,
cardData: cardDataResponse,
}
} else {
console.warn(`Card found, but user is not the creator!`)
otherPublisher = true
return null
} }
} }
return null return null
}) })
) )
// Filter out null results and check for duplicates
// 4. Filter out null results and check for duplicates
const matchingCards = validatedCards.filter((result) => result !== null) const matchingCards = validatedCards.filter((result) => result !== null)
if (matchingCards.length > 0) { if (matchingCards.length > 0) {
const { card, cardData } = matchingCards[0] // Use the first matching card const { card, cardData } = matchingCards[0] // Use the first matching card, which should be the first published for the minterName
// Determine if the card is a promotion card
// const nameInfo = await getNameInfo(cardData.minterName)
// const ownerAddress = nameInfo?.owner
// Set flags and return the existing card data
existingCardIdentifier = card.identifier existingCardIdentifier = card.identifier
existingCardData = cardData existingCardData = cardData
isExistingCard = true isExistingCard = true
@ -434,6 +395,7 @@ const publishARCard = async (cardIdentifierPrefix) => {
console.log(`MINTER NAME FOUND:`, minterNameInput) console.log(`MINTER NAME FOUND:`, minterNameInput)
minterName = minterNameInput minterName = minterNameInput
address = potentialNameInfo.owner address = potentialNameInfo.owner
} else { } else {
console.warn(`user input an address?...`, minterNameInput) console.warn(`user input an address?...`, minterNameInput)
if (!address){ if (!address){
@ -447,6 +409,7 @@ const publishARCard = async (cardIdentifierPrefix) => {
} }
} }
const checkForName = await getNameFromAddress(minterNameInput) const checkForName = await getNameFromAddress(minterNameInput)
if (checkForName) { if (checkForName) {
minterName = checkForName minterName = checkForName
} else if (!checkForName && address){ } else if (!checkForName && address){
@ -459,6 +422,19 @@ const publishARCard = async (cardIdentifierPrefix) => {
return return
} }
} }
const exists = await fetchExistingARCard(cardIdentifierPrefix, minterName)
if (exists) {
alert(`An existing card was found, you must update it, two cards for the samme name cannot be published! Loading card data...`)
await loadCardIntoForm(existingCardData)
minterName = exists.minterName
const nameInfo = await getNameInfo(exists.minterName)
address = nameInfo.owner
isExistingCard = true
} else if (otherPublisher){
alert(`An existing card was found, but you are NOT the publisher, you may not publish duplicates, and you may not update a non-owned card! Please try again with another name, or use the existing card for ${minterNameInput}`)
return
}
const minterGroupData = await fetchMinterGroupMembers() const minterGroupData = await fetchMinterGroupMembers()
minterGroupAddresses = minterGroupData.map(m => m.member) minterGroupAddresses = minterGroupData.map(m => m.member)
@ -466,14 +442,12 @@ const publishARCard = async (cardIdentifierPrefix) => {
const minterAdminGroupData = await fetchMinterGroupAdmins() const minterAdminGroupData = await fetchMinterGroupAdmins()
minterAdminAddresses = minterAdminGroupData.map(m => m.member) minterAdminAddresses = minterAdminGroupData.map(m => m.member)
if (minterGroupAddresses.includes(address)) {
isPromotionCard = true
console.warn(`address is a MINTER, this is a promotion card...`)
}
if (minterAdminAddresses.includes(address)){ if (minterAdminAddresses.includes(address)){
isPromotionCard = false isPromotionCard = false
console.warn(`this is a DEMOTION`, address) console.warn(`this is a DEMOTION`, address)
}else if (minterGroupAddresses.includes(address)) {
isPromotionCard = true
console.warn(`address is a MINTER, this is a promotion card...`)
} }
if (!minterAdminAddresses.includes(address) && !minterGroupAddresses.includes(address)) { if (!minterAdminAddresses.includes(address) && !minterGroupAddresses.includes(address)) {
@ -491,7 +465,7 @@ const publishARCard = async (cardIdentifierPrefix) => {
if (!header || !content) { if (!header || !content) {
alert("Header and content are required!") alert("Header and content are required!")
return return
} }
const cardIdentifier = isExistingCard ? existingCardIdentifier : `${cardIdentifierPrefix}-${await uid()}` const cardIdentifier = isExistingCard ? existingCardIdentifier : `${cardIdentifierPrefix}-${await uid()}`
const pollName = `${cardIdentifier}-poll` const pollName = `${cardIdentifier}-poll`
@ -539,6 +513,10 @@ const publishARCard = async (cardIdentifierPrefix) => {
isExistingCard = false isExistingCard = false
} }
if (isPromotionCard){
isPromotionCard = false
}
document.getElementById("publish-card-form").reset() document.getElementById("publish-card-form").reset()
document.getElementById("promotion-form-container").style.display = "none" document.getElementById("promotion-form-container").style.display = "none"
// document.getElementById("cards-container").style.display = "flex" // document.getElementById("cards-container").style.display = "flex"
@ -763,36 +741,37 @@ const createARCardHTML = async (cardData, pollResults, cardIdentifier, commentCo
const minterAdmins = await fetchMinterGroupAdmins() const minterAdmins = await fetchMinterGroupAdmins()
let showPromotionCard = false let showPromotionCard = false
showPromotionCard = await fallbackMinterCheck(minterName, minterGroupMembers, minterAdmins) // showPromotionCard = await fallbackMinterCheck(minterName, minterGroupMembers, minterAdmins)
// if (typeof promotionCard === 'boolean') { if (typeof promotionCard === 'boolean') {
// showPromotionCard = promotionCard; showPromotionCard = promotionCard;
// } else if (typeof promotionCard === 'string') { } else if (typeof promotionCard === 'string') {
// // Could be "true" or "false" or something else // Could be "true" or "false" or something else
// const lower = promotionCard.trim().toLowerCase() const lower = promotionCard.trim().toLowerCase()
// if (lower === "true") { if (lower === "true") {
// showPromotionCard = true showPromotionCard = true
// } else if (lower === "false") { } else if (lower === "false") {
// showPromotionCard = false showPromotionCard = false
// } else { } else {
// // Unexpected string => fallback // Unexpected string => fallback
// console.warn(`Unexpected string in promotionCard="${promotionCard}"`) console.warn(`Unexpected string in promotionCard="${promotionCard}"`)
// showPromotionCard = await fallbackMinterCheck(minterName, minterGroupMembers) showPromotionCard = await fallbackMinterCheck(minterName, minterGroupMembers)
// } }
// } else if (promotionCard == null) { } else if (promotionCard == null) {
// // null or undefined => fallback check // null or undefined => fallback check
// console.warn(`No promotionCard field in card data, doing manual check...`) console.warn(`No promotionCard field in card data, doing manual check...`)
// showPromotionCard = await fallbackMinterCheck(minterName, minterGroupMembers) showPromotionCard = await fallbackMinterCheck(minterName, minterGroupMembers)
// } else { } else {
// // If its an object or something else weird => fallback // If its an object or something else weird => fallback
// console.warn(`promotionCard has unexpected type, fallback...`) console.warn(`promotionCard has unexpected type, fallback...`)
// showPromotionCard = await fallbackMinterCheck(minterName, minterGroupMembers) showPromotionCard = await fallbackMinterCheck(minterName, minterGroupMembers)
// } }
let cardColorCode = (showPromotionCard) ? 'rgb(17, 44, 46)' : 'rgb(57, 11, 13)' let cardColorCode = (showPromotionCard) ? 'rgb(17, 44, 46)' : 'rgb(57, 11, 13)'
const promotionDemotionHtml = (showPromotionCard) ? ` const promotionDemotionHtml = (showPromotionCard) ? `
<div class="support-header"><h5> REGARDING (Promotion): </h5></div> <div class="support-header"><h5> REGARDING (Promotion): </h5></div>
${minterAvatar}
<h3>${minterName}</h3>` : <h3>${minterName}</h3>` :
` `
<div class="support-header"><h5> REGARDING (Demotion): </h5></div> <div class="support-header"><h5> REGARDING (Demotion): </h5></div>
@ -807,8 +786,8 @@ const createARCardHTML = async (cardData, pollResults, cardIdentifier, commentCo
createModal('links') createModal('links')
createModal('poll-details') createModal('poll-details')
let actionsHtml let actionsHtml = ''
let altText let altText = ''
const verifiedName = await validateMinterName(minterName) const verifiedName = await validateMinterName(minterName)
if (verifiedName) { if (verifiedName) {
@ -847,7 +826,7 @@ const createARCardHTML = async (cardData, pollResults, cardIdentifier, commentCo
} }
} else { } else {
console.log(`name could not be validated, assuming topic card (or some other issue with name validation) for removalActions`) console.warn(`name could not be validated, not setting actionsHtml`)
actionsHtml = '' actionsHtml = ''
} }

View File

@ -658,8 +658,8 @@ const publishCard = async (cardIdentifierPrefix) => {
const minterGroupData = await fetchMinterGroupMembers() const minterGroupData = await fetchMinterGroupMembers()
const minterGroupAddresses = minterGroupData.map(m => m.member) const minterGroupAddresses = minterGroupData.map(m => m.member)
const userAddress = userState.accountAddress
const userAddress = userState.accountAddress;
if (minterGroupAddresses.includes(userAddress)) { if (minterGroupAddresses.includes(userAddress)) {
alert("You are already a Minter and cannot publish a new card!") alert("You are already a Minter and cannot publish a new card!")
return return
@ -991,7 +991,6 @@ const postComment = async (cardIdentifier) => {
data64: base64CommentData, data64: base64CommentData,
}) })
alert('Comment posted successfully!')
commentInput.value = '' commentInput.value = ''
} catch (error) { } catch (error) {
console.error('Error posting comment:', error) console.error('Error posting comment:', error)

View File

@ -802,9 +802,9 @@ const searchAllWithOffset = async (service, query, limit, offset, room) => {
} }
} }
// NOTE - This function does a search and will return EITHER AN ARRAY OR A SINGLE OBJECT. if you want to guarantee a single object, pass 1 as limit. i.e. await searchSimple(service, identifier, "", 1) will return a single object. // NOTE - This function does a search and will return EITHER AN ARRAY OR A SINGLE OBJECT. if you want to guarantee a single object, pass 1 as limit. i.e. await searchSimple(service, identifier, "", 1) will return a single object.
const searchSimple = async (service, identifier, name, limit = 1500, offset = 0, room='', reverse='true') => { const searchSimple = async (service, identifier, name, limit=1500, offset=0, room='', reverse=true, prefixOnly=true) => {
try { try {
let urlSuffix = `service=${service}&identifier=${identifier}&name=${name}&prefix=true&limit=${limit}&offset=${offset}&reverse=${reverse}` let urlSuffix = `service=${service}&identifier=${identifier}&name=${name}&prefix=true&limit=${limit}&offset=${offset}&reverse=${reverse}&prefix=${prefixOnly}`
if (name && !identifier && !room) { if (name && !identifier && !room) {
console.log('name only searchSimple', name) console.log('name only searchSimple', name)

View File

@ -42,7 +42,7 @@
</a> </a>
</span> </span>
<span class="navbar-caption-wrap"> <span class="navbar-caption-wrap">
<a class="navbar-caption display-4" href="index.html">Q-Mintership (v1.01b) <a class="navbar-caption display-4" href="index.html">Q-Mintership (v1.02b)
</a> </a>
</span> </span>
</div> </div>
@ -61,7 +61,7 @@
<img src="assets/images/again-edited-qortal-minting-icon-156x156.png" alt=""> <img src="assets/images/again-edited-qortal-minting-icon-156x156.png" alt="">
</a> </a>
</span> </span>
<span class="navbar-caption-wrap"><a class="navbar-caption text-primary display-4" href="index.html">Q-Mintership v1.01b<br></a></span> <span class="navbar-caption-wrap"><a class="navbar-caption text-primary display-4" href="index.html">Q-Mintership v1.02b<br></a></span>
</div> </div>
<ul class="navbar-nav nav-dropdown" data-app-modern-menu="true"><li class="nav-item"><a class="nav-link link text-primary display-7" href="MINTERSHIP-FORUM"></a></li></ul> <ul class="navbar-nav nav-dropdown" data-app-modern-menu="true"><li class="nav-item"><a class="nav-link link text-primary display-7" href="MINTERSHIP-FORUM"></a></li></ul>
@ -93,7 +93,7 @@
<div class="item-wrapper"> <div class="item-wrapper">
<img src="assets/images/mbr-1623x1112.jpg" alt="Mintership Forum" data-slide-to="0" data-bs-slide-to="0"> <img src="assets/images/mbr-1623x1112.jpg" alt="Mintership Forum" data-slide-to="0" data-bs-slide-to="0">
<div class="item-content"> <div class="item-content">
<h2 class="card-title mbr-fonts-style display-2">New Minters - Start Here</h2> <h2 class="card-title mbr-fonts-style display-2">Minting Rights? - Start Here - MinterBoard</h2>
</div> </div>
</div> </div>
</a> </a>
@ -191,6 +191,24 @@
<section data-bs-version="5.1" class="content7 boldm5 cid-uufIRKtXOO" id="content7-6"> <section data-bs-version="5.1" class="content7 boldm5 cid-uufIRKtXOO" id="content7-6">
<div class="container">
<div class="row">
<div class="col-12 col-lg-7 card">
<div class="title-wrapper">
<h2 class="mbr-section-title mbr-fonts-style display-2">
v1.02beta 01-22-2025</h2>
</div>
</div>
<div class="col-12 col-lg-5 card">
<div class="text-wrapper">
<p class="mbr-text mbr-fonts-style display-7">
<b><u>v1.02b Fixes</u></b>- <b>There were publish issues on ARA Board</b> - These publish issues have now been resolved. DUPLICATES ARE NOT ALLOWED, and if you did not publish a card for a name, you cannot publish an update. Also removed the 'alert' for comment publish, as it was unnecessary. Also resolved an issue preventing a user from publishing more than a single card (regardless of duplicates).
</p>
</div>
</div>
</div>
</div>
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-12 col-lg-7 card"> <div class="col-12 col-lg-7 card">
@ -202,7 +220,8 @@
<div class="col-12 col-lg-5 card"> <div class="col-12 col-lg-5 card">
<div class="text-wrapper"> <div class="text-wrapper">
<p class="mbr-text mbr-fonts-style display-7"> <p class="mbr-text mbr-fonts-style display-7">
<b><u>v1.01b Major changes in 1.0.</u></b>- <b>Every feature required for the new featureTriggers have been added, and a minor bug on the ARA Board has been resolved. Pull Request from QuickMythril has also been added. Allowing cards to be arranged based on various parameters. </b> <b><u>v1.01b - Improving Major changes in 1.0.</u></b>- <b>Every feature required for the new featureTriggers have been added</b>, and a minor bug on the ARA Board has been resolved. Pull Request from QuickMythril has also been added. Allowing cards to be arranged based on various parameters.
</p>
</div> </div>
</div> </div>
</div> </div>
@ -517,12 +536,12 @@
<div class="title-wrapper"> <div class="title-wrapper">
<div class="title-wrap"> <div class="title-wrap">
<img src="assets/images/again-edited-qortal-minting-icon-156x156.png" alt=""> <img src="assets/images/again-edited-qortal-minting-icon-156x156.png" alt="">
<h2 class="mbr-section-title mbr-fonts-style display-5">Q-Mintership (v1.01b)</h2> <h2 class="mbr-section-title mbr-fonts-style display-5">Q-Mintership (v1.02b)</h2>
</div> </div>
</div> </div>
<a class="link-wrap" href="#"> <a class="link-wrap" href="#">
<p class="mbr-link mbr-fonts-style display-4">Q-Mintership v1.01beta</p> <p class="mbr-link mbr-fonts-style display-4">Q-Mintership v1.02beta</p>
</a> </a>
</div> </div>
<div class="col-12 col-lg-6"> <div class="col-12 col-lg-6">