diff --git a/amd/src/ai_manager.js b/amd/src/ai_manager.js index d224eba..27ea7c2 100644 --- a/amd/src/ai_manager.js +++ b/amd/src/ai_manager.js @@ -1,5 +1,4 @@ import {makeRequest} from 'local_ai_manager/make_request'; -import {exception as displayException} from 'core/notification'; /** * Get the async answer from the local_ai_manager. @@ -14,7 +13,6 @@ export const askLocalAiManager = async(purpose, prompt, options = []) => { try { result = await makeRequest(purpose, prompt, options); } catch (error) { - console.log(error); result.code = 'aiconnector'; result.result = error.error + " " + error.message; // For devs. diff --git a/amd/src/dialog.js b/amd/src/dialog.js index 1660064..f9fe907 100644 --- a/amd/src/dialog.js +++ b/amd/src/dialog.js @@ -64,7 +64,6 @@ class DialogModal extends Modal { modalConfig.removeOnClose = false; modalConfig.isVerticallyCentered = false; - // returnFocus: target, super.configure(modalConfig); @@ -107,7 +106,6 @@ export const init = async(params) => { templateContext: { title: strNewDialog, badge: badge, - // history: history, // history dynamically added. }, }); @@ -232,12 +230,9 @@ async function showModal() { * Webservice Get all conversations. */ const getConversations = async() => { - console.log("allConversations called"); try { allConversations = await externalServices.getAllConversations(userid, contextid); - console.log(allConversations); } catch (error) { - console.log(allConversations); displayException(error); } }; @@ -247,7 +242,6 @@ const getConversations = async() => { * @param {*} id */ const showConversation = (id = 0) => { - console.log("showConversation called"); // Dissallow changing conversations when question running. if (aiAtWork) { return; @@ -284,7 +278,6 @@ const enterQuestion = async(question) => { } const message = await userAllowed(); if (message !== '') { - console.log("User not allowed"); const notice = await getString('noticenewquestion', 'block_ai_chat'); await displayAlert(notice, message); aiAtWork = false; @@ -363,7 +356,7 @@ const enterQuestion = async(question) => { * Render reply. * @param {string} text */ -const showReply = async (text) => { +const showReply = async(text) => { // Get textblock. let fields = document.querySelectorAll('.ai_chat_modal .awaitanswer .text'); const field = fields[fields.length - 1]; @@ -378,7 +371,6 @@ const showReply = async (text) => { }; const showMessages = () => { - console.log("showMessages called"); conversation.messages.forEach((val) => { showMessage(val.message, val.sender); }); @@ -427,7 +419,6 @@ const showMessage = async(text, sender = '', answer = true) => { * @param {bool} deleted */ const newDialog = async(deleted = false) => { - console.log("newDialog called"); if (aiAtWork) { return; } @@ -449,7 +440,6 @@ const newDialog = async(deleted = false) => { * Delete /hide current dialog. */ const deleteCurrentDialog = () => { - console.log("deleteCurrentDialog called"); deleteCancelPromise( getString('delete', 'block_ai_chat'), getString('deletewarning', 'block_ai_chat'), @@ -475,7 +465,6 @@ const deleteCurrentDialog = () => { * Show conversation history. */ const showHistory = async() => { - console.log("showHistory called"); // Add current convo local representation, if not already there. if (allConversations.find(x => x.id === conversation.id) === undefined) { allConversations.push(conversation); @@ -598,7 +587,6 @@ const saveConversationLocally = (question, reply) => { * @param {*} hideinput */ const clearMessages = (hideinput = false) => { - console.log("clearMessages called"); const output = document.querySelector('.block_ai_chat-output'); output.innerHTML = ''; // For showing history. @@ -727,7 +715,6 @@ const errorHandling = async(requestresult, question, options) => { // And write generic error message in chatbot. requestresult.result = await getString('error', 'block_ai_chat'); - console.log(requestresult); return requestresult; }; @@ -738,11 +725,9 @@ const errorHandling = async(requestresult, question, options) => { */ const checkMessageHistoryLengthLimit = async(messages) => { const length = messages.length; - console.log("checkHistoryLengthLimit called"); if (length > maxHistory) { // Cut history. let shortenedMessages = [messages[0], ...messages.slice(-maxHistory)]; - console.log(shortenedMessages); // Show warning once per session. if (!maxHistoryWarnings.has(conversation.id)) { @@ -800,6 +785,7 @@ const setView = async(mode = '') => { * @returns {message} */ const userAllowed = async() => { + let message; if (tenantConfig.tenantenabled === false) { message = await getString('error_http403disabled', 'local_ai_manager'); return message; diff --git a/amd/src/helper.js b/amd/src/helper.js index ea9cc88..d82e1eb 100644 --- a/amd/src/helper.js +++ b/amd/src/helper.js @@ -47,7 +47,6 @@ export const focustextarea = () => { * Scroll to bottom of modal body. */ export const scrollToBottom = () => { - console.log("scroll to bottom called"); const modalContent = document.querySelector('.ai_chat_modal .modal-body .block_ai_chat-output-wrapper'); modalContent.scrollTop = modalContent.scrollHeight; }; @@ -71,7 +70,7 @@ export const escapeHTML = (str) => { '/': '/', }; - return String(str).replace(/[&<>"'`\/]/g, function(match) { + return String(str).replace(/[&<>"'`/]/g, function(match) { return escapeMap[match]; }); }; diff --git a/classes/external/delete_conversation.php b/classes/external/delete_conversation.php index 594dd8d..3ee147f 100644 --- a/classes/external/delete_conversation.php +++ b/classes/external/delete_conversation.php @@ -47,6 +47,8 @@ public static function execute_parameters(): external_function_parameters { * Execute the service. * * @param int $contextid + * @param int $userid + * @param int $conversationid * @return array * @throws invalid_parameter_exception * @throws dml_exception diff --git a/classes/local/hook_callbacks.php b/classes/local/hook_callbacks.php index fd1e0dd..25c0130 100644 --- a/classes/local/hook_callbacks.php +++ b/classes/local/hook_callbacks.php @@ -85,7 +85,9 @@ public static function handle_after_form_submission(\core_course\hook\after_form /** * Check if block instance is present and set addaichat form setting. * - * @param after_form_submission $hook + * @param after_form_definition_after_data $hook + * @return void + * @throws \dml_exception */ public static function handle_after_form_definition_after_data(\core_course\hook\after_form_definition_after_data $hook): void { // Get form data. diff --git a/classes/output/renderer.php b/classes/output/renderer.php index 3e8e768..33eda6d 100644 --- a/classes/output/renderer.php +++ b/classes/output/renderer.php @@ -33,6 +33,7 @@ class renderer extends plugin_renderer_base { /** * Defer to template. * + * @param block_ai_chat $block * @return string html for the page */ public function render_ai_chat_content(\block_ai_chat $block): string { diff --git a/package.json b/package.json index 5592d41..2e43113 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "moodle-block_ai_chat", "scripts": { - "compile-sass": "sass --no-source-map styles.scss styles.css" + "compile-sass": "sass --no-source-map styles.scss styles.css && sed -i 's/^ / /g' styles.css" }, "devDependencies": { "sass": "^1.77.2" diff --git a/styles.css b/styles.css index dd90c58..5d03c56 100644 --- a/styles.css +++ b/styles.css @@ -1,343 +1,345 @@ #ai_chat_button { - visibility: visible; - position: fixed; - bottom: 4.5rem; - right: 2rem; - transition: 0.2s; - z-index: 1000; - display: flex; - justify-content: center; - align-items: center; - border: 1px solid #6c757d; + visibility: visible; + position: fixed; + bottom: 4.5rem; + right: 2rem; + transition: 0.2s; + z-index: 1000; + display: flex; + justify-content: center; + align-items: center; + border: 1px solid #6c757d; } #ai_chat_button:hover { - filter: hue-rotate(10deg) brightness(90%); + filter: hue-rotate(10deg) brightness(90%); } @media (max-width: 576px) { - #ai_chat_button { - top: 87vh; - right: 0.5rem; - bottom: unset; - } + #ai_chat_button { + top: 87vh; + right: 0.5rem; + bottom: unset; + } } .drawer-right.show #ai_chat_button, .show-drawer-right #ai_chat_button { - right: calc(315px + 2rem); + right: calc(315px + 2rem); } .ai_chat_modal .modal-dialog { - min-height: 500px; + min-height: 500px; } .ai_chat_modal .modal-header { - width: 100%; - border-bottom: none; + width: 100%; + border-bottom: none; } .ai_chat_modal .modal-header .modal-title { - display: flex; - justify-content: space-between; - align-items: center; - width: calc(100% - 2rem); - font-size: 1rem; + display: flex; + justify-content: space-between; + align-items: center; + width: calc(100% - 2rem); + font-size: 1rem; } .ai_chat_modal .modal-header .modal-title .ai_chat_title { - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; } .ai_chat_modal .modal-body { - display: flex; - padding: 0 0 0 1rem; + display: flex; + padding: 0 0 0 1rem; } .ai_chat_modal .modal-body .block_ai_chat-dialog { - display: flex; - flex-direction: column; - justify-content: space-between; - width: 100%; - height: 100%; + display: flex; + flex-direction: column; + justify-content: space-between; + width: 100%; + height: 100%; } .ai_chat_modal .content { - display: flex; - align-items: flex-start; - padding: 0.5rem 1rem 0.5rem 1rem; - position: relative; + display: flex; + align-items: flex-start; + padding: 0.5rem 1rem 0.5rem 1rem; + position: relative; } .ai_chat_modal .message .copy { - visibility: hidden; - position: absolute; - top: 0; - right: 0; - padding: 0.5rem 0.75rem 2.5rem 2.75rem; + visibility: hidden; + position: absolute; + top: 0; + right: 0; + padding: 0.5rem 0.75rem 2.5rem 2.75rem; } .ai_chat_modal .message.ai:hover .copy { - visibility: visible; - cursor: pointer; + visibility: visible; + cursor: pointer; } .ai_chat_modal .message.ai .content { - padding-left: 0; + padding-left: 0; } .ai_chat_modal .message.ai .content .text { - margin-top: 0.4rem; + margin-top: 0.4rem; } .ai_chat_modal .message.ai .content .text p { - margin-bottom: 0.3rem; + margin-bottom: 0.3rem; } .ai_chat_modal .message.ai .content .ai_chat_icon { - margin-top: 0.8rem; + margin-top: 0.8rem; } .ai_chat_modal .message.ai .content .spinner-border { - width: 1.5rem; - height: 1.5rem; + width: 1.5rem; + height: 1.5rem; } .ai_chat_modal .message.ai .content.awaitanswer .ai_chat_icon, .ai_chat_modal .message.ai .content.awaitanswer .copy { - display: none; + display: none; } .ai_chat_modal .message.agent .content { - background-color: #dee2e6; - margin-left: 4rem; - border-radius: 0.5rem; + background-color: #dee2e6; + margin-left: 4rem; + border-radius: 0.5rem; } .ai_chat_modal .message.agent .content .ai_chat_icon { - display: none; + display: none; } .ai_chat_modal .message.agent .content p { - margin-bottom: 0.1rem; + margin-bottom: 0.1rem; } .ai_chat_modal .copiedtoast { - position: absolute; - top: -15px; - right: 0; - font-size: small; - border: 1px solid; - padding: 1px 3px; - background-color: #fff; - visibility: hidden; + position: absolute; + top: -15px; + right: 0; + font-size: small; + border: 1px solid; + padding: 1px 3px; + background-color: #fff; + visibility: hidden; } .ai_chat_modal .block_ai_chat-input-wrapper { - position: sticky; - bottom: 0; - background-color: #fff; - padding-right: 1rem; + position: sticky; + bottom: 0; + background-color: #fff; + padding-right: 1rem; } .ai_chat_modal .block_ai_chat-input { - display: flex; - margin-top: 0.15rem; - padding: 0 0.1rem 0 0.1rem; - position: relative; + display: flex; + margin-top: 0.15rem; + padding: 0 0.1rem 0 0.1rem; + position: relative; } .ai_chat_modal .block_ai_chat-input .ai_chat_icon { - position: absolute; - top: 1.2rem; - left: 0.5rem; + position: absolute; + top: 1.2rem; + left: 0.5rem; } .ai_chat_modal .block_ai_chat-input textarea { - height: inherit; - padding: 1rem 4.1rem 1rem 2.2rem; - resize: none; - overflow: auto; - line-height: 1.5rem; - min-height: 3.5rem; - max-height: 8rem; - box-sizing: border-box; - margin-left: 2px; + height: inherit; + padding: 1rem 4.1rem 1rem 2.2rem; + resize: none; + overflow: auto; + line-height: 1.5rem; + min-height: 3.5rem; + max-height: 8rem; + box-sizing: border-box; + margin-left: 2px; } .ai_chat_modal .block_ai_chat-input textarea::placeholder { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } .ai_chat_modal .block_ai_chat-input button { - position: absolute; - display: flex; - bottom: 0.5rem; - right: 0.7rem; + position: absolute; + display: flex; + bottom: 0.5rem; + right: 0.7rem; } .ai_chat_modal .block_ai_chat-input button i { - padding: 6.5px 0; + padding: 6.5px 0; } .ai_chat_modal .headeroptions { - display: flex; - align-items: center; + display: flex; + align-items: center; } .ai_chat_modal .headeroptions .badge-pill { - display: flex; - align-items: center; - height: 1.3rem; - font-size: 50%; + display: flex; + align-items: center; + height: 1.3rem; + font-size: 50%; } .ai_chat_modal .headeroptions .dropdown-menu { - left: 36px !important; + /* csslint disable: nextline */ + left: 36px !important; } .ai_chat_modal .headeroptions .dropdown-menu #block_ai_chat_delete_dialog { - color: #ff3333; + color: #ff3333; } .ai_chat_modal .headeroptions .dropdown-menu #block_ai_chat_delete_dialog:hover { - background-color: #ffcccc; + background-color: #ffcccc; } .ai_chat_modal #block_ai_chat_userquota { - text-align: right; - min-height: 1rem; + text-align: right; + min-height: 1rem; } .ai_chat_modal #block_ai_chat_userquota .local_ai_manager_userquota_infobox { - color: #6c757d; - background-color: inherit; - font-size: 0.6rem; - padding: 0; - margin: 0; - text-align: right; + color: #6c757d; + background-color: inherit; + font-size: 0.6rem; + padding: 0; + margin: 0; + text-align: right; } .ai_chat_modal .gradient-overlay { - content: ""; - position: sticky; - top: 0; - left: 0; - right: 0; - height: 2rem; - background: linear-gradient(to bottom, #fff 10%, transparent); - z-index: 33; + content: ""; + position: sticky; + top: 0; + left: 0; + right: 0; + height: 2rem; + background: linear-gradient(to bottom, #fff 10%, transparent); + z-index: 33; } .ai_chat_modal .ai_chat_modal_body { - width: 100%; - overflow: hidden; + width: 100%; + overflow: hidden; } .ai_chat_modal .ai_chat_modal_body .infobox { - display: flex; - align-items: center; - flex-direction: row-reverse; - padding-bottom: 0.4rem; - margin-top: -0.5rem; - z-index: 1; - min-height: 2rem; + display: flex; + align-items: center; + flex-direction: row-reverse; + padding-bottom: 0.4rem; + margin-top: -0.5rem; + z-index: 1; + min-height: 2rem; } .ai_chat_modal .ai_chat_modal_body .infobox .local_ai_manager-infobox.alert.alert-success { - color: #6c757d; - background-color: inherit; - font-size: 0.6rem; - padding: 0; - margin: 0; + color: #6c757d; + background-color: inherit; + font-size: 0.6rem; + padding: 0; + margin: 0; } .ai_chat_modal .block_ai_chat-output-wrapper { - overflow-y: auto; - height: 100%; - padding-right: 1rem; + overflow-y: auto; + height: 100%; + padding-right: 1rem; } .ai_chat_modal .block_ai-history-items { - padding: 0.5rem; + padding: 0.5rem; } .ai_chat_modal .block_ai-history-items a { - display: flex; - align-items: baseline; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; + display: flex; + align-items: baseline; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; } .ai_chat_modal .block_ai-history-items a p { - margin: 0; + margin: 0; } .ai_chat_modal .block_ai-history-items > div { - display: flex; - flex-wrap: nowrap; - justify-content: space-between; - gap: 0.2rem; + display: flex; + flex-wrap: nowrap; + justify-content: space-between; + gap: 0.2rem; } .ai_chat_modal .block_ai-history-items.card { - flex-direction: column-reverse; + flex-direction: column-reverse; } .ai_chat_modal.onhistorypage .block_ai_chat-output { - display: flex; - flex-direction: column-reverse; + display: flex; + flex-direction: column-reverse; } .ai_chat_modal.onhistorypage .infobox, .ai_chat_modal.onhistorypage #block_ai_chat_userquota { - display: none; + display: none; } .ai_chat_modal.onhistorypage .gradient-overlay { - display: none; + display: none; } +@media (min-width: 497px) { + .ai_chat_modal.onhistorypage .modal-body { + min-width: 497px; + } +} .ai_fake_block { - visibility: hidden; - height: 0; - margin: 0; + visibility: hidden; + height: 0; + margin: 0; } body.block_ai_chat_chatwindow .ai_chat_modal .modal-dialog { - position: fixed; - max-height: calc(100vh - 6rem); - right: 2rem; - bottom: 3rem; - filter: drop-shadow(3px 3px 4px black); + position: fixed; + max-height: calc(100vh - 6rem); + right: 2rem; + bottom: 3rem; + filter: drop-shadow(3px 3px 4px black); } body.block_ai_chat_chatwindow a#block_ai_chat_chatwindow { - color: #007bff; + color: #007bff; } body.block_ai_chat_chatwindow, body.block_ai_chat_dockright { - overflow: initial; + overflow: initial; } -body.block_ai_chat_chatwindow .modal-backdrop.show, body.block_ai_chat_chatwindow .ai_chat_modal, +body.block_ai_chat_chatwindow .modal-backdrop.show, +body.block_ai_chat_chatwindow .ai_chat_modal, body.block_ai_chat_dockright .modal-backdrop.show, body.block_ai_chat_dockright .ai_chat_modal { - width: 0; - height: 0; + width: 0; + height: 0; } body.block_ai_chat_openfull .ai_chat_modal .modal-dialog { - max-width: 95%; - min-height: calc(100vh - 3.5rem); + max-width: 95%; + min-height: calc(100vh - 3.5rem); } body.block_ai_chat_openfull .ai_chat_modal .ai_chat_modal_body { - max-width: 1080px; - margin: 0 auto; + max-width: 1080px; + margin: 0 auto; } body.block_ai_chat_openfull a#block_ai_chat_openfull { - color: #007bff; + color: #007bff; } body.block_ai_chat_dockright.block_ai_chat_open #page-wrapper #page { - margin-right: 50%; + margin-right: 50%; } body.block_ai_chat_dockright .ai_chat_modal .modal-dialog { - position: fixed; - width: 50%; - max-width: 50%; - height: calc(100% - 60.2px); - right: 0; - bottom: 0; - margin-top: 0; - margin-bottom: 0; + position: fixed; + width: 50%; + max-width: 50%; + height: calc(100% - 60.2px); + right: 0; + bottom: 0; + margin-top: 0; + margin-bottom: 0; } body.block_ai_chat_dockright .ai_chat_modal .modal-dialog .modal-content { - border-radius: 0; - border-top: none; - border-bottom: none; - margin-top: -1px; + border-radius: 0; + border-top: none; + border-bottom: none; + margin-top: -1px; } body.block_ai_chat_dockright a#block_ai_chat_dockright { - color: #007bff; + color: #007bff; } body.block_ai_chat_chatwindow .block_floatingbutton-floatingicons, body.block_ai_chat_dockright .block_floatingbutton-floatingicons, body.block_ai_chat_openfull .block_floatingbutton-floatingicons { - bottom: calc(2.5rem + 36px); + bottom: calc(2.5rem + 36px); } @media (max-width: 576px) { - .block_ai_chat_action_menu.views { - display: none; - } -} -@media (min-width: 497px) { - .ai_chat_modal.onhistorypage .modal-body { - min-width: 497px; - } + .block_ai_chat_action_menu.views { + display: none; + } } body.block_ai_chat_replacehelp #page-footer [data-region=footer-container-popover] .btn-footer-popover[data-action=footer-popover] { - display: none; + display: none; } body.block_ai_chat_replacehelp #ai_chat_button { - bottom: 1.9rem; + bottom: 1.9rem; } diff --git a/styles.scss b/styles.scss index affaf93..bae0404 100644 --- a/styles.scss +++ b/styles.scss @@ -176,6 +176,7 @@ font-size: 50%; } .dropdown-menu { + /* csslint disable: nextline */ left: 36px !important; #block_ai_chat_delete_dialog { color: #ff3333; @@ -269,7 +270,13 @@ } } } - +@media (min-width: 497px) { + .ai_chat_modal.onhistorypage { + .modal-body { + min-width: 497px; + } + } +} .ai_fake_block { visibility: hidden; @@ -292,7 +299,8 @@ body.block_ai_chat_chatwindow { body.block_ai_chat_chatwindow, body.block_ai_chat_dockright { overflow: initial; - .modal-backdrop.show, .ai_chat_modal { + .modal-backdrop.show, + .ai_chat_modal { width: 0; height: 0; } @@ -349,13 +357,7 @@ body.block_ai_chat_openfull { display: none; } } -@media (min-width: 497px) { - .ai_chat_modal.onhistorypage { - .modal-body { - min-width: 497px; - } - } -} + body.block_ai_chat_replacehelp { // Replace question mark popover on the bottom right corner with ai_chat. diff --git a/templates/dialog_modal.mustache b/templates/dialog_modal.mustache index 4cc00a6..4d6ea7d 100644 --- a/templates/dialog_modal.mustache +++ b/templates/dialog_modal.mustache @@ -32,7 +32,7 @@ along with Moodle. If not, see . { "history": { "message":"content", - "sender":"user", + "sender":"user" } } }} diff --git a/templates/floatingbutton.mustache b/templates/floatingbutton.mustache index bda2723..898990a 100644 --- a/templates/floatingbutton.mustache +++ b/templates/floatingbutton.mustache @@ -22,7 +22,7 @@ Example context (json): { "title":"AI Companion", - "arialabel":"Open AI Companion", + "arialabel":"Open AI Companion" } }}