satistics done
This commit is contained in:
parent
d92f58aaf4
commit
bbc34edf51
@ -3,6 +3,7 @@ import { UserInputError, AuthenticationError } from 'apollo-server-micro'
|
||||
import serialize from './serial'
|
||||
import { decodeCursor, LIMIT, nextCursorEncoded } from '../../lib/cursor'
|
||||
import lnpr from 'bolt11'
|
||||
import { SELECT } from './item'
|
||||
|
||||
export default {
|
||||
Query: {
|
||||
@ -86,9 +87,29 @@ export default {
|
||||
AND created_at <= $2)`)
|
||||
}
|
||||
|
||||
// TODO
|
||||
// 1. union invoices and withdrawals (check)
|
||||
// 2. add to union spending and receiving
|
||||
if (include.has('stacked')) {
|
||||
queries.push(
|
||||
`(SELECT ('stacked' || "Item".id) as id, "Item".id as "factId", NULL as bolt11,
|
||||
MAX("ItemAct".created_at) as "createdAt", sum("ItemAct".sats) * 1000 as msats,
|
||||
0 as "msatsFee", NULL as status, 'stacked' as type
|
||||
FROM "ItemAct"
|
||||
JOIN "Item" on "ItemAct"."itemId" = "Item".id
|
||||
WHERE "ItemAct"."userId" <> $1 AND "ItemAct".act <> 'BOOST'
|
||||
AND "Item"."userId" = $1 AND "ItemAct".created_at <= $2
|
||||
GROUP BY "Item".id)`)
|
||||
}
|
||||
|
||||
if (include.has('spent')) {
|
||||
queries.push(
|
||||
`(SELECT ('spent' || "Item".id) as id, "Item".id as "factId", NULL as bolt11,
|
||||
MAX("ItemAct".created_at) as "createdAt", sum("ItemAct".sats) * 1000 as msats,
|
||||
0 as "msatsFee", NULL as status, 'spent' as type
|
||||
FROM "ItemAct"
|
||||
JOIN "Item" on "ItemAct"."itemId" = "Item".id
|
||||
WHERE "ItemAct"."userId" = $1
|
||||
AND "ItemAct".created_at <= $2
|
||||
GROUP BY "Item".id)`)
|
||||
}
|
||||
|
||||
if (queries.length === 0) {
|
||||
return {
|
||||
@ -103,8 +124,6 @@ export default {
|
||||
OFFSET $3
|
||||
LIMIT ${LIMIT}`, me.id, decodedCursor.time, decodedCursor.offset)
|
||||
|
||||
console.log(history)
|
||||
|
||||
history = history.map(f => {
|
||||
if (f.bolt11) {
|
||||
const inv = lnpr.decode(f.bolt11)
|
||||
@ -120,6 +139,9 @@ export default {
|
||||
}
|
||||
switch (f.type) {
|
||||
case 'withdrawal':
|
||||
f.msats = (-1 * f.msats) - f.msatsFee
|
||||
break
|
||||
case 'spent':
|
||||
f.msats *= -1
|
||||
break
|
||||
default:
|
||||
@ -129,8 +151,6 @@ export default {
|
||||
return f
|
||||
})
|
||||
|
||||
console.log(history)
|
||||
|
||||
return {
|
||||
cursor: history.length === LIMIT ? nextCursorEncoded(decodedCursor) : null,
|
||||
facts: history
|
||||
@ -251,5 +271,19 @@ export default {
|
||||
satsPaid: w => Math.floor(w.msatsPaid / 1000),
|
||||
satsFeePaying: w => Math.floor(w.msatsFeePaying / 1000),
|
||||
satsFeePaid: w => Math.floor(w.msatsFeePaid / 1000)
|
||||
},
|
||||
|
||||
Fact: {
|
||||
item: async (fact, args, { models }) => {
|
||||
if (fact.type !== 'spent' && fact.type !== 'stacked') {
|
||||
return null
|
||||
}
|
||||
const [item] = await models.$queryRaw(`
|
||||
${SELECT}
|
||||
FROM "Item"
|
||||
WHERE id = $1`, Number(fact.factId))
|
||||
|
||||
return item
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,9 +46,10 @@ export default gql`
|
||||
createdAt: String!
|
||||
msats: Int!
|
||||
msatsFee: Int
|
||||
status: String!
|
||||
status: String
|
||||
type: String!
|
||||
description: String
|
||||
item: Item
|
||||
}
|
||||
|
||||
type History {
|
||||
|
@ -38,9 +38,14 @@ function Parent ({ item, rootText }) {
|
||||
)
|
||||
}
|
||||
|
||||
const truncateString = (string = '', maxLength = 140) =>
|
||||
string.length > maxLength
|
||||
? `${string.substring(0, maxLength)} […]`
|
||||
: string
|
||||
|
||||
export default function Comment ({
|
||||
item, children, replyOpen, includeParent,
|
||||
rootText, noComments, noReply
|
||||
rootText, noComments, noReply, truncate
|
||||
}) {
|
||||
const [edit, setEdit] = useState()
|
||||
const [collapse, setCollapse] = useState(false)
|
||||
@ -129,7 +134,9 @@ export default function Comment ({
|
||||
)
|
||||
: (
|
||||
<div className={styles.text}>
|
||||
<Text nofollow={item.sats + item.boost < NOFOLLOW_LIMIT}>{item.text}</Text>
|
||||
<Text nofollow={item.sats + item.boost < NOFOLLOW_LIMIT}>
|
||||
{truncate ? truncateString(item.text) : item.text}
|
||||
</Text>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
@ -132,7 +132,7 @@ export default function UserHeader ({ user }) {
|
||||
</Nav.Item>
|
||||
{isMe &&
|
||||
<Nav.Item>
|
||||
<Link href='/satistics?inc=invoice,withdrawal,stacked,spent' passHref>
|
||||
<Link href='/satistics?inc=invoice,withdrawal' passHref>
|
||||
<Nav.Link eventKey='/satistics'>satistics</Nav.Link>
|
||||
</Link>
|
||||
</Nav.Item>}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { gql } from '@apollo/client'
|
||||
import { ITEM_FIELDS } from './items'
|
||||
|
||||
export const INVOICE = gql`
|
||||
query Invoice($id: ID!) {
|
||||
@ -25,6 +26,8 @@ export const WITHDRAWL = gql`
|
||||
}`
|
||||
|
||||
export const WALLET_HISTORY = gql`
|
||||
${ITEM_FIELDS}
|
||||
|
||||
query WalletHistory($cursor: String, $inc: String) {
|
||||
walletHistory(cursor: $cursor, inc: $inc) {
|
||||
facts {
|
||||
@ -37,6 +40,10 @@ export const WALLET_HISTORY = gql`
|
||||
status
|
||||
type
|
||||
description
|
||||
item {
|
||||
...ItemFields
|
||||
text
|
||||
}
|
||||
}
|
||||
cursor
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { useQuery } from '@apollo/client'
|
||||
import Link from 'next/link'
|
||||
import { Table } from 'react-bootstrap'
|
||||
import useDarkMode from 'use-dark-mode'
|
||||
import { getGetServerSideProps } from '../api/ssrApollo'
|
||||
import Layout from '../components/layout'
|
||||
import { useMe } from '../components/me'
|
||||
@ -14,10 +13,16 @@ import Check from '../svgs/check-double-line.svg'
|
||||
import ThumbDown from '../svgs/thumb-down-fill.svg'
|
||||
import { Checkbox, Form } from '../components/form'
|
||||
import { useRouter } from 'next/router'
|
||||
import Item from '../components/item'
|
||||
import Comment from '../components/comment'
|
||||
|
||||
export const getServerSideProps = getGetServerSideProps(WALLET_HISTORY)
|
||||
|
||||
function satusClass (status) {
|
||||
if (!status) {
|
||||
return ''
|
||||
}
|
||||
|
||||
switch (status) {
|
||||
case 'CONFIRMED':
|
||||
return ''
|
||||
@ -82,14 +87,30 @@ function Satus ({ status }) {
|
||||
)
|
||||
}
|
||||
|
||||
function Detail ({ fact }) {
|
||||
if (!fact.item) {
|
||||
return (
|
||||
<>
|
||||
<div className={satusClass(fact.status)}>
|
||||
{fact.description || 'no description'}
|
||||
</div>
|
||||
<Satus status={fact.status} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
if (fact.item.title) {
|
||||
return <div className={styles.itemWrapper}><Item item={fact.item} /></div>
|
||||
}
|
||||
|
||||
return <div className={styles.commentWrapper}><Comment item={fact.item} includeParent noReply truncate /></div>
|
||||
}
|
||||
|
||||
export default function Satistics ({ data: { walletHistory: { facts, cursor } } }) {
|
||||
const me = useMe()
|
||||
const { value: darkMode } = useDarkMode()
|
||||
const router = useRouter()
|
||||
const { data, fetchMore } = useQuery(WALLET_HISTORY, { variables: { inc: router.query.inc } })
|
||||
|
||||
console.log(router.query.inc, data)
|
||||
|
||||
function filterRoutePush (filter, add) {
|
||||
const inc = new Set(router.query.inc.split(','))
|
||||
inc.delete('')
|
||||
@ -109,6 +130,16 @@ export default function Satistics ({ data: { walletHistory: { facts, cursor } }
|
||||
return inc.has(filter)
|
||||
}
|
||||
|
||||
function href (fact) {
|
||||
switch (fact.type) {
|
||||
case 'withdrawal':
|
||||
case 'invoice':
|
||||
return `/${fact.type}s/${fact.factId}`
|
||||
default:
|
||||
return `/items/${fact.factId}`
|
||||
}
|
||||
}
|
||||
|
||||
if (data) {
|
||||
({ walletHistory: { facts, cursor } } = data)
|
||||
}
|
||||
@ -149,7 +180,7 @@ export default function Satistics ({ data: { walletHistory: { facts, cursor } }
|
||||
/>
|
||||
</div>
|
||||
</Form>
|
||||
<Table className='mt-3 mb-0' bordered hover size='sm' variant={darkMode ? 'dark' : undefined}>
|
||||
<Table className='mt-3 mb-0' bordered hover size='sm'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className={styles.type}>type</th>
|
||||
@ -159,14 +190,11 @@ export default function Satistics ({ data: { walletHistory: { facts, cursor } }
|
||||
</thead>
|
||||
<tbody>
|
||||
{facts.map((f, i) => (
|
||||
<Link href={`${f.type}s/${f.factId}`} key={f.id}>
|
||||
<Link href={href(f)} key={f.id}>
|
||||
<tr className={styles.row}>
|
||||
<td className={`${styles.type} ${satusClass(f.status)}`}>{f.type}</td>
|
||||
<td className={styles.description}>
|
||||
<div className={satusClass(f.status)}>
|
||||
{f.description || 'no description'}
|
||||
</div>
|
||||
<Satus status={f.status} />
|
||||
<Detail fact={f} />
|
||||
</td>
|
||||
<td className={`${styles.sats} ${satusClass(f.status)}`}>{f.msats / 1000}</td>
|
||||
</tr>
|
||||
|
@ -59,8 +59,13 @@ $tooltip-bg: #5c8001;
|
||||
src: url(/Lightningvolt-xoqm.ttf);
|
||||
}
|
||||
|
||||
@media screen and (min-width: 767px) {
|
||||
.table-sm th, .table-sm td {
|
||||
padding: .3rem .75rem;
|
||||
}
|
||||
}
|
||||
|
||||
.table-sm th, .table-sm td {
|
||||
padding: .3rem .75rem;
|
||||
line-height: 1.2rem;
|
||||
}
|
||||
|
||||
@ -77,6 +82,11 @@ $tooltip-bg: #5c8001;
|
||||
border-color: var(--theme-borderColor);
|
||||
}
|
||||
|
||||
.table-hover tbody tr:hover {
|
||||
color: var(--theme-color);
|
||||
background-color: var(--theme-clickToContextColor);
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--theme-body);
|
||||
color: var(--theme-color);
|
||||
|
@ -15,4 +15,14 @@
|
||||
|
||||
.row {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.itemWrapper {
|
||||
padding-top: .25rem;
|
||||
margin-bottom: -.25rem;
|
||||
}
|
||||
|
||||
.commentWrapper {
|
||||
padding-top: .2rem;
|
||||
padding-bottom: .4rem;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user