diff --git a/package-lock.json b/package-lock.json index 3aefaad..6e3ae83 100644 --- a/package-lock.json +++ b/package-lock.json @@ -123,9 +123,9 @@ "license": "(Apache-2.0 AND BSD-3-Clause)" }, "node_modules/@cypress/request": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.9.tgz", - "integrity": "sha512-I3l7FdGRXluAS44/0NguwWlO83J18p0vlr2FYHrJkWdNYhgVoiYo61IXPqaOsL+vNxU1ZqMACzItGK3/KKDsdw==", + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.10.tgz", + "integrity": "sha512-hauBrOdvu08vOsagkZ/Aju5XuiZx6ldsLfByg1htFeldhex+PeMrYauANzFsMJeAA0+dyPLbDoX2OYuvVoLDkQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -142,7 +142,7 @@ "json-stringify-safe": "~5.0.1", "mime-types": "~2.1.19", "performance-now": "^2.1.0", - "qs": "6.14.0", + "qs": "~6.14.1", "safe-buffer": "^5.1.2", "tough-cookie": "^5.0.0", "tunnel-agent": "^0.6.0", @@ -3182,24 +3182,24 @@ "license": "MIT" }, "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", + "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", "dev": true, "license": "MIT", "dependencies": { - "bytes": "3.1.2", + "bytes": "~3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.14.0", + "raw-body": "~2.5.3", "type-is": "~1.6.18", - "unpipe": "1.0.0" + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8", @@ -3216,6 +3216,27 @@ "ms": "2.0.0" } }, + "node_modules/body-parser/node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -3223,20 +3244,14 @@ "dev": true, "license": "MIT" }, - "node_modules/body-parser/node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "node_modules/body-parser/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.6" - }, + "license": "MIT", "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.8" } }, "node_modules/boolbase": { @@ -4995,40 +5010,40 @@ } }, "node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", "dev": true, "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", - "on-finished": "2.4.1", + "on-finished": "~2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", + "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", - "qs": "6.13.0", + "qs": "~6.14.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", + "send": "~0.19.0", + "serve-static": "~1.16.2", "setprototypeof": "1.2.0", - "statuses": "2.0.1", + "statuses": "~2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" @@ -5058,22 +5073,6 @@ "dev": true, "license": "MIT" }, - "node_modules/express/node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -5578,9 +5577,9 @@ } }, "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, "license": "ISC", "dependencies": { @@ -6310,9 +6309,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "license": "MIT", "dependencies": { @@ -7394,9 +7393,9 @@ } }, "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.3.tgz", + "integrity": "sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==", "dev": true, "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { @@ -8039,9 +8038,9 @@ } }, "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", + "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -8111,21 +8110,52 @@ } }, "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", "dev": true, "license": "MIT", "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8" } }, + "node_modules/raw-body/node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/raw-body/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/readable-stream": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", @@ -9879,9 +9909,9 @@ } }, "node_modules/vite": { - "version": "6.3.6", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.6.tgz", - "integrity": "sha512-0msEVHJEScQbhkbVTb/4iHZdJ6SXp/AvxL2sjwYQFfBqleHtnCqv1J3sa9zbWz/6kW1m9Tfzn92vW+kZ1WV6QA==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", + "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "dev": true, "license": "MIT", "dependencies": { diff --git a/src/layouts/components/main-layout-header-bar.vue b/src/layouts/components/main-layout-header-bar.vue index 01af21c..5ad6d39 100644 --- a/src/layouts/components/main-layout-header-bar.vue +++ b/src/layouts/components/main-layout-header-bar.vue @@ -3,14 +3,8 @@ setup > import { useUiStore } from 'src/stores/ui-store'; - import { useAuthStore } from 'src/stores/auth-store'; - import { useChatbotStore } from 'src/stores/chatbot-store'; - - // import HeaderBarNotification from './main-layout-header-bar-notification.vue'; const uiStore = useUiStore(); - const chatbot_store = useChatbotStore(); - const auth_store = useAuthStore(); @@ -37,19 +31,6 @@ /> - - - - - diff --git a/src/layouts/main-layout.vue b/src/layouts/main-layout.vue index 67c31b3..1b3ab40 100644 --- a/src/layouts/main-layout.vue +++ b/src/layouts/main-layout.vue @@ -6,15 +6,17 @@ import FooterBar from 'src/layouts/components/main-layout-footer-bar.vue'; import LeftDrawer from 'src/layouts/components/main-layout-left-drawer.vue'; import ChatbotDrawer from 'src/modules/chatbot/components/chatbot-drawer.vue'; - + import { onMounted, watch, ref } from 'vue'; import { RouterView } from 'vue-router'; import { useUiStore } from 'src/stores/ui-store'; + import { useAuthStore } from 'src/stores/auth-store'; + - const ui_store = useUiStore(); + const auth_store = useAuthStore(); const user_preferences = ref(ui_store.user_preferences); - + onMounted(async () => { if (ui_store.user_preferences.id === -1) { await ui_store.getUserPreferences(); @@ -27,7 +29,7 @@ return } await ui_store.getUserPreferences(); - }, {deep: true}); + }, { deep: true }); @@ -36,12 +38,12 @@ - + - + diff --git a/src/modules/chatbot/components/chatbot-drawer.vue b/src/modules/chatbot/components/chatbot-drawer.vue index c1e307b..380c991 100644 --- a/src/modules/chatbot/components/chatbot-drawer.vue +++ b/src/modules/chatbot/components/chatbot-drawer.vue @@ -12,10 +12,14 @@ const chatbot_store = useChatbotStore(); const text = ref(''); + const is_showing_right_drawer = ref(true); + const drawer_width = ref(85); const handleSend = async () => { - await chatbot_api.sendMessage(text.value.trim()); + const message = text.value.trim(); text.value = ''; + console.log('message: ', message, ', length: ', message.length); + await chatbot_api.sendMessage(message); }; onMounted(() => { @@ -25,51 +29,79 @@ - - - - - - + + - - + + + - + + + + + + + + + + + \ No newline at end of file diff --git a/src/modules/chatbot/components/dialogue-content.vue b/src/modules/chatbot/components/dialogue-content.vue index e3a3685..f9f80dd 100644 --- a/src/modules/chatbot/components/dialogue-content.vue +++ b/src/modules/chatbot/components/dialogue-content.vue @@ -14,34 +14,38 @@ watch(chatbot_store.messages, () => { if (scroll_area.value) { - scroll_area.value.setScrollPercentage('vertical', 1.0, 500); + scroll_area.value.setScrollPosition('vertical', 999999999, 300); } }) - + - - - - {{ $t('chatbot.chat_thinking') }} - + + + + \ No newline at end of file diff --git a/src/modules/chatbot/components/dialogue-phrase.vue b/src/modules/chatbot/components/dialogue-phrase.vue index c6a4f45..7ed1152 100644 --- a/src/modules/chatbot/components/dialogue-phrase.vue +++ b/src/modules/chatbot/components/dialogue-phrase.vue @@ -3,7 +3,7 @@ lang="ts" > import { computed } from 'vue'; - import MarkdownIt from 'markdown-it' + // import MarkdownIt from 'markdown-it' import { useAuthStore } from 'src/stores/auth-store'; import type { Message } from 'src/modules/chatbot/models/dialogue-message.model'; import { useI18n } from 'vue-i18n'; @@ -15,41 +15,73 @@ message: Message; }>(); + const message_text = computed(() => message.text.includes('chatbot.') ? t(message.text) : message.text) + + const is_error = computed(() => message.text.includes('NO_REPLY_RECEIVED') || message.text.includes('SEND_MESSAGE_FAILED')); + // Initialize Markdown parser - const md = new MarkdownIt({ - breaks: false, // Support line breaks - linkify: true, // Make URLs clickable - html: false // Prevent raw HTML injection - }) + // const md = new MarkdownIt({ + // // breaks: false, // Support line breaks + // linkify: true, // Make URLs clickable + // html: false // Prevent raw HTML injection + // }) - // Removes all the h1,h2,h3 to make the Md more user friendly - const cleanMarkdown = (markdown: string): string => { - if (!markdown) return '' - return markdown - .replace(/\r\n/g, '\n') // normalize Windows line endings - .replace(/([.!?])(\s+)(?=[A-Z])/g, '$1\n') // insert line break after sentence-ending punctuation - .replace(/\n{3,}/g, '\n\n') // squash triple+ line breaks - .replace(/^#{1,3}\s(.*)$/gm, '#### $1') // downgrade headings - } + // // Removes all the h1,h2,h3 to make the Md more user friendly + // const cleanMarkdown = (markdown: string): string => { + // if (!markdown) return '' + // return markdown + // .replace(/\r\n/g, '\n') // normalize Windows line endings + // .replace(/([.!?])(\s+)(?=[A-Z])/g, '$1\n') // insert line break after sentence-ending punctuation + // .replace(/\n{3,}/g, '\n\n') // squash triple+ line breaks + // .replace(/^#{1,3}\s(.*)$/gm, '#### $1') // downgrade headings + // } - // Compute parsed content - const parsedText = computed((): string => { - const cleaned = cleanMarkdown(message.text || '') - if (cleaned.includes('chatbot.')) { - const translated_message = t(message.text); - return md.render(translated_message); - } - return md.render(cleaned); - }) + // // Compute parsed content + // const parsedText = computed((): string => { + // const cleaned = cleanMarkdown(message.text || '') + // if (cleaned.includes('chatbot.')) { + // const translated_message = t(message.text); + // return md.render(translated_message); + // } + // return md.render(cleaned); + // }) + + + {{ message_text }} + + + + - - + :text="[message_text]" + /> + + \ No newline at end of file diff --git a/src/modules/chatbot/models/page-context.model.ts b/src/modules/chatbot/models/page-context.model.ts index ea6e5d7..5d76c92 100644 --- a/src/modules/chatbot/models/page-context.model.ts +++ b/src/modules/chatbot/models/page-context.model.ts @@ -1,13 +1,13 @@ import { RouteNames } from "src/router/router-constants"; -export interface chatbotPageContext { +export interface ChatbotPageContext { name: string; description: string; features: string[]; path: RouteNames | null; } -export const dashboardContext: chatbotPageContext = { +export const dashboardContext: ChatbotPageContext = { name: "Dashboard", description: "Landing page containing useful links and a carousel showcasing recent news, as well as a local weather widget in the top right corner", features: [ @@ -18,7 +18,7 @@ export const dashboardContext: chatbotPageContext = { path: RouteNames.DASHBOARD, }; -export const leftDrawerContext: chatbotPageContext = { +export const leftDrawerContext: ChatbotPageContext = { name: "Left Drawer", description: "A drawer that acts as a navigation bar, routes to different parts of the website. Some icons will be hidden according to user access", features: [ @@ -33,7 +33,7 @@ export const leftDrawerContext: chatbotPageContext = { path: null, }; -export const profileContext: chatbotPageContext = { +export const profileContext: ChatbotPageContext = { name: "Profile", description: "Display and edit user information", features: [ @@ -44,7 +44,7 @@ export const profileContext: chatbotPageContext = { path: RouteNames.PROFILE, }; -export const employeeListContext: chatbotPageContext = { +export const employeeListContext: ChatbotPageContext = { name: "Employee List", description: "View all the hired and currently active Staff", features: [ @@ -57,7 +57,7 @@ export const employeeListContext: chatbotPageContext = { path: RouteNames.EMPLOYEE_LIST, }; -export const timesheetApprovalContext: chatbotPageContext = { +export const timesheetApprovalContext: ChatbotPageContext = { name: "Timesheet Approval", description: "Page where employee hours and shifts are approved for accounting purposes. Requires timesheet_approval module access.", features: [ @@ -71,7 +71,7 @@ export const timesheetApprovalContext: chatbotPageContext = { path: RouteNames.TIMESHEET_APPROVALS, }; -export const timesheetContext: chatbotPageContext = { +export const timesheetContext: ChatbotPageContext = { name: "Timesheet", description: "Page where an employee can enter their hours for their day and week. Display in 2-week pay periods.", @@ -86,7 +86,7 @@ export const timesheetContext: chatbotPageContext = { path: RouteNames.TIMESHEET, }; -export const helpContext: chatbotPageContext = { +export const helpContext: ChatbotPageContext = { name: "Help", description: "page containing common Q&A segments regarding website functionalities", features: [ @@ -98,7 +98,7 @@ export const helpContext: chatbotPageContext = { path: RouteNames.HELP, } -export const PageContexts: Record = { +export const PageContexts: Record = { "login": null, "login-success": null, "error": null, diff --git a/src/modules/chatbot/services/chatbot.service.ts b/src/modules/chatbot/services/chatbot.service.ts index b68f6b4..0a297ed 100644 --- a/src/modules/chatbot/services/chatbot.service.ts +++ b/src/modules/chatbot/services/chatbot.service.ts @@ -1,28 +1,28 @@ -import type { chatbotPageContext } from "src/modules/chatbot/models/page-context.model"; +import type { ChatbotPageContext } from "src/modules/chatbot/models/page-context.model"; import type { Message } from "src/modules/chatbot/models/dialogue-message.model"; import { api } from "src/boot/axios"; export const chatbotService = { // Function to send the message to the backend - sendChatMessage: async (userInput: string): Promise => { - const response = await api.post("/chatbot", { userInput }); + sendChatMessage: async (userInput: string, pageContext: ChatbotPageContext | undefined): Promise => { + const response = await api.post("/chatbot", { userInput, pageContext }); return response.data as Message; }, - // Function to send context to backend - sendPageContext: async (context: chatbotPageContext): Promise => { - const response = await api.post("/chatbot/context", context); - return response.data; - }, + // // Function to send context to backend + // sendPageContext: async (context: chatbotPageContext): Promise => { + // const response = await api.post("/chatbot/context", context); + // return response.data; + // }, - // Function to send user credentials to the backend to communicate with n8n. - sendUserCredentials: async (email: string, role: string): Promise => { - const response = await api.post("/chatbot/user", { email, role }); - return response.data; - }, + // // Function to send user credentials to the backend to communicate with n8n. + // sendUserCredentials: async (email: string, role: string): Promise => { + // const response = await api.post("/chatbot/user", { email, role }); + // return response.data; + // }, - retrieveCustomerDiagnostics: async (id: string): Promise => { - const response = await api.get(`/chat/customer/${id}`); - return response.data; - }, + // retrieveCustomerDiagnostics: async (id: string): Promise => { + // const response = await api.get(`/chat/customer/${id}`); + // return response.data; + // }, }; diff --git a/src/modules/timesheet-approval/components/details-dialog-chart-hours-worked.vue b/src/modules/timesheet-approval/components/details-dialog-chart-hours-worked.vue index 165256b..b3f8867 100644 --- a/src/modules/timesheet-approval/components/details-dialog-chart-hours-worked.vue +++ b/src/modules/timesheet-approval/components/details-dialog-chart-hours-worked.vue @@ -12,7 +12,7 @@ import { getHoursMinutesStringFromHoursFloat } from 'src/utils/date-and-time-utils'; interface ChartConfigHoursWorked { - key: keyof Pick; + key: keyof Pick; label: string; color: string; } @@ -50,6 +50,16 @@ import { getHoursMinutesStringFromHoursFloat } from 'src/utils/date-and-time-uti label: t('shared.shift_type.overtime'), color: colors.getPaletteColor('negative'), }, + { + key: 'holiday', + label: t('shared.shift_type.holiday'), + color: colors.getPaletteColor('purple-5'), + }, + { + key: 'vacation', + label: t('shared.shift_type.vacation'), + color: colors.getPaletteColor('deep-orange-5'), + }, ]; const hours_worked_labels = ref(all_days.map(day => day.date.slice(-5,))); diff --git a/src/modules/timesheet-approval/components/overview-list-filters.vue b/src/modules/timesheet-approval/components/overview-list-filters.vue index 9290348..588dab1 100644 --- a/src/modules/timesheet-approval/components/overview-list-filters.vue +++ b/src/modules/timesheet-approval/components/overview-list-filters.vue @@ -14,7 +14,6 @@ onMounted(() => { Object.values(overview_column_names).map(column => column_options.value.push({ label: `timesheet_approvals.table.${column}`, value: column as OverviewColumns })) column_options.value = column_options.value.filter(column => !EXCLUDED_COLUMNS.includes(column.value)); - console.log('filter column values: ', column_options.value ) }) diff --git a/src/modules/timesheet-approval/components/overview-list.vue b/src/modules/timesheet-approval/components/overview-list.vue index 13c8687..9e39a4d 100644 --- a/src/modules/timesheet-approval/components/overview-list.vue +++ b/src/modules/timesheet-approval/components/overview-list.vue @@ -90,7 +90,7 @@ const getListViewTimeCss = (column_name: OverviewColumns, value: number): { classes: string, style: string } => { if (WARNING_COLUMNS.includes(column_name) && value > 0) - return { classes: 'bg-warning text-white rounded-5', style: '' }; + return { classes: 'bg-warning text-white text-bold rounded-5', style: '' }; if (NEGATIVE_COLUMNS.includes(column_name) && value > 0) return { classes: 'bg-negative text-white text-bold rounded-5', style: '' }; diff --git a/src/modules/timesheets/components/timesheet-wrapper.vue b/src/modules/timesheets/components/timesheet-wrapper.vue index 5949338..00318ba 100644 --- a/src/modules/timesheets/components/timesheet-wrapper.vue +++ b/src/modules/timesheets/components/timesheet-wrapper.vue @@ -30,7 +30,7 @@ const is_timesheets_approved = computed(() => timesheet_store.timesheets.every(timesheet => timesheet.is_approved)) const total_hours = computed(() => timesheet_store.timesheets.reduce((sum, timesheet) => - sum + timesheet.weekly_hours.regular + sum += timesheet.weekly_hours.regular + timesheet.weekly_hours.evening + timesheet.weekly_hours.emergency + timesheet.weekly_hours.overtime, diff --git a/src/modules/timesheets/models/shift.models.ts b/src/modules/timesheets/models/shift.models.ts index 0524054..956adc5 100644 --- a/src/modules/timesheets/models/shift.models.ts +++ b/src/modules/timesheets/models/shift.models.ts @@ -5,11 +5,11 @@ export const SHIFT_TYPES: ShiftType[] = [ 'HOLIDAY', 'VACATION', 'SICK', - 'BANKING', + // 'BANKING', 'WITHDRAW_BANKED', ]; -export type ShiftType = 'REGULAR' | 'EVENING' | 'EMERGENCY' | 'HOLIDAY' | 'VACATION' | 'SICK' | 'BANKING' | 'WITHDRAW_BANKED'; +export type ShiftType = 'REGULAR' | 'EVENING' | 'EMERGENCY' | 'HOLIDAY' | 'VACATION' | 'SICK' | /*'BANKING'|*/ 'WITHDRAW_BANKED'; export type ShiftErrorCode = 'SHIFT_OVERLAP' | 'MISSING_START_TIME' | 'MISSING_END_TIME' | 'COMMENT_LENGTH_EXCEEDED' | 'APPROVAL_LOCK' | 'INVALID_DATE' | 'INVALID TYPE' | 'INVALID_TIMESHEET'; diff --git a/src/modules/timesheets/utils/shift.util.ts b/src/modules/timesheets/utils/shift.util.ts index f204302..812643c 100644 --- a/src/modules/timesheets/utils/shift.util.ts +++ b/src/modules/timesheets/utils/shift.util.ts @@ -33,6 +33,6 @@ export const SHIFT_OPTIONS: ShiftOption[] = [ { label: 'timesheet.shift.types.VACATION', value: 'VACATION', icon: 'beach_access', icon_color: 'deep-orange-5' }, { label: 'timesheet.shift.types.HOLIDAY', value: 'HOLIDAY', icon: 'event', icon_color: 'purple-5' }, { label: 'timesheet.shift.types.SICK', value: 'SICK', icon: 'medication_liquid', icon_color: 'light-blue-6' }, - { label: 'timesheet.shift.types.BANKING', value: 'BANKING', icon: 'savings', icon_color: 'pink-3' }, + // { label: 'timesheet.shift.types.BANKING', value: 'BANKING', icon: 'savings', icon_color: 'pink-3' }, { label: 'timesheet.shift.types.WITHDRAW_BANKED', value: 'WITHDRAW_BANKED', icon: 'attach_money', icon_color: 'yellow-4' }, ]; \ No newline at end of file diff --git a/src/router/index.ts b/src/router/index.ts index 8033b23..09c82af 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -45,12 +45,12 @@ export default defineRouter(function (/* { store, ssrContext } */) { } }) - Router.afterEach( async (destination_page) => { + Router.afterEach( (destination_page) => { const auth_store = useAuthStore(); if (auth_store.user?.user_module_access.includes('chatbot')) { const chatbot_store = useChatbotStore(); - await chatbot_store.updatePageContext(destination_page.name as RouteNames); + chatbot_store.updatePageContext(destination_page.name as RouteNames); } }) diff --git a/src/stores/chatbot-store.ts b/src/stores/chatbot-store.ts index 3b66c21..b0fc645 100644 --- a/src/stores/chatbot-store.ts +++ b/src/stores/chatbot-store.ts @@ -2,19 +2,20 @@ import { ref } from "vue"; import { defineStore } from "pinia"; import { chatbotService } from "src/modules/chatbot/services/chatbot.service"; import type { Message } from "src/modules/chatbot/models/dialogue-message.model"; +import { type ChatbotPageContext, PageContexts } from "src/modules/chatbot/models/page-context.model"; import type { RouteNames } from "src/router/router-constants"; -import { PageContexts } from "src/modules/chatbot/models/page-context.model"; export const useChatbotStore = defineStore("chatbot", () => { const messages = ref([]); const has_shown_instructions = ref(false); const is_showing_chatbot = ref(false); + const current_page_context = ref(undefined); const sendChatMessage = async (user_message: string) => { const last_chatbot_message = messages.value.at(messages.value.length - 1)!; try { - const chatbot_response = await chatbotService.sendChatMessage(user_message); + const chatbot_response = await chatbotService.sendChatMessage(user_message, current_page_context.value); if (chatbot_response) { last_chatbot_message.text = chatbot_response.text; last_chatbot_message.isThinking = false; @@ -30,11 +31,9 @@ export const useChatbotStore = defineStore("chatbot", () => { } }; - const updatePageContext = async (page_name: RouteNames) => { - const chatbot_page_context = PageContexts[page_name]; - - if (chatbot_page_context) - await chatbotService.sendPageContext(chatbot_page_context); + const updatePageContext = (page_name: RouteNames) => { + current_page_context.value = PageContexts[page_name] ?? undefined; + }; const showInstructionsOnce = () => {