mirror of
https://github.com/lnbits/lnbits.git
synced 2026-08-20 13:37:35 +02:00
442 lines
17 KiB
HTML
442 lines
17 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
{% for url in INCLUDED_CSS %}
|
|
<link
|
|
rel="stylesheet"
|
|
type="text/css"
|
|
href="{{ static_url_for('static', url ) }}"
|
|
/>
|
|
{% endfor %} {% block styles %}{% endblock %}
|
|
<style>
|
|
@font-face {
|
|
font-family: 'Material Icons';
|
|
font-style: normal;
|
|
font-weight: 400;
|
|
src: url("{{ static_url_for('static', 'fonts/material-icons-v50.woff2') }}")
|
|
format('woff2');
|
|
}
|
|
.wallet-list-card {
|
|
margin-top: 1px;
|
|
margin-right: 1rem;
|
|
}
|
|
.wallet-list-card:first-child {
|
|
margin-left: 1px;
|
|
}
|
|
</style>
|
|
<title>{% block title %}{{ SITE_TITLE }}{% endblock %}</title>
|
|
<meta charset="utf-8" />
|
|
<meta
|
|
name="viewport"
|
|
content="width=device-width, initial-scale=1, maximum-scale=1, shrink-to-fit=no"
|
|
/>
|
|
<meta name="mobile-web-app-capable" content="yes" />
|
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
{% if web_manifest %}
|
|
<link async="async" rel="manifest" href="{{ web_manifest }}" />
|
|
{% endif %} {% block head_scripts %}{% endblock %}
|
|
</head>
|
|
|
|
<body data-theme="bitcoin">
|
|
<div id="vue">
|
|
<q-layout view="hHh lpR lfr" v-cloak>
|
|
<q-header bordered class="bg-marginal-bg">
|
|
<q-toolbar>
|
|
{% block drawer_toggle %}
|
|
<q-btn
|
|
dense
|
|
flat
|
|
round
|
|
icon="menu"
|
|
@click="g.visibleDrawer = !g.visibleDrawer"
|
|
></q-btn>
|
|
{% endblock %}
|
|
<q-toolbar-title>
|
|
{% block toolbar_title %}
|
|
<q-btn flat no-caps dense size="lg" type="a" href="/"
|
|
>{% if USE_CUSTOM_LOGO %}
|
|
<img height="30px" alt="Logo" src="{{ USE_CUSTOM_LOGO }}" />
|
|
{%else%} {% if SITE_TITLE != 'LNbits' %} {{ SITE_TITLE }} {%
|
|
else %}
|
|
<span><strong>LN</strong>bits</span> {% endif %} {%endif%} </q-btn
|
|
>{% endblock %} {% block toolbar_subtitle %}
|
|
<q-badge v-if="g.user && g.user.super_user">Super User</q-badge>
|
|
<q-badge v-else-if="g.user && g.user.admin">Admin User</q-badge>
|
|
{% endblock %}
|
|
</q-toolbar-title>
|
|
{% block beta %} {% if VOIDWALLET %}
|
|
<q-badge
|
|
v-text="$t('voidwallet_active')"
|
|
color="red"
|
|
class="q-mr-md gt-md"
|
|
>
|
|
</q-badge>
|
|
{%endif%} {% if LNBITS_CUSTOM_BADGE is not none and
|
|
LNBITS_CUSTOM_BADGE != "" %}
|
|
<q-badge
|
|
v-show="$q.screen.gt.sm"
|
|
color="{{ LNBITS_CUSTOM_BADGE_COLOR }}"
|
|
class="q-mr-md"
|
|
label="{{LNBITS_CUSTOM_BADGE|e}}"
|
|
>
|
|
</q-badge>
|
|
{% endif %} {% if LNBITS_SERVICE_FEE > 0 %}
|
|
<q-badge
|
|
v-show="$q.screen.gt.sm"
|
|
v-if="g.user"
|
|
color="green"
|
|
class="q-mr-md"
|
|
>
|
|
{% if LNBITS_SERVICE_FEE_MAX > 0 %}
|
|
<span
|
|
v-text='$t("service_fee_max", { amount: "{{ LNBITS_SERVICE_FEE }}", max: "{{ LNBITS_SERVICE_FEE_MAX }}"})'
|
|
></span>
|
|
{%else%}
|
|
<span
|
|
v-text='$t("service_fee", { amount: "{{ LNBITS_SERVICE_FEE }}" })'
|
|
></span>
|
|
{%endif%}
|
|
<q-tooltip
|
|
><span v-text='$t("service_fee_tooltip")'></span
|
|
></q-tooltip>
|
|
</q-badge>
|
|
|
|
{%endif%} {% endblock %}
|
|
<q-badge v-if="g.offline" color="red" class="q-mr-md">
|
|
<span>OFFLINE</span>
|
|
</q-badge>
|
|
<q-btn-dropdown
|
|
v-if="isUserAuthorized"
|
|
flat
|
|
rounded
|
|
size="sm"
|
|
class="q-pl-sm"
|
|
>
|
|
<template v-slot:label>
|
|
<div>
|
|
{%if user and user.config and user.config.picture%}
|
|
<img src="{{user.config.picture}}" style="max-width: 32px" />
|
|
{%else%}
|
|
<q-icon name="account_circle" />
|
|
{%endif%}
|
|
</div>
|
|
</template>
|
|
<q-list>
|
|
<q-item to="/account" clickable v-close-popup
|
|
><q-item-section>
|
|
<q-icon name="person" />
|
|
</q-item-section>
|
|
<q-item-section>
|
|
<q-item-label>
|
|
<span v-text="$t('my_account')"></span>
|
|
</q-item-label>
|
|
</q-item-section>
|
|
<q-item-section>
|
|
<q-item-label> </q-item-label>
|
|
</q-item-section>
|
|
</q-item>
|
|
<q-item to="/account#theme" clickable v-close-popup
|
|
><q-item-section>
|
|
<q-icon
|
|
:name="$q.dark.isActive ? 'dark_mode' : 'light_mode'"
|
|
/>
|
|
</q-item-section>
|
|
<q-item-section>
|
|
<q-item-label>
|
|
<span v-text="$t('theme')"></span>
|
|
</q-item-label>
|
|
</q-item-section>
|
|
<q-item-section>
|
|
<q-item-label> </q-item-label>
|
|
</q-item-section>
|
|
</q-item>
|
|
<q-separator></q-separator>
|
|
<q-item clickable v-close-popup @click="logout"
|
|
><q-item-section>
|
|
<q-icon name="logout" />
|
|
</q-item-section>
|
|
<q-item-section>
|
|
<q-item-label>
|
|
<span v-text="$t('logout')"></span>
|
|
</q-item-label>
|
|
</q-item-section>
|
|
<q-item-section>
|
|
<q-item-label> </q-item-label>
|
|
</q-item-section>
|
|
</q-item>
|
|
</q-list>
|
|
</q-btn-dropdown>
|
|
</q-toolbar>
|
|
</q-header>
|
|
|
|
{% block drawer %}
|
|
<q-drawer
|
|
v-model="g.visibleDrawer"
|
|
side="left"
|
|
:width="($q.screen.lt.md) ? 260 : 230"
|
|
show-if-above
|
|
:elevated="$q.screen.lt.md"
|
|
>
|
|
<q-item>
|
|
<q-item-section>
|
|
<q-item-label
|
|
:style="$q.dark.isActive ? 'color:rgba(255, 255, 255, 0.64)' : ''"
|
|
class="q-item__label q-item__label--header q-pa-none"
|
|
header
|
|
v-text="$t('wallets')"
|
|
></q-item-label>
|
|
</q-item-section>
|
|
<q-item-section side>
|
|
<q-btn
|
|
flat
|
|
:icon=" walletFlip ? 'view_list' : 'view_column'"
|
|
color="grey"
|
|
class=""
|
|
@click="flipWallets($q.screen.lt.md)"
|
|
>
|
|
<q-tooltip
|
|
><span
|
|
v-text="walletFlip ? $t('view_list') : $t('view_column')"
|
|
></span
|
|
></q-tooltip>
|
|
</q-btn>
|
|
</q-item-section>
|
|
</q-item>
|
|
<lnbits-wallet-list
|
|
v-if="!walletFlip"
|
|
:balance="balance"
|
|
></lnbits-wallet-list>
|
|
<lnbits-manage
|
|
:show-admin="'{{LNBITS_ADMIN_UI}}' == 'True'"
|
|
:show-users="'{{LNBITS_ADMIN_UI}}' == 'True'"
|
|
:show-audit="'{{LNBITS_AUDIT_ENABLED}}' == 'True'"
|
|
:show-payments="'{{LNBITS_ADMIN_UI}}' == 'True'"
|
|
:show-node="'{{LNBITS_NODE_UI}}' == 'True'"
|
|
:show-extensions="'{{LNBITS_EXTENSIONS_DEACTIVATE_ALL}}' == 'False'"
|
|
></lnbits-manage>
|
|
<lnbits-extension-list class="q-pb-xl"></lnbits-extension-list>
|
|
</q-drawer>
|
|
{% endblock %} {% block page_container %}
|
|
<q-page-container>
|
|
<q-page class="q-px-md q-py-lg" :class="{'q-px-lg': $q.screen.gt.xs}">
|
|
<q-scroll-area
|
|
v-if="walletFlip"
|
|
style="
|
|
height: 130px;
|
|
width: 100%;
|
|
overflow-x: auto;
|
|
overflow-y: hidden;
|
|
mask-image: linear-gradient(
|
|
to right,
|
|
hsl(0 0% 0% / 1) 80%,
|
|
hsl(0 0% 0% / 0)
|
|
);
|
|
"
|
|
>
|
|
<div class="row no-wrap q-pr-md">
|
|
<q-card class="wallet-list-card">
|
|
<q-card-section
|
|
class="flex flex-center column full-height text-center"
|
|
>
|
|
<div>
|
|
<q-btn
|
|
round
|
|
color="primary"
|
|
icon="add"
|
|
@click="showAddWalletDialog.show = true"
|
|
>
|
|
<q-tooltip
|
|
><span v-text="$t('add_wallet')"></span
|
|
></q-tooltip>
|
|
</q-btn>
|
|
<q-dialog
|
|
v-model="showAddWalletDialog.show"
|
|
persistent
|
|
@hide="showAddWalletDialog = {show: false}"
|
|
>
|
|
<q-card style="min-width: 350px">
|
|
<q-card-section>
|
|
<div class="text-h6">Wallet name</div>
|
|
</q-card-section>
|
|
|
|
<q-card-section class="q-pt-none">
|
|
<q-input
|
|
dense
|
|
v-model="showAddWalletDialog.name"
|
|
autofocus
|
|
@keyup.enter="submitAddWallet()"
|
|
></q-input>
|
|
</q-card-section>
|
|
|
|
<q-card-actions align="right" class="text-primary">
|
|
<q-btn flat label="Cancel" v-close-popup></q-btn>
|
|
<q-btn
|
|
flat
|
|
label="Add wallet"
|
|
v-close-popup
|
|
@click="submitAddWallet()"
|
|
></q-btn>
|
|
</q-card-actions>
|
|
</q-card>
|
|
</q-dialog>
|
|
</div>
|
|
</q-card-section>
|
|
</q-card>
|
|
<q-card
|
|
v-for="wallet in g.user.wallets"
|
|
:key="wallet.id"
|
|
clickable
|
|
@click="selectWallet(wallet)"
|
|
class="wallet-list-card"
|
|
style="text-decoration: none"
|
|
:style="
|
|
g.wallet && g.wallet.id === wallet.id
|
|
? `width: 250px; text-decoration: none; cursor: pointer; background-color: ${
|
|
$q.dark.isActive ? 'rgba(255, 255, 255, 0.08)' : 'rgba(0, 0, 0, 0.08)'
|
|
} !important;`
|
|
: 'width: 250px; text-decoration: none; border: 0px; cursor: pointer;'
|
|
"
|
|
:class="{
|
|
'active-wallet-card': g.wallet && g.wallet.id === wallet.id
|
|
}"
|
|
>
|
|
<q-card-section>
|
|
<div class="row items-center">
|
|
<q-avatar
|
|
size="lg"
|
|
:text-color="$q.dark.isActive ? 'black' : 'grey-3'"
|
|
:class="g.wallet && g.wallet.id === wallet.id
|
|
? ''
|
|
: 'disabled'
|
|
"
|
|
:color="g.wallet && g.wallet.id === wallet.id ? wallet.extra.color : wallet.extra.color"
|
|
:icon="g.wallet && g.wallet.id === wallet.id ? wallet.extra.icon : wallet.extra.icon"
|
|
>
|
|
</q-avatar>
|
|
<div
|
|
class="text-h6 q-pl-md"
|
|
:class="{
|
|
'text-bold': g.wallet && g.wallet.id === wallet.id
|
|
}"
|
|
v-text="wallet.name"
|
|
></div>
|
|
</div>
|
|
<div class="row items-center q-pt-sm">
|
|
<h6 class="q-my-none text-no-wrap">
|
|
<strong v-text="wallet.fsat"></strong>
|
|
<small> {{LNBITS_DENOMINATION}}</small>
|
|
</h6>
|
|
</div>
|
|
</q-card-section>
|
|
</q-card>
|
|
</div>
|
|
</q-scroll-area>
|
|
|
|
<router-view v-if="isVueRoute"></router-view>
|
|
|
|
<!-- FastAPI Content -->
|
|
<div v-else>{% block page %}{% endblock %}</div>
|
|
</q-page>
|
|
</q-page-container>
|
|
{% endblock %} {% block footer %}
|
|
|
|
<q-footer
|
|
class="bg-transparent q-px-lg q-py-md"
|
|
:class="{'text-dark': !$q.dark.isActive}"
|
|
>
|
|
<q-space class="q-py-lg lt-md"></q-space>
|
|
<q-toolbar class="gt-sm">
|
|
<q-toolbar-title class="text-caption">
|
|
{{ SITE_TITLE }}, {{SITE_TAGLINE}}
|
|
<br />
|
|
<small
|
|
v-text="$t('lnbits_version') + ': {{LNBITS_VERSION}}'"
|
|
></small>
|
|
</q-toolbar-title>
|
|
<q-space></q-space>
|
|
<q-btn
|
|
flat
|
|
dense
|
|
:color="($q.dark.isActive) ? 'white' : 'primary'"
|
|
type="a"
|
|
href="/docs"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
>
|
|
<span v-text="$t('api_docs')"></span>
|
|
<q-tooltip
|
|
><span v-text="$t('view_swagger_docs')"></span
|
|
></q-tooltip>
|
|
</q-btn>
|
|
<q-btn
|
|
flat
|
|
dense
|
|
:color="($q.dark.isActive) ? 'white' : 'primary'"
|
|
icon="code"
|
|
type="a"
|
|
href="https://github.com/lnbits/lnbits"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
>
|
|
<q-tooltip><span v-text="$t('view_github')"></span></q-tooltip>
|
|
</q-btn>
|
|
</q-toolbar>
|
|
</q-footer>
|
|
|
|
{% endblock %}
|
|
</q-layout>
|
|
</div>
|
|
|
|
{% include('components.vue') %} {% block vue_templates %}{% endblock %} {%
|
|
for url in INCLUDED_JS %}
|
|
<script src="{{ static_url_for('static', url) }}"></script>
|
|
{% endfor %}
|
|
<script type="text/javascript">
|
|
const SITE_DESCRIPTION = {{ SITE_DESCRIPTION | tojson}}
|
|
const themes = {{ LNBITS_THEME_OPTIONS | tojson }}
|
|
const LNBITS_DENOMINATION = {{ LNBITS_DENOMINATION | tojson }}
|
|
const LNBITS_VERSION = {{ LNBITS_VERSION | tojson }}
|
|
const LNBITS_QR_LOGO = {{ LNBITS_QR_LOGO | tojson }}
|
|
const USE_DEFAULT_REACTION = {{ USE_DEFAULT_REACTION | tojson }}
|
|
const USE_DEFAULT_THEME = {{ USE_DEFAULT_THEME | tojson }}
|
|
const USE_DEFAULT_BORDER = {{ USE_DEFAULT_BORDER | tojson }}
|
|
const USE_DEFAULT_GRADIENT = {{ USE_DEFAULT_GRADIENT | lower | tojson }}
|
|
const USE_DEFAULT_BGIMAGE = "{{ USE_DEFAULT_BGIMAGE or None | 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: 'cn', label: '中文', display: '🇨🇳 CN' },
|
|
{ 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 do Brasil', display: '🇧🇷 BR' },
|
|
{ value: 'cs', label: 'Česky', display: '🇨🇿 CS' },
|
|
{ value: 'sk', label: 'Slovensky', display: '🇸🇰 SK' },
|
|
{ value: 'kr', label: '한국어', display: '🇰🇷 KR' },
|
|
{ value: 'fi', label: 'Suomi', display: '🇫🇮 FI' }
|
|
]
|
|
window.LOCALE = 'en'
|
|
window.dateFormat = 'YYYY-MM-DD HH:mm'
|
|
window.i18n = new VueI18n.createI18n({
|
|
locale: window.LOCALE,
|
|
fallbackLocale: window.LOCALE,
|
|
messages: window.localisation
|
|
})
|
|
const websocketPrefix =
|
|
window.location.protocol === 'http:' ? 'ws://' : 'wss://'
|
|
const websocketUrl = `${websocketPrefix}${window.location.host}/api/v1/ws`
|
|
</script>
|
|
{% block scripts %}{% endblock %} {% for url in INCLUDED_COMPONENTS %}
|
|
<script src="{{ static_url_for('static', url) }}"></script>
|
|
{% endfor %}
|
|
</body>
|
|
</html>
|