From 9971c6d595fdd5d6fb39a1b736d5e757aa773c2e Mon Sep 17 00:00:00 2001
From: QuickMythril <quickmythril@protonmail.com>
Date: Mon, 3 Feb 2025 00:43:21 -0500
Subject: [PATCH] move more code to Shared.js

---
 assets/js/MinterBoard.js | 244 ---------------------------------------
 assets/js/Shared.js      | 243 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 243 insertions(+), 244 deletions(-)

diff --git a/assets/js/MinterBoard.js b/assets/js/MinterBoard.js
index 527981d..9025d50 100644
--- a/assets/js/MinterBoard.js
+++ b/assets/js/MinterBoard.js
@@ -810,236 +810,6 @@ const publishCard = async (cardIdentifierPrefix) => {
   }
 }
 
-let globalVoterMap = new Map()
-
-const processPollData= async (pollData, minterGroupMembers, minterAdmins, creator, cardIdentifier) => {
-  if (!pollData || !Array.isArray(pollData.voteWeights) || !Array.isArray(pollData.votes)) {
-    console.warn("Poll data is missing or invalid. pollData:", pollData)
-    return {
-      adminYes: 0,
-      adminNo: 0,
-      minterYes: 0,
-      minterNo: 0,
-      totalYes: 0,
-      totalNo: 0,
-      totalYesWeight: 0,
-      totalNoWeight: 0,
-      detailsHtml: `<p>Poll data is invalid or missing.</p>`,
-      userVote: null
-    }
-  }
-
-  const memberAddresses = minterGroupMembers.map(m => m.member)
-  const minterAdminAddresses = minterAdmins.map(m => m.member)
-  const adminGroupsMembers = await fetchAllAdminGroupsMembers()
-  const featureTriggerPassed = await featureTriggerCheck()
-  const groupAdminAddresses = adminGroupsMembers.map(m => m.member)
-  let adminAddresses = [...minterAdminAddresses]
-
-  if (!featureTriggerPassed) {
-    console.log(`featureTrigger is NOT passed, only showing admin results from Minter Admins and Group Admins`)
-    adminAddresses = [...minterAdminAddresses, ...groupAdminAddresses]
-  }
-  
-  let adminYes = 0, adminNo = 0
-  let minterYes = 0, minterNo = 0
-  let yesWeight = 0, noWeight = 0
-  let userVote = null
-
-  for (const w of pollData.voteWeights) {
-    if (w.optionName.toLowerCase() === 'yes') {
-      yesWeight = w.voteWeight
-    } else if (w.optionName.toLowerCase() === 'no') {
-      noWeight = w.voteWeight
-    }
-  }
-
-  const voterPromises = pollData.votes.map(async (vote) => {
-    const optionIndex = vote.optionIndex; // 0 => yes, 1 => no
-    const voterPublicKey = vote.voterPublicKey
-    const voterAddress = await getAddressFromPublicKey(voterPublicKey)
-
-    if (voterAddress === userState.accountAddress) {
-      userVote = optionIndex
-    }
-
-    if (optionIndex === 0) {
-      if (adminAddresses.includes(voterAddress)) {
-        adminYes++
-      } else if (memberAddresses.includes(voterAddress)) {
-        minterYes++
-      } else {
-        console.log(`voter ${voterAddress} is not a minter nor an admin... Not included in aggregates.`)
-      }
-    } else if (optionIndex === 1) {
-      if (adminAddresses.includes(voterAddress)) {
-        adminNo++
-      } else if (memberAddresses.includes(voterAddress)) {
-        minterNo++
-      } else {
-        console.log(`voter ${voterAddress} is not a minter nor an admin... Not included in aggregates.`)
-      }
-    }
-
-    let voterName = ''
-    try {
-      const nameInfo = await getNameFromAddress(voterAddress)
-      if (nameInfo) {
-        voterName = nameInfo
-        if (nameInfo === voterAddress) voterName = ''
-      }
-    } catch (err) {
-      console.warn(`No name for address ${voterAddress}`, err)
-    }
-
-    let blocksMinted = 0
-    try {
-      const addressInfo = await getAddressInfo(voterAddress)
-      blocksMinted = addressInfo?.blocksMinted || 0
-    } catch (e) {
-      console.warn(`Failed to get addressInfo for ${voterAddress}`, e)
-    }
-    const isAdmin = adminAddresses.includes(voterAddress)
-    const isMinter = memberAddresses.includes(voterAddress)
-    
-    return {
-      optionIndex,
-      voterPublicKey,
-      voterAddress,
-      voterName,
-      isAdmin,
-      isMinter,
-      blocksMinted
-    }
-  })
-
-  const allVoters = await Promise.all(voterPromises)
-  const yesVoters = []
-  const noVoters = []
-  let totalMinterAndAdminYesWeight = 0
-  let totalMinterAndAdminNoWeight = 0
-
-  for (const v of allVoters) {
-    if (v.optionIndex === 0) {
-      yesVoters.push(v)
-      totalMinterAndAdminYesWeight+=v.blocksMinted
-    } else if (v.optionIndex === 1) {
-      noVoters.push(v)
-      totalMinterAndAdminNoWeight+=v.blocksMinted
-    }
-  }
-
-  yesVoters.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 noTableHtml = buildVotersTableHtml(noVoters, /* tableColor= */ "red")
-  const detailsHtml = `
-    <div class="poll-details-container" id'"${creator}-poll-details">
-      <h1 style ="color:rgb(123, 123, 85); text-align: center; font-size: 2.0rem">${creator}'s</h1><h3 style="color: white; text-align: center; font-size: 1.8rem"> Support Poll Result Details</h3>
-      <h4 style="color: green; text-align: center;">Yes Vote Details</h4>
-      ${yesTableHtml}
-      <h4 style="color: red; text-align: center; margin-top: 2em;">No Vote Details</h4>
-      ${noTableHtml}
-    </div>
-  `
-  const totalYes = adminYes + minterYes
-  const totalNo = adminNo + minterNo
-
-  return {
-    adminYes,
-    adminNo,
-    minterYes,
-    minterNo,
-    totalYes,
-    totalNo,
-    totalYesWeight: totalMinterAndAdminYesWeight,
-    totalNoWeight: totalMinterAndAdminNoWeight,
-    detailsHtml,
-    userVote
-  }
-}
-
-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) => {
-  if (!voters.length) {
-    return `<p>No voters here.</p>`
-  }
-
-  // Decide extremely dark background for the <tbody>
-  let bodyBackground
-  if (tableColor === "green") {
-    bodyBackground = "rgba(0, 18, 0, 0.8)" // near-black green
-  } else if (tableColor === "red") {
-    bodyBackground = "rgba(30, 0, 0, 0.8)" // near-black red
-  } else {
-    // fallback color if needed
-    bodyBackground = "rgba(40, 20, 10, 0.8)"
-  }
-
-  // tableColor is used for the <thead>, bodyBackground for the <tbody>
-  const minterColor = 'rgb(98, 122, 167)'
-  const adminColor = 'rgb(44, 209, 151)'
-  const userColor = 'rgb(102, 102, 102)'
-  return `
-    <table style="
-      width: 100%;
-      border-style: dotted;
-      border-width: 0.15rem;
-      border-color: #576b6f;
-      margin-bottom: 1em;
-      border-collapse: collapse;
-    ">
-      <thead style="background: ${tableColor}; color:rgb(238, 238, 238) ;">
-        <tr style="font-size: 1.5rem;">
-          <th style="padding: 0.1rem; text-align: center;">Voter Name/Address</th>
-          <th style="padding: 0.1rem; text-align: center;">Voter Type</th>
-          <th style="padding: 0.1rem; text-align: center;">Voter Weight(=BlocksMinted)</th>
-        </tr>
-      </thead>
-
-      <!-- Tbody with extremely dark green or red -->
-      <tbody style="background-color: ${bodyBackground}; color: #c6c6c6;">
-        ${voters
-          .map(v => {
-            const userType = v.isAdmin ? "Admin" : v.isMinter ? "Minter" : "User"
-            const pollName = v.pollName
-            const displayName =
-              v.voterName
-                ? v.voterName
-                : v.voterAddress
-            return `
-              <tr style="font-size: 1.2rem; border-width: 0.1rem; border-style: dotted; border-color: lightgrey; font-weight: bold;">
-                <td style="padding: 1.2rem; border-width: 0.1rem; border-style: dotted; border-color: lightgrey; text-align: center; 
-                color:${userType === 'Admin' ? adminColor : v.isMinter? minterColor : userColor };">${displayName}</td>
-                <td style="padding: 1.2rem; border-width: 0.1rem; border-style: dotted; border-color: lightgrey; text-align: center; 
-                color:${userType === 'Admin' ? adminColor : v.isMinter? minterColor : userColor };">${userType}</td>
-                <td style="padding: 1.2rem; border-width: 0.1rem; border-style: dotted; border-color: lightgrey; text-align: center; 
-                color:${userType === 'Admin' ? adminColor : v.isMinter? minterColor : userColor };">${v.blocksMinted}</td>
-              </tr>
-            `
-          })
-          .join("")}
-      </tbody>
-    </table>
-  `
-}
-
-
 // Post a comment on a card. --------------------------------- 
 const postComment = async (cardIdentifier) => {
   const commentInput = document.getElementById(`new-comment-${cardIdentifier}`)
@@ -1411,20 +1181,6 @@ const createInviteButtonHtml = (creator, cardIdentifier) => {
   `
 }
 
-const featureTriggerCheck = async () => {
-  const latestBlockInfo = await getLatestBlockInfo()
-  const isBlockPassed = latestBlockInfo.height >= GROUP_APPROVAL_FEATURE_TRIGGER_HEIGHT
-  if (isBlockPassed) {
-    console.warn(`featureTrigger check (verifyFeatureTrigger) determined block has PASSED:`, isBlockPassed)
-    featureTriggerPassed = true
-    return true
-  } else {
-    console.warn(`featureTrigger check (verifyFeatureTrigger) determined block has NOT PASSED:`, isBlockPassed)
-    featureTriggerPassed = false
-    return false
-  }
-}
-
 const checkAndDisplayInviteButton = async (adminYes, creator, cardIdentifier) => {
   const isSomeTypaAdmin = userState.isAdmin || userState.isMinterAdmin
   const isBlockPassed = await featureTriggerCheck()
diff --git a/assets/js/Shared.js b/assets/js/Shared.js
index 03b48ac..c3596f5 100644
--- a/assets/js/Shared.js
+++ b/assets/js/Shared.js
@@ -340,4 +340,247 @@ const applyVoteSortingData = async (cards, ascending = true) => {
     })
   }
 }
+  
+let globalVoterMap = new Map()
+  
+const processPollData= async (pollData, minterGroupMembers, minterAdmins, creator, cardIdentifier) => {
+  if (!pollData || !Array.isArray(pollData.voteWeights) || !Array.isArray(pollData.votes)) {
+    console.warn("Poll data is missing or invalid. pollData:", pollData)
+    return {
+      adminYes: 0,
+      adminNo: 0,
+      minterYes: 0,
+      minterNo: 0,
+      totalYes: 0,
+      totalNo: 0,
+      totalYesWeight: 0,
+      totalNoWeight: 0,
+      detailsHtml: `<p>Poll data is invalid or missing.</p>`,
+      userVote: null
+    }
+  }
+
+  const memberAddresses = minterGroupMembers.map(m => m.member)
+  const minterAdminAddresses = minterAdmins.map(m => m.member)
+  const adminGroupsMembers = await fetchAllAdminGroupsMembers()
+  const featureTriggerPassed = await featureTriggerCheck()
+  const groupAdminAddresses = adminGroupsMembers.map(m => m.member)
+  let adminAddresses = [...minterAdminAddresses]
+
+  if (!featureTriggerPassed) {
+    console.log(`featureTrigger is NOT passed, only showing admin results from Minter Admins and Group Admins`)
+    adminAddresses = [...minterAdminAddresses, ...groupAdminAddresses]
+  }
+  
+  let adminYes = 0, adminNo = 0
+  let minterYes = 0, minterNo = 0
+  let yesWeight = 0, noWeight = 0
+  let userVote = null
+
+  for (const w of pollData.voteWeights) {
+    if (w.optionName.toLowerCase() === 'yes') {
+      yesWeight = w.voteWeight
+    } else if (w.optionName.toLowerCase() === 'no') {
+      noWeight = w.voteWeight
+    }
+  }
+
+  const voterPromises = pollData.votes.map(async (vote) => {
+    const optionIndex = vote.optionIndex; // 0 => yes, 1 => no
+    const voterPublicKey = vote.voterPublicKey
+    const voterAddress = await getAddressFromPublicKey(voterPublicKey)
+
+    if (voterAddress === userState.accountAddress) {
+      userVote = optionIndex
+    }
+
+    if (optionIndex === 0) {
+      if (adminAddresses.includes(voterAddress)) {
+        adminYes++
+      } else if (memberAddresses.includes(voterAddress)) {
+        minterYes++
+      } else {
+        console.log(`voter ${voterAddress} is not a minter nor an admin... Not included in aggregates.`)
+      }
+    } else if (optionIndex === 1) {
+      if (adminAddresses.includes(voterAddress)) {
+        adminNo++
+      } else if (memberAddresses.includes(voterAddress)) {
+        minterNo++
+      } else {
+        console.log(`voter ${voterAddress} is not a minter nor an admin... Not included in aggregates.`)
+      }
+    }
+
+    let voterName = ''
+    try {
+      const nameInfo = await getNameFromAddress(voterAddress)
+      if (nameInfo) {
+        voterName = nameInfo
+        if (nameInfo === voterAddress) voterName = ''
+      }
+    } catch (err) {
+      console.warn(`No name for address ${voterAddress}`, err)
+    }
+
+    let blocksMinted = 0
+    try {
+      const addressInfo = await getAddressInfo(voterAddress)
+      blocksMinted = addressInfo?.blocksMinted || 0
+    } catch (e) {
+      console.warn(`Failed to get addressInfo for ${voterAddress}`, e)
+    }
+    const isAdmin = adminAddresses.includes(voterAddress)
+    const isMinter = memberAddresses.includes(voterAddress)
+    
+    return {
+      optionIndex,
+      voterPublicKey,
+      voterAddress,
+      voterName,
+      isAdmin,
+      isMinter,
+      blocksMinted
+    }
+  })
+
+  const allVoters = await Promise.all(voterPromises)
+  const yesVoters = []
+  const noVoters = []
+  let totalMinterAndAdminYesWeight = 0
+  let totalMinterAndAdminNoWeight = 0
+
+  for (const v of allVoters) {
+    if (v.optionIndex === 0) {
+      yesVoters.push(v)
+      totalMinterAndAdminYesWeight+=v.blocksMinted
+    } else if (v.optionIndex === 1) {
+      noVoters.push(v)
+      totalMinterAndAdminNoWeight+=v.blocksMinted
+    }
+  }
+
+  yesVoters.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 noTableHtml = buildVotersTableHtml(noVoters, /* tableColor= */ "red")
+  const detailsHtml = `
+    <div class="poll-details-container" id'"${creator}-poll-details">
+      <h1 style ="color:rgb(123, 123, 85); text-align: center; font-size: 2.0rem">${creator}'s</h1><h3 style="color: white; text-align: center; font-size: 1.8rem"> Support Poll Result Details</h3>
+      <h4 style="color: green; text-align: center;">Yes Vote Details</h4>
+      ${yesTableHtml}
+      <h4 style="color: red; text-align: center; margin-top: 2em;">No Vote Details</h4>
+      ${noTableHtml}
+    </div>
+  `
+  const totalYes = adminYes + minterYes
+  const totalNo = adminNo + minterNo
+
+  return {
+    adminYes,
+    adminNo,
+    minterYes,
+    minterNo,
+    totalYes,
+    totalNo,
+    totalYesWeight: totalMinterAndAdminYesWeight,
+    totalNoWeight: totalMinterAndAdminNoWeight,
+    detailsHtml,
+    userVote
+  }
+}
+  
+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) => {
+  if (!voters.length) {
+    return `<p>No voters here.</p>`
+  }
+
+  // Decide extremely dark background for the <tbody>
+  let bodyBackground
+  if (tableColor === "green") {
+    bodyBackground = "rgba(0, 18, 0, 0.8)" // near-black green
+  } else if (tableColor === "red") {
+    bodyBackground = "rgba(30, 0, 0, 0.8)" // near-black red
+  } else {
+    // fallback color if needed
+    bodyBackground = "rgba(40, 20, 10, 0.8)"
+  }
+
+  // tableColor is used for the <thead>, bodyBackground for the <tbody>
+  const minterColor = 'rgb(98, 122, 167)'
+  const adminColor = 'rgb(44, 209, 151)'
+  const userColor = 'rgb(102, 102, 102)'
+  return `
+    <table style="
+      width: 100%;
+      border-style: dotted;
+      border-width: 0.15rem;
+      border-color: #576b6f;
+      margin-bottom: 1em;
+      border-collapse: collapse;
+    ">
+      <thead style="background: ${tableColor}; color:rgb(238, 238, 238) ;">
+        <tr style="font-size: 1.5rem;">
+          <th style="padding: 0.1rem; text-align: center;">Voter Name/Address</th>
+          <th style="padding: 0.1rem; text-align: center;">Voter Type</th>
+          <th style="padding: 0.1rem; text-align: center;">Voter Weight(=BlocksMinted)</th>
+        </tr>
+      </thead>
+
+      <!-- Tbody with extremely dark green or red -->
+      <tbody style="background-color: ${bodyBackground}; color: #c6c6c6;">
+        ${voters
+          .map(v => {
+            const userType = v.isAdmin ? "Admin" : v.isMinter ? "Minter" : "User"
+            const pollName = v.pollName
+            const displayName =
+              v.voterName
+                ? v.voterName
+                : v.voterAddress
+            return `
+              <tr style="font-size: 1.2rem; border-width: 0.1rem; border-style: dotted; border-color: lightgrey; font-weight: bold;">
+                <td style="padding: 1.2rem; border-width: 0.1rem; border-style: dotted; border-color: lightgrey; text-align: center; 
+                color:${userType === 'Admin' ? adminColor : v.isMinter? minterColor : userColor };">${displayName}</td>
+                <td style="padding: 1.2rem; border-width: 0.1rem; border-style: dotted; border-color: lightgrey; text-align: center; 
+                color:${userType === 'Admin' ? adminColor : v.isMinter? minterColor : userColor };">${userType}</td>
+                <td style="padding: 1.2rem; border-width: 0.1rem; border-style: dotted; border-color: lightgrey; text-align: center; 
+                color:${userType === 'Admin' ? adminColor : v.isMinter? minterColor : userColor };">${v.blocksMinted}</td>
+              </tr>
+            `
+          })
+          .join("")}
+      </tbody>
+    </table>
+  `
+}
+  
+const featureTriggerCheck = async () => {
+  const latestBlockInfo = await getLatestBlockInfo()
+  const isBlockPassed = latestBlockInfo.height >= GROUP_APPROVAL_FEATURE_TRIGGER_HEIGHT
+  if (isBlockPassed) {
+    console.warn(`featureTrigger check (verifyFeatureTrigger) determined block has PASSED:`, isBlockPassed)
+    featureTriggerPassed = true
+    return true
+  } else {
+    console.warn(`featureTrigger check (verifyFeatureTrigger) determined block has NOT PASSED:`, isBlockPassed)
+    featureTriggerPassed = false
+    return false
+  }
+}
   
\ No newline at end of file