diff --git a/calendar/amd/build/export.min.js b/calendar/amd/build/export.min.js
new file mode 100644
index 00000000000..ec3eae08c69
--- /dev/null
+++ b/calendar/amd/build/export.min.js
@@ -0,0 +1,2 @@
+define ("core_calendar/export",["exports","core/copy_to_clipboard"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;var b={copyUrlId:"copyexporturl"};a.init=function init(){document.onreadystatechange=function(){if("complete"===document.readyState){var a=document.getElementById(b.copyUrlId);a.removeAttribute("disabled");a.focus()}}}});
+//# sourceMappingURL=export.min.js.map
diff --git a/calendar/amd/build/export.min.js.map b/calendar/amd/build/export.min.js.map
new file mode 100644
index 00000000000..ac7357d4a64
--- /dev/null
+++ b/calendar/amd/build/export.min.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../src/export.js"],"names":["selectors","copyUrlId","init","document","onreadystatechange","readyState","copyUrl","getElementById","removeAttribute","focus"],"mappings":"+JA8BMA,CAAAA,CAAS,CAAG,CACdC,SAAS,CAAE,eADG,C,QASE,QAAPC,CAAAA,IAAO,EAAM,CAEtBC,QAAQ,CAACC,kBAAT,CAA8B,UAAM,CAChC,GAA4B,UAAxB,GAAAD,QAAQ,CAACE,UAAb,CAAwC,CACpC,GAAMC,CAAAA,CAAO,CAAGH,QAAQ,CAACI,cAAT,CAAwBP,CAAS,CAACC,SAAlC,CAAhB,CACAK,CAAO,CAACE,eAAR,CAAwB,UAAxB,EACAF,CAAO,CAACG,KAAR,EACH,CACJ,CACJ,C","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 * A javascript module to enhance the calendar export form.\n *\n * @module core_calendar/export\n * @copyright 2021 Jun Pataleta\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport 'core/copy_to_clipboard';\n\n/**\n * Selectors for the calendar export page.\n *\n * @property {string} copyUrlId The element ID of the Copy URL button.\n */\nconst selectors = {\n copyUrlId: 'copyexporturl',\n};\n\n/**\n * Initialises the calendar export JS module.\n *\n * @method init\n */\nexport const init = () => {\n // Enable the copy URL button and focus on it after the page has loaded.\n document.onreadystatechange = () => {\n if (document.readyState === 'complete') {\n const copyUrl = document.getElementById(selectors.copyUrlId);\n copyUrl.removeAttribute('disabled');\n copyUrl.focus();\n }\n };\n};\n"],"file":"export.min.js"}
\ No newline at end of file
diff --git a/calendar/amd/src/export.js b/calendar/amd/src/export.js
new file mode 100644
index 00000000000..a8245dc148e
--- /dev/null
+++ b/calendar/amd/src/export.js
@@ -0,0 +1,49 @@
+// 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 .
+
+/**
+ * A javascript module to enhance the calendar export form.
+ *
+ * @module core_calendar/export
+ * @copyright 2021 Jun Pataleta
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+import 'core/copy_to_clipboard';
+
+/**
+ * Selectors for the calendar export page.
+ *
+ * @property {string} copyUrlId The element ID of the Copy URL button.
+ */
+const selectors = {
+ copyUrlId: 'copyexporturl',
+};
+
+/**
+ * Initialises the calendar export JS module.
+ *
+ * @method init
+ */
+export const init = () => {
+ // Enable the copy URL button and focus on it after the page has loaded.
+ document.onreadystatechange = () => {
+ if (document.readyState === 'complete') {
+ const copyUrl = document.getElementById(selectors.copyUrlId);
+ copyUrl.removeAttribute('disabled');
+ copyUrl.focus();
+ }
+ };
+};
diff --git a/calendar/export.php b/calendar/export.php
index 06486278e23..c6f94744882 100644
--- a/calendar/export.php
+++ b/calendar/export.php
@@ -151,8 +151,9 @@ if ($data = $exportform->get_data()) {
$link = new moodle_url('/calendar/export_execute.php', $params);
if (!empty($data->generateurl)) {
- $urlclasses = array('class' => 'generalbox calendarurl');
- $calendarurl = html_writer::tag( 'div', get_string('calendarurl', 'calendar', $link->out()), $urlclasses);
+ $exporturlcontext = ['calendarexporturl' => $link->out(false)];
+ $exporturl = $OUTPUT->render_from_template('core_calendar/export_calendar_url', $exporturlcontext);
+ $calendarurl = html_writer::div($exporturl, 'generalbox calendarurl mt-3');
}
if (!empty($data->export)) {
diff --git a/calendar/templates/export_calendar_url.mustache b/calendar/templates/export_calendar_url.mustache
new file mode 100644
index 00000000000..119208b6f8b
--- /dev/null
+++ b/calendar/templates/export_calendar_url.mustache
@@ -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 .
+}}
+{{!
+ @template core_calendar/export_calendar_url
+
+ Template for the URL for the exported calendar.
+
+ Example context (json):
+ {
+ "calendarexporturl": "https://www.moodle.org"
+ }
+}}
+
+{{#js}}
+require(['core_calendar/export'], function(calendarExport) {
+ calendarExport.init();
+});
+{{/js}}
diff --git a/calendar/tests/behat/export.feature b/calendar/tests/behat/export.feature
index a26439f71f1..c929094e4d3 100644
--- a/calendar/tests/behat/export.feature
+++ b/calendar/tests/behat/export.feature
@@ -1,4 +1,4 @@
-@core @core_calendar @core_calendar_export
+@core @core_calendar
Feature: Export calendar events
In order to be able to use my calendar events outside of Moodle
As a user
@@ -30,7 +30,7 @@ Feature: Export calendar events
And I set the field "All events" to "1"
And I set the field "Recent and next 60 days" to "1"
When I click on "Get calendar URL" "button"
- Then I should see "&preset_what=all&"
+ Then the "value" attribute of "Calendar URL" "field" should contain "&preset_what=all&"
Scenario: Generating calendar URL for course events
Given I follow "This month"
@@ -38,7 +38,7 @@ Feature: Export calendar events
And I set the field "Events related to courses" to "1"
And I set the field "Recent and next 60 days" to "1"
When I click on "Get calendar URL" "button"
- Then I should see "&preset_what=courses&"
+ Then the "value" attribute of "Calendar URL" "field" should contain "&preset_what=courses&"
Scenario: Generating calendar URL for group events
Given I follow "This month"
@@ -46,7 +46,7 @@ Feature: Export calendar events
And I set the field "Events related to groups" to "1"
And I set the field "Recent and next 60 days" to "1"
When I click on "Get calendar URL" "button"
- Then I should see "&preset_what=groups&"
+ Then the "value" attribute of "Calendar URL" "field" should contain "&preset_what=groups&"
Scenario: Generating calendar URL for category events
Given I follow "This month"
@@ -54,7 +54,7 @@ Feature: Export calendar events
And I set the field "Events related to categories" to "1"
And I set the field "Recent and next 60 days" to "1"
When I click on "Get calendar URL" "button"
- Then I should see "&preset_what=categories&"
+ Then the "value" attribute of "Calendar URL" "field" should contain "&preset_what=categories&"
Scenario: Generating calendar URL for user events
Given I follow "This month"
@@ -62,4 +62,4 @@ Feature: Export calendar events
And I set the field "My personal events" to "1"
And I set the field "Recent and next 60 days" to "1"
When I click on "Get calendar URL" "button"
- Then I should see "&preset_what=user&"
+ Then the "value" attribute of "Calendar URL" "field" should contain "&preset_what=user&"
diff --git a/lang/en/calendar.php b/lang/en/calendar.php
index a752eb0e449..7a5514c98d8 100644
--- a/lang/en/calendar.php
+++ b/lang/en/calendar.php
@@ -28,11 +28,12 @@ $string['addevent'] = 'Add events';
$string['annually'] = 'Annually';
$string['activityevent'] = 'Activity event';
$string['calendar'] = 'Calendar';
+$string['calendarexporturl'] = 'Calendar URL';
$string['calendarheading'] = '{$a} Calendar';
$string['calendarpreferences'] = 'Calendar preferences';
$string['calendartypes'] = 'Calendar types';
$string['calendarsubscriptions'] = 'Calendar subscriptions';
-$string['calendarurl'] = 'Calendar URL: {$a}';
+$string['calendarurlcopiedtoclipboard'] = 'Calendar URL copied to clipboard';
$string['category'] = 'Category';
$string['categoryevent'] = 'Category event';
$string['clickhide'] = 'click to hide';
@@ -44,6 +45,8 @@ $string['colactions'] = 'Actions';
$string['commontasks'] = 'Options';
$string['confirmeventdelete'] = 'Are you sure you want to delete the "{$a}" event?';
$string['confirmeventseriesdelete'] = 'The "{$a->name}" event is part of a series. Do you want to delete just this event, or all {$a->count} events in the series?';
+$string['copycalendarurl'] = 'Copy calendar URL';
+$string['copyurl'] = 'Copy URL';
$string['course'] = 'Course';
$string['courseevent'] = 'Course event';
$string['courseevents'] = 'Course events';
@@ -278,6 +281,9 @@ $string['yesterday'] = 'Yesterday';
$string['youcandeleteallrepeats'] = 'This event is part of a repeating event series. You can delete this event only, or all {$a} events in the series at once.';
$string['yoursubscriptions'] = 'Your Subscriptions';
+// Deprecated since Moodle 4.0.
+$string['calendarurl'] = 'Calendar URL: {$a}';
+
// Deprecated since Moodle 3.8.
$string['global'] = 'Global';
$string['globalevent'] = 'Global event';
diff --git a/lang/en/deprecated.txt b/lang/en/deprecated.txt
index 1d20dc3ca92..e0aa9d555ae 100644
--- a/lang/en/deprecated.txt
+++ b/lang/en/deprecated.txt
@@ -94,6 +94,7 @@ updatesite,core_hub
unregisterexplained,core_hub
configrequestcategoryselection,core_admin
requestcategoryselection,core_admin
+calendarurl,core_calendar
global,core_calendar
globalevent,core_calendar
globalevents,core_calendar