Skip to content

Commit

Permalink
feat: add nft list and links from balances
Browse files Browse the repository at this point in the history
Signed-off-by: Tim Schmidt <tim@launchbadge.com>
  • Loading branch information
Sheng-Long committed Oct 19, 2023
1 parent 105a323 commit 4aaad8a
Show file tree
Hide file tree
Showing 4 changed files with 238 additions and 4 deletions.
127 changes: 127 additions & 0 deletions src/components/account/NftsTable.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
<!--
-
- Hedera Mirror Node Explorer
-
- Copyright (C) 2021 - 2023 Hedera Hashgraph, LLC
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-->

<!-- --------------------------------------------------------------------------------------------------------------- -->
<!-- TEMPLATE -->
<!-- --------------------------------------------------------------------------------------------------------------- -->

<template>

<o-table
:data="nfts"
:loading="loading"
:hoverable="true"
:paginated="!isTouchDevice"
backend-pagination
:total="totalRowCount"
:current-page="currentPage"
:per-page="pageSize"
@page-change="onPageChange"
:striped="true"
:v-model:current-page="currentPage"
:mobile-breakpoint="ORUGA_MOBILE_BREAKPOINT"
aria-current-label="Current page"
aria-next-label="Next page"
aria-page-label="Page"
aria-previous-label="Previous page"
@cell-click="handleClick"
>
<o-table-column v-slot="props" field="token_id" label="Token">
<TokenLink
v-bind:show-extra="true"
v-bind:token-id="props.row.token_id"
v-bind:no-anchor="true"
/>
</o-table-column>

<o-table-column v-slot="props" field="serial" label="Serial Number" position="right">
{{props.row.serial_number}}
</o-table-column>

</o-table>

<EmptyTable v-if="!nfts.length"/>

</template>

<!-- --------------------------------------------------------------------------------------------------------------- -->
<!-- SCRIPT -->
<!-- --------------------------------------------------------------------------------------------------------------- -->

<script lang="ts">
import {defineComponent, inject, PropType, ref, ComputedRef, Ref} from 'vue';
import { Nft, TokenBalance, TokenRelationship } from "@/schemas/HederaSchemas";
import TokenLink from "@/components/values/TokenLink.vue";
import TokenAmount from "@/components/values/TokenAmount.vue";
import {ORUGA_MOBILE_BREAKPOINT} from '@/App.vue';
import EmptyTable from "@/components/EmptyTable.vue";
import {routeManager} from "@/router";
import { NftsTableController } from "@/components/account/NftsTableController";
export default defineComponent({
name: 'NftsTable',
components: {
EmptyTable,
TokenLink,
},
props: {
controller: {
type: Object as PropType<NftsTableController>,
required: true
},
},
setup(props) {
const isTouchDevice = inject('isTouchDevice', false)
const isMediumScreen = inject('isMediumScreen', true)
const handleClick = (nft: Nft, c: unknown, i: number, ci: number, event: MouseEvent) => {
if (nft.token_id && nft.serial_number) {
routeManager.routeToSerial(nft.token_id, nft.serial_number, event.ctrlKey || event.metaKey)
}
}
return {
isTouchDevice,
isMediumScreen,
nfts: props.controller.rows as ComputedRef<Nft[]>,
loading: props.controller.loading as ComputedRef<boolean>,
totalRowCount: props.controller.totalRowCount as ComputedRef<number>,
currentPage: props.controller.currentPage as Ref<number>,
onPageChange: props.controller.onPageChange,
pageSize: props.controller.pageSize as Ref<Number>,
handleClick,
ORUGA_MOBILE_BREAKPOINT
}
}
});
</script>

<!-- --------------------------------------------------------------------------------------------------------------- -->
<!-- STYLE -->
<!-- --------------------------------------------------------------------------------------------------------------- -->

