Compare commits

...

6 Commits

7 changed files with 262 additions and 115 deletions

View File

@ -708,31 +708,6 @@ body {
}
/* Responsive design */
@media (max-width: 768px) {
.publish-card-view {
width: 90%;
padding: 2vh;
}
.publish-card-button {
font-size: 1.8vh;
padding: 1.5vh;
}
.publish-card-form button {
font-size: 1.8vh;
padding: 1.2vh;
}
}
.refresh-cards-button {
border-color: white;
border-radius: 1.5vh;
background-color: black;
color: white;
}
/* Responsive Design */
@media (max-width: 768px) {
.publish-card-view {
@ -754,8 +729,14 @@ body {
.refresh-cards-button {
border-color: white;
border-radius: 1.5vh;
background-color: black;
background-color: rgba(0, 0, 0, 0.089);
color: white;
font-size: 0.9rem;
}
.refresh-cards-button:hover {
background-color: rgba(35, 129, 136, 0.137);
color: rgba(90, 201, 221, 0.793);
}
/* Two cards per row on medium screens */

View File

@ -60,11 +60,13 @@ const loadAddRemoveAdminPage = async () => {
<h3 style="color: #ddd;">Existing Promotion/Demotion Proposals</h3>
<button id="refresh-cards-button" class="refresh-cards-button" style="padding: 10px;">Refresh Proposal Cards</button>
<select id="time-range-select" style="margin-left: 10px; padding: 5px; font-size: 1.25rem; color: white; background-color: black;">
<option value="0">Show All</option>
<option value="1">Last 1 day</option>
<option value="7">Last 7 days</option>
<option value="30" selected>Last 30 days</option>
<option value="90">Last 90 days</option>
<option value="0">All Creation Dates</option>
<option value="1">Last 1 Day</option>
<option value="7">Last 7 Days</option>
<option value="30">...Within 30 Days</option>
<option value="45" selected>Published Within Last 45 Days</option>
<option value="60">...Within 60 Days</option>
<option value="90">...Within 90 Days</option>
</select>
</div>
<div id="cards-container" class="cards-container" style="margin-top: 1rem"">
@ -117,6 +119,13 @@ const loadAddRemoveAdminPage = async () => {
linksContainer.appendChild(newLinkInput)
})
const timeRangeSelectCheckbox = document.getElementById('time-range-select')
if (timeRangeSelectCheckbox) {
timeRangeSelectCheckbox.addEventListener('change', async (event) => {
await loadCards(addRemoveIdentifierPrefix)
})
}
document.getElementById("publish-card-form").addEventListener("submit", async (event) => {
event.preventDefault()
await publishARCard(addRemoveIdentifierPrefix)

View File

@ -84,12 +84,14 @@ const loadAdminBoardPage = async () => {
<option value="most-votes">Most Votes</option>
</select>
<select id="time-range-select" style="margin-left: 10px; padding: 5px; font-size: 1.25rem; color: white; background-color: black;">
<option value="0">Show All</option>
<option value="1">Last 1 day</option>
<option value="7">Last 7 days</option>
<option value="30" selected>Last 30 days</option>
<option value="90">Last 90 days</option>
</select>
<option value="0">All Creation Dates</option>
<option value="1">Last 1 Day</option>
<option value="7">Last 7 Days</option>
<option value="30">...Within 30 Days</option>
<option value="45" selected>Published Within Last 45 Days</option>
<option value="60">...Within 60 Days</option>
<option value="90">...Within 90 Days</option>
</select>
<div class="show-card-checkbox" style="margin-top: 1em;">
<input type="checkbox" id="admin-show-hidden-checkbox" name="adminHidden" />
<label for="admin-show-hidden-checkbox">Show User-Hidden Cards?</label>
@ -1078,7 +1080,7 @@ const createRemoveButtonHtml = (name, cardIdentifier) => {
const handleKickMinter = async (minterName) => {
try {
isAddress = await getAddressInfo(minterName)
let isAddress = await getAddressInfo(minterName)
// Optional block check
let txGroupId = 0
@ -1091,7 +1093,7 @@ const handleKickMinter = async (minterName) => {
// Get the minter address from name info
let minterAddress
if (!isAddress){
if (!isAddress.address || !isAddress.address != minterName){
const minterNameInfo = await getNameInfo(minterName)
minterAddress = minterNameInfo?.owner
} else {
@ -1107,7 +1109,7 @@ const handleKickMinter = async (minterName) => {
const reason = 'Kicked by Minter Admins'
const fee = 0.01
const rawKickTransaction = await createGroupKickTransaction(minterAddress, adminPublicKey, 694, minterAddress, reason, txGroupId, fee)
const rawKickTransaction = await createGroupKickTransaction(adminPublicKey, 694, minterAddress, reason, txGroupId, fee)
const signedKickTransaction = await qortalRequest({
action: "SIGN_TRANSACTION",
@ -1138,7 +1140,7 @@ const handleKickMinter = async (minterName) => {
}
const handleBanMinter = async (minterName) => {
isAddress = await getAddressInfo(minterName)
let isAddress = await getAddressInfo(minterName)
try {
let txGroupId = 0
// const { height: currentHeight } = await getLatestBlockInfo()
@ -1151,9 +1153,9 @@ const handleBanMinter = async (minterName) => {
txGroupId = 694
}
let minterAddress
if (!isAddress) {
if (!isAddress.address || !isAddress.address != minterName){
const minterNameInfo = await getNameInfo(minterName)
const minterAddress = minterNameInfo?.owner
minterAddress = minterNameInfo?.owner
} else {
minterAddress = minterName
}

View File

@ -25,42 +25,99 @@ const loadMinterBoardPage = async () => {
const publishButtonColor = '#527c9d'
const minterBoardNameColor = '#527c9d'
mainContent.innerHTML = `
<div class="minter-board-main" style="padding: 20px; text-align: center;">
<h1 style="color: ${minterBoardNameColor};">Minter Board</h1>
<p style="font-size: 1.25em;"> Publish a Minter Card with Information, and obtain and view the support of the community. Welcome to the Minter Board!</p>
<button id="publish-card-button" class="publish-card-button" style="margin: 20px; padding: 10px; background-color: ${publishButtonColor}">Publish Minter Card</button>
<button id="refresh-cards-button" class="refresh-cards-button" style="padding: 10px;">Refresh Cards</button>
<select id="sort-select" style="margin-left: 10px; padding: 5px; font-size: 1.25rem; color:rgb(38, 106, 106); background-color: black;">
<option value="newest" selected>Sort by Date</option>
<option value="name">Sort by Name</option>
<option value="recent-comments">Newest Comments</option>
<option value="least-votes">Least Votes</option>
<option value="most-votes">Most Votes</option>
</select>
<select id="time-range-select" style="margin-left: 10px; padding: 5px; font-size: 1.25rem; color: white; background-color: black;">
<option value="0">Show All</option>
<option value="1">Last 1 day</option>
<option value="7">Last 7 days</option>
<option value="30" selected>Last 30 days</option>
<option value="90">Last 90 days</option>
</select>
<div id="cards-container" class="cards-container" style="margin-top: 20px;"></div>
<div id="publish-card-view" class="publish-card-view" style="display: none; text-align: left; padding: 20px;">
<form id="publish-card-form" class="publish-card-form">
<h3>Create or Update Your Card</h3>
<label for="card-header">Header:</label>
<input type="text" id="card-header" maxlength="100" placeholder="Enter card header" required>
<label for="card-content">Content:</label>
<textarea id="card-content" placeholder="Enter detailed information about why you would like to be a minter... the more the better, and links to things you have published on QDN will help a lot! Give the Minter Admins things to make decisions by!" required></textarea>
<label for="card-links">Links (qortal://...):</label>
<div id="links-container">
<input type="text" class="card-link" placeholder="Enter QDN link">
<div class="minter-board-main" style="padding: 0.5vh; text-align: center;">
<!-- Board Title + Intro -->
<h1 style="color: #527c9d;">The Minter Board</h1>
<p style="font-size: 1.2em; color:rgb(85, 119, 101)">
The Minter Board is where Minting Rights are Delegated.
</p>
<p style="font-size: 1.1em; color:rgb(85, 119, 119)">
To obtain minting rights, click 'PUBLISH CARD' and create your card. A subsequent vote will approve/deny your card.
</p>
<p>
After your card has received the necessary invite, return to the card and click the Join Group button to join the MINTER group.
(A Detailed how-to guide will be coming soon.)
</p>
<div class="card-display-options">
<!-- Centered heading -->
<h4 class="options-heading"style="color: #527c9d;">CARD DISPLAY OPTIONS</h4>
<!-- A flex container for all the controls (sort, time range, checkbox) -->
<div class="options-row">
<!-- Sort by -->
<label for="sort-select" class="options-label">Sort By:</label>
<select id="sort-select" class="options-select">
<option value="newest" selected>Date</option>
<option value="name">Name</option>
<option value="recent-comments">Newest Comments</option>
<option value="least-votes">Least Votes</option>
<option value="most-votes">Most Votes</option>
</select>
<!-- Time range -->
<label for="time-range-select" class="options-label">Show Cards:</label>
<select id="time-range-select" class="options-select">
<option value="0">Show ALL Cards Published</option>
<option value="1">...Within Last 1 Day</option>
<option value="7">...Within Last 7 Days</option>
<option value="30">...Within 30 Days</option>
<option value="45" selected>Published Within Last 45 Days</option>
<option value="60">...Within 60 Days</option>
<option value="90">...Within 90 Days</option>
</select>
<!-- Show existing checkbox -->
<label class="options-check">
<input type="checkbox" id="show-existing-checkbox" />
Show Existing Minter Cards (History)
</label>
</div>
</div>
<!-- Card counter heading centered, with actual counter below if desired -->
<div style="margin-bottom: 1em;">
<div style="text-align: center; margin-top: 0.5em;">
<span id="board-card-counter" style="font-size: 1rem; color:rgb(153, 203, 204); padding: 0.5em;">
<!-- e.g. "5 cards found" -->
</span>
</div>
<button type="button" id="add-link-button">Add Another Link</button>
<button type="submit" id="submit-publish-button">Publish Card</button>
<button type="button" id="cancel-publish-button">Cancel</button>
</form>
</div>
</div>
<!-- Row for Publish / Refresh actions -->
<div class="card-actions" style="margin-bottom: 1em;">
<button id="publish-card-button" class="publish-card-button">
PUBLISH CARD
</button>
<button id="refresh-cards-button" class="refresh-cards-button"
style="padding: 1vh;">
REFRESH CARDS
</button>
</div>
<!-- Container for displayed cards -->
<div id="cards-container" class="cards-container" style="margin-top: 2vh;"></div>
<!-- Hidden Publish Card Form -->
<div id="publish-card-view" class="publish-card-view" style="display: none; text-align: left; padding: 2vh;">
<form id="publish-card-form" class="publish-card-form">
<h3>Create or Update Your Card</h3>
<label for="card-header">Header:</label>
<input type="text" id="card-header" maxlength="100" placeholder="Enter card header" required>
<label for="card-content">Content:</label>
<textarea id="card-content" placeholder="Enter detailed information about why you would like to be a minter... the more the better..." required>
</textarea>
<label for="card-links">Links (qortal://...):</label>
<div id="links-container">
<input type="text" class="card-link" placeholder="Enter QDN link">
</div>
<button type="button" id="add-link-button">Add Another Link</button>
<button type="submit" id="submit-publish-button">Publish Card</button>
<button type="button" id="cancel-publish-button">Cancel</button>
</form>
</div>
</div>
`
document.body.appendChild(mainContent)
@ -144,6 +201,13 @@ const loadMinterBoardPage = async () => {
await loadCards(minterCardIdentifierPrefix)
})
const showExistingCardsCheckbox = document.getElementById('show-existing-checkbox')
if (showExistingCardsCheckbox) {
showExistingCardsCheckbox.addEventListener('change', async (event) => {
await loadCards(minterCardIdentifierPrefix)
})
}
await featureTriggerCheck()
await loadCards(minterCardIdentifierPrefix)
}
@ -367,6 +431,12 @@ const loadCards = async (cardIdentifierPrefix) => {
const cardsContainer = document.getElementById("cards-container")
let isARBoard = false
cardsContainer.innerHTML = "<p>Loading cards...</p>"
const counterSpan = document.getElementById("board-card-counter")
if (counterSpan) {
// Clear or show "Loading..."
counterSpan.textContent = "(loading...)"
}
if (cardIdentifierPrefix.startsWith("QM-AR-card")) {
isARBoard = true
@ -375,6 +445,9 @@ const loadCards = async (cardIdentifierPrefix) => {
let afterTime = 0
const timeRangeSelect = document.getElementById("time-range-select")
const showExistingCheckbox = document.getElementById("show-existing-checkbox")
const showExisting = showExistingCheckbox && showExistingCheckbox.checked
if (timeRangeSelect) {
const days = parseInt(timeRangeSelect.value, 10)
if (days > 0) {
@ -440,6 +513,7 @@ const loadCards = async (cardIdentifierPrefix) => {
// else 'newest' => do nothing (already sorted newest-first by your process functions).
// Create the 'finalCardsArray' that includes the data, etc.
let finalCardsArray = []
let alreadyMinterCards = []
cardsContainer.innerHTML = ''
for (const card of finalCards) {
try {
@ -477,8 +551,14 @@ const loadCards = async (cardIdentifierPrefix) => {
} else {
const isAlreadyMinter = await verifyMinter(cardDataResponse.creator)
if (isAlreadyMinter) {
console.warn(`card IS ALREADY a minter, NOT displaying following identifier on the MinterBoard: ${card.identifier}`)
console.warn(`card IS ALREADY a minter, adding to alreadyMinterCards array: ${card.identifier}`)
removeSkeleton(card.identifier)
alreadyMinterCards.push({
...card,
cardDataResponse,
pollPublisherAddress,
cardPublisherAddress
})
continue
}
}
@ -489,6 +569,12 @@ const loadCards = async (cardIdentifierPrefix) => {
pollPublisherAddress,
cardPublisherAddress,
})
if (counterSpan) {
const displayedCount = finalCardsArray.length
const alreadyMinterCount = alreadyMinterCards.length
// If you want to show both
counterSpan.textContent = `(${displayedCount} cards, ${alreadyMinterCount} existingMinters)`
}
} catch (err) {
console.error(`Error preparing card ${card.identifier}`, err)
removeSkeleton(card.identifier)
@ -531,9 +617,39 @@ const loadCards = async (cardIdentifierPrefix) => {
replaceSkeleton(cardObj.identifier, finalCardHTML)
}
if (showExisting && alreadyMinterCards.length > 0) {
console.warn(`Rendering Existing Minter cards because user selected showExisting`)
for (const mintedCardObj of alreadyMinterCards) {
const skeletonHTML = createSkeletonCardHTML(mintedCardObj.identifier)
cardsContainer.insertAdjacentHTML("beforeend", skeletonHTML)
const pollResults = await fetchPollResults(mintedCardObj.cardDataResponse.poll)
const commentCount = await countComments(mintedCardObj.identifier)
const cardUpdatedTime = mintedCardObj.updated || null
const bgColor = generateDarkPastelBackgroundBy(mintedCardObj.name)
const isExistingMinter = true
const finalCardHTML = await createCardHTML(
mintedCardObj.cardDataResponse,
pollResults,
mintedCardObj.identifier,
commentCount,
cardUpdatedTime,
bgColor,
mintedCardObj.cardPublisherAddress,
isExistingMinter
)
replaceSkeleton(mintedCardObj.identifier, finalCardHTML)
}
}
} catch (error) {
console.error("Error loading cards:", error)
cardsContainer.innerHTML = "<p>Failed to load cards.</p>"
if (counterSpan) {
counterSpan.textContent = "(error loading)"
}
}
}
@ -750,7 +866,6 @@ const loadCardIntoForm = async (cardData) => {
// Main function to publish a new Minter Card -----------------------------------------------
const publishCard = async (cardIdentifierPrefix) => {
const minterGroupData = await fetchMinterGroupMembers()
const minterGroupAddresses = minterGroupData.map(m => m.member)
const userAddress = userState.accountAddress
@ -759,6 +874,7 @@ const publishCard = async (cardIdentifierPrefix) => {
alert("You are already a Minter and cannot publish a new card!")
return
}
const header = document.getElementById("card-header").value.trim()
const content = document.getElementById("card-content").value.trim()
const links = Array.from(document.querySelectorAll(".card-link"))
@ -770,8 +886,27 @@ const publishCard = async (cardIdentifierPrefix) => {
return
}
const cardIdentifier = isExistingCard ? existingCardIdentifier : `${cardIdentifierPrefix}-${await uid()}`
const pollName = `${cardIdentifier}-poll`
if (isExistingCard) {
if (!existingCardData || Object.keys(existingCardData).length === 0) {
const fetched = await fetchExistingCard(cardIdentifierPrefix)
if (fetched) {
existingCardData = fetched
} else {
console.warn("fetchExistingCard returned null. Possibly no existing card found.")
}
}
}
const cardIdentifier = isExistingCard && existingCardIdentifier
? existingCardIdentifier
: `${cardIdentifierPrefix}-${await uid()}`
let existingPollName
if (existingCardData && existingCardData.poll) {
existingPollName = existingCardData.poll
}
const pollName = existingPollName || `${cardIdentifier}-poll`
const pollDescription = `Mintership Board Poll for ${userState.accountName}`
const cardData = {
@ -781,16 +916,16 @@ const publishCard = async (cardIdentifierPrefix) => {
creator: userState.accountName,
creatorAddress: userState.accountAddress,
timestamp: Date.now(),
poll: pollName,
poll: pollName // either the existing poll or a new one
}
try {
let base64CardData = await objectToBase64(cardData)
if (!base64CardData) {
console.log(`initial base64 object creation with objectToBase64 failed, using btoa...`)
base64CardData = btoa(JSON.stringify(cardData))
}
if (!base64CardData) {
console.log(`initial base64 object creation with objectToBase64 failed, using btoa...`)
base64CardData = btoa(JSON.stringify(cardData))
}
await qortalRequest({
action: "PUBLISH_QDN_RESOURCE",
name: userState.accountName,
@ -799,7 +934,7 @@ const publishCard = async (cardIdentifierPrefix) => {
data64: base64CardData,
})
if (!isExistingCard){
if (!isExistingCard || !existingPollName) {
await qortalRequest({
action: "CREATE_POLL",
pollName,
@ -807,26 +942,33 @@ const publishCard = async (cardIdentifierPrefix) => {
pollOptions: ['Yes, No'],
pollOwnerAddress: userState.accountAddress,
})
alert("Card and poll published successfully!")
if (!isExistingCard) {
alert("Card and poll published successfully!")
} else {
alert("Existing card updated, and new poll created (since existing poll was missing)!")
}
} else {
alert("Card updated successfully! (No poll updates possible)")
}
if (isExistingCard){
alert("Card Updated Successfully! (No poll updates possible)")
if (isExistingCard) {
isExistingCard = false
existingCardData = {}
}
document.getElementById("publish-card-form").reset()
document.getElementById("publish-card-view").style.display = "none"
document.getElementById("cards-container").style.display = "flex"
await loadCards(minterCardIdentifierPrefix)
} catch (error) {
console.error("Error publishing card or poll:", error)
alert("Failed to publish card and poll.")
}
}
let globalVoterMap = new Map()
const processPollData= async (pollData, minterGroupMembers, minterAdmins, creator, cardIdentifier) => {
@ -1193,6 +1335,7 @@ const toggleComments = async (cardIdentifier) => {
const commentButton = document.getElementById(`comment-button-${cardIdentifier}`)
if (!commentsSection || !commentButton) return
const count = commentButton.dataset.commentCount
const isHidden = (commentsSection.style.display === 'none' || !commentsSection.style.display)
@ -1469,7 +1612,7 @@ const checkAndDisplayInviteButton = async (adminYes, creator, cardIdentifier) =>
// fetch all final KICK/BAN tx
const { finalKickTxs, finalBanTxs } = await fetchAllKickBanTxData()
const { finalInviteTxs, pendingInviteTxs } = await fetchAllInviteTransactions()
// check if there's a final (non-pending) KICK or BAN for this user
// check if there's a KICK or BAN for this user.
const priorKick = finalKickTxs.some(tx => tx.member === minterAddress)
const priorBan = finalBanTxs.some(tx => tx.offender === minterAddress)
const existingInvite = finalInviteTxs.some(tx => tx.invitee === minterAddress)
@ -1480,10 +1623,12 @@ const checkAndDisplayInviteButton = async (adminYes, creator, cardIdentifier) =>
// build the normal invite button & groupApprovalHtml
let inviteButtonHtml = ""
if (existingInvite || pendingInvite){
console.warn(`There is an EXISTING INVITE for this user! No invite button being created... existing: (${existingInvite}, pending: ${pendingInvite})`)
console.warn(`There is an EXISTING or PENDING INVITE for this user! No invite button being created... existing: (${existingInvite}, pending: ${pendingInvite})`)
inviteButtonHtml = ''
} else {
inviteButtonHtml = isSomeTypaAdmin ? createInviteButtonHtml(creator, cardIdentifier) : ""
}
inviteButtonHtml = isSomeTypaAdmin ? createInviteButtonHtml(creator, cardIdentifier) : ""
const groupApprovalHtml = await checkGroupApprovalAndCreateButton(minterAddress, cardIdentifier, "GROUP_INVITE")
// if user had no prior KICK/BAN
@ -1903,7 +2048,7 @@ const getNewestCommentTimestamp = async (cardIdentifier) => {
}
// Create the overall Minter Card HTML -----------------------------------------------
const createCardHTML = async (cardData, pollResults, cardIdentifier, commentCount, cardUpdatedTime, bgColor, address) => {
const createCardHTML = async (cardData, pollResults, cardIdentifier, commentCount, cardUpdatedTime, bgColor, address, isExistingMinter=false) => {
const { header, content, links, creator, creatorAddress, timestamp, poll } = cardData
const formattedDate = cardUpdatedTime ? new Date(cardUpdatedTime).toLocaleString() : new Date(timestamp).toLocaleString()
const avatarHtml = await getMinterAvatar(creator)
@ -1919,7 +2064,7 @@ const createCardHTML = async (cardData, pollResults, cardIdentifier, commentCoun
createModal('links')
createModal('poll-details')
const inviteButtonHtml = await checkAndDisplayInviteButton(adminYes, creator, cardIdentifier)
const inviteButtonHtml = isExistingMinter ? "" : await checkAndDisplayInviteButton(adminYes, creator, cardIdentifier)
let inviteHtmlAdd = (inviteButtonHtml) ? inviteButtonHtml : ''
let finalBgColor = bgColor
@ -1935,6 +2080,9 @@ const createCardHTML = async (cardData, pollResults, cardIdentifier, commentCoun
finalBgColor = "rgba(1, 65, 39, 0.41)"; // or any green you want
} else if (userVote === 1) {
finalBgColor = "rgba(107, 3, 3, 0.3)"; // or any red you want
} else if (isExistingMinter){
finalBgColor = "rgb(99, 99, 99)"
invitedText = `<h4 style="color:rgb(135, 55, 16); margin-bottom: 0.5em;">EXISTING MINTER</h4>`
} else if (hasMinterInvite) {
// If so, override background color & add an "INVITED" label
finalBgColor = "black";

View File

@ -1,4 +1,4 @@
const Q_MINTERSHIP_VERSION = "1.06"
const Q_MINTERSHIP_VERSION = "1.06.4"
const messageIdentifierPrefix = `mintership-forum-message`
const messageAttachmentIdentifierPrefix = `mintership-forum-attachment`

View File

@ -224,6 +224,12 @@ const getUserAddress = async () => {
}
const getAddressInfo = async (address) => {
const qortalAddressPattern = /^Q[A-Za-z0-9]{33}$/ // Q + 33 almum = 34 total length
if (!qortalAddressPattern.test(address)) {
console.warn(`Not a valid Qortal address format, returning same thing that was passed to not break other functions: ${address}`)
return address
}
try {
const response = await fetch (`${baseUrl}/addresses/${address}`, {
headers: { 'Accept': 'application/json' },
@ -786,18 +792,20 @@ const searchSimple = async (service, identifier, name, limit=1500, offset=0, roo
if (name && !identifier && !room) {
console.log('name only searchSimple', name)
urlSuffix = `service=${service}&name=${name}&limit=${limit}&prefix=true&reverse=${reverse}`
urlSuffix = `service=${service}&name=${name}&limit=${limit}&prefix=true&reverse=${reverse}&after=${after}`
console.log(`urlSuffix used: ${urlSuffix}`)
} else if (!name && identifier && !room) {
console.log('identifier only searchSimple', identifier)
urlSuffix = `service=${service}&identifier=${identifier}&limit=${limit}&prefix=true&reverse=${reverse}`
urlSuffix = `service=${service}&identifier=${identifier}&limit=${limit}&prefix=true&reverse=${reverse}&after=${after}`
console.log(`urlSuffix used: ${urlSuffix}`)
} else if (!name && !identifier && !room) {
console.error(`name: ${name} AND identifier: ${identifier} not passed. Must include at least one...`)
return null
} else {
console.log(`final searchSimple params = service: '${service}', identifier: '${identifier}', name: '${name}', limit: '${limit}', offset: '${offset}', room: '${room}', reverse: '${reverse}'`)
console.log(`final searchSimple params = service: '${service}', identifier: '${identifier}', name: '${name}', limit: '${limit}', offset: '${offset}', room: '${room}', reverse: '${reverse}', after: ${after}`)
}
const response = await fetch(`${baseUrl}/arbitrary/resources/searchsimple?${urlSuffix}`, {
@ -1395,16 +1403,16 @@ const createGroupInviteTransaction = async (recipientAddress, adminPublicKey, gr
}
}
const createGroupKickTransaction = async (recipientAddress, adminPublicKey, groupId=694, member, reason='Kicked by admins', txGroupId, fee) => {
const createGroupKickTransaction = async (adminPublicKey, groupId=694, member, reason='Kicked by admins', txGroupId=694, fee=0.01) => {
try {
// Fetch account reference correctly
const accountInfo = await getAddressInfo(recipientAddress)
const accountInfo = await getAddressInfo(member)
const accountReference = accountInfo.reference
// Validate inputs before making the request
if (!adminPublicKey || !accountReference || !recipientAddress) {
throw new Error("Missing required parameters for group invite transaction.")
if (!adminPublicKey || !accountReference || !member) {
throw new Error("Missing required parameters for group kick transaction.")
}
const payload = {
@ -1412,11 +1420,10 @@ const createGroupKickTransaction = async (recipientAddress, adminPublicKey, grou
reference: accountReference,
fee,
txGroupId,
recipient: null,
adminPublicKey,
groupId: groupId,
member: member || recipientAddress,
reason: reason
groupId,
member,
reason
}
console.log("Sending GROUP_KICK transaction payload:", payload)

View File

@ -141,7 +141,7 @@
<div class="row">
<div class="col-12 col-lg-4">
<div class="card-wrapper" style="justify-content:center; align: center; align-text: center;">
<div class="card-wrapper" style="justify-content:center;">
<div class="icon-wrapper">
<span class="mbr-iconfont mbr-iconfont-btn mbri-file" style="color:aliceblue;"></span>
</div>
@ -200,14 +200,14 @@
<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.06beta 01-31-2025</h2>
<h2 class="mbr-section-title mbr-fonts-style display-2 version">
</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.06b Fixes</u></b>- <b>EMERGENCY UPDATE </b> - See post in the <a href="MINTERSHIP-FORUM">FORUM</a> for RELEASE NOTES, This is an emergency update that is meant to prevent the issue that took place yesterday and ended up stalling quite a few nodes. This means that Q-Mintership should be the ONLY APP UTILIZED FOR THE FUNCTIONALITY IT PROVIDES.
<b class="version"><u>v1.06.4b</u></b>- <b>various improvements</b> - See post in the <a href="MINTERSHIP-FORUM">FORUM</a> for RELEASE NOTES.
</p>
</div>
</div>