feat: Shared Wallets/Joint Accounts (Issue #3297) (#3376)

This commit is contained in:
Ben Weeks
2025-11-07 22:25:03 +02:00
committed by GitHub
parent bd07f7a5ef
commit b54eedee84
31 changed files with 2078 additions and 163 deletions
+26 -42
View File
@@ -266,6 +266,7 @@
<lnbits-wallet-list
v-if="!walletFlip"
:balance="balance"
@wallet-action="handleWalletAction"
></lnbits-wallet-list>
<lnbits-manage
:show-admin="'{{LNBITS_ADMIN_UI}}' == 'True'"
@@ -295,57 +296,31 @@
"
>
<div class="row no-wrap q-pr-md">
<q-card class="wallet-list-card">
<q-card
@click="showAddNewWalletDialog()"
class="wallet-list-card cursor-pointer"
>
<q-card-section
class="flex flex-center column full-height text-center"
>
<div>
<q-btn
round
color="primary"
icon="add"
@click="showAddWalletDialog.show = true"
>
<q-btn round color="primary" icon="add">
<q-tooltip
><span v-text="$t('add_new_wallet')"></span
></q-tooltip>
</q-btn>
<q-dialog
v-model="showAddWalletDialog.show"
persistent
@hide="showAddWalletDialog = {show: false}"
</div>
<div>
<q-badge
@click="addWalletDialog.walletType='lightning-shared '"
dense
outline
class="q-mt-sm"
>
<q-card style="min-width: 350px">
<q-card-section>
<div class="text-h6">
<span v-text="$t('wallet_name')"></span>
</div>
</q-card-section>
<q-card-section class="q-pt-none">
<q-input
dense
v-model="showAddWalletDialog.name"
autofocus
@keyup.enter="submitAddWallet()"
></q-input>
</q-card-section>
<q-card-actions align="right" class="text-primary">
<q-btn
flat
:label="$t('cancel')"
v-close-popup
></q-btn>
<q-btn
flat
:label="$t('add_wallet')"
v-close-popup
@click="submitAddWallet()"
></q-btn>
</q-card-actions>
</q-card>
</q-dialog>
<span
v-text="'New wallet invite (' + g.user.walletInvitesCount + ')'"
></span>
</q-badge>
</div>
</q-card-section>
</q-card>
@@ -421,6 +396,15 @@
</q-card>
</div>
</q-scroll-area>
<q-dialog
v-model="addWalletDialog.show"
position="top"
@hide="addWalletDialog = {show: false}"
>
<lnbits-new-user-wallet
:form-data="formData"
></lnbits-new-user-wallet>
</q-dialog>
<router-view v-if="isVueRoute"></router-view>
+17 -27
View File
@@ -9,7 +9,8 @@ include('components/admin/audit.vue') %} {%
include('components/admin/extensions.vue') %} {%
include('components/admin/library.vue') %} {%
include('components/admin/notifications.vue') %} {%
include('components/admin/server.vue') %}
include('components/admin/server.vue') %} {%
include('components/new_user_wallet.vue') %}
<template id="lnbits-wallet-list">
<q-list
@@ -56,7 +57,12 @@ include('components/admin/server.vue') %}
<strong v-text="formatBalance(walletRec.sat)"></strong>
</q-item-label>
</q-item-section>
<q-item-section side v-show="g.wallet && g.wallet.id === walletRec.id">
<q-item-section
v-if="walletRec.walletType == 'lightning-shared'"
side
top
>
<q-icon name="group" :color="walletRec.extra.color" size="xs"></q-icon>
</q-item-section>
</q-item>
<q-item
@@ -75,13 +81,9 @@ include('components/admin/server.vue') %}
></q-item-label>
</q-item-section>
</q-item>
<q-item clickable @click="showForm = !showForm">
<q-item clickable @click="createWallet()">
<q-item-section side>
<q-icon
:name="showForm ? 'remove' : 'add'"
color="grey-5"
size="md"
></q-icon>
<q-icon name="add" color="grey-5" size="md"></q-icon>
</q-item-section>
<q-item-section>
<q-item-label
@@ -89,25 +91,13 @@ include('components/admin/server.vue') %}
class="text-caption"
v-text="$t('add_new_wallet')"
></q-item-label>
</q-item-section>
</q-item>
<q-item v-if="showForm">
<q-item-section>
<q-form @submit="createWallet">
<q-input filled dense v-model="walletName" label="Name wallet *">
<template v-slot:append>
<q-btn
round
dense
flat
icon="send"
size="sm"
@click="createWallet"
:disable="walletName === ''"
></q-btn>
</template>
</q-input>
</q-form>
<q-item-section v-if="g.user.walletInvitesCount" side>
<q-badge>
<span
v-text="'Wallet Invite (' + g.user.walletInvitesCount + ')'"
></span>
</q-badge>
</q-item-section>
</q-item-section>
</q-item>
</q-list>
@@ -0,0 +1,98 @@
<template id="lnbits-new-user-wallet">
<q-card class="q-pa-lg q-pt-md lnbits__dialog-card">
<q-card-section>
<div class="text-h6">
<span v-text="$t('add_new_wallet')"></span>
</div>
</q-card-section>
<q-card-section v-if="g.user.walletInvitesCount">
<q-badge
@click="newWallet.walletType = 'lightning-shared'"
class="cursor-pointer"
>
<span
v-text="
'You have ' +
g.user.walletInvitesCount +
' wallet invitation' +
(g.user.walletInvitesCount > 1 ? 's' : '')
"
></span>
</q-badge>
</q-card-section>
<q-card-section class="q-pt-none">
<q-select
v-if="walletTypes.length > 1"
:options="walletTypes"
emit-value
map-options
:label="$t('wallet_type')"
v-model="newWallet.walletType"
dense
></q-select>
<q-input
v-if="newWallet.walletType == 'lightning'"
dense
v-model="newWallet.name"
:label="$t('wallet_name')"
autofocus
@keyup.enter="submitAddWallet()"
class="q-mt-md"
></q-input>
<q-select
v-if="newWallet.walletType == 'lightning-shared'"
v-model="newWallet.sharedWalletId"
:label="$t('shared_wallet_id')"
emit-value
map-options
dense
:options="
g.user.extra.wallet_invite_requests.map(i => ({
label: i.to_wallet_name + ' (' + i.from_user_name + ')',
value: i.to_wallet_id
}))
"
class="q-mt-md"
></q-select>
<div v-if="newWallet.walletType == 'lightning-shared'" class="q-mt-md">
<span v-text="$t('shared_wallet_desc')" class="q-mt-lg"></span>
</div>
</q-card-section>
<q-card-actions class="text-primary">
<div class="row full-width">
<div class="col-md-4">
<q-btn
flat
:label="$t('cancel')"
class="float-left"
v-close-popup
></q-btn>
</div>
<div class="col-md-4">
<q-btn
v-if="newWallet.walletType == 'lightning-shared'"
:disabled="!newWallet.sharedWalletId"
flat
:label="$t('reject_wallet')"
v-close-popup
color="negative"
@click="submitRejectWalletInvitation()"
></q-btn>
<span v-else></span>
</div>
<div class="col-md-4">
<q-btn
flat
:label="$t('add_wallet')"
v-close-popup
@click="submitAddWallet()"
class="float-right"
></q-btn>
</div>
</div>
</q-card-actions>
</q-card>
</template>
+4 -29
View File
@@ -6,7 +6,7 @@
<div class="row items-center justify-between q-gutter-xs">
<div class="col">
<q-btn
@click="showAddWalletDialog.show = true"
@click="showNewWalletDialog()"
:label="$t('add_wallet')"
color="primary"
>
@@ -125,35 +125,10 @@
</div>
<q-dialog
v-model="showAddWalletDialog.show"
v-model="addWalletDialog.show"
persistent
@hide="showAddWalletDialog = {show: false}"
@hide="addWalletDialog = {show: false}"
>
<q-card style="min-width: 350px">
<q-card-section>
<div class="text-h6">
<span v-text="$t('wallet_name')"></span>
</div>
</q-card-section>
<q-card-section class="q-pt-none">
<q-input
dense
v-model="showAddWalletDialog.name"
autofocus
@keyup.enter="submitAddWallet()"
></q-input>
</q-card-section>
<q-card-actions align="right" class="text-primary">
<q-btn flat :label="$t('cancel')" v-close-popup></q-btn>
<q-btn
flat
:label="$t('add_wallet')"
v-close-popup
@click="submitAddWallet()"
></q-btn>
</q-card-actions>
</q-card>
<lnbits-new-user-wallet></lnbits-new-user-wallet>
</q-dialog>
</template>