fix
Deploy app frontend / app frontend (push) Successful in 1m50s

This commit is contained in:
2024-12-07 00:43:13 +02:00
parent 85ac1ce112
commit 14e7dec5b4
7 changed files with 110 additions and 125 deletions
+1
View File
@@ -11,6 +11,7 @@ declare module 'vue' {
Card: typeof import('primevue/card')['default'] Card: typeof import('primevue/card')['default']
ChatCard: typeof import('./src/components/ChatCard.vue')['default'] ChatCard: typeof import('./src/components/ChatCard.vue')['default']
ChatComponent: typeof import('./src/components/ChatComponent.vue')['default'] ChatComponent: typeof import('./src/components/ChatComponent.vue')['default']
ChatForm: typeof import('./src/components/chat/ChatForm.vue')['default']
ChatSubscribeWebPush: typeof import('./src/components/ChatSubscribeWebPush.vue')['default'] ChatSubscribeWebPush: typeof import('./src/components/ChatSubscribeWebPush.vue')['default']
Checkbox: typeof import('primevue/checkbox')['default'] Checkbox: typeof import('primevue/checkbox')['default']
CopyLinkButton: typeof import('@/components/link/LinkCopyButton.vue')['default'] CopyLinkButton: typeof import('@/components/link/LinkCopyButton.vue')['default']
+6 -5
View File
@@ -1,9 +1,9 @@
<template> <template>
<!-- TODO: figure out how to get rid of v-if. Incorrect works on switch tabs --> <RouterLink :to="route" class="p-4 rounded-lg bg-white shadow-md">
<RouterLink :to="route" class="p-4 rounded-lg bg-white shadow-md" v-if="chatDoc.qr_code_uri"> <div class="flex items-center justify-between mb-2" v-if="qrCodeDoc">
<div class="flex items-center justify-between mb-2">
<div class="flex items-center"> <div class="flex items-center">
<h2 class="text-lg font-semibold">{{ chatDoc.name }}</h2> <QRCodePlacementIcon :placement="qrCodeDoc.placement" />
<h2 class="text-lg font-semibold">{{ qrCodeDoc.name }}</h2>
</div> </div>
</div> </div>
<div class="text-gray-500"> <div class="text-gray-500">
@@ -14,11 +14,12 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue' import { computed } from 'vue'
import type { ChatDocument } from '@hereconnect/types' import type { ChatDocument, QRCodeDocument } from '@hereconnect/types'
import { ROUTE_NAMES } from '@/constants/routes' import { ROUTE_NAMES } from '@/constants/routes'
const props = defineProps<{ const props = defineProps<{
chatDoc: ChatDocument chatDoc: ChatDocument
qrCodeDoc?: QRCodeDocument
}>() }>()
const formatDate = (date: string) => { const formatDate = (date: string) => {
+5 -79
View File
@@ -1,5 +1,5 @@
<template> <template>
<div class="flex flex-col flex-grow"> <div class="flex flex-col flex-grow place-self-stretch">
<!-- Список сообщений --> <!-- Список сообщений -->
<div class="flex-grow overflow-y-auto p-4" ref="messagesContainer"> <div class="flex-grow overflow-y-auto p-4" ref="messagesContainer">
<div <div
@@ -28,41 +28,15 @@
></slot> ></slot>
</div> </div>
<div class="flex gap-3 px-4 pt-0 flex-col-reverse pb-safe-or-4"> <ChatForm :qr_code_uri :chat :userRole />
<!-- Форма отправки сообщений -->
<form @submit.prevent="sendMessage" class="flex gap-2 items-center" ref="form">
<InputText
id="newMessage"
v-model="newMessage"
class="flex-1"
placeholder="Напишите сообщение"
/>
<Button
type="submit"
icon="pi pi-send"
class="p-button-md"
:disabled="!newMessage.trim()"
/>
</form>
<ChatSubscribeWebPush :qr_code_uri :chat :user_chat_role="userRole" />
</div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, onUnmounted, useTemplateRef, watch, nextTick } from 'vue' import { ref, onMounted, onUnmounted, useTemplateRef, watch, nextTick } from 'vue'
import { import { messagesDbLocal as db, messagesDbRemote as remoteDb } from '@/api/dbs'
chatsDbLocal, import { type MessageDocument } from '@hereconnect/types'
chatsDbRemote,
messagesDbLocal as db,
messagesDbRemote as remoteDb,
} from '@/api/dbs'
import { type ChatDocument, type MessageDocument } from '@hereconnect/types'
import { getBrowserUuid } from '@/utils/getBrowserUuid'
import { getUserUuid } from '@/utils/getUserUuid'
const formRef = useTemplateRef('form')
const messagesContainerRef = useTemplateRef('messagesContainer') const messagesContainerRef = useTemplateRef('messagesContainer')
const { qr_code_uri, chat, userRole } = defineProps<{ const { qr_code_uri, chat, userRole } = defineProps<{
@@ -73,10 +47,9 @@ const { qr_code_uri, chat, userRole } = defineProps<{
// Локальные состояния // Локальные состояния
const messages = ref<MessageDocument[]>([]) const messages = ref<MessageDocument[]>([])
const newMessage = ref('')
let changesSubscription: PouchDB.Core.Changes<MessageDocument> | null = null let changesSubscription: PouchDB.Core.Changes<MessageDocument> | null = null
let syncMessages: PouchDB.Replication.Sync<MessageDocument> | null = null let syncMessages: PouchDB.Replication.Sync<MessageDocument> | null = null
// let syncChats: PouchDB.Replication.Sync<ChatDocument> | null = null
// Селектор для фильтрации сообщений // Селектор для фильтрации сообщений
const messageSelector = { const messageSelector = {
@@ -98,39 +71,6 @@ async function loadMessages() {
} }
} }
// Отправка нового сообщения
async function sendMessage() {
const created_at = new Date().toISOString()
const user_uuid = getUserUuid()
const message: MessageDocument = {
_id: `message:${qr_code_uri}:${chat}:${created_at}`,
type: 'message',
qr_code_uri,
chat,
from: userRole,
body: newMessage.value.trim(),
browser_uuid: getBrowserUuid(),
user_uuid,
created_at,
}
try {
await db.put(message)
newMessage.value = ''
// await chatsDbLocal.upsert(`chat:${user_uuid}:${userRole}:${qr_code_uri}:${chat}`, (chatDoc) => {
// if (chatDoc.last_message_at && chatDoc.last_message_at < created_at) {
// chatDoc.last_message_at = created_at
// return chatDoc
// } else {
// return false
// }
// })
} catch (error) {
console.error('Ошибка отправки сообщения:', error)
}
}
// Отслеживание изменений // Отслеживание изменений
function watchChanges() { function watchChanges() {
changesSubscription = db changesSubscription = db
@@ -169,15 +109,6 @@ function setupSync() {
syncMessages.on('error', (err) => { syncMessages.on('error', (err) => {
console.error('Ошибка синхронизации:', err) console.error('Ошибка синхронизации:', err)
}) })
// syncChats = chatsDbLocal.sync(chatsDbRemote, {
// live: true,
// retry: true,
// selector: {
// type: 'chat',
// qr_code_uri,
// chat,
// },
// })
} }
// Остановка синхронизации // Остановка синхронизации
@@ -186,10 +117,6 @@ function stopSync() {
syncMessages.cancel() syncMessages.cancel()
syncMessages = null syncMessages = null
} }
// if (syncChats) {
// syncChats.cancel()
// syncChats = null
// }
} }
// Отписка от изменений // Отписка от изменений
@@ -205,7 +132,6 @@ onMounted(async () => {
watchChanges() watchChanges()
setupSync() setupSync()
await loadMessages() await loadMessages()
formRef.value?.querySelector('input')?.focus()
}) })
watch( watch(
@@ -0,0 +1,61 @@
<template>
<div class="flex gap-3 px-4 pt-0 flex-col-reverse pb-safe-or-4">
<!-- Форма отправки сообщений -->
<form @submit.prevent="sendMessage" class="flex gap-2 items-center" ref="form">
<InputText
id="newMessage"
v-model="newMessage"
class="flex-1"
placeholder="Напишите сообщение"
/>
<Button type="submit" icon="pi pi-send" class="p-button-md" :disabled="!newMessage.trim()" />
</form>
<ChatSubscribeWebPush :qr_code_uri :chat :user_chat_role="userRole" />
</div>
</template>
<script setup lang="ts">
import { ref, useTemplateRef } from 'vue'
const newMessage = ref('')
const formRef = useTemplateRef('form')
import { getBrowserUuid } from '@/utils/getBrowserUuid'
import { getUserUuid } from '@/utils/getUserUuid'
import { type MessageDocument } from '@hereconnect/types'
import { messagesDbLocal as db } from '@/api/dbs'
const { qr_code_uri, chat, userRole } = defineProps<{
qr_code_uri: MessageDocument['qr_code_uri']
chat: MessageDocument['chat']
userRole: MessageDocument['from']
}>()
onMounted(() => {
formRef.value?.querySelector('input')?.focus()
})
// Отправка нового сообщения
async function sendMessage() {
const created_at = new Date().toISOString()
const user_uuid = getUserUuid()
const message: MessageDocument = {
_id: `message:${qr_code_uri}:${chat}:${created_at}`,
type: 'message',
qr_code_uri,
chat,
from: userRole,
body: newMessage.value.trim(),
browser_uuid: getBrowserUuid(),
user_uuid,
created_at,
}
try {
await db.put(message)
newMessage.value = ''
formRef.value?.querySelector('input')?.focus()
} catch (error) {
console.error('Ошибка отправки сообщения:', error)
}
}
</script>
-1
View File
@@ -69,7 +69,6 @@ const {
} = useMutation({ } = useMutation({
mutationKey: ['createQrCode'], mutationKey: ['createQrCode'],
mutationFn: async () => { mutationFn: async () => {
throw new Error('wtf')
const qrCodeDocument = await createQrCodeDocument({ const qrCodeDocument = await createQrCodeDocument({
name: name.value, name: name.value,
placement: placement.value!, placement: placement.value!,
@@ -8,10 +8,6 @@
/> />
</MetaHead> </MetaHead>
<div class="flex flex-col min-h-full">
<!-- Основной контент -->
<main class="flex-grow flex flex-col">
<section class="flex flex-col flex-grow max-w-prose w-full mx-auto">
<ChatComponent userRole="guest" :qr_code_uri="qr_code_uri" :chat="chat"> <ChatComponent userRole="guest" :qr_code_uri="qr_code_uri" :chat="chat">
<template #endOfMessages="{ count, lastMessage }"> <template #endOfMessages="{ count, lastMessage }">
<!-- Уведомление, если гость отправил только одно сообщение --> <!-- Уведомление, если гость отправил только одно сообщение -->
@@ -26,19 +22,6 @@
</div> </div>
</template> </template>
</ChatComponent> </ChatComponent>
</section>
</main>
<!-- Футер -->
<!-- <footer class="bg-gray-100 text-center py-4 border-t text-sm text-gray-700">-->
<!-- <p><a href="/create" class="underline underline-offset-2">Создайте свой QRкод</a>.</p>-->
<!-- <p class="mt-1">-->
<!-- Сделайте НаСвязи удобнее. Будем рады вашей&nbsp;<a href="/donate" class="underline underline-offset-2"-->
<!-- >поддержке</a-->
<!-- >.-->
<!-- </p>-->
<!-- </footer>-->
</div>
</LayoutWithTabs> </LayoutWithTabs>
</template> </template>
@@ -11,13 +11,14 @@
<QueryRender :query="query"> <QueryRender :query="query">
<template #default="{ data }"> <template #default="{ data }">
<div <div
v-if="data.rows.length > 0" v-if="data.length > 0"
class="justify-self-start align-baseline-start flex flex-col gap-4" class="justify-self-start align-baseline-start flex flex-col gap-4"
> >
<ChatCard <ChatCard
v-for="{ doc: chatDoc } in data.rows.filter((row) => !!row.doc)" v-for="row in data"
:key="`${chatDoc!._id}`" :key="row.id"
:chatDoc="chatDoc!" :chatDoc="row.doc!"
:qrCodeDoc="row.qrCodeDoc"
/> />
</div> </div>
@@ -44,19 +45,32 @@
<script setup lang="ts"> <script setup lang="ts">
import { useQuery } from '@tanstack/vue-query' import { useQuery } from '@tanstack/vue-query'
import { chatsDbRemote } from '@/api/dbs' import { chatsDbRemote, qrCodeDbLocal } from '@/api/dbs'
import { getUserUuid } from '@/utils/getUserUuid' import { getUserUuid } from '@/utils/getUserUuid'
import { type QRCodeDocument } from '@hereconnect/types'
const query = useQuery({
queryKey: ['qrCodes'],
queryFn: () => {
const user_uuid = getUserUuid() const user_uuid = getUserUuid()
return chatsDbRemote.allDocs({ const query = useQuery({
queryKey: ['chats', user_uuid],
queryFn: async () => {
const { rows } = await chatsDbRemote.allDocs({
startkey: `chat:${user_uuid}:`, startkey: `chat:${user_uuid}:`,
endkey: `chat:${user_uuid}:\uffff`, endkey: `chat:${user_uuid}:\uffff`,
limit: Number.MAX_SAFE_INTEGER, limit: Number.MAX_SAFE_INTEGER,
include_docs: true, include_docs: true,
}) })
const qrCodes = await qrCodeDbLocal.allDocs({
keys: rows.map((row) => `qr_code:${row.doc!.qr_code_uri}`),
include_docs: true,
})
const result: ((typeof rows)[number] & { qrCodeDoc?: QRCodeDocument })[] = []
qrCodes.rows.forEach((row, index) => {
result[index] = rows[index]
if ('doc' in row) {
result[index].qrCodeDoc = row.doc!
}
})
return result
}, },
}) })
</script> </script>