lnbits-legend/lnbits/static/js/init-app.js
2025-01-16 13:23:34 +02:00

206 lines
5.2 KiB
JavaScript

const DynamicComponent = {
props: {
fetchUrl: {
type: String,
required: true
},
scripts: {
type: Array,
default: () => []
}
},
async mounted() {
await this.loadDynamicContent()
},
methods: {
async loadScript(src) {
return new Promise((resolve, reject) => {
const existingScript = document.querySelector(`script[src="${src}"]`)
if (existingScript) {
existingScript.remove()
}
const script = document.createElement('script')
script.src = src
script.async = true
script.onload = resolve
script.onerror = () =>
reject(new Error(`Failed to load script: ${src}`))
document.head.appendChild(script)
})
},
async loadDynamicContent() {
this.$q.loading.show()
try {
const cleanUrl = this.fetchUrl.split('#')[0]
//grab page content, need to be before loading scripts
const response = await fetch(cleanUrl, {
credentials: 'include',
headers: {
Accept: 'text/html',
'X-Requested-With': 'XMLHttpRequest'
}
})
const html = await response.text()
// load window variables
const parser = new DOMParser()
const htmlDocument = parser.parseFromString(html, 'text/html')
const inlineScript = htmlDocument.querySelector('#window-vars-script')
if (inlineScript) {
new Function(inlineScript.innerHTML)() // Execute the script
}
//load scripts defined in the route
await this.loadScript('/static/js/base.js')
for (const script of this.scripts) {
await this.loadScript(script)
}
//housecleaning, remove old component
//const previousRouteName =
// this.$router.currentRoute.value.meta.previousRouteName
//if (
// previousRouteName &&
// window.app._context.components[previousRouteName]
//) {
// delete window.app._context.components[previousRouteName]
//}
//load component logic
const logicKey = `${this.$route.name}PageLogic`
const componentLogic = window[logicKey]
if (!componentLogic) {
throw new Error(
`Component logic '${logicKey}' not found. Ensure it is defined in the script.`
)
}
//Add mixins
componentLogic.mixins = componentLogic.mixins || []
if (window.windowMixin) {
componentLogic.mixins.push(window.windowMixin)
}
//Build component
window.app.component(this.$route.name, {
...componentLogic,
template: html // Use the fetched HTML as the template
})
delete window[logicKey] //dont need this anymore
this.$forceUpdate()
} catch (error) {
console.error('Error loading dynamic content:', error)
} finally {
this.$q.loading.hide()
}
}
},
watch: {
$route(to, from) {
const validRouteNames = routes.map(route => route.name)
if (validRouteNames.includes(to.name)) {
this.$router.currentRoute.value.meta.previousRouteName = from.name
this.loadDynamicContent()
} else {
console.log(
`Route '${to.name}' is not valid. Leave this one to Fastapi.`
)
}
}
},
template: `
<component :is="$route.name"></component>
`
}
const routes = [
{
path: '/wallet',
name: 'Wallet',
component: DynamicComponent,
props: route => ({
fetchUrl: `/wallet${route.query.wal ? `?wal=${route.query.wal}` : ''}`,
scripts: ['/static/js/wallet.js']
})
},
{
path: '/admin',
name: 'Admin',
component: DynamicComponent,
props: {
fetchUrl: '/admin',
scripts: ['/static/js/admin.js']
}
},
{
path: '/users',
name: 'Users',
component: DynamicComponent,
props: {
fetchUrl: '/users',
scripts: ['/static/js/users.js']
}
},
{
path: '/audit',
name: 'Audit',
component: DynamicComponent,
props: {
fetchUrl: '/audit',
scripts: ['/static/js/audit.js']
}
},
{
path: '/extensions',
name: 'Extensions',
component: DynamicComponent,
props: {
fetchUrl: '/extensions',
scripts: ['/static/js/extensions.js']
}
},
{
path: '/account',
name: 'Account',
component: DynamicComponent,
props: {
fetchUrl: '/account',
scripts: ['/static/js/account.js']
}
},
{
path: '/node',
name: 'Node',
component: DynamicComponent,
props: {
fetchUrl: '/node',
scripts: ['/static/js/node.js']
}
}
]
window.router = VueRouter.createRouter({
history: VueRouter.createWebHistory(),
routes
})
window.app.mixin({
computed: {
isVueRoute() {
const currentPath = window.location.pathname
const matchedRoute = window.router.resolve(currentPath)
const isVueRoute = matchedRoute?.matched?.length > 0
return isVueRoute
}
}
})
window.app.use(VueQrcodeReader)
window.app.use(Quasar)
window.app.use(window.i18n)
window.app.provide('g', g)
window.app.use(window.router)
window.app.component('DynamicComponent', DynamicComponent)
window.app.mount('#vue')