feat: add created_at time to links (#46)

closes #16
This commit is contained in:
dni ⚡ 2024-08-30 06:17:26 +02:00 committed by GitHub
commit e2f97f05dd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 55 additions and 31 deletions

View file

@ -1,4 +1,5 @@
from datetime import datetime from datetime import datetime
from time import time
from typing import List, Optional, Tuple from typing import List, Optional, Tuple
import shortuuid import shortuuid
@ -33,9 +34,10 @@ async def create_withdraw_link(
webhook_url, webhook_url,
webhook_headers, webhook_headers,
webhook_body, webhook_body,
custom_url custom_url,
created_at
) )
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""", """,
( (
link_id, link_id,
@ -54,6 +56,7 @@ async def create_withdraw_link(
data.webhook_headers, data.webhook_headers,
data.webhook_body, data.webhook_body,
data.custom_url, data.custom_url,
int(time()),
), ),
) )
link = await get_withdraw_link(link_id, 0) link = await get_withdraw_link(link_id, 0)

View file

@ -1,3 +1,6 @@
from time import time
async def m001_initial(db): async def m001_initial(db):
""" """
Creates an improved withdraw table and migrates the existing data. Creates an improved withdraw table and migrates the existing data.
@ -132,3 +135,17 @@ async def m006_webhook_headers_and_body(db):
"ALTER TABLE withdraw.withdraw_link ADD COLUMN webhook_headers TEXT;" "ALTER TABLE withdraw.withdraw_link ADD COLUMN webhook_headers TEXT;"
) )
await db.execute("ALTER TABLE withdraw.withdraw_link ADD COLUMN webhook_body TEXT;") await db.execute("ALTER TABLE withdraw.withdraw_link ADD COLUMN webhook_body TEXT;")
async def m007_add_created_at_timestamp(db):
await db.execute(
"ALTER TABLE withdraw.withdraw_link "
f"ADD COLUMN created_at TIMESTAMP DEFAULT {db.timestamp_column_default}"
)
# Set created_at to current time for all existing rows
await db.execute(
f"""
UPDATE withdraw.withdraw_link SET created_at = {db.timestamp_placeholder}
""",
(int(time()),),
)

View file

@ -1,3 +1,5 @@
import datetime
import shortuuid import shortuuid
from fastapi import Query, Request from fastapi import Query, Request
from lnurl import Lnurl, LnurlWithdrawResponse from lnurl import Lnurl, LnurlWithdrawResponse
@ -21,6 +23,7 @@ class CreateWithdrawData(BaseModel):
class WithdrawLink(BaseModel): class WithdrawLink(BaseModel):
id: str id: str
created_at: datetime.datetime
wallet: str = Query(None) wallet: str = Query(None)
title: str = Query(None) title: str = Query(None)
min_withdrawable: int = Query(0) min_withdrawable: int = Query(0)

View file

