merchant chat functional almost out of WIP
This commit is contained in:
parent
ebe8d8b0b9
commit
532e12ec83
7 changed files with 461 additions and 79 deletions
|
|
@ -408,8 +408,10 @@ async def create_diagonalley_market_stalls(
|
|||
async def update_diagonalley_market(market_id):
|
||||
pass
|
||||
|
||||
|
||||
### CHAT / MESSAGES
|
||||
|
||||
|
||||
async def create_chat_message(data: CreateChatMessage):
|
||||
print("DATA", data)
|
||||
await db.execute(
|
||||
|
|
@ -441,3 +443,14 @@ async def get_diagonalley_chat_messages(room_name: str):
|
|||
)
|
||||
|
||||
return [ChatMessage(**row) for row in rows]
|
||||
|
||||
|
||||
async def get_diagonalley_chat_by_merchant(ids: List[str]) -> List[ChatMessage]:
|
||||
|
||||
q = ",".join(["?"] * len(ids))
|
||||
rows = await db.fetchall(
|
||||
f"SELECT * FROM diagonalley.messages WHERE id_conversation IN ({q})",
|
||||
(*ids,),
|
||||
)
|
||||
print(ids, q, rows)
|
||||
return [ChatMessage(**row) for row in rows]
|
||||
|
|
|
|||
|
|
@ -78,9 +78,9 @@ class Notifier:
|
|||
|
||||
async def _notify(self, message: str, room_name: str):
|
||||
"""Notifier"""
|
||||
|
||||
d = json.loads(message)
|
||||
d["room_name"] = room_name
|
||||
print("hey", d)
|
||||
db_msg = CreateChatMessage.parse_obj(d)
|
||||
print("NOT:", db_msg)
|
||||
await create_chat_message(data=db_msg)
|
||||
|
|
|
|||
|
|
@ -345,20 +345,6 @@
|
|||
<div class="col-12 col-md-8 col-lg-7 q-gutter-y-md">
|
||||
<q-card>
|
||||
<q-card-section>
|
||||
<q-btn
|
||||
unelevated
|
||||
v-if="stalls.length > 0"
|
||||
color="primary"
|
||||
@click="productDialog.show = true"
|
||||
>+ Product <q-tooltip> List a product </q-tooltip></q-btn
|
||||
>
|
||||
<q-btn
|
||||
unelevated
|
||||
v-else
|
||||
color="primary"
|
||||
@click="errorMessage('First set shipping zone(s), then create a stall.')"
|
||||
>+ Product <q-tooltip> List a product </q-tooltip></q-btn
|
||||
>
|
||||
<q-btn unelevated color="primary" @click="zoneDialog.show = true"
|
||||
>+ Shipping Zone<q-tooltip> Create a shipping zone </q-tooltip></q-btn
|
||||
>
|
||||
|
|
@ -382,7 +368,26 @@
|
|||
Create a market stall to list products on
|
||||
</q-tooltip></q-btn
|
||||
>
|
||||
<q-btn unelevated color="primary" @click="marketDialog.show = true"
|
||||
<q-btn
|
||||
unelevated
|
||||
v-if="stalls.length > 0"
|
||||
color="primary"
|
||||
@click="productDialog.show = true"
|
||||
>+ Product <q-tooltip> List a product </q-tooltip></q-btn
|
||||
>
|
||||
<q-btn
|
||||
unelevated
|
||||
v-else
|
||||
color="primary"
|
||||
@click="errorMessage('First set shipping zone(s), then create a stall.')"
|
||||
>+ Product <q-tooltip> List a product </q-tooltip></q-btn
|
||||
>
|
||||
<q-btn
|
||||
class="float-right"
|
||||
unelevated
|
||||
flat
|
||||
color="primary"
|
||||
@click="marketDialog.show = true"
|
||||
>Create Market
|
||||
<q-tooltip>
|
||||
Makes a simple frontend shop for your stalls (not NOSTR)</q-tooltip
|
||||
|
|
@ -415,6 +420,7 @@
|
|||
{% raw %}
|
||||
<template v-slot:header="props">
|
||||
<q-tr :props="props">
|
||||
<q-th auto-width></q-th>
|
||||
<q-th auto-width></q-th>
|
||||
<q-th v-for="col in props.cols" :key="col.name" :props="props">
|
||||
{{ col.label }}
|
||||
|
|
@ -434,6 +440,23 @@
|
|||
:icon="props.expand ? 'remove' : 'add'"
|
||||
/>
|
||||
</q-td>
|
||||
<q-td auto-width>
|
||||
<q-btn
|
||||
size="sm"
|
||||
color="green"
|
||||
dense
|
||||
icon="chat"
|
||||
@click="chatRoom(props.row.invoiceid)"
|
||||
>
|
||||
<q-badge
|
||||
v-if="props.row.unread"
|
||||
color="red"
|
||||
rounded
|
||||
floating
|
||||
style="padding: 6px; border-radius: 6px"
|
||||
/>
|
||||
</q-btn>
|
||||
</q-td>
|
||||
<q-td v-for="col in props.cols" :key="col.name" :props="props">
|
||||
{{ col.value }}
|
||||
</q-td>
|
||||
|
|
@ -824,22 +847,114 @@
|
|||
<q-list> {% include "diagonalley/_api_docs.html" %} </q-list>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
<!-- CHAT BOX -->
|
||||
<q-card>
|
||||
<q-card-section>
|
||||
<h6 class="text-subtitle1 q-my-none">Messages</h6>
|
||||
</q-card-section>
|
||||
<q-card-section class="q-pa-none">
|
||||
<q-separator></q-separator>
|
||||
|
||||
<div class="column q-ma-md q-pb-lg" style="height: 350px">
|
||||
<div class="col q-pb-md">
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<q-select
|
||||
v-model="customerKey"
|
||||
:options="Object.keys(messages)"
|
||||
label="Customers"
|
||||
@input="chatRoom(customerKey)"
|
||||
></q-select>
|
||||
</q-card-section>
|
||||
<div class="chat-container q-pa-md" ref="chatCard">
|
||||
<div class="chat-box">
|
||||
<!-- <p v-if="Object.keys(messages).length === 0">No messages yet</p> -->
|
||||
<div class="chat-messages">
|
||||
<q-chat-message
|
||||
:key="index"
|
||||
v-for="(message, index) in orderMessages"
|
||||
:name="message.pubkey == keys.pubkey ? 'me' : 'customer'"
|
||||
:text="[message.msg]"
|
||||
:sent="message.pubkey == keys.pubkey ? true : false"
|
||||
:bg-color="message.pubkey == keys.pubkey ? 'white' : 'light-green-2'"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<q-form @submit="sendMessage" class="full-width chat-input">
|
||||
<q-input
|
||||
ref="newMessage"
|
||||
v-model="newMessage"
|
||||
placeholder="Message"
|
||||
class="full-width"
|
||||
dense
|
||||
outlined
|
||||
>
|
||||
<template>
|
||||
<q-btn
|
||||
round
|
||||
dense
|
||||
flat
|
||||
type="submit"
|
||||
icon="send"
|
||||
color="primary"
|
||||
/>
|
||||
</template>
|
||||
</q-input>
|
||||
</q-form>
|
||||
</div>
|
||||
</q-card>
|
||||
<!-- <q-card>
|
||||
<q-card-section>
|
||||
<h6 class="text-subtitle1 q-my-none">Messages</h6>
|
||||
</q-card-section>
|
||||
<q-card-section class="q-pa-none">
|
||||
<q-separator></q-separator>
|
||||
<div
|
||||
ref="chatCard"
|
||||
class="q-ma-md q-pb-lg"
|
||||
style="height: 350px"
|
||||
>
|
||||
<div class="q-pb-md">
|
||||
<q-select
|
||||
v-model="customerKey"
|
||||
style="width: 80%"
|
||||
:options="customerKeys"
|
||||
:options="Object.keys(messages)"
|
||||
label="Customers"
|
||||
@input="getMessages(customerKey)"
|
||||
@input="chatRoom(customerKey)"
|
||||
></q-select>
|
||||
<div class="chat-container q-pa-md">
|
||||
<div class="chat-box">
|
||||
<p v-if="Object.keys(messages).length === 0">No messages yet</p>
|
||||
<div class="chat-messages">
|
||||
<q-chat-message
|
||||
:key="index"
|
||||
v-for="(message, index) in orderMessages"
|
||||
:name="message.pubkey == keys.pubkey ? 'me' : 'customer'"
|
||||
:text="[message.msg]"
|
||||
:sent="message.pubkey == keys.pubkey ? true : false"
|
||||
:bg-color="message.pubkey == keys.pubkey ? 'white' : 'light-green-2'"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<q-form @submit="sendMessage" class="full-width chat-input">
|
||||
<q-input
|
||||
ref="newMessage"
|
||||
v-model="newMessage"
|
||||
placeholder="Message"
|
||||
class="full-width"
|
||||
dense
|
||||
outlined
|
||||
>
|
||||
<template>
|
||||
<q-btn
|
||||
round
|
||||
dense
|
||||
flat
|
||||
type="submit"
|
||||
icon="send"
|
||||
color="primary"
|
||||
/>
|
||||
</template>
|
||||
</q-input>
|
||||
</q-form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-8 q-px-md">
|
||||
<div v-for="message in customerMessages">
|
||||
|
|
@ -860,11 +975,10 @@
|
|||
</div>
|
||||
</div>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</q-card> -->
|
||||
</div>
|
||||
</div>
|
||||
<!-- </div>
|
||||
</div> -->
|
||||
|
||||
{% endblock %} {% block scripts %} {{ window_vars(user) }}
|
||||
<script src="https://cdn.jsdelivr.net/npm/pica@6.1.1/dist/pica.min.js"></script>
|
||||
|
||||
|
|
@ -873,6 +987,15 @@
|
|||
|
||||
const pica = window.pica()
|
||||
|
||||
function imgSizeFit(img, maxWidth = 1024, maxHeight = 768) {
|
||||
let ratio = Math.min(
|
||||
1,
|
||||
maxWidth / img.naturalWidth,
|
||||
maxHeight / img.naturalHeight
|
||||
)
|
||||
return {width: img.naturalWidth * ratio, height: img.naturalHeight * ratio}
|
||||
}
|
||||
|
||||
const mapStalls = obj => {
|
||||
obj._data = _.clone(obj)
|
||||
return obj
|
||||
|
|
@ -891,6 +1014,7 @@
|
|||
new Date(obj.time * 1000),
|
||||
'YYYY-MM-DD HH:mm'
|
||||
)
|
||||
// obj.unread = false
|
||||
return obj
|
||||
}
|
||||
const mapKeys = obj => {
|
||||
|
|
@ -933,8 +1057,12 @@
|
|||
customerKeys: [],
|
||||
customerKey: '',
|
||||
customerMessages: {},
|
||||
messages: {},
|
||||
newMessage: '',
|
||||
orderMessages: {},
|
||||
shippedModel: false,
|
||||
shippingZoneOptions: [
|
||||
'Free (digital)',
|
||||
'Worldwide',
|
||||
'Europe',
|
||||
'Australia',
|
||||
|
|
@ -999,17 +1127,17 @@
|
|||
ordersTable: {
|
||||
columns: [
|
||||
/*{
|
||||
name: 'product',
|
||||
align: 'left',
|
||||
label: 'Product',
|
||||
field: 'product'
|
||||
},
|
||||
{
|
||||
name: 'quantity',
|
||||
align: 'left',
|
||||
label: 'Quantity',
|
||||
field: 'quantity'
|
||||
},*/
|
||||
name: 'product',
|
||||
align: 'left',
|
||||
label: 'Product',
|
||||
field: 'product'
|
||||
},
|
||||
{
|
||||
name: 'quantity',
|
||||
align: 'left',
|
||||
label: 'Quantity',
|
||||
field: 'quantity'
|
||||
},*/
|
||||
{
|
||||
name: 'id',
|
||||
align: 'left',
|
||||
|
|
@ -1443,9 +1571,10 @@
|
|||
let image = new Image()
|
||||
image.src = blobURL
|
||||
image.onload = async () => {
|
||||
let fit = imgSizeFit(image)
|
||||
let canvas = document.createElement('canvas')
|
||||
canvas.setAttribute('width', 760)
|
||||
canvas.setAttribute('height', 490)
|
||||
canvas.setAttribute('width', fit.width)
|
||||
canvas.setAttribute('height', fit.height)
|
||||
await pica.resize(image, canvas, {
|
||||
quality: 0,
|
||||
alpha: true,
|
||||
|
|
@ -1657,7 +1786,7 @@
|
|||
.then(response => {
|
||||
if (response.data) {
|
||||
this.markets = response.data.map(mapMarkets)
|
||||
console.log(this.markets)
|
||||
// console.log(this.markets)
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
|
|
@ -1756,10 +1885,10 @@
|
|||
////////////////////////////////////////
|
||||
////////////////ORDERS//////////////////
|
||||
////////////////////////////////////////
|
||||
getOrders: function () {
|
||||
getOrders: async function () {
|
||||
var self = this
|
||||
|
||||
LNbits.api
|
||||
await LNbits.api
|
||||
.request(
|
||||
'GET',
|
||||
'/diagonalley/api/v1/orders?all_wallets=true',
|
||||
|
|
@ -1768,7 +1897,6 @@
|
|||
.then(function (response) {
|
||||
if (response.data) {
|
||||
self.orders = response.data.map(mapOrders)
|
||||
console.log(self.orders)
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
|
|
@ -1839,21 +1967,190 @@
|
|||
},
|
||||
exportOrdersCSV: function () {
|
||||
LNbits.utils.exportCSV(this.ordersTable.columns, this.orders)
|
||||
},
|
||||
/// CHAT
|
||||
async getAllMessages() {
|
||||
await LNbits.api
|
||||
.request(
|
||||
'GET',
|
||||
`/diagonalley/api/v1/chat/messages/merchant?orders=${this.orders
|
||||
.map(o => o.invoiceid)
|
||||
.toString()}`,
|
||||
this.g.user.wallets[0].adminkey
|
||||
)
|
||||
.then(res => {
|
||||
this.messages = _.groupBy(res.data, 'id_conversation')
|
||||
this.checkUnreadMessages()
|
||||
console.log('Get new messages!')
|
||||
})
|
||||
.catch(error => {
|
||||
LNbits.utils.notifyApiError(error)
|
||||
})
|
||||
},
|
||||
updateLastSeenMsg(id) {
|
||||
let data = this.$q.localStorage.getItem(
|
||||
`lnbits.diagonalley.${this.g.user.id}`
|
||||
)
|
||||
let chat = {
|
||||
...data.chat,
|
||||
[`${id}`]: {
|
||||
timestamp: Object.keys(this.orderMessages)[
|
||||
Object.keys(this.orderMessages).length - 1
|
||||
]
|
||||
}
|
||||
}
|
||||
console.log({chat})
|
||||
this.$q.localStorage.set(`lnbits.diagonalley.${this.g.user.id}`, {
|
||||
...data,
|
||||
chat
|
||||
})
|
||||
this.checkUnreadMessages()
|
||||
},
|
||||
checkUnreadMessages() {
|
||||
let lastMsgs = this.$q.localStorage.getItem(
|
||||
`lnbits.diagonalley.${this.g.user.id}`
|
||||
).chat
|
||||
for (let key in this.messages) {
|
||||
let idx = this.orders.findIndex(f => f.invoiceid == key)
|
||||
if (!lastMsgs[key]) {
|
||||
this.updateLastSeenMsg(key)
|
||||
//this.orders[idx].unread = true
|
||||
return
|
||||
}
|
||||
console.log(
|
||||
'Key',
|
||||
key,
|
||||
'saved:',
|
||||
lastMsgs[key].timestamp,
|
||||
'messages: ',
|
||||
Math.max(...this.messages[key].map(c => c.timestamp)),
|
||||
lastMsgs[key].timestamp <
|
||||
Math.max(...this.messages[key].map(c => c.timestamp))
|
||||
)
|
||||
if (
|
||||
lastMsgs[key].timestamp <
|
||||
Math.max(...this.messages[key].map(c => c.timestamp))
|
||||
) {
|
||||
this.$set(this.orders[idx], 'unread', true)
|
||||
// this.orders[idx].unread = true
|
||||
} else {
|
||||
this.$set(this.orders[idx], 'unread', false)
|
||||
// this.orders[idx].unread = false
|
||||
}
|
||||
console.log('Order:', this.orders[idx])
|
||||
}
|
||||
},
|
||||
clearMessage() {
|
||||
this.newMessage = ''
|
||||
this.$refs.newMessage.focus()
|
||||
},
|
||||
sendMessage() {
|
||||
let message = {
|
||||
msg: this.newMessage,
|
||||
pubkey: this.keys.pubkey
|
||||
}
|
||||
this.ws.send(JSON.stringify(message))
|
||||
|
||||
this.clearMessage()
|
||||
},
|
||||
chatRoom(id) {
|
||||
this.startChat(id)
|
||||
this.orderMessages = {}
|
||||
this.messages[id].map(m => {
|
||||
this.$set(this.orderMessages, m.timestamp, {
|
||||
msg: m.msg,
|
||||
pubkey: m.pubkey
|
||||
})
|
||||
})
|
||||
this.$refs.chatCard.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
inline: 'nearest'
|
||||
})
|
||||
this.updateLastSeenMsg(id)
|
||||
//"ea2fbf6c91aa228603681e2cc34bb06e34e6d1375fa4d6c35756182b2fa3307f"
|
||||
//"c7435a04875c26e28db91a377bd6e991dbfefeefea8258415f3ae0c716ed2335"
|
||||
},
|
||||
startChat(room_name) {
|
||||
if (this.ws) {
|
||||
this.ws.close()
|
||||
}
|
||||
if (location.protocol == 'https:') {
|
||||
ws_scheme = 'wss://'
|
||||
} else {
|
||||
ws_scheme = 'ws://'
|
||||
}
|
||||
ws = new WebSocket(
|
||||
ws_scheme + location.host + '/diagonalley/ws/' + room_name
|
||||
)
|
||||
|
||||
function checkWebSocket(event) {
|
||||
if (ws.readyState === WebSocket.CLOSED) {
|
||||
console.log('WebSocket CLOSED: Reopening')
|
||||
ws = new WebSocket(
|
||||
ws_scheme + location.host + '/diagonalley/ws/' + room_name
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
ws.onmessage = event => {
|
||||
let event_data = JSON.parse(event.data)
|
||||
|
||||
this.$set(this.orderMessages, Date.now(), event_data)
|
||||
this.updateLastSeenMsg(room_name)
|
||||
}
|
||||
|
||||
ws.onclose = event => {
|
||||
this.updateLastSeenMsg(room_name)
|
||||
}
|
||||
|
||||
this.ws = ws
|
||||
}
|
||||
},
|
||||
created: function () {
|
||||
async created() {
|
||||
if (this.g.user.wallets.length) {
|
||||
this.getStalls()
|
||||
this.getProducts()
|
||||
this.getZones()
|
||||
this.getOrders()
|
||||
await this.getOrders()
|
||||
this.getMarkets()
|
||||
this.customerKeys = [
|
||||
'cb4c0164fe03fcdadcbfb4f76611c71620790944c24f21a1cd119395cdedfe1b',
|
||||
'a9c17358a6dc4ceb3bb4d883eb87967a66b3453a0f3199f0b1c8eef8070c6a07'
|
||||
]
|
||||
await this.getAllMessages()
|
||||
let keys = this.$q.localStorage.getItem(
|
||||
`lnbits.diagonalley.${this.g.user.id}`
|
||||
)
|
||||
if (keys) {
|
||||
this.keys = keys
|
||||
}
|
||||
setInterval(() => {
|
||||
this.getAllMessages()
|
||||
}, 300000)
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style scoped>
|
||||
.chat-container {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-rows: 1fr auto;
|
||||
height: calc(100vh - 140px);
|
||||
}
|
||||
|
||||
.chat-box {
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
padding: 1rem;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.chat-messages {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.chat-input {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: end;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@
|
|||
dense
|
||||
emit-value
|
||||
v-model="selectedOrder"
|
||||
:options="user.orders"
|
||||
:options="Object.keys(user.orders)"
|
||||
label="Order"
|
||||
hint="Select an order from this merchant"
|
||||
@input="val => { changeOrder() }"
|
||||
|
|
@ -187,7 +187,7 @@
|
|||
msg: this.newMessage,
|
||||
pubkey: this.user.keys.publickey
|
||||
}
|
||||
ws.send(JSON.stringify(message))
|
||||
this.ws.send(JSON.stringify(message))
|
||||
|
||||
this.clearMessage()
|
||||
},
|
||||
|
|
@ -236,10 +236,16 @@
|
|||
LNbits.utils.notifyApiError(error)
|
||||
})
|
||||
},
|
||||
changeOrder() {
|
||||
console.log(this.selectedOrder)
|
||||
async changeOrder() {
|
||||
this.products = this.user.orders[this.selectedOrder]
|
||||
this.messages = {}
|
||||
await this.getMessages(this.selectedOrder)
|
||||
this.startChat(this.selectedOrder)
|
||||
},
|
||||
startChat(room_name) {
|
||||
if (this.ws) {
|
||||
this.ws.close()
|
||||
}
|
||||
if (location.protocol == 'https:') {
|
||||
ws_scheme = 'wss://'
|
||||
} else {
|
||||
|
|
@ -268,51 +274,51 @@
|
|||
}
|
||||
},
|
||||
async created() {
|
||||
this.stall = JSON.parse('{{ stall | tojson }}')
|
||||
let order_details = JSON.parse('{{ order | tojson }}')
|
||||
let products = JSON.parse('{{ products | tojson }}')
|
||||
|
||||
let order_id = '{{ order_id }}'
|
||||
|
||||
this.stall = JSON.parse('{{ stall | tojson }}')
|
||||
this.products = order_details.map(o => {
|
||||
let product = products.find(p => p.id == o.product_id)
|
||||
return {
|
||||
quantity: o.quantity,
|
||||
name: product.product,
|
||||
image: product.image,
|
||||
price: product.price
|
||||
}
|
||||
})
|
||||
|
||||
let data = this.$q.localStorage.getItem(`lnbits.diagonalley.data`)
|
||||
|
||||
try {
|
||||
if (data) {
|
||||
this.user = data
|
||||
//add chat key (merchant pubkey) if not set
|
||||
if (!this.user.chats[`${order_id}`]) {
|
||||
this.$set(this.user.chats, order_id, [])
|
||||
if (!this.user.orders[`${order_id}`]) {
|
||||
this.$set(this.user.orders, order_id, this.products)
|
||||
}
|
||||
//this.$q.localStorage.set(`lnbits.diagonalley.data`, this.user)
|
||||
} else {
|
||||
// generate keys
|
||||
await this.generateKeys()
|
||||
// populate user data
|
||||
this.user.chats = {
|
||||
[`${order_id}`]: []
|
||||
this.user.orders = {
|
||||
[`${order_id}`]: this.products
|
||||
}
|
||||
this.user.orders = []
|
||||
//this.user.orders = []
|
||||
}
|
||||
|
||||
this.order_details = order_details
|
||||
this.products = order_details.map(o => {
|
||||
let product = products.find(p => p.id == o.product_id)
|
||||
return {
|
||||
quantity: o.quantity,
|
||||
name: product.product,
|
||||
image: product.image,
|
||||
price: product.price
|
||||
}
|
||||
})
|
||||
//this.order_details = order_details
|
||||
|
||||
this.user.orders = [...new Set([...this.user.orders, order_id])]
|
||||
//this.user.orders = [...new Set([...this.user.orders, order_id])]
|
||||
this.selectedOrder = order_id
|
||||
|
||||
await this.getMessages(order_id)
|
||||
|
||||
this.$q.localStorage.set(`lnbits.diagonalley.data`, this.user)
|
||||
this.startChat(order_id)
|
||||
console.log(this.products)
|
||||
console.log(this.messages)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@
|
|||
>
|
||||
</div>
|
||||
<div v-if="item.categories" class="text-subtitle1">
|
||||
<q-chip v-for="cat in item.categories.split(',')" dense
|
||||
<q-chip v-for="(cat, i) in item.categories.split(',')" :key="i" dense
|
||||
>{{cat}}</q-chip
|
||||
>
|
||||
</div>
|
||||
|
|
@ -409,8 +409,18 @@
|
|||
if (res.data.paid) {
|
||||
this.$q.notify({
|
||||
type: 'positive',
|
||||
message: 'Sats received, thanks!',
|
||||
icon: 'thumb_up'
|
||||
multiLine: true,
|
||||
message:
|
||||
"Sats received, thanks! You'l be redirected to the order page...",
|
||||
icon: 'thumb_up',
|
||||
actions: [
|
||||
{
|
||||
label: 'See Order',
|
||||
handler: () => {
|
||||
window.location.href = `/diagonalley/order/?merch=${this.stall.id}&invoice_id=${this.qrCodeDialog.data.payment_hash}`
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
clearInterval(this.qrCodeDialog.paymentChecker)
|
||||
this.resetCart()
|
||||
|
|
|
|||
|
|
@ -94,7 +94,9 @@ async def display(request: Request, market_id):
|
|||
|
||||
|
||||
@diagonalley_ext.get("/order", response_class=HTMLResponse)
|
||||
async def chat_page(request: Request, merch: str = Query(...), invoice_id: str = Query(...)):
|
||||
async def chat_page(
|
||||
request: Request, merch: str = Query(...), invoice_id: str = Query(...)
|
||||
):
|
||||
stall = await get_diagonalley_stall(merch)
|
||||
order = await get_diagonalley_order_invoiceid(invoice_id)
|
||||
_order = await get_diagonalley_order_details(order.id)
|
||||
|
|
@ -110,9 +112,9 @@ async def chat_page(request: Request, merch: str = Query(...), invoice_id: str =
|
|||
"publickey": stall.publickey,
|
||||
"wallet": stall.wallet,
|
||||
},
|
||||
"order_id": order.id,
|
||||
"order_id": order.invoiceid,
|
||||
"order": [details.dict() for details in _order],
|
||||
"products": [product.dict() for product in products]
|
||||
"products": [product.dict() for product in products],
|
||||
},
|
||||
)
|
||||
|
||||
|
|
@ -123,6 +125,41 @@ async def chat_page(request: Request, merch: str = Query(...), invoice_id: str =
|
|||
notifier = Notifier()
|
||||
|
||||
|
||||
# class ConnectionManager:
|
||||
# def __init__(self):
|
||||
# self.active_connections: List[WebSocket] = []
|
||||
|
||||
# async def connect(self, websocket: WebSocket, room_name: str):
|
||||
# await websocket.accept()
|
||||
# websocket.id = room_name
|
||||
# self.active_connections.append(websocket)
|
||||
|
||||
# def disconnect(self, websocket: WebSocket):
|
||||
# self.active_connections.remove(websocket)
|
||||
|
||||
# async def send_personal_message(self, message: str, room_name: str):
|
||||
# for connection in self.active_connections:
|
||||
# if connection.id == room_name:
|
||||
# await connection.send_text(message)
|
||||
|
||||
# async def broadcast(self, message: str):
|
||||
# for connection in self.active_connections:
|
||||
# await connection.send_text(message)
|
||||
|
||||
|
||||
# manager = ConnectionManager()
|
||||
|
||||
|
||||
# @diagonalley_ext.websocket("/ws/{room_name}")
|
||||
# async def websocket_endpoint(websocket: WebSocket, room_name: str):
|
||||
# await manager.connect(websocket, room_name)
|
||||
# try:
|
||||
# while True:
|
||||
# data = await websocket.receive_text()
|
||||
# except WebSocketDisconnect:
|
||||
# manager.disconnect(websocket)
|
||||
|
||||
|
||||
@diagonalley_ext.websocket("/ws/{room_name}")
|
||||
async def websocket_endpoint(
|
||||
websocket: WebSocket, room_name: str, background_tasks: BackgroundTasks
|
||||
|
|
@ -143,7 +180,7 @@ async def websocket_endpoint(
|
|||
if websocket not in room_members:
|
||||
print("Sender not in room member: Reconnecting...")
|
||||
await notifier.connect(websocket, room_name)
|
||||
|
||||
print("ENDPOINT", data)
|
||||
await notifier._notify(data, room_name)
|
||||
|
||||
except WebSocketDisconnect:
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
from base64 import urlsafe_b64encode
|
||||
from http import HTTPStatus
|
||||
from typing import List
|
||||
from typing import List, Union
|
||||
from uuid import uuid4
|
||||
|
||||
from fastapi import Request
|
||||
from fastapi.param_functions import Query
|
||||
from fastapi.param_functions import Body, Query
|
||||
from fastapi.params import Depends
|
||||
from loguru import logger
|
||||
from secp256k1 import PrivateKey, PublicKey
|
||||
|
|
@ -34,6 +34,7 @@ from .crud import (
|
|||
delete_diagonalley_product,
|
||||
delete_diagonalley_stall,
|
||||
delete_diagonalley_zone,
|
||||
get_diagonalley_chat_by_merchant,
|
||||
get_diagonalley_chat_messages,
|
||||
get_diagonalley_latest_chat_messages,
|
||||
get_diagonalley_market,
|
||||
|
|
@ -255,6 +256,14 @@ async def api_diagonalley_orders(
|
|||
return {"message": "We could not retrieve the orders."}
|
||||
|
||||
|
||||
@diagonalley_ext.get("/api/v1/orders/{order_id}")
|
||||
async def api_diagonalley_order_by_id(order_id: str):
|
||||
order = (await get_diagonalley_order(order_id)).dict()
|
||||
order["details"] = await get_diagonalley_order_details(order_id)
|
||||
|
||||
return order
|
||||
|
||||
|
||||
@diagonalley_ext.post("/api/v1/orders")
|
||||
async def api_diagonalley_order_create(data: createOrder):
|
||||
ref = urlsafe_short_hash()
|
||||
|
|
@ -488,6 +497,16 @@ async def api_diagonalley_generate_keys():
|
|||
## MESSAGES/CHAT
|
||||
|
||||
|
||||
@diagonalley_ext.get("/api/v1/chat/messages/merchant")
|
||||
async def api_get_merchant_messages(
|
||||
orders: str = Query(...), wallet: WalletTypeInfo = Depends(require_admin_key)
|
||||
):
|
||||
|
||||
return [
|
||||
msg.dict() for msg in await get_diagonalley_chat_by_merchant(orders.split(","))
|
||||
]
|
||||
|
||||
|
||||
@diagonalley_ext.get("/api/v1/chat/messages/{room_name}")
|
||||
async def api_get_latest_chat_msg(room_name: str, all_messages: bool = Query(False)):
|
||||
if all_messages:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue