Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
921984e52b | ||
|
|
d0599458c6 | ||
|
|
80b803913f | ||
|
|
6eab3dae01 | ||
|
|
eab19280d5 | ||
|
|
c960f718f5 | ||
|
|
7df131d3c7 | ||
|
|
cae24b233e | ||
|
|
252fd6c313 | ||
|
|
37ac630573 | ||
|
|
035d6263f9 | ||
|
|
0ab1924327 | ||
|
|
127b780af7 | ||
|
|
39066e4bc8 | ||
|
|
ca41a92bd9 | ||
|
|
f97c698917 | ||
|
|
dd1c17f86f | ||
|
|
587b763f03 | ||
|
|
e39241a9e9 | ||
|
|
b6223f0e6d | ||
|
|
6f2771e334 | ||
|
|
3fe33dfb81 | ||
|
|
4ec16b56bf | ||
|
|
662f792d4f | ||
|
|
d8ccb4dcd8 | ||
|
|
7e0beb508c |
@@ -32,11 +32,3 @@ repos:
|
||||
hooks:
|
||||
- id: flake8
|
||||
entry: poetry run flake8
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v0.971
|
||||
hooks:
|
||||
- id: mypy
|
||||
name: mypy
|
||||
entry: poetry run mypy
|
||||
args: [--ignore-missing-imports]
|
||||
additional_dependencies: [types-mock, types-protobuf]
|
||||
|
||||
@@ -18,7 +18,7 @@ A backend wallet can be configured using the following LNbits environment variab
|
||||
- `LNBITS_BACKEND_WALLET_CLASS`: **CoreLightningWallet**
|
||||
- `CORELIGHTNING_RPC`: /file/path/lightning-rpc
|
||||
|
||||
### Spark (c-lightning)
|
||||
### Spark (Core Lightning)
|
||||
|
||||
- `LNBITS_BACKEND_WALLET_CLASS`: **SparkWallet**
|
||||
- `SPARK_URL`: http://10.147.17.230:9737/rpc
|
||||
|
||||
+6
-2
@@ -157,10 +157,14 @@ async def check_installed_extensions(app: FastAPI):
|
||||
installed = check_installed_extension(ext)
|
||||
if not installed:
|
||||
await restore_installed_extension(app, ext)
|
||||
logger.info(f"✔️ Successfully re-installed extension: {ext.id}")
|
||||
logger.info(
|
||||
f"✔️ Successfully re-installed extension: {ext.id} ({ext.installed_version})"
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(e)
|
||||
logger.warning(f"Failed to re-install extension: {ext.id}")
|
||||
logger.warning(
|
||||
f"Failed to re-install extension: {ext.id} ({ext.installed_version})"
|
||||
)
|
||||
|
||||
|
||||
async def build_all_installed_extensions_list() -> List[InstallableExtension]:
|
||||
|
||||
+6
-7
@@ -336,7 +336,7 @@ async def get_latest_payments_by_extension(ext_name: str, ext_id: str, limit: in
|
||||
rows = await db.fetchall(
|
||||
f"""
|
||||
SELECT * FROM apipayments
|
||||
WHERE pending = 'false'
|
||||
WHERE pending = false
|
||||
AND extra LIKE ?
|
||||
AND extra LIKE ?
|
||||
ORDER BY time DESC LIMIT {limit}
|
||||
@@ -426,13 +426,12 @@ async def get_payments(
|
||||
Filters payments to be returned by complete | pending | outgoing | incoming.
|
||||
"""
|
||||
|
||||
if not filters:
|
||||
filters = Filters()
|
||||
filters = filters or Filters()
|
||||
|
||||
if limit:
|
||||
filters.limit = limit
|
||||
if offset:
|
||||
filters.offset = offset
|
||||
filters.sortby = filters.sortby or "time"
|
||||
filters.direction = filters.direction or "desc"
|
||||
filters.limit = limit or filters.limit
|
||||
filters.offset = offset or filters.offset
|
||||
|
||||
page = await get_payments_paginated(
|
||||
wallet_id=wallet_id,
|
||||
|
||||
+11
-2
@@ -166,7 +166,7 @@ async def pay_invoice(
|
||||
assert internal_invoice is not None
|
||||
if (
|
||||
internal_invoice.amount != invoice.amount_msat
|
||||
or internal_invoice.bolt11 != payment_request
|
||||
or internal_invoice.bolt11 != payment_request.lower()
|
||||
):
|
||||
raise PaymentFailure("Invalid invoice.")
|
||||
|
||||
@@ -247,6 +247,15 @@ async def pay_invoice(
|
||||
new_checking_id=payment.checking_id,
|
||||
conn=conn,
|
||||
)
|
||||
wallet = await get_wallet(wallet_id, conn=conn)
|
||||
if wallet:
|
||||
await websocketUpdater(
|
||||
wallet_id,
|
||||
{
|
||||
"wallet_balance": wallet.balance or None,
|
||||
"payment": payment._asdict(),
|
||||
},
|
||||
)
|
||||
logger.debug(f"payment successful {payment.checking_id}")
|
||||
elif payment.checking_id is None and payment.ok is False:
|
||||
# payment failed
|
||||
@@ -482,7 +491,7 @@ def update_cached_settings(sets_dict: dict):
|
||||
try:
|
||||
setattr(settings, key, value)
|
||||
except:
|
||||
logger.error(f"error overriding setting: {key}, value: {value}")
|
||||
logger.warning(f"Failed overriding setting: {key}, value: {value}")
|
||||
if "super_user" in sets_dict:
|
||||
setattr(settings, "super_user", sets_dict["super_user"])
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// update cache version every time there is a new deployment
|
||||
// so the service worker reinitializes the cache
|
||||
const CACHE_VERSION = 8
|
||||
const CACHE_VERSION = 30
|
||||
const CURRENT_CACHE = `lnbits-${CACHE_VERSION}-`
|
||||
|
||||
const getApiKey = request => {
|
||||
|
||||
@@ -145,12 +145,6 @@ new Vue({
|
||||
payments: [],
|
||||
paymentsTable: {
|
||||
columns: [
|
||||
{
|
||||
name: 'memo',
|
||||
align: 'left',
|
||||
label: this.$t('memo'),
|
||||
field: 'memo'
|
||||
},
|
||||
{
|
||||
name: 'time',
|
||||
align: 'left',
|
||||
@@ -158,18 +152,19 @@ new Vue({
|
||||
field: 'date',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
name: 'memo',
|
||||
align: 'left',
|
||||
label: this.$t('memo'),
|
||||
field: 'date',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
name: 'amount',
|
||||
align: 'right',
|
||||
label: this.$t('amount') + ' (' + LNBITS_DENOMINATION + ')',
|
||||
field: 'sat',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
name: 'fee',
|
||||
align: 'right',
|
||||
label: this.$t('fee') + ' (m' + LNBITS_DENOMINATION + ')',
|
||||
field: 'fee'
|
||||
}
|
||||
],
|
||||
pagination: {
|
||||
|
||||
+10
-3
@@ -7,7 +7,7 @@ from loguru import logger
|
||||
from lnbits.tasks import SseListenersDict, register_invoice_listener
|
||||
|
||||
from . import db
|
||||
from .crud import get_balance_notify
|
||||
from .crud import get_balance_notify, get_wallet
|
||||
from .models import Payment
|
||||
from .services import websocketUpdater
|
||||
|
||||
@@ -38,8 +38,15 @@ async def wait_for_paid_invoices(invoice_paid_queue: asyncio.Queue):
|
||||
logger.trace("received invoice paid event")
|
||||
# send information to sse channel
|
||||
await dispatch_api_invoice_listeners(payment)
|
||||
await websocketUpdater(payment.wallet_id, payment.dict())
|
||||
|
||||
wallet = await get_wallet(payment.wallet_id)
|
||||
if wallet:
|
||||
await websocketUpdater(
|
||||
payment.wallet_id,
|
||||
{
|
||||
"wallet_balance": wallet.balance or None,
|
||||
"payment": payment._asdict(),
|
||||
},
|
||||
)
|
||||
# dispatch webhook
|
||||
if payment.webhook and not payment.webhook_status:
|
||||
await dispatch_webhook(payment)
|
||||
|
||||
@@ -1,46 +1,70 @@
|
||||
{% extends "base.html" %} {% from "macros.jinja" import window_vars with context
|
||||
%} {% block scripts %} {{ window_vars(user) }}
|
||||
<script src="/core/static/js/extensions.js"></script>
|
||||
{% endblock %} {% block page %}
|
||||
%} {{ window_vars(user, extensions) }}{% block page %}
|
||||
<div class="row q-col-gutter-md q-mb-md">
|
||||
<div class="col-sm-9 gt-sm col-xs-12 mt-lg">
|
||||
<p class="text-h4">
|
||||
Extensions
|
||||
<q-btn
|
||||
flat
|
||||
color="primary"
|
||||
type="a"
|
||||
:href="['/install?usr=', user.id].join('')"
|
||||
:label="$t('manage_extensions')"
|
||||
></q-btn>
|
||||
</p>
|
||||
<div class="col-sm-9 col-xs-12">
|
||||
<p class="text-h4 gt-sm">{%raw%}{{ $t('extensions') }}{%endraw%}</p>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-12 q-ml-auto">
|
||||
<q-input v-model="searchTerm" label="Search extensions">
|
||||
<q-input v-model="searchTerm" :label="$t('search_extensions')">
|
||||
<q-icon
|
||||
v-if="searchTerm !== ''"
|
||||
name="close"
|
||||
@click="searchTerm = ''"
|
||||
class="cursor-pointer q-mt-lg"
|
||||
class="cursor-pointer"
|
||||
/>
|
||||
</q-input>
|
||||
</div>
|
||||
</div>
|
||||
<p v-if="!filteredExtensions.length" v-text="$t('no_extensions')"></p>
|
||||
|
||||
<div class="row q-col-gutter-md q-mb-md">
|
||||
<div class="col-12">
|
||||
<q-card>
|
||||
<div class="q-pa-xs">
|
||||
<div class="q-gutter-y-md">
|
||||
<q-tabs
|
||||
v-model="tab"
|
||||
@input="handleTabChanged"
|
||||
active-color="primary"
|
||||
align="left"
|
||||
>
|
||||
<q-tab
|
||||
name="installed"
|
||||
:label="$t('installed')"
|
||||
@update="val => tab = val.name"
|
||||
></q-tab>
|
||||
<q-tab
|
||||
name="all"
|
||||
:label="$t('all')"
|
||||
@update="val => tab = val.name"
|
||||
></q-tab>
|
||||
<q-tab
|
||||
name="featured"
|
||||
:label="$t('featured')"
|
||||
@update="val => tab = val.name"
|
||||
></q-tab>
|
||||
<i v-if="!g.user.admin && tab != 'installed'"
|
||||
>{%raw%}{{ $t('only_admins_can_install') }}{%endraw%}</i
|
||||
>
|
||||
</q-tabs>
|
||||
</div>
|
||||
</div>
|
||||
</q-card>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row q-col-gutter-md">
|
||||
<div
|
||||
class="col-6 col-md-4 col-lg-3"
|
||||
v-for="extension in filteredExtensions"
|
||||
:key="extension.code"
|
||||
:key="extension.id + extension.hash"
|
||||
>
|
||||
<q-card>
|
||||
<q-card-section style="min-height: 140px">
|
||||
<q-card-section style="min-height: 140px" class="q-pb-none">
|
||||
<div class="row">
|
||||
<div class="col-3">
|
||||
<q-img
|
||||
v-if="extension.tile"
|
||||
:src="extension.tile"
|
||||
v-if="extension.icon"
|
||||
:src="extension.icon"
|
||||
spinner-color="white"
|
||||
style="max-width: 100%"
|
||||
></q-img>
|
||||
@@ -60,6 +84,16 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-9 q-pl-sm">
|
||||
<q-badge
|
||||
v-if="hasNewVersion(extension)"
|
||||
color="green"
|
||||
class="float-right"
|
||||
>
|
||||
<small>{%raw%}{{ $t('new_version') }}{%endraw%}</small>
|
||||
<q-tooltip
|
||||
><span v-text="extension.latestRelease.version"></span
|
||||
></q-tooltip>
|
||||
</q-badge>
|
||||
{% raw %}
|
||||
<div class="text-h5 gt-sm q-mt-sm q-mb-xs gt-sm">
|
||||
{{ extension.name }}
|
||||
@@ -88,6 +122,21 @@
|
||||
{% endraw %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row q-pt-sm">
|
||||
<div class="col">
|
||||
<small v-if="extension.dependencies?.length"
|
||||
>{%raw%}{{ $t('extension_depends_on') }}{%endraw%}</small
|
||||
>
|
||||
<small v-else> </small>
|
||||
<q-badge
|
||||
v-for="dep in extension.dependencies"
|
||||
:key="dep"
|
||||
color="orange"
|
||||
>
|
||||
<small v-text="dep"></small>
|
||||
</q-badge>
|
||||
</div>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<div>
|
||||
@@ -98,47 +147,490 @@
|
||||
size="1.5em"
|
||||
:max="5"
|
||||
color="primary"
|
||||
></q-rating>
|
||||
><q-tooltip
|
||||
>{%raw%}{{ $t('extension_rating_soon') }}{%endraw%}</q-tooltip
|
||||
></q-rating
|
||||
>
|
||||
<q-rating
|
||||
v-model="maxStars"
|
||||
class="lt-md"
|
||||
size="1.5em"
|
||||
:max="5"
|
||||
color="primary"
|
||||
></q-rating
|
||||
><q-tooltip>Ratings coming soon</q-tooltip>
|
||||
><q-tooltip
|
||||
>{%raw%}{{ $t('extension_rating_soon') }}{%endraw%}</q-tooltip
|
||||
></q-rating
|
||||
>
|
||||
<q-toggle
|
||||
v-if="extension.isAvailable && extension.isInstalled && g.user.admin"
|
||||
:label="extension.isActive ? $t('activated'): $t('deactivated') "
|
||||
color="secodary"
|
||||
style="max-height: 21px"
|
||||
v-model="extension.isActive"
|
||||
@input="toggleExtension(extension)"
|
||||
><q-tooltip
|
||||
>{%raw%}{{ $t('activate_extension_details')
|
||||
}}{%endraw%}</q-tooltip
|
||||
></q-toggle
|
||||
>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-separator></q-separator>
|
||||
<q-card-actions>
|
||||
<div v-if="extension.isEnabled">
|
||||
<q-btn
|
||||
flat
|
||||
color="primary"
|
||||
type="a"
|
||||
:href="[extension.url, '?usr=', g.user.id].join('')"
|
||||
>Open</q-btn
|
||||
<q-card-actions style="min-height: 52px">
|
||||
<div class="col-10">
|
||||
<div v-if="!extension.inProgress">
|
||||
<q-btn
|
||||
v-if="user.extensions.includes(extension.id) && extension.isActive && extension.isInstalled"
|
||||
flat
|
||||
color="primary"
|
||||
type="a"
|
||||
:href="[extension.id, '?usr=', g.user.id].join('')"
|
||||
>{%raw%}{{ $t('open') }}{%endraw%}</q-btn
|
||||
>
|
||||
<q-btn
|
||||
v-if="user.extensions.includes(extension.id) && extension.isActive && extension.isInstalled"
|
||||
flat
|
||||
color="grey-5"
|
||||
type="a"
|
||||
:href="['{{
|
||||
url_for('install.extensions')
|
||||
}}', '?usr=', g.user.id, '&disable=', extension.id].join('')"
|
||||
>
|
||||
{%raw%}{{ $t('disable') }}{%endraw%}</q-btn
|
||||
>
|
||||
<q-btn
|
||||
v-if="extension.isInstalled && !user.extensions.includes(extension.id) && extension.isActive"
|
||||
flat
|
||||
color="primary"
|
||||
type="a"
|
||||
:href="['{{
|
||||
url_for('install.extensions')
|
||||
}}', '?usr=', g.user.id, '&enable=', extension.id].join('')"
|
||||
>
|
||||
{%raw%}{{ $t('enable') }}{%endraw%}
|
||||
<q-tooltip>
|
||||
<span v-text="$t('enable_extension_details')">
|
||||
</span> </q-tooltip
|
||||
></q-btn>
|
||||
|
||||
<q-btn
|
||||
@click="showUpgrade(extension)"
|
||||
flat
|
||||
color="primary"
|
||||
v-if="g.user.admin"
|
||||
>
|
||||
{%raw%}{{ $t('manage') }}{%endraw%}<q-tooltip
|
||||
>{%raw%}{{ $t('manage_extension_details')
|
||||
}}{%endraw%}</q-tooltip
|
||||
></q-btn
|
||||
>
|
||||
</div>
|
||||
<div v-else>
|
||||
<q-spinner color="primary" size="2.55em"></q-spinner>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-2">
|
||||
<div
|
||||
v-if="extension.isInstalled && extension.installedRelease"
|
||||
class="float-right"
|
||||
>
|
||||
<q-btn
|
||||
flat
|
||||
color="grey-5"
|
||||
type="a"
|
||||
:href="['{{ url_for('core.extensions') }}', '?usr=', g.user.id, '&disable=', extension.code].join('')"
|
||||
>
|
||||
Disable</q-btn
|
||||
>
|
||||
<q-badge>
|
||||
{% raw %}{{ extension.installedRelease.version }}{% endraw
|
||||
%}<q-tooltip
|
||||
>{%raw%}{{ $t('extension_installed_version')
|
||||
}}{%endraw%}</q-tooltip
|
||||
>
|
||||
</q-badge>
|
||||
</div>
|
||||
</div>
|
||||
<q-btn
|
||||
v-else
|
||||
flat
|
||||
color="primary"
|
||||
type="a"
|
||||
:href="['{{ url_for('core.extensions') }}', '?usr=', g.user.id, '&enable=', extension.code].join('')"
|
||||
>
|
||||
Enable</q-btn
|
||||
>
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
</div>
|
||||
<q-dialog v-model="showUninstallDialog">
|
||||
<q-card class="q-pa-lg">
|
||||
<h6 class="q-my-md text-primary">{%raw%}{{ $t('warning') }}{%endraw%}</h6>
|
||||
<p>
|
||||
{%raw%}{{ $t('extension_uninstall_warning') }}{%endraw%} <br />
|
||||
{%raw%}{{ $t('confirm_continue') }}{%endraw%}
|
||||
</p>
|
||||
|
||||
<div class="row q-mt-lg">
|
||||
<q-btn outline color="grey" @click="uninstallExtension()"
|
||||
>{%raw%}{{ $t('uninstall_confirm') }}{%endraw%}</q-btn
|
||||
>
|
||||
<q-btn v-close-popup flat color="grey" class="q-ml-auto"
|
||||
>{%raw%}{{ $t('cancel') }}{%endraw%}</q-btn
|
||||
>
|
||||
</div>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
|
||||
<q-dialog v-model="showUpgradeDialog">
|
||||
<q-card class="q-pa-lg lnbits__dialog-card">
|
||||
<q-card-section>
|
||||
<div class="text-h6" v-text="selectedExtension?.name"></div>
|
||||
</q-card-section>
|
||||
<div class="col-12 col-md-5 q-gutter-y-md" v-if="selectedExtensionRepos">
|
||||
<q-card
|
||||
flat
|
||||
bordered
|
||||
class="my-card"
|
||||
v-for="repoName of Object.keys(selectedExtensionRepos)"
|
||||
:key="repoName"
|
||||
>
|
||||
<q-expansion-item
|
||||
:key="repoName"
|
||||
group="repos"
|
||||
:caption="repoName"
|
||||
:content-inset-level="0.5"
|
||||
:default-opened="selectedExtensionRepos[repoName].isInstalled"
|
||||
>
|
||||
<template v-slot:header>
|
||||
<q-item-section avatar>
|
||||
<q-avatar
|
||||
:icon="selectedExtensionRepos[repoName].isInstalled ? 'download_done': 'download'"
|
||||
:text-color="selectedExtensionRepos[repoName].isInstalled ? 'green' : ''"
|
||||
/>
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section>
|
||||
<div class="row">
|
||||
<div class="col-10">
|
||||
{%raw%}{{ $t('repository') }}{%endraw%}
|
||||
<br />
|
||||
<small v-text="repoName"></small>
|
||||
</div>
|
||||
<div class="col-2"></div>
|
||||
</div>
|
||||
</q-item-section>
|
||||
</template>
|
||||
|
||||
<q-card-section class="q-pa-none">
|
||||
<q-separator></q-separator>
|
||||
|
||||
<q-list>
|
||||
<q-expansion-item
|
||||
v-for="release of selectedExtensionRepos[repoName].releases"
|
||||
:key="release.version"
|
||||
group="releases"
|
||||
@click="getGitHubReleaseDetails(release)"
|
||||
:icon="getReleaseIcon(release)"
|
||||
:label="release.description"
|
||||
:caption="release.version"
|
||||
:content-inset-level="0.5"
|
||||
:header-class="getReleaseIconColor(release)"
|
||||
>
|
||||
<div v-if="release.inProgress">
|
||||
<q-spinner color="primary" size="2.55em"></q-spinner>
|
||||
</div>
|
||||
<div v-else-if="release.error">
|
||||
<q-icon
|
||||
class="gt-sm"
|
||||
name="error"
|
||||
color="pink"
|
||||
size="70px"
|
||||
></q-icon>
|
||||
Cannot get the release details.
|
||||
</div>
|
||||
<q-card v-else>
|
||||
<q-card-section v-if="release.is_version_compatible">
|
||||
<q-btn
|
||||
v-if="!release.isInstalled"
|
||||
@click="installExtension(release)"
|
||||
color="primary unelevated mt-lg pt-lg"
|
||||
>{%raw%}{{ $t('install') }}{%endraw%}</q-btn
|
||||
>
|
||||
<q-btn v-else @click="showUninstall()" flat color="red">
|
||||
{%raw%}{{ $t('uninstall') }}{%endraw%}</q-btn
|
||||
>
|
||||
<a
|
||||
v-if="release.html_url"
|
||||
class="text-secondary float-right"
|
||||
:href="release.html_url"
|
||||
target="_blank"
|
||||
style="color: inherit"
|
||||
>{%raw%}{{ $t('release_notes') }}{%endraw%}</a
|
||||
>
|
||||
</q-card-section>
|
||||
<q-card-section v-else>
|
||||
{%raw%}{{ $t('extension_min_lnbits_version') }}{%endraw%}
|
||||
<strong>
|
||||
<span v-text="release.min_lnbits_version"></span>
|
||||
</strong>
|
||||
</q-card-section>
|
||||
<q-card v-if="release.warning">
|
||||
<q-card-section>
|
||||
<div class="text-h6">
|
||||
<q-badge color="yellow" text-color="black">
|
||||
{%raw%}{{ $t('warning') }}{%endraw%}
|
||||
</q-badge>
|
||||
</div>
|
||||
<div class="text-subtitle2">
|
||||
<span v-text="release.warning"></span>
|
||||
</div>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
|
||||
<q-separator></q-separator> </q-card
|
||||
></q-expansion-item>
|
||||
</q-list>
|
||||
</q-card-section>
|
||||
</q-expansion-item>
|
||||
</q-card>
|
||||
</div>
|
||||
<q-spinner v-else color="primary" size="2.55em"></q-spinner>
|
||||
<div class="row q-mt-lg">
|
||||
<q-btn
|
||||
v-if="selectedExtension?.isInstalled"
|
||||
@click="showUninstall()"
|
||||
flat
|
||||
color="red"
|
||||
>
|
||||
{%raw%}{{ $t('uninstall') }}{%endraw%}</q-btn
|
||||
>
|
||||
<q-btn v-close-popup flat color="grey" class="q-ml-auto">
|
||||
{%raw%}{{ $t('close') }}{%endraw%}</q-btn
|
||||
>
|
||||
</div>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</div>
|
||||
{% endblock %} {% block scripts %} {{ window_vars(user) }}
|
||||
<script>
|
||||
new Vue({
|
||||
el: '#vue',
|
||||
data: function () {
|
||||
return {
|
||||
searchTerm: '',
|
||||
tab: 'all',
|
||||
filteredExtensions: null,
|
||||
showUninstallDialog: false,
|
||||
showUpgradeDialog: false,
|
||||
selectedExtension: null,
|
||||
selectedExtensionRepos: null,
|
||||
maxStars: 5,
|
||||
user: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
searchTerm(term) {
|
||||
this.filterExtensions(term, this.tab)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleTabChanged: function (tab) {
|
||||
this.filterExtensions(this.searchTerm, tab)
|
||||
},
|
||||
filterExtensions: function (term, tab) {
|
||||
// Filter the extensions list
|
||||
function extensionNameContains(searchTerm) {
|
||||
return function (extension) {
|
||||
return (
|
||||
extension.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
extension.shortDescription
|
||||
?.toLowerCase()
|
||||
.includes(searchTerm.toLowerCase())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
this.filteredExtensions = this.extensions
|
||||
.filter(e => (tab === 'installed' ? e.isInstalled : true))
|
||||
.filter(e =>
|
||||
tab === 'installed'
|
||||
? e.isActive
|
||||
? true
|
||||
: !!this.g.user.admin
|
||||
: true
|
||||
)
|
||||
.filter(e => (tab === 'featured' ? e.isFeatured : true))
|
||||
.filter(extensionNameContains(term))
|
||||
this.tab = tab
|
||||
},
|
||||
installExtension: async function (release) {
|
||||
const extension = this.selectedExtension
|
||||
extension.inProgress = true
|
||||
this.showUpgradeDialog = false
|
||||
LNbits.api
|
||||
.request(
|
||||
'POST',
|
||||
`/api/v1/extension?usr=${this.g.user.id}`,
|
||||
this.g.user.wallets[0].adminkey,
|
||||
{
|
||||
ext_id: extension.id,
|
||||
archive: release.archive,
|
||||
source_repo: release.source_repo
|
||||
}
|
||||
)
|
||||
.then(response => {
|
||||
extension.isAvailable = true
|
||||
extension.isInstalled = true
|
||||
extension.installedRelease = release
|
||||
this.toggleExtension(extension)
|
||||
extension.inProgress = false
|
||||
this.filteredExtensions = this.extensions.concat([])
|
||||
this.handleTabChanged('installed')
|
||||
this.tab = 'installed'
|
||||
})
|
||||
.catch(err => {
|
||||
LNbits.utils.notifyApiError(err)
|
||||
extension.inProgress = false
|
||||
})
|
||||
},
|
||||
uninstallExtension: async function () {
|
||||
const extension = this.selectedExtension
|
||||
this.showUpgradeDialog = false
|
||||
this.showUninstallDialog = false
|
||||
extension.inProgress = true
|
||||
LNbits.api
|
||||
.request(
|
||||
'DELETE',
|
||||
`/api/v1/extension/${extension.id}?usr=${this.g.user.id}`,
|
||||
this.g.user.wallets[0].adminkey
|
||||
)
|
||||
.then(response => {
|
||||
extension.isAvailable = false
|
||||
extension.isInstalled = false
|
||||
extension.inProgress = false
|
||||
extension.installedRelease = null
|
||||
this.filteredExtensions = this.extensions.concat([])
|
||||
this.handleTabChanged('installed')
|
||||
this.tab = 'installed'
|
||||
})
|
||||
.catch(err => {
|
||||
LNbits.utils.notifyApiError(err)
|
||||
extension.inProgress = false
|
||||
})
|
||||
},
|
||||
toggleExtension: function (extension) {
|
||||
const action = extension.isActive ? 'activate' : 'deactivate'
|
||||
LNbits.api
|
||||
.request(
|
||||
'GET',
|
||||
"{{ url_for('install.extensions') }}?usr=" +
|
||||
this.g.user.id +
|
||||
'&' +
|
||||
action +
|
||||
'=' +
|
||||
extension.id
|
||||
)
|
||||
.then(response => {})
|
||||
.catch(err => {
|
||||
LNbits.utils.notifyApiError(err)
|
||||
extension.inProgress = false
|
||||
})
|
||||
},
|
||||
|
||||
showUninstall: function () {
|
||||
this.showUpgradeDialog = false
|
||||
this.showUninstallDialog = true
|
||||
},
|
||||
|
||||
showUpgrade: async function (extension) {
|
||||
this.selectedExtension = extension
|
||||
this.showUpgradeDialog = true
|
||||
this.selectedExtensionRepos = null
|
||||
try {
|
||||
const {data} = await LNbits.api.request(
|
||||
'GET',
|
||||
`/api/v1/extension/${extension.id}/releases?usr=${this.g.user.id}`,
|
||||
this.g.user.wallets[0].adminkey
|
||||
)
|
||||
|
||||
this.selectedExtensionRepos = data.reduce((repos, release) => {
|
||||
repos[release.source_repo] = repos[release.source_repo] || {
|
||||
releases: [],
|
||||
isInstalled: false
|
||||
}
|
||||
release.inProgress = false
|
||||
release.error = null
|
||||
release.loaded = false
|
||||
release.isInstalled = this.isInstalledVersion(
|
||||
this.selectedExtension,
|
||||
release
|
||||
)
|
||||
if (release.isInstalled) {
|
||||
repos[release.source_repo].isInstalled = true
|
||||
}
|
||||
repos[release.source_repo].releases.push(release)
|
||||
return repos
|
||||
}, {})
|
||||
} catch (error) {
|
||||
LNbits.utils.notifyApiError(error)
|
||||
extension.inProgress = false
|
||||
}
|
||||
},
|
||||
hasNewVersion: function (extension) {
|
||||
if (extension.installedRelease && extension.latestRelease) {
|
||||
return (
|
||||
extension.installedRelease.version !==
|
||||
extension.latestRelease.version
|
||||
)
|
||||
}
|
||||
},
|
||||
isInstalledVersion: function (extension, release) {
|
||||
if (extension.installedRelease) {
|
||||
return (
|
||||
extension.installedRelease.source_repo === release.source_repo &&
|
||||
extension.installedRelease.version === release.version
|
||||
)
|
||||
}
|
||||
},
|
||||
getReleaseIcon: function (release) {
|
||||
if (!release.is_version_compatible) return 'block'
|
||||
if (release.isInstalled) return 'download_done'
|
||||
|
||||
return 'download'
|
||||
},
|
||||
getReleaseIconColor: function (release) {
|
||||
if (!release.is_version_compatible) return 'text-red'
|
||||
if (release.isInstalled) return 'text-green'
|
||||
|
||||
return ''
|
||||
},
|
||||
getGitHubReleaseDetails: async function (release) {
|
||||
if (!release.is_github_release || release.loaded) {
|
||||
return
|
||||
}
|
||||
const [org, repo] = release.source_repo.split('/')
|
||||
release.inProgress = true
|
||||
try {
|
||||
const {data} = await LNbits.api.request(
|
||||
'GET',
|
||||
`/api/v1/extension/release/${org}/${repo}/${release.version}?usr=${this.g.user.id}`,
|
||||
this.g.user.wallets[0].adminkey
|
||||
)
|
||||
release.loaded = true
|
||||
release.is_version_compatible = data.is_version_compatible
|
||||
release.min_lnbits_version = data.min_lnbits_version
|
||||
release.warning = data.warning
|
||||
} catch (error) {
|
||||
console.warn(error)
|
||||
release.error = error
|
||||
LNbits.utils.notifyApiError(error)
|
||||
} finally {
|
||||
release.inProgress = false
|
||||
}
|
||||
}
|
||||
},
|
||||
created: function () {
|
||||
this.extensions = JSON.parse('{{extensions | tojson | safe}}').map(e => ({
|
||||
...e,
|
||||
inProgress: false
|
||||
}))
|
||||
this.filteredExtensions = this.extensions.concat([])
|
||||
for (let i = 0; i < this.filteredExtensions.length; i++) {
|
||||
if (this.filteredExtensions[i].isInstalled != false) {
|
||||
this.handleTabChanged('installed')
|
||||
this.tab = 'installed'
|
||||
}
|
||||
}
|
||||
if (window.user) {
|
||||
this.user = LNbits.map.user(window.user)
|
||||
}
|
||||
},
|
||||
mixins: [windowMixin]
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -150,6 +150,17 @@
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<a href="https://voltage.cloud">
|
||||
<q-img
|
||||
contain
|
||||
:src="($q.dark.isActive) ? '/static/images/voltage.png' : '/static/images/voltagel.png'"
|
||||
></q-img>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col q-pl-md"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if AD_SPACE %} {% for ADS in AD_SPACE %} {% set AD = ADS.split(';') %}
|
||||
|
||||
@@ -1,505 +0,0 @@
|
||||
{% extends "base.html" %} {% from "macros.jinja" import window_vars with context
|
||||
%} {{ window_vars(user, extensions) }}{% block page %}
|
||||
<div class="row q-col-gutter-md q-mb-md">
|
||||
<div class="col-sm-9 col-xs-12">
|
||||
<p class="text-h4 gt-sm">Manage Extensions</p>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-12 q-ml-auto">
|
||||
<q-input v-model="searchTerm" label="Search extensions">
|
||||
<q-icon
|
||||
v-if="searchTerm !== ''"
|
||||
name="close"
|
||||
@click="searchTerm = ''"
|
||||
class="cursor-pointer"
|
||||
/>
|
||||
</q-input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row q-col-gutter-md q-mb-md">
|
||||
<div class="col-12">
|
||||
<q-card>
|
||||
<div class="q-pa-xs">
|
||||
<div class="q-gutter-y-md">
|
||||
<q-tabs
|
||||
v-model="tab"
|
||||
@input="handleTabChanged"
|
||||
active-color="primary"
|
||||
align="left"
|
||||
>
|
||||
<q-tab
|
||||
name="installed"
|
||||
label="Installed"
|
||||
@update="val => tab = val.name"
|
||||
></q-tab>
|
||||
<q-tab
|
||||
name="all"
|
||||
label="All"
|
||||
@update="val => tab = val.name"
|
||||
></q-tab>
|
||||
<q-tab
|
||||
name="featured"
|
||||
label="Featured"
|
||||
@update="val => tab = val.name"
|
||||
></q-tab>
|
||||
</q-tabs>
|
||||
</div>
|
||||
</div>
|
||||
</q-card>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row q-col-gutter-md">
|
||||
<div
|
||||
class="col-6 col-md-4 col-lg-3"
|
||||
v-for="extension in filteredExtensions"
|
||||
:key="extension.id + extension.hash"
|
||||
>
|
||||
<q-card>
|
||||
<q-card-section style="min-height: 140px">
|
||||
<div class="row">
|
||||
<div class="col-3">
|
||||
<q-img
|
||||
v-if="extension.icon"
|
||||
:src="extension.icon"
|
||||
spinner-color="white"
|
||||
style="max-width: 100%"
|
||||
></q-img>
|
||||
<div v-else>
|
||||
<q-icon
|
||||
class="gt-sm"
|
||||
name="extension"
|
||||
color="primary"
|
||||
size="70px"
|
||||
></q-icon>
|
||||
<q-icon
|
||||
class="lt-md"
|
||||
name="extension"
|
||||
color="primary"
|
||||
size="35px"
|
||||
></q-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-9 q-pl-sm">
|
||||
<q-badge
|
||||
v-if="hasNewVersion(extension)"
|
||||
color="green"
|
||||
class="float-right"
|
||||
>
|
||||
<small>New Version</small>
|
||||
</q-badge>
|
||||
{% raw %}
|
||||
<div class="text-h5 gt-sm q-mt-sm q-mb-xs gt-sm">
|
||||
{{ extension.name }}
|
||||
</div>
|
||||
<div
|
||||
class="text-h5 gt-sm q-mt-sm q-mb-xs lt-md"
|
||||
style="min-height: 60px"
|
||||
>
|
||||
{{ extension.name }}
|
||||
</div>
|
||||
<div
|
||||
class="text-subtitle2 gt-sm"
|
||||
style="font-size: 11px; height: 34px"
|
||||
>
|
||||
{{ extension.shortDescription }}
|
||||
</div>
|
||||
<div class="text-subtitle1 lt-md q-mt-sm q-mb-xs">
|
||||
{{ extension.name }}
|
||||
</div>
|
||||
<div
|
||||
class="text-subtitle2 lt-md"
|
||||
style="font-size: 9px; height: 34px"
|
||||
>
|
||||
{{ extension.shortDescription }}
|
||||
</div>
|
||||
{% endraw %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row q-pt-sm">
|
||||
<div class="col">
|
||||
<small v-if="extension.dependencies?.length">Depends on:</small>
|
||||
<small v-else> </small>
|
||||
<q-badge
|
||||
v-for="dep in extension.dependencies"
|
||||
:key="dep"
|
||||
color="orange"
|
||||
>
|
||||
<small v-text="dep"></small>
|
||||
</q-badge>
|
||||
</div>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<div>
|
||||
<q-rating
|
||||
class="gt-sm"
|
||||
v-model="maxStars"
|
||||
disable
|
||||
size="1.5em"
|
||||
:max="5"
|
||||
color="primary"
|
||||
></q-rating>
|
||||
<q-rating
|
||||
v-model="maxStars"
|
||||
class="lt-md"
|
||||
size="1.5em"
|
||||
:max="5"
|
||||
color="primary"
|
||||
></q-rating
|
||||
><q-tooltip>Ratings coming soon</q-tooltip>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-separator v-if="g.user.admin"></q-separator>
|
||||
<q-card-actions>
|
||||
<div class="col-10">
|
||||
<div v-if="g.user.admin">
|
||||
<div v-if="!extension.inProgress">
|
||||
<q-btn @click="showUpgrade(extension)" flat color="primary">
|
||||
Manage</q-btn
|
||||
>
|
||||
<q-toggle
|
||||
v-if="extension.isAvailable && extension.isInstalled"
|
||||
:label="extension.isActive ? 'Activated': 'Deactivated' "
|
||||
color="secodary"
|
||||
v-model="extension.isActive"
|
||||
@input="toggleExtension(extension)"
|
||||
></q-toggle>
|
||||
</div>
|
||||
<div v-else>
|
||||
<q-spinner color="primary" size="2.55em"></q-spinner>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-2">
|
||||
<div class="float-right"></div>
|
||||
</div>
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
</div>
|
||||
<q-dialog v-model="showUninstallDialog">
|
||||
<q-card class="q-pa-lg">
|
||||
<h6 class="q-my-md text-primary">Warning</h6>
|
||||
<p>
|
||||
You are about to remove the extension for all users. <br />
|
||||
Are you sure you want to continue?
|
||||
</p>
|
||||
|
||||
<div class="row q-mt-lg">
|
||||
<q-btn outline color="grey" @click="uninstallExtension()"
|
||||
>Yes, Uninstall</q-btn
|
||||
>
|
||||
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Cancel</q-btn>
|
||||
</div>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
|
||||
<q-dialog v-model="showUpgradeDialog">
|
||||
<q-card class="q-pa-lg lnbits__dialog-card">
|
||||
<q-card-section>
|
||||
<div class="text-h6" v-text="selectedExtension?.name"></div>
|
||||
</q-card-section>
|
||||
<div class="col-12 col-md-5 q-gutter-y-md" v-if="selectedExtensionRepos">
|
||||
<q-card
|
||||
flat
|
||||
bordered
|
||||
class="my-card"
|
||||
v-for="repoName of Object.keys(selectedExtensionRepos)"
|
||||
:key="repoName"
|
||||
>
|
||||
<q-expansion-item
|
||||
:key="repoName"
|
||||
group="repos"
|
||||
:caption="repoName"
|
||||
:content-inset-level="0.5"
|
||||
:default-opened="selectedExtensionRepos[repoName].isInstalled"
|
||||
>
|
||||
<template v-slot:header>
|
||||
<q-item-section avatar>
|
||||
<q-avatar
|
||||
:icon="selectedExtensionRepos[repoName].isInstalled ? 'download_done': 'download'"
|
||||
:text-color="selectedExtensionRepos[repoName].isInstalled ? 'green' : ''"
|
||||
/>
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section>
|
||||
<div class="row">
|
||||
<div class="col-10">
|
||||
Repository
|
||||
<br />
|
||||
<small v-text="repoName"></small>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<!-- <div v-if="selectedExtension.stars" class="float-right">
|
||||
<small v-text="selectedExtension.stars"> </small>
|
||||
<q-rating
|
||||
max="1"
|
||||
v-model="maxStars"
|
||||
size="1.5em"
|
||||
color="yellow"
|
||||
icon="star"
|
||||
icon-selected="star"
|
||||
readonly
|
||||
no-dimming
|
||||
>
|
||||
</q-rating>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</q-item-section>
|
||||
</template>
|
||||
|
||||
<q-card-section class="q-pa-none">
|
||||
<q-separator></q-separator>
|
||||
|
||||
<q-list>
|
||||
<q-expansion-item
|
||||
v-for="release of selectedExtensionRepos[repoName].releases"
|
||||
:key="release.version"
|
||||
group="releases"
|
||||
:icon="release.isInstalled ? 'download_done' : 'download'"
|
||||
:label="release.description"
|
||||
:caption="release.version"
|
||||
:content-inset-level="0.5"
|
||||
:header-class="release.isInstalled ? 'text-green' : ''"
|
||||
>
|
||||
<q-card>
|
||||
<q-card-section>
|
||||
<q-btn
|
||||
v-if="!release.isInstalled"
|
||||
@click="installExtension(release)"
|
||||
color="primary unelevated mt-lg pt-lg"
|
||||
>Install</q-btn
|
||||
>
|
||||
<q-btn v-else @click="showUninstall()" flat color="red">
|
||||
Uninstall</q-btn
|
||||
>
|
||||
<a
|
||||
v-if="release.html_url"
|
||||
class="text-secondary float-right"
|
||||
:href="release.html_url"
|
||||
target="_blank"
|
||||
style="color: inherit"
|
||||
>Release Notes</a
|
||||
>
|
||||
</q-card-section>
|
||||
|
||||
<div
|
||||
v-if="release.details_html"
|
||||
v-html="release.details_html"
|
||||
></div>
|
||||
<q-separator></q-separator> </q-card
|
||||
></q-expansion-item>
|
||||
</q-list>
|
||||
</q-card-section>
|
||||
</q-expansion-item>
|
||||
</q-card>
|
||||
</div>
|
||||
<q-spinner v-else color="primary" size="2.55em"></q-spinner>
|
||||
<div class="row q-mt-lg">
|
||||
<q-btn
|
||||
v-if="selectedExtension?.isInstalled"
|
||||
@click="showUninstall()"
|
||||
flat
|
||||
color="red"
|
||||
>
|
||||
Uninstall</q-btn
|
||||
>
|
||||
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Close</q-btn>
|
||||
</div>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</div>
|
||||
{% endblock %} {% block scripts %} {{ window_vars(user) }}
|
||||
<script>
|
||||
new Vue({
|
||||
el: '#vue',
|
||||
data: function () {
|
||||
return {
|
||||
searchTerm: '',
|
||||
tab: 'all',
|
||||
filteredExtensions: null,
|
||||
showUninstallDialog: false,
|
||||
showUpgradeDialog: false,
|
||||
selectedExtension: null,
|
||||
selectedExtensionRepos: null,
|
||||
maxStars: 5
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
searchTerm(term) {
|
||||
this.filterExtensions(term, this.tab)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleTabChanged: function (tab) {
|
||||
this.filterExtensions(this.searchTerm, tab)
|
||||
},
|
||||
filterExtensions: function (term, tab) {
|
||||
// Filter the extensions list
|
||||
function extensionNameContains(searchTerm) {
|
||||
return function (extension) {
|
||||
return (
|
||||
extension.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
extension.shortDescription
|
||||
?.toLowerCase()
|
||||
.includes(searchTerm.toLowerCase())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
this.filteredExtensions = this.extensions
|
||||
.filter(e => (tab === 'installed' ? e.isInstalled : true))
|
||||
.filter(e => (tab === 'featured' ? e.isFeatured : true))
|
||||
.filter(extensionNameContains(term))
|
||||
},
|
||||
installExtension: async function (release) {
|
||||
const extension = this.selectedExtension
|
||||
extension.inProgress = true
|
||||
this.showUpgradeDialog = false
|
||||
LNbits.api
|
||||
.request(
|
||||
'POST',
|
||||
`/api/v1/extension?usr=${this.g.user.id}`,
|
||||
this.g.user.wallets[0].adminkey,
|
||||
{
|
||||
ext_id: extension.id,
|
||||
archive: release.archive,
|
||||
source_repo: release.source_repo
|
||||
}
|
||||
)
|
||||
.then(response => {
|
||||
extension.isAvailable = true
|
||||
extension.isInstalled = true
|
||||
this.toggleExtension(extension)
|
||||
extension.inProgress = false
|
||||
this.filteredExtensions = this.extensions.concat([])
|
||||
this.handleTabChanged('installed')
|
||||
this.tab = 'installed'
|
||||
})
|
||||
.catch(err => {
|
||||
LNbits.utils.notifyApiError(err)
|
||||
extension.inProgress = false
|
||||
})
|
||||
},
|
||||
uninstallExtension: async function () {
|
||||
const extension = this.selectedExtension
|
||||
this.showUpgradeDialog = false
|
||||
this.showUninstallDialog = false
|
||||
extension.inProgress = true
|
||||
LNbits.api
|
||||
.request(
|
||||
'DELETE',
|
||||
`/api/v1/extension/${extension.id}?usr=${this.g.user.id}`,
|
||||
this.g.user.wallets[0].adminkey
|
||||
)
|
||||
.then(response => {
|
||||
extension.isAvailable = false
|
||||
extension.isInstalled = false
|
||||
extension.inProgress = false
|
||||
this.filteredExtensions = this.extensions.concat([])
|
||||
this.handleTabChanged('installed')
|
||||
this.tab = 'installed'
|
||||
})
|
||||
.catch(err => {
|
||||
LNbits.utils.notifyApiError(err)
|
||||
extension.inProgress = false
|
||||
})
|
||||
},
|
||||
toggleExtension: function (extension) {
|
||||
const action = extension.isActive ? 'activate' : 'deactivate'
|
||||
LNbits.api
|
||||
.request(
|
||||
'GET',
|
||||
"{{ url_for('install.extensions') }}?usr=" +
|
||||
this.g.user.id +
|
||||
'&' +
|
||||
action +
|
||||
'=' +
|
||||
extension.id
|
||||
)
|
||||
.then(response => {})
|
||||
.catch(err => {
|
||||
LNbits.utils.notifyApiError(err)
|
||||
extension.inProgress = false
|
||||
})
|
||||
},
|
||||
|
||||
showUninstall: function () {
|
||||
this.showUpgradeDialog = false
|
||||
this.showUninstallDialog = true
|
||||
},
|
||||
|
||||
showUpgrade: async function (extension) {
|
||||
this.selectedExtension = extension
|
||||
this.showUpgradeDialog = true
|
||||
this.selectedExtensionRepos = null
|
||||
try {
|
||||
const {data} = await LNbits.api.request(
|
||||
'GET',
|
||||
`/api/v1/extension/${extension.id}/releases?usr=${this.g.user.id}`,
|
||||
this.g.user.wallets[0].adminkey
|
||||
)
|
||||
|
||||
this.selectedExtensionRepos = data.reduce((repos, release) => {
|
||||
repos[release.source_repo] = repos[release.source_repo] || {
|
||||
releases: [],
|
||||
isInstalled: false
|
||||
}
|
||||
release.isInstalled = this.isInstalledVersion(
|
||||
this.selectedExtension,
|
||||
release
|
||||
)
|
||||
if (release.isInstalled) {
|
||||
repos[release.source_repo].isInstalled = true
|
||||
}
|
||||
repos[release.source_repo].releases.push(release)
|
||||
return repos
|
||||
}, {})
|
||||
} catch (error) {
|
||||
LNbits.utils.notifyApiError(error)
|
||||
extension.inProgress = false
|
||||
}
|
||||
},
|
||||
hasNewVersion: function (extension) {
|
||||
if (extension.installedRelease && extension.latestRelease) {
|
||||
return (
|
||||
extension.installedRelease.version !==
|
||||
extension.latestRelease.version
|
||||
)
|
||||
}
|
||||
},
|
||||
isInstalledVersion: function (extension, release) {
|
||||
if (extension.installedRelease) {
|
||||
return (
|
||||
extension.installedRelease.source_repo === release.source_repo &&
|
||||
extension.installedRelease.version === release.version
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
created: function () {
|
||||
if (!this.g.user.admin) {
|
||||
this.$q.notify({
|
||||
timeout: 3000,
|
||||
message: 'Only admin accounts can install extensions',
|
||||
icon: null
|
||||
})
|
||||
}
|
||||
this.extensions = JSON.parse('{{extensions | tojson | safe}}').map(e => ({
|
||||
...e,
|
||||
inProgress: false
|
||||
}))
|
||||
this.filteredExtensions = this.extensions.concat([])
|
||||
for (let i = 0; i < this.filteredExtensions.length; i++) {
|
||||
if (this.filteredExtensions[i].isInstalled != false) {
|
||||
this.handleTabChanged('installed')
|
||||
this.tab = 'installed'
|
||||
}
|
||||
}
|
||||
},
|
||||
mixins: [windowMixin]
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -149,7 +149,6 @@
|
||||
{% raw %}
|
||||
<template v-slot:header="props">
|
||||
<q-tr :props="props">
|
||||
<q-th auto-width></q-th>
|
||||
<q-th v-for="col in props.cols" :key="col.name" :props="props"
|
||||
>{{ col.label }}</q-th
|
||||
>
|
||||
@@ -192,11 +191,11 @@
|
||||
</a>
|
||||
</q-badge>
|
||||
{{ props.row.memo }}
|
||||
</q-td>
|
||||
<q-td auto-width key="time" :props="props">
|
||||
<br />
|
||||
<q-tooltip>{{ props.row.date }}</q-tooltip>
|
||||
{{ props.row.dateFrom }}
|
||||
<i> {{ props.row.dateFrom }}</i>
|
||||
</q-td>
|
||||
|
||||
{% endraw %}
|
||||
<q-td
|
||||
auto-width
|
||||
@@ -209,10 +208,8 @@
|
||||
</q-td>
|
||||
|
||||
<q-td auto-width key="amount" v-else :props="props">
|
||||
{{ props.row.fsat }}
|
||||
</q-td>
|
||||
<q-td auto-width key="fee" :props="props">
|
||||
{{ props.row.fee }}
|
||||
{{ props.row.fsat }}<br />
|
||||
<i>fee {{ props.row.fee }}</i>
|
||||
</q-td>
|
||||
</q-tr>
|
||||
|
||||
@@ -552,7 +549,7 @@
|
||||
</h6>
|
||||
<q-separator class="q-my-sm"></q-separator>
|
||||
<p class="text-wrap">
|
||||
<strong v-text="$t('description')">:</strong> {{
|
||||
<strong v-text="$t('memo')">:</strong> {{
|
||||
parse.invoice.description }}<br />
|
||||
<strong>Expire date:</strong> {{ parse.invoice.expireDate }}<br />
|
||||
<strong>Hash:</strong> {{ parse.invoice.hash }}
|
||||
@@ -779,23 +776,27 @@
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
|
||||
<q-tabs
|
||||
class="lt-md fixed-bottom left-0 right-0 bg-primary text-white shadow-2 z-top"
|
||||
active-class="px-0"
|
||||
indicator-color="transparent"
|
||||
align="justify"
|
||||
>
|
||||
<q-tab
|
||||
icon="account_balance_wallet"
|
||||
label="Wallets"
|
||||
@click="g.visibleDrawer = !g.visibleDrawer"
|
||||
>
|
||||
</q-tab>
|
||||
<q-tab icon="content_paste" label="Paste" @click="showParseDialog">
|
||||
</q-tab>
|
||||
<q-tab icon="file_download" label="Receive" @click="showReceiveDialog">
|
||||
</q-tab>
|
||||
|
||||
<q-tab icon="photo_camera" label="Scan" @click="showCamera"> </q-tab>
|
||||
<q-tab @click="showParseDialog" icon="file_upload" label="Send">
|
||||
</q-tab>
|
||||
<q-btn
|
||||
round
|
||||
size="35px"
|
||||
unelevated
|
||||
icon="qr_code_scanner"
|
||||
@click="showCamera"
|
||||
class="text-white bg-primary z-top vertical-bottom absolute-center absolute"
|
||||
>
|
||||
</q-btn>
|
||||
</q-tabs>
|
||||
|
||||
<q-dialog v-model="disclaimerDialog.show">
|
||||
|
||||
@@ -48,6 +48,7 @@ from lnbits.extension_manager import (
|
||||
Extension,
|
||||
ExtensionRelease,
|
||||
InstallableExtension,
|
||||
fetch_github_release_config,
|
||||
get_valid_extensions,
|
||||
)
|
||||
from lnbits.helpers import generate_filter_params_openapi, url_for
|
||||
@@ -779,6 +780,11 @@ async def api_install_extension(
|
||||
status_code=HTTPStatus.NOT_FOUND, detail="Release not found"
|
||||
)
|
||||
|
||||
if not release.is_version_compatible:
|
||||
raise HTTPException(
|
||||
status_code=HTTPStatus.BAD_REQUEST, detail="Incompatible extension version"
|
||||
)
|
||||
|
||||
ext_info = InstallableExtension(
|
||||
id=data.ext_id, name=data.ext_id, installed_release=release, icon=release.icon
|
||||
)
|
||||
@@ -814,7 +820,7 @@ async def api_install_extension(
|
||||
ext_info.clean_extension_files()
|
||||
raise HTTPException(
|
||||
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
|
||||
detail="Failed to install extension.",
|
||||
detail=f"Failed to install extension {ext_info.id} ({ext_info.installed_version}).",
|
||||
)
|
||||
|
||||
|
||||
@@ -851,6 +857,7 @@ async def api_uninstall_extension(ext_id: str, user: User = Depends(check_admin)
|
||||
ext_info.clean_extension_files()
|
||||
await delete_installed_extension(ext_id=ext_info.id)
|
||||
|
||||
logger.success(f"Extension '{ext_id}' uninstalled.")
|
||||
except Exception as ex:
|
||||
raise HTTPException(
|
||||
status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(ex)
|
||||
@@ -874,6 +881,27 @@ async def get_extension_releases(ext_id: str):
|
||||
)
|
||||
|
||||
|
||||
@core_app.get(
|
||||
"/api/v1/extension/release/{org}/{repo}/{tag_name}",
|
||||
dependencies=[Depends(check_admin)],
|
||||
)
|
||||
async def get_extension_release(org: str, repo: str, tag_name: str):
|
||||
try:
|
||||
config = await fetch_github_release_config(org, repo, tag_name)
|
||||
if not config:
|
||||
return {}
|
||||
|
||||
return {
|
||||
"min_lnbits_version": config.min_lnbits_version,
|
||||
"is_version_compatible": config.is_version_compatible(),
|
||||
"warning": config.warning,
|
||||
}
|
||||
except Exception as ex:
|
||||
raise HTTPException(
|
||||
status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(ex)
|
||||
)
|
||||
|
||||
|
||||
# TINYURL
|
||||
|
||||
|
||||
|
||||
@@ -57,11 +57,13 @@ async def robots():
|
||||
|
||||
|
||||
@core_html_routes.get(
|
||||
"/extensions", name="core.extensions", response_class=HTMLResponse
|
||||
"/extensions", name="install.extensions", response_class=HTMLResponse
|
||||
)
|
||||
async def extensions(
|
||||
async def extensions_install(
|
||||
request: Request,
|
||||
user: User = Depends(check_user_exists),
|
||||
activate: str = Query(None),
|
||||
deactivate: str = Query(None),
|
||||
enable: str = Query(None),
|
||||
disable: str = Query(None),
|
||||
):
|
||||
@@ -69,24 +71,7 @@ async def extensions(
|
||||
|
||||
# Update user as his extensions have been updated
|
||||
if enable or disable:
|
||||
updated_user = await get_user(user.id)
|
||||
assert updated_user, "User does not exist."
|
||||
user = updated_user
|
||||
|
||||
return template_renderer().TemplateResponse(
|
||||
"core/extensions.html", {"request": request, "user": user.dict()}
|
||||
)
|
||||
|
||||
|
||||
@core_html_routes.get(
|
||||
"/install", name="install.extensions", response_class=HTMLResponse
|
||||
)
|
||||
async def extensions_install(
|
||||
request: Request,
|
||||
user: User = Depends(check_user_exists),
|
||||
activate: str = Query(None),
|
||||
deactivate: str = Query(None),
|
||||
):
|
||||
user = await get_user(user.id) # type: ignore
|
||||
try:
|
||||
installed_exts: List["InstallableExtension"] = await get_installed_extensions()
|
||||
installed_exts_ids = [e.id for e in installed_exts]
|
||||
@@ -153,7 +138,7 @@ async def extensions_install(
|
||||
)
|
||||
|
||||
return template_renderer().TemplateResponse(
|
||||
"core/install.html",
|
||||
"core/extensions.html",
|
||||
{
|
||||
"request": request,
|
||||
"user": user.dict(),
|
||||
|
||||
+22
-1
@@ -11,7 +11,7 @@ from sqlite3 import Row
|
||||
from typing import Any, Generic, List, Literal, Optional, Type, TypeVar
|
||||
|
||||
from loguru import logger
|
||||
from pydantic import BaseModel, ValidationError
|
||||
from pydantic import BaseModel, ValidationError, root_validator
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy_aio.base import AsyncConnection
|
||||
from sqlalchemy_aio.strategy import ASYNCIO_STRATEGY
|
||||
@@ -344,6 +344,7 @@ class FromRowModel(BaseModel):
|
||||
|
||||
class FilterModel(BaseModel):
|
||||
__search_fields__: List[str] = []
|
||||
__sort_fields__: Optional[List[str]] = None
|
||||
|
||||
|
||||
T = TypeVar("T")
|
||||
@@ -427,6 +428,14 @@ class Filter(BaseModel, Generic[TFilterModel]):
|
||||
|
||||
|
||||
class Filters(BaseModel, Generic[TFilterModel]):
|
||||
"""
|
||||
Generic helper class for filtering and sorting data.
|
||||
For usage in an api endpoint, use the `parse_filters` dependency.
|
||||
|
||||
When constructing this class manually always make sure to pass a model so that the values can be validated.
|
||||
Otherwise, make sure to validate the inputs manually.
|
||||
"""
|
||||
|
||||
filters: List[Filter[TFilterModel]] = []
|
||||
search: Optional[str] = None
|
||||
|
||||
@@ -438,6 +447,18 @@ class Filters(BaseModel, Generic[TFilterModel]):
|
||||
|
||||
model: Optional[Type[TFilterModel]] = None
|
||||
|
||||
@root_validator(pre=True)
|
||||
def validate_sortby(cls, values):
|
||||
sortby = values.get("sortby")
|
||||
model = values.get("model")
|
||||
if sortby and model:
|
||||
model = values["model"]
|
||||
# if no sort fields are specified explicitly all fields are allowed
|
||||
allowed = model.__sort_fields__ or model.__fields__
|
||||
if sortby not in allowed:
|
||||
raise ValueError("Invalid sort field")
|
||||
return values
|
||||
|
||||
def pagination(self) -> str:
|
||||
stmt = ""
|
||||
if self.limit:
|
||||
|
||||
+86
-24
@@ -12,6 +12,7 @@ from urllib import request
|
||||
import httpx
|
||||
from fastapi import HTTPException
|
||||
from loguru import logger
|
||||
from packaging import version
|
||||
from pydantic import BaseModel
|
||||
|
||||
from lnbits.settings import settings
|
||||
@@ -26,11 +27,17 @@ class ExplicitRelease(BaseModel):
|
||||
dependencies: List[str] = []
|
||||
icon: Optional[str]
|
||||
short_description: Optional[str]
|
||||
html_url: Optional[str]
|
||||
details: Optional[str]
|
||||
min_lnbits_version: Optional[str]
|
||||
html_url: Optional[str] # todo: release_url
|
||||
warning: Optional[str]
|
||||
info_notification: Optional[str]
|
||||
critical_notification: Optional[str]
|
||||
|
||||
def is_version_compatible(self):
|
||||
if not self.min_lnbits_version:
|
||||
return True
|
||||
return version.parse(self.min_lnbits_version) <= version.parse(settings.version)
|
||||
|
||||
|
||||
class GitHubRelease(BaseModel):
|
||||
id: str
|
||||
@@ -61,6 +68,13 @@ class ExtensionConfig(BaseModel):
|
||||
name: str
|
||||
short_description: str
|
||||
tile: str = ""
|
||||
warning: Optional[str] = ""
|
||||
min_lnbits_version: Optional[str]
|
||||
|
||||
def is_version_compatible(self):
|
||||
if not self.min_lnbits_version:
|
||||
return True
|
||||
return version.parse(self.min_lnbits_version) <= version.parse(settings.version)
|
||||
|
||||
|
||||
def download_url(url, save_path):
|
||||
@@ -117,6 +131,17 @@ async def fetch_github_releases(org: str, repo: str) -> List[GitHubRepoRelease]:
|
||||
return [GitHubRepoRelease.parse_obj(r) for r in releases]
|
||||
|
||||
|
||||
async def fetch_github_release_config(
|
||||
org: str, repo: str, tag_name: str
|
||||
) -> Optional[ExtensionConfig]:
|
||||
config_url = (
|
||||
f"https://raw.githubusercontent.com/{org}/{repo}/{tag_name}/config.json"
|
||||
)
|
||||
error_msg = "Cannot fetch GitHub extension config"
|
||||
config = await gihub_api_get(config_url, error_msg)
|
||||
return ExtensionConfig.parse_obj(config)
|
||||
|
||||
|
||||
async def gihub_api_get(url: str, error_msg: Optional[str]) -> Any:
|
||||
async with httpx.AsyncClient() as client:
|
||||
headers = (
|
||||
@@ -224,9 +249,11 @@ class ExtensionRelease(BaseModel):
|
||||
source_repo: str
|
||||
is_github_release: bool = False
|
||||
hash: Optional[str] = None
|
||||
min_lnbits_version: Optional[str] = None
|
||||
is_version_compatible: Optional[bool] = True
|
||||
html_url: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
details_html: Optional[str] = None
|
||||
warning: Optional[str] = None
|
||||
icon: Optional[str] = None
|
||||
|
||||
@classmethod
|
||||
@@ -244,6 +271,24 @@ class ExtensionRelease(BaseModel):
|
||||
html_url=r.html_url,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_explicit_release(
|
||||
cls, source_repo: str, e: "ExplicitRelease"
|
||||
) -> "ExtensionRelease":
|
||||
return ExtensionRelease(
|
||||
name=e.name,
|
||||
version=e.version,
|
||||
archive=e.archive,
|
||||
hash=e.hash,
|
||||
source_repo=source_repo,
|
||||
description=e.short_description,
|
||||
min_lnbits_version=e.min_lnbits_version,
|
||||
is_version_compatible=e.is_version_compatible(),
|
||||
warning=e.warning,
|
||||
html_url=e.html_url,
|
||||
icon=e.icon,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
async def all_releases(cls, org: str, repo: str) -> List["ExtensionRelease"]:
|
||||
try:
|
||||
@@ -308,8 +353,14 @@ class InstallableExtension(BaseModel):
|
||||
return False
|
||||
return Path(self.ext_dir, "config.json").is_file()
|
||||
|
||||
@property
|
||||
def installed_version(self) -> str:
|
||||
if self.installed_release:
|
||||
return self.installed_release.version
|
||||
return ""
|
||||
|
||||
def download_archive(self):
|
||||
logger.info(f"Downloading extension {self.name}.")
|
||||
logger.info(f"Downloading extension {self.name} ({self.installed_version}).")
|
||||
ext_zip_file = self.zip_path
|
||||
if ext_zip_file.is_file():
|
||||
os.remove(ext_zip_file)
|
||||
@@ -334,7 +385,7 @@ class InstallableExtension(BaseModel):
|
||||
)
|
||||
|
||||
def extract_archive(self):
|
||||
logger.info(f"Extracting extension {self.name}.")
|
||||
logger.info(f"Extracting extension {self.name} ({self.installed_version}).")
|
||||
Path("lnbits", "upgrades").mkdir(parents=True, exist_ok=True)
|
||||
shutil.rmtree(self.ext_upgrade_dir, True)
|
||||
with zipfile.ZipFile(self.zip_path, "r") as zip_ref:
|
||||
@@ -369,7 +420,7 @@ class InstallableExtension(BaseModel):
|
||||
Path(self.ext_upgrade_dir, self.id),
|
||||
Path(settings.lnbits_path, "extensions", self.id),
|
||||
)
|
||||
logger.success(f"Extension {self.name} installed.")
|
||||
logger.success(f"Extension {self.name} ({self.installed_version}) installed.")
|
||||
|
||||
def nofiy_upgrade(self) -> None:
|
||||
"""Update the list of upgraded extensions. The middleware will perform redirects based on this"""
|
||||
@@ -394,6 +445,15 @@ class InstallableExtension(BaseModel):
|
||||
|
||||
shutil.rmtree(self.ext_upgrade_dir, True)
|
||||
|
||||
def check_latest_version(self, release: Optional[ExtensionRelease]):
|
||||
if not release:
|
||||
return
|
||||
if not self.latest_release:
|
||||
self.latest_release = release
|
||||
return
|
||||
if version.parse(self.latest_release.version) < version.parse(release.version):
|
||||
self.latest_release = release
|
||||
|
||||
@classmethod
|
||||
def from_row(cls, data: dict) -> "InstallableExtension":
|
||||
meta = json.loads(data["meta"])
|
||||
@@ -451,18 +511,30 @@ class InstallableExtension(BaseModel):
|
||||
manifest = await fetch_manifest(url)
|
||||
|
||||
for r in manifest.repos:
|
||||
if r.id in extension_id_list:
|
||||
continue
|
||||
ext = await InstallableExtension.from_github_release(r)
|
||||
if ext:
|
||||
ext.featured = ext.id in manifest.featured
|
||||
extension_list += [ext]
|
||||
extension_id_list += [ext.id]
|
||||
if not ext:
|
||||
continue
|
||||
existing_ext = next(
|
||||
(ee for ee in extension_list if ee.id == r.id), None
|
||||
)
|
||||
if existing_ext:
|
||||
existing_ext.check_latest_version(ext.latest_release)
|
||||
continue
|
||||
|
||||
ext.featured = ext.id in manifest.featured
|
||||
extension_list += [ext]
|
||||
extension_id_list += [ext.id]
|
||||
|
||||
for e in manifest.extensions:
|
||||
if e.id in extension_id_list:
|
||||
release = ExtensionRelease.from_explicit_release(url, e)
|
||||
existing_ext = next(
|
||||
(ee for ee in extension_list if ee.id == e.id), None
|
||||
)
|
||||
if existing_ext:
|
||||
existing_ext.check_latest_version(release)
|
||||
continue
|
||||
ext = InstallableExtension.from_explicit_release(e)
|
||||
ext.check_latest_version(release)
|
||||
ext.featured = ext.id in manifest.featured
|
||||
extension_list += [ext]
|
||||
extension_id_list += [e.id]
|
||||
@@ -488,17 +560,7 @@ class InstallableExtension(BaseModel):
|
||||
for e in manifest.extensions:
|
||||
if e.id == ext_id:
|
||||
extension_releases += [
|
||||
ExtensionRelease(
|
||||
name=e.name,
|
||||
version=e.version,
|
||||
archive=e.archive,
|
||||
hash=e.hash,
|
||||
source_repo=url,
|
||||
description=e.short_description,
|
||||
details_html=e.details,
|
||||
html_url=e.html_url,
|
||||
icon=e.icon,
|
||||
)
|
||||
ExtensionRelease.from_explicit_release(url, e)
|
||||
]
|
||||
|
||||
except Exception as e:
|
||||
|
||||
@@ -50,6 +50,9 @@ class ExtensionsSettings(LNbitsSettings):
|
||||
"https://raw.githubusercontent.com/lnbits/lnbits-extensions/main/extensions.json"
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class ExtensionsInstallSettings(LNbitsSettings):
|
||||
lnbits_extensions_default_install: List[str] = Field(default=[])
|
||||
# required due to GitHUb rate-limit
|
||||
lnbits_ext_github_token: str = Field(default="")
|
||||
@@ -279,6 +282,7 @@ class TransientSettings(InstalledExtensionsSettings):
|
||||
|
||||
class ReadOnlySettings(
|
||||
EnvSettings,
|
||||
ExtensionsInstallSettings,
|
||||
SaaSSettings,
|
||||
PersistenceSettings,
|
||||
SuperUserSettings,
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+9
-9
File diff suppressed because one or more lines are too long
@@ -0,0 +1,88 @@
|
||||
window.localisation.br = {
|
||||
server: 'Servidor',
|
||||
theme: 'Tema',
|
||||
funding: 'Financiamento',
|
||||
users: 'Usuários',
|
||||
restart: 'Reiniciar servidor',
|
||||
save: 'Salvar',
|
||||
save_tooltip: 'Salvar suas alterações',
|
||||
topup: 'Recarregar',
|
||||
topup_wallet: 'Recarregar uma carteira',
|
||||
topup_hint: 'Use o ID da carteira para recarregar qualquer carteira',
|
||||
restart_tooltip: 'Reinicie o servidor para que as alterações tenham efeito',
|
||||
add_funds_tooltip: 'Adicionar fundos a uma carteira.',
|
||||
reset_defaults: 'Redefinir para padrões',
|
||||
reset_defaults_tooltip:
|
||||
'Apagar todas as configurações e redefinir para os padrões.',
|
||||
download_backup: 'Fazer backup do banco de dados',
|
||||
name_your_wallet: 'Nomeie sua carteira %{name}',
|
||||
paste_invoice_label: 'Cole uma fatura, pedido de pagamento ou código lnurl *',
|
||||
lnbits_description:
|
||||
'Fácil de configurar e leve, o LNbits pode ser executado em qualquer fonte de financiamento da lightning-network, atualmente suportando LND, c-lightning, OpenNode, LNPay e até mesmo o LNbits em si! Você pode executar o LNbits para si mesmo ou oferecer facilmente uma solução de custódia para outros. Cada carteira tem suas próprias chaves de API e não há limite para o número de carteiras que você pode criar. Ser capaz de particionar fundos torna o LNbits uma ferramenta útil para gerenciamento de dinheiro e como uma ferramenta de desenvolvimento. As extensões adicionam funcionalidades extras ao LNbits para que você possa experimentar uma série de tecnologias de ponta na rede lightning. Nós tornamos o desenvolvimento de extensões o mais fácil possível e, como um projeto gratuito e de código aberto, incentivamos as pessoas a desenvolver e enviar as suas próprias.',
|
||||
export_to_phone: 'Exportar para o telefone com código QR',
|
||||
export_to_phone_desc:
|
||||
'Este código QR contém a URL da sua carteira com acesso total. Você pode escaneá-lo do seu telefone para abrir sua carteira a partir dele.',
|
||||
wallets: 'Carteiras',
|
||||
add_wallet: 'Adicionar nova carteira',
|
||||
delete_wallet: 'Excluir carteira',
|
||||
delete_wallet_desc:
|
||||
'Toda a carteira será excluída, os fundos serão IRRECUPERÁVEIS.',
|
||||
rename_wallet: 'Renomear carteira',
|
||||
update_name: 'Atualizar nome',
|
||||
press_to_claim: 'Pressione para solicitar bitcoin',
|
||||
donate: 'Doar',
|
||||
view_github: 'Ver no GitHub',
|
||||
voidwallet_active: 'VoidWallet está ativo! Pagamentos desabilitados',
|
||||
use_with_caution: 'USE COM CAUTELA - a carteira %{name} ainda está em BETA',
|
||||
toggle_darkmode: 'Alternar modo escuro',
|
||||
view_swagger_docs: 'Ver a documentação da API do LNbits Swagger',
|
||||
api_docs: 'Documentação da API',
|
||||
commit_version: 'Versão de commit',
|
||||
lnbits_version: 'Versão do LNbits',
|
||||
runs_on: 'Executa em',
|
||||
credit_hint: 'Pressione Enter para creditar a conta',
|
||||
credit_label: '%{denomination} para creditar',
|
||||
paste_request: 'Colar Pedido',
|
||||
create_invoice: 'Criar Fatura',
|
||||
camera_tooltip: 'Usar a câmara para escanear uma fatura / QR',
|
||||
export_csv: 'Exportar para CSV',
|
||||
transactions: 'Transações',
|
||||
chart_tooltip: 'Mostrar gráfico',
|
||||
pending: 'Pendente',
|
||||
copy_invoice: 'Copiar fatura',
|
||||
close: 'Fechar',
|
||||
cancel: 'Cancelar',
|
||||
scan: 'Escanear',
|
||||
read: 'Ler',
|
||||
pay: 'Pagar',
|
||||
memo: 'Memo',
|
||||
date: 'Data',
|
||||
processing_payment: 'Processando pagamento...',
|
||||
not_enough_funds: 'Fundos insuficientes!',
|
||||
search_by_tag_memo_amount: 'Pesquisar por tag, memo, quantidade',
|
||||
invoice_waiting: 'Fatura aguardando pagamento',
|
||||
payment_received: 'Pagamento Recebido',
|
||||
payment_sent: 'Pagamento Enviado',
|
||||
outgoing_payment_pending: 'Pagamento pendente de saída',
|
||||
drain_funds: 'Drenar Fundos',
|
||||
drain_funds_desc:
|
||||
'Este é um código QR de retirada do LNURL para sugar tudo desta carteira. Não compartilhe com ninguém. É compatível com balanceCheck e balanceNotify para que sua carteira possa continuar retirando os fundos continuamente daqui após a primeira retirada.',
|
||||
i_understand: 'Eu entendo',
|
||||
copy_wallet_url: 'Copiar URL da carteira',
|
||||
disclaimer_dialog:
|
||||
'Funcionalidade de login a ser lançada em uma atualização futura, por enquanto, certifique-se de marcar esta página para acesso futuro à sua carteira! Este serviço está em BETA, e não nos responsabilizamos por pessoas que perderem o acesso aos fundos.',
|
||||
no_transactions: 'Ainda não foram feitas transações',
|
||||
manage_extensions: 'Gerenciar extensões',
|
||||
manage_server: 'Gerenciar servidor',
|
||||
extensions: 'Extensões',
|
||||
no_extensions: 'Você não possui nenhuma extensão instalada :(',
|
||||
created: 'Criado',
|
||||
payment_hash: 'Hash de pagamento',
|
||||
fee: 'Taxa',
|
||||
amount: 'Quantidade',
|
||||
unit: 'Unidade',
|
||||
description: 'Descrição',
|
||||
expiry: 'Validade',
|
||||
webhook: 'Webhook',
|
||||
payment_proof: 'Comprovante de pagamento'
|
||||
}
|
||||
@@ -14,16 +14,16 @@ window.localisation.de = {
|
||||
add_funds_tooltip: 'Füge Geld zu einer Wallet hinzu.',
|
||||
reset_defaults: 'Zurücksetzen',
|
||||
reset_defaults_tooltip:
|
||||
'Alle Einstellungen zurücksetzen auf die Standardeinstellungen.',
|
||||
'Alle Einstellungen auf die Standardeinstellungen zurücksetzen.',
|
||||
download_backup: 'Datenbank-Backup herunterladen',
|
||||
name_your_wallet: 'Vergib deiner %{name} Wallet einen Namen',
|
||||
paste_invoice_label:
|
||||
'Füge eine Rechnung, Zahlungsanforderung oder lnurl ein *',
|
||||
'Füge eine Rechnung, Zahlungsanforderung oder LNURL ein *',
|
||||
lnbits_description:
|
||||
'Einfach zu installieren und kompakt, LNbits kann auf jeder Funding-Quelle im Lightning Netzwerk aufsetzen. Derzeit unterstützt: LND, c-lightning, OpenNode, LNPay und sogar LNbits selbst! Du kannst LNbits für dich selbst betreiben oder anderen die Verwaltung durch dich anbieten. Jede Wallet hat ihre eigenen API-Schlüssel und die Anzahl der Wallets ist unbegrenzt. Die Möglichkeit, Gelder auf verschiedene Accounts mit unterschiedlicher Logik aufteilen zu können macht LNbits zu einem nützlichen Werkzeug für deine Buchhaltung - aber auch als Entwicklungswerkzeug. Erweiterungen bereichern LNbits Accounts um zusätzliche Funktionalität, so dass du mit einer Reihe von neuartigen Technologien auf dem Lightning-Netzwerk experimentieren kannst. Wir haben es so einfach wie möglich gemacht, Erweiterungen zu entwickeln, und als freies und Open-Source-Projekt möchten wir Menschen ermutigen, sich selbst hieran zu versuchen und gemeinsam mit uns neue Funktionalitäten zu entwickeln.',
|
||||
'Einfach zu installieren und kompakt, LNbits kann auf jeder Funding-Quelle im Lightning Netzwerk aufsetzen. Derzeit unterstützt: LND, Core Lightning, OpenNode, LNPay und sogar LNbits selbst! Du kannst LNbits für dich selbst betreiben oder anderen die Verwaltung durch dich anbieten. Jede Wallet hat ihre eigenen API-Schlüssel und die Anzahl der Wallets ist unbegrenzt. Die Möglichkeit, Gelder auf verschiedene Accounts mit unterschiedlicher Logik aufteilen zu können macht LNbits zu einem nützlichen Werkzeug für deine Buchhaltung - aber auch als Entwicklungswerkzeug. Erweiterungen bereichern LNbits Accounts um zusätzliche Funktionalität, so dass du mit einer Reihe von neuartigen Technologien auf dem Lightning-Netzwerk experimentieren kannst. Wir haben es so einfach wie möglich gemacht, Erweiterungen zu entwickeln, und als freies und Open-Source-Projekt möchten wir Menschen ermutigen, sich selbst hieran zu versuchen und gemeinsam mit uns neue Funktionalitäten zu entwickeln.',
|
||||
export_to_phone: 'Auf dem Telefon öffnen',
|
||||
export_to_phone_desc:
|
||||
'Dieser QR-Code beinhaltet vollständige Rechte auf deine Wallet. Du kannste den QR-Code mit Deinem Telefon scannen, um deine Wallet dort zu öffnen.',
|
||||
'Dieser QR-Code beinhaltet vollständige Rechte auf deine Wallet. Du kannst den QR-Code mit Deinem Telefon scannen, um deine Wallet dort zu öffnen.',
|
||||
wallets: 'Wallets',
|
||||
add_wallet: 'Wallet hinzufügen',
|
||||
delete_wallet: 'Wallet löschen',
|
||||
@@ -35,7 +35,8 @@ window.localisation.de = {
|
||||
donate: 'Spenden',
|
||||
view_github: 'Auf GitHub anzeigen',
|
||||
voidwallet_active: 'VoidWallet ist aktiv! Zahlungen deaktiviert',
|
||||
use_with_caution: 'BITTE MIT VORSICHT BENUTZEN- %{name} Wallet ist noch BETA',
|
||||
use_with_caution:
|
||||
'BITTE MIT VORSICHT BENUTZEN - %{name} Wallet ist noch BETA',
|
||||
toggle_darkmode: 'Auf Dark Mode umschalten',
|
||||
view_swagger_docs: 'LNbits Swagger API-Dokumente',
|
||||
api_docs: 'API docs',
|
||||
@@ -46,7 +47,7 @@ window.localisation.de = {
|
||||
paste_request: 'Anfrage einfügen',
|
||||
create_invoice: 'Rechnung erstellen',
|
||||
camera_tooltip:
|
||||
'Verwenden Sie die Kamera, um eine Rechnung oder einen QR-Code zu scannen',
|
||||
'Verwende die Kamera, um eine Rechnung oder einen QR-Code zu scannen',
|
||||
export_csv: 'Exportieren als CSV',
|
||||
transactions: 'Transaktionen',
|
||||
chart_tooltip: 'Diagramm anzeigen',
|
||||
@@ -68,7 +69,7 @@ window.localisation.de = {
|
||||
outgoing_payment_pending: 'Ausgehende Zahlung wartend',
|
||||
drain_funds: 'Sats abziehen',
|
||||
drain_funds_desc:
|
||||
'LNURL-withdraw QR-Code, der das Abziehen aller Geldmittel aus dieser Wallet erlaubt. Teile ihn mit niemandem! Kompatibel mit balanceCheck und balanceNotify, so dass deine Brieftasche die Sats nach dem ersten Abzug kontinuierlich von hier abziehen kann.',
|
||||
'LNURL-withdraw QR-Code, der das Abziehen aller Geldmittel aus dieser Wallet erlaubt. Teile ihn mit niemandem! Kompatibel mit balanceCheck und balanceNotify, so dass dein Wallet die Sats nach dem ersten Abzug kontinuierlich von hier abziehen kann.',
|
||||
i_understand: 'Ich verstehe',
|
||||
copy_wallet_url: 'Wallet-URL kopieren',
|
||||
disclaimer_dialog:
|
||||
@@ -79,6 +80,39 @@ window.localisation.de = {
|
||||
extensions: 'Erweiterungen',
|
||||
no_extensions: 'Du hast noch keine Erweiterungen installiert :(',
|
||||
created: 'Erstellt',
|
||||
|
||||
search_extensions: 'Sucherweiterungen',
|
||||
warning: 'Warnung',
|
||||
manage: 'Verwalten',
|
||||
repository: 'Repository',
|
||||
confirm_continue: 'Bist du sicher, dass du fortfahren möchtest?',
|
||||
manage_extension_details: 'Erweiterung installieren/deinstallieren',
|
||||
install: 'Installieren',
|
||||
uninstall: 'Deinstallieren',
|
||||
open: 'Öffnen',
|
||||
enable: 'Aktivieren',
|
||||
enable_extension_details: 'Erweiterung für aktuellen Benutzer aktivieren',
|
||||
disable: 'Deaktivieren',
|
||||
installed: 'Installiert',
|
||||
activated: 'Aktiviert',
|
||||
deactivated: 'Deaktiviert',
|
||||
release_notes: 'Versionshinweise',
|
||||
activate_extension_details:
|
||||
'Erweiterung für Benutzer verfügbar/nicht verfügbar machen',
|
||||
featured: 'Vorgestellt',
|
||||
all: 'Alle',
|
||||
only_admins_can_install:
|
||||
'(Nur Administratorkonten können Erweiterungen installieren)',
|
||||
new_version: 'Neue Version',
|
||||
extension_depends_on: 'Hängt ab von:',
|
||||
extension_rating_soon: 'Bewertungen sind bald verfügbar',
|
||||
extension_installed_version: 'Installierte Version',
|
||||
extension_uninstall_warning:
|
||||
'Sie sind dabei, die Erweiterung für alle Benutzer zu entfernen.',
|
||||
uninstall_confirm: 'Ja, deinstallieren',
|
||||
extension_min_lnbits_version:
|
||||
'Diese Version erfordert mindestens die LNbits-Version',
|
||||
|
||||
payment_hash: 'Zahlungs-Hash',
|
||||
fee: 'Gebühr',
|
||||
amount: 'Menge',
|
||||
|
||||
@@ -17,7 +17,7 @@ window.localisation.en = {
|
||||
name_your_wallet: 'Name your %{name} wallet',
|
||||
paste_invoice_label: 'Paste an invoice, payment request or lnurl code *',
|
||||
lnbits_description:
|
||||
'Easy to set up and lightweight, LNbits can run on any lightning-network funding source, currently supporting LND, c-lightning, OpenNode, LNPay and even LNbits itself! You can run LNbits for yourself, or easily offer a custodian solution for others. Each wallet has its own API keys and there is no limit to the number of wallets you can make. Being able to partition funds makes LNbits a useful tool for money management and as a development tool. Extensions add extra functionality to LNbits so you can experiment with a range of cutting-edge technologies on the lightning network. We have made developing extensions as easy as possible, and as a free and open-source project, we encourage people to develop and submit their own.',
|
||||
'Easy to set up and lightweight, LNbits can run on any lightning-network funding source, currently supporting LND, Core Lightning, OpenNode, LNPay and even LNbits itself! You can run LNbits for yourself, or easily offer a custodian solution for others. Each wallet has its own API keys and there is no limit to the number of wallets you can make. Being able to partition funds makes LNbits a useful tool for money management and as a development tool. Extensions add extra functionality to LNbits so you can experiment with a range of cutting-edge technologies on the lightning network. We have made developing extensions as easy as possible, and as a free and open-source project, we encourage people to develop and submit their own.',
|
||||
export_to_phone: 'Export to Phone with QR Code',
|
||||
export_to_phone_desc:
|
||||
'This QR code contains your wallet URL with full access. You can scan it from your phone to open your wallet from there.',
|
||||
@@ -71,11 +71,40 @@ window.localisation.en = {
|
||||
disclaimer_dialog:
|
||||
'Login functionality to be released in a future update, for now, make sure you bookmark this page for future access to your wallet! This service is in BETA, and we hold no responsibility for people losing access to funds.',
|
||||
no_transactions: 'No transactions made yet',
|
||||
manage_extensions: 'Manage Extensions',
|
||||
manage_server: 'Manage Server',
|
||||
extensions: 'Extensions',
|
||||
no_extensions: "You don't have any extensions installed :(",
|
||||
created: 'Created',
|
||||
|
||||
search_extensions: 'Search extensions',
|
||||
warning: 'Warning',
|
||||
manage: 'Manage',
|
||||
repository: 'Repository',
|
||||
confirm_continue: 'Are you sure you want to continue?',
|
||||
manage_extension_details: 'Install/uninstall extension',
|
||||
install: 'Install',
|
||||
uninstall: 'Uninstall',
|
||||
open: 'Open',
|
||||
enable: 'Enable',
|
||||
enable_extension_details: 'Enable extension for current user',
|
||||
disable: 'Disable',
|
||||
installed: 'Installed',
|
||||
activated: 'Activated',
|
||||
deactivated: 'Deactivated',
|
||||
release_notes: 'Release Notes',
|
||||
activate_extension_details: 'Make extension available/unavailable for users',
|
||||
featured: 'Featured',
|
||||
all: 'All',
|
||||
only_admins_can_install: '(Only admin accounts can install extensions)',
|
||||
new_version: 'New Version',
|
||||
extension_depends_on: 'Depends on:',
|
||||
extension_rating_soon: 'Ratings coming soon',
|
||||
extension_installed_version: 'Installed version',
|
||||
extension_uninstall_warning:
|
||||
'You are about to remove the extension for all users.',
|
||||
uninstall_confirm: 'Yes, Uninstall',
|
||||
extension_min_lnbits_version: 'This release requires at least LNbits version',
|
||||
|
||||
payment_hash: 'Payment Hash',
|
||||
fee: 'Fee',
|
||||
amount: 'Amount',
|
||||
|
||||
@@ -19,7 +19,7 @@ window.localisation.es = {
|
||||
name_your_wallet: 'Nombre de su billetera %{name}',
|
||||
paste_invoice_label: 'Pegue la factura aquí',
|
||||
lnbits_description:
|
||||
'Fácil de instalar y liviano, LNbits puede ejecutarse en cualquier fuente de financiación de la red Lightning, actualmente compatible con LND, c-lightning, OpenNode, LNPay y hasta LNbits mismo! Puede ejecutar LNbits para usted mismo o ofrecer una solución competente a otros. Cada billetera tiene su propia clave API y no hay límite para la cantidad de billeteras que puede crear. La capacidad de particionar fondos hace de LNbits una herramienta útil para la administración de fondos y como herramienta de desarrollo. Las extensiones agregan funcionalidad adicional a LNbits, por lo que puede experimentar con una variedad de tecnologías de vanguardia en la red Lightning. Lo hemos hecho lo más simple posible para desarrollar extensiones y, como un proyecto gratuito y de código abierto, animamos a las personas a que se desarrollen a sí mismas y envíen sus propios contribuciones.',
|
||||
'Fácil de instalar y liviano, LNbits puede ejecutarse en cualquier fuente de financiación de la red Lightning, actualmente compatible con LND, Core Lightning, OpenNode, LNPay y hasta LNbits mismo! Puede ejecutar LNbits para usted mismo o ofrecer una solución competente a otros. Cada billetera tiene su propia clave API y no hay límite para la cantidad de billeteras que puede crear. La capacidad de particionar fondos hace de LNbits una herramienta útil para la administración de fondos y como herramienta de desarrollo. Las extensiones agregan funcionalidad adicional a LNbits, por lo que puede experimentar con una variedad de tecnologías de vanguardia en la red Lightning. Lo hemos hecho lo más simple posible para desarrollar extensiones y, como un proyecto gratuito y de código abierto, animamos a las personas a que se desarrollen a sí mismas y envíen sus propios contribuciones.',
|
||||
export_to_phone: 'Exportar a teléfono con código QR',
|
||||
export_to_phone_desc:
|
||||
'Este código QR contiene su URL de billetera con acceso completo. Puede escanearlo desde su teléfono para abrir su billetera allí.',
|
||||
@@ -72,11 +72,43 @@ window.localisation.es = {
|
||||
disclaimer_dialog:
|
||||
'La funcionalidad de inicio de sesión se lanzará en una actualización futura, por ahora, asegúrese de guardar esta página como marcador para acceder a su billetera en el futuro. Este servicio está en BETA y no asumimos ninguna responsabilidad por personas que pierdan el acceso a sus fondos.',
|
||||
no_transactions: 'No hay transacciones todavía',
|
||||
manage_extensions: 'Administrar extensiones',
|
||||
manage_server: 'Administrar servidor',
|
||||
extensions: 'Extensiones',
|
||||
no_extensions: 'No tienes extensiones instaladas :(',
|
||||
created: 'Creado',
|
||||
|
||||
search_extensions: 'Extensiones de búsqueda',
|
||||
warning: 'Advertencia',
|
||||
manage: 'Administrar',
|
||||
repository: 'Repositorio',
|
||||
confirm_continue: '¿Está seguro de que desea continuar?',
|
||||
manage_extension_details: 'Instalar/desinstalar extensión',
|
||||
install: 'Instalar',
|
||||
uninstall: 'Desinstalar',
|
||||
open: 'Abrir',
|
||||
enable: 'Habilitar',
|
||||
enable_extension_details: 'Habilitar extensión para el usuario actual',
|
||||
disable: 'Deshabilitar',
|
||||
installed: 'Instalado',
|
||||
activated: 'Activado',
|
||||
deactivated: 'Desactivado',
|
||||
release_notes: 'Notas de la versión',
|
||||
activate_extension_details:
|
||||
'Hacer que la extensión esté disponible/no disponible para los usuarios',
|
||||
featured: 'Destacado',
|
||||
all: 'Todos',
|
||||
only_admins_can_install:
|
||||
'(Solo las cuentas de administrador pueden instalar extensiones)',
|
||||
new_version: 'Nueva Versión',
|
||||
extension_depends_on: 'Depende de:',
|
||||
extension_rating_soon: 'Calificaciones próximamente',
|
||||
extension_installed_version: 'Versión instalada',
|
||||
extension_uninstall_warning:
|
||||
'Está a punto de eliminar la extensión para todos los usuarios.',
|
||||
uninstall_confirm: 'Sí, desinstalar',
|
||||
extension_min_lnbits_version:
|
||||
'Esta versión requiere al menos una versión de LNbits',
|
||||
|
||||
payment_hash: 'Hash de pago',
|
||||
fee: 'Cuota',
|
||||
amount: 'Cantidad',
|
||||
|
||||
@@ -21,7 +21,7 @@ window.localisation.fr = {
|
||||
paste_invoice_label:
|
||||
'Coller une facture, une demande de paiement ou un code lnurl *',
|
||||
lnbits_description:
|
||||
"Facile à installer et léger, LNbits peut fonctionner sur n'importe quelle source de financement du réseau Lightning, prenant actuellement en charge LND, c-lightning, OpenNode, LNPay et même LNbits lui-même! Vous pouvez exécuter LNbits pour vous-même ou offrir facilement une solution de gardien pour les autres. Chaque portefeuille a ses propres clés API et il n'y a pas de limite au nombre de portefeuilles que vous pouvez créer. La capacité de partitionner les fonds rend LNbits un outil utile pour la gestion de l'argent et comme outil de développement. Les extensions ajoutent une fonctionnalité supplémentaire à LNbits afin que vous puissiez expérimenter une gamme de technologies de pointe sur le réseau Lightning. Nous avons rendu le développement d'extensions aussi simple que possible et, en tant que projet gratuit et open source, nous encourageons les gens à développer et à soumettre les leurs.",
|
||||
"Facile à installer et léger, LNbits peut fonctionner sur n'importe quelle source de financement du réseau Lightning, prenant actuellement en charge LND, Core Lightning, OpenNode, LNPay et même LNbits lui-même! Vous pouvez exécuter LNbits pour vous-même ou offrir facilement une solution de gardien pour les autres. Chaque portefeuille a ses propres clés API et il n'y a pas de limite au nombre de portefeuilles que vous pouvez créer. La capacité de partitionner les fonds rend LNbits un outil utile pour la gestion de l'argent et comme outil de développement. Les extensions ajoutent une fonctionnalité supplémentaire à LNbits afin que vous puissiez expérimenter une gamme de technologies de pointe sur le réseau Lightning. Nous avons rendu le développement d'extensions aussi simple que possible et, en tant que projet gratuit et open source, nous encourageons les gens à développer et à soumettre les leurs.",
|
||||
export_to_phone: 'Exporter vers le téléphone avec un code QR',
|
||||
export_to_phone_desc:
|
||||
"Ce code QR contient l'URL de votre portefeuille avec un accès complet. Vous pouvez le scanner depuis votre téléphone pour ouvrir votre portefeuille depuis là-bas.",
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
window.localisation.it = {
|
||||
server: 'Server',
|
||||
theme: 'Tema',
|
||||
funding: 'Funding',
|
||||
users: 'Utenti',
|
||||
restart: 'Riavvia il server',
|
||||
save: 'Salva',
|
||||
save_tooltip: 'Salva le modifiche',
|
||||
topup: 'Ricarica',
|
||||
topup_wallet: 'Ricarica un portafoglio',
|
||||
topup_hint: "Usa l'ID del portafoglio per ricaricare qualsiasi portafoglio",
|
||||
restart_tooltip: 'Riavvia il server affinché le modifiche abbiano effetto',
|
||||
add_funds_tooltip: 'Aggiungere fondi a un portafoglio',
|
||||
reset_defaults: 'Ripristina le impostazioni predefinite',
|
||||
reset_defaults_tooltip:
|
||||
'Cancella tutte le impostazioni e ripristina i valori predefiniti',
|
||||
download_backup: 'Scarica il backup del database',
|
||||
name_your_wallet: 'Dai un nome al tuo portafoglio %{name}',
|
||||
paste_invoice_label:
|
||||
'Incolla una fattura, una richiesta di pagamento o un codice lnurl *',
|
||||
lnbits_description:
|
||||
"Leggero e facile da configurare, LNbits può funzionare su qualsiasi fonte di finanziamento lightning-network, attualmente supporta LND, Core Lightning, OpenNode, LNPay e persino LNbits stesso! Potete gestire LNbits per conto vostro o offrire facilmente una soluzione di custodia per altri. Ogni portafoglio ha le proprie chiavi API e non c'è limite al numero di portafogli che si possono creare. La possibilità di suddividere i fondi rende LNbits uno strumento utile per la gestione del denaro e come strumento di sviluppo. Le estensioni aggiungono ulteriori funzionalità a LNbits, consentendo di sperimentare una serie di tecnologie all'avanguardia sulla rete Lightning. Abbiamo reso lo sviluppo delle estensioni il più semplice possibile e, in quanto progetto libero e open-source, incoraggiamo le persone a sviluppare e inviare le proprie",
|
||||
export_to_phone: 'Esportazione su telefono con codice QR',
|
||||
export_to_phone_desc:
|
||||
"Questo codice QR contiene l'URL del portafoglio con accesso da amministratore. È possibile scansionarlo dal telefono per aprire il portafoglio da lì.",
|
||||
wallets: 'Portafogli',
|
||||
add_wallet: 'Aggiungi un nuovo portafoglio',
|
||||
delete_wallet: 'Elimina il portafoglio',
|
||||
delete_wallet_desc:
|
||||
"L'intero portafoglio sarà cancellato, i fondi saranno irrecuperabili",
|
||||
rename_wallet: 'Rinomina il portafoglio',
|
||||
update_name: 'Aggiorna il nome',
|
||||
press_to_claim: 'Premi per richiedere bitcoin',
|
||||
donate: 'Donazioni',
|
||||
view_github: 'Visualizza su GitHub',
|
||||
voidwallet_active: 'VoidWallet è attivo! Pagamenti disabilitati',
|
||||
use_with_caution: 'USARE CON CAUTELA - %{nome} portafoglio è ancora in BETA',
|
||||
toggle_darkmode: 'Attiva la modalità notturna',
|
||||
view_swagger_docs: "Visualizza i documenti dell'API Swagger di LNbits",
|
||||
api_docs: 'Documenti API',
|
||||
commit_version: 'Commit version',
|
||||
lnbits_version: 'Versione di LNbits',
|
||||
runs_on: 'Esegue su',
|
||||
credit_hint: 'Premere Invio per accreditare i fondi',
|
||||
credit_label: '%{denomination} da accreditare',
|
||||
paste_request: 'Richiesta di pagamento',
|
||||
create_invoice: 'Crea fattura',
|
||||
camera_tooltip: 'Usa la fotocamera per scansionare la fattura/QR',
|
||||
export_csv: 'Esporta CSV',
|
||||
transactions: 'Transazioni',
|
||||
chart_tooltip: 'Mostra grafico',
|
||||
pending: 'In attesa',
|
||||
copy_invoice: 'Copia fattura',
|
||||
close: 'Chiudi',
|
||||
cancel: 'Annulla',
|
||||
scan: 'Scansiona',
|
||||
read: 'Leggi',
|
||||
pay: 'Paga',
|
||||
memo: 'Memo',
|
||||
data: 'Dati',
|
||||
processing_payment: 'Elaborazione pagamento...',
|
||||
not_enough_funds: 'Non ci sono abbastanza fondi!',
|
||||
search_by_tag_memo_amount: 'Cerca per tag, memo, importo...',
|
||||
invoice_waiting: 'Fattura in attesa di pagamento',
|
||||
payment_received: 'Pagamento ricevuto',
|
||||
payment_sent: 'Pagamento inviato',
|
||||
outgoing_payment_pending: 'Pagamento in uscita in attesa',
|
||||
drain_funds: 'Fondi di drenaggio',
|
||||
drain_funds_desc:
|
||||
'Questo è un codice QR <code>LNURL-withdraw</code> per prelevare tutti i fondi da questo portafoglio. Non condividerlo con nessuno. È compatibile con <code>balanceCheck</code> e <code>balanceNotify</code>, di conseguenza il vostro portafoglio può continuare a prelevare continuamente i fondi da qui dopo il primo prelievo',
|
||||
i_understand: 'Ho capito',
|
||||
copy_wallet_url: 'Copia URL portafoglio',
|
||||
disclaimer_dialog:
|
||||
"La funzionalità di login sarà rilasciata in un futuro aggiornamento; per ora, assicuratevi di salvare tra i preferiti questa pagina per accedere nuovamente in futuro a questo portafoglio! Questo servizio è in fase BETA e non ci assumiamo alcuna responsabilità per la perdita all'accesso dei fondi",
|
||||
no_transactions: 'Nessuna transazione effettuata',
|
||||
manage_extensions: 'Gestisci le estensioni',
|
||||
manage_server: 'Gestisci server',
|
||||
estensioni: 'Estensioni',
|
||||
no_extensions: 'Non ci sono estensioni installate :(',
|
||||
created: 'Creato',
|
||||
payment_hash: 'Hash del pagamento',
|
||||
fee: 'Tariffa',
|
||||
amount: 'Importo',
|
||||
unit: 'Unità',
|
||||
description: 'Descrizione',
|
||||
expiry: 'Scadenza',
|
||||
webhook: 'Webhook',
|
||||
prova_di_pagamento: 'Prova di pagamento'
|
||||
}
|
||||
@@ -18,7 +18,7 @@ window.localisation.jp = {
|
||||
name_your_wallet: 'あなたのウォレットの名前 %{name}',
|
||||
paste_invoice_label: '請求書を貼り付けてください',
|
||||
lnbits_description:
|
||||
'簡単にインストールでき、軽量で、LNbitsは現在LND、c-lightning、OpenNode、LNPay、さらにLNbits自身で動作する任意のLightningネットワークの資金源で実行できます! LNbitsを自分で実行することも、他の人に優れたソリューションを提供することもできます。各ウォレットには独自のAPIキーがあり、作成できるウォレットの数に制限はありません。資金を分割する機能は、LNbitsを資金管理ツールとして使用したり、開発ツールとして使用したりするための便利なツールです。拡張機能は、LNbitsに追加の機能を追加します。そのため、LNbitsは最先端の技術をネットワークLightningで試すことができます。拡張機能を開発するのは簡単で、無料でオープンソースのプロジェクトであるため、人々が自分で開発し、自分の貢献を送信することを奨励しています。',
|
||||
'簡単にインストールでき、軽量で、LNbitsは現在LND、Core Lightning、OpenNode、LNPay、さらにLNbits自身で動作する任意のLightningネットワークの資金源で実行できます! LNbitsを自分で実行することも、他の人に優れたソリューションを提供することもできます。各ウォレットには独自のAPIキーがあり、作成できるウォレットの数に制限はありません。資金を分割する機能は、LNbitsを資金管理ツールとして使用したり、開発ツールとして使用したりするための便利なツールです。拡張機能は、LNbitsに追加の機能を追加します。そのため、LNbitsは最先端の技術をネットワークLightningで試すことができます。拡張機能を開発するのは簡単で、無料でオープンソースのプロジェクトであるため、人々が自分で開発し、自分の貢献を送信することを奨励しています。',
|
||||
export_to_phone: '電話にエクスポート',
|
||||
export_to_phone_desc:
|
||||
'ウォレットを電話にエクスポートすると、ウォレットを削除する前にウォレットを復元できます。ウォレットを削除すると、ウォレットの秘密鍵が削除され、ウォレットを復元することはできません。',
|
||||
@@ -70,11 +70,41 @@ window.localisation.jp = {
|
||||
disclaimer_dialog:
|
||||
'ウォレットを削除すると、ウォレットの秘密鍵が削除され、ウォレットを復元することはできません。ウォレットを削除する前に、ウォレットをエクスポートしてください。',
|
||||
no_transactions: 'トランザクションはありません',
|
||||
manage_extensions: '拡張機能を管理する',
|
||||
manage_server: 'サーバーを管理する',
|
||||
extensions: '拡張機能',
|
||||
no_extensions: '拡張機能はありません',
|
||||
created: '作成済み',
|
||||
search_extensions: '検索拡張機能',
|
||||
warning: '警告',
|
||||
manage: '管理',
|
||||
repository: 'リポジトリ',
|
||||
confirm_continue: '続行してもよろしいですか?',
|
||||
manage_extension_details: '拡張機能のインストール/アンインストール',
|
||||
install: 'インストール',
|
||||
uninstall: 'アンインストール',
|
||||
open: '開く',
|
||||
enable: '有効',
|
||||
enable_extension_details: '現在のユーザーの拡張機能を有効にする',
|
||||
disable: '無効',
|
||||
installed: 'インストール済み',
|
||||
activated: '有効化',
|
||||
deactivated: '無効化',
|
||||
release_notes: 'リリースノート',
|
||||
activate_extension_details:
|
||||
'拡張機能をユーザーが利用できるようにする/利用できないようにする',
|
||||
featured: '特集',
|
||||
all: 'すべて',
|
||||
only_admins_can_install:
|
||||
'(管理者アカウントのみが拡張機能をインストールできます)',
|
||||
new_version: '新しいバージョン',
|
||||
extension_depends_on: '依存先:',
|
||||
extension_rating_soon: '評価は近日公開',
|
||||
extension_installed_version: 'インストール済みバージョン',
|
||||
extension_uninstall_warning:
|
||||
'すべてのユーザーの拡張機能を削除しようとしています.',
|
||||
uninstall_confirm: 'はい、アンインストールします',
|
||||
extension_min_lnbits_version:
|
||||
'このリリースには少なくとも LNbits バージョンが必要です',
|
||||
payment_hash: '支払いハッシュ',
|
||||
fee: '料金',
|
||||
amount: '量',
|
||||
|
||||
@@ -19,7 +19,7 @@ window.localisation.nl = {
|
||||
name_your_wallet: 'Geef je %{name} portemonnee een naam',
|
||||
paste_invoice_label: 'Plak een factuur, betalingsverzoek of lnurl-code*',
|
||||
lnbits_description:
|
||||
'Gemakkelijk in te stellen en lichtgewicht, LNbits kan op elke lightning-netwerkfinancieringsbron draaien, ondersteunt op dit moment LND, c-lightning, OpenNode, LNPay en zelfs LNbits zelf! U kunt LNbits voor uzelf laten draaien of gemakkelijk een bewaardersoplossing voor anderen bieden. Elke portemonnee heeft zijn eigen API-sleutels en er is geen limiet aan het aantal portemonnees dat u kunt maken. Het kunnen partitioneren van fondsen maakt LNbits een nuttige tool voor geldbeheer en als ontwikkelingstool. Extensies voegen extra functionaliteit toe aan LNbits, zodat u kunt experimenteren met een reeks toonaangevende technologieën op het bliksemschichtnetwerk. We hebben het ontwikkelen van extensies zo eenvoudig mogelijk gemaakt en als een gratis en opensource-project moedigen we mensen aan om hun eigen ontwikkelingen in te dienen.',
|
||||
'Gemakkelijk in te stellen en lichtgewicht, LNbits kan op elke lightning-netwerkfinancieringsbron draaien, ondersteunt op dit moment LND, Core Lightning, OpenNode, LNPay en zelfs LNbits zelf! U kunt LNbits voor uzelf laten draaien of gemakkelijk een bewaardersoplossing voor anderen bieden. Elke portemonnee heeft zijn eigen API-sleutels en er is geen limiet aan het aantal portemonnees dat u kunt maken. Het kunnen partitioneren van fondsen maakt LNbits een nuttige tool voor geldbeheer en als ontwikkelingstool. Extensies voegen extra functionaliteit toe aan LNbits, zodat u kunt experimenteren met een reeks toonaangevende technologieën op het bliksemschichtnetwerk. We hebben het ontwikkelen van extensies zo eenvoudig mogelijk gemaakt en als een gratis en opensource-project moedigen we mensen aan om hun eigen ontwikkelingen in te dienen.',
|
||||
export_to_phone: 'Exporteren naar telefoon met QR-code',
|
||||
export_to_phone_desc:
|
||||
'Deze QR-code bevat uw portemonnee-URL met volledige toegang. U kunt het vanaf uw telefoon scannen om uw portemonnee van daaruit te openen.',
|
||||
|
||||
@@ -18,7 +18,7 @@ window.localisation.pi = {
|
||||
name_your_wallet: 'Name yer %{name} treasure chest',
|
||||
paste_invoice_label: 'Paste a booty, payment request or lnurl code, matey!',
|
||||
lnbits_description:
|
||||
'Arr, easy to set up and lightweight, LNbits can run on any lightning-network funding source, currently supporting LND, c-lightning, OpenNode, LNPay and even LNbits itself! Ye can run LNbits for yourself, or easily offer a custodian solution for others. Each chest has its own API keys and there be no limit to the number of chests ye can make. Being able to partition booty makes LNbits a useful tool for money management and as a development tool. Arr, extensions add extra functionality to LNbits so ye can experiment with a range of cutting-edge technologies on the lightning network. We have made developing extensions as easy as possible, and as a free and open-source project, we encourage scallywags to develop and submit their own.',
|
||||
'Arr, easy to set up and lightweight, LNbits can run on any lightning-network funding source, currently supporting LND, Core Lightning, OpenNode, LNPay and even LNbits itself! Ye can run LNbits for yourself, or easily offer a custodian solution for others. Each chest has its own API keys and there be no limit to the number of chests ye can make. Being able to partition booty makes LNbits a useful tool for money management and as a development tool. Arr, extensions add extra functionality to LNbits so ye can experiment with a range of cutting-edge technologies on the lightning network. We have made developing extensions as easy as possible, and as a free and open-source project, we encourage scallywags to develop and submit their own.',
|
||||
export_to_phone: 'Export to Phone with QR Code, me hearties',
|
||||
export_to_phone_desc:
|
||||
'This QR code contains yer chest URL with full access. Ye can scan it from yer phone to open yer chest from there, arr!',
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
window.localisation.pl = {
|
||||
server: 'Serwer',
|
||||
theme: 'Motyw',
|
||||
funding: 'Finansowanie',
|
||||
users: 'Użytkownicy',
|
||||
restart: 'Restart serwera',
|
||||
save: 'Zapisz',
|
||||
save_tooltip: 'Zapisz zmiany',
|
||||
topup: 'Doładowanie',
|
||||
topup_wallet: 'Doładuj portfel',
|
||||
topup_hint: 'Użyj ID portfela aby go doładować',
|
||||
restart_tooltip: 'Zrestartuj serwer aby aktywować zmiany',
|
||||
add_funds_tooltip: 'Dodaj środki do portfela.',
|
||||
reset_defaults: 'Powrót do ustawień domyślnych',
|
||||
reset_defaults_tooltip: 'Wymaż wszystkie ustawienia i ustaw domyślne.',
|
||||
download_backup: 'Pobierz kopię zapasową bazy danych',
|
||||
name_your_wallet: 'Nazwij swój portfel %{name}',
|
||||
paste_invoice_label: 'Wklej fakturę, żądanie zapłaty lub kod lnurl *',
|
||||
lnbits_description:
|
||||
'Łatwy i lekki w konfiguracji, LNbits może działać w oparciu o dowolne źródło finansowania w sieci lightning, obecnie wspiera LND, Core Lightning, OpenNode, LNPay czy nawet inną instancję LNbits! Możesz uruchomić instancję LNbits dla siebie lub dla innych. Każdy portfel ma swoje klucze API i nie ma ograniczeń jeśli chodzi o ilość portfeli. LNbits umożliwia dzielenie środków w celu zarządzania nimi, jest również dobrym narzędziem deweloperskim. Rozszerzenia zwiększają funkcjonalność LNbits co umożliwia eksperymentowanie z nowym technologiami w sieci lightning. Tworzenie rozszerzeń jest proste dlatego zachęcamy innych deweloperów do tworzenia dodatkowych funkcjonalności i wysyłanie do nas PR',
|
||||
export_to_phone: 'Eksport kodu QR na telefon',
|
||||
export_to_phone_desc:
|
||||
'Ten kod QR zawiera adres URL Twojego portfela z pełnym dostępem do niego. Możesz go zeskanować na swoim telefonie aby otworzyć na nim ten portfel.',
|
||||
wallets: 'Portfele',
|
||||
add_wallet: 'Dodaj portfel',
|
||||
delete_wallet: 'Usuń portfel',
|
||||
delete_wallet_desc:
|
||||
'Ten portfel zostanie usunięty, środków na nim zgromadzonych NIE BĘDZIE MOŻNA ODZYSKAĆ.',
|
||||
rename_wallet: 'Zmień nazwę portfela',
|
||||
update_name: 'Zaktualizuj nazwę',
|
||||
press_to_claim: 'Naciśnij aby odebrać Bitcoiny',
|
||||
donate: 'Podaruj',
|
||||
view_github: 'Otwórz GitHub',
|
||||
voidwallet_active: 'VoidWallet jest aktywny! Płatności są niemożliwe',
|
||||
use_with_caution: 'KORZYSTAJ Z ROZWAGĄ - portfel %{name} jest w wersji BETA',
|
||||
toggle_darkmode: 'Tryb nocny',
|
||||
view_swagger_docs: 'Dokumentacja Swagger API',
|
||||
api_docs: 'Dokumentacja API',
|
||||
commit_version: 'Commit',
|
||||
lnbits_version: 'Wersja LNbits',
|
||||
runs_on: 'Działa na',
|
||||
credit_hint: 'Naciśnij Enter aby doładować konto',
|
||||
credit_label: '%{denomination} doładowanie',
|
||||
paste_request: 'Wklej żądanie',
|
||||
create_invoice: 'Utwórz fakturę',
|
||||
camera_tooltip: 'Użyj kamery aby zeskanować fakturę lub kod QR',
|
||||
export_csv: 'Eksport do CSV',
|
||||
transactions: 'Transakcje',
|
||||
chart_tooltip: 'Wykres',
|
||||
pending: 'W toku',
|
||||
copy_invoice: 'Skopiuj fakturę',
|
||||
close: 'Zamknij',
|
||||
cancel: 'Anuluj',
|
||||
scan: 'Skanuj',
|
||||
read: 'Odczytaj',
|
||||
pay: 'Zapłać',
|
||||
memo: 'Memo',
|
||||
date: 'Data',
|
||||
processing_payment: 'Przetwarzam płatność...',
|
||||
not_enough_funds: 'Brak wystarczających środków!',
|
||||
search_by_tag_memo_amount: 'Szukaj po tagu, memo czy wartości',
|
||||
invoice_waiting: 'Faktura oczekuje na zapłatę',
|
||||
payment_received: 'Otrzymano płatność',
|
||||
payment_sent: 'Wysłano płatność',
|
||||
outgoing_payment_pending: 'Płatność wychodząca w toku',
|
||||
drain_funds: 'Opróżnij środki',
|
||||
drain_funds_desc:
|
||||
'To jest kod QR służący do opróżnienia portfela (LNURL-withdraw). Nie udostępniaj go nikomu. Ten kod jest kompatybilny z funkcjami, które umożliwiają wielokrotne żądania aż do zupełnego opróżnienia portfela.',
|
||||
i_understand: 'Rozumiem',
|
||||
copy_wallet_url: 'Skopiuj URL portfela',
|
||||
disclaimer_dialog:
|
||||
'Funkcja logowania zostanie uruchomiona w przyszłości. Póki co upewnij się, że zapisałeś adres URL tej strony aby mieć dostęp do tego portfela. Nie udostępniaj adresu tej strony nikomu, kto nie ma mieć do tego portfela dostępu! Ta usługa działa w wersji BETA, nie odpowiadamy za utratę dostępu do środków przez osoby używające LNbits.',
|
||||
no_transactions: 'Brak transakcji',
|
||||
manage_extensions: 'Zarządzaj rozszerzeniami',
|
||||
manage_server: 'Zarządzaj serwerem',
|
||||
extensions: 'Rozszerzenia',
|
||||
no_extensions: 'Nie masz zainstalowanych żadnych rozszerzeń :(',
|
||||
created: 'Utworzono',
|
||||
payment_hash: 'Hash Płatności',
|
||||
fee: 'Opłata',
|
||||
amount: 'Wartość',
|
||||
unit: 'Jednostka',
|
||||
description: 'Opis',
|
||||
expiry: 'Wygasa',
|
||||
webhook: 'Webhook',
|
||||
payment_proof: 'Potwierdzenie płatności'
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
window.localisation.pt = {
|
||||
server: 'Servidor',
|
||||
theme: 'Tema',
|
||||
funding: 'Financiamento',
|
||||
users: 'Usuários',
|
||||
restart: 'Reiniciar servidor',
|
||||
save: 'Gravar',
|
||||
save_tooltip: 'Gravar as alterações',
|
||||
topup: 'Reforçar conta',
|
||||
topup_wallet: 'Recarregar uma carteira',
|
||||
topup_hint: 'Use o ID da carteira para recarregar qualquer carteira',
|
||||
restart_tooltip: 'Reinicie o servidor para que as alterações tenham efeito',
|
||||
add_funds_tooltip: 'Adicionar fundos a uma carteira.',
|
||||
reset_defaults: 'Redefinir para padrões',
|
||||
reset_defaults_tooltip:
|
||||
'Apagar todas as configurações e redefinir para os padrões.',
|
||||
download_backup: 'Fazer backup da base de dados',
|
||||
name_your_wallet: 'Nomeie sua carteira %{name}',
|
||||
paste_invoice_label: 'Cole uma fatura, pedido de pagamento ou código lnurl *',
|
||||
lnbits_description:
|
||||
'Fácil de configurar e leve, o LNbits pode ser executado em qualquer fonte de financiamento da lightning-network, atualmente suportando LND, c-lightning, OpenNode, LNPay e até mesmo o LNbits em si! Você pode executar o LNbits para si mesmo ou oferecer facilmente uma solução de custódia para outros. Cada carteira tem suas próprias chaves de API e não há limite para o número de carteiras que você pode criar. Ser capaz de particionar fundos torna o LNbits uma ferramenta útil para gerenciamento de dinheiro e como uma ferramenta de desenvolvimento. As extensões adicionam funcionalidades extras ao LNbits para que você possa experimentar uma série de tecnologias de ponta na rede lightning. Nós tornamos o desenvolvimento de extensões o mais fácil possível e, como um projeto gratuito e de código aberto, incentivamos as pessoas a desenvolver e enviar as suas próprias.',
|
||||
export_to_phone: 'Exportar para o telefone com código QR',
|
||||
export_to_phone_desc:
|
||||
'Este código QR contém a URL da sua carteira com acesso total. Você pode escaneá-lo do seu telefone para abrir sua carteira a partir dele.',
|
||||
wallets: 'Carteiras',
|
||||
add_wallet: 'Adicionar nova carteira',
|
||||
delete_wallet: 'Excluir carteira',
|
||||
delete_wallet_desc:
|
||||
'Toda a carteira será excluída, os fundos serão IRRECUPERÁVEIS.',
|
||||
rename_wallet: 'Renomear carteira',
|
||||
update_name: 'Atualizar nome',
|
||||
press_to_claim: 'Pressione para solicitar bitcoin',
|
||||
donate: 'Doar',
|
||||
view_github: 'Ver no GitHub',
|
||||
voidwallet_active: 'VoidWallet está ativo! Pagamentos desabilitados',
|
||||
use_with_caution: 'USE COM CAUTELA - a carteira %{name} ainda está em BETA',
|
||||
toggle_darkmode: 'Alternar modo escuro',
|
||||
view_swagger_docs: 'Ver a documentação da API do LNbits Swagger',
|
||||
api_docs: 'Documentação da API',
|
||||
commit_version: 'Versão de commit',
|
||||
lnbits_version: 'Versão do LNbits',
|
||||
runs_on: 'Executa em',
|
||||
credit_hint: 'Pressione Enter para creditar a conta',
|
||||
credit_label: '%{denomination} para creditar',
|
||||
paste_request: 'Colar Pedido',
|
||||
create_invoice: 'Criar Fatura',
|
||||
camera_tooltip: 'Usar a câmara para escanear uma fatura / QR',
|
||||
export_csv: 'Exportar para CSV',
|
||||
transactions: 'Transações',
|
||||
chart_tooltip: 'Mostrar gráfico',
|
||||
pending: 'Pendente',
|
||||
copy_invoice: 'Copiar fatura',
|
||||
close: 'Fechar',
|
||||
cancel: 'Cancelar',
|
||||
scan: 'Escanear',
|
||||
read: 'Ler',
|
||||
pay: 'Pagar',
|
||||
memo: 'Memo',
|
||||
date: 'Data',
|
||||
processing_payment: 'Processando pagamento...',
|
||||
not_enough_funds: 'Fundos insuficientes!',
|
||||
search_by_tag_memo_amount: 'Pesquisar por tag, memo, quantidade',
|
||||
invoice_waiting: 'Fatura aguardando pagamento',
|
||||
payment_received: 'Pagamento Recebido',
|
||||
payment_sent: 'Pagamento Enviado',
|
||||
outgoing_payment_pending: 'Pagamento de saída pendente',
|
||||
drain_funds: 'Esvasiar carteira',
|
||||
drain_funds_desc:
|
||||
'Este é um código QR de saque LNURL para sacar tudo desta carteira. Não o partilhe com ninguém. É compatível com balanceCheck e balanceNotify para que a sua carteira possa continuar levantando os fundos continuamente daqui após o primeiro saque.',
|
||||
i_understand: 'Eu entendo',
|
||||
copy_wallet_url: 'Copiar URL da carteira',
|
||||
disclaimer_dialog:
|
||||
'Funcionalidade de login a ser lançada numa atualização futura, por enquanto, certifique-se que marca esta página para acesso futuro à sua carteira! Este serviço está em BETA, e não nos responsabilizamos por pessoas que perderem o acesso aos fundos.',
|
||||
no_transactions: 'Ainda não foram feitas transações',
|
||||
manage_extensions: 'Gerir extensões',
|
||||
manage_server: 'Gerir servidor',
|
||||
extensions: 'Extensões',
|
||||
no_extensions: 'Não há nenhuma extensão instalada :(',
|
||||
created: 'Criado',
|
||||
payment_hash: 'Hash de pagamento',
|
||||
fee: 'Taxa',
|
||||
amount: 'Quantidade',
|
||||
unit: 'Unidade',
|
||||
description: 'Descrição',
|
||||
expiry: 'Validade',
|
||||
webhook: 'Webhook',
|
||||
payment_proof: 'Comprovativo de pagamento'
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
window.localisation.we = {
|
||||
server: 'Gweinydd',
|
||||
theme: 'Thema',
|
||||
funding: 'Arian fyndio',
|
||||
users: 'Defnyddwyr',
|
||||
restart: 'Ailgychwyn gweinydd',
|
||||
save: 'Save',
|
||||
save_tooltip: 'cadw eich newidiadau',
|
||||
topup: 'Topup',
|
||||
topup_wallet: 'Atodi waled',
|
||||
topup_hint: 'Defnyddiwch ID y waled i ychwanegu at unrhyw waled',
|
||||
restart_tooltip: 'Ailgychwyn y gweinydd er mwyn i newidiadau ddod i rym',
|
||||
add_funds_tooltip: 'Ychwanegu arian at waled.',
|
||||
reset_defaults: 'Ailosod i`r rhagosodiadau',
|
||||
reset_defaults_tooltip: 'Dileu pob gosodiad ac ailosod i`r rhagosodiadau.',
|
||||
download_backup: 'Lawrlwytho copi wrth gefn cronfa ddata',
|
||||
name_your_wallet: 'Enwch eich waled %{name}',
|
||||
paste_invoice_label: 'Gludwch anfoneb, cais am daliad neu god lnurl *',
|
||||
lnbits_description:
|
||||
'Yn hawdd iw sefydlu ac yn ysgafn, gall LNbits redeg ar unrhyw ffynhonnell ariannu rhwydwaith mellt, ar hyn o bryd yn cefnogi LND, Core Lightning, OpenNode, LNPay a hyd yn oed LNbits ei hun! Gallwch redeg LNbits i chi`ch hun, neu gynnig datrysiad ceidwad i eraill yn hawdd. Mae gan bob waled ei allweddi API ei hun ac nid oes cyfyngiad ar nifer y waledi y gallwch eu gwneud. Mae gallu rhannu cronfeydd yn gwneud LNbits yn arf defnyddiol ar gyfer rheoli arian ac fel offeryn datblygu. Mae estyniadau yn ychwanegu ymarferoldeb ychwanegol at LNbits fel y gallwch arbrofi gydag ystod o dechnolegau blaengar ar y rhwydwaith mellt. Rydym wedi gwneud datblygu estyniadau mor hawdd â phosibl, ac fel prosiect ffynhonnell agored am ddim, rydym yn annog pobl i ddatblygu a chyflwyno eu rhai eu hunain.',
|
||||
export_to_phone: 'Allforio i Ffôn gyda chod QR',
|
||||
export_to_phone_desc:
|
||||
'Mae`r cod QR hwn yn cynnwys URL eich waled gyda mynediad llawn. Gallwch ei sganio o`ch ffôn i agor eich waled oddi yno.',
|
||||
waledi: 'Waledi',
|
||||
add_wallet: 'Ychwanegu waled newydd',
|
||||
delete_wallet: 'Dileu waled',
|
||||
delete_wallet_desc:
|
||||
'Bydd y waled gyfan hon yn cael ei dileu, ni fydd modd adennill yr arian.',
|
||||
rename_wallet: 'Ailenwi waled',
|
||||
update_name: 'Diweddaru enw',
|
||||
press_to_claim: 'Pwyswch i hawlio bitcoin',
|
||||
Donate: 'Rhoi',
|
||||
view_github: 'Gweld ar GitHub',
|
||||
voidwallet_active:
|
||||
' Mae VoidWallet yn weithredol! Taliadau wedi`u hanalluogi',
|
||||
use_with_caution: 'DEFNYDDIO GYDA GOFAL - mae waled %{name} yn dal yn BETA',
|
||||
toggle_darkmode: 'Toglo Modd Tywyll',
|
||||
view_swagger_docs: 'Gweld dogfennau API LNbits Swagger',
|
||||
api_docs: 'Api docs',
|
||||
commit_version: 'fersiwn ymrwymo',
|
||||
lnbits_version: 'Fersiwn LNbits',
|
||||
Runs_on: 'Yn rhedeg ymlaen',
|
||||
credit_hint: 'Pwyswch Enter i gyfrif credyd',
|
||||
credit_label: '%{enomination} i gredyd',
|
||||
paste_request: 'Gludo Cais',
|
||||
create_invoice: 'Creu Anfoneb',
|
||||
camera_tooltip: 'Defnyddio camera i sganio anfoneb/QR',
|
||||
export_csv: 'Allforio i CSV',
|
||||
trafodion: 'Trafodion',
|
||||
chart_tooltip: 'Dangos siart',
|
||||
pending: 'yn yr arfaeth',
|
||||
copy_invoice: 'Copi anfoneb',
|
||||
Close: 'cau',
|
||||
cancel: 'Canslo',
|
||||
scan: 'Sgan',
|
||||
read: 'Darllen',
|
||||
talu: 'Pay',
|
||||
memo: 'Memo',
|
||||
date: 'Dyddiad',
|
||||
processing_payment: 'Prosesu taliad...',
|
||||
not_enough_funds: 'Dim digon o arian!',
|
||||
search_by_tag_memo_amount: 'Chwilio yn ôl tag, memo, swm',
|
||||
invoice_waiting: 'Anfoneb yn aros i gael ei thalu',
|
||||
payment_received: 'Taliad a Dderbyniwyd',
|
||||
payment_sent: 'Taliad a Anfonwyd',
|
||||
outgoing_payment_pending: 'Taliad sy`n aros yn yr arfaeth',
|
||||
drain_funds: 'Cronfeydd Draenio',
|
||||
drain_funds_desc:
|
||||
'Cod QR Tynnu`n ôl LNURL yw hwn ar gyfer slurpio popeth o`r waled hon. Peidiwch â rhannu gyda neb. Mae`n gydnaws â balanceCheck a balanceNotify felly efallai y bydd eich waled yn tynnu`r arian yn barhaus o`r fan hon ar ôl y codiad cyntaf.',
|
||||
i_understand: 'Rwy`n deall',
|
||||
copy_wallet_url: 'Copi URL waled',
|
||||
disclaimer_dialog:
|
||||
'Swyddogaeth mewngofnodi i`w ryddhau mewn diweddariad yn y dyfodol, am y tro, gwnewch yn siŵr eich bod yn rhoi nod tudalen ar y dudalen hon ar gyfer mynediad i`ch waled yn y dyfodol! Mae`r gwasanaeth hwn yn BETA, ac nid ydym yn gyfrifol am bobl sy`n colli mynediad at arian.',
|
||||
no_transactions: 'Dim trafodion wedi`u gwneud eto',
|
||||
manage_extensions: 'Rheoli Estyniadau',
|
||||
manage_server: 'Rheoli Gweinydd',
|
||||
Extensions: 'Estyniadau',
|
||||
no_extensions: "Nid oes gennych unrhyw estyniadau wedi'u gosod :(",
|
||||
create: 'Crëwyd',
|
||||
payment_hash: 'Hais Taliad',
|
||||
fee: 'Fee',
|
||||
amount: 'swm',
|
||||
unit: 'Uned',
|
||||
description: 'Disgrifiad',
|
||||
expiry: 'dod i ben',
|
||||
webhook: 'bachyn we',
|
||||
payment_proof: 'prawf taliad'
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.6 KiB |
@@ -343,7 +343,8 @@ window.windowMixin = {
|
||||
user: null,
|
||||
wallet: null,
|
||||
payments: [],
|
||||
allowedThemes: null
|
||||
allowedThemes: null,
|
||||
langs: []
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -388,6 +389,8 @@ window.windowMixin = {
|
||||
window.i18n.locale = locale
|
||||
}
|
||||
|
||||
this.g.langs = window.langs ?? []
|
||||
|
||||
addEventListener('offline', event => {
|
||||
this.g.offline = true
|
||||
})
|
||||
|
||||
@@ -140,14 +140,6 @@ Vue.component('lnbits-extension-list', {
|
||||
<q-item-label lines="1" class="text-caption" v-text="$t('extensions')"></q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable tag="a" :href="['/install?usr=', user.id].join('')">
|
||||
<q-item-section side>
|
||||
<q-icon name="playlist_add" color="grey-5" size="md"></q-icon>
|
||||
</q-item-section>
|
||||
<q-item-section>
|
||||
<q-item-label lines="1" class="text-caption" v-text="$t('manage_extensions')"></q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
`,
|
||||
computed: {
|
||||
@@ -221,71 +213,73 @@ Vue.component('lnbits-payment-details', {
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div class="q-py-md" style="text-align: left">
|
||||
<div class="row justify-center q-mb-md">
|
||||
<q-badge v-if="hasTag" color="yellow" text-color="black">
|
||||
#{{ payment.tag }}
|
||||
</q-badge>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-3"><b v-text="$t('created')"></b>:</div>
|
||||
<div class="col-9">{{ payment.date }} ({{ payment.dateFrom }})</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-3"><b v-text="$t('expiry')"></b>:</div>
|
||||
<div class="col-9">{{ payment.expirydate }} ({{ payment.expirydateFrom }})</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-3"><b v-text="$t('description')"></b>:</div>
|
||||
<div class="col-9">{{ payment.memo }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-3"><b v-text="$t('amount')"></b>:</div>
|
||||
<div class="col-9">{{ (payment.amount / 1000).toFixed(3) }} {{LNBITS_DENOMINATION}}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-3"><b v-text="$t('fee')"></b>:</div>
|
||||
<div class="col-9">{{ (payment.fee / 1000).toFixed(3) }} {{LNBITS_DENOMINATION}}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-3"><b v-text="$t('payment_hash')"></b>:</div>
|
||||
<div class="col-9 text-wrap mono">
|
||||
{{ payment.payment_hash }}
|
||||
<q-icon name="content_copy" @click="copyText(payment.payment_hash)" size="1em" color="grey" class="q-mb-xs cursor-pointer" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" v-if="payment.webhook">
|
||||
<div class="col-3"><b v-text="$t('webhook')"></b>:</div>
|
||||
<div class="col-9 text-wrap mono">
|
||||
{{ payment.webhook }}
|
||||
<q-badge :color="webhookStatusColor" text-color="white">
|
||||
{{ webhookStatusText }}
|
||||
</q-badge>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" v-if="hasPreimage">
|
||||
<div class="col-3"><b v-text="$t('payment_proof')"></b>:</div>
|
||||
<div class="col-9 text-wrap mono">{{ payment.preimage }}</div>
|
||||
</div>
|
||||
<div class="row" v-for="entry in extras">
|
||||
<div class="col-3">
|
||||
<q-badge v-if="hasTag" color="secondary" text-color="white">
|
||||
extra
|
||||
</q-badge>
|
||||
<b>{{ entry.key }}</b>:
|
||||
</div>
|
||||
<div class="col-9 text-wrap mono">{{ entry.value }}</div>
|
||||
</div>
|
||||
<div class="row" v-if="hasSuccessAction">
|
||||
<div class="col-3"><b>Success action</b>:</div>
|
||||
<div class="col-9">
|
||||
<lnbits-lnurlpay-success-action
|
||||
:payment="payment"
|
||||
:success_action="payment.extra.success_action"
|
||||
></lnbits-lnurlpay-success-action>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="q-py-md" style="text-align: left">
|
||||
|
||||
<div v-if="payment.tag" class="row justify-center q-mb-md">
|
||||
<q-badge v-if="hasTag" color="yellow" text-color="black">
|
||||
#{{ payment.tag }}
|
||||
</q-badge>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<b v-text="$t('created')"></b>:
|
||||
{{ payment.date }} ({{ payment.dateFrom }})
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<b v-text="$t('expiry')"></b>:
|
||||
{{ payment.expirydate }} ({{ payment.expirydateFrom }})
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<b v-text="$t('amount')"></b>:
|
||||
{{ (payment.amount / 1000).toFixed(3) }} {{LNBITS_DENOMINATION}}
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<b v-text="$t('fee')"></b>:
|
||||
{{ (payment.fee / 1000).toFixed(3) }} {{LNBITS_DENOMINATION}}
|
||||
</div>
|
||||
|
||||
<div class="text-wrap">
|
||||
<b style="white-space: nowrap;" v-text="$t('payment_hash')"></b>: {{ payment.payment_hash }}
|
||||
<q-icon name="content_copy" @click="copyText(payment.payment_hash)" size="1em" color="grey" class="q-mb-xs cursor-pointer" />
|
||||
</div>
|
||||
|
||||
<div class="text-wrap">
|
||||
<b style="white-space: nowrap;" v-text="$t('memo')"></b>: {{ payment.memo }}
|
||||
</div>
|
||||
|
||||
<div class="row" v-if="payment.webhook">
|
||||
<b v-text="$t('webhook')"></b>:
|
||||
{{ payment.webhook }}
|
||||
<q-badge :color="webhookStatusColor" text-color="white">
|
||||
{{ webhookStatusText }}
|
||||
</q-badge>
|
||||
</div>
|
||||
|
||||
<div class="row" v-if="hasPreimage">
|
||||
<b v-text="$t('payment_proof')"></b>:
|
||||
{{ payment.preimage }}
|
||||
</div>
|
||||
|
||||
<div class="row" v-for="entry in extras">
|
||||
<q-badge v-if="hasTag" color="secondary" text-color="white">
|
||||
extra
|
||||
</q-badge>
|
||||
<b>{{ entry.key }}</b>:
|
||||
{{ entry.value }}
|
||||
</div>
|
||||
|
||||
<div class="row" v-if="hasSuccessAction">
|
||||
<b>Success action</b>:
|
||||
<lnbits-lnurlpay-success-action
|
||||
:payment="payment"
|
||||
:success_action="payment.extra.success_action"
|
||||
></lnbits-lnurlpay-success-action>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
`,
|
||||
computed: {
|
||||
hasPreimage() {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"/static/vendor/axios.js",
|
||||
"/static/vendor/vue.js",
|
||||
"/static/vendor/vue-router.js",
|
||||
"/static/vendor/vue-qrcode-reader.browser.js",
|
||||
"/static/vendor/VueQrcodeReader.umd.js",
|
||||
"/static/vendor/vue-qrcode.js",
|
||||
"/static/vendor/vuex.js",
|
||||
"/static/vendor/quasar.ie.polyfills.umd.min.js",
|
||||
@@ -13,13 +13,20 @@
|
||||
"/static/vendor/Chart.bundle.js",
|
||||
"/static/vendor/vue-i18n.js",
|
||||
"/static/i18n/i18n.js",
|
||||
"/static/i18n/en.js",
|
||||
"/static/i18n/de.js",
|
||||
"/static/i18n/en.js",
|
||||
"/static/i18n/es.js",
|
||||
"/static/i18n/fr.js",
|
||||
"/static/i18n/it.js",
|
||||
"/static/i18n/jp.js",
|
||||
"/static/i18n/nl.js",
|
||||
"/static/i18n/pi.js",
|
||||
"/static/i18n/pl.js",
|
||||
"/static/i18n/fr.js",
|
||||
"/static/i18n/nl.js",
|
||||
"/static/i18n/we.js",
|
||||
"/static/i18n/pt.js",
|
||||
"/static/i18n/br.js",
|
||||
"/static/js/base.js",
|
||||
"/static/js/components.js",
|
||||
"/static/js/bolt11-decoder.js"
|
||||
@@ -27,7 +34,6 @@
|
||||
"css": [
|
||||
"/static/vendor/quasar.css",
|
||||
"/static/vendor/Chart.css",
|
||||
"/static/vendor/vue-qrcode-reader.css",
|
||||
"/static/css/base.css"
|
||||
]
|
||||
}
|
||||
|
||||
+11616
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
-1
@@ -1 +0,0 @@
|
||||
.wrapper[data-v-1f90552a]{position:relative;z-index:0;width:100%;height:100%}.overlay[data-v-1f90552a],.tracking-layer[data-v-1f90552a]{position:absolute;width:100%;height:100%;top:0;left:0}.camera[data-v-1f90552a],.pause-frame[data-v-1f90552a]{display:block;object-fit:cover;width:100%;height:100%}
|
||||
+41
-39
@@ -40,15 +40,24 @@
|
||||
<span><strong>LN</strong>bits</span> {% endif %} {%endif%} {%
|
||||
endblock %}
|
||||
</q-btn>
|
||||
{% block toolbar_subtitle %}{%if user and user.super_user%}
|
||||
<q-badge align="middle">Super User</q-badge>
|
||||
{% elif user and user.admin %}
|
||||
<q-badge align="middle">Admin User</q-badge>
|
||||
{%endif%}{% endblock %}
|
||||
</q-toolbar-title>
|
||||
{% block beta %} {% if VOIDWALLET %}
|
||||
<q-badge color="red" text-color="black" class="q-mr-md">
|
||||
{% raw %}{{ $t('voidwallet_active') }}{% endraw %}
|
||||
</q-badge>
|
||||
{%endif%}
|
||||
<q-badge color="yellow" text-color="black" class="q-mr-md">
|
||||
<q-badge
|
||||
v-show="$q.screen.gt.sm"
|
||||
color="yellow"
|
||||
text-color="black"
|
||||
class="q-mr-md"
|
||||
>
|
||||
<span
|
||||
v-show="$q.screen.gt.sm"
|
||||
v-text='$t("use_with_caution", { name: "{{ SITE_TITLE }}" })'
|
||||
></span>
|
||||
</q-badge>
|
||||
@@ -69,40 +78,18 @@
|
||||
icon="language"
|
||||
class="q-pl-md"
|
||||
>
|
||||
<q-list>
|
||||
<q-item clickable v-close-popup @click="changeLanguage('en')">
|
||||
<q-item-section>
|
||||
<q-item-label>EN</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable v-close-popup @click="changeLanguage('de')">
|
||||
<q-item-section>
|
||||
<q-item-label>DE</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable v-close-popup @click="changeLanguage('es')">
|
||||
<q-item-section>
|
||||
<q-item-label>ES</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable v-close-popup @click="changeLanguage('jp')">
|
||||
<q-item-section>
|
||||
<q-item-label>JP</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable v-close-popup @click="changeLanguage('fr')">
|
||||
<q-item-section>
|
||||
<q-item-label>FR</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable v-close-popup @click="changeLanguage('pi')">
|
||||
<q-item-section>
|
||||
<q-item-label>PI</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable v-close-popup @click="changeLanguage('nl')">
|
||||
<q-item-section>
|
||||
<q-item-label>NL</q-item-label>
|
||||
<q-list v-for="(lang, index) in g.langs" :key="index">
|
||||
<q-item
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="changeLanguage(lang.value)"
|
||||
><q-item-section>
|
||||
{% raw %}
|
||||
<q-item-label
|
||||
>{{lang.display ?? lang.value.toUpperCase()}}</q-item-label
|
||||
>
|
||||
<q-tooltip>{{lang.label}}</q-tooltip>
|
||||
{% endraw %}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
@@ -251,6 +238,7 @@
|
||||
class="bg-transparent q-px-lg q-py-md"
|
||||
:class="{'text-dark': !$q.dark.isActive}"
|
||||
>
|
||||
<q-space class="q-py-lg lt-sm"></q-space>
|
||||
<q-toolbar class="gt-sm">
|
||||
<q-toolbar-title class="text-caption">
|
||||
{{ SITE_TITLE }}, {{SITE_TAGLINE}}
|
||||
@@ -304,11 +292,25 @@
|
||||
{% endfor %}
|
||||
<!---->
|
||||
<script type="text/javascript">
|
||||
const themes = {{ LNBITS_THEME_OPTIONS | tojson }}
|
||||
const LNBITS_DENOMINATION = {{ LNBITS_DENOMINATION | tojson}}
|
||||
if(themes && themes.length) {
|
||||
const themes = {{ LNBITS_THEME_OPTIONS | tojson }}
|
||||
const LNBITS_DENOMINATION = {{ LNBITS_DENOMINATION | tojson }}
|
||||
if (themes && themes.length) {
|
||||
window.allowedThemes = themes.map(str => str.trim())
|
||||
}
|
||||
window.langs = [
|
||||
{value: 'en', label: 'English', display: 'EN'},
|
||||
{value: 'de', label: 'Deutsch', display: 'DE'},
|
||||
{value: 'es', label: 'Español', display: 'ES'},
|
||||
{value: 'jp', label: '日本語', display: 'JP'},
|
||||
{value: 'fr', label: 'Français', display: 'FR'},
|
||||
{value: 'it', label: 'Italiano', display: 'IT'},
|
||||
{value: 'pi', label: 'Pirate', display: 'PI'},
|
||||
{value: 'nl', label: 'Nederlands', display: 'NL'},
|
||||
{value: 'we', label: 'Cymraeg', display: 'CY'},
|
||||
{value: 'pl', label: 'Polski', display: 'PL'},
|
||||
{value: 'pt', label: 'Português', display: 'PT'},
|
||||
{value: 'br', label: 'Português', display: 'BR'}
|
||||
]
|
||||
</script>
|
||||
{% block scripts %}{% endblock %}
|
||||
</body>
|
||||
|
||||
@@ -69,7 +69,7 @@ class CoreLightningWallet(Wallet):
|
||||
try:
|
||||
funds = self.ln.listfunds()
|
||||
return StatusResponse(
|
||||
None, sum([ch["channel_sat"] * 1000 for ch in funds["channels"]])
|
||||
None, sum([int(ch["our_amount_msat"]) for ch in funds["channels"]])
|
||||
)
|
||||
except RpcError as exc:
|
||||
error_message = f"lightningd '{exc.method}' failed with '{exc.error}'."
|
||||
@@ -141,7 +141,7 @@ class CoreLightningWallet(Wallet):
|
||||
except Exception as exc:
|
||||
return PaymentResponse(False, None, None, None, str(exc))
|
||||
|
||||
fee_msat = -int(r["msatoshi_sent"] - r["msatoshi"])
|
||||
fee_msat = -int(r["amount_sent_msat"] - r["amount_msat"])
|
||||
return PaymentResponse(
|
||||
True, r["payment_hash"], fee_msat, r["payment_preimage"], None
|
||||
)
|
||||
|
||||
Generated
+21
-44
@@ -14,7 +14,7 @@
|
||||
"underscore": "^1.13.6",
|
||||
"vue": "2.6.12",
|
||||
"vue-i18n": "^8.28.2",
|
||||
"vue-qrcode-reader": "2.2",
|
||||
"vue-qrcode-reader": "^2.3.18",
|
||||
"vue-router": "3.4.3",
|
||||
"vuex": "3.5.1"
|
||||
},
|
||||
@@ -172,16 +172,6 @@
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/babel-runtime": {
|
||||
"version": "6.26.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
|
||||
"integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"core-js": "^2.4.0",
|
||||
"regenerator-runtime": "^0.11.0"
|
||||
}
|
||||
},
|
||||
"node_modules/binary-extensions": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||
@@ -367,11 +357,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/core-js": {
|
||||
"version": "2.6.12",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
|
||||
"integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
|
||||
"version": "3.30.2",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.30.2.tgz",
|
||||
"integrity": "sha512-uBJiDmwqsbJCWHAwjrx3cvjbMXP7xD72Dmsn5LOJpiRmE3WbBbN5rCqQ2Qh6Ek6/eOrjlWngEynBWo4VxerQhg==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT"
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/core-js"
|
||||
}
|
||||
},
|
||||
"node_modules/css-b64-images": {
|
||||
"version": "0.2.5",
|
||||
@@ -657,12 +650,6 @@
|
||||
"integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/jsqr": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/jsqr/-/jsqr-1.4.0.tgz",
|
||||
"integrity": "sha512-dxLob7q65Xg2DvstYkRpkYtmKm2sPJ9oFhrhmudT1dZvNFFTlroai3AWSpLey/w5vMcLBXRgOJsbXpdN9HzU/A==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/locate-path": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
||||
@@ -1008,12 +995,6 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/regenerator-runtime": {
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
||||
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/relateurl": {
|
||||
"version": "0.2.7",
|
||||
"resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
|
||||
@@ -1042,7 +1023,6 @@
|
||||
"version": "1.2.15",
|
||||
"resolved": "https://registry.npmjs.org/rtcpeerconnection-shim/-/rtcpeerconnection-shim-1.2.15.tgz",
|
||||
"integrity": "sha512-C6DxhXt7bssQ1nHb154lqeL0SXz5Dx4RczXZu2Aa/L1NJFnEVDxFwCBo3fqtuljhHIGceg5JKBV4XJ0gW5JKyw==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"sdp": "^2.6.0"
|
||||
},
|
||||
@@ -1071,8 +1051,7 @@
|
||||
"node_modules/sdp": {
|
||||
"version": "2.12.0",
|
||||
"resolved": "https://registry.npmjs.org/sdp/-/sdp-2.12.0.tgz",
|
||||
"integrity": "sha512-jhXqQAQVM+8Xj5EjJGVweuEzgtGWb3tmEEpl3CLP3cStInSbVHSg0QWOGQzNq8pSID4JkpeV2mPqlMDLrm0/Vw==",
|
||||
"license": "MIT"
|
||||
"integrity": "sha512-jhXqQAQVM+8Xj5EjJGVweuEzgtGWb3tmEEpl3CLP3cStInSbVHSg0QWOGQzNq8pSID4JkpeV2mPqlMDLrm0/Vw=="
|
||||
},
|
||||
"node_modules/set-blocking": {
|
||||
"version": "2.0.0",
|
||||
@@ -1217,15 +1196,14 @@
|
||||
"integrity": "sha512-C5GZjs1tYlAqjwymaaCPDjCyGo10ajUphiwA922jKt9n7KPpqR7oM1PCwYzhB/E7+nT3wfdG3oRre5raIT1rKA=="
|
||||
},
|
||||
"node_modules/vue-qrcode-reader": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-qrcode-reader/-/vue-qrcode-reader-2.2.0.tgz",
|
||||
"integrity": "sha512-xsNptrJGTFFjwfksIK6KlbjsyIGBLTFgO9KH3JcmZzABY19c2d0+zG//LXkp8K2Jl+4APidktVtH/aTbmcgX7g==",
|
||||
"license": "MIT",
|
||||
"version": "2.3.18",
|
||||
"resolved": "https://registry.npmjs.org/vue-qrcode-reader/-/vue-qrcode-reader-2.3.18.tgz",
|
||||
"integrity": "sha512-r+nrIZQ+0helU3nfioh84iZDw39nh0w8NjMtOnWcM/3pqr9MOyUV1dkZWD144N1LB3/z5gUOAWkWHJ+6lq6rUA==",
|
||||
"dependencies": {
|
||||
"babel-runtime": "^6.26.0",
|
||||
"callforth": "^0.3.0",
|
||||
"jsqr": "^1.2.0",
|
||||
"webrtc-adapter": "^6.2.1"
|
||||
"callforth": "^0.3.1",
|
||||
"core-js": "^3.6.5",
|
||||
"vue": "^2.6.11",
|
||||
"webrtc-adapter": "7.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-router": {
|
||||
@@ -1242,13 +1220,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/webrtc-adapter": {
|
||||
"version": "6.4.8",
|
||||
"resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-6.4.8.tgz",
|
||||
"integrity": "sha512-YM8yl545c/JhYcjGHgaCoA7jRK/KZuMwEDFeP2AcP0Auv5awEd+gZE0hXy9z7Ed3p9HvAXp8jdbe+4ESb1zxAw==",
|
||||
"license": "BSD-3-Clause",
|
||||
"version": "7.7.0",
|
||||
"resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-7.7.0.tgz",
|
||||
"integrity": "sha512-7Bp9OBnx642oJRkom1tNAbeJjUadAq2rh5xLL9YXPw5hVyt2h4hHr5bcoPYDs1stp/mZHSPSQA34YISdnr0DBQ==",
|
||||
"dependencies": {
|
||||
"rtcpeerconnection-shim": "^1.2.14",
|
||||
"sdp": "^2.9.0"
|
||||
"rtcpeerconnection-shim": "^1.2.15",
|
||||
"sdp": "^2.12.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0",
|
||||
|
||||
+13
-8
@@ -12,9 +12,9 @@
|
||||
"devDependencies": {
|
||||
"concat": "^1.0.3",
|
||||
"minify": "^9.2.0",
|
||||
"sass": "^1.60.0",
|
||||
"prettier": "2.8.3",
|
||||
"pyright": "1.1.289"
|
||||
"pyright": "1.1.289",
|
||||
"sass": "^1.60.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@chenfengyuan/vue-qrcode": "1.0.2",
|
||||
@@ -25,7 +25,7 @@
|
||||
"underscore": "^1.13.6",
|
||||
"vue": "2.6.12",
|
||||
"vue-i18n": "^8.28.2",
|
||||
"vue-qrcode-reader": "2.2",
|
||||
"vue-qrcode-reader": "^2.3.18",
|
||||
"vue-router": "3.4.3",
|
||||
"vuex": "3.5.1"
|
||||
},
|
||||
@@ -35,7 +35,7 @@
|
||||
"./node_modules/axios/dist/axios.js",
|
||||
"./node_modules/vue/dist/vue.js",
|
||||
"./node_modules/vue-router/dist/vue-router.js",
|
||||
"./node_modules/vue-qrcode-reader/dist/vue-qrcode-reader.browser.js",
|
||||
"./node_modules/vue-qrcode-reader/dist/VueQrcodeReader.umd.js",
|
||||
"./node_modules/@chenfengyuan/vue-qrcode/dist/vue-qrcode.js",
|
||||
"./node_modules/vuex/dist/vuex.js",
|
||||
"./node_modules/quasar/dist/quasar.ie.polyfills.umd.min.js",
|
||||
@@ -43,7 +43,6 @@
|
||||
"./node_modules/chart.js/dist/Chart.bundle.js",
|
||||
"./node_modules/quasar/dist/quasar.css",
|
||||
"./node_modules/chart.js/dist/Chart.css",
|
||||
"./node_modules/vue-qrcode-reader/dist/vue-qrcode-reader.css",
|
||||
"./node_modules/vue-i18n/dist/vue-i18n.js"
|
||||
],
|
||||
"bundle": {
|
||||
@@ -53,7 +52,7 @@
|
||||
"/static/vendor/axios.js",
|
||||
"/static/vendor/vue.js",
|
||||
"/static/vendor/vue-router.js",
|
||||
"/static/vendor/vue-qrcode-reader.browser.js",
|
||||
"/static/vendor/VueQrcodeReader.umd.js",
|
||||
"/static/vendor/vue-qrcode.js",
|
||||
"/static/vendor/vuex.js",
|
||||
"/static/vendor/quasar.ie.polyfills.umd.min.js",
|
||||
@@ -61,13 +60,20 @@
|
||||
"/static/vendor/Chart.bundle.js",
|
||||
"/static/vendor/vue-i18n.js",
|
||||
"/static/i18n/i18n.js",
|
||||
"/static/i18n/en.js",
|
||||
"/static/i18n/de.js",
|
||||
"/static/i18n/en.js",
|
||||
"/static/i18n/es.js",
|
||||
"/static/i18n/fr.js",
|
||||
"/static/i18n/it.js",
|
||||
"/static/i18n/jp.js",
|
||||
"/static/i18n/nl.js",
|
||||
"/static/i18n/pi.js",
|
||||
"/static/i18n/pl.js",
|
||||
"/static/i18n/fr.js",
|
||||
"/static/i18n/nl.js",
|
||||
"/static/i18n/we.js",
|
||||
"/static/i18n/pt.js",
|
||||
"/static/i18n/br.js",
|
||||
"/static/js/base.js",
|
||||
"/static/js/components.js",
|
||||
"/static/js/bolt11-decoder.js"
|
||||
@@ -75,7 +81,6 @@
|
||||
"css": [
|
||||
"/static/vendor/quasar.css",
|
||||
"/static/vendor/Chart.css",
|
||||
"/static/vendor/vue-qrcode-reader.css",
|
||||
"/static/css/base.css"
|
||||
]
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "lnbits"
|
||||
version = "0.10.6"
|
||||
version = "0.10.8"
|
||||
description = "LNbits, free and open-source Lightning wallet and accounts system."
|
||||
authors = ["Alan Bits <alan@lnbits.com>"]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user