From 4ad7d22f09a87e1249f5907ae88d33f68e2bbe5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luca=20B=C3=B6sch?= Date: Sun, 26 Jul 2026 02:47:59 +0200 Subject: [PATCH] Make some Scheduler layouts more beautiful. --- amd/build/delselected.min.js | 2 +- amd/build/delselected.min.js.map | 2 +- amd/src/delselected.js | 2 +- renderer.php | 23 ++++++++++++++++++----- styles.css | 15 ++++++++++----- teacherview.php | 2 +- templates/action_menu_trigger.mustache | 2 +- view.php | 8 ++++++++ viewstatistics.php | 12 ++++++------ 9 files changed, 47 insertions(+), 21 deletions(-) diff --git a/amd/build/delselected.min.js b/amd/build/delselected.min.js index e1cfe497..efd03f6f 100644 --- a/amd/build/delselected.min.js +++ b/amd/build/delselected.min.js @@ -6,6 +6,6 @@ define("mod_scheduler/delselected",["exports"],(function(_exports){Object.define * @copyright 2024 ISB Bayern * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -const SELECTORS={DELACTION:"div.commandbar a#delselected",SELECTBOX:"table#slotmanager input.slotselect"};_exports.SELECTORS=SELECTORS;_exports.init=baseurl=>{let link=document.querySelector(SELECTORS.DELACTION);null!==link&&link.addEventListener("click",(function(){collectSelection(link,baseurl)}))};const collectSelection=(link,baseurl)=>{let sellist="";document.querySelectorAll(SELECTORS.SELECTBOX).forEach((function(box){box.checked&&(sellist.length>0&&(sellist+=","),sellist+=box.getAttribute("value"))})),link.setAttribute("href",baseurl+"&items="+sellist)};_exports.collectSelection=collectSelection})); +const SELECTORS={DELACTION:"div.commandbar a#delselected",SELECTBOX:"table#slotmanager input.slotselect.form-check-input.mt-0"};_exports.SELECTORS=SELECTORS;_exports.init=baseurl=>{let link=document.querySelector(SELECTORS.DELACTION);null!==link&&link.addEventListener("click",(function(){collectSelection(link,baseurl)}))};const collectSelection=(link,baseurl)=>{let sellist="";document.querySelectorAll(SELECTORS.SELECTBOX).forEach((function(box){box.checked&&(sellist.length>0&&(sellist+=","),sellist+=box.getAttribute("value"))})),link.setAttribute("href",baseurl+"&items="+sellist)};_exports.collectSelection=collectSelection})); //# sourceMappingURL=delselected.min.js.map \ No newline at end of file diff --git a/amd/build/delselected.min.js.map b/amd/build/delselected.min.js.map index 0b68088b..54de28df 100644 --- a/amd/build/delselected.min.js.map +++ b/amd/build/delselected.min.js.map @@ -1 +1 @@ -{"version":3,"file":"delselected.min.js","sources":["../src/delselected.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 * TODO describe module delselected\n *\n * @module mod_scheduler/delselected\n * @copyright 2024 ISB Bayern\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * Selectors used by the module.\n */\nexport const SELECTORS = {\n DELACTION: 'div.commandbar a#delselected',\n SELECTBOX: 'table#slotmanager input.slotselect',\n};\n\n/**\n * Add event listener to the delete link.\n * @param {*} baseurl\n */\nexport const init = (baseurl) => {\n let link = document.querySelector(SELECTORS.DELACTION);\n if (link !== null) {\n link.addEventListener('click', function() {\n collectSelection(link, baseurl);\n });\n }\n};\n\n/**\n * Copy the selected boxes into an input parameter of the respective form\n *\n * @param {String} link\n * @param {String} baseurl\n */\nexport const collectSelection = (link, baseurl) => {\n let sellist = '';\n document.querySelectorAll(SELECTORS.SELECTBOX).forEach(function(box) {\n if (box.checked) {\n if (sellist.length > 0) {\n sellist += ',';\n }\n sellist += box.getAttribute('value');\n }\n });\n link.setAttribute('href', baseurl + '&items=' + sellist);\n};\n"],"names":["SELECTORS","DELACTION","SELECTBOX","baseurl","link","document","querySelector","addEventListener","collectSelection","sellist","querySelectorAll","forEach","box","checked","length","getAttribute","setAttribute"],"mappings":";;;;;;;;MA0BaA,UAAY,CACrBC,UAAW,+BACXC,UAAW,iFAOMC,cACbC,KAAOC,SAASC,cAAcN,UAAUC,WAC/B,OAATG,MACAA,KAAKG,iBAAiB,SAAS,WAC3BC,iBAAiBJ,KAAMD,mBAWtBK,iBAAmB,CAACJ,KAAMD,eAC/BM,QAAU,GACdJ,SAASK,iBAAiBV,UAAUE,WAAWS,SAAQ,SAASC,KACxDA,IAAIC,UACAJ,QAAQK,OAAS,IACjBL,SAAW,KAEfA,SAAWG,IAAIG,aAAa,aAGpCX,KAAKY,aAAa,OAAQb,QAAU,UAAYM"} \ No newline at end of file +{"version":3,"file":"delselected.min.js","sources":["../src/delselected.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 * TODO describe module delselected\n *\n * @module mod_scheduler/delselected\n * @copyright 2024 ISB Bayern\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * Selectors used by the module.\n */\nexport const SELECTORS = {\n DELACTION: 'div.commandbar a#delselected',\n SELECTBOX: 'table#slotmanager input.slotselect.form-check-input.mt-0',\n};\n\n/**\n * Add event listener to the delete link.\n * @param {*} baseurl\n */\nexport const init = (baseurl) => {\n let link = document.querySelector(SELECTORS.DELACTION);\n if (link !== null) {\n link.addEventListener('click', function() {\n collectSelection(link, baseurl);\n });\n }\n};\n\n/**\n * Copy the selected boxes into an input parameter of the respective form\n *\n * @param {String} link\n * @param {String} baseurl\n */\nexport const collectSelection = (link, baseurl) => {\n let sellist = '';\n document.querySelectorAll(SELECTORS.SELECTBOX).forEach(function(box) {\n if (box.checked) {\n if (sellist.length > 0) {\n sellist += ',';\n }\n sellist += box.getAttribute('value');\n }\n });\n link.setAttribute('href', baseurl + '&items=' + sellist);\n};\n"],"names":["SELECTORS","DELACTION","SELECTBOX","baseurl","link","document","querySelector","addEventListener","collectSelection","sellist","querySelectorAll","forEach","box","checked","length","getAttribute","setAttribute"],"mappings":";;;;;;;;MA0BaA,UAAY,CACrBC,UAAW,+BACXC,UAAW,uGAOMC,cACbC,KAAOC,SAASC,cAAcN,UAAUC,WAC/B,OAATG,MACAA,KAAKG,iBAAiB,SAAS,WAC3BC,iBAAiBJ,KAAMD,mBAWtBK,iBAAmB,CAACJ,KAAMD,eAC/BM,QAAU,GACdJ,SAASK,iBAAiBV,UAAUE,WAAWS,SAAQ,SAASC,KACxDA,IAAIC,UACAJ,QAAQK,OAAS,IACjBL,SAAW,KAEfA,SAAWG,IAAIG,aAAa,aAGpCX,KAAKY,aAAa,OAAQb,QAAU,UAAYM"} \ No newline at end of file diff --git a/amd/src/delselected.js b/amd/src/delselected.js index 462f867d..59ddbce9 100644 --- a/amd/src/delselected.js +++ b/amd/src/delselected.js @@ -26,7 +26,7 @@ */ export const SELECTORS = { DELACTION: 'div.commandbar a#delselected', - SELECTBOX: 'table#slotmanager input.slotselect', + SELECTBOX: 'table#slotmanager input.slotselect.form-check-input.mt-0', }; /** diff --git a/renderer.php b/renderer.php index f53bbc6c..38e96d6b 100644 --- a/renderer.php +++ b/renderer.php @@ -301,7 +301,7 @@ public function appointment_link($scheduler, $user, $appointmentid) { 'appointmentid' => $appointmentid, ]; $url = new moodle_url('/mod/scheduler/view.php', $paras); - return html_writer::link($url, fullname($user)); + return html_writer::link($url, fullname($user), ['class' => 'align-middle']); } /** @@ -416,6 +416,7 @@ public function teacherview_tabs( */ public function render_scheduler_slot_table(scheduler_slot_table $slottable) { $table = new html_table(); + $table->attributes['class'] = 'table generaltable table-reboot table-hover table-striped'; if ($slottable->showslot) { $table->head = [get_string('date', 'scheduler')]; @@ -610,7 +611,7 @@ public function render_scheduler_student_list(scheduler_student_list $studentlis $student->entryid, $student->checked, '', - ['class' => 'studentselect'] + ['class' => 'studentselect form-check-input align-middle mt-0'] ); } else { $img = $student->checked ? 'ticked' : 'unticked'; @@ -645,13 +646,16 @@ public function render_scheduler_student_list(scheduler_student_list $studentlis $class .= ' highlight'; } - $picture = $this->user_picture($student->user, ['courseid' => $studentlist->scheduler->courseid]); + $picture = $this->user_picture( + $student->user, + ['courseid' => $studentlist->scheduler->courseid, 'class' => 'userpicture ms-1'] + ); $grade = ''; if ($studentlist->showgrades && $student->grade) { $grade = $this->format_grade($studentlist->scheduler, $student->grade, true); } - $o .= html_writer::div($checkbox . $picture . ' ' . $name . $studicons . ' ' . $grade, $class); + $o .= html_writer::div($checkbox . $picture . $name . $studicons . ' ' . $grade, $class); } if ($editable) { @@ -678,6 +682,7 @@ public function render_scheduler_student_list(scheduler_student_list $studentlis public function render_scheduler_slot_booker(scheduler_slot_booker $booker) { $table = new html_table(); + $table->attributes['class'] = 'table generaltable table-reboot table-hover table-striped'; $table->head = [ get_string('date', 'scheduler'), get_string('start', 'scheduler'), get_string('end', 'scheduler'), get_string('location', 'scheduler'), get_string('comments', 'scheduler'), s($booker->scheduler->get_teacher_name()), @@ -834,6 +839,7 @@ public function render_scheduler_slot_manager(scheduler_slot_manager $slotman) { $table->align[] = 'center'; $table->id = 'slotmanager'; + $table->attributes['class'] = 'table generaltable table-reboot table-hover table-striped'; $table->data = []; $previousdate = ''; @@ -843,7 +849,13 @@ public function render_scheduler_slot_manager(scheduler_slot_manager $slotman) { foreach ($slotman->slots as $slot) { $rowdata = []; - $selectbox = html_writer::checkbox('selectedslot[]', $slot->slotid, false, '', ['class' => 'slotselect']); + $selectbox = html_writer::checkbox( + 'selectedslot[]', + $slot->slotid, + false, + '', + ['class' => 'slotselect form-check-input mt-0'] + ); $rowdata[] = $slot->editable ? $selectbox : ''; $startdate = $this->userdate($slot->starttime); @@ -963,6 +975,7 @@ public function render_scheduler_slot_manager(scheduler_slot_manager $slotman) { public function render_scheduler_scheduling_list(scheduler_scheduling_list $list) { $mtable = new html_table(); + $mtable->attributes['class'] = 'table generaltable table-reboot table-hover table-striped'; $mtable->id = $list->id; $mtable->head = ['', get_string('name')]; diff --git a/styles.css b/styles.css index e5cfe623..fa6baa72 100644 --- a/styles.css +++ b/styles.css @@ -36,6 +36,12 @@ div .path-mod-scheduler .appointmentnote { margin-right: auto; } +.path-mod-scheduler #slotmanager td, +.path-mod-scheduler #studentstoschedule td, +.path-mod-scheduler #groupstoschedule td { + vertical-align: middle; +} + .path-mod-scheduler div.bookercontrols { text-align: center; } @@ -96,11 +102,11 @@ div .path-mod-scheduler .appointmentnote { } -body.path-mod-scheduler input.slotselect { +body.path-mod-scheduler input.slotselect.form-check-input.mt-0 { display: none; } -body.path-mod-scheduler.jsenabled input.slotselect { - display: inline; +body.path-mod-scheduler.jsenabled input.slotselect.form-check-input.mt-0 { + display: block; } body.path-mod-scheduler.jsenabled input.studentselectsubmit { @@ -119,13 +125,12 @@ body.path-mod-scheduler.jsenabled input.studentselectsubmit { } .path-mod-scheduler div.schedulelist.halfsize { - width: 46%; + width: 50%; display: inline-table; padding: 3px; } .path-mod-scheduler div.schedulelist.fullsize { - width: 96%; display: block; padding: 3px; } diff --git a/teacherview.php b/teacherview.php index 556fdaf3..78905045 100644 --- a/teacherview.php +++ b/teacherview.php @@ -621,7 +621,7 @@ function scheduler_print_schedulebox(scheduler $scheduler, $studentid, $groupid $maildisplay .= ' — '; $maildisplay .= html_writer::link($reminderurl, get_string('sendreminder', 'scheduler')); - echo $output->box_start('maildisplay'); + echo $output->box_start('maildisplay my-3'); // Print number of students who still have to make an appointment. echo $output->heading(get_string('missingstudents', 'scheduler', count($reminderstudents)), 3); // Print e-mail addresses and mailto links. diff --git a/templates/action_menu_trigger.mustache b/templates/action_menu_trigger.mustache index 98b6029a..8e9bcbf9 100644 --- a/templates/action_menu_trigger.mustache +++ b/templates/action_menu_trigger.mustache @@ -87,7 +87,7 @@ can_edit_all_slots()) || + $action === 'export' || + $action === 'viewstatistics' || + $action === 'addsession' +) { + $PAGE->add_body_class('limitedwidth'); +} // Print the page header. diff --git a/viewstatistics.php b/viewstatistics.php index 6fb8165f..54819f67 100644 --- a/viewstatistics.php +++ b/viewstatistics.php @@ -121,17 +121,17 @@ function byname($a, $b) { $allattendees = ($attendees) ? count($attendees) : 0; $str = '

