Added sub admin FLO balance checking

This commit is contained in:
sairaj mote 2023-08-15 04:27:02 +05:30
parent 1b625b1c52
commit b6d97322fd
4 changed files with 123 additions and 84 deletions

View File

@ -742,7 +742,7 @@ h3 {
flex-direction: column; flex-direction: column;
gap: 1rem; gap: 1rem;
} }
#home_page section { #home_page > section {
display: grid; display: grid;
width: min(100% - 2rem, 42rem); width: min(100% - 2rem, 42rem);
margin: 0 auto; margin: 0 auto;
@ -832,12 +832,22 @@ h3 {
color: rgba(var(--text-color), 0.8); color: rgba(var(--text-color), 0.8);
} }
#verifier_wrapper > * {
background-color: rgba(var(--foreground-color), 1);
border-radius: 0.5rem;
padding: 1rem;
}
#verifier_balance_container {
width: 100%;
}
.kyc-request { .kyc-request {
display: grid; display: grid;
gap: 1rem; gap: 1rem;
padding: 1rem; padding: 1rem;
border-radius: 0.5rem; border-radius: 0.5rem;
background-color: rgba(var(--foreground-color), 1); background-color: rgba(var(--background-color), 1);
} }
.kyc-request time { .kyc-request time {
font-size: 0.9rem; font-size: 0.9rem;
@ -863,7 +873,7 @@ h3 {
justify-content: space-between; justify-content: space-between;
padding: 1rem; padding: 1rem;
border-radius: 0.5rem; border-radius: 0.5rem;
background-color: rgba(var(--foreground-color), 1); background-color: rgba(var(--background-color), 1);
} }
.revoke-card label { .revoke-card label {
gap: 1rem; gap: 1rem;
@ -976,6 +986,13 @@ h3 {
.popup__header { .popup__header {
padding: 1.5rem 1.5rem 0 0.75rem; padding: 1.5rem 1.5rem 0 0.75rem;
} }
#verifier_wrapper {
display: grid;
grid-template-columns: 16rem 1fr;
width: min(64rem, 100%);
margin: 0 auto;
align-items: flex-start;
}
#view_file_popup { #view_file_popup {
--width: min(56rem, 100%); --width: min(56rem, 100%);
} }

2
css/main.min.css vendored

File diff suppressed because one or more lines are too long

View File

@ -705,7 +705,7 @@ h3 {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 1rem; gap: 1rem;
section { & > section {
display: grid; display: grid;
width: min(calc(100% - 2rem), 42rem); width: min(calc(100% - 2rem), 42rem);
margin: 0 auto; margin: 0 auto;
@ -792,13 +792,22 @@ h3 {
color: rgba(var(--text-color), 0.8); color: rgba(var(--text-color), 0.8);
} }
} }
#verifier_wrapper {
& > * {
background-color: rgba(var(--foreground-color), 1);
border-radius: 0.5rem;
padding: 1rem;
}
}
#verifier_balance_container {
width: 100%;
}
.kyc-request { .kyc-request {
display: grid; display: grid;
gap: 1rem; gap: 1rem;
padding: 1rem; padding: 1rem;
border-radius: 0.5rem; border-radius: 0.5rem;
background-color: rgba(var(--foreground-color), 1); background-color: rgba(var(--background-color), 1);
time { time {
font-size: 0.9rem; font-size: 0.9rem;
color: rgba(var(--text-color), 0.8); color: rgba(var(--text-color), 0.8);
@ -823,7 +832,7 @@ h3 {
justify-content: space-between; justify-content: space-between;
padding: 1rem; padding: 1rem;
border-radius: 0.5rem; border-radius: 0.5rem;
background-color: rgba(var(--foreground-color), 1); background-color: rgba(var(--background-color), 1);
label { label {
gap: 1rem; gap: 1rem;
font-weight: 500; font-weight: 500;
@ -925,6 +934,13 @@ h3 {
.popup__header { .popup__header {
padding: 1.5rem 1.5rem 0 0.75rem; padding: 1.5rem 1.5rem 0 0.75rem;
} }
#verifier_wrapper {
display: grid;
grid-template-columns: 16rem 1fr;
width: min(64rem, 100%);
margin: 0 auto;
align-items: flex-start;
}
#view_file_popup { #view_file_popup {
--width: min(56rem, 100%); --width: min(56rem, 100%);
} }

View File

@ -259,6 +259,7 @@
this.state = state this.state = state
this.routingStart = routingStart this.routingStart = routingStart
this.routingEnd = routingEnd this.routingEnd = routingEnd
this.lastPage = null
window.addEventListener('hashchange', e => this.routeTo(window.location.hash)) window.addEventListener('hashchange', e => this.routeTo(window.location.hash))
} }
addRoute(route, callback) { addRoute(route, callback) {
@ -277,7 +278,7 @@
[, page, ...wildcards] = path.split('/') [, page, ...wildcards] = path.split('/')
else else
page = path page = path
this.state = { page, wildcards } this.state = { page, wildcards, lastPage: this.lastPage }
if (queryString) { if (queryString) {
params = new URLSearchParams(queryString) params = new URLSearchParams(queryString)
this.state.params = Object.fromEntries(params) this.state.params = Object.fromEntries(params)
@ -287,9 +288,13 @@
} }
if (this.routes[page]) { if (this.routes[page]) {
await this.routes[page](this.state) await this.routes[page](this.state)
this.state.lastPage = page this.lastPage = page
} else { } else {
this.routes['404'](this.state) if (this.routes['404']) {
this.routes['404'](this.state);
} else {
console.error(`No route found for '${page}' and no '404' route is defined.`);
}
} }
if (this.routingEnd) { if (this.routingEnd) {
this.routingEnd(this.state) this.routingEnd(this.state)
@ -437,7 +442,6 @@
history.scrollRestoration = "manual"; history.scrollRestoration = "manual";
} }
window.scrollTo(0, 0); window.scrollTo(0, 0);
renderElem(getRef('app_body'), html``);
}, },
routingEnd() { routingEnd() {
document.querySelectorAll(".my-flo-address").forEach(elem => { document.querySelectorAll(".my-flo-address").forEach(elem => {
@ -860,7 +864,7 @@
} }
let userAddressTimeInterval; let userAddressTimeInterval;
function renderHome(appState) { function renderHome(appState) {
const { params: { filter = 'pending', search } = {} } = appState || {}; const { lastPage, page, params: { filter = 'pending', search } = {} } = appState || {};
const mainHeader = html` const mainHeader = html`
<header id="main_header"> <header id="main_header">
<div class="app-brand margin-right-auto hide-on-small"> <div class="app-brand margin-right-auto hide-on-small">
@ -884,49 +888,43 @@
renderElem(getRef('app_body'), html` renderElem(getRef('app_body'), html`
<article id="home_page"> <article id="home_page">
${mainHeader} ${mainHeader}
<section class="grid gap-1"> <div id="verifier_wrapper" class="flex flex-wrap gap-1 align-items-start">
<div id="kyc_requests_header" class="flex align-center space-between gap-1 flex-wrap"> <section id="verifier_balance_container" class="grid gap-1"> </section>
<h3>KYC requests</h3> <section class="grid gap-1">
<sm-chips id="kyc_request_filter" onchange=${handleRequestFilter}> <div id="kyc_requests_header" class="flex align-center space-between gap-1 flex-wrap">
<sm-chip value="pending" ?selected=${filter === "pending"}>Pending</sm-chip> <h3>KYC requests</h3>
<sm-chip value="rejected" ?selected=${filter === "rejected"}>Rejected</sm-chip> <sm-chips id="kyc_request_filter" onchange=${handleRequestFilter}>
<sm-chip value="approved" ?selected=${filter === "approved"}>Approved</sm-chip> <sm-chip value="pending" ?selected=${filter === "pending"}>Pending</sm-chip>
<sm-chip value="all" ?selected=${filter === "all"}>All</sm-chip> <sm-chip value="rejected" ?selected=${filter === "rejected"}>Rejected</sm-chip>
</sm-chips> <sm-chip value="approved" ?selected=${filter === "approved"}>Approved</sm-chip>
</div> <sm-chip value="all" ?selected=${filter === "all"}>All</sm-chip>
<sm-input id="search_approved" type="search" placeholder="Search address" oninput=${handleRequestSearch}> </sm-chips>
<svg class="icon" slot="icon" xmlns="http://www.w3.org/2000/svg" height="24px"
viewBox="0 0 24 24" width="24px" fill="#000000">
<path d="M0 0h24v24H0V0z" fill="none" />
<path
d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" />
</svg>
</sm-input>
<div id="selected_wrapper" class="flex gap-0-5 align-center hidden">
<button class="button icon-only" title="Clear selection" onclick=${clearSelection}>
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24"
width="24px" fill="#000000">
<path d="M0 0h24v24H0V0z" fill="none" />
<path
d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z" />
</svg>
</button>
<div id="selected_addresses"></div>
<div class="multi-state-button margin-left-auto">
<button id="revoke_kyc_button" class="button button--primary"
onclick=${revokeKycs}>Revoke selected</button>
</div> </div>
</div> <sm-input id="search_approved" type="search" placeholder="Search address" oninput=${handleRequestSearch}>
${filter === "approved" ? html` <svg class="icon" slot="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"> <path d="M0 0h24v24H0V0z" fill="none" /> <path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" /> </svg>
<p>Select KYC verification to revoke</p> </sm-input>
`: ''} <div id="selected_wrapper" class="flex gap-0-5 align-center hidden">
<ul id="kyc_requests_list" class="flex flex-direction-column gap-0-5" onchange=${handleAddressSelection}> <button class="button icon-only" title="Clear selection" onclick=${clearSelection}>
${renderedKycRequests?.length ? renderedKycRequests : html`<li class="text-center" style="padding: 3rem;">No requests found</li>`} <svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"> <path d="M0 0h24v24H0V0z" fill="none" /> <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z" /> </svg>
</ul> </button>
</section> <div id="selected_addresses"></div>
<div class="multi-state-button margin-left-auto">
<button id="revoke_kyc_button" class="button button--primary" onclick=${revokeKycs}>Revoke selected</button>
</div>
</div>
${filter === "approved" ? html`
<p>Select KYC verification to revoke</p>
`: ''}
<ul id="kyc_requests_list" class="flex flex-direction-column gap-0-5" onchange=${handleAddressSelection}>
${renderedKycRequests?.length ? renderedKycRequests : html`<li class="text-center" style="padding: 3rem;">No requests found</li>`}
</ul>
</section>
</div>
<button id="commit_approvals" class="fab button button--primary" data-count="0" onclick=${initApproval}>Commit approvals</button> <button id="commit_approvals" class="fab button button--primary" data-count="0" onclick=${initApproval}>Commit approvals</button>
</article> </article>
`); `);
if (lastPage !== page)
checkBalance();
} else if (floGlobals.isAdmin) { } else if (floGlobals.isAdmin) {
const renderedSubAdmins = floGlobals.subAdmins.map(address => render.approvedAggregatorCard(address)); const renderedSubAdmins = floGlobals.subAdmins.map(address => render.approvedAggregatorCard(address));
renderElem(getRef('app_body'), html` renderElem(getRef('app_body'), html`
@ -1274,7 +1272,7 @@
renderHome() renderHome()
} }
async function rejectKyc(e) { async function rejectKyc(e) {
const confirmation = await getConfirmation('Are you sure you want to reject this user?', { const confirmation = await getConfirmation('Are you sure you want to reject this KYC?', {
confirmText: 'Reject', confirmText: 'Reject',
}); });
if (!confirmation) return; if (!confirmation) return;
@ -1282,14 +1280,14 @@
buttonLoader(button, true) buttonLoader(button, true)
const { requestVC, docVC } = floGlobals.currentRequest; const { requestVC, docVC } = floGlobals.currentRequest;
try { try {
// await floCloudAPI.noteApplicationData(requestVC, 'rejected') await floCloudAPI.noteApplicationData(requestVC, 'rejected')
floGlobals.generalData[floCloudAPI.util.filterKey('userKycRequests')][requestVC].note = 'rejected' floGlobals.generalData[floCloudAPI.util.filterKey('userKycRequests')][requestVC].note = 'rejected'
notify('User rejected successfully', 'success'); notify('KYC rejected successfully', 'success');
closePopup() closePopup()
renderHome() renderHome()
} catch (err) { } catch (err) {
console.error(err) console.error(err)
notify('Error rejecting user', 'error'); notify('Error rejecting KYC', 'error');
} finally { } finally {
buttonLoader(button, false) buttonLoader(button, false)
} }
@ -1324,27 +1322,42 @@
getRef('selected_wrapper').classList.add('hidden') getRef('selected_wrapper').classList.add('hidden')
getRef('kyc_requests_list').querySelectorAll('input').forEach(input => input.checked = false) getRef('kyc_requests_list').querySelectorAll('input').forEach(input => input.checked = false)
} }
function checkBalance(address) { function checkBalance() {
if (!address) renderElem(getRef('verifier_balance_container'), html`
address = floCrypto.getFloID(getRef('approver_private_key').value.trim()) <h4>FLO balance</h4>
if (getRef('approver_private_key').isValid) { <div class="flex align-center gap-1">
floBlockchainAPI.getBalance(address).then(balance => { <sm-spinner></sm-spinner>
if (balance < 0.01) { <span>Checking balance...</span>
renderElem(getRef('aggregator_balance'), html`Balance: ${balance} FLO. You don't have enough FLO.`); </div>
getRef('aggregator_balance').classList.add('error') `)
} else { floBlockchainAPI.getBalance(floGlobals.myFloID).then(balance => {
renderElem(getRef('aggregator_balance'), html`Balance: ${balance} FLO`); if (balance < 0.01) {
getRef('aggregator_balance').classList.remove('error') renderElem(getRef('verifier_balance_container'), html`
} <div class="flex align-center space-between gap-1">
getRef('aggregator_balance').classList.remove('hidden') <h4>FLO balance</h4>
}).catch(err => { <button class="button button--colored button--small" onclick=${checkBalance}>Refresh</button>
console.error(err) </div>
notify('Error fetching balance', 'error') <h2 style="color: var(--danger-color)">Insufficient balance</h2>
getRef('aggregator_balance').classList.add('hidden') `)
}) } else {
} else { renderElem(getRef('verifier_balance_container'), html`
getRef('aggregator_balance').classList.add('hidden') <div class="flex align-center space-between gap-1">
} <h4>FLO balance</h4>
<button class="button button--colored button--small" onclick=${checkBalance}>Refresh</button>
</div>
<h2>${balance} FLO</h2>
`)
}
}).catch(err => {
console.error(err)
renderElem(getRef('verifier_balance_container'), html`
<div class="flex align-center space-between gap-1">
<h4>FLO balance</h4>
<button class="button button--colored button--small" onclick=${checkBalance}>Refresh</button>
</div>
<h2 style="color: var(--danger-color)">Error fetching balance</h2>
`)
})
} }
function initApproval() { function initApproval() {
const approvedAddress = [...floGlobals.approvalsToBeCommitted.keys()].map(address => { const approvedAddress = [...floGlobals.approvalsToBeCommitted.keys()].map(address => {
@ -1749,13 +1762,6 @@
notify('Error loading KYC documents', 'error') notify('Error loading KYC documents', 'error')
} }
}).catch(error => console.error(error)) }).catch(error => console.error(error))
try {
await getApprovedAggregators();
// await getApprovedKycs();
} catch (error) {
console.error(error);
}
} }
</script> </script>
</body> </body>