@ -11,10 +11,6 @@ var locationPath = [
var mapWithdrawLink = function (obj) { var mapWithdrawLink = function (obj) {
obj._data = _.clone(obj) obj._data = _.clone(obj)
obj.date = Quasar.utils.date.formatDate(
new Date(obj.time * 1000),
'YYYY-MM-DD HH:mm'
)
obj.min_fsat = new Intl.NumberFormat(LOCALE).format(obj.min_withdrawable) obj.min_fsat = new Intl.NumberFormat(LOCALE).format(obj.min_withdrawable)
obj.max_fsat = new Intl.NumberFormat(LOCALE).format(obj.max_withdrawable) obj.max_fsat = new Intl.NumberFormat(LOCALE).format(obj.max_withdrawable)
obj.uses_left = obj.uses - obj.used obj.uses_left = obj.uses - obj.used
@ -35,8 +31,17 @@ new Vue({
withdrawLinks: [], withdrawLinks: [],
withdrawLinksTable: { withdrawLinksTable: {
columns: [ columns: [
{name: 'id', align: 'left', label: 'ID', field: 'id'},
{name: 'title', align: 'left', label: 'Title', field: 'title'}, {name: 'title', align: 'left', label: 'Title', field: 'title'},
{
name: 'created_at',
align: 'left',
label: 'Created At',
field: 'created_at',
sortable: true,
format: function (val, row) {
return new Date(val).toLocaleString()
}
},
{ {
name: 'wait_time', name: 'wait_time',
align: 'right', align: 'right',
@ -118,13 +123,13 @@ new Vue({
`/withdraw/api/v1/links?all_wallets=true&limit=${query.limit}&offset=${query.offset}`, `/withdraw/api/v1/links?all_wallets=true&limit=${query.limit}&offset=${query.offset}`,
this.g.user.wallets[0].inkey this.g.user.wallets[0].inkey
) )
.then(function (response) { .then(response => {
self.withdrawLinks = response.data.data.map(function (obj) { this.withdrawLinks = response.data.data.map(function (obj) {
return mapWithdrawLink(obj) return mapWithdrawLink(obj)
}) })
self.withdrawLinksTable.pagination.rowsNumber = response.data.total this.withdrawLinksTable.pagination.rowsNumber = response.data.total
}) })
.catch(function (error) { .catch(error => {
clearInterval(self.checker) clearInterval(self.checker)
LNbits.utils.notifyApiError(error) LNbits.utils.notifyApiError(error)
}) })
@ -210,8 +215,6 @@ new Vue({
} }
}, },
updateWithdrawLink: function (wallet, data) { updateWithdrawLink: function (wallet, data) {
var self = this
// Remove webhook info if toggle is set to false // Remove webhook info if toggle is set to false
if (!data.has_webhook) { if (!data.has_webhook) {
data.webhook_url = null data.webhook_url = null
@ -227,26 +230,24 @@ new Vue({
data data
) )
.then(response => { .then(response => {
self.withdrawLinks = _.reject(self.withdrawLinks, function (obj) { this.withdrawLinks = _.reject(this.withdrawLinks, function (obj) {
return obj.id === data.id return obj.id === data.id
}) })
self.withdrawLinks.push(mapWithdrawLink(response.data)) this.withdrawLinks.push(mapWithdrawLink(response.data))
self.formDialog.show = false this.formDialog.show = false
this.closeFormDialog() this.closeFormDialog()
}) })
.catch(function (error) { .catch(error => {
LNbits.utils.notifyApiError(error) LNbits.utils.notifyApiError(error)
}) })
}, },
createWithdrawLink: function (wallet, data) { createWithdrawLink: function (wallet, data) {
var self = this
LNbits.api LNbits.api
.request('POST', '/withdraw/api/v1/links', wallet.adminkey, data) .request('POST', '/withdraw/api/v1/links', wallet.adminkey, data)
.then(response => { .then(response => {
self.withdrawLinks.push(mapWithdrawLink(response.data)) this.withdrawLinks.push(mapWithdrawLink(response.data))
self.formDialog.show = false this.formDialog.show = false
self.simpleformDialog.show = false this.simpleformDialog.show = false
this.closeFormDialog() this.closeFormDialog()
}) })
.catch(function (error) { .catch(function (error) {

View file

@ -37,12 +37,12 @@
{% raw %} {% raw %}
<template v-slot:header="props"> <template v-slot:header="props">
<q-tr :props="props"> <q-tr :props="props">
<q-th auto-width></q-th>
<q-th auto-width></q-th> <q-th auto-width></q-th>
<q-th v-for="col in props.cols" :key="col.name" :props="props"> <q-th v-for="col in props.cols" :key="col.name" :props="props">
{{ col.label }} {{ col.label }}
</q-th> </q-th>
<q-th auto-width></q-th> <q-th auto-width></q-th>
<q-th auto-width></q-th>
</q-tr> </q-tr>
</template> </template>
<template v-slot:body="props"> <template v-slot:body="props">
@ -92,14 +92,6 @@
><q-tooltip> view LNURL </q-tooltip></q-btn ><q-tooltip> view LNURL </q-tooltip></q-btn
> >
</q-td> </q-td>
<q-td v-for="col in props.cols" :key="col.name" :props="props">
{{ col.value }}
</q-td>
<q-td>
<q-icon v-if="props.row.webhook_url" size="14px" name="http">
<q-tooltip>Webhook to {{ props.row.webhook_url}}</q-tooltip>
</q-icon>
</q-td>
<q-td auto-width> <q-td auto-width>
<q-btn <q-btn
flat flat
@ -118,6 +110,14 @@
color="pink" color="pink"
></q-btn> ></q-btn>
</q-td> </q-td>
<q-td v-for="col in props.cols" :key="col.name" :props="props">
{{ col.value }}
</q-td>
<q-td>
<q-icon v-if="props.row.webhook_url" size="14px" name="http">
<q-tooltip>Webhook to {{ props.row.webhook_url}}</q-tooltip>
</q-icon>
</q-td>
</q-tr> </q-tr>
</template> </template>
{% endraw %} {% endraw %}