Skip to content

Commit

Permalink
Merge pull request #8 from lnbits/manage_unavailable_dates
Browse files Browse the repository at this point in the history
Delete unavailable dates
  • Loading branch information
arcbtc authored Jul 16, 2024
2 parents 610f798 + e97c121 commit bbe3948
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 15 deletions.
6 changes: 6 additions & 0 deletions crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,9 @@ async def get_unavailable_times(schedule_id: str) -> List[UnavailableTime]:
"SELECT * FROM lncalendar.unavailable WHERE schedule = ?", (schedule_id,)
)
return [UnavailableTime(**row) for row in rows]


async def delete_unavailable_time(unavailable_time_id: str) -> None:
await db.execute(
"DELETE FROM lncalendar.unavailable WHERE id = ?", (unavailable_time_id,)
)
26 changes: 24 additions & 2 deletions static/components/schedule-details/schedule-details.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
>
<q-tabs v-model="tab" no-caps align="justify">
<q-tab name="info" label="Schedule Info"></q-tab>
<q-tab name="edit_unavailable" label="Unavailable Dates"></q-tab>
<q-tab name="unavailable" label="Set Unavailable"></q-tab>
</q-tabs>
<q-card-section style="min-height: 50vh" class="scroll">
Expand All @@ -16,7 +17,6 @@
v-model="date"
:events="events"
event-color="primary"
@input="dateChanged"
:options="availableDaysFn"
today-btn
></q-date>
Expand Down Expand Up @@ -68,7 +68,6 @@
>
<span v-else>Select a date range to be unavailable</span>
</p>

<q-btn
align="right"
color="primary"
Expand All @@ -79,6 +78,29 @@
</div>
</div>
</q-tab-panel>
<q-tab-panel name="edit_unavailable">
<p class="h6">Select days off</p>
<div class="q-pa-md">
<q-table
title="Treats"
:data="unavailableDatesBlocks"
:columns="unavailableTable.columns"
row-key="id"
selection="single"
:selected.sync="selectedBlock"
:pagination.sync="unavailableTable.pagination"
></q-table>
<div class="q-mt-lg">
<q-btn
align="right"
color="primary"
label="Delete Selected"
@click="deleteUnavailableDate"
:disable="!selectedBlock.length"
></q-btn>
</div>
</div>
</q-tab-panel>
</q-tab-panels>
</q-card-section>
<q-card-actions align="right">
Expand Down
49 changes: 48 additions & 1 deletion static/components/schedule-details/schedule-details.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,32 @@ async function scheduleDetails(path) {
events: [],
splitterModel: 60,
eventsByDate: [],
unavailableDates: new Set()
unavailableDates: new Set(),
unavailableDatesBlocks: [],
selectedBlock: [],
unavailableTable: {
columns: [
{
name: 'starts',
align: 'left',
label: 'Starts',
field: 'start_time',
field: row => row.start_time,
sortable: true
},
{
name: 'ens',
align: 'left',
label: 'Ends',
field: 'end_time',
field: row => row.end_time,
sortable: true
}
],
pagination: {
rowsPerPage: 10
}
}
}
},

Expand Down Expand Up @@ -65,6 +90,7 @@ async function scheduleDetails(path) {
...this.unavailableDates,
...extractUnavailableDates(res.data)
])
this.unavailableDatesBlocks = res.data
})
.catch(err => {
console.log(err)
Expand Down Expand Up @@ -94,6 +120,27 @@ async function scheduleDetails(path) {
console.warn(error)
LNbits.utils.notifyApiError(error)
}
},
async deleteUnavailableDate() {
const id = this.selectedBlock[0].id
await LNbits.api
.request(
'DELETE',
`/lncalendar/api/v1/unavailable/${this.schedule.id}/${id}`,
this.wallet.adminkey
)
.then(res => {
this.selectedBlock = []
this.getUnavailableDates()
this.$q.notify({
type: 'positive',
message: 'Unavailable date deleted',
timeout: 3000
})
})
.catch(err => {
console.log(err)
})
}
},

