From 063fadf43d4dd994390980a22a3fd20bf6dba267 Mon Sep 17 00:00:00 2001 From: Arame22 <151528881+Arame22@users.noreply.github.com> Date: Wed, 17 Jul 2024 11:27:56 +0200 Subject: [PATCH 1/3] =?UTF-8?q?=E2=9C=A8(projet)=20add=20copilot=20iframe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We create a minimal moodle block plugin that has 1 setting: the publicly available iframe URL to a copilot. --- block_iagora.php | 38 ++++++++++++++++++++++++++---- edit_form.php | 50 ++++++++++++++++++++++++++++++++++++++++ lang/en/block_iagora.php | 6 ++++- 3 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 edit_form.php diff --git a/block_iagora.php b/block_iagora.php index 716f069..eef3503 100644 --- a/block_iagora.php +++ b/block_iagora.php @@ -23,12 +23,12 @@ */ /** - * The iagora block class. + * Store configuration data for the iagora block. */ class block_iagora extends block_base { /** - * Initialises the block. + * Initialize the block. * * @return void */ @@ -37,7 +37,7 @@ public function init() { } /** - * Gets the block contents. + * Get the block content. * * @return string The block HTML. */ @@ -48,7 +48,14 @@ public function get_content() { $this->content = new stdClass(); $this->content->footer = ''; - $this->content->text = ''; + + $iframeurl = isset($this->config->iframeurl) ? $this->config->iframeurl : ''; + + if (empty($iframeurl)) { + $this->content->text = get_string('noiframeurl', 'block_iagora'); + } else { + $this->content->text = ''; + } return $this->content; } @@ -61,4 +68,27 @@ public function get_content() { public function applicable_formats() { return ['all' => true]; } + + /** + * Allow the block to be configured. + * + * @return bool + */ + public function instance_allow_config() { + return true; + } + + /** + * Save instance configuration. + * + * @param stdClass $data The configuration data. + * @param bool $nolongerused Indicates if $data is no longer used. + * @return bool True if data was saved successfully, false otherwise. + */ + public function instance_config_save($data, $nolongerused = false) { + if (isset($data->iframeurl)) { + $data->iframeurl = clean_param($data->iframeurl, PARAM_URL); + } + return parent::instance_config_save($data, $nolongerused); + } } diff --git a/edit_form.php b/edit_form.php new file mode 100644 index 0000000..904292c --- /dev/null +++ b/edit_form.php @@ -0,0 +1,50 @@ +. + +/** + * Block edit form class for the block_iagora plugin. + * + * @package block_iagora + * @copyright 2024, Datum Academy + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +/** + * Class block_iagora_edit_form extending block_edit_form. + * + * This form class allows configuration of specific settings for the iagora block, + * including the iframe URL. + */ +class block_iagora_edit_form extends block_edit_form { + + /** + * Specific definition of the form elements. + * + * @param MoodleQuickForm $mform The Moodle form to be configured. + */ + protected function specific_definition($mform) { + // Section header title according to language file. + $mform->addElement('header', 'config_header', get_string('blocksettings', 'block')); + + // Iframe URL. + $mform->addElement('text', 'config_iframeurl', get_string('iframeurl', 'block_iagora')); + $mform->setType('config_iframeurl', PARAM_URL); + $mform->addHelpButton('config_iframeurl', 'iframeurl', 'block_iagora'); + $mform->setDefault('config_iframeurl', ''); + $mform->addElement('static', 'iframe_url_desc', '', get_string('iframe_url_desc', 'block_iagora')); + + } + +} diff --git a/lang/en/block_iagora.php b/lang/en/block_iagora.php index 18229d2..d342579 100644 --- a/lang/en/block_iagora.php +++ b/lang/en/block_iagora.php @@ -22,4 +22,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['pluginname'] = 'IAGORA'; + $string['iframe_url_desc'] = 'Public URL available for chat iframe'; + $string['iframeurl'] = 'Iframe URL'; + $string['iframeurl_help'] = 'Public URL for the Microsoft Copilot chat iframe'; + $string['noiframeurl'] = 'No url defined for this block. Please configure a URL in the block parameters'; + $string['pluginname'] = 'IAGORA'; From 43e57e8f9f2aaa7c0fcebf931eeae61cc89e0add Mon Sep 17 00:00:00 2001 From: Arame22 <151528881+Arame22@users.noreply.github.com> Date: Thu, 18 Jul 2024 13:27:28 +0200 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=92=9A(projet)=20fix=20ci=20error=20h?= =?UTF-8?q?andling?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI execution used to stop right after a git lint error so we made these changes to allow full CI execution --- .github/workflows/ci.yml | 3 +++ block_iagora.php | 2 +- edit_form.php | 2 +- lang/en/block_iagora.php | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9210b1f..f0619da 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,6 +47,7 @@ jobs: run: ~/.local/bin/gitlint --commits origin/main..HEAD - name: Setup PHP ${{ matrix.php }} + if: ${{ !cancelled() }} uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} @@ -54,6 +55,7 @@ jobs: coverage: xdebug - name: Initialise moodle-plugin-ci + if: ${{ !cancelled() }} run: | composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^4 echo $(cd ci/bin; pwd) >> $GITHUB_PATH @@ -62,6 +64,7 @@ jobs: echo "NVM_DIR=$HOME/.nvm" >> $GITHUB_ENV - name: Install moodle-plugin-ci + if: ${{ !cancelled() }} run: moodle-plugin-ci install --plugin ./plugin --db-host=127.0.0.1 env: DB: ${{ matrix.database }} diff --git a/block_iagora.php b/block_iagora.php index eef3503..40b7c39 100644 --- a/block_iagora.php +++ b/block_iagora.php @@ -61,7 +61,7 @@ public function get_content() { } /** - * Defines in which pages this block can be added. + * Define in which pages this block can be added. * * @return array of the pages where the block can be added. */ diff --git a/edit_form.php b/edit_form.php index 904292c..e18dac6 100644 --- a/edit_form.php +++ b/edit_form.php @@ -43,7 +43,7 @@ protected function specific_definition($mform) { $mform->setType('config_iframeurl', PARAM_URL); $mform->addHelpButton('config_iframeurl', 'iframeurl', 'block_iagora'); $mform->setDefault('config_iframeurl', ''); - $mform->addElement('static', 'iframe_url_desc', '', get_string('iframe_url_desc', 'block_iagora')); + $mform->addElement('static', 'iframeurl_desc', '', get_string('iframeurl_desc', 'block_iagora')); } diff --git a/lang/en/block_iagora.php b/lang/en/block_iagora.php index d342579..b92c773 100644 --- a/lang/en/block_iagora.php +++ b/lang/en/block_iagora.php @@ -22,8 +22,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - $string['iframe_url_desc'] = 'Public URL available for chat iframe'; $string['iframeurl'] = 'Iframe URL'; + $string['iframeurl_desc'] = 'Public URL available for chat iframe'; $string['iframeurl_help'] = 'Public URL for the Microsoft Copilot chat iframe'; $string['noiframeurl'] = 'No url defined for this block. Please configure a URL in the block parameters'; $string['pluginname'] = 'IAGORA'; From 0e1d688df7b78d91c5201aeed9cb556481b13ad5 Mon Sep 17 00:00:00 2001 From: Arame22 <151528881+Arame22@users.noreply.github.com> Date: Fri, 2 Aug 2024 12:34:35 +0200 Subject: [PATCH 3/3] =?UTF-8?q?=E2=9C=A8=20integration=20copilot=20with=20?= =?UTF-8?q?BotFramework-WebChat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit add webchat framework integration parts in block_iagora.php and edit_form.php files, also add iagora.js file to manage javascript with moodle --- amd/build/iagora.min.js | 3 ++ amd/build/iagora.min.js.map | 1 + amd/src/iagora.js | 56 +++++++++++++++++++++++++++++++++++++ block_iagora.php | 51 ++++++++++++++++++++++++--------- edit_form.php | 9 ++++++ lang/en/block_iagora.php | 6 +++- package.json | 16 +++++++++++ 7 files changed, 128 insertions(+), 14 deletions(-) create mode 100644 amd/build/iagora.min.js create mode 100644 amd/build/iagora.min.js.map create mode 100644 amd/src/iagora.js create mode 100644 package.json diff --git a/amd/build/iagora.min.js b/amd/build/iagora.min.js new file mode 100644 index 0000000..0985858 --- /dev/null +++ b/amd/build/iagora.min.js @@ -0,0 +1,3 @@ +define("block_iagora/iagora",["exports","botframework-webchat"],(function(_exports,_botframeworkWebchat){var obj;Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=_exports.default=void 0,_exports.initIagoraChat=initIagoraChat,_botframeworkWebchat=(obj=_botframeworkWebchat)&&obj.__esModule?obj:{default:obj};const init=_ref=>{let{copiloturl:copiloturl}=_ref;console.log("Copilot URL:",copiloturl)};function initIagoraChat(chatId){const chatContainer=document.getElementById(chatId),token=chatId;try{const directLine=_botframeworkWebchat.default.createDirectLine({domain:new URL("v3/directline","https://directline.botframework.com"),token:token}),subscription=directLine.connectionStatus$.subscribe({next(value){2===value&&(directLine.postActivity({localTimezone:Intl.DateTimeFormat().resolvedOptions().timeZone,locale:document.documentElement.lang||"en",name:"startConversation",type:"event"}).subscribe(),subscription.unsubscribe())}});_botframeworkWebchat.default.renderWebChat({directLine:directLine,locale:document.documentElement.lang||"en"},chatContainer)}catch(error){console.error("Error initializing chat:",error),chatContainer.innerHTML="Failed to load chat. Please try again later."}}_exports.init=init;var _default={init:init,initIagoraChat:initIagoraChat};return _exports.default=_default,_exports.default})); + +//# sourceMappingURL=iagora.min.js.map \ No newline at end of file diff --git a/amd/build/iagora.min.js.map b/amd/build/iagora.min.js.map new file mode 100644 index 0000000..0ec2027 --- /dev/null +++ b/amd/build/iagora.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"iagora.min.js","sources":["../src/iagora.js"],"sourcesContent":["import WebChat from 'botframework-webchat';\n/**\n * Initializes the chat with given parameters.\n * @param {Object} params - The initialization parameters.\n * @param {string} params.copiloturl - The copilot.\n * @param {string} params.categoryid - The category ID.\n * @param {string} params.chatId - The chat container ID.\n */\n\nexport const init = ({copiloturl}) => {\n // eslint-disable-next-line no-console\n console.log('Copilot URL:', copiloturl);\n //initIagoraChat(chatId);\n};\n/**\n *\n * @param {string} chatId\n */\nexport function initIagoraChat(chatId) {\n const chatContainer = document.getElementById(chatId);\n\n // Static token and directLine URL (example values)\n const directLineURL = 'https://directline.botframework.com';\n const token = chatId ;\n try {\n const directLine = WebChat.createDirectLine({domain: new URL(\"v3/directline\", directLineURL), token});\n\n const subscription = directLine.connectionStatus$.subscribe({\n next(value) {\n if (value === 2) {\n directLine\n .postActivity({\n localTimezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n locale: document.documentElement.lang || \"en\",\n name: \"startConversation\",\n type: \"event\"\n })\n .subscribe();\n\n subscription.unsubscribe();\n }\n }\n });\n\n WebChat.renderWebChat({directLine, locale: document.documentElement.lang || \"en\"}, chatContainer);\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(\"Error initializing chat:\", error);\n chatContainer.innerHTML = \"Failed to load chat. Please try again later.\";\n }\n }\n\n export default {\n init,\n initIagoraChat\n };"],"names":["init","_ref","copiloturl","console","log","initIagoraChat","chatId","chatContainer","document","getElementById","token","directLine","WebChat","createDirectLine","domain","URL","subscription","connectionStatus$","subscribe","next","value","postActivity","localTimezone","Intl","DateTimeFormat","resolvedOptions","timeZone","locale","documentElement","lang","name","type","unsubscribe","renderWebChat","error","innerHTML"],"mappings":"8UASaA,KAAOC,WAACC,WAACA,iBAElBC,QAAQC,IAAI,eAAgBF,sBAOhBG,eAAeC,cACxBC,cAAgBC,SAASC,eAAeH,QAIjCI,MAAQJ,iBAEJK,WAAaC,6BAAQC,iBAAiB,CAACC,OAAQ,IAAIC,IAAI,gBAH3C,uCAG4EL,MAAAA,QAExFM,aAAeL,WAAWM,kBAAkBC,UAAU,CACxDC,KAAKC,OACa,IAAVA,QACAT,WACKU,aAAa,CACVC,cAAeC,KAAKC,iBAAiBC,kBAAkBC,SACvDC,OAAQnB,SAASoB,gBAAgBC,MAAQ,KACzCC,KAAM,oBACNC,KAAM,UAETb,YAELF,aAAagB,+CAKjBC,cAAc,CAACtB,WAAAA,WAAYgB,OAAQnB,SAASoB,gBAAgBC,MAAQ,MAAOtB,eACrF,MAAO2B,OAEL/B,QAAQ+B,MAAM,2BAA4BA,OAC1C3B,cAAc4B,UAAY,gFAInB,CACXnC,KAAAA,KACAK,eAAAA"} \ No newline at end of file diff --git a/amd/src/iagora.js b/amd/src/iagora.js new file mode 100644 index 0000000..2d17ecb --- /dev/null +++ b/amd/src/iagora.js @@ -0,0 +1,56 @@ +import WebChat from 'botframework-webchat'; +/** + * Initializes the chat with given parameters. + * @param {Object} params - The initialization parameters. + * @param {string} params.copiloturl - The copilot. + * @param {string} params.categoryid - The category ID. + * @param {string} params.chatId - The chat container ID. + */ + +export const init = ({copiloturl}) => { + // eslint-disable-next-line no-console + console.log('Copilot URL:', copiloturl); + //initIagoraChat(chatId); +}; +/** + * + * @param {string} chatId + */ +export function initIagoraChat(chatId) { + const chatContainer = document.getElementById(chatId); + + // Static token and directLine URL (example values) + const directLineURL = 'https://directline.botframework.com'; + const token = chatId ; + try { + const directLine = WebChat.createDirectLine({domain: new URL("v3/directline", directLineURL), token}); + + const subscription = directLine.connectionStatus$.subscribe({ + next(value) { + if (value === 2) { + directLine + .postActivity({ + localTimezone: Intl.DateTimeFormat().resolvedOptions().timeZone, + locale: document.documentElement.lang || "en", + name: "startConversation", + type: "event" + }) + .subscribe(); + + subscription.unsubscribe(); + } + } + }); + + WebChat.renderWebChat({directLine, locale: document.documentElement.lang || "en"}, chatContainer); + } catch (error) { + // eslint-disable-next-line no-console + console.error("Error initializing chat:", error); + chatContainer.innerHTML = "Failed to load chat. Please try again later."; + } + } + + export default { + init, + initIagoraChat + }; \ No newline at end of file diff --git a/block_iagora.php b/block_iagora.php index 40b7c39..82c1613 100644 --- a/block_iagora.php +++ b/block_iagora.php @@ -48,14 +48,14 @@ public function get_content() { $this->content = new stdClass(); $this->content->footer = ''; - $iframeurl = isset($this->config->iframeurl) ? $this->config->iframeurl : ''; - if (empty($iframeurl)) { - $this->content->text = get_string('noiframeurl', 'block_iagora'); - } else { - $this->content->text = ''; - } + // if (empty($iframeurl)) { + // $this->content->text = get_string('noiframeurl', 'block_iagora'); + // } else { + // $this->content->text = ''; + // } + $this->content->text = $this->generate_chat_content($iframeurl); return $this->content; } @@ -63,19 +63,44 @@ public function get_content() { /** * Define in which pages this block can be added. * - * @return array of the pages where the block can be added. + * @param string $iframeurl The URL to be used in the iframe. + * @return string The generated HTML content. */ - public function applicable_formats() { - return ['all' => true]; + private function generate_chat_content($iframeurl) { + global $PAGE, $OUTPUT; die($iframeurl); + + // Load necessary styles and scripts + $PAGE->requires->js(new moodle_url('https://cdn.botframework.com/botframework-webchat/latest/webchat.js'), true); + $PAGE->requires->js_call_amd('block_iagora/iagora', 'init', [[ + 'copiloturl' => $iframeurl + ]]); + + // Generate a unique identifier for the chat container + $chat_id = uniqid('iagora_chat_'); + + // Chat button icon (using Moodle icons) + $chat_icon = $OUTPUT->pix_icon('t/message', get_string('openchat', 'block_iagora')); + + $output = html_writer::div($chat_icon, 'iagora-chat-toggle', ['id' => 'iagora-toggle-' . $chat_id,'data-url' => 'iframe_url']); + $output .= html_writer::div('', 'iagora-chat-container', ['id' => $chat_id]); + + // Add initialization script + // $output .= html_writer::script(" + // document.addEventListener('DOMContentLoaded', function() { + // initIagoraChat('{$chat_id}', " . json_encode($this->config) . "); + // }); + // "); + + return $output; } /** - * Allow the block to be configured. + * Define in which pages this block can be added. * - * @return bool + * @return array of the pages where the block can be added. */ - public function instance_allow_config() { - return true; + public function applicable_formats() { + return ['all' => true]; } /** diff --git a/edit_form.php b/edit_form.php index e18dac6..004aef2 100644 --- a/edit_form.php +++ b/edit_form.php @@ -45,6 +45,15 @@ protected function specific_definition($mform) { $mform->setDefault('config_iframeurl', ''); $mform->addElement('static', 'iframeurl_desc', '', get_string('iframeurl_desc', 'block_iagora')); + // Background color + $mform->addElement('text', 'config_backgroundcolor', get_string('backgroundcolor', 'block_iagora')); + $mform->setDefault('config_backgroundcolor', '#A9D1F3'); + $mform->setType('config_backgroundcolor', PARAM_TEXT); + + // Bubble background color + $mform->addElement('text', 'config_bubblebackground', get_string('bubblebackground', 'block_iagora')); + $mform->setDefault('config_bubblebackground', '#F3CBA9'); + $mform->setType('config_bubblebackground', PARAM_TEXT); } } diff --git a/lang/en/block_iagora.php b/lang/en/block_iagora.php index b92c773..0a097d7 100644 --- a/lang/en/block_iagora.php +++ b/lang/en/block_iagora.php @@ -22,8 +22,12 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ + $string['backgroundcolor'] = 'Background Color'; + $string['bubblebackground'] = 'Bubble Background Color'; + $string['pluginname'] = 'IAGORA'; $string['iframeurl'] = 'Iframe URL'; $string['iframeurl_desc'] = 'Public URL available for chat iframe'; $string['iframeurl_help'] = 'Public URL for the Microsoft Copilot chat iframe'; $string['noiframeurl'] = 'No url defined for this block. Please configure a URL in the block parameters'; - $string['pluginname'] = 'IAGORA'; + + \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..1e86732 --- /dev/null +++ b/package.json @@ -0,0 +1,16 @@ +{ + "name": "iagora", + "version": "1.0.0", + "description": "iagora Chat block for Moodle", + "author": "Datum Academy ", + "license": "GPL-3.0", + "private": true, + "dependencies": { + "botframework-webchat": "^4.15.0" + }, + "scripts": { + "build": "grunt amd", + "watch": "grunt watch", + "lint": "grunt eslint stylelint" + } +} \ No newline at end of file