fix: Clean up dead code and stale domain references across landing + web-app (#189)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
5ee2238604
commit
878d1337df
21 changed files with 2 additions and 263 deletions
|
|
@ -29,4 +29,4 @@ curl --netrc -s https://codeberg.org/api/v1/repos/johba/harb/pulls | jq '.[].tit
|
|||
The repo uses SSH for git push/pull (`ssh://git@codeberg.org`), so `.netrc` is only used for REST API interactions (issues, PRs, releases).
|
||||
|
||||
## Webhooks
|
||||
Codeberg sends webhooks to `https://ci.sovraigns.network/api/hook` to trigger Woodpecker CI pipelines. If webhooks stop firing (e.g. DNS issues), check Codeberg repo settings → Webhooks to verify delivery history and re-trigger.
|
||||
Codeberg sends webhooks to `https://ci.niovi.voyage/api/hook` to trigger Woodpecker CI pipelines. If webhooks stop firing (e.g. DNS issues), check Codeberg repo settings → Webhooks to verify delivery history and re-trigger.
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
<div class="k-footer__audit-note">⚠️ Unaudited — use at your own risk</div>
|
||||
</div>
|
||||
<div class="k-footer__about">
|
||||
KrAIken is a project by <u><a href="https://sovraigns.network/" target="_blank">SovrAIgns.network</a></u
|
||||
KrAIken is a project by <u><a href="https://niovi.voyage/" target="_blank">niovi.voyage</a></u
|
||||
>.<br />
|
||||
Autonomous liquidity protocol. Use at your own risk.
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,41 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
msg: string;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="greetings">
|
||||
<h1 class="green">{{ msg }}</h1>
|
||||
<h3>
|
||||
You’ve successfully created a project with
|
||||
<a href="https://vite.dev/" target="_blank" rel="noopener">Vite</a> +
|
||||
<a href="https://vuejs.org/" target="_blank" rel="noopener">Vue 3</a>. What's next?
|
||||
</h3>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
h1 {
|
||||
font-weight: 500;
|
||||
font-size: 2.6rem;
|
||||
position: relative;
|
||||
top: -10px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.greetings h1,
|
||||
.greetings h3 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.greetings h1,
|
||||
.greetings h3 {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
<template>
|
||||
<div class="item">
|
||||
<i>
|
||||
<slot name="icon"></slot>
|
||||
</i>
|
||||
<div class="details">
|
||||
<h3>
|
||||
<slot name="heading"></slot>
|
||||
</h3>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.item {
|
||||
margin-top: 2rem;
|
||||
display: flex;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.details {
|
||||
flex: 1;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
i {
|
||||
display: flex;
|
||||
place-items: center;
|
||||
place-content: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 500;
|
||||
margin-bottom: 0.4rem;
|
||||
color: var(--color-heading);
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.item {
|
||||
margin-top: 0;
|
||||
padding: 0.4rem 0 1rem calc(var(--section-gap) / 2);
|
||||
}
|
||||
|
||||
i {
|
||||
top: calc(50% - 25px);
|
||||
left: -26px;
|
||||
position: absolute;
|
||||
border: 1px solid var(--color-border);
|
||||
background: var(--color-background);
|
||||
border-radius: 8px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.item:before {
|
||||
content: ' ';
|
||||
border-left: 1px solid var(--color-border);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: calc(50% + 25px);
|
||||
height: calc(50% - 25px);
|
||||
}
|
||||
|
||||
.item:after {
|
||||
content: ' ';
|
||||
border-left: 1px solid var(--color-border);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: calc(50% + 25px);
|
||||
height: calc(50% - 25px);
|
||||
}
|
||||
|
||||
.item:first-of-type:before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.item:last-of-type:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -133,7 +133,6 @@ function removeFocus() {
|
|||
}
|
||||
|
||||
function setFocus(_event: MouseEvent) {
|
||||
// console.log("setFocus");
|
||||
if (props.disabled) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,10 +133,8 @@ function clickSelect(_event: unknown) {
|
|||
}
|
||||
|
||||
function clickItem(item: { index: number }) {
|
||||
// console.log("item", item);
|
||||
selectedIndex.value = item.index;
|
||||
showList.value = false;
|
||||
// console.log("showList.value", showList.value);
|
||||
// emit('input', item)
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -38,12 +38,6 @@ onMounted(() => {
|
|||
// resolved = {"test123": 123, "blub": "abc"}
|
||||
});
|
||||
|
||||
// const test = computed(() => {
|
||||
// console.log(instance.value);
|
||||
|
||||
// return instance.value?.parent
|
||||
// })
|
||||
|
||||
//Props
|
||||
interface Props {
|
||||
label: string;
|
||||
|
|
@ -52,9 +46,6 @@ interface Props {
|
|||
const props = defineProps<Props>();
|
||||
|
||||
watch(props, (_newValue, _oldValue) => {
|
||||
// console.log("newValue", newValue);
|
||||
// console.log("instance", instance.value);
|
||||
|
||||
updateTab({
|
||||
uid: instance.value?.uid ?? 0,
|
||||
name: props.name,
|
||||
|
|
|
|||
|
|
@ -103,21 +103,6 @@ const stakedAmount = computed(() =>
|
|||
|
||||
const instance = getCurrentInstance();
|
||||
|
||||
// const connectors = computed(() => {
|
||||
// console.log();
|
||||
// return wallet.connectors.filter((obj) => obj.id !== "injected");
|
||||
// });
|
||||
|
||||
// async function disconnect() {
|
||||
// console.log("disconnectWallet");
|
||||
// try {
|
||||
// await wallet.disconnectWallet();
|
||||
// instance.parent.emit("update:modelValue", false);
|
||||
// } catch (error) {
|
||||
// console.log("error", error);
|
||||
// }
|
||||
// }
|
||||
|
||||
// function badgeClick(token) {
|
||||
// var tokenData = tokenStore.getToken(token.contractAddress);
|
||||
// if (tokenStore.memeToken.contractAddress === token.contractAddress) {
|
||||
|
|
@ -136,10 +121,7 @@ function closeModal() {
|
|||
instance!.parent!.emit('update:modelValue', false);
|
||||
}
|
||||
|
||||
// //special case for metaMask, but I think that is the most used wallet
|
||||
async function connectWallet(connector: CreateConnectorFn | Connector, chainId: number) {
|
||||
// console.log("connector", connector);
|
||||
// console.log("connector", connector.name);
|
||||
connect({ connector, chainId });
|
||||
closeModal();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ const listInner = ref();
|
|||
|
||||
function closeMenu() {
|
||||
if (showMenu.value) {
|
||||
// console.log("tesat");
|
||||
showMenu.value = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,21 +61,6 @@ describe('SocialBadge.vue', () => {
|
|||
expect(badge.attributes('style')).toContain('border-color: white');
|
||||
});
|
||||
|
||||
// it("renders the correct icon based on the type prop", async () => {
|
||||
// wrapper = mount(SocialBadge, {
|
||||
// props: {
|
||||
// type: "discord",
|
||||
// },
|
||||
// });
|
||||
// await flushPromises();
|
||||
// const current = wrapper.getCurrentComponent()?.setupState?.img.__asyncResolved
|
||||
// console.log("current", current.default.name);
|
||||
|
||||
// expect(current.default.name).toBe("IconDiscord");
|
||||
|
||||
// // expect(icon.exists()).toBe(true);
|
||||
// });
|
||||
|
||||
it('does not render an icon if the type is unsupported', async () => {
|
||||
wrapper = mount(SocialBadge, {
|
||||
props: {
|
||||
|
|
|
|||
|
|
@ -51,8 +51,6 @@ export function useAdjustTaxRate() {
|
|||
|
||||
async function changeTax(positionId: bigint, taxRateIndex: number) {
|
||||
try {
|
||||
// console.log("changeTax", { positionId, taxRate });
|
||||
|
||||
loading.value = true;
|
||||
const option = getTaxRateOptionByIndex(taxRateIndex);
|
||||
if (!option) {
|
||||
|
|
@ -60,7 +58,6 @@ export function useAdjustTaxRate() {
|
|||
}
|
||||
|
||||
const hash = await StakeContract.changeTax(positionId, option.index);
|
||||
// console.log("hash", hash);
|
||||
loading.value = false;
|
||||
waiting.value = true;
|
||||
await waitForTransactionReceipt(config as Config, {
|
||||
|
|
@ -70,9 +67,6 @@ export function useAdjustTaxRate() {
|
|||
contractToast.showSuccessToast(option.year.toString(), 'Success!', 'You adjusted your position tax to', '', '%');
|
||||
waiting.value = false;
|
||||
} catch (error: unknown) {
|
||||
// console.error("error", error);
|
||||
// console.log(JSON.stringify(error, (_, v) => (typeof v === "bigint" ? v.toString() : v)));
|
||||
|
||||
contractToast.showFailToast((error as { shortMessage?: string })?.shortMessage ?? 'Transaction failed');
|
||||
} finally {
|
||||
loading.value = false;
|
||||
|
|
|
|||
|
|
@ -43,14 +43,12 @@ export function useClaim() {
|
|||
|
||||
loading.value = true;
|
||||
const hash = await HarbContract.claimUbi(address);
|
||||
// console.log("hash", hash);
|
||||
loading.value = false;
|
||||
waiting.value = true;
|
||||
await waitForTransactionReceipt(config as Config, {
|
||||
hash: hash,
|
||||
});
|
||||
} catch (_error) {
|
||||
// console.error("error", error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
waiting.value = false;
|
||||
|
|
@ -58,12 +56,8 @@ export function useClaim() {
|
|||
}
|
||||
|
||||
if (!unwatch) {
|
||||
// console.log("useClaim function");
|
||||
|
||||
unwatch = watchAccount(config as Config, {
|
||||
async onChange(data) {
|
||||
// console.log("watchAccount", data);
|
||||
|
||||
if (data.address) {
|
||||
await HarbContract.setHarbContract();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ const toast = useToast();
|
|||
|
||||
export function useContractToast() {
|
||||
function showFailToast(name?: string) {
|
||||
// console.log("name", name);
|
||||
if (name === 'UserRejectedRequestError') {
|
||||
//
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -87,10 +87,6 @@ const myClosedPositions: ComputedRef<Position[]> = computed(() => {
|
|||
const account = getAccount(config as Config);
|
||||
|
||||
return rawClosedPositoins.value.map(obj => {
|
||||
// console.log("taxRatePosition", taxRatePosition);
|
||||
|
||||
// console.log("taxRates[taxRatePosition]", taxRates[taxRatePosition]);
|
||||
|
||||
const taxRateDecimal = Number(obj.taxRate);
|
||||
const taxRateIndex =
|
||||
Number.isFinite(taxRateDecimal) && !Number.isNaN(taxRateDecimal) ? getTaxRateIndexByDecimal(taxRateDecimal) : undefined;
|
||||
|
|
@ -139,9 +135,6 @@ interface ActivePositionsResult {
|
|||
export async function loadActivePositions(chainId: number, endpointOverride?: string): Promise<ActivePositionsResult> {
|
||||
const targetEndpoint = resolveGraphqlEndpoint(chainId, endpointOverride);
|
||||
logger.info(`loadActivePositions for chainId: ${chainId}`);
|
||||
|
||||
// console.log("graphql endpoint", targetEndpoint);
|
||||
|
||||
const res = await axios.post(
|
||||
targetEndpoint,
|
||||
{
|
||||
|
|
|
|||
|
|
@ -44,9 +44,6 @@ export function useStake() {
|
|||
|
||||
const state: ComputedRef<StakeState> = computed(() => {
|
||||
const balance = wallet.balance.value;
|
||||
// console.log("balance123", balance);
|
||||
// console.log("wallet", wallet);
|
||||
|
||||
if (loading.value) {
|
||||
return StakeState.SignTransaction;
|
||||
} else if (minStake.value > balance || stakingAmount.value > balance) {
|
||||
|
|
@ -83,7 +80,6 @@ export function useStake() {
|
|||
// const stakingAmountNumber = computed(() => return staking)
|
||||
|
||||
async function snatch(stakingAmount: bigint, taxRateIndex: number, positions: Array<bigint> = []) {
|
||||
// console.log("snatch", { stakingAmount, taxRateIndex, positions });
|
||||
const account = getAccount(wagmiConfig);
|
||||
const taxRateOption = getTaxRateOptionByIndex(taxRateIndex);
|
||||
if (!taxRateOption) {
|
||||
|
|
@ -92,8 +88,6 @@ export function useStake() {
|
|||
|
||||
try {
|
||||
const assets: bigint = stakingAmount;
|
||||
// console.log("receiver", receiver);
|
||||
|
||||
// await snatchService(assets, receiver, taxRate, []);
|
||||
// assets: BigInt, receiver: Address, taxRate: Number, positionsToSnatch: Array<BigInt>
|
||||
const deadline = BigInt(Date.now()) / 1000n + 1200n;
|
||||
|
|
@ -110,8 +104,6 @@ export function useStake() {
|
|||
account.chainId!,
|
||||
name
|
||||
);
|
||||
// console.log("resultPermitObject", { types, message, domain, primaryType });
|
||||
|
||||
const typedData: TypedDataDefinition = {
|
||||
domain,
|
||||
message,
|
||||
|
|
@ -120,20 +112,9 @@ export function useStake() {
|
|||
};
|
||||
|
||||
const signature = await signTypedData(wagmiConfig, typedData);
|
||||
|
||||
// console.log("signature", {
|
||||
// domain,
|
||||
// message,
|
||||
// primaryType,
|
||||
// types,
|
||||
// });
|
||||
|
||||
const { r, s, v } = getSignatureRSV(signature);
|
||||
loading.value = true;
|
||||
// console.log("permitAndSnatch", assets, account.address!, taxRateOption.index, positions, deadline, v, r, s);
|
||||
|
||||
const hash = await permitAndSnatch(assets, account.address!, taxRateOption.index, positions, deadline, v, r, s);
|
||||
// console.log("hash", hash);
|
||||
loading.value = false;
|
||||
waiting.value = true;
|
||||
const data = await waitForTransactionReceipt(wagmiConfig, {
|
||||
|
|
@ -154,8 +135,6 @@ export function useStake() {
|
|||
waiting.value = false;
|
||||
await getNonce();
|
||||
} catch (error) {
|
||||
// console.error("error", error);
|
||||
// console.log(JSON.parse(JSON.stringify(error)));
|
||||
const message = error instanceof Error ? error.name : 'Transaction failed';
|
||||
contractToast.showFailToast(message);
|
||||
} finally {
|
||||
|
|
|
|||
|
|
@ -165,8 +165,6 @@ const inflation7d = computed(() => {
|
|||
|
||||
const stakeableSupply = computed(() => {
|
||||
if (rawStatsCollections.value?.length > 0 && BigInt(rawStatsCollections.value[0].kraikenTotalSupply) > 0n) {
|
||||
// console.log("rawStatsCollections.value[0]", rawStatsCollections.value[0]);
|
||||
|
||||
return stakeTotalSupply.value / 5n;
|
||||
} else {
|
||||
return 0n;
|
||||
|
|
@ -176,8 +174,6 @@ const stakeableSupply = computed(() => {
|
|||
//maxSlots
|
||||
const maxSlots = computed(() => {
|
||||
if (rawStatsCollections.value?.length > 0 && BigInt(rawStatsCollections.value[0].kraikenTotalSupply) > 0n) {
|
||||
// console.log("rawStatsCollections.value[0]", rawStatsCollections.value[0]);
|
||||
|
||||
return (bigInt2Number(stakeTotalSupply.value, 18) * 0.2) / 100;
|
||||
} else {
|
||||
return 0;
|
||||
|
|
@ -243,8 +239,6 @@ export function useStatCollection(chainId: number = DEFAULT_CHAIN_ID) {
|
|||
}
|
||||
});
|
||||
if (!unwatch) {
|
||||
// console.log("watchChain");
|
||||
|
||||
//chain Switch reload stats for other chain
|
||||
unwatch = watchChainId(config as Config, {
|
||||
async onChange(nextChainId) {
|
||||
|
|
@ -253,13 +247,6 @@ export function useStatCollection(chainId: number = DEFAULT_CHAIN_ID) {
|
|||
await loadStats(resolvedChainId);
|
||||
},
|
||||
});
|
||||
|
||||
// const unwatchBlock = watchBlocks(config as Config, {
|
||||
// async onBlock(block) {
|
||||
// console.log('Block changed!', block)
|
||||
// await loadStats();
|
||||
// },
|
||||
// })
|
||||
}
|
||||
onUnmounted(() => {
|
||||
retryManager.clear();
|
||||
|
|
|
|||
|
|
@ -39,11 +39,8 @@ export function useUnstake() {
|
|||
|
||||
async function exitPosition(positionId: bigint) {
|
||||
try {
|
||||
// console.log("positionId", positionId);
|
||||
|
||||
loading.value = true;
|
||||
const hash = await StakeContract.exitPosition(positionId);
|
||||
// console.log("hash", hash);
|
||||
loading.value = false;
|
||||
waiting.value = true;
|
||||
const data = await waitForTransactionReceipt(config as Config, {
|
||||
|
|
@ -64,7 +61,6 @@ export function useUnstake() {
|
|||
waiting.value = false;
|
||||
wallet.loadBalance();
|
||||
} catch (error) {
|
||||
// console.error("error", error);
|
||||
contractToast.showFailToast((error as Error).name);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
|
|
|
|||
|
|
@ -105,12 +105,8 @@ export function useWallet() {
|
|||
}
|
||||
|
||||
if (!unwatch) {
|
||||
// console.log("useWallet function");
|
||||
|
||||
unwatch = watchAccount(config as Config, {
|
||||
async onChange(data) {
|
||||
// console.log("watchaccount-useWallet", data);
|
||||
|
||||
if (!data.address) {
|
||||
logger.info(`disconnected`);
|
||||
setWalletPublicClient(null);
|
||||
|
|
@ -141,8 +137,6 @@ export function useWallet() {
|
|||
}
|
||||
|
||||
if (!unwatchChain) {
|
||||
// console.log("unwatchChain");
|
||||
|
||||
unwatchChain = watchChainId(config as Config, {
|
||||
async onChange(_chainId) {
|
||||
await syncWalletPublicClient(account.value);
|
||||
|
|
|
|||
|
|
@ -24,11 +24,7 @@ export const totalSupply = ref(0n);
|
|||
export let HarbContract = getHarbJson();
|
||||
|
||||
function getHarbJson() {
|
||||
// console.log("getHarbJson");
|
||||
|
||||
const chainId = getChainId(config as Config);
|
||||
// console.log("chainId", chainId);
|
||||
|
||||
const chain = getChain(chainId);
|
||||
|
||||
return { abi: KraikenAbi as Abi, contractAddress: chain?.harb } as Contract;
|
||||
|
|
@ -68,8 +64,6 @@ export async function getNonce() {
|
|||
if (!account.address) {
|
||||
return 0n;
|
||||
}
|
||||
// console.log('HarbContract.contractAddress', HarbContract.contractAddress);
|
||||
|
||||
const publicClient = getWalletPublicClient();
|
||||
if (!publicClient) {
|
||||
throw new Error('Wallet public client unavailable');
|
||||
|
|
@ -115,12 +109,9 @@ export async function approve(amount: bigint): Promise<Hash> {
|
|||
functionName: 'approve',
|
||||
args: [StakeContract.contractAddress, amount],
|
||||
});
|
||||
// console.log("result", result);
|
||||
await waitForTransactionReceipt(config as Config, {
|
||||
hash: result,
|
||||
});
|
||||
// console.log("transactionReceipt", transactionReceipt);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,8 +21,6 @@ export let StakeContract = getStakeJson();
|
|||
|
||||
function getStakeJson() {
|
||||
const chainId = getChainId(config as Config);
|
||||
// console.log("chainId", chainId);
|
||||
|
||||
const chain = getChain(chainId);
|
||||
|
||||
return { abi: StakeAbi as Abi, contractAddress: chain?.stake } as Contract;
|
||||
|
|
@ -34,8 +32,6 @@ export function setStakeContract() {
|
|||
}
|
||||
|
||||
export async function snatchService(assets: bigint, receiver: Address, taxRate: number, positionsToSnatch: Array<bigint>) {
|
||||
// console.log("StakeContract", StakeContract);
|
||||
|
||||
const result = await writeContract(config as Config, {
|
||||
abi: StakeContract.abi,
|
||||
address: StakeContract.contractAddress,
|
||||
|
|
@ -81,8 +77,6 @@ export async function permitAndSnatch(
|
|||
r: Hex,
|
||||
s: Hex
|
||||
) {
|
||||
// console.log("permitAndSnatch", assets, receiver, taxRate, positionsToSnatch, deadline, v, r, s);
|
||||
|
||||
const result = await writeContract(config as Config, {
|
||||
abi: StakeContract.abi,
|
||||
address: StakeContract.contractAddress,
|
||||
|
|
@ -101,8 +95,6 @@ export async function getTotalSupply() {
|
|||
functionName: 'totalSupply',
|
||||
args: [],
|
||||
});
|
||||
// console.log("result", result);
|
||||
|
||||
totalSupply.value = result as bigint;
|
||||
return result;
|
||||
}
|
||||
|
|
@ -133,8 +125,6 @@ export async function getTaxDue(positionID: bigint) {
|
|||
}
|
||||
|
||||
export async function payTax(positionID: bigint) {
|
||||
// console.log("payTax", positionID);
|
||||
|
||||
const result = await writeContract(config as Config, {
|
||||
abi: StakeContract.abi,
|
||||
address: StakeContract.contractAddress,
|
||||
|
|
@ -145,8 +135,6 @@ export async function payTax(positionID: bigint) {
|
|||
}
|
||||
|
||||
export async function assetsToShares(asset: bigint) {
|
||||
// console.log("assetsToShares", asset);
|
||||
|
||||
const result = await readContract(config as Config, {
|
||||
abi: StakeContract.abi,
|
||||
address: StakeContract.contractAddress,
|
||||
|
|
|
|||
|
|
@ -119,8 +119,6 @@ const stats = useStatCollection(initialChainId);
|
|||
const chains = useChains();
|
||||
|
||||
function calculateAverageTaxRate(data: Array<{ taxRate: number | string }>): number {
|
||||
// console.log("data", data);
|
||||
|
||||
if (data.length === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue