feat: add dynamic errorpage (#3602)
This commit is contained in:
parent
89cabda123
commit
eefaf3c50c
20 changed files with 143 additions and 117 deletions
|
|
@ -221,6 +221,7 @@ async def index(
|
|||
|
||||
|
||||
@generic_router.get("/")
|
||||
@generic_router.get("/error")
|
||||
@generic_router.get("/node/public")
|
||||
@generic_router.get("/first_install", dependencies=[Depends(check_first_install)])
|
||||
async def index_public(request: Request) -> HTMLResponse:
|
||||
|
|
|
|||
2
lnbits/static/bundle-components.min.js
vendored
2
lnbits/static/bundle-components.min.js
vendored
File diff suppressed because one or more lines are too long
2
lnbits/static/bundle.min.css
vendored
2
lnbits/static/bundle.min.css
vendored
File diff suppressed because one or more lines are too long
2
lnbits/static/bundle.min.js
vendored
2
lnbits/static/bundle.min.js
vendored
File diff suppressed because one or more lines are too long
|
|
@ -454,3 +454,12 @@ video {
|
|||
width: 90% !important;
|
||||
}
|
||||
}
|
||||
.error-code {
|
||||
font-size: clamp(15vh, 20vw, 30vh);
|
||||
}
|
||||
|
||||
.error-message {
|
||||
font-size: clamp(1.5rem, 3vw, 3.75rem);
|
||||
font-weight: 300;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
|
|
|||
53
lnbits/static/js/components/lnbits-error.js
Normal file
53
lnbits/static/js/components/lnbits-error.js
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
window.app.component('lnbits-error', {
|
||||
template: '#lnbits-error',
|
||||
mixins: [window.windowMixin],
|
||||
props: ['dynamic', 'code', 'message'],
|
||||
computed: {
|
||||
isExtension() {
|
||||
if (this.code != 403) return false
|
||||
if (this.message.startsWith('Extension ')) return true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goBack() {
|
||||
window.history.back()
|
||||
},
|
||||
goHome() {
|
||||
window.location = '/'
|
||||
},
|
||||
goToWallet() {
|
||||
if (this.dynamic) {
|
||||
this.$router.push('/wallet')
|
||||
return
|
||||
}
|
||||
window.location = '/wallet'
|
||||
},
|
||||
goToExtension() {
|
||||
const extension = this.message.match(/'([^']+)'/)[1]
|
||||
const url = `/extensions#${extension}`
|
||||
if (this.dynamic) {
|
||||
this.$router.push(url)
|
||||
return
|
||||
}
|
||||
window.location = url
|
||||
},
|
||||
async logOut() {
|
||||
try {
|
||||
await LNbits.api.logout()
|
||||
window.location = '/'
|
||||
} catch (e) {
|
||||
LNbits.utils.notifyApiError(e)
|
||||
}
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
// check if we have error from error.html
|
||||
if (!this.dynamic) {
|
||||
if (this.code == 401) {
|
||||
console.warn(`Unauthorized: ${this.errorMessage}`)
|
||||
this.logOut()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -9,6 +9,8 @@ const localStore = (key, defaultValue) => {
|
|||
}
|
||||
|
||||
window.g = Vue.reactive({
|
||||
errorCode: null,
|
||||
errorMessage: null,
|
||||
isUserAuthorized: !!Quasar.Cookies.get('is_lnbits_user_authorized'),
|
||||
offline: !navigator.onLine,
|
||||
hasCamera: false,
|
||||
|
|
|
|||
|
|
@ -78,6 +78,11 @@ const routes = [
|
|||
path: '/',
|
||||
name: 'PageHome',
|
||||
component: PageHome
|
||||
},
|
||||
{
|
||||
path: '/error',
|
||||
name: 'PageError',
|
||||
component: PageError
|
||||
}
|
||||
]
|
||||
|
||||
|
|
|
|||
4
lnbits/static/js/pages/error.js
Normal file
4
lnbits/static/js/pages/error.js
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
window.PageError = {
|
||||
template: '#page-error',
|
||||
mixins: [window.windowMixin]
|
||||
}
|
||||
|
|
@ -604,16 +604,17 @@ window.PageWallet = {
|
|||
this.decodeRequest()
|
||||
this.parse.show = true
|
||||
}
|
||||
let wallet = g.user.wallets.find(w => w.id === this.$route.params.id)
|
||||
if (!wallet) {
|
||||
const walletId = g.lastActiveWallet || g.user.wallets[0].id
|
||||
wallet = g.user.wallets.find(w => w.id === walletId)
|
||||
// TODO: should show PageError(404) if wallet not found
|
||||
const wallet = g.user.wallets.find(w => w.id === this.$route.params.id)
|
||||
if (wallet) {
|
||||
this.g.wallet = wallet
|
||||
this.g.lastActiveWallet = wallet.id
|
||||
this.$q.localStorage.setItem('lnbits.lastActiveWallet', wallet.id)
|
||||
this.$router.replace(`/wallet/${wallet.id}`)
|
||||
} else {
|
||||
this.g.errorCode = 404
|
||||
this.g.errorMessage = 'Wallet not found.'
|
||||
this.$router.push('/error')
|
||||
}
|
||||
this.g.wallet = wallet
|
||||
this.g.lastActiveWallet = wallet.id
|
||||
this.$q.localStorage.setItem('lnbits.lastActiveWallet', wallet.id)
|
||||
this.$router.replace(`/wallet/${wallet.id}`)
|
||||
},
|
||||
watch: {
|
||||
'g.updatePaymentsHash'() {
|
||||
|
|
|
|||
|
|
@ -197,3 +197,12 @@ video {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.error-code {
|
||||
font-size: clamp(15vh, 20vw, 30vh);
|
||||
}
|
||||
.error-message {
|
||||
font-size: clamp(1.5rem, calc(1.5 / 10 * 20vw), 3.75rem);
|
||||
font-weight: 300;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
"js/bolt11-decoder.js"
|
||||
],
|
||||
"components": [
|
||||
"js/pages/error.js",
|
||||
"js/pages/home.js",
|
||||
"js/pages/extensions_builder.js",
|
||||
"js/pages/extensions.js",
|
||||
|
|
@ -75,6 +76,7 @@
|
|||
"js/components/lnbits-wallet-paylinks.js",
|
||||
"js/components/lnbits-wallet-extra.js",
|
||||
"js/components/lnbits-home-logos.js",
|
||||
"js/components/lnbits-error.js",
|
||||
"js/components/lnbits-qrcode.js",
|
||||
"js/components/lnbits-qrcode-lnurl.js",
|
||||
"js/components/lnbits-disclaimer.js",
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@ include('components/lnbits-wallet-api-docs.vue') %} {%
|
|||
include('components/lnbits-wallet-share.vue') %} {%
|
||||
include('components/lnbits-wallet-charts.vue') %} {%
|
||||
include('components/lnbits-wallet-paylinks.vue') %} {%
|
||||
include('components/lnbits-wallet-extra.vue') %}
|
||||
include('components/lnbits-wallet-extra.vue') %} {%
|
||||
include('components/lnbits-error.vue') %}
|
||||
|
||||
<template id="lnbits-manage">
|
||||
<q-list v-if="g.user" dense class="lnbits-drawer__q-list">
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
flat
|
||||
:icon="g.walletFlip ? 'view_list' : 'view_column'"
|
||||
color="grey"
|
||||
class=""
|
||||
@click="g.walletFlip = !g.walletFlip"
|
||||
>
|
||||
<q-tooltip
|
||||
|
|
|
|||
25
lnbits/templates/components/lnbits-error.vue
Normal file
25
lnbits/templates/components/lnbits-error.vue
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<template id="lnbits-error">
|
||||
<div class="text-center q-pa-md flex flex-center">
|
||||
<div>
|
||||
<div class="error-code" v-text="code"></div>
|
||||
<div class="error-message" v-text="message"></div>
|
||||
<div class="q-mx-auto q-mt-lg justify-center" style="width: max-content">
|
||||
<q-btn
|
||||
v-if="isExtension"
|
||||
color="primary"
|
||||
@click="goToExtension()"
|
||||
label="Go To Extension"
|
||||
></q-btn>
|
||||
<q-btn
|
||||
v-else-if="g.isUserAuthorized"
|
||||
color="primary"
|
||||
@click="goToWallet()"
|
||||
label="Go to Wallet"
|
||||
></q-btn>
|
||||
<q-btn v-else color="primary" @click="goBack()" label="Go Back"></q-btn>
|
||||
<span class="q-mx-md">OR</span>
|
||||
<q-btn color="secondary" @click="goHome()" label="Go Home"></q-btn>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -1,102 +1,5 @@
|
|||
{% extends "public.html" %} {% block page_container %}
|
||||
<q-page-container>
|
||||
<q-page
|
||||
class="q-px-md q-py-lg content-center"
|
||||
:class="{'q-px-lg': $q.screen.gt.xs}"
|
||||
>
|
||||
{% block page %}
|
||||
<div class="text-center q-pa-md flex flex-center">
|
||||
<div v-if="statusCode">
|
||||
<div class="error-code" v-text="statusCode"></div>
|
||||
|
||||
<div class="error-message" v-text="message"></div>
|
||||
|
||||
<div
|
||||
class="q-mx-auto q-mt-lg justify-center"
|
||||
style="width: max-content"
|
||||
>
|
||||
<q-btn
|
||||
v-if="isExtension"
|
||||
color="primary"
|
||||
@click="goToExtension"
|
||||
label="Go To Extension"
|
||||
class="q-mb-lg full-width"
|
||||
></q-btn>
|
||||
<br />
|
||||
<q-btn color="primary" href="/" label="Go Home"></q-btn>
|
||||
<span class="q-mx-md">OR</span>
|
||||
<q-btn color="primary" @click="goBack" label="Go Back"></q-btn>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
</q-page>
|
||||
</q-page-container>
|
||||
{% endblock %} {% block scripts %}
|
||||
<style>
|
||||
.error-code {
|
||||
font-size: clamp(15vh, 20vw, 30vh);
|
||||
}
|
||||
|
||||
.error-message {
|
||||
font-size: clamp(1.5rem, calc(1.5 / 10 * 20vw), 3.75rem);
|
||||
font-weight: 300;
|
||||
opacity: 0.4;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
window.app = Vue.createApp({
|
||||
el: '#vue',
|
||||
mixins: [window.windowMixin],
|
||||
data() {
|
||||
return {
|
||||
err: null,
|
||||
statusCode: null,
|
||||
message: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goBack: function () {
|
||||
window.history.back()
|
||||
},
|
||||
goHome: function () {
|
||||
window.location.href = '/'
|
||||
},
|
||||
goToExtension() {
|
||||
window.location.href = `/extensions#${this.extension}`
|
||||
},
|
||||
async logOut() {
|
||||
|
||||
try {
|
||||
await LNbits.api.logout()
|
||||
window.location = '/'
|
||||
} catch (e) {
|
||||
LNbits.utils.notifyApiError(e)
|
||||
}
|
||||
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isExtension() {
|
||||
if (this.statusCode != 403) return false
|
||||
if (this.message.startsWith('Extension ')) return true
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
this.err = '{{ err }}'
|
||||
const statusCode = '{{ status_code }}' || 404
|
||||
this.message = String({{ message | tojson }}) || 'Page not found'
|
||||
if (statusCode == 401) {
|
||||
console.warn(`Unauthorized: ${this.message}`)
|
||||
this.logOut()
|
||||
return
|
||||
}
|
||||
this.statusCode = statusCode
|
||||
|
||||
if (this.isExtension) {
|
||||
this.extension = this.message.match(/'([^']+)'/)[1]
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
{% extends "public.html" %} {% from "macros.jinja" import window_vars with
|
||||
context %} {% block scripts %} {{ window_vars() }} {% endblock %} {% block
|
||||
page_container %}
|
||||
<lnbits-error code="{{ status_code }}" message="{{ message }}"></lnbits-error>
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -3,4 +3,5 @@ include('pages/audit.vue') %} {% include('pages/wallets.vue') %} {%
|
|||
include('pages/users.vue') %} {% include('pages/admin.vue') %} {%
|
||||
include('pages/account.vue') %} {% include('pages/extensions_builder.vue') %} {%
|
||||
include('pages/extensions.vue') %} {% include('pages/first-install.vue') %} {%
|
||||
include('pages/home.vue') %} {% include('pages/wallet.vue') %}
|
||||
include('pages/home.vue') %} {% include('pages/wallet.vue') %} {%
|
||||
include('pages/error.vue') %}
|
||||
|
|
|
|||
9
lnbits/templates/pages/error.vue
Normal file
9
lnbits/templates/pages/error.vue
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<template id="page-error">
|
||||
<div id="page-error">
|
||||
<lnbits-error
|
||||
:dynamic="true"
|
||||
:code="g.errorCode"
|
||||
:message="g.errorMessage"
|
||||
></lnbits-error>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<template id="page-wallet">
|
||||
<div class="row q-col-gutter-md" style="margin-bottom: 6rem">
|
||||
<div v-if="g.wallet" class="row q-col-gutter-md" style="margin-bottom: 6rem">
|
||||
<div class="col-12 col-md-7 q-gutter-y-md wallet-wrapper">
|
||||
<q-card class="wallet-card">
|
||||
<q-card-section>
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@
|
|||
"js/bolt11-decoder.js"
|
||||
],
|
||||
"components": [
|
||||
"js/pages/error.js",
|
||||
"js/pages/home.js",
|
||||
"js/pages/extensions_builder.js",
|
||||
"js/pages/extensions.js",
|
||||
|
|
@ -127,6 +128,7 @@
|
|||
"js/components/lnbits-wallet-paylinks.js",
|
||||
"js/components/lnbits-wallet-extra.js",
|
||||
"js/components/lnbits-home-logos.js",
|
||||
"js/components/lnbits-error.js",
|
||||
"js/components/lnbits-qrcode.js",
|
||||
"js/components/lnbits-qrcode-lnurl.js",
|
||||
"js/components/lnbits-disclaimer.js",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue