Skip to content

Commit

Permalink
Show custom block-delete modal with options to delete or keep the ser…
Browse files Browse the repository at this point in the history
…ies mapping
  • Loading branch information
justusdieckmann committed Jan 11, 2024
1 parent e03a58a commit 2cb411b
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 119 deletions.
10 changes: 10 additions & 0 deletions amd/build/block_delete_handler.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions amd/build/block_delete_handler.min.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

61 changes: 61 additions & 0 deletions amd/src/block_delete_handler.js
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.

/**
* Javascript to add a custom block_delete handler
*
* @module block_opencast/block_delete_handler
* @copyright 2024 Justus Dieckmann, University of Münster
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

import ModalFactory from 'core/modal_factory';
import Ajax from 'core/ajax';
import Templates from 'core/templates';
import Prefetch from "core/prefetch";
import {getString} from 'core/str';
import Notification from "core/notification";

export const init = (contextid, deleteurl) => {
Prefetch.prefetchTemplate('block_opencast/delete_block_modal');
Prefetch.prefetchString('block_opencast', 'deletecheck_title_modal');
const deleteButton = document.querySelector('.block_opencast a.dropdown-item.block_opencast_delete');
deleteButton.onclick = async(e) => {
e.preventDefault();

const html = await Templates.render('block_opencast/delete_block_modal', {
deleteblockurl: deleteurl
});

const modal = await ModalFactory.create({
type: ModalFactory.types.CANCEL,
body: html,
title: await getString('deletecheck_title_modal', 'block_opencast'),
large: true
});
await modal.show();
modal.body[0].querySelector('.block_opencast-delete-mapping').onclick = async() => {
try {
await Ajax.call([{
methodname: 'block_opencast_unlink_series',
args: {contextid: contextid, ocinstanceid: -1, seriesid: 'all'}
}])[0];
window.location = deleteurl;
} catch (e) {
Notification.exception(e);
}
};
};
};
46 changes: 22 additions & 24 deletions block_opencast.php
Original file line number Diff line number Diff line change
Expand Up @@ -199,49 +199,47 @@ public function instance_create() {
* @return block_contents a representation of the block, for rendering.
*/
public function get_content_for_output($output) {
global $COURSE, $PAGE;

// Get the block_contents object from parent class.
$bc = parent::get_content_for_output($output);

// We prepare the data to use and replace the existing action link contents.
$title = $this->title;
$defaultdeletestr = get_string('deleteblock', 'block', $this->title);
// Check whether the user can manually delete series mapping.
if (!has_capability('block/opencast:manageseriesforcourse', $this->context)) {
return $bc;
}

// Check if the block_contents has controls.
if (!empty($bc->controls)) {

// We filter the controls to find the delete action link.
$deleteactionfiltered = array_filter($bc->controls, function ($actionlink) use ($defaultdeletestr, $title) {
// Get the text from action link.
$actionlinktext = $actionlink->text;
// Get the text if it is a type of lang_string via __toString.
if ($actionlinktext instanceof \lang_string) {
$actionlinktext = $actionlinktext->__toString();
}
return $actionlinktext === $defaultdeletestr;
$deleteactionfiltered = array_filter($bc->controls, function ($actionlink) {
return str_contains($actionlink->attributes['class'], 'editing_delete');
});

// In case the delete action link could be found, we try to replace its properties.
if (!empty($deleteactionfiltered)) {
$index = key($deleteactionfiltered);
$deleteaction = reset($deleteactionfiltered);
// Replace the action link's text.
if (isset($deleteaction->text)) {
$deleteaction->text = get_string('delete_block_action_item_text', 'block_opencast');
}

// Delete all modal-related attributes.
if (isset($deleteaction->attributes)) {
if (isset($deleteaction->attributes['data-modal-title-str'])) {
$deleteaction->attributes['data-modal-title-str'] = json_encode(
['deletecheck_title_modal', 'block_opencast']
);
}
if (isset($deleteaction->attributes['data-modal-content-str'])) {
$deleteaction->attributes['data-modal-content-str'] = json_encode(
['deletecheck_content_modal', 'block_opencast']
);
foreach ($deleteaction->attributes as $k => $v) {
if (str_starts_with($k, 'data-modal')) {
unset($deleteaction->attributes[$k]);
}
}
$deleteaction->attributes['class'] .= ' block_opencast_delete';
}
$bc->controls[$index] = $deleteaction;
$deleteurl = new moodle_url('/course/view.php', [
'id' => $COURSE->id,
'bui_deleteid' => $this->instance->id,
'bui_confirm' => 1,
'sesskey' => sesskey()
]);
$PAGE->requires->js_call_amd('block_opencast/block_delete_handler', 'init',
[$this->context->id, $deleteurl->out(false)]);
}
}
return $bc;
Expand Down
14 changes: 9 additions & 5 deletions classes/external.php
Original file line number Diff line number Diff line change
Expand Up @@ -299,17 +299,21 @@ public static function unlink_series(int $contextid, int $ocinstanceid, string $

list($unused, $course, $cm) = get_context_info_array($context->id);

$mapping = seriesmapping::get_record(['ocinstanceid' => $params['ocinstanceid'], 'courseid' => $course->id,
'series' => $params['seriesid'], ], true);
if ($params['seriesid'] === 'all') {
$mappings = seriesmapping::get_records(['courseid' => $course->id]);
} else {
$mappings = seriesmapping::get_records(['ocinstanceid' => $params['ocinstanceid'], 'courseid' => $course->id,
'series' => $params['seriesid']]);
}

if ($mapping) {
foreach ($mappings as $mapping) {
if (!$mapping->delete()) {
throw new moodle_exception('delete_series_failed', 'block_opencast');
}

// Unlinking series from course.
$apibridge = apibridge::get_instance($params['ocinstanceid']);
$seriesunlinked = $apibridge->unlink_series_from_course($course->id, $params['seriesid']);
$apibridge = apibridge::get_instance($mapping->get('ocinstanceid'));
$seriesunlinked = $apibridge->unlink_series_from_course($course->id, $mapping->get('series'));

if (!$seriesunlinked) {
throw new moodle_exception('delete_series_failed', 'block_opencast');
Expand Down
11 changes: 6 additions & 5 deletions lang/en/block_opencast.php
Original file line number Diff line number Diff line change
Expand Up @@ -891,12 +891,13 @@
$string['directaccess_copy_success'] = 'The direct access link has been successfully copied to clipboard.';
$string['directaccess_copytoclipboard_unavialable'] = 'It seems that your browser does not support the copy to clipboard functionality, try to copy the link manually from the dropdown item.';
$string['opencast:autocompleteteacherroles'] = 'Teacher roles to be extracted and provided in the autocomplete list';
$string['delete_block_action_item_text'] = 'Remove Opencast Block';
// Strings for delete block modal.
$string['deletecheck_title_modal'] = 'Remove Opencast Block?';
$string['deletecheck_content_modal'] = 'Are you sure you want to remove the Opencast block from the course?<br /> <small>You get to decide whether to remove the series mapping in the next step.</small>';
$string['confirm_delete_seriesmapping_title_page'] = 'Opencast Block: Delete series mapping';
$string['confirm_delete_seriesmapping_title_confirm'] = 'Delete Opencast course series mapping';
$string['confirm_delete_seriesmapping_content_confirm'] = 'Do you also want to delete the course series mapping of this block?<br /><br /><small><b>NOTE:</b> If the course series mapping is deleted, it is not possible to retrieve the current series to this course anymore.</small>';
$string['error_block_delete_seriesmapping'] = 'Unfortunately, there was an error during course series mapping deletion, please contact the system administrator.';

$string['delete_mapping_explanation'] = 'The Opencast Block tracks which Opencast Series is mapped to the course.<br> You can choose whether to delete the mapping.<br> If you delete it, the series will no longer appear when you create the opencast block again.';
$string['only_delete_block'] = 'Delete block, but keep series mapping';
$string['delete_block_and_mapping'] = 'Delete block and series mapping';

// Deprecated since version 2021062300.
$string['video_already_uploaded'] = 'Video already uploaded';
85 changes: 0 additions & 85 deletions lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,88 +105,3 @@ function block_opencast_pre_course_delete(stdClass $course) {
$mapping->delete();
}
}


/**
* Pre-delete block hook to show a confirmation message or to perform cleaup the related series and videos.
*
* @param object $instance a row from the block_instances table
*
* @throws moodle_exception
*/
function block_opencast_pre_block_delete($instance) {

// We make sure if the deleting block is Opencast block, otherwise we do nothing!
if ($instance->blockname !== 'opencast') {
return;
}

// Get the course and context base don block instance parentcontextid.
list($context, $course, $cm) = get_context_info_array($instance->parentcontextid);

// We get the flag 'removeseriesmapping' to decide whether to delete the series mapping.
$removeseriesmapping = optional_param('removeseriesmapping', null, PARAM_INT);

// At first the flag is not set, therefore we have the chance to show a confirmation page.
if (is_null($removeseriesmapping) && !empty($course) && !empty($context)) {
$deletepage = new moodle_page();
$deletepage->set_pagelayout('admin');
$deletepage->blocks->show_only_fake_blocks(true);
$deletepage->set_course($course);
$deletepage->set_context($context);
if ($cm) {
$deletepage->set_cm($cm);
}
// The default delete url.
$deleteurl = new moodle_url('/course/view.php',
[
'id' => $course->id,
'sesskey' => sesskey(),
'bui_deleteid' => $instance->id,
'bui_confirm' => 1
]
);
$deletepage->set_url($deleteurl);
$deletepage->set_block_actions_done();
$PAGE = $deletepage;
/** @var core_renderer $output */
$output = $deletepage->get_renderer('core');
$OUTPUT = $output;

$deletepagetitle = get_string('confirm_delete_seriesmapping_title_page', 'block_opencast');
$confirmtitle = get_string('confirm_delete_seriesmapping_title_confirm', 'block_opencast');
$message = get_string('confirm_delete_seriesmapping_content_confirm', 'block_opencast');

$PAGE->navbar->add($deletepagetitle);
$PAGE->set_title($deletepagetitle);
$PAGE->set_heading($course->fullname);
echo $OUTPUT->header();

// Creating a confirmation page with assigning a flag 'removeseriesmapping' to decide whether to delete series mapping.
$confirmurl = new moodle_url($deletepage->url, array('removeseriesmapping' => 1));
$cancelurl = new moodle_url($deletepage->url, array('removeseriesmapping' => 0));

$yesbutton = new single_button($confirmurl, get_string('yes'));
$nobutton = new single_button($cancelurl, get_string('no'));

$displayoptions['confirmtitle'] = $confirmtitle;

echo $OUTPUT->confirm($message, $yesbutton, $nobutton, $displayoptions);
echo $OUTPUT->footer();
// Make sure that nothing else happens after we have displayed this form.
exit;
} else if ($removeseriesmapping === 1) { // We only perform the series mapping deletion if the flag is set to 1.
$success = true;
$mappings = seriesmapping::get_records(['courseid' => $course->id]);
foreach ($mappings as $mapping) {
if (!$mapping->delete()) {
$success = false;
}
}
if (!$success) {
throw new moodle_exception('error_block_delete_seriesmapping', 'block_opencast');
}
}
// We let the process continue if the flag 'removeseriesmapping' is set to 0,
// which means it is decided not to delete series mapping.
}
35 changes: 35 additions & 0 deletions templates/delete_block_modal.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{{!
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 <http://www.gnu.org/licenses/>.
}}
{{!
@template block_opencast/delete_block_modal
This template renders the delete modal
Example context (json):
{
"deleteblockurl": "https://moodle.local/blocks/opencast/managedefaults.php?courseid=3&ocinstanceid=1"
}
}}
{{#str}} delete_mapping_explanation, block_opencast {{/str}}
<div class="d-flex justify-content-end mt-3">
<div class="btn btn-primary mx-1 block_opencast-delete-mapping">
{{#str}} delete_block_and_mapping, block_opencast {{/str}}
</div>
<a class='btn btn-primary mx-1 block_opencast-keep-mapping' href="{{{deleteblockurl}}}">
{{#str}} only_delete_block, block_opencast {{/str}}
</a>
</div>

0 comments on commit 2cb411b

Please sign in to comment.