mirror of
https://github.com/lnbits/lnbits-legend.git
synced 2025-03-13 19:37:42 +01:00
350 lines
12 KiB
HTML
350 lines
12 KiB
HTML
{% extends "base.html" %} {% from "macros.jinja" import window_vars with context
|
|
%} {% block page %}
|
|
|
|
<q-dialog v-model="thingDialog.show" position="top">
|
|
<q-card class="q-pa-lg q-pt-xl lnbits__dialog-card">
|
|
<q-form @submit="sendThingDialog" class="q-gutter-md">
|
|
<q-input
|
|
filled
|
|
dense
|
|
v-model.trim="thingDialog.data.name"
|
|
type="text"
|
|
label="Name *"
|
|
></q-input>
|
|
<q-input
|
|
filled
|
|
dense
|
|
v-model.trim="thingDialog.data.email"
|
|
type="email"
|
|
label="Name *"
|
|
></q-input>
|
|
<q-select
|
|
filled
|
|
dense
|
|
emit-value
|
|
v-model="thingDialog.data.wallet"
|
|
:options="g.user.walletOptions"
|
|
label="Wallet *"
|
|
></q-select>
|
|
<div class="row q-mt-lg">
|
|
<q-btn
|
|
v-if="thingDialog.data.id"
|
|
unelevated
|
|
color="primary"
|
|
type="submit"
|
|
>Update thing</q-btn
|
|
>
|
|
<q-btn
|
|
v-else
|
|
unelevated
|
|
color="primary"
|
|
:disable="thingDialog.data.name == null"
|
|
type="submit"
|
|
>Create thing</q-btn
|
|
>
|
|
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Cancel</q-btn>
|
|
</div>
|
|
</q-form>
|
|
</q-card>
|
|
</q-dialog>
|
|
|
|
<q-card flat>
|
|
<q-card-section>
|
|
<div class="text-h5 q-mb-md">
|
|
{{SITE_TITLE}} Extension Development Guide
|
|
<small>(Collection of resources for extension developers)</small>
|
|
</div>
|
|
|
|
<q-card unelevated flat>
|
|
<q-tabs
|
|
v-model="tab"
|
|
dense
|
|
class="text-grey"
|
|
active-color="primary"
|
|
indicator-color="primary"
|
|
align="justify"
|
|
narrow-indicator
|
|
>
|
|
<q-tab name="frameworks" label="Frameworks"></q-tab>
|
|
<q-tab name="tools" label="Useful Tools"></q-tab>
|
|
<q-tab name="structure" label="File Structure"></q-tab>
|
|
<q-tab name="enviroment" label="Dev Enviroment"></q-tab>
|
|
<q-tab name="submission" label="Submisson to LNbits repo"></q-tab>
|
|
</q-tabs>
|
|
|
|
<q-separator></q-separator>
|
|
|
|
<q-tab-panels v-model="tab">
|
|
<q-tab-panel name="frameworks">
|
|
<div class="text-h6">Frameworks</div>
|
|
|
|
<div>
|
|
<q-splitter v-model="splitterModel">
|
|
<template v-slot:before>
|
|
<q-tabs v-model="framworktab" vertical>
|
|
<q-tab name="fastapi"
|
|
><img src="./static/fastapi-framework.png" />FASTAPI</q-tab
|
|
>
|
|
<q-tab name="quasar"
|
|
><img src="./static/quasar-framework.png" />QUASAR</q-tab
|
|
>
|
|
<q-tab name="vuejs"
|
|
><img src="./static/vuejs-framework.png" />VUE-JS</q-tab
|
|
>
|
|
</q-tabs>
|
|
</template>
|
|
|
|
<template v-slot:after>
|
|
<q-tab-panels v-model="framworktab">
|
|
<q-tab-panel name="fastapi" class="text-body1">
|
|
<a href="https://fastapi.tiangolo.com/"
|
|
><img src="./static/fastapilogo.png"
|
|
/></a>
|
|
<p>
|
|
LNbits API is built using
|
|
<a
|
|
href="https://fastapi.tiangolo.com/"
|
|
class="text-primary"
|
|
>FastAPI</a
|
|
>, a high-performance, easy to code API framework.<br /><br />
|
|
FastAPI auto-generates swagger UI docs for testing
|
|
endpoints <a class="text-primary" href="../docs">/docs</a>
|
|
</p>
|
|
|
|
<i>
|
|
<strong>TIP:</strong> Although it is possible for
|
|
extensions to use other extensions API endpoints (such as
|
|
with the Satspay and Onchain extension), ideally an
|
|
extension should only use LNbits
|
|
<a href="../docs#/default" class="text-primary">core</a>
|
|
endpoints. </i
|
|
><br /><br />
|
|
|
|
<code class="bg-grey-3 text-black">views.py</code> is used
|
|
for setting application routes:
|
|
<img src="./static/fastapi-example.png" />
|
|
<code class="bg-grey-3 text-black">views_api.py</code> is
|
|
used for setting application API endpoints:
|
|
<img src="./static/fastapi-example2.png" />
|
|
</q-tab-panel>
|
|
|
|
<q-tab-panel name="quasar" class="text-body1">
|
|
<a href="https://quasar.dev/"
|
|
><img src="./static/quasarlogo.png"
|
|
/></a>
|
|
<p>
|
|
LNbits uses
|
|
<a class="text-primary" href="https://quasar.dev/"
|
|
>Quasar Framework</a
|
|
>
|
|
for frontend deisgn elements. Quasar Framework is an
|
|
open-source Vue.js based framework for building apps.
|
|
</p>
|
|
|
|
<i>
|
|
<strong>TIP:</strong> Look through
|
|
<code class="bg-grey-3 text-black">/template</code> files
|
|
in other extensions for examples of Quasar elements being
|
|
used. </i
|
|
><br /><br />
|
|
|
|
<p>
|
|
In the below example we make a dialogue popup box (box can
|
|
be triggered
|
|
<q-btn
|
|
size="sm"
|
|
color="primary"
|
|
@click="thingDialog.show = true"
|
|
>here</q-btn
|
|
>): <q-tooltip>Exmple of a tooltip!</q-tooltip>
|
|
</p>
|
|
<img src="./static/quasar-example.png" /><br /><br />
|
|
<div class="text-h6">Useful links:</div>
|
|
<q-btn
|
|
color="primary"
|
|
type="a"
|
|
href="https://quasar.dev/style/"
|
|
>Style (typography, spacing, etc)</q-btn
|
|
>
|
|
<q-btn
|
|
color="primary"
|
|
type="a"
|
|
href="https://quasar.dev/vue-components/"
|
|
>Genral components (cards, buttons, popup dialogs,
|
|
etc)</q-btn
|
|
>
|
|
<q-btn
|
|
color="primary"
|
|
type="a"
|
|
href="https://quasar.dev/layout/grid"
|
|
>Layouts (rows/columns, flexbox)</q-btn
|
|
>
|
|
</q-tab-panel>
|
|
|
|
<q-tab-panel
|
|
v-if="someBool == true"
|
|
name="vuejs"
|
|
class="text-body1"
|
|
>
|
|
<a href="https://vuejs.org/">
|
|
<img src="./static/vuejslogo.png"
|
|
/></a>
|
|
<p>
|
|
LNbits uses
|
|
<a href="https://vuejs.org/" class="text-primary">Vue</a>
|
|
components for best-in-class high-performance and
|
|
responsive performance.
|
|
</p>
|
|
|
|
<p>
|
|
Typical example of Vue components in a frontend script:
|
|
</p>
|
|
<img
|
|
src="./static/script-example.png"
|
|
style="max-width: 800px"
|
|
/><br /><br />
|
|
|
|
<p>
|
|
In a page body, models can be called. <br />Content can be
|
|
conditionally rendered using Vue's
|
|
<code class="bg-grey-3 text-black">v-if</code>:
|
|
</p>
|
|
<img
|
|
src="./static/vif-example.png"
|
|
style="max-width: 800px"
|
|
/>
|
|
</q-tab-panel>
|
|
</q-tab-panels>
|
|
</template>
|
|
</q-splitter>
|
|
</div>
|
|
</q-tab-panel>
|
|
|
|
<q-tab-panel name="tools">
|
|
<div class="text-h6">Useful Tools</div>
|
|
<div>
|
|
<q-splitter v-model="splitterModel">
|
|
<template v-slot:before>
|
|
<q-tabs v-model="usefultab" vertical>
|
|
<q-tab name="magicalg">MAGICAL G</q-tab>
|
|
<q-tab name="exchange">EXCHANGE RATES</q-tab>
|
|
</q-tabs>
|
|
</template>
|
|
|
|
<template v-slot:after>
|
|
<q-tab-panels v-model="usefultab">
|
|
<q-tab-panel name="magicalg" class="text-body1">
|
|
<div class="text-h5 q-mb-md">Magical G</div>
|
|
<p>
|
|
A magical "g" (ie
|
|
<code class="bg-grey-3 text-black"
|
|
>this.g.user.wallets[0].inkey</code
|
|
>) is always available, with info about the user, wallets
|
|
and extensions:
|
|
</p>
|
|
<code class="text-caption"
|
|
>{% raw %}{{ g }}{% endraw %}</code
|
|
>
|
|
</q-tab-panel>
|
|
<q-tab-panel name="exchange">
|
|
<div class="text-h6">Exchange rates</div>
|
|
<p>
|
|
LNbits includes a handy
|
|
<a
|
|
href="../docs#/default/api_fiat_as_sats_api_v1_conversion_post"
|
|
class="text-primary"
|
|
>exchange rate function</a
|
|
>, that streams rates from 6 different sources.
|
|
</p>
|
|
Exchange rate API:<br />
|
|
<img src="./static/conversion-example.png" /><br /><br />
|
|
Exchange rate functions, included using
|
|
<code class="bg-grey-3 text-black"
|
|
>from lnbits.utils.exchange_rates import
|
|
fiat_amount_as_satoshis</code
|
|
>:<br />
|
|
<img src="./static/conversion-example2.png" />
|
|
</q-tab-panel>
|
|
</q-tab-panels>
|
|
</template>
|
|
</q-splitter>
|
|
</div>
|
|
</q-tab-panel>
|
|
|
|
<q-tab-panel name="structure">
|
|
<div class="text-h6">File Structure</div>
|
|
Coming soon...
|
|
</q-tab-panel>
|
|
|
|
<q-tab-panel name="enviroment">
|
|
<div class="text-h6">Dev Enviroment</div>
|
|
Coming soon...
|
|
</q-tab-panel>
|
|
|
|
<q-tab-panel name="submission">
|
|
<div class="text-h6">Submission</div>
|
|
Coming soon...
|
|
</q-tab-panel>
|
|
</q-tab-panels>
|
|
</q-card>
|
|
</q-card-section>
|
|
</q-card>
|
|
{% endblock %} {% block scripts %} {{ window_vars(user) }}
|
|
|
|
<script>
|
|
var someMapObject = obj => {
|
|
obj._data = _.clone(obj)
|
|
obj.date = Quasar.utils.date.formatDate(
|
|
new Date(obj.time * 1000),
|
|
'YYYY-MM-DD HH:mm'
|
|
)
|
|
// here you can do something with the mapped data
|
|
return obj
|
|
}
|
|
new Vue({
|
|
el: '#vue',
|
|
mixins: [windowMixin],
|
|
data: function () {
|
|
return {
|
|
///// Declare models/variables /////
|
|
thingDialog: {
|
|
show: false,
|
|
data: {}
|
|
},
|
|
someBool: true,
|
|
splitterModel: 20,
|
|
exampleData: [],
|
|
tab: 'frameworks',
|
|
framworktab: 'fastapi',
|
|
usefultab: 'magicalg'
|
|
}
|
|
},
|
|
///// Where functions live /////
|
|
methods: {
|
|
exampleFunction(data) {
|
|
var theData = data
|
|
LNbits.api
|
|
.request(
|
|
'GET', // Type of request
|
|
'/example/api/v1/test/' + theData, // URL of the endpoint
|
|
this.g.user.wallets[0].inkey // Often endpoints require a key
|
|
)
|
|
.then(response => {
|
|
this.exampleData = response.data.map(someMapObject) // Often whats returned is mapped onto some model
|
|
})
|
|
.catch(error => {
|
|
LNbits.utils.notifyApiError(error) // Error will be passed to the frontend
|
|
})
|
|
},
|
|
sendThingDialog() {
|
|
console.log(this.thingDialog)
|
|
}
|
|
},
|
|
///// To run on startup /////
|
|
created: function () {
|
|
self = this // Often used to run a real object, rather than the event (all a bit confusing really)
|
|
self.exampleFunction('lorum')
|
|
}
|
|
})
|
|
</script>
|
|
{% endblock %}
|