' . get_string('attendable', 'scheduler') . '

'; - $str .= '' . get_string('attendablelbl', 'scheduler') . ': ' . $allattendees . '
'; + $str .= '

' . get_string('attendablelbl', 'scheduler') . ': ' . $allattendees . '

'; $str .= '

' . get_string('attended', 'scheduler') . '

'; - $str .= '' . get_string('attendedlbl', 'scheduler') . ': ' . $attended . '

'; + $str .= '

' . get_string('attendedlbl', 'scheduler') . ': ' . $attended . '

'; $str .= '

' . get_string('unattended', 'scheduler') . '

'; - $str .= '' . get_string('registeredlbl', 'scheduler') . ': ' . $registered . '
'; + $str .= '

' . get_string('registeredlbl', 'scheduler') . ': ' . $registered . '
'; $str .= '' . get_string('unregisteredlbl', 'scheduler') . ': ' . - ($allattendees - $registered - $attended) . '
'; + ($allattendees - $registered - $attended) . '

'; $str .= '

' . get_string('availableslots', 'scheduler') . '

'; - $str .= '' . get_string('availableslotsowned', 'scheduler') . ': ' . $freeowned . '
'; + $str .= '

' . get_string('availableslotsowned', 'scheduler') . ': ' . $freeowned . '
'; $str .= '' . get_string('availableslotsnotowned', 'scheduler') . ': ' . $freenotowned . '
'; - $str .= '' . get_string('availableslotsall', 'scheduler') . ': ' . ($freeowned + $freenotowned) . '
'; + $str .= '' . get_string('availableslotsall', 'scheduler') . ': ' . ($freeowned + $freenotowned) . '

'; echo $OUTPUT->box($str);