-
Notifications
You must be signed in to change notification settings - Fork 59
history tab #70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
history tab #70
Changes from all commits
7bcebe0
773e367
30a639c
a2a5fa2
28eca8a
2869828
ae1946b
aeb35b0
7a7366d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,3 +5,4 @@ package-lock.json | |
.env.testnet | ||
dist/* | ||
addrbook.json | ||
.vscode |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
const express = require('express') | ||
const path = require('path') | ||
|
||
const PORT = 3000 | ||
|
||
const app = express() | ||
app.use(express.json()) | ||
app.use(express.text()) | ||
app.use(express.static('dist')) | ||
|
||
app.use('*', (_, res) => { | ||
const indexFilePath = path.resolve(process.cwd(), 'dist/index.html') | ||
res.sendFile(indexFilePath) | ||
}) | ||
|
||
app.listen(PORT, () => { | ||
console.log(`Server is working on http://localhost:${PORT}`) | ||
}) |
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -67,3 +67,6 @@ export { | |
|
||
getJettonBalances, | ||
}; | ||
|
||
import { getItemHistory } from './getgems.js' | ||
export { getItemHistory } |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<template> | ||
<anon-number-tabs v-bind:address="address" /> | ||
</template> | ||
|
||
<script> | ||
|
||
import AnonNumberTabs from './AnonNumberTabs.vue'; | ||
|
||
export default { | ||
props: { | ||
address: { | ||
type: String, | ||
required: true, | ||
}, | ||
}, | ||
|
||
components: { | ||
AnonNumberTabs | ||
}, | ||
}; | ||
</script> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
<script> | ||
import IconList from '@img/icons/material-duotone/list.svg?inline'; | ||
import IconContract from '@img/icons/material-duotone/data-object.svg?inline'; | ||
import TabContractSources from '../address/Verifier/Verifier.vue'; | ||
import HistoryTable from './historyTable/HistoryTable.vue'; | ||
import TxHistory from '../address/TxHistory.vue'; | ||
import UiTabs from '~/components/UiTabs.vue'; | ||
|
||
export default { | ||
props: { | ||
address: { | ||
type: String, | ||
required: true, | ||
}, | ||
}, | ||
|
||
render(createComponent) { | ||
return createComponent(UiTabs, { | ||
class: 'card card--tabbed', | ||
props: { | ||
tabs: this.tabs, | ||
changeUrlHash: true, | ||
}, | ||
}); | ||
}, | ||
|
||
computed: { | ||
tabs() { | ||
const props = { address: this.address }; | ||
const key = this.address; // keepalive key | ||
|
||
return [{ | ||
key: 'history', | ||
text: this.$t('address.tab_history'), | ||
icon: IconList, | ||
content: { | ||
key, props, | ||
eager: true, | ||
component: HistoryTable, | ||
}, | ||
},{ | ||
key: 'transactions', | ||
text: this.$t('address.tab_transactions'), | ||
icon: IconList, | ||
content: { | ||
key, props, | ||
eager: true, | ||
component: TxHistory, | ||
}, | ||
}, | ||
{ | ||
key: 'source', | ||
text: this.$t('address.tab_contract'), | ||
icon: IconContract, | ||
content: { | ||
key, | ||
component: TabContractSources, | ||
props: { | ||
address: this.address, | ||
isActive: true, | ||
}, | ||
}, | ||
}]; | ||
}, | ||
}, | ||
}; | ||
</script> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
<template> | ||
<section> | ||
<div v-if="this.isLoading && !items.length" class="tx-history-wrap"> | ||
<table class="tx-table"> | ||
<t-header /> | ||
<tbody> | ||
<tx-row-skeleton | ||
v-for="i in this.limit" | ||
v-bind:key="`tx_skeleton_${i}`" | ||
/> | ||
</tbody> | ||
</table> | ||
</div> | ||
|
||
<div v-else-if="!this.isLoading && this.error" | ||
class="tx-history-empty-panel" | ||
v-text="this.error" | ||
/> | ||
|
||
<div v-else-if="!this.isLoading && !this.error && !items.length" | ||
class="tx-history-empty-panel" | ||
v-text="$t('address.tx_table.empty')" | ||
/> | ||
|
||
<div v-else-if="items.length" class="tx-history-wrap"> | ||
<table class="tx-table"> | ||
<t-header /> | ||
<history-row | ||
v-for="item in items" | ||
v-bind:class="{ 'sub-list': item.id > 0 }" | ||
v-bind:key="item.id" | ||
v-bind:address="item.address" | ||
v-bind:from="item.from" | ||
v-bind:to="item.to" | ||
v-bind:price="item.price" | ||
v-bind:timestamp="item.timestamp" | ||
v-bind:type="item.type" | ||
/> | ||
</table> | ||
</div> | ||
|
||
<mugen-scroll class="mugen-scroll" v-bind:handler="loadMore" v-bind:should-handle="shouldHandleScroll"> | ||
<div ref="infiniteLoader" class="mugen-scroll__button" v-show="showPreloader" v-on:click="loadMore"> | ||
<template v-if="isLoading">{{$t('common.loading')}}</template> | ||
<template v-else>{{$t('common.load_more')}}</template> | ||
</div> | ||
</mugen-scroll> | ||
</section> | ||
</template> | ||
|
||
<script> | ||
import MugenScroll from 'vue-mugen-scroll'; | ||
|
||
import TxRowSkeleton from '../../address/TxRowSkeleton.vue'; | ||
import HistoryRow from './historyRow/HistoryRow.vue'; | ||
import THeader from './THeader.vue'; | ||
import { getItemHistory } from '~/api'; | ||
|
||
export default { | ||
props: { | ||
address: { | ||
type: String, | ||
required: false, | ||
}, | ||
}, | ||
|
||
data() { | ||
return { | ||
items: [], | ||
isLoading: true, | ||
error: null, | ||
|
||
hasMore: true, | ||
emptyHistory: false, | ||
lastActivity: undefined, | ||
|
||
limit: 3, | ||
}; | ||
}, | ||
|
||
computed: { | ||
shouldHandleScroll() { | ||
return !this.isLoading | ||
&& this.address | ||
&& this.hasMore | ||
&& this.items.length > 0; | ||
}, | ||
|
||
showPreloader() { | ||
return this.address && this.items.length > 0 && this.hasMore; | ||
}, | ||
}, | ||
|
||
watch: { | ||
address: { | ||
immediate: true, | ||
handler(address) { | ||
if (!address) return; | ||
|
||
this.items = [] | ||
this.isLoading = true; | ||
this.hasMore = true; | ||
this.emptyHistory = false; | ||
|
||
this.$nextTick(() => this.firstLoad()); | ||
}, | ||
}, | ||
}, | ||
|
||
activated() { | ||
this.emitLastActivity(); | ||
}, | ||
|
||
methods: { | ||
emitLastActivity() { | ||
this.$emit('lastActivityUpdate', this.lastActivity); | ||
}, | ||
|
||
async loadData(options) { | ||
try { | ||
this.isLoading = true; | ||
|
||
const items = await getItemHistory(this.address, options).then((res) => { | ||
return res.slice(options.offset, options.offset + this.limit) | ||
}) | ||
|
||
this.items = this.items.concat(items) | ||
this.emptyHistory = this.items.length === 0; | ||
|
||
this.hasMore = items.length >= this.limit; | ||
} catch (error) { | ||
this.error = 'Произошла ошибка загрузки' | ||
this.emptyHistory = true | ||
this.hasMore = false | ||
} finally { | ||
this.isLoading = false | ||
} | ||
}, | ||
|
||
async firstLoad() { | ||
await this.loadData({ limit: this.limit,offset: 0 }) | ||
|
||
this.lastActivity = this.items.length > 0 | ||
? new Date().getTime() //FIX_ME this.items[0]?.timestamp | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. здесь я не понял, откуда брать timestamp для этого |
||
: null; | ||
|
||
this.emitLastActivity(); | ||
}, | ||
|
||
async loadMore() { | ||
if (!this.shouldHandleScroll || !this.$refs.infiniteLoader.offsetParent) { | ||
return | ||
} | ||
|
||
await this.loadData({ | ||
limit: this.limit, | ||
offset: this.items.length, | ||
end_utime: this.lastActivity, // FIX_ME | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. не уверен, нужно ли передавать end_utime в ручку с получением транзакций |
||
}) | ||
}, | ||
}, | ||
|
||
components: { | ||
THeader, HistoryRow, TxRowSkeleton, MugenScroll, | ||
}, | ||
}; | ||
</script> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
<template> | ||
<thead> | ||
<tr> | ||
<th v-pre width="40"></th> | ||
|
||
<th width="100"> | ||
<div class="tx-table__cell" | ||
v-text="$t('address.history_table.time')"/> | ||
</th> | ||
|
||
<th> | ||
<div class="tx-table__cell tx-table__cell--align-right" | ||
v-text="$t('address.history_table.from')"/> | ||
</th> | ||
|
||
<th> | ||
<div class="tx-table__cell" | ||
v-text="$t('address.history_table.to')"/> | ||
</th> | ||
|
||
<th> | ||
<div class="tx-table__cell tx-table__cell--align-right" style="padding-right: 26px;" | ||
v-text="$t('address.history_table.type')"/> | ||
</th> | ||
|
||
<th> | ||
<div class="tx-table__cell tx-table__cell--align-right" style="padding-right: 26px;" | ||
v-text="$t('address.history_table.price')"/> | ||
</th> | ||
|
||
<th v-pre width="40"> | ||
<div class="tx-table__cell"></div> | ||
</th> | ||
</tr> | ||
</thead> | ||
</template> | ||
|
||
<script> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
часть с .then нужна только для мока