mirror of
https://github.com/lnbits/lnbits-legend.git
synced 2025-02-26 15:42:30 +01:00
333 lines
10 KiB
HTML
333 lines
10 KiB
HTML
{% extends "base.html" %} {% from "macros.jinja" import window_vars with context
|
|
%} {% block page %}
|
|
<div class="row q-col-gutter-md">
|
|
<div class="col-12 col-md-7 q-gutter-y-md">
|
|
<q-card>
|
|
<q-card-section>
|
|
<div class="row items-center no-wrap q-mb-md">
|
|
<div class="col">
|
|
<h5 class="text-subtitle1 q-my-none">Items</h5>
|
|
</div>
|
|
<div class="col q-ml-lg">
|
|
<q-btn unelevated color="primary" @click="openNewDialog()"
|
|
>Add new item</q-btn
|
|
>
|
|
</div>
|
|
</div>
|
|
{% raw %}
|
|
<q-table
|
|
dense
|
|
flat
|
|
selection="multiple"
|
|
:data="offlineshop.items"
|
|
row-key="id"
|
|
no-data-label="No items for sale yet"
|
|
:pagination="{rowsPerPage: 0}"
|
|
:binary-state-sort="true"
|
|
>
|
|
<template v-slot:header="props">
|
|
<q-tr :props="props">
|
|
<q-th auto-width></q-th>
|
|
<q-th auto-width>Name</q-th>
|
|
<q-th auto-width>Description</q-th>
|
|
<q-th auto-width>Image</q-th>
|
|
<q-th auto-width>Price</q-th>
|
|
<q-th auto-width></q-th>
|
|
</q-tr>
|
|
</template>
|
|
<template v-slot:body="props">
|
|
<q-tr :props="props">
|
|
<q-td auto-width>
|
|
<q-btn
|
|
unelevated
|
|
dense
|
|
size="xs"
|
|
:icon="props.row.enabled ? 'done' : 'block'"
|
|
:color="props.row.enabled ? 'green' : ($q.dark.isActive ? 'grey-7' : 'grey-5')"
|
|
type="a"
|
|
@click="toggleItem(props.row.id)"
|
|
target="_blank"
|
|
></q-btn>
|
|
</q-td>
|
|
<q-td auto-width class="text-center">{{ props.row.name }}</q-td>
|
|
<q-td auto-width> {{ props.row.description }} </q-td>
|
|
<q-td class="text-center" auto-width>
|
|
<img
|
|
v-if="props.row.image"
|
|
:src="props.row.image"
|
|
style="height: 1.5em"
|
|
/>
|
|
</q-td>
|
|
<q-td class="text-center" auto-width>
|
|
{{ props.row.price }} {{ props.row.unit }}
|
|
</q-td>
|
|
<q-td auto-width>
|
|
<q-btn
|
|
flat
|
|
dense
|
|
size="xs"
|
|
@click="openUpdateDialog(props.row.id)"
|
|
icon="edit"
|
|
color="light-blue"
|
|
></q-btn>
|
|
<q-btn
|
|
unelevated
|
|
dense
|
|
size="xs"
|
|
icon="delete"
|
|
color="negative"
|
|
type="a"
|
|
@click="deleteItem(props.row.id)"
|
|
target="_blank"
|
|
></q-btn>
|
|
</q-td>
|
|
</q-tr>
|
|
</template>
|
|
</q-table>
|
|
{% endraw %}
|
|
</q-card-section>
|
|
</q-card>
|
|
|
|
<q-card class="q-pa-sm col-5">
|
|
<q-card-section class="q-pa-none text-center">
|
|
<div class="row">
|
|
<h5 class="text-subtitle1 q-my-none">Wallet Shop</h5>
|
|
</div>
|
|
|
|
<q-form class="q-gutter-md">
|
|
<q-select
|
|
filled
|
|
dense
|
|
:options="g.user.wallets"
|
|
:value="selectedWallet"
|
|
label="Using wallet:"
|
|
option-label="name"
|
|
@input="changedWallet"
|
|
>
|
|
</q-select>
|
|
</q-form>
|
|
|
|
<div v-if="printItems.length > 0" class="row q-gutter-sm q-my-md">
|
|
<q-btn
|
|
type="a"
|
|
outline
|
|
color="secondary"
|
|
:href="'print?items=' + printItems.map(({id}) => id).join(',')"
|
|
>Print QR Codes</q-btn
|
|
>
|
|
</div>
|
|
</q-card-section>
|
|
</q-card>
|
|
|
|
<q-card class="q-pa-sm col-5">
|
|
<q-tabs
|
|
v-model="confirmationMethod"
|
|
no-caps
|
|
class="bg-dark text-white shadow-2"
|
|
>
|
|
<q-tab name="wordlist" label="Wordlist"></q-tab>
|
|
<q-tab name="totp" label="TOTP (Google Authenticator)"></q-tab>
|
|
<q-tab name="none" label="Nothing"></q-tab>
|
|
</q-tabs>
|
|
|
|
<q-card-section class="q-py-sm text-center">
|
|
<q-form
|
|
v-if="confirmationMethod === 'wordlist'"
|
|
class="q-gutter-md q-y-md"
|
|
@submit="setMethod"
|
|
>
|
|
<div class="row">
|
|
<div class="col q-mx-lg">
|
|
<q-input
|
|
v-model="offlineshop.wordlist"
|
|
@input="wordlistTainted = true"
|
|
dense
|
|
filled
|
|
autogrow
|
|
/>
|
|
</div>
|
|
<div
|
|
class="col q-mx-lg items-align flex items-center justify-center"
|
|
>
|
|
<q-btn
|
|
unelevated
|
|
color="primary"
|
|
type="submit"
|
|
:disabled="!wordlistTainted"
|
|
>
|
|
Update Wordlist
|
|
</q-btn>
|
|
<q-btn @click="loadShop" flat color="grey" class="q-ml-auto"
|
|
>Reset</q-btn
|
|
>
|
|
</div>
|
|
</div>
|
|
</q-form>
|
|
|
|
<div v-else-if="confirmationMethod === 'totp'">
|
|
<div class="row">
|
|
<div class="col q-mx-lg">
|
|
<q-responsive :ratio="1">
|
|
<qrcode
|
|
:value="`otpauth://totp/offlineshop:${selectedWallet.name}?secret=${offlineshop.otp_key}`"
|
|
:options="{width: 800}"
|
|
class="rounded-borders"
|
|
></qrcode>
|
|
</q-responsive>
|
|
</div>
|
|
<div
|
|
class="col q-mx-lg items-align flex items-center justify-center"
|
|
>
|
|
<q-btn
|
|
unelevated
|
|
color="primary"
|
|
:disabled="offlineshop.method === 'totp'"
|
|
@click="setMethod"
|
|
>
|
|
Set TOTP
|
|
</q-btn>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div v-else-if="confirmationMethod === 'none'">
|
|
<p>
|
|
Setting this option disables the confirmation code message that
|
|
appears in the consumer wallet after a purchase is paid for. It's ok
|
|
if the consumer is to be trusted when they claim to have paid.
|
|
</p>
|
|
|
|
<q-btn
|
|
unelevated
|
|
color="primary"
|
|
:disabled="offlineshop.method === 'none'"
|
|
@click="setMethod"
|
|
>
|
|
Disable Confirmation Codes
|
|
</q-btn>
|
|
</div>
|
|
</q-card-section>
|
|
</q-card>
|
|
</div>
|
|
|
|
<div class="col-12 col-md-5 q-gutter-y-md">
|
|
<q-card>
|
|
<q-card-section>
|
|
<h6 class="text-subtitle1 q-my-none">LNbits OfflineShop extension</h6>
|
|
</q-card-section>
|
|
<q-card-section class="q-pa-none">
|
|
<q-separator></q-separator>
|
|
<q-list> {% include "offlineshop/_api_docs.html" %} </q-list>
|
|
</q-card-section>
|
|
</q-card>
|
|
</div>
|
|
|
|
<q-dialog v-model="itemDialog.show">
|
|
<q-card class="q-pa-lg q-pt-xl lnbits__dialog-card">
|
|
<q-card-section>
|
|
<h5
|
|
class="q-ma-none"
|
|
v-if="itemDialog.data.id"
|
|
v-text="itemDialog.data.name"
|
|
></h5>
|
|
<h5 class="q-ma-none q-mb-xl" v-else>Adding a new item</h5>
|
|
|
|
<q-responsive v-if="itemDialog.data.id" :ratio="1">
|
|
<qrcode
|
|
:value="itemDialog.data.lnurl"
|
|
:options="{width: 800}"
|
|
class="rounded-borders"
|
|
></qrcode>
|
|
</q-responsive>
|
|
|
|
<div v-if="itemDialog.data.id" class="row q-gutter-sm justify-center">
|
|
<q-btn
|
|
outline
|
|
color="grey"
|
|
@click="copyText(itemDialog.data.lnurl, 'LNURL copied to clipboard!')"
|
|
class="q-mb-lg"
|
|
>Copy LNURL</q-btn
|
|
>
|
|
</div>
|
|
<q-form @submit="sendItem" class="q-gutter-md">
|
|
<q-input
|
|
filled
|
|
dense
|
|
v-model.trim="itemDialog.data.name"
|
|
type="text"
|
|
label="Item name"
|
|
></q-input>
|
|
<q-input
|
|
filled
|
|
dense
|
|
v-model.trim="itemDialog.data.description"
|
|
type="text"
|
|
label="Brief description"
|
|
></q-input>
|
|
<q-file
|
|
filled
|
|
dense
|
|
capture="environment"
|
|
accept="image/jpeg, image/png"
|
|
:max-file-size="3*1024**2"
|
|
label="Small image (optional)"
|
|
clearable
|
|
@input="imageAdded"
|
|
@clear="imageCleared"
|
|
>
|
|
<template v-if="itemDialog.data.image" v-slot:before>
|
|
<img style="height: 1em" :src="itemDialog.data.image" />
|
|
</template>
|
|
<template v-if="itemDialog.data.image" v-slot:append>
|
|
<q-icon
|
|
name="cancel"
|
|
@click.stop.prevent="imageCleared"
|
|
class="cursor-pointer"
|
|
/>
|
|
</template>
|
|
</q-file>
|
|
<q-input
|
|
filled
|
|
dense
|
|
v-model.number="itemDialog.data.price"
|
|
type="number"
|
|
step="0.001"
|
|
min="0.001"
|
|
:label="`Item price (${itemDialog.data.unit})`"
|
|
></q-input>
|
|
<q-select
|
|
filled
|
|
dense
|
|
v-model="itemDialog.data.unit"
|
|
type="text"
|
|
label="Unit"
|
|
:options="itemDialog.units"
|
|
></q-select>
|
|
|
|
<div class="row q-mt-lg">
|
|
<div class="col q-ml-lg">
|
|
<q-btn
|
|
unelevated
|
|
color="primary"
|
|
:disable="disabledAddItemButton()"
|
|
type="submit"
|
|
>
|
|
{% raw %}{{ itemDialog.data.id ? 'Update' : 'Add' }}{% endraw %}
|
|
Item
|
|
</q-btn>
|
|
</div>
|
|
<div class="col q-ml-lg">
|
|
<q-btn v-close-popup flat color="grey" class="q-ml-auto"
|
|
>Cancel</q-btn
|
|
>
|
|
</div>
|
|
</div>
|
|
</q-form>
|
|
</q-card-section>
|
|
</q-card>
|
|
</q-dialog>
|
|
</div>
|
|
{% endblock %} {% block scripts %} {{ window_vars(user) }}
|
|
<script src="https://cdn.jsdelivr.net/npm/pica@6.1.1/dist/pica.min.js"></script>
|
|
<script src="/offlineshop/static/js/index.js"></script>
|
|
{% endblock %}
|