<style scoped>
</style>
85 changes: 85 additions & 0 deletions src/components/account/NftsTableController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*-
*
* Hedera Mirror Node Explorer
*
* Copyright (C) 2021 - 2023 Hedera Hashgraph, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

import {
Nft,
Nfts,
NftTransactionHistory,
TokenBalancesResponse,
TokenDistribution,
TokenRelationship
} from "@/schemas/HederaSchemas";
import {ComputedRef, Ref} from "vue";
import axios, {AxiosResponse} from "axios";
import {KeyOperator, SortOrder, TableController} from "@/utils/table/TableController";
import {Router} from "vue-router";

export class NftsTableController extends TableController<Nft, string> {

public readonly accountId: Ref<string | null>

//
// Public
//

public constructor(router: Router, accountId: Ref<string | null>, pageSize: ComputedRef<number>) {
super(router, pageSize, 10 * pageSize.value, 5000, 10, 100)
this.accountId = accountId
}

//
// TableController
//

public async load(tokenId: string | null, operator: KeyOperator, order: SortOrder, limit: number): Promise<Nft[] | null> {
if (this.accountId.value == null) {
return Promise.resolve(null)
}

const params = {} as {
limit: number
"token.id": string | undefined
order: string
}
params.limit = limit
params.order = order
if (tokenId !== null) {
params["token.id"] = operator + ":" + tokenId
}

const r = await axios.get<Nfts>(
`api/v1/accounts/${this.accountId.value}/nfts`,
{params: params},
)
return r.data.nfts ?? []
}

public keyFor(row: Nft): string {
return row.token_id ?? ""
}

public stringFromKey(key: string): string {
return key;
}

public keyFromString(s: string): string | null {
return s;
}
}
29 changes: 25 additions & 4 deletions src/pages/AccountBalances.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@
</template>
</DashboardCard>

<DashboardCard>
<template v-slot:title>
<span class="h-is-primary-title">NFTs owned by </span>
<span class="h-is-secondary-text">{{ accountId }}</span>
</template>
<template v-slot:content>
<NftsTable :controller="nftsTableController"/>
</template>
</DashboardCard>

</section>

<Footer/>
Expand All @@ -55,12 +65,15 @@ import Footer from "@/components/Footer.vue";
import {TokenRelationshipsTableController} from "@/components/account/TokenRelationshipsTableController";
import {useRouter} from "vue-router";
import {EntityID} from "@/utils/EntityID";
import NftsTable from "@/components/account/NftsTable.vue";
import { NftsTableController } from "@/components/account/NftsTableController";
export default defineComponent({
name: 'AccountBalances',
components: {
NftsTable,
Footer,
DashboardCard,
BalanceTable
Expand All @@ -85,18 +98,26 @@ export default defineComponent({
})
const tokenRelationshipTableController =
new TokenRelationshipsTableController(useRouter(), normalizedAccountId, perPage)
onMounted(() => tokenRelationshipTableController.mount())
onBeforeUnmount(() => tokenRelationshipTableController.unmount())
new TokenRelationshipsTableController(useRouter(), normalizedAccountId, perPage);
const nftsTableController = new NftsTableController(useRouter(), normalizedAccountId, perPage);
onMounted(() => {
tokenRelationshipTableController.mount()
nftsTableController.mount()
})
onBeforeUnmount(() => {
tokenRelationshipTableController.unmount()
nftsTableController.unmount()
})
return {
isSmallScreen,
isTouchDevice,
tokenRelationshipTableController,
nftsTableController,
}
}
});
</script>

<style/>
<style/>
1 change: 1 addition & 0 deletions tests/e2e/specs/AccountNavigation.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ describe('Account Navigation', () => {
cy.contains('Token Balances for Account ' + accountId1)

cy.get('table')
.eq(0)
.find('tbody tr')
.should('have.length.at.least', 2)
.eq(0)
Expand Down

0 comments on commit 4aaad8a

Please sign in to comment.