New router implementation

This commit is contained in:
sairaj mote 2023-01-20 22:27:58 +05:30
parent 842be7ebbf
commit c3e2d1bef7

View File

@ -186,7 +186,7 @@
return timestamp; return timestamp;
} }
} }
window.addEventListener('hashchange', e => routeTo(window.location.hash)) // window.addEventListener('hashchange', e => routeTo(window.location.hash))
window.addEventListener("load", () => { window.addEventListener("load", () => {
document.body.classList.remove('hidden') document.body.classList.remove('hidden')
document.addEventListener("pointerdown", (e) => { document.addEventListener("pointerdown", (e) => {
@ -198,7 +198,7 @@
notify('copied', 'success') notify('copied', 'success')
}) })
getAllSuggestions().then(suggestions => { getAllSuggestions().then(suggestions => {
routeTo(window.location.hash) router.routeTo(window.location.hash)
}).catch(e => { }).catch(e => {
console.error(e) console.error(e)
notify(e, 'error') notify(e, 'error')
@ -268,187 +268,180 @@
}; };
} }
const appState = { class Router {
params: {}, constructor(options = {}) {
} const { routes = {}, state = {}, routingStart, routingEnd } = options
async function routeTo(targetPage) { this.routes = routes
const routingAnimation = { in: slideInUp, out: slideOutUp } this.state = state
let pageId this.routingStart = routingStart
let subPageId1 this.routingEnd = routingEnd
let searchParams window.addEventListener('hashchange', e => this.routeTo(window.location.hash))
let params }
if (targetPage === '') { addRoute(route, callback) {
pageId = 'home' this.routes[route] = callback
history.replaceState(null, null, '#/home'); }
} else { async routeTo(path) {
if (targetPage.includes('/')) { let page
if (targetPage.includes('?')) { let wildcards = []
const splitAddress = targetPage.split('?') let queryString
searchParams = splitAddress.pop(); let params
[, pageId, subPageId1] = splitAddress.pop().split('/') [path, queryString] = path.split('?');
} else { if (path.includes('#'))
[, pageId, subPageId1] = targetPage.split('/') path = path.split('#')[1];
} if (path.includes('/'))
[, page, ...wildcards] = path.split('/')
else
page = path
this.state = { page, wildcards }
if (queryString) {
params = new URLSearchParams(queryString)
this.state.params = Object.fromEntries(params)
}
if (this.routingStart) {
this.routingStart(this.state)
}
if (this.routes[page]) {
await this.routes[page](this.state)
this.state.lastPage = page
} else { } else {
pageId = targetPage this.routes['404'](this.state)
}
if (this.routingEnd) {
this.routingEnd(this.state)
} }
} }
appState.currentPage = pageId }
if (searchParams) { const router = new Router({
const urlSearchParams = new URLSearchParams('?' + searchParams); routingStart(state) {
params = Object.fromEntries(urlSearchParams.entries()); loading()
if ("scrollRestoration" in history) {
history.scrollRestoration = "manual";
}
window.scrollTo(0, 0);
if (state.page !== 'home')
getRef("page_header").classList.remove("hidden");
},
routingEnd() {
loading(false)
} }
if (params) })
appState.params = params async function renderHome(state) {
loading() getRef("page_header").classList.add("hidden");
if ("scrollRestoration" in history) { let [data, latestTxs, latestBlocks] = await Promise.all([getBannerData(), getLatestTxs(), getAllBlocks(6)])
history.scrollRestoration = "manual"; renderElem(getRef("page_container"), html`${render.homepage(data)}`);
renderTransactions('top_transaction_container', latestTxs)
const renderedBlocks = latestBlocks.map(block => render.blockCard(block))
renderElem(document.getElementById('top_blocks_container'), html`${renderedBlocks}`)
}
router.addRoute('', (state) => {
history.replaceState({}, '', '#/home')
renderHome(state)
})
router.addRoute('home', renderHome)
router.addRoute('address', async state => {
const [floAddress] = state.wildcards
if (!floAddress) return;
let [addressInfo, addressBalance, addressTxs] = await Promise.all([getAddressInfo(floAddress), getAddressBalance(floAddress), getAddressTxs(floAddress)])
renderElem(getRef("page_container"), html`${render.addressPage({ balance: addressBalance, address: floAddress })}`);
getRef("page_title").textContent = 'Address'
renderTransactions('address_transaction_container', addressTxs)
const tokenHolders = []
for (const token in addressInfo) {
tokenHolders.push(render.tokenBalanceCard(token, addressInfo[token].balance))
} }
window.scrollTo(0, 0); renderElem(document.getElementById('token_balance_container'), html`${tokenHolders}`)
if (pageId !== 'home') })
getRef("page_header").classList.remove("hidden"); router.addRoute('token', async state => {
switch (pageId) { const token = state.wildcards[0].toLowerCase()
case "home": { if (!token) return;
getRef("page_header").classList.add("hidden"); try {
let [data, latestTxs, latestBlocks] = await Promise.all([getBannerData(), getLatestTxs(), getAllBlocks(6)]) let [tokenInfo, tokenBalances, tokenTransactions] = await Promise.all([getTokenInfo(token), getTokenBalances(token), getTokenTransactions(token)])
renderElem(getRef("page_container"), html`${render.homepage(data)}`); const tokenHolders = []
renderTransactions('top_transaction_container', latestTxs) for (const address in tokenBalances) {
const renderedBlocks = latestBlocks.map(block => render.blockCard(block)) tokenHolders.push(render.addrBalanceCard(address, tokenBalances[address], tokenInfo.token))
renderElem(document.getElementById('top_blocks_container'), html`${renderedBlocks}`)
} }
break renderElem(getRef("page_container"), html`${render.tokenPage(tokenInfo)}`);
case "address": { getRef("page_title").textContent = "Token";
if (!subPageId1) return; renderElem(document.getElementById('token_balance_container'), html`${tokenHolders}`)
let [addressInfo, addressBalance, addressTxs] = await Promise.all([getAddressInfo(subPageId1), getAddressBalance(subPageId1), getAddressTxs(subPageId1)]) renderTransactions('token_transaction_container', tokenTransactions)
renderElem(getRef("page_container"), html`${render.addressPage({ balance: addressBalance, address: subPageId1 })}`); } catch (e) {
getRef("page_title").textContent = 'Address' console.log(e)
renderElem(getRef("page_container"), html`${render.errorPage(e)}`);
}
})
router.addRoute('contract', async state => {
const [contractId] = state.wildcards
if (!contractId) return;
// todo: load contract variable dynamically
const contract = splitContractNameAddress(contractId);
let [contractInfo, contractTransactions, contractParticipants] = await Promise.all([getContractInfo(contract), getContractTransactions(contract), getContractParticipants(contract)])
// todo : check the type of contract & then further checks like fetching details of contractParticipant
getRef("page_container").append(render.contractPage(contractInfo));
getRef("page_title").textContent = "Contract";
renderTransactions('address_transaction_container', addressTxs) console.log(contractParticipants)
const tokenHolders = [] let winners = []
for (const token in addressInfo) { for (const participant in contractParticipants) {
tokenHolders.push(render.tokenBalanceCard(token, addressInfo[token].balance)) if (contractParticipants[participant].winningAmount)
} winners.push(contractParticipants[participant])
renderElem(document.getElementById('token_balance_container'), html`${tokenHolders}`) }
} break; // append latest transactions
case "token": { renderTransactions('contract_transaction_container', contractTransactions)
if (!subPageId1) return; for (participant in contractParticipants) {
const token = subPageId1.toLowerCase() let { participantFloAddress, tokenIdentification, userChoice, tokenAmount } = contractParticipants[participant]
let [tokenInfo, tokenBalances, tokenTransactions] = await Promise.all([getTokenInfo(token), getTokenBalances(token), getTokenTransactions(token)]) frag.append(render.contractChoiceCard(participantFloAddress, tokenIdentification, userChoice, tokenAmount))
const tokenHolders = [] }
for (const address in tokenBalances) { document.getElementById('participant_container').append(frag)
tokenHolders.push(render.addrBalanceCard(address, tokenBalances[address], tokenInfo.token))
}
renderElem(getRef("page_container"), html`${render.tokenPage(tokenInfo)}`);
getRef("page_title").textContent = "Token";
renderElem(document.getElementById('token_balance_container'), html`${tokenHolders}`)
renderTransactions('token_transaction_container', tokenTransactions)
}
break
case "contract": { winners.forEach(winner => {
// todo: load contract variable dynamically let { participantFloAddress, tokenIdentification, userChoice, tokenAmount, winningAmount } = winner;
if (!subPageId1) return; frag.append(render.contractChoiceCard(participantFloAddress, tokenIdentification, userChoice, tokenAmount, winningAmount))
const contract = splitContractNameAddress(subPageId1); })
let [contractInfo, contractTransactions, contractParticipants] = await Promise.all([getContractInfo(contract), getContractTransactions(contract), getContractParticipants(contract)]) document.getElementById('winners_container').append(frag)
// todo : check the type of contract & then further checks like fetching details of contractParticipant })
getRef("page_container").append(render.contractPage(contractInfo));
getRef("page_title").textContent = "Contract";
console.log(contractParticipants) router.addRoute('block', async state => {
let winners = [] const [blockId] = state.wildcards
for (const participant in contractParticipants) { if (!blockId) return;
if (contractParticipants[participant].winningAmount) let [blockInfo, blockTxs] = await Promise.all([getBlockInfo(blockId), getBlockTxs(blockId)])
winners.push(contractParticipants[participant]) renderElem(getRef("page_container"), html`${render.blockPage(blockInfo)}`);
} getRef("page_title").textContent = 'Block'
// append latest transactions renderTransactions('block_transaction_container', blockTxs)
renderTransactions('contract_transaction_container', contractTransactions) })
for (participant in contractParticipants) { router.addRoute('blocks', async state => {
let { participantFloAddress, tokenIdentification, userChoice, tokenAmount } = contractParticipants[participant] let allBlocks = await getAllBlocks(100);
frag.append(render.contractChoiceCard(participantFloAddress, tokenIdentification, userChoice, tokenAmount)) getRef("page_title").textContent = "All Blocks";
} const renderedBlocks = allBlocks.map(block => render.blockCard(block))
document.getElementById('participant_container').append(frag) renderElem(getRef("page_container"), html`
winners.forEach(winner => {
let { participantFloAddress, tokenIdentification, userChoice, tokenAmount, winningAmount } = winner;
frag.append(render.contractChoiceCard(participantFloAddress, tokenIdentification, userChoice, tokenAmount, winningAmount))
})
document.getElementById('winners_container').append(frag)
}
break;
case "block": {
if (!subPageId1) return;
let [blockInfo, blockTransactions] = await Promise.all([getBlockInfo(subPageId1), getBlockTransactions(subPageId1)])
getRef("page_title").textContent = "block";
renderElem(getRef("page_container"), html`${render.blockPage(blockInfo)}`);
renderTransactions('block_transaction_container', blockTransactions)
}
break
case "blocks": {
let allBlocks = await getAllBlocks(100);
getRef("page_title").textContent = "All Blocks";
const renderedBlocks = allBlocks.map(block => render.blockCard(block))
renderElem(getRef("page_container"), html`
<div id="all_blocks_page" class="page"> <div id="all_blocks_page" class="page">
${renderedBlocks} ${renderedBlocks}
</div> </div>
`) `)
})
} router.addRoute('transactions', async state => {
break let allTxs = await getAllTxs();
getRef("page_title").textContent = "All Transactions";
case "transactions": { renderElem(getRef("page_container"), html`
let allTxs = await getAllTxs();
getRef("page_title").textContent = "All Transactions";
renderElem(getRef("page_container"), html`
<div id="all_transactions_page" class="page transaction-container"> </div> <div id="all_transactions_page" class="page transaction-container"> </div>
`) `)
renderTransactions('all_transactions_page', allTxs) renderTransactions('all_transactions_page', allTxs)
} })
break router.addRoute('transaction', async state => {
case "transaction": { const [txId] = state.wildcards
if (!subPageId1) return if (!txId) return
const [status, txInfo] = await getTxInfo(subPageId1); const [status, txInfo] = await getTxInfo(txId);
if (status) { if (status) {
renderElem(getRef("page_container"), html`${render.transactionPage(txInfo)}`); renderElem(getRef("page_container"), html`${render.transactionPage(txInfo)}`);
getRef("page_title").textContent = "transaction"; getRef("page_title").textContent = "transaction";
} else { } else {
render('error_page', txInfo) renderElem(getRef("page_container"), html`${render.errorPage(txInfo)}`);
}
}
break
case 'error_page': {
getRef("page_container").append(render.errorPage(field));
}
break;
} }
switch (appState.lastPage) { })
case 'intern': router.addRoute('404', state => {
routingAnimation.in = slideInRight; renderElem(getRef("page_container"), html`${render.errorPage('404 Not Found')}`);
routingAnimation.out = slideOutRight; })
break;
}
switch (pageId) {
case 'intern':
routingAnimation.in = slideInLeft;
routingAnimation.out = slideOutLeft;
break;
}
loading(false)
if (appState.lastPage !== pageId) {
// if (appState.lastPage) {
// getRef(appState.lastPage).animate(routingAnimation.out, { duration: floGlobals.prefersReducedMotion ? 0 : 150, fill: 'forwards', easing: 'ease' }).onfinish = (e) => {
// e.target.effect.target.classList.add('hidden')
// }
// }
// getRef(pageId).classList.remove('hidden')
// getRef(pageId).animate(routingAnimation.in, { duration: floGlobals.prefersReducedMotion ? 0 : 150, fill: 'forwards', easing: 'ease' }).onfinish = (e) => {
// appState.lastPage = pageId
// }
}
}
function loading(show = true) { function loading(show = true) {
if (show) { if (show) {
getRef('loading').classList.remove('hidden') getRef('loading').classList.remove('hidden')
@ -1182,23 +1175,27 @@
} }
function getTokenInfo(thisToken) { function getTokenInfo(thisToken) {
return fetchJson( return new Promise((resolve, reject) => {
`${tokenApiUrl}/api/v1.0/getTokenInfo?token=${thisToken.toLowerCase()}` fetchJson(
) `${tokenApiUrl}/api/v1.0/getTokenInfo?token=${thisToken.toLowerCase()}`
.then(function (tokenInfo) { ).then(function (tokenInfo) {
if (tokenInfo.result === "error")
reject(tokenInfo.description);
let associatedSC = {}; let associatedSC = {};
for (let i = 0, associatedScList = tokenInfo["associatedSmartContracts"]; i < associatedScList.length; i++) { tokenInfo.associatedSmartContracts.forEach((sc) => {
associatedSC[`${associatedScList[i]["contractName"]}-${associatedScList[i]["contractAddress"]}`] = associatedScList[i]; associatedSC[`${sc.contractName}-${sc.contractAddress}`] = sc;
} });
let obj = { resolve({
token: tokenInfo["token"], token: tokenInfo["token"],
supply: tokenInfo["tokenSupply"], supply: tokenInfo["tokenSupply"],
incAddress: tokenInfo["incorporationAddress"], incAddress: tokenInfo["incorporationAddress"],
associatedContracts: associatedSC, associatedContracts: associatedSC,
blockchainReference: tokenInfo["blockchainReference"], blockchainReference: tokenInfo["blockchainReference"],
}; });
return obj; }).catch((err) => {
reject(err);
}); });
})
} }
async function getTokenBalances(tokenName) { async function getTokenBalances(tokenName) {