diff --git a/amd/build/editor.min.js b/amd/build/editor.min.js index dccd8b9..8685ae5 100644 --- a/amd/build/editor.min.js +++ b/amd/build/editor.min.js @@ -1,3 +1,3 @@ -define("mod_newsletter/editor",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.loadCss=void 0;_exports.loadCss=async function(){var select=document.querySelector("#id_stylesheetid");function change_stylesheet(){console.log("config")}select&&select.addEventListener("change",change_stylesheet),new Promise((resolve=>{!function checkIfLoaded(){window.tinyMCE?resolve(window.tinyMCE):setTimeout(checkIfLoaded,100)}()})).then((tinyMCE=>{console.log("tinyMCE is loaded:",tinyMCE);const existingEditor=tinyMCE.EditorManager.get("id_htmlcontent");existingEditor&&console.log(existingEditor),change_stylesheet()}))}})); +define("mod_newsletter/editor",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.loadCss=void 0;_exports.loadCss=async function(editorconfig){var select=document.querySelector("#id_stylesheetid");function change_stylesheet(){console.log("config")}select&&select.addEventListener("change",change_stylesheet),new Promise((resolve=>{!function checkIfLoaded(){window.tinyMCE?resolve(window.tinyMCE):setTimeout(checkIfLoaded,100)}()})).then((tinyMCE=>{console.log("tinyMCE is loaded:",tinyMCE);const existingEditor=tinyMCE.add("id_htmlcontent");existingEditor&&console.log(existingEditor),tinyMCE.init(editorconfig),change_stylesheet()}))}})); //# sourceMappingURL=editor.min.js.map \ No newline at end of file diff --git a/amd/build/editor.min.js.map b/amd/build/editor.min.js.map index c5c638d..48e3a2d 100644 --- a/amd/build/editor.min.js.map +++ b/amd/build/editor.min.js.map @@ -1 +1 @@ -{"version":3,"file":"editor.min.js","sources":["../src/editor.js"],"sourcesContent":["/* eslint-disable no-console */\n// 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// import {setupForElementId} from 'editor_tiny/editor';\n\nexport const loadCss = async function() {\n var select = document.querySelector('#id_stylesheetid');\n if (select) {\n select.addEventListener('change', change_stylesheet);\n }\n /**\n * Function to wait until tinyMCE is loaded\n * @returns {Promise}\n */\n function waitUntilTinyMCELoaded() {\n return new Promise((resolve) => {\n /**\n * Check if tinyMCE object is available\n */\n function checkIfLoaded() {\n if (window.tinyMCE) {\n // If tinyMCE is available, resolve the promise\n resolve(window.tinyMCE);\n } else {\n // If not, wait and check again\n setTimeout(checkIfLoaded, 100); // Check every 100 milliseconds\n }\n }\n\n checkIfLoaded();\n });\n }\n\n /**\n * Function to change CSS for the content inside TinyMCE\n */\n waitUntilTinyMCELoaded()\n .then((tinyMCE) => {\n console.log('tinyMCE is loaded:', tinyMCE);\n const existingEditor = tinyMCE.EditorManager.get('id_htmlcontent');\n if(existingEditor) {\n console.log(existingEditor);\n }\n // Call function to change CSS for TinyMCE content\n change_stylesheet();\n });\n\n // var Tiny = setupForElementId({\n // elementId: \"id_htmlcontent\",\n // options: {},\n // });\n\n /**\n * Changes the stylesheet based on the selected option.\n */\n function change_stylesheet() {\n console.log('config');\n }\n};\n"],"names":["async","select","document","querySelector","change_stylesheet","console","log","addEventListener","Promise","resolve","checkIfLoaded","window","tinyMCE","setTimeout","then","existingEditor","EditorManager","get"],"mappings":"gKAkBuBA,qBACfC,OAASC,SAASC,cAAc,6BAiD3BC,oBACLC,QAAQC,IAAI,UAjDZL,QACAA,OAAOM,iBAAiB,SAAUH,mBAO3B,IAAII,SAASC,oBAIPC,gBACDC,OAAOC,QAEPH,QAAQE,OAAOC,SAGfC,WAAWH,cAAe,KAIlCA,MAQHI,MAAMF,UACHP,QAAQC,IAAI,qBAAsBM,eAC5BG,eAAiBH,QAAQI,cAAcC,IAAI,kBAC9CF,gBACCV,QAAQC,IAAIS,gBAGhBX"} \ No newline at end of file +{"version":3,"file":"editor.min.js","sources":["../src/editor.js"],"sourcesContent":["/* eslint-disable no-console */\n// 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\nexport const loadCss = async function(editorconfig) {\n var select = document.querySelector('#id_stylesheetid');\n if (select) {\n select.addEventListener('change', change_stylesheet);\n }\n /**\n * Function to wait until tinyMCE is loaded\n * @returns {Promise}\n */\n function waitUntilTinyMCELoaded() {\n return new Promise((resolve) => {\n /**\n * Check if tinyMCE object is available\n */\n function checkIfLoaded() {\n if (window.tinyMCE) {\n // If tinyMCE is available, resolve the promise\n resolve(window.tinyMCE);\n } else {\n // If not, wait and check again\n setTimeout(checkIfLoaded, 100); // Check every 100 milliseconds\n }\n }\n checkIfLoaded();\n });\n }\n\n /**\n * Function to change CSS for the content inside TinyMCE\n */\n waitUntilTinyMCELoaded()\n .then((tinyMCE) => {\n console.log('tinyMCE is loaded:', tinyMCE);\n const existingEditor = tinyMCE.add('id_htmlcontent');\n if(existingEditor) {\n console.log(existingEditor);\n }\n // Call function to change CSS for TinyMCE content\n tinyMCE.init(editorconfig);\n change_stylesheet();\n });\n\n /**\n * Changes the stylesheet based on the selected option.\n */\n function change_stylesheet() {\n console.log('config');\n }\n};\n"],"names":["async","editorconfig","select","document","querySelector","change_stylesheet","console","log","addEventListener","Promise","resolve","checkIfLoaded","window","tinyMCE","setTimeout","then","existingEditor","add","init"],"mappings":"gKAgBuBA,eAAeC,kBAC9BC,OAASC,SAASC,cAAc,6BA4C3BC,oBACLC,QAAQC,IAAI,UA5CZL,QACAA,OAAOM,iBAAiB,SAAUH,mBAO3B,IAAII,SAASC,oBAIPC,gBACDC,OAAOC,QAEPH,QAAQE,OAAOC,SAGfC,WAAWH,cAAe,KAGlCA,MAQHI,MAAMF,UACHP,QAAQC,IAAI,qBAAsBM,eAC5BG,eAAiBH,QAAQI,IAAI,kBAChCD,gBACCV,QAAQC,IAAIS,gBAGhBH,QAAQK,KAAKjB,cACbI"} \ No newline at end of file diff --git a/amd/src/editor.js b/amd/src/editor.js index c1b0e52..defb06c 100755 --- a/amd/src/editor.js +++ b/amd/src/editor.js @@ -14,9 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -// import {setupForElementId} from 'editor_tiny/editor'; - -export const loadCss = async function() { +/** + * This is obsolete. To be deleted in the future. Maybe if Moodle does a better integration of Tiny 6, it could be used again. + * + * @param editorconfig + * @returns {Promise} + */ +export const loadCss = async function(editorconfig) { var select = document.querySelector('#id_stylesheetid'); if (select) { select.addEventListener('change', change_stylesheet); @@ -39,7 +43,6 @@ export const loadCss = async function() { setTimeout(checkIfLoaded, 100); // Check every 100 milliseconds } } - checkIfLoaded(); }); } @@ -50,19 +53,15 @@ export const loadCss = async function() { waitUntilTinyMCELoaded() .then((tinyMCE) => { console.log('tinyMCE is loaded:', tinyMCE); - const existingEditor = tinyMCE.EditorManager.get('id_htmlcontent'); + const existingEditor = tinyMCE.add('id_htmlcontent'); if(existingEditor) { console.log(existingEditor); } // Call function to change CSS for TinyMCE content + tinyMCE.init(editorconfig); change_stylesheet(); }); - // var Tiny = setupForElementId({ - // elementId: "id_htmlcontent", - // options: {}, - // }); - /** * Changes the stylesheet based on the selected option. */ diff --git a/classes/newsletter.php b/classes/newsletter.php index 9fd55cd..b7934fb 100644 --- a/classes/newsletter.php +++ b/classes/newsletter.php @@ -29,6 +29,7 @@ use context_module; use core\event\user_created; use core_user; +use editor_tiny\editor; use editor_tiny\manager; use mod_newsletter_instance_store; use newsletter_section_list; @@ -831,49 +832,8 @@ private function view_edit_issue_page(array $params) { 'filename', false ); - $cssurls = []; - $cssurls[NEWSLETTER_DEFAULT_STYLESHEET] = "{$CFG->wwwroot}/mod/newsletter/reset.css"; - if (!empty($files)) { - foreach ($files as $file) { - $url = "{$CFG->wwwroot}/pluginfile.php/{$file->get_contextid()}/mod_newsletter/" . NEWSLETTER_FILE_AREA_STYLESHEET; - $cssurls[$file->get_id()] = $url . $file->get_filepath() . $file->get_itemid() . '/' . $file->get_filename(); - } - } - $editormanager = new manager(); - $siteconfig = get_config('editor_tiny'); - $editorconfig = json_encode([ - 'context' => $context->id, - - // File picker options. - 'filepicker' => [], - - 'currentLanguage' => current_language(), - - 'branding' => property_exists($siteconfig, 'branding') ? !empty($siteconfig->branding) : true, - - // Language options. - 'language' => [ - 'currentlang' => current_language(), - 'installed' => get_string_manager()->get_list_of_translations(true), - 'available' => get_string_manager()->get_list_of_languages() - ], - - // Placeholder selectors. - // Some contents (Example: placeholder elements) are only shown in the editor, and not to users. It is unrelated to the - // real display. We created a list of placeholder selectors, so we can decide to or not to apply rules, styles... to - // these elements. - // The default of this list will be empty. - // Other plugins can register their placeholder elements to placeholderSelectors list by calling - // editor_tiny/options::registerPlaceholderSelectors. - 'placeholderSelectors' => [], - - // Nest menu inside parent DOM. - 'nestedmenu' => true, - ]); - $plugins = json_encode($editormanager->get_plugin_configuration($context)); - $PAGE->requires->js_call_amd('mod_newsletter/editor', 'loadCss', - [$cssurls, $issue->stylesheetid, $editorconfig, $plugins]); - + $editor = new newsletter_editor(); + $editor->use_editor('id_htmlcontent', ['context' => $this->context], null, $issue, $files); $mform = new issue_form( null, array('newsletter' => $this, 'issue' => $issue, 'context' => $context) diff --git a/classes/newsletter_editor.php b/classes/newsletter_editor.php new file mode 100644 index 0000000..8252783 --- /dev/null +++ b/classes/newsletter_editor.php @@ -0,0 +1,131 @@ +. + +namespace mod_newsletter; +use editor_tiny\editor; + +/** + * Add custom css to the default editor. This is quite a hack due to the hacky implementation of Tiny 6 editor in Moodle. + */ +class newsletter_editor extends editor { + /** + * Use this editor for given element. + * + * @param string $elementid + * @param array $options + * @param null $fpoptions + * @param null $issue + */ + public function use_editor($elementid, array $options = null, $fpoptions = null, $issue = null, array $files = []) { + global $PAGE, $CFG; + // Ensure that the default configuration is set. + self::reset_default_configuration(); + self::set_default_configuration($this->manager); + + if ($fpoptions === null) { + $fpoptions = []; + } + + $context = $PAGE->context; + + if (isset($options['context']) && ($options['context'] instanceof \context)) { + // A different context was provided. + // Use that instead. + $context = $options['context']; + } + + $cssurls = []; + $cssurls[NEWSLETTER_DEFAULT_STYLESHEET] = "{$CFG->wwwroot}/mod/newsletter/reset.css"; + if (!empty($files)) { + foreach ($files as $file) { + $url = "{$CFG->wwwroot}/pluginfile.php/{$file->get_contextid()}/mod_newsletter/" . NEWSLETTER_FILE_AREA_STYLESHEET; + $cssurls[$file->get_id()] = $url . $file->get_filepath() . $file->get_itemid() . '/' . $file->get_filename(); + } + } + // Generate the configuration for this editor. + $siteconfig = get_config('editor_tiny'); + $config = (object) [ + // The URL to the CSS file for the editor. + 'css' => $cssurls[$issue->stylesheetid], + + // The current context for this page or editor. + 'context' => $context->id, + + // File picker options. + 'filepicker' => $fpoptions, + + 'currentLanguage' => current_language(), + + 'branding' => property_exists($siteconfig, 'branding') ? !empty($siteconfig->branding) : true, + + // Language options. + 'language' => [ + 'currentlang' => current_language(), + 'installed' => get_string_manager()->get_list_of_translations(true), + 'available' => get_string_manager()->get_list_of_languages() + ], + + // Placeholder selectors. + // Some contents (Example: placeholder elements) are only shown in the editor, and not to users. It is unrelated to the + // real display. We created a list of placeholder selectors, so we can decide to or not to apply rules, styles... to + // these elements. + // The default of this list will be empty. + // Other plugins can register their placeholder elements to placeholderSelectors list by calling + // editor_tiny/options::registerPlaceholderSelectors. + 'placeholderSelectors' => [], + + // Plugin configuration. + 'plugins' => $this->manager->get_plugin_configuration($context, $options, $fpoptions, $this), + + // Nest menu inside parent DOM. + 'nestedmenu' => true, + ]; + + if (defined('BEHAT_SITE_RUNNING') && BEHAT_SITE_RUNNING) { + // Add sample selectors for Behat test. + $config->placeholderSelectors = ['.behat-tinymce-placeholder']; + } + + foreach ($fpoptions as $fp) { + // Guess the draftitemid for the editor. + // Note: This is the best we can do at the moment. + if (!empty($fp->itemid)) { + $config->draftitemid = $fp->itemid; + break; + } + } + + $configoptions = json_encode(convert_to_array($config)); + + // Note: This is not ideal but the editor does not have control over any HTML output. + // The Editor API only allows you to run JavaScript. + // In the future we will extend the editor API to allow it to generate the textarea, or attributes to use in the + // textarea or its wrapper. + // For now we cannot use the `js_call_amd()` API call because it warns if the parameters passed exceed a + // relatively low character limit. + $inlinejs = << { + Tiny.setupForElementId({ + elementId: "${elementid}", + options: ${configoptions}, + }); + M.util.js_complete('editor_tiny/editor'); + }); + EOF; + $PAGE->requires->js_amd_inline($inlinejs); + } +} \ No newline at end of file diff --git a/classes/task/._send_newsletter.php b/classes/task/._send_newsletter.php deleted file mode 100644 index 85ee0ec..0000000 Binary files a/classes/task/._send_newsletter.php and /dev/null differ diff --git a/lang/de/._newsletter.php b/lang/de/._newsletter.php deleted file mode 100644 index be5ea9f..0000000 Binary files a/lang/de/._newsletter.php and /dev/null differ diff --git a/lang/de/newsletter.php b/lang/de/newsletter.php index d7afdca..d80744d 100644 --- a/lang/de/newsletter.php +++ b/lang/de/newsletter.php @@ -103,7 +103,7 @@ $string['health_2'] = 'Blacklisted'; $string['health_4'] = 'Abgemeldet'; $string['issue_htmlcontent'] = 'HTML Inhalt'; -$string['issue_stylesheet'] = 'Stylesheet-Datei für HTML Inhalt'; +$string['issue_stylesheet'] = 'Stylesheet-Datei für HTML Inhalt. '; $string['issue_title'] = 'Ausgabentitel'; $string['issue_title_help'] = 'Geben Sie hier den Titel der Ausgabe ein (erforderlich).'; $string['manage_subscriptions'] = 'Abonnements verwalten'; diff --git a/lang/en/._newsletter.php b/lang/en/._newsletter.php deleted file mode 100644 index b687a55..0000000 Binary files a/lang/en/._newsletter.php and /dev/null differ diff --git a/lang/en/newsletter.php b/lang/en/newsletter.php index e04cfdd..221c7dc 100644 --- a/lang/en/newsletter.php +++ b/lang/en/newsletter.php @@ -55,7 +55,7 @@ $string['issue_title_help'] = 'Type in the title of this issue. Required.'; $string['issue_htmlcontent'] = 'HTML content'; -$string['issue_stylesheet'] = 'Stylesheet file for HTML content'; +$string['issue_stylesheet'] = 'Stylesheet-Datei für HTML-Inhalte. Um korrekt gestyltes HTML beim Bearbeiten zu sehen, müssen Sie die Ausgabe zuerst speichern und dann erneut bearbeiten. Eine Änderung des Stylesheets während des Editierens ist derzeit nicht möglich.'; $string['mode_group_by_year'] = 'Group issues by year'; $string['mode_group_by_month'] = 'Group issues by month'; diff --git a/version.php b/version.php index 2af4cb5..c40f289 100644 --- a/version.php +++ b/version.php @@ -24,8 +24,8 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2024032900; +$plugin->version = 2024042500; $plugin->requires = 2022041900; $plugin->maturity = MATURITY_STABLE; -$plugin->release = 'v2.4.0-UkrainskaPravda'; // Already used names: Der Standard, Le Monde Diplomatique, NewYorkTimes. +$plugin->release = 'v2.4.1-UkrainskaPravda'; // Already used names: Der Standard, Le Monde Diplomatique, NewYorkTimes. $plugin->component = 'mod_newsletter';