added colorized comments based on poll results, and resolved image display issues for large images on forum posts.
This commit is contained in:
parent
10d4f09af3
commit
999b94f5e5
@ -369,36 +369,43 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.attachment button {
|
.attachment button {
|
||||||
align-self: flex-end;
|
align-self: flex-end;
|
||||||
margin-top: 0.8vh;
|
margin-top: 0.8vh;
|
||||||
background-color: #0f364c;
|
background-color: #0f364c;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
border-style: ridge;
|
border-style: ridge;
|
||||||
border-radius: 1vh;
|
border-radius: 1vh;
|
||||||
padding: 0.15vh 0.3vh;
|
padding: 0.15vh 0.3vh;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.image-modal {
|
.image-modal {
|
||||||
display: none; /* Hidden by default */
|
display: none; /* Hidden by default */
|
||||||
position: fixed; /* Stay in place */
|
position: fixed; /* Stay in place */
|
||||||
z-index: 1000; /* Sit on top */
|
z-index: 1000; /* Sit on top */
|
||||||
left: 10%;
|
/* left: 15%;
|
||||||
top: 15%;
|
top: 15%; */
|
||||||
width: 80%;
|
width: 85%;
|
||||||
height: 70%;
|
height: 75%;
|
||||||
overflow: none; /* Enable scroll if needed */
|
overflow: none; /* Enable scroll if needed */
|
||||||
background-color: rgba(0, 0, 0, 0.8); /* Black w/ opacity */
|
background-color: rgba(0, 0, 0, 0.8); /* Black w/ opacity */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.image-modal img {
|
||||||
|
max-width: 95%;
|
||||||
|
max-height: 95%;
|
||||||
|
object-fit: contain; /* Ensures the image maintains its aspect ratio */
|
||||||
|
}
|
||||||
|
|
||||||
.remove-image-button {
|
.remove-image-button {
|
||||||
background-color: #0f4c41;
|
background-color: #0f4c41;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
border: dotted;
|
border: dotted;
|
||||||
border-radius: 1vh;
|
border-radius: 1vh;
|
||||||
padding: 0.3vh 0.6vh;
|
padding: 0.3vh 0.6vh;
|
||||||
margin-top: 1px;
|
margin-top: 1px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-content {
|
.modal-content {
|
||||||
|
@ -182,7 +182,6 @@ const extractEncryptedCardsMinterName = (cardIdentifier) => {
|
|||||||
const processCards = async (validEncryptedCards) => {
|
const processCards = async (validEncryptedCards) => {
|
||||||
const latestCardsMap = new Map()
|
const latestCardsMap = new Map()
|
||||||
|
|
||||||
// Step 1: Process all cards in parallel
|
|
||||||
await Promise.all(validEncryptedCards.map(async card => {
|
await Promise.all(validEncryptedCards.map(async card => {
|
||||||
const timestamp = card.updated || card.created || 0
|
const timestamp = card.updated || card.created || 0
|
||||||
const existingCard = latestCardsMap.get(card.identifier)
|
const existingCard = latestCardsMap.get(card.identifier)
|
||||||
@ -194,7 +193,6 @@ const processCards = async (validEncryptedCards) => {
|
|||||||
|
|
||||||
console.log(`latestCardsMap, by timestamp`, latestCardsMap)
|
console.log(`latestCardsMap, by timestamp`, latestCardsMap)
|
||||||
|
|
||||||
// Step 2: Extract unique cards
|
|
||||||
const uniqueValidCards = Array.from(latestCardsMap.values())
|
const uniqueValidCards = Array.from(latestCardsMap.values())
|
||||||
|
|
||||||
return uniqueValidCards
|
return uniqueValidCards
|
||||||
@ -380,7 +378,7 @@ const fetchExistingEncryptedCard = async (minterName, existingIdentifier) => {
|
|||||||
return decryptedCardData
|
return decryptedCardData
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching existing card:", error);
|
console.error("Error fetching existing card:", error)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -610,7 +608,7 @@ const fetchEncryptedComments = async (cardIdentifier) => {
|
|||||||
try {
|
try {
|
||||||
const response = await searchSimple('MAIL_PRIVATE', `comment-${cardIdentifier}`, '', 0, 0, '', false)
|
const response = await searchSimple('MAIL_PRIVATE', `comment-${cardIdentifier}`, '', 0, 0, '', false)
|
||||||
if (response) {
|
if (response) {
|
||||||
return response;
|
return response
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error fetching comments for ${cardIdentifier}:`, error)
|
console.error(`Error fetching comments for ${cardIdentifier}:`, error)
|
||||||
@ -619,38 +617,109 @@ const fetchEncryptedComments = async (cardIdentifier) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// display the comments on the card, with passed cardIdentifier to identify the card --------------
|
// display the comments on the card, with passed cardIdentifier to identify the card --------------
|
||||||
|
// const displayEncryptedComments = async (cardIdentifier) => {
|
||||||
|
// try {
|
||||||
|
// const comments = await fetchEncryptedComments(cardIdentifier)
|
||||||
|
// const commentsContainer = document.getElementById(`comments-container-${cardIdentifier}`)
|
||||||
|
|
||||||
|
// for (const comment of comments) {
|
||||||
|
// const commentDataResponse = await qortalRequest({
|
||||||
|
// action: "FETCH_QDN_RESOURCE",
|
||||||
|
// name: comment.name,
|
||||||
|
// service: "MAIL_PRIVATE",
|
||||||
|
// identifier: comment.identifier,
|
||||||
|
// encoding: "base64"
|
||||||
|
// })
|
||||||
|
|
||||||
|
// const decryptedCommentData = await decryptAndParseObject(commentDataResponse)
|
||||||
|
// const timestampCheck = comment.updated || comment.created || 0
|
||||||
|
// const timestamp = await timestampToHumanReadableDate(timestampCheck)
|
||||||
|
// //TODO - add fetching of poll results and checking to see if the commenter has voted and display it as 'supports minter' section.
|
||||||
|
// const commentHTML = `
|
||||||
|
// <div class="comment" style="border: 1px solid gray; margin: 1vh 0; padding: 1vh; background: #1c1c1c;">
|
||||||
|
// <p><strong><u>${decryptedCommentData.creator}</strong>:</p></u>
|
||||||
|
// <p>${decryptedCommentData.content}</p>
|
||||||
|
// <p><i>${timestamp}</p></i>
|
||||||
|
// </div>
|
||||||
|
// `
|
||||||
|
// commentsContainer.insertAdjacentHTML('beforeend', commentHTML)
|
||||||
|
// }
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error(`Error displaying comments (or no comments) for ${cardIdentifier}:`, error)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//TODO testing this update to the comments fetching to improve performance by leveraging promise.all
|
||||||
const displayEncryptedComments = async (cardIdentifier) => {
|
const displayEncryptedComments = async (cardIdentifier) => {
|
||||||
try {
|
try {
|
||||||
const comments = await fetchEncryptedComments(cardIdentifier)
|
const comments = await fetchEncryptedComments(cardIdentifier)
|
||||||
const commentsContainer = document.getElementById(`comments-container-${cardIdentifier}`)
|
const commentsContainer = document.getElementById(`comments-container-${cardIdentifier}`)
|
||||||
|
|
||||||
for (const comment of comments) {
|
|
||||||
const commentDataResponse = await qortalRequest({
|
|
||||||
action: "FETCH_QDN_RESOURCE",
|
|
||||||
name: comment.name,
|
|
||||||
service: "MAIL_PRIVATE",
|
|
||||||
identifier: comment.identifier,
|
|
||||||
encoding: "base64"
|
|
||||||
})
|
|
||||||
|
|
||||||
const decryptedCommentData = await decryptAndParseObject(commentDataResponse)
|
commentsContainer.innerHTML = ''
|
||||||
const timestampCheck = comment.updated || comment.created || 0
|
|
||||||
const timestamp = await timestampToHumanReadableDate(timestampCheck)
|
const voterMap = globalVoterMap.get(cardIdentifier) || new Map()
|
||||||
//TODO - add fetching of poll results and checking to see if the commenter has voted and display it as 'supports minter' section.
|
|
||||||
const commentHTML = `
|
const commentHTMLArray = await Promise.all(
|
||||||
<div class="comment" style="border: 1px solid gray; margin: 1vh 0; padding: 1vh; background: #1c1c1c;">
|
comments.map(async (comment) => {
|
||||||
<p><strong><u>${decryptedCommentData.creator}</strong>:</p></u>
|
try {
|
||||||
<p>${decryptedCommentData.content}</p>
|
const commentDataResponse = await qortalRequest({
|
||||||
<p><i>${timestamp}</p></i>
|
action: "FETCH_QDN_RESOURCE",
|
||||||
</div>
|
name: comment.name,
|
||||||
`
|
service: "MAIL_PRIVATE",
|
||||||
commentsContainer.insertAdjacentHTML('beforeend', commentHTML)
|
identifier: comment.identifier,
|
||||||
}
|
encoding: "base64",
|
||||||
|
})
|
||||||
|
|
||||||
|
const decryptedCommentData = await decryptAndParseObject(commentDataResponse)
|
||||||
|
const timestampCheck = comment.updated || comment.created || 0
|
||||||
|
const timestamp = await timestampToHumanReadableDate(timestampCheck)
|
||||||
|
|
||||||
|
const commenter = decryptedCommentData.creator
|
||||||
|
const voterInfo = voterMap.get(commenter)
|
||||||
|
|
||||||
|
let commentColor = "transparent"
|
||||||
|
let adminBadge = ""
|
||||||
|
|
||||||
|
if (voterInfo) {
|
||||||
|
if (voterInfo.voterType === "Admin") {
|
||||||
|
// Admin-specific colors
|
||||||
|
commentColor = voterInfo.vote === "yes" ? "rgba(25, 175, 25, 0.6)" : "rgba(194, 39, 62, 0.6)" // Light green for yes, light red for no
|
||||||
|
const badgeColor = voterInfo.vote === "yes" ? "green" : "red"
|
||||||
|
adminBadge = `<span style="color: ${badgeColor}; font-weight: bold; margin-left: 0.5em;">(Admin)</span>`
|
||||||
|
} else {
|
||||||
|
// Non-admin colors
|
||||||
|
commentColor = voterInfo.vote === "yes" ? "rgba(0, 100, 0, 0.3)" : "rgba(100, 0, 0, 0.3)" // Darker green for yes, darker red for no
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return `
|
||||||
|
<div class="comment" style="border: 1px solid gray; margin: 1vh 0; padding: 1vh; background: ${commentColor};">
|
||||||
|
<p>
|
||||||
|
<strong><u>${decryptedCommentData.creator}</u></strong>
|
||||||
|
${adminBadge}
|
||||||
|
</p>
|
||||||
|
<p>${decryptedCommentData.content}</p>
|
||||||
|
<p><i>${timestamp}</i></p>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Error processing comment ${comment.identifier}:`, err)
|
||||||
|
return null // Skip this comment if it fails
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
// Add all comments to the container
|
||||||
|
commentHTMLArray
|
||||||
|
.filter((html) => html !== null) // Filter out failed comments
|
||||||
|
.forEach((commentHTML) => {
|
||||||
|
commentsContainer.insertAdjacentHTML('beforeend', commentHTML)
|
||||||
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error displaying comments (or no comments) for ${cardIdentifier}:`, error)
|
console.error(`Error displaying comments (or no comments) for ${cardIdentifier}:`, error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const toggleEncryptedComments = async (cardIdentifier) => {
|
const toggleEncryptedComments = async (cardIdentifier) => {
|
||||||
const commentsSection = document.getElementById(`comments-section-${cardIdentifier}`)
|
const commentsSection = document.getElementById(`comments-section-${cardIdentifier}`)
|
||||||
const commentButton = document.getElementById(`comment-button-${cardIdentifier}`)
|
const commentButton = document.getElementById(`comment-button-${cardIdentifier}`)
|
||||||
@ -689,25 +758,25 @@ const createLinkDisplayModal = async () => {
|
|||||||
// Function to open the modal
|
// Function to open the modal
|
||||||
const openLinkDisplayModal = async (link) => {
|
const openLinkDisplayModal = async (link) => {
|
||||||
const processedLink = await processQortalLinkForRendering(link) // Process the link to replace `qortal://` for rendering in modal
|
const processedLink = await processQortalLinkForRendering(link) // Process the link to replace `qortal://` for rendering in modal
|
||||||
const modal = document.getElementById('links-modal');
|
const modal = document.getElementById('links-modal')
|
||||||
const modalContent = document.getElementById('links-modalContent');
|
const modalContent = document.getElementById('links-modalContent')
|
||||||
modalContent.src = processedLink; // Set the iframe source to the link
|
modalContent.src = processedLink // Set the iframe source to the link
|
||||||
modal.style.display = 'block'; // Show the modal
|
modal.style.display = 'block' // Show the modal
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to close the modal
|
// Function to close the modal
|
||||||
const closeLinkDisplayModal = async () => {
|
const closeLinkDisplayModal = async () => {
|
||||||
const modal = document.getElementById('links-modal');
|
const modal = document.getElementById('links-modal')
|
||||||
const modalContent = document.getElementById('links-modalContent');
|
const modalContent = document.getElementById('links-modalContent')
|
||||||
modal.style.display = 'none'; // Hide the modal
|
modal.style.display = 'none' // Hide the modal
|
||||||
modalContent.src = ''; // Clear the iframe source
|
modalContent.src = '' // Clear the iframe source
|
||||||
}
|
}
|
||||||
|
|
||||||
const processQortalLinkForRendering = async (link) => {
|
const processQortalLinkForRendering = async (link) => {
|
||||||
if (link.startsWith('qortal://')) {
|
if (link.startsWith('qortal://')) {
|
||||||
const match = link.match(/^qortal:\/\/([^/]+)(\/.*)?$/)
|
const match = link.match(/^qortal:\/\/([^/]+)(\/.*)?$/)
|
||||||
if (match) {
|
if (match) {
|
||||||
const firstParam = match[1].toUpperCase();
|
const firstParam = match[1].toUpperCase()
|
||||||
const remainingPath = match[2] || ""
|
const remainingPath = match[2] || ""
|
||||||
const themeColor = window._qdnTheme || 'default' // Fallback to 'default' if undefined
|
const themeColor = window._qdnTheme || 'default' // Fallback to 'default' if undefined
|
||||||
// Simulating async operation if needed
|
// Simulating async operation if needed
|
||||||
@ -776,7 +845,7 @@ const createEncryptedCardHTML = async (cardData, pollResults, cardIdentifier, co
|
|||||||
|
|
||||||
const minterGroupMembers = await fetchMinterGroupMembers()
|
const minterGroupMembers = await fetchMinterGroupMembers()
|
||||||
const minterAdmins = await fetchMinterGroupAdmins()
|
const minterAdmins = await fetchMinterGroupAdmins()
|
||||||
const { adminYes = 0, adminNo = 0, minterYes = 0, minterNo = 0, totalYes = 0, totalNo = 0, totalYesWeight = 0, totalNoWeight = 0, detailsHtml } = await processPollData(pollResults, minterGroupMembers, minterAdmins, creator)
|
const { adminYes = 0, adminNo = 0, minterYes = 0, minterNo = 0, totalYes = 0, totalNo = 0, totalYesWeight = 0, totalNoWeight = 0, detailsHtml } = await processPollData(pollResults, minterGroupMembers, minterAdmins, creator, cardIdentifier)
|
||||||
createModal('links')
|
createModal('links')
|
||||||
createModal('poll-details')
|
createModal('poll-details')
|
||||||
return `
|
return `
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
// // NOTE - Change isTestMode to false prior to actual release ---- !important - You may also change identifier if you want to not show older cards.
|
// // NOTE - Change isTestMode to false prior to actual release ---- !important - You may also change identifier if you want to not show older cards.
|
||||||
const testMode = false;
|
const testMode = false
|
||||||
const cardIdentifierPrefix = "Minter-board-card";
|
const cardIdentifierPrefix = "Minter-board-card"
|
||||||
let isExistingCard = false;
|
let isExistingCard = false
|
||||||
let existingCardData = {};
|
let existingCardData = {}
|
||||||
let existingCardIdentifier = {};
|
let existingCardIdentifier = {}
|
||||||
|
|
||||||
const loadMinterBoardPage = async () => {
|
const loadMinterBoardPage = async () => {
|
||||||
// Clear existing content on the page
|
// 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--) {
|
for (let i = bodyChildren.length - 1; i >= 0; i--) {
|
||||||
const child = bodyChildren[i];
|
const child = bodyChildren[i];
|
||||||
if (!child.classList.contains("menu")) {
|
if (!child.classList.contains("menu")) {
|
||||||
child.remove();
|
child.remove()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the "Minter Board" content
|
// Add the "Minter Board" content
|
||||||
const mainContent = document.createElement("div");
|
const mainContent = document.createElement("div")
|
||||||
const publishButtonColor = '#527c9d'
|
const publishButtonColor = '#527c9d'
|
||||||
const minterBoardNameColor = '#527c9d'
|
const minterBoardNameColor = '#527c9d'
|
||||||
mainContent.innerHTML = `
|
mainContent.innerHTML = `
|
||||||
@ -43,78 +43,78 @@ const loadMinterBoardPage = async () => {
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`
|
||||||
document.body.appendChild(mainContent);
|
document.body.appendChild(mainContent)
|
||||||
|
|
||||||
document.getElementById("publish-card-button").addEventListener("click", async () => {
|
document.getElementById("publish-card-button").addEventListener("click", async () => {
|
||||||
try {
|
try {
|
||||||
const fetchedCard = await fetchExistingCard();
|
const fetchedCard = await fetchExistingCard()
|
||||||
if (fetchedCard) {
|
if (fetchedCard) {
|
||||||
// An existing card is found
|
// An existing card is found
|
||||||
if (testMode) {
|
if (testMode) {
|
||||||
// In test mode, ask user what to do
|
// In test mode, ask user what to do
|
||||||
const updateCard = confirm("A card already exists. Do you want to update it?");
|
const updateCard = confirm("A card already exists. Do you want to update it?")
|
||||||
if (updateCard) {
|
if (updateCard) {
|
||||||
isExistingCard = true;
|
isExistingCard = true
|
||||||
await loadCardIntoForm(existingCardData);
|
await loadCardIntoForm(existingCardData)
|
||||||
alert("Edit your existing card and publish.");
|
alert("Edit your existing card and publish.")
|
||||||
} else {
|
} else {
|
||||||
alert("Test mode: You can now create a new card.");
|
alert("Test mode: You can now create a new card.")
|
||||||
isExistingCard = false;
|
isExistingCard = false
|
||||||
existingCardData = {}; // Reset
|
existingCardData = {}
|
||||||
document.getElementById("publish-card-form").reset();
|
document.getElementById("publish-card-form").reset()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Not in test mode, force editing
|
// Not in test mode, force editing
|
||||||
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(existingCardData);
|
await loadCardIntoForm(existingCardData)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// No existing card found
|
// No existing card found
|
||||||
console.log("No existing card found. Creating a new card.");
|
console.log("No existing card found. Creating a new card.")
|
||||||
isExistingCard = false;
|
isExistingCard = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show the form
|
// Show the form
|
||||||
const publishCardView = document.getElementById("publish-card-view");
|
const publishCardView = document.getElementById("publish-card-view")
|
||||||
publishCardView.style.display = "flex";
|
publishCardView.style.display = "flex";
|
||||||
document.getElementById("cards-container").style.display = "none";
|
document.getElementById("cards-container").style.display = "none"
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error checking for existing card:", error);
|
console.error("Error checking for existing card:", error)
|
||||||
alert("Failed to check for existing card. Please try again.");
|
alert("Failed to check for existing card. Please try again.")
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
document.getElementById("refresh-cards-button").addEventListener("click", async () => {
|
document.getElementById("refresh-cards-button").addEventListener("click", async () => {
|
||||||
const cardsContainer = document.getElementById("cards-container");
|
const cardsContainer = document.getElementById("cards-container")
|
||||||
cardsContainer.innerHTML = "<p>Refreshing cards...</p>";
|
cardsContainer.innerHTML = "<p>Refreshing cards...</p>"
|
||||||
await loadCards();
|
await loadCards();
|
||||||
});
|
})
|
||||||
|
|
||||||
|
|
||||||
document.getElementById("cancel-publish-button").addEventListener("click", async () => {
|
document.getElementById("cancel-publish-button").addEventListener("click", async () => {
|
||||||
const cardsContainer = document.getElementById("cards-container");
|
const cardsContainer = document.getElementById("cards-container")
|
||||||
cardsContainer.style.display = "flex"; // Restore visibility
|
cardsContainer.style.display = "flex"; // Restore visibility
|
||||||
const publishCardView = document.getElementById("publish-card-view");
|
const publishCardView = document.getElementById("publish-card-view")
|
||||||
publishCardView.style.display = "none"; // Hide the publish form
|
publishCardView.style.display = "none"; // Hide the publish form
|
||||||
});
|
})
|
||||||
|
|
||||||
document.getElementById("add-link-button").addEventListener("click", async () => {
|
document.getElementById("add-link-button").addEventListener("click", async () => {
|
||||||
const linksContainer = document.getElementById("links-container");
|
const linksContainer = document.getElementById("links-container")
|
||||||
const newLinkInput = document.createElement("input");
|
const newLinkInput = document.createElement("input")
|
||||||
newLinkInput.type = "text";
|
newLinkInput.type = "text"
|
||||||
newLinkInput.className = "card-link";
|
newLinkInput.className = "card-link"
|
||||||
newLinkInput.placeholder = "Enter QDN link";
|
newLinkInput.placeholder = "Enter QDN link"
|
||||||
linksContainer.appendChild(newLinkInput);
|
linksContainer.appendChild(newLinkInput)
|
||||||
});
|
})
|
||||||
|
|
||||||
document.getElementById("publish-card-form").addEventListener("submit", async (event) => {
|
document.getElementById("publish-card-form").addEventListener("submit", async (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault()
|
||||||
await publishCard();
|
await publishCard()
|
||||||
});
|
})
|
||||||
|
|
||||||
await loadCards();
|
await loadCards()
|
||||||
}
|
}
|
||||||
|
|
||||||
const extractMinterCardsMinterName = async (cardIdentifier) => {
|
const extractMinterCardsMinterName = async (cardIdentifier) => {
|
||||||
@ -343,7 +343,6 @@ const fetchExistingCard = async () => {
|
|||||||
existingCardData = cardDataResponse
|
existingCardData = cardDataResponse
|
||||||
|
|
||||||
return cardDataResponse
|
return cardDataResponse
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const validatedCards = await Promise.all(
|
const validatedCards = await Promise.all(
|
||||||
@ -406,7 +405,7 @@ const loadCardIntoForm = async (cardData) => {
|
|||||||
linkInput.type = "text"
|
linkInput.type = "text"
|
||||||
linkInput.className = "card-link"
|
linkInput.className = "card-link"
|
||||||
linkInput.value = link;
|
linkInput.value = link;
|
||||||
linksContainer.appendChild(linkInput);
|
linksContainer.appendChild(linkInput)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,7 +418,7 @@ const publishCard = async () => {
|
|||||||
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
|
||||||
}
|
}
|
||||||
const header = document.getElementById("card-header").value.trim()
|
const header = document.getElementById("card-header").value.trim()
|
||||||
const content = document.getElementById("card-content").value.trim()
|
const content = document.getElementById("card-content").value.trim()
|
||||||
@ -487,7 +486,9 @@ const publishCard = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const processPollData= async (pollData, minterGroupMembers, minterAdmins, creator) => {
|
let globalVoterMap = new Map()
|
||||||
|
|
||||||
|
const processPollData= async (pollData, minterGroupMembers, minterAdmins, creator, cardIdentifier) => {
|
||||||
if (!pollData || !Array.isArray(pollData.voteWeights) || !Array.isArray(pollData.votes)) {
|
if (!pollData || !Array.isArray(pollData.voteWeights) || !Array.isArray(pollData.votes)) {
|
||||||
console.warn("Poll data is missing or invalid. pollData:", pollData)
|
console.warn("Poll data is missing or invalid. pollData:", pollData)
|
||||||
return {
|
return {
|
||||||
@ -574,6 +575,29 @@ const processPollData= async (pollData, minterGroupMembers, minterAdmins, creato
|
|||||||
blocksMinted
|
blocksMinted
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
//TODO verify this new voterPromises async function works better.
|
||||||
|
// const voterPromises = pollData.votes.map(async (vote) => {
|
||||||
|
// const voterPublicKey = vote.voterPublicKey;
|
||||||
|
// const voterAddress = await getAddressFromPublicKey(voterPublicKey);
|
||||||
|
|
||||||
|
// const [nameInfo, addressInfo] = await Promise.all([
|
||||||
|
// getNameFromAddress(voterAddress).catch(() => ""),
|
||||||
|
// getAddressInfo(voterAddress).catch(() => ({})),
|
||||||
|
// ]);
|
||||||
|
|
||||||
|
// const voterName = nameInfo || (nameInfo === voterAddress ? "" : voterAddress);
|
||||||
|
// const blocksMinted = addressInfo?.blocksMinted || 0;
|
||||||
|
|
||||||
|
// return {
|
||||||
|
// optionIndex: vote.optionIndex,
|
||||||
|
// voterPublicKey,
|
||||||
|
// voterAddress,
|
||||||
|
// voterName,
|
||||||
|
// isAdmin: adminAddresses.includes(voterAddress),
|
||||||
|
// isMinter: memberAddresses.includes(voterAddress),
|
||||||
|
// blocksMinted,
|
||||||
|
// };
|
||||||
|
// });
|
||||||
|
|
||||||
const allVoters = await Promise.all(voterPromises)
|
const allVoters = await Promise.all(voterPromises)
|
||||||
const yesVoters = []
|
const yesVoters = []
|
||||||
@ -591,8 +615,11 @@ const processPollData= async (pollData, minterGroupMembers, minterAdmins, creato
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
yesVoters.sort((a,b) => b.blocksMinted - a.blocksMinted);
|
yesVoters.sort((a,b) => b.blocksMinted - a.blocksMinted)
|
||||||
noVoters.sort((a,b) => b.blocksMinted - a.blocksMinted);
|
noVoters.sort((a,b) => b.blocksMinted - a.blocksMinted)
|
||||||
|
const sortedAllVoters = allVoters.sort((a,b) => b.blocksMinted - a.blocksMinted)
|
||||||
|
await createVoterMap(sortedAllVoters, cardIdentifier)
|
||||||
|
|
||||||
const yesTableHtml = buildVotersTableHtml(yesVoters, /* tableColor= */ "green")
|
const yesTableHtml = buildVotersTableHtml(yesVoters, /* tableColor= */ "green")
|
||||||
const noTableHtml = buildVotersTableHtml(noVoters, /* tableColor= */ "red")
|
const noTableHtml = buildVotersTableHtml(noVoters, /* tableColor= */ "red")
|
||||||
const detailsHtml = `
|
const detailsHtml = `
|
||||||
@ -620,13 +647,26 @@ const processPollData= async (pollData, minterGroupMembers, minterAdmins, creato
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const createVoterMap = async (voters, cardIdentifier) => {
|
||||||
|
const voterMap = new Map()
|
||||||
|
voters.forEach((voter) => {
|
||||||
|
const voterNameOrAddress = voter.voterName || voter.voterAddress
|
||||||
|
voterMap.set(voterNameOrAddress, {
|
||||||
|
vote: voter.optionIndex === 0 ? "yes" : "no", // Use optionIndex directly
|
||||||
|
voterType: voter.isAdmin ? "Admin" : voter.isMinter ? "Minter" : "User",
|
||||||
|
blocksMinted: voter.blocksMinted,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
globalVoterMap.set(cardIdentifier, voterMap)
|
||||||
|
}
|
||||||
|
|
||||||
const buildVotersTableHtml = (voters, tableColor) => {
|
const buildVotersTableHtml = (voters, tableColor) => {
|
||||||
if (!voters.length) {
|
if (!voters.length) {
|
||||||
return `<p>No voters here.</p>`;
|
return `<p>No voters here.</p>`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decide extremely dark background for the <tbody>
|
// Decide extremely dark background for the <tbody>
|
||||||
let bodyBackground;
|
let bodyBackground
|
||||||
if (tableColor === "green") {
|
if (tableColor === "green") {
|
||||||
bodyBackground = "rgba(0, 18, 0, 0.8)" // near-black green
|
bodyBackground = "rgba(0, 18, 0, 0.8)" // near-black green
|
||||||
} else if (tableColor === "red") {
|
} else if (tableColor === "red") {
|
||||||
@ -661,7 +701,7 @@ const buildVotersTableHtml = (voters, tableColor) => {
|
|||||||
<tbody style="background-color: ${bodyBackground}; color: #c6c6c6;">
|
<tbody style="background-color: ${bodyBackground}; color: #c6c6c6;">
|
||||||
${voters
|
${voters
|
||||||
.map(v => {
|
.map(v => {
|
||||||
const userType = v.isAdmin ? "Admin" : v.isMinter ? "Minter" : "User";
|
const userType = v.isAdmin ? "Admin" : v.isMinter ? "Minter" : "User"
|
||||||
const pollName = v.pollName
|
const pollName = v.pollName
|
||||||
const displayName =
|
const displayName =
|
||||||
v.voterName
|
v.voterName
|
||||||
@ -735,29 +775,95 @@ const fetchCommentsForCard = async (cardIdentifier) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// display the comments on the card, with passed cardIdentifier to identify the card --------------
|
// display the comments on the card, with passed cardIdentifier to identify the card --------------
|
||||||
|
// const displayComments = async (cardIdentifier) => {
|
||||||
|
// try {
|
||||||
|
// const comments = await fetchCommentsForCard(cardIdentifier);
|
||||||
|
// const commentsContainer = document.getElementById(`comments-container-${cardIdentifier}`)
|
||||||
|
|
||||||
|
// for (const comment of comments) {
|
||||||
|
// const commentDataResponse = await qortalRequest({
|
||||||
|
// action: "FETCH_QDN_RESOURCE",
|
||||||
|
// name: comment.name,
|
||||||
|
// service: "BLOG_POST",
|
||||||
|
// identifier: comment.identifier,
|
||||||
|
// })
|
||||||
|
// const timestamp = await timestampToHumanReadableDate(commentDataResponse.timestamp)
|
||||||
|
// const commentHTML = `
|
||||||
|
// <div class="comment" style="border: 1px solid gray; margin: 1vh 0; padding: 1vh; background: #1c1c1c;">
|
||||||
|
// <p><strong><u>${commentDataResponse.creator}</strong>:</p></u>
|
||||||
|
// <p>${commentDataResponse.content}</p>
|
||||||
|
// <p><i>${timestamp}</p></i>
|
||||||
|
// </div>
|
||||||
|
// `
|
||||||
|
// commentsContainer.insertAdjacentHTML('beforeend', commentHTML)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error(`Error displaying comments (or no comments) for ${cardIdentifier}:`, error)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
const displayComments = async (cardIdentifier) => {
|
const displayComments = async (cardIdentifier) => {
|
||||||
try {
|
try {
|
||||||
const comments = await fetchCommentsForCard(cardIdentifier);
|
const comments = await fetchCommentsForCard(cardIdentifier)
|
||||||
const commentsContainer = document.getElementById(`comments-container-${cardIdentifier}`)
|
const commentsContainer = document.getElementById(`comments-container-${cardIdentifier}`)
|
||||||
|
|
||||||
for (const comment of comments) {
|
|
||||||
const commentDataResponse = await qortalRequest({
|
|
||||||
action: "FETCH_QDN_RESOURCE",
|
|
||||||
name: comment.name,
|
|
||||||
service: "BLOG_POST",
|
|
||||||
identifier: comment.identifier,
|
|
||||||
})
|
|
||||||
const timestamp = await timestampToHumanReadableDate(commentDataResponse.timestamp)
|
|
||||||
const commentHTML = `
|
|
||||||
<div class="comment" style="border: 1px solid gray; margin: 1vh 0; padding: 1vh; background: #1c1c1c;">
|
|
||||||
<p><strong><u>${commentDataResponse.creator}</strong>:</p></u>
|
|
||||||
<p>${commentDataResponse.content}</p>
|
|
||||||
<p><i>${timestamp}</p></i>
|
|
||||||
</div>
|
|
||||||
`
|
|
||||||
commentsContainer.insertAdjacentHTML('beforeend', commentHTML)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
commentsContainer.innerHTML = ''
|
||||||
|
|
||||||
|
const voterMap = globalVoterMap.get(cardIdentifier) || new Map()
|
||||||
|
|
||||||
|
const commentHTMLArray = await Promise.all(
|
||||||
|
comments.map(async (comment) => {
|
||||||
|
try {
|
||||||
|
const commentDataResponse = await qortalRequest({
|
||||||
|
action: "FETCH_QDN_RESOURCE",
|
||||||
|
name: comment.name,
|
||||||
|
service: "BLOG_POST",
|
||||||
|
identifier: comment.identifier,
|
||||||
|
})
|
||||||
|
|
||||||
|
const timestamp = await timestampToHumanReadableDate(commentDataResponse.timestamp);
|
||||||
|
|
||||||
|
const commenter = commentDataResponse.creator
|
||||||
|
const voterInfo = voterMap.get(commenter)
|
||||||
|
|
||||||
|
let commentColor = "transparent"
|
||||||
|
let adminBadge = ""
|
||||||
|
|
||||||
|
if (voterInfo) {
|
||||||
|
if (voterInfo.voterType === "Admin") {
|
||||||
|
|
||||||
|
commentColor = voterInfo.vote === "yes" ? "rgba(21, 150, 21, 0.6)" : "rgba(212, 37, 64, 0.6)" // Light green for yes, light red for no
|
||||||
|
const badgeColor = voterInfo.vote === "yes" ? "green" : "red"
|
||||||
|
adminBadge = `<span style="color: ${badgeColor}; font-weight: bold; margin-left: 0.5em;">(Admin)</span>`
|
||||||
|
} else {
|
||||||
|
|
||||||
|
commentColor = voterInfo.vote === "yes" ? "rgba(0, 100, 0, 0.3)" : "rgba(100, 0, 0, 0.3)" // Darker green for yes, darker red for no
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return `
|
||||||
|
<div class="comment" style="border: 1px solid gray; margin: 1vh 0; padding: 1vh; background: ${commentColor};">
|
||||||
|
<p>
|
||||||
|
<strong><u>${commentDataResponse.creator}</u></strong>
|
||||||
|
${adminBadge}
|
||||||
|
</p>
|
||||||
|
<p>${commentDataResponse.content}</p>
|
||||||
|
<p><i>${timestamp}</i></p>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Error processing comment ${comment.identifier}:`, err)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
commentHTMLArray
|
||||||
|
.filter((html) => html !== null) // Filter out failed comments
|
||||||
|
.forEach((commentHTML) => {
|
||||||
|
commentsContainer.insertAdjacentHTML('beforeend', commentHTML)
|
||||||
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error displaying comments (or no comments) for ${cardIdentifier}:`, error)
|
console.error(`Error displaying comments (or no comments) for ${cardIdentifier}:`, error)
|
||||||
}
|
}
|
||||||
@ -935,7 +1041,7 @@ const generateDarkPastelBackgroundBy = (name) => {
|
|||||||
|
|
||||||
// Create the overall Minter Card HTML -----------------------------------------------
|
// Create the overall Minter Card HTML -----------------------------------------------
|
||||||
const createCardHTML = async (cardData, pollResults, cardIdentifier, commentCount, cardUpdatedTime, BgColor) => {
|
const createCardHTML = async (cardData, pollResults, cardIdentifier, commentCount, cardUpdatedTime, BgColor) => {
|
||||||
const { header, content, links, creator, timestamp, poll } = cardData;
|
const { header, content, links, creator, timestamp, poll } = cardData
|
||||||
const formattedDate = cardUpdatedTime ? new Date(cardUpdatedTime).toLocaleString() : new Date(timestamp).toLocaleString()
|
const formattedDate = cardUpdatedTime ? new Date(cardUpdatedTime).toLocaleString() : new Date(timestamp).toLocaleString()
|
||||||
const avatarHtml = await getMinterAvatar(creator)
|
const avatarHtml = await getMinterAvatar(creator)
|
||||||
const linksHTML = links.map((link, index) => `
|
const linksHTML = links.map((link, index) => `
|
||||||
@ -946,7 +1052,7 @@ const createCardHTML = async (cardData, pollResults, cardIdentifier, commentCoun
|
|||||||
|
|
||||||
const minterGroupMembers = await fetchMinterGroupMembers()
|
const minterGroupMembers = await fetchMinterGroupMembers()
|
||||||
const minterAdmins = await fetchMinterGroupAdmins()
|
const minterAdmins = await fetchMinterGroupAdmins()
|
||||||
const { adminYes = 0, adminNo = 0, minterYes = 0, minterNo = 0, totalYes = 0, totalNo = 0, totalYesWeight = 0, totalNoWeight = 0, detailsHtml } = await processPollData(pollResults, minterGroupMembers, minterAdmins, creator)
|
const { adminYes = 0, adminNo = 0, minterYes = 0, minterNo = 0, totalYes = 0, totalNo = 0, totalYesWeight = 0, totalNoWeight = 0, detailsHtml } = await processPollData(pollResults, minterGroupMembers, minterAdmins, creator, cardIdentifier)
|
||||||
createModal('links')
|
createModal('links')
|
||||||
createModal('poll-details')
|
createModal('poll-details')
|
||||||
|
|
||||||
@ -1003,6 +1109,6 @@ const createCardHTML = async (cardData, pollResults, cardIdentifier, commentCoun
|
|||||||
</div>
|
</div>
|
||||||
<p style="font-size: 0.75rem; margin-top: 3vh; color: #4496a1">By: ${creator} - ${formattedDate}</p>
|
<p style="font-size: 0.75rem; margin-top: 3vh; color: #4496a1">By: ${creator} - ${formattedDate}</p>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user