From a6032854bf18148cbd74b2dc50ce6f2e9e9aaba0 Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Wed, 12 Oct 2022 10:34:42 +0800 Subject: [PATCH] MDL-75261 tiny_h5p: Add the Tiny H5P plugin Part of MDL-75966 AMOS BEGIN CPY [browserepositories,atto_h5p],[browserepositories,tiny_h5p] CPY [copyrightbutton,atto_h5p],[bcopyrightbutton,tiny_h5p] CPY [downloadbutton,atto_h5p],[downloadbutton,tiny_h5p] CPY [embedbutton,atto_h5p],[embedbutton,tiny_h5p] CPY [h5p:addembed,atto_h5p],[h5p:addembed,tiny_h5p] CPY [h5pfile,atto_h5p],[h5pfile,tiny_h5p] CPY [h5pfileorurl,atto_h5p],[h5pfileorurl,tiny_h5p] CPY [h5poptions,atto_h5p],[h5poptions,tiny_h5p] CPY [h5purl,atto_h5p],[h5purl,tiny_h5p] CPY [invalidh5purl,atto_h5p],[invalidh5purl,tiny_h5p] CPY [instructions,atto_h5p],[instructions,tiny_h5p] CPY [noh5pcontent,atto_h5p],[noh5pcontent,tiny_h5p] AMOS END --- lib/classes/plugin_manager.php | 1 + .../plugins/h5p/amd/build/commands.min.js | 3 + .../plugins/h5p/amd/build/commands.min.js.map | 1 + .../tiny/plugins/h5p/amd/build/common.min.js | 3 + .../plugins/h5p/amd/build/common.min.js.map | 1 + .../h5p/amd/build/configuration.min.js | 3 + .../h5p/amd/build/configuration.min.js.map | 1 + .../h5p/amd/build/filtercontent.min.js | 3 + .../h5p/amd/build/filtercontent.min.js.map | 1 + .../tiny/plugins/h5p/amd/build/modal.min.js | 3 + .../plugins/h5p/amd/build/modal.min.js.map | 1 + .../tiny/plugins/h5p/amd/build/options.min.js | 11 + .../plugins/h5p/amd/build/options.min.js.map | 1 + .../tiny/plugins/h5p/amd/build/plugin.min.js | 10 + .../plugins/h5p/amd/build/plugin.min.js.map | 1 + .../tiny/plugins/h5p/amd/build/ui.min.js | 10 + .../tiny/plugins/h5p/amd/build/ui.min.js.map | 1 + .../tiny/plugins/h5p/amd/src/commands.js | 68 ++++++ lib/editor/tiny/plugins/h5p/amd/src/common.js | 29 +++ .../tiny/plugins/h5p/amd/src/configuration.js | 36 ++++ .../tiny/plugins/h5p/amd/src/filtercontent.js | 41 ++++ lib/editor/tiny/plugins/h5p/amd/src/modal.js | 44 ++++ .../tiny/plugins/h5p/amd/src/options.js | 52 +++++ lib/editor/tiny/plugins/h5p/amd/src/plugin.js | 61 ++++++ lib/editor/tiny/plugins/h5p/amd/src/ui.js | 198 ++++++++++++++++++ .../tiny/plugins/h5p/classes/plugininfo.php | 76 +++++++ .../plugins/h5p/classes/privacy/provider.php | 30 +++ lib/editor/tiny/plugins/h5p/db/access.php | 36 ++++ lib/editor/tiny/plugins/h5p/editor_styles.css | 11 + .../tiny/plugins/h5p/lang/en/tiny_h5p.php | 42 ++++ .../tiny/plugins/h5p/pix/icon-white.png | Bin 0 -> 6257 bytes .../tiny/plugins/h5p/pix/icon-white.svg | 18 ++ lib/editor/tiny/plugins/h5p/pix/icon.png | Bin 0 -> 4541 bytes lib/editor/tiny/plugins/h5p/pix/icon.svg | 14 ++ .../plugins/h5p/templates/content.mustache | 38 ++++ .../tiny/plugins/h5p/templates/modal.mustache | 167 +++++++++++++++ lib/editor/tiny/plugins/h5p/version.php | 29 +++ 37 files changed, 1045 insertions(+) create mode 100644 lib/editor/tiny/plugins/h5p/amd/build/commands.min.js create mode 100644 lib/editor/tiny/plugins/h5p/amd/build/commands.min.js.map create mode 100644 lib/editor/tiny/plugins/h5p/amd/build/common.min.js create mode 100644 lib/editor/tiny/plugins/h5p/amd/build/common.min.js.map create mode 100644 lib/editor/tiny/plugins/h5p/amd/build/configuration.min.js create mode 100644 lib/editor/tiny/plugins/h5p/amd/build/configuration.min.js.map create mode 100644 lib/editor/tiny/plugins/h5p/amd/build/filtercontent.min.js create mode 100644 lib/editor/tiny/plugins/h5p/amd/build/filtercontent.min.js.map create mode 100644 lib/editor/tiny/plugins/h5p/amd/build/modal.min.js create mode 100644 lib/editor/tiny/plugins/h5p/amd/build/modal.min.js.map create mode 100644 lib/editor/tiny/plugins/h5p/amd/build/options.min.js create mode 100644 lib/editor/tiny/plugins/h5p/amd/build/options.min.js.map create mode 100644 lib/editor/tiny/plugins/h5p/amd/build/plugin.min.js create mode 100644 lib/editor/tiny/plugins/h5p/amd/build/plugin.min.js.map create mode 100644 lib/editor/tiny/plugins/h5p/amd/build/ui.min.js create mode 100644 lib/editor/tiny/plugins/h5p/amd/build/ui.min.js.map create mode 100644 lib/editor/tiny/plugins/h5p/amd/src/commands.js create mode 100644 lib/editor/tiny/plugins/h5p/amd/src/common.js create mode 100644 lib/editor/tiny/plugins/h5p/amd/src/configuration.js create mode 100644 lib/editor/tiny/plugins/h5p/amd/src/filtercontent.js create mode 100644 lib/editor/tiny/plugins/h5p/amd/src/modal.js create mode 100644 lib/editor/tiny/plugins/h5p/amd/src/options.js create mode 100644 lib/editor/tiny/plugins/h5p/amd/src/plugin.js create mode 100644 lib/editor/tiny/plugins/h5p/amd/src/ui.js create mode 100644 lib/editor/tiny/plugins/h5p/classes/plugininfo.php create mode 100644 lib/editor/tiny/plugins/h5p/classes/privacy/provider.php create mode 100644 lib/editor/tiny/plugins/h5p/db/access.php create mode 100644 lib/editor/tiny/plugins/h5p/editor_styles.css create mode 100644 lib/editor/tiny/plugins/h5p/lang/en/tiny_h5p.php create mode 100644 lib/editor/tiny/plugins/h5p/pix/icon-white.png create mode 100644 lib/editor/tiny/plugins/h5p/pix/icon-white.svg create mode 100644 lib/editor/tiny/plugins/h5p/pix/icon.png create mode 100644 lib/editor/tiny/plugins/h5p/pix/icon.svg create mode 100644 lib/editor/tiny/plugins/h5p/templates/content.mustache create mode 100644 lib/editor/tiny/plugins/h5p/templates/modal.mustache create mode 100644 lib/editor/tiny/plugins/h5p/version.php diff --git a/lib/classes/plugin_manager.php b/lib/classes/plugin_manager.php index 727e5694385..92079d2fe8b 100644 --- a/lib/classes/plugin_manager.php +++ b/lib/classes/plugin_manager.php @@ -2029,6 +2029,7 @@ class core_plugin_manager { ), 'tiny' => [ + 'h5p', ], 'tinymce' => array( diff --git a/lib/editor/tiny/plugins/h5p/amd/build/commands.min.js b/lib/editor/tiny/plugins/h5p/amd/build/commands.min.js new file mode 100644 index 00000000000..89ae0b09c20 --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/amd/build/commands.min.js @@ -0,0 +1,3 @@ +define("tiny_h5p/commands",["exports","editor_tiny/utils","./ui","core/str","./common"],(function(_exports,_utils,_ui,_str,_common){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.getSetup=void 0;_exports.getSetup=async()=>{const[buttonText,buttonImage]=await Promise.all([(0,_str.get_string)("buttontitle",_common.component),(0,_utils.getButtonImage)("icon",_common.component)]);return editor=>{editor.ui.registry.addIcon(_common.icon,buttonImage.html),editor.ui.registry.addToggleButton(_common.buttonName,{icon:_common.icon,tooltip:buttonText,onAction:()=>(0,_ui.handleAction)(editor),onSetup:api=>{api.setActive(editor.formatter.match("h5p"));const changed=editor.formatter.formatChanged("h5p",(state=>api.setActive(state)));return()=>changed.unbind()}}),editor.ui.registry.addMenuItem(_common.buttonName,{icon:_common.icon,text:buttonText,onAction:()=>(0,_ui.handleAction)(editor)})}}})); + +//# sourceMappingURL=commands.min.js.map \ No newline at end of file diff --git a/lib/editor/tiny/plugins/h5p/amd/build/commands.min.js.map b/lib/editor/tiny/plugins/h5p/amd/build/commands.min.js.map new file mode 100644 index 00000000000..fd2305c7fa0 --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/amd/build/commands.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"commands.min.js","sources":["../src/commands.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 * Tiny H5P Content configuration.\n *\n * @module tiny_h5p/commands\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {getButtonImage} from 'editor_tiny/utils';\nimport {handleAction} from './ui';\nimport {get_string as getString} from 'core/str';\nimport {\n component,\n buttonName,\n icon,\n} from './common';\n\nexport const getSetup = async() => {\n const [\n buttonText,\n buttonImage,\n ] = await Promise.all([\n getString('buttontitle', component),\n getButtonImage('icon', component),\n ]);\n\n return (editor) => {\n // Register the H5P Icon.\n editor.ui.registry.addIcon(icon, buttonImage.html);\n\n // Register the Menu Button as a toggle.\n // This means that when highlighted over an existing H5P element it will show as toggled on.\n editor.ui.registry.addToggleButton(buttonName, {\n icon,\n tooltip: buttonText,\n onAction: () => handleAction(editor),\n onSetup: (api) => {\n // Set the button to be active if the current selection matches the h5p formatter registered above during PreInit.\n api.setActive(editor.formatter.match('h5p'));\n const changed = editor.formatter.formatChanged('h5p', (state) => api.setActive(state));\n return () => changed.unbind();\n },\n });\n\n // Add the H5P Menu Item.\n // This allows it to be added to a standard menu, or a context menu.\n editor.ui.registry.addMenuItem(buttonName, {\n icon,\n text: buttonText,\n onAction: () => handleAction(editor),\n });\n };\n};\n"],"names":["async","buttonText","buttonImage","Promise","all","component","editor","ui","registry","addIcon","icon","html","addToggleButton","buttonName","tooltip","onAction","onSetup","api","setActive","formatter","match","changed","formatChanged","state","unbind","addMenuItem","text"],"mappings":"uOAgCwBA,gBAEhBC,WACAC,mBACMC,QAAQC,IAAI,EAClB,mBAAU,cAAeC,oBACzB,yBAAe,OAAQA,4BAGnBC,SAEJA,OAAOC,GAAGC,SAASC,QAAQC,aAAMR,YAAYS,MAI7CL,OAAOC,GAAGC,SAASI,gBAAgBC,mBAAY,CAC3CH,KAAAA,aACAI,QAASb,WACTc,SAAU,KAAM,oBAAaT,QAC7BU,QAAUC,MAENA,IAAIC,UAAUZ,OAAOa,UAAUC,MAAM,cAC/BC,QAAUf,OAAOa,UAAUG,cAAc,OAAQC,OAAUN,IAAIC,UAAUK,eACxE,IAAMF,QAAQG,YAM7BlB,OAAOC,GAAGC,SAASiB,YAAYZ,mBAAY,CACvCH,KAAAA,aACAgB,KAAMzB,WACNc,SAAU,KAAM,oBAAaT"} \ No newline at end of file diff --git a/lib/editor/tiny/plugins/h5p/amd/build/common.min.js b/lib/editor/tiny/plugins/h5p/amd/build/common.min.js new file mode 100644 index 00000000000..0e5d22803a8 --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/amd/build/common.min.js @@ -0,0 +1,3 @@ +define("tiny_h5p/common",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0;return _exports.default={pluginName:"tiny_h5p/plugin",component:"tiny_h5p",buttonName:"tiny_h5p",icon:"tiny_h5p"},_exports.default})); + +//# sourceMappingURL=common.min.js.map \ No newline at end of file diff --git a/lib/editor/tiny/plugins/h5p/amd/build/common.min.js.map b/lib/editor/tiny/plugins/h5p/amd/build/common.min.js.map new file mode 100644 index 00000000000..ff892befb84 --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/amd/build/common.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"common.min.js","sources":["../src/common.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 * Tiny H5P Common values.\n *\n * @module tiny_h5p/common\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nexport default {\n pluginName: 'tiny_h5p/plugin',\n component: 'tiny_h5p',\n buttonName: 'tiny_h5p',\n icon: 'tiny_h5p',\n};\n"],"names":["pluginName","component","buttonName","icon"],"mappings":"iKAuBe,CACXA,WAAY,kBACZC,UAAW,WACXC,WAAY,WACZC,KAAM"} \ No newline at end of file diff --git a/lib/editor/tiny/plugins/h5p/amd/build/configuration.min.js b/lib/editor/tiny/plugins/h5p/amd/build/configuration.min.js new file mode 100644 index 00000000000..28f82582890 --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/amd/build/configuration.min.js @@ -0,0 +1,3 @@ +define("tiny_h5p/configuration",["exports","./common","editor_tiny/utils"],(function(_exports,_common,_utils){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.configure=void 0;_exports.configure=instanceConfig=>({toolbar:(0,_utils.addToolbarButton)(instanceConfig.toolbar,"content",_common.component),menu:(0,_utils.addMenubarItem)(instanceConfig.menu,"insert",_common.component)})})); + +//# sourceMappingURL=configuration.min.js.map \ No newline at end of file diff --git a/lib/editor/tiny/plugins/h5p/amd/build/configuration.min.js.map b/lib/editor/tiny/plugins/h5p/amd/build/configuration.min.js.map new file mode 100644 index 00000000000..98016c9056e --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/amd/build/configuration.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"configuration.min.js","sources":["../src/configuration.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 * Tiny H5P Content configuration.\n *\n * @module tiny_h5p/configuration\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {component as buttonName} from './common';\nimport {\n addMenubarItem,\n addToolbarButton,\n} from 'editor_tiny/utils';\n\nexport const configure = (instanceConfig) => {\n // Update the instance configuration to add the H5P menu option to the menus and toolbars.\n return {\n toolbar: addToolbarButton(instanceConfig.toolbar, 'content', buttonName),\n menu: addMenubarItem(instanceConfig.menu, 'insert', buttonName),\n };\n};\n"],"names":["instanceConfig","toolbar","buttonName","menu"],"mappings":"mNA6B0BA,iBAEf,CACHC,SAAS,2BAAiBD,eAAeC,QAAS,UAAWC,mBAC7DC,MAAM,yBAAeH,eAAeG,KAAM,SAAUD"} \ No newline at end of file diff --git a/lib/editor/tiny/plugins/h5p/amd/build/filtercontent.min.js b/lib/editor/tiny/plugins/h5p/amd/build/filtercontent.min.js new file mode 100644 index 00000000000..8078589c5be --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/amd/build/filtercontent.min.js @@ -0,0 +1,3 @@ +define("tiny_h5p/filtercontent",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.setup=void 0;_exports.setup=async editor=>{editor.on("PreInit",(()=>{editor.formatter.register("h5p",{inline:"div",classes:"h5p-placeholder"})})),editor.on("SetContent",(()=>{editor.getBody().querySelectorAll(".h5p-placeholder:not([contenteditable])").forEach((node=>{node.contentEditable=!1}))}))}})); + +//# sourceMappingURL=filtercontent.min.js.map \ No newline at end of file diff --git a/lib/editor/tiny/plugins/h5p/amd/build/filtercontent.min.js.map b/lib/editor/tiny/plugins/h5p/amd/build/filtercontent.min.js.map new file mode 100644 index 00000000000..f2cb6c50b9b --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/amd/build/filtercontent.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"filtercontent.min.js","sources":["../src/filtercontent.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 * Tiny H5P Content configuration.\n *\n * @module tiny_h5p/filtercontent\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nexport const setup = async(editor) => {\n // Register the H5P Formatter for use in all buttons.\n editor.on('PreInit', () => {\n editor.formatter.register('h5p', {\n inline: 'div',\n classes: 'h5p-placeholder',\n });\n });\n\n editor.on('SetContent', () => {\n // Listen to the SetContent event on the editor and update any h5p-placeholder to not be editable.\n // Doing this means that the inner content of the placeholder cannot be changed without using the dialogue.\n // The SetContent event is called whenever content is changed by actions such as initial load, paste, undo, etc.\n editor.getBody().querySelectorAll('.h5p-placeholder:not([contenteditable])').forEach((node) => {\n node.contentEditable = false;\n });\n });\n};\n"],"names":["async","editor","on","formatter","register","inline","classes","getBody","querySelectorAll","forEach","node","contentEditable"],"mappings":"6JAuBqBA,MAAAA,SAEjBC,OAAOC,GAAG,WAAW,KACjBD,OAAOE,UAAUC,SAAS,MAAO,CAC7BC,OAAQ,MACRC,QAAS,uBAIjBL,OAAOC,GAAG,cAAc,KAIpBD,OAAOM,UAAUC,iBAAiB,2CAA2CC,SAASC,OAClFA,KAAKC,iBAAkB"} \ No newline at end of file diff --git a/lib/editor/tiny/plugins/h5p/amd/build/modal.min.js b/lib/editor/tiny/plugins/h5p/amd/build/modal.min.js new file mode 100644 index 00000000000..cc5ef830e94 --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/amd/build/modal.min.js @@ -0,0 +1,3 @@ +define("tiny_h5p/modal",["exports","core/modal","core/modal_registry"],(function(_exports,_modal,_modal_registry){var _class;function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _defineProperty(obj,key,value){return key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,obj}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_modal=_interopRequireDefault(_modal),_modal_registry=_interopRequireDefault(_modal_registry);const H5PModal=(_defineProperty(_class=class extends _modal.default{registerEventListeners(){super.registerEventListeners(),this.registerCloseOnSave(),this.registerCloseOnCancel()}},"TYPE","tiny_h5p/modal"),_defineProperty(_class,"TEMPLATE","tiny_h5p/modal"),_class);_modal_registry.default.register(H5PModal.TYPE,H5PModal,H5PModal.TEMPLATE);var _default=H5PModal;return _exports.default=_default,_exports.default})); + +//# sourceMappingURL=modal.min.js.map \ No newline at end of file diff --git a/lib/editor/tiny/plugins/h5p/amd/build/modal.min.js.map b/lib/editor/tiny/plugins/h5p/amd/build/modal.min.js.map new file mode 100644 index 00000000000..0a082c4bb03 --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/amd/build/modal.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"modal.min.js","sources":["../src/modal.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 * H5P Management Modal for Tiny.\n *\n * @module tiny_h5p/modal\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Modal from 'core/modal';\nimport ModalRegistry from 'core/modal_registry';\n\nconst H5PModal = class extends Modal {\n static TYPE = 'tiny_h5p/modal';\n\n static TEMPLATE = 'tiny_h5p/modal';\n\n registerEventListeners() {\n // Call the parent registration.\n super.registerEventListeners();\n\n // Register to close on save/cancel.\n this.registerCloseOnSave();\n this.registerCloseOnCancel();\n }\n};\n\nModalRegistry.register(H5PModal.TYPE, H5PModal, H5PModal.TEMPLATE);\n\nexport default H5PModal;\n"],"names":["H5PModal","Modal","registerEventListeners","registerCloseOnSave","registerCloseOnCancel","register","TYPE","TEMPLATE"],"mappings":"uiBA0BMA,iCAAW,cAAcC,eAK3BC,+BAEUA,8BAGDC,2BACAC,iCAVK,oDAEI,kDAYRC,SAASL,SAASM,KAAMN,SAAUA,SAASO,uBAE1CP"} \ No newline at end of file diff --git a/lib/editor/tiny/plugins/h5p/amd/build/options.min.js b/lib/editor/tiny/plugins/h5p/amd/build/options.min.js new file mode 100644 index 00000000000..52511a008c3 --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/amd/build/options.min.js @@ -0,0 +1,11 @@ +define("tiny_h5p/options",["exports","editor_tiny/options","./common"],(function(_exports,_options,_common){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.register=_exports.getPermissions=void 0; +/** + * Options helper for Tiny H5P plugin. + * + * @module tiny_h5p/options + * @copyright 2022 Andrew Lyons + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +const permissionsName=(0,_options.getPluginOptionName)(_common.pluginName,"permissions");_exports.register=editor=>{(0,editor.options.register)(permissionsName,{processor:"object",default:{upload:!1,embed:!1}})};_exports.getPermissions=editor=>editor.options.get(permissionsName)})); + +//# sourceMappingURL=options.min.js.map \ No newline at end of file diff --git a/lib/editor/tiny/plugins/h5p/amd/build/options.min.js.map b/lib/editor/tiny/plugins/h5p/amd/build/options.min.js.map new file mode 100644 index 00000000000..d2346ff9373 --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/amd/build/options.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"options.min.js","sources":["../src/options.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 * Options helper for Tiny H5P plugin.\n *\n * @module tiny_h5p/options\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {getPluginOptionName} from 'editor_tiny/options';\nimport {pluginName} from './common';\n\nconst permissionsName = getPluginOptionName(pluginName, 'permissions');\n\n/**\n * Register the options for the Tiny H5P plugin.\n *\n * @param {TinyMCE} editor\n */\nexport const register = (editor) => {\n const registerOption = editor.options.register;\n\n registerOption(permissionsName, {\n processor: 'object',\n \"default\": {\n upload: false,\n embed: false,\n },\n });\n};\n\n/**\n * Get the permissions configuration for the Tiny H5P plugin.\n *\n * @param {TinyMCE} editor\n * @returns {object}\n */\nexport const getPermissions = (editor) => editor.options.get(permissionsName);\n"],"names":["permissionsName","pluginName","editor","registerOption","options","register","processor","upload","embed","get"],"mappings":";;;;;;;;MA0BMA,iBAAkB,gCAAoBC,mBAAY,iCAO/BC,UAGrBC,EAFuBD,OAAOE,QAAQC,UAEvBL,gBAAiB,CAC5BM,UAAW,iBACA,CACPC,QAAQ,EACRC,OAAO,8BAWYN,QAAWA,OAAOE,QAAQK,IAAIT"} \ No newline at end of file diff --git a/lib/editor/tiny/plugins/h5p/amd/build/plugin.min.js b/lib/editor/tiny/plugins/h5p/amd/build/plugin.min.js new file mode 100644 index 00000000000..2a4e8972b59 --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/amd/build/plugin.min.js @@ -0,0 +1,10 @@ +define("tiny_h5p/plugin",["exports","editor_tiny/loader","editor_tiny/utils","./common","./filtercontent","./commands","./configuration","./options"],(function(_exports,_loader,_utils,_common,FilterContent,Commands,Configuration,Options){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj} +/** + * Tiny H5P plugin for Moodle. + * + * @module tiny_h5p/plugin + * @copyright 2022 Andrew Lyons + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,FilterContent=_interopRequireWildcard(FilterContent),Commands=_interopRequireWildcard(Commands),Configuration=_interopRequireWildcard(Configuration),Options=_interopRequireWildcard(Options);var _default=new Promise((async resolve=>{const[tinyMCE,setupCommands,pluginMetadata]=await Promise.all([(0,_loader.getTinyMCE)(),Commands.getSetup(),(0,_utils.getPluginMetadata)(_common.component,_common.pluginName)]);tinyMCE.PluginManager.add("".concat(_common.component,"/plugin"),(editor=>(Options.register(editor),FilterContent.setup(editor),setupCommands(editor),pluginMetadata))),resolve(["".concat(_common.component,"/plugin"),Configuration])}));return _exports.default=_default,_exports.default})); + +//# sourceMappingURL=plugin.min.js.map \ No newline at end of file diff --git a/lib/editor/tiny/plugins/h5p/amd/build/plugin.min.js.map b/lib/editor/tiny/plugins/h5p/amd/build/plugin.min.js.map new file mode 100644 index 00000000000..caf967b7e4b --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/amd/build/plugin.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"plugin.min.js","sources":["../src/plugin.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 * Tiny H5P plugin for Moodle.\n *\n * @module tiny_h5p/plugin\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {getTinyMCE} from 'editor_tiny/loader';\nimport {getPluginMetadata} from 'editor_tiny/utils';\n\nimport {component, pluginName} from './common';\nimport * as FilterContent from './filtercontent';\nimport * as Commands from './commands';\nimport * as Configuration from './configuration';\nimport * as Options from './options';\n\n// Setup the H5P Plugin to add a button and menu option.\nexport default new Promise(async(resolve) => {\n const [\n tinyMCE,\n setupCommands,\n pluginMetadata,\n ] = await Promise.all([\n getTinyMCE(),\n Commands.getSetup(),\n getPluginMetadata(component, pluginName),\n ]);\n\n // Note: The PluginManager.add function does not accept a Promise.\n // Any asynchronous code must be run before this point.\n tinyMCE.PluginManager.add(`${component}/plugin`, (editor) => {\n // Register options.\n Options.register(editor);\n\n // Setup the Formatter.\n FilterContent.setup(editor);\n\n // Setup the Commands (buttons, menu items, and so on).\n setupCommands(editor);\n\n return pluginMetadata;\n });\n\n // Resolve the H5P Plugin and include configuration.\n resolve([`${component}/plugin`, Configuration]);\n});\n"],"names":["Promise","async","tinyMCE","setupCommands","pluginMetadata","all","Commands","getSetup","component","pluginName","PluginManager","add","editor","Options","register","FilterContent","setup","resolve","Configuration"],"mappings":";;;;;;;gSAgCe,IAAIA,SAAQC,MAAAA,gBAEnBC,QACAC,cACAC,sBACMJ,QAAQK,IAAI,EAClB,wBACAC,SAASC,YACT,4BAAkBC,kBAAWC,sBAKjCP,QAAQQ,cAAcC,cAAOH,8BAAqBI,SAE9CC,QAAQC,SAASF,QAGjBG,cAAcC,MAAMJ,QAGpBT,cAAcS,QAEPR,kBAIXa,QAAQ,WAAIT,6BAAoBU"} \ No newline at end of file diff --git a/lib/editor/tiny/plugins/h5p/amd/build/ui.min.js b/lib/editor/tiny/plugins/h5p/amd/build/ui.min.js new file mode 100644 index 00000000000..6e162626d39 --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/amd/build/ui.min.js @@ -0,0 +1,10 @@ +define("tiny_h5p/ui",["exports","editor_tiny/utils","./common","./options","core/normalise","core/templates","tiny_h5p/modal","core/modal_events","core/modal_factory"],(function(_exports,_utils,_common,_options,_normalise,_templates,_modal,_modal_events,_modal_factory){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}} +/** + * Tiny H5P Content configuration. + * + * @module tiny_h5p/commands + * @copyright 2022 Andrew Lyons + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.handleAction=void 0,_modal=_interopRequireDefault(_modal),_modal_events=_interopRequireDefault(_modal_events),_modal_factory=_interopRequireDefault(_modal_factory);let openingSelection=null;_exports.handleAction=editor=>{openingSelection=editor.selection.getBookmark(),displayDialogue(editor)};const getTemplateContext=(editor,data)=>{var _permissions$upload,_permissions$embed,_data$url;const permissions=(0,_options.getPermissions)(editor),canUpload=null!==(_permissions$upload=permissions.upload)&&void 0!==_permissions$upload&&_permissions$upload,canEmbed=null!==(_permissions$embed=permissions.embed)&&void 0!==_permissions$embed&&_permissions$embed,canUploadAndEmbed=canUpload&&canEmbed;return Object.assign({},{elementid:editor.id,canUpload:canUpload,canEmbed:canEmbed,canUploadAndEmbed:canUploadAndEmbed,showOptions:!1,fileURL:null!==(_data$url=null==data?void 0:data.url)&&void 0!==_data$url?_data$url:""},data)},handleDialogueSubmission=async(editor,modal,data)=>{const form=(0,_normalise.getList)(modal.getRoot())[0].querySelector("form");if(!form)return void displayDialogue(editor,Object.assign({},data));const submittedUrl=form.querySelector('input[name="url"]').value,url=((form,submittedUrl,permissions)=>{if(!submittedUrl)return null;const url=new URL(submittedUrl);return null!=permissions&&permissions.upload&&form.querySelector('[name="download"]').checked&&url.searchParams.append("export",1),null!=permissions&&permissions.embed&&form.querySelector('[name="embed"]').checked&&url.searchParams.append("embed",1),form.querySelector('[name="copyright"]').checked&&url.searchParams.append("copyright",1),url})(form,submittedUrl,(0,_options.getPermissions)(editor));if(!url)return void displayDialogue(editor,Object.assign({},data,{url:submittedUrl,invalidUrl:!0}));const content=await(0,_templates.renderForPromise)("".concat(_common.component,"/content"),{url:url.toString()});editor.selection.moveToBookmark(openingSelection),editor.execCommand("mceInsertContent",!1,content.html),editor.selection.moveToBookmark(openingSelection)},getCurrentH5PData=currentH5P=>{const data={};let url;try{url=new URL(currentH5P.textContent)}catch(error){return data}return url.searchParams.has("export")&&(data.download=!0,data.showOptions=!0,url.searchParams.delete("export")),url.searchParams.has("embed")&&(data.embed=!0,data.showOptions=!0,url.searchParams.delete("embed")),url.searchParams.has("copyright")&&(data.copyright=!0,data.showOptions=!0,url.searchParams.delete("copyright")),data.url=url.toString(),data},displayDialogue=async function(editor){let data=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const selection=editor.selection.getNode(),currentH5P=selection.closest(".h5p-placeholder");currentH5P&&Object.assign(data,getCurrentH5PData(currentH5P));const modal=await _modal_factory.default.create({type:_modal.default.TYPE,templateContext:getTemplateContext(editor,data),large:!0});modal.show();const $root=modal.getRoot(),root=$root[0];$root.on(_modal_events.default.save,((event,modal)=>{handleDialogueSubmission(editor,modal,data)})),root.addEventListener("click",(e=>{e.target.closest('[data-target="filepicker"]')&&(0,_utils.displayFilepicker)(editor,"h5p").then((params=>{if(""!==params.url){root.querySelector('form input[name="url"]').value=params.url}return params})).catch()}))}})); + +//# sourceMappingURL=ui.min.js.map \ No newline at end of file diff --git a/lib/editor/tiny/plugins/h5p/amd/build/ui.min.js.map b/lib/editor/tiny/plugins/h5p/amd/build/ui.min.js.map new file mode 100644 index 00000000000..33bfbb9230c --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/amd/build/ui.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ui.min.js","sources":["../src/ui.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 * Tiny H5P Content configuration.\n *\n * @module tiny_h5p/commands\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {displayFilepicker} from 'editor_tiny/utils';\nimport {component} from './common';\nimport {getPermissions} from './options';\n\nimport {getList} from 'core/normalise';\nimport {renderForPromise} from 'core/templates';\nimport Modal from 'tiny_h5p/modal';\nimport ModalEvents from 'core/modal_events';\nimport ModalFactory from 'core/modal_factory';\n\nlet openingSelection = null;\n\nexport const handleAction = (editor) => {\n openingSelection = editor.selection.getBookmark();\n displayDialogue(editor);\n};\n\n/**\n * Get the template context for the dialogue.\n *\n * @param {Editor} editor\n * @param {object} data\n * @returns {object} data\n */\nconst getTemplateContext = (editor, data) => {\n const permissions = getPermissions(editor);\n\n const canUpload = permissions.upload ?? false;\n const canEmbed = permissions.embed ?? false;\n const canUploadAndEmbed = canUpload && canEmbed;\n\n return Object.assign({}, {\n elementid: editor.id,\n canUpload,\n canEmbed,\n canUploadAndEmbed,\n showOptions: false,\n fileURL: data?.url ?? '',\n }, data);\n};\n\n/**\n * Get the URL from the submitted form.\n *\n * @param {FormNode} form\n * @param {string} submittedUrl\n * @param {object} permissions\n * @returns {URL|null}\n */\nconst getUrlFromSubmission = (form, submittedUrl, permissions) => {\n if (!submittedUrl) {\n return null;\n }\n\n // Generate a URL Object for the submitted URL.\n const url = new URL(submittedUrl);\n\n if (permissions?.upload) {\n if (form.querySelector('[name=\"download\"]').checked) {\n url.searchParams.append('export', 1);\n }\n }\n\n if (permissions?.embed) {\n if (form.querySelector('[name=\"embed\"]').checked) {\n url.searchParams.append('embed', 1);\n }\n }\n if (form.querySelector('[name=\"copyright\"]').checked) {\n url.searchParams.append('copyright', 1);\n }\n\n return url;\n};\n\nconst handleDialogueSubmission = async(editor, modal, data) => {\n const form = getList(modal.getRoot())[0].querySelector('form');\n if (!form) {\n // The form couldn't be found, which is weird.\n // This should not happen.\n // Display the dialogue again\n displayDialogue(editor, Object.assign({}, data));\n return;\n }\n\n // Get the URL from the submitted form.\n const submittedUrl = form.querySelector('input[name=\"url\"]').value;\n const url = getUrlFromSubmission(form, submittedUrl, getPermissions(editor));\n\n if (!url) {\n // The URL is invalid.\n // Fill it in and represent the dialogue with an error.\n displayDialogue(editor, Object.assign({}, data, {\n url: submittedUrl,\n invalidUrl: true,\n }));\n return;\n }\n\n\n const content = await renderForPromise(`${component}/content`, {\n url: url.toString(),\n });\n\n editor.selection.moveToBookmark(openingSelection);\n editor.execCommand('mceInsertContent', false, content.html);\n editor.selection.moveToBookmark(openingSelection);\n};\n\nconst getCurrentH5PData = (currentH5P) => {\n const data = {};\n let url;\n try {\n url = new URL(currentH5P.textContent);\n } catch (error) {\n return data;\n }\n\n if (url.searchParams.has('export')) {\n data.download = true;\n data.showOptions = true;\n url.searchParams.delete('export');\n }\n\n if (url.searchParams.has('embed')) {\n data.embed = true;\n data.showOptions = true;\n url.searchParams.delete('embed');\n }\n\n if (url.searchParams.has('copyright')) {\n data.copyright = true;\n data.showOptions = true;\n url.searchParams.delete('copyright');\n }\n\n data.url = url.toString();\n\n return data;\n};\n\nconst displayDialogue = async(editor, data = {}) => {\n const selection = editor.selection.getNode();\n const currentH5P = selection.closest('.h5p-placeholder');\n if (currentH5P) {\n Object.assign(data, getCurrentH5PData(currentH5P));\n }\n\n const modal = await ModalFactory.create({\n type: Modal.TYPE,\n templateContext: getTemplateContext(editor, data),\n large: true,\n });\n modal.show();\n\n const $root = modal.getRoot();\n const root = $root[0];\n $root.on(ModalEvents.save, (event, modal) => {\n handleDialogueSubmission(editor, modal, data);\n });\n\n root.addEventListener('click', (e) => {\n const filepickerButton = e.target.closest('[data-target=\"filepicker\"]');\n if (filepickerButton) {\n displayFilepicker(editor, 'h5p').then((params) => {\n if (params.url !== '') {\n const input = root.querySelector('form input[name=\"url\"]');\n input.value = params.url;\n }\n return params;\n })\n .catch();\n }\n });\n};\n"],"names":["openingSelection","editor","selection","getBookmark","displayDialogue","getTemplateContext","data","permissions","canUpload","upload","canEmbed","embed","canUploadAndEmbed","Object","assign","elementid","id","showOptions","fileURL","url","handleDialogueSubmission","async","modal","form","getRoot","querySelector","submittedUrl","value","URL","checked","searchParams","append","getUrlFromSubmission","invalidUrl","content","component","toString","moveToBookmark","execCommand","html","getCurrentH5PData","currentH5P","textContent","error","has","download","delete","copyright","getNode","closest","ModalFactory","create","type","Modal","TYPE","templateContext","large","show","$root","root","on","ModalEvents","save","event","addEventListener","e","target","then","params","catch"],"mappings":";;;;;;;8OAiCIA,iBAAmB,2BAEMC,SACzBD,iBAAmBC,OAAOC,UAAUC,cACpCC,gBAAgBH,eAUdI,mBAAqB,CAACJ,OAAQK,mEAC1BC,aAAc,2BAAeN,QAE7BO,sCAAYD,YAAYE,2DACxBC,oCAAWH,YAAYI,wDACvBC,kBAAoBJ,WAAaE,gBAEhCG,OAAOC,OAAO,GAAI,CACrBC,UAAWd,OAAOe,GAClBR,UAAAA,UACAE,SAAAA,SACAE,kBAAAA,kBACAK,aAAa,EACbC,0BAASZ,MAAAA,YAAAA,KAAMa,mCAAO,IACvBb,OAqCDc,yBAA2BC,MAAMpB,OAAQqB,MAAOhB,cAC5CiB,MAAO,sBAAQD,MAAME,WAAW,GAAGC,cAAc,YAClDF,iBAIDnB,gBAAgBH,OAAQY,OAAOC,OAAO,GAAIR,aAKxCoB,aAAeH,KAAKE,cAAc,qBAAqBE,MACvDR,IAtCmB,EAACI,KAAMG,aAAcnB,mBACzCmB,oBACM,WAILP,IAAM,IAAIS,IAAIF,qBAEhBnB,MAAAA,aAAAA,YAAaE,QACTc,KAAKE,cAAc,qBAAqBI,SACxCV,IAAIW,aAAaC,OAAO,SAAU,GAItCxB,MAAAA,aAAAA,YAAaI,OACTY,KAAKE,cAAc,kBAAkBI,SACrCV,IAAIW,aAAaC,OAAO,QAAS,GAGrCR,KAAKE,cAAc,sBAAsBI,SACzCV,IAAIW,aAAaC,OAAO,YAAa,GAGlCZ,KAeKa,CAAqBT,KAAMG,cAAc,2BAAezB,aAE/DkB,gBAGDf,gBAAgBH,OAAQY,OAAOC,OAAO,GAAIR,KAAM,CAC5Ca,IAAKO,aACLO,YAAY,WAMdC,cAAgB,yCAAoBC,8BAAqB,CAC3DhB,IAAKA,IAAIiB,aAGbnC,OAAOC,UAAUmC,eAAerC,kBAChCC,OAAOqC,YAAY,oBAAoB,EAAOJ,QAAQK,MACtDtC,OAAOC,UAAUmC,eAAerC,mBAG9BwC,kBAAqBC,mBACjBnC,KAAO,OACTa,QAEAA,IAAM,IAAIS,IAAIa,WAAWC,aAC3B,MAAOC,cACErC,YAGPa,IAAIW,aAAac,IAAI,YACrBtC,KAAKuC,UAAW,EAChBvC,KAAKW,aAAc,EACnBE,IAAIW,aAAagB,OAAO,WAGxB3B,IAAIW,aAAac,IAAI,WACrBtC,KAAKK,OAAQ,EACbL,KAAKW,aAAc,EACnBE,IAAIW,aAAagB,OAAO,UAGxB3B,IAAIW,aAAac,IAAI,eACrBtC,KAAKyC,WAAY,EACjBzC,KAAKW,aAAc,EACnBE,IAAIW,aAAagB,OAAO,cAG5BxC,KAAKa,IAAMA,IAAIiB,WAER9B,MAGLF,gBAAkBiB,eAAMpB,YAAQK,4DAAO,SACnCJ,UAAYD,OAAOC,UAAU8C,UAC7BP,WAAavC,UAAU+C,QAAQ,oBACjCR,YACA5B,OAAOC,OAAOR,KAAMkC,kBAAkBC,mBAGpCnB,YAAc4B,uBAAaC,OAAO,CACpCC,KAAMC,eAAMC,KACZC,gBAAiBlD,mBAAmBJ,OAAQK,MAC5CkD,OAAO,IAEXlC,MAAMmC,aAEAC,MAAQpC,MAAME,UACdmC,KAAOD,MAAM,GACnBA,MAAME,GAAGC,sBAAYC,MAAM,CAACC,MAAOzC,SAC/BF,yBAAyBnB,OAAQqB,MAAOhB,SAG5CqD,KAAKK,iBAAiB,SAAUC,IACHA,EAAEC,OAAOjB,QAAQ,4DAEpBhD,OAAQ,OAAOkE,MAAMC,YAChB,KAAfA,OAAOjD,IAAY,CACLwC,KAAKlC,cAAc,0BAC3BE,MAAQyC,OAAOjD,WAElBiD,UAENC"} \ No newline at end of file diff --git a/lib/editor/tiny/plugins/h5p/amd/src/commands.js b/lib/editor/tiny/plugins/h5p/amd/src/commands.js new file mode 100644 index 00000000000..4c487525491 --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/amd/src/commands.js @@ -0,0 +1,68 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Tiny H5P Content configuration. + * + * @module tiny_h5p/commands + * @copyright 2022 Andrew Lyons + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import {getButtonImage} from 'editor_tiny/utils'; +import {handleAction} from './ui'; +import {get_string as getString} from 'core/str'; +import { + component, + buttonName, + icon, +} from './common'; + +export const getSetup = async() => { + const [ + buttonText, + buttonImage, + ] = await Promise.all([ + getString('buttontitle', component), + getButtonImage('icon', component), + ]); + + return (editor) => { + // Register the H5P Icon. + editor.ui.registry.addIcon(icon, buttonImage.html); + + // Register the Menu Button as a toggle. + // This means that when highlighted over an existing H5P element it will show as toggled on. + editor.ui.registry.addToggleButton(buttonName, { + icon, + tooltip: buttonText, + onAction: () => handleAction(editor), + onSetup: (api) => { + // Set the button to be active if the current selection matches the h5p formatter registered above during PreInit. + api.setActive(editor.formatter.match('h5p')); + const changed = editor.formatter.formatChanged('h5p', (state) => api.setActive(state)); + return () => changed.unbind(); + }, + }); + + // Add the H5P Menu Item. + // This allows it to be added to a standard menu, or a context menu. + editor.ui.registry.addMenuItem(buttonName, { + icon, + text: buttonText, + onAction: () => handleAction(editor), + }); + }; +}; diff --git a/lib/editor/tiny/plugins/h5p/amd/src/common.js b/lib/editor/tiny/plugins/h5p/amd/src/common.js new file mode 100644 index 00000000000..040545ace20 --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/amd/src/common.js @@ -0,0 +1,29 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Tiny H5P Common values. + * + * @module tiny_h5p/common + * @copyright 2022 Andrew Lyons + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +export default { + pluginName: 'tiny_h5p/plugin', + component: 'tiny_h5p', + buttonName: 'tiny_h5p', + icon: 'tiny_h5p', +}; diff --git a/lib/editor/tiny/plugins/h5p/amd/src/configuration.js b/lib/editor/tiny/plugins/h5p/amd/src/configuration.js new file mode 100644 index 00000000000..0d2a91372e4 --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/amd/src/configuration.js @@ -0,0 +1,36 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Tiny H5P Content configuration. + * + * @module tiny_h5p/configuration + * @copyright 2022 Andrew Lyons + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import {component as buttonName} from './common'; +import { + addMenubarItem, + addToolbarButton, +} from 'editor_tiny/utils'; + +export const configure = (instanceConfig) => { + // Update the instance configuration to add the H5P menu option to the menus and toolbars. + return { + toolbar: addToolbarButton(instanceConfig.toolbar, 'content', buttonName), + menu: addMenubarItem(instanceConfig.menu, 'insert', buttonName), + }; +}; diff --git a/lib/editor/tiny/plugins/h5p/amd/src/filtercontent.js b/lib/editor/tiny/plugins/h5p/amd/src/filtercontent.js new file mode 100644 index 00000000000..69f35cbdc15 --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/amd/src/filtercontent.js @@ -0,0 +1,41 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Tiny H5P Content configuration. + * + * @module tiny_h5p/filtercontent + * @copyright 2022 Andrew Lyons + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +export const setup = async(editor) => { + // Register the H5P Formatter for use in all buttons. + editor.on('PreInit', () => { + editor.formatter.register('h5p', { + inline: 'div', + classes: 'h5p-placeholder', + }); + }); + + editor.on('SetContent', () => { + // Listen to the SetContent event on the editor and update any h5p-placeholder to not be editable. + // Doing this means that the inner content of the placeholder cannot be changed without using the dialogue. + // The SetContent event is called whenever content is changed by actions such as initial load, paste, undo, etc. + editor.getBody().querySelectorAll('.h5p-placeholder:not([contenteditable])').forEach((node) => { + node.contentEditable = false; + }); + }); +}; diff --git a/lib/editor/tiny/plugins/h5p/amd/src/modal.js b/lib/editor/tiny/plugins/h5p/amd/src/modal.js new file mode 100644 index 00000000000..e3798a5bdf8 --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/amd/src/modal.js @@ -0,0 +1,44 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * H5P Management Modal for Tiny. + * + * @module tiny_h5p/modal + * @copyright 2022 Andrew Lyons + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import Modal from 'core/modal'; +import ModalRegistry from 'core/modal_registry'; + +const H5PModal = class extends Modal { + static TYPE = 'tiny_h5p/modal'; + + static TEMPLATE = 'tiny_h5p/modal'; + + registerEventListeners() { + // Call the parent registration. + super.registerEventListeners(); + + // Register to close on save/cancel. + this.registerCloseOnSave(); + this.registerCloseOnCancel(); + } +}; + +ModalRegistry.register(H5PModal.TYPE, H5PModal, H5PModal.TEMPLATE); + +export default H5PModal; diff --git a/lib/editor/tiny/plugins/h5p/amd/src/options.js b/lib/editor/tiny/plugins/h5p/amd/src/options.js new file mode 100644 index 00000000000..8a32b20909f --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/amd/src/options.js @@ -0,0 +1,52 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Options helper for Tiny H5P plugin. + * + * @module tiny_h5p/options + * @copyright 2022 Andrew Lyons + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import {getPluginOptionName} from 'editor_tiny/options'; +import {pluginName} from './common'; + +const permissionsName = getPluginOptionName(pluginName, 'permissions'); + +/** + * Register the options for the Tiny H5P plugin. + * + * @param {TinyMCE} editor + */ +export const register = (editor) => { + const registerOption = editor.options.register; + + registerOption(permissionsName, { + processor: 'object', + "default": { + upload: false, + embed: false, + }, + }); +}; + +/** + * Get the permissions configuration for the Tiny H5P plugin. + * + * @param {TinyMCE} editor + * @returns {object} + */ +export const getPermissions = (editor) => editor.options.get(permissionsName); diff --git a/lib/editor/tiny/plugins/h5p/amd/src/plugin.js b/lib/editor/tiny/plugins/h5p/amd/src/plugin.js new file mode 100644 index 00000000000..68450d4b10a --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/amd/src/plugin.js @@ -0,0 +1,61 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Tiny H5P plugin for Moodle. + * + * @module tiny_h5p/plugin + * @copyright 2022 Andrew Lyons + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +import {getTinyMCE} from 'editor_tiny/loader'; +import {getPluginMetadata} from 'editor_tiny/utils'; + +import {component, pluginName} from './common'; +import * as FilterContent from './filtercontent'; +import * as Commands from './commands'; +import * as Configuration from './configuration'; +import * as Options from './options'; + +// Setup the H5P Plugin to add a button and menu option. +export default new Promise(async(resolve) => { + const [ + tinyMCE, + setupCommands, + pluginMetadata, + ] = await Promise.all([ + getTinyMCE(), + Commands.getSetup(), + getPluginMetadata(component, pluginName), + ]); + + // Note: The PluginManager.add function does not accept a Promise. + // Any asynchronous code must be run before this point. + tinyMCE.PluginManager.add(`${component}/plugin`, (editor) => { + // Register options. + Options.register(editor); + + // Setup the Formatter. + FilterContent.setup(editor); + + // Setup the Commands (buttons, menu items, and so on). + setupCommands(editor); + + return pluginMetadata; + }); + + // Resolve the H5P Plugin and include configuration. + resolve([`${component}/plugin`, Configuration]); +}); diff --git a/lib/editor/tiny/plugins/h5p/amd/src/ui.js b/lib/editor/tiny/plugins/h5p/amd/src/ui.js new file mode 100644 index 00000000000..b72b1d9c065 --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/amd/src/ui.js @@ -0,0 +1,198 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Tiny H5P Content configuration. + * + * @module tiny_h5p/commands + * @copyright 2022 Andrew Lyons + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import {displayFilepicker} from 'editor_tiny/utils'; +import {component} from './common'; +import {getPermissions} from './options'; + +import {getList} from 'core/normalise'; +import {renderForPromise} from 'core/templates'; +import Modal from 'tiny_h5p/modal'; +import ModalEvents from 'core/modal_events'; +import ModalFactory from 'core/modal_factory'; + +let openingSelection = null; + +export const handleAction = (editor) => { + openingSelection = editor.selection.getBookmark(); + displayDialogue(editor); +}; + +/** + * Get the template context for the dialogue. + * + * @param {Editor} editor + * @param {object} data + * @returns {object} data + */ +const getTemplateContext = (editor, data) => { + const permissions = getPermissions(editor); + + const canUpload = permissions.upload ?? false; + const canEmbed = permissions.embed ?? false; + const canUploadAndEmbed = canUpload && canEmbed; + + return Object.assign({}, { + elementid: editor.id, + canUpload, + canEmbed, + canUploadAndEmbed, + showOptions: false, + fileURL: data?.url ?? '', + }, data); +}; + +/** + * Get the URL from the submitted form. + * + * @param {FormNode} form + * @param {string} submittedUrl + * @param {object} permissions + * @returns {URL|null} + */ +const getUrlFromSubmission = (form, submittedUrl, permissions) => { + if (!submittedUrl) { + return null; + } + + // Generate a URL Object for the submitted URL. + const url = new URL(submittedUrl); + + if (permissions?.upload) { + if (form.querySelector('[name="download"]').checked) { + url.searchParams.append('export', 1); + } + } + + if (permissions?.embed) { + if (form.querySelector('[name="embed"]').checked) { + url.searchParams.append('embed', 1); + } + } + if (form.querySelector('[name="copyright"]').checked) { + url.searchParams.append('copyright', 1); + } + + return url; +}; + +const handleDialogueSubmission = async(editor, modal, data) => { + const form = getList(modal.getRoot())[0].querySelector('form'); + if (!form) { + // The form couldn't be found, which is weird. + // This should not happen. + // Display the dialogue again + displayDialogue(editor, Object.assign({}, data)); + return; + } + + // Get the URL from the submitted form. + const submittedUrl = form.querySelector('input[name="url"]').value; + const url = getUrlFromSubmission(form, submittedUrl, getPermissions(editor)); + + if (!url) { + // The URL is invalid. + // Fill it in and represent the dialogue with an error. + displayDialogue(editor, Object.assign({}, data, { + url: submittedUrl, + invalidUrl: true, + })); + return; + } + + + const content = await renderForPromise(`${component}/content`, { + url: url.toString(), + }); + + editor.selection.moveToBookmark(openingSelection); + editor.execCommand('mceInsertContent', false, content.html); + editor.selection.moveToBookmark(openingSelection); +}; + +const getCurrentH5PData = (currentH5P) => { + const data = {}; + let url; + try { + url = new URL(currentH5P.textContent); + } catch (error) { + return data; + } + + if (url.searchParams.has('export')) { + data.download = true; + data.showOptions = true; + url.searchParams.delete('export'); + } + + if (url.searchParams.has('embed')) { + data.embed = true; + data.showOptions = true; + url.searchParams.delete('embed'); + } + + if (url.searchParams.has('copyright')) { + data.copyright = true; + data.showOptions = true; + url.searchParams.delete('copyright'); + } + + data.url = url.toString(); + + return data; +}; + +const displayDialogue = async(editor, data = {}) => { + const selection = editor.selection.getNode(); + const currentH5P = selection.closest('.h5p-placeholder'); + if (currentH5P) { + Object.assign(data, getCurrentH5PData(currentH5P)); + } + + const modal = await ModalFactory.create({ + type: Modal.TYPE, + templateContext: getTemplateContext(editor, data), + large: true, + }); + modal.show(); + + const $root = modal.getRoot(); + const root = $root[0]; + $root.on(ModalEvents.save, (event, modal) => { + handleDialogueSubmission(editor, modal, data); + }); + + root.addEventListener('click', (e) => { + const filepickerButton = e.target.closest('[data-target="filepicker"]'); + if (filepickerButton) { + displayFilepicker(editor, 'h5p').then((params) => { + if (params.url !== '') { + const input = root.querySelector('form input[name="url"]'); + input.value = params.url; + } + return params; + }) + .catch(); + } + }); +}; diff --git a/lib/editor/tiny/plugins/h5p/classes/plugininfo.php b/lib/editor/tiny/plugins/h5p/classes/plugininfo.php new file mode 100644 index 00000000000..35dc467b0bc --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/classes/plugininfo.php @@ -0,0 +1,76 @@ +. + +namespace tiny_h5p; + +use context; +use editor_tiny\plugin; +use editor_tiny\plugin_with_buttons; +use editor_tiny\plugin_with_menuitems; +use editor_tiny\plugin_with_configuration; + +/** + * Tiny H5P plugin for Moodle. + * + * @package tiny_h5p + * @copyright 2021 Andrew Lyons + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class plugininfo extends plugin implements + plugin_with_buttons, + plugin_with_menuitems, + plugin_with_configuration { + + public static function is_enabled( + context $context, + array $options, + array $fpoptions, + ?\editor_tiny\editor $editor = null + ): bool { + // Users must have permission to embed content. + return has_capability('atto/h5p:addembed', $context); + } + + public static function get_available_buttons(): array { + return [ + 'tiny_h5p/h5p', + ]; + } + + public static function get_available_menuitems(): array { + return [ + 'tiny_h5p/h5p', + ]; + } + + public static function get_plugin_configuration_for_context( + context $context, + array $options, + array $fpoptions, + ?\editor_tiny\editor $editor = null + ): array { + $permissions = [ + 'embed' => has_capability('tiny/h5p:addembed', $context), + 'upload' => has_capability('moodle/h5p:deploy', $context), + ]; + $permissions['uploadandembed'] = $permissions['embed'] && $permissions['upload']; + + return [ + 'permissions' => $permissions, + 'storeinrepo' => true, + ]; + } +} diff --git a/lib/editor/tiny/plugins/h5p/classes/privacy/provider.php b/lib/editor/tiny/plugins/h5p/classes/privacy/provider.php new file mode 100644 index 00000000000..28b48091b01 --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/classes/privacy/provider.php @@ -0,0 +1,30 @@ +. + +namespace tiny_h5p\privacy; + +/** + * Privacy Subsystem implementation for the H5P plugin for TinyMCE. + * + * @package tiny_h5p + * @copyright 2022 Andrew Lyons + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class provider implements \core_privacy\local\metadata\null_provider { + public static function get_reason(): string { + return 'privacy:metadata'; + } +} diff --git a/lib/editor/tiny/plugins/h5p/db/access.php b/lib/editor/tiny/plugins/h5p/db/access.php new file mode 100644 index 00000000000..feaf1df12e2 --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/db/access.php @@ -0,0 +1,36 @@ +. + +/** + * Capabilities for the tiny_h5p plugin. + * + * @package tiny_h5p + * @copyright 2022 Andrew Lyons + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$capabilities = [ + 'tiny/h5p:addembed' => [ + 'captype' => 'write', + 'contextlevel' => CONTEXT_MODULE, + 'archetypes' => [ + 'editingteacher' => CAP_ALLOW, + ], + 'clonepermissionsfrom' => 'atto/h5p:addembed', + ] +]; diff --git a/lib/editor/tiny/plugins/h5p/editor_styles.css b/lib/editor/tiny/plugins/h5p/editor_styles.css new file mode 100644 index 00000000000..c2c1283c0f0 --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/editor_styles.css @@ -0,0 +1,11 @@ +.mce-content-body .h5p-placeholder + br { + display: none; +} +.mce-content-body .h5p-placeholder { + color: #6c757d; + width: 100%; + word-break: break-all; + height: 260px; + cursor: pointer; + background: url([[pix:tiny_h5p|icon-white]]) center center / 100px auto no-repeat #6c757d; +} diff --git a/lib/editor/tiny/plugins/h5p/lang/en/tiny_h5p.php b/lib/editor/tiny/plugins/h5p/lang/en/tiny_h5p.php new file mode 100644 index 00000000000..841cfac6020 --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/lang/en/tiny_h5p.php @@ -0,0 +1,42 @@ +. + +/** + * Strings for component 'tiny_h5p', language 'en'. + * + * @package tiny_h5p + * @copyright 2022 Andrew Lyons + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$string['helplinktext'] = 'Moodle H5P Helper'; +$string['modaltitle'] = 'Insert H5P content'; +$string['buttontitle'] = 'Configure H5P content'; +$string['insert'] = 'Insert H5P content'; +$string['pluginname'] = 'Tiny H5P plugin for Moodle'; +$string['browserepositories'] = 'Browse repositories...'; +$string['copyrightbutton'] = 'Copyright button'; +$string['downloadbutton'] = 'Allow download'; +$string['embedbutton'] = 'Embed button'; +$string['h5p:addembed'] = 'Add embedded H5P'; +$string['h5pfile'] = 'H5P file upload'; +$string['h5pfileorurl'] = 'H5P URL or file upload'; +$string['h5poptions'] = 'H5P options'; +$string['h5purl'] = 'H5P URL'; +$string['invalidh5purl'] = 'Invalid URL'; +$string['instructions'] = 'You can insert H5P content by either entering a URL or by uploading an H5P file.'; +$string['noh5pcontent'] = 'No H5P content added'; +$string['privacy:metadata'] = 'The H5P plugin for TinyMCE does not store any personal data.'; diff --git a/lib/editor/tiny/plugins/h5p/pix/icon-white.png b/lib/editor/tiny/plugins/h5p/pix/icon-white.png new file mode 100644 index 0000000000000000000000000000000000000000..d2ac8b26ad680b87e7509c8d720ad7401c592de1 GIT binary patch literal 6257 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 + + + + + + + + diff --git a/lib/editor/tiny/plugins/h5p/pix/icon.png b/lib/editor/tiny/plugins/h5p/pix/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..51a640dc9f264d0ae7dcc0dccb6e53833055527c GIT binary patch literal 4541 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 literal 0 HcmV?d00001 diff --git a/lib/editor/tiny/plugins/h5p/pix/icon.svg b/lib/editor/tiny/plugins/h5p/pix/icon.svg new file mode 100644 index 00000000000..2aaf327ffe2 --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/pix/icon.svg @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/lib/editor/tiny/plugins/h5p/templates/content.mustache b/lib/editor/tiny/plugins/h5p/templates/content.mustache new file mode 100644 index 00000000000..015c6ac76dc --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/templates/content.mustache @@ -0,0 +1,38 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template tiny_h5p/content + + Templated used when inserting H5P Placeholder content into the text. + + Classes required for JS: + * none + + Data attributes required for JS: + * none + + Context variables required for this template: + + Example context (json): + { + "url": "https://moodle.h5p.com/content/1290772960722742119" + } +}} + +
+ {{ url }} +
diff --git a/lib/editor/tiny/plugins/h5p/templates/modal.mustache b/lib/editor/tiny/plugins/h5p/templates/modal.mustache new file mode 100644 index 00000000000..cf741c404e9 --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/templates/modal.mustache @@ -0,0 +1,167 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template tiny_h5p/modal + + Modal to manage an H5P activity within the Tiny Edigtor. + + Classes required for JS: + * none + + Data attributes required for JS: + * none + + Context variables required for this template: + + Example context (json): + { + "elementid": "exampleId" + } +}} + +{{< core/modal }} + + {{$title}} + {{#str}} modaltitle, tiny_h5p {{/str}} + {{/title}} + + {{$body}} +
+ +{{# noh5pcontent }} + +{{/ noh5pcontent }} + +{{# invalidUrl }} + +{{/ invalidUrl }} + +{{#canUploadAndEmbed}} +
{{#str}} instructions, tiny_h5p{{/str}}
+{{/canUploadAndEmbed}} + +
+
+ {{/body}} + + {{$footer}} + + + {{/footer}} +{{/ core/modal }} diff --git a/lib/editor/tiny/plugins/h5p/version.php b/lib/editor/tiny/plugins/h5p/version.php new file mode 100644 index 00000000000..540ca533f87 --- /dev/null +++ b/lib/editor/tiny/plugins/h5p/version.php @@ -0,0 +1,29 @@ +. + +/** + * Tiny text editor H5P Plugin version file. + * + * @package tiny_h5p + * @copyright 2022 Andrew Lyons + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$plugin->version = 2022101700; +$plugin->requires = 2020061500; +$plugin->component = 'tiny_h5p';