Added linting and enforced code styling.

This commit is contained in:
Cameron Redmore 2025-04-25 08:14:48 +01:00
parent 8655eae39c
commit 86967b26cd
37 changed files with 3356 additions and 1875 deletions

View file

@ -1,51 +1,62 @@
<template>
<div class="q-pa-md column full-height">
<q-scroll-area
ref="scrollAreaRef"
class="col"
style="flex-grow: 1; overflow-x: visible; overflow-y: auto;"
<div class="q-pa-md column full-height">
<q-scroll-area
ref="scrollAreaRef"
class="col"
style="flex-grow: 1; overflow-x: visible; overflow-y: auto;"
>
<div
v-for="(message, index) in messages"
:key="index"
class="q-mb-sm q-mx-md"
>
<q-chat-message
:name="message.sender.toUpperCase()"
:sent="message.sender === 'user'"
:bg-color="message.sender === 'user' ? 'primary' : 'grey-4'"
:text-color="message.sender === 'user' ? 'white' : 'black'"
>
<div v-for="(message, index) in messages" :key="index" class="q-mb-sm q-mx-md">
<q-chat-message
:name="message.sender.toUpperCase()"
:sent="message.sender === 'user'"
:bg-color="message.sender === 'user' ? 'primary' : 'grey-4'"
:text-color="message.sender === 'user' ? 'white' : 'black'"
>
<!-- Use v-html to render parsed markdown -->
<div v-if="!message.loading" v-html="parseMarkdown(message.content)" class="message-content"></div>
<!-- Optional: Add a spinner for a better loading visual -->
<template v-if="message.loading" v-slot:default>
<q-spinner-dots size="2em" />
</template>
</q-chat-message>
</div>
</q-scroll-area>
<!-- Use v-html to render parsed markdown -->
<div
v-if="!message.loading"
v-html="parseMarkdown(message.content)"
class="message-content"
/>
<!-- Optional: Add a spinner for a better loading visual -->
<template
v-if="message.loading"
#default
>
<q-spinner-dots size="2em" />
</template>
</q-chat-message>
</div>
</q-scroll-area>
<q-separator />
<q-separator />
<div class="q-pa-sm row items-center">
<q-input
v-model="newMessage"
outlined
dense
placeholder="Type a message..."
class="col"
@keyup.enter="sendMessage"
autogrow
/>
<q-btn
round
dense
flat
icon="send"
color="primary"
class="q-ml-sm"
@click="sendMessage"
:disable="!newMessage.trim()"
/>
</div>
<div class="q-pa-sm row items-center">
<q-input
v-model="newMessage"
outlined
dense
placeholder="Type a message..."
class="col"
@keyup.enter="sendMessage"
autogrow
/>
<q-btn
round
dense
flat
icon="send"
color="primary"
class="q-ml-sm"
@click="sendMessage"
:disable="!newMessage.trim()"
/>
</div>
</div>
</template>
<script setup>
@ -54,14 +65,14 @@ import { QScrollArea, QChatMessage, QSpinnerDots } from 'quasar'; // Import QSpi
import { marked } from 'marked'; // Import marked
const props = defineProps({
messages: {
type: Array,
required: true,
default: () => [],
// Example message structure:
// { sender: 'Bot', content: 'Hello!', loading: false }
// { sender: 'You', content: 'Thinking...', loading: true }
},
messages: {
type: Array,
required: true,
'default': () => [],
// Example message structure:
// { sender: 'Bot', content: 'Hello!', loading: false }
// { sender: 'You', content: 'Thinking...', loading: true }
},
});
const emit = defineEmits(['send-message']);
@ -69,30 +80,37 @@ const emit = defineEmits(['send-message']);
const newMessage = ref('');
const scrollAreaRef = ref(null);
const scrollToBottom = () => {
if (scrollAreaRef.value) {
const scrollTarget = scrollAreaRef.value.getScrollTarget();
const duration = 300; // Optional: animation duration
// Use getScrollTarget().scrollHeight for accurate height
scrollAreaRef.value.setScrollPosition('vertical', scrollTarget.scrollHeight, duration);
}
const scrollToBottom = () =>
{
if (scrollAreaRef.value)
{
const scrollTarget = scrollAreaRef.value.getScrollTarget();
const duration = 300; // Optional: animation duration
// Use getScrollTarget().scrollHeight for accurate height
scrollAreaRef.value.setScrollPosition('vertical', scrollTarget.scrollHeight, duration);
}
};
const sendMessage = () => {
const trimmedMessage = newMessage.value.trim();
if (trimmedMessage) {
emit('send-message', trimmedMessage);
newMessage.value = '';
// Ensure the scroll happens after the message is potentially added to the list
nextTick(() => {
scrollToBottom();
});
}
const sendMessage = () =>
{
const trimmedMessage = newMessage.value.trim();
if (trimmedMessage)
{
emit('send-message', trimmedMessage);
newMessage.value = '';
// Ensure the scroll happens after the message is potentially added to the list
nextTick(() =>
{
scrollToBottom();
});
}
};
const parseMarkdown = (content) => {
const parseMarkdown = (content) =>
{
// Basic check to prevent errors if content is not a string
if (typeof content !== 'string') {
if (typeof content !== 'string')
{
return '';
}
// Configure marked options if needed (e.g., sanitization)
@ -101,10 +119,12 @@ const parseMarkdown = (content) => {
};
// Scroll to bottom when messages change or component mounts
watch(() => props.messages, () => {
nextTick(() => {
scrollToBottom();
});
watch(() => props.messages, () =>
{
nextTick(() =>
{
scrollToBottom();
});
}, { deep: true, immediate: true });
</script>