[feat] Payment labels (#3537)
This commit is contained in:
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -25,12 +25,14 @@ window.localisation.en = {
|
||||
reconnect: 'Reconnect',
|
||||
open_channel: 'Open Channel',
|
||||
open: 'Open',
|
||||
clear: 'Clear',
|
||||
close_channel: 'Close Channel',
|
||||
close: 'Close',
|
||||
restart: 'Restart server',
|
||||
image_library: 'Image Library',
|
||||
save: 'Save',
|
||||
save_tooltip: 'Save your changes',
|
||||
must_save: 'You have unsaved changes',
|
||||
credit_debit: 'Credit / Debit',
|
||||
credit_hint: 'Press Enter to credit/debit wallet (negative values allowed)',
|
||||
credit_label: '{denomination} to credit/debit',
|
||||
@@ -694,6 +696,7 @@ window.localisation.en = {
|
||||
view_list: 'View wallets as list',
|
||||
view_column: 'View wallets as rows',
|
||||
filter_payments: 'Filter payments',
|
||||
filter_labels: 'Filter labels',
|
||||
filter_date: 'Filter by date',
|
||||
websocket_example: 'Websocket example',
|
||||
secret_key: 'Secret Key',
|
||||
@@ -709,5 +712,15 @@ window.localisation.en = {
|
||||
paid: 'Paid',
|
||||
funding_source_retries: 'Max Retries',
|
||||
funding_source_retries_desc:
|
||||
'Maximum number of retries for funding sources, before it falls back to VoidWallet.'
|
||||
'Maximum number of retries for funding sources, before it falls back to VoidWallet.',
|
||||
add_label: 'Add Label',
|
||||
label: 'Label',
|
||||
labels: 'Labels',
|
||||
no_labels_defined: 'No labels defined yet',
|
||||
manage_labels: 'Manage Labels',
|
||||
update_label: 'Update Label',
|
||||
delete_label: 'Delete Label',
|
||||
add_remove_labels: 'Add or Remove Labels',
|
||||
payment_labels_updated: 'Payment labels updated',
|
||||
color: 'Color'
|
||||
}
|
||||
|
||||
@@ -94,7 +94,8 @@ window.LNbits = {
|
||||
webhook: data.webhook,
|
||||
webhook_status: data.webhook_status,
|
||||
fiat_amount: data.fiat_amount,
|
||||
fiat_currency: data.fiat_currency
|
||||
fiat_currency: data.fiat_currency,
|
||||
labels: data.labels
|
||||
}
|
||||
|
||||
obj.date = moment.utc(data.created_at).local().format(window.dateFormat)
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
window.app.component('lnbits-label-selector', {
|
||||
template: '#lnbits-label-selector',
|
||||
props: ['labels'],
|
||||
mixins: [window.windowMixin],
|
||||
data() {
|
||||
return {
|
||||
labelFilter: '',
|
||||
localLabels: []
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
toggleLabel(label) {
|
||||
const hasLabel = this.localLabels.includes(label.name)
|
||||
|
||||
if (hasLabel) {
|
||||
const index = this.localLabels.indexOf(label.name)
|
||||
if (index !== -1) {
|
||||
this.localLabels.splice(index, 1)
|
||||
}
|
||||
} else {
|
||||
this.localLabels.push(label.name)
|
||||
}
|
||||
},
|
||||
saveLabels() {
|
||||
this.$emit('update:labels', this.localLabels)
|
||||
},
|
||||
clearLabels() {
|
||||
this.localLabels = []
|
||||
this.saveLabels()
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.localLabels = [...this.labels]
|
||||
}
|
||||
})
|
||||
@@ -121,7 +121,9 @@ window.app.component('lnbits-payment-list', {
|
||||
show: false,
|
||||
payment: null,
|
||||
preimage: null
|
||||
}
|
||||
},
|
||||
selectedPayment: null,
|
||||
filterLabels: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -161,12 +163,26 @@ window.app.component('lnbits-payment-list', {
|
||||
|
||||
this.fetchPayments()
|
||||
},
|
||||
searchByLabels(labels) {
|
||||
if (!labels || labels.length === 0) {
|
||||
this.clearLabelSeach()
|
||||
return
|
||||
}
|
||||
this.filterLabels = labels
|
||||
this.paymentsTable.filter['labels[every]'] = labels
|
||||
this.fetchPayments()
|
||||
},
|
||||
clearDateSeach() {
|
||||
this.searchDate = {from: null, to: null}
|
||||
delete this.paymentFilter['time[ge]']
|
||||
delete this.paymentFilter['time[le]']
|
||||
this.fetchPayments()
|
||||
},
|
||||
clearLabelSeach() {
|
||||
this.filterLabels = []
|
||||
delete this.paymentsTable.filter['labels[every]']
|
||||
this.fetchPayments()
|
||||
},
|
||||
fetchPayments(props) {
|
||||
const params = LNbits.utils.prepareFilterQuery(
|
||||
this.paymentsTable,
|
||||
@@ -354,6 +370,47 @@ window.app.component('lnbits-payment-list', {
|
||||
paymentFilter['amount[le]'] = 0
|
||||
}
|
||||
this.paymentFilter = paymentFilter
|
||||
},
|
||||
async savePaymentLabels(labels) {
|
||||
if (!this.selectedPayment) {
|
||||
Quasar.Notify.create({
|
||||
type: 'warning',
|
||||
message: 'No payment selected'
|
||||
})
|
||||
return
|
||||
}
|
||||
try {
|
||||
await LNbits.api.request(
|
||||
'PUT',
|
||||
`/api/v1/payments/${this.selectedPayment.payment_hash}/labels`,
|
||||
this.g.wallet.adminkey,
|
||||
{
|
||||
labels: labels
|
||||
}
|
||||
)
|
||||
|
||||
const payment = this.payments.find(
|
||||
p => p.checking_id === this.selectedPayment.checking_id
|
||||
)
|
||||
if (payment) {
|
||||
payment.labels = [...labels]
|
||||
}
|
||||
|
||||
Quasar.Notify.create({
|
||||
type: 'positive',
|
||||
message: this.$t('payment_labels_updated')
|
||||
})
|
||||
} catch (error) {
|
||||
LNbits.utils.notifyApiError(error)
|
||||
}
|
||||
},
|
||||
isLightColor(color) {
|
||||
try {
|
||||
return Quasar.colors.luminosity(color) > 0.5
|
||||
} catch (e) {
|
||||
console.warning(e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
||||
@@ -4,6 +4,7 @@ window.PageAccount = {
|
||||
data() {
|
||||
return {
|
||||
user: null,
|
||||
untouchedUser: null,
|
||||
hasUsername: false,
|
||||
showUserId: false,
|
||||
themeOptions: [
|
||||
@@ -145,6 +146,47 @@ window.PageAccount = {
|
||||
nostr: {
|
||||
identifier: ''
|
||||
}
|
||||
},
|
||||
labels: [],
|
||||
labelsDialog: {
|
||||
show: false,
|
||||
data: {
|
||||
name: '',
|
||||
description: '',
|
||||
color: '#000000'
|
||||
}
|
||||
},
|
||||
labelsTable: {
|
||||
loading: false,
|
||||
columns: [
|
||||
{
|
||||
name: 'actions',
|
||||
align: 'left'
|
||||
},
|
||||
{
|
||||
name: 'name',
|
||||
align: 'left',
|
||||
label: this.$t('Name'),
|
||||
field: 'name',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
name: 'description',
|
||||
align: 'left',
|
||||
label: this.$t('description'),
|
||||
field: 'description'
|
||||
},
|
||||
{
|
||||
name: 'color',
|
||||
align: 'left',
|
||||
label: this.$t('color'),
|
||||
field: 'color'
|
||||
}
|
||||
],
|
||||
pagination: {
|
||||
rowsPerPage: 6,
|
||||
page: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -159,6 +201,11 @@ window.PageAccount = {
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isUserTouched() {
|
||||
return JSON.stringify(this.user) !== JSON.stringify(this.untouchedUser)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
activeLanguage(lang) {
|
||||
return window.i18n.global.locale === lang
|
||||
@@ -181,6 +228,7 @@ window.PageAccount = {
|
||||
}
|
||||
)
|
||||
this.user = data
|
||||
this.untouchedUser = JSON.parse(JSON.stringify(data))
|
||||
this.hasUsername = !!data.username
|
||||
Quasar.Notify.create({
|
||||
type: 'positive',
|
||||
@@ -220,6 +268,7 @@ window.PageAccount = {
|
||||
}
|
||||
)
|
||||
this.user = data
|
||||
this.untouchedUser = JSON.parse(JSON.stringify(data))
|
||||
this.hasUsername = !!data.username
|
||||
this.credentialsData.show = false
|
||||
Quasar.Notify.create({
|
||||
@@ -242,6 +291,7 @@ window.PageAccount = {
|
||||
}
|
||||
)
|
||||
this.user = data
|
||||
this.untouchedUser = JSON.parse(JSON.stringify(data))
|
||||
this.hasUsername = !!data.username
|
||||
this.credentialsData.show = false
|
||||
this.$q.notify({
|
||||
@@ -558,6 +608,73 @@ window.PageAccount = {
|
||||
copyAssetLinkToClipboard(asset) {
|
||||
const assetUrl = `${window.location.origin}/api/v1/assets/${asset.id}/binary`
|
||||
this.copyText(assetUrl)
|
||||
},
|
||||
addUserLabel() {
|
||||
if (!this.labelsDialog.data.name) {
|
||||
this.$q.notify({
|
||||
type: 'warning',
|
||||
message: 'Name is required.'
|
||||
})
|
||||
return
|
||||
}
|
||||
if (!this.labelsDialog.data.color) {
|
||||
this.$q.notify({
|
||||
type: 'warning',
|
||||
message: 'Color is required.'
|
||||
})
|
||||
return
|
||||
}
|
||||
this.user.extra.labels = this.user.extra.labels || []
|
||||
const duplicate = this.user.extra.labels.find(
|
||||
label => label.name === this.labelsDialog.data.name
|
||||
)
|
||||
if (duplicate) {
|
||||
this.$q.notify({
|
||||
type: 'warning',
|
||||
message: 'A label with this name already exists.'
|
||||
})
|
||||
return
|
||||
}
|
||||
this.user.extra.labels.unshift({...this.labelsDialog.data})
|
||||
this.labelsDialog.show = false
|
||||
return true
|
||||
},
|
||||
openAddLabelDialog() {
|
||||
this.labelsDialog.data = {
|
||||
name: '',
|
||||
description: '',
|
||||
color: '#000000'
|
||||
}
|
||||
this.labelsDialog.show = true
|
||||
},
|
||||
openEditLabelDialog(label) {
|
||||
this.labelsDialog.data = {
|
||||
name: label.name,
|
||||
description: label.description,
|
||||
color: label.color
|
||||
}
|
||||
this.labelsDialog.show = true
|
||||
},
|
||||
updateUserLabel() {
|
||||
const label = this.labelsDialog.data
|
||||
const existingLabels = JSON.parse(JSON.stringify(this.user.extra.labels))
|
||||
this.user.extra.labels = this.user.extra.labels.filter(
|
||||
l => l.name !== label.name
|
||||
)
|
||||
const labelUpdated = this.addUserLabel()
|
||||
if (!labelUpdated) {
|
||||
this.user.extra.labels = existingLabels
|
||||
}
|
||||
this.labelsDialog.show = false
|
||||
},
|
||||
deleteUserLabel(label) {
|
||||
LNbits.utils
|
||||
.confirmDialog('Are you sure you want to delete this label?')
|
||||
.onOk(() => {
|
||||
this.user.extra.labels = this.user.extra.labels.filter(
|
||||
l => l.name !== label.name
|
||||
)
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
@@ -565,6 +682,7 @@ window.PageAccount = {
|
||||
try {
|
||||
const {data} = await LNbits.api.getAuthenticatedUser()
|
||||
this.user = data
|
||||
this.untouchedUser = JSON.parse(JSON.stringify(data))
|
||||
this.hasUsername = !!data.username
|
||||
if (!this.user.extra) this.user.extra = {}
|
||||
} catch (e) {
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
"js/components/lnbits-manage-wallet-list.js",
|
||||
"js/components/lnbits-language-dropdown.js",
|
||||
"js/components/lnbits-payment-list.js",
|
||||
"js/components/lnbits-label-selector.js",
|
||||
"js/components/extension-settings.js",
|
||||
"js/components/data-fields.js",
|
||||
"js/components.js",
|
||||
|
||||
Reference in New Issue
Block a user