Expand Down
36 changes: 36 additions & 0 deletions tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import asyncio

from loguru import logger

from lnbits.core.models import Payment
from lnbits.helpers import get_current_extension_name
from lnbits.tasks import register_invoice_listener

from .crud import get_appointment, set_appointment_paid, get_schedule


async def wait_for_paid_invoices():
invoice_queue = asyncio.Queue()
register_invoice_listener(invoice_queue, get_current_extension_name())

while True:
payment = await invoice_queue.get()
await on_invoice_paid(payment)


async def on_invoice_paid(payment: Payment) -> None:
if payment.extra.get("tag") != "lncalendar":
# not a lncalendar invoice
return

appointment = await get_appointment(payment.checking_id)
if not appointment:
logger.error("this should never happen", payment)
return

schedule = await get_schedule(appointment.schedule)
assert schedule

if payment.amount == schedule.amount * 1000:
await payment.set_pending(False)
await set_appointment_paid(payment.payment_hash)
2 changes: 1 addition & 1 deletion templates/lncalendar/display.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ <h4 class="q-mt-none q-mb-md">${schedule.name}</h4>
:borderless="formDialog.data.email != ''"
></q-input>
<q-input
v-model.trim="formDialog.data.text"
v-model="formDialog.data.text"
type="textarea"
label="Write a message (optional)"
:borderless="formDialog.data.text != ''"
Expand Down
44 changes: 33 additions & 11 deletions views_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
from fastapi import Depends, Query
from fastapi.exceptions import HTTPException

from lnbits.core.crud import get_user, get_wallet, get_standalone_payment
from lnbits.core.services import check_transaction_status, create_invoice
from loguru import logger

from lnbits.core.crud import get_user
from lnbits.core.services import create_invoice
from lnbits.core.views.api import api_payment
from lnbits.decorators import (
WalletTypeInfo,
require_admin_key,
Expand All @@ -25,6 +28,7 @@
purge_appointments,
create_unavailable_time,
get_unavailable_times,
delete_unavailable_time,
)
from .models import Schedule, CreateSchedule, CreateUnavailableTime, CreateAppointment

Expand Down Expand Up @@ -133,21 +137,20 @@ async def api_purge_appointments(schedule_id: str):

@lncalendar_ext.get("/api/v1/appointment/{schedule_id}/{payment_hash}")
async def api_appointment_check_invoice(schedule_id: str, payment_hash: str):
payment = await get_standalone_payment(payment_hash)
if not payment:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="Payment does not exist."
)

schedule = await get_schedule(schedule_id)
if not schedule:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="Schedule does not exist."
)
if not payment.pending and payment.amount == schedule.amount * 1000:
await set_appointment_paid(payment_hash)
return {"paid": True}

try:
status = await api_payment(payment_hash)
if status["paid"]:
await set_appointment_paid(payment_hash)
return {"paid": True}

except Exception:
return {"paid": False}
return {"paid": False}


Expand Down Expand Up @@ -196,3 +199,22 @@ async def api_unavailable_get(schedule_id: str):
status_code=HTTPStatus.NOT_FOUND, detail="Schedule does not exist."
)
return await get_unavailable_times(schedule_id)


@lncalendar_ext.delete("/api/v1/unavailable/{schedule_id}/{unavailable_id}")
async def api_unavailable_delete(
schedule_id: str,
unavailable_id: str,
wallet: WalletTypeInfo = Depends(require_admin_key),
):
schedule = await get_schedule(schedule_id)
if not schedule:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="Schedule does not exist."
)
if schedule.wallet != wallet.wallet.id:
raise HTTPException(
status_code=HTTPStatus.FORBIDDEN, detail="Not your schedule."
)
await delete_unavailable_time(unavailable_id)
return "", HTTPStatus.NO_CONTENT

0 comments on commit bbe3948

Please sign in to comment.