Skip to content
This repository has been archived by the owner on Mar 23, 2023. It is now read-only.

Commit

Permalink
feat: transactions pagination (#364)
Browse files Browse the repository at this point in the history
* feat: add loader indicator
* fix: undefined last ticker
* feat: add initial table pagination
* fix: resolve travis
* chore: update client and add vue-spinner
* refactor: add query params in fetchTransactions
* fix: improve tests
* chore: fetch transactions according to the current page
  • Loading branch information
luciorubeens authored and faustbrian committed Oct 16, 2018
1 parent 9ca9442 commit 5a925c7
Show file tree
Hide file tree
Showing 12 changed files with 233 additions and 17 deletions.
1 change: 1 addition & 0 deletions __tests__/unit/__utils__/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ VueTestUtils.config.mocks.currency_subToUnit = jest.fn()
VueTestUtils.config.mocks.currency_format = jest.fn()
VueTestUtils.config.mocks.session_network = jest.fn()
VueTestUtils.config.mocks.session_profile = jest.fn()
VueTestUtils.config.mocks.wallet_fromRoute = {}
20 changes: 14 additions & 6 deletions __tests__/unit/services/client.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ describe('Services > Client', () => {
const resource = resource => {
if (resource === 'transactions') {
return {
all: () => ({ data: { transactions, success: true } })
all: () => ({ data: { transactions, success: true, count: 3 } })
}
}
}
Expand All @@ -315,9 +315,13 @@ describe('Services > Client', () => {

it('should return only some properties for each transaction', async () => {
const response = await client.fetchTransactions('address')
expect(response).toHaveProperty('transactions')
expect(response).toHaveProperty('totalCount')

expect(response).toHaveLength(data.length)
response.forEach((transaction, i) => {
const transactions = response.transactions
expect(transactions).toHaveLength(data.length)

transactions.forEach((transaction, i) => {
expect(transaction).toHaveProperty('totalAmount', data[i].amount + data[i].fee)
expect(transaction).toHaveProperty('timestamp')
expect(transaction.timestamp.toJSON()).toBe(data[i].timestamp.human)
Expand All @@ -344,7 +348,7 @@ describe('Services > Client', () => {
const resource = resource => {
if (resource === 'wallets') {
return {
transactions: () => ({ data: { data: transactions } })
transactions: () => ({ data: { data: transactions, meta: { totalCount: 3 } } })
}
}
}
Expand All @@ -354,9 +358,13 @@ describe('Services > Client', () => {

it('should return only some properties for each transaction', async () => {
const response = await client.fetchTransactions('address')
expect(response).toHaveProperty('transactions')
expect(response).toHaveProperty('totalCount')

const transactions = response.transactions
expect(transactions).toHaveLength(data.length)

expect(response).toHaveLength(data.length)
response.forEach((transaction, i) => {
transactions.forEach((transaction, i) => {
expect(transaction).toHaveProperty('totalAmount', data[i].amount + data[i].fee)
expect(transaction).toHaveProperty('timestamp')
expect(transaction.timestamp.toJSON()).toBe(data[i].timestamp.human)
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
"vue-good-table": "^2.14.1",
"vue-i18n": "^8.1.0",
"vue-router": "^3.0.1",
"vue-spinner": "^1.0.3",
"vue-vuelidate-jsonschema": "^0.13.4",
"vuelidate": "^0.7.4",
"vuex": "^3.0.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export default {
try {
// TODO if wallets.length > 20 do it in batches
this.wallets.map(async wallet => {
const transactions = await this.$client.fetchTransactions(wallet.address)
const { transactions } = await this.$client.fetchTransactions(wallet.address)
// Update the transactions when they are received
this.transactions = uniqBy([
Expand Down
69 changes: 68 additions & 1 deletion src/renderer/components/Transaction/TransactionTable.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,37 @@
<template>
<div class="TransactionTable w-full">
<vue-good-table
:is-loading="isLoading"
:mode="isRemote ? 'remote' : 'local'"
:columns="columns"
:rows="transactions"
:sort-options="{
enabled: true,
initialSortBy: {field: 'timestamp', type: 'desc'}
initialSortBy: sortOptions
}"
:pagination-options="{
enabled: hasPagination,
dropdownAllowAll: false,
nextLabel: $t('COMMON.NEXT'),
prevLabel: $t('COMMON.PREV'),
rowsPerPageLabel: $t('TABLE.ROWS_PER_PAGE'),
ofLabel: $t('COMMON.OF'),
pageLabel: $t('TABLE.PAGE'),
allLabel: $t('COMMON.ALL')
}"
:total-rows="totalRows"
@on-row-click="onRowClick"
@on-page-change="onPageChange"
@on-sort-change="onSortChange"
@on-per-page-change="onPerPageChange"
>
<div
slot="loadingContent"
class="flex justify-center p-5"
>
<Loader />
</div>

<template
slot="table-row"
slot-scope="table"
Expand Down Expand Up @@ -94,6 +117,7 @@
</template>

<script>
import Loader from '@/components/utils/Loader'
import SvgIcon from '@/components/SvgIcon'
import truncateMiddle from '@/filters/truncate-middle'
import { TransactionShow } from '@/components/Transaction'
Expand All @@ -103,6 +127,7 @@ export default {
name: 'TransactionTable',
components: {
Loader,
SvgIcon,
TransactionShow,
WalletAddress
Expand All @@ -112,6 +137,35 @@ export default {
transactions: {
type: Array,
required: true
},
hasPagination: {
type: Boolean,
required: false,
default: false
},
isLoading: {
type: Boolean,
required: false,
default: false
},
isRemote: {
type: Boolean,
required: false,
default: false
},
// required if is remote
totalRows: {
type: Number,
required: false,
default: 0
},
sortOptions: {
type: Object,
required: false,
default: () => ({
field: 'timestamp',
type: 'desc'
})
}
},
Expand Down Expand Up @@ -181,6 +235,19 @@ export default {
this.selected = row
},
onPageChange (options) {
this.$emit('on-page-change', options)
},
onSortChange ({ columnIndex, sortType }) {
const columnName = this.columns[columnIndex].field
this.$emit('on-sort-change', { columnName, sortType })
},
onPerPageChange (options) {
this.$emit('on-per-page-change', options)
},
onCloseModal () {
this.selected = null
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
<template>
<TransactionTable
:transactions="transactions"
:total-rows="totalCount"
:is-loading="isLoading"
:is-remote="true"
:has-pagination="true"
:sort-options="queryParams.sort"
@on-per-page-change="onPerPageChange"
@on-page-change="onPageChange"
@on-sort-change="onSortChange"
/>
</template>

<script>
import { TransactionTable } from '@/components/Transaction'
import { orderBy } from 'lodash'
export default {
name: 'WalletTransactions',
Expand All @@ -15,7 +24,17 @@ export default {
},
data: () => ({
transactions: []
isLoading: false,
transactions: [],
totalCount: 0,
queryParams: {
page: 1,
limit: 10,
sort: {
field: 'timestamp',
type: 'desc'
}
}
}),
watch: {
Expand All @@ -33,15 +52,54 @@ export default {
if (!this.wallet_fromRoute) return
try {
this.transactions = await this.$client.fetchTransactions(this.wallet_fromRoute.address)
this.isLoading = true
const { transactions, totalCount } = await this.$client.fetchTransactions(this.wallet_fromRoute.address, {
page: this.queryParams.page,
limit: this.queryParams.limit,
orderBy: `${this.queryParams.sort.field}:${this.queryParams.sort.type}`
})
this.transactions = this.__sortTransactions(transactions)
this.totalCount = totalCount
} catch (error) {
this.$logger.error(error)
this.$error(this.$t('COMMON.FAILED_FETCH', {
name: 'transactions',
msg: error.message
}))
this.transactions = []
} finally {
this.isLoading = false
}
},
onPageChange ({ currentPage }) {
this.__updateParams({ page: currentPage })
this.fetchTransactions()
},
onPerPageChange ({ currentPerPage }) {
this.__updateParams({ limit: currentPerPage, page: 1 })
this.fetchTransactions()
},
onSortChange ({ columnName, sortType }) {
this.__updateParams({
sort: {
type: sortType,
field: columnName
},
page: 1
})
this.fetchTransactions()
},
// TODO: Sort remotely
__sortTransactions (transactions = this.transactions) {
return orderBy(transactions, [this.queryParams.sort.field], [this.queryParams.sort.type])
},
__updateParams (newProps) {
this.queryParams = Object.assign({}, this.queryParams, newProps)
}
}
}
Expand Down
20 changes: 20 additions & 0 deletions src/renderer/components/utils/Loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { PulseLoader } from 'vue-spinner/dist/vue-spinner.min'
import tailwindConfig from '@tailwind'

export default {
functional: true,

props: {
color: {
type: String,
required: false,
default: tailwindConfig.colors['blue-dark']
}
},

render: (h, ctx) => h(PulseLoader, {
props: {
color: ctx.props.color
}
})
}
8 changes: 8 additions & 0 deletions src/renderer/i18n/locales/en-US.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
export default {
COMMON: {
AVATAR: 'Avatar',
ALL: 'All',
BACK: 'Back',
DONE: 'Done',
CONFIRM: 'Confirm',
CONTACT: 'Contact',
CURRENCY: 'Currency',
LANGUAGE: 'Language',
NETWORK: 'Network',
PREV: 'Prev',
NEXT: 'Next',
OF: 'of',
PROFILE_NAME: 'Profile name',
SAVE: 'Save',
SELECT_BACKGROUND: 'Select background',
Expand Down Expand Up @@ -41,6 +44,11 @@ export default {
MONTH: 'Month'
},

TABLE: {
PAGE: 'Page',
ROWS_PER_PAGE: 'Rows per page'
},

APP_SIDEMENU: {
CURRENT_PROFILE: 'Your current profile is "{profileName}"',
SETTINGS: {
Expand Down
24 changes: 20 additions & 4 deletions src/renderer/services/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,16 +102,23 @@ export default class ClientService {
* - The timestamp field is an object that already returns converted date.
*
* @param {String} address
* @param {Object} [query]
* @param {Number} [query.page=0]
* @param {Number} [query.limit=50]
* @return {Object[]}
*/
async fetchTransactions (address) {
async fetchTransactions (address, { page, limit, orderBy } = { page: 0, limit: 50, orderBy: 'timestamp:desc' }) {
let totalCount = 0
let transactions = []

if (this.__version === 1) {
const network = store.getters['session/network']
const { data } = await this.client.resource('transactions').all({
recipientId: address,
senderId: address
senderId: address,
orderBy,
offset: (page - 1) * limit,
limit
})

if (data.success) {
Expand All @@ -125,14 +132,20 @@ export default class ClientService {

return tx
})
totalCount = data.count
}
} else {
const { data } = await this.client.resource('wallets').transactions(address)
// TODO: Add orderBy field in the v2 query params
const { data } = await this.client.resource('wallets').transactions(address, {
limit,
page
})

transactions = data.data.map(tx => {
tx.timestamp = dayjs(tx.timestamp.human).toDate()
return tx
})
totalCount = data.meta.totalCount
}

// Add some utilities for each transactions
Expand All @@ -144,7 +157,10 @@ export default class ClientService {
return tx
})

return result
return {
transactions: result,
totalCount
}
}

/**
Expand Down
Loading

0 comments on commit 5a925c7

Please sign in to comment.