lnbits/lnbits/templates/base.html
2025-02-07 10:09:15 +02:00

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>