massive modifications to both MinterBoard and forum. There are still many changes to come, but these needed to be pushed to resolve important bugs on MinterBoard for testing
This commit is contained in:
parent
f0a2a3ea58
commit
a5bf12aed2
@ -169,6 +169,45 @@
|
|||||||
padding: 1vh;
|
padding: 1vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.file-input {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-input {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Custom button styling */
|
||||||
|
.custom-file-input-button {
|
||||||
|
display: inline-block;
|
||||||
|
background-color: #07375a;
|
||||||
|
color: white;
|
||||||
|
padding: 0.5vh 0.2vh;
|
||||||
|
cursor: pointer;
|
||||||
|
border: solid white;
|
||||||
|
border-radius: 5px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-file-input-button:hover {
|
||||||
|
background-color: #073783;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-image-input-button {
|
||||||
|
display: inline-block;
|
||||||
|
background-color: #350550;
|
||||||
|
color: white;
|
||||||
|
padding: 0.5vh 0.2vh;
|
||||||
|
cursor: pointer;
|
||||||
|
border: solid white;
|
||||||
|
border-radius: 5px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-image-input-button:hover {
|
||||||
|
background-color: #4d0541;
|
||||||
|
}
|
||||||
|
|
||||||
/* .ql-editor {
|
/* .ql-editor {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
@ -338,9 +377,9 @@
|
|||||||
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: 10%;
|
||||||
top: 10%;
|
top: 15%;
|
||||||
width: 80%;
|
width: 80%;
|
||||||
height: 80%;
|
height: 70%;
|
||||||
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 */
|
||||||
}
|
}
|
||||||
@ -349,7 +388,7 @@
|
|||||||
margin: auto;
|
margin: auto;
|
||||||
display: block;
|
display: block;
|
||||||
border: 2px dashed #638b93;
|
border: 2px dashed #638b93;
|
||||||
width: 60%;
|
width: 69%;
|
||||||
height: auto;
|
height: auto;
|
||||||
max-width: 1200vh;
|
max-width: 1200vh;
|
||||||
}
|
}
|
||||||
@ -436,10 +475,12 @@ body {
|
|||||||
/* Publish Card View */
|
/* Publish Card View */
|
||||||
.publish-card-view {
|
.publish-card-view {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
text-align: left;
|
||||||
justify-content: center; /* Centers vertically */
|
padding: 0em;
|
||||||
align-items: center; /* Centers horizontally */
|
flex-wrap: wrap;
|
||||||
min-height: 80vh; /* Ensures the view takes full height of the viewport */
|
align-content: flex-start;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
async function loadMinterBoardPage() {
|
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--) {
|
||||||
@ -67,7 +67,7 @@ async function loadMinterBoardPage() {
|
|||||||
|
|
||||||
if (updateCard) {
|
if (updateCard) {
|
||||||
// Load existing card into the form for editing
|
// Load existing card into the form for editing
|
||||||
loadCardIntoForm(existingCardData);
|
await loadCardIntoForm(existingCardData);
|
||||||
alert("Edit your existing card and publish.");
|
alert("Edit your existing card and publish.");
|
||||||
} else {
|
} else {
|
||||||
// Allow creating a new card for testing purposes
|
// Allow creating a new card for testing purposes
|
||||||
@ -91,14 +91,14 @@ async function loadMinterBoardPage() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById("cancel-publish-button").addEventListener("click", () => {
|
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", () => {
|
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";
|
||||||
@ -115,7 +115,75 @@ async function loadMinterBoardPage() {
|
|||||||
await loadCards();
|
await loadCards();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchExistingCard() {
|
//Main function to load the Minter Cards ----------------------------------------
|
||||||
|
const loadCards = async () => {
|
||||||
|
const cardsContainer = document.getElementById("cards-container");
|
||||||
|
cardsContainer.innerHTML = "<p>Loading cards...</p>";
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await qortalRequest({
|
||||||
|
action: "SEARCH_QDN_RESOURCES",
|
||||||
|
service: "BLOG_POST",
|
||||||
|
query: cardIdentifierPrefix,
|
||||||
|
mode: "ALL"
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response || !Array.isArray(response) || response.length === 0) {
|
||||||
|
cardsContainer.innerHTML = "<p>No cards found.</p>";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const validatedCards = await Promise.all(
|
||||||
|
response.map(async card => {
|
||||||
|
console.log("Validating card:", card);
|
||||||
|
const isValid = await validateCardStructure(card);
|
||||||
|
return isValid ? card : null;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const validCards = validatedCards.filter(card => card !== null);
|
||||||
|
cardsContainer.innerHTML = "";
|
||||||
|
|
||||||
|
if (validCards.length === 0) {
|
||||||
|
cardsContainer.innerHTML = "<p>No valid cards found.</p>";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
validCards.map(async card => {
|
||||||
|
try {
|
||||||
|
const cardDataResponse = await qortalRequest({
|
||||||
|
action: "FETCH_QDN_RESOURCE",
|
||||||
|
name: card.name,
|
||||||
|
service: "BLOG_POST",
|
||||||
|
identifier: card.identifier,
|
||||||
|
});
|
||||||
|
|
||||||
|
const cardData = cardDataResponse;
|
||||||
|
if (!cardData || !cardData.poll) {
|
||||||
|
console.warn(`Skipping card with missing poll data: ${JSON.stringify(cardData)}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pollResults = await fetchPollResults(cardData.poll);
|
||||||
|
console.log(`Poll Results Fetched - totalVotes: ${pollResults.totalVotes}`);
|
||||||
|
|
||||||
|
const cardHTML = await createCardHTML(cardData, pollResults, card.identifier);
|
||||||
|
cardsContainer.insertAdjacentHTML("beforeend", cardHTML);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error processing card ${card.identifier}:`, error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error loading cards:", error);
|
||||||
|
cardsContainer.innerHTML = "<p>Failed to load cards.</p>";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Function to check and fech an existing Minter Card if attempting to publish twice ----------------------------------------
|
||||||
|
const fetchExistingCard = async () => {
|
||||||
try {
|
try {
|
||||||
// Step 1: Perform the search
|
// Step 1: Perform the search
|
||||||
const response = await qortalRequest({
|
const response = await qortalRequest({
|
||||||
@ -123,7 +191,8 @@ async function fetchExistingCard() {
|
|||||||
service: "BLOG_POST",
|
service: "BLOG_POST",
|
||||||
identifier: cardIdentifierPrefix,
|
identifier: cardIdentifierPrefix,
|
||||||
name: userState.accountName,
|
name: userState.accountName,
|
||||||
exactMatchNames: true //we want to search for the EXACT userName only when finding existing cards.
|
mode: "ALL",
|
||||||
|
exactMatchNames: true // Search for the exact userName only when finding existing cards
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`SEARCH_QDN_RESOURCES response: ${JSON.stringify(response, null, 2)}`);
|
console.log(`SEARCH_QDN_RESOURCES response: ${JSON.stringify(response, null, 2)}`);
|
||||||
@ -134,37 +203,48 @@ async function fetchExistingCard() {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const validCards = response.filter(card => validateCardStructure(card));
|
// Step 3: Validate cards asynchronously
|
||||||
|
const validatedCards = await Promise.all(
|
||||||
|
response.map(async card => {
|
||||||
|
const isValid = await validateCardStructure(card);
|
||||||
|
return isValid ? card : null;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Step 4: Filter out invalid cards
|
||||||
|
const validCards = validatedCards.filter(card => card !== null);
|
||||||
|
|
||||||
if (validCards.length > 0) {
|
if (validCards.length > 0) {
|
||||||
// Sort by most recent timestamp
|
// Step 5: Sort by most recent timestamp
|
||||||
const mostRecentCard = validCards.sort((a, b) => b.created - a.created)[0];
|
const mostRecentCard = validCards.sort((a, b) => b.created - a.created)[0];
|
||||||
|
|
||||||
const cardDataResponse = await qortalRequest({
|
// Step 6: Fetch full card data
|
||||||
action: "FETCH_QDN_RESOURCE",
|
const cardDataResponse = await qortalRequest({
|
||||||
name: userState.accountName, // User's account name
|
action: "FETCH_QDN_RESOURCE",
|
||||||
service: "BLOG_POST",
|
name: userState.accountName, // User's account name
|
||||||
identifier: mostRecentCard.identifier,
|
service: "BLOG_POST",
|
||||||
});
|
identifier: mostRecentCard.identifier
|
||||||
|
});
|
||||||
|
|
||||||
existingCardIdentifier = mostRecentCard.identifier
|
existingCardIdentifier = mostRecentCard.identifier;
|
||||||
existingCardData = cardDataResponse
|
existingCardData = cardDataResponse;
|
||||||
|
|
||||||
console.log("Full card data fetched successfully:", cardDataResponse);
|
console.log("Full card data fetched successfully:", cardDataResponse);
|
||||||
|
|
||||||
return cardDataResponse; // Return full card data
|
return cardDataResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("No valid cards found.");
|
console.log("No valid cards found.");
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching existing card:", error);
|
console.error("Error fetching existing card:", error);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const validateCardStructure = (card) => {
|
|
||||||
|
// Validate that a card is indeed a card and not a comment. -------------------------------------
|
||||||
|
const validateCardStructure = async (card) => {
|
||||||
return (
|
return (
|
||||||
typeof card === "object" &&
|
typeof card === "object" &&
|
||||||
card.name &&
|
card.name &&
|
||||||
@ -174,7 +254,9 @@ const validateCardStructure = (card) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadCardIntoForm(cardData) {
|
// Load existing card data passed, into the form for editing -------------------------------------
|
||||||
|
const loadCardIntoForm = async (cardData) => {
|
||||||
|
console.log("Loading existing card data:", cardData);
|
||||||
document.getElementById("card-header").value = cardData.header;
|
document.getElementById("card-header").value = cardData.header;
|
||||||
document.getElementById("card-content").value = cardData.content;
|
document.getElementById("card-content").value = cardData.content;
|
||||||
|
|
||||||
@ -189,7 +271,8 @@ function loadCardIntoForm(cardData) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function publishCard() {
|
// Main function to publish a new Minter Card -----------------------------------------------
|
||||||
|
const publishCard = async () => {
|
||||||
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();
|
||||||
const links = Array.from(document.querySelectorAll(".card-link"))
|
const links = Array.from(document.querySelectorAll(".card-link"))
|
||||||
@ -213,7 +296,7 @@ async function publishCard() {
|
|||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
poll: pollName,
|
poll: pollName,
|
||||||
};
|
};
|
||||||
// new Date().toISOString()
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
let base64CardData = await objectToBase64(cardData);
|
let base64CardData = await objectToBase64(cardData);
|
||||||
@ -221,7 +304,6 @@ async function publishCard() {
|
|||||||
console.log(`initial base64 object creation with objectToBase64 failed, using btoa...`);
|
console.log(`initial base64 object creation with objectToBase64 failed, using btoa...`);
|
||||||
base64CardData = btoa(JSON.stringify(cardData));
|
base64CardData = btoa(JSON.stringify(cardData));
|
||||||
}
|
}
|
||||||
// const base64CardData = btoa(JSON.stringify(cardData));
|
|
||||||
|
|
||||||
await qortalRequest({
|
await qortalRequest({
|
||||||
action: "PUBLISH_QDN_RESOURCE",
|
action: "PUBLISH_QDN_RESOURCE",
|
||||||
@ -254,83 +336,45 @@ async function publishCard() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadCards() {
|
//Calculate the poll results passed from other functions with minterGroupMembers and minterAdmins ---------------------------
|
||||||
const cardsContainer = document.getElementById("cards-container");
|
const calculatePollResults = async (pollData, minterGroupMembers, minterAdmins) => {
|
||||||
cardsContainer.innerHTML = "<p>Loading cards...</p>";
|
const memberAddresses = minterGroupMembers.map(member => member.member)
|
||||||
|
const adminAddresses = minterAdmins.map(member => member.member)
|
||||||
|
|
||||||
try {
|
let adminYes = 0, adminNo = 0, minterYes = 0, minterNo = 0, yesWeight = 0 , noWeight = 0
|
||||||
const response = await qortalRequest({
|
|
||||||
action: "SEARCH_QDN_RESOURCES",
|
|
||||||
service: "BLOG_POST",
|
|
||||||
query: cardIdentifierPrefix,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response || response.length === 0) {
|
pollData.voteWeights.forEach(weightData => {
|
||||||
cardsContainer.innerHTML = "<p>No cards found.</p>";
|
if (weightData.optionName === 'Yes') {
|
||||||
return;
|
yesWeight = weightData.voteWeight
|
||||||
|
} else if (weightData.optionName === 'No') {
|
||||||
|
noWeight = weightData.voteWeight
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
cardsContainer.innerHTML = ""
|
for (const vote of pollData.votes) {
|
||||||
const pollResultsCache = {};
|
const voterAddress = await getAddressFromPublicKey(vote.voterPublicKey)
|
||||||
|
console.log(`voter address: ${voterAddress}`)
|
||||||
const validCards = response.filter(card => validateCardStructure(card));
|
|
||||||
|
|
||||||
for (const card of validCards) {
|
|
||||||
const cardDataResponse = await qortalRequest({
|
|
||||||
action: "FETCH_QDN_RESOURCE",
|
|
||||||
name: card.name,
|
|
||||||
service: "BLOG_POST",
|
|
||||||
identifier: card.identifier,
|
|
||||||
});
|
|
||||||
|
|
||||||
const cardData = cardDataResponse;
|
|
||||||
|
|
||||||
if (!cardData || !cardData.poll) {
|
|
||||||
console.warn(`Skipping card with missing poll data: ${JSON.stringify(cardData)}`);
|
|
||||||
continue; // Skip to the next card
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache poll results
|
|
||||||
if (!pollResultsCache[cardData.poll]) {
|
|
||||||
try {
|
|
||||||
pollResultsCache[cardData.poll] = await fetchPollResults(cardData.poll);
|
|
||||||
} catch (error) {
|
|
||||||
console.warn(`Failed to fetch poll results for poll: ${cardData.poll}`, error);
|
|
||||||
pollResultsCache[cardData.poll] = null; // Store as null to avoid repeated attempts
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const pollResults = pollResultsCache[cardData.poll];
|
|
||||||
const cardHTML = await createCardHTML(cardData, pollResults, card.identifier);
|
|
||||||
cardsContainer.insertAdjacentHTML("beforeend", cardHTML);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error loading cards:", error);
|
|
||||||
cardsContainer.innerHTML = "<p>Failed to load cards.</p>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const calculatePollResults = (pollData, minterGroupMembers) => {
|
|
||||||
const memberAddresses = minterGroupMembers.map(member => member.member);
|
|
||||||
let adminYes = 0, adminNo = 0, minterYes = 0, minterNo = 0;
|
|
||||||
|
|
||||||
pollData.votes.forEach(vote => {
|
|
||||||
const voterAddress = getAddressFromPublicKey(vote.voterPublicKey);
|
|
||||||
const isAdmin = minterGroupMembers.some(member => member.member === voterAddress && member.isAdmin);
|
|
||||||
|
|
||||||
if (vote.optionIndex === 0) {
|
if (vote.optionIndex === 0) {
|
||||||
isAdmin ? adminYes++ : memberAddresses.includes(voterAddress) ? minterYes++ : null;
|
adminAddresses.includes(voterAddress) ? adminYes++ : memberAddresses.includes(voterAddress) ? minterYes++ : console.log(`voter ${voterAddress} is not a minter nor an admin...Not including results...`)
|
||||||
} else if (vote.optionIndex === 1) {
|
} else if (vote.optionIndex === 1) {
|
||||||
isAdmin ? adminNo++ : memberAddresses.includes(voterAddress) ? minterNo++ : null;
|
adminAddresses.includes(voterAddress) ? adminNo++ : memberAddresses.includes(voterAddress) ? minterNo++ : console.log(`voter ${voterAddress} is not a minter nor an admin...Not including results...`)
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
const totalYes = adminYes + minterYes;
|
// TODO - create a new function to calculate the weights of each voting MINTER only.
|
||||||
const totalNo = adminNo + minterNo;
|
// This will give ALL weight whether voter is in minter group or not...
|
||||||
|
// until that is changed on the core we must calculate manually.
|
||||||
|
const totalYesWeight = yesWeight
|
||||||
|
const totalNoWeight = noWeight
|
||||||
|
|
||||||
return { adminYes, adminNo, minterYes, minterNo, totalYes, totalNo };
|
const totalYes = adminYes + minterYes
|
||||||
};
|
const totalNo = adminNo + minterNo
|
||||||
|
|
||||||
|
return { adminYes, adminNo, minterYes, minterNo, totalYes, totalNo, totalYesWeight, totalNoWeight }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Post a comment on a card. ---------------------------------
|
||||||
const postComment = async (cardIdentifier) => {
|
const postComment = async (cardIdentifier) => {
|
||||||
const commentInput = document.getElementById(`new-comment-${cardIdentifier}`);
|
const commentInput = document.getElementById(`new-comment-${cardIdentifier}`);
|
||||||
const commentText = commentInput.value.trim();
|
const commentText = commentInput.value.trim();
|
||||||
@ -353,7 +397,7 @@ const postComment = async (cardIdentifier) => {
|
|||||||
console.log(`initial base64 object creation with objectToBase64 failed, using btoa...`);
|
console.log(`initial base64 object creation with objectToBase64 failed, using btoa...`);
|
||||||
base64CommentData = btoa(JSON.stringify(commentData));
|
base64CommentData = btoa(JSON.stringify(commentData));
|
||||||
}
|
}
|
||||||
// const base64CommentData = btoa(JSON.stringify(commentData));
|
|
||||||
await qortalRequest({
|
await qortalRequest({
|
||||||
action: 'PUBLISH_QDN_RESOURCE',
|
action: 'PUBLISH_QDN_RESOURCE',
|
||||||
name: userState.accountName,
|
name: userState.accountName,
|
||||||
@ -371,12 +415,14 @@ const postComment = async (cardIdentifier) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//Fetch the comments for a card with passed card identifier ----------------------------
|
||||||
const fetchCommentsForCard = async (cardIdentifier) => {
|
const fetchCommentsForCard = async (cardIdentifier) => {
|
||||||
try {
|
try {
|
||||||
const response = await qortalRequest({
|
const response = await qortalRequest({
|
||||||
action: 'SEARCH_QDN_RESOURCES',
|
action: 'SEARCH_QDN_RESOURCES',
|
||||||
service: 'BLOG_POST',
|
service: 'BLOG_POST',
|
||||||
query: `comment-${cardIdentifier}`,
|
query: `comment-${cardIdentifier}`,
|
||||||
|
mode: "ALL"
|
||||||
});
|
});
|
||||||
return response;
|
return response;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -385,6 +431,7 @@ const fetchCommentsForCard = async (cardIdentifier) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// display the comments on the card, with passed cardIdentifier to identify the card --------------
|
||||||
const displayComments = async (cardIdentifier) => {
|
const displayComments = async (cardIdentifier) => {
|
||||||
try {
|
try {
|
||||||
const comments = await fetchCommentsForCard(cardIdentifier);
|
const comments = await fetchCommentsForCard(cardIdentifier);
|
||||||
@ -399,6 +446,7 @@ const displayComments = async (cardIdentifier) => {
|
|||||||
identifier: comment.identifier,
|
identifier: comment.identifier,
|
||||||
});
|
});
|
||||||
const timestamp = await timestampToHumanReadableDate(commentDataResponse.timestamp);
|
const timestamp = await timestampToHumanReadableDate(commentDataResponse.timestamp);
|
||||||
|
//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 commentHTML = `
|
||||||
<div class="comment" style="border: 1px solid gray; margin: 1vh 0; padding: 1vh; background: #1c1c1c;">
|
<div class="comment" style="border: 1px solid gray; margin: 1vh 0; padding: 1vh; background: #1c1c1c;">
|
||||||
<p><strong><u>${commentDataResponse.creator}</strong>:</p></u>
|
<p><strong><u>${commentDataResponse.creator}</strong>:</p></u>
|
||||||
@ -414,6 +462,7 @@ const displayComments = async (cardIdentifier) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Vote YES on a poll ------------------------------
|
||||||
const voteYesOnPoll = async (poll) => {
|
const voteYesOnPoll = async (poll) => {
|
||||||
await qortalRequest({
|
await qortalRequest({
|
||||||
action: "VOTE_ON_POLL",
|
action: "VOTE_ON_POLL",
|
||||||
@ -422,6 +471,7 @@ const voteYesOnPoll = async (poll) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Vote NO on a poll -----------------------------
|
||||||
const voteNoOnPoll = async (poll) => {
|
const voteNoOnPoll = async (poll) => {
|
||||||
await qortalRequest({
|
await qortalRequest({
|
||||||
action: "VOTE_ON_POLL",
|
action: "VOTE_ON_POLL",
|
||||||
@ -430,6 +480,7 @@ const voteNoOnPoll = async (poll) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Toggle comments from being shown or not, with passed cardIdentifier for comments being toggled --------------------
|
||||||
const toggleComments = async (cardIdentifier) => {
|
const toggleComments = async (cardIdentifier) => {
|
||||||
const commentsSection = document.getElementById(`comments-section-${cardIdentifier}`);
|
const commentsSection = document.getElementById(`comments-section-${cardIdentifier}`);
|
||||||
if (commentsSection.style.display === 'none' || !commentsSection.style.display) {
|
if (commentsSection.style.display === 'none' || !commentsSection.style.display) {
|
||||||
@ -440,20 +491,58 @@ const toggleComments = async (cardIdentifier) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
async function createCardHTML(cardData, pollResults, cardIdentifier) {
|
const createModal = async () => {
|
||||||
|
const modalHTML = `
|
||||||
|
<div id="modal" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.8); z-index: 1000;">
|
||||||
|
<div style="position: relative; margin: 5% auto; width: 90%; height: 90%; background: white; border-radius: 10px; overflow: hidden;">
|
||||||
|
<iframe id="modalContent" src="" style="width: 100%; height: 100%; border: none;"></iframe>
|
||||||
|
<button onclick="closeModal()" style="position: absolute; top: 10px; right: 10px; background: red; color: white; border: none; padding: 5px 10px; border-radius: 5px;">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
document.body.insertAdjacentHTML('beforeend', modalHTML);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to open the modal
|
||||||
|
const openModal = async (link) => {
|
||||||
|
const processedLink = await processLink(link) // Process the link to replace `qortal://` for rendering in modal
|
||||||
|
const modal = document.getElementById('modal');
|
||||||
|
const modalContent = document.getElementById('modalContent');
|
||||||
|
modalContent.src = processedLink; // Set the iframe source to the link
|
||||||
|
modal.style.display = 'block'; // Show the modal
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to close the modal
|
||||||
|
const closeModal = async () => {
|
||||||
|
const modal = document.getElementById('modal');
|
||||||
|
const modalContent = document.getElementById('modalContent');
|
||||||
|
modal.style.display = 'none'; // Hide the modal
|
||||||
|
modalContent.src = ''; // Clear the iframe source
|
||||||
|
}
|
||||||
|
|
||||||
|
const processLink = async (link) => {
|
||||||
|
if (link.startsWith('qortal://')) {
|
||||||
|
return link.replace('qortal://', '/render/')
|
||||||
|
}
|
||||||
|
return link // Return the link unchanged if it doesn't start with `qortal://`
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Create the overall Minter Card HTML -----------------------------------------------
|
||||||
|
const createCardHTML = async (cardData, pollResults, cardIdentifier) => {
|
||||||
const { header, content, links, creator, timestamp, poll } = cardData;
|
const { header, content, links, creator, timestamp, poll } = cardData;
|
||||||
const formattedDate = new Date(timestamp).toLocaleString();
|
const formattedDate = new Date(timestamp).toLocaleString();
|
||||||
const avatarUrl = `/arbitrary/THUMBNAIL/${creator}/qortal_avatar`;
|
const avatarUrl = `/arbitrary/THUMBNAIL/${creator}/qortal_avatar`;
|
||||||
const linksHTML = links.map((link, index) => `
|
const linksHTML = links.map((link, index) => `
|
||||||
<button onclick="window.open('${link}', '_blank')">
|
<button onclick="openModal('${link}')">
|
||||||
${`Link ${index + 1} - ${link}`}
|
${`Link ${index + 1} - ${link}`}
|
||||||
</button>
|
</button>
|
||||||
`).join("");
|
`).join("");
|
||||||
|
|
||||||
const minterGroupMembers = await fetchMinterGroupMembers();
|
const minterGroupMembers = await fetchMinterGroupMembers();
|
||||||
const { adminYes = 0, adminNo = 0, minterYes = 0, minterNo = 0, totalYes = 0, totalNo = 0 } =
|
const minterAdmins = await fetchMinterGroupAdmins();
|
||||||
calculatePollResults(pollResults, minterGroupMembers) || {};
|
const { adminYes = 0, adminNo = 0, minterYes = 0, minterNo = 0, totalYes = 0, totalNo = 0, totalYesWeight = 0, totalNoWeight = 0 } = await calculatePollResults(pollResults, minterGroupMembers, minterAdmins)
|
||||||
|
await createModal()
|
||||||
return `
|
return `
|
||||||
<div class="minter-card">
|
<div class="minter-card">
|
||||||
<div class="minter-card-header">
|
<div class="minter-card-header">
|
||||||
|
@ -14,7 +14,7 @@ if (localStorage.getItem("latestMessageIdentifiers")) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", async () => {
|
document.addEventListener("DOMContentLoaded", async () => {
|
||||||
// Identify the link for 'Mintership Forum'
|
// Identify the links for 'Mintership Forum' and apply functionality
|
||||||
const mintershipForumLinks = document.querySelectorAll('a[href="MINTERSHIP-FORUM"]');
|
const mintershipForumLinks = document.querySelectorAll('a[href="MINTERSHIP-FORUM"]');
|
||||||
|
|
||||||
mintershipForumLinks.forEach(link => {
|
mintershipForumLinks.forEach(link => {
|
||||||
@ -31,14 +31,9 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
async function loadForumPage() {
|
// Main load function to clear existing HTML and load the forum page -----------------------------------------------------
|
||||||
// // Remove all sections except the menu
|
const loadForumPage = async () => {
|
||||||
// const allSections = document.querySelectorAll('body > section');
|
// remove everything that isn't the menu from the body to use js to generate page content.
|
||||||
// allSections.forEach(section => {
|
|
||||||
// if (!section.classList.contains('menu')) {
|
|
||||||
// section.remove();
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
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];
|
||||||
@ -89,7 +84,8 @@ async function loadForumPage() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function renderPaginationControls(room, totalMessages, limit) {
|
// Function to add the pagination buttons and related control mechanisms ------------------------
|
||||||
|
const renderPaginationControls = async(room, totalMessages, limit) => {
|
||||||
const paginationContainer = document.getElementById("pagination-container");
|
const paginationContainer = document.getElementById("pagination-container");
|
||||||
if (!paginationContainer) return;
|
if (!paginationContainer) return;
|
||||||
|
|
||||||
@ -138,9 +134,8 @@ async function renderPaginationControls(room, totalMessages, limit) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Main function to load the full content of the room, along with all main functionality -----------------------------------
|
||||||
|
const loadRoomContent = async (room) => {
|
||||||
async function loadRoomContent(room) {
|
|
||||||
const forumContent = document.getElementById("forum-content");
|
const forumContent = document.getElementById("forum-content");
|
||||||
if (forumContent) {
|
if (forumContent) {
|
||||||
forumContent.innerHTML = `
|
forumContent.innerHTML = `
|
||||||
@ -153,9 +148,13 @@ async function loadRoomContent(room) {
|
|||||||
<div id="editor" class="message-input"></div>
|
<div id="editor" class="message-input"></div>
|
||||||
<div class="attachment-section">
|
<div class="attachment-section">
|
||||||
<input type="file" id="file-input" class="file-input" multiple>
|
<input type="file" id="file-input" class="file-input" multiple>
|
||||||
<button id="attach-button" class="attach-button">Attach Files</button>
|
<label for="file-input" class="custom-file-input-button">Select Files</label>
|
||||||
|
<input type="file" id="image-input" class="image-input" multiple accept="image/*">
|
||||||
|
<label for="image-input" class="custom-image-input-button">Select IMAGES w/Preview</label>
|
||||||
|
<button id="add-images-to-publish-button" disabled>Add Images to Multi-Publish</button>
|
||||||
|
<div id="preview-container" style="display: flex; flex-wrap: wrap; gap: 10px;"></div>
|
||||||
</div>
|
</div>
|
||||||
<button id="send-button" class="send-button">Send</button>
|
<button id="send-button" class="send-button">Publish</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
@ -191,7 +190,7 @@ async function loadRoomContent(room) {
|
|||||||
// Load messages from QDN for the selected room
|
// Load messages from QDN for the selected room
|
||||||
await loadMessagesFromQDN(room, currentPage);
|
await loadMessagesFromQDN(room, currentPage);
|
||||||
|
|
||||||
document.addEventListener("click", (event) => {
|
document.addEventListener("click", async (event) => {
|
||||||
if (event.target.classList.contains("inline-image")) {
|
if (event.target.classList.contains("inline-image")) {
|
||||||
const modal = document.getElementById("image-modal");
|
const modal = document.getElementById("image-modal");
|
||||||
const modalImage = document.getElementById("modal-image");
|
const modalImage = document.getElementById("modal-image");
|
||||||
@ -202,72 +201,186 @@ async function loadRoomContent(room) {
|
|||||||
modalImage.src = event.target.src;
|
modalImage.src = event.target.src;
|
||||||
caption.textContent = event.target.alt;
|
caption.textContent = event.target.alt;
|
||||||
|
|
||||||
// Set download button link - This has been moved to the Message Rendering Section of the code.
|
|
||||||
// downloadButton.onclick = () => {
|
|
||||||
// fetchAndSaveAttachment(
|
|
||||||
// "FILE",
|
|
||||||
// event.target.dataset.name,
|
|
||||||
// event.target.dataset.identifier,
|
|
||||||
// event.target.dataset.filename,
|
|
||||||
// event.target.dataset.mimeType
|
|
||||||
// );
|
|
||||||
// };
|
|
||||||
|
|
||||||
// Show the modal
|
// Show the modal
|
||||||
modal.style.display = "block";
|
modal.style.display = "block";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Close the modal
|
// Close the modal
|
||||||
document.getElementById("close-modal").addEventListener("click", () => {
|
document.getElementById("close-modal").addEventListener("click", async () => {
|
||||||
document.getElementById("image-modal").style.display = "none";
|
document.getElementById("image-modal").style.display = "none";
|
||||||
});
|
});
|
||||||
|
|
||||||
// Hide the modal when clicking outside of the image or close button
|
// Hide the modal when clicking outside of the image or close button
|
||||||
window.addEventListener("click", (event) => {
|
window.addEventListener("click", async (event) => {
|
||||||
const modal = document.getElementById("image-modal");
|
const modal = document.getElementById("image-modal");
|
||||||
if (event.target == modal) {
|
if (!event.target == modal) {
|
||||||
modal.style.display = "none";
|
modal.style.display = "none";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
let selectedFiles = [];
|
let selectedFiles = [];
|
||||||
|
let selectedImages = [];
|
||||||
|
let attachmentIdentifiers = [];
|
||||||
|
let multiResource = []
|
||||||
|
|
||||||
// Add event listener to handle file selection
|
const imageFileInput = document.getElementById('image-input');
|
||||||
document.getElementById('file-input').addEventListener('change', (event) => {
|
const previewContainer = document.getElementById('preview-container');
|
||||||
selectedFiles = Array.from(event.target.files);
|
const addToPublishButton = document.getElementById('add-images-to-publish-button')
|
||||||
|
const randomID = await uid();
|
||||||
|
const attachmentID = `${messageAttachmentIdentifierPrefix}-${room}-${randomID}`;
|
||||||
|
|
||||||
|
imageFileInput.addEventListener('change', async (event) => {
|
||||||
|
// Clear previous previews to prepare for preview generation
|
||||||
|
previewContainer.innerHTML = '';
|
||||||
|
selectedImages = Array.from(event.target.files);
|
||||||
|
|
||||||
|
if (selectedImages.length > 0) {
|
||||||
|
addToPublishButton.disabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedImages.forEach((file, index) => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = () => {
|
||||||
|
const img = document.createElement('img');
|
||||||
|
img.src = reader.result;
|
||||||
|
img.alt = file.name;
|
||||||
|
img.style.width = '100px';
|
||||||
|
img.style.height = '100px';
|
||||||
|
img.style.objectFit = 'cover';
|
||||||
|
img.style.border = '1px solid #ccc';
|
||||||
|
img.style.borderRadius = '5px';
|
||||||
|
|
||||||
|
// Add remove button
|
||||||
|
const removeButton = document.createElement('button');
|
||||||
|
removeButton.innerText = 'Remove';
|
||||||
|
removeButton.style.marginTop = '5px';
|
||||||
|
removeButton.onclick = () => {
|
||||||
|
selectedImages.splice(index, 1);
|
||||||
|
img.remove();
|
||||||
|
removeButton.remove();
|
||||||
|
if (selectedImages.length === 0) {
|
||||||
|
addToPublishButton.disabled = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const container = document.createElement('div');
|
||||||
|
container.style.display = 'flex';
|
||||||
|
container.style.flexDirection = 'column';
|
||||||
|
container.style.alignItems = 'center';
|
||||||
|
container.style.margin = '5px';
|
||||||
|
container.appendChild(img);
|
||||||
|
container.appendChild(removeButton);
|
||||||
|
previewContainer.appendChild(container);
|
||||||
|
};
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add event listener for the send button
|
addToPublishButton.addEventListener('click', async () => {
|
||||||
|
await addImagesToMultiPublish()
|
||||||
|
})
|
||||||
|
|
||||||
|
// Function to add images in the preview to the multi-publish object --------------------------
|
||||||
|
const addImagesToMultiPublish = async () => {
|
||||||
|
console.log('Adding Images to multi-publish:', selectedImages);
|
||||||
|
for (let i = 0; i < selectedImages.length; i++) {
|
||||||
|
const file = selectedImages[i];
|
||||||
|
try {
|
||||||
|
multiResource.push({
|
||||||
|
name: userState.accountName,
|
||||||
|
service: "FILE",
|
||||||
|
identifier: attachmentID,
|
||||||
|
file: file,
|
||||||
|
});
|
||||||
|
|
||||||
|
attachmentIdentifiers.push({
|
||||||
|
name: userState.accountName,
|
||||||
|
service: "FILE",
|
||||||
|
identifier: attachmentID,
|
||||||
|
filename: file.name,
|
||||||
|
mimeType: file.type
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`Attachment ${file.name} placed into multiResource with attachmentID: ${attachmentID}`);
|
||||||
|
|
||||||
|
// Remove the processed file
|
||||||
|
selectedImages.splice(i, 1);
|
||||||
|
i--; // Adjust the index since we removed an item
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error processing attachment ${file.name}:`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selectedImages = []
|
||||||
|
addToPublishButton.disabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add event listener to handle file selection
|
||||||
|
document.getElementById('file-input').addEventListener('change', async (event) => {
|
||||||
|
selectedFiles = Array.from(event.target.files);
|
||||||
|
});
|
||||||
|
// Add event listener for the PUBLISH button
|
||||||
document.getElementById("send-button").addEventListener("click", async () => {
|
document.getElementById("send-button").addEventListener("click", async () => {
|
||||||
const messageHtml = quill.root.innerHTML.trim();
|
const messageHtml = quill.root.innerHTML.trim();
|
||||||
if (messageHtml !== "" || selectedFiles.length > 0) {
|
if (messageHtml !== "" || selectedFiles.length > 0 || selectedImages.length > 0) {
|
||||||
const randomID = await uid();
|
|
||||||
const messageIdentifier = `${messageIdentifierPrefix}-${room}-${randomID}`;
|
const messageIdentifier = `${messageIdentifierPrefix}-${room}-${randomID}`;
|
||||||
let attachmentIdentifiers = [];
|
|
||||||
|
|
||||||
// Handle attachments
|
if (selectedImages.length > 0) {
|
||||||
for (const file of selectedFiles) {
|
await addImagesToMultiPublish()
|
||||||
const attachmentID = `${messageAttachmentIdentifierPrefix}-${room}-${randomID}`;
|
}
|
||||||
try {
|
if (selectedFiles.length === 1) {
|
||||||
await qortalRequest({
|
console.log(`single file has been detected, attaching single file...`)
|
||||||
action: "PUBLISH_QDN_RESOURCE",
|
const singleAttachment = selectedFiles[0]
|
||||||
name: userState.accountName,
|
|
||||||
service: "FILE",
|
multiResource.push({
|
||||||
identifier: attachmentID,
|
name: userState.accountName,
|
||||||
file: file,
|
service: "FILE",
|
||||||
});
|
identifier: attachmentID,
|
||||||
attachmentIdentifiers.push({
|
file: singleAttachment
|
||||||
name: userState.accountName,
|
})
|
||||||
service: "FILE",
|
|
||||||
identifier: attachmentID,
|
attachmentIdentifiers.push({
|
||||||
filename: file.name,
|
name: userState.accountName,
|
||||||
mimeType: file.type
|
service: "FILE",
|
||||||
});
|
identifier: attachmentID,
|
||||||
console.log(`Attachment ${file.name} published successfully with ID: ${attachmentID}`);
|
filename: singleAttachment.name,
|
||||||
} catch (error) {
|
filetype: singleAttachement.type
|
||||||
console.error(`Error publishing attachment ${file.name}:`, error);
|
})
|
||||||
|
// Clear selectedFiles as we do not need them anymore.
|
||||||
|
document.getElementById('file-input').value = "";
|
||||||
|
selectedFiles = [];
|
||||||
|
|
||||||
|
}else if (selectedFiles.length >= 2) {
|
||||||
|
console.log(`selected files found: ${selectedFiles.length}, adding multiple files to multi-publish resource...`)
|
||||||
|
// Handle Multiple attachements utilizing multi-publish
|
||||||
|
for (let i = 0; i < selectedFiles.length; i++) {
|
||||||
|
const file = selectedFiles[i];
|
||||||
|
try {
|
||||||
|
multiResource.push({
|
||||||
|
name: userState.accountName,
|
||||||
|
service: "FILE",
|
||||||
|
identifier: attachmentID,
|
||||||
|
file: file,
|
||||||
|
});
|
||||||
|
|
||||||
|
attachmentIdentifiers.push({
|
||||||
|
name: userState.accountName,
|
||||||
|
service: "FILE",
|
||||||
|
identifier: attachmentID,
|
||||||
|
filename: file.name,
|
||||||
|
mimeType: file.type
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`Attachment ${file.name} placed into multiResource with attachmentID: ${attachmentID}`);
|
||||||
|
|
||||||
|
// Remove the processed file
|
||||||
|
selectedFiles.splice(i, 1);
|
||||||
|
i--; // Adjust the index since we removed an item
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error processing attachment ${file.name}:`, error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,21 +400,24 @@ async function loadRoomContent(room) {
|
|||||||
base64Message = btoa(JSON.stringify(messageObject));
|
base64Message = btoa(JSON.stringify(messageObject));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Publish message to QDN
|
// Put the message into the multiResource for batch-publishing.
|
||||||
await qortalRequest({
|
multiResource.push({
|
||||||
action: "PUBLISH_QDN_RESOURCE",
|
|
||||||
name: userState.accountName,
|
name: userState.accountName,
|
||||||
service: "BLOG_POST",
|
service: "BLOG_POST",
|
||||||
identifier: messageIdentifier,
|
identifier: messageIdentifier,
|
||||||
data64: base64Message
|
data64: base64Message
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("Message published successfully");
|
console.log("Message added to multi-publish resource successfully, attempting multi-publish... ");
|
||||||
|
|
||||||
|
await publishMultipleResources(multiResource)
|
||||||
|
|
||||||
// Clear the editor after sending the message, including any potential attached files and replies.
|
// Clear the editor after sending the message, including any potential attached files and replies.
|
||||||
quill.root.innerHTML = "";
|
quill.root.innerHTML = "";
|
||||||
document.getElementById('file-input').value = "";
|
document.getElementById('file-input').value = "";
|
||||||
selectedFiles = [];
|
selectedFiles = [];
|
||||||
|
selectedImages = [];
|
||||||
|
multiResource = [];
|
||||||
replyToMessageIdentifier = null;
|
replyToMessageIdentifier = null;
|
||||||
const replyContainer = document.querySelector(".reply-container");
|
const replyContainer = document.querySelector(".reply-container");
|
||||||
if (replyContainer) {
|
if (replyContainer) {
|
||||||
@ -310,33 +426,24 @@ async function loadRoomContent(room) {
|
|||||||
|
|
||||||
// Show success notification
|
// Show success notification
|
||||||
const notification = document.createElement('div');
|
const notification = document.createElement('div');
|
||||||
notification.innerText = "Message published successfully! Message will take a confirmation to show.";
|
notification.innerText = "Message published successfully! Message will take a confirmation to show, please be patient...";
|
||||||
notification.style.color = "green";
|
notification.style.color = "green";
|
||||||
notification.style.marginTop = "10px";
|
notification.style.marginTop = "1em";
|
||||||
document.querySelector(".message-input-section").appendChild(notification);
|
document.querySelector(".message-input-section").appendChild(notification);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
notification.remove();
|
notification.remove();
|
||||||
}, 3000);
|
}, 10000);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error publishing message:", error);
|
console.error("Error publishing message:", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
// Add event listener for the load more button
|
|
||||||
const loadMoreContainer = document.getElementById("load-more-container");
|
|
||||||
if (loadMoreContainer) {
|
|
||||||
loadMoreContainer.innerHTML = '<button id="load-more-button" class="load-more-button" style="margin-top: 10px;">Load More</button>';
|
|
||||||
document.getElementById("load-more-button").addEventListener("click", () => {
|
|
||||||
currentPage++;
|
|
||||||
loadMessagesFromQDN(room, currentPage);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadMessagesFromQDN(room, page, isPolling = false) {
|
const loadMessagesFromQDN = async (room, page, isPolling = false) => {
|
||||||
try {
|
try {
|
||||||
const limit = 10;
|
const limit = 10;
|
||||||
const offset = page * limit;
|
const offset = page * limit;
|
||||||
|
@ -130,17 +130,31 @@ const verifyUserIsAdmin = async () => {
|
|||||||
try {
|
try {
|
||||||
const accountAddress = userState.accountAddress || await getUserAddress();
|
const accountAddress = userState.accountAddress || await getUserAddress();
|
||||||
userState.accountAddress = accountAddress;
|
userState.accountAddress = accountAddress;
|
||||||
|
|
||||||
const userGroups = await getUserGroups(accountAddress);
|
const userGroups = await getUserGroups(accountAddress);
|
||||||
|
console.log('userGroups:', userGroups);
|
||||||
|
|
||||||
const minterGroupAdmins = await fetchMinterGroupAdmins();
|
const minterGroupAdmins = await fetchMinterGroupAdmins();
|
||||||
const isAdmin = await userGroups.some(group => adminGroups.includes(group.groupName))
|
console.log('minterGroupAdmins.members:', minterGroupAdmins);
|
||||||
const isMinterAdmin = minterGroupAdmins.members.some(admin => admin.member === userState.accountAddress && admin.isAdmin)
|
|
||||||
|
if (!Array.isArray(userGroups)) {
|
||||||
|
throw new Error('userGroups is not an array or is undefined');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(minterGroupAdmins)) {
|
||||||
|
throw new Error('minterGroupAdmins.members is not an array or is undefined');
|
||||||
|
}
|
||||||
|
|
||||||
|
const isAdmin = userGroups.some(group => adminGroups.includes(group.groupName));
|
||||||
|
const isMinterAdmin = minterGroupAdmins.some(admin => admin.member === userState.accountAddress && admin.isAdmin);
|
||||||
|
|
||||||
if (isMinterAdmin) {
|
if (isMinterAdmin) {
|
||||||
userState.isMinterAdmin = true
|
userState.isMinterAdmin = true;
|
||||||
}
|
}
|
||||||
if (isAdmin) {
|
if (isAdmin) {
|
||||||
userState.isAdmin = true;
|
userState.isAdmin = true;
|
||||||
userState.isForumAdmin = true
|
userState.isForumAdmin = true;
|
||||||
}
|
}
|
||||||
return userState.isAdmin;
|
return userState.isAdmin;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error verifying user admin status:', error);
|
console.error('Error verifying user admin status:', error);
|
||||||
@ -148,6 +162,7 @@ const verifyUserIsAdmin = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const verifyAddressIsAdmin = async (address) => {
|
const verifyAddressIsAdmin = async (address) => {
|
||||||
console.log('verifyAddressIsAdmin called');
|
console.log('verifyAddressIsAdmin called');
|
||||||
console.log('address:', address);
|
console.log('address:', address);
|
||||||
@ -234,8 +249,7 @@ const getAddressFromPublicKey = async (publicKey) => {
|
|||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: { 'Accept': 'text/plain' }
|
headers: { 'Accept': 'text/plain' }
|
||||||
});
|
});
|
||||||
const data = await response.text();
|
const address = await response.text();
|
||||||
const address = data;
|
|
||||||
console.log('Converted Address:', address);
|
console.log('Converted Address:', address);
|
||||||
return address;
|
return address;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -290,7 +304,7 @@ try {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// QORTAL GROUP-RELATED CALLS ------------------------------------------
|
// QORTAL GROUP-RELATED CALLS ------------------------------------------------------------------------------------
|
||||||
const getUserGroups = async (userAddress) => {
|
const getUserGroups = async (userAddress) => {
|
||||||
console.log('getUserGroups called');
|
console.log('getUserGroups called');
|
||||||
console.log('userAddress:', userAddress);
|
console.log('userAddress:', userAddress);
|
||||||
@ -319,8 +333,15 @@ const fetchMinterGroupAdmins = async () => {
|
|||||||
headers: { 'Accept': 'application/json' }
|
headers: { 'Accept': 'application/json' }
|
||||||
});
|
});
|
||||||
const admins = await response.json();
|
const admins = await response.json();
|
||||||
|
|
||||||
|
if (!Array.isArray(admins.members)) {
|
||||||
|
throw new Error("Expected 'members' to be an array but got a different structure");
|
||||||
|
}
|
||||||
|
|
||||||
|
const adminMembers = admins.members
|
||||||
console.log('Fetched minter admins', admins);
|
console.log('Fetched minter admins', admins);
|
||||||
return admins;
|
return adminMembers;
|
||||||
|
//use what is returned .member to obtain each member... {"member": "memberAddress", "isAdmin": "true"}
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchMinterGroupMembers = async () => {
|
const fetchMinterGroupMembers = async () => {
|
||||||
@ -341,7 +362,10 @@ const fetchMinterGroupMembers = async () => {
|
|||||||
throw new Error("Expected 'members' to be an array but got a different structure");
|
throw new Error("Expected 'members' to be an array but got a different structure");
|
||||||
}
|
}
|
||||||
|
|
||||||
return data.members; // Assuming 'members' is the key in the response JSON
|
console.log(`MinterGroupMembers have been fetched.`)
|
||||||
|
return data.members;
|
||||||
|
|
||||||
|
//use what is returned .member to obtain each member... {"member": "memberAddress", "joined": "{timestamp}"}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching minter group members:", error);
|
console.error("Error fetching minter group members:", error);
|
||||||
return []; // Return an empty array to prevent further errors
|
return []; // Return an empty array to prevent further errors
|
||||||
@ -349,8 +373,6 @@ const fetchMinterGroupMembers = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const fetchAllGroups = async (limit) => {
|
const fetchAllGroups = async (limit) => {
|
||||||
console.log('fetchAllGroups called');
|
console.log('fetchAllGroups called');
|
||||||
console.log('limit:', limit);
|
console.log('limit:', limit);
|
||||||
|
@ -229,7 +229,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a class="link-wrap" href="#">
|
<a class="link-wrap" href="#">
|
||||||
<p class="mbr-link mbr-fonts-style display-4">Q-Mintership v0.24beta</p>
|
<p class="mbr-link mbr-fonts-style display-4">Q-Mintership v0.25beta</p>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 col-lg-6">
|
<div class="col-12 col-lg-6">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user