diff --git a/amd/build/rights_config_table.min.js.map b/amd/build/rights_config_table.min.js.map
index 8582286..5beabb8 100644
--- a/amd/build/rights_config_table.min.js.map
+++ b/amd/build/rights_config_table.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"rights_config_table.min.js","sources":["../src/rights_config_table.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Module handling the form submission of the statistics tables of local_ai_manager.\n *\n * @module local_ai_manager/rights_config_table\n * @copyright 2024 ISB Bayern\n * @author Philipp Memmel\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Pending from 'core/pending';\nimport {getString} from 'core/str';\n\nlet table = null;\n\nexport const selectors = {\n CHECKBOX: 'input[data-userid]',\n SELECTALLCHECKBOX: '#rights-table-selectall_checkbox',\n SELECTIONINFO: '#rights-table-selection_info',\n USERIDS_INPUT_FIELD: '#rights-table-userids'\n};\n\n/**\n * Initialize the bulk handling on the statistics table.\n * @param {string} id the id of the table to operate on\n */\nexport const init = (id) => {\n const pendingPromise = new Pending('local_ai_manager/rights_config_table');\n table = document.getElementById(id);\n table.querySelectorAll(selectors.CHECKBOX).forEach(checkbox => {\n checkbox.addEventListener('change', event => {\n updateSelectAllCheckboxState();\n updateUserIds(event.target);\n updateSelectionCountInfo();\n });\n });\n table.querySelector(selectors.SELECTALLCHECKBOX).addEventListener('change', event => {\n updateSelection(event);\n // If we set the status of the checkboxes via JS there is no change event on the checkboxes,\n // so we need to manually trigger the update of the user ids.\n updateUserIds();\n });\n updateSelectionCountInfo();\n // In case the browser remembered the state after site reload, we need to set the initial state of user ids dependent on the\n // boxes' current state.\n updateUserIds();\n pendingPromise.resolve();\n};\n\n/**\n * Update the user ids input field for form submission.\n */\nconst updateUserIds = () => {\n const userIdsInputField = document.querySelector(selectors.USERIDS_INPUT_FIELD);\n const userIds = [];\n document.querySelectorAll(selectors.CHECKBOX).forEach(checkbox => {\n if (checkbox.checked) {\n userIds.push(checkbox.dataset.userid);\n }\n });\n userIdsInputField.value = userIds.join(';');\n};\n\n/**\n * Updates the checked states of the user checkboxes according to the change of the \"select/deselect all\" checkbox.\n *\n * @param {object} changedEvent the changed event of the \"select/deselect all\" checkbox\n */\nconst updateSelection = (changedEvent) => {\n const allBoxes = table.querySelectorAll(selectors.CHECKBOX);\n if (allBoxes.length === 0) {\n return;\n }\n if (changedEvent.target.checked) {\n allBoxes.forEach((box) => {\n if (!box.checked) {\n box.checked = true;\n }\n });\n } else {\n allBoxes.forEach((box) => {\n box.checked = false;\n });\n }\n updateSelectionCountInfo();\n};\n\n/**\n * Updates the \"select/deselect all\" checkbox according to the state of the other checkboxes.\n */\nconst updateSelectAllCheckboxState = () => {\n const selectAllCheckbox = table.querySelector(selectors.SELECTALLCHECKBOX);\n selectAllCheckbox.checked = !!areAllBoxesChecked();\n};\n\n/**\n * Helper function to determine if all user checkboxes are checked or not.\n *\n * @returns {bool} true if all boxes are checked, false otherwise\n */\nconst areAllBoxesChecked = () => {\n const allBoxes = table.querySelectorAll(selectors.CHECKBOX);\n return Array.from(allBoxes).reduce((a, b) => a && b.checked, true);\n};\n\n/**\n * Returns the amount of currently checked checkboxes.\n *\n * @returns {number} the count of currently checked checkboxes\n */\nconst checkedCheckboxesCount = () => {\n const allBoxes = table.querySelectorAll(selectors.CHECKBOX);\n const checkedBoxes = Array.from(allBoxes).filter(checkbox => checkbox.checked);\n return checkedBoxes.length;\n};\n\n/**\n * Updates the selection count info text box.\n */\nconst updateSelectionCountInfo = async () => {\n const selectionCountInfoTarget = table.querySelector(selectors.SELECTIONINFO);\n const infoText = await getString('selecteduserscount', 'local_ai_manager', checkedCheckboxesCount());\n selectionCountInfoTarget.innerHTML = infoText;\n};\n"],"names":["table","selectors","CHECKBOX","SELECTALLCHECKBOX","SELECTIONINFO","USERIDS_INPUT_FIELD","id","pendingPromise","Pending","document","getElementById","querySelectorAll","forEach","checkbox","addEventListener","event","updateSelectAllCheckboxState","updateUserIds","target","updateSelectionCountInfo","querySelector","updateSelection","resolve","userIdsInputField","userIds","checked","push","dataset","userid","value","join","changedEvent","allBoxes","length","box","areAllBoxesChecked","Array","from","reduce","a","b","async","selectionCountInfoTarget","infoText","filter","checkedCheckboxesCount","innerHTML"],"mappings":";;;;;;;;mKA2BIA,MAAQ,WAECC,UAAY,CACrBC,SAAU,qBACVC,kBAAmB,mCACnBC,cAAe,+BACfC,oBAAqB,oEAOJC,WACXC,eAAiB,IAAIC,iBAAQ,wCACnCR,MAAQS,SAASC,eAAeJ,IAChCN,MAAMW,iBAAiBV,UAAUC,UAAUU,SAAQC,WAC/CA,SAASC,iBAAiB,UAAUC,QAChCC,+BACAC,cAAcF,MAAMG,QACpBC,iCAGRnB,MAAMoB,cAAcnB,UAAUE,mBAAmBW,iBAAiB,UAAUC,QACxEM,gBAAgBN,OAGhBE,mBAEJE,2BAGAF,gBACAV,eAAee,iBAMbL,cAAgB,WACZM,kBAAoBd,SAASW,cAAcnB,UAAUI,qBACrDmB,QAAU,GAChBf,SAASE,iBAAiBV,UAAUC,UAAUU,SAAQC,WAC9CA,SAASY,SACTD,QAAQE,KAAKb,SAASc,QAAQC,WAGtCL,kBAAkBM,MAAQL,QAAQM,KAAK,MAQrCT,gBAAmBU,qBACfC,SAAWhC,MAAMW,iBAAiBV,UAAUC,UAC1B,IAApB8B,SAASC,SAGTF,aAAab,OAAOO,QACpBO,SAASpB,SAASsB,MACTA,IAAIT,UACLS,IAAIT,SAAU,MAItBO,SAASpB,SAASsB,MACdA,IAAIT,SAAU,KAGtBN,6BAMEH,6BAA+B,KACPhB,MAAMoB,cAAcnB,UAAUE,mBACtCsB,UAAYU,sBAQ5BA,mBAAqB,WACjBH,SAAWhC,MAAMW,iBAAiBV,UAAUC,iBAC3CkC,MAAMC,KAAKL,UAAUM,QAAO,CAACC,EAAGC,IAAMD,GAAKC,EAAEf,UAAS,IAiB3DN,yBAA2BsB,gBACvBC,yBAA2B1C,MAAMoB,cAAcnB,UAAUG,eACzDuC,eAAiB,kBAAU,qBAAsB,mBAX5B,YACrBX,SAAWhC,MAAMW,iBAAiBV,UAAUC,iBAC7BkC,MAAMC,KAAKL,UAAUY,QAAO/B,UAAYA,SAASY,UAClDQ,QAQuDY,IAC3EH,yBAAyBI,UAAYH"}
\ No newline at end of file
+{"version":3,"file":"rights_config_table.min.js","sources":["../src/rights_config_table.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Module handling the form submission of the statistics tables of local_ai_manager.\n *\n * @module local_ai_manager/rights_config_table\n * @copyright 2024 ISB Bayern\n * @author Philipp Memmel\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Pending from 'core/pending';\nimport {getString} from 'core/str';\n\nlet table = null;\n\nexport const selectors = {\n CHECKBOX: 'input[data-userid]',\n SELECTALLCHECKBOX: '#rights-table-selectall_checkbox',\n SELECTIONINFO: '#rights-table-selection_info',\n USERIDS_INPUT_FIELD: '#rights-table-userids'\n};\n\n/**\n * Initialize the bulk handling on the statistics table.\n * @param {string} id the id of the table to operate on\n */\nexport const init = (id) => {\n const pendingPromise = new Pending('local_ai_manager/rights_config_table');\n table = document.getElementById(id);\n table.querySelectorAll(selectors.CHECKBOX).forEach(checkbox => {\n checkbox.addEventListener('change', event => {\n updateSelectAllCheckboxState();\n updateUserIds(event.target);\n updateSelectionCountInfo();\n });\n });\n table.querySelector(selectors.SELECTALLCHECKBOX).addEventListener('change', event => {\n updateSelection(event);\n // If we set the status of the checkboxes via JS there is no change event on the checkboxes,\n // so we need to manually trigger the update of the user ids.\n updateUserIds();\n });\n updateSelectionCountInfo();\n // In case the browser remembered the state after site reload, we need to set the initial state of user ids dependent on the\n // boxes' current state.\n updateUserIds();\n pendingPromise.resolve();\n};\n\n/**\n * Update the user ids input field for form submission.\n */\nconst updateUserIds = () => {\n const userIdsInputField = document.querySelector(selectors.USERIDS_INPUT_FIELD);\n const userIds = [];\n document.querySelectorAll(selectors.CHECKBOX).forEach(checkbox => {\n if (checkbox.checked) {\n userIds.push(checkbox.dataset.userid);\n }\n });\n userIdsInputField.value = userIds.join(';');\n};\n\n/**\n * Updates the checked states of the user checkboxes according to the change of the \"select/deselect all\" checkbox.\n *\n * @param {object} changedEvent the changed event of the \"select/deselect all\" checkbox\n */\nconst updateSelection = (changedEvent) => {\n const allBoxes = table.querySelectorAll(selectors.CHECKBOX);\n if (allBoxes.length === 0) {\n return;\n }\n if (changedEvent.target.checked) {\n allBoxes.forEach((box) => {\n if (!box.checked) {\n box.checked = true;\n }\n });\n } else {\n allBoxes.forEach((box) => {\n box.checked = false;\n });\n }\n updateSelectionCountInfo();\n};\n\n/**\n * Updates the \"select/deselect all\" checkbox according to the state of the other checkboxes.\n */\nconst updateSelectAllCheckboxState = () => {\n const selectAllCheckbox = table.querySelector(selectors.SELECTALLCHECKBOX);\n selectAllCheckbox.checked = !!areAllBoxesChecked();\n};\n\n/**\n * Helper function to determine if all user checkboxes are checked or not.\n *\n * @returns {bool} true if all boxes are checked, false otherwise\n */\nconst areAllBoxesChecked = () => {\n const allBoxes = table.querySelectorAll(selectors.CHECKBOX);\n return Array.from(allBoxes).reduce((a, b) => a && b.checked, true);\n};\n\n/**\n * Returns the amount of currently checked checkboxes.\n *\n * @returns {number} the count of currently checked checkboxes\n */\nconst checkedCheckboxesCount = () => {\n const allBoxes = table.querySelectorAll(selectors.CHECKBOX);\n const checkedBoxes = Array.from(allBoxes).filter(checkbox => checkbox.checked);\n return checkedBoxes.length;\n};\n\n/**\n * Updates the selection count info text box.\n */\nconst updateSelectionCountInfo = async() => {\n const selectionCountInfoTarget = table.querySelector(selectors.SELECTIONINFO);\n const infoText = await getString('selecteduserscount', 'local_ai_manager', checkedCheckboxesCount());\n selectionCountInfoTarget.innerHTML = infoText;\n};\n"],"names":["table","selectors","CHECKBOX","SELECTALLCHECKBOX","SELECTIONINFO","USERIDS_INPUT_FIELD","id","pendingPromise","Pending","document","getElementById","querySelectorAll","forEach","checkbox","addEventListener","event","updateSelectAllCheckboxState","updateUserIds","target","updateSelectionCountInfo","querySelector","updateSelection","resolve","userIdsInputField","userIds","checked","push","dataset","userid","value","join","changedEvent","allBoxes","length","box","areAllBoxesChecked","Array","from","reduce","a","b","async","selectionCountInfoTarget","infoText","filter","checkedCheckboxesCount","innerHTML"],"mappings":";;;;;;;;mKA2BIA,MAAQ,WAECC,UAAY,CACrBC,SAAU,qBACVC,kBAAmB,mCACnBC,cAAe,+BACfC,oBAAqB,oEAOJC,WACXC,eAAiB,IAAIC,iBAAQ,wCACnCR,MAAQS,SAASC,eAAeJ,IAChCN,MAAMW,iBAAiBV,UAAUC,UAAUU,SAAQC,WAC/CA,SAASC,iBAAiB,UAAUC,QAChCC,+BACAC,cAAcF,MAAMG,QACpBC,iCAGRnB,MAAMoB,cAAcnB,UAAUE,mBAAmBW,iBAAiB,UAAUC,QACxEM,gBAAgBN,OAGhBE,mBAEJE,2BAGAF,gBACAV,eAAee,iBAMbL,cAAgB,WACZM,kBAAoBd,SAASW,cAAcnB,UAAUI,qBACrDmB,QAAU,GAChBf,SAASE,iBAAiBV,UAAUC,UAAUU,SAAQC,WAC9CA,SAASY,SACTD,QAAQE,KAAKb,SAASc,QAAQC,WAGtCL,kBAAkBM,MAAQL,QAAQM,KAAK,MAQrCT,gBAAmBU,qBACfC,SAAWhC,MAAMW,iBAAiBV,UAAUC,UAC1B,IAApB8B,SAASC,SAGTF,aAAab,OAAOO,QACpBO,SAASpB,SAASsB,MACTA,IAAIT,UACLS,IAAIT,SAAU,MAItBO,SAASpB,SAASsB,MACdA,IAAIT,SAAU,KAGtBN,6BAMEH,6BAA+B,KACPhB,MAAMoB,cAAcnB,UAAUE,mBACtCsB,UAAYU,sBAQ5BA,mBAAqB,WACjBH,SAAWhC,MAAMW,iBAAiBV,UAAUC,iBAC3CkC,MAAMC,KAAKL,UAAUM,QAAO,CAACC,EAAGC,IAAMD,GAAKC,EAAEf,UAAS,IAiB3DN,yBAA2BsB,gBACvBC,yBAA2B1C,MAAMoB,cAAcnB,UAAUG,eACzDuC,eAAiB,kBAAU,qBAAsB,mBAX5B,YACrBX,SAAWhC,MAAMW,iBAAiBV,UAAUC,iBAC7BkC,MAAMC,KAAKL,UAAUY,QAAO/B,UAAYA,SAASY,UAClDQ,QAQuDY,IAC3EH,yBAAyBI,UAAYH"}
\ No newline at end of file
diff --git a/amd/build/toggle_handler.min.js.map b/amd/build/toggle_handler.min.js.map
index d8e1f74..8a3a813 100644
--- a/amd/build/toggle_handler.min.js.map
+++ b/amd/build/toggle_handler.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"toggle_handler.min.js","sources":["../src/toggle_handler.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Toggle handler.\n *\n * @module local_ai_manager/toggle_handler\n * @copyright 2024 ISB Bayern\n * @author Philipp Memmel\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nexport const init = (inputid) => {\n const toggleContainer = document.getElementById(inputid);\n if (toggleContainer) {\n const toggle = toggleContainer.querySelector('input');\n\n toggleContainer.addEventListener('click', () => {\n toggle.checked = !toggle.checked;\n toggle.dispatchEvent(new Event('change'));\n });\n\n toggle.addEventListener('change', () => {\n // New state incoming.\n if (!toggle.checked) {\n window.location.replace(toggle.dataset.targetwhenchecked);\n } else {\n window.location.replace(toggle.dataset.targetwhennotchecked);\n }\n return false;\n });\n }\n};\n\n\n"],"names":["inputid","toggleContainer","document","getElementById","toggle","querySelector","addEventListener","checked","dispatchEvent","Event","window","location","replace","dataset","targetwhennotchecked","targetwhenchecked"],"mappings":"oKAwBqBA,gBACXC,gBAAkBC,SAASC,eAAeH,YAC5CC,gBAAiB,OACXG,OAASH,gBAAgBI,cAAc,SAE7CJ,gBAAgBK,iBAAiB,SAAS,KACtCF,OAAOG,SAAWH,OAAOG,QACzBH,OAAOI,cAAc,IAAIC,MAAM,cAGnCL,OAAOE,iBAAiB,UAAU,KAEzBF,OAAOG,QAGRG,OAAOC,SAASC,QAAQR,OAAOS,QAAQC,sBAFvCJ,OAAOC,SAASC,QAAQR,OAAOS,QAAQE,oBAIpC"}
+{"version":3,"file":"toggle_handler.min.js","sources":["../src/toggle_handler.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Toggle handler.\n *\n * @module local_ai_manager/toggle_handler\n * @copyright 2024 ISB Bayern\n * @author Philipp Memmel\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nexport const init = (inputid) => {\n const toggleContainer = document.getElementById(inputid);\n if (toggleContainer) {\n const toggle = toggleContainer.querySelector('input');\n\n toggleContainer.addEventListener('click', () => {\n toggle.checked = !toggle.checked;\n toggle.dispatchEvent(new Event('change'));\n });\n\n toggle.addEventListener('change', () => {\n // New state incoming.\n if (!toggle.checked) {\n window.location.replace(toggle.dataset.targetwhenchecked);\n } else {\n window.location.replace(toggle.dataset.targetwhennotchecked);\n }\n return false;\n });\n }\n};\n\n\n"],"names":["inputid","toggleContainer","document","getElementById","toggle","querySelector","addEventListener","checked","dispatchEvent","Event","window","location","replace","dataset","targetwhennotchecked","targetwhenchecked"],"mappings":"oKAwBqBA,gBACXC,gBAAkBC,SAASC,eAAeH,YAC5CC,gBAAiB,OACXG,OAASH,gBAAgBI,cAAc,SAE7CJ,gBAAgBK,iBAAiB,SAAS,KACtCF,OAAOG,SAAWH,OAAOG,QACzBH,OAAOI,cAAc,IAAIC,MAAM,cAGnCL,OAAOE,iBAAiB,UAAU,KAEzBF,OAAOG,QAGRG,OAAOC,SAASC,QAAQR,OAAOS,QAAQC,sBAFvCJ,OAAOC,SAASC,QAAQR,OAAOS,QAAQE,oBAIpC"}
\ No newline at end of file
diff --git a/amd/build/userquota.min.js b/amd/build/userquota.min.js
index 1c7d81c..8795962 100644
--- a/amd/build/userquota.min.js
+++ b/amd/build/userquota.min.js
@@ -6,6 +6,6 @@ define("local_ai_manager/userquota",["exports","core/ajax","core/str","core/temp
* @copyright 2024 ISB Bayern
* @author Philipp Memmel
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.renderUserQuota=void 0,_templates=(obj=_templates)&&obj.__esModule?obj:{default:obj};const constants_MAXUSAGE_UNLIMITED=999999,queryCountStrings={chat:"chat requests",chat_shortened:"chat",feedback:"feedback requests",feedback_shortened:"feedback",imggen:"image generation generation requests",imggen_shortened:"image generation generation",singleprompt:"text requests",singleprompt_shortened:"text",translate:"translation requests",translate_shortened:"translation",tts:"audio requests",tts_shortened:"audio"};_exports.renderUserQuota=async(selector,purposes)=>{await localizeQueryCountTexts();const targetElement=document.querySelector(selector),userquotaData=await(0,_ajax.call)([{methodname:"local_ai_manager_get_user_quota",args:{}}])[0],purposeInfo=[];purposes.forEach((purpose=>{purposeInfo.push({purpose:purpose,currentusage:userquotaData.usage[purpose].currentusage,maxusage:userquotaData.usage[purpose].maxusage,querycounttext:queryCountStrings[purpose+"_shortened"],showmaxusage:userquotaData.usage[purpose].maxusage!==constants_MAXUSAGE_UNLIMITED,limitreached:userquotaData.usage[purpose].currentusage===userquotaData.usage[purpose].maxusage,islastelement:!1})})),purposeInfo[purposeInfo.length-1].islastelement=!0,purposeInfo[purposeInfo.length-1].querycounttext=queryCountStrings[purposeInfo[purposeInfo.length-1].purpose];const userquotaContentTemplateContext={purposes:purposeInfo,period:userquotaData.period,unlimited:"role_unlimited"===userquotaData.role},{html:html,js:js}=await _templates.default.renderForPromise("local_ai_manager/userquota",userquotaContentTemplateContext);_templates.default.appendNodeContents(targetElement,html,js)};const localizeQueryCountTexts=async()=>{const stringsToFetch=[];Object.keys(queryCountStrings).filter((key=>!key.endsWith("_shortened"))).forEach((key=>{stringsToFetch.push({key:"requestcount",component:"aipurpose_"+key}),stringsToFetch.push({key:"requestcount_shortened",component:"aipurpose_"+key})}));const strings=await(0,_str.getStrings)(stringsToFetch);let i=0;for(const key in queryCountStrings)queryCountStrings[key]=strings[i],i++}}));
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.renderUserQuota=void 0,_templates=(obj=_templates)&&obj.__esModule?obj:{default:obj};const constants_MAXUSAGE_UNLIMITED=999999,queryCountStrings={chat:"chat requests",chatShortened:"chat",feedback:"feedback requests",feedbackShortened:"feedback",imggen:"image generation generation requests",imggenShortened:"image generation generation",singleprompt:"text requests",singlepromptShortened:"text",translate:"translation requests",translateShortened:"translation",tts:"audio requests",ttsShortened:"audio"};_exports.renderUserQuota=async(selector,purposes)=>{await localizeQueryCountTexts();const targetElement=document.querySelector(selector),userquotaData=await(0,_ajax.call)([{methodname:"local_ai_manager_get_user_quota",args:{}}])[0],purposeInfo=[];purposes.forEach((purpose=>{purposeInfo.push({purpose:purpose,currentusage:userquotaData.usage[purpose].currentusage,maxusage:userquotaData.usage[purpose].maxusage,querycounttext:queryCountStrings[purpose+"_shortened"],showmaxusage:userquotaData.usage[purpose].maxusage!==constants_MAXUSAGE_UNLIMITED,limitreached:userquotaData.usage[purpose].currentusage===userquotaData.usage[purpose].maxusage,islastelement:!1})})),purposeInfo[purposeInfo.length-1].islastelement=!0,purposeInfo[purposeInfo.length-1].querycounttext=queryCountStrings[purposeInfo[purposeInfo.length-1].purpose];const userquotaContentTemplateContext={purposes:purposeInfo,period:userquotaData.period,unlimited:"role_unlimited"===userquotaData.role},{html:html,js:js}=await _templates.default.renderForPromise("local_ai_manager/userquota",userquotaContentTemplateContext);_templates.default.appendNodeContents(targetElement,html,js)};const localizeQueryCountTexts=async()=>{const stringsToFetch=[];Object.keys(queryCountStrings).filter((key=>!key.endsWith("Shortened"))).forEach((key=>{stringsToFetch.push({key:"requestcount",component:"aipurpose_"+key}),stringsToFetch.push({key:"requestcount_shortened",component:"aipurpose_"+key})}));const strings=await(0,_str.getStrings)(stringsToFetch);let i=0;for(const key in queryCountStrings)queryCountStrings[key]=strings[i],i++}}));
//# sourceMappingURL=userquota.min.js.map
\ No newline at end of file
diff --git a/amd/build/userquota.min.js.map b/amd/build/userquota.min.js.map
index 3adb64a..628adcd 100644
--- a/amd/build/userquota.min.js.map
+++ b/amd/build/userquota.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"userquota.min.js","sources":["../src/userquota.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Module handling the form submission of the statistics tables of local_ai_manager.\n *\n * @module local_ai_manager/userquota\n * @copyright 2024 ISB Bayern\n * @author Philipp Memmel\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {call as fetchMany} from 'core/ajax';\nimport {getStrings} from 'core/str';\nimport Templates from 'core/templates';\n\nconst constants = {\n MAXUSAGE_UNLIMITED: 999999\n};\n\nconst queryCountStrings = {\n chat: 'chat requests',\n chat_shortened: 'chat',\n feedback: 'feedback requests',\n feedback_shortened: 'feedback',\n imggen: 'image generation generation requests',\n imggen_shortened: 'image generation generation',\n singleprompt: 'text requests',\n singleprompt_shortened: 'text',\n translate: 'translation requests',\n translate_shortened: 'translation',\n tts: 'audio requests',\n tts_shortened: 'audio'\n};\n\nconst fetchUserquotaData = () => fetchMany([{\n methodname: 'local_ai_manager_get_user_quota',\n args: {},\n}])[0];\n\n/**\n * Renders the current user usage information into the element identified by the given selector.\n *\n * @param {string} selector the id of the element to insert the infobox\n * @param {string[]} purposes the purposes to show user quota for\n */\nexport const renderUserQuota = async (selector, purposes) => {\n await localizeQueryCountTexts();\n\n const targetElement = document.querySelector(selector);\n const userquotaData = await fetchUserquotaData();\n const purposeInfo = [];\n\n purposes.forEach(purpose => {\n purposeInfo.push(\n {\n purpose,\n 'currentusage': userquotaData.usage[purpose].currentusage,\n maxusage: userquotaData.usage[purpose].maxusage,\n 'querycounttext': queryCountStrings[purpose + '_shortened'],\n showmaxusage: userquotaData.usage[purpose].maxusage !== constants.MAXUSAGE_UNLIMITED,\n limitreached: userquotaData.usage[purpose].currentusage === userquotaData.usage[purpose].maxusage,\n islastelement: false\n });\n });\n purposeInfo[purposeInfo.length - 1].islastelement = true;\n purposeInfo[purposeInfo.length - 1].querycounttext = queryCountStrings[purposeInfo[purposeInfo.length - 1]['purpose']];\n\n const userquotaContentTemplateContext = {\n purposes: purposeInfo,\n period: userquotaData.period,\n unlimited: userquotaData.role === 'role_unlimited'\n };\n const {html, js} = await Templates.renderForPromise('local_ai_manager/userquota', userquotaContentTemplateContext);\n Templates.appendNodeContents(targetElement, html, js);\n};\n\nconst localizeQueryCountTexts = async () => {\n const stringsToFetch = [];\n Object.keys(queryCountStrings).filter(key => !key.endsWith('_shortened')).forEach((key) => {\n stringsToFetch.push({key: 'requestcount', component: 'aipurpose_' + key});\n stringsToFetch.push({key: 'requestcount_shortened', component: 'aipurpose_' + key});\n });\n const strings = await getStrings(stringsToFetch);\n let i = 0;\n for (const key in queryCountStrings) {\n queryCountStrings[key] = strings[i];\n i++;\n }\n};\n"],"names":["constants","queryCountStrings","chat","chat_shortened","feedback","feedback_shortened","imggen","imggen_shortened","singleprompt","singleprompt_shortened","translate","translate_shortened","tts","tts_shortened","async","selector","purposes","localizeQueryCountTexts","targetElement","document","querySelector","userquotaData","methodname","args","purposeInfo","forEach","purpose","push","usage","currentusage","maxusage","showmaxusage","limitreached","islastelement","length","querycounttext","userquotaContentTemplateContext","period","unlimited","role","html","js","Templates","renderForPromise","appendNodeContents","stringsToFetch","Object","keys","filter","key","endsWith","component","strings","i"],"mappings":";;;;;;;;iKA4BMA,6BACkB,OAGlBC,kBAAoB,CACtBC,KAAM,gBACNC,eAAgB,OAChBC,SAAU,oBACVC,mBAAoB,WACpBC,OAAQ,uCACRC,iBAAkB,8BAClBC,aAAc,gBACdC,uBAAwB,OACxBC,UAAW,uBACXC,oBAAqB,cACrBC,IAAK,iBACLC,cAAe,kCAcYC,MAAOC,SAAUC,kBACtCC,gCAEAC,cAAgBC,SAASC,cAAcL,UACvCM,oBAfuB,cAAU,CAAC,CACxCC,WAAY,kCACZC,KAAM,MACN,GAaMC,YAAc,GAEpBR,SAASS,SAAQC,UACbF,YAAYG,KACR,CACID,QAAAA,qBACgBL,cAAcO,MAAMF,SAASG,aAC7CC,SAAUT,cAAcO,MAAMF,SAASI,wBACrB7B,kBAAkByB,QAAU,cAC9CK,aAAcV,cAAcO,MAAMF,SAASI,WAAa9B,6BACxDgC,aAAcX,cAAcO,MAAMF,SAASG,eAAiBR,cAAcO,MAAMF,SAASI,SACzFG,eAAe,OAG3BT,YAAYA,YAAYU,OAAS,GAAGD,eAAgB,EACpDT,YAAYA,YAAYU,OAAS,GAAGC,eAAiBlC,kBAAkBuB,YAAYA,YAAYU,OAAS,GAAjC,eAEjEE,gCAAkC,CACpCpB,SAAUQ,YACVa,OAAQhB,cAAcgB,OACtBC,UAAkC,mBAAvBjB,cAAckB,OAEvBC,KAACA,KAADC,GAAOA,UAAYC,mBAAUC,iBAAiB,6BAA8BP,oDACxEQ,mBAAmB1B,cAAesB,KAAMC,WAGhDxB,wBAA0BH,gBACtB+B,eAAiB,GACvBC,OAAOC,KAAK9C,mBAAmB+C,QAAOC,MAAQA,IAAIC,SAAS,gBAAezB,SAASwB,MAC/EJ,eAAelB,KAAK,CAACsB,IAAK,eAAgBE,UAAW,aAAeF,MACpEJ,eAAelB,KAAK,CAACsB,IAAK,yBAA0BE,UAAW,aAAeF,eAE5EG,cAAgB,mBAAWP,oBAC7BQ,EAAI,MACH,MAAMJ,OAAOhD,kBACdA,kBAAkBgD,KAAOG,QAAQC,GACjCA"}
\ No newline at end of file
+{"version":3,"file":"userquota.min.js","sources":["../src/userquota.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Module handling the form submission of the statistics tables of local_ai_manager.\n *\n * @module local_ai_manager/userquota\n * @copyright 2024 ISB Bayern\n * @author Philipp Memmel\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {call as fetchMany} from 'core/ajax';\nimport {getStrings} from 'core/str';\nimport Templates from 'core/templates';\n\nconst constants = {\n MAXUSAGE_UNLIMITED: 999999\n};\n\nconst queryCountStrings = {\n chat: 'chat requests',\n chatShortened: 'chat',\n feedback: 'feedback requests',\n feedbackShortened: 'feedback',\n imggen: 'image generation generation requests',\n imggenShortened: 'image generation generation',\n singleprompt: 'text requests',\n singlepromptShortened: 'text',\n translate: 'translation requests',\n translateShortened: 'translation',\n tts: 'audio requests',\n ttsShortened: 'audio'\n};\n\nconst fetchUserquotaData = () => fetchMany([{\n methodname: 'local_ai_manager_get_user_quota',\n args: {},\n}])[0];\n\n/**\n * Renders the current user usage information into the element identified by the given selector.\n *\n * @param {string} selector the id of the element to insert the infobox\n * @param {string[]} purposes the purposes to show user quota for\n */\nexport const renderUserQuota = async(selector, purposes) => {\n await localizeQueryCountTexts();\n\n const targetElement = document.querySelector(selector);\n const userquotaData = await fetchUserquotaData();\n const purposeInfo = [];\n\n purposes.forEach(purpose => {\n purposeInfo.push(\n {\n purpose,\n 'currentusage': userquotaData.usage[purpose].currentusage,\n maxusage: userquotaData.usage[purpose].maxusage,\n 'querycounttext': queryCountStrings[purpose + '_shortened'],\n showmaxusage: userquotaData.usage[purpose].maxusage !== constants.MAXUSAGE_UNLIMITED,\n limitreached: userquotaData.usage[purpose].currentusage === userquotaData.usage[purpose].maxusage,\n islastelement: false\n });\n });\n purposeInfo[purposeInfo.length - 1].islastelement = true;\n purposeInfo[purposeInfo.length - 1].querycounttext = queryCountStrings[purposeInfo[purposeInfo.length - 1].purpose];\n\n const userquotaContentTemplateContext = {\n purposes: purposeInfo,\n period: userquotaData.period,\n unlimited: userquotaData.role === 'role_unlimited'\n };\n const {html, js} = await Templates.renderForPromise('local_ai_manager/userquota', userquotaContentTemplateContext);\n Templates.appendNodeContents(targetElement, html, js);\n};\n\nconst localizeQueryCountTexts = async() => {\n const stringsToFetch = [];\n Object.keys(queryCountStrings).filter(key => !key.endsWith('Shortened')).forEach((key) => {\n stringsToFetch.push({key: 'requestcount', component: 'aipurpose_' + key});\n stringsToFetch.push({key: 'requestcount_shortened', component: 'aipurpose_' + key});\n });\n const strings = await getStrings(stringsToFetch);\n let i = 0;\n for (const key in queryCountStrings) {\n queryCountStrings[key] = strings[i];\n i++;\n }\n};\n"],"names":["constants","queryCountStrings","chat","chatShortened","feedback","feedbackShortened","imggen","imggenShortened","singleprompt","singlepromptShortened","translate","translateShortened","tts","ttsShortened","async","selector","purposes","localizeQueryCountTexts","targetElement","document","querySelector","userquotaData","methodname","args","purposeInfo","forEach","purpose","push","usage","currentusage","maxusage","showmaxusage","limitreached","islastelement","length","querycounttext","userquotaContentTemplateContext","period","unlimited","role","html","js","Templates","renderForPromise","appendNodeContents","stringsToFetch","Object","keys","filter","key","endsWith","component","strings","i"],"mappings":";;;;;;;;iKA4BMA,6BACkB,OAGlBC,kBAAoB,CACtBC,KAAM,gBACNC,cAAe,OACfC,SAAU,oBACVC,kBAAmB,WACnBC,OAAQ,uCACRC,gBAAiB,8BACjBC,aAAc,gBACdC,sBAAuB,OACvBC,UAAW,uBACXC,mBAAoB,cACpBC,IAAK,iBACLC,aAAc,kCAcaC,MAAMC,SAAUC,kBACrCC,gCAEAC,cAAgBC,SAASC,cAAcL,UACvCM,oBAfuB,cAAU,CAAC,CACxCC,WAAY,kCACZC,KAAM,MACN,GAaMC,YAAc,GAEpBR,SAASS,SAAQC,UACbF,YAAYG,KACR,CACID,QAAAA,qBACgBL,cAAcO,MAAMF,SAASG,aAC7CC,SAAUT,cAAcO,MAAMF,SAASI,wBACrB7B,kBAAkByB,QAAU,cAC9CK,aAAcV,cAAcO,MAAMF,SAASI,WAAa9B,6BACxDgC,aAAcX,cAAcO,MAAMF,SAASG,eAAiBR,cAAcO,MAAMF,SAASI,SACzFG,eAAe,OAG3BT,YAAYA,YAAYU,OAAS,GAAGD,eAAgB,EACpDT,YAAYA,YAAYU,OAAS,GAAGC,eAAiBlC,kBAAkBuB,YAAYA,YAAYU,OAAS,GAAGR,eAErGU,gCAAkC,CACpCpB,SAAUQ,YACVa,OAAQhB,cAAcgB,OACtBC,UAAkC,mBAAvBjB,cAAckB,OAEvBC,KAACA,KAADC,GAAOA,UAAYC,mBAAUC,iBAAiB,6BAA8BP,oDACxEQ,mBAAmB1B,cAAesB,KAAMC,WAGhDxB,wBAA0BH,gBACtB+B,eAAiB,GACvBC,OAAOC,KAAK9C,mBAAmB+C,QAAOC,MAAQA,IAAIC,SAAS,eAAczB,SAASwB,MAC9EJ,eAAelB,KAAK,CAACsB,IAAK,eAAgBE,UAAW,aAAeF,MACpEJ,eAAelB,KAAK,CAACsB,IAAK,yBAA0BE,UAAW,aAAeF,eAE5EG,cAAgB,mBAAWP,oBAC7BQ,EAAI,MACH,MAAMJ,OAAOhD,kBACdA,kBAAkBgD,KAAOG,QAAQC,GACjCA"}
\ No newline at end of file
diff --git a/amd/build/warningbox.min.js.map b/amd/build/warningbox.min.js.map
index a72a1b8..e14b99f 100644
--- a/amd/build/warningbox.min.js.map
+++ b/amd/build/warningbox.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"warningbox.min.js","sources":["../src/warningbox.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Module rendering the warning box to inform the users about misleading AI results.\n *\n * @module local_ai_manager/warningbox\n * @copyright 2024 ISB Bayern\n * @author Philipp Memmel\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {getAiConfig} from 'local_ai_manager/config';\nimport Templates from 'core/templates';\n\n\n/**\n * Renders the warning box.\n *\n * @param {string} selector the selector where the warning box should be rendered into\n */\nexport const renderWarningBox = async (selector) => {\n const aiConfig = await getAiConfig();\n const showAiWarningLink = aiConfig.aiwarningurl.length > 0;\n const targetElement = document.querySelector(selector);\n const {html, js} = await Templates.renderForPromise('local_ai_manager/ai_info_warning', {\n showaiwarninglink: showAiWarningLink,\n aiwarningurl: aiConfig.aiwarningurl\n });\n Templates.appendNodeContents(targetElement, html, js);\n};\n"],"names":["async","aiConfig","showAiWarningLink","aiwarningurl","length","targetElement","document","querySelector","selector","html","js","Templates","renderForPromise","showaiwarninglink","appendNodeContents"],"mappings":";;;;;;;;sLAiCgCA,MAAAA,iBACtBC,eAAiB,yBACjBC,kBAAoBD,SAASE,aAAaC,OAAS,EACnDC,cAAgBC,SAASC,cAAcC,WACvCC,KAACA,KAADC,GAAOA,UAAYC,mBAAUC,iBAAiB,mCAAoC,CACpFC,kBAAmBX,kBACnBC,aAAcF,SAASE,kCAEjBW,mBAAmBT,cAAeI,KAAMC"}
\ No newline at end of file
+{"version":3,"file":"warningbox.min.js","sources":["../src/warningbox.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Module rendering the warning box to inform the users about misleading AI results.\n *\n * @module local_ai_manager/warningbox\n * @copyright 2024 ISB Bayern\n * @author Philipp Memmel\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {getAiConfig} from 'local_ai_manager/config';\nimport Templates from 'core/templates';\n\n\n/**\n * Renders the warning box.\n *\n * @param {string} selector the selector where the warning box should be rendered into\n */\nexport const renderWarningBox = async(selector) => {\n const aiConfig = await getAiConfig();\n const showAiWarningLink = aiConfig.aiwarningurl.length > 0;\n const targetElement = document.querySelector(selector);\n const {html, js} = await Templates.renderForPromise('local_ai_manager/ai_info_warning', {\n showaiwarninglink: showAiWarningLink,\n aiwarningurl: aiConfig.aiwarningurl\n });\n Templates.appendNodeContents(targetElement, html, js);\n};\n"],"names":["async","aiConfig","showAiWarningLink","aiwarningurl","length","targetElement","document","querySelector","selector","html","js","Templates","renderForPromise","showaiwarninglink","appendNodeContents"],"mappings":";;;;;;;;sLAiCgCA,MAAAA,iBACtBC,eAAiB,yBACjBC,kBAAoBD,SAASE,aAAaC,OAAS,EACnDC,cAAgBC,SAASC,cAAcC,WACvCC,KAACA,KAADC,GAAOA,UAAYC,mBAAUC,iBAAiB,mCAAoC,CACpFC,kBAAmBX,kBACnBC,aAAcF,SAASE,kCAEjBW,mBAAmBT,cAAeI,KAAMC"}
\ No newline at end of file
diff --git a/amd/src/rights_config_table.js b/amd/src/rights_config_table.js
index d9c15e4..87481f1 100644
--- a/amd/src/rights_config_table.js
+++ b/amd/src/rights_config_table.js
@@ -131,7 +131,7 @@ const checkedCheckboxesCount = () => {
/**
* Updates the selection count info text box.
*/
-const updateSelectionCountInfo = async () => {
+const updateSelectionCountInfo = async() => {
const selectionCountInfoTarget = table.querySelector(selectors.SELECTIONINFO);
const infoText = await getString('selecteduserscount', 'local_ai_manager', checkedCheckboxesCount());
selectionCountInfoTarget.innerHTML = infoText;
diff --git a/amd/src/userquota.js b/amd/src/userquota.js
index 01b40f7..5a866d2 100644
--- a/amd/src/userquota.js
+++ b/amd/src/userquota.js
@@ -32,17 +32,17 @@ const constants = {
const queryCountStrings = {
chat: 'chat requests',
- chat_shortened: 'chat',
+ chatShortened: 'chat',
feedback: 'feedback requests',
- feedback_shortened: 'feedback',
+ feedbackShortened: 'feedback',
imggen: 'image generation generation requests',
- imggen_shortened: 'image generation generation',
+ imggenShortened: 'image generation generation',
singleprompt: 'text requests',
- singleprompt_shortened: 'text',
+ singlepromptShortened: 'text',
translate: 'translation requests',
- translate_shortened: 'translation',
+ translateShortened: 'translation',
tts: 'audio requests',
- tts_shortened: 'audio'
+ ttsShortened: 'audio'
};
const fetchUserquotaData = () => fetchMany([{
@@ -56,7 +56,7 @@ const fetchUserquotaData = () => fetchMany([{
* @param {string} selector the id of the element to insert the infobox
* @param {string[]} purposes the purposes to show user quota for
*/
-export const renderUserQuota = async (selector, purposes) => {
+export const renderUserQuota = async(selector, purposes) => {
await localizeQueryCountTexts();
const targetElement = document.querySelector(selector);
@@ -76,7 +76,7 @@ export const renderUserQuota = async (selector, purposes) => {
});
});
purposeInfo[purposeInfo.length - 1].islastelement = true;
- purposeInfo[purposeInfo.length - 1].querycounttext = queryCountStrings[purposeInfo[purposeInfo.length - 1]['purpose']];
+ purposeInfo[purposeInfo.length - 1].querycounttext = queryCountStrings[purposeInfo[purposeInfo.length - 1].purpose];
const userquotaContentTemplateContext = {
purposes: purposeInfo,
@@ -87,9 +87,9 @@ export const renderUserQuota = async (selector, purposes) => {
Templates.appendNodeContents(targetElement, html, js);
};
-const localizeQueryCountTexts = async () => {
+const localizeQueryCountTexts = async() => {
const stringsToFetch = [];
- Object.keys(queryCountStrings).filter(key => !key.endsWith('_shortened')).forEach((key) => {
+ Object.keys(queryCountStrings).filter(key => !key.endsWith('Shortened')).forEach((key) => {
stringsToFetch.push({key: 'requestcount', component: 'aipurpose_' + key});
stringsToFetch.push({key: 'requestcount_shortened', component: 'aipurpose_' + key});
});
diff --git a/amd/src/warningbox.js b/amd/src/warningbox.js
index 95e72ab..6f8988e 100644
--- a/amd/src/warningbox.js
+++ b/amd/src/warningbox.js
@@ -31,7 +31,7 @@ import Templates from 'core/templates';
*
* @param {string} selector the selector where the warning box should be rendered into
*/
-export const renderWarningBox = async (selector) => {
+export const renderWarningBox = async(selector) => {
const aiConfig = await getAiConfig();
const showAiWarningLink = aiConfig.aiwarningurl.length > 0;
const targetElement = document.querySelector(selector);
diff --git a/styles.css b/styles.css
index 970ee6e..d72c427 100644
--- a/styles.css
+++ b/styles.css
@@ -35,7 +35,7 @@
font-family: 'Lexend';
font-style: normal;
font-weight: 200;
- src: url('[[font:local_ai_manager|Lexend-ExtraLight.ttf]]')format('truetype');
+ src: url('[[font:local_ai_manager|Lexend-ExtraLight.ttf]]') format('truetype');
}
@font-face {
@@ -43,7 +43,7 @@
font-family: 'Lexend';
font-style: normal;
font-weight: 300;
- src: url('[[font:local_ai_manager|Lexend-Light.ttf]]')format('truetype');
+ src: url('[[font:local_ai_manager|Lexend-Light.ttf]]') format('truetype');
}
@font-face {
@@ -51,7 +51,7 @@
font-family: 'Lexend';
font-style: normal;
font-weight: 400;
- src: url('[[font:local_ai_manager|Lexend-Regular.ttf]]')format('truetype');
+ src: url('[[font:local_ai_manager|Lexend-Regular.ttf]]') format('truetype');
}
@font-face {
@@ -59,7 +59,7 @@
font-family: 'Lexend';
font-style: normal;
font-weight: 600;
- src: url('[[font:local_ai_manager|Lexend-SemiBold.ttf]]')format('truetype');
+ src: url('[[font:local_ai_manager|Lexend-SemiBold.ttf]]') format('truetype');
}
@font-face {
@@ -75,14 +75,14 @@
}
.local_ai_manager-red {
- color: #ff0000;
+ color: #f00;
}
.local_ai_manager-infobox {
display: flex;
align-items: center;
gap: 10px;
- color: #60616D;
+ color: #60616d;
font-family: "Atkinson Hyperlegible";
font-size: 14px;
font-style: normal;
@@ -91,7 +91,7 @@
}
.local_ai_manager-userquota_limitreached {
- color: #ff0000;
+ color: #f00;
}
.local_ai_manager-infobox p {
@@ -106,10 +106,6 @@
min-width: 20rem;
}
-#page-local-ai_manager-quota_config .mbseasytoggle {
- display: none !important;
-}
-
#page-local-ai_manager-purpose_config #region-main select {
width: 100%;
}