From a85e546e8e2376a9e37bd6959009187b2c9f4a6c Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Tue, 5 Dec 2023 09:33:28 +0100 Subject: [PATCH 001/123] fix wrong command to install plugin --- .github/workflows/moodle-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index 9892893..07ba552 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -56,7 +56,7 @@ jobs: sudo locale-gen en_AU.UTF-8 echo "NVM_DIR=$HOME/.nvm" >> $GITHUB_ENV - - name: Install tool plugin + - name: Install mod plugin run: moodle-plugin-ci add-plugin learnweb/moodle-mod_moodleoverflow - name: Install moodle-plugin-ci From fbf4cea15a66b5003689f83f89cfa972ddcf2936 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Tue, 5 Dec 2023 09:45:18 +0100 Subject: [PATCH 002/123] experiment use of dropdowns for preferences --- templates/main.mustache | 48 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/templates/main.mustache b/templates/main.mustache index ff0a249..b27a5b3 100644 --- a/templates/main.mustache +++ b/templates/main.mustache @@ -21,11 +21,51 @@ }}
- {{!--
- in development -
--}} +
+

+

+ + +

+
+ + +
+ +

+ +
+ + +
+
-
+
{{#content}} {{#isorientationmarker}} From 30ca30ed7ba0b1991a7deb687932a7925795466d Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Wed, 20 Dec 2023 12:52:10 +0100 Subject: [PATCH 003/123] initialization for subplugin support --- classes/townsquaresupportinterface.php | 32 ++++++++++++++++++++++++++ db/subplugins.json | 5 ++++ db/subplugins.php | 23 ++++++++++++++++++ lang/en/block_townsquare.php | 4 ++++ 4 files changed, 64 insertions(+) create mode 100644 classes/townsquaresupportinterface.php create mode 100644 db/subplugins.json create mode 100644 db/subplugins.php diff --git a/classes/townsquaresupportinterface.php b/classes/townsquaresupportinterface.php new file mode 100644 index 0000000..7ee86d7 --- /dev/null +++ b/classes/townsquaresupportinterface.php @@ -0,0 +1,32 @@ +. + +/** + * Interface for the sub-plugin townsquaresupport. + * + * The Plugins of the type townsquaresupport are used to increase the content of the townsquare block. + * Every module that wants to show content on townsquare can implement this interface. + * Every module must: + * - gather "events" for a user that can be transformed into letters. + * - declare if the basic letter structure (letter class and letter template) or a custom one is used. Custom letters must be + * subclasses of the townsquare basic letter and must implement the basic letter template (extension of the template is allowed). + * - provide php_unit test to ensure the correct behaviour. + * The townsquare block will call the export function of the (custom) letter and draw the letter on the dashboard. + * + * @package block_townsquare + * @copyright 2023 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ \ No newline at end of file diff --git a/db/subplugins.json b/db/subplugins.json new file mode 100644 index 0000000..6c64f60 --- /dev/null +++ b/db/subplugins.json @@ -0,0 +1,5 @@ +{ + "plugintypes": { + "townsquaresupport": "blocks/townsquare/supportedmodules" + } +} \ No newline at end of file diff --git a/db/subplugins.php b/db/subplugins.php new file mode 100644 index 0000000..51299ef --- /dev/null +++ b/db/subplugins.php @@ -0,0 +1,23 @@ +. +/** + * This file defines the sub-plugins for the townsquare block. + * + * @package blocks_townsquare + * @copyright 2023 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +$subplugins = (array) json_decode(file_get_contents(__DIR__ . "/subplugins.json"))->plugintypes; \ No newline at end of file diff --git a/lang/en/block_townsquare.php b/lang/en/block_townsquare.php index 7d4a085..cedfbde 100644 --- a/lang/en/block_townsquare.php +++ b/lang/en/block_townsquare.php @@ -40,3 +40,7 @@ // Letter strings. $string['invalidmodulename'] = 'Module name is unknown or not supported'; + +// Subplugin strings. +$string['subplugintype_townsquaresupport'] = 'Supported module'; +$string['subplugintype_townsquaresupport_plural'] = 'Supported modules'; \ No newline at end of file From b2a020ffded239ef8f528ce5a095783ff0169aa5 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 21 Dec 2023 18:40:00 +0100 Subject: [PATCH 004/123] declaration of important functions --- classes/plugininfo/townsquaresupport.php | 42 ++++++++++++++++++++++++ classes/townsquaresupportinterface.php | 23 +++++++++++-- db/subplugins.json | 4 +-- db/subplugins.php | 6 +++- lang/en/block_townsquare.php | 2 +- 5 files changed, 70 insertions(+), 7 deletions(-) create mode 100644 classes/plugininfo/townsquaresupport.php diff --git a/classes/plugininfo/townsquaresupport.php b/classes/plugininfo/townsquaresupport.php new file mode 100644 index 0000000..d0399a7 --- /dev/null +++ b/classes/plugininfo/townsquaresupport.php @@ -0,0 +1,42 @@ +. + +/** + * TODO: Add description. + * + * @package block_townsquare + * @copyright 2023 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace block_townsquare\townsquaresupport; + +use core\plugininfo\base; +/** + * The functions for all sub-plugins of type townsquaresupport. + */ +class townsquaresupport extends base { + + + /** + * Return if a subplugin is allowed to be deleted.. + * + * @return bool + */ + public function is_uninstall_allowed(): bool { + return true; + } +} \ No newline at end of file diff --git a/classes/townsquaresupportinterface.php b/classes/townsquaresupportinterface.php index 7ee86d7..7198610 100644 --- a/classes/townsquaresupportinterface.php +++ b/classes/townsquaresupportinterface.php @@ -21,12 +21,29 @@ * Every module that wants to show content on townsquare can implement this interface. * Every module must: * - gather "events" for a user that can be transformed into letters. - * - declare if the basic letter structure (letter class and letter template) or a custom one is used. Custom letters must be - * subclasses of the townsquare basic letter and must implement the basic letter template (extension of the template is allowed). + * - declare if the basic letter structure (letter class) or a custom one is used. Custom letters must be + * subclasses of the townsquare basic letter. * - provide php_unit test to ensure the correct behaviour. * The townsquare block will call the export function of the (custom) letter and draw the letter on the dashboard. * * @package block_townsquare * @copyright 2023 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ \ No newline at end of file + */ +namespace block_townsquare; + +interface townsquaresupportinterface { + + /** + * Export function for the mustache template + * + * @return array of information about the letter + */ + public function export_letter(): array; + + /** + * Function to gather the events + * @return array of events that can be transformed into letters + */ + public function get_events(): array; +} diff --git a/db/subplugins.json b/db/subplugins.json index 6c64f60..217d83b 100644 --- a/db/subplugins.json +++ b/db/subplugins.json @@ -1,5 +1,5 @@ { "plugintypes": { - "townsquaresupport": "blocks/townsquare/supportedmodules" + "ts_pluginletters": "blocks/townsquare/supportedmodules" } -} \ No newline at end of file +} diff --git a/db/subplugins.php b/db/subplugins.php index 51299ef..362cbbb 100644 --- a/db/subplugins.php +++ b/db/subplugins.php @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + /** * This file defines the sub-plugins for the townsquare block. * @@ -20,4 +21,7 @@ * @copyright 2023 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$subplugins = (array) json_decode(file_get_contents(__DIR__ . "/subplugins.json"))->plugintypes; \ No newline at end of file + +defined('MOODLE_INTERNAL') || die(); + +$subplugins = (array) json_decode(file_get_contents(__DIR__ . "/subplugins.json"))->plugintypes; diff --git a/lang/en/block_townsquare.php b/lang/en/block_townsquare.php index cedfbde..6e607c3 100644 --- a/lang/en/block_townsquare.php +++ b/lang/en/block_townsquare.php @@ -43,4 +43,4 @@ // Subplugin strings. $string['subplugintype_townsquaresupport'] = 'Supported module'; -$string['subplugintype_townsquaresupport_plural'] = 'Supported modules'; \ No newline at end of file +$string['subplugintype_townsquaresupport_plural'] = 'Supported modules'; From e59fe3a03a5518385fdec3682253d51d8388452c Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Wed, 10 Jan 2024 12:01:05 +0100 Subject: [PATCH 005/123] change color variables, add optional admin setting page --- block_townsquare.php | 9 +++++++ lang/en/block_townsquare.php | 17 +++++++++++++ lib.php | 29 ++++++++++++++++++++++ settings.php | 48 ++++++++++++++++++++++++++++++++++++ styles.css | 11 ++++++--- version.php | 2 +- 6 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 lib.php create mode 100644 settings.php diff --git a/block_townsquare.php b/block_townsquare.php index e3475ac..8a3554b 100644 --- a/block_townsquare.php +++ b/block_townsquare.php @@ -70,4 +70,13 @@ public function applicable_formats():array { 'my' => true, ]; } + + /** + * Returns true if this block has global config. + * + * @return bool + */ + public function has_config() { + return false; + } } diff --git a/lang/en/block_townsquare.php b/lang/en/block_townsquare.php index 7d4a085..3ef8dd0 100644 --- a/lang/en/block_townsquare.php +++ b/lang/en/block_townsquare.php @@ -40,3 +40,20 @@ // Letter strings. $string['invalidmodulename'] = 'Module name is unknown or not supported'; + +// Setting strings. +$string['primarycolor'] = 'Primary color'; +$string['secondarycolor'] = 'Secondary color'; +$string['bluecolor'] = 'Blue color'; +$string['orangecolor'] = 'Orange color'; +$string['redcolor'] = 'Red color'; +$string['graycolor'] = 'Gray color'; + +$string['basiclettercolor'] = 'Color for basic letters'; +$string['completionlettercolor'] = 'Color for activity completion letters'; +$string['postlettercolor'] = 'Color for post letters'; +$string['orientationmarkercolor'] = 'Color for the orientation marker'; +$string['configbasiclettercolor'] = 'Configuration for the color of the basic notification letters'; +$string['configcompletionlettercolor'] = 'Configuration for the color of the activity completion letters'; +$string['configpostlettercolor'] = 'Configuration for the color of the post letters'; +$string['configorientationmarkercolor'] = 'Configuration for the color of the orientation marker'; \ No newline at end of file diff --git a/lib.php b/lib.php new file mode 100644 index 0000000..0199c93 --- /dev/null +++ b/lib.php @@ -0,0 +1,29 @@ +. + +/** + * Library for the townsquare block. + * + * @package block_townsquare + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +// Color constants. +define('TOWNSQUARE_PRIMARY_COLOR', 0); +define('TOWNSQUARE_SECONDARY_COLOR', 1); +define('TOWNSQUARE_BLUE_COLOR', 2); +define('TOWNSQUARE_GRAY_COLOR', 3); \ No newline at end of file diff --git a/settings.php b/settings.php new file mode 100644 index 0000000..84273aa --- /dev/null +++ b/settings.php @@ -0,0 +1,48 @@ +. + +/** + * File for the settings of moodleoverflow. + * + * @package blocks_townsquare + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die; + +if ($ADMIN->fulltree) { + require_once($CFG->dirroot . '/blocks/townsquare/lib.php'); + + // Color Setting for basic letters. + $basicletteroptions = []; + $basicletteroptions[TOWNSQUARE_PRIMARY_COLOR] = get_string('primarycolor', 'block_townsquare'); + $basicletteroptions[TOWNSQUARE_BLUE_COLOR] = get_string('bluecolor', 'block_townsquare'); + $settings->add(new admin_setting_configselect('block_townsquare/basiclettercolor', + get_string('basiclettercolor', 'block_townsquare'), + get_string('configbasiclettercolor', 'block_townsquare'), + TOWNSQUARE_PRIMARY_COLOR, $basicletteroptions)); + + // Color Setting for the orientation marker. + $orientationmarkeroptions = []; + $orientationmarkeroptions[TOWNSQUARE_SECONDARY_COLOR] = get_string('secondarycolor', 'block_townsquare'); + $orientationmarkeroptions[TOWNSQUARE_GRAY_COLOR] = get_string('graycolor', 'block_townsquare'); + $settings->add(new admin_setting_configselect('block_townsquare/orientationmarkercolor', + get_string('orientationmarkercolor', 'block_townsquare'), + get_string('configorientationmarkercolor', 'block_townsquare'), + TOWNSQUARE_SECONDARY_COLOR, $orientationmarkeroptions)); + +} diff --git a/styles.css b/styles.css index 659c3f7..03dd51b 100644 --- a/styles.css +++ b/styles.css @@ -56,11 +56,14 @@ /* basicletter Style*/ .basicletter.card { - border-color: var(--primary); + /*border-color: var(--primary);*/ + border-color: var(--blue); } .basicletter_header.card-header { - background-color: var(--primary); + /*background-color: var(--primary);*/ + background-color: var(--blue); + } /* postletter Style */ @@ -89,8 +92,8 @@ /* Style for the orientation marker */ .orientationmarker.card { - border-color: var(--secondary); - background-color: var(--secondary); + border-color: var(--gray); + background-color: var(--gray); } .orientationmarker_body.card-body { diff --git a/version.php b/version.php index 6891541..0d3a1fc 100644 --- a/version.php +++ b/version.php @@ -25,6 +25,6 @@ defined('MOODLE_INTERNAL') || die(); $plugin->component = 'block_townsquare'; $plugin->release = '0.1.0'; -$plugin->version = 2023092003; +$plugin->version = 2024011001; $plugin->requires = 2022041900; $plugin->maturity = MATURITY_ALPHA; From 19f5c55f98988d4ff1cfa8a5010d1c79c66f8e1b Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Wed, 10 Jan 2024 13:54:49 +0100 Subject: [PATCH 006/123] codecheck fix --- classes/plugininfo/townsquaresupport.php | 30 +++++++++++++++++++++++- classes/townsquaresupportinterface.php | 11 +++++---- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/classes/plugininfo/townsquaresupport.php b/classes/plugininfo/townsquaresupport.php index d0399a7..173e293 100644 --- a/classes/plugininfo/townsquaresupport.php +++ b/classes/plugininfo/townsquaresupport.php @@ -39,4 +39,32 @@ class townsquaresupport extends base { public function is_uninstall_allowed(): bool { return true; } -} \ No newline at end of file + + /** + * Checks whether sub-plugins have settings.php and adds them to the admin menu. + * In Case a sub-plugin is added the settings.php has to include all global variables it needs. + * + * @param \part_of_admin_tree $adminroot + * @param string $parentnodename + * @param bool $hassiteconfig + */ + public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { + $ADMIN = $adminroot; // May be used in settings.php. + + if (!$this->is_installed_and_upgraded()) { + return; + } + + if (!$hassiteconfig || !file_exists($this->full_path('settings.php'))) { + return; + } + + $section = $this->get_settings_section_name(); + $settings = new admin_settingpage($section, $this->displayname, 'moodle/site:config', $this->is_enabled() === false); + include($this->full_path('settings.php')); // This may also set $settings to null. + + if ($settings) { + $ADMIN->add($parentnodename, $settings); + } + } +} diff --git a/classes/townsquaresupportinterface.php b/classes/townsquaresupportinterface.php index 7198610..a78a69b 100644 --- a/classes/townsquaresupportinterface.php +++ b/classes/townsquaresupportinterface.php @@ -34,6 +34,12 @@ interface townsquaresupportinterface { + /** + * Function to gather the events + * @return array of events that can be transformed into letters + */ + public function get_events(): array; + /** * Export function for the mustache template * @@ -41,9 +47,4 @@ interface townsquaresupportinterface { */ public function export_letter(): array; - /** - * Function to gather the events - * @return array of events that can be transformed into letters - */ - public function get_events(): array; } From ed6b01a855e49a2cd0db308f6e0d8b62329eb5e7 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 11 Jan 2024 11:59:31 +0100 Subject: [PATCH 007/123] new locallib for global functions --- locallib.php | 86 +++++++++++++++++++ ...darevents_test.php => coreevents_test.php} | 4 +- 2 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 locallib.php rename tests/{calendarevents_test.php => coreevents_test.php} (98%) diff --git a/locallib.php b/locallib.php new file mode 100644 index 0000000..a3eff75 --- /dev/null +++ b/locallib.php @@ -0,0 +1,86 @@ +. + +/** + * Internal library of functions for the townsquare block + * + * @package block_townsquare + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * Gets the id of all courses where the current user is enrolled + * @return array + */ +function townsquare_get_courses(): array { + global $USER; + + $enrolledcourses = enrol_get_all_users_courses($USER->id, true); + $courses = []; + foreach ($enrolledcourses as $enrolledcourse) { + $courses[] = $enrolledcourse->id; + } + + return $courses; +} + +/** + * Merge sort function for townsquare events. + * @param $events + * @return array + */ +function townsquare_mergesort($events): array { + $length = count($events); + if ($length <= 1) { + return $events; + } + $mid = (int) ($length / 2); + $left = townsquare_mergesort(array_slice($events, 0, $mid)); + $right = townsquare_mergesort(array_slice($events, $mid)); + return townsquare_merge($left, $right); +} + +/** + * Function that sorts events in descending order by time created (newest event first) + * @param array $left + * @param array $right + * @return array + */ +function townsquare_merge(array $left, array $right): array { + $result = []; + reset($left); + reset($right); + $numberofelements = count($left) + count($right); + for ($i = 0; $i < $numberofelements; $i++) { + if (current($left) && current($right)) { + if (current($left)->timestart > current($right)->timestart) { + $result[$i] = current($left); + next($left); + } else { + $result[$i] = current($right); + next($right); + } + } else if (current($left)) { + $result[$i] = current($left); + next($left); + } else { + $result[$i] = current($right); + next($right); + } + } + return $result; +} diff --git a/tests/calendarevents_test.php b/tests/coreevents_test.php similarity index 98% rename from tests/calendarevents_test.php rename to tests/coreevents_test.php index bb96efd..269605b 100644 --- a/tests/calendarevents_test.php +++ b/tests/coreevents_test.php @@ -39,7 +39,7 @@ * @copyright 2023 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * - * @covers \block_townsquare\townsquareevents::get_calendarevents() + * @covers \block_townsquare\townsquareevents::get_coreevents() */ class calendarevents_test extends \advanced_testcase { @@ -298,7 +298,7 @@ private function create_assignment($courseid, $allowsubmissionsdate, $duedate, $ private function get_calendarevents_from_user($user):array { $this->setUser($user); $townsquareevents = new townsquareevents(); - return $townsquareevents->get_calendarevents(); + return $townsquareevents->get_coreevents(); } From 536d50ffea996a2afb9661e7de83ed4606538c09 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 11 Jan 2024 12:26:48 +0100 Subject: [PATCH 008/123] support for subplugins implemented --- classes/contentcontroller.php | 2 +- classes/letter/letter.php | 7 +- classes/letter/post_letter.php | 2 +- classes/plugininfo/townsquaresupport.php | 1 - classes/townsquareevents.php | 122 +++++++++++------------ classes/townsquaresupportinterface.php | 20 ++-- tests/coreevents_test.php | 4 +- tests/postevents_test.php | 4 +- 8 files changed, 79 insertions(+), 83 deletions(-) diff --git a/classes/contentcontroller.php b/classes/contentcontroller.php index 45a3535..45e24c8 100644 --- a/classes/contentcontroller.php +++ b/classes/contentcontroller.php @@ -68,7 +68,7 @@ public function build_content():array { // Display a orientation marker on the current date between the other events. if (!$orientationmarkerset && isset($event->eventtype) && ( ($event->eventtype != 'post' && $event->timestart <= $time) || - ($event->eventtype == 'post' && $event->postcreated <= $time))) { + ($event->eventtype == 'post' && $event->timestart <= $time))) { $orientationmarkerset = true; $tempcontent = new orientation_marker($index, $time); diff --git a/classes/letter/letter.php b/classes/letter/letter.php index 326ffb4..ff23081 100644 --- a/classes/letter/letter.php +++ b/classes/letter/letter.php @@ -84,7 +84,7 @@ class letter { * @param int $courseid Course ID from where the content comes from. * @param string $modulename Name of the module/activity. * @param string $instancename Name of the instance. - * @param mixed $content The content that will be showed in the letter. + * @param string $content The content that will be showed in the letter. * @param int $created Timestamp of creation. * @param int $cmid Course module id of the content module. */ @@ -109,9 +109,6 @@ public function __construct($contentid, $courseid, $modulename, $instancename, $ * @return array */ public function export_letter() { - // Change the timestamp to a date. - $date = date('d.m.Y', $this->created); - return [ 'contentid' => $this->contentid, 'lettertype' => $this->lettertype, @@ -120,7 +117,7 @@ public function export_letter() { 'coursename' => $this->coursename, 'instancename' => $this->instancename, 'content' => $this->content, - 'created' => $date, + 'created' => date('d.m.Y', $this->created), 'linktocourse' => $this->linktocourse->out(), 'linktoactivity' => $this->linktoactivity->out(), ]; diff --git a/classes/letter/post_letter.php b/classes/letter/post_letter.php index 74ea8a5..d514a42 100644 --- a/classes/letter/post_letter.php +++ b/classes/letter/post_letter.php @@ -80,7 +80,7 @@ class post_letter extends letter { */ public function __construct($contentid, $postevent) { parent::__construct($contentid, $postevent->courseid, $postevent->modulename, $postevent->instancename, - $postevent->postmessage, $postevent->postcreated, $postevent->coursemoduleid); + $postevent->postmessage, $postevent->timestart, $postevent->coursemoduleid); $this->author = new stdClass(); $this->post = new stdClass(); diff --git a/classes/plugininfo/townsquaresupport.php b/classes/plugininfo/townsquaresupport.php index 173e293..0a23e33 100644 --- a/classes/plugininfo/townsquaresupport.php +++ b/classes/plugininfo/townsquaresupport.php @@ -30,7 +30,6 @@ */ class townsquaresupport extends base { - /** * Return if a subplugin is allowed to be deleted.. * diff --git a/classes/townsquareevents.php b/classes/townsquareevents.php index 04fa1b4..c4aaec8 100644 --- a/classes/townsquareevents.php +++ b/classes/townsquareevents.php @@ -30,6 +30,7 @@ global $CFG; require_once($CFG->dirroot . '/calendar/lib.php'); +require_once($CFG->dirroot . '/blocks/townsquare/locallib.php'); /** * Class to get events and posts that will be shown in the townsquare block.. @@ -60,7 +61,7 @@ public function __construct() { $this->timenow = time(); $this->timestart = $this->timenow - 15768000; $this->timeend = $this->timenow + 15768000; - $this->courses = $this->get_courses(); + $this->courses = townsquare_get_courses(); } /** @@ -68,60 +69,61 @@ public function __construct() { * @return array */ public function get_all_events_sorted(): array { - $calendarevents = $this->get_calendarevents(); + $coreevents = $this->get_coreevents(); $postevents = $this->get_postevents(); + $subpluginevents = $this->get_subpluginevents(); // Merge the events in a sorted order. - $events = []; - $numberofevents = count($calendarevents) + count($postevents); - for ($i = 0; $i < $numberofevents; $i++) { - if (current($calendarevents) && current($postevents)) { - if (current($calendarevents)->timestart > current($postevents)->postcreated) { - $events[$i] = current($calendarevents); - next($calendarevents); - } else { - $events[$i] = current($postevents); - next($postevents); - } - } else if (current($calendarevents)) { - $events[$i] = current($calendarevents); - next($calendarevents); - } else { - $events[$i] = current($postevents); - next($postevents); - } - } - - return $events; + $events = $coreevents + $postevents + $subpluginevents; + return townsquare_mergesort($events); } /** - * Function to get events from that are in the calendar for the current user. + * Function to get events/notifications from core plugins for the current user. * * The events are sorted in descending order by time created (newest event first) * @return array */ - public function get_calendarevents(): array { + public function get_coreevents(): array { global $DB; // Get all events from the last six months and the next six months. - $calendarevents = $this->get_events_from_db($this->timestart, $this->timeend, $this->courses); + $coreevents = $this->get_events_from_db($this->timestart, $this->timeend, $this->courses); - // Filter the events and add the coursemoduleid. - foreach ($calendarevents as $calendarevent) { + // Filter the events and add the instancename. + foreach ($coreevents as $coreevent) { // Filter out events that are not relevant for the user. - if ($this->filter_availability($calendarevent) || - ($calendarevent->modulename == "assign" && $this->filter_assignment($calendarevent)) || - ($calendarevent->eventtype == "expectcompletionon" && $this->filter_activitycompletions($calendarevent))) { - unset($calendarevents[$calendarevent->id]); + if ($this->filter_availability($coreevent) || + ($coreevent->modulename == "assign" && $this->filter_assignment($coreevent)) || + ($coreevent->eventtype == "expectcompletionon" && $this->filter_activitycompletions($coreevent))) { + unset($coreevents[$coreevent->id]); continue; } // Add the name of the instance to the event. - $calendarevent->instancename = $DB->get_field($calendarevent->modulename, 'name', ['id' => $calendarevent->instance]); + $coreevent->instancename = $DB->get_field($coreevent->modulename, 'name', ['id' => $coreevent->instance]); } - return $calendarevents; + return $coreevents; + } + + /** + * Function to get events/notifications from other plugins than core plugins for the current user. + * This function checks for subplugins and calls their get_events() function. + * + * The events are sorted in descending order by time created (newest event first) + * @return array + */ + public function get_subpluginevents(): array { + // Get all available subplugins. + $events = []; + $subplugins = \core_plugin_manager::instance()->get_plugins_of_type('ts_pluginletters'); + + foreach ($subplugins as $subplugin) { + $events += $subplugin->get_events(); + } + // Sort the events and return them. + return townsquare_mergesort($events); } /** @@ -140,7 +142,7 @@ public function get_postevents(): array { if ($DB->get_record('modules', ['name' => 'forum', 'visible' => 1])) { $forumposts = $this->get_posts_from_db('forum', $this->courses, $this->timestart); } - + // TODO: implement support for moodleoverflow in a subplugin. if ($DB->get_record('modules', ['name' => 'moodleoverflow', 'visible' => 1])) { $moodleoverflowposts = $this->get_posts_from_db('moodleoverflow', $this->courses, $this->timestart); } @@ -172,7 +174,7 @@ public function get_postevents(): array { // Merge. if (current($forumposts) && current($moodleoverflowposts)) { - if (current($forumposts)->postcreated > current($moodleoverflowposts)->postcreated) { + if (current($forumposts)->timestart > current($moodleoverflowposts)->timestart) { $posts[$i] = current($forumposts); next($forumposts); } else { @@ -225,7 +227,7 @@ private function get_posts_from_db($modulename, $courses, $timestart): array { posts.discussion AS postdiscussion, posts.parent AS postparentid, posts.userid AS postuserid, - posts.created AS postcreated, + posts.created AS timestart, posts.message AS postmessage "; // Extend the strings for the 2 module cases. @@ -265,7 +267,7 @@ private function get_posts_from_db($modulename, $courses, $timestart): array { /** * Searches for events in the events table, that are relevant to the timeline. - * This is a helper function for get_calendarevents(). + * This is a helper function for get_coreevents(). * @param int $timestart The time from where the events should be searched. Not equal to timestart in the database events table. * @param int $timeend The time until where the events should be searched. * @param array $courses The ids of the courses where the events should be searched. @@ -307,25 +309,23 @@ private function get_events_from_db($timestart, $timeend, $courses): array { return $DB->get_records_sql($sql, $params); } + /** - * Gets the id of all courses where the current user is enrolled + * help function to sort and merge 2 array of events. + * Note that each of the arrays are already sorted in descending order by time created (newest event first). + * @param array $leftarray The first array of events. + * @param array $rightarray The second array of events. + * * @return array */ - private function get_courses(): array { - global $USER; - - $enrolledcourses = enrol_get_all_users_courses($USER->id, true); - $courses = []; - foreach ($enrolledcourses as $enrolledcourse) { - $courses[] = $enrolledcourse->id; - } - - return $courses; + private function merge_events($leftarray, $rightarray, ): array { + // TODO: merge sort events. + return []; } /** * Filter that checks if the event needs to be filtered out for the current user because it is unavailable. - * Applies to restriction that are defined in the module setting (restrict access). + * Applies to restrictions that are defined in the module setting (restrict access). * @param object $event The event that is checked. * @return bool true if the event needs to filtered out, false if not. */ @@ -348,19 +348,19 @@ private function filter_availability($event): bool { /** * Filter that checks if the event needs to be filtered out for the current user. * Applies to assignment events. - * @param object $calendarevent calendarevent that is checked + * @param object $coreevent coreevent that is checked * @return bool true if the event needs to filtered out, false if not. */ - private function filter_assignment($calendarevent): bool { + private function filter_assignment($coreevent): bool { global $DB; - $assignment = $DB->get_record('assign', ['id' => $calendarevent->instance]); - + $assignment = $DB->get_record('assign', ['id' => $coreevent->instance]); + $type = $coreevent->eventtype; // Check if the assign is longer than a week closed. - $overduecheck = $calendarevent->eventtype == "due" && $this->timenow >= ($calendarevent->timestart + 604800); + $overduecheck = ($type == "due" || $type == "gradingdue") && ($this->timenow >= ($coreevent->timestart + 604800)); // Check if the user is someone without grading capability. - $nogradecapabilitycheck = $calendarevent->eventtype == "gradingdue" && !has_capability('mod/assign:grade', - context_module::instance($calendarevent->coursemoduleid)); + $nogradecapabilitycheck = $coreevent->eventtype == "gradingdue" && !has_capability('mod/assign:grade', + context_module::instance($coreevent->coursemoduleid)); // Check if the assignment is not open yet. $stillclosedcheck = $assignment->allowsubmissionsfromdate >= $this->timenow; @@ -371,15 +371,15 @@ private function filter_assignment($calendarevent): bool { } /** - * Filter that checks if the event needs to be filtered out for the current user. + * Filter that checks if the event needs to be filtered out for the current user because it is already completed.. * Applies to activity completion events. - * @param object $calendarevent calendarevent that is checked + * @param object $coreevent coreevent that is checked * @return bool true if the event needs to filtered out, false if not. */ - private function filter_activitycompletions($calendarevent): bool { + private function filter_activitycompletions($coreevent): bool { global $DB, $USER; if ($completionstatus = $DB->get_record('course_modules_completion', - ['coursemoduleid' => $calendarevent->coursemoduleid, 'userid' => $USER->id])) { + ['coursemoduleid' => $coreevent->coursemoduleid, 'userid' => $USER->id])) { if ($completionstatus->completionstate != 0) { return true; } diff --git a/classes/townsquaresupportinterface.php b/classes/townsquaresupportinterface.php index a78a69b..c39d873 100644 --- a/classes/townsquaresupportinterface.php +++ b/classes/townsquaresupportinterface.php @@ -21,8 +21,6 @@ * Every module that wants to show content on townsquare can implement this interface. * Every module must: * - gather "events" for a user that can be transformed into letters. - * - declare if the basic letter structure (letter class) or a custom one is used. Custom letters must be - * subclasses of the townsquare basic letter. * - provide php_unit test to ensure the correct behaviour. * The townsquare block will call the export function of the (custom) letter and draw the letter on the dashboard. * @@ -36,15 +34,17 @@ interface townsquaresupportinterface { /** * Function to gather the events + * Every event must gain sufficient data so that townsquare can build a letter from it. + * The array should contain following information: + * [courseid] => int Course ID from where the content comes from. + * [modulename] => string Name of the activity module. + * [instancename] => string Name of the instance that shows the notification. + * [content] => string The content that will be showed in the letter. + * [timestart] => int Timestamp that represents the deadline/creation of a notification. Is important to sort events. + * [coursemoduleid] => int Course module id of the content module. + * [eventtype] => string Type of the event. + * * @return array of events that can be transformed into letters */ public function get_events(): array; - - /** - * Export function for the mustache template - * - * @return array of information about the letter - */ - public function export_letter(): array; - } diff --git a/tests/coreevents_test.php b/tests/coreevents_test.php index 269605b..2aba11f 100644 --- a/tests/coreevents_test.php +++ b/tests/coreevents_test.php @@ -33,7 +33,7 @@ */ /** - * PHPUnit tests for testing the process of collecting post events. + * PHPUnit tests for testing the process of collecting calendar events from core plugins. * * @package block_townsquare * @copyright 2023 Tamaro Walter @@ -41,7 +41,7 @@ * * @covers \block_townsquare\townsquareevents::get_coreevents() */ -class calendarevents_test extends \advanced_testcase { +class coreevents_test extends \advanced_testcase { // Attributes. diff --git a/tests/postevents_test.php b/tests/postevents_test.php index aba6828..42dfee5 100644 --- a/tests/postevents_test.php +++ b/tests/postevents_test.php @@ -80,8 +80,8 @@ public function test_sortorder(): void { $timestamp = 9999999999; $result = true; foreach ($posts as $post) { - if ($timestamp >= $post->postcreated) { - $timestamp = $post->postcreated; + if ($timestamp >= $post->timestart) { + $timestamp = $post->timestart; } else { $result = false; } From bfad7f22614e5cb4dd6aea729af0d1e685407554 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Mon, 15 Jan 2024 11:44:16 +0100 Subject: [PATCH 009/123] subplugin for moodleoverflow initialized --- classes/townsquareevents.php | 35 ++----- classes/townsquaresupportinterface.php | 2 +- db/subplugins.json | 2 +- locallib.php | 32 +++++++ .../block_ts_moodleoverflow.php | 78 +++++++++++++++ .../lang/en/block_ts_moodleoverflow.php | 29 ++++++ .../block_ts_moodleoverflow/locallib.php | 95 +++++++++++++++++++ .../block_ts_moodleoverflow/version.php | 30 ++++++ templates/blockcontent.mustache | 2 +- 9 files changed, 274 insertions(+), 31 deletions(-) create mode 100644 supportedmodules/block_ts_moodleoverflow/block_ts_moodleoverflow.php create mode 100644 supportedmodules/block_ts_moodleoverflow/lang/en/block_ts_moodleoverflow.php create mode 100644 supportedmodules/block_ts_moodleoverflow/locallib.php create mode 100644 supportedmodules/block_ts_moodleoverflow/version.php diff --git a/classes/townsquareevents.php b/classes/townsquareevents.php index c4aaec8..5941f39 100644 --- a/classes/townsquareevents.php +++ b/classes/townsquareevents.php @@ -93,7 +93,7 @@ public function get_coreevents(): array { // Filter the events and add the instancename. foreach ($coreevents as $coreevent) { // Filter out events that are not relevant for the user. - if ($this->filter_availability($coreevent) || + if (townsquare_filter_availability($coreevent) || ($coreevent->modulename == "assign" && $this->filter_assignment($coreevent)) || ($coreevent->eventtype == "expectcompletionon" && $this->filter_activitycompletions($coreevent))) { unset($coreevents[$coreevent->id]); @@ -117,11 +117,12 @@ public function get_coreevents(): array { public function get_subpluginevents(): array { // Get all available subplugins. $events = []; - $subplugins = \core_plugin_manager::instance()->get_plugins_of_type('ts_pluginletters'); - + $subplugins = \core_plugin_manager::instance()->get_plugins_of_type('ts_supportedmodules'); + var_dump($subplugins); foreach ($subplugins as $subplugin) { $events += $subplugin->get_events(); } + // Sort the events and return them. return townsquare_mergesort($events); } @@ -144,7 +145,7 @@ public function get_postevents(): array { } // TODO: implement support for moodleoverflow in a subplugin. if ($DB->get_record('modules', ['name' => 'moodleoverflow', 'visible' => 1])) { - $moodleoverflowposts = $this->get_posts_from_db('moodleoverflow', $this->courses, $this->timestart); + //$moodleoverflowposts = $this->get_posts_from_db('moodleoverflow', $this->courses, $this->timestart); } if (empty($forumposts) && empty($moodleoverflowposts)) { @@ -159,11 +160,11 @@ public function get_postevents(): array { for ($i = 0; $i < $numberofposts; $i++) { // Filter unavailable posts. // Iterate until the first post that is available. Decrement the number of posts each time a post is filtered. - while (current($forumposts) && $this->filter_availability(current($forumposts))) { + while (current($forumposts) && townsquare_filter_availability(current($forumposts))) { next($forumposts); $numberofposts--; } - while (current($moodleoverflowposts) && $this->filter_availability(current($moodleoverflowposts))) { + while (current($moodleoverflowposts) && townsquare_filter_availability(current($moodleoverflowposts))) { next($moodleoverflowposts); $numberofposts--; } @@ -323,28 +324,6 @@ private function merge_events($leftarray, $rightarray, ): array { return []; } - /** - * Filter that checks if the event needs to be filtered out for the current user because it is unavailable. - * Applies to restrictions that are defined in the module setting (restrict access). - * @param object $event The event that is checked. - * @return bool true if the event needs to filtered out, false if not. - */ - private function filter_availability($event): bool { - // If there is no restriction defined, the event is available. - if ($event->availability == null) { - return false; - } - - // If there is a restriction, check if it applies to the user. - $modinfo = get_fast_modinfo($event->courseid); - $moduleinfo = $modinfo->get_cm($event->coursemoduleid); - if ($moduleinfo->uservisible) { - return false; - } - - return true; - } - /** * Filter that checks if the event needs to be filtered out for the current user. * Applies to assignment events. diff --git a/classes/townsquaresupportinterface.php b/classes/townsquaresupportinterface.php index c39d873..61044da 100644 --- a/classes/townsquaresupportinterface.php +++ b/classes/townsquaresupportinterface.php @@ -28,7 +28,7 @@ * @copyright 2023 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -namespace block_townsquare; +namespace block_townsquare\townsquaresupport; interface townsquaresupportinterface { diff --git a/db/subplugins.json b/db/subplugins.json index 217d83b..b64dfea 100644 --- a/db/subplugins.json +++ b/db/subplugins.json @@ -1,5 +1,5 @@ { "plugintypes": { - "ts_pluginletters": "blocks/townsquare/supportedmodules" + "ts_supportedmodules": "blocks/townsquare/supportedmodules" } } diff --git a/locallib.php b/locallib.php index a3eff75..0c63baf 100644 --- a/locallib.php +++ b/locallib.php @@ -38,6 +38,22 @@ function townsquare_get_courses(): array { return $courses; } +/** + * Function for subplugins to get the start time of the search. + * @return int + */ +function townsquare_get_timestart(): int { + return time() - 15768000; +} + +/** + * Function for subplugins to get the end time of the search. + * @return int + */ +function townsquare_get_timeend(): int { + return time() + 15768000; +} + /** * Merge sort function for townsquare events. * @param $events @@ -84,3 +100,19 @@ function townsquare_merge(array $left, array $right): array { } return $result; } + +function townsquare_filter_availability($event): bool { + // If there is no restriction defined, the event is available. + if ($event->availability == null) { + return false; + } + + // If there is a restriction, check if it applies to the user. + $modinfo = get_fast_modinfo($event->courseid); + $moduleinfo = $modinfo->get_cm($event->coursemoduleid); + if ($moduleinfo->uservisible) { + return false; + } + + return true; +} \ No newline at end of file diff --git a/supportedmodules/block_ts_moodleoverflow/block_ts_moodleoverflow.php b/supportedmodules/block_ts_moodleoverflow/block_ts_moodleoverflow.php new file mode 100644 index 0000000..34436ff --- /dev/null +++ b/supportedmodules/block_ts_moodleoverflow/block_ts_moodleoverflow.php @@ -0,0 +1,78 @@ +. + +use block_townsquare\townsquaresupport; +use block_townsquare\townsquaresupport\townsquaresupportinterface; + +global $CFG; +require_once($CFG->dirroot . '/blocks/townsquare/supportedmodules/block_ts_moodleoverflow/locallib.php'); + +/** + * Plugin strings are defined here. + * + * @package block_townsquare + * @copyright 2023 Tamaro Walter + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class block_ts_moodleoverflow extends block_base implements townsquaresupportinterface { + + /** + * Initialises the block. + * + * @return void + */ + public function init(): void { + $this->title = get_string('pluginname', 'block_townsquare'); + } + + /** + * Gets the block contents. + * + * @return object|null The block HTML. + */ + public function get_content(): object { + global $OUTPUT; + + if ($this->content !== null) { + return $this->content; + } + + $this->content = new stdClass(); + $this->content->text = "hallo"; + return $this->content; + } + + public function get_events(): array { + $courses = townsquare_get_courses(); + $timestart = townsquare_get_timestart(); + return ts_moodleoverflow_get_events($courses, $timestart); + } + + /** + * Defines in which pages this block can be added. + * + * @return array of the pages where the block can be added. + */ + public function applicable_formats():array { + return [ + 'admin' => false, + 'site-index' => false, + 'course-view' => false, + 'mod' => false, + 'my' => false, + ]; + } +} diff --git a/supportedmodules/block_ts_moodleoverflow/lang/en/block_ts_moodleoverflow.php b/supportedmodules/block_ts_moodleoverflow/lang/en/block_ts_moodleoverflow.php new file mode 100644 index 0000000..511feac --- /dev/null +++ b/supportedmodules/block_ts_moodleoverflow/lang/en/block_ts_moodleoverflow.php @@ -0,0 +1,29 @@ +. + +/** + * Plugin strings for the townsquare subplugin for moodleoverflow support. + * + * @package block_ts_moodleoverflow + * @category string + * @copyright 2024 Tamaro Walter + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +$string['pluginname'] = 'Moodleoverflow support for townsquare block'; +$string['pluginnameadding'] = "Adding a Moodleoverflow support subplugin"; +$string['pluginnameediting'] = "Editing a Moodleoverflow support subplugin"; +$string['pluginnamesummary'] = "This subplugin allows the townsquare block to show new posts from moodleoverflow."; +$string['pluginname_help'] = 'This subplugin allows the townsquare block to show posts from moodleoverflow.'; diff --git a/supportedmodules/block_ts_moodleoverflow/locallib.php b/supportedmodules/block_ts_moodleoverflow/locallib.php new file mode 100644 index 0000000..a63d8a2 --- /dev/null +++ b/supportedmodules/block_ts_moodleoverflow/locallib.php @@ -0,0 +1,95 @@ +. + +/** + * Internal library of functions for the ts_moodleoverflow subplugin + * + * @package block_townsquare + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +global $CFG; +require_once($CFG->dirroot . '/blocks/townsquare/locallib.php'); + +/** + * Function to get the newest post from the moodleoverflow module. + * @param array $courses The courses that will searched. + * @param int $timestart The start time of the search. + * @param int $timeend The end time of the search. + * @return array + */ +function ts_moodleoverflow_get_events($courses, $timestart): array { + global $DB; + + // If moodleoverflow is not installed or not activated, return empty array. + if (!$DB->get_record('modules', ['name' => 'forum', 'visible' => 1])) { + return []; + } + + // Get posts from the database. + $posts = ts_moodleoverflow_get_post_from_db($courses, $timestart); + + // Filter posts by availability. + foreach($posts as $post) { + if (townsquare_filter_availability($post)) { + unset($posts[$post->row_num]); + } + } + + return $posts; +} + +function ts_moodleoverflow_get_post_from_db($courses, $timestart): array { + global $DB; + // Prepare params for sql statement. + list($insqlcourses, $inparamscourses) = $DB->get_in_or_equal($courses, SQL_PARAMS_NAMED); + $params = ['courses' => $courses, 'timestart' => $timestart] + $inparamscourses; + + $sql = "SELECT (ROW_NUMBER() OVER (ORDER BY posts.id)) AS row_num, + 'moodleoverflow' AS modulename, + module.id AS instanceid, + module.anonymous AS anonymoussetting, + 'post' AS eventtype, + cm.id AS coursemoduleid, + cm.availability AS availability, + module.name AS instancename, + discuss.course AS courseid, + discuss.userid AS discussionuserid, + discuss.name AS discussionsubject, + u.firstname AS postuserfirstname, + u.lastname AS postuserlastname, + posts.id AS postid, + posts.discussion AS postdiscussion, + posts.parent AS postparentid, + posts.userid AS postuserid, + posts.created AS timestart, + posts.message AS postmessage + FROM {moodleoverflow_posts} posts + JOIN {moodleoverflow_discussions} discuss ON discuss.id = posts.discussion + JOIN {moodleoverflow} module ON module.id = discuss.moodleoverflow + JOIN {modules} modules ON modules.name = 'moodleoverflow' + JOIN {user} u ON u.id = posts.userid + JOIN {course_modules} cm ON (cm.course = module.course AND cm.module = modules.id AND cm.instance = module.id) + WHERE discuss.course $insqlcourses + AND posts.created > :timestart + AND cm.visible = 1 + AND modules.visible = 1 + ORDER BY posts.created DESC;"; + + return $DB->get_records_sql($sql, $params); +} + diff --git a/supportedmodules/block_ts_moodleoverflow/version.php b/supportedmodules/block_ts_moodleoverflow/version.php new file mode 100644 index 0000000..06d77c6 --- /dev/null +++ b/supportedmodules/block_ts_moodleoverflow/version.php @@ -0,0 +1,30 @@ +. + +/** + * Plugin version and other meta-data are defined here. + * + * @package block_ts_moodleoverflow + * @copyright 2023 Tamaro Walter + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); +$plugin->component = 'block_ts_moodleoverflow'; +$plugin->release = '0.1.0'; +$plugin->version = 2024011500; +$plugin->requires = 2022041900; +$plugin->maturity = MATURITY_ALPHA; diff --git a/templates/blockcontent.mustache b/templates/blockcontent.mustache index 5fb6562..a58b93d 100644 --- a/templates/blockcontent.mustache +++ b/templates/blockcontent.mustache @@ -78,7 +78,7 @@ in development
--}} -
+
{{#content}} {{#isorientationmarker}} From a5b6c30563fcb31938069a0e48972162d6ff72ae Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Mon, 15 Jan 2024 14:00:14 +0100 Subject: [PATCH 010/123] codecheck fixes --- classes/townsquareevents.php | 2 +- locallib.php | 2 +- .../block_ts_moodleoverflow.php | 2 + .../block_ts_moodleoverflow/db/access.php | 45 +++++++++++++++++++ .../block_ts_moodleoverflow/locallib.php | 8 ++-- templates/blockcontent.mustache | 4 -- 6 files changed, 54 insertions(+), 9 deletions(-) create mode 100644 supportedmodules/block_ts_moodleoverflow/db/access.php diff --git a/classes/townsquareevents.php b/classes/townsquareevents.php index 5941f39..3b13b1b 100644 --- a/classes/townsquareevents.php +++ b/classes/townsquareevents.php @@ -145,7 +145,7 @@ public function get_postevents(): array { } // TODO: implement support for moodleoverflow in a subplugin. if ($DB->get_record('modules', ['name' => 'moodleoverflow', 'visible' => 1])) { - //$moodleoverflowposts = $this->get_posts_from_db('moodleoverflow', $this->courses, $this->timestart); + $moodleoverflowposts = $this->get_posts_from_db('moodleoverflow', $this->courses, $this->timestart); } if (empty($forumposts) && empty($moodleoverflowposts)) { diff --git a/locallib.php b/locallib.php index 0c63baf..17860c4 100644 --- a/locallib.php +++ b/locallib.php @@ -115,4 +115,4 @@ function townsquare_filter_availability($event): bool { } return true; -} \ No newline at end of file +} diff --git a/supportedmodules/block_ts_moodleoverflow/block_ts_moodleoverflow.php b/supportedmodules/block_ts_moodleoverflow/block_ts_moodleoverflow.php index 34436ff..ce449fc 100644 --- a/supportedmodules/block_ts_moodleoverflow/block_ts_moodleoverflow.php +++ b/supportedmodules/block_ts_moodleoverflow/block_ts_moodleoverflow.php @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +defined('MOODLE_INTERNAL') || die; + use block_townsquare\townsquaresupport; use block_townsquare\townsquaresupport\townsquaresupportinterface; diff --git a/supportedmodules/block_ts_moodleoverflow/db/access.php b/supportedmodules/block_ts_moodleoverflow/db/access.php new file mode 100644 index 0000000..5fe97ea --- /dev/null +++ b/supportedmodules/block_ts_moodleoverflow/db/access.php @@ -0,0 +1,45 @@ +. + +/** + * Plugin capabilities for the block_ts_moodleoverfloow subplugin. + * + * @package block_ts_moodleoverflow + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +defined('MOODLE_INTERNAL') || die(); + +$capabilities = [ + 'block/townsquare/supportedmodules/block_ts_moodleoverflow:myaddinstance' => [ + 'captype' => 'write', + 'contextlevel' => CONTEXT_SYSTEM, + 'archetypes' => [ + 'user' => CAP_PROHIBIT, + ], + 'clonepermissionsfrom' => 'moodle/my:manageblocks', + ], + + 'block/townsquare/supportedmodules/block_ts_moodleoverflow/towwnsquare:addinstance' => [ + 'riskbitmask' => RISK_SPAM | RISK_XSS, + 'captype' => 'write', + 'contextlevel' => CONTEXT_BLOCK, + 'archetypes' => [ + 'user' => CAP_PROHIBIT, + ], + 'clonepermissionsfrom' => 'moodle/site:manageblocks', + ], +]; diff --git a/supportedmodules/block_ts_moodleoverflow/locallib.php b/supportedmodules/block_ts_moodleoverflow/locallib.php index a63d8a2..ba8c604 100644 --- a/supportedmodules/block_ts_moodleoverflow/locallib.php +++ b/supportedmodules/block_ts_moodleoverflow/locallib.php @@ -22,6 +22,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +defined('MOODLE_INTERNAL') || die; + global $CFG; require_once($CFG->dirroot . '/blocks/townsquare/locallib.php'); @@ -44,7 +46,7 @@ function ts_moodleoverflow_get_events($courses, $timestart): array { $posts = ts_moodleoverflow_get_post_from_db($courses, $timestart); // Filter posts by availability. - foreach($posts as $post) { + foreach ($posts as $post) { if (townsquare_filter_availability($post)) { unset($posts[$post->row_num]); } @@ -60,9 +62,9 @@ function ts_moodleoverflow_get_post_from_db($courses, $timestart): array { $params = ['courses' => $courses, 'timestart' => $timestart] + $inparamscourses; $sql = "SELECT (ROW_NUMBER() OVER (ORDER BY posts.id)) AS row_num, - 'moodleoverflow' AS modulename, + 'moodleoverflow' AS modulename, module.id AS instanceid, - module.anonymous AS anonymoussetting, + module.anonymous AS anonymoussetting, 'post' AS eventtype, cm.id AS coursemoduleid, cm.availability AS availability, diff --git a/templates/blockcontent.mustache b/templates/blockcontent.mustache index a58b93d..9409dc0 100644 --- a/templates/blockcontent.mustache +++ b/templates/blockcontent.mustache @@ -74,10 +74,6 @@ }}
- {{!--
- in development -
--}} -
{{#content}} From 090e3d9603a27983965518bab102cc3e5e49b2e2 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Wed, 17 Jan 2024 09:56:59 +0100 Subject: [PATCH 011/123] rename files and remove block type from subplugin --- classes/townsquareevents.php | 2 +- db/subplugins.json | 2 +- .../db/access.php | 0 .../lang/en/ts_moodleoverflow.php} | 0 .../locallib.php | 0 .../ts_moodleoverflow.php} | 43 ++----------------- .../version.php | 0 7 files changed, 5 insertions(+), 42 deletions(-) rename supportedmodules/{block_ts_moodleoverflow => ts_moodleoverflow}/db/access.php (100%) rename supportedmodules/{block_ts_moodleoverflow/lang/en/block_ts_moodleoverflow.php => ts_moodleoverflow/lang/en/ts_moodleoverflow.php} (100%) rename supportedmodules/{block_ts_moodleoverflow => ts_moodleoverflow}/locallib.php (100%) rename supportedmodules/{block_ts_moodleoverflow/block_ts_moodleoverflow.php => ts_moodleoverflow/ts_moodleoverflow.php} (56%) rename supportedmodules/{block_ts_moodleoverflow => ts_moodleoverflow}/version.php (100%) diff --git a/classes/townsquareevents.php b/classes/townsquareevents.php index 3b13b1b..5941f39 100644 --- a/classes/townsquareevents.php +++ b/classes/townsquareevents.php @@ -145,7 +145,7 @@ public function get_postevents(): array { } // TODO: implement support for moodleoverflow in a subplugin. if ($DB->get_record('modules', ['name' => 'moodleoverflow', 'visible' => 1])) { - $moodleoverflowposts = $this->get_posts_from_db('moodleoverflow', $this->courses, $this->timestart); + //$moodleoverflowposts = $this->get_posts_from_db('moodleoverflow', $this->courses, $this->timestart); } if (empty($forumposts) && empty($moodleoverflowposts)) { diff --git a/db/subplugins.json b/db/subplugins.json index b64dfea..9f2a3a9 100644 --- a/db/subplugins.json +++ b/db/subplugins.json @@ -1,5 +1,5 @@ { "plugintypes": { - "ts_supportedmodules": "blocks/townsquare/supportedmodules" + "supportedmodules": "blocks/townsquare/supportedmodules" } } diff --git a/supportedmodules/block_ts_moodleoverflow/db/access.php b/supportedmodules/ts_moodleoverflow/db/access.php similarity index 100% rename from supportedmodules/block_ts_moodleoverflow/db/access.php rename to supportedmodules/ts_moodleoverflow/db/access.php diff --git a/supportedmodules/block_ts_moodleoverflow/lang/en/block_ts_moodleoverflow.php b/supportedmodules/ts_moodleoverflow/lang/en/ts_moodleoverflow.php similarity index 100% rename from supportedmodules/block_ts_moodleoverflow/lang/en/block_ts_moodleoverflow.php rename to supportedmodules/ts_moodleoverflow/lang/en/ts_moodleoverflow.php diff --git a/supportedmodules/block_ts_moodleoverflow/locallib.php b/supportedmodules/ts_moodleoverflow/locallib.php similarity index 100% rename from supportedmodules/block_ts_moodleoverflow/locallib.php rename to supportedmodules/ts_moodleoverflow/locallib.php diff --git a/supportedmodules/block_ts_moodleoverflow/block_ts_moodleoverflow.php b/supportedmodules/ts_moodleoverflow/ts_moodleoverflow.php similarity index 56% rename from supportedmodules/block_ts_moodleoverflow/block_ts_moodleoverflow.php rename to supportedmodules/ts_moodleoverflow/ts_moodleoverflow.php index ce449fc..bd689c6 100644 --- a/supportedmodules/block_ts_moodleoverflow/block_ts_moodleoverflow.php +++ b/supportedmodules/ts_moodleoverflow/ts_moodleoverflow.php @@ -16,7 +16,6 @@ defined('MOODLE_INTERNAL') || die; -use block_townsquare\townsquaresupport; use block_townsquare\townsquaresupport\townsquaresupportinterface; global $CFG; @@ -29,52 +28,16 @@ * @copyright 2023 Tamaro Walter * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class block_ts_moodleoverflow extends block_base implements townsquaresupportinterface { +class ts__moodleoverflow implements townsquaresupportinterface { /** - * Initialises the block. - * - * @return void + * Function from the interface. + * @return array */ - public function init(): void { - $this->title = get_string('pluginname', 'block_townsquare'); - } - - /** - * Gets the block contents. - * - * @return object|null The block HTML. - */ - public function get_content(): object { - global $OUTPUT; - - if ($this->content !== null) { - return $this->content; - } - - $this->content = new stdClass(); - $this->content->text = "hallo"; - return $this->content; - } - public function get_events(): array { $courses = townsquare_get_courses(); $timestart = townsquare_get_timestart(); return ts_moodleoverflow_get_events($courses, $timestart); } - /** - * Defines in which pages this block can be added. - * - * @return array of the pages where the block can be added. - */ - public function applicable_formats():array { - return [ - 'admin' => false, - 'site-index' => false, - 'course-view' => false, - 'mod' => false, - 'my' => false, - ]; - } } diff --git a/supportedmodules/block_ts_moodleoverflow/version.php b/supportedmodules/ts_moodleoverflow/version.php similarity index 100% rename from supportedmodules/block_ts_moodleoverflow/version.php rename to supportedmodules/ts_moodleoverflow/version.php From 163c3e2ab99ee8281119695c329c937bacbcaee6 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Wed, 17 Jan 2024 13:57:59 +0100 Subject: [PATCH 012/123] name changes for subplugin --- classes/townsquareevents.php | 2 +- db/subplugins.php | 2 +- .../ts_moodleoverflow/db/access.php | 45 ------------------- .../lang/en/tsmoodleoverflow.php} | 0 .../locallib.php | 0 .../tsmoodleoverflow.php} | 2 +- .../version.php | 7 +-- version.php | 2 +- 8 files changed, 8 insertions(+), 52 deletions(-) delete mode 100644 supportedmodules/ts_moodleoverflow/db/access.php rename supportedmodules/{ts_moodleoverflow/lang/en/ts_moodleoverflow.php => tsmoodleoverflow/lang/en/tsmoodleoverflow.php} (100%) rename supportedmodules/{ts_moodleoverflow => tsmoodleoverflow}/locallib.php (100%) rename supportedmodules/{ts_moodleoverflow/ts_moodleoverflow.php => tsmoodleoverflow/tsmoodleoverflow.php} (95%) rename supportedmodules/{ts_moodleoverflow => tsmoodleoverflow}/version.php (83%) diff --git a/classes/townsquareevents.php b/classes/townsquareevents.php index 5941f39..4f6cca0 100644 --- a/classes/townsquareevents.php +++ b/classes/townsquareevents.php @@ -117,7 +117,7 @@ public function get_coreevents(): array { public function get_subpluginevents(): array { // Get all available subplugins. $events = []; - $subplugins = \core_plugin_manager::instance()->get_plugins_of_type('ts_supportedmodules'); + $subplugins = \core_plugin_manager::instance()->get_plugins_of_type('supportedmodules'); var_dump($subplugins); foreach ($subplugins as $subplugin) { $events += $subplugin->get_events(); diff --git a/db/subplugins.php b/db/subplugins.php index 362cbbb..12482a8 100644 --- a/db/subplugins.php +++ b/db/subplugins.php @@ -24,4 +24,4 @@ defined('MOODLE_INTERNAL') || die(); -$subplugins = (array) json_decode(file_get_contents(__DIR__ . "/subplugins.json"))->plugintypes; +$subplugins = ['supportedmodules' => 'blocks/townsquare/supportedmodules']; diff --git a/supportedmodules/ts_moodleoverflow/db/access.php b/supportedmodules/ts_moodleoverflow/db/access.php deleted file mode 100644 index 5fe97ea..0000000 --- a/supportedmodules/ts_moodleoverflow/db/access.php +++ /dev/null @@ -1,45 +0,0 @@ -. - -/** - * Plugin capabilities for the block_ts_moodleoverfloow subplugin. - * - * @package block_ts_moodleoverflow - * @copyright 2024 Tamaro Walter - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -defined('MOODLE_INTERNAL') || die(); - -$capabilities = [ - 'block/townsquare/supportedmodules/block_ts_moodleoverflow:myaddinstance' => [ - 'captype' => 'write', - 'contextlevel' => CONTEXT_SYSTEM, - 'archetypes' => [ - 'user' => CAP_PROHIBIT, - ], - 'clonepermissionsfrom' => 'moodle/my:manageblocks', - ], - - 'block/townsquare/supportedmodules/block_ts_moodleoverflow/towwnsquare:addinstance' => [ - 'riskbitmask' => RISK_SPAM | RISK_XSS, - 'captype' => 'write', - 'contextlevel' => CONTEXT_BLOCK, - 'archetypes' => [ - 'user' => CAP_PROHIBIT, - ], - 'clonepermissionsfrom' => 'moodle/site:manageblocks', - ], -]; diff --git a/supportedmodules/ts_moodleoverflow/lang/en/ts_moodleoverflow.php b/supportedmodules/tsmoodleoverflow/lang/en/tsmoodleoverflow.php similarity index 100% rename from supportedmodules/ts_moodleoverflow/lang/en/ts_moodleoverflow.php rename to supportedmodules/tsmoodleoverflow/lang/en/tsmoodleoverflow.php diff --git a/supportedmodules/ts_moodleoverflow/locallib.php b/supportedmodules/tsmoodleoverflow/locallib.php similarity index 100% rename from supportedmodules/ts_moodleoverflow/locallib.php rename to supportedmodules/tsmoodleoverflow/locallib.php diff --git a/supportedmodules/ts_moodleoverflow/ts_moodleoverflow.php b/supportedmodules/tsmoodleoverflow/tsmoodleoverflow.php similarity index 95% rename from supportedmodules/ts_moodleoverflow/ts_moodleoverflow.php rename to supportedmodules/tsmoodleoverflow/tsmoodleoverflow.php index bd689c6..7e39304 100644 --- a/supportedmodules/ts_moodleoverflow/ts_moodleoverflow.php +++ b/supportedmodules/tsmoodleoverflow/tsmoodleoverflow.php @@ -28,7 +28,7 @@ * @copyright 2023 Tamaro Walter * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class ts__moodleoverflow implements townsquaresupportinterface { +class tsmoodleoverflow implements townsquaresupportinterface { /** * Function from the interface. diff --git a/supportedmodules/ts_moodleoverflow/version.php b/supportedmodules/tsmoodleoverflow/version.php similarity index 83% rename from supportedmodules/ts_moodleoverflow/version.php rename to supportedmodules/tsmoodleoverflow/version.php index 06d77c6..b82b83e 100644 --- a/supportedmodules/ts_moodleoverflow/version.php +++ b/supportedmodules/tsmoodleoverflow/version.php @@ -17,14 +17,15 @@ /** * Plugin version and other meta-data are defined here. * - * @package block_ts_moodleoverflow + * @package supportedmodules_tsmoodleoverflow * @copyright 2023 Tamaro Walter * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); -$plugin->component = 'block_ts_moodleoverflow'; +$plugin->component = 'supportedmodules_tsmoodleoverflow'; +$plugin->dependencies = ['block_townsquare' => ANY_VERSION]; $plugin->release = '0.1.0'; -$plugin->version = 2024011500; +$plugin->version = 2024011503; $plugin->requires = 2022041900; $plugin->maturity = MATURITY_ALPHA; diff --git a/version.php b/version.php index 6891541..0d3c448 100644 --- a/version.php +++ b/version.php @@ -25,6 +25,6 @@ defined('MOODLE_INTERNAL') || die(); $plugin->component = 'block_townsquare'; $plugin->release = '0.1.0'; -$plugin->version = 2023092003; +$plugin->version = 2023092005; $plugin->requires = 2022041900; $plugin->maturity = MATURITY_ALPHA; From 2a9e6ff0a797b6c118114981058a7612ed2e64ed Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Mon, 22 Jan 2024 18:30:32 +0100 Subject: [PATCH 013/123] add colorpicking setting for townsquare colors --- block_townsquare.php | 2 +- lang/en/block_townsquare.php | 4 ---- lib.php | 8 +++----- locallib.php | 31 +++++++++++++++++++++++++++++++ settings.php | 25 +++++++++---------------- styles.css | 3 --- version.php | 2 +- 7 files changed, 45 insertions(+), 30 deletions(-) create mode 100644 locallib.php diff --git a/block_townsquare.php b/block_townsquare.php index 8a3554b..ec29eb0 100644 --- a/block_townsquare.php +++ b/block_townsquare.php @@ -77,6 +77,6 @@ public function applicable_formats():array { * @return bool */ public function has_config() { - return false; + return true; } } diff --git a/lang/en/block_townsquare.php b/lang/en/block_townsquare.php index 3ef8dd0..84cd1e0 100644 --- a/lang/en/block_townsquare.php +++ b/lang/en/block_townsquare.php @@ -50,10 +50,6 @@ $string['graycolor'] = 'Gray color'; $string['basiclettercolor'] = 'Color for basic letters'; -$string['completionlettercolor'] = 'Color for activity completion letters'; -$string['postlettercolor'] = 'Color for post letters'; $string['orientationmarkercolor'] = 'Color for the orientation marker'; $string['configbasiclettercolor'] = 'Configuration for the color of the basic notification letters'; -$string['configcompletionlettercolor'] = 'Configuration for the color of the activity completion letters'; -$string['configpostlettercolor'] = 'Configuration for the color of the post letters'; $string['configorientationmarkercolor'] = 'Configuration for the color of the orientation marker'; \ No newline at end of file diff --git a/lib.php b/lib.php index 0199c93..7fb3c44 100644 --- a/lib.php +++ b/lib.php @@ -22,8 +22,6 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -// Color constants. -define('TOWNSQUARE_PRIMARY_COLOR', 0); -define('TOWNSQUARE_SECONDARY_COLOR', 1); -define('TOWNSQUARE_BLUE_COLOR', 2); -define('TOWNSQUARE_GRAY_COLOR', 3); \ No newline at end of file +// Color constants from bootstrap. +define('TOWNSQUARE_PRIMARY_COLOR', '#0f6cbf'); +define('TOWNSQUARE_SECONDARY_COLOR', '#6a737b'); \ No newline at end of file diff --git a/locallib.php b/locallib.php new file mode 100644 index 0000000..0ee04ed --- /dev/null +++ b/locallib.php @@ -0,0 +1,31 @@ +. + +/** + * Internal library of functions for the townsquare block + * + * @package block_townsquare + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +function townsquare_get_basiclettercolor() { + return get_config('block_townsquare', 'basiclettercolor'); +} + +function townsquare_get_orientationmarkercolor() { + return get_config('block_townsquare', 'orientationmarkercolor'); +} \ No newline at end of file diff --git a/settings.php b/settings.php index 84273aa..581d0e1 100644 --- a/settings.php +++ b/settings.php @@ -27,22 +27,15 @@ if ($ADMIN->fulltree) { require_once($CFG->dirroot . '/blocks/townsquare/lib.php'); - // Color Setting for basic letters. - $basicletteroptions = []; - $basicletteroptions[TOWNSQUARE_PRIMARY_COLOR] = get_string('primarycolor', 'block_townsquare'); - $basicletteroptions[TOWNSQUARE_BLUE_COLOR] = get_string('bluecolor', 'block_townsquare'); - $settings->add(new admin_setting_configselect('block_townsquare/basiclettercolor', - get_string('basiclettercolor', 'block_townsquare'), - get_string('configbasiclettercolor', 'block_townsquare'), - TOWNSQUARE_PRIMARY_COLOR, $basicletteroptions)); + // Color Setting for the primary color that will be used on basic letters + $settings->add(new admin_setting_configcolourpicker('block_townsquare/basiclettercolor', + get_string('basiclettercolor', 'block_townsquare'), + get_string('configbasiclettercolor', 'block_townsquare'), + TOWNSQUARE_PRIMARY_COLOR)); // Color Setting for the orientation marker. - $orientationmarkeroptions = []; - $orientationmarkeroptions[TOWNSQUARE_SECONDARY_COLOR] = get_string('secondarycolor', 'block_townsquare'); - $orientationmarkeroptions[TOWNSQUARE_GRAY_COLOR] = get_string('graycolor', 'block_townsquare'); - $settings->add(new admin_setting_configselect('block_townsquare/orientationmarkercolor', - get_string('orientationmarkercolor', 'block_townsquare'), - get_string('configorientationmarkercolor', 'block_townsquare'), - TOWNSQUARE_SECONDARY_COLOR, $orientationmarkeroptions)); - + $settings->add(new admin_setting_configcolourpicker('block_townsquare/orientationmarkercolor', + get_string('orientationmarkercolor', 'block_townsquare'), + get_string('configorientationmarkercolor', 'block_townsquare'), + TOWNSQUARE_SECONDARY_COLOR)); } diff --git a/styles.css b/styles.css index 03dd51b..ca85bda 100644 --- a/styles.css +++ b/styles.css @@ -56,14 +56,11 @@ /* basicletter Style*/ .basicletter.card { - /*border-color: var(--primary);*/ border-color: var(--blue); } .basicletter_header.card-header { - /*background-color: var(--primary);*/ background-color: var(--blue); - } /* postletter Style */ diff --git a/version.php b/version.php index 0d3a1fc..ae1f7f4 100644 --- a/version.php +++ b/version.php @@ -25,6 +25,6 @@ defined('MOODLE_INTERNAL') || die(); $plugin->component = 'block_townsquare'; $plugin->release = '0.1.0'; -$plugin->version = 2024011001; +$plugin->version = 2024011002; $plugin->requires = 2022041900; $plugin->maturity = MATURITY_ALPHA; From a4ae4c9a8f355bf6d8c578da19486bf336dc37b0 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Wed, 24 Jan 2024 10:48:51 +0100 Subject: [PATCH 014/123] color setting for letters added --- classes/letter/activitycompletion_letter.php | 5 ++-- classes/letter/letter.php | 18 +++++++++---- classes/letter/post_letter.php | 4 +-- classes/orientation_marker.php | 2 +- lang/en/block_townsquare.php | 17 ++++++------ lib.php | 6 +++-- locallib.php | 21 ++++++++++----- settings.php | 19 ++++++++++--- styles.css | 28 -------------------- templates/activitycompletionletter.mustache | 5 ++-- templates/basicletter.mustache | 4 +-- templates/orientationmarker.mustache | 3 ++- templates/postletter.mustache | 4 +-- 13 files changed, 71 insertions(+), 65 deletions(-) diff --git a/classes/letter/activitycompletion_letter.php b/classes/letter/activitycompletion_letter.php index 52819cc..abefd21 100644 --- a/classes/letter/activitycompletion_letter.php +++ b/classes/letter/activitycompletion_letter.php @@ -21,11 +21,8 @@ * @copyright 2023 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - namespace block_townsquare\letter; -use moodle_url; - /** * Class that represents an activity completion reminder. * @@ -53,6 +50,7 @@ public function __construct($contentid, $calendarevent) { parent::__construct($contentid, $calendarevent->courseid, $calendarevent->modulename, $calendarevent->instancename, $calendarevent->name, $calendarevent->timestart, $calendarevent->coursemoduleid); $this->lettertype = 'activitycompletion'; + $this->lettercolor = townsquare_get_colorsetting('completionletter'); } // Functions. @@ -76,6 +74,7 @@ public function export_letter():array { 'created' => $date, 'linktoactivity' => $this->linktoactivity->out(), 'linktocourse' => $this->linktocourse->out(), + 'completionlettercolor' => $this->lettercolor, ]; } diff --git a/classes/letter/letter.php b/classes/letter/letter.php index 326ffb4..273998e 100644 --- a/classes/letter/letter.php +++ b/classes/letter/letter.php @@ -21,11 +21,14 @@ * @copyright 2023 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - namespace block_townsquare\letter; - use moodle_url; +defined('MOODLE_INTERNAL') || die; + +global $CFG; +require_once($CFG->dirroot . '/blocks/townsquare/locallib.php'); + /** * Class that represents an unspecific type of content. * @@ -66,15 +69,18 @@ class letter { /** @var int Timestamp When the activity was created */ protected int $created; - /** @var bool variable for the mustache template */ - public bool $isbasic = true; - /** @var moodle_url Link to the course */ protected moodle_url $linktocourse; /** @var moodle_url The url to the activity */ protected moodle_url $linktoactivity; + /** @var bool variable for the mustache template */ + public bool $isbasic = true; + + /** @var mixed color of the letter. Only used by mustache */ + public mixed $lettercolor; + // Constructor. /** @@ -100,6 +106,7 @@ public function __construct($contentid, $courseid, $modulename, $instancename, $ $this->created = $created; $this->linktocourse = new moodle_url('/course/view.php', ['id' => $this->courseid]); $this->linktoactivity = new moodle_url('/mod/' . $modulename . '/view.php', ['id' => $cmid]); + $this->lettercolor = townsquare_get_colorsetting('basicletter'); } // Functions. @@ -123,6 +130,7 @@ public function export_letter() { 'created' => $date, 'linktocourse' => $this->linktocourse->out(), 'linktoactivity' => $this->linktoactivity->out(), + 'basiclettercolor' => $this->lettercolor, ]; } } diff --git a/classes/letter/post_letter.php b/classes/letter/post_letter.php index 74ea8a5..9bb2ab6 100644 --- a/classes/letter/post_letter.php +++ b/classes/letter/post_letter.php @@ -23,8 +23,6 @@ */ namespace block_townsquare\letter; - -use moodle_exception; use moodle_url; use stdClass; @@ -87,6 +85,7 @@ public function __construct($contentid, $postevent) { $this->posturls = new stdClass(); $this->lettertype = 'post'; + $this->lettercolor = townsquare_get_colorsetting('postletter'); $this->post->instanceid = $postevent->instanceid; $this->post->discussionid = $postevent->postdiscussion; $this->post->id = $postevent->postid; @@ -127,6 +126,7 @@ public function export_letter():array { 'linktoactivity' => $this->linktoactivity->out(), 'linktopost' => $this->posturls->linktopost->out(), 'linktoauthor' => $this->posturls->linktoauthor->out(), + 'postlettercolor' => $this->lettercolor, ]; } diff --git a/classes/orientation_marker.php b/classes/orientation_marker.php index 62ab900..a1f7a04 100644 --- a/classes/orientation_marker.php +++ b/classes/orientation_marker.php @@ -55,7 +55,6 @@ class orientation_marker { public function __construct($contentid, $time) { $this->contentid = $contentid; $this->today = $time; - } // Functions. @@ -72,6 +71,7 @@ public function export_data():array { 'contentid' => $this->contentid, 'date' => $date, 'isorientationmarker' => $this->isorientationmarker, + 'orientationmarkercolor' => townsquare_get_colorsetting('orientationmarker'), ]; } diff --git a/lang/en/block_townsquare.php b/lang/en/block_townsquare.php index 84cd1e0..1f48521 100644 --- a/lang/en/block_townsquare.php +++ b/lang/en/block_townsquare.php @@ -31,6 +31,9 @@ $string['pluginname:addinstance'] = 'Add the Town Square block'; $string['pluginname:myaddinstance'] = 'Add the Town Square block to the dashboard'; +// Error strings. +$string['invalidlettertype'] = 'Invalid function parameter, please use a valid letter type'; + // Mustache templates strings. $string['completionletterorigin'] = '{$a->modulename} should be completed until {$a->date}'; $string['basicletterorigin'] = 'A notification from {$a->modulename}:'; @@ -42,14 +45,12 @@ $string['invalidmodulename'] = 'Module name is unknown or not supported'; // Setting strings. -$string['primarycolor'] = 'Primary color'; -$string['secondarycolor'] = 'Secondary color'; -$string['bluecolor'] = 'Blue color'; -$string['orangecolor'] = 'Orange color'; -$string['redcolor'] = 'Red color'; -$string['graycolor'] = 'Gray color'; - $string['basiclettercolor'] = 'Color for basic letters'; +$string['postlettercolor'] = 'Color for post letters'; +$string['completionlettercolor'] = 'Color for activity completion letters'; $string['orientationmarkercolor'] = 'Color for the orientation marker'; + $string['configbasiclettercolor'] = 'Configuration for the color of the basic notification letters'; -$string['configorientationmarkercolor'] = 'Configuration for the color of the orientation marker'; \ No newline at end of file +$string['configpostlettercolor'] = 'Configuration for the color of the post letters'; +$string['configcompletionlettercolor'] = 'Configuration for the color of the activity completion letters'; +$string['configorientationmarkercolor'] = 'Configuration for the color of the orientation marker'; diff --git a/lib.php b/lib.php index 7fb3c44..6a6801d 100644 --- a/lib.php +++ b/lib.php @@ -23,5 +23,7 @@ */ // Color constants from bootstrap. -define('TOWNSQUARE_PRIMARY_COLOR', '#0f6cbf'); -define('TOWNSQUARE_SECONDARY_COLOR', '#6a737b'); \ No newline at end of file +define('TOWNSQUARE_BASICLETTER_DEFAULTCOLOR', '#0f6cbf'); +define('TOWNSQUARE_POSTLETTER_DEFAULTCOLOR', '#f7634d'); +define('TOWNSQUARE_COMPLETIONLETTER_DEFAULTCOLOR', '#ca3120'); +define('TOWNSQUARE_ORIENTATIONMARKER_DEFAULTCOLOR', '#6a737b'); diff --git a/locallib.php b/locallib.php index 0ee04ed..6874aaf 100644 --- a/locallib.php +++ b/locallib.php @@ -22,10 +22,19 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -function townsquare_get_basiclettercolor() { - return get_config('block_townsquare', 'basiclettercolor'); +/** + * Function to get the color of a letter. + * + * @param string $lettertype The type of the letter that wants to retrieve its color setting. + * @return false|mixed The color of the letter. + * @throws moodle_exception + */ +function townsquare_get_colorsetting($lettertype) { + return match ($lettertype) { + 'basicletter' => get_config('block_townsquare', 'basiclettercolor'), + 'postletter' => get_config('block_townsquare', 'postlettercolor'), + 'completionletter' => get_config('block_townsquare', 'completionlettercolor'), + 'orientationmarker' => get_config('block_townsquare', 'orientationmarkercolor'), + default => throw new \moodle_exception('invalidlettertype', 'block_townsquare'), + }; } - -function townsquare_get_orientationmarkercolor() { - return get_config('block_townsquare', 'orientationmarkercolor'); -} \ No newline at end of file diff --git a/settings.php b/settings.php index 581d0e1..232317f 100644 --- a/settings.php +++ b/settings.php @@ -23,19 +23,32 @@ */ defined('MOODLE_INTERNAL') || die; +global $ADMIN, $CFG; if ($ADMIN->fulltree) { require_once($CFG->dirroot . '/blocks/townsquare/lib.php'); - // Color Setting for the primary color that will be used on basic letters + // Color Setting for the color that will be used on basic letters. $settings->add(new admin_setting_configcolourpicker('block_townsquare/basiclettercolor', get_string('basiclettercolor', 'block_townsquare'), get_string('configbasiclettercolor', 'block_townsquare'), - TOWNSQUARE_PRIMARY_COLOR)); + TOWNSQUARE_BASICLETTER_DEFAULTCOLOR)); + + // Color Setting for the color that will be used on post letters. + $settings->add(new admin_setting_configcolourpicker('block_townsquare/postlettercolor', + get_string('postlettercolor', 'block_townsquare'), + get_string('configpostlettercolor', 'block_townsquare'), + TOWNSQUARE_POSTLETTER_DEFAULTCOLOR)); + + // Color Setting for the color that will be used on completion letters. + $settings->add(new admin_setting_configcolourpicker('block_townsquare/completionlettercolor', + get_string('completionlettercolor', 'block_townsquare'), + get_string('configcompletionlettercolor', 'block_townsquare'), + TOWNSQUARE_COMPLETIONLETTER_DEFAULTCOLOR)); // Color Setting for the orientation marker. $settings->add(new admin_setting_configcolourpicker('block_townsquare/orientationmarkercolor', get_string('orientationmarkercolor', 'block_townsquare'), get_string('configorientationmarkercolor', 'block_townsquare'), - TOWNSQUARE_SECONDARY_COLOR)); + TOWNSQUARE_ORIENTATIONMARKER_DEFAULTCOLOR)); } diff --git a/styles.css b/styles.css index ca85bda..e4ce887 100644 --- a/styles.css +++ b/styles.css @@ -55,43 +55,15 @@ /* basicletter Style*/ -.basicletter.card { - border-color: var(--blue); -} - -.basicletter_header.card-header { - background-color: var(--blue); -} - /* postletter Style */ -.postletter.card { - border-color: var(--activitycollaboration); -} - -.postletter_header.card-header { - background-color: var(--activitycollaboration); -} - .postletter_origin { margin-bottom: 0.4rem; } /* actvitiycompletionletter Style*/ -.completionletter.card { - border-color: var(--danger); -} - -.completionletter_header.card-header { - background-color: var(--danger); -} - /* Style for the orientation marker */ -.orientationmarker.card { - border-color: var(--gray); - background-color: var(--gray); -} .orientationmarker_body.card-body { padding-top: 0.6rem; diff --git a/templates/activitycompletionletter.mustache b/templates/activitycompletionletter.mustache index 00077ae..3d4037c 100644 --- a/templates/activitycompletionletter.mustache +++ b/templates/activitycompletionletter.mustache @@ -40,8 +40,9 @@ "linktocourse": "http://localhost/moodle/course/view.php?id=3" } }} -
-
+
+
{{#str}} coursetitle, moodle, {"course": diff --git a/templates/basicletter.mustache b/templates/basicletter.mustache index 26f73c1..e408c18 100644 --- a/templates/basicletter.mustache +++ b/templates/basicletter.mustache @@ -41,8 +41,8 @@ "linktoactivity": "http://localhost/moodle/mod/lesson/view.php?id=314" } }} -
-
+
+
{{#str}} coursetitle, moodle, {"course": diff --git a/templates/orientationmarker.mustache b/templates/orientationmarker.mustache index 89d17e4..85c4104 100644 --- a/templates/orientationmarker.mustache +++ b/templates/orientationmarker.mustache @@ -29,7 +29,8 @@ "isorientationmarker": true } }} -
+
\ No newline at end of file diff --git a/templates/postletter.mustache b/templates/postletter.mustache index 784ed61..309e34e 100644 --- a/templates/postletter.mustache +++ b/templates/postletter.mustache @@ -53,8 +53,8 @@ "linktoauthor": "http://localhost/moodle/user/view.php?id=2" } }} -
-
+
+
{{#str}} coursetitle, moodle, { From 6b0351c48156b9f9b8d60a4ba74336737481e760 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Wed, 31 Jan 2024 13:59:20 +0100 Subject: [PATCH 015/123] add coursefilter checkboxes and basic javascript --- amd/build/coursefilter.min.js | 14 ++++ amd/build/coursefilter.min.js.map | 1 + amd/src/coursefilter.js | 51 ++++++++++++ block_townsquare.php | 4 +- classes/contentcontroller.php | 15 +++- classes/orientation_marker.php | 5 ++ classes/townsquareevents.php | 2 +- styles.css | 6 +- templates/activitycompletionletter.mustache | 2 + templates/basicletter.mustache | 2 + templates/blockcontent.mustache | 89 ++++++++++++--------- templates/orientationmarker.mustache | 2 + templates/postletter.mustache | 2 + 13 files changed, 153 insertions(+), 42 deletions(-) create mode 100644 amd/build/coursefilter.min.js create mode 100644 amd/build/coursefilter.min.js.map create mode 100644 amd/src/coursefilter.js diff --git a/amd/build/coursefilter.min.js b/amd/build/coursefilter.min.js new file mode 100644 index 0000000..109b896 --- /dev/null +++ b/amd/build/coursefilter.min.js @@ -0,0 +1,14 @@ +define("block_townsquare/coursefilter",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){checkboxes.forEach((element=>{element.addEventListener("change",executecoursefilter)}))}; +/** + * Javascript for the course filter + * + * This file implements 1 functionality: + * - Checks the checkboxes of the course filter and hides content from courses if the checkbox is not checked. + * + * @module block_townsquare/coursefilter + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +const checkboxes=document.querySelectorAll("input[type=checkbox][name=ts_course_checkbox]");let enabledSettings=[];function executecoursefilter(){enabledSettings=Array.from(checkboxes).filter((i=>i.checked)).map((i=>i.value)),window.alert(enabledSettings)}})); + +//# sourceMappingURL=coursefilter.min.js.map \ No newline at end of file diff --git a/amd/build/coursefilter.min.js.map b/amd/build/coursefilter.min.js.map new file mode 100644 index 0000000..67b626c --- /dev/null +++ b/amd/build/coursefilter.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"coursefilter.min.js","sources":["../src/coursefilter.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 * Javascript for the course filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the course filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/coursefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nconst checkboxes = document.querySelectorAll(\"input[type=checkbox][name=ts_course_checkbox]\");\nlet enabledSettings = [];\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(\n (element) => {\n element.addEventListener('change', executecoursefilter);\n }\n );\n}\n\n/**\n * Checks if the checkboxes are checked.\n */\nfunction executecoursefilter() {\n enabledSettings =\n Array.from(checkboxes) // Convert checkboxes to an array to use filter and map.\n .filter(i => i.checked) // Use Array.filter to remove unchecked checkboxes.\n .map(i => i.value); // Use Array.map to extract only the checkbox values from the array of objects.\n\n window.alert(enabledSettings);\n}"],"names":["checkboxes","forEach","element","addEventListener","executecoursefilter","document","querySelectorAll","enabledSettings","Array","from","filter","i","checked","map","value","window","alert"],"mappings":"wJAiCIA,WAAWC,SACNC,UACGA,QAAQC,iBAAiB,SAAUC;;;;;;;;;;;MATzCJ,WAAaK,SAASC,iBAAiB,qDACzCC,gBAAkB,YAgBbH,sBACLG,gBACIC,MAAMC,KAAKT,YACNU,QAAOC,GAAKA,EAAEC,UACdC,KAAIF,GAAKA,EAAEG,QAEpBC,OAAOC,MAAMT"} \ No newline at end of file diff --git a/amd/src/coursefilter.js b/amd/src/coursefilter.js new file mode 100644 index 0000000..eacc177 --- /dev/null +++ b/amd/src/coursefilter.js @@ -0,0 +1,51 @@ +// 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 . + +/** + * Javascript for the course filter + * + * This file implements 1 functionality: + * - Checks the checkboxes of the course filter and hides content from courses if the checkbox is not checked. + * + * @module block_townsquare/coursefilter + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +const checkboxes = document.querySelectorAll("input[type=checkbox][name=ts_course_checkbox]"); +let enabledSettings = []; + +/** + * Init function + */ +export function init() { + checkboxes.forEach( + (element) => { + element.addEventListener('change', executecoursefilter); + } + ); +} + +/** + * Checks if the checkboxes are checked. + */ +function executecoursefilter() { + enabledSettings = + Array.from(checkboxes) // Convert checkboxes to an array to use filter and map. + .filter(i => i.checked) // Use Array.filter to remove unchecked checkboxes. + .map(i => i.value); // Use Array.map to extract only the checkbox values from the array of objects. + + window.alert(enabledSettings); +} \ No newline at end of file diff --git a/block_townsquare.php b/block_townsquare.php index ec29eb0..b3edf68 100644 --- a/block_townsquare.php +++ b/block_townsquare.php @@ -49,10 +49,12 @@ public function get_content():object { $controller = new contentcontroller(); $mustachedata = new stdClass(); $mustachedata->content = $controller->content; - + $mustachedata->courses = $controller->courses; $this->content = new stdClass(); $this->content->text = $OUTPUT->render_from_template('block_townsquare/blockcontent', $mustachedata); + // Load all javascripts. $this->page->requires->js_call_amd('block_townsquare/postletter', 'init'); + $this->page->requires->js_call_amd('block_townsquare/coursefilter', 'init'); return $this->content; } diff --git a/classes/contentcontroller.php b/classes/contentcontroller.php index 45a3535..3fc5aaf 100644 --- a/classes/contentcontroller.php +++ b/classes/contentcontroller.php @@ -43,11 +43,15 @@ class contentcontroller { /** @var array letters and other content that will be shown to the user */ public array $content; + /** @var array courses that show content in townsquare (not the same as enrolled courses) */ + public array $courses; + /** * Constructor for the controller. */ public function __construct() { $this->townsquareevents = new townsquareevents(); + $this->courses = []; $this->content = $this->build_content(); } @@ -57,12 +61,13 @@ public function __construct() { * Builds the content from events. * @return array */ - public function build_content():array { + public function build_content(): array { $this->events = $this->townsquareevents->get_all_events_sorted(); $orientationmarkerset = false; $index = 0; $time = time(); + $appearedcourses = []; // Build a letter for each event. foreach ($this->events as $event) { // Display a orientation marker on the current date between the other events. @@ -74,6 +79,7 @@ public function build_content():array { $tempcontent = new orientation_marker($index, $time); $this->content[$index] = $tempcontent->export_data(); $index++; + continue; } if (isset($event->eventtype) && $event->eventtype == 'post') { $templetter = new letter\post_letter($index, $event); @@ -84,6 +90,13 @@ public function build_content():array { $event->name, $event->timestart, $event->coursemoduleid); } $this->content[$index] = $templetter->export_letter(); + + // Collect the courses shown in the townsquare to be able to filter them afterwards. + if (!array_key_exists($this->content[$index]['courseid'], $appearedcourses)) { + $this->courses[] = ['courseid' => $this->content[$index]['courseid'], + 'coursename' => $this->content[$index]['coursename'], ]; + $appearedcourses[$event->courseid] = true; + } $index++; } return $this->content; diff --git a/classes/orientation_marker.php b/classes/orientation_marker.php index a1f7a04..741dadf 100644 --- a/classes/orientation_marker.php +++ b/classes/orientation_marker.php @@ -24,6 +24,11 @@ namespace block_townsquare; +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->dirroot . '/blocks/townsquare/locallib.php'); + /** * Class that represent a orientation marker. * diff --git a/classes/townsquareevents.php b/classes/townsquareevents.php index 04fa1b4..d614861 100644 --- a/classes/townsquareevents.php +++ b/classes/townsquareevents.php @@ -30,7 +30,7 @@ global $CFG; require_once($CFG->dirroot . '/calendar/lib.php'); - +require_once($CFG->dirroot . '/blocks/townsquare/locallib.php'); /** * Class to get events and posts that will be shown in the townsquare block.. * diff --git a/styles.css b/styles.css index e4ce887..bfe4e06 100644 --- a/styles.css +++ b/styles.css @@ -1,7 +1,9 @@ /* Style for the blockcontent template*/ -.townsquare_sidepanel { +.townsquare_sidepanel.col-md-3 { background-color: #eee; border-radius: 0.5rem; + padding-left: 0.0rem; + padding-right: 0.0rem; } .townsquare_content { @@ -12,6 +14,8 @@ overflow-x: hidden; } +/* Style for the side panel filter */ + /* Style for all letter or content templates */ .townsquareletter_header.card-header { diff --git a/templates/activitycompletionletter.mustache b/templates/activitycompletionletter.mustache index 3d4037c..787d9fb 100644 --- a/templates/activitycompletionletter.mustache +++ b/templates/activitycompletionletter.mustache @@ -27,6 +27,7 @@ * created - Due date of activity completions * linktocourse - Link to the course * linktoactivity - Link to the module instance + * completionlettercolor - Color of the letter Example (json): { @@ -38,6 +39,7 @@ "created": "28.10.2023", "linktoactivity": "http://localhost/moodle/mod/survey/view.php?id=72", "linktocourse": "http://localhost/moodle/course/view.php?id=3" + "completionlettercolor": "#ca3120" } }}
diff --git a/templates/blockcontent.mustache b/templates/blockcontent.mustache index 1cc3e26..cb9356e 100644 --- a/templates/blockcontent.mustache +++ b/templates/blockcontent.mustache @@ -74,49 +74,62 @@ }}
-
-

-

- - -

-
- - -
- -

+
+
+
+
+

+ +

+
-
- - -
diff --git a/templates/orientationmarker.mustache b/templates/orientationmarker.mustache index 85c4104..3bfca8f 100644 --- a/templates/orientationmarker.mustache +++ b/templates/orientationmarker.mustache @@ -22,11 +22,13 @@ Variables required for this template (more variables are available for testing and future features): * contentid - Unique identification for every shown plugin content * isorientationmarker - variable for the blockcontent template to assure this template is used + * orientationmarkercolor - Color of the letter Example (json): { "contentid": 1, "isorientationmarker": true + "orientationmarkercolor": "#6a737b" } }}
From 6e4a3bc9dc3f67d11d915f084ec26986ae415310 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 1 Feb 2024 12:05:57 +0100 Subject: [PATCH 016/123] course filter functionality implemented --- amd/build/coursefilter.min.js | 4 +- amd/build/coursefilter.min.js.map | 2 +- amd/src/coursefilter.js | 41 ++++++++++++--------- styles.css | 3 ++ templates/activitycompletionletter.mustache | 4 +- templates/basicletter.mustache | 4 +- templates/blockcontent.mustache | 29 ++++++++++----- templates/postletter.mustache | 4 +- 8 files changed, 58 insertions(+), 33 deletions(-) diff --git a/amd/build/coursefilter.min.js b/amd/build/coursefilter.min.js index 109b896..a930af2 100644 --- a/amd/build/coursefilter.min.js +++ b/amd/build/coursefilter.min.js @@ -1,4 +1,4 @@ -define("block_townsquare/coursefilter",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){checkboxes.forEach((element=>{element.addEventListener("change",executecoursefilter)}))}; +define("block_townsquare/coursefilter",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){checkboxes.forEach((function(checkbox){checkbox.addEventListener("change",(function(){var courseid=checkbox.id;document.querySelectorAll(".townsquare_letter").forEach((function(letter){var letterCourseId=letter.querySelector(".townsquareletter_course").id;courseid===letterCourseId&&(checkbox.checked?letter.style.display="block":letter.style.display="none")}))}))}))}; /** * Javascript for the course filter * @@ -9,6 +9,6 @@ define("block_townsquare/coursefilter",["exports"],(function(_exports){Object.de * @copyright 2024 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -const checkboxes=document.querySelectorAll("input[type=checkbox][name=ts_course_checkbox]");let enabledSettings=[];function executecoursefilter(){enabledSettings=Array.from(checkboxes).filter((i=>i.checked)).map((i=>i.value)),window.alert(enabledSettings)}})); +const checkboxes=document.querySelectorAll(".ts_course_checkbox")})); //# sourceMappingURL=coursefilter.min.js.map \ No newline at end of file diff --git a/amd/build/coursefilter.min.js.map b/amd/build/coursefilter.min.js.map index 67b626c..4e5eed1 100644 --- a/amd/build/coursefilter.min.js.map +++ b/amd/build/coursefilter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"coursefilter.min.js","sources":["../src/coursefilter.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 * Javascript for the course filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the course filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/coursefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nconst checkboxes = document.querySelectorAll(\"input[type=checkbox][name=ts_course_checkbox]\");\nlet enabledSettings = [];\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(\n (element) => {\n element.addEventListener('change', executecoursefilter);\n }\n );\n}\n\n/**\n * Checks if the checkboxes are checked.\n */\nfunction executecoursefilter() {\n enabledSettings =\n Array.from(checkboxes) // Convert checkboxes to an array to use filter and map.\n .filter(i => i.checked) // Use Array.filter to remove unchecked checkboxes.\n .map(i => i.value); // Use Array.map to extract only the checkbox values from the array of objects.\n\n window.alert(enabledSettings);\n}"],"names":["checkboxes","forEach","element","addEventListener","executecoursefilter","document","querySelectorAll","enabledSettings","Array","from","filter","i","checked","map","value","window","alert"],"mappings":"wJAiCIA,WAAWC,SACNC,UACGA,QAAQC,iBAAiB,SAAUC;;;;;;;;;;;MATzCJ,WAAaK,SAASC,iBAAiB,qDACzCC,gBAAkB,YAgBbH,sBACLG,gBACIC,MAAMC,KAAKT,YACNU,QAAOC,GAAKA,EAAEC,UACdC,KAAIF,GAAKA,EAAEG,QAEpBC,OAAOC,MAAMT"} \ No newline at end of file +{"version":3,"file":"coursefilter.min.js","sources":["../src/coursefilter.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 * Javascript for the course filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the course filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/coursefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n//const checkboxes = document.querySelectorAll(\"input[type=checkbox][name=ts_course_checkbox]\");\nconst checkboxes = document.querySelectorAll('.ts_course_checkbox');\n///const checkboxelements = document.getElementsByClassName('ts_course_checkbox');\n\n//let enabledSettings = [];\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n // Get the courseid associated with the checkbox\n var courseid = checkbox.id;\n\n // Get all letters with the corresponding courseid\n var letters = document.querySelectorAll('.townsquare_letter');\n\n // Loop through each letter and hide/show based on checkbox state\n letters.forEach(function(letter) {\n var letterCourseId = letter.querySelector('.townsquareletter_course').id;\n\n if (courseid === letterCourseId) {\n if (checkbox.checked) {\n letter.style.display = 'block'; // Show the letter\n } else {\n letter.style.display = 'none'; // Hide the letter\n }\n }\n });\n });\n });\n}\n\n/**\n * If a checkbox is checked, show the content from the checkbox course. If it is not checked, hide the content.\n * //@param {HTMLElement} element - The checkbox that was clicked.\n *\nfunction executecoursefilter() {\n // Get the course id from the checkbox.\n var courseid = element.id;\n //courseid = 5;\n\n // Search for the divs with the classes \"townsquare_letter\" and a child divs with the class\n // \"townsquareletter_course\" that has the id=courseid.\n //let content = document.querySelectorAll(\".townsquare_letter > .townsquareletter_course[id='\" + courseid + \"']\");\n //window.alert(content);\n\n enabledSettings =\n Array.from(checkboxes) // Convert checkboxes to an array to use filter and map.\n .filter(i => i.checked) // Use Array.filter to remove unchecked checkboxes.\n .map(i => i.value); // Use Array.map to extract only the checkbox values from the array of objects.\n\n window.alert(enabledSettings);\n}\n */\n"],"names":["checkboxes","forEach","checkbox","addEventListener","courseid","id","document","querySelectorAll","letter","letterCourseId","querySelector","checked","style","display"],"mappings":"wJAoCIA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,eAE5BC,SAAWF,SAASG,GAGVC,SAASC,iBAAiB,sBAGhCN,SAAQ,SAASO,YACjBC,eAAiBD,OAAOE,cAAc,4BAA4BL,GAElED,WAAaK,iBACTP,SAASS,QACTH,OAAOI,MAAMC,QAAU,QAEvBL,OAAOI,MAAMC,QAAU;;;;;;;;;;;MAzBzCb,WAAaM,SAASC,iBAAiB"} \ No newline at end of file diff --git a/amd/src/coursefilter.js b/amd/src/coursefilter.js index eacc177..d8adaa1 100644 --- a/amd/src/coursefilter.js +++ b/amd/src/coursefilter.js @@ -24,28 +24,33 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -const checkboxes = document.querySelectorAll("input[type=checkbox][name=ts_course_checkbox]"); -let enabledSettings = []; +//const checkboxes = document.querySelectorAll("input[type=checkbox][name=ts_course_checkbox]"); +const checkboxes = document.querySelectorAll('.ts_course_checkbox'); /** * Init function */ export function init() { - checkboxes.forEach( - (element) => { - element.addEventListener('change', executecoursefilter); - } - ); -} + checkboxes.forEach(function(checkbox) { + checkbox.addEventListener('change', function() { + // Get the courseid associated with the checkbox + const courseid = checkbox.id; -/** - * Checks if the checkboxes are checked. - */ -function executecoursefilter() { - enabledSettings = - Array.from(checkboxes) // Convert checkboxes to an array to use filter and map. - .filter(i => i.checked) // Use Array.filter to remove unchecked checkboxes. - .map(i => i.value); // Use Array.map to extract only the checkbox values from the array of objects. + // Get all letters with the corresponding courseid + const letters = document.querySelectorAll('.townsquare_letter'); - window.alert(enabledSettings); -} \ No newline at end of file + // Loop through each letter and hide/show based on checkbox state + letters.forEach(function(letter) { + let letterCourseId = letter.querySelector('.townsquareletter_course').id; + + if (courseid === letterCourseId) { + if (checkbox.checked) { + letter.style.display = 'block'; // Show the letter + } else { + letter.style.display = 'none'; // Hide the letter + } + } + }); + }); + }); +} diff --git a/styles.css b/styles.css index bfe4e06..38c5281 100644 --- a/styles.css +++ b/styles.css @@ -16,6 +16,9 @@ /* Style for the side panel filter */ +.ts_time_buttons.btn-group { + display: block; +} /* Style for all letter or content templates */ .townsquareletter_header.card-header { diff --git a/templates/activitycompletionletter.mustache b/templates/activitycompletionletter.mustache index 787d9fb..dcf0d0e 100644 --- a/templates/activitycompletionletter.mustache +++ b/templates/activitycompletionletter.mustache @@ -23,6 +23,7 @@ * contentid - Unique identification for every shown plugin content * isactivitycompletion - Variable for the blockcontent template to assure this template is used. * coursename - Name of the course + * courseid - Id of the course * instancename - Name of the instance * created - Due date of activity completions * linktocourse - Link to the course @@ -34,6 +35,7 @@ "contentid": 28, "isactivitycompletion": true, "coursename": "Moodle Engineering", + "courseid": 3, "modulename": "survey", "instancename": "How difficult was the exam?", "created": "28.10.2023", @@ -46,7 +48,7 @@ style="border-color: {{completionlettercolor}}">
-
+
{{#str}} coursetitle, moodle, {"course": {{#quote}} {{coursename}} {{/quote}} } {{/str}} diff --git a/templates/basicletter.mustache b/templates/basicletter.mustache index aa1bebe..71a2a83 100644 --- a/templates/basicletter.mustache +++ b/templates/basicletter.mustache @@ -23,6 +23,7 @@ * contentid - Unique identification for every shown plugin content * isbasic - Variable for the blockcontent template to assure this template is used. * coursename - Name of the course + * courseid - Id of the course * instancename - Name of the instance * content - Content of the letter * created - Date of the notification @@ -35,6 +36,7 @@ "contentid": 0, "isbasic": true, "coursename": "Moodle Engineering", + "courseid": 3, "instancename": "Lesson 1: Quantum Theory", "content": "Lesson 1: Quantum Theory closes", "created": "20.12.2023", @@ -46,7 +48,7 @@
-
+
{{#str}} coursetitle, moodle, {"course": {{#quote}} {{coursename}} {{/quote}} } {{/str}} diff --git a/templates/blockcontent.mustache b/templates/blockcontent.mustache index cb9356e..3dc97b7 100644 --- a/templates/blockcontent.mustache +++ b/templates/blockcontent.mustache @@ -79,18 +79,18 @@

-

-
+
{{#courses}}
- -
@@ -98,21 +98,32 @@
- {{! +
-
+

-

-
+
- Second Card Body +
+ + + +
+ {{!

diff --git a/templates/postletter.mustache b/templates/postletter.mustache index f47cdea..4cae473 100644 --- a/templates/postletter.mustache +++ b/templates/postletter.mustache @@ -23,6 +23,7 @@ * contentid - Unique identification for every shown plugin content * ispost - Variable for the blockcontent template to assure this template is used. * coursename - Name of the course + * courseid - Id of the course * instancename - Name of the forum/moodleoverflow * discussionsubject - Name of the discussion * anonymous - if the post is anonymous @@ -41,6 +42,7 @@ "contentid": 27, "ispost": true, "coursename": "Moodle Engineering", + "courseid": 3, "instancename": "Exam Questions", "discussionsubject": "Hour of Exam", "anonymous": false, @@ -58,7 +60,7 @@
-
+
{{#str}} coursetitle, moodle, { "course": {{#quote}} {{coursename}} {{/quote}} } From b9122408f2378ff64c65086275759c169b8f4831 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Wed, 7 Feb 2024 10:38:19 +0100 Subject: [PATCH 017/123] all filters defined --- styles.css | 5 +- templates/blockcontent.mustache | 71 ++------------------- templates/sidepanel.mustache | 108 ++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+), 69 deletions(-) create mode 100644 templates/sidepanel.mustache diff --git a/styles.css b/styles.css index 38c5281..822f27a 100644 --- a/styles.css +++ b/styles.css @@ -16,9 +16,10 @@ /* Style for the side panel filter */ -.ts_time_buttons.btn-group { - display: block; +.ts_time_buttons.btn-group-vertical { + width: 100%; } + /* Style for all letter or content templates */ .townsquareletter_header.card-header { diff --git a/templates/blockcontent.mustache b/templates/blockcontent.mustache index 3dc97b7..57b827b 100644 --- a/templates/blockcontent.mustache +++ b/templates/blockcontent.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template block_townsquare/main + @template block_townsquare/blockcontent This template renders the main content area for the townsquare block. @@ -74,73 +74,10 @@ }}
-
-
-
-
-

- -

-
-
-
- {{#courses}} -
- - -
- {{/courses}} -
-
-
- -
-
-

- -

-
-
-
-
- - - -
-
-
-
- {{! -
-
-

- -

-
-
-
- Third Card Body -
-
-
}} -
- -
+
+ {{> block_townsquare/sidepanel}} +
diff --git a/templates/sidepanel.mustache b/templates/sidepanel.mustache new file mode 100644 index 0000000..f575782 --- /dev/null +++ b/templates/sidepanel.mustache @@ -0,0 +1,108 @@ +{{! + 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 block_townsquare/blockcontent + + This template renders the side panel with the filters for the townsquare content. +}} +
+
+
+

+ +

+
+ +
+
+ {{#courses}} +
+ + +
+ {{/courses}} +
+
+
+ +
+
+

+ +

+
+
+
+
+ + + + + +
+
+
+
+ +
+
+

+ +

+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
\ No newline at end of file From 2ed9d81cd00fc1683626466d9914b6e26dc985ed Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Wed, 7 Feb 2024 12:17:37 +0100 Subject: [PATCH 018/123] filters in js completed --- amd/build/coursefilter.min.js | 2 +- amd/build/coursefilter.min.js.map | 2 +- amd/build/letterfilter.min.js | 14 +++++ amd/build/letterfilter.min.js.map | 1 + amd/build/timefilter.min.js | 14 +++++ amd/build/timefilter.min.js.map | 1 + amd/src/coursefilter.js | 6 +- amd/src/letterfilter.js | 53 ++++++++++++++++++ amd/src/timefilter.js | 91 +++++++++++++++++++++++++++++++ 9 files changed, 179 insertions(+), 5 deletions(-) create mode 100644 amd/build/letterfilter.min.js create mode 100644 amd/build/letterfilter.min.js.map create mode 100644 amd/build/timefilter.min.js create mode 100644 amd/build/timefilter.min.js.map create mode 100644 amd/src/letterfilter.js create mode 100644 amd/src/timefilter.js diff --git a/amd/build/coursefilter.min.js b/amd/build/coursefilter.min.js index a930af2..6fabffd 100644 --- a/amd/build/coursefilter.min.js +++ b/amd/build/coursefilter.min.js @@ -1,4 +1,4 @@ -define("block_townsquare/coursefilter",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){checkboxes.forEach((function(checkbox){checkbox.addEventListener("change",(function(){var courseid=checkbox.id;document.querySelectorAll(".townsquare_letter").forEach((function(letter){var letterCourseId=letter.querySelector(".townsquareletter_course").id;courseid===letterCourseId&&(checkbox.checked?letter.style.display="block":letter.style.display="none")}))}))}))}; +define("block_townsquare/coursefilter",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){checkboxes.forEach((function(checkbox){checkbox.addEventListener("change",(function(){const courseid=checkbox.id;document.querySelectorAll(".townsquare_letter").forEach((function(letter){let letterCourseId=letter.querySelector(".townsquareletter_course").id;courseid===letterCourseId&&(checkbox.checked?letter.style.display="block":letter.style.display="none")}))}))}))}; /** * Javascript for the course filter * diff --git a/amd/build/coursefilter.min.js.map b/amd/build/coursefilter.min.js.map index 4e5eed1..cb4cc7a 100644 --- a/amd/build/coursefilter.min.js.map +++ b/amd/build/coursefilter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"coursefilter.min.js","sources":["../src/coursefilter.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 * Javascript for the course filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the course filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/coursefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n//const checkboxes = document.querySelectorAll(\"input[type=checkbox][name=ts_course_checkbox]\");\nconst checkboxes = document.querySelectorAll('.ts_course_checkbox');\n///const checkboxelements = document.getElementsByClassName('ts_course_checkbox');\n\n//let enabledSettings = [];\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n // Get the courseid associated with the checkbox\n var courseid = checkbox.id;\n\n // Get all letters with the corresponding courseid\n var letters = document.querySelectorAll('.townsquare_letter');\n\n // Loop through each letter and hide/show based on checkbox state\n letters.forEach(function(letter) {\n var letterCourseId = letter.querySelector('.townsquareletter_course').id;\n\n if (courseid === letterCourseId) {\n if (checkbox.checked) {\n letter.style.display = 'block'; // Show the letter\n } else {\n letter.style.display = 'none'; // Hide the letter\n }\n }\n });\n });\n });\n}\n\n/**\n * If a checkbox is checked, show the content from the checkbox course. If it is not checked, hide the content.\n * //@param {HTMLElement} element - The checkbox that was clicked.\n *\nfunction executecoursefilter() {\n // Get the course id from the checkbox.\n var courseid = element.id;\n //courseid = 5;\n\n // Search for the divs with the classes \"townsquare_letter\" and a child divs with the class\n // \"townsquareletter_course\" that has the id=courseid.\n //let content = document.querySelectorAll(\".townsquare_letter > .townsquareletter_course[id='\" + courseid + \"']\");\n //window.alert(content);\n\n enabledSettings =\n Array.from(checkboxes) // Convert checkboxes to an array to use filter and map.\n .filter(i => i.checked) // Use Array.filter to remove unchecked checkboxes.\n .map(i => i.value); // Use Array.map to extract only the checkbox values from the array of objects.\n\n window.alert(enabledSettings);\n}\n */\n"],"names":["checkboxes","forEach","checkbox","addEventListener","courseid","id","document","querySelectorAll","letter","letterCourseId","querySelector","checked","style","display"],"mappings":"wJAoCIA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,eAE5BC,SAAWF,SAASG,GAGVC,SAASC,iBAAiB,sBAGhCN,SAAQ,SAASO,YACjBC,eAAiBD,OAAOE,cAAc,4BAA4BL,GAElED,WAAaK,iBACTP,SAASS,QACTH,OAAOI,MAAMC,QAAU,QAEvBL,OAAOI,MAAMC,QAAU;;;;;;;;;;;MAzBzCb,WAAaM,SAASC,iBAAiB"} \ No newline at end of file +{"version":3,"file":"coursefilter.min.js","sources":["../src/coursefilter.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 * Javascript for the course filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the course filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/coursefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant checkboxes.\nconst checkboxes = document.querySelectorAll('.ts_course_checkbox');\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n // Get the courseid associated with the checkbox\n const courseid = checkbox.id;\n\n // Get all letters.\n const letters = document.querySelectorAll('.townsquare_letter');\n\n // Loop through each letter and hide/show based on checkbox state and the letter id.\n letters.forEach(function(letter) {\n let letterCourseId = letter.querySelector('.townsquareletter_course').id;\n\n if (courseid === letterCourseId) {\n if (checkbox.checked) {\n letter.style.display = 'block'; // Show the letter\n } else {\n letter.style.display = 'none'; // Hide the letter\n }\n }\n });\n });\n });\n}\n"],"names":["checkboxes","forEach","checkbox","addEventListener","courseid","id","document","querySelectorAll","letter","letterCourseId","querySelector","checked","style","display"],"mappings":"wJAiCIA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,iBAE1BC,SAAWF,SAASG,GAGVC,SAASC,iBAAiB,sBAGlCN,SAAQ,SAASO,YACjBC,eAAiBD,OAAOE,cAAc,4BAA4BL,GAElED,WAAaK,iBACTP,SAASS,QACTH,OAAOI,MAAMC,QAAU,QAEvBL,OAAOI,MAAMC,QAAU;;;;;;;;;;;MAtBzCb,WAAaM,SAASC,iBAAiB"} \ No newline at end of file diff --git a/amd/build/letterfilter.min.js b/amd/build/letterfilter.min.js new file mode 100644 index 0000000..e33134e --- /dev/null +++ b/amd/build/letterfilter.min.js @@ -0,0 +1,14 @@ +define("block_townsquare/letterfilter",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){checkboxes.forEach((function(checkbox){checkbox.addEventListener("change",(function(){const lettername=checkbox.id;document.querySelectorAll(".townsquare_letter."+lettername).forEach((function(letter){checkbox.checked?letter.style.display="block":letter.style.display="none"}))}))}))}; +/** + * Javascript for the letter filter + * + * This file implements 1 functionality: + * - Checks the checkboxes of the letter filter and hides content from courses if the checkbox is not checked. + * + * @module block_townsquare/letterfilter + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +const checkboxes=document.querySelectorAll(".ts_letter_checkbox")})); + +//# sourceMappingURL=letterfilter.min.js.map \ No newline at end of file diff --git a/amd/build/letterfilter.min.js.map b/amd/build/letterfilter.min.js.map new file mode 100644 index 0000000..333d338 --- /dev/null +++ b/amd/build/letterfilter.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"letterfilter.min.js","sources":["../src/letterfilter.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 * Javascript for the letter filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the letter filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/letterfilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant checkboxes.\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n\n // Get the letter name associated with the checkbox\n const lettername = checkbox.id;\n\n // Get all the right letters.\n const letters = document.querySelectorAll('.townsquare_letter.' + lettername);\n\n // Loop through each letter and hide/show based on checkbox state\n letters.forEach(function(letter) {\n if (checkbox.checked) {\n letter.style.display = 'block'; // Show the letter\n } else {\n letter.style.display = 'none'; // Hide the letter\n }\n });\n });\n });\n}"],"names":["checkboxes","forEach","checkbox","addEventListener","lettername","id","document","querySelectorAll","letter","checked","style","display"],"mappings":"wJAiCIA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,iBAG1BC,WAAaF,SAASG,GAGZC,SAASC,iBAAiB,sBAAwBH,YAG1DH,SAAQ,SAASO,QACjBN,SAASO,QACTD,OAAOE,MAAMC,QAAU,QAEvBH,OAAOE,MAAMC,QAAU;;;;;;;;;;;MApBrCX,WAAaM,SAASC,iBAAiB"} \ No newline at end of file diff --git a/amd/build/timefilter.min.js b/amd/build/timefilter.min.js new file mode 100644 index 0000000..e105a71 --- /dev/null +++ b/amd/build/timefilter.min.js @@ -0,0 +1,14 @@ +define("block_townsquare/timefilter",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){radiobuttons.forEach((function(radiobutton){radiobutton.addEventListener("change",(function(){let timestart,timeend,currenttime=(new Date).getTime()/1e3;switch(radiobutton.id){case"ts_time_all":default:timestart=-9999999999,timeend=9999999999;break;case"ts_time_next_week":timestart=currenttime,timeend=currenttime+604800;break;case"ts_time_next_month":timestart=currenttime,timeend=currenttime+2629743;break;case"ts_time_last_week":timestart=currenttime-604800,timeend=currenttime;break;case"ts_time_last_month":timestart=currenttime-2629743,timeend=currenttime}document.querySelectorAll(".townsquare_letter").forEach((function(letter){let lettertime=letter.querySelector(".townsquareletter_date").id;radiobutton.checked?letter.style.display=lettertime>=timestart&&lettertime<=timeend?"block":"none":letter.style.display="block"}))}))}))}; +/** + * Javascript for the time filter + * + * This file implements 1 functionality: + * - Checks, which of the radio buttons is pressed and filters the content based on the time. + * + * @module block_townsquare/timefilter + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +const radiobuttons=document.querySelectorAll(".ts_time_button")})); + +//# sourceMappingURL=timefilter.min.js.map \ No newline at end of file diff --git a/amd/build/timefilter.min.js.map b/amd/build/timefilter.min.js.map new file mode 100644 index 0000000..8552abb --- /dev/null +++ b/amd/build/timefilter.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"timefilter.min.js","sources":["../src/timefilter.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 * Javascript for the time filter\n *\n * This file implements 1 functionality:\n * - Checks, which of the radio buttons is pressed and filters the content based on the time.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant radio buttons.\nconst radiobuttons = document.querySelectorAll('.ts_time_button');\n\n/**\n * Init function\n */\nexport function init() {\n radiobuttons.forEach(function(radiobutton) {\n radiobutton.addEventListener('change', function() {\n //window.alert(radiobutton.id + \" \" + radiobutton.checked);\n // Get\n let currenttime = new Date().getTime() / 1000;\n //window.alert(currenttime);\n let timestart;\n let timeend;\n\n // Depending on the id, set a time span.\n switch (radiobutton.id) {\n case \"ts_time_all\":\n timestart = -9999999999;\n timeend = 9999999999;\n break;\n case \"ts_time_next_week\":\n timestart = currenttime;\n timeend = currenttime + 604800;\n break;\n case \"ts_time_next_month\":\n timestart = currenttime;\n timeend = currenttime + 2629743;\n break;\n case \"ts_time_last_week\":\n timestart = currenttime - 604800;\n timeend = currenttime;\n break;\n case \"ts_time_last_month\":\n timestart = currenttime - 2629743;\n timeend = currenttime;\n break;\n default:\n timestart = -9999999999;\n timeend = 9999999999;\n break;\n }\n\n // Get all the right letters.\n const letters = document.querySelectorAll('.townsquare_letter');\n\n // Loop through each letter and hide/show based on radiobutton state\n letters.forEach(function(letter) {\n // Get the created time stamp of each letter.\n let lettertime = letter.querySelector('.townsquareletter_date').id;\n\n // If the letter is in the time span, show it.\n if (radiobutton.checked) {\n if (lettertime >= timestart && lettertime <= timeend) {\n letter.style.display = 'block'; // Show the letter\n } else {\n letter.style.display = 'none'; // Hide the letter\n }\n } else {\n letter.style.display = 'block'; // Show the letter\n }\n\n });\n });\n });\n}"],"names":["radiobuttons","forEach","radiobutton","addEventListener","timestart","timeend","currenttime","Date","getTime","id","document","querySelectorAll","letter","lettertime","querySelector","checked","style","display"],"mappings":"sJAiCIA,aAAaC,SAAQ,SAASC,aAC1BA,YAAYC,iBAAiB,UAAU,eAK/BC,UACAC,QAHAC,aAAc,IAAIC,MAAOC,UAAY,WAMjCN,YAAYO,QACX,sBAqBDL,WAAa,WACbC,QAAU,qBAlBT,oBACDD,UAAYE,YACZD,QAAUC,YAAc,iBAEvB,qBACDF,UAAYE,YACZD,QAAUC,YAAc,kBAEvB,oBACDF,UAAYE,YAAc,OAC1BD,QAAUC,sBAET,qBACDF,UAAYE,YAAc,QAC1BD,QAAUC,YASFI,SAASC,iBAAiB,sBAGlCV,SAAQ,SAASW,YAEjBC,WAAaD,OAAOE,cAAc,0BAA0BL,GAG5DP,YAAYa,QAERH,OAAOI,MAAMC,QADbJ,YAAcT,WAAaS,YAAcR,QAClB,QAEA,OAG3BO,OAAOI,MAAMC,QAAU;;;;;;;;;;;MA3DrCjB,aAAeU,SAASC,iBAAiB"} \ No newline at end of file diff --git a/amd/src/coursefilter.js b/amd/src/coursefilter.js index d8adaa1..3c4bf0e 100644 --- a/amd/src/coursefilter.js +++ b/amd/src/coursefilter.js @@ -24,7 +24,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -//const checkboxes = document.querySelectorAll("input[type=checkbox][name=ts_course_checkbox]"); +// Get the relevant checkboxes. const checkboxes = document.querySelectorAll('.ts_course_checkbox'); /** @@ -36,10 +36,10 @@ export function init() { // Get the courseid associated with the checkbox const courseid = checkbox.id; - // Get all letters with the corresponding courseid + // Get all letters. const letters = document.querySelectorAll('.townsquare_letter'); - // Loop through each letter and hide/show based on checkbox state + // Loop through each letter and hide/show based on checkbox state and the letter id. letters.forEach(function(letter) { let letterCourseId = letter.querySelector('.townsquareletter_course').id; diff --git a/amd/src/letterfilter.js b/amd/src/letterfilter.js new file mode 100644 index 0000000..3359d40 --- /dev/null +++ b/amd/src/letterfilter.js @@ -0,0 +1,53 @@ +// 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 . + +/** + * Javascript for the letter filter + * + * This file implements 1 functionality: + * - Checks the checkboxes of the letter filter and hides content from courses if the checkbox is not checked. + * + * @module block_townsquare/letterfilter + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +// Get the relevant checkboxes. +const checkboxes = document.querySelectorAll('.ts_letter_checkbox'); + +/** + * Init function + */ +export function init() { + checkboxes.forEach(function(checkbox) { + checkbox.addEventListener('change', function() { + + // Get the letter name associated with the checkbox + const lettername = checkbox.id; + + // Get all the right letters. + const letters = document.querySelectorAll('.townsquare_letter.' + lettername); + + // Loop through each letter and hide/show based on checkbox state + letters.forEach(function(letter) { + if (checkbox.checked) { + letter.style.display = 'block'; // Show the letter + } else { + letter.style.display = 'none'; // Hide the letter + } + }); + }); + }); +} \ No newline at end of file diff --git a/amd/src/timefilter.js b/amd/src/timefilter.js new file mode 100644 index 0000000..9abf260 --- /dev/null +++ b/amd/src/timefilter.js @@ -0,0 +1,91 @@ +// 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 . + +/** + * Javascript for the time filter + * + * This file implements 1 functionality: + * - Checks, which of the radio buttons is pressed and filters the content based on the time. + * + * @module block_townsquare/timefilter + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +// Get the relevant radio buttons. +const radiobuttons = document.querySelectorAll('.ts_time_button'); + +/** + * Init function + */ +export function init() { + radiobuttons.forEach(function(radiobutton) { + radiobutton.addEventListener('change', function() { + // Get the current time in seconds. + let currenttime = new Date().getTime() / 1000; + let timestart; + let timeend; + + // Depending on the radiobutton id, set a time span. + switch (radiobutton.id) { + case "ts_time_all": + timestart = -9999999999; + timeend = 9999999999; + break; + case "ts_time_next_week": + timestart = currenttime; + timeend = currenttime + 604800; + break; + case "ts_time_next_month": + timestart = currenttime; + timeend = currenttime + 2629743; + break; + case "ts_time_last_week": + timestart = currenttime - 604800; + timeend = currenttime; + break; + case "ts_time_last_month": + timestart = currenttime - 2629743; + timeend = currenttime; + break; + default: + timestart = -9999999999; + timeend = 9999999999; + break; + } + + // Get all the right letters. + const letters = document.querySelectorAll('.townsquare_letter'); + + // Loop through each letter and hide/show based on radiobutton state + letters.forEach(function(letter) { + // Get the created time stamp of each letter. + let lettertime = letter.querySelector('.townsquareletter_date').id; + + // If the radio button is checked and the letter is in the time span, show it. + if (radiobutton.checked) { + if (lettertime >= timestart && lettertime <= timeend) { + letter.style.display = 'block'; // Show the letter + } else { + letter.style.display = 'none'; // Hide the letter + } + } else { + letter.style.display = 'block'; // Show the letter + } + + }); + }); + }); +} \ No newline at end of file From 9ad9fe1bad7d42c5f58c7dd994402390b7663236 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Wed, 7 Feb 2024 12:19:23 +0100 Subject: [PATCH 019/123] files adapted for js filters --- block_townsquare.php | 2 ++ classes/letter/activitycompletion_letter.php | 6 ++---- classes/letter/letter.php | 5 ++--- classes/letter/post_letter.php | 1 + styles.css | 4 ---- templates/activitycompletionletter.mustache | 2 +- templates/basicletter.mustache | 2 +- templates/postletter.mustache | 2 +- templates/sidepanel.mustache | 20 ++++++++++---------- 9 files changed, 20 insertions(+), 24 deletions(-) diff --git a/block_townsquare.php b/block_townsquare.php index b3edf68..156729d 100644 --- a/block_townsquare.php +++ b/block_townsquare.php @@ -55,6 +55,8 @@ public function get_content():object { // Load all javascripts. $this->page->requires->js_call_amd('block_townsquare/postletter', 'init'); $this->page->requires->js_call_amd('block_townsquare/coursefilter', 'init'); + $this->page->requires->js_call_amd('block_townsquare/timefilter', 'init'); + $this->page->requires->js_call_amd('block_townsquare/letterfilter', 'init'); return $this->content; } diff --git a/classes/letter/activitycompletion_letter.php b/classes/letter/activitycompletion_letter.php index abefd21..4d84ffa 100644 --- a/classes/letter/activitycompletion_letter.php +++ b/classes/letter/activitycompletion_letter.php @@ -60,9 +60,6 @@ public function __construct($contentid, $calendarevent) { * return array */ public function export_letter():array { - // Change the timestamp to a date. - $date = date('d.m.Y', $this->created); - return [ 'contentid' => $this->contentid, 'lettertype' => $this->lettertype, @@ -71,7 +68,8 @@ public function export_letter():array { 'coursename' => $this->coursename, 'instancename' => $this->instancename, 'content' => $this->content, - 'created' => $date, + 'created' => date('d.m.Y', $this->created), + 'createdtimestamp' => $this->created, 'linktoactivity' => $this->linktoactivity->out(), 'linktocourse' => $this->linktocourse->out(), 'completionlettercolor' => $this->lettercolor, diff --git a/classes/letter/letter.php b/classes/letter/letter.php index 273998e..48a71f0 100644 --- a/classes/letter/letter.php +++ b/classes/letter/letter.php @@ -117,8 +117,6 @@ public function __construct($contentid, $courseid, $modulename, $instancename, $ */ public function export_letter() { // Change the timestamp to a date. - $date = date('d.m.Y', $this->created); - return [ 'contentid' => $this->contentid, 'lettertype' => $this->lettertype, @@ -127,7 +125,8 @@ public function export_letter() { 'coursename' => $this->coursename, 'instancename' => $this->instancename, 'content' => $this->content, - 'created' => $date, + 'created' => date('d.m.Y', $this->created), + 'createdtimestamp' => $this->created, 'linktocourse' => $this->linktocourse->out(), 'linktoactivity' => $this->linktoactivity->out(), 'basiclettercolor' => $this->lettercolor, diff --git a/classes/letter/post_letter.php b/classes/letter/post_letter.php index 9bb2ab6..2c1829b 100644 --- a/classes/letter/post_letter.php +++ b/classes/letter/post_letter.php @@ -122,6 +122,7 @@ public function export_letter():array { 'postid' => $this->post->id, 'message' => format_text($this->post->message), 'created' => date('d.m.Y', $this->created), + 'createdtimestamp' => $this->created, 'linktocourse' => $this->linktocourse->out(), 'linktoactivity' => $this->linktoactivity->out(), 'linktopost' => $this->posturls->linktopost->out(), diff --git a/styles.css b/styles.css index 822f27a..bfe4e06 100644 --- a/styles.css +++ b/styles.css @@ -16,10 +16,6 @@ /* Style for the side panel filter */ -.ts_time_buttons.btn-group-vertical { - width: 100%; -} - /* Style for all letter or content templates */ .townsquareletter_header.card-header { diff --git a/templates/activitycompletionletter.mustache b/templates/activitycompletionletter.mustache index dcf0d0e..856e9cd 100644 --- a/templates/activitycompletionletter.mustache +++ b/templates/activitycompletionletter.mustache @@ -53,7 +53,7 @@ {{#quote}} {{coursename}} {{/quote}} } {{/str}}
-
+
{{created}}
diff --git a/templates/basicletter.mustache b/templates/basicletter.mustache index 71a2a83..9d2b2fb 100644 --- a/templates/basicletter.mustache +++ b/templates/basicletter.mustache @@ -53,7 +53,7 @@ {{#quote}} {{coursename}} {{/quote}} } {{/str}}
-
+
{{created}}
diff --git a/templates/postletter.mustache b/templates/postletter.mustache index 4cae473..65e5b44 100644 --- a/templates/postletter.mustache +++ b/templates/postletter.mustache @@ -66,7 +66,7 @@ {{/quote}} } {{/str}}
-
+
{{created}}
diff --git a/templates/sidepanel.mustache b/templates/sidepanel.mustache index f575782..fd404fc 100644 --- a/templates/sidepanel.mustache +++ b/templates/sidepanel.mustache @@ -53,21 +53,21 @@
-
-
@@ -85,19 +85,19 @@
- +
- +
- + From 41111f86b7a5db9b76e68a81c0c656ed3777e390 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Wed, 7 Feb 2024 12:28:38 +0100 Subject: [PATCH 020/123] code styling --- amd/src/letterfilter.js | 10 +++++----- amd/src/timefilter.js | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/amd/src/letterfilter.js b/amd/src/letterfilter.js index 3359d40..e79bcf7 100644 --- a/amd/src/letterfilter.js +++ b/amd/src/letterfilter.js @@ -34,20 +34,20 @@ export function init() { checkboxes.forEach(function(checkbox) { checkbox.addEventListener('change', function() { - // Get the letter name associated with the checkbox + // Get the letter name associated with the checkbox. const lettername = checkbox.id; // Get all the right letters. const letters = document.querySelectorAll('.townsquare_letter.' + lettername); - // Loop through each letter and hide/show based on checkbox state + // Loop through each letter and hide/show based on checkbox state. letters.forEach(function(letter) { if (checkbox.checked) { - letter.style.display = 'block'; // Show the letter + letter.style.display = 'block'; // Show the letter. } else { - letter.style.display = 'none'; // Hide the letter + letter.style.display = 'none'; // Hide the letter. } }); }); }); -} \ No newline at end of file +} diff --git a/amd/src/timefilter.js b/amd/src/timefilter.js index 9abf260..2ddb3e0 100644 --- a/amd/src/timefilter.js +++ b/amd/src/timefilter.js @@ -69,7 +69,7 @@ export function init() { // Get all the right letters. const letters = document.querySelectorAll('.townsquare_letter'); - // Loop through each letter and hide/show based on radiobutton state + // Loop through each letter and hide/show based on radiobutton state. letters.forEach(function(letter) { // Get the created time stamp of each letter. let lettertime = letter.querySelector('.townsquareletter_date').id; @@ -77,15 +77,15 @@ export function init() { // If the radio button is checked and the letter is in the time span, show it. if (radiobutton.checked) { if (lettertime >= timestart && lettertime <= timeend) { - letter.style.display = 'block'; // Show the letter + letter.style.display = 'block'; // Show the letter. } else { - letter.style.display = 'none'; // Hide the letter + letter.style.display = 'none'; // Hide the letter. } } else { - letter.style.display = 'block'; // Show the letter + letter.style.display = 'block'; // Show the letter. } }); }); }); -} \ No newline at end of file +} From 0b878f7aac68f4d5c0d73211c04798e8cd64e18f Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Wed, 7 Feb 2024 13:00:56 +0100 Subject: [PATCH 021/123] language strings for filters --- lang/en/block_townsquare.php | 13 +++++++++++++ templates/sidepanel.mustache | 34 +++++++++++++++++----------------- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/lang/en/block_townsquare.php b/lang/en/block_townsquare.php index 1f48521..f887806 100644 --- a/lang/en/block_townsquare.php +++ b/lang/en/block_townsquare.php @@ -41,6 +41,19 @@ $string['postletterorigin'] = '{$a->authorname} posted in {$a->instancename} -> {$a->discussionname}:'; $string['orientationmarkercontent'] = 'Hi {$a->username}, welcome to townsquare! Today is the {$a->date}'; +// Side panel filter strings. +$string['coursefilter'] = 'Course filter'; +$string['timefilter'] = 'Time filter'; +$string['letterfilter'] = 'Letter filter'; +$string['allnotifications'] = 'All notifications'; +$string['nextweeknotifications'] = 'Next week'; +$string['nextmonthnotifications'] = 'Next month'; +$string['lastweeknotifications'] = 'Last week'; +$string['lastmonthnotifications'] = 'Last month'; +$string['basicletters'] = 'Basic letters'; +$string['completionletters'] = 'Activity Completions'; +$string['postletters'] = 'Forum Posts'; + // Letter strings. $string['invalidmodulename'] = 'Module name is unknown or not supported'; diff --git a/templates/sidepanel.mustache b/templates/sidepanel.mustache index fd404fc..bb75c7a 100644 --- a/templates/sidepanel.mustache +++ b/templates/sidepanel.mustache @@ -24,7 +24,7 @@

@@ -47,27 +47,27 @@

-
-
@@ -78,7 +78,7 @@

@@ -87,19 +87,19 @@
From 9f5ed72a0888bfd8f0aa792831ed54b50f507119 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Wed, 7 Feb 2024 13:10:11 +0100 Subject: [PATCH 022/123] typo fix --- templates/sidepanel.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/sidepanel.mustache b/templates/sidepanel.mustache index bb75c7a..4f92b96 100644 --- a/templates/sidepanel.mustache +++ b/templates/sidepanel.mustache @@ -47,7 +47,7 @@

From dc471d57fe9e1df6f15cd88b04eec6075ddbe437 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Wed, 7 Feb 2024 16:37:03 +0100 Subject: [PATCH 023/123] new database to store filter settings for a user --- classes/filtercontroller.php | 156 +++++++++++++++++++++++++++++++++++ db/install.xml | 19 +++++ db/upgrade.php | 24 +++++- version.php | 2 +- 4 files changed, 199 insertions(+), 2 deletions(-) create mode 100644 classes/filtercontroller.php create mode 100644 db/install.xml diff --git a/classes/filtercontroller.php b/classes/filtercontroller.php new file mode 100644 index 0000000..ec85b71 --- /dev/null +++ b/classes/filtercontroller.php @@ -0,0 +1,156 @@ +. + +/** + * Filter Controller of block_townsquare + * + * @package block_townsquare + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace block_townsquare; + +/** + * Filter Controller Class. + * + * This Class controls the filter settings that user sets for the townsquare. + * The main functionality are: + * - store the filter settings that the user sets in the database + * - retrieve filter settings from the database and apply them when the user loads the townsquare + */ +class filtercontroller { + + /** @var array usersettings that the current user set */ + public array $usersettings; + + /** @var array timefilter that the user set */ + public array $timefilter; + + /** @var array letterfilter that the user set */ + public array $letterfilter; + + public function __construct() { + global $DB, $USER; + + // Retrieve the user filter settings from the database. If there are no settings, store a empty array. + if (!$this->usersettings = $DB->get_record('townsquare_usersettings', ['userid' => $USER->id])) { + $this->usersettings = []; + } + + // Build an array for the mustache templates to use. + } + + // Store functions. + public function store_usersettings(array $usersettings) { + // Change the information from the array to a number that can store the database. + // Check if the user already has settings in the database. + // If yes,update the settings. + // If no, insert the settings (on the GUI is a "submit" button, that also has a helpicon). + } + + // Retrieve functions. + public function set_timefilter(): array { + if ($this->usersettings == []) { + return []; + } + + // Set the default. + $this->timefilter = [ + 'all' => true, + 'nextweek' => false, + 'nextmonth' => false, + 'lastweek' => false, + 'lastmonth' => false, + ]; + + // Change the setting according to the database (case 0 is the default). + switch($this->usersettings->timefilter) { + case 1: + $this->timefilter['all'] = false; + $this->timefilter['nextweek'] = true; + break; + case 2: + $this->timefilter['all'] = false; + $this->timefilter['nextmonth'] = true; + break; + case 3: + $this->timefilter['all'] = false; + $this->timefilter['lastweek'] = true; + break; + case 4: + $this->timefilter['all'] = false; + $this->timefilter['lastmonth'] = true; + break; + default: + break; + } + + return $this->timefilter; + } + + public function set_letterfilter(): array { + if ($this->usersettings == []) { + return []; + } + + switch($this->usersettings->letterfilter) { + case 0: + $this->letterfilter['basicletter'] = true; + $this->letterfilter['completionletter'] = true; + $this->letterfilter['postletter'] = true; + break; + case 1: + $this->letterfilter['basicletter'] = true; + $this->letterfilter['completionletter'] = true; + $this->letterfilter['postletter'] = false; + break; + case 2: + $this->letterfilter['basicletter'] = true; + $this->letterfilter['completionletter'] = false; + $this->letterfilter['postletter'] = true; + break; + case 3: + $this->letterfilter['basicletter'] = true; + $this->letterfilter['completionletter'] = false; + $this->letterfilter['postletter'] = false; + break; + case 4: + $this->letterfilter['basicletter'] = false; + $this->letterfilter['completionletter'] = true; + $this->letterfilter['postletter'] = true; + break; + case 5: + $this->letterfilter['basicletter'] = false; + $this->letterfilter['completionletter'] = true; + $this->letterfilter['postletter'] = false; + break; + case 6: + $this->letterfilter['basicletter'] = false; + $this->letterfilter['completionletter'] = false; + $this->letterfilter['postletter'] = true; + break; + case 7: + $this->letterfilter['basicletter'] = false; + $this->letterfilter['completionletter'] = false; + $this->letterfilter['postletter'] = false; + break; + default: + break; + } + return $this->letterfilter; + } + +} diff --git a/db/install.xml b/db/install.xml new file mode 100644 index 0000000..669d645 --- /dev/null +++ b/db/install.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + +
+
+
\ No newline at end of file diff --git a/db/upgrade.php b/db/upgrade.php index d9ae3d0..ceb11cd 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -30,7 +30,7 @@ * @return bool */ function xmldb_block_townsquare_upgrade($oldversion) { - global $DB; + global $DB, $CFG; $dbman = $DB->get_manager(); @@ -39,5 +39,27 @@ function xmldb_block_townsquare_upgrade($oldversion) { // You will also have to create the db/install.xml file by using the XMLDB Editor. // Documentation for the XMLDB Editor can be found at {@link https://docs.moodle.org/dev/XMLDB_editor}. + if ($oldversion < 2024020700) { + // Define new table townsquare_usersettings to be created. + $table = new xmldb_table('townsquare_usersettings'); + + // Adding fields to table townsquare_usersettings. + $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); + $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); + $table->add_field('timefilter', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); + $table->add_field('letterfilter', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); + + // Adding keys to table townsquare_usersettings. + $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); + + // Conditionally launch create table for townsquare_usersettings. + if (!$dbman->table_exists($table)) { + $dbman->create_table($table); + } + + // Moodleoverflow savepoint reached. + upgrade_block_savepoint(true, 2024020700, 'townsquare'); + } + return true; } diff --git a/version.php b/version.php index ae1f7f4..6eaf1cf 100644 --- a/version.php +++ b/version.php @@ -25,6 +25,6 @@ defined('MOODLE_INTERNAL') || die(); $plugin->component = 'block_townsquare'; $plugin->release = '0.1.0'; -$plugin->version = 2024011002; +$plugin->version = 2024020700; $plugin->requires = 2022041900; $plugin->maturity = MATURITY_ALPHA; From 6e1c5c9a86d3157aaaabc480e27afa707bc97bc7 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 8 Feb 2024 15:00:23 +0100 Subject: [PATCH 024/123] improved time filter --- amd/build/letterfilter.min.js.map | 2 +- amd/build/timefilter.min.js | 4 +- amd/build/timefilter.min.js.map | 2 +- amd/src/timefilter.js | 210 ++++++++++++++++++++++-------- db/install.xml | 3 +- db/upgrade.php | 3 +- lang/en/block_townsquare.php | 4 + templates/sidepanel.mustache | 31 ++++- 8 files changed, 194 insertions(+), 65 deletions(-) diff --git a/amd/build/letterfilter.min.js.map b/amd/build/letterfilter.min.js.map index 333d338..a68866a 100644 --- a/amd/build/letterfilter.min.js.map +++ b/amd/build/letterfilter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"letterfilter.min.js","sources":["../src/letterfilter.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 * Javascript for the letter filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the letter filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/letterfilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant checkboxes.\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n\n // Get the letter name associated with the checkbox\n const lettername = checkbox.id;\n\n // Get all the right letters.\n const letters = document.querySelectorAll('.townsquare_letter.' + lettername);\n\n // Loop through each letter and hide/show based on checkbox state\n letters.forEach(function(letter) {\n if (checkbox.checked) {\n letter.style.display = 'block'; // Show the letter\n } else {\n letter.style.display = 'none'; // Hide the letter\n }\n });\n });\n });\n}"],"names":["checkboxes","forEach","checkbox","addEventListener","lettername","id","document","querySelectorAll","letter","checked","style","display"],"mappings":"wJAiCIA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,iBAG1BC,WAAaF,SAASG,GAGZC,SAASC,iBAAiB,sBAAwBH,YAG1DH,SAAQ,SAASO,QACjBN,SAASO,QACTD,OAAOE,MAAMC,QAAU,QAEvBH,OAAOE,MAAMC,QAAU;;;;;;;;;;;MApBrCX,WAAaM,SAASC,iBAAiB"} \ No newline at end of file +{"version":3,"file":"letterfilter.min.js","sources":["../src/letterfilter.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 * Javascript for the letter filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the letter filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/letterfilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant checkboxes.\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n\n // Get the letter name associated with the checkbox.\n const lettername = checkbox.id;\n\n // Get all the right letters.\n const letters = document.querySelectorAll('.townsquare_letter.' + lettername);\n\n // Loop through each letter and hide/show based on checkbox state.\n letters.forEach(function(letter) {\n if (checkbox.checked) {\n letter.style.display = 'block'; // Show the letter.\n } else {\n letter.style.display = 'none'; // Hide the letter.\n }\n });\n });\n });\n}\n"],"names":["checkboxes","forEach","checkbox","addEventListener","lettername","id","document","querySelectorAll","letter","checked","style","display"],"mappings":"wJAiCIA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,iBAG1BC,WAAaF,SAASG,GAGZC,SAASC,iBAAiB,sBAAwBH,YAG1DH,SAAQ,SAASO,QACjBN,SAASO,QACTD,OAAOE,MAAMC,QAAU,QAEvBH,OAAOE,MAAMC,QAAU;;;;;;;;;;;MApBrCX,WAAaM,SAASC,iBAAiB"} \ No newline at end of file diff --git a/amd/build/timefilter.min.js b/amd/build/timefilter.min.js index e105a71..0bab738 100644 --- a/amd/build/timefilter.min.js +++ b/amd/build/timefilter.min.js @@ -1,4 +1,4 @@ -define("block_townsquare/timefilter",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){radiobuttons.forEach((function(radiobutton){radiobutton.addEventListener("change",(function(){let timestart,timeend,currenttime=(new Date).getTime()/1e3;switch(radiobutton.id){case"ts_time_all":default:timestart=-9999999999,timeend=9999999999;break;case"ts_time_next_week":timestart=currenttime,timeend=currenttime+604800;break;case"ts_time_next_month":timestart=currenttime,timeend=currenttime+2629743;break;case"ts_time_last_week":timestart=currenttime-604800,timeend=currenttime;break;case"ts_time_last_month":timestart=currenttime-2629743,timeend=currenttime}document.querySelectorAll(".townsquare_letter").forEach((function(letter){let lettertime=letter.querySelector(".townsquareletter_date").id;radiobutton.checked?letter.style.display=lettertime>=timestart&&lettertime<=timeend?"block":"none":letter.style.display="block"}))}))}))}; +define("block_townsquare/timefilter",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){currenttime=(new Date).getTime()/1e3,alltimebutton.forEach((function(button){button.addEventListener("change",(function(){timestart=currenttime-convertidtotime(button.id),timeend=currenttime+convertidtotime(button.id),addstarttime=0,addendtime=0,futureradiobuttons.forEach((function(futureradiobutton){futureradiobutton.checked=!1,futureradiobutton.parentNode.classList.remove("active")})),pastradiobuttons.forEach((function(pastradiobutton){pastradiobutton.checked=!1,pastradiobutton.parentNode.classList.remove("active")})),executefilter(timestart,timeend,addstarttime,addendtime,button.checked)}))})),futureradiobuttons.forEach((function(button){button.addEventListener("change",(function(){alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})),timestart=currenttime,timeend=currenttime+convertidtotime(button.id),addstarttime=0,addendtime=0,pastradiobuttons.forEach((function(pastradiobutton){pastradiobutton.parentNode.classList.contains("active")&&(addstarttime=currenttime-convertidtotime(pastradiobutton.id),addendtime=currenttime)})),executefilter(timestart,timeend,addstarttime,addendtime,button.checked)}))})),pastradiobuttons.forEach((function(button){button.addEventListener("change",(function(){alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})),timestart=currenttime-convertidtotime(button.id),timeend=currenttime,addstarttime=0,addendtime=0,futureradiobuttons.forEach((function(futureradiobutton){futureradiobutton.parentNode.classList.contains("active")&&(addstarttime=currenttime,addendtime=currenttime+convertidtotime(futureradiobutton.id))})),executefilter(timestart,timeend,addstarttime,addendtime,button.checked)}))}))}; /** * Javascript for the time filter * @@ -9,6 +9,6 @@ define("block_townsquare/timefilter",["exports"],(function(_exports){Object.defi * @copyright 2024 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -const radiobuttons=document.querySelectorAll(".ts_time_button")})); +const alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button");let currenttime,timestart,timeend,addstarttime,addendtime;function executefilter(starttime,endtime,addstarttime,addendtime,buttonstate){document.querySelectorAll(".townsquare_letter").forEach((function(letter){letter.style.display="none";let lettertime=letter.querySelector(".townsquareletter_date").id;(buttonstate&&lettertime>=starttime&&lettertime<=endtime||lettertime>=addstarttime&&lettertime<=addendtime)&&(letter.style.display="block")}))}function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}})); //# sourceMappingURL=timefilter.min.js.map \ No newline at end of file diff --git a/amd/build/timefilter.min.js.map b/amd/build/timefilter.min.js.map index 8552abb..d15d352 100644 --- a/amd/build/timefilter.min.js.map +++ b/amd/build/timefilter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"timefilter.min.js","sources":["../src/timefilter.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 * Javascript for the time filter\n *\n * This file implements 1 functionality:\n * - Checks, which of the radio buttons is pressed and filters the content based on the time.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant radio buttons.\nconst radiobuttons = document.querySelectorAll('.ts_time_button');\n\n/**\n * Init function\n */\nexport function init() {\n radiobuttons.forEach(function(radiobutton) {\n radiobutton.addEventListener('change', function() {\n //window.alert(radiobutton.id + \" \" + radiobutton.checked);\n // Get\n let currenttime = new Date().getTime() / 1000;\n //window.alert(currenttime);\n let timestart;\n let timeend;\n\n // Depending on the id, set a time span.\n switch (radiobutton.id) {\n case \"ts_time_all\":\n timestart = -9999999999;\n timeend = 9999999999;\n break;\n case \"ts_time_next_week\":\n timestart = currenttime;\n timeend = currenttime + 604800;\n break;\n case \"ts_time_next_month\":\n timestart = currenttime;\n timeend = currenttime + 2629743;\n break;\n case \"ts_time_last_week\":\n timestart = currenttime - 604800;\n timeend = currenttime;\n break;\n case \"ts_time_last_month\":\n timestart = currenttime - 2629743;\n timeend = currenttime;\n break;\n default:\n timestart = -9999999999;\n timeend = 9999999999;\n break;\n }\n\n // Get all the right letters.\n const letters = document.querySelectorAll('.townsquare_letter');\n\n // Loop through each letter and hide/show based on radiobutton state\n letters.forEach(function(letter) {\n // Get the created time stamp of each letter.\n let lettertime = letter.querySelector('.townsquareletter_date').id;\n\n // If the letter is in the time span, show it.\n if (radiobutton.checked) {\n if (lettertime >= timestart && lettertime <= timeend) {\n letter.style.display = 'block'; // Show the letter\n } else {\n letter.style.display = 'none'; // Hide the letter\n }\n } else {\n letter.style.display = 'block'; // Show the letter\n }\n\n });\n });\n });\n}"],"names":["radiobuttons","forEach","radiobutton","addEventListener","timestart","timeend","currenttime","Date","getTime","id","document","querySelectorAll","letter","lettertime","querySelector","checked","style","display"],"mappings":"sJAiCIA,aAAaC,SAAQ,SAASC,aAC1BA,YAAYC,iBAAiB,UAAU,eAK/BC,UACAC,QAHAC,aAAc,IAAIC,MAAOC,UAAY,WAMjCN,YAAYO,QACX,sBAqBDL,WAAa,WACbC,QAAU,qBAlBT,oBACDD,UAAYE,YACZD,QAAUC,YAAc,iBAEvB,qBACDF,UAAYE,YACZD,QAAUC,YAAc,kBAEvB,oBACDF,UAAYE,YAAc,OAC1BD,QAAUC,sBAET,qBACDF,UAAYE,YAAc,QAC1BD,QAAUC,YASFI,SAASC,iBAAiB,sBAGlCV,SAAQ,SAASW,YAEjBC,WAAaD,OAAOE,cAAc,0BAA0BL,GAG5DP,YAAYa,QAERH,OAAOI,MAAMC,QADbJ,YAAcT,WAAaS,YAAcR,QAClB,QAEA,OAG3BO,OAAOI,MAAMC,QAAU;;;;;;;;;;;MA3DrCjB,aAAeU,SAASC,iBAAiB"} \ No newline at end of file +{"version":3,"file":"timefilter.min.js","sources":["../src/timefilter.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 * Javascript for the time filter\n *\n * This file implements 1 functionality:\n * - Checks, which of the radio buttons is pressed and filters the content based on the time.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant radio buttons.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Define to change the time span, an additional time span and the current time.\nlet currenttime;\nlet timestart;\nlet timeend;\nlet addstarttime;\nlet addendtime;\n\n/**\n * Init function\n */\nexport function init() {\n // Set the current time.\n currenttime = new Date().getTime() / 1000;\n\n // Add event listeners to the all kind of buttons.\n alltimeaddEventListener();\n futuretimeaddEventListener();\n pasttimeaddEventListener();\n}\n\n/**\n * Function to execute the filter\n * @param {int} starttime Start of time span for filtering of the current pressed button\n * @param {int} endtime End of time span for filtering of the current pressed\n * @param {int} addstarttime Start of time span for filtering of an additional radio button.\n * @param {int} addendtime End of time span for filtering of an additional radio button.\n * @param {bool} buttonstate State of the radio button (true of false)\n */\nfunction executefilter(starttime, endtime, addstarttime, addendtime, buttonstate) {\n // Get all the letters.\n const letters = document.querySelectorAll('.townsquare_letter');\n\n // Loop through each letter and hide/show based on radiobutton state.\n letters.forEach(function(letter) {\n // First hide all letters, as different time spans can overlap.\n letter.style.display = 'none';\n\n // Get the created time stamp of each letter.\n let lettertime = letter.querySelector('.townsquareletter_date').id;\n\n // If the radio button is checked and the letter is in the time span, show it.\n if ((buttonstate && (lettertime >= starttime && lettertime <= endtime)) ||\n (lettertime >= addstarttime && lettertime <= addendtime)) {\n letter.style.display = 'block';\n }\n });\n}\n\n/**\n * Function to add event listeners to the all_time button.\n */\nfunction alltimeaddEventListener() {\n alltimebutton.forEach(function(button) {\n button.addEventListener('change', function() {\n // Set the time span to show all letters.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime + convertidtotime(button.id);\n addstarttime = 0;\n addendtime = 0;\n\n // Disable all other radio buttons that filter more specific times.\n futureradiobuttons.forEach(function(futureradiobutton) {\n futureradiobutton.checked = false;\n futureradiobutton.parentNode.classList.remove(\"active\");\n });\n pastradiobuttons.forEach(function(pastradiobutton) {\n pastradiobutton.checked = false;\n pastradiobutton.parentNode.classList.remove(\"active\");\n\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime,addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the future time radio buttons.\n */\nfunction futuretimeaddEventListener() {\n futureradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime;\n timeend = currenttime + convertidtotime(button.id);\n\n // Check if one past time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n pastradiobuttons.forEach(function(pastradiobutton) {\n if (pastradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime - convertidtotime(pastradiobutton.id);\n addendtime = currenttime;\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the past time radio buttons.\n */\nfunction pasttimeaddEventListener() {\n pastradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime;\n\n // Check if one future time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n futureradiobuttons.forEach(function(futureradiobutton) {\n if (futureradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime;\n addendtime = currenttime + convertidtotime(futureradiobutton.id);\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n"],"names":["currenttime","Date","getTime","alltimebutton","forEach","button","addEventListener","timestart","convertidtotime","id","timeend","addstarttime","addendtime","futureradiobuttons","futureradiobutton","checked","parentNode","classList","remove","pastradiobuttons","pastradiobutton","executefilter","contains","document","querySelectorAll","starttime","endtime","buttonstate","letter","style","display","lettertime","querySelector"],"mappings":"sJA2CIA,aAAc,IAAIC,MAAOC,UAAY,IAwCrCC,cAAcC,SAAQ,SAASC,QAC3BA,OAAOC,iBAAiB,UAAU,WAE9BC,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAC/CE,aAAe,EACfC,WAAa,EAGbC,mBAAmBT,SAAQ,SAASU,mBAChCA,kBAAkBC,SAAU,EAC5BD,kBAAkBE,WAAWC,UAAUC,OAAO,aAElDC,iBAAiBf,SAAQ,SAASgB,iBAC9BA,gBAAgBL,SAAU,EAC1BK,gBAAgBJ,WAAWC,UAAUC,OAAO,aAKhDG,cAAcd,UAAWG,QAASC,aAAaC,WAAYP,OAAOU,eAS1EF,mBAAmBT,SAAQ,SAASC,QAChCA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YACZU,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAG/CE,aAAe,EACfC,WAAa,EACbO,iBAAiBf,SAAQ,SAASgB,iBAC1BA,gBAAgBJ,WAAWC,UAAUK,SAAS,YAC9CX,aAAeX,YAAcQ,gBAAgBY,gBAAgBX,IAC7DG,WAAaZ,gBAKrBqB,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU,eAS3EI,iBAAiBf,SAAQ,SAASC,QAC9BA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAGVW,aAAe,EACfC,WAAa,EACbC,mBAAmBT,SAAQ,SAASU,mBAC5BA,kBAAkBE,WAAWC,UAAUK,SAAS,YAChDX,aAAeX,YACfY,WAAaZ,YAAcQ,gBAAgBM,kBAAkBL,QAKrEY,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU;;;;;;;;;;;MA5IzEZ,cAAgBoB,SAASC,iBAAiB,uBAC1CX,mBAAqBU,SAASC,iBAAiB,0BAC/CL,iBAAmBI,SAASC,iBAAiB,4BAG/CxB,YACAO,UACAG,QACAC,aACAC,oBAuBKS,cAAcI,UAAWC,QAASf,aAAcC,WAAYe,aAEjDJ,SAASC,iBAAiB,sBAGlCpB,SAAQ,SAASwB,QAErBA,OAAOC,MAAMC,QAAU,WAGnBC,WAAaH,OAAOI,cAAc,0BAA0BvB,IAG3DkB,aAAgBI,YAAcN,WAAaM,YAAcL,SACzDK,YAAcpB,cAAgBoB,YAAcnB,cAC7CgB,OAAOC,MAAMC,QAAU,qBAuG1BtB,gBAAgBC,WACdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM"} \ No newline at end of file diff --git a/amd/src/timefilter.js b/amd/src/timefilter.js index 2ddb3e0..31cf5ff 100644 --- a/amd/src/timefilter.js +++ b/amd/src/timefilter.js @@ -25,67 +25,171 @@ */ // Get the relevant radio buttons. -const radiobuttons = document.querySelectorAll('.ts_time_button'); +const alltimebutton = document.querySelectorAll('.ts_all_time_button'); +const futureradiobuttons = document.querySelectorAll('.ts_future_time_button'); +const pastradiobuttons = document.querySelectorAll('.ts_past_time_button'); + +// Define to change the time span, an additional time span and the current time. +let currenttime; +let timestart; +let timeend; +let addstarttime; +let addendtime; /** * Init function */ export function init() { - radiobuttons.forEach(function(radiobutton) { - radiobutton.addEventListener('change', function() { - // Get the current time in seconds. - let currenttime = new Date().getTime() / 1000; - let timestart; - let timeend; - - // Depending on the radiobutton id, set a time span. - switch (radiobutton.id) { - case "ts_time_all": - timestart = -9999999999; - timeend = 9999999999; - break; - case "ts_time_next_week": - timestart = currenttime; - timeend = currenttime + 604800; - break; - case "ts_time_next_month": - timestart = currenttime; - timeend = currenttime + 2629743; - break; - case "ts_time_last_week": - timestart = currenttime - 604800; - timeend = currenttime; - break; - case "ts_time_last_month": - timestart = currenttime - 2629743; - timeend = currenttime; - break; - default: - timestart = -9999999999; - timeend = 9999999999; - break; - } - - // Get all the right letters. - const letters = document.querySelectorAll('.townsquare_letter'); - - // Loop through each letter and hide/show based on radiobutton state. - letters.forEach(function(letter) { - // Get the created time stamp of each letter. - let lettertime = letter.querySelector('.townsquareletter_date').id; - - // If the radio button is checked and the letter is in the time span, show it. - if (radiobutton.checked) { - if (lettertime >= timestart && lettertime <= timeend) { - letter.style.display = 'block'; // Show the letter. - } else { - letter.style.display = 'none'; // Hide the letter. - } - } else { - letter.style.display = 'block'; // Show the letter. + // Set the current time. + currenttime = new Date().getTime() / 1000; + + // Add event listeners to the all kind of buttons. + alltimeaddEventListener(); + futuretimeaddEventListener(); + pasttimeaddEventListener(); +} + +/** + * Function to execute the filter + * @param {int} starttime Start of time span for filtering of the current pressed button + * @param {int} endtime End of time span for filtering of the current pressed + * @param {int} addstarttime Start of time span for filtering of an additional radio button. + * @param {int} addendtime End of time span for filtering of an additional radio button. + * @param {bool} buttonstate State of the radio button (true of false) + */ +function executefilter(starttime, endtime, addstarttime, addendtime, buttonstate) { + // Get all the letters. + const letters = document.querySelectorAll('.townsquare_letter'); + + // Loop through each letter and hide/show based on radiobutton state. + letters.forEach(function(letter) { + // First hide all letters, as different time spans can overlap. + letter.style.display = 'none'; + + // Get the created time stamp of each letter. + let lettertime = letter.querySelector('.townsquareletter_date').id; + + // If the radio button is checked and the letter is in the time span, show it. + if ((buttonstate && (lettertime >= starttime && lettertime <= endtime)) || + (lettertime >= addstarttime && lettertime <= addendtime)) { + letter.style.display = 'block'; + } + }); +} + +/** + * Function to add event listeners to the all_time button. + */ +function alltimeaddEventListener() { + alltimebutton.forEach(function(button) { + button.addEventListener('change', function() { + // Set the time span to show all letters. + timestart = currenttime - convertidtotime(button.id); + timeend = currenttime + convertidtotime(button.id); + addstarttime = 0; + addendtime = 0; + + // Disable all other radio buttons that filter more specific times. + futureradiobuttons.forEach(function(futureradiobutton) { + futureradiobutton.checked = false; + futureradiobutton.parentNode.classList.remove("active"); + }); + pastradiobuttons.forEach(function(pastradiobutton) { + pastradiobutton.checked = false; + pastradiobutton.parentNode.classList.remove("active"); + + }); + + // Execute the filter function. + executefilter(timestart, timeend, addstarttime,addendtime, button.checked); + }); + }); +} + +/** + * Function to add event listeners to the future time radio buttons. + */ +function futuretimeaddEventListener() { + futureradiobuttons.forEach(function(button) { + button.addEventListener('change', function() { + // Disable the all_time button. + alltimebutton.forEach(function(alltimebutton) { + alltimebutton.checked = false; + alltimebutton.parentNode.classList.remove('active'); + }); + + // Set the time span based on the radiobutton id. + timestart = currenttime; + timeend = currenttime + convertidtotime(button.id); + + // Check if one past time button is checked. If yes, set the additional time span based on its id. + addstarttime = 0; + addendtime = 0; + pastradiobuttons.forEach(function(pastradiobutton) { + if (pastradiobutton.parentNode.classList.contains('active')) { + addstarttime = currenttime - convertidtotime(pastradiobutton.id); + addendtime = currenttime; } + }); + + // Execute the filter function. + executefilter(timestart, timeend, addstarttime, addendtime, button.checked); + }); + }); +} +/** + * Function to add event listeners to the past time radio buttons. + */ +function pasttimeaddEventListener() { + pastradiobuttons.forEach(function(button) { + button.addEventListener('change', function() { + // Disable the all_time button. + alltimebutton.forEach(function(alltimebutton) { + alltimebutton.checked = false; + alltimebutton.parentNode.classList.remove('active'); + }); + + // Set the time span based on the radiobutton id. + timestart = currenttime - convertidtotime(button.id); + timeend = currenttime; + + // Check if one future time button is checked. If yes, set the additional time span based on its id. + addstarttime = 0; + addendtime = 0; + futureradiobuttons.forEach(function(futureradiobutton) { + if (futureradiobutton.parentNode.classList.contains('active')) { + addstarttime = currenttime; + addendtime = currenttime + convertidtotime(futureradiobutton.id); + } }); + + // Execute the filter function. + executefilter(timestart, timeend, addstarttime, addendtime, button.checked); }); }); } + +/** + * Function to convert the radio button id to a useable time span. + * @param {string} id The id of the radio button + * @returns {number} + */ +function convertidtotime(id) { + switch(id) { + case "ts_time_all": + return 15778463; + case "ts_time_next_twodays": + case "ts_time_last_twodays": + return 172800; + case "ts_time_next_fivedays": + case "ts_time_last_fivedays": + return 432000; + case "ts_time_next_week": + case "ts_time_last_week": + return 604800; + case "ts_time_next_month": + case "ts_time_last_month": + return 2592000; + } +} diff --git a/db/install.xml b/db/install.xml index 669d645..c904a77 100644 --- a/db/install.xml +++ b/db/install.xml @@ -8,7 +8,8 @@ - + + diff --git a/db/upgrade.php b/db/upgrade.php index ceb11cd..5b41a82 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -46,7 +46,8 @@ function xmldb_block_townsquare_upgrade($oldversion) { // Adding fields to table townsquare_usersettings. $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); - $table->add_field('timefilter', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); + $table->add_field('timefilterstart', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); + $table->add_field('timefilterend', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); $table->add_field('letterfilter', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); // Adding keys to table townsquare_usersettings. diff --git a/lang/en/block_townsquare.php b/lang/en/block_townsquare.php index f887806..551a894 100644 --- a/lang/en/block_townsquare.php +++ b/lang/en/block_townsquare.php @@ -46,8 +46,12 @@ $string['timefilter'] = 'Time filter'; $string['letterfilter'] = 'Letter filter'; $string['allnotifications'] = 'All notifications'; +$string['nexttwodaysnotifications'] = 'Next two days'; +$string['nextfivedaysnotifications'] = 'Next five days'; $string['nextweeknotifications'] = 'Next week'; $string['nextmonthnotifications'] = 'Next month'; +$string['lasttwodaysnotifications'] = 'last two days'; +$string['lastfivedaysnotifications'] = 'last five days'; $string['lastweeknotifications'] = 'Last week'; $string['lastmonthnotifications'] = 'Last month'; $string['basicletters'] = 'Basic letters'; diff --git a/templates/sidepanel.mustache b/templates/sidepanel.mustache index 4f92b96..de6e5d1 100644 --- a/templates/sidepanel.mustache +++ b/templates/sidepanel.mustache @@ -54,20 +54,39 @@
-
+ +
+ + + +
+ +
+ +
From a4ffb513143808c5e4685e3ab5024e5007a5e617 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 8 Feb 2024 17:20:42 +0100 Subject: [PATCH 025/123] WIP: functionality to save usersettings --- amd/build/timefilter.min.js | 2 +- amd/build/timefilter.min.js.map | 2 +- amd/build/usersettings_save.min.js | 12 +++ amd/build/usersettings_save.min.js.map | 1 + amd/src/usersettings_save.js | 139 +++++++++++++++++++++++++ block_townsquare.php | 2 + db/install.xml | 4 +- db/upgrade.php | 4 +- lang/en/block_townsquare.php | 10 ++ styles.css | 7 ++ templates/sidepanel.mustache | 16 ++- 11 files changed, 191 insertions(+), 8 deletions(-) create mode 100644 amd/build/usersettings_save.min.js create mode 100644 amd/build/usersettings_save.min.js.map create mode 100644 amd/src/usersettings_save.js diff --git a/amd/build/timefilter.min.js b/amd/build/timefilter.min.js index 0bab738..99931e3 100644 --- a/amd/build/timefilter.min.js +++ b/amd/build/timefilter.min.js @@ -1,4 +1,4 @@ -define("block_townsquare/timefilter",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){currenttime=(new Date).getTime()/1e3,alltimebutton.forEach((function(button){button.addEventListener("change",(function(){timestart=currenttime-convertidtotime(button.id),timeend=currenttime+convertidtotime(button.id),addstarttime=0,addendtime=0,futureradiobuttons.forEach((function(futureradiobutton){futureradiobutton.checked=!1,futureradiobutton.parentNode.classList.remove("active")})),pastradiobuttons.forEach((function(pastradiobutton){pastradiobutton.checked=!1,pastradiobutton.parentNode.classList.remove("active")})),executefilter(timestart,timeend,addstarttime,addendtime,button.checked)}))})),futureradiobuttons.forEach((function(button){button.addEventListener("change",(function(){alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})),timestart=currenttime,timeend=currenttime+convertidtotime(button.id),addstarttime=0,addendtime=0,pastradiobuttons.forEach((function(pastradiobutton){pastradiobutton.parentNode.classList.contains("active")&&(addstarttime=currenttime-convertidtotime(pastradiobutton.id),addendtime=currenttime)})),executefilter(timestart,timeend,addstarttime,addendtime,button.checked)}))})),pastradiobuttons.forEach((function(button){button.addEventListener("change",(function(){alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})),timestart=currenttime-convertidtotime(button.id),timeend=currenttime,addstarttime=0,addendtime=0,futureradiobuttons.forEach((function(futureradiobutton){futureradiobutton.parentNode.classList.contains("active")&&(addstarttime=currenttime,addendtime=currenttime+convertidtotime(futureradiobutton.id))})),executefilter(timestart,timeend,addstarttime,addendtime,button.checked)}))}))}; +define("block_townsquare/timefilter",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){currenttime=(new Date).getTime()/1e3,alltimebutton.forEach((function(button){button.addEventListener("click",(function(){timestart=currenttime-convertidtotime(button.id),timeend=currenttime+convertidtotime(button.id),addstarttime=0,addendtime=0,futureradiobuttons.forEach((function(futureradiobutton){futureradiobutton.checked=!1,futureradiobutton.parentNode.classList.remove("active")})),pastradiobuttons.forEach((function(pastradiobutton){pastradiobutton.checked=!1,pastradiobutton.parentNode.classList.remove("active")})),executefilter(timestart,timeend,addstarttime,addendtime,button.checked)}))})),futureradiobuttons.forEach((function(button){button.addEventListener("click",(function(){alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})),timestart=currenttime,timeend=currenttime+convertidtotime(button.id),addstarttime=0,addendtime=0,pastradiobuttons.forEach((function(pastradiobutton){pastradiobutton.parentNode.classList.contains("active")&&(addstarttime=currenttime-convertidtotime(pastradiobutton.id),addendtime=currenttime)})),executefilter(timestart,timeend,addstarttime,addendtime,button.checked)}))})),pastradiobuttons.forEach((function(button){button.addEventListener("click",(function(){alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})),timestart=currenttime-convertidtotime(button.id),timeend=currenttime,addstarttime=0,addendtime=0,futureradiobuttons.forEach((function(futureradiobutton){futureradiobutton.parentNode.classList.contains("active")&&(addstarttime=currenttime,addendtime=currenttime+convertidtotime(futureradiobutton.id))})),executefilter(timestart,timeend,addstarttime,addendtime,button.checked)}))}))}; /** * Javascript for the time filter * diff --git a/amd/build/timefilter.min.js.map b/amd/build/timefilter.min.js.map index d15d352..910e58a 100644 --- a/amd/build/timefilter.min.js.map +++ b/amd/build/timefilter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"timefilter.min.js","sources":["../src/timefilter.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 * Javascript for the time filter\n *\n * This file implements 1 functionality:\n * - Checks, which of the radio buttons is pressed and filters the content based on the time.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant radio buttons.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Define to change the time span, an additional time span and the current time.\nlet currenttime;\nlet timestart;\nlet timeend;\nlet addstarttime;\nlet addendtime;\n\n/**\n * Init function\n */\nexport function init() {\n // Set the current time.\n currenttime = new Date().getTime() / 1000;\n\n // Add event listeners to the all kind of buttons.\n alltimeaddEventListener();\n futuretimeaddEventListener();\n pasttimeaddEventListener();\n}\n\n/**\n * Function to execute the filter\n * @param {int} starttime Start of time span for filtering of the current pressed button\n * @param {int} endtime End of time span for filtering of the current pressed\n * @param {int} addstarttime Start of time span for filtering of an additional radio button.\n * @param {int} addendtime End of time span for filtering of an additional radio button.\n * @param {bool} buttonstate State of the radio button (true of false)\n */\nfunction executefilter(starttime, endtime, addstarttime, addendtime, buttonstate) {\n // Get all the letters.\n const letters = document.querySelectorAll('.townsquare_letter');\n\n // Loop through each letter and hide/show based on radiobutton state.\n letters.forEach(function(letter) {\n // First hide all letters, as different time spans can overlap.\n letter.style.display = 'none';\n\n // Get the created time stamp of each letter.\n let lettertime = letter.querySelector('.townsquareletter_date').id;\n\n // If the radio button is checked and the letter is in the time span, show it.\n if ((buttonstate && (lettertime >= starttime && lettertime <= endtime)) ||\n (lettertime >= addstarttime && lettertime <= addendtime)) {\n letter.style.display = 'block';\n }\n });\n}\n\n/**\n * Function to add event listeners to the all_time button.\n */\nfunction alltimeaddEventListener() {\n alltimebutton.forEach(function(button) {\n button.addEventListener('change', function() {\n // Set the time span to show all letters.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime + convertidtotime(button.id);\n addstarttime = 0;\n addendtime = 0;\n\n // Disable all other radio buttons that filter more specific times.\n futureradiobuttons.forEach(function(futureradiobutton) {\n futureradiobutton.checked = false;\n futureradiobutton.parentNode.classList.remove(\"active\");\n });\n pastradiobuttons.forEach(function(pastradiobutton) {\n pastradiobutton.checked = false;\n pastradiobutton.parentNode.classList.remove(\"active\");\n\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime,addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the future time radio buttons.\n */\nfunction futuretimeaddEventListener() {\n futureradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime;\n timeend = currenttime + convertidtotime(button.id);\n\n // Check if one past time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n pastradiobuttons.forEach(function(pastradiobutton) {\n if (pastradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime - convertidtotime(pastradiobutton.id);\n addendtime = currenttime;\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the past time radio buttons.\n */\nfunction pasttimeaddEventListener() {\n pastradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime;\n\n // Check if one future time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n futureradiobuttons.forEach(function(futureradiobutton) {\n if (futureradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime;\n addendtime = currenttime + convertidtotime(futureradiobutton.id);\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n"],"names":["currenttime","Date","getTime","alltimebutton","forEach","button","addEventListener","timestart","convertidtotime","id","timeend","addstarttime","addendtime","futureradiobuttons","futureradiobutton","checked","parentNode","classList","remove","pastradiobuttons","pastradiobutton","executefilter","contains","document","querySelectorAll","starttime","endtime","buttonstate","letter","style","display","lettertime","querySelector"],"mappings":"sJA2CIA,aAAc,IAAIC,MAAOC,UAAY,IAwCrCC,cAAcC,SAAQ,SAASC,QAC3BA,OAAOC,iBAAiB,UAAU,WAE9BC,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAC/CE,aAAe,EACfC,WAAa,EAGbC,mBAAmBT,SAAQ,SAASU,mBAChCA,kBAAkBC,SAAU,EAC5BD,kBAAkBE,WAAWC,UAAUC,OAAO,aAElDC,iBAAiBf,SAAQ,SAASgB,iBAC9BA,gBAAgBL,SAAU,EAC1BK,gBAAgBJ,WAAWC,UAAUC,OAAO,aAKhDG,cAAcd,UAAWG,QAASC,aAAaC,WAAYP,OAAOU,eAS1EF,mBAAmBT,SAAQ,SAASC,QAChCA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YACZU,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAG/CE,aAAe,EACfC,WAAa,EACbO,iBAAiBf,SAAQ,SAASgB,iBAC1BA,gBAAgBJ,WAAWC,UAAUK,SAAS,YAC9CX,aAAeX,YAAcQ,gBAAgBY,gBAAgBX,IAC7DG,WAAaZ,gBAKrBqB,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU,eAS3EI,iBAAiBf,SAAQ,SAASC,QAC9BA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAGVW,aAAe,EACfC,WAAa,EACbC,mBAAmBT,SAAQ,SAASU,mBAC5BA,kBAAkBE,WAAWC,UAAUK,SAAS,YAChDX,aAAeX,YACfY,WAAaZ,YAAcQ,gBAAgBM,kBAAkBL,QAKrEY,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU;;;;;;;;;;;MA5IzEZ,cAAgBoB,SAASC,iBAAiB,uBAC1CX,mBAAqBU,SAASC,iBAAiB,0BAC/CL,iBAAmBI,SAASC,iBAAiB,4BAG/CxB,YACAO,UACAG,QACAC,aACAC,oBAuBKS,cAAcI,UAAWC,QAASf,aAAcC,WAAYe,aAEjDJ,SAASC,iBAAiB,sBAGlCpB,SAAQ,SAASwB,QAErBA,OAAOC,MAAMC,QAAU,WAGnBC,WAAaH,OAAOI,cAAc,0BAA0BvB,IAG3DkB,aAAgBI,YAAcN,WAAaM,YAAcL,SACzDK,YAAcpB,cAAgBoB,YAAcnB,cAC7CgB,OAAOC,MAAMC,QAAU,qBAuG1BtB,gBAAgBC,WACdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM"} \ No newline at end of file +{"version":3,"file":"timefilter.min.js","sources":["../src/timefilter.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 * Javascript for the time filter\n *\n * This file implements 1 functionality:\n * - Checks, which of the radio buttons is pressed and filters the content based on the time.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant radio buttons.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Define to change the time span, an additional time span and the current time.\nlet currenttime;\nlet timestart;\nlet timeend;\nlet addstarttime;\nlet addendtime;\n\n/**\n * Init function\n */\nexport function init() {\n // Set the current time.\n currenttime = new Date().getTime() / 1000;\n\n // Add event listeners to the all kind of buttons.\n alltimeaddEventListener();\n futuretimeaddEventListener();\n pasttimeaddEventListener();\n}\n\n/**\n * Function to execute the filter\n * @param {int} starttime Start of time span for filtering of the current pressed button\n * @param {int} endtime End of time span for filtering of the current pressed\n * @param {int} addstarttime Start of time span for filtering of an additional radio button.\n * @param {int} addendtime End of time span for filtering of an additional radio button.\n * @param {bool} buttonstate State of the radio button (true of false)\n */\nfunction executefilter(starttime, endtime, addstarttime, addendtime, buttonstate) {\n // Get all the letters.\n const letters = document.querySelectorAll('.townsquare_letter');\n\n // Loop through each letter and hide/show based on radiobutton state.\n letters.forEach(function(letter) {\n // First hide all letters, as different time spans can overlap.\n letter.style.display = 'none';\n\n // Get the created time stamp of each letter.\n let lettertime = letter.querySelector('.townsquareletter_date').id;\n\n // If the radio button is checked and the letter is in the time span, show it.\n if ((buttonstate && (lettertime >= starttime && lettertime <= endtime)) ||\n (lettertime >= addstarttime && lettertime <= addendtime)) {\n letter.style.display = 'block';\n }\n });\n}\n\n/**\n * Function to add event listeners to the all_time button.\n */\nfunction alltimeaddEventListener() {\n alltimebutton.forEach(function(button) {\n button.addEventListener('click', function() {\n // Set the time span to show all letters.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime + convertidtotime(button.id);\n addstarttime = 0;\n addendtime = 0;\n\n // Disable all other radio buttons that filter more specific times.\n futureradiobuttons.forEach(function(futureradiobutton) {\n futureradiobutton.checked = false;\n futureradiobutton.parentNode.classList.remove(\"active\");\n });\n pastradiobuttons.forEach(function(pastradiobutton) {\n pastradiobutton.checked = false;\n pastradiobutton.parentNode.classList.remove(\"active\");\n\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime,addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the future time radio buttons.\n */\nfunction futuretimeaddEventListener() {\n futureradiobuttons.forEach(function(button) {\n button.addEventListener('click', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime;\n timeend = currenttime + convertidtotime(button.id);\n\n // Check if one past time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n pastradiobuttons.forEach(function(pastradiobutton) {\n if (pastradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime - convertidtotime(pastradiobutton.id);\n addendtime = currenttime;\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the past time radio buttons.\n */\nfunction pasttimeaddEventListener() {\n pastradiobuttons.forEach(function(button) {\n button.addEventListener('click', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime;\n\n // Check if one future time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n futureradiobuttons.forEach(function(futureradiobutton) {\n if (futureradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime;\n addendtime = currenttime + convertidtotime(futureradiobutton.id);\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n"],"names":["currenttime","Date","getTime","alltimebutton","forEach","button","addEventListener","timestart","convertidtotime","id","timeend","addstarttime","addendtime","futureradiobuttons","futureradiobutton","checked","parentNode","classList","remove","pastradiobuttons","pastradiobutton","executefilter","contains","document","querySelectorAll","starttime","endtime","buttonstate","letter","style","display","lettertime","querySelector"],"mappings":"sJA2CIA,aAAc,IAAIC,MAAOC,UAAY,IAwCrCC,cAAcC,SAAQ,SAASC,QAC3BA,OAAOC,iBAAiB,SAAS,WAE7BC,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAC/CE,aAAe,EACfC,WAAa,EAGbC,mBAAmBT,SAAQ,SAASU,mBAChCA,kBAAkBC,SAAU,EAC5BD,kBAAkBE,WAAWC,UAAUC,OAAO,aAElDC,iBAAiBf,SAAQ,SAASgB,iBAC9BA,gBAAgBL,SAAU,EAC1BK,gBAAgBJ,WAAWC,UAAUC,OAAO,aAKhDG,cAAcd,UAAWG,QAASC,aAAaC,WAAYP,OAAOU,eAS1EF,mBAAmBT,SAAQ,SAASC,QAChCA,OAAOC,iBAAiB,SAAS,WAE7BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YACZU,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAG/CE,aAAe,EACfC,WAAa,EACbO,iBAAiBf,SAAQ,SAASgB,iBAC1BA,gBAAgBJ,WAAWC,UAAUK,SAAS,YAC9CX,aAAeX,YAAcQ,gBAAgBY,gBAAgBX,IAC7DG,WAAaZ,gBAKrBqB,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU,eAS3EI,iBAAiBf,SAAQ,SAASC,QAC9BA,OAAOC,iBAAiB,SAAS,WAE7BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAGVW,aAAe,EACfC,WAAa,EACbC,mBAAmBT,SAAQ,SAASU,mBAC5BA,kBAAkBE,WAAWC,UAAUK,SAAS,YAChDX,aAAeX,YACfY,WAAaZ,YAAcQ,gBAAgBM,kBAAkBL,QAKrEY,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU;;;;;;;;;;;MA5IzEZ,cAAgBoB,SAASC,iBAAiB,uBAC1CX,mBAAqBU,SAASC,iBAAiB,0BAC/CL,iBAAmBI,SAASC,iBAAiB,4BAG/CxB,YACAO,UACAG,QACAC,aACAC,oBAuBKS,cAAcI,UAAWC,QAASf,aAAcC,WAAYe,aAEjDJ,SAASC,iBAAiB,sBAGlCpB,SAAQ,SAASwB,QAErBA,OAAOC,MAAMC,QAAU,WAGnBC,WAAaH,OAAOI,cAAc,0BAA0BvB,IAG3DkB,aAAgBI,YAAcN,WAAaM,YAAcL,SACzDK,YAAcpB,cAAgBoB,YAAcnB,cAC7CgB,OAAOC,MAAMC,QAAU,qBAuG1BtB,gBAAgBC,WACdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM"} \ No newline at end of file diff --git a/amd/build/usersettings_save.min.js b/amd/build/usersettings_save.min.js new file mode 100644 index 0000000..317a021 --- /dev/null +++ b/amd/build/usersettings_save.min.js @@ -0,0 +1,12 @@ +/** + * Javascript to save the user settings in the database. + * + * This file implements 1 functionality: + * - If the "save settings" button is pressed, store the settings in the database. + * + * @module block_townsquare/timefilter + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +//# sourceMappingURL=usersettings_save.min.js.map \ No newline at end of file diff --git a/amd/build/usersettings_save.min.js.map b/amd/build/usersettings_save.min.js.map new file mode 100644 index 0000000..3732e99 --- /dev/null +++ b/amd/build/usersettings_save.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"usersettings_save.min.js","sources":[],"sourcesContent":[],"names":[],"mappings":""} \ No newline at end of file diff --git a/amd/src/usersettings_save.js b/amd/src/usersettings_save.js new file mode 100644 index 0000000..1e2a6bf --- /dev/null +++ b/amd/src/usersettings_save.js @@ -0,0 +1,139 @@ +// 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 . + +/** + * Javascript to save the user settings in the database. + * + * This file implements 1 functionality: + * - If the "save settings" button is pressed, store the settings in the database. + * + * @module block_townsquare/timefilter + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +// Get the save button for the user settings. +const savebutton = document.getElementById('ts_usersettings_savebutton'); + +/** + * Init function + */ +export function init() { + // Add event listener to the save button. + savebutton.addEventListener('click', function(button) { + // First step: collect the current settings. + + // Get the relevant time spans of the time filter. + let timespans = collecttimefiltersettings(); + + // Get the setting of the letter filter checkboxes. + let letterfilters = collectletterfiltersettings(); + + // Second step: store the usersettings in the database.atu + }); +} + +/** + * Function to collect the letter filter settings. + * @returns {{completionletter: boolean, basicletter: boolean, postletter: boolean}} + */ +function collectletterfiltersettings() { + let settings = {'basicletter': false, 'completionletter': false, 'postletter':false }; + + const checkboxes = document.querySelectorAll('.ts_letter_checkbox'); + + checkboxes.forEach(function(checkbox) { + if (checkbox.checked) { + switch(checkbox.id) { + case "basicletter": + settings['basicletter'] = true; + break; + case "completionletter": + settings['completionletter'] = true; + break; + case "postletter": + settings['postletter'] = true; + break; + + } + } + }); + return settings; +} + +/** + * Function to collect the time filter settings. + * @returns {{timepast: number, timefuture: number}} + */ +function collecttimefiltersettings() { + let settings = { timepast: 0, timefuture: 0}; + + // Get the relevant time spans of the time filter. + const alltimebutton = document.querySelectorAll('.ts_all_time_button'); + const futureradiobuttons = document.querySelectorAll('.ts_future_time_button'); + const pastradiobuttons = document.querySelectorAll('.ts_past_time_button'); + + // Check if the alltimebutton is set. + alltimebutton.foreach(function(button) { + if (button.parentNode.classList.contains('active')) { + // Get the timespan. + settings['timepast'] = convertidtotime(button.id); + settings['timefuture'] = convertidtotime(button.id); + return settings; + } + }); + + // If the alltimebutton is not set, check which of the future/past buttons is set. + futureradiobuttons.foreach(function(button) { + if (button.parentNode.classList.contains('active')) { + // Get the timespan. + settings['timefuture'] = convertidtotime(button.id); + } + }); + + pastradiobuttons.foreach(function(button) { + if (button.parentNode.classList.contains('active')) { + // Get the timespan. + settings['timepast'] = convertidtotime(button.id); + } + }); + return settings; +} + + +/** + * Function to convert the radio button id to a useable time span. + * @param {string} id The id of the radio button + * @returns {number} + */ +function convertidtotime(id) { + // TODO: Please use global functions if possible. + switch(id) { + case "ts_time_all": + return 15778463; + case "ts_time_next_twodays": + case "ts_time_last_twodays": + return 172800; + case "ts_time_next_fivedays": + case "ts_time_last_fivedays": + return 432000; + case "ts_time_next_week": + case "ts_time_last_week": + return 604800; + case "ts_time_next_month": + case "ts_time_last_month": + return 2592000; + } +} \ No newline at end of file diff --git a/block_townsquare.php b/block_townsquare.php index 156729d..c45a453 100644 --- a/block_townsquare.php +++ b/block_townsquare.php @@ -50,8 +50,10 @@ public function get_content():object { $mustachedata = new stdClass(); $mustachedata->content = $controller->content; $mustachedata->courses = $controller->courses; + $mustachedata->helpicon = ['text' => get_string('savehelpicontext', 'block_townsquare')]; $this->content = new stdClass(); $this->content->text = $OUTPUT->render_from_template('block_townsquare/blockcontent', $mustachedata); + // Load all javascripts. $this->page->requires->js_call_amd('block_townsquare/postletter', 'init'); $this->page->requires->js_call_amd('block_townsquare/coursefilter', 'init'); diff --git a/db/install.xml b/db/install.xml index c904a77..33e90b2 100644 --- a/db/install.xml +++ b/db/install.xml @@ -8,8 +8,8 @@ - - + + diff --git a/db/upgrade.php b/db/upgrade.php index 5b41a82..a5f9af0 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -46,8 +46,8 @@ function xmldb_block_townsquare_upgrade($oldversion) { // Adding fields to table townsquare_usersettings. $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); - $table->add_field('timefilterstart', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); - $table->add_field('timefilterend', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); + $table->add_field('timefilterpast', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); + $table->add_field('timefilterfuture', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); $table->add_field('letterfilter', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); // Adding keys to table townsquare_usersettings. diff --git a/lang/en/block_townsquare.php b/lang/en/block_townsquare.php index 551a894..7afcdee 100644 --- a/lang/en/block_townsquare.php +++ b/lang/en/block_townsquare.php @@ -42,9 +42,13 @@ $string['orientationmarkercontent'] = 'Hi {$a->username}, welcome to townsquare! Today is the {$a->date}'; // Side panel filter strings. + +// Filter headers. $string['coursefilter'] = 'Course filter'; $string['timefilter'] = 'Time filter'; $string['letterfilter'] = 'Letter filter'; + +// Time filter options. $string['allnotifications'] = 'All notifications'; $string['nexttwodaysnotifications'] = 'Next two days'; $string['nextfivedaysnotifications'] = 'Next five days'; @@ -54,10 +58,16 @@ $string['lastfivedaysnotifications'] = 'last five days'; $string['lastweeknotifications'] = 'Last week'; $string['lastmonthnotifications'] = 'Last month'; + +// Letter filter options. $string['basicletters'] = 'Basic letters'; $string['completionletters'] = 'Activity Completions'; $string['postletters'] = 'Forum Posts'; +// Save button strings. +$string['savebutton'] = 'Save settings'; +$string['savehelpicontext'] = 'Save Settings for the future'; + // Letter strings. $string['invalidmodulename'] = 'Module name is unknown or not supported'; diff --git a/styles.css b/styles.css index bfe4e06..da70b1b 100644 --- a/styles.css +++ b/styles.css @@ -15,6 +15,13 @@ } /* Style for the side panel filter */ +.ts_usersettings_save { + display: flex; +} + +.ts_usersettings_button { + flex: 1; +} /* Style for all letter or content templates */ diff --git a/templates/sidepanel.mustache b/templates/sidepanel.mustache index de6e5d1..2535573 100644 --- a/templates/sidepanel.mustache +++ b/templates/sidepanel.mustache @@ -54,8 +54,8 @@
-
@@ -124,4 +124,16 @@
+ +
+
+ +
+
+ {{#helpicon}} + {{>core/help_icon}} + {{/helpicon}} +
+
+
\ No newline at end of file From 37a45792d33c31f8375a63a5549f38c5ea8af113 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 9 Feb 2024 12:45:26 +0100 Subject: [PATCH 026/123] support for database call from javascript --- block_townsquare.php | 6 ++- db/services.php | 36 +++++++++++++++ externallib.php | 108 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 db/services.php create mode 100644 externallib.php diff --git a/block_townsquare.php b/block_townsquare.php index c45a453..c65528b 100644 --- a/block_townsquare.php +++ b/block_townsquare.php @@ -40,7 +40,7 @@ public function init():void { * @return object|null The block HTML. */ public function get_content():object { - global $OUTPUT; + global $OUTPUT, $DB, $USER; if ($this->content !== null) { return $this->content; @@ -54,11 +54,15 @@ public function get_content():object { $this->content = new stdClass(); $this->content->text = $OUTPUT->render_from_template('block_townsquare/blockcontent', $mustachedata); + // Get the user settings if available. + $usersettings = $DB->get_record('townsquare_usersettings', ['userid' => $USER->id]); + // Load all javascripts. $this->page->requires->js_call_amd('block_townsquare/postletter', 'init'); $this->page->requires->js_call_amd('block_townsquare/coursefilter', 'init'); $this->page->requires->js_call_amd('block_townsquare/timefilter', 'init'); $this->page->requires->js_call_amd('block_townsquare/letterfilter', 'init'); + $this->page->requires->js_call_amd('block_townsquare/usersettings_save', 'init', [$USER->id, $usersettings]); return $this->content; } diff --git a/db/services.php b/db/services.php new file mode 100644 index 0000000..b2e13bf --- /dev/null +++ b/db/services.php @@ -0,0 +1,36 @@ +. + +/** + * Townsquare external functions and service definitions. + * + * @package block_townsquare + * @category external + * @copyright 2017 Kennet Winter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +defined('MOODLE_INTERNAL') || die; + +$functions = [ + 'block_townsquare_record_usersettings' => [ + 'classname' => 'block_townsquare_external', + 'methodname' => 'record_usersettings', + 'classpath' => 'blocks/townsquare/externallib.php', + 'description' => 'Records the user settings for the townsquare block', + 'type' => 'write', + 'ajax' => true, + ], +]; \ No newline at end of file diff --git a/externallib.php b/externallib.php new file mode 100644 index 0000000..e8b4ae5 --- /dev/null +++ b/externallib.php @@ -0,0 +1,108 @@ +. + +/** + * External townsquare API + * + * @package block_townsquare + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->libdir . '/externallib.php'); +require_once($CFG->dirroot . '/mod/moodleoverflow/locallib.php'); + +/** + * Class implementing the external API, esp. for AJAX functions. + * + * @package block_townsquare + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class block_townsquare_external extends external_api { + + /** + * Returns description of method parameters + * @return external_function_parameters + */ + public static function record_usersettings_parameters() { + return new external_function_parameters( + [ + 'userid' => new external_value(PARAM_INT, 'the user id'), + 'timefilterpast' => new external_value(PARAM_INT, 'time span for filtering the past'), + 'timefilterfuture' => new external_value(PARAM_INT, 'time span for filtering the future'), + 'letterfilter' => new external_value(PARAM_INT, 'setting of the letter filter'), + ] + ); + } + + /** + * Return the result of the record_usersettings function + * @return external_value + */ + public static function record_usersettings_returns() { + return new external_value(PARAM_BOOL, 'true if successful'); + } + + /** + * Record the user settings + * + * @param int $userid The user id + * @param int $timefilterpast Time span for filtering the past + * @param int $timefilterfuture Time span for filtering the future + * @param int $letterfilter Setting of the letter filter + * @return bool + */ + public static function record_usersettings($userid, $timefilterpast, $timefilterfuture, $letterfilter) { + global $DB; + + $transaction = $DB->start_delegated_transaction(); + + // Check if the user already has a record in the database + if ($records = $DB->get_records('townsquare_usersettings', ['userid' => $userid])) { + // If there more than a record (it only should be only one), delete all of them and insert the new one. + if (count($records) > 1) { + try { + foreach ($records as $record) { + $DB->delete_records('townsquare_usersettings', ['id' => $record->id]); + } + } catch (Exception $e) { + $transaction->rollback($e); + return false; + } + } else { + // Upgrade the existing record. + $record = reset($records); + $record->timefilterpast = $timefilterpast; + $record->timefilterfuture = $timefilterfuture; + $record->letterfilter = $letterfilter; + $DB->update_record('townsquare_usersettings', $record); + return true; + } + } + $record = new stdClass(); + $record->userid = $userid; + $record->timefilterpast = $timefilterpast; + $record->timefilterfuture = $timefilterfuture; + $record->letterfilter = $letterfilter; + $DB->insert_record('townsquare_usersettings', $record); + return true; + } + +} \ No newline at end of file From 684e9af57b801fa2547fe6ee9e620482a850493a Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 9 Feb 2024 13:38:14 +0100 Subject: [PATCH 027/123] WIP: use javascript to controll settings saving --- amd/build/timefilter.min.js | 2 +- amd/build/timefilter.min.js.map | 2 +- amd/build/usersettings_save.min.js | 19 +-- amd/build/usersettings_save.min.js.map | 2 +- amd/src/usersettings_save.js | 199 ++++++++++++++++++++++--- externallib.php | 2 +- templates/sidepanel.mustache | 6 +- 7 files changed, 192 insertions(+), 40 deletions(-) diff --git a/amd/build/timefilter.min.js b/amd/build/timefilter.min.js index 99931e3..0bab738 100644 --- a/amd/build/timefilter.min.js +++ b/amd/build/timefilter.min.js @@ -1,4 +1,4 @@ -define("block_townsquare/timefilter",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){currenttime=(new Date).getTime()/1e3,alltimebutton.forEach((function(button){button.addEventListener("click",(function(){timestart=currenttime-convertidtotime(button.id),timeend=currenttime+convertidtotime(button.id),addstarttime=0,addendtime=0,futureradiobuttons.forEach((function(futureradiobutton){futureradiobutton.checked=!1,futureradiobutton.parentNode.classList.remove("active")})),pastradiobuttons.forEach((function(pastradiobutton){pastradiobutton.checked=!1,pastradiobutton.parentNode.classList.remove("active")})),executefilter(timestart,timeend,addstarttime,addendtime,button.checked)}))})),futureradiobuttons.forEach((function(button){button.addEventListener("click",(function(){alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})),timestart=currenttime,timeend=currenttime+convertidtotime(button.id),addstarttime=0,addendtime=0,pastradiobuttons.forEach((function(pastradiobutton){pastradiobutton.parentNode.classList.contains("active")&&(addstarttime=currenttime-convertidtotime(pastradiobutton.id),addendtime=currenttime)})),executefilter(timestart,timeend,addstarttime,addendtime,button.checked)}))})),pastradiobuttons.forEach((function(button){button.addEventListener("click",(function(){alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})),timestart=currenttime-convertidtotime(button.id),timeend=currenttime,addstarttime=0,addendtime=0,futureradiobuttons.forEach((function(futureradiobutton){futureradiobutton.parentNode.classList.contains("active")&&(addstarttime=currenttime,addendtime=currenttime+convertidtotime(futureradiobutton.id))})),executefilter(timestart,timeend,addstarttime,addendtime,button.checked)}))}))}; +define("block_townsquare/timefilter",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){currenttime=(new Date).getTime()/1e3,alltimebutton.forEach((function(button){button.addEventListener("change",(function(){timestart=currenttime-convertidtotime(button.id),timeend=currenttime+convertidtotime(button.id),addstarttime=0,addendtime=0,futureradiobuttons.forEach((function(futureradiobutton){futureradiobutton.checked=!1,futureradiobutton.parentNode.classList.remove("active")})),pastradiobuttons.forEach((function(pastradiobutton){pastradiobutton.checked=!1,pastradiobutton.parentNode.classList.remove("active")})),executefilter(timestart,timeend,addstarttime,addendtime,button.checked)}))})),futureradiobuttons.forEach((function(button){button.addEventListener("change",(function(){alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})),timestart=currenttime,timeend=currenttime+convertidtotime(button.id),addstarttime=0,addendtime=0,pastradiobuttons.forEach((function(pastradiobutton){pastradiobutton.parentNode.classList.contains("active")&&(addstarttime=currenttime-convertidtotime(pastradiobutton.id),addendtime=currenttime)})),executefilter(timestart,timeend,addstarttime,addendtime,button.checked)}))})),pastradiobuttons.forEach((function(button){button.addEventListener("change",(function(){alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})),timestart=currenttime-convertidtotime(button.id),timeend=currenttime,addstarttime=0,addendtime=0,futureradiobuttons.forEach((function(futureradiobutton){futureradiobutton.parentNode.classList.contains("active")&&(addstarttime=currenttime,addendtime=currenttime+convertidtotime(futureradiobutton.id))})),executefilter(timestart,timeend,addstarttime,addendtime,button.checked)}))}))}; /** * Javascript for the time filter * diff --git a/amd/build/timefilter.min.js.map b/amd/build/timefilter.min.js.map index 910e58a..d15d352 100644 --- a/amd/build/timefilter.min.js.map +++ b/amd/build/timefilter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"timefilter.min.js","sources":["../src/timefilter.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 * Javascript for the time filter\n *\n * This file implements 1 functionality:\n * - Checks, which of the radio buttons is pressed and filters the content based on the time.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant radio buttons.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Define to change the time span, an additional time span and the current time.\nlet currenttime;\nlet timestart;\nlet timeend;\nlet addstarttime;\nlet addendtime;\n\n/**\n * Init function\n */\nexport function init() {\n // Set the current time.\n currenttime = new Date().getTime() / 1000;\n\n // Add event listeners to the all kind of buttons.\n alltimeaddEventListener();\n futuretimeaddEventListener();\n pasttimeaddEventListener();\n}\n\n/**\n * Function to execute the filter\n * @param {int} starttime Start of time span for filtering of the current pressed button\n * @param {int} endtime End of time span for filtering of the current pressed\n * @param {int} addstarttime Start of time span for filtering of an additional radio button.\n * @param {int} addendtime End of time span for filtering of an additional radio button.\n * @param {bool} buttonstate State of the radio button (true of false)\n */\nfunction executefilter(starttime, endtime, addstarttime, addendtime, buttonstate) {\n // Get all the letters.\n const letters = document.querySelectorAll('.townsquare_letter');\n\n // Loop through each letter and hide/show based on radiobutton state.\n letters.forEach(function(letter) {\n // First hide all letters, as different time spans can overlap.\n letter.style.display = 'none';\n\n // Get the created time stamp of each letter.\n let lettertime = letter.querySelector('.townsquareletter_date').id;\n\n // If the radio button is checked and the letter is in the time span, show it.\n if ((buttonstate && (lettertime >= starttime && lettertime <= endtime)) ||\n (lettertime >= addstarttime && lettertime <= addendtime)) {\n letter.style.display = 'block';\n }\n });\n}\n\n/**\n * Function to add event listeners to the all_time button.\n */\nfunction alltimeaddEventListener() {\n alltimebutton.forEach(function(button) {\n button.addEventListener('click', function() {\n // Set the time span to show all letters.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime + convertidtotime(button.id);\n addstarttime = 0;\n addendtime = 0;\n\n // Disable all other radio buttons that filter more specific times.\n futureradiobuttons.forEach(function(futureradiobutton) {\n futureradiobutton.checked = false;\n futureradiobutton.parentNode.classList.remove(\"active\");\n });\n pastradiobuttons.forEach(function(pastradiobutton) {\n pastradiobutton.checked = false;\n pastradiobutton.parentNode.classList.remove(\"active\");\n\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime,addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the future time radio buttons.\n */\nfunction futuretimeaddEventListener() {\n futureradiobuttons.forEach(function(button) {\n button.addEventListener('click', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime;\n timeend = currenttime + convertidtotime(button.id);\n\n // Check if one past time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n pastradiobuttons.forEach(function(pastradiobutton) {\n if (pastradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime - convertidtotime(pastradiobutton.id);\n addendtime = currenttime;\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the past time radio buttons.\n */\nfunction pasttimeaddEventListener() {\n pastradiobuttons.forEach(function(button) {\n button.addEventListener('click', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime;\n\n // Check if one future time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n futureradiobuttons.forEach(function(futureradiobutton) {\n if (futureradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime;\n addendtime = currenttime + convertidtotime(futureradiobutton.id);\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n"],"names":["currenttime","Date","getTime","alltimebutton","forEach","button","addEventListener","timestart","convertidtotime","id","timeend","addstarttime","addendtime","futureradiobuttons","futureradiobutton","checked","parentNode","classList","remove","pastradiobuttons","pastradiobutton","executefilter","contains","document","querySelectorAll","starttime","endtime","buttonstate","letter","style","display","lettertime","querySelector"],"mappings":"sJA2CIA,aAAc,IAAIC,MAAOC,UAAY,IAwCrCC,cAAcC,SAAQ,SAASC,QAC3BA,OAAOC,iBAAiB,SAAS,WAE7BC,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAC/CE,aAAe,EACfC,WAAa,EAGbC,mBAAmBT,SAAQ,SAASU,mBAChCA,kBAAkBC,SAAU,EAC5BD,kBAAkBE,WAAWC,UAAUC,OAAO,aAElDC,iBAAiBf,SAAQ,SAASgB,iBAC9BA,gBAAgBL,SAAU,EAC1BK,gBAAgBJ,WAAWC,UAAUC,OAAO,aAKhDG,cAAcd,UAAWG,QAASC,aAAaC,WAAYP,OAAOU,eAS1EF,mBAAmBT,SAAQ,SAASC,QAChCA,OAAOC,iBAAiB,SAAS,WAE7BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YACZU,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAG/CE,aAAe,EACfC,WAAa,EACbO,iBAAiBf,SAAQ,SAASgB,iBAC1BA,gBAAgBJ,WAAWC,UAAUK,SAAS,YAC9CX,aAAeX,YAAcQ,gBAAgBY,gBAAgBX,IAC7DG,WAAaZ,gBAKrBqB,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU,eAS3EI,iBAAiBf,SAAQ,SAASC,QAC9BA,OAAOC,iBAAiB,SAAS,WAE7BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAGVW,aAAe,EACfC,WAAa,EACbC,mBAAmBT,SAAQ,SAASU,mBAC5BA,kBAAkBE,WAAWC,UAAUK,SAAS,YAChDX,aAAeX,YACfY,WAAaZ,YAAcQ,gBAAgBM,kBAAkBL,QAKrEY,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU;;;;;;;;;;;MA5IzEZ,cAAgBoB,SAASC,iBAAiB,uBAC1CX,mBAAqBU,SAASC,iBAAiB,0BAC/CL,iBAAmBI,SAASC,iBAAiB,4BAG/CxB,YACAO,UACAG,QACAC,aACAC,oBAuBKS,cAAcI,UAAWC,QAASf,aAAcC,WAAYe,aAEjDJ,SAASC,iBAAiB,sBAGlCpB,SAAQ,SAASwB,QAErBA,OAAOC,MAAMC,QAAU,WAGnBC,WAAaH,OAAOI,cAAc,0BAA0BvB,IAG3DkB,aAAgBI,YAAcN,WAAaM,YAAcL,SACzDK,YAAcpB,cAAgBoB,YAAcnB,cAC7CgB,OAAOC,MAAMC,QAAU,qBAuG1BtB,gBAAgBC,WACdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM"} \ No newline at end of file +{"version":3,"file":"timefilter.min.js","sources":["../src/timefilter.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 * Javascript for the time filter\n *\n * This file implements 1 functionality:\n * - Checks, which of the radio buttons is pressed and filters the content based on the time.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant radio buttons.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Define to change the time span, an additional time span and the current time.\nlet currenttime;\nlet timestart;\nlet timeend;\nlet addstarttime;\nlet addendtime;\n\n/**\n * Init function\n */\nexport function init() {\n // Set the current time.\n currenttime = new Date().getTime() / 1000;\n\n // Add event listeners to the all kind of buttons.\n alltimeaddEventListener();\n futuretimeaddEventListener();\n pasttimeaddEventListener();\n}\n\n/**\n * Function to execute the filter\n * @param {int} starttime Start of time span for filtering of the current pressed button\n * @param {int} endtime End of time span for filtering of the current pressed\n * @param {int} addstarttime Start of time span for filtering of an additional radio button.\n * @param {int} addendtime End of time span for filtering of an additional radio button.\n * @param {bool} buttonstate State of the radio button (true of false)\n */\nfunction executefilter(starttime, endtime, addstarttime, addendtime, buttonstate) {\n // Get all the letters.\n const letters = document.querySelectorAll('.townsquare_letter');\n\n // Loop through each letter and hide/show based on radiobutton state.\n letters.forEach(function(letter) {\n // First hide all letters, as different time spans can overlap.\n letter.style.display = 'none';\n\n // Get the created time stamp of each letter.\n let lettertime = letter.querySelector('.townsquareletter_date').id;\n\n // If the radio button is checked and the letter is in the time span, show it.\n if ((buttonstate && (lettertime >= starttime && lettertime <= endtime)) ||\n (lettertime >= addstarttime && lettertime <= addendtime)) {\n letter.style.display = 'block';\n }\n });\n}\n\n/**\n * Function to add event listeners to the all_time button.\n */\nfunction alltimeaddEventListener() {\n alltimebutton.forEach(function(button) {\n button.addEventListener('change', function() {\n // Set the time span to show all letters.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime + convertidtotime(button.id);\n addstarttime = 0;\n addendtime = 0;\n\n // Disable all other radio buttons that filter more specific times.\n futureradiobuttons.forEach(function(futureradiobutton) {\n futureradiobutton.checked = false;\n futureradiobutton.parentNode.classList.remove(\"active\");\n });\n pastradiobuttons.forEach(function(pastradiobutton) {\n pastradiobutton.checked = false;\n pastradiobutton.parentNode.classList.remove(\"active\");\n\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime,addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the future time radio buttons.\n */\nfunction futuretimeaddEventListener() {\n futureradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime;\n timeend = currenttime + convertidtotime(button.id);\n\n // Check if one past time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n pastradiobuttons.forEach(function(pastradiobutton) {\n if (pastradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime - convertidtotime(pastradiobutton.id);\n addendtime = currenttime;\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the past time radio buttons.\n */\nfunction pasttimeaddEventListener() {\n pastradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime;\n\n // Check if one future time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n futureradiobuttons.forEach(function(futureradiobutton) {\n if (futureradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime;\n addendtime = currenttime + convertidtotime(futureradiobutton.id);\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n"],"names":["currenttime","Date","getTime","alltimebutton","forEach","button","addEventListener","timestart","convertidtotime","id","timeend","addstarttime","addendtime","futureradiobuttons","futureradiobutton","checked","parentNode","classList","remove","pastradiobuttons","pastradiobutton","executefilter","contains","document","querySelectorAll","starttime","endtime","buttonstate","letter","style","display","lettertime","querySelector"],"mappings":"sJA2CIA,aAAc,IAAIC,MAAOC,UAAY,IAwCrCC,cAAcC,SAAQ,SAASC,QAC3BA,OAAOC,iBAAiB,UAAU,WAE9BC,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAC/CE,aAAe,EACfC,WAAa,EAGbC,mBAAmBT,SAAQ,SAASU,mBAChCA,kBAAkBC,SAAU,EAC5BD,kBAAkBE,WAAWC,UAAUC,OAAO,aAElDC,iBAAiBf,SAAQ,SAASgB,iBAC9BA,gBAAgBL,SAAU,EAC1BK,gBAAgBJ,WAAWC,UAAUC,OAAO,aAKhDG,cAAcd,UAAWG,QAASC,aAAaC,WAAYP,OAAOU,eAS1EF,mBAAmBT,SAAQ,SAASC,QAChCA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YACZU,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAG/CE,aAAe,EACfC,WAAa,EACbO,iBAAiBf,SAAQ,SAASgB,iBAC1BA,gBAAgBJ,WAAWC,UAAUK,SAAS,YAC9CX,aAAeX,YAAcQ,gBAAgBY,gBAAgBX,IAC7DG,WAAaZ,gBAKrBqB,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU,eAS3EI,iBAAiBf,SAAQ,SAASC,QAC9BA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAGVW,aAAe,EACfC,WAAa,EACbC,mBAAmBT,SAAQ,SAASU,mBAC5BA,kBAAkBE,WAAWC,UAAUK,SAAS,YAChDX,aAAeX,YACfY,WAAaZ,YAAcQ,gBAAgBM,kBAAkBL,QAKrEY,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU;;;;;;;;;;;MA5IzEZ,cAAgBoB,SAASC,iBAAiB,uBAC1CX,mBAAqBU,SAASC,iBAAiB,0BAC/CL,iBAAmBI,SAASC,iBAAiB,4BAG/CxB,YACAO,UACAG,QACAC,aACAC,oBAuBKS,cAAcI,UAAWC,QAASf,aAAcC,WAAYe,aAEjDJ,SAASC,iBAAiB,sBAGlCpB,SAAQ,SAASwB,QAErBA,OAAOC,MAAMC,QAAU,WAGnBC,WAAaH,OAAOI,cAAc,0BAA0BvB,IAG3DkB,aAAgBI,YAAcN,WAAaM,YAAcL,SACzDK,YAAcpB,cAAgBoB,YAAcnB,cAC7CgB,OAAOC,MAAMC,QAAU,qBAuG1BtB,gBAAgBC,WACdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM"} \ No newline at end of file diff --git a/amd/build/usersettings_save.min.js b/amd/build/usersettings_save.min.js index 317a021..d34e195 100644 --- a/amd/build/usersettings_save.min.js +++ b/amd/build/usersettings_save.min.js @@ -1,12 +1,13 @@ +define("block_townsquare/usersettings_save",["exports","core/ajax"],(function(_exports,_ajax){var obj; /** - * Javascript to save the user settings in the database. - * - * This file implements 1 functionality: - * - If the "save settings" button is pressed, store the settings in the database. - * - * @module block_townsquare/timefilter - * @copyright 2024 Tamaro Walter - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ + * Javascript to save the user settings in the database. + * + * This file implements 1 functionality: + * - If the "save settings" button is pressed, store the settings in the database. + * + * @module block_townsquare/timefilter + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,settingsfromdb){settingsfromdb&&function(settingsfromdb){let timefilterfuture=settingsfromdb.timefilterfuture,timefilterpast=settingsfromdb.timefilterpast,letterfilter=settingsfromdb.letterfilter,futurebuttonid=converttimetoid(timefilterfuture,!0),pastbuttonid=converttimetoid(timefilterpast,!1);"ts_time_all"!==futurebuttonid?(futureradiobuttons.forEach((function(button){button.id===futurebuttonid&&button.click()})),pastradiobuttons.forEach((function(button){button.id===pastbuttonid&&button.click()}))):alltimebutton.forEach((function(button){button.id===futurebuttonid&&button.click()}));let letterfilters=function(settingnumber){let settings={basicletter:0,completionletter:0,postletter:0};settingnumber>=4&&(settings.basicletter=1);2!==settingnumber&&3!==settingnumber&&6!==settingnumber&&7!==settingnumber||(settings.completionletter=1);settingnumber%2==1&&(settings.postletter=1);return settings}(letterfilter);checkboxes.forEach((function(checkbox){("basicletter"===checkbox.id&&1===letterfilters.basicletter||"completionletter"===checkbox.id&&1===letterfilters.completionletter||"postletter"===checkbox.id&&1===letterfilters.postletter)&&(checkbox.click(),checkbox.checked=!0)}))}(settingsfromdb);savebutton.addEventListener("click",(async function(){let timespans=function(){let settings={timepast:0,timefuture:0},settingsset=!1;if(alltimebutton.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id),settings.timefuture=convertidtotime(button.id),settingsset=!0)})),settingsset)return settings;return futureradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timefuture=convertidtotime(button.id))})),pastradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id))})),settings}(),letterfilter=function(){let settings={basicletter:0,completionletter:0,postletter:0};return checkboxes.forEach((function(checkbox){if(checkbox.checked)switch(checkbox.id){case"basicletter":settings.basicletter=1;break;case"completionletter":settings.completionletter=1;break;case"postletter":settings.postletter=1}})),4*settings.basicletter+2*settings.completionletter+1*settings.postletter}();await async function(userid,timefilterpast,timefilterfuture,letterfilter){window.alert("Settings here."),window.alert(userid),window.alert(timefilterpast),window.alert(timefilterfuture),window.alert(letterfilter);let result=await _ajax.default.call([{methodname:"block_townsquare_record_usersettings",args:{userid:userid,timefilterpast:timefilterpast,timefilterfuture:timefilterfuture,letterfilter:letterfilter}}]);return window.alert("im done"),result}(userid,timespans.timepast,timespans.timefuture,letterfilter)}))},_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};const savebutton=document.getElementById("ts_usersettings_savebutton"),alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button"),checkboxes=document.querySelectorAll(".ts_letter_checkbox");function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}function converttimetoid(time,future){switch(time){case 15778463:return"ts_time_all";case 172800:return future?"ts_time_next_twodays":"ts_time_past_twodays";case 432e3:return future?"ts_time_next_fivedays":"ts_time_last_fivedays";case 604800:return future?"ts_time_next_week":"ts_time_last_week";case 2592e3:return future?"ts_time_next_month":"ts_time_last_month"}}})); //# sourceMappingURL=usersettings_save.min.js.map \ No newline at end of file diff --git a/amd/build/usersettings_save.min.js.map b/amd/build/usersettings_save.min.js.map index 3732e99..e26f33d 100644 --- a/amd/build/usersettings_save.min.js.map +++ b/amd/build/usersettings_save.min.js.map @@ -1 +1 @@ -{"version":3,"file":"usersettings_save.min.js","sources":[],"sourcesContent":[],"names":[],"mappings":""} \ No newline at end of file +{"version":3,"file":"usersettings_save.min.js","sources":["../src/usersettings_save.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 * Javascript to save the user settings in the database.\n *\n * This file implements 1 functionality:\n * - If the \"save settings\" button is pressed, store the settings in the database.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n// Get the save button for the user settings.\nconst savebutton = document.getElementById('ts_usersettings_savebutton');\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n *\n * @param {number} userid The id of the current user.\n * @param {object} settingsfromdb The settings from the database, if there are any.\n */\nexport function init(userid, settingsfromdb) {\n // When the page is loaded, set the settings from the database.\n if (settingsfromdb) {\n executeusersettings(settingsfromdb);\n }\n\n // Add event listener to the save button.\n savebutton.addEventListener('click', async function() {\n\n // First step: collect the current settings.\n // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes..\n let timespans = collecttimefiltersettings();\n let letterfilter = collectletterfiltersettings();\n\n // Second step: store the usersettings in the database.\n await saveusersettings(userid, timespans['timepast'], timespans['timefuture'], letterfilter);\n });\n}\n\n/**\n * Function to save the user settings in the database.\n * @param {number} userid\n * @param {number} timefilterpast\n * @param {number} timefilterfuture\n * @param {number} letterfilter\n * @returns {Promise<*>}\n */\nasync function saveusersettings(userid, timefilterpast, timefilterfuture, letterfilter) {\n window.alert('Settings here.');\n window.alert(userid);\n window.alert(timefilterpast);\n window.alert(timefilterfuture);\n window.alert(letterfilter);\n let result = await Ajax.call([{\n methodname: 'block_townsquare_record_usersettings',\n args: {\n userid: userid,\n timefilterpast: timefilterpast,\n timefilterfuture: timefilterfuture,\n letterfilter: letterfilter\n }\n }]);\n window.alert('im done');\n return result;\n}\n\n/**\n * Function to execute existing user settings when loading the townsquare.\n * @param {number} settingsfromdb\n */\nfunction executeusersettings(settingsfromdb) {\n // Load the settings.\n let timefilterfuture = settingsfromdb['timefilterfuture'];\n let timefilterpast = settingsfromdb['timefilterpast'];\n let letterfilter = settingsfromdb['letterfilter'];\n\n // First step: set the time filter settings.\n // Change the time into the correct radio button id.\n let futurebuttonid = converttimetoid(timefilterfuture, true);\n let pastbuttonid = converttimetoid(timefilterpast, false);\n // If the time span is a combination of past and future, go through the two radio buttons and click them to activate the filter.\n if (futurebuttonid !== \"ts_time_all\") {\n futureradiobuttons.forEach(function(button) {\n if (button.id === futurebuttonid) {\n button.click();\n }\n });\n pastradiobuttons.forEach(function(button) {\n if (button.id === pastbuttonid) {\n button.click();\n }\n });\n } else {\n // If the time span is the all time filter, click the all time button.\n alltimebutton.forEach(function(button) {\n if (button.id === futurebuttonid) {\n button.click();\n }\n });\n }\n\n // Second step: set the letter filter settings.\n let letterfilters = convertletterfiltersetting(letterfilter);\n checkboxes.forEach(function(checkbox) {\n if (checkbox.id === \"basicletter\" && letterfilters['basicletter'] === 1) {\n checkbox.click();\n checkbox.checked = true;\n } else if (checkbox.id === \"completionletter\" && letterfilters['completionletter'] === 1) {\n checkbox.click();\n checkbox.checked = true;\n } else if (checkbox.id === \"postletter\" && letterfilters['postletter'] === 1) {\n checkbox.click();\n checkbox.checked = true;\n }\n });\n}\n\n/**\n * Function to collect the letter filter settings.\n * @returns {number} The setting number.\n */\nfunction collectletterfiltersettings() {\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\n\n checkboxes.forEach(function(checkbox) {\n if (checkbox.checked) {\n switch(checkbox.id) {\n case \"basicletter\":\n settings['basicletter'] = 1;\n break;\n case \"completionletter\":\n settings['completionletter'] = 1;\n break;\n case \"postletter\":\n settings['postletter'] = 1;\n break;\n\n }\n }\n });\n // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit.\n return 4 * settings['basicletter'] + 2 * settings['completionletter'] + 1 * settings['postletter'];\n}\n\n/**\n * Function to collect the time filter settings.\n * @returns {{timepast: number, timefuture: number}}\n */\nfunction collecttimefiltersettings() {\n let settings = { timepast: 0, timefuture: 0};\n let settingsset = false;\n\n // Get the relevant time spans of the time filter.\n // Check if the alltimebutton is set.\n alltimebutton.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n settings['timefuture'] = convertidtotime(button.id);\n settingsset = true;\n }\n });\n\n if (settingsset) {\n return settings;\n }\n\n // If the alltimebutton is not set, check which of the future/past buttons is set.\n futureradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timefuture'] = convertidtotime(button.id);\n }\n });\n\n pastradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n }\n });\n return settings;\n}\n\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n // TODO: Please use global functions if possible.\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n\n/**\n * Function to convert the time span to a radio button id.\n * @param {number} time\n * @param {bool} future\n * @returns {string}\n */\nfunction converttimetoid(time, future) {\n switch (time) {\n case 15778463:\n return \"ts_time_all\";\n case 172800:\n if (future) {\n return \"ts_time_next_twodays\";\n }\n return \"ts_time_past_twodays\";\n case 432000:\n if (future) {\n return \"ts_time_next_fivedays\";\n }\n return \"ts_time_last_fivedays\";\n case 604800:\n if (future) {\n return \"ts_time_next_week\";\n }\n return \"ts_time_last_week\";\n case 2592000:\n if (future) {\n return \"ts_time_next_month\";\n\n }\n return \"ts_time_last_month\";\n }\n}\n\n/**\n * Converts the number of the letter filter to an object that has the activated letter filters.\n * @param {number} settingnumber\n */\nfunction convertletterfiltersetting(settingnumber) {\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\n\n // Check if the basicletter is active.\n if (settingnumber >= 4) {\n settings['basicletter'] = 1;\n }\n\n // Check if the completionletter is active.\n if (settingnumber === 2 || settingnumber === 3 || settingnumber === 6 || settingnumber === 7) {\n settings['completionletter'] = 1;\n }\n\n // check if the postletter is active.\n if (settingnumber % 2 === 1) {\n settings['postletter'] = 1;\n }\n\n return settings;\n\n}\n"],"names":["userid","settingsfromdb","timefilterfuture","timefilterpast","letterfilter","futurebuttonid","converttimetoid","pastbuttonid","futureradiobuttons","forEach","button","id","click","pastradiobuttons","alltimebutton","letterfilters","settingnumber","settings","convertletterfiltersetting","checkboxes","checkbox","checked","executeusersettings","savebutton","addEventListener","async","timespans","timepast","timefuture","settingsset","parentNode","classList","contains","convertidtotime","collecttimefiltersettings","collectletterfiltersettings","window","alert","result","Ajax","call","methodname","args","saveusersettings","document","getElementById","querySelectorAll","time","future"],"mappings":";;;;;;;;;;oFAyCqBA,OAAQC,gBAErBA,yBAgDqBA,oBAErBC,iBAAmBD,eAAc,iBACjCE,eAAiBF,eAAc,eAC/BG,aAAeH,eAAc,aAI7BI,eAAiBC,gBAAgBJ,kBAAkB,GACnDK,aAAeD,gBAAgBH,gBAAgB,GAE5B,gBAAnBE,gBACAG,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOC,KAAON,gBACdK,OAAOE,WAGfC,iBAAiBJ,SAAQ,SAASC,QAC1BA,OAAOC,KAAOJ,cACdG,OAAOE,YAKfE,cAAcL,SAAQ,SAASC,QACvBA,OAAOC,KAAON,gBACdK,OAAOE,eAMfG,uBAkJ4BC,mBAC5BC,SAAW,aAAgB,mBAAuB,aAAiB,GAGnED,eAAiB,IACjBC,SAAQ,YAAkB,GAIR,IAAlBD,eAAyC,IAAlBA,eAAyC,IAAlBA,eAAyC,IAAlBA,gBACrEC,SAAQ,iBAAuB,GAI/BD,cAAgB,GAAM,IACtBC,SAAQ,WAAiB,UAGtBA,SApKaC,CAA2Bd,cAC/Ce,WAAWV,SAAQ,SAASW,WACJ,gBAAhBA,SAAST,IAAyD,IAAjCI,cAAa,aAGvB,qBAAhBK,SAAST,IAAmE,IAAtCI,cAAa,kBAGnC,eAAhBK,SAAST,IAAuD,IAAhCI,cAAa,cALpDK,SAASR,QACTQ,SAASC,SAAU,MAnFvBC,CAAoBrB,gBAIxBsB,WAAWC,iBAAiB,SAASC,qBAI7BC,yBAsHJT,SAAW,CAAEU,SAAU,EAAGC,WAAY,GACtCC,aAAc,KAIlBf,cAAcL,SAAQ,SAASC,QACxBA,OAAOoB,WAAWC,UAAUC,SAAS,YAErCf,SAAQ,SAAegB,gBAAgBvB,OAAOC,IAC9CM,SAAQ,WAAiBgB,gBAAgBvB,OAAOC,IAChDkB,aAAc,MAIjBA,mBACOZ,gBAIXT,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOoB,WAAWC,UAAUC,SAAS,YAErCf,SAAQ,WAAiBgB,gBAAgBvB,OAAOC,QAIxDE,iBAAiBJ,SAAQ,SAASC,QAC1BA,OAAOoB,WAAWC,UAAUC,SAAS,YAErCf,SAAQ,SAAegB,gBAAgBvB,OAAOC,QAG/CM,SAtJaiB,GACZ9B,4BA0FJa,SAAW,aAAgB,mBAAuB,aAAiB,UAEvEE,WAAWV,SAAQ,SAASW,aACpBA,SAASC,eACFD,SAAST,QACP,cACDM,SAAQ,YAAkB,YAEzB,mBACDA,SAAQ,iBAAuB,YAE9B,aACDA,SAAQ,WAAiB,MAOlC,EAAIA,SAAQ,YAAkB,EAAIA,SAAQ,iBAAuB,EAAIA,SAAQ,WA7G7DkB,wBAeKnC,OAAQG,eAAgBD,iBAAkBE,cACtEgC,OAAOC,MAAM,kBACbD,OAAOC,MAAMrC,QACboC,OAAOC,MAAMlC,gBACbiC,OAAOC,MAAMnC,kBACbkC,OAAOC,MAAMjC,kBACTkC,aAAeC,cAAKC,KAAK,CAAC,CAC1BC,WAAY,uCACZC,KAAM,CACF1C,OAAQA,OACRG,eAAgBA,eAChBD,iBAAkBA,iBAClBE,aAAcA,wBAGtBgC,OAAOC,MAAM,WACNC,OA5BGK,CAAiB3C,OAAQ0B,UAAS,SAAcA,UAAS,WAAgBtB,4EA3BjFmB,WAAaqB,SAASC,eAAe,8BACrC/B,cAAgB8B,SAASE,iBAAiB,uBAC1CtC,mBAAqBoC,SAASE,iBAAiB,0BAC/CjC,iBAAmB+B,SAASE,iBAAiB,wBAC7C3B,WAAayB,SAASE,iBAAiB,gCAkLpCb,gBAAgBtB,WAEdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM,iBAUVL,gBAAgByC,KAAMC,eACnBD,WACC,eACM,mBACN,cACGC,OACO,uBAEJ,4BACN,aACGA,OACO,wBAEJ,6BACN,cACGA,OACO,oBAEJ,yBACN,cACGA,OACO,qBAGJ"} \ No newline at end of file diff --git a/amd/src/usersettings_save.js b/amd/src/usersettings_save.js index 1e2a6bf..75b3277 100644 --- a/amd/src/usersettings_save.js +++ b/amd/src/usersettings_save.js @@ -24,53 +24,143 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +import Ajax from 'core/ajax'; + // Get the save button for the user settings. const savebutton = document.getElementById('ts_usersettings_savebutton'); +const alltimebutton = document.querySelectorAll('.ts_all_time_button'); +const futureradiobuttons = document.querySelectorAll('.ts_future_time_button'); +const pastradiobuttons = document.querySelectorAll('.ts_past_time_button'); +const checkboxes = document.querySelectorAll('.ts_letter_checkbox'); /** * Init function + * + * @param {number} userid The id of the current user. + * @param {object} settingsfromdb The settings from the database, if there are any. */ -export function init() { +export function init(userid, settingsfromdb) { + // When the page is loaded, set the settings from the database. + if (settingsfromdb) { + executeusersettings(settingsfromdb); + } + // Add event listener to the save button. - savebutton.addEventListener('click', function(button) { - // First step: collect the current settings. + savebutton.addEventListener('click', async function() { - // Get the relevant time spans of the time filter. + // First step: collect the current settings. + // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes.. let timespans = collecttimefiltersettings(); + let letterfilter = collectletterfiltersettings(); + + // Second step: store the usersettings in the database. + await saveusersettings(userid, timespans['timepast'], timespans['timefuture'], letterfilter); + }); +} + +/** + * Function to save the user settings in the database. + * @param {number} userid + * @param {number} timefilterpast + * @param {number} timefilterfuture + * @param {number} letterfilter + * @returns {Promise<*>} + */ +async function saveusersettings(userid, timefilterpast, timefilterfuture, letterfilter) { + window.alert('Settings here.'); + window.alert(userid); + window.alert(timefilterpast); + window.alert(timefilterfuture); + window.alert(letterfilter); + let result = await Ajax.call([{ + methodname: 'block_townsquare_record_usersettings', + args: { + userid: userid, + timefilterpast: timefilterpast, + timefilterfuture: timefilterfuture, + letterfilter: letterfilter + } + }]); + window.alert('im done'); + return result; +} - // Get the setting of the letter filter checkboxes. - let letterfilters = collectletterfiltersettings(); +/** + * Function to execute existing user settings when loading the townsquare. + * @param {number} settingsfromdb + */ +function executeusersettings(settingsfromdb) { + // Load the settings. + let timefilterfuture = settingsfromdb['timefilterfuture']; + let timefilterpast = settingsfromdb['timefilterpast']; + let letterfilter = settingsfromdb['letterfilter']; - // Second step: store the usersettings in the database.atu + // First step: set the time filter settings. + // Change the time into the correct radio button id. + let futurebuttonid = converttimetoid(timefilterfuture, true); + let pastbuttonid = converttimetoid(timefilterpast, false); + // If the time span is a combination of past and future, go through the two radio buttons and click them to activate the filter. + if (futurebuttonid !== "ts_time_all") { + futureradiobuttons.forEach(function(button) { + if (button.id === futurebuttonid) { + button.click(); + } + }); + pastradiobuttons.forEach(function(button) { + if (button.id === pastbuttonid) { + button.click(); + } + }); + } else { + // If the time span is the all time filter, click the all time button. + alltimebutton.forEach(function(button) { + if (button.id === futurebuttonid) { + button.click(); + } + }); + } + + // Second step: set the letter filter settings. + let letterfilters = convertletterfiltersetting(letterfilter); + checkboxes.forEach(function(checkbox) { + if (checkbox.id === "basicletter" && letterfilters['basicletter'] === 1) { + checkbox.click(); + checkbox.checked = true; + } else if (checkbox.id === "completionletter" && letterfilters['completionletter'] === 1) { + checkbox.click(); + checkbox.checked = true; + } else if (checkbox.id === "postletter" && letterfilters['postletter'] === 1) { + checkbox.click(); + checkbox.checked = true; + } }); } /** * Function to collect the letter filter settings. - * @returns {{completionletter: boolean, basicletter: boolean, postletter: boolean}} + * @returns {number} The setting number. */ function collectletterfiltersettings() { - let settings = {'basicletter': false, 'completionletter': false, 'postletter':false }; - - const checkboxes = document.querySelectorAll('.ts_letter_checkbox'); + let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 }; checkboxes.forEach(function(checkbox) { if (checkbox.checked) { switch(checkbox.id) { case "basicletter": - settings['basicletter'] = true; + settings['basicletter'] = 1; break; case "completionletter": - settings['completionletter'] = true; + settings['completionletter'] = 1; break; case "postletter": - settings['postletter'] = true; + settings['postletter'] = 1; break; } } }); - return settings; + // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit. + return 4 * settings['basicletter'] + 2 * settings['completionletter'] + 1 * settings['postletter']; } /** @@ -79,31 +169,32 @@ function collectletterfiltersettings() { */ function collecttimefiltersettings() { let settings = { timepast: 0, timefuture: 0}; + let settingsset = false; // Get the relevant time spans of the time filter. - const alltimebutton = document.querySelectorAll('.ts_all_time_button'); - const futureradiobuttons = document.querySelectorAll('.ts_future_time_button'); - const pastradiobuttons = document.querySelectorAll('.ts_past_time_button'); - // Check if the alltimebutton is set. - alltimebutton.foreach(function(button) { + alltimebutton.forEach(function(button) { if (button.parentNode.classList.contains('active')) { // Get the timespan. settings['timepast'] = convertidtotime(button.id); settings['timefuture'] = convertidtotime(button.id); - return settings; + settingsset = true; } }); + if (settingsset) { + return settings; + } + // If the alltimebutton is not set, check which of the future/past buttons is set. - futureradiobuttons.foreach(function(button) { + futureradiobuttons.forEach(function(button) { if (button.parentNode.classList.contains('active')) { // Get the timespan. settings['timefuture'] = convertidtotime(button.id); } }); - pastradiobuttons.foreach(function(button) { + pastradiobuttons.forEach(function(button) { if (button.parentNode.classList.contains('active')) { // Get the timespan. settings['timepast'] = convertidtotime(button.id); @@ -136,4 +227,64 @@ function convertidtotime(id) { case "ts_time_last_month": return 2592000; } -} \ No newline at end of file +} + +/** + * Function to convert the time span to a radio button id. + * @param {number} time + * @param {bool} future + * @returns {string} + */ +function converttimetoid(time, future) { + switch (time) { + case 15778463: + return "ts_time_all"; + case 172800: + if (future) { + return "ts_time_next_twodays"; + } + return "ts_time_past_twodays"; + case 432000: + if (future) { + return "ts_time_next_fivedays"; + } + return "ts_time_last_fivedays"; + case 604800: + if (future) { + return "ts_time_next_week"; + } + return "ts_time_last_week"; + case 2592000: + if (future) { + return "ts_time_next_month"; + + } + return "ts_time_last_month"; + } +} + +/** + * Converts the number of the letter filter to an object that has the activated letter filters. + * @param {number} settingnumber + */ +function convertletterfiltersetting(settingnumber) { + let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 }; + + // Check if the basicletter is active. + if (settingnumber >= 4) { + settings['basicletter'] = 1; + } + + // Check if the completionletter is active. + if (settingnumber === 2 || settingnumber === 3 || settingnumber === 6 || settingnumber === 7) { + settings['completionletter'] = 1; + } + + // check if the postletter is active. + if (settingnumber % 2 === 1) { + settings['postletter'] = 1; + } + + return settings; + +} diff --git a/externallib.php b/externallib.php index e8b4ae5..5538791 100644 --- a/externallib.php +++ b/externallib.php @@ -71,7 +71,7 @@ public static function record_usersettings_returns() { */ public static function record_usersettings($userid, $timefilterpast, $timefilterfuture, $letterfilter) { global $DB; - + echo ''; $transaction = $DB->start_delegated_transaction(); // Check if the user already has a record in the database diff --git a/templates/sidepanel.mustache b/templates/sidepanel.mustache index 2535573..5134c90 100644 --- a/templates/sidepanel.mustache +++ b/templates/sidepanel.mustache @@ -104,19 +104,19 @@
- +
- +
- + From 94db6cb8e73b2c1c9a9476bc829d34447237d8a5 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 9 Feb 2024 17:32:15 +0100 Subject: [PATCH 028/123] WIP: load usersettingsfrom database into townsquare --- amd/build/usersettings_save.min.js | 2 +- amd/build/usersettings_save.min.js.map | 2 +- amd/src/usersettings_save.js | 100 ++++++++++--------------- db/install.xml | 4 +- db/upgrade.php | 4 +- externallib.php | 15 +++- 6 files changed, 59 insertions(+), 68 deletions(-) diff --git a/amd/build/usersettings_save.min.js b/amd/build/usersettings_save.min.js index d34e195..ab75713 100644 --- a/amd/build/usersettings_save.min.js +++ b/amd/build/usersettings_save.min.js @@ -8,6 +8,6 @@ define("block_townsquare/usersettings_save",["exports","core/ajax"],(function(_e * @module block_townsquare/timefilter * @copyright 2024 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,settingsfromdb){settingsfromdb&&function(settingsfromdb){let timefilterfuture=settingsfromdb.timefilterfuture,timefilterpast=settingsfromdb.timefilterpast,letterfilter=settingsfromdb.letterfilter,futurebuttonid=converttimetoid(timefilterfuture,!0),pastbuttonid=converttimetoid(timefilterpast,!1);"ts_time_all"!==futurebuttonid?(futureradiobuttons.forEach((function(button){button.id===futurebuttonid&&button.click()})),pastradiobuttons.forEach((function(button){button.id===pastbuttonid&&button.click()}))):alltimebutton.forEach((function(button){button.id===futurebuttonid&&button.click()}));let letterfilters=function(settingnumber){let settings={basicletter:0,completionletter:0,postletter:0};settingnumber>=4&&(settings.basicletter=1);2!==settingnumber&&3!==settingnumber&&6!==settingnumber&&7!==settingnumber||(settings.completionletter=1);settingnumber%2==1&&(settings.postletter=1);return settings}(letterfilter);checkboxes.forEach((function(checkbox){("basicletter"===checkbox.id&&1===letterfilters.basicletter||"completionletter"===checkbox.id&&1===letterfilters.completionletter||"postletter"===checkbox.id&&1===letterfilters.postletter)&&(checkbox.click(),checkbox.checked=!0)}))}(settingsfromdb);savebutton.addEventListener("click",(async function(){let timespans=function(){let settings={timepast:0,timefuture:0},settingsset=!1;if(alltimebutton.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id),settings.timefuture=convertidtotime(button.id),settingsset=!0)})),settingsset)return settings;return futureradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timefuture=convertidtotime(button.id))})),pastradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id))})),settings}(),letterfilter=function(){let settings={basicletter:0,completionletter:0,postletter:0};return checkboxes.forEach((function(checkbox){if(checkbox.checked)switch(checkbox.id){case"basicletter":settings.basicletter=1;break;case"completionletter":settings.completionletter=1;break;case"postletter":settings.postletter=1}})),4*settings.basicletter+2*settings.completionletter+1*settings.postletter}();await async function(userid,timefilterpast,timefilterfuture,letterfilter){window.alert("Settings here."),window.alert(userid),window.alert(timefilterpast),window.alert(timefilterfuture),window.alert(letterfilter);let result=await _ajax.default.call([{methodname:"block_townsquare_record_usersettings",args:{userid:userid,timefilterpast:timefilterpast,timefilterfuture:timefilterfuture,letterfilter:letterfilter}}]);return window.alert("im done"),result}(userid,timespans.timepast,timespans.timefuture,letterfilter)}))},_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};const savebutton=document.getElementById("ts_usersettings_savebutton"),alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button"),checkboxes=document.querySelectorAll(".ts_letter_checkbox");function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}function converttimetoid(time,future){switch(time){case 15778463:return"ts_time_all";case 172800:return future?"ts_time_next_twodays":"ts_time_past_twodays";case 432e3:return future?"ts_time_next_fivedays":"ts_time_last_fivedays";case 604800:return future?"ts_time_next_week":"ts_time_last_week";case 2592e3:return future?"ts_time_next_month":"ts_time_last_month"}}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,settingsfromdb){settingsfromdb&&function(settingsfromdb){let timefilterfuture=settingsfromdb.timefilterfuture,timefilterpast=settingsfromdb.timefilterpast,basicletter=settingsfromdb.basicletter,completionletter=settingsfromdb.completionletter,postletter=settingsfromdb.postletter,futurebuttonid=converttimetoid(timefilterfuture,!0),pastbuttonid=converttimetoid(timefilterpast,!1);"ts_time_all"!==futurebuttonid?(futureradiobuttons.forEach((function(button){button.id==futurebuttonid&&(button.checked=!0,button.parentNode.classList.add("active"))})),pastradiobuttons.forEach((function(button){button.id==pastbuttonid&&(button.checked=!0,button.parentNode.classList.add("active"))}))):alltimebutton.forEach((function(button){button.id==futurebuttonid&&(button.checked=!0,button.parentNode.classList.add("active"))}));checkboxes.forEach((function(checkbox){let basiclettercheck="basicletter"===checkbox.id&&"1"===basicletter,completionlettercheck="completionletter"===checkbox.id&&"1"===completionletter,postlettercheck="postletter"===checkbox.id&&"1"===postletter;(basiclettercheck||completionlettercheck||postlettercheck)&&checkbox.click()}))}(settingsfromdb);savebutton.addEventListener("click",(async function(){let timespans=function(){let settings={timepast:0,timefuture:0},settingsset=!1;if(alltimebutton.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id),settings.timefuture=convertidtotime(button.id),settingsset=!0)})),settingsset)return settings;return futureradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timefuture=convertidtotime(button.id))})),pastradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id))})),settings}(),letterfilter=function(){let settings={basicletter:0,completionletter:0,postletter:0};return checkboxes.forEach((function(checkbox){if(checkbox.checked)switch(checkbox.id){case"basicletter":settings.basicletter=1;break;case"completionletter":settings.completionletter=1;break;case"postletter":settings.postletter=1}})),settings}();await async function(userid,timefilterpast,timefilterfuture,basicletter,completionletter,postletter){window.alert("Settings here.");let result=await _ajax.default.call([{methodname:"block_townsquare_record_usersettings",args:{userid:userid,timefilterpast:timefilterpast,timefilterfuture:timefilterfuture,basicletter:basicletter,completionletter:completionletter,postletter:postletter}}]);return window.alert("im done"),result}(userid,timespans.timepast,timespans.timefuture,letterfilter.basicletter,letterfilter.completionletter,letterfilter.postletter)}))},_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};const savebutton=document.getElementById("ts_usersettings_savebutton"),alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button"),checkboxes=document.querySelectorAll(".ts_letter_checkbox");function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}function converttimetoid(time,future){switch(time){case"15778463":return"ts_time_all";case"172800":return future?"ts_time_next_twodays":"ts_time_past_twodays";case"432000":return future?"ts_time_next_fivedays":"ts_time_last_fivedays";case"604800":return future?"ts_time_next_week":"ts_time_last_week";case"2592000":return future?"ts_time_next_month":"ts_time_last_month"}}})); //# sourceMappingURL=usersettings_save.min.js.map \ No newline at end of file diff --git a/amd/build/usersettings_save.min.js.map b/amd/build/usersettings_save.min.js.map index e26f33d..d35f275 100644 --- a/amd/build/usersettings_save.min.js.map +++ b/amd/build/usersettings_save.min.js.map @@ -1 +1 @@ -{"version":3,"file":"usersettings_save.min.js","sources":["../src/usersettings_save.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 * Javascript to save the user settings in the database.\n *\n * This file implements 1 functionality:\n * - If the \"save settings\" button is pressed, store the settings in the database.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n// Get the save button for the user settings.\nconst savebutton = document.getElementById('ts_usersettings_savebutton');\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n *\n * @param {number} userid The id of the current user.\n * @param {object} settingsfromdb The settings from the database, if there are any.\n */\nexport function init(userid, settingsfromdb) {\n // When the page is loaded, set the settings from the database.\n if (settingsfromdb) {\n executeusersettings(settingsfromdb);\n }\n\n // Add event listener to the save button.\n savebutton.addEventListener('click', async function() {\n\n // First step: collect the current settings.\n // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes..\n let timespans = collecttimefiltersettings();\n let letterfilter = collectletterfiltersettings();\n\n // Second step: store the usersettings in the database.\n await saveusersettings(userid, timespans['timepast'], timespans['timefuture'], letterfilter);\n });\n}\n\n/**\n * Function to save the user settings in the database.\n * @param {number} userid\n * @param {number} timefilterpast\n * @param {number} timefilterfuture\n * @param {number} letterfilter\n * @returns {Promise<*>}\n */\nasync function saveusersettings(userid, timefilterpast, timefilterfuture, letterfilter) {\n window.alert('Settings here.');\n window.alert(userid);\n window.alert(timefilterpast);\n window.alert(timefilterfuture);\n window.alert(letterfilter);\n let result = await Ajax.call([{\n methodname: 'block_townsquare_record_usersettings',\n args: {\n userid: userid,\n timefilterpast: timefilterpast,\n timefilterfuture: timefilterfuture,\n letterfilter: letterfilter\n }\n }]);\n window.alert('im done');\n return result;\n}\n\n/**\n * Function to execute existing user settings when loading the townsquare.\n * @param {number} settingsfromdb\n */\nfunction executeusersettings(settingsfromdb) {\n // Load the settings.\n let timefilterfuture = settingsfromdb['timefilterfuture'];\n let timefilterpast = settingsfromdb['timefilterpast'];\n let letterfilter = settingsfromdb['letterfilter'];\n\n // First step: set the time filter settings.\n // Change the time into the correct radio button id.\n let futurebuttonid = converttimetoid(timefilterfuture, true);\n let pastbuttonid = converttimetoid(timefilterpast, false);\n // If the time span is a combination of past and future, go through the two radio buttons and click them to activate the filter.\n if (futurebuttonid !== \"ts_time_all\") {\n futureradiobuttons.forEach(function(button) {\n if (button.id === futurebuttonid) {\n button.click();\n }\n });\n pastradiobuttons.forEach(function(button) {\n if (button.id === pastbuttonid) {\n button.click();\n }\n });\n } else {\n // If the time span is the all time filter, click the all time button.\n alltimebutton.forEach(function(button) {\n if (button.id === futurebuttonid) {\n button.click();\n }\n });\n }\n\n // Second step: set the letter filter settings.\n let letterfilters = convertletterfiltersetting(letterfilter);\n checkboxes.forEach(function(checkbox) {\n if (checkbox.id === \"basicletter\" && letterfilters['basicletter'] === 1) {\n checkbox.click();\n checkbox.checked = true;\n } else if (checkbox.id === \"completionletter\" && letterfilters['completionletter'] === 1) {\n checkbox.click();\n checkbox.checked = true;\n } else if (checkbox.id === \"postletter\" && letterfilters['postletter'] === 1) {\n checkbox.click();\n checkbox.checked = true;\n }\n });\n}\n\n/**\n * Function to collect the letter filter settings.\n * @returns {number} The setting number.\n */\nfunction collectletterfiltersettings() {\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\n\n checkboxes.forEach(function(checkbox) {\n if (checkbox.checked) {\n switch(checkbox.id) {\n case \"basicletter\":\n settings['basicletter'] = 1;\n break;\n case \"completionletter\":\n settings['completionletter'] = 1;\n break;\n case \"postletter\":\n settings['postletter'] = 1;\n break;\n\n }\n }\n });\n // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit.\n return 4 * settings['basicletter'] + 2 * settings['completionletter'] + 1 * settings['postletter'];\n}\n\n/**\n * Function to collect the time filter settings.\n * @returns {{timepast: number, timefuture: number}}\n */\nfunction collecttimefiltersettings() {\n let settings = { timepast: 0, timefuture: 0};\n let settingsset = false;\n\n // Get the relevant time spans of the time filter.\n // Check if the alltimebutton is set.\n alltimebutton.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n settings['timefuture'] = convertidtotime(button.id);\n settingsset = true;\n }\n });\n\n if (settingsset) {\n return settings;\n }\n\n // If the alltimebutton is not set, check which of the future/past buttons is set.\n futureradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timefuture'] = convertidtotime(button.id);\n }\n });\n\n pastradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n }\n });\n return settings;\n}\n\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n // TODO: Please use global functions if possible.\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n\n/**\n * Function to convert the time span to a radio button id.\n * @param {number} time\n * @param {bool} future\n * @returns {string}\n */\nfunction converttimetoid(time, future) {\n switch (time) {\n case 15778463:\n return \"ts_time_all\";\n case 172800:\n if (future) {\n return \"ts_time_next_twodays\";\n }\n return \"ts_time_past_twodays\";\n case 432000:\n if (future) {\n return \"ts_time_next_fivedays\";\n }\n return \"ts_time_last_fivedays\";\n case 604800:\n if (future) {\n return \"ts_time_next_week\";\n }\n return \"ts_time_last_week\";\n case 2592000:\n if (future) {\n return \"ts_time_next_month\";\n\n }\n return \"ts_time_last_month\";\n }\n}\n\n/**\n * Converts the number of the letter filter to an object that has the activated letter filters.\n * @param {number} settingnumber\n */\nfunction convertletterfiltersetting(settingnumber) {\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\n\n // Check if the basicletter is active.\n if (settingnumber >= 4) {\n settings['basicletter'] = 1;\n }\n\n // Check if the completionletter is active.\n if (settingnumber === 2 || settingnumber === 3 || settingnumber === 6 || settingnumber === 7) {\n settings['completionletter'] = 1;\n }\n\n // check if the postletter is active.\n if (settingnumber % 2 === 1) {\n settings['postletter'] = 1;\n }\n\n return settings;\n\n}\n"],"names":["userid","settingsfromdb","timefilterfuture","timefilterpast","letterfilter","futurebuttonid","converttimetoid","pastbuttonid","futureradiobuttons","forEach","button","id","click","pastradiobuttons","alltimebutton","letterfilters","settingnumber","settings","convertletterfiltersetting","checkboxes","checkbox","checked","executeusersettings","savebutton","addEventListener","async","timespans","timepast","timefuture","settingsset","parentNode","classList","contains","convertidtotime","collecttimefiltersettings","collectletterfiltersettings","window","alert","result","Ajax","call","methodname","args","saveusersettings","document","getElementById","querySelectorAll","time","future"],"mappings":";;;;;;;;;;oFAyCqBA,OAAQC,gBAErBA,yBAgDqBA,oBAErBC,iBAAmBD,eAAc,iBACjCE,eAAiBF,eAAc,eAC/BG,aAAeH,eAAc,aAI7BI,eAAiBC,gBAAgBJ,kBAAkB,GACnDK,aAAeD,gBAAgBH,gBAAgB,GAE5B,gBAAnBE,gBACAG,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOC,KAAON,gBACdK,OAAOE,WAGfC,iBAAiBJ,SAAQ,SAASC,QAC1BA,OAAOC,KAAOJ,cACdG,OAAOE,YAKfE,cAAcL,SAAQ,SAASC,QACvBA,OAAOC,KAAON,gBACdK,OAAOE,eAMfG,uBAkJ4BC,mBAC5BC,SAAW,aAAgB,mBAAuB,aAAiB,GAGnED,eAAiB,IACjBC,SAAQ,YAAkB,GAIR,IAAlBD,eAAyC,IAAlBA,eAAyC,IAAlBA,eAAyC,IAAlBA,gBACrEC,SAAQ,iBAAuB,GAI/BD,cAAgB,GAAM,IACtBC,SAAQ,WAAiB,UAGtBA,SApKaC,CAA2Bd,cAC/Ce,WAAWV,SAAQ,SAASW,WACJ,gBAAhBA,SAAST,IAAyD,IAAjCI,cAAa,aAGvB,qBAAhBK,SAAST,IAAmE,IAAtCI,cAAa,kBAGnC,eAAhBK,SAAST,IAAuD,IAAhCI,cAAa,cALpDK,SAASR,QACTQ,SAASC,SAAU,MAnFvBC,CAAoBrB,gBAIxBsB,WAAWC,iBAAiB,SAASC,qBAI7BC,yBAsHJT,SAAW,CAAEU,SAAU,EAAGC,WAAY,GACtCC,aAAc,KAIlBf,cAAcL,SAAQ,SAASC,QACxBA,OAAOoB,WAAWC,UAAUC,SAAS,YAErCf,SAAQ,SAAegB,gBAAgBvB,OAAOC,IAC9CM,SAAQ,WAAiBgB,gBAAgBvB,OAAOC,IAChDkB,aAAc,MAIjBA,mBACOZ,gBAIXT,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOoB,WAAWC,UAAUC,SAAS,YAErCf,SAAQ,WAAiBgB,gBAAgBvB,OAAOC,QAIxDE,iBAAiBJ,SAAQ,SAASC,QAC1BA,OAAOoB,WAAWC,UAAUC,SAAS,YAErCf,SAAQ,SAAegB,gBAAgBvB,OAAOC,QAG/CM,SAtJaiB,GACZ9B,4BA0FJa,SAAW,aAAgB,mBAAuB,aAAiB,UAEvEE,WAAWV,SAAQ,SAASW,aACpBA,SAASC,eACFD,SAAST,QACP,cACDM,SAAQ,YAAkB,YAEzB,mBACDA,SAAQ,iBAAuB,YAE9B,aACDA,SAAQ,WAAiB,MAOlC,EAAIA,SAAQ,YAAkB,EAAIA,SAAQ,iBAAuB,EAAIA,SAAQ,WA7G7DkB,wBAeKnC,OAAQG,eAAgBD,iBAAkBE,cACtEgC,OAAOC,MAAM,kBACbD,OAAOC,MAAMrC,QACboC,OAAOC,MAAMlC,gBACbiC,OAAOC,MAAMnC,kBACbkC,OAAOC,MAAMjC,kBACTkC,aAAeC,cAAKC,KAAK,CAAC,CAC1BC,WAAY,uCACZC,KAAM,CACF1C,OAAQA,OACRG,eAAgBA,eAChBD,iBAAkBA,iBAClBE,aAAcA,wBAGtBgC,OAAOC,MAAM,WACNC,OA5BGK,CAAiB3C,OAAQ0B,UAAS,SAAcA,UAAS,WAAgBtB,4EA3BjFmB,WAAaqB,SAASC,eAAe,8BACrC/B,cAAgB8B,SAASE,iBAAiB,uBAC1CtC,mBAAqBoC,SAASE,iBAAiB,0BAC/CjC,iBAAmB+B,SAASE,iBAAiB,wBAC7C3B,WAAayB,SAASE,iBAAiB,gCAkLpCb,gBAAgBtB,WAEdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM,iBAUVL,gBAAgByC,KAAMC,eACnBD,WACC,eACM,mBACN,cACGC,OACO,uBAEJ,4BACN,aACGA,OACO,wBAEJ,6BACN,cACGA,OACO,oBAEJ,yBACN,cACGA,OACO,qBAGJ"} \ No newline at end of file +{"version":3,"file":"usersettings_save.min.js","sources":["../src/usersettings_save.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 * Javascript to save the user settings in the database.\n *\n * This file implements 1 functionality:\n * - If the \"save settings\" button is pressed, store the settings in the database.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n// Get the save button for the user settings.\nconst savebutton = document.getElementById('ts_usersettings_savebutton');\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n *\n * @param {number} userid The id of the current user.\n * @param {object} settingsfromdb The settings from the database, if there are any.\n */\nexport function init(userid, settingsfromdb) {\n // When the page is loaded, set the settings from the database.\n if (settingsfromdb) {\n executeusersettings(settingsfromdb);\n }\n\n // Add event listener to the save button.\n savebutton.addEventListener('click', async function() {\n\n // First step: collect the current settings.\n // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes..\n let timespans = collecttimefiltersettings();\n let letterfilter = collectletterfiltersettings();\n\n // Second step: store the usersettings in the database.\n await saveusersettings(userid, timespans['timepast'], timespans['timefuture'],\n letterfilter['basicletter'], letterfilter['completionletter'], letterfilter['postletter']);\n });\n}\n\n/**\n * Function to save the user settings in the database.\n * @param {number} userid\n * @param {number} timefilterpast\n * @param {number} timefilterfuture\n * @param {number} basicletter\n * @param {number} completionletter\n * @param {number} postletter\n * @returns {Promise<*>}\n */\nasync function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) {\n window.alert('Settings here.');\n let result = await Ajax.call([{\n methodname: 'block_townsquare_record_usersettings',\n args: {\n userid: userid,\n timefilterpast: timefilterpast,\n timefilterfuture: timefilterfuture,\n basicletter: basicletter,\n completionletter: completionletter,\n postletter: postletter\n }\n }]);\n window.alert('im done');\n return result;\n}\n\n/**\n * Function to execute existing user settings when loading the townsquare.\n * @param {Object} settingsfromdb\n */\nfunction executeusersettings(settingsfromdb) {\n // Load the settings.\n let timefilterfuture = settingsfromdb['timefilterfuture'];\n let timefilterpast = settingsfromdb['timefilterpast'];\n let basicletter = settingsfromdb['basicletter'];\n let completionletter = settingsfromdb['completionletter'];\n let postletter = settingsfromdb['postletter'];\n\n // First step: set the time filter settings.\n // Change the time into the correct radio button id.\n let futurebuttonid = converttimetoid(timefilterfuture, true);\n let pastbuttonid = converttimetoid(timefilterpast, false);\n\n // If the time span is a combination of past and future, go through the two radio buttons and click them to activate the filter.\n if (futurebuttonid !== \"ts_time_all\") {\n futureradiobuttons.forEach(function(button) {\n if (button.id == futurebuttonid) {\n button.checked = true;\n button.parentNode.classList.add('active');\n\n }\n });\n pastradiobuttons.forEach(function(button) {\n if (button.id == pastbuttonid) {\n button.checked = true;\n button.parentNode.classList.add('active');\n //button.parentNode.click();\n }\n });\n } else {\n // If the time span is the all time filter, click the all time button.\n alltimebutton.forEach(function(button) {\n if (button.id == futurebuttonid) {\n button.checked = true;\n button.parentNode.classList.add('active');\n // button.parentNode.click();\n }\n });\n }\n\n // Second step: set the letter filter settings.\n checkboxes.forEach(function(checkbox) {\n let basiclettercheck = checkbox.id === 'basicletter' && basicletter === \"1\";\n let completionlettercheck = checkbox.id === 'completionletter' && completionletter === \"1\";\n let postlettercheck = checkbox.id === 'postletter' && postletter === \"1\";\n\n if (basiclettercheck || completionlettercheck || postlettercheck) {\n checkbox.click();\n }\n });\n}\n\n/**\n * Function to collect the letter filter settings.\n * @returns {{basicletter: number, completionletter: number, postletter: number}}\n */\nfunction collectletterfiltersettings() {\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\n\n checkboxes.forEach(function(checkbox) {\n if (checkbox.checked) {\n switch(checkbox.id) {\n case \"basicletter\":\n settings['basicletter'] = 1;\n break;\n case \"completionletter\":\n settings['completionletter'] = 1;\n break;\n case \"postletter\":\n settings['postletter'] = 1;\n break;\n\n }\n }\n });\n // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit.\n return settings;\n}\n\n/**\n * Function to collect the time filter settings.\n * @returns {{timepast: number, timefuture: number}}\n */\nfunction collecttimefiltersettings() {\n let settings = { timepast: 0, timefuture: 0};\n let settingsset = false;\n\n // Get the relevant time spans of the time filter.\n // Check if the alltimebutton is set.\n alltimebutton.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n settings['timefuture'] = convertidtotime(button.id);\n settingsset = true;\n }\n });\n\n if (settingsset) {\n return settings;\n }\n\n // If the alltimebutton is not set, check which of the future/past buttons is set.\n futureradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timefuture'] = convertidtotime(button.id);\n }\n });\n\n pastradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n }\n });\n return settings;\n}\n\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n // TODO: Please use global functions if possible.\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n\n/**\n * Function to convert the time span to a radio button id.\n * @param {string} time\n * @param {boolean} future\n * @returns {string}\n */\nfunction converttimetoid(time, future) {\n switch (time) {\n case \"15778463\":\n return \"ts_time_all\";\n case \"172800\":\n if (future) {\n return \"ts_time_next_twodays\";\n }\n return \"ts_time_past_twodays\";\n case \"432000\":\n if (future) {\n return \"ts_time_next_fivedays\";\n }\n return \"ts_time_last_fivedays\";\n case \"604800\":\n if (future) {\n return \"ts_time_next_week\";\n }\n return \"ts_time_last_week\";\n case \"2592000\":\n if (future) {\n return \"ts_time_next_month\";\n\n }\n return \"ts_time_last_month\";\n }\n}\n"],"names":["userid","settingsfromdb","timefilterfuture","timefilterpast","basicletter","completionletter","postletter","futurebuttonid","converttimetoid","pastbuttonid","futureradiobuttons","forEach","button","id","checked","parentNode","classList","add","pastradiobuttons","alltimebutton","checkboxes","checkbox","basiclettercheck","completionlettercheck","postlettercheck","click","executeusersettings","savebutton","addEventListener","async","timespans","settings","timepast","timefuture","settingsset","contains","convertidtotime","collecttimefiltersettings","letterfilter","collectletterfiltersettings","window","alert","result","Ajax","call","methodname","args","saveusersettings","document","getElementById","querySelectorAll","time","future"],"mappings":";;;;;;;;;;oFAyCqBA,OAAQC,gBAErBA,yBAiDqBA,oBAErBC,iBAAmBD,eAAc,iBACjCE,eAAiBF,eAAc,eAC/BG,YAAcH,eAAc,YAC5BI,iBAAmBJ,eAAc,iBACjCK,WAAaL,eAAc,WAI3BM,eAAiBC,gBAAgBN,kBAAkB,GACnDO,aAAeD,gBAAgBL,gBAAgB,GAG5B,gBAAnBI,gBACAG,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOC,IAAMN,iBACbK,OAAOE,SAAU,EACjBF,OAAOG,WAAWC,UAAUC,IAAI,cAIxCC,iBAAiBP,SAAQ,SAASC,QAC1BA,OAAOC,IAAMJ,eACbG,OAAOE,SAAU,EACjBF,OAAOG,WAAWC,UAAUC,IAAI,eAMxCE,cAAcR,SAAQ,SAASC,QACvBA,OAAOC,IAAMN,iBACbK,OAAOE,SAAU,EACjBF,OAAOG,WAAWC,UAAUC,IAAI,cAO5CG,WAAWT,SAAQ,SAASU,cACpBC,iBAAmC,gBAAhBD,SAASR,IAAwC,MAAhBT,YACpDmB,sBAAwC,qBAAhBF,SAASR,IAAkD,MAArBR,iBAC9DmB,gBAAkC,eAAhBH,SAASR,IAAsC,MAAfP,YAElDgB,kBAAoBC,uBAAyBC,kBAC7CH,SAASI,WA/FbC,CAAoBzB,gBAIxB0B,WAAWC,iBAAiB,SAASC,qBAI7BC,yBA4HJC,SAAW,CAAEC,SAAU,EAAGC,WAAY,GACtCC,aAAc,KAIlBf,cAAcR,SAAQ,SAASC,QACxBA,OAAOG,WAAWC,UAAUmB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgBxB,OAAOC,IAC9CkB,SAAQ,WAAiBK,gBAAgBxB,OAAOC,IAChDqB,aAAc,MAIjBA,mBACOH,gBAIXrB,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOG,WAAWC,UAAUmB,SAAS,YAErCJ,SAAQ,WAAiBK,gBAAgBxB,OAAOC,QAIxDK,iBAAiBP,SAAQ,SAASC,QAC1BA,OAAOG,WAAWC,UAAUmB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgBxB,OAAOC,QAG/CkB,SA5JaM,GACZC,4BAgGJP,SAAW,aAAgB,mBAAuB,aAAiB,UAEvEX,WAAWT,SAAQ,SAASU,aACpBA,SAASP,eACFO,SAASR,QACP,cACDkB,SAAQ,YAAkB,YAEzB,mBACDA,SAAQ,iBAAuB,YAE9B,aACDA,SAAQ,WAAiB,MAOlCA,SAnHgBQ,wBAkBKvC,OAAQG,eAAgBD,iBAAkBE,YAAaC,iBAAkBC,YACrGkC,OAAOC,MAAM,sBACTC,aAAeC,cAAKC,KAAK,CAAC,CAC1BC,WAAY,uCACZC,KAAM,CACF9C,OAAQA,OACRG,eAAgBA,eAChBD,iBAAkBA,iBAClBE,YAAaA,YACbC,iBAAkBA,iBAClBC,WAAYA,sBAGpBkC,OAAOC,MAAM,WACNC,OA7BGK,CAAiB/C,OAAQ8B,UAAS,SAAcA,UAAS,WACxCQ,aAAY,YAAiBA,aAAY,iBAAsBA,aAAY,0EA5BpGX,WAAaqB,SAASC,eAAe,8BACrC9B,cAAgB6B,SAASE,iBAAiB,uBAC1CxC,mBAAqBsC,SAASE,iBAAiB,0BAC/ChC,iBAAmB8B,SAASE,iBAAiB,wBAC7C9B,WAAa4B,SAASE,iBAAiB,gCAwLpCd,gBAAgBvB,WAEdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM,iBAUVL,gBAAgB2C,KAAMC,eACnBD,UACC,iBACM,kBACN,gBACGC,OACO,uBAEJ,2BACN,gBACGA,OACO,wBAEJ,4BACN,gBACGA,OACO,oBAEJ,wBACN,iBACGA,OACO,qBAGJ"} \ No newline at end of file diff --git a/amd/src/usersettings_save.js b/amd/src/usersettings_save.js index 75b3277..1dbfe2a 100644 --- a/amd/src/usersettings_save.js +++ b/amd/src/usersettings_save.js @@ -54,7 +54,8 @@ export function init(userid, settingsfromdb) { let letterfilter = collectletterfiltersettings(); // Second step: store the usersettings in the database. - await saveusersettings(userid, timespans['timepast'], timespans['timefuture'], letterfilter); + await saveusersettings(userid, timespans['timepast'], timespans['timefuture'], + letterfilter['basicletter'], letterfilter['completionletter'], letterfilter['postletter']); }); } @@ -63,22 +64,22 @@ export function init(userid, settingsfromdb) { * @param {number} userid * @param {number} timefilterpast * @param {number} timefilterfuture - * @param {number} letterfilter + * @param {number} basicletter + * @param {number} completionletter + * @param {number} postletter * @returns {Promise<*>} */ -async function saveusersettings(userid, timefilterpast, timefilterfuture, letterfilter) { +async function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) { window.alert('Settings here.'); - window.alert(userid); - window.alert(timefilterpast); - window.alert(timefilterfuture); - window.alert(letterfilter); let result = await Ajax.call([{ methodname: 'block_townsquare_record_usersettings', args: { userid: userid, timefilterpast: timefilterpast, timefilterfuture: timefilterfuture, - letterfilter: letterfilter + basicletter: basicletter, + completionletter: completionletter, + postletter: postletter } }]); window.alert('im done'); @@ -87,58 +88,63 @@ async function saveusersettings(userid, timefilterpast, timefilterfuture, letter /** * Function to execute existing user settings when loading the townsquare. - * @param {number} settingsfromdb + * @param {Object} settingsfromdb */ function executeusersettings(settingsfromdb) { // Load the settings. let timefilterfuture = settingsfromdb['timefilterfuture']; let timefilterpast = settingsfromdb['timefilterpast']; - let letterfilter = settingsfromdb['letterfilter']; + let basicletter = settingsfromdb['basicletter']; + let completionletter = settingsfromdb['completionletter']; + let postletter = settingsfromdb['postletter']; // First step: set the time filter settings. // Change the time into the correct radio button id. let futurebuttonid = converttimetoid(timefilterfuture, true); let pastbuttonid = converttimetoid(timefilterpast, false); + // If the time span is a combination of past and future, go through the two radio buttons and click them to activate the filter. if (futurebuttonid !== "ts_time_all") { futureradiobuttons.forEach(function(button) { - if (button.id === futurebuttonid) { - button.click(); + if (button.id == futurebuttonid) { + button.checked = true; + button.parentNode.classList.add('active'); + } }); pastradiobuttons.forEach(function(button) { - if (button.id === pastbuttonid) { - button.click(); + if (button.id == pastbuttonid) { + button.checked = true; + button.parentNode.classList.add('active'); + //button.parentNode.click(); } }); } else { // If the time span is the all time filter, click the all time button. alltimebutton.forEach(function(button) { - if (button.id === futurebuttonid) { - button.click(); + if (button.id == futurebuttonid) { + button.checked = true; + button.parentNode.classList.add('active'); + // button.parentNode.click(); } }); } // Second step: set the letter filter settings. - let letterfilters = convertletterfiltersetting(letterfilter); checkboxes.forEach(function(checkbox) { - if (checkbox.id === "basicletter" && letterfilters['basicletter'] === 1) { - checkbox.click(); - checkbox.checked = true; - } else if (checkbox.id === "completionletter" && letterfilters['completionletter'] === 1) { - checkbox.click(); - checkbox.checked = true; - } else if (checkbox.id === "postletter" && letterfilters['postletter'] === 1) { + let basiclettercheck = checkbox.id === 'basicletter' && basicletter === "1"; + let completionlettercheck = checkbox.id === 'completionletter' && completionletter === "1"; + let postlettercheck = checkbox.id === 'postletter' && postletter === "1"; + + if (basiclettercheck || completionlettercheck || postlettercheck) { checkbox.click(); - checkbox.checked = true; } }); } /** * Function to collect the letter filter settings. - * @returns {number} The setting number. + * @returns {{basicletter: number, completionletter: number, postletter: number}} */ function collectletterfiltersettings() { let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 }; @@ -160,7 +166,7 @@ function collectletterfiltersettings() { } }); // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit. - return 4 * settings['basicletter'] + 2 * settings['completionletter'] + 1 * settings['postletter']; + return settings; } /** @@ -231,30 +237,30 @@ function convertidtotime(id) { /** * Function to convert the time span to a radio button id. - * @param {number} time - * @param {bool} future + * @param {string} time + * @param {boolean} future * @returns {string} */ function converttimetoid(time, future) { switch (time) { - case 15778463: + case "15778463": return "ts_time_all"; - case 172800: + case "172800": if (future) { return "ts_time_next_twodays"; } return "ts_time_past_twodays"; - case 432000: + case "432000": if (future) { return "ts_time_next_fivedays"; } return "ts_time_last_fivedays"; - case 604800: + case "604800": if (future) { return "ts_time_next_week"; } return "ts_time_last_week"; - case 2592000: + case "2592000": if (future) { return "ts_time_next_month"; @@ -262,29 +268,3 @@ function converttimetoid(time, future) { return "ts_time_last_month"; } } - -/** - * Converts the number of the letter filter to an object that has the activated letter filters. - * @param {number} settingnumber - */ -function convertletterfiltersetting(settingnumber) { - let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 }; - - // Check if the basicletter is active. - if (settingnumber >= 4) { - settings['basicletter'] = 1; - } - - // Check if the completionletter is active. - if (settingnumber === 2 || settingnumber === 3 || settingnumber === 6 || settingnumber === 7) { - settings['completionletter'] = 1; - } - - // check if the postletter is active. - if (settingnumber % 2 === 1) { - settings['postletter'] = 1; - } - - return settings; - -} diff --git a/db/install.xml b/db/install.xml index 33e90b2..46b5367 100644 --- a/db/install.xml +++ b/db/install.xml @@ -10,7 +10,9 @@ - + + + diff --git a/db/upgrade.php b/db/upgrade.php index a5f9af0..6292709 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -48,7 +48,9 @@ function xmldb_block_townsquare_upgrade($oldversion) { $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); $table->add_field('timefilterpast', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); $table->add_field('timefilterfuture', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); - $table->add_field('letterfilter', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); + $table->add_field('basicletter', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); + $table->add_field('completionletter', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); + $table->add_field('postletter', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); // Adding keys to table townsquare_usersettings. $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); diff --git a/externallib.php b/externallib.php index 5538791..df6578a 100644 --- a/externallib.php +++ b/externallib.php @@ -47,7 +47,9 @@ public static function record_usersettings_parameters() { 'userid' => new external_value(PARAM_INT, 'the user id'), 'timefilterpast' => new external_value(PARAM_INT, 'time span for filtering the past'), 'timefilterfuture' => new external_value(PARAM_INT, 'time span for filtering the future'), - 'letterfilter' => new external_value(PARAM_INT, 'setting of the letter filter'), + 'basicletter' => new external_value(PARAM_INT, 'Setting of the letter filter for basic letters'), + 'completionletter' => new external_value(PARAM_INT, 'Setting of the letter filter for completion letters'), + 'postletter' => new external_value(PARAM_INT, 'Setting of the letter filter for post letters'), ] ); } @@ -69,7 +71,8 @@ public static function record_usersettings_returns() { * @param int $letterfilter Setting of the letter filter * @return bool */ - public static function record_usersettings($userid, $timefilterpast, $timefilterfuture, $letterfilter) { + public static function record_usersettings($userid, $timefilterpast, $timefilterfuture, + $basicletter, $completionletter, $postletter) { global $DB; echo ''; $transaction = $DB->start_delegated_transaction(); @@ -91,7 +94,9 @@ public static function record_usersettings($userid, $timefilterpast, $timefilter $record = reset($records); $record->timefilterpast = $timefilterpast; $record->timefilterfuture = $timefilterfuture; - $record->letterfilter = $letterfilter; + $record->basicletter = $basicletter; + $record->completionletter = $completionletter; + $record->postletter = $postletter; $DB->update_record('townsquare_usersettings', $record); return true; } @@ -100,7 +105,9 @@ public static function record_usersettings($userid, $timefilterpast, $timefilter $record->userid = $userid; $record->timefilterpast = $timefilterpast; $record->timefilterfuture = $timefilterfuture; - $record->letterfilter = $letterfilter; + $record->basicletter = $basicletter; + $record->completionletter = $completionletter; + $record->postletter = $postletter; $DB->insert_record('townsquare_usersettings', $record); return true; } From 40967f3732b90123ba55a7347ed47d10cab37e91 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Mon, 12 Feb 2024 15:21:23 +0100 Subject: [PATCH 029/123] filter controller to enable multiple filters at once --- amd/build/coursefilter.min.js | 2 +- amd/build/coursefilter.min.js.map | 2 +- amd/build/filtercontroller.min.js | 14 ++++++ amd/build/filtercontroller.min.js.map | 1 + amd/build/letterfilter.min.js | 2 +- amd/build/letterfilter.min.js.map | 2 +- amd/build/timefilter.min.js | 2 +- amd/build/timefilter.min.js.map | 2 +- amd/src/coursefilter.js | 15 ++++--- amd/src/filtercontroller.js | 63 +++++++++++++++++++++++++++ amd/src/letterfilter.js | 12 +++-- amd/src/timefilter.js | 15 ++++--- block_townsquare.php | 1 + styles.css | 4 +- templates/sidepanel.mustache | 6 +-- 15 files changed, 117 insertions(+), 26 deletions(-) create mode 100644 amd/build/filtercontroller.min.js create mode 100644 amd/build/filtercontroller.min.js.map create mode 100644 amd/src/filtercontroller.js diff --git a/amd/build/coursefilter.min.js b/amd/build/coursefilter.min.js index 6fabffd..9122415 100644 --- a/amd/build/coursefilter.min.js +++ b/amd/build/coursefilter.min.js @@ -1,4 +1,4 @@ -define("block_townsquare/coursefilter",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){checkboxes.forEach((function(checkbox){checkbox.addEventListener("change",(function(){const courseid=checkbox.id;document.querySelectorAll(".townsquare_letter").forEach((function(letter){let letterCourseId=letter.querySelector(".townsquareletter_course").id;courseid===letterCourseId&&(checkbox.checked?letter.style.display="block":letter.style.display="none")}))}))}))}; +define("block_townsquare/coursefilter",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){checkboxes.forEach((function(checkbox){checkbox.addEventListener("change",(function(){const courseid=checkbox.id;document.querySelectorAll(".townsquare_letter.ts_timefilter_active.ts_letterfilter_active").forEach((function(letter){let letterCourseId=letter.querySelector(".townsquareletter_course").id;courseid===letterCourseId&&(checkbox.checked?letter.classList.add("ts_coursefilter_active"):letter.classList.remove("ts_coursefilter_active"))}))}))}))}; /** * Javascript for the course filter * diff --git a/amd/build/coursefilter.min.js.map b/amd/build/coursefilter.min.js.map index cb4cc7a..1d371ed 100644 --- a/amd/build/coursefilter.min.js.map +++ b/amd/build/coursefilter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"coursefilter.min.js","sources":["../src/coursefilter.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 * Javascript for the course filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the course filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/coursefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant checkboxes.\nconst checkboxes = document.querySelectorAll('.ts_course_checkbox');\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n // Get the courseid associated with the checkbox\n const courseid = checkbox.id;\n\n // Get all letters.\n const letters = document.querySelectorAll('.townsquare_letter');\n\n // Loop through each letter and hide/show based on checkbox state and the letter id.\n letters.forEach(function(letter) {\n let letterCourseId = letter.querySelector('.townsquareletter_course').id;\n\n if (courseid === letterCourseId) {\n if (checkbox.checked) {\n letter.style.display = 'block'; // Show the letter\n } else {\n letter.style.display = 'none'; // Hide the letter\n }\n }\n });\n });\n });\n}\n"],"names":["checkboxes","forEach","checkbox","addEventListener","courseid","id","document","querySelectorAll","letter","letterCourseId","querySelector","checked","style","display"],"mappings":"wJAiCIA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,iBAE1BC,SAAWF,SAASG,GAGVC,SAASC,iBAAiB,sBAGlCN,SAAQ,SAASO,YACjBC,eAAiBD,OAAOE,cAAc,4BAA4BL,GAElED,WAAaK,iBACTP,SAASS,QACTH,OAAOI,MAAMC,QAAU,QAEvBL,OAAOI,MAAMC,QAAU;;;;;;;;;;;MAtBzCb,WAAaM,SAASC,iBAAiB"} \ No newline at end of file +{"version":3,"file":"coursefilter.min.js","sources":["../src/coursefilter.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 * Javascript for the course filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the course filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/coursefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant checkboxes.\nconst checkboxes = document.querySelectorAll('.ts_course_checkbox');\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n // Get the courseid associated with the checkbox\n const courseid = checkbox.id;\n\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.ts_timefilter_active.ts_letterfilter_active');\n\n // Loop through each letter mark it as \"active\" or not based on checkbox state and the letter id.\n letters.forEach(function(letter) {\n let letterCourseId = letter.querySelector('.townsquareletter_course').id;\n\n if (courseid === letterCourseId) {\n if (checkbox.checked) {\n //window.alert('activated');\n letter.classList.add('ts_coursefilter_active'); // Mark the letter as \"active\".\n //letter.style.display = 'block'; // Show the letter\n } else {\n //window.alert('not activated');\n letter.classList.remove('ts_coursefilter_active'); // Mark the letter as \"not active\".\n //letter.style.display = 'none'; // Hide the letter.\n }\n }\n });\n });\n });\n}\n"],"names":["checkboxes","forEach","checkbox","addEventListener","courseid","id","document","querySelectorAll","letter","letterCourseId","querySelector","checked","classList","add","remove"],"mappings":"wJAiCIA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,iBAE1BC,SAAWF,SAASG,GAIVC,SAASC,iBAAiB,kEAGlCN,SAAQ,SAASO,YACjBC,eAAiBD,OAAOE,cAAc,4BAA4BL,GAElED,WAAaK,iBACTP,SAASS,QAETH,OAAOI,UAAUC,IAAI,0BAIrBL,OAAOI,UAAUE,OAAO;;;;;;;;;;;MA1B1Cd,WAAaM,SAASC,iBAAiB"} \ No newline at end of file diff --git a/amd/build/filtercontroller.min.js b/amd/build/filtercontroller.min.js new file mode 100644 index 0000000..4a17ab0 --- /dev/null +++ b/amd/build/filtercontroller.min.js @@ -0,0 +1,14 @@ +define("block_townsquare/filtercontroller",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){letters.forEach((function(letter){letter.classList.add("ts_coursefilter_active"),letter.classList.add("ts_timefilter_active"),letter.classList.add("ts_letterfilter_active")})),letters.forEach((function(letter){new MutationObserver((function(mutations){mutations.forEach((function(mutation){if("class"===mutation.attributeName){let coursefilter=letter.classList.contains("ts_coursefilter_active"),timefilter=letter.classList.contains("ts_timefilter_active"),letterfilter=letter.classList.contains("ts_letterfilter_active");letter.style.display=coursefilter&&timefilter&&letterfilter?"block":"none"}}))})).observe(letter,{attributes:!0})}))}; +/** + * Javascript to show/hide letters based on all filters + * + * This file implements 1 functionality: + * - If the "save settings" button is pressed, store the settings in the database. + * + * @module block_townsquare/filtercontroller + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +const letters=document.querySelectorAll(".townsquare_letter")})); + +//# sourceMappingURL=filtercontroller.min.js.map \ No newline at end of file diff --git a/amd/build/filtercontroller.min.js.map b/amd/build/filtercontroller.min.js.map new file mode 100644 index 0000000..c6fdfb0 --- /dev/null +++ b/amd/build/filtercontroller.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"filtercontroller.min.js","sources":["../src/filtercontroller.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 * Javascript to show/hide letters based on all filters\n *\n * This file implements 1 functionality:\n * - If the \"save settings\" button is pressed, store the settings in the database.\n *\n * @module block_townsquare/filtercontroller\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get all letters from townsquare.\nconst letters = document.querySelectorAll('.townsquare_letter');\n\n/**\n * Init function\n */\nexport function init() {\n // First step: activate every letter by adding the filter classes.\n letters.forEach(function(letter) {\n letter.classList.add('ts_coursefilter_active');\n letter.classList.add('ts_timefilter_active');\n letter.classList.add('ts_letterfilter_active');\n });\n\n // Add a mutation listener to each letter.\n letters.forEach(function(letter) {\n const observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(mutation) {\n if (mutation.attributeName === 'class') {\n // If the class of the letter changes, check if the letter should be shown or hidden.\n let coursefilter = letter.classList.contains('ts_coursefilter_active');\n let timefilter = letter.classList.contains('ts_timefilter_active');\n let letterfilter = letter.classList.contains('ts_letterfilter_active');\n\n // If all filters are active, show the letter.\n if (coursefilter && timefilter && letterfilter) {\n letter.style.display = 'block';\n } else {\n letter.style.display = 'none';\n }\n }\n });\n });\n\n observer.observe(letter, {attributes: true});\n });\n}\n"],"names":["letters","forEach","letter","classList","add","MutationObserver","mutations","mutation","attributeName","coursefilter","contains","timefilter","letterfilter","style","display","observe","attributes","document","querySelectorAll"],"mappings":"4JAkCIA,QAAQC,SAAQ,SAASC,QACrBA,OAAOC,UAAUC,IAAI,0BACrBF,OAAOC,UAAUC,IAAI,wBACrBF,OAAOC,UAAUC,IAAI,6BAIzBJ,QAAQC,SAAQ,SAASC,QACJ,IAAIG,kBAAiB,SAASC,WAC3CA,UAAUL,SAAQ,SAASM,aACQ,UAA3BA,SAASC,cAA2B,KAEhCC,aAAeP,OAAOC,UAAUO,SAAS,0BACzCC,WAAaT,OAAOC,UAAUO,SAAS,wBACvCE,aAAeV,OAAOC,UAAUO,SAAS,0BAIzCR,OAAOW,MAAMC,QADbL,cAAgBE,YAAcC,aACP,QAEA,cAM9BG,QAAQb,OAAQ,CAACc,YAAY;;;;;;;;;;;MAjCxChB,QAAUiB,SAASC,iBAAiB"} \ No newline at end of file diff --git a/amd/build/letterfilter.min.js b/amd/build/letterfilter.min.js index e33134e..880a8cd 100644 --- a/amd/build/letterfilter.min.js +++ b/amd/build/letterfilter.min.js @@ -1,4 +1,4 @@ -define("block_townsquare/letterfilter",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){checkboxes.forEach((function(checkbox){checkbox.addEventListener("change",(function(){const lettername=checkbox.id;document.querySelectorAll(".townsquare_letter."+lettername).forEach((function(letter){checkbox.checked?letter.style.display="block":letter.style.display="none"}))}))}))}; +define("block_townsquare/letterfilter",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){checkboxes.forEach((function(checkbox){checkbox.addEventListener("change",(function(){const lettername=checkbox.id;document.querySelectorAll(".townsquare_letter."+lettername+".ts_timefilter_active.ts_coursefilter_active").forEach((function(letter){checkbox.checked?letter.classList.add("ts_letterfilter_active"):letter.classList.remove("ts_letterfilter_active")}))}))}))}; /** * Javascript for the letter filter * diff --git a/amd/build/letterfilter.min.js.map b/amd/build/letterfilter.min.js.map index a68866a..d0bce3e 100644 --- a/amd/build/letterfilter.min.js.map +++ b/amd/build/letterfilter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"letterfilter.min.js","sources":["../src/letterfilter.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 * Javascript for the letter filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the letter filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/letterfilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant checkboxes.\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n\n // Get the letter name associated with the checkbox.\n const lettername = checkbox.id;\n\n // Get all the right letters.\n const letters = document.querySelectorAll('.townsquare_letter.' + lettername);\n\n // Loop through each letter and hide/show based on checkbox state.\n letters.forEach(function(letter) {\n if (checkbox.checked) {\n letter.style.display = 'block'; // Show the letter.\n } else {\n letter.style.display = 'none'; // Hide the letter.\n }\n });\n });\n });\n}\n"],"names":["checkboxes","forEach","checkbox","addEventListener","lettername","id","document","querySelectorAll","letter","checked","style","display"],"mappings":"wJAiCIA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,iBAG1BC,WAAaF,SAASG,GAGZC,SAASC,iBAAiB,sBAAwBH,YAG1DH,SAAQ,SAASO,QACjBN,SAASO,QACTD,OAAOE,MAAMC,QAAU,QAEvBH,OAAOE,MAAMC,QAAU;;;;;;;;;;;MApBrCX,WAAaM,SAASC,iBAAiB"} \ No newline at end of file +{"version":3,"file":"letterfilter.min.js","sources":["../src/letterfilter.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 * Javascript for the letter filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the letter filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/letterfilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant checkboxes.\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n\n // Get the letter name associated with the checkbox.\n const lettername = checkbox.id;\n\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.' + lettername +\n '.ts_timefilter_active.ts_coursefilter_active');\n\n // Loop through each letter and hide/show based on checkbox state.\n letters.forEach(function(letter) {\n if (checkbox.checked) {\n letter.classList.add('ts_letterfilter_active'); // Mark the letter as \"active\".\n //letter.style.display = 'block'; // Show the letter.\n } else {\n letter.classList.remove('ts_letterfilter_active'); // Mark the letter as \"not active\".\n //letter.style.display = 'none'; // Hide the letter.\n }\n });\n });\n });\n}\n"],"names":["checkboxes","forEach","checkbox","addEventListener","lettername","id","document","querySelectorAll","letter","checked","classList","add","remove"],"mappings":"wJAiCIA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,iBAG1BC,WAAaF,SAASG,GAIZC,SAASC,iBAAiB,sBAAwBH,WACxB,gDAGlCH,SAAQ,SAASO,QACjBN,SAASO,QACTD,OAAOE,UAAUC,IAAI,0BAGrBH,OAAOE,UAAUE,OAAO;;;;;;;;;;;MAvBtCZ,WAAaM,SAASC,iBAAiB"} \ No newline at end of file diff --git a/amd/build/timefilter.min.js b/amd/build/timefilter.min.js index 0bab738..48b36ec 100644 --- a/amd/build/timefilter.min.js +++ b/amd/build/timefilter.min.js @@ -9,6 +9,6 @@ define("block_townsquare/timefilter",["exports"],(function(_exports){Object.defi * @copyright 2024 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -const alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button");let currenttime,timestart,timeend,addstarttime,addendtime;function executefilter(starttime,endtime,addstarttime,addendtime,buttonstate){document.querySelectorAll(".townsquare_letter").forEach((function(letter){letter.style.display="none";let lettertime=letter.querySelector(".townsquareletter_date").id;(buttonstate&&lettertime>=starttime&&lettertime<=endtime||lettertime>=addstarttime&&lettertime<=addendtime)&&(letter.style.display="block")}))}function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}})); +const alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button");let currenttime,timestart,timeend,addstarttime,addendtime;function executefilter(starttime,endtime,addstarttime,addendtime,buttonstate){document.querySelectorAll(".townsquare_letter.ts_coursefilter_active.ts_letterfilter_active").forEach((function(letter){letter.classList.remove("ts_timefilter_active");let lettertime=letter.querySelector(".townsquareletter_date").id;(buttonstate&&lettertime>=starttime&&lettertime<=endtime||lettertime>=addstarttime&&lettertime<=addendtime)&&letter.classList.add("ts_timefilter_active")}))}function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}})); //# sourceMappingURL=timefilter.min.js.map \ No newline at end of file diff --git a/amd/build/timefilter.min.js.map b/amd/build/timefilter.min.js.map index d15d352..4f353dc 100644 --- a/amd/build/timefilter.min.js.map +++ b/amd/build/timefilter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"timefilter.min.js","sources":["../src/timefilter.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 * Javascript for the time filter\n *\n * This file implements 1 functionality:\n * - Checks, which of the radio buttons is pressed and filters the content based on the time.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant radio buttons.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Define to change the time span, an additional time span and the current time.\nlet currenttime;\nlet timestart;\nlet timeend;\nlet addstarttime;\nlet addendtime;\n\n/**\n * Init function\n */\nexport function init() {\n // Set the current time.\n currenttime = new Date().getTime() / 1000;\n\n // Add event listeners to the all kind of buttons.\n alltimeaddEventListener();\n futuretimeaddEventListener();\n pasttimeaddEventListener();\n}\n\n/**\n * Function to execute the filter\n * @param {int} starttime Start of time span for filtering of the current pressed button\n * @param {int} endtime End of time span for filtering of the current pressed\n * @param {int} addstarttime Start of time span for filtering of an additional radio button.\n * @param {int} addendtime End of time span for filtering of an additional radio button.\n * @param {bool} buttonstate State of the radio button (true of false)\n */\nfunction executefilter(starttime, endtime, addstarttime, addendtime, buttonstate) {\n // Get all the letters.\n const letters = document.querySelectorAll('.townsquare_letter');\n\n // Loop through each letter and hide/show based on radiobutton state.\n letters.forEach(function(letter) {\n // First hide all letters, as different time spans can overlap.\n letter.style.display = 'none';\n\n // Get the created time stamp of each letter.\n let lettertime = letter.querySelector('.townsquareletter_date').id;\n\n // If the radio button is checked and the letter is in the time span, show it.\n if ((buttonstate && (lettertime >= starttime && lettertime <= endtime)) ||\n (lettertime >= addstarttime && lettertime <= addendtime)) {\n letter.style.display = 'block';\n }\n });\n}\n\n/**\n * Function to add event listeners to the all_time button.\n */\nfunction alltimeaddEventListener() {\n alltimebutton.forEach(function(button) {\n button.addEventListener('change', function() {\n // Set the time span to show all letters.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime + convertidtotime(button.id);\n addstarttime = 0;\n addendtime = 0;\n\n // Disable all other radio buttons that filter more specific times.\n futureradiobuttons.forEach(function(futureradiobutton) {\n futureradiobutton.checked = false;\n futureradiobutton.parentNode.classList.remove(\"active\");\n });\n pastradiobuttons.forEach(function(pastradiobutton) {\n pastradiobutton.checked = false;\n pastradiobutton.parentNode.classList.remove(\"active\");\n\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime,addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the future time radio buttons.\n */\nfunction futuretimeaddEventListener() {\n futureradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime;\n timeend = currenttime + convertidtotime(button.id);\n\n // Check if one past time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n pastradiobuttons.forEach(function(pastradiobutton) {\n if (pastradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime - convertidtotime(pastradiobutton.id);\n addendtime = currenttime;\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the past time radio buttons.\n */\nfunction pasttimeaddEventListener() {\n pastradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime;\n\n // Check if one future time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n futureradiobuttons.forEach(function(futureradiobutton) {\n if (futureradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime;\n addendtime = currenttime + convertidtotime(futureradiobutton.id);\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n"],"names":["currenttime","Date","getTime","alltimebutton","forEach","button","addEventListener","timestart","convertidtotime","id","timeend","addstarttime","addendtime","futureradiobuttons","futureradiobutton","checked","parentNode","classList","remove","pastradiobuttons","pastradiobutton","executefilter","contains","document","querySelectorAll","starttime","endtime","buttonstate","letter","style","display","lettertime","querySelector"],"mappings":"sJA2CIA,aAAc,IAAIC,MAAOC,UAAY,IAwCrCC,cAAcC,SAAQ,SAASC,QAC3BA,OAAOC,iBAAiB,UAAU,WAE9BC,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAC/CE,aAAe,EACfC,WAAa,EAGbC,mBAAmBT,SAAQ,SAASU,mBAChCA,kBAAkBC,SAAU,EAC5BD,kBAAkBE,WAAWC,UAAUC,OAAO,aAElDC,iBAAiBf,SAAQ,SAASgB,iBAC9BA,gBAAgBL,SAAU,EAC1BK,gBAAgBJ,WAAWC,UAAUC,OAAO,aAKhDG,cAAcd,UAAWG,QAASC,aAAaC,WAAYP,OAAOU,eAS1EF,mBAAmBT,SAAQ,SAASC,QAChCA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YACZU,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAG/CE,aAAe,EACfC,WAAa,EACbO,iBAAiBf,SAAQ,SAASgB,iBAC1BA,gBAAgBJ,WAAWC,UAAUK,SAAS,YAC9CX,aAAeX,YAAcQ,gBAAgBY,gBAAgBX,IAC7DG,WAAaZ,gBAKrBqB,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU,eAS3EI,iBAAiBf,SAAQ,SAASC,QAC9BA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAGVW,aAAe,EACfC,WAAa,EACbC,mBAAmBT,SAAQ,SAASU,mBAC5BA,kBAAkBE,WAAWC,UAAUK,SAAS,YAChDX,aAAeX,YACfY,WAAaZ,YAAcQ,gBAAgBM,kBAAkBL,QAKrEY,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU;;;;;;;;;;;MA5IzEZ,cAAgBoB,SAASC,iBAAiB,uBAC1CX,mBAAqBU,SAASC,iBAAiB,0BAC/CL,iBAAmBI,SAASC,iBAAiB,4BAG/CxB,YACAO,UACAG,QACAC,aACAC,oBAuBKS,cAAcI,UAAWC,QAASf,aAAcC,WAAYe,aAEjDJ,SAASC,iBAAiB,sBAGlCpB,SAAQ,SAASwB,QAErBA,OAAOC,MAAMC,QAAU,WAGnBC,WAAaH,OAAOI,cAAc,0BAA0BvB,IAG3DkB,aAAgBI,YAAcN,WAAaM,YAAcL,SACzDK,YAAcpB,cAAgBoB,YAAcnB,cAC7CgB,OAAOC,MAAMC,QAAU,qBAuG1BtB,gBAAgBC,WACdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM"} \ No newline at end of file +{"version":3,"file":"timefilter.min.js","sources":["../src/timefilter.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 * Javascript for the time filter\n *\n * This file implements 1 functionality:\n * - Checks, which of the radio buttons is pressed and filters the content based on the time.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant radio buttons.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Define to change the time span, an additional time span and the current time.\nlet currenttime;\nlet timestart;\nlet timeend;\nlet addstarttime;\nlet addendtime;\n\n/**\n * Init function\n */\nexport function init() {\n // Set the current time.\n currenttime = new Date().getTime() / 1000;\n\n // Add event listeners to the all kind of buttons.\n alltimeaddEventListener();\n futuretimeaddEventListener();\n pasttimeaddEventListener();\n}\n\n/**\n * Function to execute the filter\n * @param {int} starttime Start of time span for filtering of the current pressed button\n * @param {int} endtime End of time span for filtering of the current pressed\n * @param {int} addstarttime Start of time span for filtering of an additional radio button.\n * @param {int} addendtime End of time span for filtering of an additional radio button.\n * @param {bool} buttonstate State of the radio button (true of false)\n */\nfunction executefilter(starttime, endtime, addstarttime, addendtime, buttonstate) {\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.ts_coursefilter_active.ts_letterfilter_active');\n\n // Loop through each letter and hide/show based on radiobutton state.\n letters.forEach(function(letter) {\n // First deactiveate all letters, as different time spans can overlap.\n letter.classList.remove('ts_timefilter_active'); // Mark the letter as \"not active\".\n //letter.style.display = 'none';\n\n // Get the created time stamp of each letter.\n let lettertime = letter.querySelector('.townsquareletter_date').id;\n\n // If the radio button is checked and the letter is in the time span, activate it.\n if ((buttonstate && (lettertime >= starttime && lettertime <= endtime)) ||\n (lettertime >= addstarttime && lettertime <= addendtime)) {\n letter.classList.add('ts_timefilter_active'); // Mark the letter as \"active\".\n //letter.style.display = 'block';\n }\n });\n}\n\n/**\n * Function to add event listeners to the all_time button.\n */\nfunction alltimeaddEventListener() {\n alltimebutton.forEach(function(button) {\n button.addEventListener('change', function() {\n // Set the time span to show all letters.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime + convertidtotime(button.id);\n addstarttime = 0;\n addendtime = 0;\n\n // Disable all other radio buttons that filter more specific times.\n futureradiobuttons.forEach(function(futureradiobutton) {\n futureradiobutton.checked = false;\n futureradiobutton.parentNode.classList.remove(\"active\");\n });\n pastradiobuttons.forEach(function(pastradiobutton) {\n pastradiobutton.checked = false;\n pastradiobutton.parentNode.classList.remove(\"active\");\n\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime,addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the future time radio buttons.\n */\nfunction futuretimeaddEventListener() {\n futureradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime;\n timeend = currenttime + convertidtotime(button.id);\n\n // Check if one past time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n pastradiobuttons.forEach(function(pastradiobutton) {\n if (pastradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime - convertidtotime(pastradiobutton.id);\n addendtime = currenttime;\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the past time radio buttons.\n */\nfunction pasttimeaddEventListener() {\n pastradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime;\n\n // Check if one future time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n futureradiobuttons.forEach(function(futureradiobutton) {\n if (futureradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime;\n addendtime = currenttime + convertidtotime(futureradiobutton.id);\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n"],"names":["currenttime","Date","getTime","alltimebutton","forEach","button","addEventListener","timestart","convertidtotime","id","timeend","addstarttime","addendtime","futureradiobuttons","futureradiobutton","checked","parentNode","classList","remove","pastradiobuttons","pastradiobutton","executefilter","contains","document","querySelectorAll","starttime","endtime","buttonstate","letter","lettertime","querySelector","add"],"mappings":"sJA2CIA,aAAc,IAAIC,MAAOC,UAAY,IA2CrCC,cAAcC,SAAQ,SAASC,QAC3BA,OAAOC,iBAAiB,UAAU,WAE9BC,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAC/CE,aAAe,EACfC,WAAa,EAGbC,mBAAmBT,SAAQ,SAASU,mBAChCA,kBAAkBC,SAAU,EAC5BD,kBAAkBE,WAAWC,UAAUC,OAAO,aAElDC,iBAAiBf,SAAQ,SAASgB,iBAC9BA,gBAAgBL,SAAU,EAC1BK,gBAAgBJ,WAAWC,UAAUC,OAAO,aAKhDG,cAAcd,UAAWG,QAASC,aAAaC,WAAYP,OAAOU,eAS1EF,mBAAmBT,SAAQ,SAASC,QAChCA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YACZU,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAG/CE,aAAe,EACfC,WAAa,EACbO,iBAAiBf,SAAQ,SAASgB,iBAC1BA,gBAAgBJ,WAAWC,UAAUK,SAAS,YAC9CX,aAAeX,YAAcQ,gBAAgBY,gBAAgBX,IAC7DG,WAAaZ,gBAKrBqB,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU,eAS3EI,iBAAiBf,SAAQ,SAASC,QAC9BA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAGVW,aAAe,EACfC,WAAa,EACbC,mBAAmBT,SAAQ,SAASU,mBAC5BA,kBAAkBE,WAAWC,UAAUK,SAAS,YAChDX,aAAeX,YACfY,WAAaZ,YAAcQ,gBAAgBM,kBAAkBL,QAKrEY,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU;;;;;;;;;;;MA/IzEZ,cAAgBoB,SAASC,iBAAiB,uBAC1CX,mBAAqBU,SAASC,iBAAiB,0BAC/CL,iBAAmBI,SAASC,iBAAiB,4BAG/CxB,YACAO,UACAG,QACAC,aACAC,oBAuBKS,cAAcI,UAAWC,QAASf,aAAcC,WAAYe,aAGjDJ,SAASC,iBAAiB,oEAGlCpB,SAAQ,SAASwB,QAErBA,OAAOX,UAAUC,OAAO,4BAIpBW,WAAaD,OAAOE,cAAc,0BAA0BrB,IAG3DkB,aAAgBE,YAAcJ,WAAaI,YAAcH,SACzDG,YAAclB,cAAgBkB,YAAcjB,aAC7CgB,OAAOX,UAAUc,IAAI,oCAwGxBvB,gBAAgBC,WACdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM"} \ No newline at end of file diff --git a/amd/src/coursefilter.js b/amd/src/coursefilter.js index 3c4bf0e..2964a6e 100644 --- a/amd/src/coursefilter.js +++ b/amd/src/coursefilter.js @@ -36,18 +36,23 @@ export function init() { // Get the courseid associated with the checkbox const courseid = checkbox.id; - // Get all letters. - const letters = document.querySelectorAll('.townsquare_letter'); + // Get all letters that are "activated". + // Activated means that all filters accept the letter and want to show it. + const letters = document.querySelectorAll('.townsquare_letter.ts_timefilter_active.ts_letterfilter_active'); - // Loop through each letter and hide/show based on checkbox state and the letter id. + // Loop through each letter mark it as "active" or not based on checkbox state and the letter id. letters.forEach(function(letter) { let letterCourseId = letter.querySelector('.townsquareletter_course').id; if (courseid === letterCourseId) { if (checkbox.checked) { - letter.style.display = 'block'; // Show the letter + //window.alert('activated'); + letter.classList.add('ts_coursefilter_active'); // Mark the letter as "active". + //letter.style.display = 'block'; // Show the letter } else { - letter.style.display = 'none'; // Hide the letter + //window.alert('not activated'); + letter.classList.remove('ts_coursefilter_active'); // Mark the letter as "not active". + //letter.style.display = 'none'; // Hide the letter. } } }); diff --git a/amd/src/filtercontroller.js b/amd/src/filtercontroller.js new file mode 100644 index 0000000..11ccf50 --- /dev/null +++ b/amd/src/filtercontroller.js @@ -0,0 +1,63 @@ +// 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 . + +/** + * Javascript to show/hide letters based on all filters + * + * This file implements 1 functionality: + * - If the "save settings" button is pressed, store the settings in the database. + * + * @module block_townsquare/filtercontroller + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +// Get all letters from townsquare. +const letters = document.querySelectorAll('.townsquare_letter'); + +/** + * Init function + */ +export function init() { + // First step: activate every letter by adding the filter classes. + letters.forEach(function(letter) { + letter.classList.add('ts_coursefilter_active'); + letter.classList.add('ts_timefilter_active'); + letter.classList.add('ts_letterfilter_active'); + }); + + // Add a mutation listener to each letter. + letters.forEach(function(letter) { + const observer = new MutationObserver(function(mutations) { + mutations.forEach(function(mutation) { + if (mutation.attributeName === 'class') { + // If the class of the letter changes, check if the letter should be shown or hidden. + let coursefilter = letter.classList.contains('ts_coursefilter_active'); + let timefilter = letter.classList.contains('ts_timefilter_active'); + let letterfilter = letter.classList.contains('ts_letterfilter_active'); + + // If all filters are active, show the letter. + if (coursefilter && timefilter && letterfilter) { + letter.style.display = 'block'; + } else { + letter.style.display = 'none'; + } + } + }); + }); + + observer.observe(letter, {attributes: true}); + }); +} diff --git a/amd/src/letterfilter.js b/amd/src/letterfilter.js index e79bcf7..b9d3a2a 100644 --- a/amd/src/letterfilter.js +++ b/amd/src/letterfilter.js @@ -37,15 +37,19 @@ export function init() { // Get the letter name associated with the checkbox. const lettername = checkbox.id; - // Get all the right letters. - const letters = document.querySelectorAll('.townsquare_letter.' + lettername); + // Get all letters that are "activated". + // Activated means that all filters accept the letter and want to show it. + const letters = document.querySelectorAll('.townsquare_letter.' + lettername + + '.ts_timefilter_active.ts_coursefilter_active'); // Loop through each letter and hide/show based on checkbox state. letters.forEach(function(letter) { if (checkbox.checked) { - letter.style.display = 'block'; // Show the letter. + letter.classList.add('ts_letterfilter_active'); // Mark the letter as "active". + //letter.style.display = 'block'; // Show the letter. } else { - letter.style.display = 'none'; // Hide the letter. + letter.classList.remove('ts_letterfilter_active'); // Mark the letter as "not active". + //letter.style.display = 'none'; // Hide the letter. } }); }); diff --git a/amd/src/timefilter.js b/amd/src/timefilter.js index 31cf5ff..b515bc3 100644 --- a/amd/src/timefilter.js +++ b/amd/src/timefilter.js @@ -58,21 +58,24 @@ export function init() { * @param {bool} buttonstate State of the radio button (true of false) */ function executefilter(starttime, endtime, addstarttime, addendtime, buttonstate) { - // Get all the letters. - const letters = document.querySelectorAll('.townsquare_letter'); + // Get all letters that are "activated". + // Activated means that all filters accept the letter and want to show it. + const letters = document.querySelectorAll('.townsquare_letter.ts_coursefilter_active.ts_letterfilter_active'); // Loop through each letter and hide/show based on radiobutton state. letters.forEach(function(letter) { - // First hide all letters, as different time spans can overlap. - letter.style.display = 'none'; + // First deactiveate all letters, as different time spans can overlap. + letter.classList.remove('ts_timefilter_active'); // Mark the letter as "not active". + //letter.style.display = 'none'; // Get the created time stamp of each letter. let lettertime = letter.querySelector('.townsquareletter_date').id; - // If the radio button is checked and the letter is in the time span, show it. + // If the radio button is checked and the letter is in the time span, activate it. if ((buttonstate && (lettertime >= starttime && lettertime <= endtime)) || (lettertime >= addstarttime && lettertime <= addendtime)) { - letter.style.display = 'block'; + letter.classList.add('ts_timefilter_active'); // Mark the letter as "active". + //letter.style.display = 'block'; } }); } diff --git a/block_townsquare.php b/block_townsquare.php index c65528b..abd4c48 100644 --- a/block_townsquare.php +++ b/block_townsquare.php @@ -62,6 +62,7 @@ public function get_content():object { $this->page->requires->js_call_amd('block_townsquare/coursefilter', 'init'); $this->page->requires->js_call_amd('block_townsquare/timefilter', 'init'); $this->page->requires->js_call_amd('block_townsquare/letterfilter', 'init'); + $this->page->requires->js_call_amd('block_townsquare/filtercontroller', 'init'); $this->page->requires->js_call_amd('block_townsquare/usersettings_save', 'init', [$USER->id, $usersettings]); return $this->content; } diff --git a/styles.css b/styles.css index da70b1b..19f24fc 100644 --- a/styles.css +++ b/styles.css @@ -9,7 +9,7 @@ .townsquare_content { max-height: 750px; border-radius: 0.5rem; - overflow:scroll; + overflow: scroll; max-width: 100%; overflow-x: hidden; } @@ -47,7 +47,7 @@ color: #fff; text-decoration: underline; } -.townsquareletter_courselink{ +.townsquareletter_courselink { color: #fff; text-decoration: none; } diff --git a/templates/sidepanel.mustache b/templates/sidepanel.mustache index 5134c90..2535573 100644 --- a/templates/sidepanel.mustache +++ b/templates/sidepanel.mustache @@ -104,19 +104,19 @@
- +
- +
- + From 6db1557502216b238f56db13821be696fcbc169c Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Mon, 12 Feb 2024 15:49:39 +0100 Subject: [PATCH 030/123] time filter error fixed and coding style --- amd/build/coursefilter.min.js.map | 2 +- amd/build/letterfilter.min.js.map | 2 +- amd/build/timefilter.min.js | 2 +- amd/build/timefilter.min.js.map | 2 +- amd/src/coursefilter.js | 4 ---- amd/src/letterfilter.js | 3 --- amd/src/timefilter.js | 8 +++----- 7 files changed, 7 insertions(+), 16 deletions(-) diff --git a/amd/build/coursefilter.min.js.map b/amd/build/coursefilter.min.js.map index 1d371ed..4b6bcae 100644 --- a/amd/build/coursefilter.min.js.map +++ b/amd/build/coursefilter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"coursefilter.min.js","sources":["../src/coursefilter.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 * Javascript for the course filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the course filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/coursefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant checkboxes.\nconst checkboxes = document.querySelectorAll('.ts_course_checkbox');\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n // Get the courseid associated with the checkbox\n const courseid = checkbox.id;\n\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.ts_timefilter_active.ts_letterfilter_active');\n\n // Loop through each letter mark it as \"active\" or not based on checkbox state and the letter id.\n letters.forEach(function(letter) {\n let letterCourseId = letter.querySelector('.townsquareletter_course').id;\n\n if (courseid === letterCourseId) {\n if (checkbox.checked) {\n //window.alert('activated');\n letter.classList.add('ts_coursefilter_active'); // Mark the letter as \"active\".\n //letter.style.display = 'block'; // Show the letter\n } else {\n //window.alert('not activated');\n letter.classList.remove('ts_coursefilter_active'); // Mark the letter as \"not active\".\n //letter.style.display = 'none'; // Hide the letter.\n }\n }\n });\n });\n });\n}\n"],"names":["checkboxes","forEach","checkbox","addEventListener","courseid","id","document","querySelectorAll","letter","letterCourseId","querySelector","checked","classList","add","remove"],"mappings":"wJAiCIA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,iBAE1BC,SAAWF,SAASG,GAIVC,SAASC,iBAAiB,kEAGlCN,SAAQ,SAASO,YACjBC,eAAiBD,OAAOE,cAAc,4BAA4BL,GAElED,WAAaK,iBACTP,SAASS,QAETH,OAAOI,UAAUC,IAAI,0BAIrBL,OAAOI,UAAUE,OAAO;;;;;;;;;;;MA1B1Cd,WAAaM,SAASC,iBAAiB"} \ No newline at end of file +{"version":3,"file":"coursefilter.min.js","sources":["../src/coursefilter.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 * Javascript for the course filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the course filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/coursefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant checkboxes.\nconst checkboxes = document.querySelectorAll('.ts_course_checkbox');\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n // Get the courseid associated with the checkbox\n const courseid = checkbox.id;\n\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.ts_timefilter_active.ts_letterfilter_active');\n\n // Loop through each letter mark it as \"active\" or not based on checkbox state and the letter id.\n letters.forEach(function(letter) {\n let letterCourseId = letter.querySelector('.townsquareletter_course').id;\n\n if (courseid === letterCourseId) {\n if (checkbox.checked) {\n letter.classList.add('ts_coursefilter_active'); // Mark the letter as \"active\".\n } else {\n letter.classList.remove('ts_coursefilter_active'); // Mark the letter as \"not active\".\n }\n }\n });\n });\n });\n}\n"],"names":["checkboxes","forEach","checkbox","addEventListener","courseid","id","document","querySelectorAll","letter","letterCourseId","querySelector","checked","classList","add","remove"],"mappings":"wJAiCIA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,iBAE1BC,SAAWF,SAASG,GAIVC,SAASC,iBAAiB,kEAGlCN,SAAQ,SAASO,YACjBC,eAAiBD,OAAOE,cAAc,4BAA4BL,GAElED,WAAaK,iBACTP,SAASS,QACTH,OAAOI,UAAUC,IAAI,0BAErBL,OAAOI,UAAUE,OAAO;;;;;;;;;;;MAvB1Cd,WAAaM,SAASC,iBAAiB"} \ No newline at end of file diff --git a/amd/build/letterfilter.min.js.map b/amd/build/letterfilter.min.js.map index d0bce3e..9f6c13e 100644 --- a/amd/build/letterfilter.min.js.map +++ b/amd/build/letterfilter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"letterfilter.min.js","sources":["../src/letterfilter.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 * Javascript for the letter filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the letter filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/letterfilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant checkboxes.\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n\n // Get the letter name associated with the checkbox.\n const lettername = checkbox.id;\n\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.' + lettername +\n '.ts_timefilter_active.ts_coursefilter_active');\n\n // Loop through each letter and hide/show based on checkbox state.\n letters.forEach(function(letter) {\n if (checkbox.checked) {\n letter.classList.add('ts_letterfilter_active'); // Mark the letter as \"active\".\n //letter.style.display = 'block'; // Show the letter.\n } else {\n letter.classList.remove('ts_letterfilter_active'); // Mark the letter as \"not active\".\n //letter.style.display = 'none'; // Hide the letter.\n }\n });\n });\n });\n}\n"],"names":["checkboxes","forEach","checkbox","addEventListener","lettername","id","document","querySelectorAll","letter","checked","classList","add","remove"],"mappings":"wJAiCIA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,iBAG1BC,WAAaF,SAASG,GAIZC,SAASC,iBAAiB,sBAAwBH,WACxB,gDAGlCH,SAAQ,SAASO,QACjBN,SAASO,QACTD,OAAOE,UAAUC,IAAI,0BAGrBH,OAAOE,UAAUE,OAAO;;;;;;;;;;;MAvBtCZ,WAAaM,SAASC,iBAAiB"} \ No newline at end of file +{"version":3,"file":"letterfilter.min.js","sources":["../src/letterfilter.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 * Javascript for the letter filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the letter filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/letterfilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant checkboxes.\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n // Get the letter name associated with the checkbox.\n const lettername = checkbox.id;\n\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.' + lettername +\n '.ts_timefilter_active.ts_coursefilter_active');\n\n // Loop through each letter and hide/show based on checkbox state.\n letters.forEach(function(letter) {\n if (checkbox.checked) {\n letter.classList.add('ts_letterfilter_active'); // Mark the letter as \"active\".\n } else {\n letter.classList.remove('ts_letterfilter_active'); // Mark the letter as \"not active\".\n }\n });\n });\n });\n}\n"],"names":["checkboxes","forEach","checkbox","addEventListener","lettername","id","document","querySelectorAll","letter","checked","classList","add","remove"],"mappings":"wJAiCIA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,iBAE1BC,WAAaF,SAASG,GAIZC,SAASC,iBAAiB,sBAAwBH,WACxB,gDAGlCH,SAAQ,SAASO,QACjBN,SAASO,QACTD,OAAOE,UAAUC,IAAI,0BAErBH,OAAOE,UAAUE,OAAO;;;;;;;;;;;MArBtCZ,WAAaM,SAASC,iBAAiB"} \ No newline at end of file diff --git a/amd/build/timefilter.min.js b/amd/build/timefilter.min.js index 48b36ec..8205054 100644 --- a/amd/build/timefilter.min.js +++ b/amd/build/timefilter.min.js @@ -9,6 +9,6 @@ define("block_townsquare/timefilter",["exports"],(function(_exports){Object.defi * @copyright 2024 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -const alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button");let currenttime,timestart,timeend,addstarttime,addendtime;function executefilter(starttime,endtime,addstarttime,addendtime,buttonstate){document.querySelectorAll(".townsquare_letter.ts_coursefilter_active.ts_letterfilter_active").forEach((function(letter){letter.classList.remove("ts_timefilter_active");let lettertime=letter.querySelector(".townsquareletter_date").id;(buttonstate&&lettertime>=starttime&&lettertime<=endtime||lettertime>=addstarttime&&lettertime<=addendtime)&&letter.classList.add("ts_timefilter_active")}))}function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}})); +const alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button");let currenttime,timestart,timeend,addstarttime,addendtime;function executefilter(starttime,endtime,addstarttime,addendtime,buttonstate){document.querySelectorAll(".townsquare_letter.ts_coursefilter_active.ts_letterfilter_active").forEach((function(letter){let lettertime=letter.querySelector(".townsquareletter_date").id;buttonstate&&lettertime>=starttime&&lettertime<=endtime||lettertime>=addstarttime&&lettertime<=addendtime?letter.classList.add("ts_timefilter_active"):letter.classList.remove("ts_timefilter_active")}))}function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}})); //# sourceMappingURL=timefilter.min.js.map \ No newline at end of file diff --git a/amd/build/timefilter.min.js.map b/amd/build/timefilter.min.js.map index 4f353dc..238ee47 100644 --- a/amd/build/timefilter.min.js.map +++ b/amd/build/timefilter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"timefilter.min.js","sources":["../src/timefilter.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 * Javascript for the time filter\n *\n * This file implements 1 functionality:\n * - Checks, which of the radio buttons is pressed and filters the content based on the time.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant radio buttons.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Define to change the time span, an additional time span and the current time.\nlet currenttime;\nlet timestart;\nlet timeend;\nlet addstarttime;\nlet addendtime;\n\n/**\n * Init function\n */\nexport function init() {\n // Set the current time.\n currenttime = new Date().getTime() / 1000;\n\n // Add event listeners to the all kind of buttons.\n alltimeaddEventListener();\n futuretimeaddEventListener();\n pasttimeaddEventListener();\n}\n\n/**\n * Function to execute the filter\n * @param {int} starttime Start of time span for filtering of the current pressed button\n * @param {int} endtime End of time span for filtering of the current pressed\n * @param {int} addstarttime Start of time span for filtering of an additional radio button.\n * @param {int} addendtime End of time span for filtering of an additional radio button.\n * @param {bool} buttonstate State of the radio button (true of false)\n */\nfunction executefilter(starttime, endtime, addstarttime, addendtime, buttonstate) {\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.ts_coursefilter_active.ts_letterfilter_active');\n\n // Loop through each letter and hide/show based on radiobutton state.\n letters.forEach(function(letter) {\n // First deactiveate all letters, as different time spans can overlap.\n letter.classList.remove('ts_timefilter_active'); // Mark the letter as \"not active\".\n //letter.style.display = 'none';\n\n // Get the created time stamp of each letter.\n let lettertime = letter.querySelector('.townsquareletter_date').id;\n\n // If the radio button is checked and the letter is in the time span, activate it.\n if ((buttonstate && (lettertime >= starttime && lettertime <= endtime)) ||\n (lettertime >= addstarttime && lettertime <= addendtime)) {\n letter.classList.add('ts_timefilter_active'); // Mark the letter as \"active\".\n //letter.style.display = 'block';\n }\n });\n}\n\n/**\n * Function to add event listeners to the all_time button.\n */\nfunction alltimeaddEventListener() {\n alltimebutton.forEach(function(button) {\n button.addEventListener('change', function() {\n // Set the time span to show all letters.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime + convertidtotime(button.id);\n addstarttime = 0;\n addendtime = 0;\n\n // Disable all other radio buttons that filter more specific times.\n futureradiobuttons.forEach(function(futureradiobutton) {\n futureradiobutton.checked = false;\n futureradiobutton.parentNode.classList.remove(\"active\");\n });\n pastradiobuttons.forEach(function(pastradiobutton) {\n pastradiobutton.checked = false;\n pastradiobutton.parentNode.classList.remove(\"active\");\n\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime,addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the future time radio buttons.\n */\nfunction futuretimeaddEventListener() {\n futureradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime;\n timeend = currenttime + convertidtotime(button.id);\n\n // Check if one past time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n pastradiobuttons.forEach(function(pastradiobutton) {\n if (pastradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime - convertidtotime(pastradiobutton.id);\n addendtime = currenttime;\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the past time radio buttons.\n */\nfunction pasttimeaddEventListener() {\n pastradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime;\n\n // Check if one future time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n futureradiobuttons.forEach(function(futureradiobutton) {\n if (futureradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime;\n addendtime = currenttime + convertidtotime(futureradiobutton.id);\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n"],"names":["currenttime","Date","getTime","alltimebutton","forEach","button","addEventListener","timestart","convertidtotime","id","timeend","addstarttime","addendtime","futureradiobuttons","futureradiobutton","checked","parentNode","classList","remove","pastradiobuttons","pastradiobutton","executefilter","contains","document","querySelectorAll","starttime","endtime","buttonstate","letter","lettertime","querySelector","add"],"mappings":"sJA2CIA,aAAc,IAAIC,MAAOC,UAAY,IA2CrCC,cAAcC,SAAQ,SAASC,QAC3BA,OAAOC,iBAAiB,UAAU,WAE9BC,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAC/CE,aAAe,EACfC,WAAa,EAGbC,mBAAmBT,SAAQ,SAASU,mBAChCA,kBAAkBC,SAAU,EAC5BD,kBAAkBE,WAAWC,UAAUC,OAAO,aAElDC,iBAAiBf,SAAQ,SAASgB,iBAC9BA,gBAAgBL,SAAU,EAC1BK,gBAAgBJ,WAAWC,UAAUC,OAAO,aAKhDG,cAAcd,UAAWG,QAASC,aAAaC,WAAYP,OAAOU,eAS1EF,mBAAmBT,SAAQ,SAASC,QAChCA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YACZU,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAG/CE,aAAe,EACfC,WAAa,EACbO,iBAAiBf,SAAQ,SAASgB,iBAC1BA,gBAAgBJ,WAAWC,UAAUK,SAAS,YAC9CX,aAAeX,YAAcQ,gBAAgBY,gBAAgBX,IAC7DG,WAAaZ,gBAKrBqB,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU,eAS3EI,iBAAiBf,SAAQ,SAASC,QAC9BA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAGVW,aAAe,EACfC,WAAa,EACbC,mBAAmBT,SAAQ,SAASU,mBAC5BA,kBAAkBE,WAAWC,UAAUK,SAAS,YAChDX,aAAeX,YACfY,WAAaZ,YAAcQ,gBAAgBM,kBAAkBL,QAKrEY,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU;;;;;;;;;;;MA/IzEZ,cAAgBoB,SAASC,iBAAiB,uBAC1CX,mBAAqBU,SAASC,iBAAiB,0BAC/CL,iBAAmBI,SAASC,iBAAiB,4BAG/CxB,YACAO,UACAG,QACAC,aACAC,oBAuBKS,cAAcI,UAAWC,QAASf,aAAcC,WAAYe,aAGjDJ,SAASC,iBAAiB,oEAGlCpB,SAAQ,SAASwB,QAErBA,OAAOX,UAAUC,OAAO,4BAIpBW,WAAaD,OAAOE,cAAc,0BAA0BrB,IAG3DkB,aAAgBE,YAAcJ,WAAaI,YAAcH,SACzDG,YAAclB,cAAgBkB,YAAcjB,aAC7CgB,OAAOX,UAAUc,IAAI,oCAwGxBvB,gBAAgBC,WACdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM"} \ No newline at end of file +{"version":3,"file":"timefilter.min.js","sources":["../src/timefilter.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 * Javascript for the time filter\n *\n * This file implements 1 functionality:\n * - Checks, which of the radio buttons is pressed and filters the content based on the time.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant radio buttons.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Define to change the time span, an additional time span and the current time.\nlet currenttime;\nlet timestart;\nlet timeend;\nlet addstarttime;\nlet addendtime;\n\n/**\n * Init function\n */\nexport function init() {\n // Set the current time.\n currenttime = new Date().getTime() / 1000;\n\n // Add event listeners to the all kind of buttons.\n alltimeaddEventListener();\n futuretimeaddEventListener();\n pasttimeaddEventListener();\n}\n\n/**\n * Function to execute the filter\n * @param {int} starttime Start of time span for filtering of the current pressed button\n * @param {int} endtime End of time span for filtering of the current pressed\n * @param {int} addstarttime Start of time span for filtering of an additional radio button.\n * @param {int} addendtime End of time span for filtering of an additional radio button.\n * @param {boolean} buttonstate State of the radio button (true or false)\n */\nfunction executefilter(starttime, endtime, addstarttime, addendtime, buttonstate) {\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.ts_coursefilter_active.ts_letterfilter_active');\n\n // Loop through each letter and hide/show based on radiobutton state.\n letters.forEach(function(letter) {\n\n // Get the created time stamp of each letter.\n let lettertime = letter.querySelector('.townsquareletter_date').id;\n\n // If the radio button is checked and the letter is in the time span, activate it.\n if ((buttonstate && (lettertime >= starttime && lettertime <= endtime)) ||\n (lettertime >= addstarttime && lettertime <= addendtime)) {\n letter.classList.add('ts_timefilter_active'); // Mark the letter as \"active\".\n } else {\n letter.classList.remove('ts_timefilter_active'); // Mark the letter as \"not active\".\n }\n });\n}\n\n/**\n * Function to add event listeners to the all_time button.\n */\nfunction alltimeaddEventListener() {\n alltimebutton.forEach(function(button) {\n button.addEventListener('change', function() {\n // Set the time span to show all letters.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime + convertidtotime(button.id);\n addstarttime = 0;\n addendtime = 0;\n\n // Disable all other radio buttons that filter more specific times.\n futureradiobuttons.forEach(function(futureradiobutton) {\n futureradiobutton.checked = false;\n futureradiobutton.parentNode.classList.remove(\"active\");\n });\n pastradiobuttons.forEach(function(pastradiobutton) {\n pastradiobutton.checked = false;\n pastradiobutton.parentNode.classList.remove(\"active\");\n\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime,addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the future time radio buttons.\n */\nfunction futuretimeaddEventListener() {\n futureradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime;\n timeend = currenttime + convertidtotime(button.id);\n\n // Check if one past time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n pastradiobuttons.forEach(function(pastradiobutton) {\n if (pastradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime - convertidtotime(pastradiobutton.id);\n addendtime = currenttime;\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the past time radio buttons.\n */\nfunction pasttimeaddEventListener() {\n pastradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime;\n\n // Check if one future time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n futureradiobuttons.forEach(function(futureradiobutton) {\n if (futureradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime;\n addendtime = currenttime + convertidtotime(futureradiobutton.id);\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n"],"names":["currenttime","Date","getTime","alltimebutton","forEach","button","addEventListener","timestart","convertidtotime","id","timeend","addstarttime","addendtime","futureradiobuttons","futureradiobutton","checked","parentNode","classList","remove","pastradiobuttons","pastradiobutton","executefilter","contains","document","querySelectorAll","starttime","endtime","buttonstate","letter","lettertime","querySelector","add"],"mappings":"sJA2CIA,aAAc,IAAIC,MAAOC,UAAY,IAyCrCC,cAAcC,SAAQ,SAASC,QAC3BA,OAAOC,iBAAiB,UAAU,WAE9BC,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAC/CE,aAAe,EACfC,WAAa,EAGbC,mBAAmBT,SAAQ,SAASU,mBAChCA,kBAAkBC,SAAU,EAC5BD,kBAAkBE,WAAWC,UAAUC,OAAO,aAElDC,iBAAiBf,SAAQ,SAASgB,iBAC9BA,gBAAgBL,SAAU,EAC1BK,gBAAgBJ,WAAWC,UAAUC,OAAO,aAKhDG,cAAcd,UAAWG,QAASC,aAAaC,WAAYP,OAAOU,eAS1EF,mBAAmBT,SAAQ,SAASC,QAChCA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YACZU,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAG/CE,aAAe,EACfC,WAAa,EACbO,iBAAiBf,SAAQ,SAASgB,iBAC1BA,gBAAgBJ,WAAWC,UAAUK,SAAS,YAC9CX,aAAeX,YAAcQ,gBAAgBY,gBAAgBX,IAC7DG,WAAaZ,gBAKrBqB,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU,eAS3EI,iBAAiBf,SAAQ,SAASC,QAC9BA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAGVW,aAAe,EACfC,WAAa,EACbC,mBAAmBT,SAAQ,SAASU,mBAC5BA,kBAAkBE,WAAWC,UAAUK,SAAS,YAChDX,aAAeX,YACfY,WAAaZ,YAAcQ,gBAAgBM,kBAAkBL,QAKrEY,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU;;;;;;;;;;;MA7IzEZ,cAAgBoB,SAASC,iBAAiB,uBAC1CX,mBAAqBU,SAASC,iBAAiB,0BAC/CL,iBAAmBI,SAASC,iBAAiB,4BAG/CxB,YACAO,UACAG,QACAC,aACAC,oBAuBKS,cAAcI,UAAWC,QAASf,aAAcC,WAAYe,aAGjDJ,SAASC,iBAAiB,oEAGlCpB,SAAQ,SAASwB,YAGjBC,WAAaD,OAAOE,cAAc,0BAA0BrB,GAG3DkB,aAAgBE,YAAcJ,WAAaI,YAAcH,SACzDG,YAAclB,cAAgBkB,YAAcjB,WAC7CgB,OAAOX,UAAUc,IAAI,wBAErBH,OAAOX,UAAUC,OAAO,oCAuG3BV,gBAAgBC,WACdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM"} \ No newline at end of file diff --git a/amd/src/coursefilter.js b/amd/src/coursefilter.js index 2964a6e..04baad9 100644 --- a/amd/src/coursefilter.js +++ b/amd/src/coursefilter.js @@ -46,13 +46,9 @@ export function init() { if (courseid === letterCourseId) { if (checkbox.checked) { - //window.alert('activated'); letter.classList.add('ts_coursefilter_active'); // Mark the letter as "active". - //letter.style.display = 'block'; // Show the letter } else { - //window.alert('not activated'); letter.classList.remove('ts_coursefilter_active'); // Mark the letter as "not active". - //letter.style.display = 'none'; // Hide the letter. } } }); diff --git a/amd/src/letterfilter.js b/amd/src/letterfilter.js index b9d3a2a..77c544c 100644 --- a/amd/src/letterfilter.js +++ b/amd/src/letterfilter.js @@ -33,7 +33,6 @@ const checkboxes = document.querySelectorAll('.ts_letter_checkbox'); export function init() { checkboxes.forEach(function(checkbox) { checkbox.addEventListener('change', function() { - // Get the letter name associated with the checkbox. const lettername = checkbox.id; @@ -46,10 +45,8 @@ export function init() { letters.forEach(function(letter) { if (checkbox.checked) { letter.classList.add('ts_letterfilter_active'); // Mark the letter as "active". - //letter.style.display = 'block'; // Show the letter. } else { letter.classList.remove('ts_letterfilter_active'); // Mark the letter as "not active". - //letter.style.display = 'none'; // Hide the letter. } }); }); diff --git a/amd/src/timefilter.js b/amd/src/timefilter.js index b515bc3..3a2b3c5 100644 --- a/amd/src/timefilter.js +++ b/amd/src/timefilter.js @@ -55,7 +55,7 @@ export function init() { * @param {int} endtime End of time span for filtering of the current pressed * @param {int} addstarttime Start of time span for filtering of an additional radio button. * @param {int} addendtime End of time span for filtering of an additional radio button. - * @param {bool} buttonstate State of the radio button (true of false) + * @param {boolean} buttonstate State of the radio button (true or false) */ function executefilter(starttime, endtime, addstarttime, addendtime, buttonstate) { // Get all letters that are "activated". @@ -64,9 +64,6 @@ function executefilter(starttime, endtime, addstarttime, addendtime, buttonstate // Loop through each letter and hide/show based on radiobutton state. letters.forEach(function(letter) { - // First deactiveate all letters, as different time spans can overlap. - letter.classList.remove('ts_timefilter_active'); // Mark the letter as "not active". - //letter.style.display = 'none'; // Get the created time stamp of each letter. let lettertime = letter.querySelector('.townsquareletter_date').id; @@ -75,7 +72,8 @@ function executefilter(starttime, endtime, addstarttime, addendtime, buttonstate if ((buttonstate && (lettertime >= starttime && lettertime <= endtime)) || (lettertime >= addstarttime && lettertime <= addendtime)) { letter.classList.add('ts_timefilter_active'); // Mark the letter as "active". - //letter.style.display = 'block'; + } else { + letter.classList.remove('ts_timefilter_active'); // Mark the letter as "not active". } }); } From 5fc48419191e4a019bd42f211f5f7168f2ec4498 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Wed, 13 Mar 2024 17:04:38 +0100 Subject: [PATCH 031/123] WIP try to acces own web service --- amd/build/usersettings_save.min.js | 2 +- amd/build/usersettings_save.min.js.map | 2 +- amd/src/usersettings_save.js | 38 ++++-- classes/filtercontroller.php | 156 ------------------------- db/services.php | 2 +- externallib.php | 18 +-- 6 files changed, 43 insertions(+), 175 deletions(-) delete mode 100644 classes/filtercontroller.php diff --git a/amd/build/usersettings_save.min.js b/amd/build/usersettings_save.min.js index ab75713..542d40d 100644 --- a/amd/build/usersettings_save.min.js +++ b/amd/build/usersettings_save.min.js @@ -8,6 +8,6 @@ define("block_townsquare/usersettings_save",["exports","core/ajax"],(function(_e * @module block_townsquare/timefilter * @copyright 2024 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,settingsfromdb){settingsfromdb&&function(settingsfromdb){let timefilterfuture=settingsfromdb.timefilterfuture,timefilterpast=settingsfromdb.timefilterpast,basicletter=settingsfromdb.basicletter,completionletter=settingsfromdb.completionletter,postletter=settingsfromdb.postletter,futurebuttonid=converttimetoid(timefilterfuture,!0),pastbuttonid=converttimetoid(timefilterpast,!1);"ts_time_all"!==futurebuttonid?(futureradiobuttons.forEach((function(button){button.id==futurebuttonid&&(button.checked=!0,button.parentNode.classList.add("active"))})),pastradiobuttons.forEach((function(button){button.id==pastbuttonid&&(button.checked=!0,button.parentNode.classList.add("active"))}))):alltimebutton.forEach((function(button){button.id==futurebuttonid&&(button.checked=!0,button.parentNode.classList.add("active"))}));checkboxes.forEach((function(checkbox){let basiclettercheck="basicletter"===checkbox.id&&"1"===basicletter,completionlettercheck="completionletter"===checkbox.id&&"1"===completionletter,postlettercheck="postletter"===checkbox.id&&"1"===postletter;(basiclettercheck||completionlettercheck||postlettercheck)&&checkbox.click()}))}(settingsfromdb);savebutton.addEventListener("click",(async function(){let timespans=function(){let settings={timepast:0,timefuture:0},settingsset=!1;if(alltimebutton.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id),settings.timefuture=convertidtotime(button.id),settingsset=!0)})),settingsset)return settings;return futureradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timefuture=convertidtotime(button.id))})),pastradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id))})),settings}(),letterfilter=function(){let settings={basicletter:0,completionletter:0,postletter:0};return checkboxes.forEach((function(checkbox){if(checkbox.checked)switch(checkbox.id){case"basicletter":settings.basicletter=1;break;case"completionletter":settings.completionletter=1;break;case"postletter":settings.postletter=1}})),settings}();await async function(userid,timefilterpast,timefilterfuture,basicletter,completionletter,postletter){window.alert("Settings here.");let result=await _ajax.default.call([{methodname:"block_townsquare_record_usersettings",args:{userid:userid,timefilterpast:timefilterpast,timefilterfuture:timefilterfuture,basicletter:basicletter,completionletter:completionletter,postletter:postletter}}]);return window.alert("im done"),result}(userid,timespans.timepast,timespans.timefuture,letterfilter.basicletter,letterfilter.completionletter,letterfilter.postletter)}))},_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};const savebutton=document.getElementById("ts_usersettings_savebutton"),alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button"),checkboxes=document.querySelectorAll(".ts_letter_checkbox");function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}function converttimetoid(time,future){switch(time){case"15778463":return"ts_time_all";case"172800":return future?"ts_time_next_twodays":"ts_time_past_twodays";case"432000":return future?"ts_time_next_fivedays":"ts_time_last_fivedays";case"604800":return future?"ts_time_next_week":"ts_time_last_week";case"2592000":return future?"ts_time_next_month":"ts_time_last_month"}}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,settingsfromdb){settingsfromdb&&function(settingsfromdb){let timefilterfuture=settingsfromdb.timefilterfuture,timefilterpast=settingsfromdb.timefilterpast,basicletter=settingsfromdb.basicletter,completionletter=settingsfromdb.completionletter,postletter=settingsfromdb.postletter,futurebuttonid=converttimetoid(timefilterfuture,!0),pastbuttonid=converttimetoid(timefilterpast,!1);"ts_time_all"!==futurebuttonid?(futureradiobuttons.forEach((function(button){button.id==futurebuttonid&&(button.checked=!0,button.parentNode.classList.add("active"))})),pastradiobuttons.forEach((function(button){button.id==pastbuttonid&&(button.checked=!0,button.parentNode.classList.add("active"))}))):alltimebutton.forEach((function(button){button.id==futurebuttonid&&(button.checked=!0,button.parentNode.classList.add("active"))}));checkboxes.forEach((function(checkbox){let basiclettercheck="basicletter"===checkbox.id&&"1"===basicletter,completionlettercheck="completionletter"===checkbox.id&&"1"===completionletter,postlettercheck="postletter"===checkbox.id&&"1"===postletter;(basiclettercheck||completionlettercheck||postlettercheck)&&checkbox.click()}))}(settingsfromdb);savebutton.addEventListener("click",(async function(){let timespans=function(){let settings={timepast:0,timefuture:0},settingsset=!1;if(alltimebutton.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id),settings.timefuture=convertidtotime(button.id),settingsset=!0)})),settingsset)return settings;return futureradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timefuture=convertidtotime(button.id))})),pastradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id))})),settings}(),letterfilter=function(){let settings={basicletter:0,completionletter:0,postletter:0};return checkboxes.forEach((function(checkbox){if(checkbox.checked)switch(checkbox.id){case"basicletter":settings.basicletter=1;break;case"completionletter":settings.completionletter=1;break;case"postletter":settings.postletter=1}})),settings}();await async function(userid,timefilterpast,timefilterfuture,basicletter,completionletter,postletter){let result;window.alert("Settings here.");try{console.log({userid:parseInt(userid),timefilterpast:timefilterpast,timefilterfuture:timefilterfuture,basicletter:basicletter,completionletter:completionletter,postletter:postletter}),result=await _ajax.default.call([{methodname:"block_townsquare_record_usersettings",args:JSON.stringify({userid:parseInt(userid),timefilterpast:timefilterpast,timefilterfuture:timefilterfuture,basicletter:basicletter,completionletter:completionletter,postletter:postletter})}]),window.alert("im in a try")}catch(error){console.log(error)}window.alert("im done"),console.log(await result);return(await Promise.all(result)).forEach((response=>{console.log(response)})),result}(userid,timespans.timepast,timespans.timefuture,letterfilter.basicletter,letterfilter.completionletter,letterfilter.postletter)}))},_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};const savebutton=document.getElementById("ts_usersettings_savebutton"),alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button"),checkboxes=document.querySelectorAll(".ts_letter_checkbox");function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}function converttimetoid(time,future){switch(time){case"15778463":return"ts_time_all";case"172800":return future?"ts_time_next_twodays":"ts_time_past_twodays";case"432000":return future?"ts_time_next_fivedays":"ts_time_last_fivedays";case"604800":return future?"ts_time_next_week":"ts_time_last_week";case"2592000":return future?"ts_time_next_month":"ts_time_last_month"}}})); //# sourceMappingURL=usersettings_save.min.js.map \ No newline at end of file diff --git a/amd/build/usersettings_save.min.js.map b/amd/build/usersettings_save.min.js.map index d35f275..ef5e92d 100644 --- a/amd/build/usersettings_save.min.js.map +++ b/amd/build/usersettings_save.min.js.map @@ -1 +1 @@ -{"version":3,"file":"usersettings_save.min.js","sources":["../src/usersettings_save.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 * Javascript to save the user settings in the database.\n *\n * This file implements 1 functionality:\n * - If the \"save settings\" button is pressed, store the settings in the database.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n// Get the save button for the user settings.\nconst savebutton = document.getElementById('ts_usersettings_savebutton');\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n *\n * @param {number} userid The id of the current user.\n * @param {object} settingsfromdb The settings from the database, if there are any.\n */\nexport function init(userid, settingsfromdb) {\n // When the page is loaded, set the settings from the database.\n if (settingsfromdb) {\n executeusersettings(settingsfromdb);\n }\n\n // Add event listener to the save button.\n savebutton.addEventListener('click', async function() {\n\n // First step: collect the current settings.\n // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes..\n let timespans = collecttimefiltersettings();\n let letterfilter = collectletterfiltersettings();\n\n // Second step: store the usersettings in the database.\n await saveusersettings(userid, timespans['timepast'], timespans['timefuture'],\n letterfilter['basicletter'], letterfilter['completionletter'], letterfilter['postletter']);\n });\n}\n\n/**\n * Function to save the user settings in the database.\n * @param {number} userid\n * @param {number} timefilterpast\n * @param {number} timefilterfuture\n * @param {number} basicletter\n * @param {number} completionletter\n * @param {number} postletter\n * @returns {Promise<*>}\n */\nasync function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) {\n window.alert('Settings here.');\n let result = await Ajax.call([{\n methodname: 'block_townsquare_record_usersettings',\n args: {\n userid: userid,\n timefilterpast: timefilterpast,\n timefilterfuture: timefilterfuture,\n basicletter: basicletter,\n completionletter: completionletter,\n postletter: postletter\n }\n }]);\n window.alert('im done');\n return result;\n}\n\n/**\n * Function to execute existing user settings when loading the townsquare.\n * @param {Object} settingsfromdb\n */\nfunction executeusersettings(settingsfromdb) {\n // Load the settings.\n let timefilterfuture = settingsfromdb['timefilterfuture'];\n let timefilterpast = settingsfromdb['timefilterpast'];\n let basicletter = settingsfromdb['basicletter'];\n let completionletter = settingsfromdb['completionletter'];\n let postletter = settingsfromdb['postletter'];\n\n // First step: set the time filter settings.\n // Change the time into the correct radio button id.\n let futurebuttonid = converttimetoid(timefilterfuture, true);\n let pastbuttonid = converttimetoid(timefilterpast, false);\n\n // If the time span is a combination of past and future, go through the two radio buttons and click them to activate the filter.\n if (futurebuttonid !== \"ts_time_all\") {\n futureradiobuttons.forEach(function(button) {\n if (button.id == futurebuttonid) {\n button.checked = true;\n button.parentNode.classList.add('active');\n\n }\n });\n pastradiobuttons.forEach(function(button) {\n if (button.id == pastbuttonid) {\n button.checked = true;\n button.parentNode.classList.add('active');\n //button.parentNode.click();\n }\n });\n } else {\n // If the time span is the all time filter, click the all time button.\n alltimebutton.forEach(function(button) {\n if (button.id == futurebuttonid) {\n button.checked = true;\n button.parentNode.classList.add('active');\n // button.parentNode.click();\n }\n });\n }\n\n // Second step: set the letter filter settings.\n checkboxes.forEach(function(checkbox) {\n let basiclettercheck = checkbox.id === 'basicletter' && basicletter === \"1\";\n let completionlettercheck = checkbox.id === 'completionletter' && completionletter === \"1\";\n let postlettercheck = checkbox.id === 'postletter' && postletter === \"1\";\n\n if (basiclettercheck || completionlettercheck || postlettercheck) {\n checkbox.click();\n }\n });\n}\n\n/**\n * Function to collect the letter filter settings.\n * @returns {{basicletter: number, completionletter: number, postletter: number}}\n */\nfunction collectletterfiltersettings() {\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\n\n checkboxes.forEach(function(checkbox) {\n if (checkbox.checked) {\n switch(checkbox.id) {\n case \"basicletter\":\n settings['basicletter'] = 1;\n break;\n case \"completionletter\":\n settings['completionletter'] = 1;\n break;\n case \"postletter\":\n settings['postletter'] = 1;\n break;\n\n }\n }\n });\n // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit.\n return settings;\n}\n\n/**\n * Function to collect the time filter settings.\n * @returns {{timepast: number, timefuture: number}}\n */\nfunction collecttimefiltersettings() {\n let settings = { timepast: 0, timefuture: 0};\n let settingsset = false;\n\n // Get the relevant time spans of the time filter.\n // Check if the alltimebutton is set.\n alltimebutton.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n settings['timefuture'] = convertidtotime(button.id);\n settingsset = true;\n }\n });\n\n if (settingsset) {\n return settings;\n }\n\n // If the alltimebutton is not set, check which of the future/past buttons is set.\n futureradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timefuture'] = convertidtotime(button.id);\n }\n });\n\n pastradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n }\n });\n return settings;\n}\n\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n // TODO: Please use global functions if possible.\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n\n/**\n * Function to convert the time span to a radio button id.\n * @param {string} time\n * @param {boolean} future\n * @returns {string}\n */\nfunction converttimetoid(time, future) {\n switch (time) {\n case \"15778463\":\n return \"ts_time_all\";\n case \"172800\":\n if (future) {\n return \"ts_time_next_twodays\";\n }\n return \"ts_time_past_twodays\";\n case \"432000\":\n if (future) {\n return \"ts_time_next_fivedays\";\n }\n return \"ts_time_last_fivedays\";\n case \"604800\":\n if (future) {\n return \"ts_time_next_week\";\n }\n return \"ts_time_last_week\";\n case \"2592000\":\n if (future) {\n return \"ts_time_next_month\";\n\n }\n return \"ts_time_last_month\";\n }\n}\n"],"names":["userid","settingsfromdb","timefilterfuture","timefilterpast","basicletter","completionletter","postletter","futurebuttonid","converttimetoid","pastbuttonid","futureradiobuttons","forEach","button","id","checked","parentNode","classList","add","pastradiobuttons","alltimebutton","checkboxes","checkbox","basiclettercheck","completionlettercheck","postlettercheck","click","executeusersettings","savebutton","addEventListener","async","timespans","settings","timepast","timefuture","settingsset","contains","convertidtotime","collecttimefiltersettings","letterfilter","collectletterfiltersettings","window","alert","result","Ajax","call","methodname","args","saveusersettings","document","getElementById","querySelectorAll","time","future"],"mappings":";;;;;;;;;;oFAyCqBA,OAAQC,gBAErBA,yBAiDqBA,oBAErBC,iBAAmBD,eAAc,iBACjCE,eAAiBF,eAAc,eAC/BG,YAAcH,eAAc,YAC5BI,iBAAmBJ,eAAc,iBACjCK,WAAaL,eAAc,WAI3BM,eAAiBC,gBAAgBN,kBAAkB,GACnDO,aAAeD,gBAAgBL,gBAAgB,GAG5B,gBAAnBI,gBACAG,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOC,IAAMN,iBACbK,OAAOE,SAAU,EACjBF,OAAOG,WAAWC,UAAUC,IAAI,cAIxCC,iBAAiBP,SAAQ,SAASC,QAC1BA,OAAOC,IAAMJ,eACbG,OAAOE,SAAU,EACjBF,OAAOG,WAAWC,UAAUC,IAAI,eAMxCE,cAAcR,SAAQ,SAASC,QACvBA,OAAOC,IAAMN,iBACbK,OAAOE,SAAU,EACjBF,OAAOG,WAAWC,UAAUC,IAAI,cAO5CG,WAAWT,SAAQ,SAASU,cACpBC,iBAAmC,gBAAhBD,SAASR,IAAwC,MAAhBT,YACpDmB,sBAAwC,qBAAhBF,SAASR,IAAkD,MAArBR,iBAC9DmB,gBAAkC,eAAhBH,SAASR,IAAsC,MAAfP,YAElDgB,kBAAoBC,uBAAyBC,kBAC7CH,SAASI,WA/FbC,CAAoBzB,gBAIxB0B,WAAWC,iBAAiB,SAASC,qBAI7BC,yBA4HJC,SAAW,CAAEC,SAAU,EAAGC,WAAY,GACtCC,aAAc,KAIlBf,cAAcR,SAAQ,SAASC,QACxBA,OAAOG,WAAWC,UAAUmB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgBxB,OAAOC,IAC9CkB,SAAQ,WAAiBK,gBAAgBxB,OAAOC,IAChDqB,aAAc,MAIjBA,mBACOH,gBAIXrB,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOG,WAAWC,UAAUmB,SAAS,YAErCJ,SAAQ,WAAiBK,gBAAgBxB,OAAOC,QAIxDK,iBAAiBP,SAAQ,SAASC,QAC1BA,OAAOG,WAAWC,UAAUmB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgBxB,OAAOC,QAG/CkB,SA5JaM,GACZC,4BAgGJP,SAAW,aAAgB,mBAAuB,aAAiB,UAEvEX,WAAWT,SAAQ,SAASU,aACpBA,SAASP,eACFO,SAASR,QACP,cACDkB,SAAQ,YAAkB,YAEzB,mBACDA,SAAQ,iBAAuB,YAE9B,aACDA,SAAQ,WAAiB,MAOlCA,SAnHgBQ,wBAkBKvC,OAAQG,eAAgBD,iBAAkBE,YAAaC,iBAAkBC,YACrGkC,OAAOC,MAAM,sBACTC,aAAeC,cAAKC,KAAK,CAAC,CAC1BC,WAAY,uCACZC,KAAM,CACF9C,OAAQA,OACRG,eAAgBA,eAChBD,iBAAkBA,iBAClBE,YAAaA,YACbC,iBAAkBA,iBAClBC,WAAYA,sBAGpBkC,OAAOC,MAAM,WACNC,OA7BGK,CAAiB/C,OAAQ8B,UAAS,SAAcA,UAAS,WACxCQ,aAAY,YAAiBA,aAAY,iBAAsBA,aAAY,0EA5BpGX,WAAaqB,SAASC,eAAe,8BACrC9B,cAAgB6B,SAASE,iBAAiB,uBAC1CxC,mBAAqBsC,SAASE,iBAAiB,0BAC/ChC,iBAAmB8B,SAASE,iBAAiB,wBAC7C9B,WAAa4B,SAASE,iBAAiB,gCAwLpCd,gBAAgBvB,WAEdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM,iBAUVL,gBAAgB2C,KAAMC,eACnBD,UACC,iBACM,kBACN,gBACGC,OACO,uBAEJ,2BACN,gBACGA,OACO,wBAEJ,4BACN,gBACGA,OACO,oBAEJ,wBACN,iBACGA,OACO,qBAGJ"} \ No newline at end of file +{"version":3,"file":"usersettings_save.min.js","sources":["../src/usersettings_save.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 * Javascript to save the user settings in the database.\n *\n * This file implements 1 functionality:\n * - If the \"save settings\" button is pressed, store the settings in the database.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n// Get the save button for the user settings.\nconst savebutton = document.getElementById('ts_usersettings_savebutton');\n\n// Get the buttons from the time filter.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Get the checkboxes from the letter filter.\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n *\n * @param {number} userid The id of the current user.\n * @param {object} settingsfromdb The settings from the database, if there are any.\n */\nexport function init(userid, settingsfromdb) {\n // When the page is loaded, set the settings from the database.\n if (settingsfromdb) {\n executeusersettings(settingsfromdb);\n }\n\n // Add event listener to the save button.\n savebutton.addEventListener('click', async function() {\n\n // First step: collect the current settings.\n // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes.\n let timespans = collecttimefiltersettings();\n let letterfilter = collectletterfiltersettings();\n\n // Second step: store the usersettings in the database.\n await saveusersettings(userid, timespans['timepast'], timespans['timefuture'],\n letterfilter['basicletter'], letterfilter['completionletter'], letterfilter['postletter']);\n });\n}\n\n/**\n * Function to save the user settings in the database.\n * @param {number} userid\n * @param {number} timefilterpast\n * @param {number} timefilterfuture\n * @param {number} basicletter\n * @param {number} completionletter\n * @param {number} postletter\n * @returns {Promise<*>}\n */\nasync function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) {\n window.alert('Settings here.');\n let result ;\n try {\n console.log({\n userid: parseInt(userid),\n timefilterpast: timefilterpast,\n timefilterfuture: timefilterfuture,\n basicletter: basicletter,\n completionletter: completionletter,\n postletter: postletter\n });\n result = await Ajax.call([{\n methodname: 'block_townsquare_record_usersettings',\n args: JSON.stringify({\n userid: parseInt(userid),\n timefilterpast: timefilterpast,\n timefilterfuture: timefilterfuture,\n basicletter: basicletter,\n completionletter: completionletter,\n postletter: postletter\n }),\n }]);\n window.alert('im in a try');\n } catch (error) {\n console.log(error);\n }\n window.alert('im done');\n console.log(await result);\n const responses = await Promise.all(result);\n\n responses.forEach(response => {\n console.log(response);\n });\n return result;\n}\n\n/**\n * Function to execute existing user settings when loading the townsquare.\n * @param {Object} settingsfromdb\n */\nfunction executeusersettings(settingsfromdb) {\n // Load the settings.\n let timefilterfuture = settingsfromdb['timefilterfuture'];\n let timefilterpast = settingsfromdb['timefilterpast'];\n let basicletter = settingsfromdb['basicletter'];\n let completionletter = settingsfromdb['completionletter'];\n let postletter = settingsfromdb['postletter'];\n\n // First step: set the time filter settings.\n // Change the time into the correct radio button id.\n let futurebuttonid = converttimetoid(timefilterfuture, true);\n let pastbuttonid = converttimetoid(timefilterpast, false);\n\n // If the time span is a combination of past and future, go through the two radio buttons and click them to activate the filter.\n if (futurebuttonid !== \"ts_time_all\") {\n futureradiobuttons.forEach(function(button) {\n if (button.id == futurebuttonid) {\n button.checked = true;\n button.parentNode.classList.add('active');\n\n }\n });\n pastradiobuttons.forEach(function(button) {\n if (button.id == pastbuttonid) {\n button.checked = true;\n button.parentNode.classList.add('active');\n //button.parentNode.click();\n }\n });\n } else {\n // If the time span is the all time filter, click the all time button.\n alltimebutton.forEach(function(button) {\n if (button.id == futurebuttonid) {\n button.checked = true;\n button.parentNode.classList.add('active');\n // button.parentNode.click();\n }\n });\n }\n\n // Second step: set the letter filter settings.\n checkboxes.forEach(function(checkbox) {\n let basiclettercheck = checkbox.id === 'basicletter' && basicletter === \"1\";\n let completionlettercheck = checkbox.id === 'completionletter' && completionletter === \"1\";\n let postlettercheck = checkbox.id === 'postletter' && postletter === \"1\";\n\n if (basiclettercheck || completionlettercheck || postlettercheck) {\n checkbox.click();\n }\n });\n}\n\n/**\n * Function to collect the letter filter settings.\n * @returns {{basicletter: number, completionletter: number, postletter: number}}\n */\nfunction collectletterfiltersettings() {\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\n\n checkboxes.forEach(function(checkbox) {\n if (checkbox.checked) {\n switch(checkbox.id) {\n case \"basicletter\":\n settings['basicletter'] = 1;\n break;\n case \"completionletter\":\n settings['completionletter'] = 1;\n break;\n case \"postletter\":\n settings['postletter'] = 1;\n break;\n\n }\n }\n });\n // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit.\n return settings;\n}\n\n/**\n * Function to collect the time filter settings.\n * @returns {{timepast: number, timefuture: number}}\n */\nfunction collecttimefiltersettings() {\n let settings = { timepast: 0, timefuture: 0};\n let settingsset = false;\n\n // Get the relevant time spans of the time filter.\n // Check if the alltimebutton is set.\n alltimebutton.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n settings['timefuture'] = convertidtotime(button.id);\n settingsset = true;\n }\n });\n\n if (settingsset) {\n return settings;\n }\n\n // If the alltimebutton is not set, check which of the future/past buttons is set.\n futureradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timefuture'] = convertidtotime(button.id);\n }\n });\n\n pastradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n }\n });\n return settings;\n}\n\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n // TODO: Please use global functions if possible.\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n\n/**\n * Function to convert the time span to a radio button id.\n * @param {string} time\n * @param {boolean} future\n * @returns {string}\n */\nfunction converttimetoid(time, future) {\n switch (time) {\n case \"15778463\":\n return \"ts_time_all\";\n case \"172800\":\n if (future) {\n return \"ts_time_next_twodays\";\n }\n return \"ts_time_past_twodays\";\n case \"432000\":\n if (future) {\n return \"ts_time_next_fivedays\";\n }\n return \"ts_time_last_fivedays\";\n case \"604800\":\n if (future) {\n return \"ts_time_next_week\";\n }\n return \"ts_time_last_week\";\n case \"2592000\":\n if (future) {\n return \"ts_time_next_month\";\n\n }\n return \"ts_time_last_month\";\n }\n}\n"],"names":["userid","settingsfromdb","timefilterfuture","timefilterpast","basicletter","completionletter","postletter","futurebuttonid","converttimetoid","pastbuttonid","futureradiobuttons","forEach","button","id","checked","parentNode","classList","add","pastradiobuttons","alltimebutton","checkboxes","checkbox","basiclettercheck","completionlettercheck","postlettercheck","click","executeusersettings","savebutton","addEventListener","async","timespans","settings","timepast","timefuture","settingsset","contains","convertidtotime","collecttimefiltersettings","letterfilter","collectletterfiltersettings","result","window","alert","console","log","parseInt","Ajax","call","methodname","args","JSON","stringify","error","Promise","all","response","saveusersettings","document","getElementById","querySelectorAll","time","future"],"mappings":";;;;;;;;;;oFA6CqBA,OAAQC,gBAErBA,yBAqEqBA,oBAErBC,iBAAmBD,eAAc,iBACjCE,eAAiBF,eAAc,eAC/BG,YAAcH,eAAc,YAC5BI,iBAAmBJ,eAAc,iBACjCK,WAAaL,eAAc,WAI3BM,eAAiBC,gBAAgBN,kBAAkB,GACnDO,aAAeD,gBAAgBL,gBAAgB,GAG5B,gBAAnBI,gBACAG,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOC,IAAMN,iBACbK,OAAOE,SAAU,EACjBF,OAAOG,WAAWC,UAAUC,IAAI,cAIxCC,iBAAiBP,SAAQ,SAASC,QAC1BA,OAAOC,IAAMJ,eACbG,OAAOE,SAAU,EACjBF,OAAOG,WAAWC,UAAUC,IAAI,eAMxCE,cAAcR,SAAQ,SAASC,QACvBA,OAAOC,IAAMN,iBACbK,OAAOE,SAAU,EACjBF,OAAOG,WAAWC,UAAUC,IAAI,cAO5CG,WAAWT,SAAQ,SAASU,cACpBC,iBAAmC,gBAAhBD,SAASR,IAAwC,MAAhBT,YACpDmB,sBAAwC,qBAAhBF,SAASR,IAAkD,MAArBR,iBAC9DmB,gBAAkC,eAAhBH,SAASR,IAAsC,MAAfP,YAElDgB,kBAAoBC,uBAAyBC,kBAC7CH,SAASI,WAnHbC,CAAoBzB,gBAIxB0B,WAAWC,iBAAiB,SAASC,qBAI7BC,yBAgJJC,SAAW,CAAEC,SAAU,EAAGC,WAAY,GACtCC,aAAc,KAIlBf,cAAcR,SAAQ,SAASC,QACxBA,OAAOG,WAAWC,UAAUmB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgBxB,OAAOC,IAC9CkB,SAAQ,WAAiBK,gBAAgBxB,OAAOC,IAChDqB,aAAc,MAIjBA,mBACOH,gBAIXrB,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOG,WAAWC,UAAUmB,SAAS,YAErCJ,SAAQ,WAAiBK,gBAAgBxB,OAAOC,QAIxDK,iBAAiBP,SAAQ,SAASC,QAC1BA,OAAOG,WAAWC,UAAUmB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgBxB,OAAOC,QAG/CkB,SAhLaM,GACZC,4BAoHJP,SAAW,aAAgB,mBAAuB,aAAiB,UAEvEX,WAAWT,SAAQ,SAASU,aACpBA,SAASP,eACFO,SAASR,QACP,cACDkB,SAAQ,YAAkB,YAEzB,mBACDA,SAAQ,iBAAuB,YAE9B,aACDA,SAAQ,WAAiB,MAOlCA,SAvIgBQ,wBAkBKvC,OAAQG,eAAgBD,iBAAkBE,YAAaC,iBAAkBC,gBAEjGkC,OADJC,OAAOC,MAAM,sBAGTC,QAAQC,IAAI,CACR5C,OAAQ6C,SAAS7C,QACjBG,eAAgBA,eAChBD,iBAAkBA,iBAClBE,YAAaA,YACbC,iBAAkBA,iBAClBC,WAAYA,aAEhBkC,aAAeM,cAAKC,KAAK,CAAC,CACtBC,WAAY,uCACZC,KAAMC,KAAKC,UAAU,CACjBnD,OAAQ6C,SAAS7C,QACjBG,eAAgBA,eAChBD,iBAAkBA,iBAClBE,YAAaA,YACbC,iBAAkBA,iBAClBC,WAAYA,gBAGpBmC,OAAOC,MAAM,eACf,MAAOU,OACLT,QAAQC,IAAIQ,OAEhBX,OAAOC,MAAM,WACbC,QAAQC,UAAUJ,qBACMa,QAAQC,IAAId,SAE1B7B,SAAQ4C,WACdZ,QAAQC,IAAIW,aAETf,OAjDGgB,CAAiBxD,OAAQ8B,UAAS,SAAcA,UAAS,WACxCQ,aAAY,YAAiBA,aAAY,iBAAsBA,aAAY,0EAhCpGX,WAAa8B,SAASC,eAAe,8BAGrCvC,cAAgBsC,SAASE,iBAAiB,uBAC1CjD,mBAAqB+C,SAASE,iBAAiB,0BAC/CzC,iBAAmBuC,SAASE,iBAAiB,wBAG7CvC,WAAaqC,SAASE,iBAAiB,gCA4MpCvB,gBAAgBvB,WAEdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM,iBAUVL,gBAAgBoD,KAAMC,eACnBD,UACC,iBACM,kBACN,gBACGC,OACO,uBAEJ,2BACN,gBACGA,OACO,wBAEJ,4BACN,gBACGA,OACO,oBAEJ,wBACN,iBACGA,OACO,qBAGJ"} \ No newline at end of file diff --git a/amd/src/usersettings_save.js b/amd/src/usersettings_save.js index 1dbfe2a..2eee4ac 100644 --- a/amd/src/usersettings_save.js +++ b/amd/src/usersettings_save.js @@ -28,9 +28,13 @@ import Ajax from 'core/ajax'; // Get the save button for the user settings. const savebutton = document.getElementById('ts_usersettings_savebutton'); + +// Get the buttons from the time filter. const alltimebutton = document.querySelectorAll('.ts_all_time_button'); const futureradiobuttons = document.querySelectorAll('.ts_future_time_button'); const pastradiobuttons = document.querySelectorAll('.ts_past_time_button'); + +// Get the checkboxes from the letter filter. const checkboxes = document.querySelectorAll('.ts_letter_checkbox'); /** @@ -49,7 +53,7 @@ export function init(userid, settingsfromdb) { savebutton.addEventListener('click', async function() { // First step: collect the current settings. - // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes.. + // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes. let timespans = collecttimefiltersettings(); let letterfilter = collectletterfiltersettings(); @@ -71,18 +75,38 @@ export function init(userid, settingsfromdb) { */ async function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) { window.alert('Settings here.'); - let result = await Ajax.call([{ - methodname: 'block_townsquare_record_usersettings', - args: { - userid: userid, + let result ; + try { + console.log({ + userid: parseInt(userid), timefilterpast: timefilterpast, timefilterfuture: timefilterfuture, basicletter: basicletter, completionletter: completionletter, postletter: postletter - } - }]); + }); + result = await Ajax.call([{ + methodname: 'block_townsquare_record_usersettings', + args: JSON.stringify({ + userid: parseInt(userid), + timefilterpast: timefilterpast, + timefilterfuture: timefilterfuture, + basicletter: basicletter, + completionletter: completionletter, + postletter: postletter + }), + }]); + window.alert('im in a try'); + } catch (error) { + console.log(error); + } window.alert('im done'); + console.log(await result); + const responses = await Promise.all(result); + + responses.forEach(response => { + console.log(response); + }); return result; } diff --git a/classes/filtercontroller.php b/classes/filtercontroller.php deleted file mode 100644 index ec85b71..0000000 --- a/classes/filtercontroller.php +++ /dev/null @@ -1,156 +0,0 @@ -. - -/** - * Filter Controller of block_townsquare - * - * @package block_townsquare - * @copyright 2024 Tamaro Walter - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -namespace block_townsquare; - -/** - * Filter Controller Class. - * - * This Class controls the filter settings that user sets for the townsquare. - * The main functionality are: - * - store the filter settings that the user sets in the database - * - retrieve filter settings from the database and apply them when the user loads the townsquare - */ -class filtercontroller { - - /** @var array usersettings that the current user set */ - public array $usersettings; - - /** @var array timefilter that the user set */ - public array $timefilter; - - /** @var array letterfilter that the user set */ - public array $letterfilter; - - public function __construct() { - global $DB, $USER; - - // Retrieve the user filter settings from the database. If there are no settings, store a empty array. - if (!$this->usersettings = $DB->get_record('townsquare_usersettings', ['userid' => $USER->id])) { - $this->usersettings = []; - } - - // Build an array for the mustache templates to use. - } - - // Store functions. - public function store_usersettings(array $usersettings) { - // Change the information from the array to a number that can store the database. - // Check if the user already has settings in the database. - // If yes,update the settings. - // If no, insert the settings (on the GUI is a "submit" button, that also has a helpicon). - } - - // Retrieve functions. - public function set_timefilter(): array { - if ($this->usersettings == []) { - return []; - } - - // Set the default. - $this->timefilter = [ - 'all' => true, - 'nextweek' => false, - 'nextmonth' => false, - 'lastweek' => false, - 'lastmonth' => false, - ]; - - // Change the setting according to the database (case 0 is the default). - switch($this->usersettings->timefilter) { - case 1: - $this->timefilter['all'] = false; - $this->timefilter['nextweek'] = true; - break; - case 2: - $this->timefilter['all'] = false; - $this->timefilter['nextmonth'] = true; - break; - case 3: - $this->timefilter['all'] = false; - $this->timefilter['lastweek'] = true; - break; - case 4: - $this->timefilter['all'] = false; - $this->timefilter['lastmonth'] = true; - break; - default: - break; - } - - return $this->timefilter; - } - - public function set_letterfilter(): array { - if ($this->usersettings == []) { - return []; - } - - switch($this->usersettings->letterfilter) { - case 0: - $this->letterfilter['basicletter'] = true; - $this->letterfilter['completionletter'] = true; - $this->letterfilter['postletter'] = true; - break; - case 1: - $this->letterfilter['basicletter'] = true; - $this->letterfilter['completionletter'] = true; - $this->letterfilter['postletter'] = false; - break; - case 2: - $this->letterfilter['basicletter'] = true; - $this->letterfilter['completionletter'] = false; - $this->letterfilter['postletter'] = true; - break; - case 3: - $this->letterfilter['basicletter'] = true; - $this->letterfilter['completionletter'] = false; - $this->letterfilter['postletter'] = false; - break; - case 4: - $this->letterfilter['basicletter'] = false; - $this->letterfilter['completionletter'] = true; - $this->letterfilter['postletter'] = true; - break; - case 5: - $this->letterfilter['basicletter'] = false; - $this->letterfilter['completionletter'] = true; - $this->letterfilter['postletter'] = false; - break; - case 6: - $this->letterfilter['basicletter'] = false; - $this->letterfilter['completionletter'] = false; - $this->letterfilter['postletter'] = true; - break; - case 7: - $this->letterfilter['basicletter'] = false; - $this->letterfilter['completionletter'] = false; - $this->letterfilter['postletter'] = false; - break; - default: - break; - } - return $this->letterfilter; - } - -} diff --git a/db/services.php b/db/services.php index b2e13bf..fdd160c 100644 --- a/db/services.php +++ b/db/services.php @@ -27,7 +27,7 @@ $functions = [ 'block_townsquare_record_usersettings' => [ 'classname' => 'block_townsquare_external', - 'methodname' => 'record_usersettings', + 'methodname' => 'execute', 'classpath' => 'blocks/townsquare/externallib.php', 'description' => 'Records the user settings for the townsquare block', 'type' => 'write', diff --git a/externallib.php b/externallib.php index df6578a..effeb98 100644 --- a/externallib.php +++ b/externallib.php @@ -26,7 +26,6 @@ global $CFG; require_once($CFG->libdir . '/externallib.php'); -require_once($CFG->dirroot . '/mod/moodleoverflow/locallib.php'); /** * Class implementing the external API, esp. for AJAX functions. @@ -35,13 +34,13 @@ * @copyright 2024 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class block_townsquare_external extends external_api { +class block_townsquare_external extends \core_external\external_api { /** * Returns description of method parameters * @return external_function_parameters */ - public static function record_usersettings_parameters() { + public static function execute_parameters(): external_function_parameters { return new external_function_parameters( [ 'userid' => new external_value(PARAM_INT, 'the user id'), @@ -58,7 +57,7 @@ public static function record_usersettings_parameters() { * Return the result of the record_usersettings function * @return external_value */ - public static function record_usersettings_returns() { + public static function execute_returns() { return new external_value(PARAM_BOOL, 'true if successful'); } @@ -71,11 +70,10 @@ public static function record_usersettings_returns() { * @param int $letterfilter Setting of the letter filter * @return bool */ - public static function record_usersettings($userid, $timefilterpast, $timefilterfuture, - $basicletter, $completionletter, $postletter) { + public static function execute($userid, $timefilterpast, $timefilterfuture, $basicletter, $completionletter, $postletter) { global $DB; - echo ''; - $transaction = $DB->start_delegated_transaction(); + //echo ''; + //$transaction = $DB->start_delegated_transaction(); // Check if the user already has a record in the database if ($records = $DB->get_records('townsquare_usersettings', ['userid' => $userid])) { @@ -86,7 +84,7 @@ public static function record_usersettings($userid, $timefilterpast, $timefilter $DB->delete_records('townsquare_usersettings', ['id' => $record->id]); } } catch (Exception $e) { - $transaction->rollback($e); + // $transaction->rollback($e); return false; } } else { @@ -98,6 +96,7 @@ public static function record_usersettings($userid, $timefilterpast, $timefilter $record->completionletter = $completionletter; $record->postletter = $postletter; $DB->update_record('townsquare_usersettings', $record); + // $transaction->allow_commit(); return true; } } @@ -109,6 +108,7 @@ public static function record_usersettings($userid, $timefilterpast, $timefilter $record->completionletter = $completionletter; $record->postletter = $postletter; $DB->insert_record('townsquare_usersettings', $record); + //$transaction->allow_commit(); return true; } From 710a24f4c0c3d553158bbfed132be27ab3bbabbe Mon Sep 17 00:00:00 2001 From: Tamaro Walter Date: Fri, 15 Mar 2024 17:23:13 +0100 Subject: [PATCH 032/123] Save settings in Database works correctly --- amd/build/coursefilter.min.js.map | 2 +- amd/build/filtercontroller.min.js.map | 2 +- amd/build/letterfilter.min.js.map | 2 +- amd/build/postletter.min.js.map | 2 +- amd/build/timefilter.min.js.map | 2 +- amd/build/usersettings_save.min.js | 2 +- amd/build/usersettings_save.min.js.map | 2 +- amd/src/usersettings_save.js | 567 +++++++++--------- classes/contentcontroller.php | 245 ++++---- classes/townsquareevents.php | 786 +++++++++++++------------ db/services.php | 69 ++- externallib.php | 228 +++---- 12 files changed, 948 insertions(+), 961 deletions(-) diff --git a/amd/build/coursefilter.min.js.map b/amd/build/coursefilter.min.js.map index 4b6bcae..c40b743 100644 --- a/amd/build/coursefilter.min.js.map +++ b/amd/build/coursefilter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"coursefilter.min.js","sources":["../src/coursefilter.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 * Javascript for the course filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the course filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/coursefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant checkboxes.\nconst checkboxes = document.querySelectorAll('.ts_course_checkbox');\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n // Get the courseid associated with the checkbox\n const courseid = checkbox.id;\n\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.ts_timefilter_active.ts_letterfilter_active');\n\n // Loop through each letter mark it as \"active\" or not based on checkbox state and the letter id.\n letters.forEach(function(letter) {\n let letterCourseId = letter.querySelector('.townsquareletter_course').id;\n\n if (courseid === letterCourseId) {\n if (checkbox.checked) {\n letter.classList.add('ts_coursefilter_active'); // Mark the letter as \"active\".\n } else {\n letter.classList.remove('ts_coursefilter_active'); // Mark the letter as \"not active\".\n }\n }\n });\n });\n });\n}\n"],"names":["checkboxes","forEach","checkbox","addEventListener","courseid","id","document","querySelectorAll","letter","letterCourseId","querySelector","checked","classList","add","remove"],"mappings":"wJAiCIA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,iBAE1BC,SAAWF,SAASG,GAIVC,SAASC,iBAAiB,kEAGlCN,SAAQ,SAASO,YACjBC,eAAiBD,OAAOE,cAAc,4BAA4BL,GAElED,WAAaK,iBACTP,SAASS,QACTH,OAAOI,UAAUC,IAAI,0BAErBL,OAAOI,UAAUE,OAAO;;;;;;;;;;;MAvB1Cd,WAAaM,SAASC,iBAAiB"} \ No newline at end of file +{"version":3,"file":"coursefilter.min.js","sources":["../src/coursefilter.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\r\n//\r\n// Moodle is free software: you can redistribute it and/or modify\r\n// it under the terms of the GNU General Public License as published by\r\n// the Free Software Foundation, either version 3 of the License, or\r\n// (at your option) any later version.\r\n//\r\n// Moodle is distributed in the hope that it will be useful,\r\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n// GNU General Public License for more details.\r\n//\r\n// You should have received a copy of the GNU General Public License\r\n// along with Moodle. If not, see .\r\n\r\n/**\r\n * Javascript for the course filter\r\n *\r\n * This file implements 1 functionality:\r\n * - Checks the checkboxes of the course filter and hides content from courses if the checkbox is not checked.\r\n *\r\n * @module block_townsquare/coursefilter\r\n * @copyright 2024 Tamaro Walter\r\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\r\n */\r\n\r\n// Get the relevant checkboxes.\r\nconst checkboxes = document.querySelectorAll('.ts_course_checkbox');\r\n\r\n/**\r\n * Init function\r\n */\r\nexport function init() {\r\n checkboxes.forEach(function(checkbox) {\r\n checkbox.addEventListener('change', function() {\r\n // Get the courseid associated with the checkbox\r\n const courseid = checkbox.id;\r\n\r\n // Get all letters that are \"activated\".\r\n // Activated means that all filters accept the letter and want to show it.\r\n const letters = document.querySelectorAll('.townsquare_letter.ts_timefilter_active.ts_letterfilter_active');\r\n\r\n // Loop through each letter mark it as \"active\" or not based on checkbox state and the letter id.\r\n letters.forEach(function(letter) {\r\n let letterCourseId = letter.querySelector('.townsquareletter_course').id;\r\n\r\n if (courseid === letterCourseId) {\r\n if (checkbox.checked) {\r\n letter.classList.add('ts_coursefilter_active'); // Mark the letter as \"active\".\r\n } else {\r\n letter.classList.remove('ts_coursefilter_active'); // Mark the letter as \"not active\".\r\n }\r\n }\r\n });\r\n });\r\n });\r\n}\r\n"],"names":["checkboxes","forEach","checkbox","addEventListener","courseid","id","document","querySelectorAll","letter","letterCourseId","querySelector","checked","classList","add","remove"],"mappings":"wJAiCIA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,iBAE1BC,SAAWF,SAASG,GAIVC,SAASC,iBAAiB,kEAGlCN,SAAQ,SAASO,YACjBC,eAAiBD,OAAOE,cAAc,4BAA4BL,GAElED,WAAaK,iBACTP,SAASS,QACTH,OAAOI,UAAUC,IAAI,0BAErBL,OAAOI,UAAUE,OAAO;;;;;;;;;;;MAvB1Cd,WAAaM,SAASC,iBAAiB"} \ No newline at end of file diff --git a/amd/build/filtercontroller.min.js.map b/amd/build/filtercontroller.min.js.map index c6fdfb0..f9ce468 100644 --- a/amd/build/filtercontroller.min.js.map +++ b/amd/build/filtercontroller.min.js.map @@ -1 +1 @@ -{"version":3,"file":"filtercontroller.min.js","sources":["../src/filtercontroller.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 * Javascript to show/hide letters based on all filters\n *\n * This file implements 1 functionality:\n * - If the \"save settings\" button is pressed, store the settings in the database.\n *\n * @module block_townsquare/filtercontroller\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get all letters from townsquare.\nconst letters = document.querySelectorAll('.townsquare_letter');\n\n/**\n * Init function\n */\nexport function init() {\n // First step: activate every letter by adding the filter classes.\n letters.forEach(function(letter) {\n letter.classList.add('ts_coursefilter_active');\n letter.classList.add('ts_timefilter_active');\n letter.classList.add('ts_letterfilter_active');\n });\n\n // Add a mutation listener to each letter.\n letters.forEach(function(letter) {\n const observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(mutation) {\n if (mutation.attributeName === 'class') {\n // If the class of the letter changes, check if the letter should be shown or hidden.\n let coursefilter = letter.classList.contains('ts_coursefilter_active');\n let timefilter = letter.classList.contains('ts_timefilter_active');\n let letterfilter = letter.classList.contains('ts_letterfilter_active');\n\n // If all filters are active, show the letter.\n if (coursefilter && timefilter && letterfilter) {\n letter.style.display = 'block';\n } else {\n letter.style.display = 'none';\n }\n }\n });\n });\n\n observer.observe(letter, {attributes: true});\n });\n}\n"],"names":["letters","forEach","letter","classList","add","MutationObserver","mutations","mutation","attributeName","coursefilter","contains","timefilter","letterfilter","style","display","observe","attributes","document","querySelectorAll"],"mappings":"4JAkCIA,QAAQC,SAAQ,SAASC,QACrBA,OAAOC,UAAUC,IAAI,0BACrBF,OAAOC,UAAUC,IAAI,wBACrBF,OAAOC,UAAUC,IAAI,6BAIzBJ,QAAQC,SAAQ,SAASC,QACJ,IAAIG,kBAAiB,SAASC,WAC3CA,UAAUL,SAAQ,SAASM,aACQ,UAA3BA,SAASC,cAA2B,KAEhCC,aAAeP,OAAOC,UAAUO,SAAS,0BACzCC,WAAaT,OAAOC,UAAUO,SAAS,wBACvCE,aAAeV,OAAOC,UAAUO,SAAS,0BAIzCR,OAAOW,MAAMC,QADbL,cAAgBE,YAAcC,aACP,QAEA,cAM9BG,QAAQb,OAAQ,CAACc,YAAY;;;;;;;;;;;MAjCxChB,QAAUiB,SAASC,iBAAiB"} \ No newline at end of file +{"version":3,"file":"filtercontroller.min.js","sources":["../src/filtercontroller.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\r\n//\r\n// Moodle is free software: you can redistribute it and/or modify\r\n// it under the terms of the GNU General Public License as published by\r\n// the Free Software Foundation, either version 3 of the License, or\r\n// (at your option) any later version.\r\n//\r\n// Moodle is distributed in the hope that it will be useful,\r\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n// GNU General Public License for more details.\r\n//\r\n// You should have received a copy of the GNU General Public License\r\n// along with Moodle. If not, see .\r\n\r\n/**\r\n * Javascript to show/hide letters based on all filters\r\n *\r\n * This file implements 1 functionality:\r\n * - If the \"save settings\" button is pressed, store the settings in the database.\r\n *\r\n * @module block_townsquare/filtercontroller\r\n * @copyright 2024 Tamaro Walter\r\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\r\n */\r\n\r\n// Get all letters from townsquare.\r\nconst letters = document.querySelectorAll('.townsquare_letter');\r\n\r\n/**\r\n * Init function\r\n */\r\nexport function init() {\r\n // First step: activate every letter by adding the filter classes.\r\n letters.forEach(function(letter) {\r\n letter.classList.add('ts_coursefilter_active');\r\n letter.classList.add('ts_timefilter_active');\r\n letter.classList.add('ts_letterfilter_active');\r\n });\r\n\r\n // Add a mutation listener to each letter.\r\n letters.forEach(function(letter) {\r\n const observer = new MutationObserver(function(mutations) {\r\n mutations.forEach(function(mutation) {\r\n if (mutation.attributeName === 'class') {\r\n // If the class of the letter changes, check if the letter should be shown or hidden.\r\n let coursefilter = letter.classList.contains('ts_coursefilter_active');\r\n let timefilter = letter.classList.contains('ts_timefilter_active');\r\n let letterfilter = letter.classList.contains('ts_letterfilter_active');\r\n\r\n // If all filters are active, show the letter.\r\n if (coursefilter && timefilter && letterfilter) {\r\n letter.style.display = 'block';\r\n } else {\r\n letter.style.display = 'none';\r\n }\r\n }\r\n });\r\n });\r\n\r\n observer.observe(letter, {attributes: true});\r\n });\r\n}\r\n"],"names":["letters","forEach","letter","classList","add","MutationObserver","mutations","mutation","attributeName","coursefilter","contains","timefilter","letterfilter","style","display","observe","attributes","document","querySelectorAll"],"mappings":"4JAkCIA,QAAQC,SAAQ,SAASC,QACrBA,OAAOC,UAAUC,IAAI,0BACrBF,OAAOC,UAAUC,IAAI,wBACrBF,OAAOC,UAAUC,IAAI,6BAIzBJ,QAAQC,SAAQ,SAASC,QACJ,IAAIG,kBAAiB,SAASC,WAC3CA,UAAUL,SAAQ,SAASM,aACQ,UAA3BA,SAASC,cAA2B,KAEhCC,aAAeP,OAAOC,UAAUO,SAAS,0BACzCC,WAAaT,OAAOC,UAAUO,SAAS,wBACvCE,aAAeV,OAAOC,UAAUO,SAAS,0BAIzCR,OAAOW,MAAMC,QADbL,cAAgBE,YAAcC,aACP,QAEA,cAM9BG,QAAQb,OAAQ,CAACc,YAAY;;;;;;;;;;;MAjCxChB,QAAUiB,SAASC,iBAAiB"} \ No newline at end of file diff --git a/amd/build/letterfilter.min.js.map b/amd/build/letterfilter.min.js.map index 9f6c13e..a632bbe 100644 --- a/amd/build/letterfilter.min.js.map +++ b/amd/build/letterfilter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"letterfilter.min.js","sources":["../src/letterfilter.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 * Javascript for the letter filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the letter filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/letterfilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant checkboxes.\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n // Get the letter name associated with the checkbox.\n const lettername = checkbox.id;\n\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.' + lettername +\n '.ts_timefilter_active.ts_coursefilter_active');\n\n // Loop through each letter and hide/show based on checkbox state.\n letters.forEach(function(letter) {\n if (checkbox.checked) {\n letter.classList.add('ts_letterfilter_active'); // Mark the letter as \"active\".\n } else {\n letter.classList.remove('ts_letterfilter_active'); // Mark the letter as \"not active\".\n }\n });\n });\n });\n}\n"],"names":["checkboxes","forEach","checkbox","addEventListener","lettername","id","document","querySelectorAll","letter","checked","classList","add","remove"],"mappings":"wJAiCIA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,iBAE1BC,WAAaF,SAASG,GAIZC,SAASC,iBAAiB,sBAAwBH,WACxB,gDAGlCH,SAAQ,SAASO,QACjBN,SAASO,QACTD,OAAOE,UAAUC,IAAI,0BAErBH,OAAOE,UAAUE,OAAO;;;;;;;;;;;MArBtCZ,WAAaM,SAASC,iBAAiB"} \ No newline at end of file +{"version":3,"file":"letterfilter.min.js","sources":["../src/letterfilter.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\r\n//\r\n// Moodle is free software: you can redistribute it and/or modify\r\n// it under the terms of the GNU General Public License as published by\r\n// the Free Software Foundation, either version 3 of the License, or\r\n// (at your option) any later version.\r\n//\r\n// Moodle is distributed in the hope that it will be useful,\r\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n// GNU General Public License for more details.\r\n//\r\n// You should have received a copy of the GNU General Public License\r\n// along with Moodle. If not, see .\r\n\r\n/**\r\n * Javascript for the letter filter\r\n *\r\n * This file implements 1 functionality:\r\n * - Checks the checkboxes of the letter filter and hides content from courses if the checkbox is not checked.\r\n *\r\n * @module block_townsquare/letterfilter\r\n * @copyright 2024 Tamaro Walter\r\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\r\n */\r\n\r\n// Get the relevant checkboxes.\r\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\r\n\r\n/**\r\n * Init function\r\n */\r\nexport function init() {\r\n checkboxes.forEach(function(checkbox) {\r\n checkbox.addEventListener('change', function() {\r\n // Get the letter name associated with the checkbox.\r\n const lettername = checkbox.id;\r\n\r\n // Get all letters that are \"activated\".\r\n // Activated means that all filters accept the letter and want to show it.\r\n const letters = document.querySelectorAll('.townsquare_letter.' + lettername +\r\n '.ts_timefilter_active.ts_coursefilter_active');\r\n\r\n // Loop through each letter and hide/show based on checkbox state.\r\n letters.forEach(function(letter) {\r\n if (checkbox.checked) {\r\n letter.classList.add('ts_letterfilter_active'); // Mark the letter as \"active\".\r\n } else {\r\n letter.classList.remove('ts_letterfilter_active'); // Mark the letter as \"not active\".\r\n }\r\n });\r\n });\r\n });\r\n}\r\n"],"names":["checkboxes","forEach","checkbox","addEventListener","lettername","id","document","querySelectorAll","letter","checked","classList","add","remove"],"mappings":"wJAiCIA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,iBAE1BC,WAAaF,SAASG,GAIZC,SAASC,iBAAiB,sBAAwBH,WACxB,gDAGlCH,SAAQ,SAASO,QACjBN,SAASO,QACTD,OAAOE,UAAUC,IAAI,0BAErBH,OAAOE,UAAUE,OAAO;;;;;;;;;;;MArBtCZ,WAAaM,SAASC,iBAAiB"} \ No newline at end of file diff --git a/amd/build/postletter.min.js.map b/amd/build/postletter.min.js.map index 46772fc..aba2bad 100644 --- a/amd/build/postletter.min.js.map +++ b/amd/build/postletter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"postletter.min.js","sources":["../src/postletter.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\nimport {getString} from \"core/str\";\nimport {prefetchStrings} from 'core/prefetch';\n\n/**\n * Javascript for the post letter\n *\n * This file implements 2 functionalities:\n * - cuts posts that have many characters and shows a \"see more\" Button to see the whole text.\n * - Unnecessary

Tags from the Database are being replaced with line breaks to make the text more readable.\n *\n * @module block_townsquare/postletter\n * @copyright 2023 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nconst contentElements = document.getElementsByClassName('postletter_message');\nconst buttons = document.getElementsByClassName('townsquare_showmore');\nconst originalTexts = [];\n\nconst Selectors = {\n actions: {\n seemorebutton: '[data-action=\"block_townsquare/showmore_button\"]',\n },\n};\n\n/**\n * Init function\n *\n * The function can cut the text or extract paragraphs of a post.\n */\nexport function init() {\n contentElements.forEach(\n (element) => {\n // Replace all

within the text with simple line breaks..\n replaceParagraghTags(element);\n\n // Check if the text is too long.\n if (element.textContent.length >= 250) {\n // If the text is too long, cut it.\n originalTexts[element.id] = element.innerHTML;\n cutString(element);\n element.parentElement.insertAdjacentHTML('beforeend', '

');\n buttons[element.id].setAttribute('showmore', 'true');\n } else {\n // If the text is not too long, hide the show more button.\n buttons[element.id].style.display = \"none\";\n }\n }\n );\n\n // Get the strings for the show more/show less button.\n prefetchStrings('moodle', ['showmore', 'showless',]);\n\n // Add event listeners for the show more Button.\n addEventListener();\n}\n\n/**\n * Function to cut a String at a length of 250 characters.\n * The function does not cut within a word or after a space.\n * If the cutting point is within a word, the function searches for the next space and cuts there.\n * @param {object} element\n */\nfunction cutString(element) {\n let text = element.textContent;\n let index = 250;\n while (text.charAt(index) != \" \") {\n index++;\n }\n element.innerHTML = text.substring(0,index);\n}\n\n/**\n * Event listener for the show more/show less button.\n */\nconst addEventListener = () => {\n document.addEventListener('click', e => {\n if (e.target.closest(Selectors.actions.seemorebutton)) {\n // Get the id of the clicked element.\n let letterid = e.target.id;\n contentElements.forEach(\n (element) => {\n if (element.id == letterid) {\n if (buttons[letterid].getAttribute('showmore') == 'true') {\n element.innerHTML = originalTexts[letterid];\n changeButtonString(letterid, false);\n } else {\n cutString(element);\n changeButtonString(letterid, true);\n }\n }\n }\n );\n }\n });\n};\n\n/**\n * Changes the button strings.\n * @param {string} index Which button should be changed\n * @param {boolean} toshowmore a boolean that indicates if the button should show more or less\n */\nasync function changeButtonString(index, toshowmore) {\n if (toshowmore == true) {\n buttons[index].textContent = await getString('showmore', 'moodle');\n buttons[index].setAttribute('showmore', 'true');\n } else {\n buttons[index].textContent = await getString('showless', 'moodle');\n buttons[index].setAttribute('showmore', 'false');\n }\n}\n\n/**\n * Removes in a text all   and surrounding

tags excluding the first occurrence.\n *\n * Helper function to make post look better.\n * @param {object} element\n */\nasync function replaceParagraghTags(element) {\n // Identify and store the first

and

tags\n let message = element.innerHTML;\n const firstPTag = message.indexOf('

');\n const lastPTag = message.lastIndexOf('

');\n\n // Remove   and surrounding

tags excluding the first occurrence\n message = message.replace(/

 <\\/p>/g, '').replace(/ /g, '');\n\n // Replace

tags with
excluding the first occurrence\n message = message.substring(0, firstPTag + 3) +\n message.substring(firstPTag + 3, lastPTag).replace(/

/g, '
').replace(/<\\/p>/g, '') +\n message.substring(lastPTag);\n element.innerHTML = message;\n}"],"names":["contentElements","forEach","element","message","innerHTML","firstPTag","indexOf","lastPTag","lastIndexOf","replace","substring","replaceParagraghTags","textContent","length","originalTexts","id","cutString","parentElement","insertAdjacentHTML","buttons","setAttribute","style","display","addEventListener","document","getElementsByClassName","Selectors","seemorebutton","text","index","charAt","e","target","closest","letterid","getAttribute","changeButtonString","toshowmore"],"mappings":"gMA8CIA,gBAAgBC,SACXC,0BAsF2BA,aAE5BC,QAAUD,QAAQE,gBAChBC,UAAYF,QAAQG,QAAQ,OAC5BC,SAAWJ,QAAQK,YAAY,QAGrCL,QAAUA,QAAQM,QAAQ,kBAAmB,IAAIA,QAAQ,UAAW,IAGpEN,QAAUA,QAAQO,UAAU,EAAGL,UAAY,GACvCF,QAAQO,UAAUL,UAAY,EAAGE,UAAUE,QAAQ,OAAQ,QAAQA,QAAQ,SAAU,IACrFN,QAAQO,UAAUH,UACtBL,QAAQE,UAAYD,QAjGZQ,CAAqBT,SAGjBA,QAAQU,YAAYC,QAAU,KAE9BC,cAAcZ,QAAQa,IAAMb,QAAQE,UACpCY,UAAUd,SACVA,QAAQe,cAAcC,mBAAmB,YAAa,OACtDC,QAAQjB,QAAQa,IAAIK,aAAa,WAAY,SAG7CD,QAAQjB,QAAQa,IAAIM,MAAMC,QAAU,wCAMhC,SAAU,CAAC,WAAY,aAGvCC;;;;;;;;;;;;MAvCEvB,gBAAkBwB,SAASC,uBAAuB,sBAClDN,QAAUK,SAASC,uBAAuB,uBAC1CX,cAAgB,GAEhBY,kBACO,CACLC,cAAe,6DA0CdX,UAAUd,aACX0B,KAAO1B,QAAQU,YACfiB,MAAQ,SACiB,KAAtBD,KAAKE,OAAOD,QACfA,QAEJ3B,QAAQE,UAAYwB,KAAKlB,UAAU,EAAEmB,aAMnCN,iBAAmB,KACrBC,SAASD,iBAAiB,SAASQ,OAC3BA,EAAEC,OAAOC,QAAQP,kBAAkBC,eAAgB,KAE/CO,SAAWH,EAAEC,OAAOjB,GACxBf,gBAAgBC,SACXC,UACOA,QAAQa,IAAMmB,WACoC,QAA9Cf,QAAQe,UAAUC,aAAa,aAC/BjC,QAAQE,UAAYU,cAAcoB,UAClCE,mBAAmBF,UAAU,KAE7BlB,UAAUd,SACVkC,mBAAmBF,UAAU,4BAc1CE,mBAAmBP,MAAOQ,YACnB,GAAdA,YACAlB,QAAQU,OAAOjB,kBAAoB,kBAAU,WAAY,UACzDO,QAAQU,OAAOT,aAAa,WAAY,UAExCD,QAAQU,OAAOjB,kBAAoB,kBAAU,WAAY,UACzDO,QAAQU,OAAOT,aAAa,WAAY"} \ No newline at end of file +{"version":3,"file":"postletter.min.js","sources":["../src/postletter.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\r\n//\r\n// Moodle is free software: you can redistribute it and/or modify\r\n// it under the terms of the GNU General Public License as published by\r\n// the Free Software Foundation, either version 3 of the License, or\r\n// (at your option) any later version.\r\n//\r\n// Moodle is distributed in the hope that it will be useful,\r\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n// GNU General Public License for more details.\r\n//\r\n// You should have received a copy of the GNU General Public License\r\n// along with Moodle. If not, see .\r\n\r\nimport {getString} from \"core/str\";\r\nimport {prefetchStrings} from 'core/prefetch';\r\n\r\n/**\r\n * Javascript for the post letter\r\n *\r\n * This file implements 2 functionalities:\r\n * - cuts posts that have many characters and shows a \"see more\" Button to see the whole text.\r\n * - Unnecessary

Tags from the Database are being replaced with line breaks to make the text more readable.\r\n *\r\n * @module block_townsquare/postletter\r\n * @copyright 2023 Tamaro Walter\r\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\r\n */\r\n\r\nconst contentElements = document.getElementsByClassName('postletter_message');\r\nconst buttons = document.getElementsByClassName('townsquare_showmore');\r\nconst originalTexts = [];\r\n\r\nconst Selectors = {\r\n actions: {\r\n seemorebutton: '[data-action=\"block_townsquare/showmore_button\"]',\r\n },\r\n};\r\n\r\n/**\r\n * Init function\r\n *\r\n * The function can cut the text or extract paragraphs of a post.\r\n */\r\nexport function init() {\r\n contentElements.forEach(\r\n (element) => {\r\n // Replace all

within the text with simple line breaks..\r\n replaceParagraghTags(element);\r\n\r\n // Check if the text is too long.\r\n if (element.textContent.length >= 250) {\r\n // If the text is too long, cut it.\r\n originalTexts[element.id] = element.innerHTML;\r\n cutString(element);\r\n element.parentElement.insertAdjacentHTML('beforeend', '

');\r\n buttons[element.id].setAttribute('showmore', 'true');\r\n } else {\r\n // If the text is not too long, hide the show more button.\r\n buttons[element.id].style.display = \"none\";\r\n }\r\n }\r\n );\r\n\r\n // Get the strings for the show more/show less button.\r\n prefetchStrings('moodle', ['showmore', 'showless',]);\r\n\r\n // Add event listeners for the show more Button.\r\n addEventListener();\r\n}\r\n\r\n/**\r\n * Function to cut a String at a length of 250 characters.\r\n * The function does not cut within a word or after a space.\r\n * If the cutting point is within a word, the function searches for the next space and cuts there.\r\n * @param {object} element\r\n */\r\nfunction cutString(element) {\r\n let text = element.textContent;\r\n let index = 250;\r\n while (text.charAt(index) != \" \") {\r\n index++;\r\n }\r\n element.innerHTML = text.substring(0,index);\r\n}\r\n\r\n/**\r\n * Event listener for the show more/show less button.\r\n */\r\nconst addEventListener = () => {\r\n document.addEventListener('click', e => {\r\n if (e.target.closest(Selectors.actions.seemorebutton)) {\r\n // Get the id of the clicked element.\r\n let letterid = e.target.id;\r\n contentElements.forEach(\r\n (element) => {\r\n if (element.id == letterid) {\r\n if (buttons[letterid].getAttribute('showmore') == 'true') {\r\n element.innerHTML = originalTexts[letterid];\r\n changeButtonString(letterid, false);\r\n } else {\r\n cutString(element);\r\n changeButtonString(letterid, true);\r\n }\r\n }\r\n }\r\n );\r\n }\r\n });\r\n};\r\n\r\n/**\r\n * Changes the button strings.\r\n * @param {string} index Which button should be changed\r\n * @param {boolean} toshowmore a boolean that indicates if the button should show more or less\r\n */\r\nasync function changeButtonString(index, toshowmore) {\r\n if (toshowmore == true) {\r\n buttons[index].textContent = await getString('showmore', 'moodle');\r\n buttons[index].setAttribute('showmore', 'true');\r\n } else {\r\n buttons[index].textContent = await getString('showless', 'moodle');\r\n buttons[index].setAttribute('showmore', 'false');\r\n }\r\n}\r\n\r\n/**\r\n * Removes in a text all   and surrounding

tags excluding the first occurrence.\r\n *\r\n * Helper function to make post look better.\r\n * @param {object} element\r\n */\r\nasync function replaceParagraghTags(element) {\r\n // Identify and store the first

and

tags\r\n let message = element.innerHTML;\r\n const firstPTag = message.indexOf('

');\r\n const lastPTag = message.lastIndexOf('

');\r\n\r\n // Remove   and surrounding

tags excluding the first occurrence\r\n message = message.replace(/

 <\\/p>/g, '').replace(/ /g, '');\r\n\r\n // Replace

tags with
excluding the first occurrence\r\n message = message.substring(0, firstPTag + 3) +\r\n message.substring(firstPTag + 3, lastPTag).replace(/

/g, '
').replace(/<\\/p>/g, '') +\r\n message.substring(lastPTag);\r\n element.innerHTML = message;\r\n}"],"names":["contentElements","forEach","element","message","innerHTML","firstPTag","indexOf","lastPTag","lastIndexOf","replace","substring","replaceParagraghTags","textContent","length","originalTexts","id","cutString","parentElement","insertAdjacentHTML","buttons","setAttribute","style","display","addEventListener","document","getElementsByClassName","Selectors","seemorebutton","text","index","charAt","e","target","closest","letterid","getAttribute","changeButtonString","toshowmore"],"mappings":"gMA8CIA,gBAAgBC,SACXC,0BAsF2BA,aAE5BC,QAAUD,QAAQE,gBAChBC,UAAYF,QAAQG,QAAQ,OAC5BC,SAAWJ,QAAQK,YAAY,QAGrCL,QAAUA,QAAQM,QAAQ,kBAAmB,IAAIA,QAAQ,UAAW,IAGpEN,QAAUA,QAAQO,UAAU,EAAGL,UAAY,GACvCF,QAAQO,UAAUL,UAAY,EAAGE,UAAUE,QAAQ,OAAQ,QAAQA,QAAQ,SAAU,IACrFN,QAAQO,UAAUH,UACtBL,QAAQE,UAAYD,QAjGZQ,CAAqBT,SAGjBA,QAAQU,YAAYC,QAAU,KAE9BC,cAAcZ,QAAQa,IAAMb,QAAQE,UACpCY,UAAUd,SACVA,QAAQe,cAAcC,mBAAmB,YAAa,OACtDC,QAAQjB,QAAQa,IAAIK,aAAa,WAAY,SAG7CD,QAAQjB,QAAQa,IAAIM,MAAMC,QAAU,wCAMhC,SAAU,CAAC,WAAY,aAGvCC;;;;;;;;;;;;MAvCEvB,gBAAkBwB,SAASC,uBAAuB,sBAClDN,QAAUK,SAASC,uBAAuB,uBAC1CX,cAAgB,GAEhBY,kBACO,CACLC,cAAe,6DA0CdX,UAAUd,aACX0B,KAAO1B,QAAQU,YACfiB,MAAQ,SACiB,KAAtBD,KAAKE,OAAOD,QACfA,QAEJ3B,QAAQE,UAAYwB,KAAKlB,UAAU,EAAEmB,aAMnCN,iBAAmB,KACrBC,SAASD,iBAAiB,SAASQ,OAC3BA,EAAEC,OAAOC,QAAQP,kBAAkBC,eAAgB,KAE/CO,SAAWH,EAAEC,OAAOjB,GACxBf,gBAAgBC,SACXC,UACOA,QAAQa,IAAMmB,WACoC,QAA9Cf,QAAQe,UAAUC,aAAa,aAC/BjC,QAAQE,UAAYU,cAAcoB,UAClCE,mBAAmBF,UAAU,KAE7BlB,UAAUd,SACVkC,mBAAmBF,UAAU,4BAc1CE,mBAAmBP,MAAOQ,YACnB,GAAdA,YACAlB,QAAQU,OAAOjB,kBAAoB,kBAAU,WAAY,UACzDO,QAAQU,OAAOT,aAAa,WAAY,UAExCD,QAAQU,OAAOjB,kBAAoB,kBAAU,WAAY,UACzDO,QAAQU,OAAOT,aAAa,WAAY"} \ No newline at end of file diff --git a/amd/build/timefilter.min.js.map b/amd/build/timefilter.min.js.map index 238ee47..7e721f9 100644 --- a/amd/build/timefilter.min.js.map +++ b/amd/build/timefilter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"timefilter.min.js","sources":["../src/timefilter.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 * Javascript for the time filter\n *\n * This file implements 1 functionality:\n * - Checks, which of the radio buttons is pressed and filters the content based on the time.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant radio buttons.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Define to change the time span, an additional time span and the current time.\nlet currenttime;\nlet timestart;\nlet timeend;\nlet addstarttime;\nlet addendtime;\n\n/**\n * Init function\n */\nexport function init() {\n // Set the current time.\n currenttime = new Date().getTime() / 1000;\n\n // Add event listeners to the all kind of buttons.\n alltimeaddEventListener();\n futuretimeaddEventListener();\n pasttimeaddEventListener();\n}\n\n/**\n * Function to execute the filter\n * @param {int} starttime Start of time span for filtering of the current pressed button\n * @param {int} endtime End of time span for filtering of the current pressed\n * @param {int} addstarttime Start of time span for filtering of an additional radio button.\n * @param {int} addendtime End of time span for filtering of an additional radio button.\n * @param {boolean} buttonstate State of the radio button (true or false)\n */\nfunction executefilter(starttime, endtime, addstarttime, addendtime, buttonstate) {\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.ts_coursefilter_active.ts_letterfilter_active');\n\n // Loop through each letter and hide/show based on radiobutton state.\n letters.forEach(function(letter) {\n\n // Get the created time stamp of each letter.\n let lettertime = letter.querySelector('.townsquareletter_date').id;\n\n // If the radio button is checked and the letter is in the time span, activate it.\n if ((buttonstate && (lettertime >= starttime && lettertime <= endtime)) ||\n (lettertime >= addstarttime && lettertime <= addendtime)) {\n letter.classList.add('ts_timefilter_active'); // Mark the letter as \"active\".\n } else {\n letter.classList.remove('ts_timefilter_active'); // Mark the letter as \"not active\".\n }\n });\n}\n\n/**\n * Function to add event listeners to the all_time button.\n */\nfunction alltimeaddEventListener() {\n alltimebutton.forEach(function(button) {\n button.addEventListener('change', function() {\n // Set the time span to show all letters.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime + convertidtotime(button.id);\n addstarttime = 0;\n addendtime = 0;\n\n // Disable all other radio buttons that filter more specific times.\n futureradiobuttons.forEach(function(futureradiobutton) {\n futureradiobutton.checked = false;\n futureradiobutton.parentNode.classList.remove(\"active\");\n });\n pastradiobuttons.forEach(function(pastradiobutton) {\n pastradiobutton.checked = false;\n pastradiobutton.parentNode.classList.remove(\"active\");\n\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime,addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the future time radio buttons.\n */\nfunction futuretimeaddEventListener() {\n futureradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime;\n timeend = currenttime + convertidtotime(button.id);\n\n // Check if one past time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n pastradiobuttons.forEach(function(pastradiobutton) {\n if (pastradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime - convertidtotime(pastradiobutton.id);\n addendtime = currenttime;\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the past time radio buttons.\n */\nfunction pasttimeaddEventListener() {\n pastradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime;\n\n // Check if one future time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n futureradiobuttons.forEach(function(futureradiobutton) {\n if (futureradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime;\n addendtime = currenttime + convertidtotime(futureradiobutton.id);\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n"],"names":["currenttime","Date","getTime","alltimebutton","forEach","button","addEventListener","timestart","convertidtotime","id","timeend","addstarttime","addendtime","futureradiobuttons","futureradiobutton","checked","parentNode","classList","remove","pastradiobuttons","pastradiobutton","executefilter","contains","document","querySelectorAll","starttime","endtime","buttonstate","letter","lettertime","querySelector","add"],"mappings":"sJA2CIA,aAAc,IAAIC,MAAOC,UAAY,IAyCrCC,cAAcC,SAAQ,SAASC,QAC3BA,OAAOC,iBAAiB,UAAU,WAE9BC,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAC/CE,aAAe,EACfC,WAAa,EAGbC,mBAAmBT,SAAQ,SAASU,mBAChCA,kBAAkBC,SAAU,EAC5BD,kBAAkBE,WAAWC,UAAUC,OAAO,aAElDC,iBAAiBf,SAAQ,SAASgB,iBAC9BA,gBAAgBL,SAAU,EAC1BK,gBAAgBJ,WAAWC,UAAUC,OAAO,aAKhDG,cAAcd,UAAWG,QAASC,aAAaC,WAAYP,OAAOU,eAS1EF,mBAAmBT,SAAQ,SAASC,QAChCA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YACZU,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAG/CE,aAAe,EACfC,WAAa,EACbO,iBAAiBf,SAAQ,SAASgB,iBAC1BA,gBAAgBJ,WAAWC,UAAUK,SAAS,YAC9CX,aAAeX,YAAcQ,gBAAgBY,gBAAgBX,IAC7DG,WAAaZ,gBAKrBqB,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU,eAS3EI,iBAAiBf,SAAQ,SAASC,QAC9BA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAGVW,aAAe,EACfC,WAAa,EACbC,mBAAmBT,SAAQ,SAASU,mBAC5BA,kBAAkBE,WAAWC,UAAUK,SAAS,YAChDX,aAAeX,YACfY,WAAaZ,YAAcQ,gBAAgBM,kBAAkBL,QAKrEY,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU;;;;;;;;;;;MA7IzEZ,cAAgBoB,SAASC,iBAAiB,uBAC1CX,mBAAqBU,SAASC,iBAAiB,0BAC/CL,iBAAmBI,SAASC,iBAAiB,4BAG/CxB,YACAO,UACAG,QACAC,aACAC,oBAuBKS,cAAcI,UAAWC,QAASf,aAAcC,WAAYe,aAGjDJ,SAASC,iBAAiB,oEAGlCpB,SAAQ,SAASwB,YAGjBC,WAAaD,OAAOE,cAAc,0BAA0BrB,GAG3DkB,aAAgBE,YAAcJ,WAAaI,YAAcH,SACzDG,YAAclB,cAAgBkB,YAAcjB,WAC7CgB,OAAOX,UAAUc,IAAI,wBAErBH,OAAOX,UAAUC,OAAO,oCAuG3BV,gBAAgBC,WACdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM"} \ No newline at end of file +{"version":3,"file":"timefilter.min.js","sources":["../src/timefilter.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\r\n//\r\n// Moodle is free software: you can redistribute it and/or modify\r\n// it under the terms of the GNU General Public License as published by\r\n// the Free Software Foundation, either version 3 of the License, or\r\n// (at your option) any later version.\r\n//\r\n// Moodle is distributed in the hope that it will be useful,\r\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n// GNU General Public License for more details.\r\n//\r\n// You should have received a copy of the GNU General Public License\r\n// along with Moodle. If not, see .\r\n\r\n/**\r\n * Javascript for the time filter\r\n *\r\n * This file implements 1 functionality:\r\n * - Checks, which of the radio buttons is pressed and filters the content based on the time.\r\n *\r\n * @module block_townsquare/timefilter\r\n * @copyright 2024 Tamaro Walter\r\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\r\n */\r\n\r\n// Get the relevant radio buttons.\r\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\r\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\r\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\r\n\r\n// Define to change the time span, an additional time span and the current time.\r\nlet currenttime;\r\nlet timestart;\r\nlet timeend;\r\nlet addstarttime;\r\nlet addendtime;\r\n\r\n/**\r\n * Init function\r\n */\r\nexport function init() {\r\n // Set the current time.\r\n currenttime = new Date().getTime() / 1000;\r\n\r\n // Add event listeners to the all kind of buttons.\r\n alltimeaddEventListener();\r\n futuretimeaddEventListener();\r\n pasttimeaddEventListener();\r\n}\r\n\r\n/**\r\n * Function to execute the filter\r\n * @param {int} starttime Start of time span for filtering of the current pressed button\r\n * @param {int} endtime End of time span for filtering of the current pressed\r\n * @param {int} addstarttime Start of time span for filtering of an additional radio button.\r\n * @param {int} addendtime End of time span for filtering of an additional radio button.\r\n * @param {boolean} buttonstate State of the radio button (true or false)\r\n */\r\nfunction executefilter(starttime, endtime, addstarttime, addendtime, buttonstate) {\r\n // Get all letters that are \"activated\".\r\n // Activated means that all filters accept the letter and want to show it.\r\n const letters = document.querySelectorAll('.townsquare_letter.ts_coursefilter_active.ts_letterfilter_active');\r\n\r\n // Loop through each letter and hide/show based on radiobutton state.\r\n letters.forEach(function(letter) {\r\n\r\n // Get the created time stamp of each letter.\r\n let lettertime = letter.querySelector('.townsquareletter_date').id;\r\n\r\n // If the radio button is checked and the letter is in the time span, activate it.\r\n if ((buttonstate && (lettertime >= starttime && lettertime <= endtime)) ||\r\n (lettertime >= addstarttime && lettertime <= addendtime)) {\r\n letter.classList.add('ts_timefilter_active'); // Mark the letter as \"active\".\r\n } else {\r\n letter.classList.remove('ts_timefilter_active'); // Mark the letter as \"not active\".\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Function to add event listeners to the all_time button.\r\n */\r\nfunction alltimeaddEventListener() {\r\n alltimebutton.forEach(function(button) {\r\n button.addEventListener('change', function() {\r\n // Set the time span to show all letters.\r\n timestart = currenttime - convertidtotime(button.id);\r\n timeend = currenttime + convertidtotime(button.id);\r\n addstarttime = 0;\r\n addendtime = 0;\r\n\r\n // Disable all other radio buttons that filter more specific times.\r\n futureradiobuttons.forEach(function(futureradiobutton) {\r\n futureradiobutton.checked = false;\r\n futureradiobutton.parentNode.classList.remove(\"active\");\r\n });\r\n pastradiobuttons.forEach(function(pastradiobutton) {\r\n pastradiobutton.checked = false;\r\n pastradiobutton.parentNode.classList.remove(\"active\");\r\n\r\n });\r\n\r\n // Execute the filter function.\r\n executefilter(timestart, timeend, addstarttime,addendtime, button.checked);\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * Function to add event listeners to the future time radio buttons.\r\n */\r\nfunction futuretimeaddEventListener() {\r\n futureradiobuttons.forEach(function(button) {\r\n button.addEventListener('change', function() {\r\n // Disable the all_time button.\r\n alltimebutton.forEach(function(alltimebutton) {\r\n alltimebutton.checked = false;\r\n alltimebutton.parentNode.classList.remove('active');\r\n });\r\n\r\n // Set the time span based on the radiobutton id.\r\n timestart = currenttime;\r\n timeend = currenttime + convertidtotime(button.id);\r\n\r\n // Check if one past time button is checked. If yes, set the additional time span based on its id.\r\n addstarttime = 0;\r\n addendtime = 0;\r\n pastradiobuttons.forEach(function(pastradiobutton) {\r\n if (pastradiobutton.parentNode.classList.contains('active')) {\r\n addstarttime = currenttime - convertidtotime(pastradiobutton.id);\r\n addendtime = currenttime;\r\n }\r\n });\r\n\r\n // Execute the filter function.\r\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * Function to add event listeners to the past time radio buttons.\r\n */\r\nfunction pasttimeaddEventListener() {\r\n pastradiobuttons.forEach(function(button) {\r\n button.addEventListener('change', function() {\r\n // Disable the all_time button.\r\n alltimebutton.forEach(function(alltimebutton) {\r\n alltimebutton.checked = false;\r\n alltimebutton.parentNode.classList.remove('active');\r\n });\r\n\r\n // Set the time span based on the radiobutton id.\r\n timestart = currenttime - convertidtotime(button.id);\r\n timeend = currenttime;\r\n\r\n // Check if one future time button is checked. If yes, set the additional time span based on its id.\r\n addstarttime = 0;\r\n addendtime = 0;\r\n futureradiobuttons.forEach(function(futureradiobutton) {\r\n if (futureradiobutton.parentNode.classList.contains('active')) {\r\n addstarttime = currenttime;\r\n addendtime = currenttime + convertidtotime(futureradiobutton.id);\r\n }\r\n });\r\n\r\n // Execute the filter function.\r\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * Function to convert the radio button id to a useable time span.\r\n * @param {string} id The id of the radio button\r\n * @returns {number}\r\n */\r\nfunction convertidtotime(id) {\r\n switch(id) {\r\n case \"ts_time_all\":\r\n return 15778463;\r\n case \"ts_time_next_twodays\":\r\n case \"ts_time_last_twodays\":\r\n return 172800;\r\n case \"ts_time_next_fivedays\":\r\n case \"ts_time_last_fivedays\":\r\n return 432000;\r\n case \"ts_time_next_week\":\r\n case \"ts_time_last_week\":\r\n return 604800;\r\n case \"ts_time_next_month\":\r\n case \"ts_time_last_month\":\r\n return 2592000;\r\n }\r\n}\r\n"],"names":["currenttime","Date","getTime","alltimebutton","forEach","button","addEventListener","timestart","convertidtotime","id","timeend","addstarttime","addendtime","futureradiobuttons","futureradiobutton","checked","parentNode","classList","remove","pastradiobuttons","pastradiobutton","executefilter","contains","document","querySelectorAll","starttime","endtime","buttonstate","letter","lettertime","querySelector","add"],"mappings":"sJA2CIA,aAAc,IAAIC,MAAOC,UAAY,IAyCrCC,cAAcC,SAAQ,SAASC,QAC3BA,OAAOC,iBAAiB,UAAU,WAE9BC,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAC/CE,aAAe,EACfC,WAAa,EAGbC,mBAAmBT,SAAQ,SAASU,mBAChCA,kBAAkBC,SAAU,EAC5BD,kBAAkBE,WAAWC,UAAUC,OAAO,aAElDC,iBAAiBf,SAAQ,SAASgB,iBAC9BA,gBAAgBL,SAAU,EAC1BK,gBAAgBJ,WAAWC,UAAUC,OAAO,aAKhDG,cAAcd,UAAWG,QAASC,aAAaC,WAAYP,OAAOU,eAS1EF,mBAAmBT,SAAQ,SAASC,QAChCA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YACZU,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAG/CE,aAAe,EACfC,WAAa,EACbO,iBAAiBf,SAAQ,SAASgB,iBAC1BA,gBAAgBJ,WAAWC,UAAUK,SAAS,YAC9CX,aAAeX,YAAcQ,gBAAgBY,gBAAgBX,IAC7DG,WAAaZ,gBAKrBqB,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU,eAS3EI,iBAAiBf,SAAQ,SAASC,QAC9BA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAGVW,aAAe,EACfC,WAAa,EACbC,mBAAmBT,SAAQ,SAASU,mBAC5BA,kBAAkBE,WAAWC,UAAUK,SAAS,YAChDX,aAAeX,YACfY,WAAaZ,YAAcQ,gBAAgBM,kBAAkBL,QAKrEY,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU;;;;;;;;;;;MA7IzEZ,cAAgBoB,SAASC,iBAAiB,uBAC1CX,mBAAqBU,SAASC,iBAAiB,0BAC/CL,iBAAmBI,SAASC,iBAAiB,4BAG/CxB,YACAO,UACAG,QACAC,aACAC,oBAuBKS,cAAcI,UAAWC,QAASf,aAAcC,WAAYe,aAGjDJ,SAASC,iBAAiB,oEAGlCpB,SAAQ,SAASwB,YAGjBC,WAAaD,OAAOE,cAAc,0BAA0BrB,GAG3DkB,aAAgBE,YAAcJ,WAAaI,YAAcH,SACzDG,YAAclB,cAAgBkB,YAAcjB,WAC7CgB,OAAOX,UAAUc,IAAI,wBAErBH,OAAOX,UAAUC,OAAO,oCAuG3BV,gBAAgBC,WACdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM"} \ No newline at end of file diff --git a/amd/build/usersettings_save.min.js b/amd/build/usersettings_save.min.js index 542d40d..269e595 100644 --- a/amd/build/usersettings_save.min.js +++ b/amd/build/usersettings_save.min.js @@ -8,6 +8,6 @@ define("block_townsquare/usersettings_save",["exports","core/ajax"],(function(_e * @module block_townsquare/timefilter * @copyright 2024 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,settingsfromdb){settingsfromdb&&function(settingsfromdb){let timefilterfuture=settingsfromdb.timefilterfuture,timefilterpast=settingsfromdb.timefilterpast,basicletter=settingsfromdb.basicletter,completionletter=settingsfromdb.completionletter,postletter=settingsfromdb.postletter,futurebuttonid=converttimetoid(timefilterfuture,!0),pastbuttonid=converttimetoid(timefilterpast,!1);"ts_time_all"!==futurebuttonid?(futureradiobuttons.forEach((function(button){button.id==futurebuttonid&&(button.checked=!0,button.parentNode.classList.add("active"))})),pastradiobuttons.forEach((function(button){button.id==pastbuttonid&&(button.checked=!0,button.parentNode.classList.add("active"))}))):alltimebutton.forEach((function(button){button.id==futurebuttonid&&(button.checked=!0,button.parentNode.classList.add("active"))}));checkboxes.forEach((function(checkbox){let basiclettercheck="basicletter"===checkbox.id&&"1"===basicletter,completionlettercheck="completionletter"===checkbox.id&&"1"===completionletter,postlettercheck="postletter"===checkbox.id&&"1"===postletter;(basiclettercheck||completionlettercheck||postlettercheck)&&checkbox.click()}))}(settingsfromdb);savebutton.addEventListener("click",(async function(){let timespans=function(){let settings={timepast:0,timefuture:0},settingsset=!1;if(alltimebutton.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id),settings.timefuture=convertidtotime(button.id),settingsset=!0)})),settingsset)return settings;return futureradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timefuture=convertidtotime(button.id))})),pastradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id))})),settings}(),letterfilter=function(){let settings={basicletter:0,completionletter:0,postletter:0};return checkboxes.forEach((function(checkbox){if(checkbox.checked)switch(checkbox.id){case"basicletter":settings.basicletter=1;break;case"completionletter":settings.completionletter=1;break;case"postletter":settings.postletter=1}})),settings}();await async function(userid,timefilterpast,timefilterfuture,basicletter,completionletter,postletter){let result;window.alert("Settings here.");try{console.log({userid:parseInt(userid),timefilterpast:timefilterpast,timefilterfuture:timefilterfuture,basicletter:basicletter,completionletter:completionletter,postletter:postletter}),result=await _ajax.default.call([{methodname:"block_townsquare_record_usersettings",args:JSON.stringify({userid:parseInt(userid),timefilterpast:timefilterpast,timefilterfuture:timefilterfuture,basicletter:basicletter,completionletter:completionletter,postletter:postletter})}]),window.alert("im in a try")}catch(error){console.log(error)}window.alert("im done"),console.log(await result);return(await Promise.all(result)).forEach((response=>{console.log(response)})),result}(userid,timespans.timepast,timespans.timefuture,letterfilter.basicletter,letterfilter.completionletter,letterfilter.postletter)}))},_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};const savebutton=document.getElementById("ts_usersettings_savebutton"),alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button"),checkboxes=document.querySelectorAll(".ts_letter_checkbox");function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}function converttimetoid(time,future){switch(time){case"15778463":return"ts_time_all";case"172800":return future?"ts_time_next_twodays":"ts_time_past_twodays";case"432000":return future?"ts_time_next_fivedays":"ts_time_last_fivedays";case"604800":return future?"ts_time_next_week":"ts_time_last_week";case"2592000":return future?"ts_time_next_month":"ts_time_last_month"}}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,settingsfromdb){settingsfromdb&&function(settingsfromdb){let timefilterfuture=settingsfromdb.timefilterfuture,timefilterpast=settingsfromdb.timefilterpast,basicletter=settingsfromdb.basicletter,completionletter=settingsfromdb.completionletter,postletter=settingsfromdb.postletter,futurebuttonid=converttimetoid(timefilterfuture,!0),pastbuttonid=converttimetoid(timefilterpast,!1);"ts_time_all"!==futurebuttonid?(futureradiobuttons.forEach((function(button){button.id==futurebuttonid&&(button.checked=!0,button.parentNode.classList.add("active"))})),pastradiobuttons.forEach((function(button){button.id==pastbuttonid&&(button.checked=!0,button.parentNode.classList.add("active"))}))):alltimebutton.forEach((function(button){button.id==futurebuttonid&&(button.checked=!0,button.parentNode.classList.add("active"))}));checkboxes.forEach((function(checkbox){let basiclettercheck="basicletter"===checkbox.id&&"1"===basicletter,completionlettercheck="completionletter"===checkbox.id&&"1"===completionletter,postlettercheck="postletter"===checkbox.id&&"1"===postletter;(basiclettercheck||completionlettercheck||postlettercheck)&&checkbox.click()}))}(settingsfromdb);savebutton.addEventListener("click",(async function(){let timespans=function(){let settings={timepast:0,timefuture:0},settingsset=!1;if(alltimebutton.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id),settings.timefuture=convertidtotime(button.id),settingsset=!0)})),settingsset)return settings;return futureradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timefuture=convertidtotime(button.id))})),pastradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id))})),settings}(),letterfilter=function(){let settings={basicletter:0,completionletter:0,postletter:0};return checkboxes.forEach((function(checkbox){if(checkbox.checked)switch(checkbox.id){case"basicletter":settings.basicletter=1;break;case"completionletter":settings.completionletter=1;break;case"postletter":settings.postletter=1}})),settings}();await async function(userid,timefilterpast,timefilterfuture,basicletter,completionletter,postletter){let result;return result=await _ajax.default.call([{methodname:"block_townsquare_record_usersettings",args:{userid:parseInt(userid),timefilterpast:timefilterpast,timefilterfuture:timefilterfuture,basicletter:basicletter,completionletter:completionletter,postletter:postletter}}]),result}(userid,timespans.timepast,timespans.timefuture,letterfilter.basicletter,letterfilter.completionletter,letterfilter.postletter)}))},_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};const savebutton=document.getElementById("ts_usersettings_savebutton"),alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button"),checkboxes=document.querySelectorAll(".ts_letter_checkbox");function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}function converttimetoid(time,future){switch(time){case"15778463":return"ts_time_all";case"172800":return future?"ts_time_next_twodays":"ts_time_past_twodays";case"432000":return future?"ts_time_next_fivedays":"ts_time_last_fivedays";case"604800":return future?"ts_time_next_week":"ts_time_last_week";case"2592000":return future?"ts_time_next_month":"ts_time_last_month"}}})); //# sourceMappingURL=usersettings_save.min.js.map \ No newline at end of file diff --git a/amd/build/usersettings_save.min.js.map b/amd/build/usersettings_save.min.js.map index ef5e92d..2d74cdb 100644 --- a/amd/build/usersettings_save.min.js.map +++ b/amd/build/usersettings_save.min.js.map @@ -1 +1 @@ -{"version":3,"file":"usersettings_save.min.js","sources":["../src/usersettings_save.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 * Javascript to save the user settings in the database.\n *\n * This file implements 1 functionality:\n * - If the \"save settings\" button is pressed, store the settings in the database.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n// Get the save button for the user settings.\nconst savebutton = document.getElementById('ts_usersettings_savebutton');\n\n// Get the buttons from the time filter.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Get the checkboxes from the letter filter.\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n *\n * @param {number} userid The id of the current user.\n * @param {object} settingsfromdb The settings from the database, if there are any.\n */\nexport function init(userid, settingsfromdb) {\n // When the page is loaded, set the settings from the database.\n if (settingsfromdb) {\n executeusersettings(settingsfromdb);\n }\n\n // Add event listener to the save button.\n savebutton.addEventListener('click', async function() {\n\n // First step: collect the current settings.\n // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes.\n let timespans = collecttimefiltersettings();\n let letterfilter = collectletterfiltersettings();\n\n // Second step: store the usersettings in the database.\n await saveusersettings(userid, timespans['timepast'], timespans['timefuture'],\n letterfilter['basicletter'], letterfilter['completionletter'], letterfilter['postletter']);\n });\n}\n\n/**\n * Function to save the user settings in the database.\n * @param {number} userid\n * @param {number} timefilterpast\n * @param {number} timefilterfuture\n * @param {number} basicletter\n * @param {number} completionletter\n * @param {number} postletter\n * @returns {Promise<*>}\n */\nasync function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) {\n window.alert('Settings here.');\n let result ;\n try {\n console.log({\n userid: parseInt(userid),\n timefilterpast: timefilterpast,\n timefilterfuture: timefilterfuture,\n basicletter: basicletter,\n completionletter: completionletter,\n postletter: postletter\n });\n result = await Ajax.call([{\n methodname: 'block_townsquare_record_usersettings',\n args: JSON.stringify({\n userid: parseInt(userid),\n timefilterpast: timefilterpast,\n timefilterfuture: timefilterfuture,\n basicletter: basicletter,\n completionletter: completionletter,\n postletter: postletter\n }),\n }]);\n window.alert('im in a try');\n } catch (error) {\n console.log(error);\n }\n window.alert('im done');\n console.log(await result);\n const responses = await Promise.all(result);\n\n responses.forEach(response => {\n console.log(response);\n });\n return result;\n}\n\n/**\n * Function to execute existing user settings when loading the townsquare.\n * @param {Object} settingsfromdb\n */\nfunction executeusersettings(settingsfromdb) {\n // Load the settings.\n let timefilterfuture = settingsfromdb['timefilterfuture'];\n let timefilterpast = settingsfromdb['timefilterpast'];\n let basicletter = settingsfromdb['basicletter'];\n let completionletter = settingsfromdb['completionletter'];\n let postletter = settingsfromdb['postletter'];\n\n // First step: set the time filter settings.\n // Change the time into the correct radio button id.\n let futurebuttonid = converttimetoid(timefilterfuture, true);\n let pastbuttonid = converttimetoid(timefilterpast, false);\n\n // If the time span is a combination of past and future, go through the two radio buttons and click them to activate the filter.\n if (futurebuttonid !== \"ts_time_all\") {\n futureradiobuttons.forEach(function(button) {\n if (button.id == futurebuttonid) {\n button.checked = true;\n button.parentNode.classList.add('active');\n\n }\n });\n pastradiobuttons.forEach(function(button) {\n if (button.id == pastbuttonid) {\n button.checked = true;\n button.parentNode.classList.add('active');\n //button.parentNode.click();\n }\n });\n } else {\n // If the time span is the all time filter, click the all time button.\n alltimebutton.forEach(function(button) {\n if (button.id == futurebuttonid) {\n button.checked = true;\n button.parentNode.classList.add('active');\n // button.parentNode.click();\n }\n });\n }\n\n // Second step: set the letter filter settings.\n checkboxes.forEach(function(checkbox) {\n let basiclettercheck = checkbox.id === 'basicletter' && basicletter === \"1\";\n let completionlettercheck = checkbox.id === 'completionletter' && completionletter === \"1\";\n let postlettercheck = checkbox.id === 'postletter' && postletter === \"1\";\n\n if (basiclettercheck || completionlettercheck || postlettercheck) {\n checkbox.click();\n }\n });\n}\n\n/**\n * Function to collect the letter filter settings.\n * @returns {{basicletter: number, completionletter: number, postletter: number}}\n */\nfunction collectletterfiltersettings() {\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\n\n checkboxes.forEach(function(checkbox) {\n if (checkbox.checked) {\n switch(checkbox.id) {\n case \"basicletter\":\n settings['basicletter'] = 1;\n break;\n case \"completionletter\":\n settings['completionletter'] = 1;\n break;\n case \"postletter\":\n settings['postletter'] = 1;\n break;\n\n }\n }\n });\n // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit.\n return settings;\n}\n\n/**\n * Function to collect the time filter settings.\n * @returns {{timepast: number, timefuture: number}}\n */\nfunction collecttimefiltersettings() {\n let settings = { timepast: 0, timefuture: 0};\n let settingsset = false;\n\n // Get the relevant time spans of the time filter.\n // Check if the alltimebutton is set.\n alltimebutton.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n settings['timefuture'] = convertidtotime(button.id);\n settingsset = true;\n }\n });\n\n if (settingsset) {\n return settings;\n }\n\n // If the alltimebutton is not set, check which of the future/past buttons is set.\n futureradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timefuture'] = convertidtotime(button.id);\n }\n });\n\n pastradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n }\n });\n return settings;\n}\n\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n // TODO: Please use global functions if possible.\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n\n/**\n * Function to convert the time span to a radio button id.\n * @param {string} time\n * @param {boolean} future\n * @returns {string}\n */\nfunction converttimetoid(time, future) {\n switch (time) {\n case \"15778463\":\n return \"ts_time_all\";\n case \"172800\":\n if (future) {\n return \"ts_time_next_twodays\";\n }\n return \"ts_time_past_twodays\";\n case \"432000\":\n if (future) {\n return \"ts_time_next_fivedays\";\n }\n return \"ts_time_last_fivedays\";\n case \"604800\":\n if (future) {\n return \"ts_time_next_week\";\n }\n return \"ts_time_last_week\";\n case \"2592000\":\n if (future) {\n return \"ts_time_next_month\";\n\n }\n return \"ts_time_last_month\";\n }\n}\n"],"names":["userid","settingsfromdb","timefilterfuture","timefilterpast","basicletter","completionletter","postletter","futurebuttonid","converttimetoid","pastbuttonid","futureradiobuttons","forEach","button","id","checked","parentNode","classList","add","pastradiobuttons","alltimebutton","checkboxes","checkbox","basiclettercheck","completionlettercheck","postlettercheck","click","executeusersettings","savebutton","addEventListener","async","timespans","settings","timepast","timefuture","settingsset","contains","convertidtotime","collecttimefiltersettings","letterfilter","collectletterfiltersettings","result","window","alert","console","log","parseInt","Ajax","call","methodname","args","JSON","stringify","error","Promise","all","response","saveusersettings","document","getElementById","querySelectorAll","time","future"],"mappings":";;;;;;;;;;oFA6CqBA,OAAQC,gBAErBA,yBAqEqBA,oBAErBC,iBAAmBD,eAAc,iBACjCE,eAAiBF,eAAc,eAC/BG,YAAcH,eAAc,YAC5BI,iBAAmBJ,eAAc,iBACjCK,WAAaL,eAAc,WAI3BM,eAAiBC,gBAAgBN,kBAAkB,GACnDO,aAAeD,gBAAgBL,gBAAgB,GAG5B,gBAAnBI,gBACAG,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOC,IAAMN,iBACbK,OAAOE,SAAU,EACjBF,OAAOG,WAAWC,UAAUC,IAAI,cAIxCC,iBAAiBP,SAAQ,SAASC,QAC1BA,OAAOC,IAAMJ,eACbG,OAAOE,SAAU,EACjBF,OAAOG,WAAWC,UAAUC,IAAI,eAMxCE,cAAcR,SAAQ,SAASC,QACvBA,OAAOC,IAAMN,iBACbK,OAAOE,SAAU,EACjBF,OAAOG,WAAWC,UAAUC,IAAI,cAO5CG,WAAWT,SAAQ,SAASU,cACpBC,iBAAmC,gBAAhBD,SAASR,IAAwC,MAAhBT,YACpDmB,sBAAwC,qBAAhBF,SAASR,IAAkD,MAArBR,iBAC9DmB,gBAAkC,eAAhBH,SAASR,IAAsC,MAAfP,YAElDgB,kBAAoBC,uBAAyBC,kBAC7CH,SAASI,WAnHbC,CAAoBzB,gBAIxB0B,WAAWC,iBAAiB,SAASC,qBAI7BC,yBAgJJC,SAAW,CAAEC,SAAU,EAAGC,WAAY,GACtCC,aAAc,KAIlBf,cAAcR,SAAQ,SAASC,QACxBA,OAAOG,WAAWC,UAAUmB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgBxB,OAAOC,IAC9CkB,SAAQ,WAAiBK,gBAAgBxB,OAAOC,IAChDqB,aAAc,MAIjBA,mBACOH,gBAIXrB,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOG,WAAWC,UAAUmB,SAAS,YAErCJ,SAAQ,WAAiBK,gBAAgBxB,OAAOC,QAIxDK,iBAAiBP,SAAQ,SAASC,QAC1BA,OAAOG,WAAWC,UAAUmB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgBxB,OAAOC,QAG/CkB,SAhLaM,GACZC,4BAoHJP,SAAW,aAAgB,mBAAuB,aAAiB,UAEvEX,WAAWT,SAAQ,SAASU,aACpBA,SAASP,eACFO,SAASR,QACP,cACDkB,SAAQ,YAAkB,YAEzB,mBACDA,SAAQ,iBAAuB,YAE9B,aACDA,SAAQ,WAAiB,MAOlCA,SAvIgBQ,wBAkBKvC,OAAQG,eAAgBD,iBAAkBE,YAAaC,iBAAkBC,gBAEjGkC,OADJC,OAAOC,MAAM,sBAGTC,QAAQC,IAAI,CACR5C,OAAQ6C,SAAS7C,QACjBG,eAAgBA,eAChBD,iBAAkBA,iBAClBE,YAAaA,YACbC,iBAAkBA,iBAClBC,WAAYA,aAEhBkC,aAAeM,cAAKC,KAAK,CAAC,CACtBC,WAAY,uCACZC,KAAMC,KAAKC,UAAU,CACjBnD,OAAQ6C,SAAS7C,QACjBG,eAAgBA,eAChBD,iBAAkBA,iBAClBE,YAAaA,YACbC,iBAAkBA,iBAClBC,WAAYA,gBAGpBmC,OAAOC,MAAM,eACf,MAAOU,OACLT,QAAQC,IAAIQ,OAEhBX,OAAOC,MAAM,WACbC,QAAQC,UAAUJ,qBACMa,QAAQC,IAAId,SAE1B7B,SAAQ4C,WACdZ,QAAQC,IAAIW,aAETf,OAjDGgB,CAAiBxD,OAAQ8B,UAAS,SAAcA,UAAS,WACxCQ,aAAY,YAAiBA,aAAY,iBAAsBA,aAAY,0EAhCpGX,WAAa8B,SAASC,eAAe,8BAGrCvC,cAAgBsC,SAASE,iBAAiB,uBAC1CjD,mBAAqB+C,SAASE,iBAAiB,0BAC/CzC,iBAAmBuC,SAASE,iBAAiB,wBAG7CvC,WAAaqC,SAASE,iBAAiB,gCA4MpCvB,gBAAgBvB,WAEdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM,iBAUVL,gBAAgBoD,KAAMC,eACnBD,UACC,iBACM,kBACN,gBACGC,OACO,uBAEJ,2BACN,gBACGA,OACO,wBAEJ,4BACN,gBACGA,OACO,oBAEJ,wBACN,iBACGA,OACO,qBAGJ"} \ No newline at end of file +{"version":3,"file":"usersettings_save.min.js","sources":["../src/usersettings_save.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\r\n//\r\n// Moodle is free software: you can redistribute it and/or modify\r\n// it under the terms of the GNU General Public License as published by\r\n// the Free Software Foundation, either version 3 of the License, or\r\n// (at your option) any later version.\r\n//\r\n// Moodle is distributed in the hope that it will be useful,\r\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n// GNU General Public License for more details.\r\n//\r\n// You should have received a copy of the GNU General Public License\r\n// along with Moodle. If not, see .\r\n\r\n/**\r\n * Javascript to save the user settings in the database.\r\n *\r\n * This file implements 1 functionality:\r\n * - If the \"save settings\" button is pressed, store the settings in the database.\r\n *\r\n * @module block_townsquare/timefilter\r\n * @copyright 2024 Tamaro Walter\r\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\r\n */\r\n\r\nimport Ajax from 'core/ajax';\r\n\r\n// Get the save button for the user settings.\r\nconst savebutton = document.getElementById('ts_usersettings_savebutton');\r\n\r\n// Get the buttons from the time filter.\r\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\r\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\r\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\r\n\r\n// Get the checkboxes from the letter filter.\r\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\r\n\r\n/**\r\n * Init function\r\n *\r\n * @param {number} userid The id of the current user.\r\n * @param {object} settingsfromdb The settings from the database, if there are any.\r\n */\r\nexport function init(userid, settingsfromdb) {\r\n // When the page is loaded, set the settings from the database.\r\n if (settingsfromdb) {\r\n executeusersettings(settingsfromdb);\r\n }\r\n\r\n // Add event listener to the save button.\r\n savebutton.addEventListener('click', async function() {\r\n\r\n // First step: collect the current settings.\r\n // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes.\r\n let timespans = collecttimefiltersettings();\r\n let letterfilter = collectletterfiltersettings();\r\n\r\n // Second step: store the usersettings in the database.\r\n await saveusersettings(userid, timespans['timepast'], timespans['timefuture'],\r\n letterfilter['basicletter'], letterfilter['completionletter'], letterfilter['postletter']);\r\n });\r\n}\r\n\r\n/**\r\n * Function to save the user settings in the database.\r\n * @param {number} userid\r\n * @param {number} timefilterpast\r\n * @param {number} timefilterfuture\r\n * @param {number} basicletter\r\n * @param {number} completionletter\r\n * @param {number} postletter\r\n * @returns {Promise<*>}\r\n */\r\nasync function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) {\r\n let result ;\r\n result = await Ajax.call([{\r\n methodname: 'block_townsquare_record_usersettings',\r\n args: {\r\n userid: parseInt(userid),\r\n timefilterpast: timefilterpast,\r\n timefilterfuture: timefilterfuture,\r\n basicletter: basicletter,\r\n completionletter: completionletter,\r\n postletter: postletter\r\n },\r\n }]);\r\n return result;\r\n}\r\n\r\n/**\r\n * Function to execute existing user settings when loading the townsquare.\r\n * @param {Object} settingsfromdb\r\n */\r\nfunction executeusersettings(settingsfromdb) {\r\n // Load the settings.\r\n let timefilterfuture = settingsfromdb['timefilterfuture'];\r\n let timefilterpast = settingsfromdb['timefilterpast'];\r\n let basicletter = settingsfromdb['basicletter'];\r\n let completionletter = settingsfromdb['completionletter'];\r\n let postletter = settingsfromdb['postletter'];\r\n\r\n // First step: set the time filter settings.\r\n // Change the time into the correct radio button id.\r\n let futurebuttonid = converttimetoid(timefilterfuture, true);\r\n let pastbuttonid = converttimetoid(timefilterpast, false);\r\n\r\n // If the time span is a combination of past and future, go through the two radio buttons and click them to activate the filter.\r\n if (futurebuttonid !== \"ts_time_all\") {\r\n futureradiobuttons.forEach(function(button) {\r\n if (button.id == futurebuttonid) {\r\n button.checked = true;\r\n button.parentNode.classList.add('active');\r\n\r\n }\r\n });\r\n pastradiobuttons.forEach(function(button) {\r\n if (button.id == pastbuttonid) {\r\n button.checked = true;\r\n button.parentNode.classList.add('active');\r\n //button.parentNode.click();\r\n }\r\n });\r\n } else {\r\n // If the time span is the all time filter, click the all time button.\r\n alltimebutton.forEach(function(button) {\r\n if (button.id == futurebuttonid) {\r\n button.checked = true;\r\n button.parentNode.classList.add('active');\r\n // button.parentNode.click();\r\n }\r\n });\r\n }\r\n\r\n // Second step: set the letter filter settings.\r\n checkboxes.forEach(function(checkbox) {\r\n let basiclettercheck = checkbox.id === 'basicletter' && basicletter === \"1\";\r\n let completionlettercheck = checkbox.id === 'completionletter' && completionletter === \"1\";\r\n let postlettercheck = checkbox.id === 'postletter' && postletter === \"1\";\r\n\r\n if (basiclettercheck || completionlettercheck || postlettercheck) {\r\n checkbox.click();\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Function to collect the letter filter settings.\r\n * @returns {{basicletter: number, completionletter: number, postletter: number}}\r\n */\r\nfunction collectletterfiltersettings() {\r\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\r\n\r\n checkboxes.forEach(function(checkbox) {\r\n if (checkbox.checked) {\r\n switch(checkbox.id) {\r\n case \"basicletter\":\r\n settings['basicletter'] = 1;\r\n break;\r\n case \"completionletter\":\r\n settings['completionletter'] = 1;\r\n break;\r\n case \"postletter\":\r\n settings['postletter'] = 1;\r\n break;\r\n\r\n }\r\n }\r\n });\r\n // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit.\r\n return settings;\r\n}\r\n\r\n/**\r\n * Function to collect the time filter settings.\r\n * @returns {{timepast: number, timefuture: number}}\r\n */\r\nfunction collecttimefiltersettings() {\r\n let settings = { timepast: 0, timefuture: 0};\r\n let settingsset = false;\r\n\r\n // Get the relevant time spans of the time filter.\r\n // Check if the alltimebutton is set.\r\n alltimebutton.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timepast'] = convertidtotime(button.id);\r\n settings['timefuture'] = convertidtotime(button.id);\r\n settingsset = true;\r\n }\r\n });\r\n\r\n if (settingsset) {\r\n return settings;\r\n }\r\n\r\n // If the alltimebutton is not set, check which of the future/past buttons is set.\r\n futureradiobuttons.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timefuture'] = convertidtotime(button.id);\r\n }\r\n });\r\n\r\n pastradiobuttons.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timepast'] = convertidtotime(button.id);\r\n }\r\n });\r\n return settings;\r\n}\r\n\r\n\r\n/**\r\n * Function to convert the radio button id to a useable time span.\r\n * @param {string} id The id of the radio button\r\n * @returns {number}\r\n */\r\nfunction convertidtotime(id) {\r\n // TODO: Please use global functions if possible.\r\n switch(id) {\r\n case \"ts_time_all\":\r\n return 15778463;\r\n case \"ts_time_next_twodays\":\r\n case \"ts_time_last_twodays\":\r\n return 172800;\r\n case \"ts_time_next_fivedays\":\r\n case \"ts_time_last_fivedays\":\r\n return 432000;\r\n case \"ts_time_next_week\":\r\n case \"ts_time_last_week\":\r\n return 604800;\r\n case \"ts_time_next_month\":\r\n case \"ts_time_last_month\":\r\n return 2592000;\r\n }\r\n}\r\n\r\n/**\r\n * Function to convert the time span to a radio button id.\r\n * @param {string} time\r\n * @param {boolean} future\r\n * @returns {string}\r\n */\r\nfunction converttimetoid(time, future) {\r\n switch (time) {\r\n case \"15778463\":\r\n return \"ts_time_all\";\r\n case \"172800\":\r\n if (future) {\r\n return \"ts_time_next_twodays\";\r\n }\r\n return \"ts_time_past_twodays\";\r\n case \"432000\":\r\n if (future) {\r\n return \"ts_time_next_fivedays\";\r\n }\r\n return \"ts_time_last_fivedays\";\r\n case \"604800\":\r\n if (future) {\r\n return \"ts_time_next_week\";\r\n }\r\n return \"ts_time_last_week\";\r\n case \"2592000\":\r\n if (future) {\r\n return \"ts_time_next_month\";\r\n\r\n }\r\n return \"ts_time_last_month\";\r\n }\r\n}\r\n"],"names":["userid","settingsfromdb","timefilterfuture","timefilterpast","basicletter","completionletter","postletter","futurebuttonid","converttimetoid","pastbuttonid","futureradiobuttons","forEach","button","id","checked","parentNode","classList","add","pastradiobuttons","alltimebutton","checkboxes","checkbox","basiclettercheck","completionlettercheck","postlettercheck","click","executeusersettings","savebutton","addEventListener","async","timespans","settings","timepast","timefuture","settingsset","contains","convertidtotime","collecttimefiltersettings","letterfilter","collectletterfiltersettings","result","Ajax","call","methodname","args","parseInt","saveusersettings","document","getElementById","querySelectorAll","time","future"],"mappings":";;;;;;;;;;oFA6CqBA,OAAQC,gBAErBA,yBAgDqBA,oBAErBC,iBAAmBD,eAAc,iBACjCE,eAAiBF,eAAc,eAC/BG,YAAcH,eAAc,YAC5BI,iBAAmBJ,eAAc,iBACjCK,WAAaL,eAAc,WAI3BM,eAAiBC,gBAAgBN,kBAAkB,GACnDO,aAAeD,gBAAgBL,gBAAgB,GAG5B,gBAAnBI,gBACAG,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOC,IAAMN,iBACbK,OAAOE,SAAU,EACjBF,OAAOG,WAAWC,UAAUC,IAAI,cAIxCC,iBAAiBP,SAAQ,SAASC,QAC1BA,OAAOC,IAAMJ,eACbG,OAAOE,SAAU,EACjBF,OAAOG,WAAWC,UAAUC,IAAI,eAMxCE,cAAcR,SAAQ,SAASC,QACvBA,OAAOC,IAAMN,iBACbK,OAAOE,SAAU,EACjBF,OAAOG,WAAWC,UAAUC,IAAI,cAO5CG,WAAWT,SAAQ,SAASU,cACpBC,iBAAmC,gBAAhBD,SAASR,IAAwC,MAAhBT,YACpDmB,sBAAwC,qBAAhBF,SAASR,IAAkD,MAArBR,iBAC9DmB,gBAAkC,eAAhBH,SAASR,IAAsC,MAAfP,YAElDgB,kBAAoBC,uBAAyBC,kBAC7CH,SAASI,WA9FbC,CAAoBzB,gBAIxB0B,WAAWC,iBAAiB,SAASC,qBAI7BC,yBA2HJC,SAAW,CAAEC,SAAU,EAAGC,WAAY,GACtCC,aAAc,KAIlBf,cAAcR,SAAQ,SAASC,QACxBA,OAAOG,WAAWC,UAAUmB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgBxB,OAAOC,IAC9CkB,SAAQ,WAAiBK,gBAAgBxB,OAAOC,IAChDqB,aAAc,MAIjBA,mBACOH,gBAIXrB,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOG,WAAWC,UAAUmB,SAAS,YAErCJ,SAAQ,WAAiBK,gBAAgBxB,OAAOC,QAIxDK,iBAAiBP,SAAQ,SAASC,QAC1BA,OAAOG,WAAWC,UAAUmB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgBxB,OAAOC,QAG/CkB,SA3JaM,GACZC,4BA+FJP,SAAW,aAAgB,mBAAuB,aAAiB,UAEvEX,WAAWT,SAAQ,SAASU,aACpBA,SAASP,eACFO,SAASR,QACP,cACDkB,SAAQ,YAAkB,YAEzB,mBACDA,SAAQ,iBAAuB,YAE9B,aACDA,SAAQ,WAAiB,MAOlCA,SAlHgBQ,wBAkBKvC,OAAQG,eAAgBD,iBAAkBE,YAAaC,iBAAkBC,gBACjGkC,cACJA,aAAeC,cAAKC,KAAK,CAAC,CACtBC,WAAY,uCACZC,KAAM,CACF5C,OAAQ6C,SAAS7C,QACjBG,eAAgBA,eAChBD,iBAAkBA,iBAClBE,YAAaA,YACbC,iBAAkBA,iBAClBC,WAAYA,eAGbkC,OA5BGM,CAAiB9C,OAAQ8B,UAAS,SAAcA,UAAS,WACxCQ,aAAY,YAAiBA,aAAY,iBAAsBA,aAAY,0EAhCpGX,WAAaoB,SAASC,eAAe,8BAGrC7B,cAAgB4B,SAASE,iBAAiB,uBAC1CvC,mBAAqBqC,SAASE,iBAAiB,0BAC/C/B,iBAAmB6B,SAASE,iBAAiB,wBAG7C7B,WAAa2B,SAASE,iBAAiB,gCAuLpCb,gBAAgBvB,WAEdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM,iBAUVL,gBAAgB0C,KAAMC,eACnBD,UACC,iBACM,kBACN,gBACGC,OACO,uBAEJ,2BACN,gBACGA,OACO,wBAEJ,4BACN,gBACGA,OACO,oBAEJ,wBACN,iBACGA,OACO,qBAGJ"} \ No newline at end of file diff --git a/amd/src/usersettings_save.js b/amd/src/usersettings_save.js index 2eee4ac..08f1b72 100644 --- a/amd/src/usersettings_save.js +++ b/amd/src/usersettings_save.js @@ -1,294 +1,273 @@ -// 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 . - -/** - * Javascript to save the user settings in the database. - * - * This file implements 1 functionality: - * - If the "save settings" button is pressed, store the settings in the database. - * - * @module block_townsquare/timefilter - * @copyright 2024 Tamaro Walter - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -import Ajax from 'core/ajax'; - -// Get the save button for the user settings. -const savebutton = document.getElementById('ts_usersettings_savebutton'); - -// Get the buttons from the time filter. -const alltimebutton = document.querySelectorAll('.ts_all_time_button'); -const futureradiobuttons = document.querySelectorAll('.ts_future_time_button'); -const pastradiobuttons = document.querySelectorAll('.ts_past_time_button'); - -// Get the checkboxes from the letter filter. -const checkboxes = document.querySelectorAll('.ts_letter_checkbox'); - -/** - * Init function - * - * @param {number} userid The id of the current user. - * @param {object} settingsfromdb The settings from the database, if there are any. - */ -export function init(userid, settingsfromdb) { - // When the page is loaded, set the settings from the database. - if (settingsfromdb) { - executeusersettings(settingsfromdb); - } - - // Add event listener to the save button. - savebutton.addEventListener('click', async function() { - - // First step: collect the current settings. - // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes. - let timespans = collecttimefiltersettings(); - let letterfilter = collectletterfiltersettings(); - - // Second step: store the usersettings in the database. - await saveusersettings(userid, timespans['timepast'], timespans['timefuture'], - letterfilter['basicletter'], letterfilter['completionletter'], letterfilter['postletter']); - }); -} - -/** - * Function to save the user settings in the database. - * @param {number} userid - * @param {number} timefilterpast - * @param {number} timefilterfuture - * @param {number} basicletter - * @param {number} completionletter - * @param {number} postletter - * @returns {Promise<*>} - */ -async function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) { - window.alert('Settings here.'); - let result ; - try { - console.log({ - userid: parseInt(userid), - timefilterpast: timefilterpast, - timefilterfuture: timefilterfuture, - basicletter: basicletter, - completionletter: completionletter, - postletter: postletter - }); - result = await Ajax.call([{ - methodname: 'block_townsquare_record_usersettings', - args: JSON.stringify({ - userid: parseInt(userid), - timefilterpast: timefilterpast, - timefilterfuture: timefilterfuture, - basicletter: basicletter, - completionletter: completionletter, - postletter: postletter - }), - }]); - window.alert('im in a try'); - } catch (error) { - console.log(error); - } - window.alert('im done'); - console.log(await result); - const responses = await Promise.all(result); - - responses.forEach(response => { - console.log(response); - }); - return result; -} - -/** - * Function to execute existing user settings when loading the townsquare. - * @param {Object} settingsfromdb - */ -function executeusersettings(settingsfromdb) { - // Load the settings. - let timefilterfuture = settingsfromdb['timefilterfuture']; - let timefilterpast = settingsfromdb['timefilterpast']; - let basicletter = settingsfromdb['basicletter']; - let completionletter = settingsfromdb['completionletter']; - let postletter = settingsfromdb['postletter']; - - // First step: set the time filter settings. - // Change the time into the correct radio button id. - let futurebuttonid = converttimetoid(timefilterfuture, true); - let pastbuttonid = converttimetoid(timefilterpast, false); - - // If the time span is a combination of past and future, go through the two radio buttons and click them to activate the filter. - if (futurebuttonid !== "ts_time_all") { - futureradiobuttons.forEach(function(button) { - if (button.id == futurebuttonid) { - button.checked = true; - button.parentNode.classList.add('active'); - - } - }); - pastradiobuttons.forEach(function(button) { - if (button.id == pastbuttonid) { - button.checked = true; - button.parentNode.classList.add('active'); - //button.parentNode.click(); - } - }); - } else { - // If the time span is the all time filter, click the all time button. - alltimebutton.forEach(function(button) { - if (button.id == futurebuttonid) { - button.checked = true; - button.parentNode.classList.add('active'); - // button.parentNode.click(); - } - }); - } - - // Second step: set the letter filter settings. - checkboxes.forEach(function(checkbox) { - let basiclettercheck = checkbox.id === 'basicletter' && basicletter === "1"; - let completionlettercheck = checkbox.id === 'completionletter' && completionletter === "1"; - let postlettercheck = checkbox.id === 'postletter' && postletter === "1"; - - if (basiclettercheck || completionlettercheck || postlettercheck) { - checkbox.click(); - } - }); -} - -/** - * Function to collect the letter filter settings. - * @returns {{basicletter: number, completionletter: number, postletter: number}} - */ -function collectletterfiltersettings() { - let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 }; - - checkboxes.forEach(function(checkbox) { - if (checkbox.checked) { - switch(checkbox.id) { - case "basicletter": - settings['basicletter'] = 1; - break; - case "completionletter": - settings['completionletter'] = 1; - break; - case "postletter": - settings['postletter'] = 1; - break; - - } - } - }); - // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit. - return settings; -} - -/** - * Function to collect the time filter settings. - * @returns {{timepast: number, timefuture: number}} - */ -function collecttimefiltersettings() { - let settings = { timepast: 0, timefuture: 0}; - let settingsset = false; - - // Get the relevant time spans of the time filter. - // Check if the alltimebutton is set. - alltimebutton.forEach(function(button) { - if (button.parentNode.classList.contains('active')) { - // Get the timespan. - settings['timepast'] = convertidtotime(button.id); - settings['timefuture'] = convertidtotime(button.id); - settingsset = true; - } - }); - - if (settingsset) { - return settings; - } - - // If the alltimebutton is not set, check which of the future/past buttons is set. - futureradiobuttons.forEach(function(button) { - if (button.parentNode.classList.contains('active')) { - // Get the timespan. - settings['timefuture'] = convertidtotime(button.id); - } - }); - - pastradiobuttons.forEach(function(button) { - if (button.parentNode.classList.contains('active')) { - // Get the timespan. - settings['timepast'] = convertidtotime(button.id); - } - }); - return settings; -} - - -/** - * Function to convert the radio button id to a useable time span. - * @param {string} id The id of the radio button - * @returns {number} - */ -function convertidtotime(id) { - // TODO: Please use global functions if possible. - switch(id) { - case "ts_time_all": - return 15778463; - case "ts_time_next_twodays": - case "ts_time_last_twodays": - return 172800; - case "ts_time_next_fivedays": - case "ts_time_last_fivedays": - return 432000; - case "ts_time_next_week": - case "ts_time_last_week": - return 604800; - case "ts_time_next_month": - case "ts_time_last_month": - return 2592000; - } -} - -/** - * Function to convert the time span to a radio button id. - * @param {string} time - * @param {boolean} future - * @returns {string} - */ -function converttimetoid(time, future) { - switch (time) { - case "15778463": - return "ts_time_all"; - case "172800": - if (future) { - return "ts_time_next_twodays"; - } - return "ts_time_past_twodays"; - case "432000": - if (future) { - return "ts_time_next_fivedays"; - } - return "ts_time_last_fivedays"; - case "604800": - if (future) { - return "ts_time_next_week"; - } - return "ts_time_last_week"; - case "2592000": - if (future) { - return "ts_time_next_month"; - - } - return "ts_time_last_month"; - } -} +// 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 . + +/** + * Javascript to save the user settings in the database. + * + * This file implements 1 functionality: + * - If the "save settings" button is pressed, store the settings in the database. + * + * @module block_townsquare/timefilter + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import Ajax from 'core/ajax'; + +// Get the save button for the user settings. +const savebutton = document.getElementById('ts_usersettings_savebutton'); + +// Get the buttons from the time filter. +const alltimebutton = document.querySelectorAll('.ts_all_time_button'); +const futureradiobuttons = document.querySelectorAll('.ts_future_time_button'); +const pastradiobuttons = document.querySelectorAll('.ts_past_time_button'); + +// Get the checkboxes from the letter filter. +const checkboxes = document.querySelectorAll('.ts_letter_checkbox'); + +/** + * Init function + * + * @param {number} userid The id of the current user. + * @param {object} settingsfromdb The settings from the database, if there are any. + */ +export function init(userid, settingsfromdb) { + // When the page is loaded, set the settings from the database. + if (settingsfromdb) { + executeusersettings(settingsfromdb); + } + + // Add event listener to the save button. + savebutton.addEventListener('click', async function() { + + // First step: collect the current settings. + // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes. + let timespans = collecttimefiltersettings(); + let letterfilter = collectletterfiltersettings(); + + // Second step: store the usersettings in the database. + await saveusersettings(userid, timespans['timepast'], timespans['timefuture'], + letterfilter['basicletter'], letterfilter['completionletter'], letterfilter['postletter']); + }); +} + +/** + * Function to save the user settings in the database. + * @param {number} userid + * @param {number} timefilterpast + * @param {number} timefilterfuture + * @param {number} basicletter + * @param {number} completionletter + * @param {number} postletter + * @returns {Promise<*>} + */ +async function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) { + let result ; + result = await Ajax.call([{ + methodname: 'block_townsquare_record_usersettings', + args: { + userid: parseInt(userid), + timefilterpast: timefilterpast, + timefilterfuture: timefilterfuture, + basicletter: basicletter, + completionletter: completionletter, + postletter: postletter + }, + }]); + return result; +} + +/** + * Function to execute existing user settings when loading the townsquare. + * @param {Object} settingsfromdb + */ +function executeusersettings(settingsfromdb) { + // Load the settings. + let timefilterfuture = settingsfromdb['timefilterfuture']; + let timefilterpast = settingsfromdb['timefilterpast']; + let basicletter = settingsfromdb['basicletter']; + let completionletter = settingsfromdb['completionletter']; + let postletter = settingsfromdb['postletter']; + + // First step: set the time filter settings. + // Change the time into the correct radio button id. + let futurebuttonid = converttimetoid(timefilterfuture, true); + let pastbuttonid = converttimetoid(timefilterpast, false); + + // If the time span is a combination of past and future, go through the two radio buttons and click them to activate the filter. + if (futurebuttonid !== "ts_time_all") { + futureradiobuttons.forEach(function(button) { + if (button.id == futurebuttonid) { + button.checked = true; + button.parentNode.classList.add('active'); + + } + }); + pastradiobuttons.forEach(function(button) { + if (button.id == pastbuttonid) { + button.checked = true; + button.parentNode.classList.add('active'); + //button.parentNode.click(); + } + }); + } else { + // If the time span is the all time filter, click the all time button. + alltimebutton.forEach(function(button) { + if (button.id == futurebuttonid) { + button.checked = true; + button.parentNode.classList.add('active'); + // button.parentNode.click(); + } + }); + } + + // Second step: set the letter filter settings. + checkboxes.forEach(function(checkbox) { + let basiclettercheck = checkbox.id === 'basicletter' && basicletter === "1"; + let completionlettercheck = checkbox.id === 'completionletter' && completionletter === "1"; + let postlettercheck = checkbox.id === 'postletter' && postletter === "1"; + + if (basiclettercheck || completionlettercheck || postlettercheck) { + checkbox.click(); + } + }); +} + +/** + * Function to collect the letter filter settings. + * @returns {{basicletter: number, completionletter: number, postletter: number}} + */ +function collectletterfiltersettings() { + let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 }; + + checkboxes.forEach(function(checkbox) { + if (checkbox.checked) { + switch(checkbox.id) { + case "basicletter": + settings['basicletter'] = 1; + break; + case "completionletter": + settings['completionletter'] = 1; + break; + case "postletter": + settings['postletter'] = 1; + break; + + } + } + }); + // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit. + return settings; +} + +/** + * Function to collect the time filter settings. + * @returns {{timepast: number, timefuture: number}} + */ +function collecttimefiltersettings() { + let settings = { timepast: 0, timefuture: 0}; + let settingsset = false; + + // Get the relevant time spans of the time filter. + // Check if the alltimebutton is set. + alltimebutton.forEach(function(button) { + if (button.parentNode.classList.contains('active')) { + // Get the timespan. + settings['timepast'] = convertidtotime(button.id); + settings['timefuture'] = convertidtotime(button.id); + settingsset = true; + } + }); + + if (settingsset) { + return settings; + } + + // If the alltimebutton is not set, check which of the future/past buttons is set. + futureradiobuttons.forEach(function(button) { + if (button.parentNode.classList.contains('active')) { + // Get the timespan. + settings['timefuture'] = convertidtotime(button.id); + } + }); + + pastradiobuttons.forEach(function(button) { + if (button.parentNode.classList.contains('active')) { + // Get the timespan. + settings['timepast'] = convertidtotime(button.id); + } + }); + return settings; +} + + +/** + * Function to convert the radio button id to a useable time span. + * @param {string} id The id of the radio button + * @returns {number} + */ +function convertidtotime(id) { + // TODO: Please use global functions if possible. + switch(id) { + case "ts_time_all": + return 15778463; + case "ts_time_next_twodays": + case "ts_time_last_twodays": + return 172800; + case "ts_time_next_fivedays": + case "ts_time_last_fivedays": + return 432000; + case "ts_time_next_week": + case "ts_time_last_week": + return 604800; + case "ts_time_next_month": + case "ts_time_last_month": + return 2592000; + } +} + +/** + * Function to convert the time span to a radio button id. + * @param {string} time + * @param {boolean} future + * @returns {string} + */ +function converttimetoid(time, future) { + switch (time) { + case "15778463": + return "ts_time_all"; + case "172800": + if (future) { + return "ts_time_next_twodays"; + } + return "ts_time_past_twodays"; + case "432000": + if (future) { + return "ts_time_next_fivedays"; + } + return "ts_time_last_fivedays"; + case "604800": + if (future) { + return "ts_time_next_week"; + } + return "ts_time_last_week"; + case "2592000": + if (future) { + return "ts_time_next_month"; + + } + return "ts_time_last_month"; + } +} diff --git a/classes/contentcontroller.php b/classes/contentcontroller.php index 3fc5aaf..111d292 100644 --- a/classes/contentcontroller.php +++ b/classes/contentcontroller.php @@ -1,122 +1,123 @@ -. - -/** - * Letter Controller of block_townsquare - * - * @package block_townsquare - * @copyright 2023 Tamaro Walter - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -namespace block_townsquare; - -/** - * Letter Controller Class. - * - * This Class controls access to the townsquareevents class. It retrieves all important events and builds the letters. - * - * @package block_townsquare - * @copyright 2023 Tamaro Walter - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class contentcontroller { - - /** @var object Class to retrieve events */ - public object $townsquareevents; - - /** @var array events that are relevant for the townsquare */ - public array $events; - - /** @var array letters and other content that will be shown to the user */ - public array $content; - - /** @var array courses that show content in townsquare (not the same as enrolled courses) */ - public array $courses; - - /** - * Constructor for the controller. - */ - public function __construct() { - $this->townsquareevents = new townsquareevents(); - $this->courses = []; - $this->content = $this->build_content(); - } - - // Core functions. - - /** - * Builds the content from events. - * @return array - */ - public function build_content(): array { - $this->events = $this->townsquareevents->get_all_events_sorted(); - - $orientationmarkerset = false; - $index = 0; - $time = time(); - $appearedcourses = []; - // Build a letter for each event. - foreach ($this->events as $event) { - // Display a orientation marker on the current date between the other events. - if (!$orientationmarkerset && isset($event->eventtype) && ( - ($event->eventtype != 'post' && $event->timestart <= $time) || - ($event->eventtype == 'post' && $event->postcreated <= $time))) { - - $orientationmarkerset = true; - $tempcontent = new orientation_marker($index, $time); - $this->content[$index] = $tempcontent->export_data(); - $index++; - continue; - } - if (isset($event->eventtype) && $event->eventtype == 'post') { - $templetter = new letter\post_letter($index, $event); - } else if (isset($event->eventtype) && $event->eventtype == 'expectcompletionon') { - $templetter = new letter\activitycompletion_letter($index, $event); - } else { - $templetter = new letter\letter($index, $event->courseid, $event->modulename, $event->instancename, - $event->name, $event->timestart, $event->coursemoduleid); - } - $this->content[$index] = $templetter->export_letter(); - - // Collect the courses shown in the townsquare to be able to filter them afterwards. - if (!array_key_exists($this->content[$index]['courseid'], $appearedcourses)) { - $this->courses[] = ['courseid' => $this->content[$index]['courseid'], - 'coursename' => $this->content[$index]['coursename'], ]; - $appearedcourses[$event->courseid] = true; - } - $index++; - } - return $this->content; - } - - // Getter. - - /** - * Getter for the content - * @return array - */ - public function get_content():array { - return $this->content; - } - - /** - * Getter for the events - * @return array - */ - public function get_events():array { - return $this->events; - } -} +. + +/** + * Letter Controller of block_townsquare + * + * @package block_townsquare + * @copyright 2023 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace block_townsquare; + +/** + * Letter Controller Class. + * + * This Class controls access to the townsquareevents class. It retrieves all important events and builds the letters. + * + * @package block_townsquare + * @copyright 2023 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class contentcontroller { + + /** @var object Class to retrieve events */ + public object $townsquareevents; + + /** @var array events that are relevant for the townsquare */ + public array $events; + + /** @var array letters and other content that will be shown to the user */ + public array $content; + + /** @var array courses that show content in townsquare (not the same as enrolled courses) */ + public array $courses; + + /** + * Constructor for the controller. + */ + public function __construct() { + $this->townsquareevents = new townsquareevents(); + $this->courses = []; + $this->content = []; + $this->build_content(); + } + + // Core functions. + + /** + * Builds the content from events. + * @return array + */ + public function build_content(): array { + $this->events = $this->townsquareevents->get_all_events_sorted(); + + $orientationmarkerset = false; + $index = 0; + $time = time(); + $appearedcourses = []; + // Build a letter for each event. + foreach ($this->events as $event) { + // Display a orientation marker on the current date between the other events. + if (!$orientationmarkerset && isset($event->eventtype) && ( + ($event->eventtype != 'post' && $event->timestart <= $time) || + ($event->eventtype == 'post' && $event->postcreated <= $time))) { + + $orientationmarkerset = true; + $tempcontent = new orientation_marker($index, $time); + $this->content[$index] = $tempcontent->export_data(); + $index++; + continue; + } + if (isset($event->eventtype) && $event->eventtype == 'post') { + $templetter = new letter\post_letter($index, $event); + } else if (isset($event->eventtype) && $event->eventtype == 'expectcompletionon') { + $templetter = new letter\activitycompletion_letter($index, $event); + } else { + $templetter = new letter\letter($index, $event->courseid, $event->modulename, $event->instancename, + $event->name, $event->timestart, $event->coursemoduleid); + } + $this->content[$index] = $templetter->export_letter(); + + // Collect the courses shown in the townsquare to be able to filter them afterwards. + if (!array_key_exists($this->content[$index]['courseid'], $appearedcourses)) { + $this->courses[] = ['courseid' => $this->content[$index]['courseid'], + 'coursename' => $this->content[$index]['coursename'], ]; + $appearedcourses[$event->courseid] = true; + } + $index++; + } + return $this->content; + } + + // Getter. + + /** + * Getter for the content + * @return array + */ + public function get_content():array { + return $this->content; + } + + /** + * Getter for the events + * @return array + */ + public function get_events():array { + return $this->events; + } +} diff --git a/classes/townsquareevents.php b/classes/townsquareevents.php index d614861..cfc8e2a 100644 --- a/classes/townsquareevents.php +++ b/classes/townsquareevents.php @@ -1,389 +1,397 @@ -. - -/** - * Class to get relevant events from courses the user is enrolled to.. - * - * @package block_townsquare - * @copyright 2023 Tamaro Walter - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -namespace block_townsquare; - -defined('MOODLE_INTERNAL') || die(); - -use context_module; -use dml_exception; - -global $CFG; -require_once($CFG->dirroot . '/calendar/lib.php'); -require_once($CFG->dirroot . '/blocks/townsquare/locallib.php'); -/** - * Class to get events and posts that will be shown in the townsquare block.. - * - * @package block_townsquare - * @copyright 2023 Tamaro Walter - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class townsquareevents { - - /** @var int timestamp of the current time */ - public int $timenow; - - /** @var int timestamp from where the events should be searched */ - public int $timestart; - - /** @var int timestamp until where the events should be searched */ - public int $timeend; - - /** @var array ids of the courses where the events should be searched */ - public array $courses; - - /** - * Constructor of the townsquareevents class. - * Events will be searched in the timespan of 6 months in the past and 6 months in the future. - */ - public function __construct() { - $this->timenow = time(); - $this->timestart = $this->timenow - 15768000; - $this->timeend = $this->timenow + 15768000; - $this->courses = $this->get_courses(); - } - - /** - * Retrieves calendar and post events, merges and sorts them. - * @return array - */ - public function get_all_events_sorted(): array { - $calendarevents = $this->get_calendarevents(); - $postevents = $this->get_postevents(); - - // Merge the events in a sorted order. - $events = []; - $numberofevents = count($calendarevents) + count($postevents); - for ($i = 0; $i < $numberofevents; $i++) { - if (current($calendarevents) && current($postevents)) { - if (current($calendarevents)->timestart > current($postevents)->postcreated) { - $events[$i] = current($calendarevents); - next($calendarevents); - } else { - $events[$i] = current($postevents); - next($postevents); - } - } else if (current($calendarevents)) { - $events[$i] = current($calendarevents); - next($calendarevents); - } else { - $events[$i] = current($postevents); - next($postevents); - } - } - - return $events; - } - - /** - * Function to get events from that are in the calendar for the current user. - * - * The events are sorted in descending order by time created (newest event first) - * @return array - */ - public function get_calendarevents(): array { - global $DB; - - // Get all events from the last six months and the next six months. - $calendarevents = $this->get_events_from_db($this->timestart, $this->timeend, $this->courses); - - // Filter the events and add the coursemoduleid. - foreach ($calendarevents as $calendarevent) { - // Filter out events that are not relevant for the user. - if ($this->filter_availability($calendarevent) || - ($calendarevent->modulename == "assign" && $this->filter_assignment($calendarevent)) || - ($calendarevent->eventtype == "expectcompletionon" && $this->filter_activitycompletions($calendarevent))) { - unset($calendarevents[$calendarevent->id]); - continue; - } - - // Add the name of the instance to the event. - $calendarevent->instancename = $DB->get_field($calendarevent->modulename, 'name', ['id' => $calendarevent->instance]); - } - - return $calendarevents; - } - - /** - * Function to get the newest posts from modules like the forum or moodleoverflow. - * - * The events are sorted in descending order by time created (newest event first) - * @return array; - */ - public function get_postevents(): array { - global $DB; - - $forumposts = []; - $moodleoverflowposts = []; - - // Check which modules are installed and activated and get their data. - if ($DB->get_record('modules', ['name' => 'forum', 'visible' => 1])) { - $forumposts = $this->get_posts_from_db('forum', $this->courses, $this->timestart); - } - - if ($DB->get_record('modules', ['name' => 'moodleoverflow', 'visible' => 1])) { - $moodleoverflowposts = $this->get_posts_from_db('moodleoverflow', $this->courses, $this->timestart); - } - - if (empty($forumposts) && empty($moodleoverflowposts)) { - return []; - } - - // Merge the posts in a sorted order. While merging, filter out irrelevant posts and add relevant attributes if necessary. - $posts = []; - $numberofposts = count($forumposts) + count($moodleoverflowposts); - reset($forumposts); - reset($moodleoverflowposts); - for ($i = 0; $i < $numberofposts; $i++) { - // Filter unavailable posts. - // Iterate until the first post that is available. Decrement the number of posts each time a post is filtered. - while (current($forumposts) && $this->filter_availability(current($forumposts))) { - next($forumposts); - $numberofposts--; - } - while (current($moodleoverflowposts) && $this->filter_availability(current($moodleoverflowposts))) { - next($moodleoverflowposts); - $numberofposts--; - } - // If there no posts left after filtering, break. - if ($i >= $numberofposts) { - break; - } - - // Merge. - if (current($forumposts) && current($moodleoverflowposts)) { - if (current($forumposts)->postcreated > current($moodleoverflowposts)->postcreated) { - $posts[$i] = current($forumposts); - next($forumposts); - } else { - $posts[$i] = current($moodleoverflowposts); - next($moodleoverflowposts); - } - } else if (current($forumposts)) { - $posts[$i] = current($forumposts); - next($forumposts); - } else { - $posts[$i] = current($moodleoverflowposts); - next($moodleoverflowposts); - } - } - - // Add an event type to the posts and add the anonymous setting to the moodleoverflow posts. Then return it. - return $posts; - } - - // Helper functions. - - /** - * Searches for posts in the forum or moodleoverflow module. - * The sql query makes sure that the modules are installed and available.. - * This is a helper function for get_postevents(). - * @param string $modulename The name of the module, is 'forum' or 'moodleoverflow'. - * @param array $courses The ids of the courses where the posts should be searched. - * @param int $timestart The timestamp from where the posts should be searched. - * @return array - */ - private function get_posts_from_db($modulename, $courses, $timestart): array { - global $DB; - // Prepare params for sql statement. - list($insqlcourses, $inparamscourses) = $DB->get_in_or_equal($courses, SQL_PARAMS_NAMED); - $params = ['courses' => $courses, 'timestart' => $timestart] + $inparamscourses; - // Set begin of sql statement. - $begin = "SELECT (ROW_NUMBER() OVER (ORDER BY posts.id)) AS row_num, "; - - // Set the select part of the sql that is always the same. - $middle = "'post' AS eventtype, - cm.id AS coursemoduleid, - cm.availability AS availability, - module.name AS instancename, - discuss.course AS courseid, - discuss.userid AS discussionuserid, - discuss.name AS discussionsubject, - u.firstname AS postuserfirstname, - u.lastname AS postuserlastname, - posts.id AS postid, - posts.discussion AS postdiscussion, - posts.parent AS postparentid, - posts.userid AS postuserid, - posts.created AS postcreated, - posts.message AS postmessage "; - - // Extend the strings for the 2 module cases. - if ($modulename == 'forum') { - $begin .= "'forum' AS modulename, module.id AS instanceid,"; - $middle .= "FROM {forum_posts} posts - JOIN {forum_discussions} discuss ON discuss.id = posts.discussion - JOIN {forum} module ON module.id = discuss.forum - JOIN {modules} modules ON modules.name = 'forum' "; - - } else if ($modulename == 'moodleoverflow') { - $begin .= "'moodleoverflow' AS modulename, module.id AS instanceid, module.anonymous AS anonymoussetting, "; - $middle .= "FROM {moodleoverflow_posts} posts - JOIN {moodleoverflow_discussions} discuss ON discuss.id = posts.discussion - JOIN {moodleoverflow} module ON module.id = discuss.moodleoverflow - JOIN {modules} modules ON modules.name = 'moodleoverflow' "; - } - - // Extension of the middle string. - $middle .= "JOIN {user} u ON u.id = posts.userid - JOIN {course_modules} cm ON (cm.course = module.course AND cm.module = modules.id - AND cm.instance = module.id) "; - - // Set the where clause of the string. - $end = "WHERE discuss.course $insqlcourses - AND posts.created > :timestart - AND cm.visible = 1 - AND modules.visible = 1 - ORDER BY posts.created DESC;"; - - // Concatenate all strings. - $sql = $begin . $middle . $end; - - // Get all posts. - return $DB->get_records_sql($sql, $params); - } - - /** - * Searches for events in the events table, that are relevant to the timeline. - * This is a helper function for get_calendarevents(). - * @param int $timestart The time from where the events should be searched. Not equal to timestart in the database events table. - * @param int $timeend The time until where the events should be searched. - * @param array $courses The ids of the courses where the events should be searched. - * @return array - * @throws dml_exception - */ - private function get_events_from_db($timestart, $timeend, $courses): array { - global $DB; - - // Due to compatability reasons, only events from supported modules are shown. - // Supported modules are: core modules and custom additional modules. - $coremodules = ['assign', 'book', 'chat', 'choice', 'data', 'feedback', 'folder', 'forum', 'glossary', 'h5pactivity', - 'imscp', 'label', 'lesson', 'lti', 'page', 'quiz', 'resource', 'scorm', 'survey', 'url', 'wiki', 'workshop', ]; - $additionalmodules = ['moodleoverflow', 'ratingallocate']; - $modules = $coremodules + $additionalmodules; - - // Prepare params for sql statement. - list($insqlcourses, $inparamscourses) = $DB->get_in_or_equal($courses, SQL_PARAMS_NAMED); - list($insqlmodules, $inparamsmodules) = $DB->get_in_or_equal($modules, SQL_PARAMS_NAMED); - $params = ['timestart' => $timestart, 'timeduration' => $timestart, - 'timeend' => $timeend, 'courses' => $courses, ] + $inparamscourses + $inparamsmodules; - - // Set the sql statement. - $sql = "SELECT e.id, e.name, e.courseid, cm.id AS coursemoduleid, cm.availability AS availability, e.groupid, e.userid, - e.modulename, e.instance, e.eventtype, e.timestart, e.visible - FROM {event} e - JOIN {modules} m ON e.modulename = m.name - JOIN {course_modules} cm ON (cm.course = e.courseid AND cm.module = m.id AND cm.instance = e.instance) - WHERE (e.timestart >= :timestart OR e.timestart+e.timeduration > :timeduration) - AND e.timestart <= :timeend - AND e.courseid $insqlcourses - AND e.modulename $insqlmodules - AND m.visible = 1 - AND (e.name NOT LIKE '" .'0'. "' AND e.eventtype NOT LIKE '" .'0'. "' ) - AND (e.instance <> 0 AND e.visible = 1) - ORDER BY e.timestart DESC"; - - // Get all events. - return $DB->get_records_sql($sql, $params); - } - - /** - * Gets the id of all courses where the current user is enrolled - * @return array - */ - private function get_courses(): array { - global $USER; - - $enrolledcourses = enrol_get_all_users_courses($USER->id, true); - $courses = []; - foreach ($enrolledcourses as $enrolledcourse) { - $courses[] = $enrolledcourse->id; - } - - return $courses; - } - - /** - * Filter that checks if the event needs to be filtered out for the current user because it is unavailable. - * Applies to restriction that are defined in the module setting (restrict access). - * @param object $event The event that is checked. - * @return bool true if the event needs to filtered out, false if not. - */ - private function filter_availability($event): bool { - // If there is no restriction defined, the event is available. - if ($event->availability == null) { - return false; - } - - // If there is a restriction, check if it applies to the user. - $modinfo = get_fast_modinfo($event->courseid); - $moduleinfo = $modinfo->get_cm($event->coursemoduleid); - if ($moduleinfo->uservisible) { - return false; - } - - return true; - } - - /** - * Filter that checks if the event needs to be filtered out for the current user. - * Applies to assignment events. - * @param object $calendarevent calendarevent that is checked - * @return bool true if the event needs to filtered out, false if not. - */ - private function filter_assignment($calendarevent): bool { - global $DB; - $assignment = $DB->get_record('assign', ['id' => $calendarevent->instance]); - - // Check if the assign is longer than a week closed. - $overduecheck = $calendarevent->eventtype == "due" && $this->timenow >= ($calendarevent->timestart + 604800); - - // Check if the user is someone without grading capability. - $nogradecapabilitycheck = $calendarevent->eventtype == "gradingdue" && !has_capability('mod/assign:grade', - context_module::instance($calendarevent->coursemoduleid)); - // Check if the assignment is not open yet. - $stillclosedcheck = $assignment->allowsubmissionsfromdate >= $this->timenow; - - if ($overduecheck || $nogradecapabilitycheck || $stillclosedcheck) { - return true; - } - return false; - } - - /** - * Filter that checks if the event needs to be filtered out for the current user. - * Applies to activity completion events. - * @param object $calendarevent calendarevent that is checked - * @return bool true if the event needs to filtered out, false if not. - */ - private function filter_activitycompletions($calendarevent): bool { - global $DB, $USER; - if ($completionstatus = $DB->get_record('course_modules_completion', - ['coursemoduleid' => $calendarevent->coursemoduleid, 'userid' => $USER->id])) { - if ($completionstatus->completionstate != 0) { - return true; - } - } - return false; - } -} +. + +/** + * Class to get relevant events from courses the user is enrolled to.. + * + * @package block_townsquare + * @copyright 2023 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace block_townsquare; + +defined('MOODLE_INTERNAL') || die(); + +use context_module; +use dml_exception; + +global $CFG; +require_once($CFG->dirroot . '/calendar/lib.php'); +require_once($CFG->dirroot . '/blocks/townsquare/locallib.php'); +/** + * Class to get events and posts that will be shown in the townsquare block.. + * + * @package block_townsquare + * @copyright 2023 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class townsquareevents { + + /** @var int timestamp of the current time */ + public int $timenow; + + /** @var int timestamp from where the events should be searched */ + public int $timestart; + + /** @var int timestamp until where the events should be searched */ + public int $timeend; + + /** @var array ids of the courses where the events should be searched */ + public array $courses; + + /** + * Constructor of the townsquareevents class. + * Events will be searched in the timespan of 6 months in the past and 6 months in the future. + */ + public function __construct() { + $this->timenow = time(); + $this->timestart = $this->timenow - 15768000; + $this->timeend = $this->timenow + 15768000; + $this->courses = $this->get_courses(); + } + + /** + * Retrieves calendar and post events, merges and sorts them. + * @return array + */ + public function get_all_events_sorted(): array { + $calendarevents = $this->get_calendarevents(); + $postevents = $this->get_postevents(); + + // Merge the events in a sorted order. + $events = []; + $numberofevents = count($calendarevents) + count($postevents); + for ($i = 0; $i < $numberofevents; $i++) { + if (current($calendarevents) && current($postevents)) { + if (current($calendarevents)->timestart > current($postevents)->postcreated) { + $events[$i] = current($calendarevents); + next($calendarevents); + } else { + $events[$i] = current($postevents); + next($postevents); + } + } else if (current($calendarevents)) { + $events[$i] = current($calendarevents); + next($calendarevents); + } else { + $events[$i] = current($postevents); + next($postevents); + } + } + + return $events; + } + + /** + * Function to get events from that are in the calendar for the current user. + * + * The events are sorted in descending order by time created (newest event first) + * @return array + */ + public function get_calendarevents(): array { + global $DB; + + // Get all events from the last six months and the next six months. + $calendarevents = $this->get_events_from_db($this->timestart, $this->timeend, $this->courses); + + // Filter the events and add the coursemoduleid. + foreach ($calendarevents as $calendarevent) { + // Filter out events that are not relevant for the user. + if ($this->filter_availability($calendarevent) || + ($calendarevent->modulename == "assign" && $this->filter_assignment($calendarevent)) || + ($calendarevent->eventtype == "expectcompletionon" && $this->filter_activitycompletions($calendarevent))) { + unset($calendarevents[$calendarevent->id]); + continue; + } + + // Add the name of the instance to the event. + $calendarevent->instancename = $DB->get_field($calendarevent->modulename, 'name', ['id' => $calendarevent->instance]); + } + + return $calendarevents; + } + + /** + * Function to get the newest posts from modules like the forum or moodleoverflow. + * + * The events are sorted in descending order by time created (newest event first) + * @return array; + */ + public function get_postevents(): array { + global $DB; + + $forumposts = []; + $moodleoverflowposts = []; + + // Check which modules are installed and activated and get their data. + if ($DB->get_record('modules', ['name' => 'forum', 'visible' => 1])) { + $forumposts = $this->get_posts_from_db('forum', $this->courses, $this->timestart); + } + + if ($DB->get_record('modules', ['name' => 'moodleoverflow', 'visible' => 1])) { + $moodleoverflowposts = $this->get_posts_from_db('moodleoverflow', $this->courses, $this->timestart); + } + + if (empty($forumposts) && empty($moodleoverflowposts)) { + return []; + } + + // Merge the posts in a sorted order. While merging, filter out irrelevant posts and add relevant attributes if necessary. + $posts = []; + $numberofposts = count($forumposts) + count($moodleoverflowposts); + reset($forumposts); + reset($moodleoverflowposts); + for ($i = 0; $i < $numberofposts; $i++) { + // Filter unavailable posts. + // Iterate until the first post that is available. Decrement the number of posts each time a post is filtered. + while (current($forumposts) && $this->filter_availability(current($forumposts))) { + next($forumposts); + $numberofposts--; + } + while (current($moodleoverflowposts) && $this->filter_availability(current($moodleoverflowposts))) { + next($moodleoverflowposts); + $numberofposts--; + } + // If there no posts left after filtering, break. + if ($i >= $numberofposts) { + break; + } + + // Merge. + if (current($forumposts) && current($moodleoverflowposts)) { + if (current($forumposts)->postcreated > current($moodleoverflowposts)->postcreated) { + $posts[$i] = current($forumposts); + next($forumposts); + } else { + $posts[$i] = current($moodleoverflowposts); + next($moodleoverflowposts); + } + } else if (current($forumposts)) { + $posts[$i] = current($forumposts); + next($forumposts); + } else { + $posts[$i] = current($moodleoverflowposts); + next($moodleoverflowposts); + } + } + + // Add an event type to the posts and add the anonymous setting to the moodleoverflow posts. Then return it. + return $posts; + } + + // Helper functions. + + /** + * Searches for posts in the forum or moodleoverflow module. + * The sql query makes sure that the modules are installed and available.. + * This is a helper function for get_postevents(). + * @param string $modulename The name of the module, is 'forum' or 'moodleoverflow'. + * @param array $courses The ids of the courses where the posts should be searched. + * @param int $timestart The timestamp from where the posts should be searched. + * @return array + */ + private function get_posts_from_db($modulename, $courses, $timestart): array { + global $DB; + // Prepare params for sql statement. + if ($courses == []) { + return []; + } + list($insqlcourses, $inparamscourses) = $DB->get_in_or_equal($courses, SQL_PARAMS_NAMED); + $params = ['courses' => $courses, 'timestart' => $timestart] + $inparamscourses; + // Set begin of sql statement. + $begin = "SELECT (ROW_NUMBER() OVER (ORDER BY posts.id)) AS row_num, "; + + // Set the select part of the sql that is always the same. + $middle = "'post' AS eventtype, + cm.id AS coursemoduleid, + cm.availability AS availability, + module.name AS instancename, + discuss.course AS courseid, + discuss.userid AS discussionuserid, + discuss.name AS discussionsubject, + u.firstname AS postuserfirstname, + u.lastname AS postuserlastname, + posts.id AS postid, + posts.discussion AS postdiscussion, + posts.parent AS postparentid, + posts.userid AS postuserid, + posts.created AS postcreated, + posts.message AS postmessage "; + + // Extend the strings for the 2 module cases. + if ($modulename == 'forum') { + $begin .= "'forum' AS modulename, module.id AS instanceid,"; + $middle .= "FROM {forum_posts} posts + JOIN {forum_discussions} discuss ON discuss.id = posts.discussion + JOIN {forum} module ON module.id = discuss.forum + JOIN {modules} modules ON modules.name = 'forum' "; + + } else if ($modulename == 'moodleoverflow') { + $begin .= "'moodleoverflow' AS modulename, module.id AS instanceid, module.anonymous AS anonymoussetting, "; + $middle .= "FROM {moodleoverflow_posts} posts + JOIN {moodleoverflow_discussions} discuss ON discuss.id = posts.discussion + JOIN {moodleoverflow} module ON module.id = discuss.moodleoverflow + JOIN {modules} modules ON modules.name = 'moodleoverflow' "; + } + + // Extension of the middle string. + $middle .= "JOIN {user} u ON u.id = posts.userid + JOIN {course_modules} cm ON (cm.course = module.course AND cm.module = modules.id + AND cm.instance = module.id) "; + + // Set the where clause of the string. + $end = "WHERE discuss.course $insqlcourses + AND posts.created > :timestart + AND cm.visible = 1 + AND modules.visible = 1 + ORDER BY posts.created DESC;"; + + // Concatenate all strings. + $sql = $begin . $middle . $end; + + // Get all posts. + return $DB->get_records_sql($sql, $params); + } + + /** + * Searches for events in the events table, that are relevant to the timeline. + * This is a helper function for get_calendarevents(). + * @param int $timestart The time from where the events should be searched. Not equal to timestart in the database events table. + * @param int $timeend The time until where the events should be searched. + * @param array $courses The ids of the courses where the events should be searched. + * @return array + * @throws dml_exception + */ + private function get_events_from_db($timestart, $timeend, $courses): array { + global $DB; + + // As there are no events without courses, return an empty array. + if ($courses == []) { + return []; + } + + // Due to compatability reasons, only events from supported modules are shown. + // Supported modules are: core modules and custom additional modules. + $coremodules = ['assign', 'book', 'chat', 'choice', 'data', 'feedback', 'folder', 'forum', 'glossary', 'h5pactivity', + 'imscp', 'label', 'lesson', 'lti', 'page', 'quiz', 'resource', 'scorm', 'survey', 'url', 'wiki', 'workshop', ]; + $additionalmodules = ['moodleoverflow', 'ratingallocate']; + $modules = $coremodules + $additionalmodules; + + // Prepare params for sql statement. + list($insqlcourses, $inparamscourses) = $DB->get_in_or_equal($courses, SQL_PARAMS_NAMED); + list($insqlmodules, $inparamsmodules) = $DB->get_in_or_equal($modules, SQL_PARAMS_NAMED); + $params = ['timestart' => $timestart, 'timeduration' => $timestart, + 'timeend' => $timeend, 'courses' => $courses, ] + $inparamscourses + $inparamsmodules; + + // Set the sql statement. + $sql = "SELECT e.id, e.name, e.courseid, cm.id AS coursemoduleid, cm.availability AS availability, e.groupid, e.userid, + e.modulename, e.instance, e.eventtype, e.timestart, e.visible + FROM {event} e + JOIN {modules} m ON e.modulename = m.name + JOIN {course_modules} cm ON (cm.course = e.courseid AND cm.module = m.id AND cm.instance = e.instance) + WHERE (e.timestart >= :timestart OR e.timestart+e.timeduration > :timeduration) + AND e.timestart <= :timeend + AND e.courseid $insqlcourses + AND e.modulename $insqlmodules + AND m.visible = 1 + AND (e.name NOT LIKE '" .'0'. "' AND e.eventtype NOT LIKE '" .'0'. "' ) + AND (e.instance <> 0 AND e.visible = 1) + ORDER BY e.timestart DESC"; + + // Get all events. + return $DB->get_records_sql($sql, $params); + } + + /** + * Gets the id of all courses where the current user is enrolled + * @return array + */ + private function get_courses(): array { + global $USER; + + $enrolledcourses = enrol_get_all_users_courses($USER->id, true); + $courses = []; + foreach ($enrolledcourses as $enrolledcourse) { + $courses[] = $enrolledcourse->id; + } + + return $courses; + } + + /** + * Filter that checks if the event needs to be filtered out for the current user because it is unavailable. + * Applies to restriction that are defined in the module setting (restrict access). + * @param object $event The event that is checked. + * @return bool true if the event needs to filtered out, false if not. + */ + private function filter_availability($event): bool { + // If there is no restriction defined, the event is available. + if ($event->availability == null) { + return false; + } + + // If there is a restriction, check if it applies to the user. + $modinfo = get_fast_modinfo($event->courseid); + $moduleinfo = $modinfo->get_cm($event->coursemoduleid); + if ($moduleinfo->uservisible) { + return false; + } + + return true; + } + + /** + * Filter that checks if the event needs to be filtered out for the current user. + * Applies to assignment events. + * @param object $calendarevent calendarevent that is checked + * @return bool true if the event needs to filtered out, false if not. + */ + private function filter_assignment($calendarevent): bool { + global $DB; + $assignment = $DB->get_record('assign', ['id' => $calendarevent->instance]); + + // Check if the assign is longer than a week closed. + $overduecheck = $calendarevent->eventtype == "due" && $this->timenow >= ($calendarevent->timestart + 604800); + + // Check if the user is someone without grading capability. + $nogradecapabilitycheck = $calendarevent->eventtype == "gradingdue" && !has_capability('mod/assign:grade', + context_module::instance($calendarevent->coursemoduleid)); + // Check if the assignment is not open yet. + $stillclosedcheck = $assignment->allowsubmissionsfromdate >= $this->timenow; + + if ($overduecheck || $nogradecapabilitycheck || $stillclosedcheck) { + return true; + } + return false; + } + + /** + * Filter that checks if the event needs to be filtered out for the current user. + * Applies to activity completion events. + * @param object $calendarevent calendarevent that is checked + * @return bool true if the event needs to filtered out, false if not. + */ + private function filter_activitycompletions($calendarevent): bool { + global $DB, $USER; + if ($completionstatus = $DB->get_record('course_modules_completion', + ['coursemoduleid' => $calendarevent->coursemoduleid, 'userid' => $USER->id])) { + if ($completionstatus->completionstate != 0) { + return true; + } + } + return false; + } +} diff --git a/db/services.php b/db/services.php index fdd160c..c5eb7a2 100644 --- a/db/services.php +++ b/db/services.php @@ -1,36 +1,35 @@ -. - -/** - * Townsquare external functions and service definitions. - * - * @package block_townsquare - * @category external - * @copyright 2017 Kennet Winter - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -defined('MOODLE_INTERNAL') || die; - -$functions = [ - 'block_townsquare_record_usersettings' => [ - 'classname' => 'block_townsquare_external', - 'methodname' => 'execute', - 'classpath' => 'blocks/townsquare/externallib.php', - 'description' => 'Records the user settings for the townsquare block', - 'type' => 'write', - 'ajax' => true, - ], +. + +/** + * Townsquare external functions and service definitions. + * + * @package block_townsquare + * @category external + * @copyright 2017 Kennet Winter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +defined('MOODLE_INTERNAL') || die; + +$functions = [ + 'block_townsquare_record_usersettings' => [ + 'classname' => 'block_townsquare_external', + 'classpath' => 'blocks/townsquare/externallib.php', + 'description' => 'Records the user settings for the townsquare block', + 'type' => 'write', + 'ajax' => true, + ], ]; \ No newline at end of file diff --git a/externallib.php b/externallib.php index effeb98..51b7c98 100644 --- a/externallib.php +++ b/externallib.php @@ -1,115 +1,115 @@ -. - -/** - * External townsquare API - * - * @package block_townsquare - * @copyright 2024 Tamaro Walter - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -global $CFG; -require_once($CFG->libdir . '/externallib.php'); - -/** - * Class implementing the external API, esp. for AJAX functions. - * - * @package block_townsquare - * @copyright 2024 Tamaro Walter - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class block_townsquare_external extends \core_external\external_api { - - /** - * Returns description of method parameters - * @return external_function_parameters - */ - public static function execute_parameters(): external_function_parameters { - return new external_function_parameters( - [ - 'userid' => new external_value(PARAM_INT, 'the user id'), - 'timefilterpast' => new external_value(PARAM_INT, 'time span for filtering the past'), - 'timefilterfuture' => new external_value(PARAM_INT, 'time span for filtering the future'), - 'basicletter' => new external_value(PARAM_INT, 'Setting of the letter filter for basic letters'), - 'completionletter' => new external_value(PARAM_INT, 'Setting of the letter filter for completion letters'), - 'postletter' => new external_value(PARAM_INT, 'Setting of the letter filter for post letters'), - ] - ); - } - - /** - * Return the result of the record_usersettings function - * @return external_value - */ - public static function execute_returns() { - return new external_value(PARAM_BOOL, 'true if successful'); - } - - /** - * Record the user settings - * - * @param int $userid The user id - * @param int $timefilterpast Time span for filtering the past - * @param int $timefilterfuture Time span for filtering the future - * @param int $letterfilter Setting of the letter filter - * @return bool - */ - public static function execute($userid, $timefilterpast, $timefilterfuture, $basicletter, $completionletter, $postletter) { - global $DB; - //echo ''; - //$transaction = $DB->start_delegated_transaction(); - - // Check if the user already has a record in the database - if ($records = $DB->get_records('townsquare_usersettings', ['userid' => $userid])) { - // If there more than a record (it only should be only one), delete all of them and insert the new one. - if (count($records) > 1) { - try { - foreach ($records as $record) { - $DB->delete_records('townsquare_usersettings', ['id' => $record->id]); - } - } catch (Exception $e) { - // $transaction->rollback($e); - return false; - } - } else { - // Upgrade the existing record. - $record = reset($records); - $record->timefilterpast = $timefilterpast; - $record->timefilterfuture = $timefilterfuture; - $record->basicletter = $basicletter; - $record->completionletter = $completionletter; - $record->postletter = $postletter; - $DB->update_record('townsquare_usersettings', $record); - // $transaction->allow_commit(); - return true; - } - } - $record = new stdClass(); - $record->userid = $userid; - $record->timefilterpast = $timefilterpast; - $record->timefilterfuture = $timefilterfuture; - $record->basicletter = $basicletter; - $record->completionletter = $completionletter; - $record->postletter = $postletter; - $DB->insert_record('townsquare_usersettings', $record); - //$transaction->allow_commit(); - return true; - } - +. + +/** + * External townsquare API + * + * @package block_townsquare + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->libdir . '/externallib.php'); + +/** + * Class implementing the external API, esp. for AJAX functions. + * + * @package block_townsquare + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class block_townsquare_external extends \core_external\external_api { + + /** + * Returns description of method parameters + * @return external_function_parameters + */ + public static function record_usersettings_parameters(): external_function_parameters { + return new external_function_parameters( + [ + 'userid' => new external_value(PARAM_INT, 'the user id'), + 'timefilterpast' => new external_value(PARAM_INT, 'time span for filtering the past'), + 'timefilterfuture' => new external_value(PARAM_INT, 'time span for filtering the future'), + 'basicletter' => new external_value(PARAM_INT, 'Setting of the letter filter for basic letters'), + 'completionletter' => new external_value(PARAM_INT, 'Setting of the letter filter for completion letters'), + 'postletter' => new external_value(PARAM_INT, 'Setting of the letter filter for post letters'), + ] + ); + } + + /** + * Return the result of the record_usersettings function + * @return external_value + */ + public static function record_usersettings_returns() { + return new external_value(PARAM_BOOL, 'true if successful'); + } + + /** + * Record the user settings + * + * @param int $userid The user id + * @param int $timefilterpast Time span for filtering the past + * @param int $timefilterfuture Time span for filtering the future + * @param int $letterfilter Setting of the letter filter + * @return bool + */ + public static function record_usersettings($userid, $timefilterpast, $timefilterfuture, $basicletter, $completionletter, $postletter) { + global $DB; + //echo ''; + //$transaction = $DB->start_delegated_transaction(); + + // Check if the user already has a record in the database + if ($records = $DB->get_records('townsquare_usersettings', ['userid' => $userid])) { + // If there more than a record (it only should be only one), delete all of them and insert the new one. + if (count($records) > 1) { + try { + foreach ($records as $record) { + $DB->delete_records('townsquare_usersettings', ['id' => $record->id]); + } + } catch (Exception $e) { + // $transaction->rollback($e); + return false; + } + } else { + // Upgrade the existing record. + $record = reset($records); + $record->timefilterpast = $timefilterpast; + $record->timefilterfuture = $timefilterfuture; + $record->basicletter = $basicletter; + $record->completionletter = $completionletter; + $record->postletter = $postletter; + $DB->update_record('townsquare_usersettings', $record); + // $transaction->allow_commit(); + return true; + } + } + $record = new stdClass(); + $record->userid = $userid; + $record->timefilterpast = $timefilterpast; + $record->timefilterfuture = $timefilterfuture; + $record->basicletter = $basicletter; + $record->completionletter = $completionletter; + $record->postletter = $postletter; + $DB->insert_record('townsquare_usersettings', $record); + //$transaction->allow_commit(); + return true; + } + } \ No newline at end of file From 7d4cb65e783adc64c4774dcbb0478ed0a5a97505 Mon Sep 17 00:00:00 2001 From: Tamaro Walter Date: Fri, 15 Mar 2024 17:59:11 +0100 Subject: [PATCH 033/123] WIP: execute time filter. Letter filter functions correctly --- amd/build/usersettings_save.min.js | 2 +- amd/build/usersettings_save.min.js.map | 2 +- amd/src/usersettings_save.js | 37 ++++++++++++++++++-------- 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/amd/build/usersettings_save.min.js b/amd/build/usersettings_save.min.js index 269e595..12561a1 100644 --- a/amd/build/usersettings_save.min.js +++ b/amd/build/usersettings_save.min.js @@ -8,6 +8,6 @@ define("block_townsquare/usersettings_save",["exports","core/ajax"],(function(_e * @module block_townsquare/timefilter * @copyright 2024 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,settingsfromdb){settingsfromdb&&function(settingsfromdb){let timefilterfuture=settingsfromdb.timefilterfuture,timefilterpast=settingsfromdb.timefilterpast,basicletter=settingsfromdb.basicletter,completionletter=settingsfromdb.completionletter,postletter=settingsfromdb.postletter,futurebuttonid=converttimetoid(timefilterfuture,!0),pastbuttonid=converttimetoid(timefilterpast,!1);"ts_time_all"!==futurebuttonid?(futureradiobuttons.forEach((function(button){button.id==futurebuttonid&&(button.checked=!0,button.parentNode.classList.add("active"))})),pastradiobuttons.forEach((function(button){button.id==pastbuttonid&&(button.checked=!0,button.parentNode.classList.add("active"))}))):alltimebutton.forEach((function(button){button.id==futurebuttonid&&(button.checked=!0,button.parentNode.classList.add("active"))}));checkboxes.forEach((function(checkbox){let basiclettercheck="basicletter"===checkbox.id&&"1"===basicletter,completionlettercheck="completionletter"===checkbox.id&&"1"===completionletter,postlettercheck="postletter"===checkbox.id&&"1"===postletter;(basiclettercheck||completionlettercheck||postlettercheck)&&checkbox.click()}))}(settingsfromdb);savebutton.addEventListener("click",(async function(){let timespans=function(){let settings={timepast:0,timefuture:0},settingsset=!1;if(alltimebutton.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id),settings.timefuture=convertidtotime(button.id),settingsset=!0)})),settingsset)return settings;return futureradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timefuture=convertidtotime(button.id))})),pastradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id))})),settings}(),letterfilter=function(){let settings={basicletter:0,completionletter:0,postletter:0};return checkboxes.forEach((function(checkbox){if(checkbox.checked)switch(checkbox.id){case"basicletter":settings.basicletter=1;break;case"completionletter":settings.completionletter=1;break;case"postletter":settings.postletter=1}})),settings}();await async function(userid,timefilterpast,timefilterfuture,basicletter,completionletter,postletter){let result;return result=await _ajax.default.call([{methodname:"block_townsquare_record_usersettings",args:{userid:parseInt(userid),timefilterpast:timefilterpast,timefilterfuture:timefilterfuture,basicletter:basicletter,completionletter:completionletter,postletter:postletter}}]),result}(userid,timespans.timepast,timespans.timefuture,letterfilter.basicletter,letterfilter.completionletter,letterfilter.postletter)}))},_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};const savebutton=document.getElementById("ts_usersettings_savebutton"),alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button"),checkboxes=document.querySelectorAll(".ts_letter_checkbox");function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}function converttimetoid(time,future){switch(time){case"15778463":return"ts_time_all";case"172800":return future?"ts_time_next_twodays":"ts_time_past_twodays";case"432000":return future?"ts_time_next_fivedays":"ts_time_last_fivedays";case"604800":return future?"ts_time_next_week":"ts_time_last_week";case"2592000":return future?"ts_time_next_month":"ts_time_last_month"}}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,settingsfromdb){settingsfromdb&&(console.log(settingsfromdb),function(settingsfromdb){let timefilterfuture=settingsfromdb.timefilterfuture,timefilterpast=settingsfromdb.timefilterpast,basicletter=settingsfromdb.basicletter,completionletter=settingsfromdb.completionletter,postletter=settingsfromdb.postletter,futurebuttonid=converttimetoid(timefilterfuture,!0),pastbuttonid=converttimetoid(timefilterpast,!1);"ts_time_all"!==futurebuttonid?(futureradiobuttons.forEach((function(button){button.id==futurebuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))})),pastradiobuttons.forEach((function(button){button.id==pastbuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))}))):alltimebutton.forEach((function(button){button.parentNode.classList.add("active"),button.checked=!0,futureradiobuttons.forEach((function(futureradiobutton){futureradiobutton.checked=!1,futureradiobutton.parentNode.classList.remove("active")})),pastradiobuttons.forEach((function(pastradiobutton){pastradiobutton.checked=!1,pastradiobutton.parentNode.classList.remove("active")}))}));checkboxes.forEach((function(checkbox){let basiclettercheck="basicletter"===checkbox.id&&""===basicletter,completionlettercheck="completionletter"===checkbox.id&&"0"===completionletter,postlettercheck="postletter"===checkbox.id&&"0"===postletter;(basiclettercheck||completionlettercheck||postlettercheck)&&checkbox.click()}))}(settingsfromdb));savebutton.addEventListener("click",(async function(){let timespans=function(){let settings={timepast:0,timefuture:0},settingsset=!1;if(alltimebutton.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id),settings.timefuture=convertidtotime(button.id),settingsset=!0)})),settingsset)return settings;return futureradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timefuture=convertidtotime(button.id))})),pastradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id))})),settings}(),letterfilter=function(){let settings={basicletter:0,completionletter:0,postletter:0};return checkboxes.forEach((function(checkbox){if(checkbox.checked)switch(checkbox.id){case"basicletter":settings.basicletter=1;break;case"completionletter":settings.completionletter=1;break;case"postletter":settings.postletter=1}})),settings}();await async function(userid,timefilterpast,timefilterfuture,basicletter,completionletter,postletter){let result;return result=await _ajax.default.call([{methodname:"block_townsquare_record_usersettings",args:{userid:parseInt(userid),timefilterpast:timefilterpast,timefilterfuture:timefilterfuture,basicletter:basicletter,completionletter:completionletter,postletter:postletter}}]),result}(userid,timespans.timepast,timespans.timefuture,letterfilter.basicletter,letterfilter.completionletter,letterfilter.postletter)}))},_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};const savebutton=document.getElementById("ts_usersettings_savebutton"),alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button"),checkboxes=document.querySelectorAll(".ts_letter_checkbox");function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}function converttimetoid(time,future){switch(time){case"15778463":return"ts_time_all";case"172800":return future?"ts_time_next_twodays":"ts_time_past_twodays";case"432000":return future?"ts_time_next_fivedays":"ts_time_last_fivedays";case"604800":return future?"ts_time_next_week":"ts_time_last_week";case"2592000":return future?"ts_time_next_month":"ts_time_last_month"}}})); //# sourceMappingURL=usersettings_save.min.js.map \ No newline at end of file diff --git a/amd/build/usersettings_save.min.js.map b/amd/build/usersettings_save.min.js.map index 2d74cdb..4150abe 100644 --- a/amd/build/usersettings_save.min.js.map +++ b/amd/build/usersettings_save.min.js.map @@ -1 +1 @@ -{"version":3,"file":"usersettings_save.min.js","sources":["../src/usersettings_save.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\r\n//\r\n// Moodle is free software: you can redistribute it and/or modify\r\n// it under the terms of the GNU General Public License as published by\r\n// the Free Software Foundation, either version 3 of the License, or\r\n// (at your option) any later version.\r\n//\r\n// Moodle is distributed in the hope that it will be useful,\r\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n// GNU General Public License for more details.\r\n//\r\n// You should have received a copy of the GNU General Public License\r\n// along with Moodle. If not, see .\r\n\r\n/**\r\n * Javascript to save the user settings in the database.\r\n *\r\n * This file implements 1 functionality:\r\n * - If the \"save settings\" button is pressed, store the settings in the database.\r\n *\r\n * @module block_townsquare/timefilter\r\n * @copyright 2024 Tamaro Walter\r\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\r\n */\r\n\r\nimport Ajax from 'core/ajax';\r\n\r\n// Get the save button for the user settings.\r\nconst savebutton = document.getElementById('ts_usersettings_savebutton');\r\n\r\n// Get the buttons from the time filter.\r\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\r\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\r\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\r\n\r\n// Get the checkboxes from the letter filter.\r\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\r\n\r\n/**\r\n * Init function\r\n *\r\n * @param {number} userid The id of the current user.\r\n * @param {object} settingsfromdb The settings from the database, if there are any.\r\n */\r\nexport function init(userid, settingsfromdb) {\r\n // When the page is loaded, set the settings from the database.\r\n if (settingsfromdb) {\r\n executeusersettings(settingsfromdb);\r\n }\r\n\r\n // Add event listener to the save button.\r\n savebutton.addEventListener('click', async function() {\r\n\r\n // First step: collect the current settings.\r\n // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes.\r\n let timespans = collecttimefiltersettings();\r\n let letterfilter = collectletterfiltersettings();\r\n\r\n // Second step: store the usersettings in the database.\r\n await saveusersettings(userid, timespans['timepast'], timespans['timefuture'],\r\n letterfilter['basicletter'], letterfilter['completionletter'], letterfilter['postletter']);\r\n });\r\n}\r\n\r\n/**\r\n * Function to save the user settings in the database.\r\n * @param {number} userid\r\n * @param {number} timefilterpast\r\n * @param {number} timefilterfuture\r\n * @param {number} basicletter\r\n * @param {number} completionletter\r\n * @param {number} postletter\r\n * @returns {Promise<*>}\r\n */\r\nasync function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) {\r\n let result ;\r\n result = await Ajax.call([{\r\n methodname: 'block_townsquare_record_usersettings',\r\n args: {\r\n userid: parseInt(userid),\r\n timefilterpast: timefilterpast,\r\n timefilterfuture: timefilterfuture,\r\n basicletter: basicletter,\r\n completionletter: completionletter,\r\n postletter: postletter\r\n },\r\n }]);\r\n return result;\r\n}\r\n\r\n/**\r\n * Function to execute existing user settings when loading the townsquare.\r\n * @param {Object} settingsfromdb\r\n */\r\nfunction executeusersettings(settingsfromdb) {\r\n // Load the settings.\r\n let timefilterfuture = settingsfromdb['timefilterfuture'];\r\n let timefilterpast = settingsfromdb['timefilterpast'];\r\n let basicletter = settingsfromdb['basicletter'];\r\n let completionletter = settingsfromdb['completionletter'];\r\n let postletter = settingsfromdb['postletter'];\r\n\r\n // First step: set the time filter settings.\r\n // Change the time into the correct radio button id.\r\n let futurebuttonid = converttimetoid(timefilterfuture, true);\r\n let pastbuttonid = converttimetoid(timefilterpast, false);\r\n\r\n // If the time span is a combination of past and future, go through the two radio buttons and click them to activate the filter.\r\n if (futurebuttonid !== \"ts_time_all\") {\r\n futureradiobuttons.forEach(function(button) {\r\n if (button.id == futurebuttonid) {\r\n button.checked = true;\r\n button.parentNode.classList.add('active');\r\n\r\n }\r\n });\r\n pastradiobuttons.forEach(function(button) {\r\n if (button.id == pastbuttonid) {\r\n button.checked = true;\r\n button.parentNode.classList.add('active');\r\n //button.parentNode.click();\r\n }\r\n });\r\n } else {\r\n // If the time span is the all time filter, click the all time button.\r\n alltimebutton.forEach(function(button) {\r\n if (button.id == futurebuttonid) {\r\n button.checked = true;\r\n button.parentNode.classList.add('active');\r\n // button.parentNode.click();\r\n }\r\n });\r\n }\r\n\r\n // Second step: set the letter filter settings.\r\n checkboxes.forEach(function(checkbox) {\r\n let basiclettercheck = checkbox.id === 'basicletter' && basicletter === \"1\";\r\n let completionlettercheck = checkbox.id === 'completionletter' && completionletter === \"1\";\r\n let postlettercheck = checkbox.id === 'postletter' && postletter === \"1\";\r\n\r\n if (basiclettercheck || completionlettercheck || postlettercheck) {\r\n checkbox.click();\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Function to collect the letter filter settings.\r\n * @returns {{basicletter: number, completionletter: number, postletter: number}}\r\n */\r\nfunction collectletterfiltersettings() {\r\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\r\n\r\n checkboxes.forEach(function(checkbox) {\r\n if (checkbox.checked) {\r\n switch(checkbox.id) {\r\n case \"basicletter\":\r\n settings['basicletter'] = 1;\r\n break;\r\n case \"completionletter\":\r\n settings['completionletter'] = 1;\r\n break;\r\n case \"postletter\":\r\n settings['postletter'] = 1;\r\n break;\r\n\r\n }\r\n }\r\n });\r\n // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit.\r\n return settings;\r\n}\r\n\r\n/**\r\n * Function to collect the time filter settings.\r\n * @returns {{timepast: number, timefuture: number}}\r\n */\r\nfunction collecttimefiltersettings() {\r\n let settings = { timepast: 0, timefuture: 0};\r\n let settingsset = false;\r\n\r\n // Get the relevant time spans of the time filter.\r\n // Check if the alltimebutton is set.\r\n alltimebutton.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timepast'] = convertidtotime(button.id);\r\n settings['timefuture'] = convertidtotime(button.id);\r\n settingsset = true;\r\n }\r\n });\r\n\r\n if (settingsset) {\r\n return settings;\r\n }\r\n\r\n // If the alltimebutton is not set, check which of the future/past buttons is set.\r\n futureradiobuttons.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timefuture'] = convertidtotime(button.id);\r\n }\r\n });\r\n\r\n pastradiobuttons.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timepast'] = convertidtotime(button.id);\r\n }\r\n });\r\n return settings;\r\n}\r\n\r\n\r\n/**\r\n * Function to convert the radio button id to a useable time span.\r\n * @param {string} id The id of the radio button\r\n * @returns {number}\r\n */\r\nfunction convertidtotime(id) {\r\n // TODO: Please use global functions if possible.\r\n switch(id) {\r\n case \"ts_time_all\":\r\n return 15778463;\r\n case \"ts_time_next_twodays\":\r\n case \"ts_time_last_twodays\":\r\n return 172800;\r\n case \"ts_time_next_fivedays\":\r\n case \"ts_time_last_fivedays\":\r\n return 432000;\r\n case \"ts_time_next_week\":\r\n case \"ts_time_last_week\":\r\n return 604800;\r\n case \"ts_time_next_month\":\r\n case \"ts_time_last_month\":\r\n return 2592000;\r\n }\r\n}\r\n\r\n/**\r\n * Function to convert the time span to a radio button id.\r\n * @param {string} time\r\n * @param {boolean} future\r\n * @returns {string}\r\n */\r\nfunction converttimetoid(time, future) {\r\n switch (time) {\r\n case \"15778463\":\r\n return \"ts_time_all\";\r\n case \"172800\":\r\n if (future) {\r\n return \"ts_time_next_twodays\";\r\n }\r\n return \"ts_time_past_twodays\";\r\n case \"432000\":\r\n if (future) {\r\n return \"ts_time_next_fivedays\";\r\n }\r\n return \"ts_time_last_fivedays\";\r\n case \"604800\":\r\n if (future) {\r\n return \"ts_time_next_week\";\r\n }\r\n return \"ts_time_last_week\";\r\n case \"2592000\":\r\n if (future) {\r\n return \"ts_time_next_month\";\r\n\r\n }\r\n return \"ts_time_last_month\";\r\n }\r\n}\r\n"],"names":["userid","settingsfromdb","timefilterfuture","timefilterpast","basicletter","completionletter","postletter","futurebuttonid","converttimetoid","pastbuttonid","futureradiobuttons","forEach","button","id","checked","parentNode","classList","add","pastradiobuttons","alltimebutton","checkboxes","checkbox","basiclettercheck","completionlettercheck","postlettercheck","click","executeusersettings","savebutton","addEventListener","async","timespans","settings","timepast","timefuture","settingsset","contains","convertidtotime","collecttimefiltersettings","letterfilter","collectletterfiltersettings","result","Ajax","call","methodname","args","parseInt","saveusersettings","document","getElementById","querySelectorAll","time","future"],"mappings":";;;;;;;;;;oFA6CqBA,OAAQC,gBAErBA,yBAgDqBA,oBAErBC,iBAAmBD,eAAc,iBACjCE,eAAiBF,eAAc,eAC/BG,YAAcH,eAAc,YAC5BI,iBAAmBJ,eAAc,iBACjCK,WAAaL,eAAc,WAI3BM,eAAiBC,gBAAgBN,kBAAkB,GACnDO,aAAeD,gBAAgBL,gBAAgB,GAG5B,gBAAnBI,gBACAG,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOC,IAAMN,iBACbK,OAAOE,SAAU,EACjBF,OAAOG,WAAWC,UAAUC,IAAI,cAIxCC,iBAAiBP,SAAQ,SAASC,QAC1BA,OAAOC,IAAMJ,eACbG,OAAOE,SAAU,EACjBF,OAAOG,WAAWC,UAAUC,IAAI,eAMxCE,cAAcR,SAAQ,SAASC,QACvBA,OAAOC,IAAMN,iBACbK,OAAOE,SAAU,EACjBF,OAAOG,WAAWC,UAAUC,IAAI,cAO5CG,WAAWT,SAAQ,SAASU,cACpBC,iBAAmC,gBAAhBD,SAASR,IAAwC,MAAhBT,YACpDmB,sBAAwC,qBAAhBF,SAASR,IAAkD,MAArBR,iBAC9DmB,gBAAkC,eAAhBH,SAASR,IAAsC,MAAfP,YAElDgB,kBAAoBC,uBAAyBC,kBAC7CH,SAASI,WA9FbC,CAAoBzB,gBAIxB0B,WAAWC,iBAAiB,SAASC,qBAI7BC,yBA2HJC,SAAW,CAAEC,SAAU,EAAGC,WAAY,GACtCC,aAAc,KAIlBf,cAAcR,SAAQ,SAASC,QACxBA,OAAOG,WAAWC,UAAUmB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgBxB,OAAOC,IAC9CkB,SAAQ,WAAiBK,gBAAgBxB,OAAOC,IAChDqB,aAAc,MAIjBA,mBACOH,gBAIXrB,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOG,WAAWC,UAAUmB,SAAS,YAErCJ,SAAQ,WAAiBK,gBAAgBxB,OAAOC,QAIxDK,iBAAiBP,SAAQ,SAASC,QAC1BA,OAAOG,WAAWC,UAAUmB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgBxB,OAAOC,QAG/CkB,SA3JaM,GACZC,4BA+FJP,SAAW,aAAgB,mBAAuB,aAAiB,UAEvEX,WAAWT,SAAQ,SAASU,aACpBA,SAASP,eACFO,SAASR,QACP,cACDkB,SAAQ,YAAkB,YAEzB,mBACDA,SAAQ,iBAAuB,YAE9B,aACDA,SAAQ,WAAiB,MAOlCA,SAlHgBQ,wBAkBKvC,OAAQG,eAAgBD,iBAAkBE,YAAaC,iBAAkBC,gBACjGkC,cACJA,aAAeC,cAAKC,KAAK,CAAC,CACtBC,WAAY,uCACZC,KAAM,CACF5C,OAAQ6C,SAAS7C,QACjBG,eAAgBA,eAChBD,iBAAkBA,iBAClBE,YAAaA,YACbC,iBAAkBA,iBAClBC,WAAYA,eAGbkC,OA5BGM,CAAiB9C,OAAQ8B,UAAS,SAAcA,UAAS,WACxCQ,aAAY,YAAiBA,aAAY,iBAAsBA,aAAY,0EAhCpGX,WAAaoB,SAASC,eAAe,8BAGrC7B,cAAgB4B,SAASE,iBAAiB,uBAC1CvC,mBAAqBqC,SAASE,iBAAiB,0BAC/C/B,iBAAmB6B,SAASE,iBAAiB,wBAG7C7B,WAAa2B,SAASE,iBAAiB,gCAuLpCb,gBAAgBvB,WAEdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM,iBAUVL,gBAAgB0C,KAAMC,eACnBD,UACC,iBACM,kBACN,gBACGC,OACO,uBAEJ,2BACN,gBACGA,OACO,wBAEJ,4BACN,gBACGA,OACO,oBAEJ,wBACN,iBACGA,OACO,qBAGJ"} \ No newline at end of file +{"version":3,"file":"usersettings_save.min.js","sources":["../src/usersettings_save.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\r\n//\r\n// Moodle is free software: you can redistribute it and/or modify\r\n// it under the terms of the GNU General Public License as published by\r\n// the Free Software Foundation, either version 3 of the License, or\r\n// (at your option) any later version.\r\n//\r\n// Moodle is distributed in the hope that it will be useful,\r\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n// GNU General Public License for more details.\r\n//\r\n// You should have received a copy of the GNU General Public License\r\n// along with Moodle. If not, see .\r\n\r\n/**\r\n * Javascript to save the user settings in the database.\r\n *\r\n * This file implements 1 functionality:\r\n * - If the \"save settings\" button is pressed, store the settings in the database.\r\n *\r\n * @module block_townsquare/timefilter\r\n * @copyright 2024 Tamaro Walter\r\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\r\n */\r\n\r\nimport Ajax from 'core/ajax';\r\n\r\n// Get the save button for the user settings.\r\nconst savebutton = document.getElementById('ts_usersettings_savebutton');\r\n\r\n// Get the buttons from the time filter.\r\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\r\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\r\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\r\n\r\n// Get the checkboxes from the letter filter.\r\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\r\n\r\n/**\r\n * Init function\r\n *\r\n * @param {number} userid The id of the current user.\r\n * @param {object} settingsfromdb The settings from the database, if there are any.\r\n */\r\nexport function init(userid, settingsfromdb) {\r\n // When the page is loaded, set the settings from the database.\r\n if (settingsfromdb) {\r\n console.log(settingsfromdb);\r\n executeusersettings(settingsfromdb);\r\n }\r\n\r\n // Add event listener to the save button.\r\n savebutton.addEventListener('click', async function() {\r\n\r\n // First step: collect the current settings.\r\n // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes.\r\n let timespans = collecttimefiltersettings();\r\n let letterfilter = collectletterfiltersettings();\r\n\r\n // Second step: store the usersettings in the database.\r\n await saveusersettings(userid, timespans['timepast'], timespans['timefuture'],\r\n letterfilter['basicletter'], letterfilter['completionletter'], letterfilter['postletter']);\r\n });\r\n}\r\n\r\n/**\r\n * Function to save the user settings in the database.\r\n * @param {number} userid\r\n * @param {number} timefilterpast\r\n * @param {number} timefilterfuture\r\n * @param {number} basicletter\r\n * @param {number} completionletter\r\n * @param {number} postletter\r\n * @returns {Promise<*>}\r\n */\r\nasync function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) {\r\n let result ;\r\n result = await Ajax.call([{\r\n methodname: 'block_townsquare_record_usersettings',\r\n args: {\r\n userid: parseInt(userid),\r\n timefilterpast: timefilterpast,\r\n timefilterfuture: timefilterfuture,\r\n basicletter: basicletter,\r\n completionletter: completionletter,\r\n postletter: postletter\r\n },\r\n }]);\r\n return result;\r\n}\r\n\r\n/**\r\n * Function to execute existing user settings when loading the townsquare.\r\n * @param {Object} settingsfromdb\r\n */\r\nfunction executeusersettings(settingsfromdb) {\r\n // Load the settings.\r\n let timefilterfuture = settingsfromdb['timefilterfuture'];\r\n let timefilterpast = settingsfromdb['timefilterpast'];\r\n let basicletter = settingsfromdb['basicletter'];\r\n let completionletter = settingsfromdb['completionletter'];\r\n let postletter = settingsfromdb['postletter'];\r\n\r\n // First step: set the time filter settings.\r\n // Change the time into the correct radio button id.\r\n let futurebuttonid = converttimetoid(timefilterfuture, true);\r\n let pastbuttonid = converttimetoid(timefilterpast, false);\r\n\r\n // If the time span is a combination of past and future, go through the two radio buttons and click them to activate the filter.\r\n if (futurebuttonid !== \"ts_time_all\") {\r\n futureradiobuttons.forEach(function(button) {\r\n if (button.id == futurebuttonid) {\r\n button.parentNode.classList.add('active');\r\n button.checked = true;\r\n alltimebutton.forEach(function(alltimebutton) {\r\n alltimebutton.checked = false;\r\n alltimebutton.parentNode.classList.remove('active');\r\n });\r\n }\r\n });\r\n pastradiobuttons.forEach(function(button) {\r\n if (button.id == pastbuttonid) {\r\n button.parentNode.classList.add('active');\r\n button.checked = true;\r\n alltimebutton.forEach(function(alltimebutton) {\r\n alltimebutton.checked = false;\r\n alltimebutton.parentNode.classList.remove('active');\r\n });\r\n }\r\n });\r\n } else {\r\n // If the time span is the all time filter, click the all time button.\r\n alltimebutton.forEach(function(button) {\r\n // if (button.id == futurebuttonid) {\r\n button.parentNode.classList.add('active');\r\n button.checked = true;\r\n futureradiobuttons.forEach(function(futureradiobutton) {\r\n futureradiobutton.checked = false;\r\n futureradiobutton.parentNode.classList.remove('active');\r\n });\r\n pastradiobuttons.forEach(function(pastradiobutton) {\r\n pastradiobutton.checked = false;\r\n pastradiobutton.parentNode.classList.remove('active');\r\n });\r\n //}\r\n });\r\n }\r\n\r\n // Second step: set the letter filter settings.\r\n // Per default all checkboxes are checked. If the setting is 0, uncheck the checkbox.\r\n checkboxes.forEach(function(checkbox) {\r\n let basiclettercheck = checkbox.id === 'basicletter' && basicletter === \"\";\r\n let completionlettercheck = checkbox.id === 'completionletter' && completionletter === \"0\";\r\n let postlettercheck = checkbox.id === 'postletter' && postletter === \"0\";\r\n\r\n if (basiclettercheck || completionlettercheck || postlettercheck) {\r\n checkbox.click();\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Function to collect the letter filter settings.\r\n * @returns {{basicletter: number, completionletter: number, postletter: number}}\r\n */\r\nfunction collectletterfiltersettings() {\r\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\r\n\r\n checkboxes.forEach(function(checkbox) {\r\n if (checkbox.checked) {\r\n switch(checkbox.id) {\r\n case \"basicletter\":\r\n settings['basicletter'] = 1;\r\n break;\r\n case \"completionletter\":\r\n settings['completionletter'] = 1;\r\n break;\r\n case \"postletter\":\r\n settings['postletter'] = 1;\r\n break;\r\n\r\n }\r\n }\r\n });\r\n // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit.\r\n return settings;\r\n}\r\n\r\n/**\r\n * Function to collect the time filter settings.\r\n * @returns {{timepast: number, timefuture: number}}\r\n */\r\nfunction collecttimefiltersettings() {\r\n let settings = { timepast: 0, timefuture: 0};\r\n let settingsset = false;\r\n\r\n // Get the relevant time spans of the time filter.\r\n // Check if the alltimebutton is set.\r\n alltimebutton.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timepast'] = convertidtotime(button.id);\r\n settings['timefuture'] = convertidtotime(button.id);\r\n settingsset = true;\r\n }\r\n });\r\n\r\n if (settingsset) {\r\n return settings;\r\n }\r\n\r\n // If the alltimebutton is not set, check which of the future/past buttons is set.\r\n futureradiobuttons.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timefuture'] = convertidtotime(button.id);\r\n }\r\n });\r\n\r\n pastradiobuttons.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timepast'] = convertidtotime(button.id);\r\n }\r\n });\r\n return settings;\r\n}\r\n\r\n\r\n/**\r\n * Function to convert the radio button id to a useable time span.\r\n * @param {string} id The id of the radio button\r\n * @returns {number}\r\n */\r\nfunction convertidtotime(id) {\r\n // TODO: Please use global functions if possible.\r\n switch(id) {\r\n case \"ts_time_all\":\r\n return 15778463;\r\n case \"ts_time_next_twodays\":\r\n case \"ts_time_last_twodays\":\r\n return 172800;\r\n case \"ts_time_next_fivedays\":\r\n case \"ts_time_last_fivedays\":\r\n return 432000;\r\n case \"ts_time_next_week\":\r\n case \"ts_time_last_week\":\r\n return 604800;\r\n case \"ts_time_next_month\":\r\n case \"ts_time_last_month\":\r\n return 2592000;\r\n }\r\n}\r\n\r\n/**\r\n * Function to convert the time span to a radio button id.\r\n * @param {string} time\r\n * @param {boolean} future\r\n * @returns {string}\r\n */\r\nfunction converttimetoid(time, future) {\r\n switch (time) {\r\n case \"15778463\":\r\n return \"ts_time_all\";\r\n case \"172800\":\r\n if (future) {\r\n return \"ts_time_next_twodays\";\r\n }\r\n return \"ts_time_past_twodays\";\r\n case \"432000\":\r\n if (future) {\r\n return \"ts_time_next_fivedays\";\r\n }\r\n return \"ts_time_last_fivedays\";\r\n case \"604800\":\r\n if (future) {\r\n return \"ts_time_next_week\";\r\n }\r\n return \"ts_time_last_week\";\r\n case \"2592000\":\r\n if (future) {\r\n return \"ts_time_next_month\";\r\n\r\n }\r\n return \"ts_time_last_month\";\r\n }\r\n}\r\n"],"names":["userid","settingsfromdb","console","log","timefilterfuture","timefilterpast","basicletter","completionletter","postletter","futurebuttonid","converttimetoid","pastbuttonid","futureradiobuttons","forEach","button","id","parentNode","classList","add","checked","alltimebutton","remove","pastradiobuttons","futureradiobutton","pastradiobutton","checkboxes","checkbox","basiclettercheck","completionlettercheck","postlettercheck","click","executeusersettings","savebutton","addEventListener","async","timespans","settings","timepast","timefuture","settingsset","contains","convertidtotime","collecttimefiltersettings","letterfilter","collectletterfiltersettings","result","Ajax","call","methodname","args","parseInt","saveusersettings","document","getElementById","querySelectorAll","time","future"],"mappings":";;;;;;;;;;oFA6CqBA,OAAQC,gBAErBA,iBACAC,QAAQC,IAAIF,yBAgDSA,oBAErBG,iBAAmBH,eAAc,iBACjCI,eAAiBJ,eAAc,eAC/BK,YAAcL,eAAc,YAC5BM,iBAAmBN,eAAc,iBACjCO,WAAaP,eAAc,WAI3BQ,eAAiBC,gBAAgBN,kBAAkB,GACnDO,aAAeD,gBAAgBL,gBAAgB,GAG5B,gBAAnBI,gBACAG,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOC,IAAMN,iBACbK,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBC,cAAcP,SAAQ,SAASO,eAC3BA,cAAcD,SAAU,EACxBC,cAAcJ,WAAWC,UAAUI,OAAO,iBAItDC,iBAAiBT,SAAQ,SAASC,QAC1BA,OAAOC,IAAMJ,eACbG,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBC,cAAcP,SAAQ,SAASO,eAC3BA,cAAcD,SAAU,EACxBC,cAAcJ,WAAWC,UAAUI,OAAO,kBAMtDD,cAAcP,SAAQ,SAASC,QAEvBA,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBP,mBAAmBC,SAAQ,SAASU,mBAChCA,kBAAkBJ,SAAU,EAC5BI,kBAAkBP,WAAWC,UAAUI,OAAO,aAElDC,iBAAiBT,SAAQ,SAASW,iBAC9BA,gBAAgBL,SAAU,EAC1BK,gBAAgBR,WAAWC,UAAUI,OAAO,gBAQ5DI,WAAWZ,SAAQ,SAASa,cACpBC,iBAAmC,gBAAhBD,SAASX,IAAwC,KAAhBT,YACpDsB,sBAAwC,qBAAhBF,SAASX,IAAkD,MAArBR,iBAC9DsB,gBAAkC,eAAhBH,SAASX,IAAsC,MAAfP,YAElDmB,kBAAoBC,uBAAyBC,kBAC7CH,SAASI,WA5GbC,CAAoB9B,iBAIxB+B,WAAWC,iBAAiB,SAASC,qBAI7BC,yBAyIJC,SAAW,CAAEC,SAAU,EAAGC,WAAY,GACtCC,aAAc,KAIlBnB,cAAcP,SAAQ,SAASC,QACxBA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgB3B,OAAOC,IAC9CqB,SAAQ,WAAiBK,gBAAgB3B,OAAOC,IAChDwB,aAAc,MAIjBA,mBACOH,gBAIXxB,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,WAAiBK,gBAAgB3B,OAAOC,QAIxDO,iBAAiBT,SAAQ,SAASC,QAC1BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgB3B,OAAOC,QAG/CqB,SAzKaM,GACZC,4BA6GJP,SAAW,aAAgB,mBAAuB,aAAiB,UAEvEX,WAAWZ,SAAQ,SAASa,aACpBA,SAASP,eACFO,SAASX,QACP,cACDqB,SAAQ,YAAkB,YAEzB,mBACDA,SAAQ,iBAAuB,YAE9B,aACDA,SAAQ,WAAiB,MAOlCA,SAhIgBQ,wBAkBK5C,OAAQK,eAAgBD,iBAAkBE,YAAaC,iBAAkBC,gBACjGqC,cACJA,aAAeC,cAAKC,KAAK,CAAC,CACtBC,WAAY,uCACZC,KAAM,CACFjD,OAAQkD,SAASlD,QACjBK,eAAgBA,eAChBD,iBAAkBA,iBAClBE,YAAaA,YACbC,iBAAkBA,iBAClBC,WAAYA,eAGbqC,OA5BGM,CAAiBnD,OAAQmC,UAAS,SAAcA,UAAS,WACxCQ,aAAY,YAAiBA,aAAY,iBAAsBA,aAAY,0EAjCpGX,WAAaoB,SAASC,eAAe,8BAGrCjC,cAAgBgC,SAASE,iBAAiB,uBAC1C1C,mBAAqBwC,SAASE,iBAAiB,0BAC/ChC,iBAAmB8B,SAASE,iBAAiB,wBAG7C7B,WAAa2B,SAASE,iBAAiB,gCAsMpCb,gBAAgB1B,WAEdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM,iBAUVL,gBAAgB6C,KAAMC,eACnBD,UACC,iBACM,kBACN,gBACGC,OACO,uBAEJ,2BACN,gBACGA,OACO,wBAEJ,4BACN,gBACGA,OACO,oBAEJ,wBACN,iBACGA,OACO,qBAGJ"} \ No newline at end of file diff --git a/amd/src/usersettings_save.js b/amd/src/usersettings_save.js index 08f1b72..55be81a 100644 --- a/amd/src/usersettings_save.js +++ b/amd/src/usersettings_save.js @@ -46,6 +46,7 @@ const checkboxes = document.querySelectorAll('.ts_letter_checkbox'); export function init(userid, settingsfromdb) { // When the page is loaded, set the settings from the database. if (settingsfromdb) { + console.log(settingsfromdb); executeusersettings(settingsfromdb); } @@ -110,34 +111,48 @@ function executeusersettings(settingsfromdb) { if (futurebuttonid !== "ts_time_all") { futureradiobuttons.forEach(function(button) { if (button.id == futurebuttonid) { - button.checked = true; button.parentNode.classList.add('active'); - + button.checked = true; + alltimebutton.forEach(function(alltimebutton) { + alltimebutton.checked = false; + alltimebutton.parentNode.classList.remove('active'); + }); } }); pastradiobuttons.forEach(function(button) { if (button.id == pastbuttonid) { - button.checked = true; button.parentNode.classList.add('active'); - //button.parentNode.click(); + button.checked = true; + alltimebutton.forEach(function(alltimebutton) { + alltimebutton.checked = false; + alltimebutton.parentNode.classList.remove('active'); + }); } }); } else { // If the time span is the all time filter, click the all time button. alltimebutton.forEach(function(button) { - if (button.id == futurebuttonid) { - button.checked = true; + // if (button.id == futurebuttonid) { button.parentNode.classList.add('active'); - // button.parentNode.click(); - } + button.checked = true; + futureradiobuttons.forEach(function(futureradiobutton) { + futureradiobutton.checked = false; + futureradiobutton.parentNode.classList.remove('active'); + }); + pastradiobuttons.forEach(function(pastradiobutton) { + pastradiobutton.checked = false; + pastradiobutton.parentNode.classList.remove('active'); + }); + //} }); } // Second step: set the letter filter settings. + // Per default all checkboxes are checked. If the setting is 0, uncheck the checkbox. checkboxes.forEach(function(checkbox) { - let basiclettercheck = checkbox.id === 'basicletter' && basicletter === "1"; - let completionlettercheck = checkbox.id === 'completionletter' && completionletter === "1"; - let postlettercheck = checkbox.id === 'postletter' && postletter === "1"; + let basiclettercheck = checkbox.id === 'basicletter' && basicletter === ""; + let completionlettercheck = checkbox.id === 'completionletter' && completionletter === "0"; + let postlettercheck = checkbox.id === 'postletter' && postletter === "0"; if (basiclettercheck || completionlettercheck || postlettercheck) { checkbox.click(); From cd7915bbf55a43de0875b914b885980958d45f72 Mon Sep 17 00:00:00 2001 From: Tamaro Walter Date: Mon, 18 Mar 2024 14:44:38 +0100 Subject: [PATCH 034/123] executing usersettings functions --- amd/build/usersettings_save.min.js | 2 +- amd/build/usersettings_save.min.js.map | 2 +- amd/src/usersettings_save.js | 42 +++++++++----------------- 3 files changed, 16 insertions(+), 30 deletions(-) diff --git a/amd/build/usersettings_save.min.js b/amd/build/usersettings_save.min.js index 12561a1..7962e6f 100644 --- a/amd/build/usersettings_save.min.js +++ b/amd/build/usersettings_save.min.js @@ -8,6 +8,6 @@ define("block_townsquare/usersettings_save",["exports","core/ajax"],(function(_e * @module block_townsquare/timefilter * @copyright 2024 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,settingsfromdb){settingsfromdb&&(console.log(settingsfromdb),function(settingsfromdb){let timefilterfuture=settingsfromdb.timefilterfuture,timefilterpast=settingsfromdb.timefilterpast,basicletter=settingsfromdb.basicletter,completionletter=settingsfromdb.completionletter,postletter=settingsfromdb.postletter,futurebuttonid=converttimetoid(timefilterfuture,!0),pastbuttonid=converttimetoid(timefilterpast,!1);"ts_time_all"!==futurebuttonid?(futureradiobuttons.forEach((function(button){button.id==futurebuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))})),pastradiobuttons.forEach((function(button){button.id==pastbuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))}))):alltimebutton.forEach((function(button){button.parentNode.classList.add("active"),button.checked=!0,futureradiobuttons.forEach((function(futureradiobutton){futureradiobutton.checked=!1,futureradiobutton.parentNode.classList.remove("active")})),pastradiobuttons.forEach((function(pastradiobutton){pastradiobutton.checked=!1,pastradiobutton.parentNode.classList.remove("active")}))}));checkboxes.forEach((function(checkbox){let basiclettercheck="basicletter"===checkbox.id&&""===basicletter,completionlettercheck="completionletter"===checkbox.id&&"0"===completionletter,postlettercheck="postletter"===checkbox.id&&"0"===postletter;(basiclettercheck||completionlettercheck||postlettercheck)&&checkbox.click()}))}(settingsfromdb));savebutton.addEventListener("click",(async function(){let timespans=function(){let settings={timepast:0,timefuture:0},settingsset=!1;if(alltimebutton.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id),settings.timefuture=convertidtotime(button.id),settingsset=!0)})),settingsset)return settings;return futureradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timefuture=convertidtotime(button.id))})),pastradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id))})),settings}(),letterfilter=function(){let settings={basicletter:0,completionletter:0,postletter:0};return checkboxes.forEach((function(checkbox){if(checkbox.checked)switch(checkbox.id){case"basicletter":settings.basicletter=1;break;case"completionletter":settings.completionletter=1;break;case"postletter":settings.postletter=1}})),settings}();await async function(userid,timefilterpast,timefilterfuture,basicletter,completionletter,postletter){let result;return result=await _ajax.default.call([{methodname:"block_townsquare_record_usersettings",args:{userid:parseInt(userid),timefilterpast:timefilterpast,timefilterfuture:timefilterfuture,basicletter:basicletter,completionletter:completionletter,postletter:postletter}}]),result}(userid,timespans.timepast,timespans.timefuture,letterfilter.basicletter,letterfilter.completionletter,letterfilter.postletter)}))},_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};const savebutton=document.getElementById("ts_usersettings_savebutton"),alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button"),checkboxes=document.querySelectorAll(".ts_letter_checkbox");function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}function converttimetoid(time,future){switch(time){case"15778463":return"ts_time_all";case"172800":return future?"ts_time_next_twodays":"ts_time_past_twodays";case"432000":return future?"ts_time_next_fivedays":"ts_time_last_fivedays";case"604800":return future?"ts_time_next_week":"ts_time_last_week";case"2592000":return future?"ts_time_next_month":"ts_time_last_month"}}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,settingsfromdb){settingsfromdb&&function(settingsfromdb){let futurebuttonid=converttimetoid(settingsfromdb.timefilterfuture,!0),pastbuttonid=converttimetoid(settingsfromdb.timefilterpast,!1);"ts_time_all"!==futurebuttonid?(futureradiobuttons.forEach((function(button){button.id===futurebuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change")),alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))})),pastradiobuttons.forEach((function(button){button.id===pastbuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change")),alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))}))):alltimebutton.forEach((function(button){button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change"))}));checkboxes.forEach((function(checkbox){let basiclettercheck="basicletter"===checkbox.id&&""===settingsfromdb.basicletter,completionlettercheck="completionletter"===checkbox.id&&"0"===settingsfromdb.completionletter,postlettercheck="postletter"===checkbox.id&&"0"===settingsfromdb.postletter;(basiclettercheck||completionlettercheck||postlettercheck)&&checkbox.click()}))}(settingsfromdb);savebutton.addEventListener("click",(async function(){let timespans=function(){let settings={timepast:0,timefuture:0},settingsset=!1;if(alltimebutton.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id),settings.timefuture=convertidtotime(button.id),settingsset=!0)})),settingsset)return settings;return futureradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timefuture=convertidtotime(button.id))})),pastradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id))})),settings}(),letterfilter=function(){let settings={basicletter:0,completionletter:0,postletter:0};return checkboxes.forEach((function(checkbox){if(checkbox.checked)switch(checkbox.id){case"basicletter":settings.basicletter=1;break;case"completionletter":settings.completionletter=1;break;case"postletter":settings.postletter=1}})),settings}();await async function(userid,timefilterpast,timefilterfuture,basicletter,completionletter,postletter){let result;return result=await _ajax.default.call([{methodname:"block_townsquare_record_usersettings",args:{userid:parseInt(userid),timefilterpast:timefilterpast,timefilterfuture:timefilterfuture,basicletter:basicletter,completionletter:completionletter,postletter:postletter}}]),result}(userid,timespans.timepast,timespans.timefuture,letterfilter.basicletter,letterfilter.completionletter,letterfilter.postletter)}))},_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};const savebutton=document.getElementById("ts_usersettings_savebutton"),alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button"),checkboxes=document.querySelectorAll(".ts_letter_checkbox");function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}function converttimetoid(time,future){switch(time){case"15778463":return"ts_time_all";case"172800":return future?"ts_time_next_twodays":"ts_time_past_twodays";case"432000":return future?"ts_time_next_fivedays":"ts_time_last_fivedays";case"604800":return future?"ts_time_next_week":"ts_time_last_week";case"2592000":return future?"ts_time_next_month":"ts_time_last_month"}}})); //# sourceMappingURL=usersettings_save.min.js.map \ No newline at end of file diff --git a/amd/build/usersettings_save.min.js.map b/amd/build/usersettings_save.min.js.map index 4150abe..23cd064 100644 --- a/amd/build/usersettings_save.min.js.map +++ b/amd/build/usersettings_save.min.js.map @@ -1 +1 @@ -{"version":3,"file":"usersettings_save.min.js","sources":["../src/usersettings_save.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\r\n//\r\n// Moodle is free software: you can redistribute it and/or modify\r\n// it under the terms of the GNU General Public License as published by\r\n// the Free Software Foundation, either version 3 of the License, or\r\n// (at your option) any later version.\r\n//\r\n// Moodle is distributed in the hope that it will be useful,\r\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n// GNU General Public License for more details.\r\n//\r\n// You should have received a copy of the GNU General Public License\r\n// along with Moodle. If not, see .\r\n\r\n/**\r\n * Javascript to save the user settings in the database.\r\n *\r\n * This file implements 1 functionality:\r\n * - If the \"save settings\" button is pressed, store the settings in the database.\r\n *\r\n * @module block_townsquare/timefilter\r\n * @copyright 2024 Tamaro Walter\r\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\r\n */\r\n\r\nimport Ajax from 'core/ajax';\r\n\r\n// Get the save button for the user settings.\r\nconst savebutton = document.getElementById('ts_usersettings_savebutton');\r\n\r\n// Get the buttons from the time filter.\r\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\r\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\r\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\r\n\r\n// Get the checkboxes from the letter filter.\r\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\r\n\r\n/**\r\n * Init function\r\n *\r\n * @param {number} userid The id of the current user.\r\n * @param {object} settingsfromdb The settings from the database, if there are any.\r\n */\r\nexport function init(userid, settingsfromdb) {\r\n // When the page is loaded, set the settings from the database.\r\n if (settingsfromdb) {\r\n console.log(settingsfromdb);\r\n executeusersettings(settingsfromdb);\r\n }\r\n\r\n // Add event listener to the save button.\r\n savebutton.addEventListener('click', async function() {\r\n\r\n // First step: collect the current settings.\r\n // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes.\r\n let timespans = collecttimefiltersettings();\r\n let letterfilter = collectletterfiltersettings();\r\n\r\n // Second step: store the usersettings in the database.\r\n await saveusersettings(userid, timespans['timepast'], timespans['timefuture'],\r\n letterfilter['basicletter'], letterfilter['completionletter'], letterfilter['postletter']);\r\n });\r\n}\r\n\r\n/**\r\n * Function to save the user settings in the database.\r\n * @param {number} userid\r\n * @param {number} timefilterpast\r\n * @param {number} timefilterfuture\r\n * @param {number} basicletter\r\n * @param {number} completionletter\r\n * @param {number} postletter\r\n * @returns {Promise<*>}\r\n */\r\nasync function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) {\r\n let result ;\r\n result = await Ajax.call([{\r\n methodname: 'block_townsquare_record_usersettings',\r\n args: {\r\n userid: parseInt(userid),\r\n timefilterpast: timefilterpast,\r\n timefilterfuture: timefilterfuture,\r\n basicletter: basicletter,\r\n completionletter: completionletter,\r\n postletter: postletter\r\n },\r\n }]);\r\n return result;\r\n}\r\n\r\n/**\r\n * Function to execute existing user settings when loading the townsquare.\r\n * @param {Object} settingsfromdb\r\n */\r\nfunction executeusersettings(settingsfromdb) {\r\n // Load the settings.\r\n let timefilterfuture = settingsfromdb['timefilterfuture'];\r\n let timefilterpast = settingsfromdb['timefilterpast'];\r\n let basicletter = settingsfromdb['basicletter'];\r\n let completionletter = settingsfromdb['completionletter'];\r\n let postletter = settingsfromdb['postletter'];\r\n\r\n // First step: set the time filter settings.\r\n // Change the time into the correct radio button id.\r\n let futurebuttonid = converttimetoid(timefilterfuture, true);\r\n let pastbuttonid = converttimetoid(timefilterpast, false);\r\n\r\n // If the time span is a combination of past and future, go through the two radio buttons and click them to activate the filter.\r\n if (futurebuttonid !== \"ts_time_all\") {\r\n futureradiobuttons.forEach(function(button) {\r\n if (button.id == futurebuttonid) {\r\n button.parentNode.classList.add('active');\r\n button.checked = true;\r\n alltimebutton.forEach(function(alltimebutton) {\r\n alltimebutton.checked = false;\r\n alltimebutton.parentNode.classList.remove('active');\r\n });\r\n }\r\n });\r\n pastradiobuttons.forEach(function(button) {\r\n if (button.id == pastbuttonid) {\r\n button.parentNode.classList.add('active');\r\n button.checked = true;\r\n alltimebutton.forEach(function(alltimebutton) {\r\n alltimebutton.checked = false;\r\n alltimebutton.parentNode.classList.remove('active');\r\n });\r\n }\r\n });\r\n } else {\r\n // If the time span is the all time filter, click the all time button.\r\n alltimebutton.forEach(function(button) {\r\n // if (button.id == futurebuttonid) {\r\n button.parentNode.classList.add('active');\r\n button.checked = true;\r\n futureradiobuttons.forEach(function(futureradiobutton) {\r\n futureradiobutton.checked = false;\r\n futureradiobutton.parentNode.classList.remove('active');\r\n });\r\n pastradiobuttons.forEach(function(pastradiobutton) {\r\n pastradiobutton.checked = false;\r\n pastradiobutton.parentNode.classList.remove('active');\r\n });\r\n //}\r\n });\r\n }\r\n\r\n // Second step: set the letter filter settings.\r\n // Per default all checkboxes are checked. If the setting is 0, uncheck the checkbox.\r\n checkboxes.forEach(function(checkbox) {\r\n let basiclettercheck = checkbox.id === 'basicletter' && basicletter === \"\";\r\n let completionlettercheck = checkbox.id === 'completionletter' && completionletter === \"0\";\r\n let postlettercheck = checkbox.id === 'postletter' && postletter === \"0\";\r\n\r\n if (basiclettercheck || completionlettercheck || postlettercheck) {\r\n checkbox.click();\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Function to collect the letter filter settings.\r\n * @returns {{basicletter: number, completionletter: number, postletter: number}}\r\n */\r\nfunction collectletterfiltersettings() {\r\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\r\n\r\n checkboxes.forEach(function(checkbox) {\r\n if (checkbox.checked) {\r\n switch(checkbox.id) {\r\n case \"basicletter\":\r\n settings['basicletter'] = 1;\r\n break;\r\n case \"completionletter\":\r\n settings['completionletter'] = 1;\r\n break;\r\n case \"postletter\":\r\n settings['postletter'] = 1;\r\n break;\r\n\r\n }\r\n }\r\n });\r\n // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit.\r\n return settings;\r\n}\r\n\r\n/**\r\n * Function to collect the time filter settings.\r\n * @returns {{timepast: number, timefuture: number}}\r\n */\r\nfunction collecttimefiltersettings() {\r\n let settings = { timepast: 0, timefuture: 0};\r\n let settingsset = false;\r\n\r\n // Get the relevant time spans of the time filter.\r\n // Check if the alltimebutton is set.\r\n alltimebutton.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timepast'] = convertidtotime(button.id);\r\n settings['timefuture'] = convertidtotime(button.id);\r\n settingsset = true;\r\n }\r\n });\r\n\r\n if (settingsset) {\r\n return settings;\r\n }\r\n\r\n // If the alltimebutton is not set, check which of the future/past buttons is set.\r\n futureradiobuttons.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timefuture'] = convertidtotime(button.id);\r\n }\r\n });\r\n\r\n pastradiobuttons.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timepast'] = convertidtotime(button.id);\r\n }\r\n });\r\n return settings;\r\n}\r\n\r\n\r\n/**\r\n * Function to convert the radio button id to a useable time span.\r\n * @param {string} id The id of the radio button\r\n * @returns {number}\r\n */\r\nfunction convertidtotime(id) {\r\n // TODO: Please use global functions if possible.\r\n switch(id) {\r\n case \"ts_time_all\":\r\n return 15778463;\r\n case \"ts_time_next_twodays\":\r\n case \"ts_time_last_twodays\":\r\n return 172800;\r\n case \"ts_time_next_fivedays\":\r\n case \"ts_time_last_fivedays\":\r\n return 432000;\r\n case \"ts_time_next_week\":\r\n case \"ts_time_last_week\":\r\n return 604800;\r\n case \"ts_time_next_month\":\r\n case \"ts_time_last_month\":\r\n return 2592000;\r\n }\r\n}\r\n\r\n/**\r\n * Function to convert the time span to a radio button id.\r\n * @param {string} time\r\n * @param {boolean} future\r\n * @returns {string}\r\n */\r\nfunction converttimetoid(time, future) {\r\n switch (time) {\r\n case \"15778463\":\r\n return \"ts_time_all\";\r\n case \"172800\":\r\n if (future) {\r\n return \"ts_time_next_twodays\";\r\n }\r\n return \"ts_time_past_twodays\";\r\n case \"432000\":\r\n if (future) {\r\n return \"ts_time_next_fivedays\";\r\n }\r\n return \"ts_time_last_fivedays\";\r\n case \"604800\":\r\n if (future) {\r\n return \"ts_time_next_week\";\r\n }\r\n return \"ts_time_last_week\";\r\n case \"2592000\":\r\n if (future) {\r\n return \"ts_time_next_month\";\r\n\r\n }\r\n return \"ts_time_last_month\";\r\n }\r\n}\r\n"],"names":["userid","settingsfromdb","console","log","timefilterfuture","timefilterpast","basicletter","completionletter","postletter","futurebuttonid","converttimetoid","pastbuttonid","futureradiobuttons","forEach","button","id","parentNode","classList","add","checked","alltimebutton","remove","pastradiobuttons","futureradiobutton","pastradiobutton","checkboxes","checkbox","basiclettercheck","completionlettercheck","postlettercheck","click","executeusersettings","savebutton","addEventListener","async","timespans","settings","timepast","timefuture","settingsset","contains","convertidtotime","collecttimefiltersettings","letterfilter","collectletterfiltersettings","result","Ajax","call","methodname","args","parseInt","saveusersettings","document","getElementById","querySelectorAll","time","future"],"mappings":";;;;;;;;;;oFA6CqBA,OAAQC,gBAErBA,iBACAC,QAAQC,IAAIF,yBAgDSA,oBAErBG,iBAAmBH,eAAc,iBACjCI,eAAiBJ,eAAc,eAC/BK,YAAcL,eAAc,YAC5BM,iBAAmBN,eAAc,iBACjCO,WAAaP,eAAc,WAI3BQ,eAAiBC,gBAAgBN,kBAAkB,GACnDO,aAAeD,gBAAgBL,gBAAgB,GAG5B,gBAAnBI,gBACAG,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOC,IAAMN,iBACbK,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBC,cAAcP,SAAQ,SAASO,eAC3BA,cAAcD,SAAU,EACxBC,cAAcJ,WAAWC,UAAUI,OAAO,iBAItDC,iBAAiBT,SAAQ,SAASC,QAC1BA,OAAOC,IAAMJ,eACbG,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBC,cAAcP,SAAQ,SAASO,eAC3BA,cAAcD,SAAU,EACxBC,cAAcJ,WAAWC,UAAUI,OAAO,kBAMtDD,cAAcP,SAAQ,SAASC,QAEvBA,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBP,mBAAmBC,SAAQ,SAASU,mBAChCA,kBAAkBJ,SAAU,EAC5BI,kBAAkBP,WAAWC,UAAUI,OAAO,aAElDC,iBAAiBT,SAAQ,SAASW,iBAC9BA,gBAAgBL,SAAU,EAC1BK,gBAAgBR,WAAWC,UAAUI,OAAO,gBAQ5DI,WAAWZ,SAAQ,SAASa,cACpBC,iBAAmC,gBAAhBD,SAASX,IAAwC,KAAhBT,YACpDsB,sBAAwC,qBAAhBF,SAASX,IAAkD,MAArBR,iBAC9DsB,gBAAkC,eAAhBH,SAASX,IAAsC,MAAfP,YAElDmB,kBAAoBC,uBAAyBC,kBAC7CH,SAASI,WA5GbC,CAAoB9B,iBAIxB+B,WAAWC,iBAAiB,SAASC,qBAI7BC,yBAyIJC,SAAW,CAAEC,SAAU,EAAGC,WAAY,GACtCC,aAAc,KAIlBnB,cAAcP,SAAQ,SAASC,QACxBA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgB3B,OAAOC,IAC9CqB,SAAQ,WAAiBK,gBAAgB3B,OAAOC,IAChDwB,aAAc,MAIjBA,mBACOH,gBAIXxB,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,WAAiBK,gBAAgB3B,OAAOC,QAIxDO,iBAAiBT,SAAQ,SAASC,QAC1BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgB3B,OAAOC,QAG/CqB,SAzKaM,GACZC,4BA6GJP,SAAW,aAAgB,mBAAuB,aAAiB,UAEvEX,WAAWZ,SAAQ,SAASa,aACpBA,SAASP,eACFO,SAASX,QACP,cACDqB,SAAQ,YAAkB,YAEzB,mBACDA,SAAQ,iBAAuB,YAE9B,aACDA,SAAQ,WAAiB,MAOlCA,SAhIgBQ,wBAkBK5C,OAAQK,eAAgBD,iBAAkBE,YAAaC,iBAAkBC,gBACjGqC,cACJA,aAAeC,cAAKC,KAAK,CAAC,CACtBC,WAAY,uCACZC,KAAM,CACFjD,OAAQkD,SAASlD,QACjBK,eAAgBA,eAChBD,iBAAkBA,iBAClBE,YAAaA,YACbC,iBAAkBA,iBAClBC,WAAYA,eAGbqC,OA5BGM,CAAiBnD,OAAQmC,UAAS,SAAcA,UAAS,WACxCQ,aAAY,YAAiBA,aAAY,iBAAsBA,aAAY,0EAjCpGX,WAAaoB,SAASC,eAAe,8BAGrCjC,cAAgBgC,SAASE,iBAAiB,uBAC1C1C,mBAAqBwC,SAASE,iBAAiB,0BAC/ChC,iBAAmB8B,SAASE,iBAAiB,wBAG7C7B,WAAa2B,SAASE,iBAAiB,gCAsMpCb,gBAAgB1B,WAEdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM,iBAUVL,gBAAgB6C,KAAMC,eACnBD,UACC,iBACM,kBACN,gBACGC,OACO,uBAEJ,2BACN,gBACGA,OACO,wBAEJ,4BACN,gBACGA,OACO,oBAEJ,wBACN,iBACGA,OACO,qBAGJ"} \ No newline at end of file +{"version":3,"file":"usersettings_save.min.js","sources":["../src/usersettings_save.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\r\n//\r\n// Moodle is free software: you can redistribute it and/or modify\r\n// it under the terms of the GNU General Public License as published by\r\n// the Free Software Foundation, either version 3 of the License, or\r\n// (at your option) any later version.\r\n//\r\n// Moodle is distributed in the hope that it will be useful,\r\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n// GNU General Public License for more details.\r\n//\r\n// You should have received a copy of the GNU General Public License\r\n// along with Moodle. If not, see .\r\n\r\n/**\r\n * Javascript to save the user settings in the database.\r\n *\r\n * This file implements 1 functionality:\r\n * - If the \"save settings\" button is pressed, store the settings in the database.\r\n *\r\n * @module block_townsquare/timefilter\r\n * @copyright 2024 Tamaro Walter\r\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\r\n */\r\n\r\nimport Ajax from 'core/ajax';\r\n\r\n// Get the save button for the user settings.\r\nconst savebutton = document.getElementById('ts_usersettings_savebutton');\r\n\r\n// Get the buttons from the time filter.\r\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\r\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\r\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\r\n\r\n// Get the checkboxes from the letter filter.\r\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\r\n\r\n/**\r\n * Init function\r\n *\r\n * @param {number} userid The id of the current user.\r\n * @param {object} settingsfromdb The settings from the database, if there are any.\r\n */\r\nexport function init(userid, settingsfromdb) {\r\n // When the page is loaded, set the settings from the database.\r\n if (settingsfromdb) {\r\n executeusersettings(settingsfromdb);\r\n }\r\n\r\n // Add event listener to the save button.\r\n savebutton.addEventListener('click', async function() {\r\n\r\n // First step: collect the current settings.\r\n // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes.\r\n let timespans = collecttimefiltersettings();\r\n let letterfilter = collectletterfiltersettings();\r\n\r\n // Second step: store the usersettings in the database.\r\n await saveusersettings(userid, timespans['timepast'], timespans['timefuture'],\r\n letterfilter['basicletter'], letterfilter['completionletter'], letterfilter['postletter']);\r\n });\r\n}\r\n\r\n/**\r\n * Function to save the user settings in the database.\r\n * @param {number} userid\r\n * @param {number} timefilterpast\r\n * @param {number} timefilterfuture\r\n * @param {number} basicletter\r\n * @param {number} completionletter\r\n * @param {number} postletter\r\n * @returns {Promise<*>}\r\n */\r\nasync function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) {\r\n let result ;\r\n result = await Ajax.call([{\r\n methodname: 'block_townsquare_record_usersettings',\r\n args: {\r\n userid: parseInt(userid),\r\n timefilterpast: timefilterpast,\r\n timefilterfuture: timefilterfuture,\r\n basicletter: basicletter,\r\n completionletter: completionletter,\r\n postletter: postletter\r\n },\r\n }]);\r\n return result;\r\n}\r\n\r\n/**\r\n * Function to execute existing user settings when loading the townsquare.\r\n * @param {Object} settingsfromdb\r\n */\r\nfunction executeusersettings(settingsfromdb) {\r\n\r\n // First step: set the time filter settings.\r\n // Change the time into the correct radio button id.\r\n let futurebuttonid = converttimetoid(settingsfromdb['timefilterfuture'], true);\r\n let pastbuttonid = converttimetoid(settingsfromdb['timefilterpast'], false);\r\n\r\n // If the time span is a combination of past and future, go through the two radio buttons and activate the filter.\r\n if (futurebuttonid !== \"ts_time_all\") {\r\n futureradiobuttons.forEach(function(button) {\r\n if (button.id === futurebuttonid) {\r\n button.parentNode.classList.add('active');\r\n button.checked = true;\r\n button.dispatchEvent(new Event('change'));\r\n alltimebutton.forEach(function(alltimebutton) {\r\n alltimebutton.checked = false;\r\n alltimebutton.parentNode.classList.remove('active');\r\n });\r\n }\r\n });\r\n pastradiobuttons.forEach(function(button) {\r\n if (button.id === pastbuttonid) {\r\n button.parentNode.classList.add('active');\r\n button.checked = true;\r\n button.dispatchEvent(new Event('change'));\r\n alltimebutton.forEach(function(alltimebutton) {\r\n alltimebutton.checked = false;\r\n alltimebutton.parentNode.classList.remove('active');\r\n });\r\n }\r\n });\r\n } else {\r\n // If the time span is set to all time, activate the all time button.\r\n alltimebutton.forEach(function(button) {\r\n button.parentNode.classList.add('active');\r\n button.checked = true;\r\n button.dispatchEvent(new Event('change'));\r\n });\r\n }\r\n\r\n // Second step: set the letter filter settings.\r\n // Per default all checkboxes are checked. If the setting is 0, uncheck the checkbox.\r\n checkboxes.forEach(function(checkbox) {\r\n let basiclettercheck = checkbox.id === 'basicletter' && settingsfromdb['basicletter'] === \"\";\r\n let completionlettercheck = checkbox.id === 'completionletter' && settingsfromdb['completionletter'] === \"0\";\r\n let postlettercheck = checkbox.id === 'postletter' && settingsfromdb['postletter'] === \"0\";\r\n\r\n if (basiclettercheck || completionlettercheck || postlettercheck) {\r\n checkbox.click();\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Function to collect the letter filter settings.\r\n * @returns {{basicletter: number, completionletter: number, postletter: number}}\r\n */\r\nfunction collectletterfiltersettings() {\r\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\r\n\r\n checkboxes.forEach(function(checkbox) {\r\n if (checkbox.checked) {\r\n switch(checkbox.id) {\r\n case \"basicletter\":\r\n settings['basicletter'] = 1;\r\n break;\r\n case \"completionletter\":\r\n settings['completionletter'] = 1;\r\n break;\r\n case \"postletter\":\r\n settings['postletter'] = 1;\r\n break;\r\n\r\n }\r\n }\r\n });\r\n // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit.\r\n return settings;\r\n}\r\n\r\n/**\r\n * Function to collect the time filter settings.\r\n * @returns {{timepast: number, timefuture: number}}\r\n */\r\nfunction collecttimefiltersettings() {\r\n let settings = { timepast: 0, timefuture: 0};\r\n let settingsset = false;\r\n\r\n // Get the relevant time spans of the time filter.\r\n // Check if the alltimebutton is set.\r\n alltimebutton.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timepast'] = convertidtotime(button.id);\r\n settings['timefuture'] = convertidtotime(button.id);\r\n settingsset = true;\r\n }\r\n });\r\n\r\n if (settingsset) {\r\n return settings;\r\n }\r\n\r\n // If the alltimebutton is not set, check which of the future/past buttons is set.\r\n futureradiobuttons.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timefuture'] = convertidtotime(button.id);\r\n }\r\n });\r\n\r\n pastradiobuttons.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timepast'] = convertidtotime(button.id);\r\n }\r\n });\r\n return settings;\r\n}\r\n\r\n\r\n/**\r\n * Function to convert the radio button id to a useable time span.\r\n * @param {string} id The id of the radio button\r\n * @returns {number}\r\n */\r\nfunction convertidtotime(id) {\r\n // TODO: Please use global functions if possible.\r\n switch(id) {\r\n case \"ts_time_all\":\r\n return 15778463;\r\n case \"ts_time_next_twodays\":\r\n case \"ts_time_last_twodays\":\r\n return 172800;\r\n case \"ts_time_next_fivedays\":\r\n case \"ts_time_last_fivedays\":\r\n return 432000;\r\n case \"ts_time_next_week\":\r\n case \"ts_time_last_week\":\r\n return 604800;\r\n case \"ts_time_next_month\":\r\n case \"ts_time_last_month\":\r\n return 2592000;\r\n }\r\n}\r\n\r\n/**\r\n * Function to convert the time span to a radio button id.\r\n * @param {string} time\r\n * @param {boolean} future\r\n * @returns {string}\r\n */\r\nfunction converttimetoid(time, future) {\r\n switch (time) {\r\n case \"15778463\":\r\n return \"ts_time_all\";\r\n case \"172800\":\r\n if (future) {\r\n return \"ts_time_next_twodays\";\r\n }\r\n return \"ts_time_past_twodays\";\r\n case \"432000\":\r\n if (future) {\r\n return \"ts_time_next_fivedays\";\r\n }\r\n return \"ts_time_last_fivedays\";\r\n case \"604800\":\r\n if (future) {\r\n return \"ts_time_next_week\";\r\n }\r\n return \"ts_time_last_week\";\r\n case \"2592000\":\r\n if (future) {\r\n return \"ts_time_next_month\";\r\n\r\n }\r\n return \"ts_time_last_month\";\r\n }\r\n}\r\n"],"names":["userid","settingsfromdb","futurebuttonid","converttimetoid","pastbuttonid","futureradiobuttons","forEach","button","id","parentNode","classList","add","checked","dispatchEvent","Event","alltimebutton","remove","pastradiobuttons","checkboxes","checkbox","basiclettercheck","completionlettercheck","postlettercheck","click","executeusersettings","savebutton","addEventListener","async","timespans","settings","timepast","timefuture","settingsset","contains","convertidtotime","collecttimefiltersettings","letterfilter","collectletterfiltersettings","timefilterpast","timefilterfuture","basicletter","completionletter","postletter","result","Ajax","call","methodname","args","parseInt","saveusersettings","document","getElementById","querySelectorAll","time","future"],"mappings":";;;;;;;;;;oFA6CqBA,OAAQC,gBAErBA,yBAgDqBA,oBAIrBC,eAAiBC,gBAAgBF,eAAc,kBAAsB,GACrEG,aAAeD,gBAAgBF,eAAc,gBAAoB,GAG9C,gBAAnBC,gBACAG,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOC,KAAON,iBACdK,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,iBAItDC,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOC,KAAOJ,eACdG,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,kBAMtDD,cAAcT,SAAQ,SAASC,QAC3BA,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,cAMvCI,WAAWZ,SAAQ,SAASa,cACpBC,iBAAmC,gBAAhBD,SAASX,IAA0D,KAAlCP,eAAc,YAClEoB,sBAAwC,qBAAhBF,SAASX,IAAoE,MAAvCP,eAAc,iBAC5EqB,gBAAkC,eAAhBH,SAASX,IAAwD,MAAjCP,eAAc,YAEhEmB,kBAAoBC,uBAAyBC,kBAC7CH,SAASI,WA/FbC,CAAoBvB,gBAIxBwB,WAAWC,iBAAiB,SAASC,qBAI7BC,yBA4HJC,SAAW,CAAEC,SAAU,EAAGC,WAAY,GACtCC,aAAc,KAIlBjB,cAAcT,SAAQ,SAASC,QACxBA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgB3B,OAAOC,IAC9CqB,SAAQ,WAAiBK,gBAAgB3B,OAAOC,IAChDwB,aAAc,MAIjBA,mBACOH,gBAIXxB,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,WAAiBK,gBAAgB3B,OAAOC,QAIxDS,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgB3B,OAAOC,QAG/CqB,SA5JaM,GACZC,4BAgGJP,SAAW,aAAgB,mBAAuB,aAAiB,UAEvEX,WAAWZ,SAAQ,SAASa,aACpBA,SAASP,eACFO,SAASX,QACP,cACDqB,SAAQ,YAAkB,YAEzB,mBACDA,SAAQ,iBAAuB,YAE9B,aACDA,SAAQ,WAAiB,MAOlCA,SAnHgBQ,wBAkBKrC,OAAQsC,eAAgBC,iBAAkBC,YAAaC,iBAAkBC,gBACjGC,cACJA,aAAeC,cAAKC,KAAK,CAAC,CACtBC,WAAY,uCACZC,KAAM,CACF/C,OAAQgD,SAAShD,QACjBsC,eAAgBA,eAChBC,iBAAkBA,iBAClBC,YAAaA,YACbC,iBAAkBA,iBAClBC,WAAYA,eAGbC,OA5BGM,CAAiBjD,OAAQ4B,UAAS,SAAcA,UAAS,WACxCQ,aAAY,YAAiBA,aAAY,iBAAsBA,aAAY,0EAhCpGX,WAAayB,SAASC,eAAe,8BAGrCpC,cAAgBmC,SAASE,iBAAiB,uBAC1C/C,mBAAqB6C,SAASE,iBAAiB,0BAC/CnC,iBAAmBiC,SAASE,iBAAiB,wBAG7ClC,WAAagC,SAASE,iBAAiB,gCAwLpClB,gBAAgB1B,WAEdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM,iBAUVL,gBAAgBkD,KAAMC,eACnBD,UACC,iBACM,kBACN,gBACGC,OACO,uBAEJ,2BACN,gBACGA,OACO,wBAEJ,4BACN,gBACGA,OACO,oBAEJ,wBACN,iBACGA,OACO,qBAGJ"} \ No newline at end of file diff --git a/amd/src/usersettings_save.js b/amd/src/usersettings_save.js index 55be81a..62d40e1 100644 --- a/amd/src/usersettings_save.js +++ b/amd/src/usersettings_save.js @@ -46,7 +46,6 @@ const checkboxes = document.querySelectorAll('.ts_letter_checkbox'); export function init(userid, settingsfromdb) { // When the page is loaded, set the settings from the database. if (settingsfromdb) { - console.log(settingsfromdb); executeusersettings(settingsfromdb); } @@ -95,24 +94,19 @@ async function saveusersettings(userid, timefilterpast, timefilterfuture, basicl * @param {Object} settingsfromdb */ function executeusersettings(settingsfromdb) { - // Load the settings. - let timefilterfuture = settingsfromdb['timefilterfuture']; - let timefilterpast = settingsfromdb['timefilterpast']; - let basicletter = settingsfromdb['basicletter']; - let completionletter = settingsfromdb['completionletter']; - let postletter = settingsfromdb['postletter']; // First step: set the time filter settings. // Change the time into the correct radio button id. - let futurebuttonid = converttimetoid(timefilterfuture, true); - let pastbuttonid = converttimetoid(timefilterpast, false); + let futurebuttonid = converttimetoid(settingsfromdb['timefilterfuture'], true); + let pastbuttonid = converttimetoid(settingsfromdb['timefilterpast'], false); - // If the time span is a combination of past and future, go through the two radio buttons and click them to activate the filter. + // If the time span is a combination of past and future, go through the two radio buttons and activate the filter. if (futurebuttonid !== "ts_time_all") { futureradiobuttons.forEach(function(button) { - if (button.id == futurebuttonid) { + if (button.id === futurebuttonid) { button.parentNode.classList.add('active'); button.checked = true; + button.dispatchEvent(new Event('change')); alltimebutton.forEach(function(alltimebutton) { alltimebutton.checked = false; alltimebutton.parentNode.classList.remove('active'); @@ -120,9 +114,10 @@ function executeusersettings(settingsfromdb) { } }); pastradiobuttons.forEach(function(button) { - if (button.id == pastbuttonid) { + if (button.id === pastbuttonid) { button.parentNode.classList.add('active'); button.checked = true; + button.dispatchEvent(new Event('change')); alltimebutton.forEach(function(alltimebutton) { alltimebutton.checked = false; alltimebutton.parentNode.classList.remove('active'); @@ -130,29 +125,20 @@ function executeusersettings(settingsfromdb) { } }); } else { - // If the time span is the all time filter, click the all time button. + // If the time span is set to all time, activate the all time button. alltimebutton.forEach(function(button) { - // if (button.id == futurebuttonid) { - button.parentNode.classList.add('active'); - button.checked = true; - futureradiobuttons.forEach(function(futureradiobutton) { - futureradiobutton.checked = false; - futureradiobutton.parentNode.classList.remove('active'); - }); - pastradiobuttons.forEach(function(pastradiobutton) { - pastradiobutton.checked = false; - pastradiobutton.parentNode.classList.remove('active'); - }); - //} + button.parentNode.classList.add('active'); + button.checked = true; + button.dispatchEvent(new Event('change')); }); } // Second step: set the letter filter settings. // Per default all checkboxes are checked. If the setting is 0, uncheck the checkbox. checkboxes.forEach(function(checkbox) { - let basiclettercheck = checkbox.id === 'basicletter' && basicletter === ""; - let completionlettercheck = checkbox.id === 'completionletter' && completionletter === "0"; - let postlettercheck = checkbox.id === 'postletter' && postletter === "0"; + let basiclettercheck = checkbox.id === 'basicletter' && settingsfromdb['basicletter'] === ""; + let completionlettercheck = checkbox.id === 'completionletter' && settingsfromdb['completionletter'] === "0"; + let postlettercheck = checkbox.id === 'postletter' && settingsfromdb['postletter'] === "0"; if (basiclettercheck || completionlettercheck || postlettercheck) { checkbox.click(); From 5fe450c34a637349c0e061a5be51efe908a0e0d7 Mon Sep 17 00:00:00 2001 From: Tamaro Walter Date: Mon, 18 Mar 2024 15:48:13 +0100 Subject: [PATCH 035/123] WIP: add a success label --- amd/build/usersettings_save.min.js | 2 +- amd/build/usersettings_save.min.js.map | 2 +- amd/src/usersettings_save.js | 15 ++ lang/en/block_townsquare.php | 167 +++++++-------- styles.css | 169 +++++++-------- templates/sidepanel.mustache | 279 +++++++++++++------------ 6 files changed, 329 insertions(+), 305 deletions(-) diff --git a/amd/build/usersettings_save.min.js b/amd/build/usersettings_save.min.js index 7962e6f..038e610 100644 --- a/amd/build/usersettings_save.min.js +++ b/amd/build/usersettings_save.min.js @@ -8,6 +8,6 @@ define("block_townsquare/usersettings_save",["exports","core/ajax"],(function(_e * @module block_townsquare/timefilter * @copyright 2024 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,settingsfromdb){settingsfromdb&&function(settingsfromdb){let futurebuttonid=converttimetoid(settingsfromdb.timefilterfuture,!0),pastbuttonid=converttimetoid(settingsfromdb.timefilterpast,!1);"ts_time_all"!==futurebuttonid?(futureradiobuttons.forEach((function(button){button.id===futurebuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change")),alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))})),pastradiobuttons.forEach((function(button){button.id===pastbuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change")),alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))}))):alltimebutton.forEach((function(button){button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change"))}));checkboxes.forEach((function(checkbox){let basiclettercheck="basicletter"===checkbox.id&&""===settingsfromdb.basicletter,completionlettercheck="completionletter"===checkbox.id&&"0"===settingsfromdb.completionletter,postlettercheck="postletter"===checkbox.id&&"0"===settingsfromdb.postletter;(basiclettercheck||completionlettercheck||postlettercheck)&&checkbox.click()}))}(settingsfromdb);savebutton.addEventListener("click",(async function(){let timespans=function(){let settings={timepast:0,timefuture:0},settingsset=!1;if(alltimebutton.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id),settings.timefuture=convertidtotime(button.id),settingsset=!0)})),settingsset)return settings;return futureradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timefuture=convertidtotime(button.id))})),pastradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id))})),settings}(),letterfilter=function(){let settings={basicletter:0,completionletter:0,postletter:0};return checkboxes.forEach((function(checkbox){if(checkbox.checked)switch(checkbox.id){case"basicletter":settings.basicletter=1;break;case"completionletter":settings.completionletter=1;break;case"postletter":settings.postletter=1}})),settings}();await async function(userid,timefilterpast,timefilterfuture,basicletter,completionletter,postletter){let result;return result=await _ajax.default.call([{methodname:"block_townsquare_record_usersettings",args:{userid:parseInt(userid),timefilterpast:timefilterpast,timefilterfuture:timefilterfuture,basicletter:basicletter,completionletter:completionletter,postletter:postletter}}]),result}(userid,timespans.timepast,timespans.timefuture,letterfilter.basicletter,letterfilter.completionletter,letterfilter.postletter)}))},_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};const savebutton=document.getElementById("ts_usersettings_savebutton"),alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button"),checkboxes=document.querySelectorAll(".ts_letter_checkbox");function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}function converttimetoid(time,future){switch(time){case"15778463":return"ts_time_all";case"172800":return future?"ts_time_next_twodays":"ts_time_past_twodays";case"432000":return future?"ts_time_next_fivedays":"ts_time_last_fivedays";case"604800":return future?"ts_time_next_week":"ts_time_last_week";case"2592000":return future?"ts_time_next_month":"ts_time_last_month"}}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,settingsfromdb){settingsfromdb&&function(settingsfromdb){let futurebuttonid=converttimetoid(settingsfromdb.timefilterfuture,!0),pastbuttonid=converttimetoid(settingsfromdb.timefilterpast,!1);"ts_time_all"!==futurebuttonid?(futureradiobuttons.forEach((function(button){button.id===futurebuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change")),alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))})),pastradiobuttons.forEach((function(button){button.id===pastbuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change")),alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))}))):alltimebutton.forEach((function(button){button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change"))}));checkboxes.forEach((function(checkbox){let basiclettercheck="basicletter"===checkbox.id&&""===settingsfromdb.basicletter,completionlettercheck="completionletter"===checkbox.id&&"0"===settingsfromdb.completionletter,postlettercheck="postletter"===checkbox.id&&"0"===settingsfromdb.postletter;(basiclettercheck||completionlettercheck||postlettercheck)&&checkbox.click()}))}(settingsfromdb);savebutton.addEventListener("click",(async function(){let timespans=function(){let settings={timepast:0,timefuture:0},settingsset=!1;if(alltimebutton.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id),settings.timefuture=convertidtotime(button.id),settingsset=!0)})),settingsset)return settings;return futureradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timefuture=convertidtotime(button.id))})),pastradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id))})),settings}(),letterfilter=function(){let settings={basicletter:0,completionletter:0,postletter:0};return checkboxes.forEach((function(checkbox){if(checkbox.checked)switch(checkbox.id){case"basicletter":settings.basicletter=1;break;case"completionletter":settings.completionletter=1;break;case"postletter":settings.postletter=1}})),settings}();await async function(userid,timefilterpast,timefilterfuture,basicletter,completionletter,postletter){let result;result=await _ajax.default.call([{methodname:"block_townsquare_record_usersettings",args:{userid:parseInt(userid),timefilterpast:timefilterpast,timefilterfuture:timefilterfuture,basicletter:basicletter,completionletter:completionletter,postletter:postletter}}]);let el=document.getElementById("ts_usersettings_successlabel");return el.style.opacity=1,el.style.display="block",result}(userid,timespans.timepast,timespans.timefuture,letterfilter.basicletter,letterfilter.completionletter,letterfilter.postletter)}))},_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};const savebutton=document.getElementById("ts_usersettings_savebutton"),alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button"),checkboxes=document.querySelectorAll(".ts_letter_checkbox");function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}function converttimetoid(time,future){switch(time){case"15778463":return"ts_time_all";case"172800":return future?"ts_time_next_twodays":"ts_time_past_twodays";case"432000":return future?"ts_time_next_fivedays":"ts_time_last_fivedays";case"604800":return future?"ts_time_next_week":"ts_time_last_week";case"2592000":return future?"ts_time_next_month":"ts_time_last_month"}}})); //# sourceMappingURL=usersettings_save.min.js.map \ No newline at end of file diff --git a/amd/build/usersettings_save.min.js.map b/amd/build/usersettings_save.min.js.map index 23cd064..c526c29 100644 --- a/amd/build/usersettings_save.min.js.map +++ b/amd/build/usersettings_save.min.js.map @@ -1 +1 @@ -{"version":3,"file":"usersettings_save.min.js","sources":["../src/usersettings_save.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\r\n//\r\n// Moodle is free software: you can redistribute it and/or modify\r\n// it under the terms of the GNU General Public License as published by\r\n// the Free Software Foundation, either version 3 of the License, or\r\n// (at your option) any later version.\r\n//\r\n// Moodle is distributed in the hope that it will be useful,\r\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n// GNU General Public License for more details.\r\n//\r\n// You should have received a copy of the GNU General Public License\r\n// along with Moodle. If not, see .\r\n\r\n/**\r\n * Javascript to save the user settings in the database.\r\n *\r\n * This file implements 1 functionality:\r\n * - If the \"save settings\" button is pressed, store the settings in the database.\r\n *\r\n * @module block_townsquare/timefilter\r\n * @copyright 2024 Tamaro Walter\r\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\r\n */\r\n\r\nimport Ajax from 'core/ajax';\r\n\r\n// Get the save button for the user settings.\r\nconst savebutton = document.getElementById('ts_usersettings_savebutton');\r\n\r\n// Get the buttons from the time filter.\r\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\r\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\r\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\r\n\r\n// Get the checkboxes from the letter filter.\r\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\r\n\r\n/**\r\n * Init function\r\n *\r\n * @param {number} userid The id of the current user.\r\n * @param {object} settingsfromdb The settings from the database, if there are any.\r\n */\r\nexport function init(userid, settingsfromdb) {\r\n // When the page is loaded, set the settings from the database.\r\n if (settingsfromdb) {\r\n executeusersettings(settingsfromdb);\r\n }\r\n\r\n // Add event listener to the save button.\r\n savebutton.addEventListener('click', async function() {\r\n\r\n // First step: collect the current settings.\r\n // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes.\r\n let timespans = collecttimefiltersettings();\r\n let letterfilter = collectletterfiltersettings();\r\n\r\n // Second step: store the usersettings in the database.\r\n await saveusersettings(userid, timespans['timepast'], timespans['timefuture'],\r\n letterfilter['basicletter'], letterfilter['completionletter'], letterfilter['postletter']);\r\n });\r\n}\r\n\r\n/**\r\n * Function to save the user settings in the database.\r\n * @param {number} userid\r\n * @param {number} timefilterpast\r\n * @param {number} timefilterfuture\r\n * @param {number} basicletter\r\n * @param {number} completionletter\r\n * @param {number} postletter\r\n * @returns {Promise<*>}\r\n */\r\nasync function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) {\r\n let result ;\r\n result = await Ajax.call([{\r\n methodname: 'block_townsquare_record_usersettings',\r\n args: {\r\n userid: parseInt(userid),\r\n timefilterpast: timefilterpast,\r\n timefilterfuture: timefilterfuture,\r\n basicletter: basicletter,\r\n completionletter: completionletter,\r\n postletter: postletter\r\n },\r\n }]);\r\n return result;\r\n}\r\n\r\n/**\r\n * Function to execute existing user settings when loading the townsquare.\r\n * @param {Object} settingsfromdb\r\n */\r\nfunction executeusersettings(settingsfromdb) {\r\n\r\n // First step: set the time filter settings.\r\n // Change the time into the correct radio button id.\r\n let futurebuttonid = converttimetoid(settingsfromdb['timefilterfuture'], true);\r\n let pastbuttonid = converttimetoid(settingsfromdb['timefilterpast'], false);\r\n\r\n // If the time span is a combination of past and future, go through the two radio buttons and activate the filter.\r\n if (futurebuttonid !== \"ts_time_all\") {\r\n futureradiobuttons.forEach(function(button) {\r\n if (button.id === futurebuttonid) {\r\n button.parentNode.classList.add('active');\r\n button.checked = true;\r\n button.dispatchEvent(new Event('change'));\r\n alltimebutton.forEach(function(alltimebutton) {\r\n alltimebutton.checked = false;\r\n alltimebutton.parentNode.classList.remove('active');\r\n });\r\n }\r\n });\r\n pastradiobuttons.forEach(function(button) {\r\n if (button.id === pastbuttonid) {\r\n button.parentNode.classList.add('active');\r\n button.checked = true;\r\n button.dispatchEvent(new Event('change'));\r\n alltimebutton.forEach(function(alltimebutton) {\r\n alltimebutton.checked = false;\r\n alltimebutton.parentNode.classList.remove('active');\r\n });\r\n }\r\n });\r\n } else {\r\n // If the time span is set to all time, activate the all time button.\r\n alltimebutton.forEach(function(button) {\r\n button.parentNode.classList.add('active');\r\n button.checked = true;\r\n button.dispatchEvent(new Event('change'));\r\n });\r\n }\r\n\r\n // Second step: set the letter filter settings.\r\n // Per default all checkboxes are checked. If the setting is 0, uncheck the checkbox.\r\n checkboxes.forEach(function(checkbox) {\r\n let basiclettercheck = checkbox.id === 'basicletter' && settingsfromdb['basicletter'] === \"\";\r\n let completionlettercheck = checkbox.id === 'completionletter' && settingsfromdb['completionletter'] === \"0\";\r\n let postlettercheck = checkbox.id === 'postletter' && settingsfromdb['postletter'] === \"0\";\r\n\r\n if (basiclettercheck || completionlettercheck || postlettercheck) {\r\n checkbox.click();\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Function to collect the letter filter settings.\r\n * @returns {{basicletter: number, completionletter: number, postletter: number}}\r\n */\r\nfunction collectletterfiltersettings() {\r\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\r\n\r\n checkboxes.forEach(function(checkbox) {\r\n if (checkbox.checked) {\r\n switch(checkbox.id) {\r\n case \"basicletter\":\r\n settings['basicletter'] = 1;\r\n break;\r\n case \"completionletter\":\r\n settings['completionletter'] = 1;\r\n break;\r\n case \"postletter\":\r\n settings['postletter'] = 1;\r\n break;\r\n\r\n }\r\n }\r\n });\r\n // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit.\r\n return settings;\r\n}\r\n\r\n/**\r\n * Function to collect the time filter settings.\r\n * @returns {{timepast: number, timefuture: number}}\r\n */\r\nfunction collecttimefiltersettings() {\r\n let settings = { timepast: 0, timefuture: 0};\r\n let settingsset = false;\r\n\r\n // Get the relevant time spans of the time filter.\r\n // Check if the alltimebutton is set.\r\n alltimebutton.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timepast'] = convertidtotime(button.id);\r\n settings['timefuture'] = convertidtotime(button.id);\r\n settingsset = true;\r\n }\r\n });\r\n\r\n if (settingsset) {\r\n return settings;\r\n }\r\n\r\n // If the alltimebutton is not set, check which of the future/past buttons is set.\r\n futureradiobuttons.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timefuture'] = convertidtotime(button.id);\r\n }\r\n });\r\n\r\n pastradiobuttons.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timepast'] = convertidtotime(button.id);\r\n }\r\n });\r\n return settings;\r\n}\r\n\r\n\r\n/**\r\n * Function to convert the radio button id to a useable time span.\r\n * @param {string} id The id of the radio button\r\n * @returns {number}\r\n */\r\nfunction convertidtotime(id) {\r\n // TODO: Please use global functions if possible.\r\n switch(id) {\r\n case \"ts_time_all\":\r\n return 15778463;\r\n case \"ts_time_next_twodays\":\r\n case \"ts_time_last_twodays\":\r\n return 172800;\r\n case \"ts_time_next_fivedays\":\r\n case \"ts_time_last_fivedays\":\r\n return 432000;\r\n case \"ts_time_next_week\":\r\n case \"ts_time_last_week\":\r\n return 604800;\r\n case \"ts_time_next_month\":\r\n case \"ts_time_last_month\":\r\n return 2592000;\r\n }\r\n}\r\n\r\n/**\r\n * Function to convert the time span to a radio button id.\r\n * @param {string} time\r\n * @param {boolean} future\r\n * @returns {string}\r\n */\r\nfunction converttimetoid(time, future) {\r\n switch (time) {\r\n case \"15778463\":\r\n return \"ts_time_all\";\r\n case \"172800\":\r\n if (future) {\r\n return \"ts_time_next_twodays\";\r\n }\r\n return \"ts_time_past_twodays\";\r\n case \"432000\":\r\n if (future) {\r\n return \"ts_time_next_fivedays\";\r\n }\r\n return \"ts_time_last_fivedays\";\r\n case \"604800\":\r\n if (future) {\r\n return \"ts_time_next_week\";\r\n }\r\n return \"ts_time_last_week\";\r\n case \"2592000\":\r\n if (future) {\r\n return \"ts_time_next_month\";\r\n\r\n }\r\n return \"ts_time_last_month\";\r\n }\r\n}\r\n"],"names":["userid","settingsfromdb","futurebuttonid","converttimetoid","pastbuttonid","futureradiobuttons","forEach","button","id","parentNode","classList","add","checked","dispatchEvent","Event","alltimebutton","remove","pastradiobuttons","checkboxes","checkbox","basiclettercheck","completionlettercheck","postlettercheck","click","executeusersettings","savebutton","addEventListener","async","timespans","settings","timepast","timefuture","settingsset","contains","convertidtotime","collecttimefiltersettings","letterfilter","collectletterfiltersettings","timefilterpast","timefilterfuture","basicletter","completionletter","postletter","result","Ajax","call","methodname","args","parseInt","saveusersettings","document","getElementById","querySelectorAll","time","future"],"mappings":";;;;;;;;;;oFA6CqBA,OAAQC,gBAErBA,yBAgDqBA,oBAIrBC,eAAiBC,gBAAgBF,eAAc,kBAAsB,GACrEG,aAAeD,gBAAgBF,eAAc,gBAAoB,GAG9C,gBAAnBC,gBACAG,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOC,KAAON,iBACdK,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,iBAItDC,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOC,KAAOJ,eACdG,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,kBAMtDD,cAAcT,SAAQ,SAASC,QAC3BA,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,cAMvCI,WAAWZ,SAAQ,SAASa,cACpBC,iBAAmC,gBAAhBD,SAASX,IAA0D,KAAlCP,eAAc,YAClEoB,sBAAwC,qBAAhBF,SAASX,IAAoE,MAAvCP,eAAc,iBAC5EqB,gBAAkC,eAAhBH,SAASX,IAAwD,MAAjCP,eAAc,YAEhEmB,kBAAoBC,uBAAyBC,kBAC7CH,SAASI,WA/FbC,CAAoBvB,gBAIxBwB,WAAWC,iBAAiB,SAASC,qBAI7BC,yBA4HJC,SAAW,CAAEC,SAAU,EAAGC,WAAY,GACtCC,aAAc,KAIlBjB,cAAcT,SAAQ,SAASC,QACxBA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgB3B,OAAOC,IAC9CqB,SAAQ,WAAiBK,gBAAgB3B,OAAOC,IAChDwB,aAAc,MAIjBA,mBACOH,gBAIXxB,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,WAAiBK,gBAAgB3B,OAAOC,QAIxDS,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgB3B,OAAOC,QAG/CqB,SA5JaM,GACZC,4BAgGJP,SAAW,aAAgB,mBAAuB,aAAiB,UAEvEX,WAAWZ,SAAQ,SAASa,aACpBA,SAASP,eACFO,SAASX,QACP,cACDqB,SAAQ,YAAkB,YAEzB,mBACDA,SAAQ,iBAAuB,YAE9B,aACDA,SAAQ,WAAiB,MAOlCA,SAnHgBQ,wBAkBKrC,OAAQsC,eAAgBC,iBAAkBC,YAAaC,iBAAkBC,gBACjGC,cACJA,aAAeC,cAAKC,KAAK,CAAC,CACtBC,WAAY,uCACZC,KAAM,CACF/C,OAAQgD,SAAShD,QACjBsC,eAAgBA,eAChBC,iBAAkBA,iBAClBC,YAAaA,YACbC,iBAAkBA,iBAClBC,WAAYA,eAGbC,OA5BGM,CAAiBjD,OAAQ4B,UAAS,SAAcA,UAAS,WACxCQ,aAAY,YAAiBA,aAAY,iBAAsBA,aAAY,0EAhCpGX,WAAayB,SAASC,eAAe,8BAGrCpC,cAAgBmC,SAASE,iBAAiB,uBAC1C/C,mBAAqB6C,SAASE,iBAAiB,0BAC/CnC,iBAAmBiC,SAASE,iBAAiB,wBAG7ClC,WAAagC,SAASE,iBAAiB,gCAwLpClB,gBAAgB1B,WAEdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM,iBAUVL,gBAAgBkD,KAAMC,eACnBD,UACC,iBACM,kBACN,gBACGC,OACO,uBAEJ,2BACN,gBACGA,OACO,wBAEJ,4BACN,gBACGA,OACO,oBAEJ,wBACN,iBACGA,OACO,qBAGJ"} \ No newline at end of file +{"version":3,"file":"usersettings_save.min.js","sources":["../src/usersettings_save.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\r\n//\r\n// Moodle is free software: you can redistribute it and/or modify\r\n// it under the terms of the GNU General Public License as published by\r\n// the Free Software Foundation, either version 3 of the License, or\r\n// (at your option) any later version.\r\n//\r\n// Moodle is distributed in the hope that it will be useful,\r\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n// GNU General Public License for more details.\r\n//\r\n// You should have received a copy of the GNU General Public License\r\n// along with Moodle. If not, see .\r\n\r\n/**\r\n * Javascript to save the user settings in the database.\r\n *\r\n * This file implements 1 functionality:\r\n * - If the \"save settings\" button is pressed, store the settings in the database.\r\n *\r\n * @module block_townsquare/timefilter\r\n * @copyright 2024 Tamaro Walter\r\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\r\n */\r\n\r\nimport Ajax from 'core/ajax';\r\n\r\n// Get the save button for the user settings.\r\nconst savebutton = document.getElementById('ts_usersettings_savebutton');\r\n\r\n// Get the buttons from the time filter.\r\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\r\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\r\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\r\n\r\n// Get the checkboxes from the letter filter.\r\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\r\n\r\n/**\r\n * Init function\r\n *\r\n * @param {number} userid The id of the current user.\r\n * @param {object} settingsfromdb The settings from the database, if there are any.\r\n */\r\nexport function init(userid, settingsfromdb) {\r\n // When the page is loaded, set the settings from the database.\r\n if (settingsfromdb) {\r\n executeusersettings(settingsfromdb);\r\n }\r\n\r\n // Add event listener to the save button.\r\n savebutton.addEventListener('click', async function() {\r\n\r\n // First step: collect the current settings.\r\n // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes.\r\n let timespans = collecttimefiltersettings();\r\n let letterfilter = collectletterfiltersettings();\r\n\r\n // Second step: store the usersettings in the database.\r\n await saveusersettings(userid, timespans['timepast'], timespans['timefuture'],\r\n letterfilter['basicletter'], letterfilter['completionletter'], letterfilter['postletter']);\r\n });\r\n}\r\n\r\n/**\r\n * Function to save the user settings in the database.\r\n * @param {number} userid\r\n * @param {number} timefilterpast\r\n * @param {number} timefilterfuture\r\n * @param {number} basicletter\r\n * @param {number} completionletter\r\n * @param {number} postletter\r\n * @returns {Promise<*>}\r\n */\r\nasync function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) {\r\n let result ;\r\n result = await Ajax.call([{\r\n methodname: 'block_townsquare_record_usersettings',\r\n args: {\r\n userid: parseInt(userid),\r\n timefilterpast: timefilterpast,\r\n timefilterfuture: timefilterfuture,\r\n basicletter: basicletter,\r\n completionletter: completionletter,\r\n postletter: postletter\r\n },\r\n }]);\r\n\r\n //if (result === true) {\r\n\r\n //}\r\n //window.alert('Settings saved');\r\n // Show a success message.\r\n let el = document.getElementById('ts_usersettings_successlabel');\r\n el.style.opacity = 1;\r\n el.style.display = 'block';\r\n /*setInterval(function() {\r\n if (el.style.opacity > 0) {\r\n el.style.opacity -= 0.1;\r\n }\r\n }, 100);\r\n el.style.display = 'none';*/\r\n return result;\r\n}\r\n\r\n/**\r\n * Function to execute existing user settings when loading the townsquare.\r\n * @param {Object} settingsfromdb\r\n */\r\nfunction executeusersettings(settingsfromdb) {\r\n\r\n // First step: set the time filter settings.\r\n // Change the time into the correct radio button id.\r\n let futurebuttonid = converttimetoid(settingsfromdb['timefilterfuture'], true);\r\n let pastbuttonid = converttimetoid(settingsfromdb['timefilterpast'], false);\r\n\r\n // If the time span is a combination of past and future, go through the two radio buttons and activate the filter.\r\n if (futurebuttonid !== \"ts_time_all\") {\r\n futureradiobuttons.forEach(function(button) {\r\n if (button.id === futurebuttonid) {\r\n button.parentNode.classList.add('active');\r\n button.checked = true;\r\n button.dispatchEvent(new Event('change'));\r\n alltimebutton.forEach(function(alltimebutton) {\r\n alltimebutton.checked = false;\r\n alltimebutton.parentNode.classList.remove('active');\r\n });\r\n }\r\n });\r\n pastradiobuttons.forEach(function(button) {\r\n if (button.id === pastbuttonid) {\r\n button.parentNode.classList.add('active');\r\n button.checked = true;\r\n button.dispatchEvent(new Event('change'));\r\n alltimebutton.forEach(function(alltimebutton) {\r\n alltimebutton.checked = false;\r\n alltimebutton.parentNode.classList.remove('active');\r\n });\r\n }\r\n });\r\n } else {\r\n // If the time span is set to all time, activate the all time button.\r\n alltimebutton.forEach(function(button) {\r\n button.parentNode.classList.add('active');\r\n button.checked = true;\r\n button.dispatchEvent(new Event('change'));\r\n });\r\n }\r\n\r\n // Second step: set the letter filter settings.\r\n // Per default all checkboxes are checked. If the setting is 0, uncheck the checkbox.\r\n checkboxes.forEach(function(checkbox) {\r\n let basiclettercheck = checkbox.id === 'basicletter' && settingsfromdb['basicletter'] === \"\";\r\n let completionlettercheck = checkbox.id === 'completionletter' && settingsfromdb['completionletter'] === \"0\";\r\n let postlettercheck = checkbox.id === 'postletter' && settingsfromdb['postletter'] === \"0\";\r\n\r\n if (basiclettercheck || completionlettercheck || postlettercheck) {\r\n checkbox.click();\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Function to collect the letter filter settings.\r\n * @returns {{basicletter: number, completionletter: number, postletter: number}}\r\n */\r\nfunction collectletterfiltersettings() {\r\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\r\n\r\n checkboxes.forEach(function(checkbox) {\r\n if (checkbox.checked) {\r\n switch(checkbox.id) {\r\n case \"basicletter\":\r\n settings['basicletter'] = 1;\r\n break;\r\n case \"completionletter\":\r\n settings['completionletter'] = 1;\r\n break;\r\n case \"postletter\":\r\n settings['postletter'] = 1;\r\n break;\r\n\r\n }\r\n }\r\n });\r\n // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit.\r\n return settings;\r\n}\r\n\r\n/**\r\n * Function to collect the time filter settings.\r\n * @returns {{timepast: number, timefuture: number}}\r\n */\r\nfunction collecttimefiltersettings() {\r\n let settings = { timepast: 0, timefuture: 0};\r\n let settingsset = false;\r\n\r\n // Get the relevant time spans of the time filter.\r\n // Check if the alltimebutton is set.\r\n alltimebutton.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timepast'] = convertidtotime(button.id);\r\n settings['timefuture'] = convertidtotime(button.id);\r\n settingsset = true;\r\n }\r\n });\r\n\r\n if (settingsset) {\r\n return settings;\r\n }\r\n\r\n // If the alltimebutton is not set, check which of the future/past buttons is set.\r\n futureradiobuttons.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timefuture'] = convertidtotime(button.id);\r\n }\r\n });\r\n\r\n pastradiobuttons.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timepast'] = convertidtotime(button.id);\r\n }\r\n });\r\n return settings;\r\n}\r\n\r\n\r\n/**\r\n * Function to convert the radio button id to a useable time span.\r\n * @param {string} id The id of the radio button\r\n * @returns {number}\r\n */\r\nfunction convertidtotime(id) {\r\n // TODO: Please use global functions if possible.\r\n switch(id) {\r\n case \"ts_time_all\":\r\n return 15778463;\r\n case \"ts_time_next_twodays\":\r\n case \"ts_time_last_twodays\":\r\n return 172800;\r\n case \"ts_time_next_fivedays\":\r\n case \"ts_time_last_fivedays\":\r\n return 432000;\r\n case \"ts_time_next_week\":\r\n case \"ts_time_last_week\":\r\n return 604800;\r\n case \"ts_time_next_month\":\r\n case \"ts_time_last_month\":\r\n return 2592000;\r\n }\r\n}\r\n\r\n/**\r\n * Function to convert the time span to a radio button id.\r\n * @param {string} time\r\n * @param {boolean} future\r\n * @returns {string}\r\n */\r\nfunction converttimetoid(time, future) {\r\n switch (time) {\r\n case \"15778463\":\r\n return \"ts_time_all\";\r\n case \"172800\":\r\n if (future) {\r\n return \"ts_time_next_twodays\";\r\n }\r\n return \"ts_time_past_twodays\";\r\n case \"432000\":\r\n if (future) {\r\n return \"ts_time_next_fivedays\";\r\n }\r\n return \"ts_time_last_fivedays\";\r\n case \"604800\":\r\n if (future) {\r\n return \"ts_time_next_week\";\r\n }\r\n return \"ts_time_last_week\";\r\n case \"2592000\":\r\n if (future) {\r\n return \"ts_time_next_month\";\r\n\r\n }\r\n return \"ts_time_last_month\";\r\n }\r\n}\r\n"],"names":["userid","settingsfromdb","futurebuttonid","converttimetoid","pastbuttonid","futureradiobuttons","forEach","button","id","parentNode","classList","add","checked","dispatchEvent","Event","alltimebutton","remove","pastradiobuttons","checkboxes","checkbox","basiclettercheck","completionlettercheck","postlettercheck","click","executeusersettings","savebutton","addEventListener","async","timespans","settings","timepast","timefuture","settingsset","contains","convertidtotime","collecttimefiltersettings","letterfilter","collectletterfiltersettings","timefilterpast","timefilterfuture","basicletter","completionletter","postletter","result","Ajax","call","methodname","args","parseInt","el","document","getElementById","style","opacity","display","saveusersettings","querySelectorAll","time","future"],"mappings":";;;;;;;;;;oFA6CqBA,OAAQC,gBAErBA,yBA+DqBA,oBAIrBC,eAAiBC,gBAAgBF,eAAc,kBAAsB,GACrEG,aAAeD,gBAAgBF,eAAc,gBAAoB,GAG9C,gBAAnBC,gBACAG,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOC,KAAON,iBACdK,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,iBAItDC,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOC,KAAOJ,eACdG,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,kBAMtDD,cAAcT,SAAQ,SAASC,QAC3BA,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,cAMvCI,WAAWZ,SAAQ,SAASa,cACpBC,iBAAmC,gBAAhBD,SAASX,IAA0D,KAAlCP,eAAc,YAClEoB,sBAAwC,qBAAhBF,SAASX,IAAoE,MAAvCP,eAAc,iBAC5EqB,gBAAkC,eAAhBH,SAASX,IAAwD,MAAjCP,eAAc,YAEhEmB,kBAAoBC,uBAAyBC,kBAC7CH,SAASI,WA9GbC,CAAoBvB,gBAIxBwB,WAAWC,iBAAiB,SAASC,qBAI7BC,yBA2IJC,SAAW,CAAEC,SAAU,EAAGC,WAAY,GACtCC,aAAc,KAIlBjB,cAAcT,SAAQ,SAASC,QACxBA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgB3B,OAAOC,IAC9CqB,SAAQ,WAAiBK,gBAAgB3B,OAAOC,IAChDwB,aAAc,MAIjBA,mBACOH,gBAIXxB,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,WAAiBK,gBAAgB3B,OAAOC,QAIxDS,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgB3B,OAAOC,QAG/CqB,SA3KaM,GACZC,4BA+GJP,SAAW,aAAgB,mBAAuB,aAAiB,UAEvEX,WAAWZ,SAAQ,SAASa,aACpBA,SAASP,eACFO,SAASX,QACP,cACDqB,SAAQ,YAAkB,YAEzB,mBACDA,SAAQ,iBAAuB,YAE9B,aACDA,SAAQ,WAAiB,MAOlCA,SAlIgBQ,wBAkBKrC,OAAQsC,eAAgBC,iBAAkBC,YAAaC,iBAAkBC,gBACjGC,OACJA,aAAeC,cAAKC,KAAK,CAAC,CACtBC,WAAY,uCACZC,KAAM,CACF/C,OAAQgD,SAAShD,QACjBsC,eAAgBA,eAChBC,iBAAkBA,iBAClBC,YAAaA,YACbC,iBAAkBA,iBAClBC,WAAYA,mBAShBO,GAAKC,SAASC,eAAe,uCACjCF,GAAGG,MAAMC,QAAU,EACnBJ,GAAGG,MAAME,QAAU,QAOZX,OA3CGY,CAAiBvD,OAAQ4B,UAAS,SAAcA,UAAS,WACxCQ,aAAY,YAAiBA,aAAY,iBAAsBA,aAAY,0EAhCpGX,WAAayB,SAASC,eAAe,8BAGrCpC,cAAgBmC,SAASM,iBAAiB,uBAC1CnD,mBAAqB6C,SAASM,iBAAiB,0BAC/CvC,iBAAmBiC,SAASM,iBAAiB,wBAG7CtC,WAAagC,SAASM,iBAAiB,gCAuMpCtB,gBAAgB1B,WAEdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM,iBAUVL,gBAAgBsD,KAAMC,eACnBD,UACC,iBACM,kBACN,gBACGC,OACO,uBAEJ,2BACN,gBACGA,OACO,wBAEJ,4BACN,gBACGA,OACO,oBAEJ,wBACN,iBACGA,OACO,qBAGJ"} \ No newline at end of file diff --git a/amd/src/usersettings_save.js b/amd/src/usersettings_save.js index 62d40e1..7a8d964 100644 --- a/amd/src/usersettings_save.js +++ b/amd/src/usersettings_save.js @@ -86,6 +86,21 @@ async function saveusersettings(userid, timefilterpast, timefilterfuture, basicl postletter: postletter }, }]); + + //if (result === true) { + + //} + //window.alert('Settings saved'); + // Show a success message. + let el = document.getElementById('ts_usersettings_successlabel'); + el.style.opacity = 1; + el.style.display = 'block'; + /*setInterval(function() { + if (el.style.opacity > 0) { + el.style.opacity -= 0.1; + } + }, 100); + el.style.display = 'none';*/ return result; } diff --git a/lang/en/block_townsquare.php b/lang/en/block_townsquare.php index 7afcdee..0c1b260 100644 --- a/lang/en/block_townsquare.php +++ b/lang/en/block_townsquare.php @@ -1,83 +1,84 @@ -. - -/** - * Plugin strings are defined here. - * - * @package block_townsquare - * @category string - * @copyright 2023 Tamaro Walter - * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -// Core strings for the installation. -$string['pluginname'] = 'Townsquare block'; -$string['pluginname'] = 'Town Square'; -$string['pluginname:addinstance'] = 'Add the Town Square block'; -$string['pluginname:myaddinstance'] = 'Add the Town Square block to the dashboard'; - -// Error strings. -$string['invalidlettertype'] = 'Invalid function parameter, please use a valid letter type'; - -// Mustache templates strings. -$string['completionletterorigin'] = '{$a->modulename} should be completed until {$a->date}'; -$string['basicletterorigin'] = 'A notification from {$a->modulename}:'; -$string['postletternotification'] = 'New {$a->modulename} post!'; -$string['postletterorigin'] = '{$a->authorname} posted in {$a->instancename} -> {$a->discussionname}:'; -$string['orientationmarkercontent'] = 'Hi {$a->username}, welcome to townsquare! Today is the {$a->date}'; - -// Side panel filter strings. - -// Filter headers. -$string['coursefilter'] = 'Course filter'; -$string['timefilter'] = 'Time filter'; -$string['letterfilter'] = 'Letter filter'; - -// Time filter options. -$string['allnotifications'] = 'All notifications'; -$string['nexttwodaysnotifications'] = 'Next two days'; -$string['nextfivedaysnotifications'] = 'Next five days'; -$string['nextweeknotifications'] = 'Next week'; -$string['nextmonthnotifications'] = 'Next month'; -$string['lasttwodaysnotifications'] = 'last two days'; -$string['lastfivedaysnotifications'] = 'last five days'; -$string['lastweeknotifications'] = 'Last week'; -$string['lastmonthnotifications'] = 'Last month'; - -// Letter filter options. -$string['basicletters'] = 'Basic letters'; -$string['completionletters'] = 'Activity Completions'; -$string['postletters'] = 'Forum Posts'; - -// Save button strings. -$string['savebutton'] = 'Save settings'; -$string['savehelpicontext'] = 'Save Settings for the future'; - -// Letter strings. -$string['invalidmodulename'] = 'Module name is unknown or not supported'; - -// Setting strings. -$string['basiclettercolor'] = 'Color for basic letters'; -$string['postlettercolor'] = 'Color for post letters'; -$string['completionlettercolor'] = 'Color for activity completion letters'; -$string['orientationmarkercolor'] = 'Color for the orientation marker'; - -$string['configbasiclettercolor'] = 'Configuration for the color of the basic notification letters'; -$string['configpostlettercolor'] = 'Configuration for the color of the post letters'; -$string['configcompletionlettercolor'] = 'Configuration for the color of the activity completion letters'; -$string['configorientationmarkercolor'] = 'Configuration for the color of the orientation marker'; +. + +/** + * Plugin strings are defined here. + * + * @package block_townsquare + * @category string + * @copyright 2023 Tamaro Walter + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +// Core strings for the installation. +$string['pluginname'] = 'Townsquare block'; +$string['pluginname'] = 'Town Square'; +$string['pluginname:addinstance'] = 'Add the Town Square block'; +$string['pluginname:myaddinstance'] = 'Add the Town Square block to the dashboard'; + +// Error strings. +$string['invalidlettertype'] = 'Invalid function parameter, please use a valid letter type'; + +// Mustache templates strings. +$string['completionletterorigin'] = '{$a->modulename} should be completed until {$a->date}'; +$string['basicletterorigin'] = 'A notification from {$a->modulename}:'; +$string['postletternotification'] = 'New {$a->modulename} post!'; +$string['postletterorigin'] = '{$a->authorname} posted in {$a->instancename} -> {$a->discussionname}:'; +$string['orientationmarkercontent'] = 'Hi {$a->username}, welcome to townsquare! Today is the {$a->date}'; + +// Side panel filter strings. + +// Filter headers. +$string['coursefilter'] = 'Course filter'; +$string['timefilter'] = 'Time filter'; +$string['letterfilter'] = 'Letter filter'; + +// Time filter options. +$string['allnotifications'] = 'All notifications'; +$string['nexttwodaysnotifications'] = 'Next two days'; +$string['nextfivedaysnotifications'] = 'Next five days'; +$string['nextweeknotifications'] = 'Next week'; +$string['nextmonthnotifications'] = 'Next month'; +$string['lasttwodaysnotifications'] = 'last two days'; +$string['lastfivedaysnotifications'] = 'last five days'; +$string['lastweeknotifications'] = 'Last week'; +$string['lastmonthnotifications'] = 'Last month'; + +// Letter filter options. +$string['basicletters'] = 'Basic letters'; +$string['completionletters'] = 'Activity Completions'; +$string['postletters'] = 'Forum Posts'; + +// Save button strings. +$string['savebutton'] = 'Save settings'; +$string['savehelpicontext'] = 'Save Settings for the future'; +$string['savemessage'] = 'Settings successfully saved!'; + +// Letter strings. +$string['invalidmodulename'] = 'Module name is unknown or not supported'; + +// Setting strings. +$string['basiclettercolor'] = 'Color for basic letters'; +$string['postlettercolor'] = 'Color for post letters'; +$string['completionlettercolor'] = 'Color for activity completion letters'; +$string['orientationmarkercolor'] = 'Color for the orientation marker'; + +$string['configbasiclettercolor'] = 'Configuration for the color of the basic notification letters'; +$string['configpostlettercolor'] = 'Configuration for the color of the post letters'; +$string['configcompletionlettercolor'] = 'Configuration for the color of the activity completion letters'; +$string['configorientationmarkercolor'] = 'Configuration for the color of the orientation marker'; diff --git a/styles.css b/styles.css index 19f24fc..09426a0 100644 --- a/styles.css +++ b/styles.css @@ -1,82 +1,87 @@ -/* Style for the blockcontent template*/ -.townsquare_sidepanel.col-md-3 { - background-color: #eee; - border-radius: 0.5rem; - padding-left: 0.0rem; - padding-right: 0.0rem; -} - -.townsquare_content { - max-height: 750px; - border-radius: 0.5rem; - overflow: scroll; - max-width: 100%; - overflow-x: hidden; -} - -/* Style for the side panel filter */ -.ts_usersettings_save { - display: flex; -} - -.ts_usersettings_button { - flex: 1; -} - -/* Style for all letter or content templates */ - -.townsquareletter_header.card-header { - padding-top: 0.4rem; - padding-bottom: 0.4rem; -} - -.townsquareletter_body.card-body { - padding-top: 0.7rem; - padding-bottom: 0.6rem; -} - -.townsquareletter_top { - display: flex; -} - -.townsquareletter_course { - flex: 1; -} - -.townsquareletter_courselink:hover { - color: #fff; - text-decoration: underline; -} -.townsquareletter_courselink { - color: #fff; - text-decoration: none; -} - -.townsquareletter_course, -.townsquareletter_date { - color: #fff; - text-shadow: 1px 1px 2px #000; -} - -.townsquare_showmore { - cursor: pointer; -} - -/* Styles for individual letters */ - -/* basicletter Style*/ - -/* postletter Style */ - -.postletter_origin { - margin-bottom: 0.4rem; -} - -/* actvitiycompletionletter Style*/ - -/* Style for the orientation marker */ - -.orientationmarker_body.card-body { - padding-top: 0.6rem; -} -/*# sourceMappingURL=styles.css.map */ +/* Style for the blockcontent template*/ +.townsquare_sidepanel.col-md-3 { + background-color: #eee; + border-radius: 0.5rem; + padding-left: 0.0rem; + padding-right: 0.0rem; +} + +.townsquare_content { + max-height: 750px; + border-radius: 0.5rem; + overflow: scroll; + max-width: 100%; + overflow-x: hidden; +} + +/* Style for the side panel filter */ +.ts_usersettings_save { + display: flex; +} + +.ts_usersettings_button { + flex: 1; +} + +.ts_usersettings_message { + display: none; + opacity: 1.0; +} + +/* Style for all letter or content templates */ + +.townsquareletter_header.card-header { + padding-top: 0.4rem; + padding-bottom: 0.4rem; +} + +.townsquareletter_body.card-body { + padding-top: 0.7rem; + padding-bottom: 0.6rem; +} + +.townsquareletter_top { + display: flex; +} + +.townsquareletter_course { + flex: 1; +} + +.townsquareletter_courselink:hover { + color: #fff; + text-decoration: underline; +} +.townsquareletter_courselink { + color: #fff; + text-decoration: none; +} + +.townsquareletter_course, +.townsquareletter_date { + color: #fff; + text-shadow: 1px 1px 2px #000; +} + +.townsquare_showmore { + cursor: pointer; +} + +/* Styles for individual letters */ + +/* basicletter Style*/ + +/* postletter Style */ + +.postletter_origin { + margin-bottom: 0.4rem; +} + +/* actvitiycompletionletter Style*/ + +/* Style for the orientation marker */ + +.orientationmarker_body.card-body { + padding-top: 0.6rem; +} +/*# sourceMappingURL=styles.css.map */ diff --git a/templates/sidepanel.mustache b/templates/sidepanel.mustache index 2535573..e1ca3a7 100644 --- a/templates/sidepanel.mustache +++ b/templates/sidepanel.mustache @@ -1,139 +1,142 @@ -{{! - 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 block_townsquare/blockcontent - - This template renders the side panel with the filters for the townsquare content. -}} -

-
-
-

- -

-
- -
-
- {{#courses}} -
- - -
- {{/courses}} -
-
-
- -
-
-

- -

-
-
-
-
- -
- -
- - - - -
- -
- - - -
- -
-
-
-
- -
-
-

- -

-
-
-
-
- - -
-
- - -
-
- - -
-
-
-
- -
-
- -
-
- {{#helpicon}} - {{>core/help_icon}} - {{/helpicon}} -
-
- +{{! + 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 block_townsquare/blockcontent + + This template renders the side panel with the filters for the townsquare content. +}} +
+
+
+

+ +

+
+ +
+
+ {{#courses}} +
+ + +
+ {{/courses}} +
+
+
+ +
+
+

+ +

+
+
+
+
+ +
+ +
+ + + + +
+ +
+ + + +
+ +
+
+
+
+ +
+
+

+ +

+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ +
+
+ +
+
+ {{#helpicon}} + {{>core/help_icon}} + {{/helpicon}} +
+
+
+ {{#str}}savemessage, block_townsquare{{/str}} +
+
\ No newline at end of file From 4bef8d6e091d5e24c263c25c44ab2e3cc0d0d77a Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Mon, 18 Mar 2024 15:52:22 +0100 Subject: [PATCH 036/123] codecleaning --- classes/contentcontroller.php | 246 +++++----- classes/townsquareevents.php | 794 +++++++++++++++---------------- db/services.php | 70 +-- externallib.php | 233 ++++----- lang/en/block_townsquare.php | 168 +++---- tests/calendarevents_test.php | 2 +- tests/contentcontroller_test.php | 2 +- tests/postevents_test.php | 2 +- 8 files changed, 760 insertions(+), 757 deletions(-) diff --git a/classes/contentcontroller.php b/classes/contentcontroller.php index 111d292..1ca5449 100644 --- a/classes/contentcontroller.php +++ b/classes/contentcontroller.php @@ -1,123 +1,123 @@ -. - -/** - * Letter Controller of block_townsquare - * - * @package block_townsquare - * @copyright 2023 Tamaro Walter - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -namespace block_townsquare; - -/** - * Letter Controller Class. - * - * This Class controls access to the townsquareevents class. It retrieves all important events and builds the letters. - * - * @package block_townsquare - * @copyright 2023 Tamaro Walter - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class contentcontroller { - - /** @var object Class to retrieve events */ - public object $townsquareevents; - - /** @var array events that are relevant for the townsquare */ - public array $events; - - /** @var array letters and other content that will be shown to the user */ - public array $content; - - /** @var array courses that show content in townsquare (not the same as enrolled courses) */ - public array $courses; - - /** - * Constructor for the controller. - */ - public function __construct() { - $this->townsquareevents = new townsquareevents(); - $this->courses = []; - $this->content = []; - $this->build_content(); - } - - // Core functions. - - /** - * Builds the content from events. - * @return array - */ - public function build_content(): array { - $this->events = $this->townsquareevents->get_all_events_sorted(); - - $orientationmarkerset = false; - $index = 0; - $time = time(); - $appearedcourses = []; - // Build a letter for each event. - foreach ($this->events as $event) { - // Display a orientation marker on the current date between the other events. - if (!$orientationmarkerset && isset($event->eventtype) && ( - ($event->eventtype != 'post' && $event->timestart <= $time) || - ($event->eventtype == 'post' && $event->postcreated <= $time))) { - - $orientationmarkerset = true; - $tempcontent = new orientation_marker($index, $time); - $this->content[$index] = $tempcontent->export_data(); - $index++; - continue; - } - if (isset($event->eventtype) && $event->eventtype == 'post') { - $templetter = new letter\post_letter($index, $event); - } else if (isset($event->eventtype) && $event->eventtype == 'expectcompletionon') { - $templetter = new letter\activitycompletion_letter($index, $event); - } else { - $templetter = new letter\letter($index, $event->courseid, $event->modulename, $event->instancename, - $event->name, $event->timestart, $event->coursemoduleid); - } - $this->content[$index] = $templetter->export_letter(); - - // Collect the courses shown in the townsquare to be able to filter them afterwards. - if (!array_key_exists($this->content[$index]['courseid'], $appearedcourses)) { - $this->courses[] = ['courseid' => $this->content[$index]['courseid'], - 'coursename' => $this->content[$index]['coursename'], ]; - $appearedcourses[$event->courseid] = true; - } - $index++; - } - return $this->content; - } - - // Getter. - - /** - * Getter for the content - * @return array - */ - public function get_content():array { - return $this->content; - } - - /** - * Getter for the events - * @return array - */ - public function get_events():array { - return $this->events; - } -} +. + +/** + * Letter Controller of block_townsquare + * + * @package block_townsquare + * @copyright 2023 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace block_townsquare; + +/** + * Letter Controller Class. + * + * This Class controls access to the townsquareevents class. It retrieves all important events and builds the letters. + * + * @package block_townsquare + * @copyright 2023 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class contentcontroller { + + /** @var object Class to retrieve events */ + public object $townsquareevents; + + /** @var array events that are relevant for the townsquare */ + public array $events; + + /** @var array letters and other content that will be shown to the user */ + public array $content; + + /** @var array courses that show content in townsquare (not the same as enrolled courses) */ + public array $courses; + + /** + * Constructor for the controller. + */ + public function __construct() { + $this->townsquareevents = new townsquareevents(); + $this->courses = []; + $this->content = []; + $this->build_content(); + } + + // Core functions. + + /** + * Builds the content from events. + * @return array + */ + public function build_content(): array { + $this->events = $this->townsquareevents->get_all_events_sorted(); + + $orientationmarkerset = false; + $index = 0; + $time = time(); + $appearedcourses = []; + // Build a letter for each event. + foreach ($this->events as $event) { + // Display a orientation marker on the current date between the other events. + if (!$orientationmarkerset && isset($event->eventtype) && ( + ($event->eventtype != 'post' && $event->timestart <= $time) || + ($event->eventtype == 'post' && $event->postcreated <= $time))) { + + $orientationmarkerset = true; + $tempcontent = new orientation_marker($index, $time); + $this->content[$index] = $tempcontent->export_data(); + $index++; + continue; + } + if (isset($event->eventtype) && $event->eventtype == 'post') { + $templetter = new letter\post_letter($index, $event); + } else if (isset($event->eventtype) && $event->eventtype == 'expectcompletionon') { + $templetter = new letter\activitycompletion_letter($index, $event); + } else { + $templetter = new letter\letter($index, $event->courseid, $event->modulename, $event->instancename, + $event->name, $event->timestart, $event->coursemoduleid); + } + $this->content[$index] = $templetter->export_letter(); + + // Collect the courses shown in the townsquare to be able to filter them afterwards. + if (!array_key_exists($this->content[$index]['courseid'], $appearedcourses)) { + $this->courses[] = ['courseid' => $this->content[$index]['courseid'], + 'coursename' => $this->content[$index]['coursename'], ]; + $appearedcourses[$event->courseid] = true; + } + $index++; + } + return $this->content; + } + + // Getter. + + /** + * Getter for the content + * @return array + */ + public function get_content():array { + return $this->content; + } + + /** + * Getter for the events + * @return array + */ + public function get_events():array { + return $this->events; + } +} diff --git a/classes/townsquareevents.php b/classes/townsquareevents.php index cfc8e2a..c5312a4 100644 --- a/classes/townsquareevents.php +++ b/classes/townsquareevents.php @@ -1,397 +1,397 @@ -. - -/** - * Class to get relevant events from courses the user is enrolled to.. - * - * @package block_townsquare - * @copyright 2023 Tamaro Walter - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -namespace block_townsquare; - -defined('MOODLE_INTERNAL') || die(); - -use context_module; -use dml_exception; - -global $CFG; -require_once($CFG->dirroot . '/calendar/lib.php'); -require_once($CFG->dirroot . '/blocks/townsquare/locallib.php'); -/** - * Class to get events and posts that will be shown in the townsquare block.. - * - * @package block_townsquare - * @copyright 2023 Tamaro Walter - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class townsquareevents { - - /** @var int timestamp of the current time */ - public int $timenow; - - /** @var int timestamp from where the events should be searched */ - public int $timestart; - - /** @var int timestamp until where the events should be searched */ - public int $timeend; - - /** @var array ids of the courses where the events should be searched */ - public array $courses; - - /** - * Constructor of the townsquareevents class. - * Events will be searched in the timespan of 6 months in the past and 6 months in the future. - */ - public function __construct() { - $this->timenow = time(); - $this->timestart = $this->timenow - 15768000; - $this->timeend = $this->timenow + 15768000; - $this->courses = $this->get_courses(); - } - - /** - * Retrieves calendar and post events, merges and sorts them. - * @return array - */ - public function get_all_events_sorted(): array { - $calendarevents = $this->get_calendarevents(); - $postevents = $this->get_postevents(); - - // Merge the events in a sorted order. - $events = []; - $numberofevents = count($calendarevents) + count($postevents); - for ($i = 0; $i < $numberofevents; $i++) { - if (current($calendarevents) && current($postevents)) { - if (current($calendarevents)->timestart > current($postevents)->postcreated) { - $events[$i] = current($calendarevents); - next($calendarevents); - } else { - $events[$i] = current($postevents); - next($postevents); - } - } else if (current($calendarevents)) { - $events[$i] = current($calendarevents); - next($calendarevents); - } else { - $events[$i] = current($postevents); - next($postevents); - } - } - - return $events; - } - - /** - * Function to get events from that are in the calendar for the current user. - * - * The events are sorted in descending order by time created (newest event first) - * @return array - */ - public function get_calendarevents(): array { - global $DB; - - // Get all events from the last six months and the next six months. - $calendarevents = $this->get_events_from_db($this->timestart, $this->timeend, $this->courses); - - // Filter the events and add the coursemoduleid. - foreach ($calendarevents as $calendarevent) { - // Filter out events that are not relevant for the user. - if ($this->filter_availability($calendarevent) || - ($calendarevent->modulename == "assign" && $this->filter_assignment($calendarevent)) || - ($calendarevent->eventtype == "expectcompletionon" && $this->filter_activitycompletions($calendarevent))) { - unset($calendarevents[$calendarevent->id]); - continue; - } - - // Add the name of the instance to the event. - $calendarevent->instancename = $DB->get_field($calendarevent->modulename, 'name', ['id' => $calendarevent->instance]); - } - - return $calendarevents; - } - - /** - * Function to get the newest posts from modules like the forum or moodleoverflow. - * - * The events are sorted in descending order by time created (newest event first) - * @return array; - */ - public function get_postevents(): array { - global $DB; - - $forumposts = []; - $moodleoverflowposts = []; - - // Check which modules are installed and activated and get their data. - if ($DB->get_record('modules', ['name' => 'forum', 'visible' => 1])) { - $forumposts = $this->get_posts_from_db('forum', $this->courses, $this->timestart); - } - - if ($DB->get_record('modules', ['name' => 'moodleoverflow', 'visible' => 1])) { - $moodleoverflowposts = $this->get_posts_from_db('moodleoverflow', $this->courses, $this->timestart); - } - - if (empty($forumposts) && empty($moodleoverflowposts)) { - return []; - } - - // Merge the posts in a sorted order. While merging, filter out irrelevant posts and add relevant attributes if necessary. - $posts = []; - $numberofposts = count($forumposts) + count($moodleoverflowposts); - reset($forumposts); - reset($moodleoverflowposts); - for ($i = 0; $i < $numberofposts; $i++) { - // Filter unavailable posts. - // Iterate until the first post that is available. Decrement the number of posts each time a post is filtered. - while (current($forumposts) && $this->filter_availability(current($forumposts))) { - next($forumposts); - $numberofposts--; - } - while (current($moodleoverflowposts) && $this->filter_availability(current($moodleoverflowposts))) { - next($moodleoverflowposts); - $numberofposts--; - } - // If there no posts left after filtering, break. - if ($i >= $numberofposts) { - break; - } - - // Merge. - if (current($forumposts) && current($moodleoverflowposts)) { - if (current($forumposts)->postcreated > current($moodleoverflowposts)->postcreated) { - $posts[$i] = current($forumposts); - next($forumposts); - } else { - $posts[$i] = current($moodleoverflowposts); - next($moodleoverflowposts); - } - } else if (current($forumposts)) { - $posts[$i] = current($forumposts); - next($forumposts); - } else { - $posts[$i] = current($moodleoverflowposts); - next($moodleoverflowposts); - } - } - - // Add an event type to the posts and add the anonymous setting to the moodleoverflow posts. Then return it. - return $posts; - } - - // Helper functions. - - /** - * Searches for posts in the forum or moodleoverflow module. - * The sql query makes sure that the modules are installed and available.. - * This is a helper function for get_postevents(). - * @param string $modulename The name of the module, is 'forum' or 'moodleoverflow'. - * @param array $courses The ids of the courses where the posts should be searched. - * @param int $timestart The timestamp from where the posts should be searched. - * @return array - */ - private function get_posts_from_db($modulename, $courses, $timestart): array { - global $DB; - // Prepare params for sql statement. - if ($courses == []) { - return []; - } - list($insqlcourses, $inparamscourses) = $DB->get_in_or_equal($courses, SQL_PARAMS_NAMED); - $params = ['courses' => $courses, 'timestart' => $timestart] + $inparamscourses; - // Set begin of sql statement. - $begin = "SELECT (ROW_NUMBER() OVER (ORDER BY posts.id)) AS row_num, "; - - // Set the select part of the sql that is always the same. - $middle = "'post' AS eventtype, - cm.id AS coursemoduleid, - cm.availability AS availability, - module.name AS instancename, - discuss.course AS courseid, - discuss.userid AS discussionuserid, - discuss.name AS discussionsubject, - u.firstname AS postuserfirstname, - u.lastname AS postuserlastname, - posts.id AS postid, - posts.discussion AS postdiscussion, - posts.parent AS postparentid, - posts.userid AS postuserid, - posts.created AS postcreated, - posts.message AS postmessage "; - - // Extend the strings for the 2 module cases. - if ($modulename == 'forum') { - $begin .= "'forum' AS modulename, module.id AS instanceid,"; - $middle .= "FROM {forum_posts} posts - JOIN {forum_discussions} discuss ON discuss.id = posts.discussion - JOIN {forum} module ON module.id = discuss.forum - JOIN {modules} modules ON modules.name = 'forum' "; - - } else if ($modulename == 'moodleoverflow') { - $begin .= "'moodleoverflow' AS modulename, module.id AS instanceid, module.anonymous AS anonymoussetting, "; - $middle .= "FROM {moodleoverflow_posts} posts - JOIN {moodleoverflow_discussions} discuss ON discuss.id = posts.discussion - JOIN {moodleoverflow} module ON module.id = discuss.moodleoverflow - JOIN {modules} modules ON modules.name = 'moodleoverflow' "; - } - - // Extension of the middle string. - $middle .= "JOIN {user} u ON u.id = posts.userid - JOIN {course_modules} cm ON (cm.course = module.course AND cm.module = modules.id - AND cm.instance = module.id) "; - - // Set the where clause of the string. - $end = "WHERE discuss.course $insqlcourses - AND posts.created > :timestart - AND cm.visible = 1 - AND modules.visible = 1 - ORDER BY posts.created DESC;"; - - // Concatenate all strings. - $sql = $begin . $middle . $end; - - // Get all posts. - return $DB->get_records_sql($sql, $params); - } - - /** - * Searches for events in the events table, that are relevant to the timeline. - * This is a helper function for get_calendarevents(). - * @param int $timestart The time from where the events should be searched. Not equal to timestart in the database events table. - * @param int $timeend The time until where the events should be searched. - * @param array $courses The ids of the courses where the events should be searched. - * @return array - * @throws dml_exception - */ - private function get_events_from_db($timestart, $timeend, $courses): array { - global $DB; - - // As there are no events without courses, return an empty array. - if ($courses == []) { - return []; - } - - // Due to compatability reasons, only events from supported modules are shown. - // Supported modules are: core modules and custom additional modules. - $coremodules = ['assign', 'book', 'chat', 'choice', 'data', 'feedback', 'folder', 'forum', 'glossary', 'h5pactivity', - 'imscp', 'label', 'lesson', 'lti', 'page', 'quiz', 'resource', 'scorm', 'survey', 'url', 'wiki', 'workshop', ]; - $additionalmodules = ['moodleoverflow', 'ratingallocate']; - $modules = $coremodules + $additionalmodules; - - // Prepare params for sql statement. - list($insqlcourses, $inparamscourses) = $DB->get_in_or_equal($courses, SQL_PARAMS_NAMED); - list($insqlmodules, $inparamsmodules) = $DB->get_in_or_equal($modules, SQL_PARAMS_NAMED); - $params = ['timestart' => $timestart, 'timeduration' => $timestart, - 'timeend' => $timeend, 'courses' => $courses, ] + $inparamscourses + $inparamsmodules; - - // Set the sql statement. - $sql = "SELECT e.id, e.name, e.courseid, cm.id AS coursemoduleid, cm.availability AS availability, e.groupid, e.userid, - e.modulename, e.instance, e.eventtype, e.timestart, e.visible - FROM {event} e - JOIN {modules} m ON e.modulename = m.name - JOIN {course_modules} cm ON (cm.course = e.courseid AND cm.module = m.id AND cm.instance = e.instance) - WHERE (e.timestart >= :timestart OR e.timestart+e.timeduration > :timeduration) - AND e.timestart <= :timeend - AND e.courseid $insqlcourses - AND e.modulename $insqlmodules - AND m.visible = 1 - AND (e.name NOT LIKE '" .'0'. "' AND e.eventtype NOT LIKE '" .'0'. "' ) - AND (e.instance <> 0 AND e.visible = 1) - ORDER BY e.timestart DESC"; - - // Get all events. - return $DB->get_records_sql($sql, $params); - } - - /** - * Gets the id of all courses where the current user is enrolled - * @return array - */ - private function get_courses(): array { - global $USER; - - $enrolledcourses = enrol_get_all_users_courses($USER->id, true); - $courses = []; - foreach ($enrolledcourses as $enrolledcourse) { - $courses[] = $enrolledcourse->id; - } - - return $courses; - } - - /** - * Filter that checks if the event needs to be filtered out for the current user because it is unavailable. - * Applies to restriction that are defined in the module setting (restrict access). - * @param object $event The event that is checked. - * @return bool true if the event needs to filtered out, false if not. - */ - private function filter_availability($event): bool { - // If there is no restriction defined, the event is available. - if ($event->availability == null) { - return false; - } - - // If there is a restriction, check if it applies to the user. - $modinfo = get_fast_modinfo($event->courseid); - $moduleinfo = $modinfo->get_cm($event->coursemoduleid); - if ($moduleinfo->uservisible) { - return false; - } - - return true; - } - - /** - * Filter that checks if the event needs to be filtered out for the current user. - * Applies to assignment events. - * @param object $calendarevent calendarevent that is checked - * @return bool true if the event needs to filtered out, false if not. - */ - private function filter_assignment($calendarevent): bool { - global $DB; - $assignment = $DB->get_record('assign', ['id' => $calendarevent->instance]); - - // Check if the assign is longer than a week closed. - $overduecheck = $calendarevent->eventtype == "due" && $this->timenow >= ($calendarevent->timestart + 604800); - - // Check if the user is someone without grading capability. - $nogradecapabilitycheck = $calendarevent->eventtype == "gradingdue" && !has_capability('mod/assign:grade', - context_module::instance($calendarevent->coursemoduleid)); - // Check if the assignment is not open yet. - $stillclosedcheck = $assignment->allowsubmissionsfromdate >= $this->timenow; - - if ($overduecheck || $nogradecapabilitycheck || $stillclosedcheck) { - return true; - } - return false; - } - - /** - * Filter that checks if the event needs to be filtered out for the current user. - * Applies to activity completion events. - * @param object $calendarevent calendarevent that is checked - * @return bool true if the event needs to filtered out, false if not. - */ - private function filter_activitycompletions($calendarevent): bool { - global $DB, $USER; - if ($completionstatus = $DB->get_record('course_modules_completion', - ['coursemoduleid' => $calendarevent->coursemoduleid, 'userid' => $USER->id])) { - if ($completionstatus->completionstate != 0) { - return true; - } - } - return false; - } -} +. + +/** + * Class to get relevant events from courses the user is enrolled to.. + * + * @package block_townsquare + * @copyright 2023 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace block_townsquare; + +defined('MOODLE_INTERNAL') || die(); + +use context_module; +use dml_exception; + +global $CFG; +require_once($CFG->dirroot . '/calendar/lib.php'); +require_once($CFG->dirroot . '/blocks/townsquare/locallib.php'); +/** + * Class to get events and posts that will be shown in the townsquare block.. + * + * @package block_townsquare + * @copyright 2023 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class townsquareevents { + + /** @var int timestamp of the current time */ + public int $timenow; + + /** @var int timestamp from where the events should be searched */ + public int $timestart; + + /** @var int timestamp until where the events should be searched */ + public int $timeend; + + /** @var array ids of the courses where the events should be searched */ + public array $courses; + + /** + * Constructor of the townsquareevents class. + * Events will be searched in the timespan of 6 months in the past and 6 months in the future. + */ + public function __construct() { + $this->timenow = time(); + $this->timestart = $this->timenow - 15768000; + $this->timeend = $this->timenow + 15768000; + $this->courses = $this->get_courses(); + } + + /** + * Retrieves calendar and post events, merges and sorts them. + * @return array + */ + public function get_all_events_sorted(): array { + $calendarevents = $this->get_calendarevents(); + $postevents = $this->get_postevents(); + + // Merge the events in a sorted order. + $events = []; + $numberofevents = count($calendarevents) + count($postevents); + for ($i = 0; $i < $numberofevents; $i++) { + if (current($calendarevents) && current($postevents)) { + if (current($calendarevents)->timestart > current($postevents)->postcreated) { + $events[$i] = current($calendarevents); + next($calendarevents); + } else { + $events[$i] = current($postevents); + next($postevents); + } + } else if (current($calendarevents)) { + $events[$i] = current($calendarevents); + next($calendarevents); + } else { + $events[$i] = current($postevents); + next($postevents); + } + } + + return $events; + } + + /** + * Function to get events from that are in the calendar for the current user. + * + * The events are sorted in descending order by time created (newest event first) + * @return array + */ + public function get_calendarevents(): array { + global $DB; + + // Get all events from the last six months and the next six months. + $calendarevents = $this->get_events_from_db($this->timestart, $this->timeend, $this->courses); + + // Filter the events and add the coursemoduleid. + foreach ($calendarevents as $calendarevent) { + // Filter out events that are not relevant for the user. + if ($this->filter_availability($calendarevent) || + ($calendarevent->modulename == "assign" && $this->filter_assignment($calendarevent)) || + ($calendarevent->eventtype == "expectcompletionon" && $this->filter_activitycompletions($calendarevent))) { + unset($calendarevents[$calendarevent->id]); + continue; + } + + // Add the name of the instance to the event. + $calendarevent->instancename = $DB->get_field($calendarevent->modulename, 'name', ['id' => $calendarevent->instance]); + } + + return $calendarevents; + } + + /** + * Function to get the newest posts from modules like the forum or moodleoverflow. + * + * The events are sorted in descending order by time created (newest event first) + * @return array; + */ + public function get_postevents(): array { + global $DB; + + $forumposts = []; + $moodleoverflowposts = []; + + // Check which modules are installed and activated and get their data. + if ($DB->get_record('modules', ['name' => 'forum', 'visible' => 1])) { + $forumposts = $this->get_posts_from_db('forum', $this->courses, $this->timestart); + } + + if ($DB->get_record('modules', ['name' => 'moodleoverflow', 'visible' => 1])) { + $moodleoverflowposts = $this->get_posts_from_db('moodleoverflow', $this->courses, $this->timestart); + } + + if (empty($forumposts) && empty($moodleoverflowposts)) { + return []; + } + + // Merge the posts in a sorted order. While merging, filter out irrelevant posts and add relevant attributes if necessary. + $posts = []; + $numberofposts = count($forumposts) + count($moodleoverflowposts); + reset($forumposts); + reset($moodleoverflowposts); + for ($i = 0; $i < $numberofposts; $i++) { + // Filter unavailable posts. + // Iterate until the first post that is available. Decrement the number of posts each time a post is filtered. + while (current($forumposts) && $this->filter_availability(current($forumposts))) { + next($forumposts); + $numberofposts--; + } + while (current($moodleoverflowposts) && $this->filter_availability(current($moodleoverflowposts))) { + next($moodleoverflowposts); + $numberofposts--; + } + // If there no posts left after filtering, break. + if ($i >= $numberofposts) { + break; + } + + // Merge. + if (current($forumposts) && current($moodleoverflowposts)) { + if (current($forumposts)->postcreated > current($moodleoverflowposts)->postcreated) { + $posts[$i] = current($forumposts); + next($forumposts); + } else { + $posts[$i] = current($moodleoverflowposts); + next($moodleoverflowposts); + } + } else if (current($forumposts)) { + $posts[$i] = current($forumposts); + next($forumposts); + } else { + $posts[$i] = current($moodleoverflowposts); + next($moodleoverflowposts); + } + } + + // Add an event type to the posts and add the anonymous setting to the moodleoverflow posts. Then return it. + return $posts; + } + + // Helper functions. + + /** + * Searches for posts in the forum or moodleoverflow module. + * The sql query makes sure that the modules are installed and available.. + * This is a helper function for get_postevents(). + * @param string $modulename The name of the module, is 'forum' or 'moodleoverflow'. + * @param array $courses The ids of the courses where the posts should be searched. + * @param int $timestart The timestamp from where the posts should be searched. + * @return array + */ + private function get_posts_from_db($modulename, $courses, $timestart): array { + global $DB; + // Prepare params for sql statement. + if ($courses == []) { + return []; + } + list($insqlcourses, $inparamscourses) = $DB->get_in_or_equal($courses, SQL_PARAMS_NAMED); + $params = ['courses' => $courses, 'timestart' => $timestart] + $inparamscourses; + // Set begin of sql statement. + $begin = "SELECT (ROW_NUMBER() OVER (ORDER BY posts.id)) AS row_num, "; + + // Set the select part of the sql that is always the same. + $middle = "'post' AS eventtype, + cm.id AS coursemoduleid, + cm.availability AS availability, + module.name AS instancename, + discuss.course AS courseid, + discuss.userid AS discussionuserid, + discuss.name AS discussionsubject, + u.firstname AS postuserfirstname, + u.lastname AS postuserlastname, + posts.id AS postid, + posts.discussion AS postdiscussion, + posts.parent AS postparentid, + posts.userid AS postuserid, + posts.created AS postcreated, + posts.message AS postmessage "; + + // Extend the strings for the 2 module cases. + if ($modulename == 'forum') { + $begin .= "'forum' AS modulename, module.id AS instanceid,"; + $middle .= "FROM {forum_posts} posts + JOIN {forum_discussions} discuss ON discuss.id = posts.discussion + JOIN {forum} module ON module.id = discuss.forum + JOIN {modules} modules ON modules.name = 'forum' "; + + } else if ($modulename == 'moodleoverflow') { + $begin .= "'moodleoverflow' AS modulename, module.id AS instanceid, module.anonymous AS anonymoussetting, "; + $middle .= "FROM {moodleoverflow_posts} posts + JOIN {moodleoverflow_discussions} discuss ON discuss.id = posts.discussion + JOIN {moodleoverflow} module ON module.id = discuss.moodleoverflow + JOIN {modules} modules ON modules.name = 'moodleoverflow' "; + } + + // Extension of the middle string. + $middle .= "JOIN {user} u ON u.id = posts.userid + JOIN {course_modules} cm ON (cm.course = module.course AND cm.module = modules.id + AND cm.instance = module.id) "; + + // Set the where clause of the string. + $end = "WHERE discuss.course $insqlcourses + AND posts.created > :timestart + AND cm.visible = 1 + AND modules.visible = 1 + ORDER BY posts.created DESC;"; + + // Concatenate all strings. + $sql = $begin . $middle . $end; + + // Get all posts. + return $DB->get_records_sql($sql, $params); + } + + /** + * Searches for events in the events table, that are relevant to the timeline. + * This is a helper function for get_calendarevents(). + * @param int $timestart The time from where the events should be searched. Not equal to timestart in the database events table. + * @param int $timeend The time until where the events should be searched. + * @param array $courses The ids of the courses where the events should be searched. + * @return array + * @throws dml_exception + */ + private function get_events_from_db($timestart, $timeend, $courses): array { + global $DB; + + // As there are no events without courses, return an empty array. + if ($courses == []) { + return []; + } + + // Due to compatability reasons, only events from supported modules are shown. + // Supported modules are: core modules and custom additional modules. + $coremodules = ['assign', 'book', 'chat', 'choice', 'data', 'feedback', 'folder', 'forum', 'glossary', 'h5pactivity', + 'imscp', 'label', 'lesson', 'lti', 'page', 'quiz', 'resource', 'scorm', 'survey', 'url', 'wiki', 'workshop', ]; + $additionalmodules = ['moodleoverflow', 'ratingallocate']; + $modules = $coremodules + $additionalmodules; + + // Prepare params for sql statement. + list($insqlcourses, $inparamscourses) = $DB->get_in_or_equal($courses, SQL_PARAMS_NAMED); + list($insqlmodules, $inparamsmodules) = $DB->get_in_or_equal($modules, SQL_PARAMS_NAMED); + $params = ['timestart' => $timestart, 'timeduration' => $timestart, + 'timeend' => $timeend, 'courses' => $courses, ] + $inparamscourses + $inparamsmodules; + + // Set the sql statement. + $sql = "SELECT e.id, e.name, e.courseid, cm.id AS coursemoduleid, cm.availability AS availability, e.groupid, e.userid, + e.modulename, e.instance, e.eventtype, e.timestart, e.visible + FROM {event} e + JOIN {modules} m ON e.modulename = m.name + JOIN {course_modules} cm ON (cm.course = e.courseid AND cm.module = m.id AND cm.instance = e.instance) + WHERE (e.timestart >= :timestart OR e.timestart+e.timeduration > :timeduration) + AND e.timestart <= :timeend + AND e.courseid $insqlcourses + AND e.modulename $insqlmodules + AND m.visible = 1 + AND (e.name NOT LIKE '" .'0'. "' AND e.eventtype NOT LIKE '" .'0'. "' ) + AND (e.instance <> 0 AND e.visible = 1) + ORDER BY e.timestart DESC"; + + // Get all events. + return $DB->get_records_sql($sql, $params); + } + + /** + * Gets the id of all courses where the current user is enrolled + * @return array + */ + private function get_courses(): array { + global $USER; + + $enrolledcourses = enrol_get_all_users_courses($USER->id, true); + $courses = []; + foreach ($enrolledcourses as $enrolledcourse) { + $courses[] = $enrolledcourse->id; + } + + return $courses; + } + + /** + * Filter that checks if the event needs to be filtered out for the current user because it is unavailable. + * Applies to restriction that are defined in the module setting (restrict access). + * @param object $event The event that is checked. + * @return bool true if the event needs to filtered out, false if not. + */ + private function filter_availability($event): bool { + // If there is no restriction defined, the event is available. + if ($event->availability == null) { + return false; + } + + // If there is a restriction, check if it applies to the user. + $modinfo = get_fast_modinfo($event->courseid); + $moduleinfo = $modinfo->get_cm($event->coursemoduleid); + if ($moduleinfo->uservisible) { + return false; + } + + return true; + } + + /** + * Filter that checks if the event needs to be filtered out for the current user. + * Applies to assignment events. + * @param object $calendarevent calendarevent that is checked + * @return bool true if the event needs to filtered out, false if not. + */ + private function filter_assignment($calendarevent): bool { + global $DB; + $assignment = $DB->get_record('assign', ['id' => $calendarevent->instance]); + + // Check if the assign is longer than a week closed. + $overduecheck = $calendarevent->eventtype == "due" && $this->timenow >= ($calendarevent->timestart + 604800); + + // Check if the user is someone without grading capability. + $nogradecapabilitycheck = $calendarevent->eventtype == "gradingdue" && !has_capability('mod/assign:grade', + context_module::instance($calendarevent->coursemoduleid)); + // Check if the assignment is not open yet. + $stillclosedcheck = $assignment->allowsubmissionsfromdate >= $this->timenow; + + if ($overduecheck || $nogradecapabilitycheck || $stillclosedcheck) { + return true; + } + return false; + } + + /** + * Filter that checks if the event needs to be filtered out for the current user. + * Applies to activity completion events. + * @param object $calendarevent calendarevent that is checked + * @return bool true if the event needs to filtered out, false if not. + */ + private function filter_activitycompletions($calendarevent): bool { + global $DB, $USER; + if ($completionstatus = $DB->get_record('course_modules_completion', + ['coursemoduleid' => $calendarevent->coursemoduleid, 'userid' => $USER->id])) { + if ($completionstatus->completionstate != 0) { + return true; + } + } + return false; + } +} diff --git a/db/services.php b/db/services.php index c5eb7a2..936e023 100644 --- a/db/services.php +++ b/db/services.php @@ -1,35 +1,35 @@ -. - -/** - * Townsquare external functions and service definitions. - * - * @package block_townsquare - * @category external - * @copyright 2017 Kennet Winter - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -defined('MOODLE_INTERNAL') || die; - -$functions = [ - 'block_townsquare_record_usersettings' => [ - 'classname' => 'block_townsquare_external', - 'classpath' => 'blocks/townsquare/externallib.php', - 'description' => 'Records the user settings for the townsquare block', - 'type' => 'write', - 'ajax' => true, - ], -]; \ No newline at end of file +. + +/** + * Townsquare external functions and service definitions. + * + * @package block_townsquare + * @category external + * @copyright 2017 Kennet Winter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +defined('MOODLE_INTERNAL') || die; + +$functions = [ + 'block_townsquare_record_usersettings' => [ + 'classname' => 'block_townsquare_external', + 'classpath' => 'blocks/townsquare/externallib.php', + 'description' => 'Records the user settings for the townsquare block', + 'type' => 'write', + 'ajax' => true, + ], +]; diff --git a/externallib.php b/externallib.php index 51b7c98..adb894c 100644 --- a/externallib.php +++ b/externallib.php @@ -1,115 +1,118 @@ -. - -/** - * External townsquare API - * - * @package block_townsquare - * @copyright 2024 Tamaro Walter - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -global $CFG; -require_once($CFG->libdir . '/externallib.php'); - -/** - * Class implementing the external API, esp. for AJAX functions. - * - * @package block_townsquare - * @copyright 2024 Tamaro Walter - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class block_townsquare_external extends \core_external\external_api { - - /** - * Returns description of method parameters - * @return external_function_parameters - */ - public static function record_usersettings_parameters(): external_function_parameters { - return new external_function_parameters( - [ - 'userid' => new external_value(PARAM_INT, 'the user id'), - 'timefilterpast' => new external_value(PARAM_INT, 'time span for filtering the past'), - 'timefilterfuture' => new external_value(PARAM_INT, 'time span for filtering the future'), - 'basicletter' => new external_value(PARAM_INT, 'Setting of the letter filter for basic letters'), - 'completionletter' => new external_value(PARAM_INT, 'Setting of the letter filter for completion letters'), - 'postletter' => new external_value(PARAM_INT, 'Setting of the letter filter for post letters'), - ] - ); - } - - /** - * Return the result of the record_usersettings function - * @return external_value - */ - public static function record_usersettings_returns() { - return new external_value(PARAM_BOOL, 'true if successful'); - } - - /** - * Record the user settings - * - * @param int $userid The user id - * @param int $timefilterpast Time span for filtering the past - * @param int $timefilterfuture Time span for filtering the future - * @param int $letterfilter Setting of the letter filter - * @return bool - */ - public static function record_usersettings($userid, $timefilterpast, $timefilterfuture, $basicletter, $completionletter, $postletter) { - global $DB; - //echo ''; - //$transaction = $DB->start_delegated_transaction(); - - // Check if the user already has a record in the database - if ($records = $DB->get_records('townsquare_usersettings', ['userid' => $userid])) { - // If there more than a record (it only should be only one), delete all of them and insert the new one. - if (count($records) > 1) { - try { - foreach ($records as $record) { - $DB->delete_records('townsquare_usersettings', ['id' => $record->id]); - } - } catch (Exception $e) { - // $transaction->rollback($e); - return false; - } - } else { - // Upgrade the existing record. - $record = reset($records); - $record->timefilterpast = $timefilterpast; - $record->timefilterfuture = $timefilterfuture; - $record->basicletter = $basicletter; - $record->completionletter = $completionletter; - $record->postletter = $postletter; - $DB->update_record('townsquare_usersettings', $record); - // $transaction->allow_commit(); - return true; - } - } - $record = new stdClass(); - $record->userid = $userid; - $record->timefilterpast = $timefilterpast; - $record->timefilterfuture = $timefilterfuture; - $record->basicletter = $basicletter; - $record->completionletter = $completionletter; - $record->postletter = $postletter; - $DB->insert_record('townsquare_usersettings', $record); - //$transaction->allow_commit(); - return true; - } - -} \ No newline at end of file +. + +/** + * External townsquare API + * + * @package block_townsquare + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->libdir . '/externallib.php'); + +/** + * Class implementing the external API, esp. for AJAX functions. + * + * @package block_townsquare + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class block_townsquare_external extends \core_external\external_api { + + /** + * Returns description of method parameters + * @return external_function_parameters + */ + public static function record_usersettings_parameters(): external_function_parameters { + return new external_function_parameters( + [ + 'userid' => new external_value(PARAM_INT, 'the user id'), + 'timefilterpast' => new external_value(PARAM_INT, 'time span for filtering the past'), + 'timefilterfuture' => new external_value(PARAM_INT, 'time span for filtering the future'), + 'basicletter' => new external_value(PARAM_INT, 'Setting of the letter filter for basic letters'), + 'completionletter' => new external_value(PARAM_INT, 'Setting of the letter filter for completion letters'), + 'postletter' => new external_value(PARAM_INT, 'Setting of the letter filter for post letters'), + ] + ); + } + + /** + * Return the result of the record_usersettings function + * @return external_value + */ + public static function record_usersettings_returns() { + return new external_value(PARAM_BOOL, 'true if successful'); + } + + /** + * Record the user settings + * + * @param int $userid The user id + * @param int $timefilterpast Time span for filtering the past + * @param int $timefilterfuture Time span for filtering the future + * @param int $basicletter If basic letters should be shown + * @param int $completionletter If completion letters should be shown + * @param int $postletter If post letters should be shown + * @return bool + */ + public static function record_usersettings($userid, $timefilterpast, $timefilterfuture, + $basicletter, $completionletter, $postletter) { + global $DB; + + $transaction = $DB->start_delegated_transaction(); + + // Check if the user already has a record in the database. + if ($records = $DB->get_records('townsquare_usersettings', ['userid' => $userid])) { + // If there more than a record (it only should be only one), delete all of them and insert the new one. + if (count($records) > 1) { + try { + foreach ($records as $record) { + $DB->delete_records('townsquare_usersettings', ['id' => $record->id]); + } + } catch (Exception $e) { + $transaction->rollback($e); + return false; + } + } else { + // Upgrade the existing record. + $record = reset($records); + $record->timefilterpast = $timefilterpast; + $record->timefilterfuture = $timefilterfuture; + $record->basicletter = $basicletter; + $record->completionletter = $completionletter; + $record->postletter = $postletter; + $DB->update_record('townsquare_usersettings', $record); + $transaction->allow_commit(); + return true; + } + } + $record = new stdClass(); + $record->userid = $userid; + $record->timefilterpast = $timefilterpast; + $record->timefilterfuture = $timefilterfuture; + $record->basicletter = $basicletter; + $record->completionletter = $completionletter; + $record->postletter = $postletter; + $DB->insert_record('townsquare_usersettings', $record); + $transaction->allow_commit(); + return true; + } + +} diff --git a/lang/en/block_townsquare.php b/lang/en/block_townsquare.php index 0c1b260..e3e6467 100644 --- a/lang/en/block_townsquare.php +++ b/lang/en/block_townsquare.php @@ -1,84 +1,84 @@ -. - -/** - * Plugin strings are defined here. - * - * @package block_townsquare - * @category string - * @copyright 2023 Tamaro Walter - * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -// Core strings for the installation. -$string['pluginname'] = 'Townsquare block'; -$string['pluginname'] = 'Town Square'; -$string['pluginname:addinstance'] = 'Add the Town Square block'; -$string['pluginname:myaddinstance'] = 'Add the Town Square block to the dashboard'; - -// Error strings. -$string['invalidlettertype'] = 'Invalid function parameter, please use a valid letter type'; - -// Mustache templates strings. -$string['completionletterorigin'] = '{$a->modulename} should be completed until {$a->date}'; -$string['basicletterorigin'] = 'A notification from {$a->modulename}:'; -$string['postletternotification'] = 'New {$a->modulename} post!'; -$string['postletterorigin'] = '{$a->authorname} posted in {$a->instancename} -> {$a->discussionname}:'; -$string['orientationmarkercontent'] = 'Hi {$a->username}, welcome to townsquare! Today is the {$a->date}'; - -// Side panel filter strings. - -// Filter headers. -$string['coursefilter'] = 'Course filter'; -$string['timefilter'] = 'Time filter'; -$string['letterfilter'] = 'Letter filter'; - -// Time filter options. -$string['allnotifications'] = 'All notifications'; -$string['nexttwodaysnotifications'] = 'Next two days'; -$string['nextfivedaysnotifications'] = 'Next five days'; -$string['nextweeknotifications'] = 'Next week'; -$string['nextmonthnotifications'] = 'Next month'; -$string['lasttwodaysnotifications'] = 'last two days'; -$string['lastfivedaysnotifications'] = 'last five days'; -$string['lastweeknotifications'] = 'Last week'; -$string['lastmonthnotifications'] = 'Last month'; - -// Letter filter options. -$string['basicletters'] = 'Basic letters'; -$string['completionletters'] = 'Activity Completions'; -$string['postletters'] = 'Forum Posts'; - -// Save button strings. -$string['savebutton'] = 'Save settings'; -$string['savehelpicontext'] = 'Save Settings for the future'; -$string['savemessage'] = 'Settings successfully saved!'; - -// Letter strings. -$string['invalidmodulename'] = 'Module name is unknown or not supported'; - -// Setting strings. -$string['basiclettercolor'] = 'Color for basic letters'; -$string['postlettercolor'] = 'Color for post letters'; -$string['completionlettercolor'] = 'Color for activity completion letters'; -$string['orientationmarkercolor'] = 'Color for the orientation marker'; - -$string['configbasiclettercolor'] = 'Configuration for the color of the basic notification letters'; -$string['configpostlettercolor'] = 'Configuration for the color of the post letters'; -$string['configcompletionlettercolor'] = 'Configuration for the color of the activity completion letters'; -$string['configorientationmarkercolor'] = 'Configuration for the color of the orientation marker'; +. + +/** + * Plugin strings are defined here. + * + * @package block_townsquare + * @category string + * @copyright 2023 Tamaro Walter + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +// Core strings for the installation. +$string['pluginname'] = 'Townsquare block'; +$string['pluginname'] = 'Town Square'; +$string['pluginname:addinstance'] = 'Add the Town Square block'; +$string['pluginname:myaddinstance'] = 'Add the Town Square block to the dashboard'; + +// Error strings. +$string['invalidlettertype'] = 'Invalid function parameter, please use a valid letter type'; + +// Mustache templates strings. +$string['completionletterorigin'] = '{$a->modulename} should be completed until {$a->date}'; +$string['basicletterorigin'] = 'A notification from {$a->modulename}:'; +$string['postletternotification'] = 'New {$a->modulename} post!'; +$string['postletterorigin'] = '{$a->authorname} posted in {$a->instancename} -> {$a->discussionname}:'; +$string['orientationmarkercontent'] = 'Hi {$a->username}, welcome to townsquare! Today is the {$a->date}'; + +// Side panel filter strings. + +// Filter headers. +$string['coursefilter'] = 'Course filter'; +$string['timefilter'] = 'Time filter'; +$string['letterfilter'] = 'Letter filter'; + +// Time filter options. +$string['allnotifications'] = 'All notifications'; +$string['nexttwodaysnotifications'] = 'Next two days'; +$string['nextfivedaysnotifications'] = 'Next five days'; +$string['nextweeknotifications'] = 'Next week'; +$string['nextmonthnotifications'] = 'Next month'; +$string['lasttwodaysnotifications'] = 'last two days'; +$string['lastfivedaysnotifications'] = 'last five days'; +$string['lastweeknotifications'] = 'Last week'; +$string['lastmonthnotifications'] = 'Last month'; + +// Letter filter options. +$string['basicletters'] = 'Basic letters'; +$string['completionletters'] = 'Activity Completions'; +$string['postletters'] = 'Forum Posts'; + +// Save button strings. +$string['savebutton'] = 'Save settings'; +$string['savehelpicontext'] = 'Save Settings for the future'; +$string['savemessage'] = 'Settings successfully saved!'; + +// Letter strings. +$string['invalidmodulename'] = 'Module name is unknown or not supported'; + +// Setting strings. +$string['basiclettercolor'] = 'Color for basic letters'; +$string['postlettercolor'] = 'Color for post letters'; +$string['completionlettercolor'] = 'Color for activity completion letters'; +$string['orientationmarkercolor'] = 'Color for the orientation marker'; + +$string['configbasiclettercolor'] = 'Configuration for the color of the basic notification letters'; +$string['configpostlettercolor'] = 'Configuration for the color of the post letters'; +$string['configcompletionlettercolor'] = 'Configuration for the color of the activity completion letters'; +$string['configorientationmarkercolor'] = 'Configuration for the color of the orientation marker'; diff --git a/tests/calendarevents_test.php b/tests/calendarevents_test.php index bb96efd..103dd32 100644 --- a/tests/calendarevents_test.php +++ b/tests/calendarevents_test.php @@ -96,7 +96,7 @@ public function test_sortorder(): void { * Test, if the post events are processed correctly if the course disappears. * @return void */ - public function test_course_deleted() { + public function test_course_deleted(): void { global $DB; // Delete the course from the database. $DB->delete_records('course', ['id' => $this->testdata->course1->id]); diff --git a/tests/contentcontroller_test.php b/tests/contentcontroller_test.php index b00ed1b..53b88ac 100644 --- a/tests/contentcontroller_test.php +++ b/tests/contentcontroller_test.php @@ -69,7 +69,7 @@ public function tearDown(): void { * Test, if the right letters are created. * @return void */ - public function test_letters() { + public function test_letters(): void { // Set an logged in user. $this->setUser($this->testdata->teacher); diff --git a/tests/postevents_test.php b/tests/postevents_test.php index aba6828..a7a21dd 100644 --- a/tests/postevents_test.php +++ b/tests/postevents_test.php @@ -151,7 +151,7 @@ public function test_module_forum(): void { * Test, if the post events are processed correctly if the course disappears. * @return void */ - public function test_course_deleted() { + public function test_course_deleted(): void { global $DB; // Delete the course from the database. $DB->delete_records('course', ['id' => $this->testdata->course1->id]); From 2f1666ad6e3c14fa47f8a25588ccaaadf98d0c35 Mon Sep 17 00:00:00 2001 From: Tamaro Walter Date: Mon, 18 Mar 2024 17:12:25 +0100 Subject: [PATCH 037/123] add a success label --- amd/build/usersettings_save.min.js | 2 +- amd/build/usersettings_save.min.js.map | 2 +- amd/src/usersettings_save.js | 34 ++++++++++++++++---------- lang/en/block_townsquare.php | 2 ++ styles.css | 2 +- 5 files changed, 26 insertions(+), 16 deletions(-) diff --git a/amd/build/usersettings_save.min.js b/amd/build/usersettings_save.min.js index 038e610..4932bde 100644 --- a/amd/build/usersettings_save.min.js +++ b/amd/build/usersettings_save.min.js @@ -8,6 +8,6 @@ define("block_townsquare/usersettings_save",["exports","core/ajax"],(function(_e * @module block_townsquare/timefilter * @copyright 2024 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,settingsfromdb){settingsfromdb&&function(settingsfromdb){let futurebuttonid=converttimetoid(settingsfromdb.timefilterfuture,!0),pastbuttonid=converttimetoid(settingsfromdb.timefilterpast,!1);"ts_time_all"!==futurebuttonid?(futureradiobuttons.forEach((function(button){button.id===futurebuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change")),alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))})),pastradiobuttons.forEach((function(button){button.id===pastbuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change")),alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))}))):alltimebutton.forEach((function(button){button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change"))}));checkboxes.forEach((function(checkbox){let basiclettercheck="basicletter"===checkbox.id&&""===settingsfromdb.basicletter,completionlettercheck="completionletter"===checkbox.id&&"0"===settingsfromdb.completionletter,postlettercheck="postletter"===checkbox.id&&"0"===settingsfromdb.postletter;(basiclettercheck||completionlettercheck||postlettercheck)&&checkbox.click()}))}(settingsfromdb);savebutton.addEventListener("click",(async function(){let timespans=function(){let settings={timepast:0,timefuture:0},settingsset=!1;if(alltimebutton.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id),settings.timefuture=convertidtotime(button.id),settingsset=!0)})),settingsset)return settings;return futureradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timefuture=convertidtotime(button.id))})),pastradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id))})),settings}(),letterfilter=function(){let settings={basicletter:0,completionletter:0,postletter:0};return checkboxes.forEach((function(checkbox){if(checkbox.checked)switch(checkbox.id){case"basicletter":settings.basicletter=1;break;case"completionletter":settings.completionletter=1;break;case"postletter":settings.postletter=1}})),settings}();await async function(userid,timefilterpast,timefilterfuture,basicletter,completionletter,postletter){let result;result=await _ajax.default.call([{methodname:"block_townsquare_record_usersettings",args:{userid:parseInt(userid),timefilterpast:timefilterpast,timefilterfuture:timefilterfuture,basicletter:basicletter,completionletter:completionletter,postletter:postletter}}]);let el=document.getElementById("ts_usersettings_successlabel");return el.style.opacity=1,el.style.display="block",result}(userid,timespans.timepast,timespans.timefuture,letterfilter.basicletter,letterfilter.completionletter,letterfilter.postletter)}))},_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};const savebutton=document.getElementById("ts_usersettings_savebutton"),alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button"),checkboxes=document.querySelectorAll(".ts_letter_checkbox");function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}function converttimetoid(time,future){switch(time){case"15778463":return"ts_time_all";case"172800":return future?"ts_time_next_twodays":"ts_time_past_twodays";case"432000":return future?"ts_time_next_fivedays":"ts_time_last_fivedays";case"604800":return future?"ts_time_next_week":"ts_time_last_week";case"2592000":return future?"ts_time_next_month":"ts_time_last_month"}}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,settingsfromdb){settingsfromdb&&function(settingsfromdb){let futurebuttonid=converttimetoid(settingsfromdb.timefilterfuture,!0),pastbuttonid=converttimetoid(settingsfromdb.timefilterpast,!1);"ts_time_all"!==futurebuttonid?(futureradiobuttons.forEach((function(button){button.id===futurebuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change")),alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))})),pastradiobuttons.forEach((function(button){button.id===pastbuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change")),alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))}))):alltimebutton.forEach((function(button){button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change"))}));checkboxes.forEach((function(checkbox){let basiclettercheck="basicletter"===checkbox.id&&""===settingsfromdb.basicletter,completionlettercheck="completionletter"===checkbox.id&&"0"===settingsfromdb.completionletter,postlettercheck="postletter"===checkbox.id&&"0"===settingsfromdb.postletter;(basiclettercheck||completionlettercheck||postlettercheck)&&checkbox.click()}))}(settingsfromdb);savebutton.addEventListener("click",(async function(){let timespans=function(){let settings={timepast:0,timefuture:0},settingsset=!1;if(alltimebutton.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id),settings.timefuture=convertidtotime(button.id),settingsset=!0)})),settingsset)return settings;return futureradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timefuture=convertidtotime(button.id))})),pastradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id))})),settings}(),letterfilter=function(){let settings={basicletter:0,completionletter:0,postletter:0};return checkboxes.forEach((function(checkbox){if(checkbox.checked)switch(checkbox.id){case"basicletter":settings.basicletter=1;break;case"completionletter":settings.completionletter=1;break;case"postletter":settings.postletter=1}})),settings}();await async function(userid,timefilterpast,timefilterfuture,basicletter,completionletter,postletter){let result;result=await _ajax.default.call([{methodname:"block_townsquare_record_usersettings",args:{userid:parseInt(userid),timefilterpast:timefilterpast,timefilterfuture:timefilterfuture,basicletter:basicletter,completionletter:completionletter,postletter:postletter}}]);let el=document.getElementById("ts_usersettings_successlabel");el.style.display="block",el.style.opacity=1,el.fadeOutTimer&&clearInterval(el.fadeOutTimer);return setTimeout((function(){el.fadeOutTimer=setInterval((function(){el.style.opacity>.4?el.style.opacity-=.1:el.style.opacity>0?el.style.opacity-=.2:(clearInterval(el.fadeOutTimer),el.style.display="none")}),100)}),3e3),result}(userid,timespans.timepast,timespans.timefuture,letterfilter.basicletter,letterfilter.completionletter,letterfilter.postletter)}))},_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};const savebutton=document.getElementById("ts_usersettings_savebutton"),alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button"),checkboxes=document.querySelectorAll(".ts_letter_checkbox");function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}function converttimetoid(time,future){switch(time){case"15778463":return"ts_time_all";case"172800":return future?"ts_time_next_twodays":"ts_time_past_twodays";case"432000":return future?"ts_time_next_fivedays":"ts_time_last_fivedays";case"604800":return future?"ts_time_next_week":"ts_time_last_week";case"2592000":return future?"ts_time_next_month":"ts_time_last_month"}}})); //# sourceMappingURL=usersettings_save.min.js.map \ No newline at end of file diff --git a/amd/build/usersettings_save.min.js.map b/amd/build/usersettings_save.min.js.map index c526c29..eadc75d 100644 --- a/amd/build/usersettings_save.min.js.map +++ b/amd/build/usersettings_save.min.js.map @@ -1 +1 @@ -{"version":3,"file":"usersettings_save.min.js","sources":["../src/usersettings_save.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\r\n//\r\n// Moodle is free software: you can redistribute it and/or modify\r\n// it under the terms of the GNU General Public License as published by\r\n// the Free Software Foundation, either version 3 of the License, or\r\n// (at your option) any later version.\r\n//\r\n// Moodle is distributed in the hope that it will be useful,\r\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n// GNU General Public License for more details.\r\n//\r\n// You should have received a copy of the GNU General Public License\r\n// along with Moodle. If not, see .\r\n\r\n/**\r\n * Javascript to save the user settings in the database.\r\n *\r\n * This file implements 1 functionality:\r\n * - If the \"save settings\" button is pressed, store the settings in the database.\r\n *\r\n * @module block_townsquare/timefilter\r\n * @copyright 2024 Tamaro Walter\r\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\r\n */\r\n\r\nimport Ajax from 'core/ajax';\r\n\r\n// Get the save button for the user settings.\r\nconst savebutton = document.getElementById('ts_usersettings_savebutton');\r\n\r\n// Get the buttons from the time filter.\r\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\r\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\r\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\r\n\r\n// Get the checkboxes from the letter filter.\r\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\r\n\r\n/**\r\n * Init function\r\n *\r\n * @param {number} userid The id of the current user.\r\n * @param {object} settingsfromdb The settings from the database, if there are any.\r\n */\r\nexport function init(userid, settingsfromdb) {\r\n // When the page is loaded, set the settings from the database.\r\n if (settingsfromdb) {\r\n executeusersettings(settingsfromdb);\r\n }\r\n\r\n // Add event listener to the save button.\r\n savebutton.addEventListener('click', async function() {\r\n\r\n // First step: collect the current settings.\r\n // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes.\r\n let timespans = collecttimefiltersettings();\r\n let letterfilter = collectletterfiltersettings();\r\n\r\n // Second step: store the usersettings in the database.\r\n await saveusersettings(userid, timespans['timepast'], timespans['timefuture'],\r\n letterfilter['basicletter'], letterfilter['completionletter'], letterfilter['postletter']);\r\n });\r\n}\r\n\r\n/**\r\n * Function to save the user settings in the database.\r\n * @param {number} userid\r\n * @param {number} timefilterpast\r\n * @param {number} timefilterfuture\r\n * @param {number} basicletter\r\n * @param {number} completionletter\r\n * @param {number} postletter\r\n * @returns {Promise<*>}\r\n */\r\nasync function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) {\r\n let result ;\r\n result = await Ajax.call([{\r\n methodname: 'block_townsquare_record_usersettings',\r\n args: {\r\n userid: parseInt(userid),\r\n timefilterpast: timefilterpast,\r\n timefilterfuture: timefilterfuture,\r\n basicletter: basicletter,\r\n completionletter: completionletter,\r\n postletter: postletter\r\n },\r\n }]);\r\n\r\n //if (result === true) {\r\n\r\n //}\r\n //window.alert('Settings saved');\r\n // Show a success message.\r\n let el = document.getElementById('ts_usersettings_successlabel');\r\n el.style.opacity = 1;\r\n el.style.display = 'block';\r\n /*setInterval(function() {\r\n if (el.style.opacity > 0) {\r\n el.style.opacity -= 0.1;\r\n }\r\n }, 100);\r\n el.style.display = 'none';*/\r\n return result;\r\n}\r\n\r\n/**\r\n * Function to execute existing user settings when loading the townsquare.\r\n * @param {Object} settingsfromdb\r\n */\r\nfunction executeusersettings(settingsfromdb) {\r\n\r\n // First step: set the time filter settings.\r\n // Change the time into the correct radio button id.\r\n let futurebuttonid = converttimetoid(settingsfromdb['timefilterfuture'], true);\r\n let pastbuttonid = converttimetoid(settingsfromdb['timefilterpast'], false);\r\n\r\n // If the time span is a combination of past and future, go through the two radio buttons and activate the filter.\r\n if (futurebuttonid !== \"ts_time_all\") {\r\n futureradiobuttons.forEach(function(button) {\r\n if (button.id === futurebuttonid) {\r\n button.parentNode.classList.add('active');\r\n button.checked = true;\r\n button.dispatchEvent(new Event('change'));\r\n alltimebutton.forEach(function(alltimebutton) {\r\n alltimebutton.checked = false;\r\n alltimebutton.parentNode.classList.remove('active');\r\n });\r\n }\r\n });\r\n pastradiobuttons.forEach(function(button) {\r\n if (button.id === pastbuttonid) {\r\n button.parentNode.classList.add('active');\r\n button.checked = true;\r\n button.dispatchEvent(new Event('change'));\r\n alltimebutton.forEach(function(alltimebutton) {\r\n alltimebutton.checked = false;\r\n alltimebutton.parentNode.classList.remove('active');\r\n });\r\n }\r\n });\r\n } else {\r\n // If the time span is set to all time, activate the all time button.\r\n alltimebutton.forEach(function(button) {\r\n button.parentNode.classList.add('active');\r\n button.checked = true;\r\n button.dispatchEvent(new Event('change'));\r\n });\r\n }\r\n\r\n // Second step: set the letter filter settings.\r\n // Per default all checkboxes are checked. If the setting is 0, uncheck the checkbox.\r\n checkboxes.forEach(function(checkbox) {\r\n let basiclettercheck = checkbox.id === 'basicletter' && settingsfromdb['basicletter'] === \"\";\r\n let completionlettercheck = checkbox.id === 'completionletter' && settingsfromdb['completionletter'] === \"0\";\r\n let postlettercheck = checkbox.id === 'postletter' && settingsfromdb['postletter'] === \"0\";\r\n\r\n if (basiclettercheck || completionlettercheck || postlettercheck) {\r\n checkbox.click();\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Function to collect the letter filter settings.\r\n * @returns {{basicletter: number, completionletter: number, postletter: number}}\r\n */\r\nfunction collectletterfiltersettings() {\r\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\r\n\r\n checkboxes.forEach(function(checkbox) {\r\n if (checkbox.checked) {\r\n switch(checkbox.id) {\r\n case \"basicletter\":\r\n settings['basicletter'] = 1;\r\n break;\r\n case \"completionletter\":\r\n settings['completionletter'] = 1;\r\n break;\r\n case \"postletter\":\r\n settings['postletter'] = 1;\r\n break;\r\n\r\n }\r\n }\r\n });\r\n // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit.\r\n return settings;\r\n}\r\n\r\n/**\r\n * Function to collect the time filter settings.\r\n * @returns {{timepast: number, timefuture: number}}\r\n */\r\nfunction collecttimefiltersettings() {\r\n let settings = { timepast: 0, timefuture: 0};\r\n let settingsset = false;\r\n\r\n // Get the relevant time spans of the time filter.\r\n // Check if the alltimebutton is set.\r\n alltimebutton.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timepast'] = convertidtotime(button.id);\r\n settings['timefuture'] = convertidtotime(button.id);\r\n settingsset = true;\r\n }\r\n });\r\n\r\n if (settingsset) {\r\n return settings;\r\n }\r\n\r\n // If the alltimebutton is not set, check which of the future/past buttons is set.\r\n futureradiobuttons.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timefuture'] = convertidtotime(button.id);\r\n }\r\n });\r\n\r\n pastradiobuttons.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timepast'] = convertidtotime(button.id);\r\n }\r\n });\r\n return settings;\r\n}\r\n\r\n\r\n/**\r\n * Function to convert the radio button id to a useable time span.\r\n * @param {string} id The id of the radio button\r\n * @returns {number}\r\n */\r\nfunction convertidtotime(id) {\r\n // TODO: Please use global functions if possible.\r\n switch(id) {\r\n case \"ts_time_all\":\r\n return 15778463;\r\n case \"ts_time_next_twodays\":\r\n case \"ts_time_last_twodays\":\r\n return 172800;\r\n case \"ts_time_next_fivedays\":\r\n case \"ts_time_last_fivedays\":\r\n return 432000;\r\n case \"ts_time_next_week\":\r\n case \"ts_time_last_week\":\r\n return 604800;\r\n case \"ts_time_next_month\":\r\n case \"ts_time_last_month\":\r\n return 2592000;\r\n }\r\n}\r\n\r\n/**\r\n * Function to convert the time span to a radio button id.\r\n * @param {string} time\r\n * @param {boolean} future\r\n * @returns {string}\r\n */\r\nfunction converttimetoid(time, future) {\r\n switch (time) {\r\n case \"15778463\":\r\n return \"ts_time_all\";\r\n case \"172800\":\r\n if (future) {\r\n return \"ts_time_next_twodays\";\r\n }\r\n return \"ts_time_past_twodays\";\r\n case \"432000\":\r\n if (future) {\r\n return \"ts_time_next_fivedays\";\r\n }\r\n return \"ts_time_last_fivedays\";\r\n case \"604800\":\r\n if (future) {\r\n return \"ts_time_next_week\";\r\n }\r\n return \"ts_time_last_week\";\r\n case \"2592000\":\r\n if (future) {\r\n return \"ts_time_next_month\";\r\n\r\n }\r\n return \"ts_time_last_month\";\r\n }\r\n}\r\n"],"names":["userid","settingsfromdb","futurebuttonid","converttimetoid","pastbuttonid","futureradiobuttons","forEach","button","id","parentNode","classList","add","checked","dispatchEvent","Event","alltimebutton","remove","pastradiobuttons","checkboxes","checkbox","basiclettercheck","completionlettercheck","postlettercheck","click","executeusersettings","savebutton","addEventListener","async","timespans","settings","timepast","timefuture","settingsset","contains","convertidtotime","collecttimefiltersettings","letterfilter","collectletterfiltersettings","timefilterpast","timefilterfuture","basicletter","completionletter","postletter","result","Ajax","call","methodname","args","parseInt","el","document","getElementById","style","opacity","display","saveusersettings","querySelectorAll","time","future"],"mappings":";;;;;;;;;;oFA6CqBA,OAAQC,gBAErBA,yBA+DqBA,oBAIrBC,eAAiBC,gBAAgBF,eAAc,kBAAsB,GACrEG,aAAeD,gBAAgBF,eAAc,gBAAoB,GAG9C,gBAAnBC,gBACAG,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOC,KAAON,iBACdK,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,iBAItDC,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOC,KAAOJ,eACdG,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,kBAMtDD,cAAcT,SAAQ,SAASC,QAC3BA,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,cAMvCI,WAAWZ,SAAQ,SAASa,cACpBC,iBAAmC,gBAAhBD,SAASX,IAA0D,KAAlCP,eAAc,YAClEoB,sBAAwC,qBAAhBF,SAASX,IAAoE,MAAvCP,eAAc,iBAC5EqB,gBAAkC,eAAhBH,SAASX,IAAwD,MAAjCP,eAAc,YAEhEmB,kBAAoBC,uBAAyBC,kBAC7CH,SAASI,WA9GbC,CAAoBvB,gBAIxBwB,WAAWC,iBAAiB,SAASC,qBAI7BC,yBA2IJC,SAAW,CAAEC,SAAU,EAAGC,WAAY,GACtCC,aAAc,KAIlBjB,cAAcT,SAAQ,SAASC,QACxBA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgB3B,OAAOC,IAC9CqB,SAAQ,WAAiBK,gBAAgB3B,OAAOC,IAChDwB,aAAc,MAIjBA,mBACOH,gBAIXxB,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,WAAiBK,gBAAgB3B,OAAOC,QAIxDS,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgB3B,OAAOC,QAG/CqB,SA3KaM,GACZC,4BA+GJP,SAAW,aAAgB,mBAAuB,aAAiB,UAEvEX,WAAWZ,SAAQ,SAASa,aACpBA,SAASP,eACFO,SAASX,QACP,cACDqB,SAAQ,YAAkB,YAEzB,mBACDA,SAAQ,iBAAuB,YAE9B,aACDA,SAAQ,WAAiB,MAOlCA,SAlIgBQ,wBAkBKrC,OAAQsC,eAAgBC,iBAAkBC,YAAaC,iBAAkBC,gBACjGC,OACJA,aAAeC,cAAKC,KAAK,CAAC,CACtBC,WAAY,uCACZC,KAAM,CACF/C,OAAQgD,SAAShD,QACjBsC,eAAgBA,eAChBC,iBAAkBA,iBAClBC,YAAaA,YACbC,iBAAkBA,iBAClBC,WAAYA,mBAShBO,GAAKC,SAASC,eAAe,uCACjCF,GAAGG,MAAMC,QAAU,EACnBJ,GAAGG,MAAME,QAAU,QAOZX,OA3CGY,CAAiBvD,OAAQ4B,UAAS,SAAcA,UAAS,WACxCQ,aAAY,YAAiBA,aAAY,iBAAsBA,aAAY,0EAhCpGX,WAAayB,SAASC,eAAe,8BAGrCpC,cAAgBmC,SAASM,iBAAiB,uBAC1CnD,mBAAqB6C,SAASM,iBAAiB,0BAC/CvC,iBAAmBiC,SAASM,iBAAiB,wBAG7CtC,WAAagC,SAASM,iBAAiB,gCAuMpCtB,gBAAgB1B,WAEdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM,iBAUVL,gBAAgBsD,KAAMC,eACnBD,UACC,iBACM,kBACN,gBACGC,OACO,uBAEJ,2BACN,gBACGA,OACO,wBAEJ,4BACN,gBACGA,OACO,oBAEJ,wBACN,iBACGA,OACO,qBAGJ"} \ No newline at end of file +{"version":3,"file":"usersettings_save.min.js","sources":["../src/usersettings_save.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\r\n//\r\n// Moodle is free software: you can redistribute it and/or modify\r\n// it under the terms of the GNU General Public License as published by\r\n// the Free Software Foundation, either version 3 of the License, or\r\n// (at your option) any later version.\r\n//\r\n// Moodle is distributed in the hope that it will be useful,\r\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n// GNU General Public License for more details.\r\n//\r\n// You should have received a copy of the GNU General Public License\r\n// along with Moodle. If not, see .\r\n\r\n/**\r\n * Javascript to save the user settings in the database.\r\n *\r\n * This file implements 1 functionality:\r\n * - If the \"save settings\" button is pressed, store the settings in the database.\r\n *\r\n * @module block_townsquare/timefilter\r\n * @copyright 2024 Tamaro Walter\r\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\r\n */\r\n\r\nimport Ajax from 'core/ajax';\r\n\r\n// Get the save button for the user settings.\r\nconst savebutton = document.getElementById('ts_usersettings_savebutton');\r\n\r\n// Get the buttons from the time filter.\r\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\r\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\r\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\r\n\r\n// Get the checkboxes from the letter filter.\r\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\r\n\r\n/**\r\n * Init function\r\n *\r\n * @param {number} userid The id of the current user.\r\n * @param {object} settingsfromdb The settings from the database, if there are any.\r\n */\r\nexport function init(userid, settingsfromdb) {\r\n // When the page is loaded, set the settings from the database.\r\n if (settingsfromdb) {\r\n executeusersettings(settingsfromdb);\r\n }\r\n\r\n // Add event listener to the save button.\r\n savebutton.addEventListener('click', async function() {\r\n\r\n // First step: collect the current settings.\r\n // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes.\r\n let timespans = collecttimefiltersettings();\r\n let letterfilter = collectletterfiltersettings();\r\n\r\n // Second step: store the usersettings in the database.\r\n await saveusersettings(userid, timespans['timepast'], timespans['timefuture'], letterfilter['basicletter'],\r\n letterfilter['completionletter'], letterfilter['postletter']);\r\n });\r\n}\r\n\r\n/**\r\n * Function to save the user settings in the database.\r\n * @param {number} userid\r\n * @param {number} timefilterpast\r\n * @param {number} timefilterfuture\r\n * @param {number} basicletter\r\n * @param {number} completionletter\r\n * @param {number} postletter\r\n * @returns {Promise<*>}\r\n */\r\nasync function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) {\r\n let result ;\r\n result = await Ajax.call([{\r\n methodname: 'block_townsquare_record_usersettings',\r\n args: {\r\n userid: parseInt(userid),\r\n timefilterpast: timefilterpast,\r\n timefilterfuture: timefilterfuture,\r\n basicletter: basicletter,\r\n completionletter: completionletter,\r\n postletter: postletter\r\n },\r\n }]);\r\n\r\n // Show a success message.\r\n let el = document.getElementById('ts_usersettings_successlabel');\r\n el.style.display = 'block';\r\n el.style.opacity = 1.0;\r\n\r\n // Start a new setInterval timer to gradually fade out the label.\r\n if (el.fadeOutTimer) {\r\n clearInterval(el.fadeOutTimer);\r\n }\r\n setTimeout(function () {\r\n el.fadeOutTimer = setInterval(function () {\r\n if (el.style.opacity > 0.4) {\r\n el.style.opacity -= 0.1;\r\n } else if (el.style.opacity > 0) {\r\n el.style.opacity -= 0.2;\r\n } else {\r\n // Once opacity reaches 0, clear the timer and hide the label.\r\n clearInterval(el.fadeOutTimer);\r\n el.style.display = 'none';\r\n }\r\n }, 100);\r\n }, 3000);\r\n return result;\r\n}\r\n\r\n/**\r\n * Function to execute existing user settings when loading the townsquare.\r\n * @param {Object} settingsfromdb\r\n */\r\nfunction executeusersettings(settingsfromdb) {\r\n\r\n // First step: set the time filter settings.\r\n // Change the time into the correct radio button id.\r\n let futurebuttonid = converttimetoid(settingsfromdb['timefilterfuture'], true);\r\n let pastbuttonid = converttimetoid(settingsfromdb['timefilterpast'], false);\r\n\r\n // If the time span is a combination of past and future, go through the two radio buttons and activate the filter.\r\n if (futurebuttonid !== \"ts_time_all\") {\r\n futureradiobuttons.forEach(function(button) {\r\n if (button.id === futurebuttonid) {\r\n button.parentNode.classList.add('active');\r\n button.checked = true;\r\n button.dispatchEvent(new Event('change'));\r\n alltimebutton.forEach(function(alltimebutton) {\r\n alltimebutton.checked = false;\r\n alltimebutton.parentNode.classList.remove('active');\r\n });\r\n }\r\n });\r\n pastradiobuttons.forEach(function(button) {\r\n if (button.id === pastbuttonid) {\r\n button.parentNode.classList.add('active');\r\n button.checked = true;\r\n button.dispatchEvent(new Event('change'));\r\n alltimebutton.forEach(function(alltimebutton) {\r\n alltimebutton.checked = false;\r\n alltimebutton.parentNode.classList.remove('active');\r\n });\r\n }\r\n });\r\n } else {\r\n // If the time span is set to all time, activate the all time button.\r\n alltimebutton.forEach(function(button) {\r\n button.parentNode.classList.add('active');\r\n button.checked = true;\r\n button.dispatchEvent(new Event('change'));\r\n });\r\n }\r\n\r\n // Second step: set the letter filter settings.\r\n // Per default all checkboxes are checked. If the setting is 0, uncheck the checkbox.\r\n checkboxes.forEach(function(checkbox) {\r\n let basiclettercheck = checkbox.id === 'basicletter' && settingsfromdb['basicletter'] === \"\";\r\n let completionlettercheck = checkbox.id === 'completionletter' && settingsfromdb['completionletter'] === \"0\";\r\n let postlettercheck = checkbox.id === 'postletter' && settingsfromdb['postletter'] === \"0\";\r\n\r\n if (basiclettercheck || completionlettercheck || postlettercheck) {\r\n checkbox.click();\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Function to collect the letter filter settings.\r\n * @returns {{basicletter: number, completionletter: number, postletter: number}}\r\n */\r\nfunction collectletterfiltersettings() {\r\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\r\n\r\n checkboxes.forEach(function(checkbox) {\r\n if (checkbox.checked) {\r\n switch(checkbox.id) {\r\n case \"basicletter\":\r\n settings['basicletter'] = 1;\r\n break;\r\n case \"completionletter\":\r\n settings['completionletter'] = 1;\r\n break;\r\n case \"postletter\":\r\n settings['postletter'] = 1;\r\n break;\r\n\r\n }\r\n }\r\n });\r\n // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit.\r\n return settings;\r\n}\r\n\r\n/**\r\n * Function to collect the time filter settings.\r\n * @returns {{timepast: number, timefuture: number}}\r\n */\r\nfunction collecttimefiltersettings() {\r\n let settings = { timepast: 0, timefuture: 0};\r\n let settingsset = false;\r\n\r\n // Get the relevant time spans of the time filter.\r\n // Check if the alltimebutton is set.\r\n alltimebutton.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timepast'] = convertidtotime(button.id);\r\n settings['timefuture'] = convertidtotime(button.id);\r\n settingsset = true;\r\n }\r\n });\r\n\r\n if (settingsset) {\r\n return settings;\r\n }\r\n\r\n // If the alltimebutton is not set, check which of the future/past buttons is set.\r\n futureradiobuttons.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timefuture'] = convertidtotime(button.id);\r\n }\r\n });\r\n\r\n pastradiobuttons.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timepast'] = convertidtotime(button.id);\r\n }\r\n });\r\n return settings;\r\n}\r\n\r\n\r\n/**\r\n * Function to convert the radio button id to a useable time span.\r\n * @param {string} id The id of the radio button\r\n * @returns {number}\r\n */\r\nfunction convertidtotime(id) {\r\n // TODO: Please use global functions if possible.\r\n switch(id) {\r\n case \"ts_time_all\":\r\n return 15778463;\r\n case \"ts_time_next_twodays\":\r\n case \"ts_time_last_twodays\":\r\n return 172800;\r\n case \"ts_time_next_fivedays\":\r\n case \"ts_time_last_fivedays\":\r\n return 432000;\r\n case \"ts_time_next_week\":\r\n case \"ts_time_last_week\":\r\n return 604800;\r\n case \"ts_time_next_month\":\r\n case \"ts_time_last_month\":\r\n return 2592000;\r\n }\r\n}\r\n\r\n/**\r\n * Function to convert the time span to a radio button id.\r\n * @param {string} time\r\n * @param {boolean} future\r\n * @returns {string}\r\n */\r\nfunction converttimetoid(time, future) {\r\n switch (time) {\r\n case \"15778463\":\r\n return \"ts_time_all\";\r\n case \"172800\":\r\n if (future) {\r\n return \"ts_time_next_twodays\";\r\n }\r\n return \"ts_time_past_twodays\";\r\n case \"432000\":\r\n if (future) {\r\n return \"ts_time_next_fivedays\";\r\n }\r\n return \"ts_time_last_fivedays\";\r\n case \"604800\":\r\n if (future) {\r\n return \"ts_time_next_week\";\r\n }\r\n return \"ts_time_last_week\";\r\n case \"2592000\":\r\n if (future) {\r\n return \"ts_time_next_month\";\r\n\r\n }\r\n return \"ts_time_last_month\";\r\n }\r\n}\r\n"],"names":["userid","settingsfromdb","futurebuttonid","converttimetoid","pastbuttonid","futureradiobuttons","forEach","button","id","parentNode","classList","add","checked","dispatchEvent","Event","alltimebutton","remove","pastradiobuttons","checkboxes","checkbox","basiclettercheck","completionlettercheck","postlettercheck","click","executeusersettings","savebutton","addEventListener","async","timespans","settings","timepast","timefuture","settingsset","contains","convertidtotime","collecttimefiltersettings","letterfilter","collectletterfiltersettings","timefilterpast","timefilterfuture","basicletter","completionletter","postletter","result","Ajax","call","methodname","args","parseInt","el","document","getElementById","style","display","opacity","fadeOutTimer","clearInterval","setTimeout","setInterval","saveusersettings","querySelectorAll","time","future"],"mappings":";;;;;;;;;;oFA6CqBA,OAAQC,gBAErBA,yBAuEqBA,oBAIrBC,eAAiBC,gBAAgBF,eAAc,kBAAsB,GACrEG,aAAeD,gBAAgBF,eAAc,gBAAoB,GAG9C,gBAAnBC,gBACAG,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOC,KAAON,iBACdK,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,iBAItDC,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOC,KAAOJ,eACdG,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,kBAMtDD,cAAcT,SAAQ,SAASC,QAC3BA,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,cAMvCI,WAAWZ,SAAQ,SAASa,cACpBC,iBAAmC,gBAAhBD,SAASX,IAA0D,KAAlCP,eAAc,YAClEoB,sBAAwC,qBAAhBF,SAASX,IAAoE,MAAvCP,eAAc,iBAC5EqB,gBAAkC,eAAhBH,SAASX,IAAwD,MAAjCP,eAAc,YAEhEmB,kBAAoBC,uBAAyBC,kBAC7CH,SAASI,WAtHbC,CAAoBvB,gBAIxBwB,WAAWC,iBAAiB,SAASC,qBAI7BC,yBAmJJC,SAAW,CAAEC,SAAU,EAAGC,WAAY,GACtCC,aAAc,KAIlBjB,cAAcT,SAAQ,SAASC,QACxBA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgB3B,OAAOC,IAC9CqB,SAAQ,WAAiBK,gBAAgB3B,OAAOC,IAChDwB,aAAc,MAIjBA,mBACOH,gBAIXxB,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,WAAiBK,gBAAgB3B,OAAOC,QAIxDS,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgB3B,OAAOC,QAG/CqB,SAnLaM,GACZC,4BAuHJP,SAAW,aAAgB,mBAAuB,aAAiB,UAEvEX,WAAWZ,SAAQ,SAASa,aACpBA,SAASP,eACFO,SAASX,QACP,cACDqB,SAAQ,YAAkB,YAEzB,mBACDA,SAAQ,iBAAuB,YAE9B,aACDA,SAAQ,WAAiB,MAOlCA,SA1IgBQ,wBAkBKrC,OAAQsC,eAAgBC,iBAAkBC,YAAaC,iBAAkBC,gBACjGC,OACJA,aAAeC,cAAKC,KAAK,CAAC,CACtBC,WAAY,uCACZC,KAAM,CACF/C,OAAQgD,SAAShD,QACjBsC,eAAgBA,eAChBC,iBAAkBA,iBAClBC,YAAaA,YACbC,iBAAkBA,iBAClBC,WAAYA,mBAKhBO,GAAKC,SAASC,eAAe,gCACjCF,GAAGG,MAAMC,QAAU,QACnBJ,GAAGG,MAAME,QAAU,EAGfL,GAAGM,cACHC,cAAcP,GAAGM,qBAErBE,YAAW,WACPR,GAAGM,aAAeG,aAAY,WACtBT,GAAGG,MAAME,QAAU,GACnBL,GAAGG,MAAME,SAAW,GACbL,GAAGG,MAAME,QAAU,EAC1BL,GAAGG,MAAME,SAAW,IAGpBE,cAAcP,GAAGM,cACjBN,GAAGG,MAAMC,QAAU,UAExB,OACJ,KACIV,OAnDGgB,CAAiB3D,OAAQ4B,UAAS,SAAcA,UAAS,WAAgBQ,aAAY,YACpEA,aAAY,iBAAsBA,aAAY,0EAhCvEX,WAAayB,SAASC,eAAe,8BAGrCpC,cAAgBmC,SAASU,iBAAiB,uBAC1CvD,mBAAqB6C,SAASU,iBAAiB,0BAC/C3C,iBAAmBiC,SAASU,iBAAiB,wBAG7C1C,WAAagC,SAASU,iBAAiB,gCA+MpC1B,gBAAgB1B,WAEdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM,iBAUVL,gBAAgB0D,KAAMC,eACnBD,UACC,iBACM,kBACN,gBACGC,OACO,uBAEJ,2BACN,gBACGA,OACO,wBAEJ,4BACN,gBACGA,OACO,oBAEJ,wBACN,iBACGA,OACO,qBAGJ"} \ No newline at end of file diff --git a/amd/src/usersettings_save.js b/amd/src/usersettings_save.js index 7a8d964..56957e5 100644 --- a/amd/src/usersettings_save.js +++ b/amd/src/usersettings_save.js @@ -58,8 +58,8 @@ export function init(userid, settingsfromdb) { let letterfilter = collectletterfiltersettings(); // Second step: store the usersettings in the database. - await saveusersettings(userid, timespans['timepast'], timespans['timefuture'], - letterfilter['basicletter'], letterfilter['completionletter'], letterfilter['postletter']); + await saveusersettings(userid, timespans['timepast'], timespans['timefuture'], letterfilter['basicletter'], + letterfilter['completionletter'], letterfilter['postletter']); }); } @@ -87,20 +87,28 @@ async function saveusersettings(userid, timefilterpast, timefilterfuture, basicl }, }]); - //if (result === true) { - - //} - //window.alert('Settings saved'); // Show a success message. let el = document.getElementById('ts_usersettings_successlabel'); - el.style.opacity = 1; el.style.display = 'block'; - /*setInterval(function() { - if (el.style.opacity > 0) { - el.style.opacity -= 0.1; - } - }, 100); - el.style.display = 'none';*/ + el.style.opacity = 1.0; + + // Start a new setInterval timer to gradually fade out the label. + if (el.fadeOutTimer) { + clearInterval(el.fadeOutTimer); + } + setTimeout(function () { + el.fadeOutTimer = setInterval(function () { + if (el.style.opacity > 0.4) { + el.style.opacity -= 0.1; + } else if (el.style.opacity > 0) { + el.style.opacity -= 0.2; + } else { + // Once opacity reaches 0, clear the timer and hide the label. + clearInterval(el.fadeOutTimer); + el.style.display = 'none'; + } + }, 100); + }, 3000); return result; } diff --git a/lang/en/block_townsquare.php b/lang/en/block_townsquare.php index e3e6467..694fc88 100644 --- a/lang/en/block_townsquare.php +++ b/lang/en/block_townsquare.php @@ -69,6 +69,8 @@ $string['savehelpicontext'] = 'Save Settings for the future'; $string['savemessage'] = 'Settings successfully saved!'; +// End of the side panel filter strings. + // Letter strings. $string['invalidmodulename'] = 'Module name is unknown or not supported'; diff --git a/styles.css b/styles.css index 09426a0..8ac9b65 100644 --- a/styles.css +++ b/styles.css @@ -24,8 +24,8 @@ } .ts_usersettings_message { + background-color: #eee; display: none; - opacity: 1.0; } /* Style for all letter or content templates */ From 844b12ed0a187d9ca47a7b1087d0243e586ee4b6 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Mon, 18 Mar 2024 17:18:32 +0100 Subject: [PATCH 038/123] update workflows to moodle 403 --- .github/workflows/moodle-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index 07ba552..a2eae8d 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: - php: ['8.1'] + php: ['8.2'] moodle-branch: ['MOODLE_403_STABLE'] database: ['pgsql'] From 37f741d7f48cca97dbed3ff3bb864b1deb7d3046 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Wed, 20 Mar 2024 16:17:44 +0100 Subject: [PATCH 039/123] change database name --- block_townsquare.php | 2 +- db/install.xml | 2 +- db/upgrade.php | 10 +++++----- externallib.php | 8 ++++---- version.php | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/block_townsquare.php b/block_townsquare.php index abd4c48..438108b 100644 --- a/block_townsquare.php +++ b/block_townsquare.php @@ -55,7 +55,7 @@ public function get_content():object { $this->content->text = $OUTPUT->render_from_template('block_townsquare/blockcontent', $mustachedata); // Get the user settings if available. - $usersettings = $DB->get_record('townsquare_usersettings', ['userid' => $USER->id]); + $usersettings = $DB->get_record('block_townsquare_usersettings', ['userid' => $USER->id]); // Load all javascripts. $this->page->requires->js_call_amd('block_townsquare/postletter', 'init'); diff --git a/db/install.xml b/db/install.xml index 46b5367..6ce3173 100644 --- a/db/install.xml +++ b/db/install.xml @@ -4,7 +4,7 @@ xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd" > - +
diff --git a/db/upgrade.php b/db/upgrade.php index 6292709..d0a22c5 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -40,10 +40,10 @@ function xmldb_block_townsquare_upgrade($oldversion) { // Documentation for the XMLDB Editor can be found at {@link https://docs.moodle.org/dev/XMLDB_editor}. if ($oldversion < 2024020700) { - // Define new table townsquare_usersettings to be created. - $table = new xmldb_table('townsquare_usersettings'); + // Define new table block_townsquare_usersettings to be created. + $table = new xmldb_table('block_townsquare_usersettings'); - // Adding fields to table townsquare_usersettings. + // Adding fields to table block_townsquare_usersettings. $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); $table->add_field('timefilterpast', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); @@ -52,10 +52,10 @@ function xmldb_block_townsquare_upgrade($oldversion) { $table->add_field('completionletter', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); $table->add_field('postletter', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); - // Adding keys to table townsquare_usersettings. + // Adding keys to table block_townsquare_usersettings. $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); - // Conditionally launch create table for townsquare_usersettings. + // Conditionally launch create table for block_townsquare_usersettings. if (!$dbman->table_exists($table)) { $dbman->create_table($table); } diff --git a/externallib.php b/externallib.php index adb894c..a72e212 100644 --- a/externallib.php +++ b/externallib.php @@ -79,12 +79,12 @@ public static function record_usersettings($userid, $timefilterpast, $timefilter $transaction = $DB->start_delegated_transaction(); // Check if the user already has a record in the database. - if ($records = $DB->get_records('townsquare_usersettings', ['userid' => $userid])) { + if ($records = $DB->get_records('block_townsquare_usersettings', ['userid' => $userid])) { // If there more than a record (it only should be only one), delete all of them and insert the new one. if (count($records) > 1) { try { foreach ($records as $record) { - $DB->delete_records('townsquare_usersettings', ['id' => $record->id]); + $DB->delete_records('block_townsquare_usersettings', ['id' => $record->id]); } } catch (Exception $e) { $transaction->rollback($e); @@ -98,7 +98,7 @@ public static function record_usersettings($userid, $timefilterpast, $timefilter $record->basicletter = $basicletter; $record->completionletter = $completionletter; $record->postletter = $postletter; - $DB->update_record('townsquare_usersettings', $record); + $DB->update_record('block_townsquare_usersettings', $record); $transaction->allow_commit(); return true; } @@ -110,7 +110,7 @@ public static function record_usersettings($userid, $timefilterpast, $timefilter $record->basicletter = $basicletter; $record->completionletter = $completionletter; $record->postletter = $postletter; - $DB->insert_record('townsquare_usersettings', $record); + $DB->insert_record('block_townsquare_usersettings', $record); $transaction->allow_commit(); return true; } diff --git a/version.php b/version.php index 6eaf1cf..8ef746d 100644 --- a/version.php +++ b/version.php @@ -25,6 +25,6 @@ defined('MOODLE_INTERNAL') || die(); $plugin->component = 'block_townsquare'; $plugin->release = '0.1.0'; -$plugin->version = 2024020700; +$plugin->version = 2024032000; $plugin->requires = 2022041900; $plugin->maturity = MATURITY_ALPHA; From 72ca2abac44d23e502bff76a0966c7d4a749b2a4 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Wed, 20 Mar 2024 16:26:48 +0100 Subject: [PATCH 040/123] make tablename shorter --- block_townsquare.php | 2 +- db/install.xml | 2 +- db/upgrade.php | 7 +++---- externallib.php | 8 ++++---- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/block_townsquare.php b/block_townsquare.php index 438108b..70433ee 100644 --- a/block_townsquare.php +++ b/block_townsquare.php @@ -55,7 +55,7 @@ public function get_content():object { $this->content->text = $OUTPUT->render_from_template('block_townsquare/blockcontent', $mustachedata); // Get the user settings if available. - $usersettings = $DB->get_record('block_townsquare_usersettings', ['userid' => $USER->id]); + $usersettings = $DB->get_record('block_townsquare_preferences', ['userid' => $USER->id]); // Load all javascripts. $this->page->requires->js_call_amd('block_townsquare/postletter', 'init'); diff --git a/db/install.xml b/db/install.xml index 6ce3173..7cb2ae0 100644 --- a/db/install.xml +++ b/db/install.xml @@ -4,7 +4,7 @@ xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd" > -
+
diff --git a/db/upgrade.php b/db/upgrade.php index d0a22c5..a7d90dd 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -35,15 +35,14 @@ function xmldb_block_townsquare_upgrade($oldversion) { $dbman = $DB->get_manager(); // For further information please read {@link https://docs.moodle.org/dev/Upgrade_API}. - // // You will also have to create the db/install.xml file by using the XMLDB Editor. // Documentation for the XMLDB Editor can be found at {@link https://docs.moodle.org/dev/XMLDB_editor}. if ($oldversion < 2024020700) { - // Define new table block_townsquare_usersettings to be created. - $table = new xmldb_table('block_townsquare_usersettings'); + // Define new table block_townsquare_preferences to be created. + $table = new xmldb_table('block_townsquare_preferences'); - // Adding fields to table block_townsquare_usersettings. + // Adding fields to table block_townsquare_preferences. $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); $table->add_field('timefilterpast', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); diff --git a/externallib.php b/externallib.php index a72e212..b4f8e42 100644 --- a/externallib.php +++ b/externallib.php @@ -79,12 +79,12 @@ public static function record_usersettings($userid, $timefilterpast, $timefilter $transaction = $DB->start_delegated_transaction(); // Check if the user already has a record in the database. - if ($records = $DB->get_records('block_townsquare_usersettings', ['userid' => $userid])) { + if ($records = $DB->get_records('block_townsquare_preferences', ['userid' => $userid])) { // If there more than a record (it only should be only one), delete all of them and insert the new one. if (count($records) > 1) { try { foreach ($records as $record) { - $DB->delete_records('block_townsquare_usersettings', ['id' => $record->id]); + $DB->delete_records('block_townsquare_preferences', ['id' => $record->id]); } } catch (Exception $e) { $transaction->rollback($e); @@ -98,7 +98,7 @@ public static function record_usersettings($userid, $timefilterpast, $timefilter $record->basicletter = $basicletter; $record->completionletter = $completionletter; $record->postletter = $postletter; - $DB->update_record('block_townsquare_usersettings', $record); + $DB->update_record('block_townsquare_preferences', $record); $transaction->allow_commit(); return true; } @@ -110,7 +110,7 @@ public static function record_usersettings($userid, $timefilterpast, $timefilter $record->basicletter = $basicletter; $record->completionletter = $completionletter; $record->postletter = $postletter; - $DB->insert_record('block_townsquare_usersettings', $record); + $DB->insert_record('block_townsquare_preferences', $record); $transaction->allow_commit(); return true; } From ae0685181d99388649c076db7cc73a36b95e23be Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 21 Mar 2024 17:08:31 +0100 Subject: [PATCH 041/123] update table in database --- db/services.php | 1 + db/upgrade.php | 8 ++++---- version.php | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/db/services.php b/db/services.php index 936e023..cd10d72 100644 --- a/db/services.php +++ b/db/services.php @@ -28,6 +28,7 @@ 'block_townsquare_record_usersettings' => [ 'classname' => 'block_townsquare_external', 'classpath' => 'blocks/townsquare/externallib.php', + 'methodname' => 'record_usersettings', 'description' => 'Records the user settings for the townsquare block', 'type' => 'write', 'ajax' => true, diff --git a/db/upgrade.php b/db/upgrade.php index a7d90dd..619432e 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -38,7 +38,7 @@ function xmldb_block_townsquare_upgrade($oldversion) { // You will also have to create the db/install.xml file by using the XMLDB Editor. // Documentation for the XMLDB Editor can be found at {@link https://docs.moodle.org/dev/XMLDB_editor}. - if ($oldversion < 2024020700) { + if ($oldversion < 2024032201) { // Define new table block_townsquare_preferences to be created. $table = new xmldb_table('block_townsquare_preferences'); @@ -51,16 +51,16 @@ function xmldb_block_townsquare_upgrade($oldversion) { $table->add_field('completionletter', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); $table->add_field('postletter', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); - // Adding keys to table block_townsquare_usersettings. + // Adding keys to table block_townsquare_preferences. $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); - // Conditionally launch create table for block_townsquare_usersettings. + // Conditionally launch create table for block_townsquare_preferences. if (!$dbman->table_exists($table)) { $dbman->create_table($table); } // Moodleoverflow savepoint reached. - upgrade_block_savepoint(true, 2024020700, 'townsquare'); + upgrade_block_savepoint(true, 2024032201, 'townsquare'); } return true; diff --git a/version.php b/version.php index 8ef746d..bfb54b8 100644 --- a/version.php +++ b/version.php @@ -25,6 +25,6 @@ defined('MOODLE_INTERNAL') || die(); $plugin->component = 'block_townsquare'; $plugin->release = '0.1.0'; -$plugin->version = 2024032000; +$plugin->version = 2024032201; $plugin->requires = 2022041900; $plugin->maturity = MATURITY_ALPHA; From 91833cc042c06a9c936cb10caf1a59589a0a4a5f Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 21 Mar 2024 17:08:54 +0100 Subject: [PATCH 042/123] add privacy provider functions --- classes/privacy/provider.php | 184 +++++++++++++++++++++++++++++++++++ lang/en/block_townsquare.php | 9 ++ 2 files changed, 193 insertions(+) create mode 100644 classes/privacy/provider.php diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php new file mode 100644 index 0000000..0f7be2b --- /dev/null +++ b/classes/privacy/provider.php @@ -0,0 +1,184 @@ +. + + +/** + * Privacy Provider for block_townsquare. + * @package block_townsquare + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace block_townsquare\privacy; + +use core_privacy\local\request\approved_userlist; +use core_privacy\local\request\userlist; +use core_privacy\local\metadata\collection; +use core_privacy\local\request\approved_contextlist; +use core_privacy\local\request\contextlist; +use core_privacy\local\request\writer; +use core_privacy\local\request\helper as request_helper; + + +/** + * Class that describes the type of data that is stored. + * + * @package block_townsquare + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class provider implements + \core_privacy\local\metadata\provider, + \core_privacy\local\request\plugin\provider, + \core_privacy\local\request\core_userlist_provider { + + + /** + * get_contexts_for_userid - to explain where data is held within Moodle for your plugin; and + * export_user_data - to export a user's personal data from your plugin. + * delete_data_for_all_users_in_context - to delete all data for all users in the specified context. + * delete_data_for_user - to delete all user data for the specified user, in the specified contexts. + * get_users_in_context - to locate the users who hold any personal data in a specific context; and + * delete_data_for_users - to delete data for multiple users in the specified context. + */ + + /** + * Function that describes the type of data that is stored. + * @param collection $collection + * @return collection + */ + public static function get_metadata(collection $collection): collection { + $collection->add_database_table('block_townsquare_preferences', [ + 'userid' => 'privacy:metadata:block_townsquare_preferences:userid', + 'timefilterpast' => 'privacy:metadata:block_townsquare_preferences:timefilterpast', + 'timefilterfuture' => 'privacy:metadata:block_townsquare_preferences:timefilterfuture', + 'basicletter' => 'privacy:metadata:block_townsquare_preferences:basicletter', + 'completionletter' => 'privacy:metadata:block_townsquare_preferences:completionletter', + 'postletter' => 'privacy:metadata:block_townsquare_preferences:postletter', + ], 'privacy:metadata:block_townsquare_preferences'); + return $collection; + } + + /** + * Get the list of contexts that contain user information for the specified user. + * + * @param int $userid The user to search. + * @return contextlist $contextlist The list of contexts used in this plugin. + */ + public static function get_contexts_for_userid(int $userid): contextlist { + $sql = "SELECT context.id + FROM {block_townsquare_preferences} preferences + JOIN {user} user + ON preferences.userid = user.id + JOIN {context} context + ON context.instanceid = user.id + AND context.contextlevel = :contextlevel + WHERE preferences.userid = :userid"; + + $params = ['userid' => $userid, 'contextlevel' => CONTEXT_USER]; + + $contextlist = new contextlist(); + $contextlist->add_from_sql($sql, $params); + return $contextlist; + } + + /** + * Get the list of users within a specific context. + * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination. + * @return void + */ + public static function get_users_in_context(userlist $userlist): void { + $context = $userlist->get_context(); + + if (!$context instanceof \context_user) { + return; + } + + $sql = "SELECT userid + FROM {block_townsquare_preferences} + WHERE userid = ?"; + $params = [$context->instanceid]; + $userlist->add_from_sql('userid', $sql, $params); + } + + /** + * Export all user data for the specified user, in the specified contexts. + * @param approved_contextlist $contextlist + * @return void + */ + public static function export_user_data(approved_contextlist $contextlist): void { + global $DB; + $townsquaredata = []; + $results = $DB->get_records('block_townsquare_preferences', ['userid' => $contextlist->get_user()->id]); + + foreach ($results as $result) { + $data = new \stdClass(); + $data->userid = $result->userid; + $data->timefilterpast = $result->timefilterpast; + $data->timefilterfuture = $result->timefilterfuture; + $data->basicletter = $result->basicletter; + $data->completionletter = $result->completionletter; + $data->postletter = $result->postletter; + + $townsquaredata[] = $data; + } + if (!empty($townsquaredata)) { + writer::with_context($contextlist->current())->export_data([ + get_string('pluginname', 'block_townsquare')], (object) $townsquaredata); + } + } + + /** + * Delete multiple user data within a single context. + * @param approved_userlist $userlist The approved context and user information to delete information for. + */ + public static function delete_data_for_users(approved_userlist $userlist) { + global $DB; + $context = $userlist->get_context(); + if ($context == CONTEXT_USER && + in_array($context->instanceid, $userlist->get_userids())) { + $DB->delete_records('block_townsquare_preferences', ['userid' => $context->instanceid]); + } + } + + /** + * Delete all data for all users in the specified context. + * @param \context $context The specific context to delete data for. + * @return void + * @throws \dml_exception + */ + public static function delete_data_for_all_users_in_context(\context $context) { + global $DB; + if ($context == CONTEXT_USER) { + $DB->delete_records('block_townsquare_preferences', ['userid' => $context->instanceid]); + } + } + + + /** + * Delete all user data for the specified user, in the specified contexts. + * @param approved_contextlist $contextlist The approved contexts and user information to delete information for. + * @return void + * @throws \dml_exception + */ + public static function delete_data_for_user(approved_contextlist $contextlist) { + global $DB; + foreach($contextlist as $context) { + if ($context->contextlevel == CONTEXT_USER && $contextlist->get_user()->id == $context->instanceid) { + $DB->delete_records('block_townsquare_preferences', ['userid' => $contextlist->get_user()->id]); + } + } + } +} \ No newline at end of file diff --git a/lang/en/block_townsquare.php b/lang/en/block_townsquare.php index 694fc88..09e5bbd 100644 --- a/lang/en/block_townsquare.php +++ b/lang/en/block_townsquare.php @@ -31,6 +31,15 @@ $string['pluginname:addinstance'] = 'Add the Town Square block'; $string['pluginname:myaddinstance'] = 'Add the Town Square block to the dashboard'; +// Privacy strings. +$string['privacy:metadata:block_townsquare_preferences'] = 'Town Square stores the filters that a user wants to have activated.'; +$string['privacy:metadata:block_townsquare_preferences:userid'] = 'The user id'; +$string['privacy:metadata:block_townsquare_preferences:timefilterpast'] = 'How far back the user wants to see notifications'; +$string['privacy:metadata:block_townsquare_preferences:timefilterfuture'] = 'How far into the future the user wants to see notifications'; +$string['privacy:metadata:block_townsquare_preferences:basicletter'] = 'If the user wants to see basic letters'; +$string['privacy:metadata:block_townsquare_preferences:completionletter'] = 'If the user wants to see completion letters'; +$string['privacy:metadata:block_townsquare_preferences:postletter'] = 'If the user wants to see post letters'; + // Error strings. $string['invalidlettertype'] = 'Invalid function parameter, please use a valid letter type'; From 7c5dd1d874d0e05cfe566e6ac2aa5d4b1ba91686 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 21 Mar 2024 17:54:31 +0100 Subject: [PATCH 043/123] fix error in contentcontroller --- classes/contentcontroller.php | 1 - 1 file changed, 1 deletion(-) diff --git a/classes/contentcontroller.php b/classes/contentcontroller.php index 1ca5449..878ce7e 100644 --- a/classes/contentcontroller.php +++ b/classes/contentcontroller.php @@ -80,7 +80,6 @@ public function build_content(): array { $tempcontent = new orientation_marker($index, $time); $this->content[$index] = $tempcontent->export_data(); $index++; - continue; } if (isset($event->eventtype) && $event->eventtype == 'post') { $templetter = new letter\post_letter($index, $event); From bf838a6252a5368540473dfb3929649d136e7039 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 21 Mar 2024 18:11:15 +0100 Subject: [PATCH 044/123] WIP: write test for privacy provider --- classes/privacy/provider.php | 9 +++---- tests/privacy/provider_test.php | 48 +++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 tests/privacy/provider_test.php diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php index 0f7be2b..82bef46 100644 --- a/classes/privacy/provider.php +++ b/classes/privacy/provider.php @@ -29,7 +29,6 @@ use core_privacy\local\request\approved_contextlist; use core_privacy\local\request\contextlist; use core_privacy\local\request\writer; -use core_privacy\local\request\helper as request_helper; /** @@ -42,7 +41,7 @@ class provider implements \core_privacy\local\metadata\provider, \core_privacy\local\request\plugin\provider, - \core_privacy\local\request\core_userlist_provider { + \core_privacy\local\request\core_userlist_provider { /** @@ -136,7 +135,7 @@ public static function export_user_data(approved_contextlist $contextlist): void } if (!empty($townsquaredata)) { writer::with_context($contextlist->current())->export_data([ - get_string('pluginname', 'block_townsquare')], (object) $townsquaredata); + get_string('pluginname', 'block_townsquare'), ], (object) $townsquaredata); } } @@ -175,10 +174,10 @@ public static function delete_data_for_all_users_in_context(\context $context) { */ public static function delete_data_for_user(approved_contextlist $contextlist) { global $DB; - foreach($contextlist as $context) { + foreach ($contextlist as $context) { if ($context->contextlevel == CONTEXT_USER && $contextlist->get_user()->id == $context->instanceid) { $DB->delete_records('block_townsquare_preferences', ['userid' => $contextlist->get_user()->id]); } } } -} \ No newline at end of file +} diff --git a/tests/privacy/provider_test.php b/tests/privacy/provider_test.php new file mode 100644 index 0000000..10d6faf --- /dev/null +++ b/tests/privacy/provider_test.php @@ -0,0 +1,48 @@ +. + +/** + * Block recentlyaccesseditems privacy provider tests. + * + * @package block_recentlyaccesseditems + * @copyright 2018 Michael Hawkins + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since Moodle 3.6 + */ +namespace block_townsquare\privacy; + +defined('MOODLE_INTERNAL') || die(); + +use core_privacy\local\request\approved_contextlist; +use core_privacy\local\request\userlist; +use block_townsquare\privacy\provider; +use core_privacy\tests\provider_testcase; + +class provider_test extends provider_testcase { + // TODO: implement privacy provider tests. + public function test_provider(): void { + } + + // Functions that needs to be implemented. + // public function test_get_contexts_for_userid() {} // Test getting the context for the user id related to this plugin. + // public function test_get_users_in_context() {} // Test getting the users in the context related to this plugin. + + // public function test_get_metadata() {} + // public function test_export_user_data() {} + // public function test_delete_data_for_all_users_in_context() {} + // public function test_delete_data_for_user() {} + // public function test_delete_data_for_users() {} +} From edbb2eda9b5a7996b58dcc3889e30aa94478b2d3 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 22 Mar 2024 18:00:50 +0100 Subject: [PATCH 045/123] add privacy provider test --- classes/privacy/provider.php | 16 +-- tests/privacy/provider_test.php | 212 ++++++++++++++++++++++++++++++-- 2 files changed, 205 insertions(+), 23 deletions(-) diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php index 82bef46..b0af406 100644 --- a/classes/privacy/provider.php +++ b/classes/privacy/provider.php @@ -43,23 +43,13 @@ class provider implements \core_privacy\local\request\plugin\provider, \core_privacy\local\request\core_userlist_provider { - - /** - * get_contexts_for_userid - to explain where data is held within Moodle for your plugin; and - * export_user_data - to export a user's personal data from your plugin. - * delete_data_for_all_users_in_context - to delete all data for all users in the specified context. - * delete_data_for_user - to delete all user data for the specified user, in the specified contexts. - * get_users_in_context - to locate the users who hold any personal data in a specific context; and - * delete_data_for_users - to delete data for multiple users in the specified context. - */ - /** * Function that describes the type of data that is stored. * @param collection $collection * @return collection */ public static function get_metadata(collection $collection): collection { - $collection->add_database_table('block_townsquare_preferences', [ + $collection->add_database_table('block_townsquare', [ 'userid' => 'privacy:metadata:block_townsquare_preferences:userid', 'timefilterpast' => 'privacy:metadata:block_townsquare_preferences:timefilterpast', 'timefilterfuture' => 'privacy:metadata:block_townsquare_preferences:timefilterfuture', @@ -146,7 +136,7 @@ public static function export_user_data(approved_contextlist $contextlist): void public static function delete_data_for_users(approved_userlist $userlist) { global $DB; $context = $userlist->get_context(); - if ($context == CONTEXT_USER && + if ($context instanceof \context_user && in_array($context->instanceid, $userlist->get_userids())) { $DB->delete_records('block_townsquare_preferences', ['userid' => $context->instanceid]); } @@ -160,7 +150,7 @@ public static function delete_data_for_users(approved_userlist $userlist) { */ public static function delete_data_for_all_users_in_context(\context $context) { global $DB; - if ($context == CONTEXT_USER) { + if ($context instanceof \context_user) { $DB->delete_records('block_townsquare_preferences', ['userid' => $context->instanceid]); } } diff --git a/tests/privacy/provider_test.php b/tests/privacy/provider_test.php index 10d6faf..3571e46 100644 --- a/tests/privacy/provider_test.php +++ b/tests/privacy/provider_test.php @@ -26,23 +26,215 @@ defined('MOODLE_INTERNAL') || die(); +use core_privacy\local\metadata\collection; use core_privacy\local\request\approved_contextlist; +use core_privacy\local\request\approved_userlist; use core_privacy\local\request\userlist; use block_townsquare\privacy\provider; +use core_privacy\local\request\writer; use core_privacy\tests\provider_testcase; class provider_test extends provider_testcase { - // TODO: implement privacy provider tests. - public function test_provider(): void { + + // Attributes. + private $testdata; + + public function setUp(): void { + // Create a course and a user. + $this->testdata = new \stdClass(); + $this->testdata->course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]); + $this->testdata->student = $this->getDataGenerator()->create_user(); + $this->testdata->studentcontext = \context_user::instance($this->testdata->student->id); + $this->getDataGenerator()->enrol_user($this->testdata->student->id, $this->testdata->course->id, 'student'); + $this->resetAfterTest(); } + // public function tearDown(): void {} + // Functions that needs to be implemented. - // public function test_get_contexts_for_userid() {} // Test getting the context for the user id related to this plugin. - // public function test_get_users_in_context() {} // Test getting the users in the context related to this plugin. - - // public function test_get_metadata() {} - // public function test_export_user_data() {} - // public function test_delete_data_for_all_users_in_context() {} - // public function test_delete_data_for_user() {} - // public function test_delete_data_for_users() {} + + /** + * Test if the provider gets the right context for a user. + * @return void + */ + public function test_get_contexts_for_userid(): void { + // Check that no context are found before the setting is set. + $contextlist = provider::get_contexts_for_userid($this->testdata->student->id); + $this->assertEquals(0, count($contextlist)); + + // Add a usersetting. + $this->helper_add_preference($this->testdata->student->id); + $contextlist = provider::get_contexts_for_userid($this->testdata->student->id); + + // Check the context that should be there. + $this->assertEquals(1, count($contextlist)); + $this->assertEquals($this->testdata->studentcontext, $contextlist->current()); + } + + /** + * Test getting the users in the context related to this plugin. + * @return void + */ + public function test_get_users_in_context():void { + // Check that no users are found in the context before the setting is set. + $userlist = new userlist($this->testdata->studentcontext, 'block_townsquare'); + provider::get_users_in_context($userlist); + $this->assertEquals(0 , count($userlist)); + + // Add a usersetting. + $this->helper_add_preference($this->testdata->student->id); + provider::get_users_in_context($userlist); + + // Check that the provider fetches the right data. + $this->assertEquals(1, count($userlist)); + $this->assertEquals($this->testdata->student, $userlist->current()); + } + + + /** + * Test if the metadata is correct. + * @return void + */ + public function test_get_metadata():void { + // Get the metadata and check if a collection exists. + $metadata = provider::get_metadata(new collection('block_townsquare')); + $collection = $metadata->get_collection(); + $this->assertEquals(1, count($collection)); + + // Check the content of the metadata. + $table = reset($collection); + $privacyfields = $table->get_privacy_fields(); + + $this->assertEquals('block_townsquare', $table->get_name()); + $this->assertEquals(6, count($privacyfields)); + $this->assertArrayHasKey('userid', $privacyfields); + $this->assertArrayHasKey('timefilterpast', $privacyfields); + $this->assertArrayHasKey('timefilterfuture', $privacyfields); + $this->assertArrayHasKey('basicletter', $privacyfields); + $this->assertArrayHasKey('completionletter', $privacyfields); + $this->assertArrayHasKey('postletter', $privacyfields); + } + + /** + * Test if user data get exported correctly. + * @return void + */ + public function test_export_user_data() { + global $DB; + // Add a usersetting. + $this->helper_add_preference($this->testdata->student->id); + + // Confirm that the setting is in the database. + $record = $DB->get_records('block_townsquare_preferences', ['userid' => $this->testdata->student->id]); + $this->assertEquals(1, count($record)); + + // Export the data. + $approvedlist = new approved_contextlist($this->testdata->student, 'block_townsquare', [$this->testdata->studentcontext->id]); + provider::export_user_data($approvedlist); + $writer = writer::with_context($this->testdata->studentcontext); + $this->assertEquals(true, $writer->has_any_data()); + } + + /** + * Test if data is delete for all users within an approved contextlist + * @return void + */ + public function test_delete_data_for_all_users_in_context() { + global $DB; + // Add another user with a different context and add usersettings. + $user2 = $this->getDataGenerator()->create_user(); + $this->getDataGenerator()->enrol_user($user2->id, $this->testdata->course->id, 'teacher'); + $this->helper_add_preference($this->testdata->student->id); + $this->helper_add_preference($user2->id); + + // Try a system context deletion, which should have no effect. + provider::delete_data_for_all_users_in_context(\context_system::instance()); + $this->assertEquals(2, count($DB->get_records('block_townsquare_preferences'))); + + // Delete all data in the first users context (studentcontext). + provider::delete_data_for_all_users_in_context(\context_user::instance($this->testdata->student->id)); + + // Only students data should be deleted. + $records = $DB->get_records('block_townsquare_preferences'); + $this->assertEquals(1, count($records)); + } + + /** + * Test deleting data within an approved contextlist for a user. + * @return void + */ + public function test_delete_data_for_user() { + global $DB; + // Add another user with a different context and add usersettings. + $teacher = $this->getDataGenerator()->create_user(); + $this->getDataGenerator()->enrol_user($teacher->id, $this->testdata->course->id, 'teacher'); + $this->helper_add_preference($this->testdata->student->id); + $this->helper_add_preference($teacher->id); + + // Try a system context deletion, which should have no effect. + provider::delete_data_for_all_users_in_context(\context_system::instance()); + $this->assertEquals(2, count($DB->get_records('block_townsquare_preferences'))); + + // Try to delete the teacher data in a students context, which should have no effect. + $approvedlist = new approved_contextlist($teacher, 'block_townsquare', [$this->testdata->studentcontext->id]); + provider::delete_data_for_user($approvedlist); + $this->assertEquals(2, count($DB->get_records('block_townsquare_preferences'))); + + // Delete the teacher date in its own context. + $approvedlist = new approved_contextlist($teacher, 'block_townsquare', [\context_user::instance($teacher->id)->id]); + provider::delete_data_for_user($approvedlist); + $record = $DB->get_record('block_townsquare_preferences', ['userid' => $this->testdata->student->id]); + $this->assertEquals(1, count($DB->get_records('block_townsquare_preferences'))); + $this->assertEquals($this->testdata->student->id, $record->userid); + } + + /** + * Test deleting data within a contest for an approved userlist. + * @return void + */ + public function test_delete_data_for_users() { + global $DB; + // Add another user with a different context and add usersettings. + $teacher = $this->getDataGenerator()->create_user(); + $this->getDataGenerator()->enrol_user($teacher->id, $this->testdata->course->id, 'teacher'); + $this->helper_add_preference($this->testdata->student->id); + $this->helper_add_preference($teacher->id); + + // Try a system context deletion, which should have no effect. + provider::delete_data_for_all_users_in_context(\context_system::instance()); + $this->assertEquals(2, count($DB->get_records('block_townsquare_preferences'))); + + // Try to delete user data in another users context, which should have no effect.. + $approvedlist = new approved_userlist($this->testdata->studentcontext, 'block_townsquare', [$teacher->id]); + provider::delete_data_for_users($approvedlist); + $this->assertEquals(2, count($DB->get_records('block_townsquare_preferences'))); + + // Delete user data in the right context. + $approvedlist = new approved_userlist($this->testdata->studentcontext, 'block_townsquare', [$this->testdata->student->id]); + provider::delete_data_for_users($approvedlist); + $this->assertEquals(1, count($DB->get_records('block_townsquare_preferences'))); + $record = $DB->get_record('block_townsquare_preferences', ['userid' => $teacher->id]); + $this->assertEquals($teacher->id, $record->userid); + + } + + + // Helper functions. + + /** + * Helper function that sets up the test data. + * @return void + */ + private function helper_add_preference($userid) { + global $DB; + // Create a user preference for townsquare content filter. + $this->testdata->setting = new \stdClass(); + $this->testdata->setting->userid = $userid; + $this->testdata->setting->timefilterpast = 15778463; + $this->testdata->setting->timefilterfuture = 15778463; + $this->testdata->setting->basicletter = 1; + $this->testdata->setting->completionletter = 1; + $this->testdata->setting->postletter = 0; + $DB->insert_record('block_townsquare_preferences', $this->testdata->setting); + } } From 96ae09956cf350ba0c1b6304c5c5df79d9614e02 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 22 Mar 2024 18:22:14 +0100 Subject: [PATCH 046/123] moodlecheck fixes and code cleaning --- tests/privacy/provider_test.php | 71 +++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/tests/privacy/provider_test.php b/tests/privacy/provider_test.php index 3571e46..4830c70 100644 --- a/tests/privacy/provider_test.php +++ b/tests/privacy/provider_test.php @@ -15,17 +15,14 @@ // along with Moodle. If not, see . /** - * Block recentlyaccesseditems privacy provider tests. + * Unit tests for the block_townsquare * - * @package block_recentlyaccesseditems - * @copyright 2018 Michael Hawkins + * @package block_townsquare + * @copyright 2024 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @since Moodle 3.6 */ namespace block_townsquare\privacy; -defined('MOODLE_INTERNAL') || die(); - use core_privacy\local\metadata\collection; use core_privacy\local\request\approved_contextlist; use core_privacy\local\request\approved_userlist; @@ -34,9 +31,24 @@ use core_privacy\local\request\writer; use core_privacy\tests\provider_testcase; +/** + * PHPUnit tests for testing the functionalities of the townsquare privacy provider + * + * @package block_townsquare + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * + * @covers \block_townsquare\privacy\provider + */ class provider_test extends provider_testcase { // Attributes. + + /** @var object The data that will be used for testing. + * This Class contains: + * - a course + * - a student and a teacher and context for both + */ private $testdata; public function setUp(): void { @@ -45,13 +57,14 @@ public function setUp(): void { $this->testdata->course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]); $this->testdata->student = $this->getDataGenerator()->create_user(); $this->testdata->studentcontext = \context_user::instance($this->testdata->student->id); + $this->testdata->teacher = $this->getDataGenerator()->create_user(); + $this->testdata->teachercontext = \context_user::instance($this->testdata->teacher->id); + $this->getDataGenerator()->enrol_user($this->testdata->teacher->id, $this->testdata->course->id, 'teacher'); $this->getDataGenerator()->enrol_user($this->testdata->student->id, $this->testdata->course->id, 'student'); $this->resetAfterTest(); } - // public function tearDown(): void {} - - // Functions that needs to be implemented. + // Test functions. /** * Test if the provider gets the right context for a user. @@ -119,7 +132,7 @@ public function test_get_metadata():void { * Test if user data get exported correctly. * @return void */ - public function test_export_user_data() { + public function test_export_user_data(): void { global $DB; // Add a usersetting. $this->helper_add_preference($this->testdata->student->id); @@ -129,7 +142,8 @@ public function test_export_user_data() { $this->assertEquals(1, count($record)); // Export the data. - $approvedlist = new approved_contextlist($this->testdata->student, 'block_townsquare', [$this->testdata->studentcontext->id]); + $approvedlist = new approved_contextlist($this->testdata->student, 'block_townsquare', + [$this->testdata->studentcontext->id]); provider::export_user_data($approvedlist); $writer = writer::with_context($this->testdata->studentcontext); $this->assertEquals(true, $writer->has_any_data()); @@ -139,13 +153,11 @@ public function test_export_user_data() { * Test if data is delete for all users within an approved contextlist * @return void */ - public function test_delete_data_for_all_users_in_context() { + public function test_delete_data_for_all_users_in_context(): void { global $DB; // Add another user with a different context and add usersettings. - $user2 = $this->getDataGenerator()->create_user(); - $this->getDataGenerator()->enrol_user($user2->id, $this->testdata->course->id, 'teacher'); $this->helper_add_preference($this->testdata->student->id); - $this->helper_add_preference($user2->id); + $this->helper_add_preference($this->testdata->teacher->id); // Try a system context deletion, which should have no effect. provider::delete_data_for_all_users_in_context(\context_system::instance()); @@ -163,25 +175,25 @@ public function test_delete_data_for_all_users_in_context() { * Test deleting data within an approved contextlist for a user. * @return void */ - public function test_delete_data_for_user() { + public function test_delete_data_for_user(): void { global $DB; - // Add another user with a different context and add usersettings. - $teacher = $this->getDataGenerator()->create_user(); - $this->getDataGenerator()->enrol_user($teacher->id, $this->testdata->course->id, 'teacher'); + // Add usersettings for both user. $this->helper_add_preference($this->testdata->student->id); - $this->helper_add_preference($teacher->id); + $this->helper_add_preference($this->testdata->teacher->id); // Try a system context deletion, which should have no effect. provider::delete_data_for_all_users_in_context(\context_system::instance()); $this->assertEquals(2, count($DB->get_records('block_townsquare_preferences'))); // Try to delete the teacher data in a students context, which should have no effect. - $approvedlist = new approved_contextlist($teacher, 'block_townsquare', [$this->testdata->studentcontext->id]); + $approvedlist = new approved_contextlist($this->testdata->teacher, 'block_townsquare', + [$this->testdata->studentcontext->id]); provider::delete_data_for_user($approvedlist); $this->assertEquals(2, count($DB->get_records('block_townsquare_preferences'))); // Delete the teacher date in its own context. - $approvedlist = new approved_contextlist($teacher, 'block_townsquare', [\context_user::instance($teacher->id)->id]); + $approvedlist = new approved_contextlist($this->testdata->teacher, 'block_townsquare', + [$this->testdata->teachercontext->id]); provider::delete_data_for_user($approvedlist); $record = $DB->get_record('block_townsquare_preferences', ['userid' => $this->testdata->student->id]); $this->assertEquals(1, count($DB->get_records('block_townsquare_preferences'))); @@ -192,20 +204,18 @@ public function test_delete_data_for_user() { * Test deleting data within a contest for an approved userlist. * @return void */ - public function test_delete_data_for_users() { + public function test_delete_data_for_users(): void { global $DB; - // Add another user with a different context and add usersettings. - $teacher = $this->getDataGenerator()->create_user(); - $this->getDataGenerator()->enrol_user($teacher->id, $this->testdata->course->id, 'teacher'); + // Add usersettings for both user. $this->helper_add_preference($this->testdata->student->id); - $this->helper_add_preference($teacher->id); + $this->helper_add_preference($this->testdata->teacher->id); // Try a system context deletion, which should have no effect. provider::delete_data_for_all_users_in_context(\context_system::instance()); $this->assertEquals(2, count($DB->get_records('block_townsquare_preferences'))); // Try to delete user data in another users context, which should have no effect.. - $approvedlist = new approved_userlist($this->testdata->studentcontext, 'block_townsquare', [$teacher->id]); + $approvedlist = new approved_userlist($this->testdata->studentcontext, 'block_townsquare', [$this->testdata->teacher->id]); provider::delete_data_for_users($approvedlist); $this->assertEquals(2, count($DB->get_records('block_townsquare_preferences'))); @@ -213,12 +223,11 @@ public function test_delete_data_for_users() { $approvedlist = new approved_userlist($this->testdata->studentcontext, 'block_townsquare', [$this->testdata->student->id]); provider::delete_data_for_users($approvedlist); $this->assertEquals(1, count($DB->get_records('block_townsquare_preferences'))); - $record = $DB->get_record('block_townsquare_preferences', ['userid' => $teacher->id]); - $this->assertEquals($teacher->id, $record->userid); + $record = $DB->get_record('block_townsquare_preferences', ['userid' => $this->testdata->teacher->id]); + $this->assertEquals($this->testdata->teacher->id, $record->userid); } - // Helper functions. /** From 572fce9be281665e55066cf27bdb00adc96837b7 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 22 Mar 2024 18:26:47 +0100 Subject: [PATCH 047/123] change user table name for pgsql --- classes/privacy/provider.php | 6 +++--- tests/privacy/provider_test.php | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php index b0af406..5b2633c 100644 --- a/classes/privacy/provider.php +++ b/classes/privacy/provider.php @@ -69,10 +69,10 @@ public static function get_metadata(collection $collection): collection { public static function get_contexts_for_userid(int $userid): contextlist { $sql = "SELECT context.id FROM {block_townsquare_preferences} preferences - JOIN {user} user - ON preferences.userid = user.id + JOIN {user} u + ON preferences.userid = u.id JOIN {context} context - ON context.instanceid = user.id + ON context.instanceid = u.id AND context.contextlevel = :contextlevel WHERE preferences.userid = :userid"; diff --git a/tests/privacy/provider_test.php b/tests/privacy/provider_test.php index 4830c70..c3355ac 100644 --- a/tests/privacy/provider_test.php +++ b/tests/privacy/provider_test.php @@ -42,8 +42,6 @@ */ class provider_test extends provider_testcase { - // Attributes. - /** @var object The data that will be used for testing. * This Class contains: * - a course From 57de45500ef2cda03f683d877c9e46c1bc635da0 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 22 Mar 2024 18:36:36 +0100 Subject: [PATCH 048/123] change line breaks to LF in JS-file --- amd/build/coursefilter.min.js.map | 2 +- amd/build/filtercontroller.min.js.map | 2 +- amd/build/letterfilter.min.js.map | 2 +- amd/build/postletter.min.js.map | 2 +- amd/build/timefilter.min.js.map | 2 +- amd/build/usersettings_save.min.js.map | 2 +- amd/src/usersettings_save.js | 594 ++++++++++++------------- 7 files changed, 303 insertions(+), 303 deletions(-) diff --git a/amd/build/coursefilter.min.js.map b/amd/build/coursefilter.min.js.map index c40b743..de47173 100644 --- a/amd/build/coursefilter.min.js.map +++ b/amd/build/coursefilter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"coursefilter.min.js","sources":["../src/coursefilter.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\r\n//\r\n// Moodle is free software: you can redistribute it and/or modify\r\n// it under the terms of the GNU General Public License as published by\r\n// the Free Software Foundation, either version 3 of the License, or\r\n// (at your option) any later version.\r\n//\r\n// Moodle is distributed in the hope that it will be useful,\r\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n// GNU General Public License for more details.\r\n//\r\n// You should have received a copy of the GNU General Public License\r\n// along with Moodle. If not, see .\r\n\r\n/**\r\n * Javascript for the course filter\r\n *\r\n * This file implements 1 functionality:\r\n * - Checks the checkboxes of the course filter and hides content from courses if the checkbox is not checked.\r\n *\r\n * @module block_townsquare/coursefilter\r\n * @copyright 2024 Tamaro Walter\r\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\r\n */\r\n\r\n// Get the relevant checkboxes.\r\nconst checkboxes = document.querySelectorAll('.ts_course_checkbox');\r\n\r\n/**\r\n * Init function\r\n */\r\nexport function init() {\r\n checkboxes.forEach(function(checkbox) {\r\n checkbox.addEventListener('change', function() {\r\n // Get the courseid associated with the checkbox\r\n const courseid = checkbox.id;\r\n\r\n // Get all letters that are \"activated\".\r\n // Activated means that all filters accept the letter and want to show it.\r\n const letters = document.querySelectorAll('.townsquare_letter.ts_timefilter_active.ts_letterfilter_active');\r\n\r\n // Loop through each letter mark it as \"active\" or not based on checkbox state and the letter id.\r\n letters.forEach(function(letter) {\r\n let letterCourseId = letter.querySelector('.townsquareletter_course').id;\r\n\r\n if (courseid === letterCourseId) {\r\n if (checkbox.checked) {\r\n letter.classList.add('ts_coursefilter_active'); // Mark the letter as \"active\".\r\n } else {\r\n letter.classList.remove('ts_coursefilter_active'); // Mark the letter as \"not active\".\r\n }\r\n }\r\n });\r\n });\r\n });\r\n}\r\n"],"names":["checkboxes","forEach","checkbox","addEventListener","courseid","id","document","querySelectorAll","letter","letterCourseId","querySelector","checked","classList","add","remove"],"mappings":"wJAiCIA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,iBAE1BC,SAAWF,SAASG,GAIVC,SAASC,iBAAiB,kEAGlCN,SAAQ,SAASO,YACjBC,eAAiBD,OAAOE,cAAc,4BAA4BL,GAElED,WAAaK,iBACTP,SAASS,QACTH,OAAOI,UAAUC,IAAI,0BAErBL,OAAOI,UAAUE,OAAO;;;;;;;;;;;MAvB1Cd,WAAaM,SAASC,iBAAiB"} \ No newline at end of file +{"version":3,"file":"coursefilter.min.js","sources":["../src/coursefilter.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 * Javascript for the course filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the course filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/coursefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant checkboxes.\nconst checkboxes = document.querySelectorAll('.ts_course_checkbox');\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n // Get the courseid associated with the checkbox\n const courseid = checkbox.id;\n\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.ts_timefilter_active.ts_letterfilter_active');\n\n // Loop through each letter mark it as \"active\" or not based on checkbox state and the letter id.\n letters.forEach(function(letter) {\n let letterCourseId = letter.querySelector('.townsquareletter_course').id;\n\n if (courseid === letterCourseId) {\n if (checkbox.checked) {\n letter.classList.add('ts_coursefilter_active'); // Mark the letter as \"active\".\n } else {\n letter.classList.remove('ts_coursefilter_active'); // Mark the letter as \"not active\".\n }\n }\n });\n });\n });\n}\n"],"names":["checkboxes","forEach","checkbox","addEventListener","courseid","id","document","querySelectorAll","letter","letterCourseId","querySelector","checked","classList","add","remove"],"mappings":"6IAgCO,WACHA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,WAEhC,MAAMC,SAAWF,SAASG,GAIVC,SAASC,iBAAiB,kEAGlCN,SAAQ,SAASO,QACrB,IAAIC,eAAiBD,OAAOE,cAAc,4BAA4BL,GAElED,WAAaK,iBACTP,SAASS,QACTH,OAAOI,UAAUC,IAAI,0BAErBL,OAAOI,UAAUE,OAAO;;;;;;;;;;;AAvBhD,MAAMd,WAAaM,SAASC,iBAAiB,sBA6B5C"} \ No newline at end of file diff --git a/amd/build/filtercontroller.min.js.map b/amd/build/filtercontroller.min.js.map index f9ce468..ed17974 100644 --- a/amd/build/filtercontroller.min.js.map +++ b/amd/build/filtercontroller.min.js.map @@ -1 +1 @@ -{"version":3,"file":"filtercontroller.min.js","sources":["../src/filtercontroller.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\r\n//\r\n// Moodle is free software: you can redistribute it and/or modify\r\n// it under the terms of the GNU General Public License as published by\r\n// the Free Software Foundation, either version 3 of the License, or\r\n// (at your option) any later version.\r\n//\r\n// Moodle is distributed in the hope that it will be useful,\r\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n// GNU General Public License for more details.\r\n//\r\n// You should have received a copy of the GNU General Public License\r\n// along with Moodle. If not, see .\r\n\r\n/**\r\n * Javascript to show/hide letters based on all filters\r\n *\r\n * This file implements 1 functionality:\r\n * - If the \"save settings\" button is pressed, store the settings in the database.\r\n *\r\n * @module block_townsquare/filtercontroller\r\n * @copyright 2024 Tamaro Walter\r\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\r\n */\r\n\r\n// Get all letters from townsquare.\r\nconst letters = document.querySelectorAll('.townsquare_letter');\r\n\r\n/**\r\n * Init function\r\n */\r\nexport function init() {\r\n // First step: activate every letter by adding the filter classes.\r\n letters.forEach(function(letter) {\r\n letter.classList.add('ts_coursefilter_active');\r\n letter.classList.add('ts_timefilter_active');\r\n letter.classList.add('ts_letterfilter_active');\r\n });\r\n\r\n // Add a mutation listener to each letter.\r\n letters.forEach(function(letter) {\r\n const observer = new MutationObserver(function(mutations) {\r\n mutations.forEach(function(mutation) {\r\n if (mutation.attributeName === 'class') {\r\n // If the class of the letter changes, check if the letter should be shown or hidden.\r\n let coursefilter = letter.classList.contains('ts_coursefilter_active');\r\n let timefilter = letter.classList.contains('ts_timefilter_active');\r\n let letterfilter = letter.classList.contains('ts_letterfilter_active');\r\n\r\n // If all filters are active, show the letter.\r\n if (coursefilter && timefilter && letterfilter) {\r\n letter.style.display = 'block';\r\n } else {\r\n letter.style.display = 'none';\r\n }\r\n }\r\n });\r\n });\r\n\r\n observer.observe(letter, {attributes: true});\r\n });\r\n}\r\n"],"names":["letters","forEach","letter","classList","add","MutationObserver","mutations","mutation","attributeName","coursefilter","contains","timefilter","letterfilter","style","display","observe","attributes","document","querySelectorAll"],"mappings":"4JAkCIA,QAAQC,SAAQ,SAASC,QACrBA,OAAOC,UAAUC,IAAI,0BACrBF,OAAOC,UAAUC,IAAI,wBACrBF,OAAOC,UAAUC,IAAI,6BAIzBJ,QAAQC,SAAQ,SAASC,QACJ,IAAIG,kBAAiB,SAASC,WAC3CA,UAAUL,SAAQ,SAASM,aACQ,UAA3BA,SAASC,cAA2B,KAEhCC,aAAeP,OAAOC,UAAUO,SAAS,0BACzCC,WAAaT,OAAOC,UAAUO,SAAS,wBACvCE,aAAeV,OAAOC,UAAUO,SAAS,0BAIzCR,OAAOW,MAAMC,QADbL,cAAgBE,YAAcC,aACP,QAEA,cAM9BG,QAAQb,OAAQ,CAACc,YAAY;;;;;;;;;;;MAjCxChB,QAAUiB,SAASC,iBAAiB"} \ No newline at end of file +{"version":3,"file":"filtercontroller.min.js","sources":["../src/filtercontroller.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 * Javascript to show/hide letters based on all filters\n *\n * This file implements 1 functionality:\n * - If the \"save settings\" button is pressed, store the settings in the database.\n *\n * @module block_townsquare/filtercontroller\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get all letters from townsquare.\nconst letters = document.querySelectorAll('.townsquare_letter');\n\n/**\n * Init function\n */\nexport function init() {\n // First step: activate every letter by adding the filter classes.\n letters.forEach(function(letter) {\n letter.classList.add('ts_coursefilter_active');\n letter.classList.add('ts_timefilter_active');\n letter.classList.add('ts_letterfilter_active');\n });\n\n // Add a mutation listener to each letter.\n letters.forEach(function(letter) {\n const observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(mutation) {\n if (mutation.attributeName === 'class') {\n // If the class of the letter changes, check if the letter should be shown or hidden.\n let coursefilter = letter.classList.contains('ts_coursefilter_active');\n let timefilter = letter.classList.contains('ts_timefilter_active');\n let letterfilter = letter.classList.contains('ts_letterfilter_active');\n\n // If all filters are active, show the letter.\n if (coursefilter && timefilter && letterfilter) {\n letter.style.display = 'block';\n } else {\n letter.style.display = 'none';\n }\n }\n });\n });\n\n observer.observe(letter, {attributes: true});\n });\n}\n"],"names":["letters","forEach","letter","classList","add","MutationObserver","mutations","mutation","attributeName","coursefilter","contains","timefilter","letterfilter","style","display","observe","attributes","document","querySelectorAll"],"mappings":"iJAgCO,WAEHA,QAAQC,SAAQ,SAASC,QACrBA,OAAOC,UAAUC,IAAI,0BACrBF,OAAOC,UAAUC,IAAI,wBACrBF,OAAOC,UAAUC,IAAI,6BAIzBJ,QAAQC,SAAQ,SAASC,QACJ,IAAIG,kBAAiB,SAASC,WAC3CA,UAAUL,SAAQ,SAASM,UACvB,GAA+B,UAA3BA,SAASC,cAA2B,CAEpC,IAAIC,aAAeP,OAAOC,UAAUO,SAAS,0BACzCC,WAAaT,OAAOC,UAAUO,SAAS,wBACvCE,aAAeV,OAAOC,UAAUO,SAAS,0BAIzCR,OAAOW,MAAMC,QADbL,cAAgBE,YAAcC,aACP,QAEA,cAM9BG,QAAQb,OAAQ,CAACc,YAAY;;;;;;;;;;;AAjC9C,MAAMhB,QAAUiB,SAASC,iBAAiB,qBAmCzC"} \ No newline at end of file diff --git a/amd/build/letterfilter.min.js.map b/amd/build/letterfilter.min.js.map index a632bbe..02c4ab5 100644 --- a/amd/build/letterfilter.min.js.map +++ b/amd/build/letterfilter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"letterfilter.min.js","sources":["../src/letterfilter.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\r\n//\r\n// Moodle is free software: you can redistribute it and/or modify\r\n// it under the terms of the GNU General Public License as published by\r\n// the Free Software Foundation, either version 3 of the License, or\r\n// (at your option) any later version.\r\n//\r\n// Moodle is distributed in the hope that it will be useful,\r\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n// GNU General Public License for more details.\r\n//\r\n// You should have received a copy of the GNU General Public License\r\n// along with Moodle. If not, see .\r\n\r\n/**\r\n * Javascript for the letter filter\r\n *\r\n * This file implements 1 functionality:\r\n * - Checks the checkboxes of the letter filter and hides content from courses if the checkbox is not checked.\r\n *\r\n * @module block_townsquare/letterfilter\r\n * @copyright 2024 Tamaro Walter\r\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\r\n */\r\n\r\n// Get the relevant checkboxes.\r\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\r\n\r\n/**\r\n * Init function\r\n */\r\nexport function init() {\r\n checkboxes.forEach(function(checkbox) {\r\n checkbox.addEventListener('change', function() {\r\n // Get the letter name associated with the checkbox.\r\n const lettername = checkbox.id;\r\n\r\n // Get all letters that are \"activated\".\r\n // Activated means that all filters accept the letter and want to show it.\r\n const letters = document.querySelectorAll('.townsquare_letter.' + lettername +\r\n '.ts_timefilter_active.ts_coursefilter_active');\r\n\r\n // Loop through each letter and hide/show based on checkbox state.\r\n letters.forEach(function(letter) {\r\n if (checkbox.checked) {\r\n letter.classList.add('ts_letterfilter_active'); // Mark the letter as \"active\".\r\n } else {\r\n letter.classList.remove('ts_letterfilter_active'); // Mark the letter as \"not active\".\r\n }\r\n });\r\n });\r\n });\r\n}\r\n"],"names":["checkboxes","forEach","checkbox","addEventListener","lettername","id","document","querySelectorAll","letter","checked","classList","add","remove"],"mappings":"wJAiCIA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,iBAE1BC,WAAaF,SAASG,GAIZC,SAASC,iBAAiB,sBAAwBH,WACxB,gDAGlCH,SAAQ,SAASO,QACjBN,SAASO,QACTD,OAAOE,UAAUC,IAAI,0BAErBH,OAAOE,UAAUE,OAAO;;;;;;;;;;;MArBtCZ,WAAaM,SAASC,iBAAiB"} \ No newline at end of file +{"version":3,"file":"letterfilter.min.js","sources":["../src/letterfilter.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 * Javascript for the letter filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the letter filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/letterfilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant checkboxes.\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n // Get the letter name associated with the checkbox.\n const lettername = checkbox.id;\n\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.' + lettername +\n '.ts_timefilter_active.ts_coursefilter_active');\n\n // Loop through each letter and hide/show based on checkbox state.\n letters.forEach(function(letter) {\n if (checkbox.checked) {\n letter.classList.add('ts_letterfilter_active'); // Mark the letter as \"active\".\n } else {\n letter.classList.remove('ts_letterfilter_active'); // Mark the letter as \"not active\".\n }\n });\n });\n });\n}\n"],"names":["checkboxes","forEach","checkbox","addEventListener","lettername","id","document","querySelectorAll","letter","checked","classList","add","remove"],"mappings":"6IAgCO,WACHA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,WAEhC,MAAMC,WAAaF,SAASG,GAIZC,SAASC,iBAAiB,sBAAwBH,WACxB,gDAGlCH,SAAQ,SAASO,QACjBN,SAASO,QACTD,OAAOE,UAAUC,IAAI,0BAErBH,OAAOE,UAAUE,OAAO;;;;;;;;;;;AArB5C,MAAMZ,WAAaM,SAASC,iBAAiB,sBA0B5C"} \ No newline at end of file diff --git a/amd/build/postletter.min.js.map b/amd/build/postletter.min.js.map index aba2bad..fde6c82 100644 --- a/amd/build/postletter.min.js.map +++ b/amd/build/postletter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"postletter.min.js","sources":["../src/postletter.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\r\n//\r\n// Moodle is free software: you can redistribute it and/or modify\r\n// it under the terms of the GNU General Public License as published by\r\n// the Free Software Foundation, either version 3 of the License, or\r\n// (at your option) any later version.\r\n//\r\n// Moodle is distributed in the hope that it will be useful,\r\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n// GNU General Public License for more details.\r\n//\r\n// You should have received a copy of the GNU General Public License\r\n// along with Moodle. If not, see .\r\n\r\nimport {getString} from \"core/str\";\r\nimport {prefetchStrings} from 'core/prefetch';\r\n\r\n/**\r\n * Javascript for the post letter\r\n *\r\n * This file implements 2 functionalities:\r\n * - cuts posts that have many characters and shows a \"see more\" Button to see the whole text.\r\n * - Unnecessary

Tags from the Database are being replaced with line breaks to make the text more readable.\r\n *\r\n * @module block_townsquare/postletter\r\n * @copyright 2023 Tamaro Walter\r\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\r\n */\r\n\r\nconst contentElements = document.getElementsByClassName('postletter_message');\r\nconst buttons = document.getElementsByClassName('townsquare_showmore');\r\nconst originalTexts = [];\r\n\r\nconst Selectors = {\r\n actions: {\r\n seemorebutton: '[data-action=\"block_townsquare/showmore_button\"]',\r\n },\r\n};\r\n\r\n/**\r\n * Init function\r\n *\r\n * The function can cut the text or extract paragraphs of a post.\r\n */\r\nexport function init() {\r\n contentElements.forEach(\r\n (element) => {\r\n // Replace all

within the text with simple line breaks..\r\n replaceParagraghTags(element);\r\n\r\n // Check if the text is too long.\r\n if (element.textContent.length >= 250) {\r\n // If the text is too long, cut it.\r\n originalTexts[element.id] = element.innerHTML;\r\n cutString(element);\r\n element.parentElement.insertAdjacentHTML('beforeend', '

');\r\n buttons[element.id].setAttribute('showmore', 'true');\r\n } else {\r\n // If the text is not too long, hide the show more button.\r\n buttons[element.id].style.display = \"none\";\r\n }\r\n }\r\n );\r\n\r\n // Get the strings for the show more/show less button.\r\n prefetchStrings('moodle', ['showmore', 'showless',]);\r\n\r\n // Add event listeners for the show more Button.\r\n addEventListener();\r\n}\r\n\r\n/**\r\n * Function to cut a String at a length of 250 characters.\r\n * The function does not cut within a word or after a space.\r\n * If the cutting point is within a word, the function searches for the next space and cuts there.\r\n * @param {object} element\r\n */\r\nfunction cutString(element) {\r\n let text = element.textContent;\r\n let index = 250;\r\n while (text.charAt(index) != \" \") {\r\n index++;\r\n }\r\n element.innerHTML = text.substring(0,index);\r\n}\r\n\r\n/**\r\n * Event listener for the show more/show less button.\r\n */\r\nconst addEventListener = () => {\r\n document.addEventListener('click', e => {\r\n if (e.target.closest(Selectors.actions.seemorebutton)) {\r\n // Get the id of the clicked element.\r\n let letterid = e.target.id;\r\n contentElements.forEach(\r\n (element) => {\r\n if (element.id == letterid) {\r\n if (buttons[letterid].getAttribute('showmore') == 'true') {\r\n element.innerHTML = originalTexts[letterid];\r\n changeButtonString(letterid, false);\r\n } else {\r\n cutString(element);\r\n changeButtonString(letterid, true);\r\n }\r\n }\r\n }\r\n );\r\n }\r\n });\r\n};\r\n\r\n/**\r\n * Changes the button strings.\r\n * @param {string} index Which button should be changed\r\n * @param {boolean} toshowmore a boolean that indicates if the button should show more or less\r\n */\r\nasync function changeButtonString(index, toshowmore) {\r\n if (toshowmore == true) {\r\n buttons[index].textContent = await getString('showmore', 'moodle');\r\n buttons[index].setAttribute('showmore', 'true');\r\n } else {\r\n buttons[index].textContent = await getString('showless', 'moodle');\r\n buttons[index].setAttribute('showmore', 'false');\r\n }\r\n}\r\n\r\n/**\r\n * Removes in a text all   and surrounding

tags excluding the first occurrence.\r\n *\r\n * Helper function to make post look better.\r\n * @param {object} element\r\n */\r\nasync function replaceParagraghTags(element) {\r\n // Identify and store the first

and

tags\r\n let message = element.innerHTML;\r\n const firstPTag = message.indexOf('

');\r\n const lastPTag = message.lastIndexOf('

');\r\n\r\n // Remove   and surrounding

tags excluding the first occurrence\r\n message = message.replace(/

 <\\/p>/g, '').replace(/ /g, '');\r\n\r\n // Replace

tags with
excluding the first occurrence\r\n message = message.substring(0, firstPTag + 3) +\r\n message.substring(firstPTag + 3, lastPTag).replace(/

/g, '
').replace(/<\\/p>/g, '') +\r\n message.substring(lastPTag);\r\n element.innerHTML = message;\r\n}"],"names":["contentElements","forEach","element","message","innerHTML","firstPTag","indexOf","lastPTag","lastIndexOf","replace","substring","replaceParagraghTags","textContent","length","originalTexts","id","cutString","parentElement","insertAdjacentHTML","buttons","setAttribute","style","display","addEventListener","document","getElementsByClassName","Selectors","seemorebutton","text","index","charAt","e","target","closest","letterid","getAttribute","changeButtonString","toshowmore"],"mappings":"gMA8CIA,gBAAgBC,SACXC,0BAsF2BA,aAE5BC,QAAUD,QAAQE,gBAChBC,UAAYF,QAAQG,QAAQ,OAC5BC,SAAWJ,QAAQK,YAAY,QAGrCL,QAAUA,QAAQM,QAAQ,kBAAmB,IAAIA,QAAQ,UAAW,IAGpEN,QAAUA,QAAQO,UAAU,EAAGL,UAAY,GACvCF,QAAQO,UAAUL,UAAY,EAAGE,UAAUE,QAAQ,OAAQ,QAAQA,QAAQ,SAAU,IACrFN,QAAQO,UAAUH,UACtBL,QAAQE,UAAYD,QAjGZQ,CAAqBT,SAGjBA,QAAQU,YAAYC,QAAU,KAE9BC,cAAcZ,QAAQa,IAAMb,QAAQE,UACpCY,UAAUd,SACVA,QAAQe,cAAcC,mBAAmB,YAAa,OACtDC,QAAQjB,QAAQa,IAAIK,aAAa,WAAY,SAG7CD,QAAQjB,QAAQa,IAAIM,MAAMC,QAAU,wCAMhC,SAAU,CAAC,WAAY,aAGvCC;;;;;;;;;;;;MAvCEvB,gBAAkBwB,SAASC,uBAAuB,sBAClDN,QAAUK,SAASC,uBAAuB,uBAC1CX,cAAgB,GAEhBY,kBACO,CACLC,cAAe,6DA0CdX,UAAUd,aACX0B,KAAO1B,QAAQU,YACfiB,MAAQ,SACiB,KAAtBD,KAAKE,OAAOD,QACfA,QAEJ3B,QAAQE,UAAYwB,KAAKlB,UAAU,EAAEmB,aAMnCN,iBAAmB,KACrBC,SAASD,iBAAiB,SAASQ,OAC3BA,EAAEC,OAAOC,QAAQP,kBAAkBC,eAAgB,KAE/CO,SAAWH,EAAEC,OAAOjB,GACxBf,gBAAgBC,SACXC,UACOA,QAAQa,IAAMmB,WACoC,QAA9Cf,QAAQe,UAAUC,aAAa,aAC/BjC,QAAQE,UAAYU,cAAcoB,UAClCE,mBAAmBF,UAAU,KAE7BlB,UAAUd,SACVkC,mBAAmBF,UAAU,4BAc1CE,mBAAmBP,MAAOQ,YACnB,GAAdA,YACAlB,QAAQU,OAAOjB,kBAAoB,kBAAU,WAAY,UACzDO,QAAQU,OAAOT,aAAa,WAAY,UAExCD,QAAQU,OAAOjB,kBAAoB,kBAAU,WAAY,UACzDO,QAAQU,OAAOT,aAAa,WAAY"} \ No newline at end of file +{"version":3,"file":"postletter.min.js","sources":["../src/postletter.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\nimport {getString} from \"core/str\";\nimport {prefetchStrings} from 'core/prefetch';\n\n/**\n * Javascript for the post letter\n *\n * This file implements 2 functionalities:\n * - cuts posts that have many characters and shows a \"see more\" Button to see the whole text.\n * - Unnecessary

Tags from the Database are being replaced with line breaks to make the text more readable.\n *\n * @module block_townsquare/postletter\n * @copyright 2023 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nconst contentElements = document.getElementsByClassName('postletter_message');\nconst buttons = document.getElementsByClassName('townsquare_showmore');\nconst originalTexts = [];\n\nconst Selectors = {\n actions: {\n seemorebutton: '[data-action=\"block_townsquare/showmore_button\"]',\n },\n};\n\n/**\n * Init function\n *\n * The function can cut the text or extract paragraphs of a post.\n */\nexport function init() {\n contentElements.forEach(\n (element) => {\n // Replace all

within the text with simple line breaks..\n replaceParagraghTags(element);\n\n // Check if the text is too long.\n if (element.textContent.length >= 250) {\n // If the text is too long, cut it.\n originalTexts[element.id] = element.innerHTML;\n cutString(element);\n element.parentElement.insertAdjacentHTML('beforeend', '

');\n buttons[element.id].setAttribute('showmore', 'true');\n } else {\n // If the text is not too long, hide the show more button.\n buttons[element.id].style.display = \"none\";\n }\n }\n );\n\n // Get the strings for the show more/show less button.\n prefetchStrings('moodle', ['showmore', 'showless',]);\n\n // Add event listeners for the show more Button.\n addEventListener();\n}\n\n/**\n * Function to cut a String at a length of 250 characters.\n * The function does not cut within a word or after a space.\n * If the cutting point is within a word, the function searches for the next space and cuts there.\n * @param {object} element\n */\nfunction cutString(element) {\n let text = element.textContent;\n let index = 250;\n while (text.charAt(index) != \" \") {\n index++;\n }\n element.innerHTML = text.substring(0,index);\n}\n\n/**\n * Event listener for the show more/show less button.\n */\nconst addEventListener = () => {\n document.addEventListener('click', e => {\n if (e.target.closest(Selectors.actions.seemorebutton)) {\n // Get the id of the clicked element.\n let letterid = e.target.id;\n contentElements.forEach(\n (element) => {\n if (element.id == letterid) {\n if (buttons[letterid].getAttribute('showmore') == 'true') {\n element.innerHTML = originalTexts[letterid];\n changeButtonString(letterid, false);\n } else {\n cutString(element);\n changeButtonString(letterid, true);\n }\n }\n }\n );\n }\n });\n};\n\n/**\n * Changes the button strings.\n * @param {string} index Which button should be changed\n * @param {boolean} toshowmore a boolean that indicates if the button should show more or less\n */\nasync function changeButtonString(index, toshowmore) {\n if (toshowmore == true) {\n buttons[index].textContent = await getString('showmore', 'moodle');\n buttons[index].setAttribute('showmore', 'true');\n } else {\n buttons[index].textContent = await getString('showless', 'moodle');\n buttons[index].setAttribute('showmore', 'false');\n }\n}\n\n/**\n * Removes in a text all   and surrounding

tags excluding the first occurrence.\n *\n * Helper function to make post look better.\n * @param {object} element\n */\nasync function replaceParagraghTags(element) {\n // Identify and store the first

and

tags\n let message = element.innerHTML;\n const firstPTag = message.indexOf('

');\n const lastPTag = message.lastIndexOf('

');\n\n // Remove   and surrounding

tags excluding the first occurrence\n message = message.replace(/

 <\\/p>/g, '').replace(/ /g, '');\n\n // Replace

tags with
excluding the first occurrence\n message = message.substring(0, firstPTag + 3) +\n message.substring(firstPTag + 3, lastPTag).replace(/

/g, '
').replace(/<\\/p>/g, '') +\n message.substring(lastPTag);\n element.innerHTML = message;\n}"],"names":["contentElements","forEach","element","async","message","innerHTML","firstPTag","indexOf","lastPTag","lastIndexOf","replace","substring","replaceParagraghTags","textContent","length","originalTexts","id","cutString","parentElement","insertAdjacentHTML","buttons","setAttribute","style","display","prefetchStrings","addEventListener","document","getElementsByClassName","Selectors","seemorebutton","text","index","charAt","e","target","closest","letterid","getAttribute","changeButtonString","toshowmore","getString"],"mappings":"qLA6CO,WACHA,gBAAgBC,SACXC,WAsFTC,eAAoCD,SAEhC,IAAIE,QAAUF,QAAQG,UACtB,MAAMC,UAAYF,QAAQG,QAAQ,OAC5BC,SAAWJ,QAAQK,YAAY,QAGrCL,QAAUA,QAAQM,QAAQ,kBAAmB,IAAIA,QAAQ,UAAW,IAGpEN,QAAUA,QAAQO,UAAU,EAAGL,UAAY,GACvCF,QAAQO,UAAUL,UAAY,EAAGE,UAAUE,QAAQ,OAAQ,QAAQA,QAAQ,SAAU,IACrFN,QAAQO,UAAUH,UACtBN,QAAQG,UAAYD,QAjGZQ,CAAqBV,SAGjBA,QAAQW,YAAYC,QAAU,KAE9BC,cAAcb,QAAQc,IAAMd,QAAQG,UACpCY,UAAUf,SACVA,QAAQgB,cAAcC,mBAAmB,YAAa,OACtDC,QAAQlB,QAAQc,IAAIK,aAAa,WAAY,SAG7CD,QAAQlB,QAAQc,IAAIM,MAAMC,QAAU,WAMhD,EAAAC,2BAAgB,SAAU,CAAC,WAAY,aAGvCC;;;;;;;;;;;;AAvCJ,MAAMzB,gBAAkB0B,SAASC,uBAAuB,sBAClDP,QAAUM,SAASC,uBAAuB,uBAC1CZ,cAAgB,GAEhBa,kBACO,CACLC,cAAe,oDA0CvB,SAASZ,UAAUf,SACf,IAAI4B,KAAO5B,QAAQW,YACfkB,MAAQ,IACZ,KAA6B,KAAtBD,KAAKE,OAAOD,QACfA,QAEJ7B,QAAQG,UAAYyB,KAAKnB,UAAU,EAAEoB,OAMzC,MAAMN,iBAAmBA,KACrBC,SAASD,iBAAiB,SAASQ,IAC/B,GAAIA,EAAEC,OAAOC,QAAQP,kBAAkBC,eAAgB,CAEnD,IAAIO,SAAWH,EAAEC,OAAOlB,GACxBhB,gBAAgBC,SACXC,UACOA,QAAQc,IAAMoB,WACoC,QAA9ChB,QAAQgB,UAAUC,aAAa,aAC/BnC,QAAQG,UAAYU,cAAcqB,UAClCE,mBAAmBF,UAAU,KAE7BnB,UAAUf,SACVoC,mBAAmBF,UAAU,WAMnD,EAQNjC,eAAemC,mBAAmBP,MAAOQ,YACnB,GAAdA,YACAnB,QAAQW,OAAOlB,kBAAoB,EAAA2B,gBAAU,WAAY,UACzDpB,QAAQW,OAAOV,aAAa,WAAY,UAExCD,QAAQW,OAAOlB,kBAAoB,EAAA2B,gBAAU,WAAY,UACzDpB,QAAQW,OAAOV,aAAa,WAAY,UAwB/C"} \ No newline at end of file diff --git a/amd/build/timefilter.min.js.map b/amd/build/timefilter.min.js.map index 7e721f9..1763f9d 100644 --- a/amd/build/timefilter.min.js.map +++ b/amd/build/timefilter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"timefilter.min.js","sources":["../src/timefilter.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\r\n//\r\n// Moodle is free software: you can redistribute it and/or modify\r\n// it under the terms of the GNU General Public License as published by\r\n// the Free Software Foundation, either version 3 of the License, or\r\n// (at your option) any later version.\r\n//\r\n// Moodle is distributed in the hope that it will be useful,\r\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n// GNU General Public License for more details.\r\n//\r\n// You should have received a copy of the GNU General Public License\r\n// along with Moodle. If not, see .\r\n\r\n/**\r\n * Javascript for the time filter\r\n *\r\n * This file implements 1 functionality:\r\n * - Checks, which of the radio buttons is pressed and filters the content based on the time.\r\n *\r\n * @module block_townsquare/timefilter\r\n * @copyright 2024 Tamaro Walter\r\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\r\n */\r\n\r\n// Get the relevant radio buttons.\r\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\r\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\r\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\r\n\r\n// Define to change the time span, an additional time span and the current time.\r\nlet currenttime;\r\nlet timestart;\r\nlet timeend;\r\nlet addstarttime;\r\nlet addendtime;\r\n\r\n/**\r\n * Init function\r\n */\r\nexport function init() {\r\n // Set the current time.\r\n currenttime = new Date().getTime() / 1000;\r\n\r\n // Add event listeners to the all kind of buttons.\r\n alltimeaddEventListener();\r\n futuretimeaddEventListener();\r\n pasttimeaddEventListener();\r\n}\r\n\r\n/**\r\n * Function to execute the filter\r\n * @param {int} starttime Start of time span for filtering of the current pressed button\r\n * @param {int} endtime End of time span for filtering of the current pressed\r\n * @param {int} addstarttime Start of time span for filtering of an additional radio button.\r\n * @param {int} addendtime End of time span for filtering of an additional radio button.\r\n * @param {boolean} buttonstate State of the radio button (true or false)\r\n */\r\nfunction executefilter(starttime, endtime, addstarttime, addendtime, buttonstate) {\r\n // Get all letters that are \"activated\".\r\n // Activated means that all filters accept the letter and want to show it.\r\n const letters = document.querySelectorAll('.townsquare_letter.ts_coursefilter_active.ts_letterfilter_active');\r\n\r\n // Loop through each letter and hide/show based on radiobutton state.\r\n letters.forEach(function(letter) {\r\n\r\n // Get the created time stamp of each letter.\r\n let lettertime = letter.querySelector('.townsquareletter_date').id;\r\n\r\n // If the radio button is checked and the letter is in the time span, activate it.\r\n if ((buttonstate && (lettertime >= starttime && lettertime <= endtime)) ||\r\n (lettertime >= addstarttime && lettertime <= addendtime)) {\r\n letter.classList.add('ts_timefilter_active'); // Mark the letter as \"active\".\r\n } else {\r\n letter.classList.remove('ts_timefilter_active'); // Mark the letter as \"not active\".\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Function to add event listeners to the all_time button.\r\n */\r\nfunction alltimeaddEventListener() {\r\n alltimebutton.forEach(function(button) {\r\n button.addEventListener('change', function() {\r\n // Set the time span to show all letters.\r\n timestart = currenttime - convertidtotime(button.id);\r\n timeend = currenttime + convertidtotime(button.id);\r\n addstarttime = 0;\r\n addendtime = 0;\r\n\r\n // Disable all other radio buttons that filter more specific times.\r\n futureradiobuttons.forEach(function(futureradiobutton) {\r\n futureradiobutton.checked = false;\r\n futureradiobutton.parentNode.classList.remove(\"active\");\r\n });\r\n pastradiobuttons.forEach(function(pastradiobutton) {\r\n pastradiobutton.checked = false;\r\n pastradiobutton.parentNode.classList.remove(\"active\");\r\n\r\n });\r\n\r\n // Execute the filter function.\r\n executefilter(timestart, timeend, addstarttime,addendtime, button.checked);\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * Function to add event listeners to the future time radio buttons.\r\n */\r\nfunction futuretimeaddEventListener() {\r\n futureradiobuttons.forEach(function(button) {\r\n button.addEventListener('change', function() {\r\n // Disable the all_time button.\r\n alltimebutton.forEach(function(alltimebutton) {\r\n alltimebutton.checked = false;\r\n alltimebutton.parentNode.classList.remove('active');\r\n });\r\n\r\n // Set the time span based on the radiobutton id.\r\n timestart = currenttime;\r\n timeend = currenttime + convertidtotime(button.id);\r\n\r\n // Check if one past time button is checked. If yes, set the additional time span based on its id.\r\n addstarttime = 0;\r\n addendtime = 0;\r\n pastradiobuttons.forEach(function(pastradiobutton) {\r\n if (pastradiobutton.parentNode.classList.contains('active')) {\r\n addstarttime = currenttime - convertidtotime(pastradiobutton.id);\r\n addendtime = currenttime;\r\n }\r\n });\r\n\r\n // Execute the filter function.\r\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * Function to add event listeners to the past time radio buttons.\r\n */\r\nfunction pasttimeaddEventListener() {\r\n pastradiobuttons.forEach(function(button) {\r\n button.addEventListener('change', function() {\r\n // Disable the all_time button.\r\n alltimebutton.forEach(function(alltimebutton) {\r\n alltimebutton.checked = false;\r\n alltimebutton.parentNode.classList.remove('active');\r\n });\r\n\r\n // Set the time span based on the radiobutton id.\r\n timestart = currenttime - convertidtotime(button.id);\r\n timeend = currenttime;\r\n\r\n // Check if one future time button is checked. If yes, set the additional time span based on its id.\r\n addstarttime = 0;\r\n addendtime = 0;\r\n futureradiobuttons.forEach(function(futureradiobutton) {\r\n if (futureradiobutton.parentNode.classList.contains('active')) {\r\n addstarttime = currenttime;\r\n addendtime = currenttime + convertidtotime(futureradiobutton.id);\r\n }\r\n });\r\n\r\n // Execute the filter function.\r\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * Function to convert the radio button id to a useable time span.\r\n * @param {string} id The id of the radio button\r\n * @returns {number}\r\n */\r\nfunction convertidtotime(id) {\r\n switch(id) {\r\n case \"ts_time_all\":\r\n return 15778463;\r\n case \"ts_time_next_twodays\":\r\n case \"ts_time_last_twodays\":\r\n return 172800;\r\n case \"ts_time_next_fivedays\":\r\n case \"ts_time_last_fivedays\":\r\n return 432000;\r\n case \"ts_time_next_week\":\r\n case \"ts_time_last_week\":\r\n return 604800;\r\n case \"ts_time_next_month\":\r\n case \"ts_time_last_month\":\r\n return 2592000;\r\n }\r\n}\r\n"],"names":["currenttime","Date","getTime","alltimebutton","forEach","button","addEventListener","timestart","convertidtotime","id","timeend","addstarttime","addendtime","futureradiobuttons","futureradiobutton","checked","parentNode","classList","remove","pastradiobuttons","pastradiobutton","executefilter","contains","document","querySelectorAll","starttime","endtime","buttonstate","letter","lettertime","querySelector","add"],"mappings":"sJA2CIA,aAAc,IAAIC,MAAOC,UAAY,IAyCrCC,cAAcC,SAAQ,SAASC,QAC3BA,OAAOC,iBAAiB,UAAU,WAE9BC,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAC/CE,aAAe,EACfC,WAAa,EAGbC,mBAAmBT,SAAQ,SAASU,mBAChCA,kBAAkBC,SAAU,EAC5BD,kBAAkBE,WAAWC,UAAUC,OAAO,aAElDC,iBAAiBf,SAAQ,SAASgB,iBAC9BA,gBAAgBL,SAAU,EAC1BK,gBAAgBJ,WAAWC,UAAUC,OAAO,aAKhDG,cAAcd,UAAWG,QAASC,aAAaC,WAAYP,OAAOU,eAS1EF,mBAAmBT,SAAQ,SAASC,QAChCA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YACZU,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAG/CE,aAAe,EACfC,WAAa,EACbO,iBAAiBf,SAAQ,SAASgB,iBAC1BA,gBAAgBJ,WAAWC,UAAUK,SAAS,YAC9CX,aAAeX,YAAcQ,gBAAgBY,gBAAgBX,IAC7DG,WAAaZ,gBAKrBqB,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU,eAS3EI,iBAAiBf,SAAQ,SAASC,QAC9BA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAGVW,aAAe,EACfC,WAAa,EACbC,mBAAmBT,SAAQ,SAASU,mBAC5BA,kBAAkBE,WAAWC,UAAUK,SAAS,YAChDX,aAAeX,YACfY,WAAaZ,YAAcQ,gBAAgBM,kBAAkBL,QAKrEY,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU;;;;;;;;;;;MA7IzEZ,cAAgBoB,SAASC,iBAAiB,uBAC1CX,mBAAqBU,SAASC,iBAAiB,0BAC/CL,iBAAmBI,SAASC,iBAAiB,4BAG/CxB,YACAO,UACAG,QACAC,aACAC,oBAuBKS,cAAcI,UAAWC,QAASf,aAAcC,WAAYe,aAGjDJ,SAASC,iBAAiB,oEAGlCpB,SAAQ,SAASwB,YAGjBC,WAAaD,OAAOE,cAAc,0BAA0BrB,GAG3DkB,aAAgBE,YAAcJ,WAAaI,YAAcH,SACzDG,YAAclB,cAAgBkB,YAAcjB,WAC7CgB,OAAOX,UAAUc,IAAI,wBAErBH,OAAOX,UAAUC,OAAO,oCAuG3BV,gBAAgBC,WACdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM"} \ No newline at end of file +{"version":3,"file":"timefilter.min.js","sources":["../src/timefilter.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 * Javascript for the time filter\n *\n * This file implements 1 functionality:\n * - Checks, which of the radio buttons is pressed and filters the content based on the time.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant radio buttons.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Define to change the time span, an additional time span and the current time.\nlet currenttime;\nlet timestart;\nlet timeend;\nlet addstarttime;\nlet addendtime;\n\n/**\n * Init function\n */\nexport function init() {\n // Set the current time.\n currenttime = new Date().getTime() / 1000;\n\n // Add event listeners to the all kind of buttons.\n alltimeaddEventListener();\n futuretimeaddEventListener();\n pasttimeaddEventListener();\n}\n\n/**\n * Function to execute the filter\n * @param {int} starttime Start of time span for filtering of the current pressed button\n * @param {int} endtime End of time span for filtering of the current pressed\n * @param {int} addstarttime Start of time span for filtering of an additional radio button.\n * @param {int} addendtime End of time span for filtering of an additional radio button.\n * @param {boolean} buttonstate State of the radio button (true or false)\n */\nfunction executefilter(starttime, endtime, addstarttime, addendtime, buttonstate) {\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.ts_coursefilter_active.ts_letterfilter_active');\n\n // Loop through each letter and hide/show based on radiobutton state.\n letters.forEach(function(letter) {\n\n // Get the created time stamp of each letter.\n let lettertime = letter.querySelector('.townsquareletter_date').id;\n\n // If the radio button is checked and the letter is in the time span, activate it.\n if ((buttonstate && (lettertime >= starttime && lettertime <= endtime)) ||\n (lettertime >= addstarttime && lettertime <= addendtime)) {\n letter.classList.add('ts_timefilter_active'); // Mark the letter as \"active\".\n } else {\n letter.classList.remove('ts_timefilter_active'); // Mark the letter as \"not active\".\n }\n });\n}\n\n/**\n * Function to add event listeners to the all_time button.\n */\nfunction alltimeaddEventListener() {\n alltimebutton.forEach(function(button) {\n button.addEventListener('change', function() {\n // Set the time span to show all letters.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime + convertidtotime(button.id);\n addstarttime = 0;\n addendtime = 0;\n\n // Disable all other radio buttons that filter more specific times.\n futureradiobuttons.forEach(function(futureradiobutton) {\n futureradiobutton.checked = false;\n futureradiobutton.parentNode.classList.remove(\"active\");\n });\n pastradiobuttons.forEach(function(pastradiobutton) {\n pastradiobutton.checked = false;\n pastradiobutton.parentNode.classList.remove(\"active\");\n\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime,addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the future time radio buttons.\n */\nfunction futuretimeaddEventListener() {\n futureradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime;\n timeend = currenttime + convertidtotime(button.id);\n\n // Check if one past time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n pastradiobuttons.forEach(function(pastradiobutton) {\n if (pastradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime - convertidtotime(pastradiobutton.id);\n addendtime = currenttime;\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the past time radio buttons.\n */\nfunction pasttimeaddEventListener() {\n pastradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime;\n\n // Check if one future time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n futureradiobuttons.forEach(function(futureradiobutton) {\n if (futureradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime;\n addendtime = currenttime + convertidtotime(futureradiobutton.id);\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n"],"names":["currenttime","Date","getTime","alltimebutton","forEach","button","addEventListener","timestart","convertidtotime","id","timeend","addstarttime","addendtime","futureradiobuttons","futureradiobutton","checked","parentNode","classList","remove","pastradiobuttons","pastradiobutton","executefilter","contains","document","querySelectorAll","starttime","endtime","buttonstate","letter","lettertime","querySelector","add"],"mappings":"2IAyCO,WAEHA,aAAc,IAAIC,MAAOC,UAAY,IAyCrCC,cAAcC,SAAQ,SAASC,QAC3BA,OAAOC,iBAAiB,UAAU,WAE9BC,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAC/CE,aAAe,EACfC,WAAa,EAGbC,mBAAmBT,SAAQ,SAASU,mBAChCA,kBAAkBC,SAAU,EAC5BD,kBAAkBE,WAAWC,UAAUC,OAAO,aAElDC,iBAAiBf,SAAQ,SAASgB,iBAC9BA,gBAAgBL,SAAU,EAC1BK,gBAAgBJ,WAAWC,UAAUC,OAAO,aAKhDG,cAAcd,UAAWG,QAASC,aAAaC,WAAYP,OAAOU,eAS1EF,mBAAmBT,SAAQ,SAASC,QAChCA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YACZU,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAG/CE,aAAe,EACfC,WAAa,EACbO,iBAAiBf,SAAQ,SAASgB,iBAC1BA,gBAAgBJ,WAAWC,UAAUK,SAAS,YAC9CX,aAAeX,YAAcQ,gBAAgBY,gBAAgBX,IAC7DG,WAAaZ,gBAKrBqB,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU,eAS3EI,iBAAiBf,SAAQ,SAASC,QAC9BA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAGVW,aAAe,EACfC,WAAa,EACbC,mBAAmBT,SAAQ,SAASU,mBAC5BA,kBAAkBE,WAAWC,UAAUK,SAAS,YAChDX,aAAeX,YACfY,WAAaZ,YAAcQ,gBAAgBM,kBAAkBL,QAKrEY,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU;;;;;;;;;;;AA7I/E,MAAMZ,cAAgBoB,SAASC,iBAAiB,uBAC1CX,mBAAqBU,SAASC,iBAAiB,0BAC/CL,iBAAmBI,SAASC,iBAAiB,wBAGnD,IAAIxB,YACAO,UACAG,QACAC,aACAC,WAuBJ,SAASS,cAAcI,UAAWC,QAASf,aAAcC,WAAYe,aAGjDJ,SAASC,iBAAiB,oEAGlCpB,SAAQ,SAASwB,QAGrB,IAAIC,WAAaD,OAAOE,cAAc,0BAA0BrB,GAG3DkB,aAAgBE,YAAcJ,WAAaI,YAAcH,SACzDG,YAAclB,cAAgBkB,YAAcjB,WAC7CgB,OAAOX,UAAUc,IAAI,wBAErBH,OAAOX,UAAUC,OAAO,2BAuGpC,SAASV,gBAAgBC,IACrB,OAAOA,IACH,IAAK,cACD,OAAO,SACX,IAAK,uBACL,IAAK,uBACD,OAAO,OACX,IAAK,wBACL,IAAK,wBACD,OAAO,MACX,IAAK,oBACL,IAAK,oBACD,OAAO,OACX,IAAK,qBACL,IAAK,qBACD,OAAO,QAElB"} \ No newline at end of file diff --git a/amd/build/usersettings_save.min.js.map b/amd/build/usersettings_save.min.js.map index eadc75d..db58f32 100644 --- a/amd/build/usersettings_save.min.js.map +++ b/amd/build/usersettings_save.min.js.map @@ -1 +1 @@ -{"version":3,"file":"usersettings_save.min.js","sources":["../src/usersettings_save.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\r\n//\r\n// Moodle is free software: you can redistribute it and/or modify\r\n// it under the terms of the GNU General Public License as published by\r\n// the Free Software Foundation, either version 3 of the License, or\r\n// (at your option) any later version.\r\n//\r\n// Moodle is distributed in the hope that it will be useful,\r\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n// GNU General Public License for more details.\r\n//\r\n// You should have received a copy of the GNU General Public License\r\n// along with Moodle. If not, see .\r\n\r\n/**\r\n * Javascript to save the user settings in the database.\r\n *\r\n * This file implements 1 functionality:\r\n * - If the \"save settings\" button is pressed, store the settings in the database.\r\n *\r\n * @module block_townsquare/timefilter\r\n * @copyright 2024 Tamaro Walter\r\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\r\n */\r\n\r\nimport Ajax from 'core/ajax';\r\n\r\n// Get the save button for the user settings.\r\nconst savebutton = document.getElementById('ts_usersettings_savebutton');\r\n\r\n// Get the buttons from the time filter.\r\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\r\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\r\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\r\n\r\n// Get the checkboxes from the letter filter.\r\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\r\n\r\n/**\r\n * Init function\r\n *\r\n * @param {number} userid The id of the current user.\r\n * @param {object} settingsfromdb The settings from the database, if there are any.\r\n */\r\nexport function init(userid, settingsfromdb) {\r\n // When the page is loaded, set the settings from the database.\r\n if (settingsfromdb) {\r\n executeusersettings(settingsfromdb);\r\n }\r\n\r\n // Add event listener to the save button.\r\n savebutton.addEventListener('click', async function() {\r\n\r\n // First step: collect the current settings.\r\n // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes.\r\n let timespans = collecttimefiltersettings();\r\n let letterfilter = collectletterfiltersettings();\r\n\r\n // Second step: store the usersettings in the database.\r\n await saveusersettings(userid, timespans['timepast'], timespans['timefuture'], letterfilter['basicletter'],\r\n letterfilter['completionletter'], letterfilter['postletter']);\r\n });\r\n}\r\n\r\n/**\r\n * Function to save the user settings in the database.\r\n * @param {number} userid\r\n * @param {number} timefilterpast\r\n * @param {number} timefilterfuture\r\n * @param {number} basicletter\r\n * @param {number} completionletter\r\n * @param {number} postletter\r\n * @returns {Promise<*>}\r\n */\r\nasync function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) {\r\n let result ;\r\n result = await Ajax.call([{\r\n methodname: 'block_townsquare_record_usersettings',\r\n args: {\r\n userid: parseInt(userid),\r\n timefilterpast: timefilterpast,\r\n timefilterfuture: timefilterfuture,\r\n basicletter: basicletter,\r\n completionletter: completionletter,\r\n postletter: postletter\r\n },\r\n }]);\r\n\r\n // Show a success message.\r\n let el = document.getElementById('ts_usersettings_successlabel');\r\n el.style.display = 'block';\r\n el.style.opacity = 1.0;\r\n\r\n // Start a new setInterval timer to gradually fade out the label.\r\n if (el.fadeOutTimer) {\r\n clearInterval(el.fadeOutTimer);\r\n }\r\n setTimeout(function () {\r\n el.fadeOutTimer = setInterval(function () {\r\n if (el.style.opacity > 0.4) {\r\n el.style.opacity -= 0.1;\r\n } else if (el.style.opacity > 0) {\r\n el.style.opacity -= 0.2;\r\n } else {\r\n // Once opacity reaches 0, clear the timer and hide the label.\r\n clearInterval(el.fadeOutTimer);\r\n el.style.display = 'none';\r\n }\r\n }, 100);\r\n }, 3000);\r\n return result;\r\n}\r\n\r\n/**\r\n * Function to execute existing user settings when loading the townsquare.\r\n * @param {Object} settingsfromdb\r\n */\r\nfunction executeusersettings(settingsfromdb) {\r\n\r\n // First step: set the time filter settings.\r\n // Change the time into the correct radio button id.\r\n let futurebuttonid = converttimetoid(settingsfromdb['timefilterfuture'], true);\r\n let pastbuttonid = converttimetoid(settingsfromdb['timefilterpast'], false);\r\n\r\n // If the time span is a combination of past and future, go through the two radio buttons and activate the filter.\r\n if (futurebuttonid !== \"ts_time_all\") {\r\n futureradiobuttons.forEach(function(button) {\r\n if (button.id === futurebuttonid) {\r\n button.parentNode.classList.add('active');\r\n button.checked = true;\r\n button.dispatchEvent(new Event('change'));\r\n alltimebutton.forEach(function(alltimebutton) {\r\n alltimebutton.checked = false;\r\n alltimebutton.parentNode.classList.remove('active');\r\n });\r\n }\r\n });\r\n pastradiobuttons.forEach(function(button) {\r\n if (button.id === pastbuttonid) {\r\n button.parentNode.classList.add('active');\r\n button.checked = true;\r\n button.dispatchEvent(new Event('change'));\r\n alltimebutton.forEach(function(alltimebutton) {\r\n alltimebutton.checked = false;\r\n alltimebutton.parentNode.classList.remove('active');\r\n });\r\n }\r\n });\r\n } else {\r\n // If the time span is set to all time, activate the all time button.\r\n alltimebutton.forEach(function(button) {\r\n button.parentNode.classList.add('active');\r\n button.checked = true;\r\n button.dispatchEvent(new Event('change'));\r\n });\r\n }\r\n\r\n // Second step: set the letter filter settings.\r\n // Per default all checkboxes are checked. If the setting is 0, uncheck the checkbox.\r\n checkboxes.forEach(function(checkbox) {\r\n let basiclettercheck = checkbox.id === 'basicletter' && settingsfromdb['basicletter'] === \"\";\r\n let completionlettercheck = checkbox.id === 'completionletter' && settingsfromdb['completionletter'] === \"0\";\r\n let postlettercheck = checkbox.id === 'postletter' && settingsfromdb['postletter'] === \"0\";\r\n\r\n if (basiclettercheck || completionlettercheck || postlettercheck) {\r\n checkbox.click();\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Function to collect the letter filter settings.\r\n * @returns {{basicletter: number, completionletter: number, postletter: number}}\r\n */\r\nfunction collectletterfiltersettings() {\r\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\r\n\r\n checkboxes.forEach(function(checkbox) {\r\n if (checkbox.checked) {\r\n switch(checkbox.id) {\r\n case \"basicletter\":\r\n settings['basicletter'] = 1;\r\n break;\r\n case \"completionletter\":\r\n settings['completionletter'] = 1;\r\n break;\r\n case \"postletter\":\r\n settings['postletter'] = 1;\r\n break;\r\n\r\n }\r\n }\r\n });\r\n // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit.\r\n return settings;\r\n}\r\n\r\n/**\r\n * Function to collect the time filter settings.\r\n * @returns {{timepast: number, timefuture: number}}\r\n */\r\nfunction collecttimefiltersettings() {\r\n let settings = { timepast: 0, timefuture: 0};\r\n let settingsset = false;\r\n\r\n // Get the relevant time spans of the time filter.\r\n // Check if the alltimebutton is set.\r\n alltimebutton.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timepast'] = convertidtotime(button.id);\r\n settings['timefuture'] = convertidtotime(button.id);\r\n settingsset = true;\r\n }\r\n });\r\n\r\n if (settingsset) {\r\n return settings;\r\n }\r\n\r\n // If the alltimebutton is not set, check which of the future/past buttons is set.\r\n futureradiobuttons.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timefuture'] = convertidtotime(button.id);\r\n }\r\n });\r\n\r\n pastradiobuttons.forEach(function(button) {\r\n if (button.parentNode.classList.contains('active')) {\r\n // Get the timespan.\r\n settings['timepast'] = convertidtotime(button.id);\r\n }\r\n });\r\n return settings;\r\n}\r\n\r\n\r\n/**\r\n * Function to convert the radio button id to a useable time span.\r\n * @param {string} id The id of the radio button\r\n * @returns {number}\r\n */\r\nfunction convertidtotime(id) {\r\n // TODO: Please use global functions if possible.\r\n switch(id) {\r\n case \"ts_time_all\":\r\n return 15778463;\r\n case \"ts_time_next_twodays\":\r\n case \"ts_time_last_twodays\":\r\n return 172800;\r\n case \"ts_time_next_fivedays\":\r\n case \"ts_time_last_fivedays\":\r\n return 432000;\r\n case \"ts_time_next_week\":\r\n case \"ts_time_last_week\":\r\n return 604800;\r\n case \"ts_time_next_month\":\r\n case \"ts_time_last_month\":\r\n return 2592000;\r\n }\r\n}\r\n\r\n/**\r\n * Function to convert the time span to a radio button id.\r\n * @param {string} time\r\n * @param {boolean} future\r\n * @returns {string}\r\n */\r\nfunction converttimetoid(time, future) {\r\n switch (time) {\r\n case \"15778463\":\r\n return \"ts_time_all\";\r\n case \"172800\":\r\n if (future) {\r\n return \"ts_time_next_twodays\";\r\n }\r\n return \"ts_time_past_twodays\";\r\n case \"432000\":\r\n if (future) {\r\n return \"ts_time_next_fivedays\";\r\n }\r\n return \"ts_time_last_fivedays\";\r\n case \"604800\":\r\n if (future) {\r\n return \"ts_time_next_week\";\r\n }\r\n return \"ts_time_last_week\";\r\n case \"2592000\":\r\n if (future) {\r\n return \"ts_time_next_month\";\r\n\r\n }\r\n return \"ts_time_last_month\";\r\n }\r\n}\r\n"],"names":["userid","settingsfromdb","futurebuttonid","converttimetoid","pastbuttonid","futureradiobuttons","forEach","button","id","parentNode","classList","add","checked","dispatchEvent","Event","alltimebutton","remove","pastradiobuttons","checkboxes","checkbox","basiclettercheck","completionlettercheck","postlettercheck","click","executeusersettings","savebutton","addEventListener","async","timespans","settings","timepast","timefuture","settingsset","contains","convertidtotime","collecttimefiltersettings","letterfilter","collectletterfiltersettings","timefilterpast","timefilterfuture","basicletter","completionletter","postletter","result","Ajax","call","methodname","args","parseInt","el","document","getElementById","style","display","opacity","fadeOutTimer","clearInterval","setTimeout","setInterval","saveusersettings","querySelectorAll","time","future"],"mappings":";;;;;;;;;;oFA6CqBA,OAAQC,gBAErBA,yBAuEqBA,oBAIrBC,eAAiBC,gBAAgBF,eAAc,kBAAsB,GACrEG,aAAeD,gBAAgBF,eAAc,gBAAoB,GAG9C,gBAAnBC,gBACAG,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOC,KAAON,iBACdK,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,iBAItDC,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOC,KAAOJ,eACdG,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,kBAMtDD,cAAcT,SAAQ,SAASC,QAC3BA,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,cAMvCI,WAAWZ,SAAQ,SAASa,cACpBC,iBAAmC,gBAAhBD,SAASX,IAA0D,KAAlCP,eAAc,YAClEoB,sBAAwC,qBAAhBF,SAASX,IAAoE,MAAvCP,eAAc,iBAC5EqB,gBAAkC,eAAhBH,SAASX,IAAwD,MAAjCP,eAAc,YAEhEmB,kBAAoBC,uBAAyBC,kBAC7CH,SAASI,WAtHbC,CAAoBvB,gBAIxBwB,WAAWC,iBAAiB,SAASC,qBAI7BC,yBAmJJC,SAAW,CAAEC,SAAU,EAAGC,WAAY,GACtCC,aAAc,KAIlBjB,cAAcT,SAAQ,SAASC,QACxBA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgB3B,OAAOC,IAC9CqB,SAAQ,WAAiBK,gBAAgB3B,OAAOC,IAChDwB,aAAc,MAIjBA,mBACOH,gBAIXxB,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,WAAiBK,gBAAgB3B,OAAOC,QAIxDS,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgB3B,OAAOC,QAG/CqB,SAnLaM,GACZC,4BAuHJP,SAAW,aAAgB,mBAAuB,aAAiB,UAEvEX,WAAWZ,SAAQ,SAASa,aACpBA,SAASP,eACFO,SAASX,QACP,cACDqB,SAAQ,YAAkB,YAEzB,mBACDA,SAAQ,iBAAuB,YAE9B,aACDA,SAAQ,WAAiB,MAOlCA,SA1IgBQ,wBAkBKrC,OAAQsC,eAAgBC,iBAAkBC,YAAaC,iBAAkBC,gBACjGC,OACJA,aAAeC,cAAKC,KAAK,CAAC,CACtBC,WAAY,uCACZC,KAAM,CACF/C,OAAQgD,SAAShD,QACjBsC,eAAgBA,eAChBC,iBAAkBA,iBAClBC,YAAaA,YACbC,iBAAkBA,iBAClBC,WAAYA,mBAKhBO,GAAKC,SAASC,eAAe,gCACjCF,GAAGG,MAAMC,QAAU,QACnBJ,GAAGG,MAAME,QAAU,EAGfL,GAAGM,cACHC,cAAcP,GAAGM,qBAErBE,YAAW,WACPR,GAAGM,aAAeG,aAAY,WACtBT,GAAGG,MAAME,QAAU,GACnBL,GAAGG,MAAME,SAAW,GACbL,GAAGG,MAAME,QAAU,EAC1BL,GAAGG,MAAME,SAAW,IAGpBE,cAAcP,GAAGM,cACjBN,GAAGG,MAAMC,QAAU,UAExB,OACJ,KACIV,OAnDGgB,CAAiB3D,OAAQ4B,UAAS,SAAcA,UAAS,WAAgBQ,aAAY,YACpEA,aAAY,iBAAsBA,aAAY,0EAhCvEX,WAAayB,SAASC,eAAe,8BAGrCpC,cAAgBmC,SAASU,iBAAiB,uBAC1CvD,mBAAqB6C,SAASU,iBAAiB,0BAC/C3C,iBAAmBiC,SAASU,iBAAiB,wBAG7C1C,WAAagC,SAASU,iBAAiB,gCA+MpC1B,gBAAgB1B,WAEdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM,iBAUVL,gBAAgB0D,KAAMC,eACnBD,UACC,iBACM,kBACN,gBACGC,OACO,uBAEJ,2BACN,gBACGA,OACO,wBAEJ,4BACN,gBACGA,OACO,oBAEJ,wBACN,iBACGA,OACO,qBAGJ"} \ No newline at end of file +{"version":3,"file":"usersettings_save.min.js","sources":["../src/usersettings_save.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 * Javascript to save the user settings in the database.\n *\n * This file implements 1 functionality:\n * - If the \"save settings\" button is pressed, store the settings in the database.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n// Get the save button for the user settings.\nconst savebutton = document.getElementById('ts_usersettings_savebutton');\n\n// Get the buttons from the time filter.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Get the checkboxes from the letter filter.\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n *\n * @param {number} userid The id of the current user.\n * @param {object} settingsfromdb The settings from the database, if there are any.\n */\nexport function init(userid, settingsfromdb) {\n // When the page is loaded, set the settings from the database.\n if (settingsfromdb) {\n executeusersettings(settingsfromdb);\n }\n\n // Add event listener to the save button.\n savebutton.addEventListener('click', async function() {\n\n // First step: collect the current settings.\n // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes.\n let timespans = collecttimefiltersettings();\n let letterfilter = collectletterfiltersettings();\n\n // Second step: store the usersettings in the database.\n await saveusersettings(userid, timespans['timepast'], timespans['timefuture'], letterfilter['basicletter'],\n letterfilter['completionletter'], letterfilter['postletter']);\n });\n}\n\n/**\n * Function to save the user settings in the database.\n * @param {number} userid\n * @param {number} timefilterpast\n * @param {number} timefilterfuture\n * @param {number} basicletter\n * @param {number} completionletter\n * @param {number} postletter\n * @returns {Promise<*>}\n */\nasync function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) {\n let result ;\n result = await Ajax.call([{\n methodname: 'block_townsquare_record_usersettings',\n args: {\n userid: parseInt(userid),\n timefilterpast: timefilterpast,\n timefilterfuture: timefilterfuture,\n basicletter: basicletter,\n completionletter: completionletter,\n postletter: postletter\n },\n }]);\n\n // Show a success message.\n let el = document.getElementById('ts_usersettings_successlabel');\n el.style.display = 'block';\n el.style.opacity = 1.0;\n\n // Start a new setInterval timer to gradually fade out the label.\n if (el.fadeOutTimer) {\n clearInterval(el.fadeOutTimer);\n }\n setTimeout(function () {\n el.fadeOutTimer = setInterval(function () {\n if (el.style.opacity > 0.4) {\n el.style.opacity -= 0.1;\n } else if (el.style.opacity > 0) {\n el.style.opacity -= 0.2;\n } else {\n // Once opacity reaches 0, clear the timer and hide the label.\n clearInterval(el.fadeOutTimer);\n el.style.display = 'none';\n }\n }, 100);\n }, 3000);\n return result;\n}\n\n/**\n * Function to execute existing user settings when loading the townsquare.\n * @param {Object} settingsfromdb\n */\nfunction executeusersettings(settingsfromdb) {\n\n // First step: set the time filter settings.\n // Change the time into the correct radio button id.\n let futurebuttonid = converttimetoid(settingsfromdb['timefilterfuture'], true);\n let pastbuttonid = converttimetoid(settingsfromdb['timefilterpast'], false);\n\n // If the time span is a combination of past and future, go through the two radio buttons and activate the filter.\n if (futurebuttonid !== \"ts_time_all\") {\n futureradiobuttons.forEach(function(button) {\n if (button.id === futurebuttonid) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n }\n });\n pastradiobuttons.forEach(function(button) {\n if (button.id === pastbuttonid) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n }\n });\n } else {\n // If the time span is set to all time, activate the all time button.\n alltimebutton.forEach(function(button) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n });\n }\n\n // Second step: set the letter filter settings.\n // Per default all checkboxes are checked. If the setting is 0, uncheck the checkbox.\n checkboxes.forEach(function(checkbox) {\n let basiclettercheck = checkbox.id === 'basicletter' && settingsfromdb['basicletter'] === \"\";\n let completionlettercheck = checkbox.id === 'completionletter' && settingsfromdb['completionletter'] === \"0\";\n let postlettercheck = checkbox.id === 'postletter' && settingsfromdb['postletter'] === \"0\";\n\n if (basiclettercheck || completionlettercheck || postlettercheck) {\n checkbox.click();\n }\n });\n}\n\n/**\n * Function to collect the letter filter settings.\n * @returns {{basicletter: number, completionletter: number, postletter: number}}\n */\nfunction collectletterfiltersettings() {\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\n\n checkboxes.forEach(function(checkbox) {\n if (checkbox.checked) {\n switch(checkbox.id) {\n case \"basicletter\":\n settings['basicletter'] = 1;\n break;\n case \"completionletter\":\n settings['completionletter'] = 1;\n break;\n case \"postletter\":\n settings['postletter'] = 1;\n break;\n\n }\n }\n });\n // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit.\n return settings;\n}\n\n/**\n * Function to collect the time filter settings.\n * @returns {{timepast: number, timefuture: number}}\n */\nfunction collecttimefiltersettings() {\n let settings = { timepast: 0, timefuture: 0};\n let settingsset = false;\n\n // Get the relevant time spans of the time filter.\n // Check if the alltimebutton is set.\n alltimebutton.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n settings['timefuture'] = convertidtotime(button.id);\n settingsset = true;\n }\n });\n\n if (settingsset) {\n return settings;\n }\n\n // If the alltimebutton is not set, check which of the future/past buttons is set.\n futureradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timefuture'] = convertidtotime(button.id);\n }\n });\n\n pastradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n }\n });\n return settings;\n}\n\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n // TODO: Please use global functions if possible.\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n\n/**\n * Function to convert the time span to a radio button id.\n * @param {string} time\n * @param {boolean} future\n * @returns {string}\n */\nfunction converttimetoid(time, future) {\n switch (time) {\n case \"15778463\":\n return \"ts_time_all\";\n case \"172800\":\n if (future) {\n return \"ts_time_next_twodays\";\n }\n return \"ts_time_past_twodays\";\n case \"432000\":\n if (future) {\n return \"ts_time_next_fivedays\";\n }\n return \"ts_time_last_fivedays\";\n case \"604800\":\n if (future) {\n return \"ts_time_next_week\";\n }\n return \"ts_time_last_week\";\n case \"2592000\":\n if (future) {\n return \"ts_time_next_month\";\n\n }\n return \"ts_time_last_month\";\n }\n}\n"],"names":["obj","userid","settingsfromdb","futurebuttonid","converttimetoid","pastbuttonid","futureradiobuttons","forEach","button","id","parentNode","classList","add","checked","dispatchEvent","Event","alltimebutton","remove","pastradiobuttons","checkboxes","checkbox","basiclettercheck","completionlettercheck","postlettercheck","click","executeusersettings","savebutton","addEventListener","async","timespans","settings","timepast","timefuture","settingsset","contains","convertidtotime","collecttimefiltersettings","letterfilter","basicletter","completionletter","postletter","collectletterfiltersettings","timefilterpast","timefilterfuture","result","Ajax","call","methodname","args","parseInt","el","document","getElementById","style","display","opacity","fadeOutTimer","clearInterval","setTimeout","setInterval","saveusersettings","_ajax","__esModule","default","querySelectorAll","time","future"],"mappings":"8FA0B6B,IAAAA;;;;;;;;;;2EAmBtB,SAAcC,OAAQC,gBAErBA,gBAuER,SAA6BA,gBAIzB,IAAIC,eAAiBC,gBAAgBF,eAAiC,kBAAG,GACrEG,aAAeD,gBAAgBF,eAA+B,gBAAG,GAG9C,gBAAnBC,gBACAG,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOC,KAAON,iBACdK,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,iBAItDC,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOC,KAAOJ,eACdG,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,kBAMtDD,cAAcT,SAAQ,SAASC,QAC3BA,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,cAMvCI,WAAWZ,SAAQ,SAASa,UACxB,IAAIC,iBAAmC,gBAAhBD,SAASX,IAA0D,KAAlCP,eAA4B,YAChFoB,sBAAwC,qBAAhBF,SAASX,IAAoE,MAAvCP,eAAiC,iBAC/FqB,gBAAkC,eAAhBH,SAASX,IAAwD,MAAjCP,eAA2B,YAE7EmB,kBAAoBC,uBAAyBC,kBAC7CH,SAASI,WAtHbC,CAAoBvB,gBAIxBwB,WAAWC,iBAAiB,SAASC,iBAIjC,IAAIC,UAkJZ,WACI,IAAIC,SAAW,CAAEC,SAAU,EAAGC,WAAY,GACtCC,aAAc,EAalB,GATAjB,cAAcT,SAAQ,SAASC,QACxBA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAmB,SAAIK,gBAAgB3B,OAAOC,IAC9CqB,SAAqB,WAAIK,gBAAgB3B,OAAOC,IAChDwB,aAAc,MAIjBA,YACA,OAAOH,SAiBX,OAbAxB,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAqB,WAAIK,gBAAgB3B,OAAOC,QAIxDS,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAmB,SAAIK,gBAAgB3B,OAAOC,QAG/CqB,SAnLaM,GACZC,aAsHZ,WACI,IAAIP,SAAW,CAACQ,YAAe,EAAGC,iBAAoB,EAAGC,WAAc,GAmBvE,OAjBArB,WAAWZ,SAAQ,SAASa,UACxB,GAAIA,SAASP,QACT,OAAOO,SAASX,IACZ,IAAK,cACDqB,SAAsB,YAAI,EAC1B,MACJ,IAAK,mBACDA,SAA2B,iBAAI,EAC/B,MACJ,IAAK,aACDA,SAAqB,WAAI,MAOlCA,SA1IgBW,SAkB3Bb,eAAgC3B,OAAQyC,eAAgBC,iBAAkBL,YAAaC,iBAAkBC,YACrG,IAAII,OACJA,aAAeC,cAAKC,KAAK,CAAC,CACtBC,WAAY,uCACZC,KAAM,CACF/C,OAAQgD,SAAShD,QACjByC,eAAgBA,eAChBC,iBAAkBA,iBAClBL,YAAaA,YACbC,iBAAkBA,iBAClBC,WAAYA,eAKpB,IAAIU,GAAKC,SAASC,eAAe,gCACjCF,GAAGG,MAAMC,QAAU,QACnBJ,GAAGG,MAAME,QAAU,EAGfL,GAAGM,cACHC,cAAcP,GAAGM,cAerB,OAbAE,YAAW,WACPR,GAAGM,aAAeG,aAAY,WACtBT,GAAGG,MAAME,QAAU,GACnBL,GAAGG,MAAME,SAAW,GACbL,GAAGG,MAAME,QAAU,EAC1BL,GAAGG,MAAME,SAAW,IAGpBE,cAAcP,GAAGM,cACjBN,GAAGG,MAAMC,QAAU,UAExB,OACJ,KACIV,OAnDGgB,CAAiB3D,OAAQ4B,UAAoB,SAAGA,UAAsB,WAAGQ,aAA0B,YAClFA,aAA+B,iBAAGA,aAAyB,gBAnC1FwB,OAA6B7D,IAA7B6D,QAA6B7D,IAAA8D,WAAA9D,KAAA+D,QAAA/D,KAG7B,MAAM0B,WAAayB,SAASC,eAAe,8BAGrCpC,cAAgBmC,SAASa,iBAAiB,uBAC1C1D,mBAAqB6C,SAASa,iBAAiB,0BAC/C9C,iBAAmBiC,SAASa,iBAAiB,wBAG7C7C,WAAagC,SAASa,iBAAiB,uBA+M7C,SAAS7B,gBAAgB1B,IAErB,OAAOA,IACH,IAAK,cACD,OAAO,SACX,IAAK,uBACL,IAAK,uBACD,OAAO,OACX,IAAK,wBACL,IAAK,wBACD,OAAO,MACX,IAAK,oBACL,IAAK,oBACD,OAAO,OACX,IAAK,qBACL,IAAK,qBACD,OAAO,QAUnB,SAASL,gBAAgB6D,KAAMC,QAC3B,OAAQD,MACJ,IAAK,WACD,MAAO,cACX,IAAK,SACD,OAAIC,OACO,uBAEJ,uBACX,IAAK,SACD,OAAIA,OACO,wBAEJ,wBACX,IAAK,SACD,OAAIA,OACO,oBAEJ,oBACX,IAAK,UACD,OAAIA,OACO,qBAGJ,sBAElB"} \ No newline at end of file diff --git a/amd/src/usersettings_save.js b/amd/src/usersettings_save.js index 56957e5..6ba9673 100644 --- a/amd/src/usersettings_save.js +++ b/amd/src/usersettings_save.js @@ -1,297 +1,297 @@ -// 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 . - -/** - * Javascript to save the user settings in the database. - * - * This file implements 1 functionality: - * - If the "save settings" button is pressed, store the settings in the database. - * - * @module block_townsquare/timefilter - * @copyright 2024 Tamaro Walter - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -import Ajax from 'core/ajax'; - -// Get the save button for the user settings. -const savebutton = document.getElementById('ts_usersettings_savebutton'); - -// Get the buttons from the time filter. -const alltimebutton = document.querySelectorAll('.ts_all_time_button'); -const futureradiobuttons = document.querySelectorAll('.ts_future_time_button'); -const pastradiobuttons = document.querySelectorAll('.ts_past_time_button'); - -// Get the checkboxes from the letter filter. -const checkboxes = document.querySelectorAll('.ts_letter_checkbox'); - -/** - * Init function - * - * @param {number} userid The id of the current user. - * @param {object} settingsfromdb The settings from the database, if there are any. - */ -export function init(userid, settingsfromdb) { - // When the page is loaded, set the settings from the database. - if (settingsfromdb) { - executeusersettings(settingsfromdb); - } - - // Add event listener to the save button. - savebutton.addEventListener('click', async function() { - - // First step: collect the current settings. - // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes. - let timespans = collecttimefiltersettings(); - let letterfilter = collectletterfiltersettings(); - - // Second step: store the usersettings in the database. - await saveusersettings(userid, timespans['timepast'], timespans['timefuture'], letterfilter['basicletter'], - letterfilter['completionletter'], letterfilter['postletter']); - }); -} - -/** - * Function to save the user settings in the database. - * @param {number} userid - * @param {number} timefilterpast - * @param {number} timefilterfuture - * @param {number} basicletter - * @param {number} completionletter - * @param {number} postletter - * @returns {Promise<*>} - */ -async function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) { - let result ; - result = await Ajax.call([{ - methodname: 'block_townsquare_record_usersettings', - args: { - userid: parseInt(userid), - timefilterpast: timefilterpast, - timefilterfuture: timefilterfuture, - basicletter: basicletter, - completionletter: completionletter, - postletter: postletter - }, - }]); - - // Show a success message. - let el = document.getElementById('ts_usersettings_successlabel'); - el.style.display = 'block'; - el.style.opacity = 1.0; - - // Start a new setInterval timer to gradually fade out the label. - if (el.fadeOutTimer) { - clearInterval(el.fadeOutTimer); - } - setTimeout(function () { - el.fadeOutTimer = setInterval(function () { - if (el.style.opacity > 0.4) { - el.style.opacity -= 0.1; - } else if (el.style.opacity > 0) { - el.style.opacity -= 0.2; - } else { - // Once opacity reaches 0, clear the timer and hide the label. - clearInterval(el.fadeOutTimer); - el.style.display = 'none'; - } - }, 100); - }, 3000); - return result; -} - -/** - * Function to execute existing user settings when loading the townsquare. - * @param {Object} settingsfromdb - */ -function executeusersettings(settingsfromdb) { - - // First step: set the time filter settings. - // Change the time into the correct radio button id. - let futurebuttonid = converttimetoid(settingsfromdb['timefilterfuture'], true); - let pastbuttonid = converttimetoid(settingsfromdb['timefilterpast'], false); - - // If the time span is a combination of past and future, go through the two radio buttons and activate the filter. - if (futurebuttonid !== "ts_time_all") { - futureradiobuttons.forEach(function(button) { - if (button.id === futurebuttonid) { - button.parentNode.classList.add('active'); - button.checked = true; - button.dispatchEvent(new Event('change')); - alltimebutton.forEach(function(alltimebutton) { - alltimebutton.checked = false; - alltimebutton.parentNode.classList.remove('active'); - }); - } - }); - pastradiobuttons.forEach(function(button) { - if (button.id === pastbuttonid) { - button.parentNode.classList.add('active'); - button.checked = true; - button.dispatchEvent(new Event('change')); - alltimebutton.forEach(function(alltimebutton) { - alltimebutton.checked = false; - alltimebutton.parentNode.classList.remove('active'); - }); - } - }); - } else { - // If the time span is set to all time, activate the all time button. - alltimebutton.forEach(function(button) { - button.parentNode.classList.add('active'); - button.checked = true; - button.dispatchEvent(new Event('change')); - }); - } - - // Second step: set the letter filter settings. - // Per default all checkboxes are checked. If the setting is 0, uncheck the checkbox. - checkboxes.forEach(function(checkbox) { - let basiclettercheck = checkbox.id === 'basicletter' && settingsfromdb['basicletter'] === ""; - let completionlettercheck = checkbox.id === 'completionletter' && settingsfromdb['completionletter'] === "0"; - let postlettercheck = checkbox.id === 'postletter' && settingsfromdb['postletter'] === "0"; - - if (basiclettercheck || completionlettercheck || postlettercheck) { - checkbox.click(); - } - }); -} - -/** - * Function to collect the letter filter settings. - * @returns {{basicletter: number, completionletter: number, postletter: number}} - */ -function collectletterfiltersettings() { - let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 }; - - checkboxes.forEach(function(checkbox) { - if (checkbox.checked) { - switch(checkbox.id) { - case "basicletter": - settings['basicletter'] = 1; - break; - case "completionletter": - settings['completionletter'] = 1; - break; - case "postletter": - settings['postletter'] = 1; - break; - - } - } - }); - // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit. - return settings; -} - -/** - * Function to collect the time filter settings. - * @returns {{timepast: number, timefuture: number}} - */ -function collecttimefiltersettings() { - let settings = { timepast: 0, timefuture: 0}; - let settingsset = false; - - // Get the relevant time spans of the time filter. - // Check if the alltimebutton is set. - alltimebutton.forEach(function(button) { - if (button.parentNode.classList.contains('active')) { - // Get the timespan. - settings['timepast'] = convertidtotime(button.id); - settings['timefuture'] = convertidtotime(button.id); - settingsset = true; - } - }); - - if (settingsset) { - return settings; - } - - // If the alltimebutton is not set, check which of the future/past buttons is set. - futureradiobuttons.forEach(function(button) { - if (button.parentNode.classList.contains('active')) { - // Get the timespan. - settings['timefuture'] = convertidtotime(button.id); - } - }); - - pastradiobuttons.forEach(function(button) { - if (button.parentNode.classList.contains('active')) { - // Get the timespan. - settings['timepast'] = convertidtotime(button.id); - } - }); - return settings; -} - - -/** - * Function to convert the radio button id to a useable time span. - * @param {string} id The id of the radio button - * @returns {number} - */ -function convertidtotime(id) { - // TODO: Please use global functions if possible. - switch(id) { - case "ts_time_all": - return 15778463; - case "ts_time_next_twodays": - case "ts_time_last_twodays": - return 172800; - case "ts_time_next_fivedays": - case "ts_time_last_fivedays": - return 432000; - case "ts_time_next_week": - case "ts_time_last_week": - return 604800; - case "ts_time_next_month": - case "ts_time_last_month": - return 2592000; - } -} - -/** - * Function to convert the time span to a radio button id. - * @param {string} time - * @param {boolean} future - * @returns {string} - */ -function converttimetoid(time, future) { - switch (time) { - case "15778463": - return "ts_time_all"; - case "172800": - if (future) { - return "ts_time_next_twodays"; - } - return "ts_time_past_twodays"; - case "432000": - if (future) { - return "ts_time_next_fivedays"; - } - return "ts_time_last_fivedays"; - case "604800": - if (future) { - return "ts_time_next_week"; - } - return "ts_time_last_week"; - case "2592000": - if (future) { - return "ts_time_next_month"; - - } - return "ts_time_last_month"; - } -} +// 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 . + +/** + * Javascript to save the user settings in the database. + * + * This file implements 1 functionality: + * - If the "save settings" button is pressed, store the settings in the database. + * + * @module block_townsquare/timefilter + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import Ajax from 'core/ajax'; + +// Get the save button for the user settings. +const savebutton = document.getElementById('ts_usersettings_savebutton'); + +// Get the buttons from the time filter. +const alltimebutton = document.querySelectorAll('.ts_all_time_button'); +const futureradiobuttons = document.querySelectorAll('.ts_future_time_button'); +const pastradiobuttons = document.querySelectorAll('.ts_past_time_button'); + +// Get the checkboxes from the letter filter. +const checkboxes = document.querySelectorAll('.ts_letter_checkbox'); + +/** + * Init function + * + * @param {number} userid The id of the current user. + * @param {object} settingsfromdb The settings from the database, if there are any. + */ +export function init(userid, settingsfromdb) { + // When the page is loaded, set the settings from the database. + if (settingsfromdb) { + executeusersettings(settingsfromdb); + } + + // Add event listener to the save button. + savebutton.addEventListener('click', async function() { + + // First step: collect the current settings. + // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes. + let timespans = collecttimefiltersettings(); + let letterfilter = collectletterfiltersettings(); + + // Second step: store the usersettings in the database. + await saveusersettings(userid, timespans['timepast'], timespans['timefuture'], letterfilter['basicletter'], + letterfilter['completionletter'], letterfilter['postletter']); + }); +} + +/** + * Function to save the user settings in the database. + * @param {number} userid + * @param {number} timefilterpast + * @param {number} timefilterfuture + * @param {number} basicletter + * @param {number} completionletter + * @param {number} postletter + * @returns {Promise<*>} + */ +async function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) { + let result ; + result = await Ajax.call([{ + methodname: 'block_townsquare_record_usersettings', + args: { + userid: parseInt(userid), + timefilterpast: timefilterpast, + timefilterfuture: timefilterfuture, + basicletter: basicletter, + completionletter: completionletter, + postletter: postletter + }, + }]); + + // Show a success message. + let el = document.getElementById('ts_usersettings_successlabel'); + el.style.display = 'block'; + el.style.opacity = 1.0; + + // Start a new setInterval timer to gradually fade out the label. + if (el.fadeOutTimer) { + clearInterval(el.fadeOutTimer); + } + setTimeout(function () { + el.fadeOutTimer = setInterval(function () { + if (el.style.opacity > 0.4) { + el.style.opacity -= 0.1; + } else if (el.style.opacity > 0) { + el.style.opacity -= 0.2; + } else { + // Once opacity reaches 0, clear the timer and hide the label. + clearInterval(el.fadeOutTimer); + el.style.display = 'none'; + } + }, 100); + }, 3000); + return result; +} + +/** + * Function to execute existing user settings when loading the townsquare. + * @param {Object} settingsfromdb + */ +function executeusersettings(settingsfromdb) { + + // First step: set the time filter settings. + // Change the time into the correct radio button id. + let futurebuttonid = converttimetoid(settingsfromdb['timefilterfuture'], true); + let pastbuttonid = converttimetoid(settingsfromdb['timefilterpast'], false); + + // If the time span is a combination of past and future, go through the two radio buttons and activate the filter. + if (futurebuttonid !== "ts_time_all") { + futureradiobuttons.forEach(function(button) { + if (button.id === futurebuttonid) { + button.parentNode.classList.add('active'); + button.checked = true; + button.dispatchEvent(new Event('change')); + alltimebutton.forEach(function(alltimebutton) { + alltimebutton.checked = false; + alltimebutton.parentNode.classList.remove('active'); + }); + } + }); + pastradiobuttons.forEach(function(button) { + if (button.id === pastbuttonid) { + button.parentNode.classList.add('active'); + button.checked = true; + button.dispatchEvent(new Event('change')); + alltimebutton.forEach(function(alltimebutton) { + alltimebutton.checked = false; + alltimebutton.parentNode.classList.remove('active'); + }); + } + }); + } else { + // If the time span is set to all time, activate the all time button. + alltimebutton.forEach(function(button) { + button.parentNode.classList.add('active'); + button.checked = true; + button.dispatchEvent(new Event('change')); + }); + } + + // Second step: set the letter filter settings. + // Per default all checkboxes are checked. If the setting is 0, uncheck the checkbox. + checkboxes.forEach(function(checkbox) { + let basiclettercheck = checkbox.id === 'basicletter' && settingsfromdb['basicletter'] === ""; + let completionlettercheck = checkbox.id === 'completionletter' && settingsfromdb['completionletter'] === "0"; + let postlettercheck = checkbox.id === 'postletter' && settingsfromdb['postletter'] === "0"; + + if (basiclettercheck || completionlettercheck || postlettercheck) { + checkbox.click(); + } + }); +} + +/** + * Function to collect the letter filter settings. + * @returns {{basicletter: number, completionletter: number, postletter: number}} + */ +function collectletterfiltersettings() { + let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 }; + + checkboxes.forEach(function(checkbox) { + if (checkbox.checked) { + switch(checkbox.id) { + case "basicletter": + settings['basicletter'] = 1; + break; + case "completionletter": + settings['completionletter'] = 1; + break; + case "postletter": + settings['postletter'] = 1; + break; + + } + } + }); + // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit. + return settings; +} + +/** + * Function to collect the time filter settings. + * @returns {{timepast: number, timefuture: number}} + */ +function collecttimefiltersettings() { + let settings = { timepast: 0, timefuture: 0}; + let settingsset = false; + + // Get the relevant time spans of the time filter. + // Check if the alltimebutton is set. + alltimebutton.forEach(function(button) { + if (button.parentNode.classList.contains('active')) { + // Get the timespan. + settings['timepast'] = convertidtotime(button.id); + settings['timefuture'] = convertidtotime(button.id); + settingsset = true; + } + }); + + if (settingsset) { + return settings; + } + + // If the alltimebutton is not set, check which of the future/past buttons is set. + futureradiobuttons.forEach(function(button) { + if (button.parentNode.classList.contains('active')) { + // Get the timespan. + settings['timefuture'] = convertidtotime(button.id); + } + }); + + pastradiobuttons.forEach(function(button) { + if (button.parentNode.classList.contains('active')) { + // Get the timespan. + settings['timepast'] = convertidtotime(button.id); + } + }); + return settings; +} + + +/** + * Function to convert the radio button id to a useable time span. + * @param {string} id The id of the radio button + * @returns {number} + */ +function convertidtotime(id) { + // TODO: Please use global functions if possible. + switch(id) { + case "ts_time_all": + return 15778463; + case "ts_time_next_twodays": + case "ts_time_last_twodays": + return 172800; + case "ts_time_next_fivedays": + case "ts_time_last_fivedays": + return 432000; + case "ts_time_next_week": + case "ts_time_last_week": + return 604800; + case "ts_time_next_month": + case "ts_time_last_month": + return 2592000; + } +} + +/** + * Function to convert the time span to a radio button id. + * @param {string} time + * @param {boolean} future + * @returns {string} + */ +function converttimetoid(time, future) { + switch (time) { + case "15778463": + return "ts_time_all"; + case "172800": + if (future) { + return "ts_time_next_twodays"; + } + return "ts_time_past_twodays"; + case "432000": + if (future) { + return "ts_time_next_fivedays"; + } + return "ts_time_last_fivedays"; + case "604800": + if (future) { + return "ts_time_next_week"; + } + return "ts_time_last_week"; + case "2592000": + if (future) { + return "ts_time_next_month"; + + } + return "ts_time_last_month"; + } +} From f8b94203600ce47d48d0bfcb7d4ae75cd627a192 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Mon, 25 Mar 2024 11:55:50 +0100 Subject: [PATCH 049/123] record_usersettings function shorter --- externallib.php | 35 ++++++----------------------------- 1 file changed, 6 insertions(+), 29 deletions(-) diff --git a/externallib.php b/externallib.php index b4f8e42..1cd2bc7 100644 --- a/externallib.php +++ b/externallib.php @@ -75,34 +75,6 @@ public static function record_usersettings_returns() { public static function record_usersettings($userid, $timefilterpast, $timefilterfuture, $basicletter, $completionletter, $postletter) { global $DB; - - $transaction = $DB->start_delegated_transaction(); - - // Check if the user already has a record in the database. - if ($records = $DB->get_records('block_townsquare_preferences', ['userid' => $userid])) { - // If there more than a record (it only should be only one), delete all of them and insert the new one. - if (count($records) > 1) { - try { - foreach ($records as $record) { - $DB->delete_records('block_townsquare_preferences', ['id' => $record->id]); - } - } catch (Exception $e) { - $transaction->rollback($e); - return false; - } - } else { - // Upgrade the existing record. - $record = reset($records); - $record->timefilterpast = $timefilterpast; - $record->timefilterfuture = $timefilterfuture; - $record->basicletter = $basicletter; - $record->completionletter = $completionletter; - $record->postletter = $postletter; - $DB->update_record('block_townsquare_preferences', $record); - $transaction->allow_commit(); - return true; - } - } $record = new stdClass(); $record->userid = $userid; $record->timefilterpast = $timefilterpast; @@ -110,8 +82,13 @@ public static function record_usersettings($userid, $timefilterpast, $timefilter $record->basicletter = $basicletter; $record->completionletter = $completionletter; $record->postletter = $postletter; + // Check if the user already has a record in the database. + if ($DB->get_record('block_townsquare_preferences', ['userid' => $userid])) { + // Upgrade the existing record. + $DB->update_record('block_townsquare_preferences', $record); + return true; + } $DB->insert_record('block_townsquare_preferences', $record); - $transaction->allow_commit(); return true; } From 8db0fb966196fe631b8cfe21c26a6e51233aef79 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Mon, 25 Mar 2024 14:17:43 +0100 Subject: [PATCH 050/123] add test for externallib --- externallib.php | 38 +++++++++++-- tests/externallib_test.php | 110 +++++++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+), 6 deletions(-) create mode 100644 tests/externallib_test.php diff --git a/externallib.php b/externallib.php index 1cd2bc7..bcd1f04 100644 --- a/externallib.php +++ b/externallib.php @@ -22,8 +22,13 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +namespace block_townsquare\external; +use Exception; +use stdClass; + defined('MOODLE_INTERNAL') || die(); + global $CFG; require_once($CFG->libdir . '/externallib.php'); @@ -75,6 +80,32 @@ public static function record_usersettings_returns() { public static function record_usersettings($userid, $timefilterpast, $timefilterfuture, $basicletter, $completionletter, $postletter) { global $DB; + $transaction = $DB->start_delegated_transaction(); + // Check if the user already has a record in the database. + if ($records = $DB->get_records('block_townsquare_preferences', ['userid' => $userid])) { + // If there more than a record (it only should be only one), delete all of them and insert the new one. + if (count($records) > 1) { + try { + foreach ($records as $record) { + $DB->delete_records('block_townsquare_preferences', ['id' => $record->id]); + } + } catch (Exception $e) { + $transaction->rollback($e); + return false; + } + } else { + // Upgrade the existing record. + $record = reset($records); + $record->timefilterpast = $timefilterpast; + $record->timefilterfuture = $timefilterfuture; + $record->basicletter = $basicletter; + $record->completionletter = $completionletter; + $record->postletter = $postletter; + $DB->update_record('block_townsquare_preferences', $record); + $transaction->allow_commit(); + return true; + } + } $record = new stdClass(); $record->userid = $userid; $record->timefilterpast = $timefilterpast; @@ -82,13 +113,8 @@ public static function record_usersettings($userid, $timefilterpast, $timefilter $record->basicletter = $basicletter; $record->completionletter = $completionletter; $record->postletter = $postletter; - // Check if the user already has a record in the database. - if ($DB->get_record('block_townsquare_preferences', ['userid' => $userid])) { - // Upgrade the existing record. - $DB->update_record('block_townsquare_preferences', $record); - return true; - } $DB->insert_record('block_townsquare_preferences', $record); + $transaction->allow_commit(); return true; } diff --git a/tests/externallib_test.php b/tests/externallib_test.php new file mode 100644 index 0000000..dd954a9 --- /dev/null +++ b/tests/externallib_test.php @@ -0,0 +1,110 @@ +. + +/** + * Unit tests for the block_townsquare. + * + * @package block_townsquare + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace block_townsquare; + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->dirroot . '/webservice/tests/helpers.php'); + +use block_townsquare\external\block_townsquare_external; + +/** + * PHPUnit tests for testing the process of the externallib. + * + * @package block_townsquare + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * + * @covers \block_townsquare\block_townsquare_external::record_usersettings + */ +class externallib_test extends \advanced_testcase { + + public function setUp(): void { + global $CFG; + require_once($CFG->dirroot . '/blocks/townsquare/externallib.php'); + $this->resetAfterTest(); + } + + /** + * Tests the record_usersettings method. + * @runInSeparateProcess + */ + public function test_record_usersettings(): void { + global $DB; + + $usersetting = new \stdClass(); + $usersetting->userid = 1; + $usersetting->timefilterpast = 432000; + $usersetting->timefilterfuture = 2592000; + $usersetting->basicletter = 0; + $usersetting->completionletter = 1; + $usersetting->postletter = 1; + + // Test Case 1: The User sets the setting for the first time. + + // Check that there is no record in the database. + $record = $DB->get_record('block_townsquare_preferences', ['userid' => $usersetting->userid]); + $this->assertEquals(false, $record); + + // Call the function to record the user settings and check, if the record is created. + $result = block_townsquare_external::record_usersettings($usersetting->userid, $usersetting->timefilterpast, + $usersetting->timefilterfuture, $usersetting->basicletter, + $usersetting->completionletter, $usersetting->postletter); + + $this->assertEquals(true, $result); + $record = $DB->get_record('block_townsquare_preferences', ['userid' => $usersetting->userid]); + + // Check if the record is correct. + $this->assertEquals($usersetting->timefilterpast, $record->timefilterpast); + $this->assertEquals($usersetting->timefilterfuture, $record->timefilterfuture); + $this->assertEquals($usersetting->basicletter, $record->basicletter); + $this->assertEquals($usersetting->completionletter, $record->completionletter); + $this->assertEquals($usersetting->postletter, $record->postletter); + + // Test Case 2: The User updates the settings. + $usersetting->timefilterpast = 2592000; + $usersetting->timefilterfuture = 0; + $usersetting->basicletter = 1; + $usersetting->completionletter = 0; + $usersetting->postletter = 0; + + // Call the function to record the user settings and check, if the record is created. + $result = block_townsquare_external::record_usersettings($usersetting->userid, $usersetting->timefilterpast, + $usersetting->timefilterfuture, $usersetting->basicletter, + $usersetting->completionletter, $usersetting->postletter); + + $this->assertEquals(true, $result); + $record = $DB->get_record('block_townsquare_preferences', ['userid' => $usersetting->userid]); + + // Check if the record is correct. + $this->assertEquals($usersetting->timefilterpast, $record->timefilterpast); + $this->assertEquals($usersetting->timefilterfuture, $record->timefilterfuture); + $this->assertEquals($usersetting->basicletter, $record->basicletter); + $this->assertEquals($usersetting->completionletter, $record->completionletter); + $this->assertEquals($usersetting->postletter, $record->postletter); + + } +} From 1bc6555f94d8f3d2ffb82f21443038a9882ae385 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Mon, 25 Mar 2024 14:48:27 +0100 Subject: [PATCH 051/123] try to fix github workflow issues --- externallib.php | 1 - tests/externallib_test.php | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/externallib.php b/externallib.php index bcd1f04..788f3f1 100644 --- a/externallib.php +++ b/externallib.php @@ -28,7 +28,6 @@ defined('MOODLE_INTERNAL') || die(); - global $CFG; require_once($CFG->libdir . '/externallib.php'); diff --git a/tests/externallib_test.php b/tests/externallib_test.php index dd954a9..541fcf7 100644 --- a/tests/externallib_test.php +++ b/tests/externallib_test.php @@ -28,6 +28,7 @@ global $CFG; require_once($CFG->dirroot . '/webservice/tests/helpers.php'); +require_once($CFG->libdir . '/externallib.php'); use block_townsquare\external\block_townsquare_external; From b1036ff2e980838856590d96926d4c2c108bd36a Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Mon, 25 Mar 2024 14:59:21 +0100 Subject: [PATCH 052/123] WIP: fix failing tests --- externallib.php | 5 +++-- tests/externallib_test.php | 3 +-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/externallib.php b/externallib.php index 788f3f1..42d8133 100644 --- a/externallib.php +++ b/externallib.php @@ -23,13 +23,14 @@ */ namespace block_townsquare\external; +use core_external\external_api; use Exception; use stdClass; defined('MOODLE_INTERNAL') || die(); global $CFG; -require_once($CFG->libdir . '/externallib.php'); +//require_once($CFG->libdir . '/externallib.php'); /** * Class implementing the external API, esp. for AJAX functions. @@ -38,7 +39,7 @@ * @copyright 2024 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class block_townsquare_external extends \core_external\external_api { +class block_townsquare_external extends external_api { /** * Returns description of method parameters diff --git a/tests/externallib_test.php b/tests/externallib_test.php index 541fcf7..81b94b3 100644 --- a/tests/externallib_test.php +++ b/tests/externallib_test.php @@ -28,10 +28,9 @@ global $CFG; require_once($CFG->dirroot . '/webservice/tests/helpers.php'); -require_once($CFG->libdir . '/externallib.php'); use block_townsquare\external\block_townsquare_external; - +use core_external\external_api; /** * PHPUnit tests for testing the process of the externallib. * From 7b463e947022cea6e94d161fa12fd6509cc92938 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Mon, 25 Mar 2024 15:03:26 +0100 Subject: [PATCH 053/123] WIP: trying to fix phpunit test --- externallib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externallib.php b/externallib.php index 42d8133..86e2933 100644 --- a/externallib.php +++ b/externallib.php @@ -30,7 +30,7 @@ defined('MOODLE_INTERNAL') || die(); global $CFG; -//require_once($CFG->libdir . '/externallib.php'); +// require_once($CFG->libdir . '/externallib.php'); /** * Class implementing the external API, esp. for AJAX functions. From c5fcd754331c65858f2673dca92716c8acfb745c Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Mon, 25 Mar 2024 15:53:49 +0100 Subject: [PATCH 054/123] phpunit test work in M4.1 now --- externallib.php | 4 ++-- styles.css | 4 ++-- tests/externallib_test.php | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/externallib.php b/externallib.php index 86e2933..e0a4e3d 100644 --- a/externallib.php +++ b/externallib.php @@ -23,14 +23,14 @@ */ namespace block_townsquare\external; -use core_external\external_api; use Exception; +use external_api; use stdClass; defined('MOODLE_INTERNAL') || die(); global $CFG; -// require_once($CFG->libdir . '/externallib.php'); +require_once($CFG->dirroot . '/lib/externallib.php'); /** * Class implementing the external API, esp. for AJAX functions. diff --git a/styles.css b/styles.css index 8ac9b65..f139438 100644 --- a/styles.css +++ b/styles.css @@ -2,8 +2,8 @@ .townsquare_sidepanel.col-md-3 { background-color: #eee; border-radius: 0.5rem; - padding-left: 0.0rem; - padding-right: 0.0rem; + padding-left: 0; + padding-right: 0; } .townsquare_content { diff --git a/tests/externallib_test.php b/tests/externallib_test.php index 81b94b3..dd954a9 100644 --- a/tests/externallib_test.php +++ b/tests/externallib_test.php @@ -30,7 +30,7 @@ require_once($CFG->dirroot . '/webservice/tests/helpers.php'); use block_townsquare\external\block_townsquare_external; -use core_external\external_api; + /** * PHPUnit tests for testing the process of the externallib. * From 3662158c3df848fd34e0385fe935fa15f14bcf18 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Wed, 27 Mar 2024 13:48:00 +0100 Subject: [PATCH 055/123] use language strings in townsquare letters --- classes/townsquareevents.php | 21 ++----- lang/en/block_townsquare.php | 27 +++++++- locallib.php | 69 +++++++++++++++++++++ templates/activitycompletionletter.mustache | 3 +- templates/basicletter.mustache | 2 +- 5 files changed, 100 insertions(+), 22 deletions(-) diff --git a/classes/townsquareevents.php b/classes/townsquareevents.php index 4f6cca0..c850de1 100644 --- a/classes/townsquareevents.php +++ b/classes/townsquareevents.php @@ -102,6 +102,9 @@ public function get_coreevents(): array { // Add the name of the instance to the event. $coreevent->instancename = $DB->get_field($coreevent->modulename, 'name', ['id' => $coreevent->instance]); + + // Modify the content of the event if needed. + townsquare_check_coreevent($coreevent); } return $coreevents; @@ -280,7 +283,7 @@ private function get_events_from_db($timestart, $timeend, $courses): array { // Due to compatability reasons, only events from supported modules are shown. // Supported modules are: core modules and custom additional modules. - $coremodules = ['assign', 'book', 'chat', 'choice', 'data', 'feedback', 'folder', 'forum', 'glossary', 'h5pactivity', + $coremodules = ['assign', 'book', 'chat', 'choice', 'data', 'feedback', 'file', 'folder', 'forum', 'glossary', 'h5pactivity', 'imscp', 'label', 'lesson', 'lti', 'page', 'quiz', 'resource', 'scorm', 'survey', 'url', 'wiki', 'workshop', ]; $additionalmodules = ['moodleoverflow', 'ratingallocate']; $modules = $coremodules + $additionalmodules; @@ -293,7 +296,7 @@ private function get_events_from_db($timestart, $timeend, $courses): array { // Set the sql statement. $sql = "SELECT e.id, e.name, e.courseid, cm.id AS coursemoduleid, cm.availability AS availability, e.groupid, e.userid, - e.modulename, e.instance, e.eventtype, e.timestart, e.visible + e.modulename, e.instance, e.eventtype, e.timestart, e.timemodified, e.visible FROM {event} e JOIN {modules} m ON e.modulename = m.name JOIN {course_modules} cm ON (cm.course = e.courseid AND cm.module = m.id AND cm.instance = e.instance) @@ -310,20 +313,6 @@ private function get_events_from_db($timestart, $timeend, $courses): array { return $DB->get_records_sql($sql, $params); } - - /** - * help function to sort and merge 2 array of events. - * Note that each of the arrays are already sorted in descending order by time created (newest event first). - * @param array $leftarray The first array of events. - * @param array $rightarray The second array of events. - * - * @return array - */ - private function merge_events($leftarray, $rightarray, ): array { - // TODO: merge sort events. - return []; - } - /** * Filter that checks if the event needs to be filtered out for the current user. * Applies to assignment events. diff --git a/lang/en/block_townsquare.php b/lang/en/block_townsquare.php index 6e607c3..5efa161 100644 --- a/lang/en/block_townsquare.php +++ b/lang/en/block_townsquare.php @@ -32,9 +32,8 @@ $string['pluginname:myaddinstance'] = 'Add the Town Square block to the dashboard'; // Mustache templates strings. -$string['completionletterorigin'] = '{$a->modulename} should be completed until {$a->date}'; -$string['basicletterorigin'] = 'A notification from {$a->modulename}:'; -$string['postletternotification'] = 'New {$a->modulename} post!'; +$string['completionletterorigin'] = '{$a->modulename} should be completed until today'; +$string['basicletterorigin'] = 'A notification from {$a->instancename}:'; $string['postletterorigin'] = '{$a->authorname} posted in {$a->instancename} -> {$a->discussionname}:'; $string['orientationmarkercontent'] = 'Hi {$a->username}, welcome to townsquare! Today is the {$a->date}'; @@ -44,3 +43,25 @@ // Subplugin strings. $string['subplugintype_townsquaresupport'] = 'Supported module'; $string['subplugintype_townsquaresupport_plural'] = 'Supported modules'; + +// Event strings. +$string['assignduemessage'] = 'Assignment is due until {$a->time}'; +$string['assigngradingduemessage'] = 'Assignment is due to be graded until {$a->time}'; +$string['chattimemessage'] = 'The next chat time is today at {$a->time}'; +$string['choiceopenmessage'] = 'Voting is possible from {$a->time} onwards'; +$string['choiceclosemessage'] = 'Please vote until {$a->time}. Afterwards the choice is closed'; +$string['dataopenmessage'] = 'The database opens today'; +$string['dataclosemessage'] = 'Please submit your entries until {$a->time}. The database closes afterwards'; +$string['feedbackopenmessage'] = 'Writing feedback is possible from {$a->time} onwards'; +$string['feedbackclosemessage'] = 'Writing feedback is possible until {$a->time}'; +$string['forumduemessage'] = 'The forum is due until {$a->time}'; +$string['lessonopenmessage'] = 'The lesson opens today at {$a->time}'; +$string['lessonclosemessage'] = 'The lesson ends today at {$a->time}'; +$string['quizopenmessage'] = 'The Quiz is open from {$a->time} onwards'; +$string['quizclosemessage'] = 'The Quiz closes today at {$a->time}'; +$string['quizopenmessage'] = 'Scorm Activity opens today'; +$string['quizclosemessage'] = 'Scorm Activity closes today'; +$string['workshopopensubmission'] = 'Submissions for the workshop are possible from {$a->time} onwards'; +$string['workshopclosesubmission'] = 'Please submit your work until {$a->time}. The workshop closes afterwards'; +$string['workshopopenassessment'] = 'The assessment phase starts today at {$a->time}'; +$string['workshopcloseassessment'] = 'Assessments for the workshop are due until {$a->time}'; \ No newline at end of file diff --git a/locallib.php b/locallib.php index 17860c4..465ba52 100644 --- a/locallib.php +++ b/locallib.php @@ -116,3 +116,72 @@ function townsquare_filter_availability($event): bool { return true; } + +/** + * General Support function for core events. + * Can be used to modify the event content, as in some cases, core events don't have a good text in the events-datatable. + * @param object $event The event, that is being checked. + * @return void + */ +function townsquare_check_coreevent($event) { + $time = date('H:i', $event->timestart); + if ($event->modulename == 'assign') { + if ($event->eventtype == 'due') { + $event->name = get_string('assignduemessage', 'block_townsquare', ['time' => $time]); + } else if ($event->eventtype == 'gradingdue') { + $event->name = get_string('assigngradingduemessage', 'block_townsquare', ['time' => $time]); + } + } else if ($event->modulename == 'chat' && $event->eventtype == 'chattime') { + $event->name = get_string('chattimemessage', 'block_townsquare', ['time' => $time]); + } else if ($event->modulename == 'choice') { + if ($event->eventtype == 'open') { + $event->name = get_string('choiceopenmessage', 'block_townsquare', ['time' => $time]); + } else if ($event->eventtype == 'close') { + $event->name = get_string('choiceclosemessage', 'block_townsquare', ['time' => $time]); + } + } else if ($event->modulename == 'data') { + if ($event->eventtype == 'open') { + $event->name = get_string('dataopenmessage', 'block_townsquare'); + }else if ($event->eventtype == 'close') { + $event->name = get_string('dataclosemessage', 'block_townsquare', ['time' => $time]); + } + } else if ($event->modulename == 'feedback') { + if ($event->eventtype == 'open') { + $event->name = get_string('feedbackopenmessage', 'block_townsquare', ['time' => $time]); + } else if ($event->eventtype == 'close') { + $event->name = get_string('feedbackclosemessage', 'block_townsquare', ['time' => $time]); + } + } else if ($event->modulename == 'forum') { + if ($event->eventtype == 'due') { + $event->name = get_string('forumduemessage', 'block_townsquare', ['time' => $time]); + } + } else if ($event->modulename == 'lesson') { + if ($event->eventtype == 'open') { + $event->name = get_string('lessonopenmessage', 'block_townsquare', ['time' => $time]); + } else if ($event->eventtype == 'close') { + $event->name = get_string('lessonclosemessage', 'block_townsquare', ['time' => $time]); + } + } else if ($event->modulename == 'quiz') { + if ($event->eventtype == 'open') { + $event->name = get_string('quizopenmessage', 'block_townsquare', ['time' => $time]); + } else if ($event->eventtype == 'close') { + $event->name = get_string('quizclosemessage', 'block_townsquare', ['time' => $time]); + } + } else if ($event->modulename == 'scorm') { + if ($event->eventtype == 'open') { + $event->name = get_string('scormopenmessage', 'block_townsquare'); + } else if ($event->eventtype == 'close') { + $event->name = get_string('scormclosemessage', 'block_townsquare'); + } + } else if ($event->modulename == 'workshop') { + if ($event->eventtype == 'opensubmission') { + $event->name = get_string('workshopopensubmission', 'block_townsquare', ['time' => $time]); + } else if ($event->eventtype == 'closesubmission') { + $event->name = get_string('workshopclosesubmission', 'block_townsquare', ['time' => $time]); + } else if ($event->eventtype == 'openassessment') { + $event->name = get_string('workshopopenassessment', 'block_townsquare', ['time' => $time]); + } else if ($event->eventtype == 'closeassessment') { + $event->name = get_string('workshopcloseassessment', 'block_townsquare', ['time' => $time]); + } + } +} \ No newline at end of file diff --git a/templates/activitycompletionletter.mustache b/templates/activitycompletionletter.mustache index 00077ae..72a5ca9 100644 --- a/templates/activitycompletionletter.mustache +++ b/templates/activitycompletionletter.mustache @@ -57,8 +57,7 @@

{{#str}} completionletterorigin, block_townsquare, { - "modulename": {{#quote}} {{instancename}} {{/quote}}, - "date": {{#quote}} {{created}} {{/quote}} } + "modulename": {{#quote}} {{instancename}} {{/quote}} } {{/str}}
diff --git a/templates/basicletter.mustache b/templates/basicletter.mustache index 26f73c1..622a6e0 100644 --- a/templates/basicletter.mustache +++ b/templates/basicletter.mustache @@ -58,7 +58,7 @@
{{#str}} basicletterorigin, block_townsquare, - { "modulename": {{#quote}} {{instancename}} {{/quote}} } + { "instancename": {{#quote}} {{instancename}} {{/quote}} } {{/str}}
From 89089f1705bf8130bbcb2cb4aa5b105ab695e159 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Wed, 3 Apr 2024 12:55:00 +0200 Subject: [PATCH 056/123] WIP: Add behat tests to townsquare --- classes/townsquareevents.php | 1 + tests/behat/behat_block_townsquare.php | 43 +++++++++++++++++++ .../block_townsquare_coursefilter.feature | 43 +++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 tests/behat/behat_block_townsquare.php create mode 100644 tests/behat/block_townsquare_coursefilter.feature diff --git a/classes/townsquareevents.php b/classes/townsquareevents.php index c5312a4..dd32d2d 100644 --- a/classes/townsquareevents.php +++ b/classes/townsquareevents.php @@ -26,6 +26,7 @@ defined('MOODLE_INTERNAL') || die(); use context_module; +use core_component; use dml_exception; global $CFG; diff --git a/tests/behat/behat_block_townsquare.php b/tests/behat/behat_block_townsquare.php new file mode 100644 index 0000000..9e039de --- /dev/null +++ b/tests/behat/behat_block_townsquare.php @@ -0,0 +1,43 @@ +. + +/** + * Steps definitions related with the townsquare block. + * + * @package block_townsquare + * @category test + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once(__DIR__ . '/../../../../lib/behat/behat_base.php'); + +use Behat\Gherkin\Node\TableNode as TableNode; +use Behat\Mink\Exception\ElementNotFoundException; +use Behat\Mink\Exception\ExpectationException; + + +/** + * townsquare-related steps definitions. + * + * @package block_townsquare + * @category test + * @copyright 2024 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class behat_block_townsquare extends behat_base { + +} diff --git a/tests/behat/block_townsquare_coursefilter.feature b/tests/behat/block_townsquare_coursefilter.feature new file mode 100644 index 0000000..9f808e2 --- /dev/null +++ b/tests/behat/block_townsquare_coursefilter.feature @@ -0,0 +1,43 @@ +@block @block_townsquare @javascript +Feature: The townsquare block allows users to see notifications from different courses + In order to enable the townsquare block + As a student + I can add the townsquare block to my dashboard + + Background: + Given the following "users" exist: + | username | firstname | lastname | email | idnumber | + | student1 | Tamaro | Walter | student1@example.com | S1 | + And the following "courses" exist: + | fullname | shortname | category | startdate | enddate | + | Course 1 | C1 | 0 | ##yesterday## | ##now +6 months## | + | Course 2 | C2 | 0 | ##yesterday## | ##now +6 months## | + | Course 3 | C3 | 0 | ##yesterday## | ##now +6 months## | + And the following "course enrolments" exist: + | user | course | role | + | student1 | C1 | student | + | student1 | C2 | student | + | student1 | C3 | student | + And the following "activities" exist: + | activity | course | idnumber | name | intro | timeopen | duedate | + | assign | C1 | assign1 | Test assign 1 | Assign due in 2 months | ##now -2 days## | ##now +2 month## | + | assign | C2 | assign2 | Test assign 2 | Assign due tomorrow | ##now -2 days## | ##tomorrow## | + | assign | C3 | assign3 | Test assign 3 | Assign due yesterday | ##now -2 days## | ##yesterday## | + + + Scenario: If the user unselects the a course in the course filter, the assignment from that course should be hidden + Given I log in as "student1" + And I turn editing mode on + And I add the "Town Square" block + Then I should see "Test assign 1" + And I should see "Test assign 2" + And I should see "Test assign 3" + And I click on "Course 1" "checkbox" + Then "C1" "css_element" should not be visible + And "C2" "css_element" should be visible + And "C3" "css_element" should be visible + And I click on "Course 2" "checkbox" + Then "C2" "css_element" should not be visible + And "C3" "css_element" should be visible + And I click on "Course 3" "checkbox" + Then "C3" "css_element" should not be visible From 2e25efd4110fae9049f83a50ac908f929fe709b8 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Wed, 3 Apr 2024 12:58:59 +0200 Subject: [PATCH 057/123] basic coursefilter behat test added --- tests/behat/block_townsquare_coursefilter.feature | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/behat/block_townsquare_coursefilter.feature b/tests/behat/block_townsquare_coursefilter.feature index 9f808e2..1cea74e 100644 --- a/tests/behat/block_townsquare_coursefilter.feature +++ b/tests/behat/block_townsquare_coursefilter.feature @@ -34,10 +34,10 @@ Feature: The townsquare block allows users to see notifications from different c And I should see "Test assign 3" And I click on "Course 1" "checkbox" Then "C1" "css_element" should not be visible - And "C2" "css_element" should be visible - And "C3" "css_element" should be visible + And "Test assign 2" "text" should be visible + And "Test assign 3" "text" should be visible And I click on "Course 2" "checkbox" Then "C2" "css_element" should not be visible - And "C3" "css_element" should be visible + And "Test assign 3" "text" should be visible And I click on "Course 3" "checkbox" Then "C3" "css_element" should not be visible From 97bba0bdf2f697a177cfb8d5e18c3458142211b0 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 4 Apr 2024 15:21:00 +0200 Subject: [PATCH 058/123] WIP: time filter behat test --- .../block_townsquare_coursefilter.feature | 68 +++++++++++++------ 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/tests/behat/block_townsquare_coursefilter.feature b/tests/behat/block_townsquare_coursefilter.feature index 1cea74e..839cac1 100644 --- a/tests/behat/block_townsquare_coursefilter.feature +++ b/tests/behat/block_townsquare_coursefilter.feature @@ -19,25 +19,53 @@ Feature: The townsquare block allows users to see notifications from different c | student1 | C2 | student | | student1 | C3 | student | And the following "activities" exist: - | activity | course | idnumber | name | intro | timeopen | duedate | - | assign | C1 | assign1 | Test assign 1 | Assign due in 2 months | ##now -2 days## | ##now +2 month## | - | assign | C2 | assign2 | Test assign 2 | Assign due tomorrow | ##now -2 days## | ##tomorrow## | - | assign | C3 | assign3 | Test assign 3 | Assign due yesterday | ##now -2 days## | ##yesterday## | + | activity | course | idnumber | name | intro | timeopen | duedate | + | assign | C1 | assign1 | Test assign 1 | Assign due in 2 months | ##now -2 days## | ##now +1 days## | + | assign | C2 | assign2 | Test assign 2 | Assign due in 4 days | ##now -2 days## | ##now +4 days## | + | assign | C3 | assign3 | Test assign 3 | Assign due in 6 days | ##now -2 days## | ##now +6 days## | + Scenario: If the user unselects the a course in the course filter, the assignment from that course should be hidden + Given I log in as "student1" + And I turn editing mode on + When I add the "Town Square" block + Then I should see "Test assign 1" + And I should see "Test assign 2" + And I should see "Test assign 3" + When I click on "Course 1" "checkbox" + Then "Test assign 1" "text" should not be visible + And "Test assign 2" "text" should be visible + And "Test assign 3" "text" should be visible + When I click on "Course 2" "checkbox" + Then "Test assign 2" "text" should not be visible + And "Test assign 3" "text" should be visible + When I click on "Course 3" "checkbox" + Then "Test assign 3" "text" should not be visible + + Scenario: If the user changes the time filter, the content should adapt to the selected time spans + Given the following "activities" exist: + | activity | course | idnumber | name | intro | timeopen | duedate | + | assign | C1 | assign4 | Test assign 4 | Assign due in 2 months | ##now -2 days## | ##now +8 days## | + | assign | C1 | assign5 | Test assign 5 | Assign due tomorrow | ##now -2 days## | ##now -1 days## | + | assign | C1 | assign6 | Test assign 6 | Assign due yesterday | ##now -2 days## | ##now -4 days## | + | assign | C1 | assign7 | Test assign 7 | Assign due in 2 months | ##now -2 days## | ##now -6 days## | + And the following "activities" exist: + | activity | course | idnumber | name | intro | timeopen | timeclose | + | choice | C2 | choice1 | Test choice 1 | Choice description | ##now -10 days## | ##now -8 days## | + And I log in as "student1" + And I turn editing mode on + And I add the "Town Square" block to the "content" region + And I click on "Time filter" "text" + And I click on "Next two days" "text" + Then "Test assign 1" "text" should be visible + And "Test assign 2" "text" should not be visible + And "Choice description" "text" should not be visible + And I click on "Next five days" "text" + Then "Test assign 1" "text" should be visible + And "Test assign 2" "text" should be visible + And "Test assign 3" "text" should not be visible + And I click on "Next week" "text" + Then "Test assign 1" "text" should be visible + And "Test assign 2" "text" should be visible + And "Test assign 3" "text" should be visible + And "Test assign 4" "text" should not be visible - Scenario: If the user unselects the a course in the course filter, the assignment from that course should be hidden - Given I log in as "student1" - And I turn editing mode on - And I add the "Town Square" block - Then I should see "Test assign 1" - And I should see "Test assign 2" - And I should see "Test assign 3" - And I click on "Course 1" "checkbox" - Then "C1" "css_element" should not be visible - And "Test assign 2" "text" should be visible - And "Test assign 3" "text" should be visible - And I click on "Course 2" "checkbox" - Then "C2" "css_element" should not be visible - And "Test assign 3" "text" should be visible - And I click on "Course 3" "checkbox" - Then "C3" "css_element" should not be visible From 36e4c1b12151c5df9bfb5e44f217d036a080d2a0 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 5 Apr 2024 15:29:48 +0200 Subject: [PATCH 059/123] complete behat tests added --- lang/en/block_townsquare.php | 8 +- tests/behat/behat_block_townsquare.php | 25 ++- .../block_townsquare_coursefilter.feature | 147 ++++++++++++++---- 3 files changed, 144 insertions(+), 36 deletions(-) diff --git a/lang/en/block_townsquare.php b/lang/en/block_townsquare.php index 09e5bbd..8dfb31e 100644 --- a/lang/en/block_townsquare.php +++ b/lang/en/block_townsquare.php @@ -63,15 +63,15 @@ $string['nextfivedaysnotifications'] = 'Next five days'; $string['nextweeknotifications'] = 'Next week'; $string['nextmonthnotifications'] = 'Next month'; -$string['lasttwodaysnotifications'] = 'last two days'; -$string['lastfivedaysnotifications'] = 'last five days'; +$string['lasttwodaysnotifications'] = 'Last two days'; +$string['lastfivedaysnotifications'] = 'Last five days'; $string['lastweeknotifications'] = 'Last week'; $string['lastmonthnotifications'] = 'Last month'; // Letter filter options. $string['basicletters'] = 'Basic letters'; -$string['completionletters'] = 'Activity Completions'; -$string['postletters'] = 'Forum Posts'; +$string['completionletters'] = 'Activity completions'; +$string['postletters'] = 'Forum posts'; // Save button strings. $string['savebutton'] = 'Save settings'; diff --git a/tests/behat/behat_block_townsquare.php b/tests/behat/behat_block_townsquare.php index 9e039de..49cd84e 100644 --- a/tests/behat/behat_block_townsquare.php +++ b/tests/behat/behat_block_townsquare.php @@ -22,14 +22,12 @@ * @copyright 2024 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - require_once(__DIR__ . '/../../../../lib/behat/behat_base.php'); use Behat\Gherkin\Node\TableNode as TableNode; use Behat\Mink\Exception\ElementNotFoundException; use Behat\Mink\Exception\ExpectationException; - /** * townsquare-related steps definitions. * @@ -40,4 +38,27 @@ */ class behat_block_townsquare extends behat_base { + /** + * Adds an activity completion event. + * @Given /^I add a townsquare completion event to "(?P(?:[^"]|\\")*)"$/ + * @param string $coursename, the course short name. + */ + public function i_add_an_townsquare_completion_event(string $coursename) { + global $DB; + $generator = new testing_data_generator(); + $course = $DB->get_record('course', ['shortname' => $coursename]); + $featurecompletionmanual = [ + 'completion' => COMPLETION_TRACKING_MANUAL, + 'completionexpected' => time() + 604800, + ]; + + $assignrecord = [ + 'course' => $course->id, + 'courseid' => $course->id, + 'duedate' => time() + 604800, + 'allowsubmissionsfromdate' => time() - 604800, + 'gradingduedate' => time() + 604860, + ]; + $generator->create_module('assign', $assignrecord, $featurecompletionmanual); + } } diff --git a/tests/behat/block_townsquare_coursefilter.feature b/tests/behat/block_townsquare_coursefilter.feature index 839cac1..df4338b 100644 --- a/tests/behat/block_townsquare_coursefilter.feature +++ b/tests/behat/block_townsquare_coursefilter.feature @@ -1,4 +1,4 @@ -@block @block_townsquare @javascript +@block @block_townsquare @javascript @core_completion Feature: The townsquare block allows users to see notifications from different courses In order to enable the townsquare block As a student @@ -9,10 +9,10 @@ Feature: The townsquare block allows users to see notifications from different c | username | firstname | lastname | email | idnumber | | student1 | Tamaro | Walter | student1@example.com | S1 | And the following "courses" exist: - | fullname | shortname | category | startdate | enddate | - | Course 1 | C1 | 0 | ##yesterday## | ##now +6 months## | - | Course 2 | C2 | 0 | ##yesterday## | ##now +6 months## | - | Course 3 | C3 | 0 | ##yesterday## | ##now +6 months## | + | fullname | shortname | category | startdate | enddate | enablecompletion | showcompletionconditions | + | Course 1 | C1 | 0 | ##yesterday## | ##now +6 months## | 1 | 1 | + | Course 2 | C2 | 0 | ##yesterday## | ##now +6 months## | 1 | 1 | + | Course 3 | C3 | 0 | ##yesterday## | ##now +6 months## | 1 | 1 | And the following "course enrolments" exist: | user | course | role | | student1 | C1 | student | @@ -20,11 +20,11 @@ Feature: The townsquare block allows users to see notifications from different c | student1 | C3 | student | And the following "activities" exist: | activity | course | idnumber | name | intro | timeopen | duedate | - | assign | C1 | assign1 | Test assign 1 | Assign due in 2 months | ##now -2 days## | ##now +1 days## | - | assign | C2 | assign2 | Test assign 2 | Assign due in 4 days | ##now -2 days## | ##now +4 days## | - | assign | C3 | assign3 | Test assign 3 | Assign due in 6 days | ##now -2 days## | ##now +6 days## | + | assign | C1 | 10 | Test assign 1 | Assign due in 2 months | ##now -2 days## | ##now +1 days## | + | assign | C2 | 11 | Test assign 2 | Assign due in 4 days | ##now -2 days## | ##now +4 days## | + | assign | C3 | 12 | Test assign 3 | Assign due in 6 days | ##now -2 days## | ##now +6 days## | - Scenario: If the user unselects the a course in the course filter, the assignment from that course should be hidden + Scenario: Test the course filter Given I log in as "student1" And I turn editing mode on When I add the "Town Square" block @@ -41,31 +41,118 @@ Feature: The townsquare block allows users to see notifications from different c When I click on "Course 3" "checkbox" Then "Test assign 3" "text" should not be visible - Scenario: If the user changes the time filter, the content should adapt to the selected time spans + + Scenario: Test the time filter Given the following "activities" exist: - | activity | course | idnumber | name | intro | timeopen | duedate | - | assign | C1 | assign4 | Test assign 4 | Assign due in 2 months | ##now -2 days## | ##now +8 days## | - | assign | C1 | assign5 | Test assign 5 | Assign due tomorrow | ##now -2 days## | ##now -1 days## | - | assign | C1 | assign6 | Test assign 6 | Assign due yesterday | ##now -2 days## | ##now -4 days## | - | assign | C1 | assign7 | Test assign 7 | Assign due in 2 months | ##now -2 days## | ##now -6 days## | + | activity | course | idnumber | name | intro | timeopen | duedate | + | assign | C1 | 13 | Test assign 4 | Assign due in 8 days | ##now -2 days## | ##now +8 days## | + | assign | C1 | 14 | Test assign 5 | Assign due in 3 months | ##now -2 days## | ##now +2 months## | + | assign | C1 | 15 | Test assign 6 | Assign due tomorrow | ##now -2 days## | ##now -1 days## | + | assign | C1 | 16 | Test assign 7 | Assign due yesterday | ##now -2 days## | ##now -4 days## | + | assign | C1 | 17 | Test assign 8 | Assign due in 2 months | ##now -2 days## | ##now -6 days## | And the following "activities" exist: - | activity | course | idnumber | name | intro | timeopen | timeclose | - | choice | C2 | choice1 | Test choice 1 | Choice description | ##now -10 days## | ##now -8 days## | + | activity | course | idnumber | name | intro | timeopen | timeclose | + | choice | C2 | 18 | Test choice 1 | Choice description | ##now -8 days## | ##now -8 days## | + | choice | C2 | 19 | Test choice 2 | Choice description | ##now -2 months##| ##now -2 months## | And I log in as "student1" And I turn editing mode on And I add the "Town Square" block to the "content" region And I click on "Time filter" "text" - And I click on "Next two days" "text" - Then "Test assign 1" "text" should be visible - And "Test assign 2" "text" should not be visible - And "Choice description" "text" should not be visible - And I click on "Next five days" "text" - Then "Test assign 1" "text" should be visible - And "Test assign 2" "text" should be visible - And "Test assign 3" "text" should not be visible - And I click on "Next week" "text" - Then "Test assign 1" "text" should be visible - And "Test assign 2" "text" should be visible - And "Test assign 3" "text" should be visible - And "Test assign 4" "text" should not be visible + # Test the time filter for the future + When I click on "Next two days" "text" + Then I should see "Test assign 1" in the "Town Square" "block" + And I should not see "Test assign 2" in the "Town Square" "block" + And I should not see "Choice description" in the "Town Square" "block" + When I click on "Next five days" "text" + Then I should see "Test assign 1" in the "Town Square" "block" + And I should see "Test assign 2" in the "Town Square" "block" + And I should not see "Test assign 3" in the "Town Square" "block" + And I should not see "Choice description" in the "Town Square" "block" + When I click on "Next week" "text" + Then I should see "Test assign 1" in the "Town Square" "block" + And I should see "Test assign 2" in the "Town Square" "block" + And I should see "Test assign 3" in the "Town Square" "block" + And I should not see "Test assign 4" in the "Town Square" "block" + And I should not see "Choice description" in the "Town Square" "block" + When I click on "Next month" "text" + Then I should see "Test assign 1" in the "Town Square" "block" + And I should see "Test assign 3" in the "Town Square" "block" + And I should see "Test assign 4" in the "Town Square" "block" + And I should not see "Test assign 5" in the "Town Square" "block" + And I should not see "Choice description" in the "Town Square" "block" + # All notifications button + When I click on "All notifications" "text" + Then I should see "Test assign 1" in the "Town Square" "block" + And I should see "Test assign 3" in the "Town Square" "block" + And I should see "Test assign 5" in the "Town Square" "block" + # Test time filter for the past + When I click on "Last two days" "text" + Then I should see "Test assign 6" in the "Town Square" "block" + And I should not see "Test assign 7" in the "Town Square" "block" + And I should not see "Test assign 1" in the "Town Square" "block" + When I click on "Last five days" "text" + Then I should see "Test assign 6" in the "Town Square" "block" + And I should see "Test assign 7" in the "Town Square" "block" + And I should not see "Test assign 8" in the "Town Square" "block" + And I should not see "Test assign 1" in the "Town Square" "block" + When I click on "Last week" "text" + Then I should see "Test assign 6" in the "Town Square" "block" + And I should see "Test assign 8" in the "Town Square" "block" + And I should not see "Test choice 1" in the "Town Square" "block" + When I click on "Last month" "text" + Then I should see "Test assign 6" in the "Town Square" "block" + And I should see "Test assign 8" in the "Town Square" "block" + And I should see "Test choice 1" in the "Town Square" "block" + And I should not see "Test choice 2" in the "Town Square" "block" + When I click on "All notifications" "text" + Then I should see "Test choice 2" in the "Town Square" "block" + # Test different combinations of time filters + When I click on "Next two days" "text" + And I click on "Last five days" "text" + Then I should see "Test assign 1" in the "Town Square" "block" + And I should not see "Test assign 2" in the "Town Square" "block" + And I should see "Test assign 6" in the "Town Square" "block" + And I should see "Test assign 7" in the "Town Square" "block" + And I should not see "Test assign 8" in the "Town Square" "block" + When I click on "Next week" "text" + And I click on "Last two days" "text" + Then I should see "Test assign 1" in the "Town Square" "block" + And I should see "Test assign 3" in the "Town Square" "block" + And I should not see "Test assign 4" in the "Town Square" "block" + And I should see "Test assign 6" in the "Town Square" "block" + And I should not see "Test assign 7" in the "Town Square" "block" + When I click on "Next month" "text" + And I click on "Last week" "text" + Then I should see "Test assign 1" in the "Town Square" "block" + And I should see "Test assign 4" in the "Town Square" "block" + And I should not see "Test assign 5" in the "Town Square" "block" + And I should see "Test assign 6" in the "Town Square" "block" + And I should see "Test assign 8" in the "Town Square" "block" + And I should not see "Test Choice 1" in the "Town Square" "block" + Scenario: Test the letter filter + Given the following "activity" exists: + | course | C1 | + | activity | forum | + | name | Test forum name | + | idnumber | forum | + And the following "mod_forum > discussions" exist: + | forum | name | subject | message | + | forum | Discussion 1 | Discussion 1 | Discussion contents 1, first message | + And I add a townsquare completion event to "C1" + And I log in as "student1" + And I turn editing mode on + And I add the "Town Square" block to the "content" region + And I click on "Letter filter" "text" + Then I should see "Test forum name" in the "Town Square" "block" + And I should see "Test assign 1" in the "Town Square" "block" + And I should see "Assignment 1" in the "Town Square" "block" + When I click on "basicletter" "checkbox" + And I should not see "Test assign 1" in the "Town Square" "block" + And I should see "Test forum name" in the "Town Square" "block" + And I should see "Assignment 1" in the "Town Square" "block" + When I click on "postletter" "checkbox" + Then I should not see "Test forum name" in the "Town Square" "block" + And I should see "Assignment 1" in the "Town Square" "block" + When I click on "completionletter" "checkbox" + Then I should not see "Assignment 1" in the "Town Square" "block" From 6b4180867ba642f80fb67846979cc4aa0b161228 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Mon, 8 Apr 2024 14:25:10 +0200 Subject: [PATCH 060/123] adapt behat for older moodle versions --- .../block_townsquare_coursefilter.feature | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/tests/behat/block_townsquare_coursefilter.feature b/tests/behat/block_townsquare_coursefilter.feature index df4338b..8ae05da 100644 --- a/tests/behat/block_townsquare_coursefilter.feature +++ b/tests/behat/block_townsquare_coursefilter.feature @@ -23,23 +23,24 @@ Feature: The townsquare block allows users to see notifications from different c | assign | C1 | 10 | Test assign 1 | Assign due in 2 months | ##now -2 days## | ##now +1 days## | | assign | C2 | 11 | Test assign 2 | Assign due in 4 days | ##now -2 days## | ##now +4 days## | | assign | C3 | 12 | Test assign 3 | Assign due in 6 days | ##now -2 days## | ##now +6 days## | + And the following "blocks" exist: + | blockname | contextlevel | reference | pagetypepattern | defaultregion | + | townsquare | System | 1 | my-index | content | Scenario: Test the course filter Given I log in as "student1" - And I turn editing mode on - When I add the "Town Square" block - Then I should see "Test assign 1" - And I should see "Test assign 2" - And I should see "Test assign 3" + Then I should see "Test assign 1" in the "Town Square" "block" + And I should see "Test assign 2" in the "Town Square" "block" + And I should see "Test assign 3" in the "Town Square" "block" When I click on "Course 1" "checkbox" - Then "Test assign 1" "text" should not be visible - And "Test assign 2" "text" should be visible - And "Test assign 3" "text" should be visible + Then I should not see "Test assign 1" in the "Town Square" "block" + And I should see "Test assign 2" in the "Town Square" "block" + And I should see "Test assign 3" in the "Town Square" "block" When I click on "Course 2" "checkbox" - Then "Test assign 2" "text" should not be visible - And "Test assign 3" "text" should be visible + Then I should not see "Test assign 2" in the "Town Square" "block" + And I should see "Test assign 3" in the "Town Square" "block" When I click on "Course 3" "checkbox" - Then "Test assign 3" "text" should not be visible + Then I should not see "Test assign 3" in the "Town Square" "block" Scenario: Test the time filter @@ -55,8 +56,6 @@ Feature: The townsquare block allows users to see notifications from different c | choice | C2 | 18 | Test choice 1 | Choice description | ##now -8 days## | ##now -8 days## | | choice | C2 | 19 | Test choice 2 | Choice description | ##now -2 months##| ##now -2 months## | And I log in as "student1" - And I turn editing mode on - And I add the "Town Square" block to the "content" region And I click on "Time filter" "text" # Test the time filter for the future When I click on "Next two days" "text" @@ -141,8 +140,6 @@ Feature: The townsquare block allows users to see notifications from different c | forum | Discussion 1 | Discussion 1 | Discussion contents 1, first message | And I add a townsquare completion event to "C1" And I log in as "student1" - And I turn editing mode on - And I add the "Town Square" block to the "content" region And I click on "Letter filter" "text" Then I should see "Test forum name" in the "Town Square" "block" And I should see "Test assign 1" in the "Town Square" "block" From 16b9e62d02a8175d7b3c62f6edbb6e3ad0821603 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Mon, 8 Apr 2024 15:05:54 +0200 Subject: [PATCH 061/123] use non deprecated language strings --- lang/en/block_townsquare.php | 1 + templates/postletter.mustache | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lang/en/block_townsquare.php b/lang/en/block_townsquare.php index 8dfb31e..2163001 100644 --- a/lang/en/block_townsquare.php +++ b/lang/en/block_townsquare.php @@ -72,6 +72,7 @@ $string['basicletters'] = 'Basic letters'; $string['completionletters'] = 'Activity completions'; $string['postletters'] = 'Forum posts'; +$string['showmore'] = 'Show more'; // Save button strings. $string['savebutton'] = 'Save settings'; diff --git a/templates/postletter.mustache b/templates/postletter.mustache index 65e5b44..6f2d7e8 100644 --- a/templates/postletter.mustache +++ b/templates/postletter.mustache @@ -97,7 +97,7 @@ - {{#str}} showmore, moodle {{/str}} + {{#str}} showmore, block_townsquare {{/str}} From 0a4fb3d332f98c0ac5fa62516c48c925cffa5847 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Mon, 8 Apr 2024 15:16:52 +0200 Subject: [PATCH 062/123] update workflow php version --- .github/workflows/moodle-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index 07ba552..a2eae8d 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: - php: ['8.1'] + php: ['8.2'] moodle-branch: ['MOODLE_403_STABLE'] database: ['pgsql'] From 0811b57f7a70514b5641fca4d406df69b1389ad2 Mon Sep 17 00:00:00 2001 From: Tamaro Walter Date: Mon, 8 Apr 2024 16:27:58 +0200 Subject: [PATCH 063/123] implement feature from other branch --- classes/townsquareevents.php | 3 ++ lang/en/block_townsquare.php | 22 ++++++++++++ locallib.php | 69 ++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+) diff --git a/classes/townsquareevents.php b/classes/townsquareevents.php index dd32d2d..36271ab 100644 --- a/classes/townsquareevents.php +++ b/classes/townsquareevents.php @@ -120,6 +120,9 @@ public function get_calendarevents(): array { // Add the name of the instance to the event. $calendarevent->instancename = $DB->get_field($calendarevent->modulename, 'name', ['id' => $calendarevent->instance]); + + // Modify the content of the event if necessary. + townsquare_check_coreevent($calendarevent); } return $calendarevents; diff --git a/lang/en/block_townsquare.php b/lang/en/block_townsquare.php index 2163001..3b8bf9d 100644 --- a/lang/en/block_townsquare.php +++ b/lang/en/block_townsquare.php @@ -94,3 +94,25 @@ $string['configpostlettercolor'] = 'Configuration for the color of the post letters'; $string['configcompletionlettercolor'] = 'Configuration for the color of the activity completion letters'; $string['configorientationmarkercolor'] = 'Configuration for the color of the orientation marker'; + +// Event strings. +$string['assignduemessage'] = 'Assignment is due until {$a->time}'; +$string['assigngradingduemessage'] = 'Assignment is due to be graded until {$a->time}'; +$string['chattimemessage'] = 'The next chat time is today at {$a->time}'; +$string['choiceopenmessage'] = 'Voting is possible from {$a->time} onwards'; +$string['choiceclosemessage'] = 'Please vote until {$a->time}. Afterwards the choice is closed'; +$string['dataopenmessage'] = 'The database opens today'; +$string['dataclosemessage'] = 'Please submit your entries until {$a->time}. The database closes afterwards'; +$string['feedbackopenmessage'] = 'Writing feedback is possible from {$a->time} onwards'; +$string['feedbackclosemessage'] = 'Writing feedback is possible until {$a->time}'; +$string['forumduemessage'] = 'The forum is due until {$a->time}'; +$string['lessonopenmessage'] = 'The lesson opens today at {$a->time}'; +$string['lessonclosemessage'] = 'The lesson ends today at {$a->time}'; +$string['quizopenmessage'] = 'The Quiz is open from {$a->time} onwards'; +$string['quizclosemessage'] = 'The Quiz closes today at {$a->time}'; +$string['quizopenmessage'] = 'Scorm Activity opens today'; +$string['quizclosemessage'] = 'Scorm Activity closes today'; +$string['workshopopensubmission'] = 'Submissions for the workshop are possible from {$a->time} onwards'; +$string['workshopclosesubmission'] = 'Please submit your work until {$a->time}. The workshop closes afterwards'; +$string['workshopopenassessment'] = 'The assessment phase starts today at {$a->time}'; +$string['workshopcloseassessment'] = 'Assessments for the workshop are due until {$a->time}'; \ No newline at end of file diff --git a/locallib.php b/locallib.php index 6874aaf..535a7e8 100644 --- a/locallib.php +++ b/locallib.php @@ -38,3 +38,72 @@ function townsquare_get_colorsetting($lettertype) { default => throw new \moodle_exception('invalidlettertype', 'block_townsquare'), }; } + +/** + * General Support function for core events. + * Can be used to modify the event content, as in some cases, core events don't have a good text in the events-datatable. + * @param object $event The event, that is being checked. + * @return void + */ +function townsquare_check_coreevent($event): void { + $time = date('H:i', $event->timestart); + if ($event->modulename == 'assign') { + if ($event->eventtype == 'due') { + $event->name = get_string('assignduemessage', 'block_townsquare', ['time' => $time]); + } else if ($event->eventtype == 'gradingdue') { + $event->name = get_string('assigngradingduemessage', 'block_townsquare', ['time' => $time]); + } + } else if ($event->modulename == 'chat' && $event->eventtype == 'chattime') { + $event->name = get_string('chattimemessage', 'block_townsquare', ['time' => $time]); + } else if ($event->modulename == 'choice') { + if ($event->eventtype == 'open') { + $event->name = get_string('choiceopenmessage', 'block_townsquare', ['time' => $time]); + } else if ($event->eventtype == 'close') { + $event->name = get_string('choiceclosemessage', 'block_townsquare', ['time' => $time]); + } + } else if ($event->modulename == 'data') { + if ($event->eventtype == 'open') { + $event->name = get_string('dataopenmessage', 'block_townsquare'); + }else if ($event->eventtype == 'close') { + $event->name = get_string('dataclosemessage', 'block_townsquare', ['time' => $time]); + } + } else if ($event->modulename == 'feedback') { + if ($event->eventtype == 'open') { + $event->name = get_string('feedbackopenmessage', 'block_townsquare', ['time' => $time]); + } else if ($event->eventtype == 'close') { + $event->name = get_string('feedbackclosemessage', 'block_townsquare', ['time' => $time]); + } + } else if ($event->modulename == 'forum') { + if ($event->eventtype == 'due') { + $event->name = get_string('forumduemessage', 'block_townsquare', ['time' => $time]); + } + } else if ($event->modulename == 'lesson') { + if ($event->eventtype == 'open') { + $event->name = get_string('lessonopenmessage', 'block_townsquare', ['time' => $time]); + } else if ($event->eventtype == 'close') { + $event->name = get_string('lessonclosemessage', 'block_townsquare', ['time' => $time]); + } + } else if ($event->modulename == 'quiz') { + if ($event->eventtype == 'open') { + $event->name = get_string('quizopenmessage', 'block_townsquare', ['time' => $time]); + } else if ($event->eventtype == 'close') { + $event->name = get_string('quizclosemessage', 'block_townsquare', ['time' => $time]); + } + } else if ($event->modulename == 'scorm') { + if ($event->eventtype == 'open') { + $event->name = get_string('scormopenmessage', 'block_townsquare'); + } else if ($event->eventtype == 'close') { + $event->name = get_string('scormclosemessage', 'block_townsquare'); + } + } else if ($event->modulename == 'workshop') { + if ($event->eventtype == 'opensubmission') { + $event->name = get_string('workshopopensubmission', 'block_townsquare', ['time' => $time]); + } else if ($event->eventtype == 'closesubmission') { + $event->name = get_string('workshopclosesubmission', 'block_townsquare', ['time' => $time]); + } else if ($event->eventtype == 'openassessment') { + $event->name = get_string('workshopopenassessment', 'block_townsquare', ['time' => $time]); + } else if ($event->eventtype == 'closeassessment') { + $event->name = get_string('workshopcloseassessment', 'block_townsquare', ['time' => $time]); + } + } +} \ No newline at end of file From d6fddff2324ab10bea20469591cf2329776609d4 Mon Sep 17 00:00:00 2001 From: Tamaro Walter Date: Mon, 8 Apr 2024 16:39:39 +0200 Subject: [PATCH 064/123] fix codechecker fails --- lang/en/block_townsquare.php | 2 +- locallib.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lang/en/block_townsquare.php b/lang/en/block_townsquare.php index 3b8bf9d..f5822d9 100644 --- a/lang/en/block_townsquare.php +++ b/lang/en/block_townsquare.php @@ -115,4 +115,4 @@ $string['workshopopensubmission'] = 'Submissions for the workshop are possible from {$a->time} onwards'; $string['workshopclosesubmission'] = 'Please submit your work until {$a->time}. The workshop closes afterwards'; $string['workshopopenassessment'] = 'The assessment phase starts today at {$a->time}'; -$string['workshopcloseassessment'] = 'Assessments for the workshop are due until {$a->time}'; \ No newline at end of file +$string['workshopcloseassessment'] = 'Assessments for the workshop are due until {$a->time}'; diff --git a/locallib.php b/locallib.php index 535a7e8..c7f9dfc 100644 --- a/locallib.php +++ b/locallib.php @@ -64,7 +64,7 @@ function townsquare_check_coreevent($event): void { } else if ($event->modulename == 'data') { if ($event->eventtype == 'open') { $event->name = get_string('dataopenmessage', 'block_townsquare'); - }else if ($event->eventtype == 'close') { + } else if ($event->eventtype == 'close') { $event->name = get_string('dataclosemessage', 'block_townsquare', ['time' => $time]); } } else if ($event->modulename == 'feedback') { @@ -106,4 +106,4 @@ function townsquare_check_coreevent($event): void { $event->name = get_string('workshopcloseassessment', 'block_townsquare', ['time' => $time]); } } -} \ No newline at end of file +} From 2de340bbf743303e43fa19195fd5eb86c6115762 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Mon, 8 Apr 2024 18:17:53 +0200 Subject: [PATCH 065/123] add test for usersetting save function --- .../block_townsquare_coursefilter.feature | 2 +- .../block_townsquare_savepreferences.feature | 35 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 tests/behat/block_townsquare_savepreferences.feature diff --git a/tests/behat/block_townsquare_coursefilter.feature b/tests/behat/block_townsquare_coursefilter.feature index 8ae05da..61d728f 100644 --- a/tests/behat/block_townsquare_coursefilter.feature +++ b/tests/behat/block_townsquare_coursefilter.feature @@ -1,4 +1,4 @@ -@block @block_townsquare @javascript @core_completion +@block @block_townsquare @javascript Feature: The townsquare block allows users to see notifications from different courses In order to enable the townsquare block As a student diff --git a/tests/behat/block_townsquare_savepreferences.feature b/tests/behat/block_townsquare_savepreferences.feature new file mode 100644 index 0000000..b3c8c9c --- /dev/null +++ b/tests/behat/block_townsquare_savepreferences.feature @@ -0,0 +1,35 @@ +@block @block_townsquare @javascript +Feature: In the townsquare block user can save their settings in a database. + + Background: + Given the following "users" exist: + | username | firstname | lastname | email | idnumber | + | student1 | Tamaro | Walter | student1@example.com | S1 | + And the following "courses" exist: + | fullname | shortname | category | startdate | enddate | enablecompletion | showcompletionconditions | + | Course 1 | C1 | 0 | ##yesterday## | ##now +6 months## | 1 | 1 | + | Course 2 | C2 | 0 | ##yesterday## | ##now +6 months## | 1 | 1 | + | Course 3 | C3 | 0 | ##yesterday## | ##now +6 months## | 1 | 1 | + And the following "course enrolments" exist: + | user | course | role | + | student1 | C1 | student | + | student1 | C2 | student | + | student1 | C3 | student | + And the following "activities" exist: + | activity | course | idnumber | name | intro | timeopen | duedate | + | assign | C1 | 10 | Test assign 1 | Assign due in 2 months | ##now -2 days## | ##now +1 days## | + | assign | C2 | 11 | Test assign 2 | Assign due in 4 days | ##now -2 days## | ##now +4 days## | + | assign | C3 | 12 | Test assign 3 | Assign due in 6 days | ##now -2 days## | ##now +6 days## | + And the following "blocks" exist: + | blockname | contextlevel | reference | pagetypepattern | defaultregion | + | townsquare | System | 1 | my-index | content | + + Scenario: Test the course filter + Given I log in as "student1" + Then I should see "Test assign 2" in the "Town Square" "block" + And I click on "Time filter" "text" + And I click on "Next two days" "text" + When I click on "Save settings" "text" in the "Town Square" "block" + Then I should not see "Test assign 2" in the "Town Square" "block" + And I reload the page + Then I should not see "Test assign 2" in the "Town Square" "block" \ No newline at end of file From 969295d562faa94a4059292e88f17bc078602ee3 Mon Sep 17 00:00:00 2001 From: Tamaro Walter Date: Tue, 9 Apr 2024 17:34:46 +0200 Subject: [PATCH 066/123] WIP: Try to fix Web-service --- amd/build/coursefilter.min.js.map | 2 +- amd/build/filtercontroller.min.js.map | 2 +- amd/build/letterfilter.min.js.map | 2 +- amd/build/postletter.min.js.map | 2 +- amd/build/timefilter.min.js.map | 2 +- amd/build/usersettings_save.min.js | 2 +- amd/build/usersettings_save.min.js.map | 2 +- amd/src/usersettings_save.js | 8 +++++--- db/services.php | 3 +-- externallib.php | 14 ++++++-------- 10 files changed, 19 insertions(+), 20 deletions(-) diff --git a/amd/build/coursefilter.min.js.map b/amd/build/coursefilter.min.js.map index de47173..4b6bcae 100644 --- a/amd/build/coursefilter.min.js.map +++ b/amd/build/coursefilter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"coursefilter.min.js","sources":["../src/coursefilter.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 * Javascript for the course filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the course filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/coursefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant checkboxes.\nconst checkboxes = document.querySelectorAll('.ts_course_checkbox');\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n // Get the courseid associated with the checkbox\n const courseid = checkbox.id;\n\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.ts_timefilter_active.ts_letterfilter_active');\n\n // Loop through each letter mark it as \"active\" or not based on checkbox state and the letter id.\n letters.forEach(function(letter) {\n let letterCourseId = letter.querySelector('.townsquareletter_course').id;\n\n if (courseid === letterCourseId) {\n if (checkbox.checked) {\n letter.classList.add('ts_coursefilter_active'); // Mark the letter as \"active\".\n } else {\n letter.classList.remove('ts_coursefilter_active'); // Mark the letter as \"not active\".\n }\n }\n });\n });\n });\n}\n"],"names":["checkboxes","forEach","checkbox","addEventListener","courseid","id","document","querySelectorAll","letter","letterCourseId","querySelector","checked","classList","add","remove"],"mappings":"6IAgCO,WACHA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,WAEhC,MAAMC,SAAWF,SAASG,GAIVC,SAASC,iBAAiB,kEAGlCN,SAAQ,SAASO,QACrB,IAAIC,eAAiBD,OAAOE,cAAc,4BAA4BL,GAElED,WAAaK,iBACTP,SAASS,QACTH,OAAOI,UAAUC,IAAI,0BAErBL,OAAOI,UAAUE,OAAO;;;;;;;;;;;AAvBhD,MAAMd,WAAaM,SAASC,iBAAiB,sBA6B5C"} \ No newline at end of file +{"version":3,"file":"coursefilter.min.js","sources":["../src/coursefilter.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 * Javascript for the course filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the course filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/coursefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant checkboxes.\nconst checkboxes = document.querySelectorAll('.ts_course_checkbox');\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n // Get the courseid associated with the checkbox\n const courseid = checkbox.id;\n\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.ts_timefilter_active.ts_letterfilter_active');\n\n // Loop through each letter mark it as \"active\" or not based on checkbox state and the letter id.\n letters.forEach(function(letter) {\n let letterCourseId = letter.querySelector('.townsquareletter_course').id;\n\n if (courseid === letterCourseId) {\n if (checkbox.checked) {\n letter.classList.add('ts_coursefilter_active'); // Mark the letter as \"active\".\n } else {\n letter.classList.remove('ts_coursefilter_active'); // Mark the letter as \"not active\".\n }\n }\n });\n });\n });\n}\n"],"names":["checkboxes","forEach","checkbox","addEventListener","courseid","id","document","querySelectorAll","letter","letterCourseId","querySelector","checked","classList","add","remove"],"mappings":"wJAiCIA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,iBAE1BC,SAAWF,SAASG,GAIVC,SAASC,iBAAiB,kEAGlCN,SAAQ,SAASO,YACjBC,eAAiBD,OAAOE,cAAc,4BAA4BL,GAElED,WAAaK,iBACTP,SAASS,QACTH,OAAOI,UAAUC,IAAI,0BAErBL,OAAOI,UAAUE,OAAO;;;;;;;;;;;MAvB1Cd,WAAaM,SAASC,iBAAiB"} \ No newline at end of file diff --git a/amd/build/filtercontroller.min.js.map b/amd/build/filtercontroller.min.js.map index ed17974..c6fdfb0 100644 --- a/amd/build/filtercontroller.min.js.map +++ b/amd/build/filtercontroller.min.js.map @@ -1 +1 @@ -{"version":3,"file":"filtercontroller.min.js","sources":["../src/filtercontroller.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 * Javascript to show/hide letters based on all filters\n *\n * This file implements 1 functionality:\n * - If the \"save settings\" button is pressed, store the settings in the database.\n *\n * @module block_townsquare/filtercontroller\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get all letters from townsquare.\nconst letters = document.querySelectorAll('.townsquare_letter');\n\n/**\n * Init function\n */\nexport function init() {\n // First step: activate every letter by adding the filter classes.\n letters.forEach(function(letter) {\n letter.classList.add('ts_coursefilter_active');\n letter.classList.add('ts_timefilter_active');\n letter.classList.add('ts_letterfilter_active');\n });\n\n // Add a mutation listener to each letter.\n letters.forEach(function(letter) {\n const observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(mutation) {\n if (mutation.attributeName === 'class') {\n // If the class of the letter changes, check if the letter should be shown or hidden.\n let coursefilter = letter.classList.contains('ts_coursefilter_active');\n let timefilter = letter.classList.contains('ts_timefilter_active');\n let letterfilter = letter.classList.contains('ts_letterfilter_active');\n\n // If all filters are active, show the letter.\n if (coursefilter && timefilter && letterfilter) {\n letter.style.display = 'block';\n } else {\n letter.style.display = 'none';\n }\n }\n });\n });\n\n observer.observe(letter, {attributes: true});\n });\n}\n"],"names":["letters","forEach","letter","classList","add","MutationObserver","mutations","mutation","attributeName","coursefilter","contains","timefilter","letterfilter","style","display","observe","attributes","document","querySelectorAll"],"mappings":"iJAgCO,WAEHA,QAAQC,SAAQ,SAASC,QACrBA,OAAOC,UAAUC,IAAI,0BACrBF,OAAOC,UAAUC,IAAI,wBACrBF,OAAOC,UAAUC,IAAI,6BAIzBJ,QAAQC,SAAQ,SAASC,QACJ,IAAIG,kBAAiB,SAASC,WAC3CA,UAAUL,SAAQ,SAASM,UACvB,GAA+B,UAA3BA,SAASC,cAA2B,CAEpC,IAAIC,aAAeP,OAAOC,UAAUO,SAAS,0BACzCC,WAAaT,OAAOC,UAAUO,SAAS,wBACvCE,aAAeV,OAAOC,UAAUO,SAAS,0BAIzCR,OAAOW,MAAMC,QADbL,cAAgBE,YAAcC,aACP,QAEA,cAM9BG,QAAQb,OAAQ,CAACc,YAAY;;;;;;;;;;;AAjC9C,MAAMhB,QAAUiB,SAASC,iBAAiB,qBAmCzC"} \ No newline at end of file +{"version":3,"file":"filtercontroller.min.js","sources":["../src/filtercontroller.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 * Javascript to show/hide letters based on all filters\n *\n * This file implements 1 functionality:\n * - If the \"save settings\" button is pressed, store the settings in the database.\n *\n * @module block_townsquare/filtercontroller\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get all letters from townsquare.\nconst letters = document.querySelectorAll('.townsquare_letter');\n\n/**\n * Init function\n */\nexport function init() {\n // First step: activate every letter by adding the filter classes.\n letters.forEach(function(letter) {\n letter.classList.add('ts_coursefilter_active');\n letter.classList.add('ts_timefilter_active');\n letter.classList.add('ts_letterfilter_active');\n });\n\n // Add a mutation listener to each letter.\n letters.forEach(function(letter) {\n const observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(mutation) {\n if (mutation.attributeName === 'class') {\n // If the class of the letter changes, check if the letter should be shown or hidden.\n let coursefilter = letter.classList.contains('ts_coursefilter_active');\n let timefilter = letter.classList.contains('ts_timefilter_active');\n let letterfilter = letter.classList.contains('ts_letterfilter_active');\n\n // If all filters are active, show the letter.\n if (coursefilter && timefilter && letterfilter) {\n letter.style.display = 'block';\n } else {\n letter.style.display = 'none';\n }\n }\n });\n });\n\n observer.observe(letter, {attributes: true});\n });\n}\n"],"names":["letters","forEach","letter","classList","add","MutationObserver","mutations","mutation","attributeName","coursefilter","contains","timefilter","letterfilter","style","display","observe","attributes","document","querySelectorAll"],"mappings":"4JAkCIA,QAAQC,SAAQ,SAASC,QACrBA,OAAOC,UAAUC,IAAI,0BACrBF,OAAOC,UAAUC,IAAI,wBACrBF,OAAOC,UAAUC,IAAI,6BAIzBJ,QAAQC,SAAQ,SAASC,QACJ,IAAIG,kBAAiB,SAASC,WAC3CA,UAAUL,SAAQ,SAASM,aACQ,UAA3BA,SAASC,cAA2B,KAEhCC,aAAeP,OAAOC,UAAUO,SAAS,0BACzCC,WAAaT,OAAOC,UAAUO,SAAS,wBACvCE,aAAeV,OAAOC,UAAUO,SAAS,0BAIzCR,OAAOW,MAAMC,QADbL,cAAgBE,YAAcC,aACP,QAEA,cAM9BG,QAAQb,OAAQ,CAACc,YAAY;;;;;;;;;;;MAjCxChB,QAAUiB,SAASC,iBAAiB"} \ No newline at end of file diff --git a/amd/build/letterfilter.min.js.map b/amd/build/letterfilter.min.js.map index 02c4ab5..9f6c13e 100644 --- a/amd/build/letterfilter.min.js.map +++ b/amd/build/letterfilter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"letterfilter.min.js","sources":["../src/letterfilter.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 * Javascript for the letter filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the letter filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/letterfilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant checkboxes.\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n // Get the letter name associated with the checkbox.\n const lettername = checkbox.id;\n\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.' + lettername +\n '.ts_timefilter_active.ts_coursefilter_active');\n\n // Loop through each letter and hide/show based on checkbox state.\n letters.forEach(function(letter) {\n if (checkbox.checked) {\n letter.classList.add('ts_letterfilter_active'); // Mark the letter as \"active\".\n } else {\n letter.classList.remove('ts_letterfilter_active'); // Mark the letter as \"not active\".\n }\n });\n });\n });\n}\n"],"names":["checkboxes","forEach","checkbox","addEventListener","lettername","id","document","querySelectorAll","letter","checked","classList","add","remove"],"mappings":"6IAgCO,WACHA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,WAEhC,MAAMC,WAAaF,SAASG,GAIZC,SAASC,iBAAiB,sBAAwBH,WACxB,gDAGlCH,SAAQ,SAASO,QACjBN,SAASO,QACTD,OAAOE,UAAUC,IAAI,0BAErBH,OAAOE,UAAUE,OAAO;;;;;;;;;;;AArB5C,MAAMZ,WAAaM,SAASC,iBAAiB,sBA0B5C"} \ No newline at end of file +{"version":3,"file":"letterfilter.min.js","sources":["../src/letterfilter.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 * Javascript for the letter filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the letter filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/letterfilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant checkboxes.\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n // Get the letter name associated with the checkbox.\n const lettername = checkbox.id;\n\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.' + lettername +\n '.ts_timefilter_active.ts_coursefilter_active');\n\n // Loop through each letter and hide/show based on checkbox state.\n letters.forEach(function(letter) {\n if (checkbox.checked) {\n letter.classList.add('ts_letterfilter_active'); // Mark the letter as \"active\".\n } else {\n letter.classList.remove('ts_letterfilter_active'); // Mark the letter as \"not active\".\n }\n });\n });\n });\n}\n"],"names":["checkboxes","forEach","checkbox","addEventListener","lettername","id","document","querySelectorAll","letter","checked","classList","add","remove"],"mappings":"wJAiCIA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,iBAE1BC,WAAaF,SAASG,GAIZC,SAASC,iBAAiB,sBAAwBH,WACxB,gDAGlCH,SAAQ,SAASO,QACjBN,SAASO,QACTD,OAAOE,UAAUC,IAAI,0BAErBH,OAAOE,UAAUE,OAAO;;;;;;;;;;;MArBtCZ,WAAaM,SAASC,iBAAiB"} \ No newline at end of file diff --git a/amd/build/postletter.min.js.map b/amd/build/postletter.min.js.map index fde6c82..aba2bad 100644 --- a/amd/build/postletter.min.js.map +++ b/amd/build/postletter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"postletter.min.js","sources":["../src/postletter.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\nimport {getString} from \"core/str\";\nimport {prefetchStrings} from 'core/prefetch';\n\n/**\n * Javascript for the post letter\n *\n * This file implements 2 functionalities:\n * - cuts posts that have many characters and shows a \"see more\" Button to see the whole text.\n * - Unnecessary

Tags from the Database are being replaced with line breaks to make the text more readable.\n *\n * @module block_townsquare/postletter\n * @copyright 2023 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nconst contentElements = document.getElementsByClassName('postletter_message');\nconst buttons = document.getElementsByClassName('townsquare_showmore');\nconst originalTexts = [];\n\nconst Selectors = {\n actions: {\n seemorebutton: '[data-action=\"block_townsquare/showmore_button\"]',\n },\n};\n\n/**\n * Init function\n *\n * The function can cut the text or extract paragraphs of a post.\n */\nexport function init() {\n contentElements.forEach(\n (element) => {\n // Replace all

within the text with simple line breaks..\n replaceParagraghTags(element);\n\n // Check if the text is too long.\n if (element.textContent.length >= 250) {\n // If the text is too long, cut it.\n originalTexts[element.id] = element.innerHTML;\n cutString(element);\n element.parentElement.insertAdjacentHTML('beforeend', '

');\n buttons[element.id].setAttribute('showmore', 'true');\n } else {\n // If the text is not too long, hide the show more button.\n buttons[element.id].style.display = \"none\";\n }\n }\n );\n\n // Get the strings for the show more/show less button.\n prefetchStrings('moodle', ['showmore', 'showless',]);\n\n // Add event listeners for the show more Button.\n addEventListener();\n}\n\n/**\n * Function to cut a String at a length of 250 characters.\n * The function does not cut within a word or after a space.\n * If the cutting point is within a word, the function searches for the next space and cuts there.\n * @param {object} element\n */\nfunction cutString(element) {\n let text = element.textContent;\n let index = 250;\n while (text.charAt(index) != \" \") {\n index++;\n }\n element.innerHTML = text.substring(0,index);\n}\n\n/**\n * Event listener for the show more/show less button.\n */\nconst addEventListener = () => {\n document.addEventListener('click', e => {\n if (e.target.closest(Selectors.actions.seemorebutton)) {\n // Get the id of the clicked element.\n let letterid = e.target.id;\n contentElements.forEach(\n (element) => {\n if (element.id == letterid) {\n if (buttons[letterid].getAttribute('showmore') == 'true') {\n element.innerHTML = originalTexts[letterid];\n changeButtonString(letterid, false);\n } else {\n cutString(element);\n changeButtonString(letterid, true);\n }\n }\n }\n );\n }\n });\n};\n\n/**\n * Changes the button strings.\n * @param {string} index Which button should be changed\n * @param {boolean} toshowmore a boolean that indicates if the button should show more or less\n */\nasync function changeButtonString(index, toshowmore) {\n if (toshowmore == true) {\n buttons[index].textContent = await getString('showmore', 'moodle');\n buttons[index].setAttribute('showmore', 'true');\n } else {\n buttons[index].textContent = await getString('showless', 'moodle');\n buttons[index].setAttribute('showmore', 'false');\n }\n}\n\n/**\n * Removes in a text all   and surrounding

tags excluding the first occurrence.\n *\n * Helper function to make post look better.\n * @param {object} element\n */\nasync function replaceParagraghTags(element) {\n // Identify and store the first

and

tags\n let message = element.innerHTML;\n const firstPTag = message.indexOf('

');\n const lastPTag = message.lastIndexOf('

');\n\n // Remove   and surrounding

tags excluding the first occurrence\n message = message.replace(/

 <\\/p>/g, '').replace(/ /g, '');\n\n // Replace

tags with
excluding the first occurrence\n message = message.substring(0, firstPTag + 3) +\n message.substring(firstPTag + 3, lastPTag).replace(/

/g, '
').replace(/<\\/p>/g, '') +\n message.substring(lastPTag);\n element.innerHTML = message;\n}"],"names":["contentElements","forEach","element","async","message","innerHTML","firstPTag","indexOf","lastPTag","lastIndexOf","replace","substring","replaceParagraghTags","textContent","length","originalTexts","id","cutString","parentElement","insertAdjacentHTML","buttons","setAttribute","style","display","prefetchStrings","addEventListener","document","getElementsByClassName","Selectors","seemorebutton","text","index","charAt","e","target","closest","letterid","getAttribute","changeButtonString","toshowmore","getString"],"mappings":"qLA6CO,WACHA,gBAAgBC,SACXC,WAsFTC,eAAoCD,SAEhC,IAAIE,QAAUF,QAAQG,UACtB,MAAMC,UAAYF,QAAQG,QAAQ,OAC5BC,SAAWJ,QAAQK,YAAY,QAGrCL,QAAUA,QAAQM,QAAQ,kBAAmB,IAAIA,QAAQ,UAAW,IAGpEN,QAAUA,QAAQO,UAAU,EAAGL,UAAY,GACvCF,QAAQO,UAAUL,UAAY,EAAGE,UAAUE,QAAQ,OAAQ,QAAQA,QAAQ,SAAU,IACrFN,QAAQO,UAAUH,UACtBN,QAAQG,UAAYD,QAjGZQ,CAAqBV,SAGjBA,QAAQW,YAAYC,QAAU,KAE9BC,cAAcb,QAAQc,IAAMd,QAAQG,UACpCY,UAAUf,SACVA,QAAQgB,cAAcC,mBAAmB,YAAa,OACtDC,QAAQlB,QAAQc,IAAIK,aAAa,WAAY,SAG7CD,QAAQlB,QAAQc,IAAIM,MAAMC,QAAU,WAMhD,EAAAC,2BAAgB,SAAU,CAAC,WAAY,aAGvCC;;;;;;;;;;;;AAvCJ,MAAMzB,gBAAkB0B,SAASC,uBAAuB,sBAClDP,QAAUM,SAASC,uBAAuB,uBAC1CZ,cAAgB,GAEhBa,kBACO,CACLC,cAAe,oDA0CvB,SAASZ,UAAUf,SACf,IAAI4B,KAAO5B,QAAQW,YACfkB,MAAQ,IACZ,KAA6B,KAAtBD,KAAKE,OAAOD,QACfA,QAEJ7B,QAAQG,UAAYyB,KAAKnB,UAAU,EAAEoB,OAMzC,MAAMN,iBAAmBA,KACrBC,SAASD,iBAAiB,SAASQ,IAC/B,GAAIA,EAAEC,OAAOC,QAAQP,kBAAkBC,eAAgB,CAEnD,IAAIO,SAAWH,EAAEC,OAAOlB,GACxBhB,gBAAgBC,SACXC,UACOA,QAAQc,IAAMoB,WACoC,QAA9ChB,QAAQgB,UAAUC,aAAa,aAC/BnC,QAAQG,UAAYU,cAAcqB,UAClCE,mBAAmBF,UAAU,KAE7BnB,UAAUf,SACVoC,mBAAmBF,UAAU,WAMnD,EAQNjC,eAAemC,mBAAmBP,MAAOQ,YACnB,GAAdA,YACAnB,QAAQW,OAAOlB,kBAAoB,EAAA2B,gBAAU,WAAY,UACzDpB,QAAQW,OAAOV,aAAa,WAAY,UAExCD,QAAQW,OAAOlB,kBAAoB,EAAA2B,gBAAU,WAAY,UACzDpB,QAAQW,OAAOV,aAAa,WAAY,UAwB/C"} \ No newline at end of file +{"version":3,"file":"postletter.min.js","sources":["../src/postletter.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\r\n//\r\n// Moodle is free software: you can redistribute it and/or modify\r\n// it under the terms of the GNU General Public License as published by\r\n// the Free Software Foundation, either version 3 of the License, or\r\n// (at your option) any later version.\r\n//\r\n// Moodle is distributed in the hope that it will be useful,\r\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n// GNU General Public License for more details.\r\n//\r\n// You should have received a copy of the GNU General Public License\r\n// along with Moodle. If not, see .\r\n\r\nimport {getString} from \"core/str\";\r\nimport {prefetchStrings} from 'core/prefetch';\r\n\r\n/**\r\n * Javascript for the post letter\r\n *\r\n * This file implements 2 functionalities:\r\n * - cuts posts that have many characters and shows a \"see more\" Button to see the whole text.\r\n * - Unnecessary

Tags from the Database are being replaced with line breaks to make the text more readable.\r\n *\r\n * @module block_townsquare/postletter\r\n * @copyright 2023 Tamaro Walter\r\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\r\n */\r\n\r\nconst contentElements = document.getElementsByClassName('postletter_message');\r\nconst buttons = document.getElementsByClassName('townsquare_showmore');\r\nconst originalTexts = [];\r\n\r\nconst Selectors = {\r\n actions: {\r\n seemorebutton: '[data-action=\"block_townsquare/showmore_button\"]',\r\n },\r\n};\r\n\r\n/**\r\n * Init function\r\n *\r\n * The function can cut the text or extract paragraphs of a post.\r\n */\r\nexport function init() {\r\n contentElements.forEach(\r\n (element) => {\r\n // Replace all

within the text with simple line breaks..\r\n replaceParagraghTags(element);\r\n\r\n // Check if the text is too long.\r\n if (element.textContent.length >= 250) {\r\n // If the text is too long, cut it.\r\n originalTexts[element.id] = element.innerHTML;\r\n cutString(element);\r\n element.parentElement.insertAdjacentHTML('beforeend', '

');\r\n buttons[element.id].setAttribute('showmore', 'true');\r\n } else {\r\n // If the text is not too long, hide the show more button.\r\n buttons[element.id].style.display = \"none\";\r\n }\r\n }\r\n );\r\n\r\n // Get the strings for the show more/show less button.\r\n prefetchStrings('moodle', ['showmore', 'showless',]);\r\n\r\n // Add event listeners for the show more Button.\r\n addEventListener();\r\n}\r\n\r\n/**\r\n * Function to cut a String at a length of 250 characters.\r\n * The function does not cut within a word or after a space.\r\n * If the cutting point is within a word, the function searches for the next space and cuts there.\r\n * @param {object} element\r\n */\r\nfunction cutString(element) {\r\n let text = element.textContent;\r\n let index = 250;\r\n while (text.charAt(index) != \" \") {\r\n index++;\r\n }\r\n element.innerHTML = text.substring(0,index);\r\n}\r\n\r\n/**\r\n * Event listener for the show more/show less button.\r\n */\r\nconst addEventListener = () => {\r\n document.addEventListener('click', e => {\r\n if (e.target.closest(Selectors.actions.seemorebutton)) {\r\n // Get the id of the clicked element.\r\n let letterid = e.target.id;\r\n contentElements.forEach(\r\n (element) => {\r\n if (element.id == letterid) {\r\n if (buttons[letterid].getAttribute('showmore') == 'true') {\r\n element.innerHTML = originalTexts[letterid];\r\n changeButtonString(letterid, false);\r\n } else {\r\n cutString(element);\r\n changeButtonString(letterid, true);\r\n }\r\n }\r\n }\r\n );\r\n }\r\n });\r\n};\r\n\r\n/**\r\n * Changes the button strings.\r\n * @param {string} index Which button should be changed\r\n * @param {boolean} toshowmore a boolean that indicates if the button should show more or less\r\n */\r\nasync function changeButtonString(index, toshowmore) {\r\n if (toshowmore == true) {\r\n buttons[index].textContent = await getString('showmore', 'moodle');\r\n buttons[index].setAttribute('showmore', 'true');\r\n } else {\r\n buttons[index].textContent = await getString('showless', 'moodle');\r\n buttons[index].setAttribute('showmore', 'false');\r\n }\r\n}\r\n\r\n/**\r\n * Removes in a text all   and surrounding

tags excluding the first occurrence.\r\n *\r\n * Helper function to make post look better.\r\n * @param {object} element\r\n */\r\nasync function replaceParagraghTags(element) {\r\n // Identify and store the first

and

tags\r\n let message = element.innerHTML;\r\n const firstPTag = message.indexOf('

');\r\n const lastPTag = message.lastIndexOf('

');\r\n\r\n // Remove   and surrounding

tags excluding the first occurrence\r\n message = message.replace(/

 <\\/p>/g, '').replace(/ /g, '');\r\n\r\n // Replace

tags with
excluding the first occurrence\r\n message = message.substring(0, firstPTag + 3) +\r\n message.substring(firstPTag + 3, lastPTag).replace(/

/g, '
').replace(/<\\/p>/g, '') +\r\n message.substring(lastPTag);\r\n element.innerHTML = message;\r\n}"],"names":["contentElements","forEach","element","message","innerHTML","firstPTag","indexOf","lastPTag","lastIndexOf","replace","substring","replaceParagraghTags","textContent","length","originalTexts","id","cutString","parentElement","insertAdjacentHTML","buttons","setAttribute","style","display","addEventListener","document","getElementsByClassName","Selectors","seemorebutton","text","index","charAt","e","target","closest","letterid","getAttribute","changeButtonString","toshowmore"],"mappings":"gMA8CIA,gBAAgBC,SACXC,0BAsF2BA,aAE5BC,QAAUD,QAAQE,gBAChBC,UAAYF,QAAQG,QAAQ,OAC5BC,SAAWJ,QAAQK,YAAY,QAGrCL,QAAUA,QAAQM,QAAQ,kBAAmB,IAAIA,QAAQ,UAAW,IAGpEN,QAAUA,QAAQO,UAAU,EAAGL,UAAY,GACvCF,QAAQO,UAAUL,UAAY,EAAGE,UAAUE,QAAQ,OAAQ,QAAQA,QAAQ,SAAU,IACrFN,QAAQO,UAAUH,UACtBL,QAAQE,UAAYD,QAjGZQ,CAAqBT,SAGjBA,QAAQU,YAAYC,QAAU,KAE9BC,cAAcZ,QAAQa,IAAMb,QAAQE,UACpCY,UAAUd,SACVA,QAAQe,cAAcC,mBAAmB,YAAa,OACtDC,QAAQjB,QAAQa,IAAIK,aAAa,WAAY,SAG7CD,QAAQjB,QAAQa,IAAIM,MAAMC,QAAU,wCAMhC,SAAU,CAAC,WAAY,aAGvCC;;;;;;;;;;;;MAvCEvB,gBAAkBwB,SAASC,uBAAuB,sBAClDN,QAAUK,SAASC,uBAAuB,uBAC1CX,cAAgB,GAEhBY,kBACO,CACLC,cAAe,6DA0CdX,UAAUd,aACX0B,KAAO1B,QAAQU,YACfiB,MAAQ,SACiB,KAAtBD,KAAKE,OAAOD,QACfA,QAEJ3B,QAAQE,UAAYwB,KAAKlB,UAAU,EAAEmB,aAMnCN,iBAAmB,KACrBC,SAASD,iBAAiB,SAASQ,OAC3BA,EAAEC,OAAOC,QAAQP,kBAAkBC,eAAgB,KAE/CO,SAAWH,EAAEC,OAAOjB,GACxBf,gBAAgBC,SACXC,UACOA,QAAQa,IAAMmB,WACoC,QAA9Cf,QAAQe,UAAUC,aAAa,aAC/BjC,QAAQE,UAAYU,cAAcoB,UAClCE,mBAAmBF,UAAU,KAE7BlB,UAAUd,SACVkC,mBAAmBF,UAAU,4BAc1CE,mBAAmBP,MAAOQ,YACnB,GAAdA,YACAlB,QAAQU,OAAOjB,kBAAoB,kBAAU,WAAY,UACzDO,QAAQU,OAAOT,aAAa,WAAY,UAExCD,QAAQU,OAAOjB,kBAAoB,kBAAU,WAAY,UACzDO,QAAQU,OAAOT,aAAa,WAAY"} \ No newline at end of file diff --git a/amd/build/timefilter.min.js.map b/amd/build/timefilter.min.js.map index 1763f9d..238ee47 100644 --- a/amd/build/timefilter.min.js.map +++ b/amd/build/timefilter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"timefilter.min.js","sources":["../src/timefilter.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 * Javascript for the time filter\n *\n * This file implements 1 functionality:\n * - Checks, which of the radio buttons is pressed and filters the content based on the time.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant radio buttons.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Define to change the time span, an additional time span and the current time.\nlet currenttime;\nlet timestart;\nlet timeend;\nlet addstarttime;\nlet addendtime;\n\n/**\n * Init function\n */\nexport function init() {\n // Set the current time.\n currenttime = new Date().getTime() / 1000;\n\n // Add event listeners to the all kind of buttons.\n alltimeaddEventListener();\n futuretimeaddEventListener();\n pasttimeaddEventListener();\n}\n\n/**\n * Function to execute the filter\n * @param {int} starttime Start of time span for filtering of the current pressed button\n * @param {int} endtime End of time span for filtering of the current pressed\n * @param {int} addstarttime Start of time span for filtering of an additional radio button.\n * @param {int} addendtime End of time span for filtering of an additional radio button.\n * @param {boolean} buttonstate State of the radio button (true or false)\n */\nfunction executefilter(starttime, endtime, addstarttime, addendtime, buttonstate) {\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.ts_coursefilter_active.ts_letterfilter_active');\n\n // Loop through each letter and hide/show based on radiobutton state.\n letters.forEach(function(letter) {\n\n // Get the created time stamp of each letter.\n let lettertime = letter.querySelector('.townsquareletter_date').id;\n\n // If the radio button is checked and the letter is in the time span, activate it.\n if ((buttonstate && (lettertime >= starttime && lettertime <= endtime)) ||\n (lettertime >= addstarttime && lettertime <= addendtime)) {\n letter.classList.add('ts_timefilter_active'); // Mark the letter as \"active\".\n } else {\n letter.classList.remove('ts_timefilter_active'); // Mark the letter as \"not active\".\n }\n });\n}\n\n/**\n * Function to add event listeners to the all_time button.\n */\nfunction alltimeaddEventListener() {\n alltimebutton.forEach(function(button) {\n button.addEventListener('change', function() {\n // Set the time span to show all letters.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime + convertidtotime(button.id);\n addstarttime = 0;\n addendtime = 0;\n\n // Disable all other radio buttons that filter more specific times.\n futureradiobuttons.forEach(function(futureradiobutton) {\n futureradiobutton.checked = false;\n futureradiobutton.parentNode.classList.remove(\"active\");\n });\n pastradiobuttons.forEach(function(pastradiobutton) {\n pastradiobutton.checked = false;\n pastradiobutton.parentNode.classList.remove(\"active\");\n\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime,addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the future time radio buttons.\n */\nfunction futuretimeaddEventListener() {\n futureradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime;\n timeend = currenttime + convertidtotime(button.id);\n\n // Check if one past time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n pastradiobuttons.forEach(function(pastradiobutton) {\n if (pastradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime - convertidtotime(pastradiobutton.id);\n addendtime = currenttime;\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the past time radio buttons.\n */\nfunction pasttimeaddEventListener() {\n pastradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime;\n\n // Check if one future time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n futureradiobuttons.forEach(function(futureradiobutton) {\n if (futureradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime;\n addendtime = currenttime + convertidtotime(futureradiobutton.id);\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n"],"names":["currenttime","Date","getTime","alltimebutton","forEach","button","addEventListener","timestart","convertidtotime","id","timeend","addstarttime","addendtime","futureradiobuttons","futureradiobutton","checked","parentNode","classList","remove","pastradiobuttons","pastradiobutton","executefilter","contains","document","querySelectorAll","starttime","endtime","buttonstate","letter","lettertime","querySelector","add"],"mappings":"2IAyCO,WAEHA,aAAc,IAAIC,MAAOC,UAAY,IAyCrCC,cAAcC,SAAQ,SAASC,QAC3BA,OAAOC,iBAAiB,UAAU,WAE9BC,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAC/CE,aAAe,EACfC,WAAa,EAGbC,mBAAmBT,SAAQ,SAASU,mBAChCA,kBAAkBC,SAAU,EAC5BD,kBAAkBE,WAAWC,UAAUC,OAAO,aAElDC,iBAAiBf,SAAQ,SAASgB,iBAC9BA,gBAAgBL,SAAU,EAC1BK,gBAAgBJ,WAAWC,UAAUC,OAAO,aAKhDG,cAAcd,UAAWG,QAASC,aAAaC,WAAYP,OAAOU,eAS1EF,mBAAmBT,SAAQ,SAASC,QAChCA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YACZU,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAG/CE,aAAe,EACfC,WAAa,EACbO,iBAAiBf,SAAQ,SAASgB,iBAC1BA,gBAAgBJ,WAAWC,UAAUK,SAAS,YAC9CX,aAAeX,YAAcQ,gBAAgBY,gBAAgBX,IAC7DG,WAAaZ,gBAKrBqB,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU,eAS3EI,iBAAiBf,SAAQ,SAASC,QAC9BA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAGVW,aAAe,EACfC,WAAa,EACbC,mBAAmBT,SAAQ,SAASU,mBAC5BA,kBAAkBE,WAAWC,UAAUK,SAAS,YAChDX,aAAeX,YACfY,WAAaZ,YAAcQ,gBAAgBM,kBAAkBL,QAKrEY,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU;;;;;;;;;;;AA7I/E,MAAMZ,cAAgBoB,SAASC,iBAAiB,uBAC1CX,mBAAqBU,SAASC,iBAAiB,0BAC/CL,iBAAmBI,SAASC,iBAAiB,wBAGnD,IAAIxB,YACAO,UACAG,QACAC,aACAC,WAuBJ,SAASS,cAAcI,UAAWC,QAASf,aAAcC,WAAYe,aAGjDJ,SAASC,iBAAiB,oEAGlCpB,SAAQ,SAASwB,QAGrB,IAAIC,WAAaD,OAAOE,cAAc,0BAA0BrB,GAG3DkB,aAAgBE,YAAcJ,WAAaI,YAAcH,SACzDG,YAAclB,cAAgBkB,YAAcjB,WAC7CgB,OAAOX,UAAUc,IAAI,wBAErBH,OAAOX,UAAUC,OAAO,2BAuGpC,SAASV,gBAAgBC,IACrB,OAAOA,IACH,IAAK,cACD,OAAO,SACX,IAAK,uBACL,IAAK,uBACD,OAAO,OACX,IAAK,wBACL,IAAK,wBACD,OAAO,MACX,IAAK,oBACL,IAAK,oBACD,OAAO,OACX,IAAK,qBACL,IAAK,qBACD,OAAO,QAElB"} \ No newline at end of file +{"version":3,"file":"timefilter.min.js","sources":["../src/timefilter.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 * Javascript for the time filter\n *\n * This file implements 1 functionality:\n * - Checks, which of the radio buttons is pressed and filters the content based on the time.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant radio buttons.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Define to change the time span, an additional time span and the current time.\nlet currenttime;\nlet timestart;\nlet timeend;\nlet addstarttime;\nlet addendtime;\n\n/**\n * Init function\n */\nexport function init() {\n // Set the current time.\n currenttime = new Date().getTime() / 1000;\n\n // Add event listeners to the all kind of buttons.\n alltimeaddEventListener();\n futuretimeaddEventListener();\n pasttimeaddEventListener();\n}\n\n/**\n * Function to execute the filter\n * @param {int} starttime Start of time span for filtering of the current pressed button\n * @param {int} endtime End of time span for filtering of the current pressed\n * @param {int} addstarttime Start of time span for filtering of an additional radio button.\n * @param {int} addendtime End of time span for filtering of an additional radio button.\n * @param {boolean} buttonstate State of the radio button (true or false)\n */\nfunction executefilter(starttime, endtime, addstarttime, addendtime, buttonstate) {\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.ts_coursefilter_active.ts_letterfilter_active');\n\n // Loop through each letter and hide/show based on radiobutton state.\n letters.forEach(function(letter) {\n\n // Get the created time stamp of each letter.\n let lettertime = letter.querySelector('.townsquareletter_date').id;\n\n // If the radio button is checked and the letter is in the time span, activate it.\n if ((buttonstate && (lettertime >= starttime && lettertime <= endtime)) ||\n (lettertime >= addstarttime && lettertime <= addendtime)) {\n letter.classList.add('ts_timefilter_active'); // Mark the letter as \"active\".\n } else {\n letter.classList.remove('ts_timefilter_active'); // Mark the letter as \"not active\".\n }\n });\n}\n\n/**\n * Function to add event listeners to the all_time button.\n */\nfunction alltimeaddEventListener() {\n alltimebutton.forEach(function(button) {\n button.addEventListener('change', function() {\n // Set the time span to show all letters.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime + convertidtotime(button.id);\n addstarttime = 0;\n addendtime = 0;\n\n // Disable all other radio buttons that filter more specific times.\n futureradiobuttons.forEach(function(futureradiobutton) {\n futureradiobutton.checked = false;\n futureradiobutton.parentNode.classList.remove(\"active\");\n });\n pastradiobuttons.forEach(function(pastradiobutton) {\n pastradiobutton.checked = false;\n pastradiobutton.parentNode.classList.remove(\"active\");\n\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime,addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the future time radio buttons.\n */\nfunction futuretimeaddEventListener() {\n futureradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime;\n timeend = currenttime + convertidtotime(button.id);\n\n // Check if one past time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n pastradiobuttons.forEach(function(pastradiobutton) {\n if (pastradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime - convertidtotime(pastradiobutton.id);\n addendtime = currenttime;\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the past time radio buttons.\n */\nfunction pasttimeaddEventListener() {\n pastradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime;\n\n // Check if one future time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n futureradiobuttons.forEach(function(futureradiobutton) {\n if (futureradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime;\n addendtime = currenttime + convertidtotime(futureradiobutton.id);\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n"],"names":["currenttime","Date","getTime","alltimebutton","forEach","button","addEventListener","timestart","convertidtotime","id","timeend","addstarttime","addendtime","futureradiobuttons","futureradiobutton","checked","parentNode","classList","remove","pastradiobuttons","pastradiobutton","executefilter","contains","document","querySelectorAll","starttime","endtime","buttonstate","letter","lettertime","querySelector","add"],"mappings":"sJA2CIA,aAAc,IAAIC,MAAOC,UAAY,IAyCrCC,cAAcC,SAAQ,SAASC,QAC3BA,OAAOC,iBAAiB,UAAU,WAE9BC,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAC/CE,aAAe,EACfC,WAAa,EAGbC,mBAAmBT,SAAQ,SAASU,mBAChCA,kBAAkBC,SAAU,EAC5BD,kBAAkBE,WAAWC,UAAUC,OAAO,aAElDC,iBAAiBf,SAAQ,SAASgB,iBAC9BA,gBAAgBL,SAAU,EAC1BK,gBAAgBJ,WAAWC,UAAUC,OAAO,aAKhDG,cAAcd,UAAWG,QAASC,aAAaC,WAAYP,OAAOU,eAS1EF,mBAAmBT,SAAQ,SAASC,QAChCA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YACZU,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAG/CE,aAAe,EACfC,WAAa,EACbO,iBAAiBf,SAAQ,SAASgB,iBAC1BA,gBAAgBJ,WAAWC,UAAUK,SAAS,YAC9CX,aAAeX,YAAcQ,gBAAgBY,gBAAgBX,IAC7DG,WAAaZ,gBAKrBqB,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU,eAS3EI,iBAAiBf,SAAQ,SAASC,QAC9BA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAGVW,aAAe,EACfC,WAAa,EACbC,mBAAmBT,SAAQ,SAASU,mBAC5BA,kBAAkBE,WAAWC,UAAUK,SAAS,YAChDX,aAAeX,YACfY,WAAaZ,YAAcQ,gBAAgBM,kBAAkBL,QAKrEY,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU;;;;;;;;;;;MA7IzEZ,cAAgBoB,SAASC,iBAAiB,uBAC1CX,mBAAqBU,SAASC,iBAAiB,0BAC/CL,iBAAmBI,SAASC,iBAAiB,4BAG/CxB,YACAO,UACAG,QACAC,aACAC,oBAuBKS,cAAcI,UAAWC,QAASf,aAAcC,WAAYe,aAGjDJ,SAASC,iBAAiB,oEAGlCpB,SAAQ,SAASwB,YAGjBC,WAAaD,OAAOE,cAAc,0BAA0BrB,GAG3DkB,aAAgBE,YAAcJ,WAAaI,YAAcH,SACzDG,YAAclB,cAAgBkB,YAAcjB,WAC7CgB,OAAOX,UAAUc,IAAI,wBAErBH,OAAOX,UAAUC,OAAO,oCAuG3BV,gBAAgBC,WACdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM"} \ No newline at end of file diff --git a/amd/build/usersettings_save.min.js b/amd/build/usersettings_save.min.js index 4932bde..4e4ccbb 100644 --- a/amd/build/usersettings_save.min.js +++ b/amd/build/usersettings_save.min.js @@ -8,6 +8,6 @@ define("block_townsquare/usersettings_save",["exports","core/ajax"],(function(_e * @module block_townsquare/timefilter * @copyright 2024 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,settingsfromdb){settingsfromdb&&function(settingsfromdb){let futurebuttonid=converttimetoid(settingsfromdb.timefilterfuture,!0),pastbuttonid=converttimetoid(settingsfromdb.timefilterpast,!1);"ts_time_all"!==futurebuttonid?(futureradiobuttons.forEach((function(button){button.id===futurebuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change")),alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))})),pastradiobuttons.forEach((function(button){button.id===pastbuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change")),alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))}))):alltimebutton.forEach((function(button){button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change"))}));checkboxes.forEach((function(checkbox){let basiclettercheck="basicletter"===checkbox.id&&""===settingsfromdb.basicletter,completionlettercheck="completionletter"===checkbox.id&&"0"===settingsfromdb.completionletter,postlettercheck="postletter"===checkbox.id&&"0"===settingsfromdb.postletter;(basiclettercheck||completionlettercheck||postlettercheck)&&checkbox.click()}))}(settingsfromdb);savebutton.addEventListener("click",(async function(){let timespans=function(){let settings={timepast:0,timefuture:0},settingsset=!1;if(alltimebutton.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id),settings.timefuture=convertidtotime(button.id),settingsset=!0)})),settingsset)return settings;return futureradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timefuture=convertidtotime(button.id))})),pastradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id))})),settings}(),letterfilter=function(){let settings={basicletter:0,completionletter:0,postletter:0};return checkboxes.forEach((function(checkbox){if(checkbox.checked)switch(checkbox.id){case"basicletter":settings.basicletter=1;break;case"completionletter":settings.completionletter=1;break;case"postletter":settings.postletter=1}})),settings}();await async function(userid,timefilterpast,timefilterfuture,basicletter,completionletter,postletter){let result;result=await _ajax.default.call([{methodname:"block_townsquare_record_usersettings",args:{userid:parseInt(userid),timefilterpast:timefilterpast,timefilterfuture:timefilterfuture,basicletter:basicletter,completionletter:completionletter,postletter:postletter}}]);let el=document.getElementById("ts_usersettings_successlabel");el.style.display="block",el.style.opacity=1,el.fadeOutTimer&&clearInterval(el.fadeOutTimer);return setTimeout((function(){el.fadeOutTimer=setInterval((function(){el.style.opacity>.4?el.style.opacity-=.1:el.style.opacity>0?el.style.opacity-=.2:(clearInterval(el.fadeOutTimer),el.style.display="none")}),100)}),3e3),result}(userid,timespans.timepast,timespans.timefuture,letterfilter.basicletter,letterfilter.completionletter,letterfilter.postletter)}))},_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};const savebutton=document.getElementById("ts_usersettings_savebutton"),alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button"),checkboxes=document.querySelectorAll(".ts_letter_checkbox");function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}function converttimetoid(time,future){switch(time){case"15778463":return"ts_time_all";case"172800":return future?"ts_time_next_twodays":"ts_time_past_twodays";case"432000":return future?"ts_time_next_fivedays":"ts_time_last_fivedays";case"604800":return future?"ts_time_next_week":"ts_time_last_week";case"2592000":return future?"ts_time_next_month":"ts_time_last_month"}}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,settingsfromdb){settingsfromdb&&function(settingsfromdb){let futurebuttonid=converttimetoid(settingsfromdb.timefilterfuture,!0),pastbuttonid=converttimetoid(settingsfromdb.timefilterpast,!1);"ts_time_all"!==futurebuttonid?(futureradiobuttons.forEach((function(button){button.id===futurebuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change")),alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))})),pastradiobuttons.forEach((function(button){button.id===pastbuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change")),alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))}))):alltimebutton.forEach((function(button){button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change"))}));checkboxes.forEach((function(checkbox){let basiclettercheck="basicletter"===checkbox.id&&""===settingsfromdb.basicletter,completionlettercheck="completionletter"===checkbox.id&&"0"===settingsfromdb.completionletter,postlettercheck="postletter"===checkbox.id&&"0"===settingsfromdb.postletter;(basiclettercheck||completionlettercheck||postlettercheck)&&checkbox.click()}))}(settingsfromdb);savebutton.addEventListener("click",(async function(){let timespans=function(){let settings={timepast:0,timefuture:0},settingsset=!1;if(alltimebutton.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id),settings.timefuture=convertidtotime(button.id),settingsset=!0)})),settingsset)return settings;return futureradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timefuture=convertidtotime(button.id))})),pastradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id))})),settings}(),letterfilter=function(){let settings={basicletter:0,completionletter:0,postletter:0};return checkboxes.forEach((function(checkbox){if(checkbox.checked)switch(checkbox.id){case"basicletter":settings.basicletter=1;break;case"completionletter":settings.completionletter=1;break;case"postletter":settings.postletter=1}})),settings}();await async function(userid,timefilterpast,timefilterfuture,basicletter,completionletter,postletter){let result;result=await _ajax.default.call([{methodname:"block_townsquare_record_usersettings",args:{userid:parseInt(userid),timefilterpast:timefilterpast,timefilterfuture:timefilterfuture,basicletter:basicletter,completionletter:completionletter,postletter:postletter,success:function(){console.log("Settings saved.")}}}]);let el=document.getElementById("ts_usersettings_successlabel");el.style.display="block",el.style.opacity=1,el.fadeOutTimer&&clearInterval(el.fadeOutTimer);return setTimeout((function(){el.fadeOutTimer=setInterval((function(){el.style.opacity>.4?el.style.opacity-=.1:el.style.opacity>0?el.style.opacity-=.2:(clearInterval(el.fadeOutTimer),el.style.display="none")}),100)}),3e3),result}(userid,timespans.timepast,timespans.timefuture,letterfilter.basicletter,letterfilter.completionletter,letterfilter.postletter)}))},_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};const savebutton=document.getElementById("ts_usersettings_savebutton"),alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button"),checkboxes=document.querySelectorAll(".ts_letter_checkbox");function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}function converttimetoid(time,future){switch(time){case"15778463":return"ts_time_all";case"172800":return future?"ts_time_next_twodays":"ts_time_past_twodays";case"432000":return future?"ts_time_next_fivedays":"ts_time_last_fivedays";case"604800":return future?"ts_time_next_week":"ts_time_last_week";case"2592000":return future?"ts_time_next_month":"ts_time_last_month"}}})); //# sourceMappingURL=usersettings_save.min.js.map \ No newline at end of file diff --git a/amd/build/usersettings_save.min.js.map b/amd/build/usersettings_save.min.js.map index db58f32..a034acd 100644 --- a/amd/build/usersettings_save.min.js.map +++ b/amd/build/usersettings_save.min.js.map @@ -1 +1 @@ -{"version":3,"file":"usersettings_save.min.js","sources":["../src/usersettings_save.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 * Javascript to save the user settings in the database.\n *\n * This file implements 1 functionality:\n * - If the \"save settings\" button is pressed, store the settings in the database.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n// Get the save button for the user settings.\nconst savebutton = document.getElementById('ts_usersettings_savebutton');\n\n// Get the buttons from the time filter.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Get the checkboxes from the letter filter.\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n *\n * @param {number} userid The id of the current user.\n * @param {object} settingsfromdb The settings from the database, if there are any.\n */\nexport function init(userid, settingsfromdb) {\n // When the page is loaded, set the settings from the database.\n if (settingsfromdb) {\n executeusersettings(settingsfromdb);\n }\n\n // Add event listener to the save button.\n savebutton.addEventListener('click', async function() {\n\n // First step: collect the current settings.\n // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes.\n let timespans = collecttimefiltersettings();\n let letterfilter = collectletterfiltersettings();\n\n // Second step: store the usersettings in the database.\n await saveusersettings(userid, timespans['timepast'], timespans['timefuture'], letterfilter['basicletter'],\n letterfilter['completionletter'], letterfilter['postletter']);\n });\n}\n\n/**\n * Function to save the user settings in the database.\n * @param {number} userid\n * @param {number} timefilterpast\n * @param {number} timefilterfuture\n * @param {number} basicletter\n * @param {number} completionletter\n * @param {number} postletter\n * @returns {Promise<*>}\n */\nasync function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) {\n let result ;\n result = await Ajax.call([{\n methodname: 'block_townsquare_record_usersettings',\n args: {\n userid: parseInt(userid),\n timefilterpast: timefilterpast,\n timefilterfuture: timefilterfuture,\n basicletter: basicletter,\n completionletter: completionletter,\n postletter: postletter\n },\n }]);\n\n // Show a success message.\n let el = document.getElementById('ts_usersettings_successlabel');\n el.style.display = 'block';\n el.style.opacity = 1.0;\n\n // Start a new setInterval timer to gradually fade out the label.\n if (el.fadeOutTimer) {\n clearInterval(el.fadeOutTimer);\n }\n setTimeout(function () {\n el.fadeOutTimer = setInterval(function () {\n if (el.style.opacity > 0.4) {\n el.style.opacity -= 0.1;\n } else if (el.style.opacity > 0) {\n el.style.opacity -= 0.2;\n } else {\n // Once opacity reaches 0, clear the timer and hide the label.\n clearInterval(el.fadeOutTimer);\n el.style.display = 'none';\n }\n }, 100);\n }, 3000);\n return result;\n}\n\n/**\n * Function to execute existing user settings when loading the townsquare.\n * @param {Object} settingsfromdb\n */\nfunction executeusersettings(settingsfromdb) {\n\n // First step: set the time filter settings.\n // Change the time into the correct radio button id.\n let futurebuttonid = converttimetoid(settingsfromdb['timefilterfuture'], true);\n let pastbuttonid = converttimetoid(settingsfromdb['timefilterpast'], false);\n\n // If the time span is a combination of past and future, go through the two radio buttons and activate the filter.\n if (futurebuttonid !== \"ts_time_all\") {\n futureradiobuttons.forEach(function(button) {\n if (button.id === futurebuttonid) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n }\n });\n pastradiobuttons.forEach(function(button) {\n if (button.id === pastbuttonid) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n }\n });\n } else {\n // If the time span is set to all time, activate the all time button.\n alltimebutton.forEach(function(button) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n });\n }\n\n // Second step: set the letter filter settings.\n // Per default all checkboxes are checked. If the setting is 0, uncheck the checkbox.\n checkboxes.forEach(function(checkbox) {\n let basiclettercheck = checkbox.id === 'basicletter' && settingsfromdb['basicletter'] === \"\";\n let completionlettercheck = checkbox.id === 'completionletter' && settingsfromdb['completionletter'] === \"0\";\n let postlettercheck = checkbox.id === 'postletter' && settingsfromdb['postletter'] === \"0\";\n\n if (basiclettercheck || completionlettercheck || postlettercheck) {\n checkbox.click();\n }\n });\n}\n\n/**\n * Function to collect the letter filter settings.\n * @returns {{basicletter: number, completionletter: number, postletter: number}}\n */\nfunction collectletterfiltersettings() {\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\n\n checkboxes.forEach(function(checkbox) {\n if (checkbox.checked) {\n switch(checkbox.id) {\n case \"basicletter\":\n settings['basicletter'] = 1;\n break;\n case \"completionletter\":\n settings['completionletter'] = 1;\n break;\n case \"postletter\":\n settings['postletter'] = 1;\n break;\n\n }\n }\n });\n // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit.\n return settings;\n}\n\n/**\n * Function to collect the time filter settings.\n * @returns {{timepast: number, timefuture: number}}\n */\nfunction collecttimefiltersettings() {\n let settings = { timepast: 0, timefuture: 0};\n let settingsset = false;\n\n // Get the relevant time spans of the time filter.\n // Check if the alltimebutton is set.\n alltimebutton.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n settings['timefuture'] = convertidtotime(button.id);\n settingsset = true;\n }\n });\n\n if (settingsset) {\n return settings;\n }\n\n // If the alltimebutton is not set, check which of the future/past buttons is set.\n futureradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timefuture'] = convertidtotime(button.id);\n }\n });\n\n pastradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n }\n });\n return settings;\n}\n\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n // TODO: Please use global functions if possible.\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n\n/**\n * Function to convert the time span to a radio button id.\n * @param {string} time\n * @param {boolean} future\n * @returns {string}\n */\nfunction converttimetoid(time, future) {\n switch (time) {\n case \"15778463\":\n return \"ts_time_all\";\n case \"172800\":\n if (future) {\n return \"ts_time_next_twodays\";\n }\n return \"ts_time_past_twodays\";\n case \"432000\":\n if (future) {\n return \"ts_time_next_fivedays\";\n }\n return \"ts_time_last_fivedays\";\n case \"604800\":\n if (future) {\n return \"ts_time_next_week\";\n }\n return \"ts_time_last_week\";\n case \"2592000\":\n if (future) {\n return \"ts_time_next_month\";\n\n }\n return \"ts_time_last_month\";\n }\n}\n"],"names":["obj","userid","settingsfromdb","futurebuttonid","converttimetoid","pastbuttonid","futureradiobuttons","forEach","button","id","parentNode","classList","add","checked","dispatchEvent","Event","alltimebutton","remove","pastradiobuttons","checkboxes","checkbox","basiclettercheck","completionlettercheck","postlettercheck","click","executeusersettings","savebutton","addEventListener","async","timespans","settings","timepast","timefuture","settingsset","contains","convertidtotime","collecttimefiltersettings","letterfilter","basicletter","completionletter","postletter","collectletterfiltersettings","timefilterpast","timefilterfuture","result","Ajax","call","methodname","args","parseInt","el","document","getElementById","style","display","opacity","fadeOutTimer","clearInterval","setTimeout","setInterval","saveusersettings","_ajax","__esModule","default","querySelectorAll","time","future"],"mappings":"8FA0B6B,IAAAA;;;;;;;;;;2EAmBtB,SAAcC,OAAQC,gBAErBA,gBAuER,SAA6BA,gBAIzB,IAAIC,eAAiBC,gBAAgBF,eAAiC,kBAAG,GACrEG,aAAeD,gBAAgBF,eAA+B,gBAAG,GAG9C,gBAAnBC,gBACAG,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOC,KAAON,iBACdK,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,iBAItDC,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOC,KAAOJ,eACdG,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,kBAMtDD,cAAcT,SAAQ,SAASC,QAC3BA,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,cAMvCI,WAAWZ,SAAQ,SAASa,UACxB,IAAIC,iBAAmC,gBAAhBD,SAASX,IAA0D,KAAlCP,eAA4B,YAChFoB,sBAAwC,qBAAhBF,SAASX,IAAoE,MAAvCP,eAAiC,iBAC/FqB,gBAAkC,eAAhBH,SAASX,IAAwD,MAAjCP,eAA2B,YAE7EmB,kBAAoBC,uBAAyBC,kBAC7CH,SAASI,WAtHbC,CAAoBvB,gBAIxBwB,WAAWC,iBAAiB,SAASC,iBAIjC,IAAIC,UAkJZ,WACI,IAAIC,SAAW,CAAEC,SAAU,EAAGC,WAAY,GACtCC,aAAc,EAalB,GATAjB,cAAcT,SAAQ,SAASC,QACxBA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAmB,SAAIK,gBAAgB3B,OAAOC,IAC9CqB,SAAqB,WAAIK,gBAAgB3B,OAAOC,IAChDwB,aAAc,MAIjBA,YACA,OAAOH,SAiBX,OAbAxB,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAqB,WAAIK,gBAAgB3B,OAAOC,QAIxDS,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAmB,SAAIK,gBAAgB3B,OAAOC,QAG/CqB,SAnLaM,GACZC,aAsHZ,WACI,IAAIP,SAAW,CAACQ,YAAe,EAAGC,iBAAoB,EAAGC,WAAc,GAmBvE,OAjBArB,WAAWZ,SAAQ,SAASa,UACxB,GAAIA,SAASP,QACT,OAAOO,SAASX,IACZ,IAAK,cACDqB,SAAsB,YAAI,EAC1B,MACJ,IAAK,mBACDA,SAA2B,iBAAI,EAC/B,MACJ,IAAK,aACDA,SAAqB,WAAI,MAOlCA,SA1IgBW,SAkB3Bb,eAAgC3B,OAAQyC,eAAgBC,iBAAkBL,YAAaC,iBAAkBC,YACrG,IAAII,OACJA,aAAeC,cAAKC,KAAK,CAAC,CACtBC,WAAY,uCACZC,KAAM,CACF/C,OAAQgD,SAAShD,QACjByC,eAAgBA,eAChBC,iBAAkBA,iBAClBL,YAAaA,YACbC,iBAAkBA,iBAClBC,WAAYA,eAKpB,IAAIU,GAAKC,SAASC,eAAe,gCACjCF,GAAGG,MAAMC,QAAU,QACnBJ,GAAGG,MAAME,QAAU,EAGfL,GAAGM,cACHC,cAAcP,GAAGM,cAerB,OAbAE,YAAW,WACPR,GAAGM,aAAeG,aAAY,WACtBT,GAAGG,MAAME,QAAU,GACnBL,GAAGG,MAAME,SAAW,GACbL,GAAGG,MAAME,QAAU,EAC1BL,GAAGG,MAAME,SAAW,IAGpBE,cAAcP,GAAGM,cACjBN,GAAGG,MAAMC,QAAU,UAExB,OACJ,KACIV,OAnDGgB,CAAiB3D,OAAQ4B,UAAoB,SAAGA,UAAsB,WAAGQ,aAA0B,YAClFA,aAA+B,iBAAGA,aAAyB,gBAnC1FwB,OAA6B7D,IAA7B6D,QAA6B7D,IAAA8D,WAAA9D,KAAA+D,QAAA/D,KAG7B,MAAM0B,WAAayB,SAASC,eAAe,8BAGrCpC,cAAgBmC,SAASa,iBAAiB,uBAC1C1D,mBAAqB6C,SAASa,iBAAiB,0BAC/C9C,iBAAmBiC,SAASa,iBAAiB,wBAG7C7C,WAAagC,SAASa,iBAAiB,uBA+M7C,SAAS7B,gBAAgB1B,IAErB,OAAOA,IACH,IAAK,cACD,OAAO,SACX,IAAK,uBACL,IAAK,uBACD,OAAO,OACX,IAAK,wBACL,IAAK,wBACD,OAAO,MACX,IAAK,oBACL,IAAK,oBACD,OAAO,OACX,IAAK,qBACL,IAAK,qBACD,OAAO,QAUnB,SAASL,gBAAgB6D,KAAMC,QAC3B,OAAQD,MACJ,IAAK,WACD,MAAO,cACX,IAAK,SACD,OAAIC,OACO,uBAEJ,uBACX,IAAK,SACD,OAAIA,OACO,wBAEJ,wBACX,IAAK,SACD,OAAIA,OACO,oBAEJ,oBACX,IAAK,UACD,OAAIA,OACO,qBAGJ,sBAElB"} \ No newline at end of file +{"version":3,"file":"usersettings_save.min.js","sources":["../src/usersettings_save.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 * Javascript to save the user settings in the database.\n *\n * This file implements 1 functionality:\n * - If the \"save settings\" button is pressed, store the settings in the database.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n// Get the save button for the user settings.\nconst savebutton = document.getElementById('ts_usersettings_savebutton');\n\n// Get the buttons from the time filter.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Get the checkboxes from the letter filter.\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n *\n * @param {number} userid The id of the current user.\n * @param {object} settingsfromdb The settings from the database, if there are any.\n */\nexport function init(userid, settingsfromdb) {\n // When the page is loaded, set the settings from the database.\n if (settingsfromdb) {\n executeusersettings(settingsfromdb);\n }\n\n // Add event listener to the save button.\n savebutton.addEventListener('click', async function() {\n\n // First step: collect the current settings.\n // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes.\n let timespans = collecttimefiltersettings();\n let letterfilter = collectletterfiltersettings();\n\n // Second step: store the usersettings in the database.\n await saveusersettings(userid, timespans['timepast'], timespans['timefuture'], letterfilter['basicletter'],\n letterfilter['completionletter'], letterfilter['postletter']);\n });\n}\n\n/**\n * Function to save the user settings in the database.\n * @param {number} userid\n * @param {number} timefilterpast\n * @param {number} timefilterfuture\n * @param {number} basicletter\n * @param {number} completionletter\n * @param {number} postletter\n * @returns {Promise<*>}\n */\nasync function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) {\n let result;\n result = await Ajax.call([{\n methodname: 'block_townsquare_record_usersettings',\n args: {\n userid: parseInt(userid),\n timefilterpast: timefilterpast,\n timefilterfuture: timefilterfuture,\n basicletter: basicletter,\n completionletter: completionletter,\n postletter: postletter,\n success: function() {\n console.log('Settings saved.');\n },\n },\n }]);\n // Show a success message.\n let el = document.getElementById('ts_usersettings_successlabel');\n el.style.display = 'block';\n el.style.opacity = 1.0;\n\n // Start a new setInterval timer to gradually fade out the label.\n if (el.fadeOutTimer) {\n clearInterval(el.fadeOutTimer);\n }\n setTimeout(function () {\n el.fadeOutTimer = setInterval(function () {\n if (el.style.opacity > 0.4) {\n el.style.opacity -= 0.1;\n } else if (el.style.opacity > 0) {\n el.style.opacity -= 0.2;\n } else {\n // Once opacity reaches 0, clear the timer and hide the label.\n clearInterval(el.fadeOutTimer);\n el.style.display = 'none';\n }\n }, 100);\n }, 3000);\n return result;\n}\n\n/**\n * Function to execute existing user settings when loading the townsquare.\n * @param {Object} settingsfromdb\n */\nfunction executeusersettings(settingsfromdb) {\n\n // First step: set the time filter settings.\n // Change the time into the correct radio button id.\n let futurebuttonid = converttimetoid(settingsfromdb['timefilterfuture'], true);\n let pastbuttonid = converttimetoid(settingsfromdb['timefilterpast'], false);\n\n // If the time span is a combination of past and future, go through the two radio buttons and activate the filter.\n if (futurebuttonid !== \"ts_time_all\") {\n futureradiobuttons.forEach(function(button) {\n if (button.id === futurebuttonid) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n }\n });\n pastradiobuttons.forEach(function(button) {\n if (button.id === pastbuttonid) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n }\n });\n } else {\n // If the time span is set to all time, activate the all time button.\n alltimebutton.forEach(function(button) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n });\n }\n\n // Second step: set the letter filter settings.\n // Per default all checkboxes are checked. If the setting is 0, uncheck the checkbox.\n checkboxes.forEach(function(checkbox) {\n let basiclettercheck = checkbox.id === 'basicletter' && settingsfromdb['basicletter'] === \"\";\n let completionlettercheck = checkbox.id === 'completionletter' && settingsfromdb['completionletter'] === \"0\";\n let postlettercheck = checkbox.id === 'postletter' && settingsfromdb['postletter'] === \"0\";\n\n if (basiclettercheck || completionlettercheck || postlettercheck) {\n checkbox.click();\n }\n });\n}\n\n/**\n * Function to collect the letter filter settings.\n * @returns {{basicletter: number, completionletter: number, postletter: number}}\n */\nfunction collectletterfiltersettings() {\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\n\n checkboxes.forEach(function(checkbox) {\n if (checkbox.checked) {\n switch(checkbox.id) {\n case \"basicletter\":\n settings['basicletter'] = 1;\n break;\n case \"completionletter\":\n settings['completionletter'] = 1;\n break;\n case \"postletter\":\n settings['postletter'] = 1;\n break;\n\n }\n }\n });\n // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit.\n return settings;\n}\n\n/**\n * Function to collect the time filter settings.\n * @returns {{timepast: number, timefuture: number}}\n */\nfunction collecttimefiltersettings() {\n let settings = { timepast: 0, timefuture: 0};\n let settingsset = false;\n\n // Get the relevant time spans of the time filter.\n // Check if the alltimebutton is set.\n alltimebutton.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n settings['timefuture'] = convertidtotime(button.id);\n settingsset = true;\n }\n });\n\n if (settingsset) {\n return settings;\n }\n\n // If the alltimebutton is not set, check which of the future/past buttons is set.\n futureradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timefuture'] = convertidtotime(button.id);\n }\n });\n\n pastradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n }\n });\n return settings;\n}\n\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n // TODO: Please use global functions if possible.\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n\n/**\n * Function to convert the time span to a radio button id.\n * @param {string} time\n * @param {boolean} future\n * @returns {string}\n */\nfunction converttimetoid(time, future) {\n switch (time) {\n case \"15778463\":\n return \"ts_time_all\";\n case \"172800\":\n if (future) {\n return \"ts_time_next_twodays\";\n }\n return \"ts_time_past_twodays\";\n case \"432000\":\n if (future) {\n return \"ts_time_next_fivedays\";\n }\n return \"ts_time_last_fivedays\";\n case \"604800\":\n if (future) {\n return \"ts_time_next_week\";\n }\n return \"ts_time_last_week\";\n case \"2592000\":\n if (future) {\n return \"ts_time_next_month\";\n\n }\n return \"ts_time_last_month\";\n }\n}\n"],"names":["userid","settingsfromdb","futurebuttonid","converttimetoid","pastbuttonid","futureradiobuttons","forEach","button","id","parentNode","classList","add","checked","dispatchEvent","Event","alltimebutton","remove","pastradiobuttons","checkboxes","checkbox","basiclettercheck","completionlettercheck","postlettercheck","click","executeusersettings","savebutton","addEventListener","async","timespans","settings","timepast","timefuture","settingsset","contains","convertidtotime","collecttimefiltersettings","letterfilter","collectletterfiltersettings","timefilterpast","timefilterfuture","basicletter","completionletter","postletter","result","Ajax","call","methodname","args","parseInt","success","console","log","el","document","getElementById","style","display","opacity","fadeOutTimer","clearInterval","setTimeout","setInterval","saveusersettings","querySelectorAll","time","future"],"mappings":";;;;;;;;;;oFA6CqBA,OAAQC,gBAErBA,yBAyEqBA,oBAIrBC,eAAiBC,gBAAgBF,eAAc,kBAAsB,GACrEG,aAAeD,gBAAgBF,eAAc,gBAAoB,GAG9C,gBAAnBC,gBACAG,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOC,KAAON,iBACdK,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,iBAItDC,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOC,KAAOJ,eACdG,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,kBAMtDD,cAAcT,SAAQ,SAASC,QAC3BA,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,cAMvCI,WAAWZ,SAAQ,SAASa,cACpBC,iBAAmC,gBAAhBD,SAASX,IAA0D,KAAlCP,eAAc,YAClEoB,sBAAwC,qBAAhBF,SAASX,IAAoE,MAAvCP,eAAc,iBAC5EqB,gBAAkC,eAAhBH,SAASX,IAAwD,MAAjCP,eAAc,YAEhEmB,kBAAoBC,uBAAyBC,kBAC7CH,SAASI,WAxHbC,CAAoBvB,gBAIxBwB,WAAWC,iBAAiB,SAASC,qBAI7BC,yBAqJJC,SAAW,CAAEC,SAAU,EAAGC,WAAY,GACtCC,aAAc,KAIlBjB,cAAcT,SAAQ,SAASC,QACxBA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgB3B,OAAOC,IAC9CqB,SAAQ,WAAiBK,gBAAgB3B,OAAOC,IAChDwB,aAAc,MAIjBA,mBACOH,gBAIXxB,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,WAAiBK,gBAAgB3B,OAAOC,QAIxDS,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgB3B,OAAOC,QAG/CqB,SArLaM,GACZC,4BAyHJP,SAAW,aAAgB,mBAAuB,aAAiB,UAEvEX,WAAWZ,SAAQ,SAASa,aACpBA,SAASP,eACFO,SAASX,QACP,cACDqB,SAAQ,YAAkB,YAEzB,mBACDA,SAAQ,iBAAuB,YAE9B,aACDA,SAAQ,WAAiB,MAOlCA,SA5IgBQ,wBAkBKrC,OAAQsC,eAAgBC,iBAAkBC,YAAaC,iBAAkBC,gBACjGC,OACJA,aAAeC,cAAKC,KAAK,CAAC,CACtBC,WAAY,uCACZC,KAAM,CACF/C,OAAQgD,SAAShD,QACjBsC,eAAgBA,eAChBC,iBAAkBA,iBAClBC,YAAaA,YACbC,iBAAkBA,iBAClBC,WAAYA,WACZO,QAAS,WACLC,QAAQC,IAAI,4BAKpBC,GAAKC,SAASC,eAAe,gCACjCF,GAAGG,MAAMC,QAAU,QACnBJ,GAAGG,MAAME,QAAU,EAGfL,GAAGM,cACHC,cAAcP,GAAGM,qBAErBE,YAAW,WACPR,GAAGM,aAAeG,aAAY,WACtBT,GAAGG,MAAME,QAAU,GACnBL,GAAGG,MAAME,SAAW,GACbL,GAAGG,MAAME,QAAU,EAC1BL,GAAGG,MAAME,SAAW,IAGpBE,cAAcP,GAAGM,cACjBN,GAAGG,MAAMC,QAAU,UAExB,OACJ,KACIb,OArDGmB,CAAiB9D,OAAQ4B,UAAS,SAAcA,UAAS,WAAgBQ,aAAY,YACpEA,aAAY,iBAAsBA,aAAY,0EAhCvEX,WAAa4B,SAASC,eAAe,8BAGrCvC,cAAgBsC,SAASU,iBAAiB,uBAC1C1D,mBAAqBgD,SAASU,iBAAiB,0BAC/C9C,iBAAmBoC,SAASU,iBAAiB,wBAG7C7C,WAAamC,SAASU,iBAAiB,gCAiNpC7B,gBAAgB1B,WAEdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM,iBAUVL,gBAAgB6D,KAAMC,eACnBD,UACC,iBACM,kBACN,gBACGC,OACO,uBAEJ,2BACN,gBACGA,OACO,wBAEJ,4BACN,gBACGA,OACO,oBAEJ,wBACN,iBACGA,OACO,qBAGJ"} \ No newline at end of file diff --git a/amd/src/usersettings_save.js b/amd/src/usersettings_save.js index 6ba9673..8ccf6b7 100644 --- a/amd/src/usersettings_save.js +++ b/amd/src/usersettings_save.js @@ -74,7 +74,7 @@ export function init(userid, settingsfromdb) { * @returns {Promise<*>} */ async function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) { - let result ; + let result; result = await Ajax.call([{ methodname: 'block_townsquare_record_usersettings', args: { @@ -83,10 +83,12 @@ async function saveusersettings(userid, timefilterpast, timefilterfuture, basicl timefilterfuture: timefilterfuture, basicletter: basicletter, completionletter: completionletter, - postletter: postletter + postletter: postletter, + success: function() { + console.log('Settings saved.'); + }, }, }]); - // Show a success message. let el = document.getElementById('ts_usersettings_successlabel'); el.style.display = 'block'; diff --git a/db/services.php b/db/services.php index cd10d72..6a7ef48 100644 --- a/db/services.php +++ b/db/services.php @@ -26,9 +26,8 @@ $functions = [ 'block_townsquare_record_usersettings' => [ - 'classname' => 'block_townsquare_external', 'classpath' => 'blocks/townsquare/externallib.php', - 'methodname' => 'record_usersettings', + 'classname' => 'block_townsquare\external\block_townsquare_external', 'description' => 'Records the user settings for the townsquare block', 'type' => 'write', 'ajax' => true, diff --git a/externallib.php b/externallib.php index e0a4e3d..da3a31e 100644 --- a/externallib.php +++ b/externallib.php @@ -25,6 +25,7 @@ namespace block_townsquare\external; use Exception; use external_api; +use external_value; use stdClass; defined('MOODLE_INTERNAL') || die(); @@ -45,7 +46,7 @@ class block_townsquare_external extends external_api { * Returns description of method parameters * @return external_function_parameters */ - public static function record_usersettings_parameters(): external_function_parameters { + public static function execute_parameters(): external_function_parameters { return new external_function_parameters( [ 'userid' => new external_value(PARAM_INT, 'the user id'), @@ -62,7 +63,7 @@ public static function record_usersettings_parameters(): external_function_param * Return the result of the record_usersettings function * @return external_value */ - public static function record_usersettings_returns() { + public static function eyecute_returns(): external_value { return new external_value(PARAM_BOOL, 'true if successful'); } @@ -77,10 +78,9 @@ public static function record_usersettings_returns() { * @param int $postletter If post letters should be shown * @return bool */ - public static function record_usersettings($userid, $timefilterpast, $timefilterfuture, - $basicletter, $completionletter, $postletter) { + public static function execute($userid, $timefilterpast, $timefilterfuture, + $basicletter, $completionletter, $postletter): bool { global $DB; - $transaction = $DB->start_delegated_transaction(); // Check if the user already has a record in the database. if ($records = $DB->get_records('block_townsquare_preferences', ['userid' => $userid])) { // If there more than a record (it only should be only one), delete all of them and insert the new one. @@ -90,7 +90,7 @@ public static function record_usersettings($userid, $timefilterpast, $timefilter $DB->delete_records('block_townsquare_preferences', ['id' => $record->id]); } } catch (Exception $e) { - $transaction->rollback($e); + return false; } } else { @@ -102,7 +102,6 @@ public static function record_usersettings($userid, $timefilterpast, $timefilter $record->completionletter = $completionletter; $record->postletter = $postletter; $DB->update_record('block_townsquare_preferences', $record); - $transaction->allow_commit(); return true; } } @@ -114,7 +113,6 @@ public static function record_usersettings($userid, $timefilterpast, $timefilter $record->completionletter = $completionletter; $record->postletter = $postletter; $DB->insert_record('block_townsquare_preferences', $record); - $transaction->allow_commit(); return true; } From d9cfd6562081447a42d495e53a027d96a89cef43 Mon Sep 17 00:00:00 2001 From: Tamaro Walter Date: Thu, 11 Apr 2024 16:41:22 +0200 Subject: [PATCH 067/123] adapt function names to moodleoverflow --- db/services.php | 3 ++- externallib.php | 12 ++++++------ tests/externallib_test.php | 4 +--- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/db/services.php b/db/services.php index 6a7ef48..fbba3b4 100644 --- a/db/services.php +++ b/db/services.php @@ -26,8 +26,9 @@ $functions = [ 'block_townsquare_record_usersettings' => [ + 'classname' => 'block_townsquare_external', + 'methodname' => 'record_usersettings', 'classpath' => 'blocks/townsquare/externallib.php', - 'classname' => 'block_townsquare\external\block_townsquare_external', 'description' => 'Records the user settings for the townsquare block', 'type' => 'write', 'ajax' => true, diff --git a/externallib.php b/externallib.php index da3a31e..fa19f99 100644 --- a/externallib.php +++ b/externallib.php @@ -21,8 +21,8 @@ * @copyright 2024 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - -namespace block_townsquare\external; +namespace block_townsquare; +use core_external\external_function_parameters; use Exception; use external_api; use external_value; @@ -46,7 +46,7 @@ class block_townsquare_external extends external_api { * Returns description of method parameters * @return external_function_parameters */ - public static function execute_parameters(): external_function_parameters { + public static function record_usersettings_parameters(): external_function_parameters { return new external_function_parameters( [ 'userid' => new external_value(PARAM_INT, 'the user id'), @@ -63,7 +63,7 @@ public static function execute_parameters(): external_function_parameters { * Return the result of the record_usersettings function * @return external_value */ - public static function eyecute_returns(): external_value { + public static function record_usersettings_returns(): external_value { return new external_value(PARAM_BOOL, 'true if successful'); } @@ -78,7 +78,7 @@ public static function eyecute_returns(): external_value { * @param int $postletter If post letters should be shown * @return bool */ - public static function execute($userid, $timefilterpast, $timefilterfuture, + public static function record_usersettings($userid, $timefilterpast, $timefilterfuture, $basicletter, $completionletter, $postletter): bool { global $DB; // Check if the user already has a record in the database. @@ -116,4 +116,4 @@ public static function execute($userid, $timefilterpast, $timefilterfuture, return true; } -} +} \ No newline at end of file diff --git a/tests/externallib_test.php b/tests/externallib_test.php index dd954a9..bd7be03 100644 --- a/tests/externallib_test.php +++ b/tests/externallib_test.php @@ -29,8 +29,6 @@ global $CFG; require_once($CFG->dirroot . '/webservice/tests/helpers.php'); -use block_townsquare\external\block_townsquare_external; - /** * PHPUnit tests for testing the process of the externallib. * @@ -70,7 +68,7 @@ public function test_record_usersettings(): void { $this->assertEquals(false, $record); // Call the function to record the user settings and check, if the record is created. - $result = block_townsquare_external::record_usersettings($usersetting->userid, $usersetting->timefilterpast, + $result = \block_townsquare\block_townsquare_external::record_usersettings($usersetting->userid, $usersetting->timefilterpast, $usersetting->timefilterfuture, $usersetting->basicletter, $usersetting->completionletter, $usersetting->postletter); From 5af694dedd93b5bbf415fcb04a2d63f7c50c3285 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Tue, 23 Apr 2024 17:48:17 +0200 Subject: [PATCH 068/123] WIP: try to implement new subplugin structure --- classes/townsquareevents.php | 7 +- classes/townsquaresupportinterface.php | 2 +- locallib.php | 32 ------ .../lang/en/tsmoodleoverflow.php | 29 ------ .../tsmoodleoverflow/locallib.php | 97 ------------------- .../tsmoodleoverflow/tsmoodleoverflow.php | 43 -------- supportedmodules/tsmoodleoverflow/version.php | 31 ------ version.php | 1 + 8 files changed, 8 insertions(+), 234 deletions(-) delete mode 100644 supportedmodules/tsmoodleoverflow/lang/en/tsmoodleoverflow.php delete mode 100644 supportedmodules/tsmoodleoverflow/locallib.php delete mode 100644 supportedmodules/tsmoodleoverflow/tsmoodleoverflow.php delete mode 100644 supportedmodules/tsmoodleoverflow/version.php diff --git a/classes/townsquareevents.php b/classes/townsquareevents.php index c850de1..208cb09 100644 --- a/classes/townsquareevents.php +++ b/classes/townsquareevents.php @@ -58,10 +58,15 @@ class townsquareevents { * Events will be searched in the timespan of 6 months in the past and 6 months in the future. */ public function __construct() { + global $USER; $this->timenow = time(); $this->timestart = $this->timenow - 15768000; $this->timeend = $this->timenow + 15768000; - $this->courses = townsquare_get_courses(); + $this->courses = []; + $enrolledcourses = enrol_get_all_users_courses($USER->id, true); + foreach ($enrolledcourses as $enrolledcourse) { + $this->courses[] = $enrolledcourse->id; + } } /** diff --git a/classes/townsquaresupportinterface.php b/classes/townsquaresupportinterface.php index 61044da..e167547 100644 --- a/classes/townsquaresupportinterface.php +++ b/classes/townsquaresupportinterface.php @@ -28,7 +28,7 @@ * @copyright 2023 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -namespace block_townsquare\townsquaresupport; +namespace local_townsquaresupport\townsquaresupportinterface; interface townsquaresupportinterface { diff --git a/locallib.php b/locallib.php index 465ba52..a15d222 100644 --- a/locallib.php +++ b/locallib.php @@ -22,38 +22,6 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -/** - * Gets the id of all courses where the current user is enrolled - * @return array - */ -function townsquare_get_courses(): array { - global $USER; - - $enrolledcourses = enrol_get_all_users_courses($USER->id, true); - $courses = []; - foreach ($enrolledcourses as $enrolledcourse) { - $courses[] = $enrolledcourse->id; - } - - return $courses; -} - -/** - * Function for subplugins to get the start time of the search. - * @return int - */ -function townsquare_get_timestart(): int { - return time() - 15768000; -} - -/** - * Function for subplugins to get the end time of the search. - * @return int - */ -function townsquare_get_timeend(): int { - return time() + 15768000; -} - /** * Merge sort function for townsquare events. * @param $events diff --git a/supportedmodules/tsmoodleoverflow/lang/en/tsmoodleoverflow.php b/supportedmodules/tsmoodleoverflow/lang/en/tsmoodleoverflow.php deleted file mode 100644 index 511feac..0000000 --- a/supportedmodules/tsmoodleoverflow/lang/en/tsmoodleoverflow.php +++ /dev/null @@ -1,29 +0,0 @@ -. - -/** - * Plugin strings for the townsquare subplugin for moodleoverflow support. - * - * @package block_ts_moodleoverflow - * @category string - * @copyright 2024 Tamaro Walter - * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -$string['pluginname'] = 'Moodleoverflow support for townsquare block'; -$string['pluginnameadding'] = "Adding a Moodleoverflow support subplugin"; -$string['pluginnameediting'] = "Editing a Moodleoverflow support subplugin"; -$string['pluginnamesummary'] = "This subplugin allows the townsquare block to show new posts from moodleoverflow."; -$string['pluginname_help'] = 'This subplugin allows the townsquare block to show posts from moodleoverflow.'; diff --git a/supportedmodules/tsmoodleoverflow/locallib.php b/supportedmodules/tsmoodleoverflow/locallib.php deleted file mode 100644 index ba8c604..0000000 --- a/supportedmodules/tsmoodleoverflow/locallib.php +++ /dev/null @@ -1,97 +0,0 @@ -. - -/** - * Internal library of functions for the ts_moodleoverflow subplugin - * - * @package block_townsquare - * @copyright 2024 Tamaro Walter - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die; - -global $CFG; -require_once($CFG->dirroot . '/blocks/townsquare/locallib.php'); - -/** - * Function to get the newest post from the moodleoverflow module. - * @param array $courses The courses that will searched. - * @param int $timestart The start time of the search. - * @param int $timeend The end time of the search. - * @return array - */ -function ts_moodleoverflow_get_events($courses, $timestart): array { - global $DB; - - // If moodleoverflow is not installed or not activated, return empty array. - if (!$DB->get_record('modules', ['name' => 'forum', 'visible' => 1])) { - return []; - } - - // Get posts from the database. - $posts = ts_moodleoverflow_get_post_from_db($courses, $timestart); - - // Filter posts by availability. - foreach ($posts as $post) { - if (townsquare_filter_availability($post)) { - unset($posts[$post->row_num]); - } - } - - return $posts; -} - -function ts_moodleoverflow_get_post_from_db($courses, $timestart): array { - global $DB; - // Prepare params for sql statement. - list($insqlcourses, $inparamscourses) = $DB->get_in_or_equal($courses, SQL_PARAMS_NAMED); - $params = ['courses' => $courses, 'timestart' => $timestart] + $inparamscourses; - - $sql = "SELECT (ROW_NUMBER() OVER (ORDER BY posts.id)) AS row_num, - 'moodleoverflow' AS modulename, - module.id AS instanceid, - module.anonymous AS anonymoussetting, - 'post' AS eventtype, - cm.id AS coursemoduleid, - cm.availability AS availability, - module.name AS instancename, - discuss.course AS courseid, - discuss.userid AS discussionuserid, - discuss.name AS discussionsubject, - u.firstname AS postuserfirstname, - u.lastname AS postuserlastname, - posts.id AS postid, - posts.discussion AS postdiscussion, - posts.parent AS postparentid, - posts.userid AS postuserid, - posts.created AS timestart, - posts.message AS postmessage - FROM {moodleoverflow_posts} posts - JOIN {moodleoverflow_discussions} discuss ON discuss.id = posts.discussion - JOIN {moodleoverflow} module ON module.id = discuss.moodleoverflow - JOIN {modules} modules ON modules.name = 'moodleoverflow' - JOIN {user} u ON u.id = posts.userid - JOIN {course_modules} cm ON (cm.course = module.course AND cm.module = modules.id AND cm.instance = module.id) - WHERE discuss.course $insqlcourses - AND posts.created > :timestart - AND cm.visible = 1 - AND modules.visible = 1 - ORDER BY posts.created DESC;"; - - return $DB->get_records_sql($sql, $params); -} - diff --git a/supportedmodules/tsmoodleoverflow/tsmoodleoverflow.php b/supportedmodules/tsmoodleoverflow/tsmoodleoverflow.php deleted file mode 100644 index 7e39304..0000000 --- a/supportedmodules/tsmoodleoverflow/tsmoodleoverflow.php +++ /dev/null @@ -1,43 +0,0 @@ -. - -defined('MOODLE_INTERNAL') || die; - -use block_townsquare\townsquaresupport\townsquaresupportinterface; - -global $CFG; -require_once($CFG->dirroot . '/blocks/townsquare/supportedmodules/block_ts_moodleoverflow/locallib.php'); - -/** - * Plugin strings are defined here. - * - * @package block_townsquare - * @copyright 2023 Tamaro Walter - * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class tsmoodleoverflow implements townsquaresupportinterface { - - /** - * Function from the interface. - * @return array - */ - public function get_events(): array { - $courses = townsquare_get_courses(); - $timestart = townsquare_get_timestart(); - return ts_moodleoverflow_get_events($courses, $timestart); - } - -} diff --git a/supportedmodules/tsmoodleoverflow/version.php b/supportedmodules/tsmoodleoverflow/version.php deleted file mode 100644 index b82b83e..0000000 --- a/supportedmodules/tsmoodleoverflow/version.php +++ /dev/null @@ -1,31 +0,0 @@ -. - -/** - * Plugin version and other meta-data are defined here. - * - * @package supportedmodules_tsmoodleoverflow - * @copyright 2023 Tamaro Walter - * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); -$plugin->component = 'supportedmodules_tsmoodleoverflow'; -$plugin->dependencies = ['block_townsquare' => ANY_VERSION]; -$plugin->release = '0.1.0'; -$plugin->version = 2024011503; -$plugin->requires = 2022041900; -$plugin->maturity = MATURITY_ALPHA; diff --git a/version.php b/version.php index 0d3c448..02058d9 100644 --- a/version.php +++ b/version.php @@ -26,5 +26,6 @@ $plugin->component = 'block_townsquare'; $plugin->release = '0.1.0'; $plugin->version = 2023092005; +$plugin->version = 2024032201; $plugin->requires = 2022041900; $plugin->maturity = MATURITY_ALPHA; From 7d533f151642f738e597a5f3ef71dcab745ff6ee Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Tue, 7 May 2024 18:05:57 +0200 Subject: [PATCH 069/123] townsquare subplugin adaptation successful --- block_townsquare.php | 1 + classes/letter/post_letter.php | 1 - classes/plugininfo/townsquaresupport.php | 69 --------- classes/townsquareevents.php | 172 ++++++----------------- classes/townsquaresupportinterface.php | 50 ------- db/subplugins.json | 5 - db/subplugins.php | 27 ---- lang/en/block_townsquare.php | 6 +- locallib.php | 28 +++- tests/contentcontroller_test.php | 2 +- tests/coreevents_test.php | 2 +- tests/postevents_test.php | 2 +- 12 files changed, 75 insertions(+), 290 deletions(-) delete mode 100644 classes/plugininfo/townsquaresupport.php delete mode 100644 classes/townsquaresupportinterface.php delete mode 100644 db/subplugins.json delete mode 100644 db/subplugins.php diff --git a/block_townsquare.php b/block_townsquare.php index e3475ac..cb03108 100644 --- a/block_townsquare.php +++ b/block_townsquare.php @@ -16,6 +16,7 @@ use block_townsquare\contentcontroller; + /** * Plugin strings are defined here. * diff --git a/classes/letter/post_letter.php b/classes/letter/post_letter.php index d514a42..3b56eef 100644 --- a/classes/letter/post_letter.php +++ b/classes/letter/post_letter.php @@ -191,7 +191,6 @@ private function add_anonymousattribute($postevent): void { } else { $this->post->anonymous = false; } - } } diff --git a/classes/plugininfo/townsquaresupport.php b/classes/plugininfo/townsquaresupport.php deleted file mode 100644 index 0a23e33..0000000 --- a/classes/plugininfo/townsquaresupport.php +++ /dev/null @@ -1,69 +0,0 @@ -. - -/** - * TODO: Add description. - * - * @package block_townsquare - * @copyright 2023 Tamaro Walter - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace block_townsquare\townsquaresupport; - -use core\plugininfo\base; -/** - * The functions for all sub-plugins of type townsquaresupport. - */ -class townsquaresupport extends base { - - /** - * Return if a subplugin is allowed to be deleted.. - * - * @return bool - */ - public function is_uninstall_allowed(): bool { - return true; - } - - /** - * Checks whether sub-plugins have settings.php and adds them to the admin menu. - * In Case a sub-plugin is added the settings.php has to include all global variables it needs. - * - * @param \part_of_admin_tree $adminroot - * @param string $parentnodename - * @param bool $hassiteconfig - */ - public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { - $ADMIN = $adminroot; // May be used in settings.php. - - if (!$this->is_installed_and_upgraded()) { - return; - } - - if (!$hassiteconfig || !file_exists($this->full_path('settings.php'))) { - return; - } - - $section = $this->get_settings_section_name(); - $settings = new admin_settingpage($section, $this->displayname, 'moodle/site:config', $this->is_enabled() === false); - include($this->full_path('settings.php')); // This may also set $settings to null. - - if ($settings) { - $ADMIN->add($parentnodename, $settings); - } - } -} diff --git a/classes/townsquareevents.php b/classes/townsquareevents.php index 208cb09..0c798cc 100644 --- a/classes/townsquareevents.php +++ b/classes/townsquareevents.php @@ -27,10 +27,12 @@ use context_module; use dml_exception; +use function local_townsquaresupport\townsquaresupport_get_subplugin_events; global $CFG; require_once($CFG->dirroot . '/calendar/lib.php'); require_once($CFG->dirroot . '/blocks/townsquare/locallib.php'); +require_once($CFG->dirroot . '/local/townsquaresupport/lib.php'); /** * Class to get events and posts that will be shown in the townsquare block.. @@ -58,15 +60,10 @@ class townsquareevents { * Events will be searched in the timespan of 6 months in the past and 6 months in the future. */ public function __construct() { - global $USER; $this->timenow = time(); $this->timestart = $this->timenow - 15768000; $this->timeend = $this->timenow + 15768000; - $this->courses = []; - $enrolledcourses = enrol_get_all_users_courses($USER->id, true); - foreach ($enrolledcourses as $enrolledcourse) { - $this->courses[] = $enrolledcourse->id; - } + $this->courses = townsquare_get_courses(); } /** @@ -76,7 +73,7 @@ public function __construct() { public function get_all_events_sorted(): array { $coreevents = $this->get_coreevents(); $postevents = $this->get_postevents(); - $subpluginevents = $this->get_subpluginevents(); + $subpluginevents = townsquaresupport_get_subplugin_events(); // Merge the events in a sorted order. $events = $coreevents + $postevents + $subpluginevents; @@ -115,26 +112,6 @@ public function get_coreevents(): array { return $coreevents; } - /** - * Function to get events/notifications from other plugins than core plugins for the current user. - * This function checks for subplugins and calls their get_events() function. - * - * The events are sorted in descending order by time created (newest event first) - * @return array - */ - public function get_subpluginevents(): array { - // Get all available subplugins. - $events = []; - $subplugins = \core_plugin_manager::instance()->get_plugins_of_type('supportedmodules'); - var_dump($subplugins); - foreach ($subplugins as $subplugin) { - $events += $subplugin->get_events(); - } - - // Sort the events and return them. - return townsquare_mergesort($events); - } - /** * Function to get the newest posts from modules like the forum or moodleoverflow. * @@ -144,63 +121,20 @@ public function get_subpluginevents(): array { public function get_postevents(): array { global $DB; - $forumposts = []; - $moodleoverflowposts = []; - - // Check which modules are installed and activated and get their data. - if ($DB->get_record('modules', ['name' => 'forum', 'visible' => 1])) { - $forumposts = $this->get_posts_from_db('forum', $this->courses, $this->timestart); - } - // TODO: implement support for moodleoverflow in a subplugin. - if ($DB->get_record('modules', ['name' => 'moodleoverflow', 'visible' => 1])) { - //$moodleoverflowposts = $this->get_posts_from_db('moodleoverflow', $this->courses, $this->timestart); - } - - if (empty($forumposts) && empty($moodleoverflowposts)) { + // If forum is not installed or not activated, return empty array. + if (!$DB->get_record('modules', ['name' => 'forum', 'visible' => 1])) { return []; } - // Merge the posts in a sorted order. While merging, filter out irrelevant posts and add relevant attributes if necessary. - $posts = []; - $numberofposts = count($forumposts) + count($moodleoverflowposts); - reset($forumposts); - reset($moodleoverflowposts); - for ($i = 0; $i < $numberofposts; $i++) { - // Filter unavailable posts. - // Iterate until the first post that is available. Decrement the number of posts each time a post is filtered. - while (current($forumposts) && townsquare_filter_availability(current($forumposts))) { - next($forumposts); - $numberofposts--; - } - while (current($moodleoverflowposts) && townsquare_filter_availability(current($moodleoverflowposts))) { - next($moodleoverflowposts); - $numberofposts--; - } - // If there no posts left after filtering, break. - if ($i >= $numberofposts) { - break; - } + $forumposts = $this->get_forumposts_from_db($this->courses, $this->timestart); - // Merge. - if (current($forumposts) && current($moodleoverflowposts)) { - if (current($forumposts)->timestart > current($moodleoverflowposts)->timestart) { - $posts[$i] = current($forumposts); - next($forumposts); - } else { - $posts[$i] = current($moodleoverflowposts); - next($moodleoverflowposts); - } - } else if (current($forumposts)) { - $posts[$i] = current($forumposts); - next($forumposts); - } else { - $posts[$i] = current($moodleoverflowposts); - next($moodleoverflowposts); + foreach ($forumposts as $post) { + if (townsquare_filter_availability($post)) { + unset($forumposts[$post->row_num]); } } - // Add an event type to the posts and add the anonymous setting to the moodleoverflow posts. Then return it. - return $posts; + return $forumposts; } // Helper functions. @@ -214,62 +148,43 @@ public function get_postevents(): array { * @param int $timestart The timestamp from where the posts should be searched. * @return array */ - private function get_posts_from_db($modulename, $courses, $timestart): array { + private function get_forumposts_from_db($courses, $timestart): array { global $DB; // Prepare params for sql statement. list($insqlcourses, $inparamscourses) = $DB->get_in_or_equal($courses, SQL_PARAMS_NAMED); $params = ['courses' => $courses, 'timestart' => $timestart] + $inparamscourses; - // Set begin of sql statement. - $begin = "SELECT (ROW_NUMBER() OVER (ORDER BY posts.id)) AS row_num, "; - - // Set the select part of the sql that is always the same. - $middle = "'post' AS eventtype, - cm.id AS coursemoduleid, - cm.availability AS availability, - module.name AS instancename, - discuss.course AS courseid, - discuss.userid AS discussionuserid, - discuss.name AS discussionsubject, - u.firstname AS postuserfirstname, - u.lastname AS postuserlastname, - posts.id AS postid, - posts.discussion AS postdiscussion, - posts.parent AS postparentid, - posts.userid AS postuserid, - posts.created AS timestart, - posts.message AS postmessage "; - - // Extend the strings for the 2 module cases. - if ($modulename == 'forum') { - $begin .= "'forum' AS modulename, module.id AS instanceid,"; - $middle .= "FROM {forum_posts} posts - JOIN {forum_discussions} discuss ON discuss.id = posts.discussion - JOIN {forum} module ON module.id = discuss.forum - JOIN {modules} modules ON modules.name = 'forum' "; - - } else if ($modulename == 'moodleoverflow') { - $begin .= "'moodleoverflow' AS modulename, module.id AS instanceid, module.anonymous AS anonymoussetting, "; - $middle .= "FROM {moodleoverflow_posts} posts - JOIN {moodleoverflow_discussions} discuss ON discuss.id = posts.discussion - JOIN {moodleoverflow} module ON module.id = discuss.moodleoverflow - JOIN {modules} modules ON modules.name = 'moodleoverflow' "; - } - // Extension of the middle string. - $middle .= "JOIN {user} u ON u.id = posts.userid - JOIN {course_modules} cm ON (cm.course = module.course AND cm.module = modules.id - AND cm.instance = module.id) "; - - // Set the where clause of the string. - $end = "WHERE discuss.course $insqlcourses - AND posts.created > :timestart - AND cm.visible = 1 - AND modules.visible = 1 + $sql = "SELECT (ROW_NUMBER() OVER (ORDER BY posts.id)) AS row_num, + 'forum' AS modulename, + module.id AS instanceid, + 'post' AS eventtype, + cm.id AS coursemoduleid, + cm.availability AS availability, + module.name AS instancename, + discuss.course AS courseid, + discuss.userid AS discussionuserid, + discuss.name AS discussionsubject, + u.firstname AS postuserfirstname, + u.lastname AS postuserlastname, + posts.id AS postid, + posts.discussion AS postdiscussion, + posts.parent AS postparentid, + posts.userid AS postuserid, + posts.created AS timestart, + posts.message AS postmessage + FROM {forum_posts} posts + JOIN {forum_discussions} discuss ON discuss.id = posts.discussion + JOIN {forum} module ON module.id = discuss.forum + JOIN {modules} modules ON modules.name = 'forum' + JOIN {user} u ON u.id = posts.userid + JOIN {course_modules} cm ON (cm.course = module.course AND cm.module = modules.id + AND cm.instance = module.id) + WHERE discuss.course $insqlcourses + AND posts.created > :timestart + AND cm.visible = 1 + AND modules.visible = 1 ORDER BY posts.created DESC;"; - // Concatenate all strings. - $sql = $begin . $middle . $end; - // Get all posts. return $DB->get_records_sql($sql, $params); } @@ -288,8 +203,9 @@ private function get_events_from_db($timestart, $timeend, $courses): array { // Due to compatability reasons, only events from supported modules are shown. // Supported modules are: core modules and custom additional modules. - $coremodules = ['assign', 'book', 'chat', 'choice', 'data', 'feedback', 'file', 'folder', 'forum', 'glossary', 'h5pactivity', - 'imscp', 'label', 'lesson', 'lti', 'page', 'quiz', 'resource', 'scorm', 'survey', 'url', 'wiki', 'workshop', ]; + $coremodules = ['assign', 'book', 'chat', 'choice', 'data', 'feedback', 'file', 'folder', 'forum', 'glossary', + 'h5pactivity', 'imscp', 'label', 'lesson', 'lti', 'page', 'quiz', 'resource', 'scorm', 'survey', 'url', + 'wiki', 'workshop', ]; $additionalmodules = ['moodleoverflow', 'ratingallocate']; $modules = $coremodules + $additionalmodules; diff --git a/classes/townsquaresupportinterface.php b/classes/townsquaresupportinterface.php deleted file mode 100644 index e167547..0000000 --- a/classes/townsquaresupportinterface.php +++ /dev/null @@ -1,50 +0,0 @@ -. - -/** - * Interface for the sub-plugin townsquaresupport. - * - * The Plugins of the type townsquaresupport are used to increase the content of the townsquare block. - * Every module that wants to show content on townsquare can implement this interface. - * Every module must: - * - gather "events" for a user that can be transformed into letters. - * - provide php_unit test to ensure the correct behaviour. - * The townsquare block will call the export function of the (custom) letter and draw the letter on the dashboard. - * - * @package block_townsquare - * @copyright 2023 Tamaro Walter - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -namespace local_townsquaresupport\townsquaresupportinterface; - -interface townsquaresupportinterface { - - /** - * Function to gather the events - * Every event must gain sufficient data so that townsquare can build a letter from it. - * The array should contain following information: - * [courseid] => int Course ID from where the content comes from. - * [modulename] => string Name of the activity module. - * [instancename] => string Name of the instance that shows the notification. - * [content] => string The content that will be showed in the letter. - * [timestart] => int Timestamp that represents the deadline/creation of a notification. Is important to sort events. - * [coursemoduleid] => int Course module id of the content module. - * [eventtype] => string Type of the event. - * - * @return array of events that can be transformed into letters - */ - public function get_events(): array; -} diff --git a/db/subplugins.json b/db/subplugins.json deleted file mode 100644 index 9f2a3a9..0000000 --- a/db/subplugins.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "plugintypes": { - "supportedmodules": "blocks/townsquare/supportedmodules" - } -} diff --git a/db/subplugins.php b/db/subplugins.php deleted file mode 100644 index 12482a8..0000000 --- a/db/subplugins.php +++ /dev/null @@ -1,27 +0,0 @@ -. - -/** - * This file defines the sub-plugins for the townsquare block. - * - * @package blocks_townsquare - * @copyright 2023 Tamaro Walter - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -$subplugins = ['supportedmodules' => 'blocks/townsquare/supportedmodules']; diff --git a/lang/en/block_townsquare.php b/lang/en/block_townsquare.php index 5efa161..57341d8 100644 --- a/lang/en/block_townsquare.php +++ b/lang/en/block_townsquare.php @@ -40,10 +40,6 @@ // Letter strings. $string['invalidmodulename'] = 'Module name is unknown or not supported'; -// Subplugin strings. -$string['subplugintype_townsquaresupport'] = 'Supported module'; -$string['subplugintype_townsquaresupport_plural'] = 'Supported modules'; - // Event strings. $string['assignduemessage'] = 'Assignment is due until {$a->time}'; $string['assigngradingduemessage'] = 'Assignment is due to be graded until {$a->time}'; @@ -64,4 +60,4 @@ $string['workshopopensubmission'] = 'Submissions for the workshop are possible from {$a->time} onwards'; $string['workshopclosesubmission'] = 'Please submit your work until {$a->time}. The workshop closes afterwards'; $string['workshopopenassessment'] = 'The assessment phase starts today at {$a->time}'; -$string['workshopcloseassessment'] = 'Assessments for the workshop are due until {$a->time}'; \ No newline at end of file +$string['workshopcloseassessment'] = 'Assessments for the workshop are due until {$a->time}'; diff --git a/locallib.php b/locallib.php index a15d222..454cee5 100644 --- a/locallib.php +++ b/locallib.php @@ -22,6 +22,30 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +/** + * Gets the id of all courses where the current user is enrolled + * @return array + */ +function townsquare_get_courses(): array { + global $USER; + + $enrolledcourses = enrol_get_all_users_courses($USER->id, true); + $courses = []; + foreach ($enrolledcourses as $enrolledcourse) { + $courses[] = $enrolledcourse->id; + } + + return $courses; +} + +/** + * Function for subplugins to get the start time of the search. + * @return int + */ +function townsquare_get_timestart(): int { + return time() - 15768000; +} + /** * Merge sort function for townsquare events. * @param $events @@ -110,7 +134,7 @@ function townsquare_check_coreevent($event) { } else if ($event->modulename == 'data') { if ($event->eventtype == 'open') { $event->name = get_string('dataopenmessage', 'block_townsquare'); - }else if ($event->eventtype == 'close') { + } else if ($event->eventtype == 'close') { $event->name = get_string('dataclosemessage', 'block_townsquare', ['time' => $time]); } } else if ($event->modulename == 'feedback') { @@ -152,4 +176,4 @@ function townsquare_check_coreevent($event) { $event->name = get_string('workshopcloseassessment', 'block_townsquare', ['time' => $time]); } } -} \ No newline at end of file +} diff --git a/tests/contentcontroller_test.php b/tests/contentcontroller_test.php index b00ed1b..53b88ac 100644 --- a/tests/contentcontroller_test.php +++ b/tests/contentcontroller_test.php @@ -69,7 +69,7 @@ public function tearDown(): void { * Test, if the right letters are created. * @return void */ - public function test_letters() { + public function test_letters(): void { // Set an logged in user. $this->setUser($this->testdata->teacher); diff --git a/tests/coreevents_test.php b/tests/coreevents_test.php index 2aba11f..05213a1 100644 --- a/tests/coreevents_test.php +++ b/tests/coreevents_test.php @@ -96,7 +96,7 @@ public function test_sortorder(): void { * Test, if the post events are processed correctly if the course disappears. * @return void */ - public function test_course_deleted() { + public function test_course_deleted(): void { global $DB; // Delete the course from the database. $DB->delete_records('course', ['id' => $this->testdata->course1->id]); diff --git a/tests/postevents_test.php b/tests/postevents_test.php index 42dfee5..4a93b22 100644 --- a/tests/postevents_test.php +++ b/tests/postevents_test.php @@ -151,7 +151,7 @@ public function test_module_forum(): void { * Test, if the post events are processed correctly if the course disappears. * @return void */ - public function test_course_deleted() { + public function test_course_deleted(): void { global $DB; // Delete the course from the database. $DB->delete_records('course', ['id' => $this->testdata->course1->id]); From f2e1f6f2847735b1f2e5f001fa4e5dbc231f59ce Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Wed, 8 May 2024 15:57:25 +0200 Subject: [PATCH 070/123] add townsquaresupport plugin installation for workflows --- .github/workflows/moodle-ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index a2eae8d..2304155 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -59,6 +59,9 @@ jobs: - name: Install mod plugin run: moodle-plugin-ci add-plugin learnweb/moodle-mod_moodleoverflow + - name: Install local plugin + run: moodle-plugin-ci add-plugin learnweb/moodle-local_townsquaresupport + - name: Install moodle-plugin-ci run: | moodle-plugin-ci install --plugin ./plugin --db-host=127.0.0.1 --no-init From 5730a5ec6e15102c0f1ed31f55bf0028c1df2781 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Wed, 8 May 2024 16:03:50 +0200 Subject: [PATCH 071/123] codecleaning --- externallib.php | 2 +- tests/externallib_test.php | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/externallib.php b/externallib.php index fa19f99..c95dd55 100644 --- a/externallib.php +++ b/externallib.php @@ -116,4 +116,4 @@ public static function record_usersettings($userid, $timefilterpast, $timefilter return true; } -} \ No newline at end of file +} diff --git a/tests/externallib_test.php b/tests/externallib_test.php index bd7be03..8ebf8b8 100644 --- a/tests/externallib_test.php +++ b/tests/externallib_test.php @@ -68,7 +68,8 @@ public function test_record_usersettings(): void { $this->assertEquals(false, $record); // Call the function to record the user settings and check, if the record is created. - $result = \block_townsquare\block_townsquare_external::record_usersettings($usersetting->userid, $usersetting->timefilterpast, + $result = \block_townsquare\block_townsquare_external::record_usersettings($usersetting->userid, + $usersetting->timefilterpast, $usersetting->timefilterfuture, $usersetting->basicletter, $usersetting->completionletter, $usersetting->postletter); From 37873d639917799c235d05c3dbf7c6b723a625e2 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Wed, 8 May 2024 16:40:44 +0200 Subject: [PATCH 072/123] add todo for subplugins --- classes/townsquareevents.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/classes/townsquareevents.php b/classes/townsquareevents.php index 36271ab..2f275f6 100644 --- a/classes/townsquareevents.php +++ b/classes/townsquareevents.php @@ -291,6 +291,8 @@ private function get_events_from_db($timestart, $timeend, $courses): array { // Supported modules are: core modules and custom additional modules. $coremodules = ['assign', 'book', 'chat', 'choice', 'data', 'feedback', 'folder', 'forum', 'glossary', 'h5pactivity', 'imscp', 'label', 'lesson', 'lti', 'page', 'quiz', 'resource', 'scorm', 'survey', 'url', 'wiki', 'workshop', ]; + + // TODO: Additional modules should be implemented with subplugins. $additionalmodules = ['moodleoverflow', 'ratingallocate']; $modules = $coremodules + $additionalmodules; From 14b2074900e5b29c86d6e815486d27bd8ccaf6a3 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Wed, 8 May 2024 16:42:33 +0200 Subject: [PATCH 073/123] update workflow matrix --- .github/workflows/moodle-ci.yml | 24 +++++++++++++++++++++--- classes/townsquareevents.php | 2 ++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index 2304155..4e61abb 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -116,9 +116,27 @@ jobs: strategy: fail-fast: false matrix: - php: ['8.0', '8.1'] - moodle-branch: ['MOODLE_401_STABLE', 'MOODLE_402_STABLE', 'MOODLE_403_STABLE'] - database: ['mariadb', 'pgsql'] + php: ['8.0', '8.1', '8.2', '8.3'] + moodle-branch: ['MOODLE_401_STABLE', 'MOODLE_402_STABLE', 'MOODLE_403_STABLE', 'MOODLE_404_STABLE'] + database: [ 'mariadb', 'pgsql' ] + exclude: + - php: '8.0' + moodle-branch: 'MOODLE_404_STABLE' + - php: '8.2' + moodle-branch: 'MOODLE_401_STABLE' + - php: '8.3' + moodle-branch: 'MOODLE_401_STABLE' + - php: '8.3' + moodle-branch: 'MOODLE_402_STABLE' + - php: '8.3' + moodle-branch: 'MOODLE_403_STABLE' + include: + - php: '7.4' + moodle-branch: 'MOODLE_401_STABLE' + database: 'pgsql' + - php: '7.4' + moodle-branch: 'MOODLE_401_STABLE' + database: 'mariadb' steps: - name: Start MariaDB diff --git a/classes/townsquareevents.php b/classes/townsquareevents.php index 0c798cc..8633e9d 100644 --- a/classes/townsquareevents.php +++ b/classes/townsquareevents.php @@ -206,6 +206,8 @@ private function get_events_from_db($timestart, $timeend, $courses): array { $coremodules = ['assign', 'book', 'chat', 'choice', 'data', 'feedback', 'file', 'folder', 'forum', 'glossary', 'h5pactivity', 'imscp', 'label', 'lesson', 'lti', 'page', 'quiz', 'resource', 'scorm', 'survey', 'url', 'wiki', 'workshop', ]; + + // TODO: Additional modules should be implemented with subplugins. $additionalmodules = ['moodleoverflow', 'ratingallocate']; $modules = $coremodules + $additionalmodules; From 3cae9ce8db095bdaaeabde1c4d4bef7460315c7e Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Wed, 8 May 2024 18:03:50 +0200 Subject: [PATCH 074/123] delete moodleoverflow native support, adapt locallib --- classes/townsquareevents.php | 24 ++++-------------------- locallib.php | 31 +++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 20 deletions(-) diff --git a/classes/townsquareevents.php b/classes/townsquareevents.php index 8633e9d..88b94c9 100644 --- a/classes/townsquareevents.php +++ b/classes/townsquareevents.php @@ -61,8 +61,8 @@ class townsquareevents { */ public function __construct() { $this->timenow = time(); - $this->timestart = $this->timenow - 15768000; - $this->timeend = $this->timenow + 15768000; + $this->timestart = townsquare_get_timestart(); + $this->timeend = townsquare_get_timeend(); $this->courses = townsquare_get_courses(); } @@ -97,7 +97,7 @@ public function get_coreevents(): array { // Filter out events that are not relevant for the user. if (townsquare_filter_availability($coreevent) || ($coreevent->modulename == "assign" && $this->filter_assignment($coreevent)) || - ($coreevent->eventtype == "expectcompletionon" && $this->filter_activitycompletions($coreevent))) { + ($coreevent->eventtype == "expectcompletionon" && townsquare_filter_activitycompletions($coreevent))) { unset($coreevents[$coreevent->id]); continue; } @@ -208,7 +208,7 @@ private function get_events_from_db($timestart, $timeend, $courses): array { 'wiki', 'workshop', ]; // TODO: Additional modules should be implemented with subplugins. - $additionalmodules = ['moodleoverflow', 'ratingallocate']; + $additionalmodules = ['ratingallocate']; $modules = $coremodules + $additionalmodules; // Prepare params for sql statement. @@ -261,20 +261,4 @@ private function filter_assignment($coreevent): bool { return false; } - /** - * Filter that checks if the event needs to be filtered out for the current user because it is already completed.. - * Applies to activity completion events. - * @param object $coreevent coreevent that is checked - * @return bool true if the event needs to filtered out, false if not. - */ - private function filter_activitycompletions($coreevent): bool { - global $DB, $USER; - if ($completionstatus = $DB->get_record('course_modules_completion', - ['coursemoduleid' => $coreevent->coursemoduleid, 'userid' => $USER->id])) { - if ($completionstatus->completionstate != 0) { - return true; - } - } - return false; - } } diff --git a/locallib.php b/locallib.php index 454cee5..6e9e42d 100644 --- a/locallib.php +++ b/locallib.php @@ -46,6 +46,14 @@ function townsquare_get_timestart(): int { return time() - 15768000; } +/** + * Function for subplugins to get the end time of the search. + * @return int + */ +function townsquare_get_timeend(): int { + return time() + 15768000; +} + /** * Merge sort function for townsquare events. * @param $events @@ -93,6 +101,8 @@ function townsquare_merge(array $left, array $right): array { return $result; } +// Filter functions. + function townsquare_filter_availability($event): bool { // If there is no restriction defined, the event is available. if ($event->availability == null) { @@ -109,6 +119,27 @@ function townsquare_filter_availability($event): bool { return true; } +/** + * Filter that checks if the event needs to be filtered out for the current user because it is already completed.. + * Applies to activity completion events. + * @param object $coreevent coreevent that is checked + * @return bool true if the event needs to filtered out, false if not. + */ +function townsquare_filter_activitycompletions($coreevent): bool { + global $DB, $USER; + if ($completionstatus = $DB->get_record('course_modules_completion', + ['coursemoduleid' => $coreevent->coursemoduleid, 'userid' => $USER->id])) { + if ($completionstatus->completionstate != 0) { + return true; + } + } + return false; +} + + + +// Strings adaptation functions. + /** * General Support function for core events. * Can be used to modify the event content, as in some cases, core events don't have a good text in the events-datatable. From c47b5f74bc9c102a6637ea98eb5ae99d4178ba07 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 9 May 2024 17:28:00 +0200 Subject: [PATCH 075/123] support for ratingallocate made with subplugin --- classes/townsquareevents.php | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/classes/townsquareevents.php b/classes/townsquareevents.php index 88b94c9..90c0da0 100644 --- a/classes/townsquareevents.php +++ b/classes/townsquareevents.php @@ -202,14 +202,9 @@ private function get_events_from_db($timestart, $timeend, $courses): array { global $DB; // Due to compatability reasons, only events from supported modules are shown. - // Supported modules are: core modules and custom additional modules. - $coremodules = ['assign', 'book', 'chat', 'choice', 'data', 'feedback', 'file', 'folder', 'forum', 'glossary', - 'h5pactivity', 'imscp', 'label', 'lesson', 'lti', 'page', 'quiz', 'resource', 'scorm', 'survey', 'url', - 'wiki', 'workshop', ]; - - // TODO: Additional modules should be implemented with subplugins. - $additionalmodules = ['ratingallocate']; - $modules = $coremodules + $additionalmodules; + $modules = ['assign', 'book', 'chat', 'choice', 'data', 'feedback', 'file', 'folder', 'forum', 'glossary', + 'h5pactivity', 'imscp', 'label', 'lesson', 'lti', 'page', 'quiz', 'resource', 'scorm', 'survey', 'url', + 'wiki', 'workshop', ]; // Prepare params for sql statement. list($insqlcourses, $inparamscourses) = $DB->get_in_or_equal($courses, SQL_PARAMS_NAMED); From 67f731b2a0eb9453343107ffa8ef302e8f48fe66 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 9 May 2024 18:38:41 +0200 Subject: [PATCH 076/123] update readme --- README.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1447c51..855647d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,22 @@ # Town Square # -A moodle block for the dashboard.This Plugin shows current events and forum posts in courses the user is enrolled to. +A moodle block for the dashboard. This Plugin shows current events and forum posts in courses the user is enrolled. + +## Description ## + +The Goal of this plugin is to implement a block, where the different notifications (e.g. deadlines), activity completion and forum posts +from different courses are shown. Additionally, the user is able to filter the notifications by different parameters. + +## Subplugin functionality ## + +Townsquare does not show notfications from every installed plugin. As every plugin can have different type of notifications that +not always should be shown to the current user (e.g. a teacher should not see the same notifications as a student). +Therefore, only the moodle core plugins are supported by the plugin. +To show notifications from other plugins, a subplugin can be implemented or installed. To do that, install local plugin +local_townsquaresupport (see: https://github.com/learnweb/moodle-local_townsquaresupport). Townsquaresupport manages +subplugins and makes them available to townsquare. + +More information on how to install subplugins: https://github.com/learnweb/moodle-local_townsquaresupport ## Installing via uploaded ZIP file ## From a5cb904340176c3b269f2100ff185a4b4343aadd Mon Sep 17 00:00:00 2001 From: Tamaro Walter Date: Tue, 14 May 2024 17:08:05 +0200 Subject: [PATCH 077/123] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 855647d..93c03a2 100644 --- a/README.md +++ b/README.md @@ -9,14 +9,14 @@ from different courses are shown. Additionally, the user is able to filter the n ## Subplugin functionality ## -Townsquare does not show notfications from every installed plugin. As every plugin can have different type of notifications that +Townsquare does not show notifications from every installed plugin, as every plugin can have different types of notifications that not always should be shown to the current user (e.g. a teacher should not see the same notifications as a student). -Therefore, only the moodle core plugins are supported by the plugin. -To show notifications from other plugins, a subplugin can be implemented or installed. To do that, install local plugin +Therefore, only the Moodle core plugins are supported by the plugin. +To show notifications from other plugins, a subplugin can be implemented or installed. To do that, install the local plugin local_townsquaresupport (see: https://github.com/learnweb/moodle-local_townsquaresupport). Townsquaresupport manages -subplugins and makes them available to townsquare. +subplugins and makes them available to Townsquare. -More information on how to install subplugins: https://github.com/learnweb/moodle-local_townsquaresupport +More information on townsquare subplugins: https://github.com/learnweb/moodle-local_townsquaresupport/wiki ## Installing via uploaded ZIP file ## From 9bdfa2a85e836e6eff93dcc6a964a724c538795b Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 16 May 2024 10:14:49 +0200 Subject: [PATCH 078/123] move anonymous attribute to subplugin --- classes/letter/post_letter.php | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/classes/letter/post_letter.php b/classes/letter/post_letter.php index 3b56eef..1e91278 100644 --- a/classes/letter/post_letter.php +++ b/classes/letter/post_letter.php @@ -93,10 +93,10 @@ public function __construct($contentid, $postevent) { $this->post->message = $postevent->postmessage; $this->post->discussionsubject = $postevent->discussionsubject; $this->post->parentid = $postevent->postparentid; + $this->post->anonymous = $postevent->anonymous ?? false; $this->author->id = $postevent->postuserid; $this->author->name = $postevent->postuserfirstname . ' ' . $postevent->postuserlastname; - $this->add_anonymousattribute($postevent); $this->retrieve_profilepicture(); $this->build_links(); } @@ -174,23 +174,4 @@ private function retrieve_profilepicture() { } } - /** - * Method to add the anonymous attribute to the post. - * @param object $postevent a post event with information,for more see classes/townsquareevents.php. - * @return void - */ - private function add_anonymousattribute($postevent): void { - if ($this->modulename == 'moodleoverflow') { - if ($postevent->anonymoussetting == \mod_moodleoverflow\anonymous::EVERYTHING_ANONYMOUS) { - $this->post->anonymous = true; - } else if ($postevent->anonymoussetting == \mod_moodleoverflow\anonymous::QUESTION_ANONYMOUS) { - $this->post->anonymous = $this->author->id == $postevent->discussionuserid; - } else { - $this->post->anonymous = false; - } - } else { - $this->post->anonymous = false; - } - } - } From 667d400f38d6033366a0d50a37802ef3084a1c87 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 16 May 2024 10:49:03 +0200 Subject: [PATCH 079/123] move function to subplugins --- classes/letter/post_letter.php | 25 ++----------------------- classes/townsquareevents.php | 6 ++++++ 2 files changed, 8 insertions(+), 23 deletions(-) diff --git a/classes/letter/post_letter.php b/classes/letter/post_letter.php index 1e91278..fd368f7 100644 --- a/classes/letter/post_letter.php +++ b/classes/letter/post_letter.php @@ -96,9 +96,10 @@ public function __construct($contentid, $postevent) { $this->post->anonymous = $postevent->anonymous ?? false; $this->author->id = $postevent->postuserid; $this->author->name = $postevent->postuserfirstname . ' ' . $postevent->postuserlastname; + $this->posturls->linktopost = $postevent->linktopost; + $this->posturls->linktoauthor = $postevent->linktoauthor; $this->retrieve_profilepicture(); - $this->build_links(); } // Functions. @@ -132,28 +133,6 @@ public function export_letter():array { // Helper functions. - /** - * Function to build the links to the post, author. - * @return void - */ - private function build_links() { - $this->posturls->linktoauthor = new moodle_url('/user/view.php', ['id' => $this->author->id]); - if ($this->modulename == 'forum') { - $this->posturls->linktopost = new moodle_url('/mod/forum/discuss.php', - ['d' => $this->post->discussionid], 'p' . $this->post->id); - } else { - $this->posturls->linktopost = new moodle_url('/mod/moodleoverflow/discussion.php', - ['d' => $this->post->discussionid], 'p' . $this->post->id); - - // If the post in the moodleoverflow is anonymous, the user should not be visible. - if ($this->post->anonymous) { - $this->posturls->linktoauthor = new moodle_url(''); - $this->author->id = -1; - $this->author->name = 'anonymous'; - } - } - } - /** * Method to retrieve the profile picture of the author. * @return void diff --git a/classes/townsquareevents.php b/classes/townsquareevents.php index 90c0da0..e833d79 100644 --- a/classes/townsquareevents.php +++ b/classes/townsquareevents.php @@ -27,6 +27,7 @@ use context_module; use dml_exception; +use moodle_url; use function local_townsquaresupport\townsquaresupport_get_subplugin_events; global $CFG; @@ -132,6 +133,11 @@ public function get_postevents(): array { if (townsquare_filter_availability($post)) { unset($forumposts[$post->row_num]); } + + // Add a links and the authors picture. + $post->linktopost = new moodle_url('/mod/forum/discuss.php', + ['d' => $post->postdiscussion], 'p' . $post->postid); + $post->linktoauthor = new moodle_url('/user/view.php', ['id' => $post->postuserid]); } return $forumposts; From 581b5db57082a51bfb76fde97bb25c3847009293 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 16 May 2024 14:24:23 +0200 Subject: [PATCH 080/123] WIP: try to fix webservice --- amd/build/coursefilter.min.js.map | 2 +- amd/build/filtercontroller.min.js.map | 2 +- amd/build/letterfilter.min.js.map | 2 +- amd/build/postletter.min.js.map | 2 +- amd/build/timefilter.min.js.map | 2 +- amd/build/usersettings_save.min.js | 2 +- amd/build/usersettings_save.min.js.map | 2 +- amd/src/usersettings_save.js | 22 +++++++++++++--------- tests/externallib_test.php | 4 ++-- 9 files changed, 22 insertions(+), 18 deletions(-) diff --git a/amd/build/coursefilter.min.js.map b/amd/build/coursefilter.min.js.map index 4b6bcae..de47173 100644 --- a/amd/build/coursefilter.min.js.map +++ b/amd/build/coursefilter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"coursefilter.min.js","sources":["../src/coursefilter.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 * Javascript for the course filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the course filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/coursefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant checkboxes.\nconst checkboxes = document.querySelectorAll('.ts_course_checkbox');\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n // Get the courseid associated with the checkbox\n const courseid = checkbox.id;\n\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.ts_timefilter_active.ts_letterfilter_active');\n\n // Loop through each letter mark it as \"active\" or not based on checkbox state and the letter id.\n letters.forEach(function(letter) {\n let letterCourseId = letter.querySelector('.townsquareletter_course').id;\n\n if (courseid === letterCourseId) {\n if (checkbox.checked) {\n letter.classList.add('ts_coursefilter_active'); // Mark the letter as \"active\".\n } else {\n letter.classList.remove('ts_coursefilter_active'); // Mark the letter as \"not active\".\n }\n }\n });\n });\n });\n}\n"],"names":["checkboxes","forEach","checkbox","addEventListener","courseid","id","document","querySelectorAll","letter","letterCourseId","querySelector","checked","classList","add","remove"],"mappings":"wJAiCIA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,iBAE1BC,SAAWF,SAASG,GAIVC,SAASC,iBAAiB,kEAGlCN,SAAQ,SAASO,YACjBC,eAAiBD,OAAOE,cAAc,4BAA4BL,GAElED,WAAaK,iBACTP,SAASS,QACTH,OAAOI,UAAUC,IAAI,0BAErBL,OAAOI,UAAUE,OAAO;;;;;;;;;;;MAvB1Cd,WAAaM,SAASC,iBAAiB"} \ No newline at end of file +{"version":3,"file":"coursefilter.min.js","sources":["../src/coursefilter.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 * Javascript for the course filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the course filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/coursefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant checkboxes.\nconst checkboxes = document.querySelectorAll('.ts_course_checkbox');\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n // Get the courseid associated with the checkbox\n const courseid = checkbox.id;\n\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.ts_timefilter_active.ts_letterfilter_active');\n\n // Loop through each letter mark it as \"active\" or not based on checkbox state and the letter id.\n letters.forEach(function(letter) {\n let letterCourseId = letter.querySelector('.townsquareletter_course').id;\n\n if (courseid === letterCourseId) {\n if (checkbox.checked) {\n letter.classList.add('ts_coursefilter_active'); // Mark the letter as \"active\".\n } else {\n letter.classList.remove('ts_coursefilter_active'); // Mark the letter as \"not active\".\n }\n }\n });\n });\n });\n}\n"],"names":["checkboxes","forEach","checkbox","addEventListener","courseid","id","document","querySelectorAll","letter","letterCourseId","querySelector","checked","classList","add","remove"],"mappings":"6IAgCO,WACHA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,WAEhC,MAAMC,SAAWF,SAASG,GAIVC,SAASC,iBAAiB,kEAGlCN,SAAQ,SAASO,QACrB,IAAIC,eAAiBD,OAAOE,cAAc,4BAA4BL,GAElED,WAAaK,iBACTP,SAASS,QACTH,OAAOI,UAAUC,IAAI,0BAErBL,OAAOI,UAAUE,OAAO;;;;;;;;;;;AAvBhD,MAAMd,WAAaM,SAASC,iBAAiB,sBA6B5C"} \ No newline at end of file diff --git a/amd/build/filtercontroller.min.js.map b/amd/build/filtercontroller.min.js.map index c6fdfb0..ed17974 100644 --- a/amd/build/filtercontroller.min.js.map +++ b/amd/build/filtercontroller.min.js.map @@ -1 +1 @@ -{"version":3,"file":"filtercontroller.min.js","sources":["../src/filtercontroller.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 * Javascript to show/hide letters based on all filters\n *\n * This file implements 1 functionality:\n * - If the \"save settings\" button is pressed, store the settings in the database.\n *\n * @module block_townsquare/filtercontroller\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get all letters from townsquare.\nconst letters = document.querySelectorAll('.townsquare_letter');\n\n/**\n * Init function\n */\nexport function init() {\n // First step: activate every letter by adding the filter classes.\n letters.forEach(function(letter) {\n letter.classList.add('ts_coursefilter_active');\n letter.classList.add('ts_timefilter_active');\n letter.classList.add('ts_letterfilter_active');\n });\n\n // Add a mutation listener to each letter.\n letters.forEach(function(letter) {\n const observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(mutation) {\n if (mutation.attributeName === 'class') {\n // If the class of the letter changes, check if the letter should be shown or hidden.\n let coursefilter = letter.classList.contains('ts_coursefilter_active');\n let timefilter = letter.classList.contains('ts_timefilter_active');\n let letterfilter = letter.classList.contains('ts_letterfilter_active');\n\n // If all filters are active, show the letter.\n if (coursefilter && timefilter && letterfilter) {\n letter.style.display = 'block';\n } else {\n letter.style.display = 'none';\n }\n }\n });\n });\n\n observer.observe(letter, {attributes: true});\n });\n}\n"],"names":["letters","forEach","letter","classList","add","MutationObserver","mutations","mutation","attributeName","coursefilter","contains","timefilter","letterfilter","style","display","observe","attributes","document","querySelectorAll"],"mappings":"4JAkCIA,QAAQC,SAAQ,SAASC,QACrBA,OAAOC,UAAUC,IAAI,0BACrBF,OAAOC,UAAUC,IAAI,wBACrBF,OAAOC,UAAUC,IAAI,6BAIzBJ,QAAQC,SAAQ,SAASC,QACJ,IAAIG,kBAAiB,SAASC,WAC3CA,UAAUL,SAAQ,SAASM,aACQ,UAA3BA,SAASC,cAA2B,KAEhCC,aAAeP,OAAOC,UAAUO,SAAS,0BACzCC,WAAaT,OAAOC,UAAUO,SAAS,wBACvCE,aAAeV,OAAOC,UAAUO,SAAS,0BAIzCR,OAAOW,MAAMC,QADbL,cAAgBE,YAAcC,aACP,QAEA,cAM9BG,QAAQb,OAAQ,CAACc,YAAY;;;;;;;;;;;MAjCxChB,QAAUiB,SAASC,iBAAiB"} \ No newline at end of file +{"version":3,"file":"filtercontroller.min.js","sources":["../src/filtercontroller.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 * Javascript to show/hide letters based on all filters\n *\n * This file implements 1 functionality:\n * - If the \"save settings\" button is pressed, store the settings in the database.\n *\n * @module block_townsquare/filtercontroller\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get all letters from townsquare.\nconst letters = document.querySelectorAll('.townsquare_letter');\n\n/**\n * Init function\n */\nexport function init() {\n // First step: activate every letter by adding the filter classes.\n letters.forEach(function(letter) {\n letter.classList.add('ts_coursefilter_active');\n letter.classList.add('ts_timefilter_active');\n letter.classList.add('ts_letterfilter_active');\n });\n\n // Add a mutation listener to each letter.\n letters.forEach(function(letter) {\n const observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(mutation) {\n if (mutation.attributeName === 'class') {\n // If the class of the letter changes, check if the letter should be shown or hidden.\n let coursefilter = letter.classList.contains('ts_coursefilter_active');\n let timefilter = letter.classList.contains('ts_timefilter_active');\n let letterfilter = letter.classList.contains('ts_letterfilter_active');\n\n // If all filters are active, show the letter.\n if (coursefilter && timefilter && letterfilter) {\n letter.style.display = 'block';\n } else {\n letter.style.display = 'none';\n }\n }\n });\n });\n\n observer.observe(letter, {attributes: true});\n });\n}\n"],"names":["letters","forEach","letter","classList","add","MutationObserver","mutations","mutation","attributeName","coursefilter","contains","timefilter","letterfilter","style","display","observe","attributes","document","querySelectorAll"],"mappings":"iJAgCO,WAEHA,QAAQC,SAAQ,SAASC,QACrBA,OAAOC,UAAUC,IAAI,0BACrBF,OAAOC,UAAUC,IAAI,wBACrBF,OAAOC,UAAUC,IAAI,6BAIzBJ,QAAQC,SAAQ,SAASC,QACJ,IAAIG,kBAAiB,SAASC,WAC3CA,UAAUL,SAAQ,SAASM,UACvB,GAA+B,UAA3BA,SAASC,cAA2B,CAEpC,IAAIC,aAAeP,OAAOC,UAAUO,SAAS,0BACzCC,WAAaT,OAAOC,UAAUO,SAAS,wBACvCE,aAAeV,OAAOC,UAAUO,SAAS,0BAIzCR,OAAOW,MAAMC,QADbL,cAAgBE,YAAcC,aACP,QAEA,cAM9BG,QAAQb,OAAQ,CAACc,YAAY;;;;;;;;;;;AAjC9C,MAAMhB,QAAUiB,SAASC,iBAAiB,qBAmCzC"} \ No newline at end of file diff --git a/amd/build/letterfilter.min.js.map b/amd/build/letterfilter.min.js.map index 9f6c13e..02c4ab5 100644 --- a/amd/build/letterfilter.min.js.map +++ b/amd/build/letterfilter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"letterfilter.min.js","sources":["../src/letterfilter.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 * Javascript for the letter filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the letter filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/letterfilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant checkboxes.\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n // Get the letter name associated with the checkbox.\n const lettername = checkbox.id;\n\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.' + lettername +\n '.ts_timefilter_active.ts_coursefilter_active');\n\n // Loop through each letter and hide/show based on checkbox state.\n letters.forEach(function(letter) {\n if (checkbox.checked) {\n letter.classList.add('ts_letterfilter_active'); // Mark the letter as \"active\".\n } else {\n letter.classList.remove('ts_letterfilter_active'); // Mark the letter as \"not active\".\n }\n });\n });\n });\n}\n"],"names":["checkboxes","forEach","checkbox","addEventListener","lettername","id","document","querySelectorAll","letter","checked","classList","add","remove"],"mappings":"wJAiCIA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,iBAE1BC,WAAaF,SAASG,GAIZC,SAASC,iBAAiB,sBAAwBH,WACxB,gDAGlCH,SAAQ,SAASO,QACjBN,SAASO,QACTD,OAAOE,UAAUC,IAAI,0BAErBH,OAAOE,UAAUE,OAAO;;;;;;;;;;;MArBtCZ,WAAaM,SAASC,iBAAiB"} \ No newline at end of file +{"version":3,"file":"letterfilter.min.js","sources":["../src/letterfilter.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 * Javascript for the letter filter\n *\n * This file implements 1 functionality:\n * - Checks the checkboxes of the letter filter and hides content from courses if the checkbox is not checked.\n *\n * @module block_townsquare/letterfilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant checkboxes.\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n */\nexport function init() {\n checkboxes.forEach(function(checkbox) {\n checkbox.addEventListener('change', function() {\n // Get the letter name associated with the checkbox.\n const lettername = checkbox.id;\n\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.' + lettername +\n '.ts_timefilter_active.ts_coursefilter_active');\n\n // Loop through each letter and hide/show based on checkbox state.\n letters.forEach(function(letter) {\n if (checkbox.checked) {\n letter.classList.add('ts_letterfilter_active'); // Mark the letter as \"active\".\n } else {\n letter.classList.remove('ts_letterfilter_active'); // Mark the letter as \"not active\".\n }\n });\n });\n });\n}\n"],"names":["checkboxes","forEach","checkbox","addEventListener","lettername","id","document","querySelectorAll","letter","checked","classList","add","remove"],"mappings":"6IAgCO,WACHA,WAAWC,SAAQ,SAASC,UACxBA,SAASC,iBAAiB,UAAU,WAEhC,MAAMC,WAAaF,SAASG,GAIZC,SAASC,iBAAiB,sBAAwBH,WACxB,gDAGlCH,SAAQ,SAASO,QACjBN,SAASO,QACTD,OAAOE,UAAUC,IAAI,0BAErBH,OAAOE,UAAUE,OAAO;;;;;;;;;;;AArB5C,MAAMZ,WAAaM,SAASC,iBAAiB,sBA0B5C"} \ No newline at end of file diff --git a/amd/build/postletter.min.js.map b/amd/build/postletter.min.js.map index aba2bad..fde6c82 100644 --- a/amd/build/postletter.min.js.map +++ b/amd/build/postletter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"postletter.min.js","sources":["../src/postletter.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\r\n//\r\n// Moodle is free software: you can redistribute it and/or modify\r\n// it under the terms of the GNU General Public License as published by\r\n// the Free Software Foundation, either version 3 of the License, or\r\n// (at your option) any later version.\r\n//\r\n// Moodle is distributed in the hope that it will be useful,\r\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n// GNU General Public License for more details.\r\n//\r\n// You should have received a copy of the GNU General Public License\r\n// along with Moodle. If not, see .\r\n\r\nimport {getString} from \"core/str\";\r\nimport {prefetchStrings} from 'core/prefetch';\r\n\r\n/**\r\n * Javascript for the post letter\r\n *\r\n * This file implements 2 functionalities:\r\n * - cuts posts that have many characters and shows a \"see more\" Button to see the whole text.\r\n * - Unnecessary

Tags from the Database are being replaced with line breaks to make the text more readable.\r\n *\r\n * @module block_townsquare/postletter\r\n * @copyright 2023 Tamaro Walter\r\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\r\n */\r\n\r\nconst contentElements = document.getElementsByClassName('postletter_message');\r\nconst buttons = document.getElementsByClassName('townsquare_showmore');\r\nconst originalTexts = [];\r\n\r\nconst Selectors = {\r\n actions: {\r\n seemorebutton: '[data-action=\"block_townsquare/showmore_button\"]',\r\n },\r\n};\r\n\r\n/**\r\n * Init function\r\n *\r\n * The function can cut the text or extract paragraphs of a post.\r\n */\r\nexport function init() {\r\n contentElements.forEach(\r\n (element) => {\r\n // Replace all

within the text with simple line breaks..\r\n replaceParagraghTags(element);\r\n\r\n // Check if the text is too long.\r\n if (element.textContent.length >= 250) {\r\n // If the text is too long, cut it.\r\n originalTexts[element.id] = element.innerHTML;\r\n cutString(element);\r\n element.parentElement.insertAdjacentHTML('beforeend', '

');\r\n buttons[element.id].setAttribute('showmore', 'true');\r\n } else {\r\n // If the text is not too long, hide the show more button.\r\n buttons[element.id].style.display = \"none\";\r\n }\r\n }\r\n );\r\n\r\n // Get the strings for the show more/show less button.\r\n prefetchStrings('moodle', ['showmore', 'showless',]);\r\n\r\n // Add event listeners for the show more Button.\r\n addEventListener();\r\n}\r\n\r\n/**\r\n * Function to cut a String at a length of 250 characters.\r\n * The function does not cut within a word or after a space.\r\n * If the cutting point is within a word, the function searches for the next space and cuts there.\r\n * @param {object} element\r\n */\r\nfunction cutString(element) {\r\n let text = element.textContent;\r\n let index = 250;\r\n while (text.charAt(index) != \" \") {\r\n index++;\r\n }\r\n element.innerHTML = text.substring(0,index);\r\n}\r\n\r\n/**\r\n * Event listener for the show more/show less button.\r\n */\r\nconst addEventListener = () => {\r\n document.addEventListener('click', e => {\r\n if (e.target.closest(Selectors.actions.seemorebutton)) {\r\n // Get the id of the clicked element.\r\n let letterid = e.target.id;\r\n contentElements.forEach(\r\n (element) => {\r\n if (element.id == letterid) {\r\n if (buttons[letterid].getAttribute('showmore') == 'true') {\r\n element.innerHTML = originalTexts[letterid];\r\n changeButtonString(letterid, false);\r\n } else {\r\n cutString(element);\r\n changeButtonString(letterid, true);\r\n }\r\n }\r\n }\r\n );\r\n }\r\n });\r\n};\r\n\r\n/**\r\n * Changes the button strings.\r\n * @param {string} index Which button should be changed\r\n * @param {boolean} toshowmore a boolean that indicates if the button should show more or less\r\n */\r\nasync function changeButtonString(index, toshowmore) {\r\n if (toshowmore == true) {\r\n buttons[index].textContent = await getString('showmore', 'moodle');\r\n buttons[index].setAttribute('showmore', 'true');\r\n } else {\r\n buttons[index].textContent = await getString('showless', 'moodle');\r\n buttons[index].setAttribute('showmore', 'false');\r\n }\r\n}\r\n\r\n/**\r\n * Removes in a text all   and surrounding

tags excluding the first occurrence.\r\n *\r\n * Helper function to make post look better.\r\n * @param {object} element\r\n */\r\nasync function replaceParagraghTags(element) {\r\n // Identify and store the first

and

tags\r\n let message = element.innerHTML;\r\n const firstPTag = message.indexOf('

');\r\n const lastPTag = message.lastIndexOf('

');\r\n\r\n // Remove   and surrounding

tags excluding the first occurrence\r\n message = message.replace(/

 <\\/p>/g, '').replace(/ /g, '');\r\n\r\n // Replace

tags with
excluding the first occurrence\r\n message = message.substring(0, firstPTag + 3) +\r\n message.substring(firstPTag + 3, lastPTag).replace(/

/g, '
').replace(/<\\/p>/g, '') +\r\n message.substring(lastPTag);\r\n element.innerHTML = message;\r\n}"],"names":["contentElements","forEach","element","message","innerHTML","firstPTag","indexOf","lastPTag","lastIndexOf","replace","substring","replaceParagraghTags","textContent","length","originalTexts","id","cutString","parentElement","insertAdjacentHTML","buttons","setAttribute","style","display","addEventListener","document","getElementsByClassName","Selectors","seemorebutton","text","index","charAt","e","target","closest","letterid","getAttribute","changeButtonString","toshowmore"],"mappings":"gMA8CIA,gBAAgBC,SACXC,0BAsF2BA,aAE5BC,QAAUD,QAAQE,gBAChBC,UAAYF,QAAQG,QAAQ,OAC5BC,SAAWJ,QAAQK,YAAY,QAGrCL,QAAUA,QAAQM,QAAQ,kBAAmB,IAAIA,QAAQ,UAAW,IAGpEN,QAAUA,QAAQO,UAAU,EAAGL,UAAY,GACvCF,QAAQO,UAAUL,UAAY,EAAGE,UAAUE,QAAQ,OAAQ,QAAQA,QAAQ,SAAU,IACrFN,QAAQO,UAAUH,UACtBL,QAAQE,UAAYD,QAjGZQ,CAAqBT,SAGjBA,QAAQU,YAAYC,QAAU,KAE9BC,cAAcZ,QAAQa,IAAMb,QAAQE,UACpCY,UAAUd,SACVA,QAAQe,cAAcC,mBAAmB,YAAa,OACtDC,QAAQjB,QAAQa,IAAIK,aAAa,WAAY,SAG7CD,QAAQjB,QAAQa,IAAIM,MAAMC,QAAU,wCAMhC,SAAU,CAAC,WAAY,aAGvCC;;;;;;;;;;;;MAvCEvB,gBAAkBwB,SAASC,uBAAuB,sBAClDN,QAAUK,SAASC,uBAAuB,uBAC1CX,cAAgB,GAEhBY,kBACO,CACLC,cAAe,6DA0CdX,UAAUd,aACX0B,KAAO1B,QAAQU,YACfiB,MAAQ,SACiB,KAAtBD,KAAKE,OAAOD,QACfA,QAEJ3B,QAAQE,UAAYwB,KAAKlB,UAAU,EAAEmB,aAMnCN,iBAAmB,KACrBC,SAASD,iBAAiB,SAASQ,OAC3BA,EAAEC,OAAOC,QAAQP,kBAAkBC,eAAgB,KAE/CO,SAAWH,EAAEC,OAAOjB,GACxBf,gBAAgBC,SACXC,UACOA,QAAQa,IAAMmB,WACoC,QAA9Cf,QAAQe,UAAUC,aAAa,aAC/BjC,QAAQE,UAAYU,cAAcoB,UAClCE,mBAAmBF,UAAU,KAE7BlB,UAAUd,SACVkC,mBAAmBF,UAAU,4BAc1CE,mBAAmBP,MAAOQ,YACnB,GAAdA,YACAlB,QAAQU,OAAOjB,kBAAoB,kBAAU,WAAY,UACzDO,QAAQU,OAAOT,aAAa,WAAY,UAExCD,QAAQU,OAAOjB,kBAAoB,kBAAU,WAAY,UACzDO,QAAQU,OAAOT,aAAa,WAAY"} \ No newline at end of file +{"version":3,"file":"postletter.min.js","sources":["../src/postletter.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\nimport {getString} from \"core/str\";\nimport {prefetchStrings} from 'core/prefetch';\n\n/**\n * Javascript for the post letter\n *\n * This file implements 2 functionalities:\n * - cuts posts that have many characters and shows a \"see more\" Button to see the whole text.\n * - Unnecessary

Tags from the Database are being replaced with line breaks to make the text more readable.\n *\n * @module block_townsquare/postletter\n * @copyright 2023 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nconst contentElements = document.getElementsByClassName('postletter_message');\nconst buttons = document.getElementsByClassName('townsquare_showmore');\nconst originalTexts = [];\n\nconst Selectors = {\n actions: {\n seemorebutton: '[data-action=\"block_townsquare/showmore_button\"]',\n },\n};\n\n/**\n * Init function\n *\n * The function can cut the text or extract paragraphs of a post.\n */\nexport function init() {\n contentElements.forEach(\n (element) => {\n // Replace all

within the text with simple line breaks..\n replaceParagraghTags(element);\n\n // Check if the text is too long.\n if (element.textContent.length >= 250) {\n // If the text is too long, cut it.\n originalTexts[element.id] = element.innerHTML;\n cutString(element);\n element.parentElement.insertAdjacentHTML('beforeend', '

');\n buttons[element.id].setAttribute('showmore', 'true');\n } else {\n // If the text is not too long, hide the show more button.\n buttons[element.id].style.display = \"none\";\n }\n }\n );\n\n // Get the strings for the show more/show less button.\n prefetchStrings('moodle', ['showmore', 'showless',]);\n\n // Add event listeners for the show more Button.\n addEventListener();\n}\n\n/**\n * Function to cut a String at a length of 250 characters.\n * The function does not cut within a word or after a space.\n * If the cutting point is within a word, the function searches for the next space and cuts there.\n * @param {object} element\n */\nfunction cutString(element) {\n let text = element.textContent;\n let index = 250;\n while (text.charAt(index) != \" \") {\n index++;\n }\n element.innerHTML = text.substring(0,index);\n}\n\n/**\n * Event listener for the show more/show less button.\n */\nconst addEventListener = () => {\n document.addEventListener('click', e => {\n if (e.target.closest(Selectors.actions.seemorebutton)) {\n // Get the id of the clicked element.\n let letterid = e.target.id;\n contentElements.forEach(\n (element) => {\n if (element.id == letterid) {\n if (buttons[letterid].getAttribute('showmore') == 'true') {\n element.innerHTML = originalTexts[letterid];\n changeButtonString(letterid, false);\n } else {\n cutString(element);\n changeButtonString(letterid, true);\n }\n }\n }\n );\n }\n });\n};\n\n/**\n * Changes the button strings.\n * @param {string} index Which button should be changed\n * @param {boolean} toshowmore a boolean that indicates if the button should show more or less\n */\nasync function changeButtonString(index, toshowmore) {\n if (toshowmore == true) {\n buttons[index].textContent = await getString('showmore', 'moodle');\n buttons[index].setAttribute('showmore', 'true');\n } else {\n buttons[index].textContent = await getString('showless', 'moodle');\n buttons[index].setAttribute('showmore', 'false');\n }\n}\n\n/**\n * Removes in a text all   and surrounding

tags excluding the first occurrence.\n *\n * Helper function to make post look better.\n * @param {object} element\n */\nasync function replaceParagraghTags(element) {\n // Identify and store the first

and

tags\n let message = element.innerHTML;\n const firstPTag = message.indexOf('

');\n const lastPTag = message.lastIndexOf('

');\n\n // Remove   and surrounding

tags excluding the first occurrence\n message = message.replace(/

 <\\/p>/g, '').replace(/ /g, '');\n\n // Replace

tags with
excluding the first occurrence\n message = message.substring(0, firstPTag + 3) +\n message.substring(firstPTag + 3, lastPTag).replace(/

/g, '
').replace(/<\\/p>/g, '') +\n message.substring(lastPTag);\n element.innerHTML = message;\n}"],"names":["contentElements","forEach","element","async","message","innerHTML","firstPTag","indexOf","lastPTag","lastIndexOf","replace","substring","replaceParagraghTags","textContent","length","originalTexts","id","cutString","parentElement","insertAdjacentHTML","buttons","setAttribute","style","display","prefetchStrings","addEventListener","document","getElementsByClassName","Selectors","seemorebutton","text","index","charAt","e","target","closest","letterid","getAttribute","changeButtonString","toshowmore","getString"],"mappings":"qLA6CO,WACHA,gBAAgBC,SACXC,WAsFTC,eAAoCD,SAEhC,IAAIE,QAAUF,QAAQG,UACtB,MAAMC,UAAYF,QAAQG,QAAQ,OAC5BC,SAAWJ,QAAQK,YAAY,QAGrCL,QAAUA,QAAQM,QAAQ,kBAAmB,IAAIA,QAAQ,UAAW,IAGpEN,QAAUA,QAAQO,UAAU,EAAGL,UAAY,GACvCF,QAAQO,UAAUL,UAAY,EAAGE,UAAUE,QAAQ,OAAQ,QAAQA,QAAQ,SAAU,IACrFN,QAAQO,UAAUH,UACtBN,QAAQG,UAAYD,QAjGZQ,CAAqBV,SAGjBA,QAAQW,YAAYC,QAAU,KAE9BC,cAAcb,QAAQc,IAAMd,QAAQG,UACpCY,UAAUf,SACVA,QAAQgB,cAAcC,mBAAmB,YAAa,OACtDC,QAAQlB,QAAQc,IAAIK,aAAa,WAAY,SAG7CD,QAAQlB,QAAQc,IAAIM,MAAMC,QAAU,WAMhD,EAAAC,2BAAgB,SAAU,CAAC,WAAY,aAGvCC;;;;;;;;;;;;AAvCJ,MAAMzB,gBAAkB0B,SAASC,uBAAuB,sBAClDP,QAAUM,SAASC,uBAAuB,uBAC1CZ,cAAgB,GAEhBa,kBACO,CACLC,cAAe,oDA0CvB,SAASZ,UAAUf,SACf,IAAI4B,KAAO5B,QAAQW,YACfkB,MAAQ,IACZ,KAA6B,KAAtBD,KAAKE,OAAOD,QACfA,QAEJ7B,QAAQG,UAAYyB,KAAKnB,UAAU,EAAEoB,OAMzC,MAAMN,iBAAmBA,KACrBC,SAASD,iBAAiB,SAASQ,IAC/B,GAAIA,EAAEC,OAAOC,QAAQP,kBAAkBC,eAAgB,CAEnD,IAAIO,SAAWH,EAAEC,OAAOlB,GACxBhB,gBAAgBC,SACXC,UACOA,QAAQc,IAAMoB,WACoC,QAA9ChB,QAAQgB,UAAUC,aAAa,aAC/BnC,QAAQG,UAAYU,cAAcqB,UAClCE,mBAAmBF,UAAU,KAE7BnB,UAAUf,SACVoC,mBAAmBF,UAAU,WAMnD,EAQNjC,eAAemC,mBAAmBP,MAAOQ,YACnB,GAAdA,YACAnB,QAAQW,OAAOlB,kBAAoB,EAAA2B,gBAAU,WAAY,UACzDpB,QAAQW,OAAOV,aAAa,WAAY,UAExCD,QAAQW,OAAOlB,kBAAoB,EAAA2B,gBAAU,WAAY,UACzDpB,QAAQW,OAAOV,aAAa,WAAY,UAwB/C"} \ No newline at end of file diff --git a/amd/build/timefilter.min.js.map b/amd/build/timefilter.min.js.map index 238ee47..1763f9d 100644 --- a/amd/build/timefilter.min.js.map +++ b/amd/build/timefilter.min.js.map @@ -1 +1 @@ -{"version":3,"file":"timefilter.min.js","sources":["../src/timefilter.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 * Javascript for the time filter\n *\n * This file implements 1 functionality:\n * - Checks, which of the radio buttons is pressed and filters the content based on the time.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant radio buttons.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Define to change the time span, an additional time span and the current time.\nlet currenttime;\nlet timestart;\nlet timeend;\nlet addstarttime;\nlet addendtime;\n\n/**\n * Init function\n */\nexport function init() {\n // Set the current time.\n currenttime = new Date().getTime() / 1000;\n\n // Add event listeners to the all kind of buttons.\n alltimeaddEventListener();\n futuretimeaddEventListener();\n pasttimeaddEventListener();\n}\n\n/**\n * Function to execute the filter\n * @param {int} starttime Start of time span for filtering of the current pressed button\n * @param {int} endtime End of time span for filtering of the current pressed\n * @param {int} addstarttime Start of time span for filtering of an additional radio button.\n * @param {int} addendtime End of time span for filtering of an additional radio button.\n * @param {boolean} buttonstate State of the radio button (true or false)\n */\nfunction executefilter(starttime, endtime, addstarttime, addendtime, buttonstate) {\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.ts_coursefilter_active.ts_letterfilter_active');\n\n // Loop through each letter and hide/show based on radiobutton state.\n letters.forEach(function(letter) {\n\n // Get the created time stamp of each letter.\n let lettertime = letter.querySelector('.townsquareletter_date').id;\n\n // If the radio button is checked and the letter is in the time span, activate it.\n if ((buttonstate && (lettertime >= starttime && lettertime <= endtime)) ||\n (lettertime >= addstarttime && lettertime <= addendtime)) {\n letter.classList.add('ts_timefilter_active'); // Mark the letter as \"active\".\n } else {\n letter.classList.remove('ts_timefilter_active'); // Mark the letter as \"not active\".\n }\n });\n}\n\n/**\n * Function to add event listeners to the all_time button.\n */\nfunction alltimeaddEventListener() {\n alltimebutton.forEach(function(button) {\n button.addEventListener('change', function() {\n // Set the time span to show all letters.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime + convertidtotime(button.id);\n addstarttime = 0;\n addendtime = 0;\n\n // Disable all other radio buttons that filter more specific times.\n futureradiobuttons.forEach(function(futureradiobutton) {\n futureradiobutton.checked = false;\n futureradiobutton.parentNode.classList.remove(\"active\");\n });\n pastradiobuttons.forEach(function(pastradiobutton) {\n pastradiobutton.checked = false;\n pastradiobutton.parentNode.classList.remove(\"active\");\n\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime,addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the future time radio buttons.\n */\nfunction futuretimeaddEventListener() {\n futureradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime;\n timeend = currenttime + convertidtotime(button.id);\n\n // Check if one past time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n pastradiobuttons.forEach(function(pastradiobutton) {\n if (pastradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime - convertidtotime(pastradiobutton.id);\n addendtime = currenttime;\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the past time radio buttons.\n */\nfunction pasttimeaddEventListener() {\n pastradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime;\n\n // Check if one future time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n futureradiobuttons.forEach(function(futureradiobutton) {\n if (futureradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime;\n addendtime = currenttime + convertidtotime(futureradiobutton.id);\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n"],"names":["currenttime","Date","getTime","alltimebutton","forEach","button","addEventListener","timestart","convertidtotime","id","timeend","addstarttime","addendtime","futureradiobuttons","futureradiobutton","checked","parentNode","classList","remove","pastradiobuttons","pastradiobutton","executefilter","contains","document","querySelectorAll","starttime","endtime","buttonstate","letter","lettertime","querySelector","add"],"mappings":"sJA2CIA,aAAc,IAAIC,MAAOC,UAAY,IAyCrCC,cAAcC,SAAQ,SAASC,QAC3BA,OAAOC,iBAAiB,UAAU,WAE9BC,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAC/CE,aAAe,EACfC,WAAa,EAGbC,mBAAmBT,SAAQ,SAASU,mBAChCA,kBAAkBC,SAAU,EAC5BD,kBAAkBE,WAAWC,UAAUC,OAAO,aAElDC,iBAAiBf,SAAQ,SAASgB,iBAC9BA,gBAAgBL,SAAU,EAC1BK,gBAAgBJ,WAAWC,UAAUC,OAAO,aAKhDG,cAAcd,UAAWG,QAASC,aAAaC,WAAYP,OAAOU,eAS1EF,mBAAmBT,SAAQ,SAASC,QAChCA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YACZU,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAG/CE,aAAe,EACfC,WAAa,EACbO,iBAAiBf,SAAQ,SAASgB,iBAC1BA,gBAAgBJ,WAAWC,UAAUK,SAAS,YAC9CX,aAAeX,YAAcQ,gBAAgBY,gBAAgBX,IAC7DG,WAAaZ,gBAKrBqB,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU,eAS3EI,iBAAiBf,SAAQ,SAASC,QAC9BA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAGVW,aAAe,EACfC,WAAa,EACbC,mBAAmBT,SAAQ,SAASU,mBAC5BA,kBAAkBE,WAAWC,UAAUK,SAAS,YAChDX,aAAeX,YACfY,WAAaZ,YAAcQ,gBAAgBM,kBAAkBL,QAKrEY,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU;;;;;;;;;;;MA7IzEZ,cAAgBoB,SAASC,iBAAiB,uBAC1CX,mBAAqBU,SAASC,iBAAiB,0BAC/CL,iBAAmBI,SAASC,iBAAiB,4BAG/CxB,YACAO,UACAG,QACAC,aACAC,oBAuBKS,cAAcI,UAAWC,QAASf,aAAcC,WAAYe,aAGjDJ,SAASC,iBAAiB,oEAGlCpB,SAAQ,SAASwB,YAGjBC,WAAaD,OAAOE,cAAc,0BAA0BrB,GAG3DkB,aAAgBE,YAAcJ,WAAaI,YAAcH,SACzDG,YAAclB,cAAgBkB,YAAcjB,WAC7CgB,OAAOX,UAAUc,IAAI,wBAErBH,OAAOX,UAAUC,OAAO,oCAuG3BV,gBAAgBC,WACdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM"} \ No newline at end of file +{"version":3,"file":"timefilter.min.js","sources":["../src/timefilter.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 * Javascript for the time filter\n *\n * This file implements 1 functionality:\n * - Checks, which of the radio buttons is pressed and filters the content based on the time.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// Get the relevant radio buttons.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Define to change the time span, an additional time span and the current time.\nlet currenttime;\nlet timestart;\nlet timeend;\nlet addstarttime;\nlet addendtime;\n\n/**\n * Init function\n */\nexport function init() {\n // Set the current time.\n currenttime = new Date().getTime() / 1000;\n\n // Add event listeners to the all kind of buttons.\n alltimeaddEventListener();\n futuretimeaddEventListener();\n pasttimeaddEventListener();\n}\n\n/**\n * Function to execute the filter\n * @param {int} starttime Start of time span for filtering of the current pressed button\n * @param {int} endtime End of time span for filtering of the current pressed\n * @param {int} addstarttime Start of time span for filtering of an additional radio button.\n * @param {int} addendtime End of time span for filtering of an additional radio button.\n * @param {boolean} buttonstate State of the radio button (true or false)\n */\nfunction executefilter(starttime, endtime, addstarttime, addendtime, buttonstate) {\n // Get all letters that are \"activated\".\n // Activated means that all filters accept the letter and want to show it.\n const letters = document.querySelectorAll('.townsquare_letter.ts_coursefilter_active.ts_letterfilter_active');\n\n // Loop through each letter and hide/show based on radiobutton state.\n letters.forEach(function(letter) {\n\n // Get the created time stamp of each letter.\n let lettertime = letter.querySelector('.townsquareletter_date').id;\n\n // If the radio button is checked and the letter is in the time span, activate it.\n if ((buttonstate && (lettertime >= starttime && lettertime <= endtime)) ||\n (lettertime >= addstarttime && lettertime <= addendtime)) {\n letter.classList.add('ts_timefilter_active'); // Mark the letter as \"active\".\n } else {\n letter.classList.remove('ts_timefilter_active'); // Mark the letter as \"not active\".\n }\n });\n}\n\n/**\n * Function to add event listeners to the all_time button.\n */\nfunction alltimeaddEventListener() {\n alltimebutton.forEach(function(button) {\n button.addEventListener('change', function() {\n // Set the time span to show all letters.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime + convertidtotime(button.id);\n addstarttime = 0;\n addendtime = 0;\n\n // Disable all other radio buttons that filter more specific times.\n futureradiobuttons.forEach(function(futureradiobutton) {\n futureradiobutton.checked = false;\n futureradiobutton.parentNode.classList.remove(\"active\");\n });\n pastradiobuttons.forEach(function(pastradiobutton) {\n pastradiobutton.checked = false;\n pastradiobutton.parentNode.classList.remove(\"active\");\n\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime,addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the future time radio buttons.\n */\nfunction futuretimeaddEventListener() {\n futureradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime;\n timeend = currenttime + convertidtotime(button.id);\n\n // Check if one past time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n pastradiobuttons.forEach(function(pastradiobutton) {\n if (pastradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime - convertidtotime(pastradiobutton.id);\n addendtime = currenttime;\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to add event listeners to the past time radio buttons.\n */\nfunction pasttimeaddEventListener() {\n pastradiobuttons.forEach(function(button) {\n button.addEventListener('change', function() {\n // Disable the all_time button.\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n\n // Set the time span based on the radiobutton id.\n timestart = currenttime - convertidtotime(button.id);\n timeend = currenttime;\n\n // Check if one future time button is checked. If yes, set the additional time span based on its id.\n addstarttime = 0;\n addendtime = 0;\n futureradiobuttons.forEach(function(futureradiobutton) {\n if (futureradiobutton.parentNode.classList.contains('active')) {\n addstarttime = currenttime;\n addendtime = currenttime + convertidtotime(futureradiobutton.id);\n }\n });\n\n // Execute the filter function.\n executefilter(timestart, timeend, addstarttime, addendtime, button.checked);\n });\n });\n}\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n"],"names":["currenttime","Date","getTime","alltimebutton","forEach","button","addEventListener","timestart","convertidtotime","id","timeend","addstarttime","addendtime","futureradiobuttons","futureradiobutton","checked","parentNode","classList","remove","pastradiobuttons","pastradiobutton","executefilter","contains","document","querySelectorAll","starttime","endtime","buttonstate","letter","lettertime","querySelector","add"],"mappings":"2IAyCO,WAEHA,aAAc,IAAIC,MAAOC,UAAY,IAyCrCC,cAAcC,SAAQ,SAASC,QAC3BA,OAAOC,iBAAiB,UAAU,WAE9BC,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAC/CE,aAAe,EACfC,WAAa,EAGbC,mBAAmBT,SAAQ,SAASU,mBAChCA,kBAAkBC,SAAU,EAC5BD,kBAAkBE,WAAWC,UAAUC,OAAO,aAElDC,iBAAiBf,SAAQ,SAASgB,iBAC9BA,gBAAgBL,SAAU,EAC1BK,gBAAgBJ,WAAWC,UAAUC,OAAO,aAKhDG,cAAcd,UAAWG,QAASC,aAAaC,WAAYP,OAAOU,eAS1EF,mBAAmBT,SAAQ,SAASC,QAChCA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YACZU,QAAUV,YAAcQ,gBAAgBH,OAAOI,IAG/CE,aAAe,EACfC,WAAa,EACbO,iBAAiBf,SAAQ,SAASgB,iBAC1BA,gBAAgBJ,WAAWC,UAAUK,SAAS,YAC9CX,aAAeX,YAAcQ,gBAAgBY,gBAAgBX,IAC7DG,WAAaZ,gBAKrBqB,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU,eAS3EI,iBAAiBf,SAAQ,SAASC,QAC9BA,OAAOC,iBAAiB,UAAU,WAE9BH,cAAcC,SAAQ,SAASD,eAC3BA,cAAcY,SAAU,EACxBZ,cAAca,WAAWC,UAAUC,OAAO,aAI9CX,UAAYP,YAAcQ,gBAAgBH,OAAOI,IACjDC,QAAUV,YAGVW,aAAe,EACfC,WAAa,EACbC,mBAAmBT,SAAQ,SAASU,mBAC5BA,kBAAkBE,WAAWC,UAAUK,SAAS,YAChDX,aAAeX,YACfY,WAAaZ,YAAcQ,gBAAgBM,kBAAkBL,QAKrEY,cAAcd,UAAWG,QAASC,aAAcC,WAAYP,OAAOU;;;;;;;;;;;AA7I/E,MAAMZ,cAAgBoB,SAASC,iBAAiB,uBAC1CX,mBAAqBU,SAASC,iBAAiB,0BAC/CL,iBAAmBI,SAASC,iBAAiB,wBAGnD,IAAIxB,YACAO,UACAG,QACAC,aACAC,WAuBJ,SAASS,cAAcI,UAAWC,QAASf,aAAcC,WAAYe,aAGjDJ,SAASC,iBAAiB,oEAGlCpB,SAAQ,SAASwB,QAGrB,IAAIC,WAAaD,OAAOE,cAAc,0BAA0BrB,GAG3DkB,aAAgBE,YAAcJ,WAAaI,YAAcH,SACzDG,YAAclB,cAAgBkB,YAAcjB,WAC7CgB,OAAOX,UAAUc,IAAI,wBAErBH,OAAOX,UAAUC,OAAO,2BAuGpC,SAASV,gBAAgBC,IACrB,OAAOA,IACH,IAAK,cACD,OAAO,SACX,IAAK,uBACL,IAAK,uBACD,OAAO,OACX,IAAK,wBACL,IAAK,wBACD,OAAO,MACX,IAAK,oBACL,IAAK,oBACD,OAAO,OACX,IAAK,qBACL,IAAK,qBACD,OAAO,QAElB"} \ No newline at end of file diff --git a/amd/build/usersettings_save.min.js b/amd/build/usersettings_save.min.js index 4e4ccbb..b8c1c21 100644 --- a/amd/build/usersettings_save.min.js +++ b/amd/build/usersettings_save.min.js @@ -8,6 +8,6 @@ define("block_townsquare/usersettings_save",["exports","core/ajax"],(function(_e * @module block_townsquare/timefilter * @copyright 2024 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,settingsfromdb){settingsfromdb&&function(settingsfromdb){let futurebuttonid=converttimetoid(settingsfromdb.timefilterfuture,!0),pastbuttonid=converttimetoid(settingsfromdb.timefilterpast,!1);"ts_time_all"!==futurebuttonid?(futureradiobuttons.forEach((function(button){button.id===futurebuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change")),alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))})),pastradiobuttons.forEach((function(button){button.id===pastbuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change")),alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))}))):alltimebutton.forEach((function(button){button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change"))}));checkboxes.forEach((function(checkbox){let basiclettercheck="basicletter"===checkbox.id&&""===settingsfromdb.basicletter,completionlettercheck="completionletter"===checkbox.id&&"0"===settingsfromdb.completionletter,postlettercheck="postletter"===checkbox.id&&"0"===settingsfromdb.postletter;(basiclettercheck||completionlettercheck||postlettercheck)&&checkbox.click()}))}(settingsfromdb);savebutton.addEventListener("click",(async function(){let timespans=function(){let settings={timepast:0,timefuture:0},settingsset=!1;if(alltimebutton.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id),settings.timefuture=convertidtotime(button.id),settingsset=!0)})),settingsset)return settings;return futureradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timefuture=convertidtotime(button.id))})),pastradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id))})),settings}(),letterfilter=function(){let settings={basicletter:0,completionletter:0,postletter:0};return checkboxes.forEach((function(checkbox){if(checkbox.checked)switch(checkbox.id){case"basicletter":settings.basicletter=1;break;case"completionletter":settings.completionletter=1;break;case"postletter":settings.postletter=1}})),settings}();await async function(userid,timefilterpast,timefilterfuture,basicletter,completionletter,postletter){let result;result=await _ajax.default.call([{methodname:"block_townsquare_record_usersettings",args:{userid:parseInt(userid),timefilterpast:timefilterpast,timefilterfuture:timefilterfuture,basicletter:basicletter,completionletter:completionletter,postletter:postletter,success:function(){console.log("Settings saved.")}}}]);let el=document.getElementById("ts_usersettings_successlabel");el.style.display="block",el.style.opacity=1,el.fadeOutTimer&&clearInterval(el.fadeOutTimer);return setTimeout((function(){el.fadeOutTimer=setInterval((function(){el.style.opacity>.4?el.style.opacity-=.1:el.style.opacity>0?el.style.opacity-=.2:(clearInterval(el.fadeOutTimer),el.style.display="none")}),100)}),3e3),result}(userid,timespans.timepast,timespans.timefuture,letterfilter.basicletter,letterfilter.completionletter,letterfilter.postletter)}))},_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};const savebutton=document.getElementById("ts_usersettings_savebutton"),alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button"),checkboxes=document.querySelectorAll(".ts_letter_checkbox");function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}function converttimetoid(time,future){switch(time){case"15778463":return"ts_time_all";case"172800":return future?"ts_time_next_twodays":"ts_time_past_twodays";case"432000":return future?"ts_time_next_fivedays":"ts_time_last_fivedays";case"604800":return future?"ts_time_next_week":"ts_time_last_week";case"2592000":return future?"ts_time_next_month":"ts_time_last_month"}}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,settingsfromdb){settingsfromdb&&function(settingsfromdb){let futurebuttonid=converttimetoid(settingsfromdb.timefilterfuture,!0),pastbuttonid=converttimetoid(settingsfromdb.timefilterpast,!1);"ts_time_all"!==futurebuttonid?(futureradiobuttons.forEach((function(button){button.id===futurebuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change")),alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))})),pastradiobuttons.forEach((function(button){button.id===pastbuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change")),alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))}))):alltimebutton.forEach((function(button){button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change"))}));checkboxes.forEach((function(checkbox){let basiclettercheck="basicletter"===checkbox.id&&""===settingsfromdb.basicletter,completionlettercheck="completionletter"===checkbox.id&&"0"===settingsfromdb.completionletter,postlettercheck="postletter"===checkbox.id&&"0"===settingsfromdb.postletter;(basiclettercheck||completionlettercheck||postlettercheck)&&checkbox.click()}))}(settingsfromdb);savebutton.addEventListener("click",(async function(){let timespans=function(){let settings={timepast:0,timefuture:0},settingsset=!1;if(alltimebutton.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id),settings.timefuture=convertidtotime(button.id),settingsset=!0)})),settingsset)return settings;return futureradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timefuture=convertidtotime(button.id))})),pastradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id))})),settings}(),letterfilter=function(){let settings={basicletter:0,completionletter:0,postletter:0};return checkboxes.forEach((function(checkbox){if(checkbox.checked)switch(checkbox.id){case"basicletter":settings.basicletter=1;break;case"completionletter":settings.completionletter=1;break;case"postletter":settings.postletter=1}})),settings}();!function(userid,timefilterpast,timefilterfuture,basicletter,completionletter,postletter){let result;const data={methodname:"block_townsquare_record_usersettings",args:{userid:userid,timefilterpast:timefilterpast,timefilterfuture:timefilterfuture,basicletter:basicletter,completionletter:completionletter,postletter:postletter}};result=_ajax.default.call([data]);let el=document.getElementById("ts_usersettings_successlabel");el.style.display="block",el.style.opacity=1,el.fadeOutTimer&&clearInterval(el.fadeOutTimer);setTimeout((function(){el.fadeOutTimer=setInterval((function(){el.style.opacity>.4?el.style.opacity-=.1:el.style.opacity>0?el.style.opacity-=.2:(clearInterval(el.fadeOutTimer),el.style.display="none")}),100)}),3e3)}(userid,timespans.timepast,timespans.timefuture,letterfilter.basicletter,letterfilter.completionletter,letterfilter.postletter)}))},_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};const savebutton=document.getElementById("ts_usersettings_savebutton"),alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button"),checkboxes=document.querySelectorAll(".ts_letter_checkbox");function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}function converttimetoid(time,future){switch(time){case"15778463":return"ts_time_all";case"172800":return future?"ts_time_next_twodays":"ts_time_past_twodays";case"432000":return future?"ts_time_next_fivedays":"ts_time_last_fivedays";case"604800":return future?"ts_time_next_week":"ts_time_last_week";case"2592000":return future?"ts_time_next_month":"ts_time_last_month"}}})); //# sourceMappingURL=usersettings_save.min.js.map \ No newline at end of file diff --git a/amd/build/usersettings_save.min.js.map b/amd/build/usersettings_save.min.js.map index a034acd..ccf8a70 100644 --- a/amd/build/usersettings_save.min.js.map +++ b/amd/build/usersettings_save.min.js.map @@ -1 +1 @@ -{"version":3,"file":"usersettings_save.min.js","sources":["../src/usersettings_save.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 * Javascript to save the user settings in the database.\n *\n * This file implements 1 functionality:\n * - If the \"save settings\" button is pressed, store the settings in the database.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n// Get the save button for the user settings.\nconst savebutton = document.getElementById('ts_usersettings_savebutton');\n\n// Get the buttons from the time filter.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Get the checkboxes from the letter filter.\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n *\n * @param {number} userid The id of the current user.\n * @param {object} settingsfromdb The settings from the database, if there are any.\n */\nexport function init(userid, settingsfromdb) {\n // When the page is loaded, set the settings from the database.\n if (settingsfromdb) {\n executeusersettings(settingsfromdb);\n }\n\n // Add event listener to the save button.\n savebutton.addEventListener('click', async function() {\n\n // First step: collect the current settings.\n // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes.\n let timespans = collecttimefiltersettings();\n let letterfilter = collectletterfiltersettings();\n\n // Second step: store the usersettings in the database.\n await saveusersettings(userid, timespans['timepast'], timespans['timefuture'], letterfilter['basicletter'],\n letterfilter['completionletter'], letterfilter['postletter']);\n });\n}\n\n/**\n * Function to save the user settings in the database.\n * @param {number} userid\n * @param {number} timefilterpast\n * @param {number} timefilterfuture\n * @param {number} basicletter\n * @param {number} completionletter\n * @param {number} postletter\n * @returns {Promise<*>}\n */\nasync function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) {\n let result;\n result = await Ajax.call([{\n methodname: 'block_townsquare_record_usersettings',\n args: {\n userid: parseInt(userid),\n timefilterpast: timefilterpast,\n timefilterfuture: timefilterfuture,\n basicletter: basicletter,\n completionletter: completionletter,\n postletter: postletter,\n success: function() {\n console.log('Settings saved.');\n },\n },\n }]);\n // Show a success message.\n let el = document.getElementById('ts_usersettings_successlabel');\n el.style.display = 'block';\n el.style.opacity = 1.0;\n\n // Start a new setInterval timer to gradually fade out the label.\n if (el.fadeOutTimer) {\n clearInterval(el.fadeOutTimer);\n }\n setTimeout(function () {\n el.fadeOutTimer = setInterval(function () {\n if (el.style.opacity > 0.4) {\n el.style.opacity -= 0.1;\n } else if (el.style.opacity > 0) {\n el.style.opacity -= 0.2;\n } else {\n // Once opacity reaches 0, clear the timer and hide the label.\n clearInterval(el.fadeOutTimer);\n el.style.display = 'none';\n }\n }, 100);\n }, 3000);\n return result;\n}\n\n/**\n * Function to execute existing user settings when loading the townsquare.\n * @param {Object} settingsfromdb\n */\nfunction executeusersettings(settingsfromdb) {\n\n // First step: set the time filter settings.\n // Change the time into the correct radio button id.\n let futurebuttonid = converttimetoid(settingsfromdb['timefilterfuture'], true);\n let pastbuttonid = converttimetoid(settingsfromdb['timefilterpast'], false);\n\n // If the time span is a combination of past and future, go through the two radio buttons and activate the filter.\n if (futurebuttonid !== \"ts_time_all\") {\n futureradiobuttons.forEach(function(button) {\n if (button.id === futurebuttonid) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n }\n });\n pastradiobuttons.forEach(function(button) {\n if (button.id === pastbuttonid) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n }\n });\n } else {\n // If the time span is set to all time, activate the all time button.\n alltimebutton.forEach(function(button) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n });\n }\n\n // Second step: set the letter filter settings.\n // Per default all checkboxes are checked. If the setting is 0, uncheck the checkbox.\n checkboxes.forEach(function(checkbox) {\n let basiclettercheck = checkbox.id === 'basicletter' && settingsfromdb['basicletter'] === \"\";\n let completionlettercheck = checkbox.id === 'completionletter' && settingsfromdb['completionletter'] === \"0\";\n let postlettercheck = checkbox.id === 'postletter' && settingsfromdb['postletter'] === \"0\";\n\n if (basiclettercheck || completionlettercheck || postlettercheck) {\n checkbox.click();\n }\n });\n}\n\n/**\n * Function to collect the letter filter settings.\n * @returns {{basicletter: number, completionletter: number, postletter: number}}\n */\nfunction collectletterfiltersettings() {\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\n\n checkboxes.forEach(function(checkbox) {\n if (checkbox.checked) {\n switch(checkbox.id) {\n case \"basicletter\":\n settings['basicletter'] = 1;\n break;\n case \"completionletter\":\n settings['completionletter'] = 1;\n break;\n case \"postletter\":\n settings['postletter'] = 1;\n break;\n\n }\n }\n });\n // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit.\n return settings;\n}\n\n/**\n * Function to collect the time filter settings.\n * @returns {{timepast: number, timefuture: number}}\n */\nfunction collecttimefiltersettings() {\n let settings = { timepast: 0, timefuture: 0};\n let settingsset = false;\n\n // Get the relevant time spans of the time filter.\n // Check if the alltimebutton is set.\n alltimebutton.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n settings['timefuture'] = convertidtotime(button.id);\n settingsset = true;\n }\n });\n\n if (settingsset) {\n return settings;\n }\n\n // If the alltimebutton is not set, check which of the future/past buttons is set.\n futureradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timefuture'] = convertidtotime(button.id);\n }\n });\n\n pastradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n }\n });\n return settings;\n}\n\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n // TODO: Please use global functions if possible.\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n\n/**\n * Function to convert the time span to a radio button id.\n * @param {string} time\n * @param {boolean} future\n * @returns {string}\n */\nfunction converttimetoid(time, future) {\n switch (time) {\n case \"15778463\":\n return \"ts_time_all\";\n case \"172800\":\n if (future) {\n return \"ts_time_next_twodays\";\n }\n return \"ts_time_past_twodays\";\n case \"432000\":\n if (future) {\n return \"ts_time_next_fivedays\";\n }\n return \"ts_time_last_fivedays\";\n case \"604800\":\n if (future) {\n return \"ts_time_next_week\";\n }\n return \"ts_time_last_week\";\n case \"2592000\":\n if (future) {\n return \"ts_time_next_month\";\n\n }\n return \"ts_time_last_month\";\n }\n}\n"],"names":["userid","settingsfromdb","futurebuttonid","converttimetoid","pastbuttonid","futureradiobuttons","forEach","button","id","parentNode","classList","add","checked","dispatchEvent","Event","alltimebutton","remove","pastradiobuttons","checkboxes","checkbox","basiclettercheck","completionlettercheck","postlettercheck","click","executeusersettings","savebutton","addEventListener","async","timespans","settings","timepast","timefuture","settingsset","contains","convertidtotime","collecttimefiltersettings","letterfilter","collectletterfiltersettings","timefilterpast","timefilterfuture","basicletter","completionletter","postletter","result","Ajax","call","methodname","args","parseInt","success","console","log","el","document","getElementById","style","display","opacity","fadeOutTimer","clearInterval","setTimeout","setInterval","saveusersettings","querySelectorAll","time","future"],"mappings":";;;;;;;;;;oFA6CqBA,OAAQC,gBAErBA,yBAyEqBA,oBAIrBC,eAAiBC,gBAAgBF,eAAc,kBAAsB,GACrEG,aAAeD,gBAAgBF,eAAc,gBAAoB,GAG9C,gBAAnBC,gBACAG,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOC,KAAON,iBACdK,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,iBAItDC,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOC,KAAOJ,eACdG,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,kBAMtDD,cAAcT,SAAQ,SAASC,QAC3BA,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,cAMvCI,WAAWZ,SAAQ,SAASa,cACpBC,iBAAmC,gBAAhBD,SAASX,IAA0D,KAAlCP,eAAc,YAClEoB,sBAAwC,qBAAhBF,SAASX,IAAoE,MAAvCP,eAAc,iBAC5EqB,gBAAkC,eAAhBH,SAASX,IAAwD,MAAjCP,eAAc,YAEhEmB,kBAAoBC,uBAAyBC,kBAC7CH,SAASI,WAxHbC,CAAoBvB,gBAIxBwB,WAAWC,iBAAiB,SAASC,qBAI7BC,yBAqJJC,SAAW,CAAEC,SAAU,EAAGC,WAAY,GACtCC,aAAc,KAIlBjB,cAAcT,SAAQ,SAASC,QACxBA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgB3B,OAAOC,IAC9CqB,SAAQ,WAAiBK,gBAAgB3B,OAAOC,IAChDwB,aAAc,MAIjBA,mBACOH,gBAIXxB,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,WAAiBK,gBAAgB3B,OAAOC,QAIxDS,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAQ,SAAeK,gBAAgB3B,OAAOC,QAG/CqB,SArLaM,GACZC,4BAyHJP,SAAW,aAAgB,mBAAuB,aAAiB,UAEvEX,WAAWZ,SAAQ,SAASa,aACpBA,SAASP,eACFO,SAASX,QACP,cACDqB,SAAQ,YAAkB,YAEzB,mBACDA,SAAQ,iBAAuB,YAE9B,aACDA,SAAQ,WAAiB,MAOlCA,SA5IgBQ,wBAkBKrC,OAAQsC,eAAgBC,iBAAkBC,YAAaC,iBAAkBC,gBACjGC,OACJA,aAAeC,cAAKC,KAAK,CAAC,CACtBC,WAAY,uCACZC,KAAM,CACF/C,OAAQgD,SAAShD,QACjBsC,eAAgBA,eAChBC,iBAAkBA,iBAClBC,YAAaA,YACbC,iBAAkBA,iBAClBC,WAAYA,WACZO,QAAS,WACLC,QAAQC,IAAI,4BAKpBC,GAAKC,SAASC,eAAe,gCACjCF,GAAGG,MAAMC,QAAU,QACnBJ,GAAGG,MAAME,QAAU,EAGfL,GAAGM,cACHC,cAAcP,GAAGM,qBAErBE,YAAW,WACPR,GAAGM,aAAeG,aAAY,WACtBT,GAAGG,MAAME,QAAU,GACnBL,GAAGG,MAAME,SAAW,GACbL,GAAGG,MAAME,QAAU,EAC1BL,GAAGG,MAAME,SAAW,IAGpBE,cAAcP,GAAGM,cACjBN,GAAGG,MAAMC,QAAU,UAExB,OACJ,KACIb,OArDGmB,CAAiB9D,OAAQ4B,UAAS,SAAcA,UAAS,WAAgBQ,aAAY,YACpEA,aAAY,iBAAsBA,aAAY,0EAhCvEX,WAAa4B,SAASC,eAAe,8BAGrCvC,cAAgBsC,SAASU,iBAAiB,uBAC1C1D,mBAAqBgD,SAASU,iBAAiB,0BAC/C9C,iBAAmBoC,SAASU,iBAAiB,wBAG7C7C,WAAamC,SAASU,iBAAiB,gCAiNpC7B,gBAAgB1B,WAEdA,QACE,qBACM,aACN,2BACA,8BACM,WACN,4BACA,+BACM,UACN,wBACA,2BACM,WACN,yBACA,4BACM,iBAUVL,gBAAgB6D,KAAMC,eACnBD,UACC,iBACM,kBACN,gBACGC,OACO,uBAEJ,2BACN,gBACGA,OACO,wBAEJ,4BACN,gBACGA,OACO,oBAEJ,wBACN,iBACGA,OACO,qBAGJ"} \ No newline at end of file +{"version":3,"file":"usersettings_save.min.js","sources":["../src/usersettings_save.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 * Javascript to save the user settings in the database.\n *\n * This file implements 1 functionality:\n * - If the \"save settings\" button is pressed, store the settings in the database.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n// Get the save button for the user settings.\nconst savebutton = document.getElementById('ts_usersettings_savebutton');\n\n// Get the buttons from the time filter.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Get the checkboxes from the letter filter.\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n *\n * @param {number} userid The id of the current user.\n * @param {object} settingsfromdb The settings from the database, if there are any.\n */\nexport function init(userid, settingsfromdb) {\n // When the page is loaded, set the settings from the database.\n if (settingsfromdb) {\n executeusersettings(settingsfromdb);\n }\n\n // Add event listener to the save button.\n savebutton.addEventListener('click', async function() {\n\n // First step: collect the current settings.\n // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes.\n let timespans = collecttimefiltersettings();\n let letterfilter = collectletterfiltersettings();\n\n // Second step: store the usersettings in the database.\n saveusersettings(userid, timespans['timepast'], timespans['timefuture'], letterfilter['basicletter'],\n letterfilter['completionletter'], letterfilter['postletter']);\n });\n}\n\n/**\n * Function to save the user settings in the database.\n * @param {number} userid\n * @param {number} timefilterpast\n * @param {number} timefilterfuture\n * @param {number} basicletter\n * @param {number} completionletter\n * @param {number} postletter\n * @returns {Promise<*>}\n */\nfunction saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) {\n let result;\n\n const data = {\n methodname: 'block_townsquare_record_usersettings',\n args: {\n userid: userid,\n timefilterpast: timefilterpast,\n timefilterfuture: timefilterfuture,\n basicletter: basicletter,\n completionletter: completionletter,\n postletter: postletter,\n },\n };\n //console.log(data);\n result = Ajax.call([data]);\n\n //console.log(\"The result [0] object \",result[0]);\n\n // Show a success message.\n let el = document.getElementById('ts_usersettings_successlabel');\n el.style.display = 'block';\n el.style.opacity = 1.0;\n\n // Start a new setInterval timer to gradually fade out the label.\n if (el.fadeOutTimer) {\n clearInterval(el.fadeOutTimer);\n }\n setTimeout(function () {\n el.fadeOutTimer = setInterval(function () {\n if (el.style.opacity > 0.4) {\n el.style.opacity -= 0.1;\n } else if (el.style.opacity > 0) {\n el.style.opacity -= 0.2;\n } else {\n // Once opacity reaches 0, clear the timer and hide the label.\n clearInterval(el.fadeOutTimer);\n el.style.display = 'none';\n }\n }, 100);\n }, 3000);\n return result;\n\n}\n\n/**\n * Function to execute existing user settings when loading the townsquare.\n * @param {Object} settingsfromdb\n */\nfunction executeusersettings(settingsfromdb) {\n\n // First step: set the time filter settings.\n // Change the time into the correct radio button id.\n let futurebuttonid = converttimetoid(settingsfromdb['timefilterfuture'], true);\n let pastbuttonid = converttimetoid(settingsfromdb['timefilterpast'], false);\n\n // If the time span is a combination of past and future, go through the two radio buttons and activate the filter.\n if (futurebuttonid !== \"ts_time_all\") {\n futureradiobuttons.forEach(function(button) {\n if (button.id === futurebuttonid) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n }\n });\n pastradiobuttons.forEach(function(button) {\n if (button.id === pastbuttonid) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n }\n });\n } else {\n // If the time span is set to all time, activate the all time button.\n alltimebutton.forEach(function(button) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n });\n }\n\n // Second step: set the letter filter settings.\n // Per default all checkboxes are checked. If the setting is 0, uncheck the checkbox.\n checkboxes.forEach(function(checkbox) {\n let basiclettercheck = checkbox.id === 'basicletter' && settingsfromdb['basicletter'] === \"\";\n let completionlettercheck = checkbox.id === 'completionletter' && settingsfromdb['completionletter'] === \"0\";\n let postlettercheck = checkbox.id === 'postletter' && settingsfromdb['postletter'] === \"0\";\n\n if (basiclettercheck || completionlettercheck || postlettercheck) {\n checkbox.click();\n }\n });\n}\n\n/**\n * Function to collect the letter filter settings.\n * @returns {{basicletter: number, completionletter: number, postletter: number}}\n */\nfunction collectletterfiltersettings() {\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\n\n checkboxes.forEach(function(checkbox) {\n if (checkbox.checked) {\n switch(checkbox.id) {\n case \"basicletter\":\n settings['basicletter'] = 1;\n break;\n case \"completionletter\":\n settings['completionletter'] = 1;\n break;\n case \"postletter\":\n settings['postletter'] = 1;\n break;\n\n }\n }\n });\n // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit.\n return settings;\n}\n\n/**\n * Function to collect the time filter settings.\n * @returns {{timepast: number, timefuture: number}}\n */\nfunction collecttimefiltersettings() {\n let settings = { timepast: 0, timefuture: 0};\n let settingsset = false;\n\n // Get the relevant time spans of the time filter.\n // Check if the alltimebutton is set.\n alltimebutton.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n settings['timefuture'] = convertidtotime(button.id);\n settingsset = true;\n }\n });\n\n if (settingsset) {\n return settings;\n }\n\n // If the alltimebutton is not set, check which of the future/past buttons is set.\n futureradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timefuture'] = convertidtotime(button.id);\n }\n });\n\n pastradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n }\n });\n return settings;\n}\n\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n // TODO: Please use global functions if possible.\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n\n/**\n * Function to convert the time span to a radio button id.\n * @param {string} time\n * @param {boolean} future\n * @returns {string}\n */\nfunction converttimetoid(time, future) {\n switch (time) {\n case \"15778463\":\n return \"ts_time_all\";\n case \"172800\":\n if (future) {\n return \"ts_time_next_twodays\";\n }\n return \"ts_time_past_twodays\";\n case \"432000\":\n if (future) {\n return \"ts_time_next_fivedays\";\n }\n return \"ts_time_last_fivedays\";\n case \"604800\":\n if (future) {\n return \"ts_time_next_week\";\n }\n return \"ts_time_last_week\";\n case \"2592000\":\n if (future) {\n return \"ts_time_next_month\";\n\n }\n return \"ts_time_last_month\";\n }\n}\n"],"names":["obj","userid","settingsfromdb","futurebuttonid","converttimetoid","pastbuttonid","futureradiobuttons","forEach","button","id","parentNode","classList","add","checked","dispatchEvent","Event","alltimebutton","remove","pastradiobuttons","checkboxes","checkbox","basiclettercheck","completionlettercheck","postlettercheck","click","executeusersettings","savebutton","addEventListener","async","timespans","settings","timepast","timefuture","settingsset","contains","convertidtotime","collecttimefiltersettings","letterfilter","basicletter","completionletter","postletter","collectletterfiltersettings","timefilterpast","timefilterfuture","result","data","methodname","args","Ajax","call","el","document","getElementById","style","display","opacity","fadeOutTimer","clearInterval","setTimeout","setInterval","saveusersettings","_ajax","__esModule","default","querySelectorAll","time","future"],"mappings":"8FA0B6B,IAAAA;;;;;;;;;;2EAmBtB,SAAcC,OAAQC,gBAErBA,gBA6ER,SAA6BA,gBAIzB,IAAIC,eAAiBC,gBAAgBF,eAAiC,kBAAG,GACrEG,aAAeD,gBAAgBF,eAA+B,gBAAG,GAG9C,gBAAnBC,gBACAG,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOC,KAAON,iBACdK,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,iBAItDC,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOC,KAAOJ,eACdG,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,kBAMtDD,cAAcT,SAAQ,SAASC,QAC3BA,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,cAMvCI,WAAWZ,SAAQ,SAASa,UACxB,IAAIC,iBAAmC,gBAAhBD,SAASX,IAA0D,KAAlCP,eAA4B,YAChFoB,sBAAwC,qBAAhBF,SAASX,IAAoE,MAAvCP,eAAiC,iBAC/FqB,gBAAkC,eAAhBH,SAASX,IAAwD,MAAjCP,eAA2B,YAE7EmB,kBAAoBC,uBAAyBC,kBAC7CH,SAASI,WA5HbC,CAAoBvB,gBAIxBwB,WAAWC,iBAAiB,SAASC,iBAIjC,IAAIC,UAwJZ,WACI,IAAIC,SAAW,CAAEC,SAAU,EAAGC,WAAY,GACtCC,aAAc,EAalB,GATAjB,cAAcT,SAAQ,SAASC,QACxBA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAmB,SAAIK,gBAAgB3B,OAAOC,IAC9CqB,SAAqB,WAAIK,gBAAgB3B,OAAOC,IAChDwB,aAAc,MAIjBA,YACA,OAAOH,SAiBX,OAbAxB,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAqB,WAAIK,gBAAgB3B,OAAOC,QAIxDS,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAmB,SAAIK,gBAAgB3B,OAAOC,QAG/CqB,SAzLaM,GACZC,aA4HZ,WACI,IAAIP,SAAW,CAACQ,YAAe,EAAGC,iBAAoB,EAAGC,WAAc,GAmBvE,OAjBArB,WAAWZ,SAAQ,SAASa,UACxB,GAAIA,SAASP,QACT,OAAOO,SAASX,IACZ,IAAK,cACDqB,SAAsB,YAAI,EAC1B,MACJ,IAAK,mBACDA,SAA2B,iBAAI,EAC/B,MACJ,IAAK,aACDA,SAAqB,WAAI,MAOlCA,SAhJgBW,IAkB3B,SAA0BxC,OAAQyC,eAAgBC,iBAAkBL,YAAaC,iBAAkBC,YAC/F,IAAII,OAEJ,MAAMC,KAAO,CACTC,WAAY,uCACZC,KAAM,CACF9C,OAAQA,OACRyC,eAAgBA,eAChBC,iBAAkBA,iBAClBL,YAAaA,YACbC,iBAAkBA,iBAClBC,WAAYA,aAIpBI,OAASI,cAAKC,KAAK,CAACJ,OAKpB,IAAIK,GAAKC,SAASC,eAAe,gCACjCF,GAAGG,MAAMC,QAAU,QACnBJ,GAAGG,MAAME,QAAU,EAGfL,GAAGM,cACHC,cAAcP,GAAGM,cAErBE,YAAW,WACPR,GAAGM,aAAeG,aAAY,WACtBT,GAAGG,MAAME,QAAU,GACnBL,GAAGG,MAAME,SAAW,GACbL,GAAGG,MAAME,QAAU,EAC1BL,GAAGG,MAAME,SAAW,IAGpBE,cAAcP,GAAGM,cACjBN,GAAGG,MAAMC,QAAU,UAExB,OACJ,KAvDCM,CAAiB3D,OAAQ4B,UAAoB,SAAGA,UAAsB,WAAGQ,aAA0B,YAC/FA,aAA+B,iBAAGA,aAAyB,gBAnCvEwB,OAA6B7D,IAA7B6D,QAA6B7D,IAAA8D,WAAA9D,KAAA+D,QAAA/D,KAG7B,MAAM0B,WAAayB,SAASC,eAAe,8BAGrCpC,cAAgBmC,SAASa,iBAAiB,uBAC1C1D,mBAAqB6C,SAASa,iBAAiB,0BAC/C9C,iBAAmBiC,SAASa,iBAAiB,wBAG7C7C,WAAagC,SAASa,iBAAiB,uBAqN7C,SAAS7B,gBAAgB1B,IAErB,OAAOA,IACH,IAAK,cACD,OAAO,SACX,IAAK,uBACL,IAAK,uBACD,OAAO,OACX,IAAK,wBACL,IAAK,wBACD,OAAO,MACX,IAAK,oBACL,IAAK,oBACD,OAAO,OACX,IAAK,qBACL,IAAK,qBACD,OAAO,QAUnB,SAASL,gBAAgB6D,KAAMC,QAC3B,OAAQD,MACJ,IAAK,WACD,MAAO,cACX,IAAK,SACD,OAAIC,OACO,uBAEJ,uBACX,IAAK,SACD,OAAIA,OACO,wBAEJ,wBACX,IAAK,SACD,OAAIA,OACO,oBAEJ,oBACX,IAAK,UACD,OAAIA,OACO,qBAGJ,sBAElB"} \ No newline at end of file diff --git a/amd/src/usersettings_save.js b/amd/src/usersettings_save.js index 8ccf6b7..8b1172f 100644 --- a/amd/src/usersettings_save.js +++ b/amd/src/usersettings_save.js @@ -58,8 +58,8 @@ export function init(userid, settingsfromdb) { let letterfilter = collectletterfiltersettings(); // Second step: store the usersettings in the database. - await saveusersettings(userid, timespans['timepast'], timespans['timefuture'], letterfilter['basicletter'], - letterfilter['completionletter'], letterfilter['postletter']); + saveusersettings(userid, timespans['timepast'], timespans['timefuture'], letterfilter['basicletter'], + letterfilter['completionletter'], letterfilter['postletter']); }); } @@ -73,22 +73,25 @@ export function init(userid, settingsfromdb) { * @param {number} postletter * @returns {Promise<*>} */ -async function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) { +function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) { let result; - result = await Ajax.call([{ + + const data = { methodname: 'block_townsquare_record_usersettings', args: { - userid: parseInt(userid), + userid: userid, timefilterpast: timefilterpast, timefilterfuture: timefilterfuture, basicletter: basicletter, completionletter: completionletter, postletter: postletter, - success: function() { - console.log('Settings saved.'); - }, }, - }]); + }; + //console.log(data); + result = Ajax.call([data]); + + //console.log("The result [0] object ",result[0]); + // Show a success message. let el = document.getElementById('ts_usersettings_successlabel'); el.style.display = 'block'; @@ -112,6 +115,7 @@ async function saveusersettings(userid, timefilterpast, timefilterfuture, basicl }, 100); }, 3000); return result; + } /** diff --git a/tests/externallib_test.php b/tests/externallib_test.php index 8ebf8b8..f360582 100644 --- a/tests/externallib_test.php +++ b/tests/externallib_test.php @@ -36,7 +36,7 @@ * @copyright 2024 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * - * @covers \block_townsquare\block_townsquare_external::record_usersettings + * @covers block_townsquare_external::record_usersettings */ class externallib_test extends \advanced_testcase { @@ -68,7 +68,7 @@ public function test_record_usersettings(): void { $this->assertEquals(false, $record); // Call the function to record the user settings and check, if the record is created. - $result = \block_townsquare\block_townsquare_external::record_usersettings($usersetting->userid, + $result = block_townsquare_external::record_usersettings($usersetting->userid, $usersetting->timefilterpast, $usersetting->timefilterfuture, $usersetting->basicletter, $usersetting->completionletter, $usersetting->postletter); From 8fdd5c0e27f717fbd83b3dec515612f5ce14078b Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 17 May 2024 15:58:58 +0200 Subject: [PATCH 081/123] web service fixed --- amd/build/usersettings_save.min.js | 2 +- amd/build/usersettings_save.min.js.map | 2 +- amd/src/usersettings_save.js | 7 ++-- externallib.php => classes/external.php | 36 ++++++++++++------- db/services.php | 6 ++-- ...externallib_test.php => external_test.php} | 20 +++++------ version.php | 2 +- 7 files changed, 40 insertions(+), 35 deletions(-) rename externallib.php => classes/external.php (78%) rename tests/{externallib_test.php => external_test.php} (84%) diff --git a/amd/build/usersettings_save.min.js b/amd/build/usersettings_save.min.js index b8c1c21..ff6e923 100644 --- a/amd/build/usersettings_save.min.js +++ b/amd/build/usersettings_save.min.js @@ -5,7 +5,7 @@ define("block_townsquare/usersettings_save",["exports","core/ajax"],(function(_e * This file implements 1 functionality: * - If the "save settings" button is pressed, store the settings in the database. * - * @module block_townsquare/timefilter + * @module block_townsquare/usersettings_save * @copyright 2024 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,settingsfromdb){settingsfromdb&&function(settingsfromdb){let futurebuttonid=converttimetoid(settingsfromdb.timefilterfuture,!0),pastbuttonid=converttimetoid(settingsfromdb.timefilterpast,!1);"ts_time_all"!==futurebuttonid?(futureradiobuttons.forEach((function(button){button.id===futurebuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change")),alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))})),pastradiobuttons.forEach((function(button){button.id===pastbuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change")),alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))}))):alltimebutton.forEach((function(button){button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change"))}));checkboxes.forEach((function(checkbox){let basiclettercheck="basicletter"===checkbox.id&&""===settingsfromdb.basicletter,completionlettercheck="completionletter"===checkbox.id&&"0"===settingsfromdb.completionletter,postlettercheck="postletter"===checkbox.id&&"0"===settingsfromdb.postletter;(basiclettercheck||completionlettercheck||postlettercheck)&&checkbox.click()}))}(settingsfromdb);savebutton.addEventListener("click",(async function(){let timespans=function(){let settings={timepast:0,timefuture:0},settingsset=!1;if(alltimebutton.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id),settings.timefuture=convertidtotime(button.id),settingsset=!0)})),settingsset)return settings;return futureradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timefuture=convertidtotime(button.id))})),pastradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id))})),settings}(),letterfilter=function(){let settings={basicletter:0,completionletter:0,postletter:0};return checkboxes.forEach((function(checkbox){if(checkbox.checked)switch(checkbox.id){case"basicletter":settings.basicletter=1;break;case"completionletter":settings.completionletter=1;break;case"postletter":settings.postletter=1}})),settings}();!function(userid,timefilterpast,timefilterfuture,basicletter,completionletter,postletter){let result;const data={methodname:"block_townsquare_record_usersettings",args:{userid:userid,timefilterpast:timefilterpast,timefilterfuture:timefilterfuture,basicletter:basicletter,completionletter:completionletter,postletter:postletter}};result=_ajax.default.call([data]);let el=document.getElementById("ts_usersettings_successlabel");el.style.display="block",el.style.opacity=1,el.fadeOutTimer&&clearInterval(el.fadeOutTimer);setTimeout((function(){el.fadeOutTimer=setInterval((function(){el.style.opacity>.4?el.style.opacity-=.1:el.style.opacity>0?el.style.opacity-=.2:(clearInterval(el.fadeOutTimer),el.style.display="none")}),100)}),3e3)}(userid,timespans.timepast,timespans.timefuture,letterfilter.basicletter,letterfilter.completionletter,letterfilter.postletter)}))},_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};const savebutton=document.getElementById("ts_usersettings_savebutton"),alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button"),checkboxes=document.querySelectorAll(".ts_letter_checkbox");function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}function converttimetoid(time,future){switch(time){case"15778463":return"ts_time_all";case"172800":return future?"ts_time_next_twodays":"ts_time_past_twodays";case"432000":return future?"ts_time_next_fivedays":"ts_time_last_fivedays";case"604800":return future?"ts_time_next_week":"ts_time_last_week";case"2592000":return future?"ts_time_next_month":"ts_time_last_month"}}})); diff --git a/amd/build/usersettings_save.min.js.map b/amd/build/usersettings_save.min.js.map index ccf8a70..f83e831 100644 --- a/amd/build/usersettings_save.min.js.map +++ b/amd/build/usersettings_save.min.js.map @@ -1 +1 @@ -{"version":3,"file":"usersettings_save.min.js","sources":["../src/usersettings_save.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 * Javascript to save the user settings in the database.\n *\n * This file implements 1 functionality:\n * - If the \"save settings\" button is pressed, store the settings in the database.\n *\n * @module block_townsquare/timefilter\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n// Get the save button for the user settings.\nconst savebutton = document.getElementById('ts_usersettings_savebutton');\n\n// Get the buttons from the time filter.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Get the checkboxes from the letter filter.\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n *\n * @param {number} userid The id of the current user.\n * @param {object} settingsfromdb The settings from the database, if there are any.\n */\nexport function init(userid, settingsfromdb) {\n // When the page is loaded, set the settings from the database.\n if (settingsfromdb) {\n executeusersettings(settingsfromdb);\n }\n\n // Add event listener to the save button.\n savebutton.addEventListener('click', async function() {\n\n // First step: collect the current settings.\n // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes.\n let timespans = collecttimefiltersettings();\n let letterfilter = collectletterfiltersettings();\n\n // Second step: store the usersettings in the database.\n saveusersettings(userid, timespans['timepast'], timespans['timefuture'], letterfilter['basicletter'],\n letterfilter['completionletter'], letterfilter['postletter']);\n });\n}\n\n/**\n * Function to save the user settings in the database.\n * @param {number} userid\n * @param {number} timefilterpast\n * @param {number} timefilterfuture\n * @param {number} basicletter\n * @param {number} completionletter\n * @param {number} postletter\n * @returns {Promise<*>}\n */\nfunction saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) {\n let result;\n\n const data = {\n methodname: 'block_townsquare_record_usersettings',\n args: {\n userid: userid,\n timefilterpast: timefilterpast,\n timefilterfuture: timefilterfuture,\n basicletter: basicletter,\n completionletter: completionletter,\n postletter: postletter,\n },\n };\n //console.log(data);\n result = Ajax.call([data]);\n\n //console.log(\"The result [0] object \",result[0]);\n\n // Show a success message.\n let el = document.getElementById('ts_usersettings_successlabel');\n el.style.display = 'block';\n el.style.opacity = 1.0;\n\n // Start a new setInterval timer to gradually fade out the label.\n if (el.fadeOutTimer) {\n clearInterval(el.fadeOutTimer);\n }\n setTimeout(function () {\n el.fadeOutTimer = setInterval(function () {\n if (el.style.opacity > 0.4) {\n el.style.opacity -= 0.1;\n } else if (el.style.opacity > 0) {\n el.style.opacity -= 0.2;\n } else {\n // Once opacity reaches 0, clear the timer and hide the label.\n clearInterval(el.fadeOutTimer);\n el.style.display = 'none';\n }\n }, 100);\n }, 3000);\n return result;\n\n}\n\n/**\n * Function to execute existing user settings when loading the townsquare.\n * @param {Object} settingsfromdb\n */\nfunction executeusersettings(settingsfromdb) {\n\n // First step: set the time filter settings.\n // Change the time into the correct radio button id.\n let futurebuttonid = converttimetoid(settingsfromdb['timefilterfuture'], true);\n let pastbuttonid = converttimetoid(settingsfromdb['timefilterpast'], false);\n\n // If the time span is a combination of past and future, go through the two radio buttons and activate the filter.\n if (futurebuttonid !== \"ts_time_all\") {\n futureradiobuttons.forEach(function(button) {\n if (button.id === futurebuttonid) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n }\n });\n pastradiobuttons.forEach(function(button) {\n if (button.id === pastbuttonid) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n }\n });\n } else {\n // If the time span is set to all time, activate the all time button.\n alltimebutton.forEach(function(button) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n });\n }\n\n // Second step: set the letter filter settings.\n // Per default all checkboxes are checked. If the setting is 0, uncheck the checkbox.\n checkboxes.forEach(function(checkbox) {\n let basiclettercheck = checkbox.id === 'basicletter' && settingsfromdb['basicletter'] === \"\";\n let completionlettercheck = checkbox.id === 'completionletter' && settingsfromdb['completionletter'] === \"0\";\n let postlettercheck = checkbox.id === 'postletter' && settingsfromdb['postletter'] === \"0\";\n\n if (basiclettercheck || completionlettercheck || postlettercheck) {\n checkbox.click();\n }\n });\n}\n\n/**\n * Function to collect the letter filter settings.\n * @returns {{basicletter: number, completionletter: number, postletter: number}}\n */\nfunction collectletterfiltersettings() {\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\n\n checkboxes.forEach(function(checkbox) {\n if (checkbox.checked) {\n switch(checkbox.id) {\n case \"basicletter\":\n settings['basicletter'] = 1;\n break;\n case \"completionletter\":\n settings['completionletter'] = 1;\n break;\n case \"postletter\":\n settings['postletter'] = 1;\n break;\n\n }\n }\n });\n // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit.\n return settings;\n}\n\n/**\n * Function to collect the time filter settings.\n * @returns {{timepast: number, timefuture: number}}\n */\nfunction collecttimefiltersettings() {\n let settings = { timepast: 0, timefuture: 0};\n let settingsset = false;\n\n // Get the relevant time spans of the time filter.\n // Check if the alltimebutton is set.\n alltimebutton.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n settings['timefuture'] = convertidtotime(button.id);\n settingsset = true;\n }\n });\n\n if (settingsset) {\n return settings;\n }\n\n // If the alltimebutton is not set, check which of the future/past buttons is set.\n futureradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timefuture'] = convertidtotime(button.id);\n }\n });\n\n pastradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n }\n });\n return settings;\n}\n\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n // TODO: Please use global functions if possible.\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n\n/**\n * Function to convert the time span to a radio button id.\n * @param {string} time\n * @param {boolean} future\n * @returns {string}\n */\nfunction converttimetoid(time, future) {\n switch (time) {\n case \"15778463\":\n return \"ts_time_all\";\n case \"172800\":\n if (future) {\n return \"ts_time_next_twodays\";\n }\n return \"ts_time_past_twodays\";\n case \"432000\":\n if (future) {\n return \"ts_time_next_fivedays\";\n }\n return \"ts_time_last_fivedays\";\n case \"604800\":\n if (future) {\n return \"ts_time_next_week\";\n }\n return \"ts_time_last_week\";\n case \"2592000\":\n if (future) {\n return \"ts_time_next_month\";\n\n }\n return \"ts_time_last_month\";\n }\n}\n"],"names":["obj","userid","settingsfromdb","futurebuttonid","converttimetoid","pastbuttonid","futureradiobuttons","forEach","button","id","parentNode","classList","add","checked","dispatchEvent","Event","alltimebutton","remove","pastradiobuttons","checkboxes","checkbox","basiclettercheck","completionlettercheck","postlettercheck","click","executeusersettings","savebutton","addEventListener","async","timespans","settings","timepast","timefuture","settingsset","contains","convertidtotime","collecttimefiltersettings","letterfilter","basicletter","completionletter","postletter","collectletterfiltersettings","timefilterpast","timefilterfuture","result","data","methodname","args","Ajax","call","el","document","getElementById","style","display","opacity","fadeOutTimer","clearInterval","setTimeout","setInterval","saveusersettings","_ajax","__esModule","default","querySelectorAll","time","future"],"mappings":"8FA0B6B,IAAAA;;;;;;;;;;2EAmBtB,SAAcC,OAAQC,gBAErBA,gBA6ER,SAA6BA,gBAIzB,IAAIC,eAAiBC,gBAAgBF,eAAiC,kBAAG,GACrEG,aAAeD,gBAAgBF,eAA+B,gBAAG,GAG9C,gBAAnBC,gBACAG,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOC,KAAON,iBACdK,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,iBAItDC,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOC,KAAOJ,eACdG,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,kBAMtDD,cAAcT,SAAQ,SAASC,QAC3BA,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,cAMvCI,WAAWZ,SAAQ,SAASa,UACxB,IAAIC,iBAAmC,gBAAhBD,SAASX,IAA0D,KAAlCP,eAA4B,YAChFoB,sBAAwC,qBAAhBF,SAASX,IAAoE,MAAvCP,eAAiC,iBAC/FqB,gBAAkC,eAAhBH,SAASX,IAAwD,MAAjCP,eAA2B,YAE7EmB,kBAAoBC,uBAAyBC,kBAC7CH,SAASI,WA5HbC,CAAoBvB,gBAIxBwB,WAAWC,iBAAiB,SAASC,iBAIjC,IAAIC,UAwJZ,WACI,IAAIC,SAAW,CAAEC,SAAU,EAAGC,WAAY,GACtCC,aAAc,EAalB,GATAjB,cAAcT,SAAQ,SAASC,QACxBA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAmB,SAAIK,gBAAgB3B,OAAOC,IAC9CqB,SAAqB,WAAIK,gBAAgB3B,OAAOC,IAChDwB,aAAc,MAIjBA,YACA,OAAOH,SAiBX,OAbAxB,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAqB,WAAIK,gBAAgB3B,OAAOC,QAIxDS,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAmB,SAAIK,gBAAgB3B,OAAOC,QAG/CqB,SAzLaM,GACZC,aA4HZ,WACI,IAAIP,SAAW,CAACQ,YAAe,EAAGC,iBAAoB,EAAGC,WAAc,GAmBvE,OAjBArB,WAAWZ,SAAQ,SAASa,UACxB,GAAIA,SAASP,QACT,OAAOO,SAASX,IACZ,IAAK,cACDqB,SAAsB,YAAI,EAC1B,MACJ,IAAK,mBACDA,SAA2B,iBAAI,EAC/B,MACJ,IAAK,aACDA,SAAqB,WAAI,MAOlCA,SAhJgBW,IAkB3B,SAA0BxC,OAAQyC,eAAgBC,iBAAkBL,YAAaC,iBAAkBC,YAC/F,IAAII,OAEJ,MAAMC,KAAO,CACTC,WAAY,uCACZC,KAAM,CACF9C,OAAQA,OACRyC,eAAgBA,eAChBC,iBAAkBA,iBAClBL,YAAaA,YACbC,iBAAkBA,iBAClBC,WAAYA,aAIpBI,OAASI,cAAKC,KAAK,CAACJ,OAKpB,IAAIK,GAAKC,SAASC,eAAe,gCACjCF,GAAGG,MAAMC,QAAU,QACnBJ,GAAGG,MAAME,QAAU,EAGfL,GAAGM,cACHC,cAAcP,GAAGM,cAErBE,YAAW,WACPR,GAAGM,aAAeG,aAAY,WACtBT,GAAGG,MAAME,QAAU,GACnBL,GAAGG,MAAME,SAAW,GACbL,GAAGG,MAAME,QAAU,EAC1BL,GAAGG,MAAME,SAAW,IAGpBE,cAAcP,GAAGM,cACjBN,GAAGG,MAAMC,QAAU,UAExB,OACJ,KAvDCM,CAAiB3D,OAAQ4B,UAAoB,SAAGA,UAAsB,WAAGQ,aAA0B,YAC/FA,aAA+B,iBAAGA,aAAyB,gBAnCvEwB,OAA6B7D,IAA7B6D,QAA6B7D,IAAA8D,WAAA9D,KAAA+D,QAAA/D,KAG7B,MAAM0B,WAAayB,SAASC,eAAe,8BAGrCpC,cAAgBmC,SAASa,iBAAiB,uBAC1C1D,mBAAqB6C,SAASa,iBAAiB,0BAC/C9C,iBAAmBiC,SAASa,iBAAiB,wBAG7C7C,WAAagC,SAASa,iBAAiB,uBAqN7C,SAAS7B,gBAAgB1B,IAErB,OAAOA,IACH,IAAK,cACD,OAAO,SACX,IAAK,uBACL,IAAK,uBACD,OAAO,OACX,IAAK,wBACL,IAAK,wBACD,OAAO,MACX,IAAK,oBACL,IAAK,oBACD,OAAO,OACX,IAAK,qBACL,IAAK,qBACD,OAAO,QAUnB,SAASL,gBAAgB6D,KAAMC,QAC3B,OAAQD,MACJ,IAAK,WACD,MAAO,cACX,IAAK,SACD,OAAIC,OACO,uBAEJ,uBACX,IAAK,SACD,OAAIA,OACO,wBAEJ,wBACX,IAAK,SACD,OAAIA,OACO,oBAEJ,oBACX,IAAK,UACD,OAAIA,OACO,qBAGJ,sBAElB"} \ No newline at end of file +{"version":3,"file":"usersettings_save.min.js","sources":["../src/usersettings_save.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 * Javascript to save the user settings in the database.\n *\n * This file implements 1 functionality:\n * - If the \"save settings\" button is pressed, store the settings in the database.\n *\n * @module block_townsquare/usersettings_save\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n// Get the save button for the user settings.\nconst savebutton = document.getElementById('ts_usersettings_savebutton');\n\n// Get the buttons from the time filter.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Get the checkboxes from the letter filter.\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n *\n * @param {number} userid The id of the current user.\n * @param {object} settingsfromdb The settings from the database, if there are any.\n */\nexport function init(userid, settingsfromdb) {\n // When the page is loaded, set the settings from the database.\n if (settingsfromdb) {\n executeusersettings(settingsfromdb);\n }\n\n // Add event listener to the save button.\n\n savebutton.addEventListener('click', async function() {\n\n // First step: collect the current settings.\n // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes.\n let timespans = collecttimefiltersettings();\n let letterfilter = collectletterfiltersettings();\n\n // Second step: store the usersettings in the database.\n saveusersettings(userid, timespans['timepast'], timespans['timefuture'], letterfilter['basicletter'],\n letterfilter['completionletter'], letterfilter['postletter']);\n });\n}\n\n/**\n * Function to save the user settings in the database.\n * @param {number} userid\n * @param {number} timefilterpast\n * @param {number} timefilterfuture\n * @param {number} basicletter\n * @param {number} completionletter\n * @param {number} postletter\n * @returns {Promise<*>}\n */\nfunction saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) {\n let result;\n\n const data = {\n methodname: 'block_townsquare_record_usersettings',\n args: {\n userid: userid,\n timefilterpast: timefilterpast,\n timefilterfuture: timefilterfuture,\n basicletter: basicletter,\n completionletter: completionletter,\n postletter: postletter,\n },\n };\n //console.log(data);\n result = Ajax.call([data]);\n\n //console.log(\"The result [0] object \",result[0]);\n\n // Show a success message.\n let el = document.getElementById('ts_usersettings_successlabel');\n el.style.display = 'block';\n el.style.opacity = 1.0;\n\n // Start a new setInterval timer to gradually fade out the label.\n if (el.fadeOutTimer) {\n clearInterval(el.fadeOutTimer);\n }\n setTimeout(function () {\n el.fadeOutTimer = setInterval(function () {\n if (el.style.opacity > 0.4) {\n el.style.opacity -= 0.1;\n } else if (el.style.opacity > 0) {\n el.style.opacity -= 0.2;\n } else {\n // Once opacity reaches 0, clear the timer and hide the label.\n clearInterval(el.fadeOutTimer);\n el.style.display = 'none';\n }\n }, 100);\n }, 3000);\n return result;\n\n}\n\n/**\n * Function to execute existing user settings when loading the townsquare.\n * @param {Object} settingsfromdb\n */\nfunction executeusersettings(settingsfromdb) {\n\n // First step: set the time filter settings.\n // Change the time into the correct radio button id.\n let futurebuttonid = converttimetoid(settingsfromdb['timefilterfuture'], true);\n let pastbuttonid = converttimetoid(settingsfromdb['timefilterpast'], false);\n\n // If the time span is a combination of past and future, go through the two radio buttons and activate the filter.\n if (futurebuttonid !== \"ts_time_all\") {\n futureradiobuttons.forEach(function(button) {\n if (button.id === futurebuttonid) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n }\n });\n pastradiobuttons.forEach(function(button) {\n if (button.id === pastbuttonid) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n }\n });\n } else {\n // If the time span is set to all time, activate the all time button.\n alltimebutton.forEach(function(button) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n });\n }\n\n // Second step: set the letter filter settings.\n // Per default all checkboxes are checked. If the setting is 0, uncheck the checkbox.\n checkboxes.forEach(function(checkbox) {\n let basiclettercheck = checkbox.id === 'basicletter' && settingsfromdb['basicletter'] === \"\";\n let completionlettercheck = checkbox.id === 'completionletter' && settingsfromdb['completionletter'] === \"0\";\n let postlettercheck = checkbox.id === 'postletter' && settingsfromdb['postletter'] === \"0\";\n\n if (basiclettercheck || completionlettercheck || postlettercheck) {\n checkbox.click();\n }\n });\n}\n\n/**\n * Function to collect the letter filter settings.\n * @returns {{basicletter: number, completionletter: number, postletter: number}}\n */\nfunction collectletterfiltersettings() {\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\n\n checkboxes.forEach(function(checkbox) {\n if (checkbox.checked) {\n switch(checkbox.id) {\n case \"basicletter\":\n settings['basicletter'] = 1;\n break;\n case \"completionletter\":\n settings['completionletter'] = 1;\n break;\n case \"postletter\":\n settings['postletter'] = 1;\n break;\n\n }\n }\n });\n // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit.\n return settings;\n}\n\n/**\n * Function to collect the time filter settings.\n * @returns {{timepast: number, timefuture: number}}\n */\nfunction collecttimefiltersettings() {\n let settings = { timepast: 0, timefuture: 0};\n let settingsset = false;\n\n // Get the relevant time spans of the time filter.\n // Check if the alltimebutton is set.\n alltimebutton.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n settings['timefuture'] = convertidtotime(button.id);\n settingsset = true;\n }\n });\n\n if (settingsset) {\n return settings;\n }\n\n // If the alltimebutton is not set, check which of the future/past buttons is set.\n futureradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timefuture'] = convertidtotime(button.id);\n }\n });\n\n pastradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n }\n });\n return settings;\n}\n\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n // TODO: Please use global functions if possible.\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n\n/**\n * Function to convert the time span to a radio button id.\n * @param {string} time\n * @param {boolean} future\n * @returns {string}\n */\nfunction converttimetoid(time, future) {\n switch (time) {\n case \"15778463\":\n return \"ts_time_all\";\n case \"172800\":\n if (future) {\n return \"ts_time_next_twodays\";\n }\n return \"ts_time_past_twodays\";\n case \"432000\":\n if (future) {\n return \"ts_time_next_fivedays\";\n }\n return \"ts_time_last_fivedays\";\n case \"604800\":\n if (future) {\n return \"ts_time_next_week\";\n }\n return \"ts_time_last_week\";\n case \"2592000\":\n if (future) {\n return \"ts_time_next_month\";\n\n }\n return \"ts_time_last_month\";\n }\n}\n"],"names":["obj","userid","settingsfromdb","futurebuttonid","converttimetoid","pastbuttonid","futureradiobuttons","forEach","button","id","parentNode","classList","add","checked","dispatchEvent","Event","alltimebutton","remove","pastradiobuttons","checkboxes","checkbox","basiclettercheck","completionlettercheck","postlettercheck","click","executeusersettings","savebutton","addEventListener","async","timespans","settings","timepast","timefuture","settingsset","contains","convertidtotime","collecttimefiltersettings","letterfilter","basicletter","completionletter","postletter","collectletterfiltersettings","timefilterpast","timefilterfuture","result","data","methodname","args","Ajax","call","el","document","getElementById","style","display","opacity","fadeOutTimer","clearInterval","setTimeout","setInterval","saveusersettings","_ajax","__esModule","default","querySelectorAll","time","future"],"mappings":"8FA0B6B,IAAAA;;;;;;;;;;2EAmBtB,SAAcC,OAAQC,gBAErBA,gBA8ER,SAA6BA,gBAIzB,IAAIC,eAAiBC,gBAAgBF,eAAiC,kBAAG,GACrEG,aAAeD,gBAAgBF,eAA+B,gBAAG,GAG9C,gBAAnBC,gBACAG,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOC,KAAON,iBACdK,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,iBAItDC,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOC,KAAOJ,eACdG,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,kBAMtDD,cAAcT,SAAQ,SAASC,QAC3BA,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,cAMvCI,WAAWZ,SAAQ,SAASa,UACxB,IAAIC,iBAAmC,gBAAhBD,SAASX,IAA0D,KAAlCP,eAA4B,YAChFoB,sBAAwC,qBAAhBF,SAASX,IAAoE,MAAvCP,eAAiC,iBAC/FqB,gBAAkC,eAAhBH,SAASX,IAAwD,MAAjCP,eAA2B,YAE7EmB,kBAAoBC,uBAAyBC,kBAC7CH,SAASI,WA7HbC,CAAoBvB,gBAKxBwB,WAAWC,iBAAiB,SAASC,iBAIjC,IAAIC,UAwJZ,WACI,IAAIC,SAAW,CAAEC,SAAU,EAAGC,WAAY,GACtCC,aAAc,EAalB,GATAjB,cAAcT,SAAQ,SAASC,QACxBA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAmB,SAAIK,gBAAgB3B,OAAOC,IAC9CqB,SAAqB,WAAIK,gBAAgB3B,OAAOC,IAChDwB,aAAc,MAIjBA,YACA,OAAOH,SAiBX,OAbAxB,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAqB,WAAIK,gBAAgB3B,OAAOC,QAIxDS,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAmB,SAAIK,gBAAgB3B,OAAOC,QAG/CqB,SAzLaM,GACZC,aA4HZ,WACI,IAAIP,SAAW,CAACQ,YAAe,EAAGC,iBAAoB,EAAGC,WAAc,GAmBvE,OAjBArB,WAAWZ,SAAQ,SAASa,UACxB,GAAIA,SAASP,QACT,OAAOO,SAASX,IACZ,IAAK,cACDqB,SAAsB,YAAI,EAC1B,MACJ,IAAK,mBACDA,SAA2B,iBAAI,EAC/B,MACJ,IAAK,aACDA,SAAqB,WAAI,MAOlCA,SAhJgBW,IAkB3B,SAA0BxC,OAAQyC,eAAgBC,iBAAkBL,YAAaC,iBAAkBC,YAC/F,IAAII,OAEJ,MAAMC,KAAO,CACTC,WAAY,uCACZC,KAAM,CACF9C,OAAQA,OACRyC,eAAgBA,eAChBC,iBAAkBA,iBAClBL,YAAaA,YACbC,iBAAkBA,iBAClBC,WAAYA,aAIpBI,OAASI,cAAKC,KAAK,CAACJ,OAKpB,IAAIK,GAAKC,SAASC,eAAe,gCACjCF,GAAGG,MAAMC,QAAU,QACnBJ,GAAGG,MAAME,QAAU,EAGfL,GAAGM,cACHC,cAAcP,GAAGM,cAErBE,YAAW,WACPR,GAAGM,aAAeG,aAAY,WACtBT,GAAGG,MAAME,QAAU,GACnBL,GAAGG,MAAME,SAAW,GACbL,GAAGG,MAAME,QAAU,EAC1BL,GAAGG,MAAME,SAAW,IAGpBE,cAAcP,GAAGM,cACjBN,GAAGG,MAAMC,QAAU,UAExB,OACJ,KAvDCM,CAAiB3D,OAAQ4B,UAAoB,SAAGA,UAAsB,WAAGQ,aAA0B,YAC/FA,aAA+B,iBAAGA,aAAyB,gBApCvEwB,OAA6B7D,IAA7B6D,QAA6B7D,IAAA8D,WAAA9D,KAAA+D,QAAA/D,KAG7B,MAAM0B,WAAayB,SAASC,eAAe,8BAGrCpC,cAAgBmC,SAASa,iBAAiB,uBAC1C1D,mBAAqB6C,SAASa,iBAAiB,0BAC/C9C,iBAAmBiC,SAASa,iBAAiB,wBAG7C7C,WAAagC,SAASa,iBAAiB,uBAsN7C,SAAS7B,gBAAgB1B,IAErB,OAAOA,IACH,IAAK,cACD,OAAO,SACX,IAAK,uBACL,IAAK,uBACD,OAAO,OACX,IAAK,wBACL,IAAK,wBACD,OAAO,MACX,IAAK,oBACL,IAAK,oBACD,OAAO,OACX,IAAK,qBACL,IAAK,qBACD,OAAO,QAUnB,SAASL,gBAAgB6D,KAAMC,QAC3B,OAAQD,MACJ,IAAK,WACD,MAAO,cACX,IAAK,SACD,OAAIC,OACO,uBAEJ,uBACX,IAAK,SACD,OAAIA,OACO,wBAEJ,wBACX,IAAK,SACD,OAAIA,OACO,oBAEJ,oBACX,IAAK,UACD,OAAIA,OACO,qBAGJ,sBAElB"} \ No newline at end of file diff --git a/amd/src/usersettings_save.js b/amd/src/usersettings_save.js index 8b1172f..2136743 100644 --- a/amd/src/usersettings_save.js +++ b/amd/src/usersettings_save.js @@ -19,7 +19,7 @@ * This file implements 1 functionality: * - If the "save settings" button is pressed, store the settings in the database. * - * @module block_townsquare/timefilter + * @module block_townsquare/usersettings_save * @copyright 2024 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -58,7 +58,7 @@ export function init(userid, settingsfromdb) { let letterfilter = collectletterfiltersettings(); // Second step: store the usersettings in the database. - saveusersettings(userid, timespans['timepast'], timespans['timefuture'], letterfilter['basicletter'], + await saveusersettings(userid, timespans['timepast'], timespans['timefuture'], letterfilter['basicletter'], letterfilter['completionletter'], letterfilter['postletter']); }); } @@ -87,11 +87,8 @@ function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, postletter: postletter, }, }; - //console.log(data); result = Ajax.call([data]); - //console.log("The result [0] object ",result[0]); - // Show a success message. let el = document.getElementById('ts_usersettings_successlabel'); el.style.display = 'block'; diff --git a/externallib.php b/classes/external.php similarity index 78% rename from externallib.php rename to classes/external.php index c95dd55..fc9ed3a 100644 --- a/externallib.php +++ b/classes/external.php @@ -40,7 +40,7 @@ * @copyright 2024 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class block_townsquare_external extends external_api { +class external extends external_api { /** * Returns description of method parameters @@ -81,6 +81,17 @@ public static function record_usersettings_returns(): external_value { public static function record_usersettings($userid, $timefilterpast, $timefilterfuture, $basicletter, $completionletter, $postletter): bool { global $DB; + + // Parameter validation. + $params = self::validate_parameters(self::record_usersettings_parameters(), [ + 'userid' => $userid, + 'timefilterpast' => $timefilterpast, + 'timefilterfuture' => $timefilterfuture, + 'basicletter' => $basicletter, + 'completionletter' => $completionletter, + 'postletter' => $postletter, + ]); + // Check if the user already has a record in the database. if ($records = $DB->get_records('block_townsquare_preferences', ['userid' => $userid])) { // If there more than a record (it only should be only one), delete all of them and insert the new one. @@ -96,24 +107,23 @@ public static function record_usersettings($userid, $timefilterpast, $timefilter } else { // Upgrade the existing record. $record = reset($records); - $record->timefilterpast = $timefilterpast; - $record->timefilterfuture = $timefilterfuture; - $record->basicletter = $basicletter; - $record->completionletter = $completionletter; - $record->postletter = $postletter; + $record->timefilterpast = $params['timefilterpast']; + $record->timefilterfuture = $params['timefilterfuture']; + $record->basicletter = $params['basicletter']; + $record->completionletter = $params['completionletter']; + $record->postletter = $params['postletter']; $DB->update_record('block_townsquare_preferences', $record); return true; } } $record = new stdClass(); - $record->userid = $userid; - $record->timefilterpast = $timefilterpast; - $record->timefilterfuture = $timefilterfuture; - $record->basicletter = $basicletter; - $record->completionletter = $completionletter; - $record->postletter = $postletter; + $record->userid = $params['userid']; + $record->timefilterpast = $params['timefilterpast']; + $record->timefilterfuture = $params['timefilterfuture']; + $record->basicletter = $params['basicletter']; + $record->completionletter = $params['completionletter']; + $record->postletter = $params['postletter']; $DB->insert_record('block_townsquare_preferences', $record); return true; } - } diff --git a/db/services.php b/db/services.php index fbba3b4..87b6096 100644 --- a/db/services.php +++ b/db/services.php @@ -26,11 +26,11 @@ $functions = [ 'block_townsquare_record_usersettings' => [ - 'classname' => 'block_townsquare_external', + 'classname' => 'block_townsquare\external', 'methodname' => 'record_usersettings', - 'classpath' => 'blocks/townsquare/externallib.php', + 'classpath' => 'blocks/townsquare/classes/external.php', 'description' => 'Records the user settings for the townsquare block', - 'type' => 'write', + 'type' => 'read', 'ajax' => true, ], ]; diff --git a/tests/externallib_test.php b/tests/external_test.php similarity index 84% rename from tests/externallib_test.php rename to tests/external_test.php index f360582..b2ed162 100644 --- a/tests/externallib_test.php +++ b/tests/external_test.php @@ -36,13 +36,11 @@ * @copyright 2024 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * - * @covers block_townsquare_external::record_usersettings + * @covers \block_townsquare\external::record_usersettings */ -class externallib_test extends \advanced_testcase { +class external_test extends \advanced_testcase { public function setUp(): void { - global $CFG; - require_once($CFG->dirroot . '/blocks/townsquare/externallib.php'); $this->resetAfterTest(); } @@ -68,10 +66,10 @@ public function test_record_usersettings(): void { $this->assertEquals(false, $record); // Call the function to record the user settings and check, if the record is created. - $result = block_townsquare_external::record_usersettings($usersetting->userid, - $usersetting->timefilterpast, - $usersetting->timefilterfuture, $usersetting->basicletter, - $usersetting->completionletter, $usersetting->postletter); + $result = \block_townsquare\external::record_usersettings($usersetting->userid, + $usersetting->timefilterpast, + $usersetting->timefilterfuture, $usersetting->basicletter, + $usersetting->completionletter, $usersetting->postletter); $this->assertEquals(true, $result); $record = $DB->get_record('block_townsquare_preferences', ['userid' => $usersetting->userid]); @@ -91,9 +89,9 @@ public function test_record_usersettings(): void { $usersetting->postletter = 0; // Call the function to record the user settings and check, if the record is created. - $result = block_townsquare_external::record_usersettings($usersetting->userid, $usersetting->timefilterpast, - $usersetting->timefilterfuture, $usersetting->basicletter, - $usersetting->completionletter, $usersetting->postletter); + $result = \block_townsquare\external::record_usersettings($usersetting->userid, $usersetting->timefilterpast, + $usersetting->timefilterfuture, $usersetting->basicletter, + $usersetting->completionletter, $usersetting->postletter); $this->assertEquals(true, $result); $record = $DB->get_record('block_townsquare_preferences', ['userid' => $usersetting->userid]); diff --git a/version.php b/version.php index bfb54b8..1e19259 100644 --- a/version.php +++ b/version.php @@ -25,6 +25,6 @@ defined('MOODLE_INTERNAL') || die(); $plugin->component = 'block_townsquare'; $plugin->release = '0.1.0'; -$plugin->version = 2024032201; +$plugin->version = 2024051701; $plugin->requires = 2022041900; $plugin->maturity = MATURITY_ALPHA; From f657fe5ded5334710df47080638e83a024e4d065 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 17 May 2024 16:12:44 +0200 Subject: [PATCH 082/123] adapt external class for moodle 401 --- classes/external.php | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/classes/external.php b/classes/external.php index fc9ed3a..674e237 100644 --- a/classes/external.php +++ b/classes/external.php @@ -80,17 +80,18 @@ public static function record_usersettings_returns(): external_value { */ public static function record_usersettings($userid, $timefilterpast, $timefilterfuture, $basicletter, $completionletter, $postletter): bool { - global $DB; + global $DB, $CFG; // Parameter validation. - $params = self::validate_parameters(self::record_usersettings_parameters(), [ - 'userid' => $userid, - 'timefilterpast' => $timefilterpast, - 'timefilterfuture' => $timefilterfuture, - 'basicletter' => $basicletter, - 'completionletter' => $completionletter, - 'postletter' => $postletter, - ]); + if ($CFG->branch >= 402) { + $params = self::validate_parameters(self::record_usersettings_parameters(), [ + 'userid' => $userid, 'timefilterpast' => $timefilterpast, 'timefilterfuture' => $timefilterfuture, + 'basicletter' => $basicletter, 'completionletter' => $completionletter, 'postletter' => $postletter, + ]); + } else { + $params = ['userid' => $userid, 'timefilterpast' => $timefilterpast, 'timefilterfuture' => $timefilterfuture, + 'basicletter' => $basicletter, 'completionletter' => $completionletter, 'postletter' => $postletter, ]; + } // Check if the user already has a record in the database. if ($records = $DB->get_records('block_townsquare_preferences', ['userid' => $userid])) { From c35f6f452de3c7ffd45f4aae39a2768a2e2e5b94 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 17 May 2024 16:23:35 +0200 Subject: [PATCH 083/123] require externallib for moodle 401 --- classes/external.php | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/classes/external.php b/classes/external.php index 674e237..aa1b1f4 100644 --- a/classes/external.php +++ b/classes/external.php @@ -47,6 +47,10 @@ class external extends external_api { * @return external_function_parameters */ public static function record_usersettings_parameters(): external_function_parameters { + global $CFG; + if ($CFG->branch < 402) { + require_once("$CFG->libdir/externallib.php"); + } return new external_function_parameters( [ 'userid' => new external_value(PARAM_INT, 'the user id'), @@ -59,6 +63,8 @@ public static function record_usersettings_parameters(): external_function_param ); } + public static function record_usersettings_params(): {} + /** * Return the result of the record_usersettings function * @return external_value @@ -80,18 +86,13 @@ public static function record_usersettings_returns(): external_value { */ public static function record_usersettings($userid, $timefilterpast, $timefilterfuture, $basicletter, $completionletter, $postletter): bool { - global $DB, $CFG; + global $DB; // Parameter validation. - if ($CFG->branch >= 402) { - $params = self::validate_parameters(self::record_usersettings_parameters(), [ - 'userid' => $userid, 'timefilterpast' => $timefilterpast, 'timefilterfuture' => $timefilterfuture, - 'basicletter' => $basicletter, 'completionletter' => $completionletter, 'postletter' => $postletter, - ]); - } else { - $params = ['userid' => $userid, 'timefilterpast' => $timefilterpast, 'timefilterfuture' => $timefilterfuture, - 'basicletter' => $basicletter, 'completionletter' => $completionletter, 'postletter' => $postletter, ]; - } + $params = self::validate_parameters(self::record_usersettings_parameters(), [ + 'userid' => $userid, 'timefilterpast' => $timefilterpast, 'timefilterfuture' => $timefilterfuture, + 'basicletter' => $basicletter, 'completionletter' => $completionletter, 'postletter' => $postletter, + ]); // Check if the user already has a record in the database. if ($records = $DB->get_records('block_townsquare_preferences', ['userid' => $userid])) { From 52f74f41e3e019575c2d6339b2b4269166f247bc Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 17 May 2024 16:27:20 +0200 Subject: [PATCH 084/123] delete unused function --- classes/external.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/classes/external.php b/classes/external.php index aa1b1f4..677986f 100644 --- a/classes/external.php +++ b/classes/external.php @@ -63,8 +63,6 @@ public static function record_usersettings_parameters(): external_function_param ); } - public static function record_usersettings_params(): {} - /** * Return the result of the record_usersettings function * @return external_value From 03d3e813869fb4af166549ec528c999745913d66 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 17 May 2024 16:38:17 +0200 Subject: [PATCH 085/123] add branch condition and require externallib --- classes/external.php | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/classes/external.php b/classes/external.php index 677986f..f660634 100644 --- a/classes/external.php +++ b/classes/external.php @@ -32,6 +32,7 @@ global $CFG; require_once($CFG->dirroot . '/lib/externallib.php'); +require_once("$CFG->libdir/externallib.php"); /** * Class implementing the external API, esp. for AJAX functions. @@ -46,11 +47,7 @@ class external extends external_api { * Returns description of method parameters * @return external_function_parameters */ - public static function record_usersettings_parameters(): external_function_parameters { - global $CFG; - if ($CFG->branch < 402) { - require_once("$CFG->libdir/externallib.php"); - } + public static function record_usersettings_parameters() { return new external_function_parameters( [ 'userid' => new external_value(PARAM_INT, 'the user id'), @@ -84,13 +81,19 @@ public static function record_usersettings_returns(): external_value { */ public static function record_usersettings($userid, $timefilterpast, $timefilterfuture, $basicletter, $completionletter, $postletter): bool { - global $DB; + global $DB, $CFG; // Parameter validation. - $params = self::validate_parameters(self::record_usersettings_parameters(), [ - 'userid' => $userid, 'timefilterpast' => $timefilterpast, 'timefilterfuture' => $timefilterfuture, - 'basicletter' => $basicletter, 'completionletter' => $completionletter, 'postletter' => $postletter, - ]); + if ($CFG->branch >= 402) { + $params = self::validate_parameters(self::record_usersettings_parameters(), [ + 'userid' => $userid, 'timefilterpast' => $timefilterpast, 'timefilterfuture' => $timefilterfuture, + 'basicletter' => $basicletter, 'completionletter' => $completionletter, 'postletter' => $postletter, + ]); + } else { + $params = [ + 'userid' => $userid, 'timefilterpast' => $timefilterpast, 'timefilterfuture' => $timefilterfuture, + 'basicletter' => $basicletter, 'completionletter' => $completionletter, 'postletter' => $postletter, ]; + } // Check if the user already has a record in the database. if ($records = $DB->get_records('block_townsquare_preferences', ['userid' => $userid])) { From 7bbecd7d8d8343951a22ceac541fc4f7897e821a Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 17 May 2024 16:48:56 +0200 Subject: [PATCH 086/123] try to fix behat failing in M4.1 --- db/services.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/db/services.php b/db/services.php index 87b6096..5b177bd 100644 --- a/db/services.php +++ b/db/services.php @@ -24,6 +24,10 @@ */ defined('MOODLE_INTERNAL') || die; +// TODO: Delete the include when Moodle 4.1 is no longer supported. +global $CFG; +require_once("$CFG->libdir/externallib.php"); + $functions = [ 'block_townsquare_record_usersettings' => [ 'classname' => 'block_townsquare\external', From 7d0f2a32e6be212ec27a78dbe7a5c5d7788cba0f Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 17 May 2024 16:58:39 +0200 Subject: [PATCH 087/123] add annotation to phpunit --- tests/external_test.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/external_test.php b/tests/external_test.php index b2ed162..d88e3e8 100644 --- a/tests/external_test.php +++ b/tests/external_test.php @@ -37,6 +37,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * * @covers \block_townsquare\external::record_usersettings + * @runTestsInSeparateProcesses */ class external_test extends \advanced_testcase { From 447ff94a968be6eda61c255de6c7d0f48fd183f0 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 17 May 2024 17:05:59 +0200 Subject: [PATCH 088/123] delete require once in services --- db/services.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/db/services.php b/db/services.php index 5b177bd..87b6096 100644 --- a/db/services.php +++ b/db/services.php @@ -24,10 +24,6 @@ */ defined('MOODLE_INTERNAL') || die; -// TODO: Delete the include when Moodle 4.1 is no longer supported. -global $CFG; -require_once("$CFG->libdir/externallib.php"); - $functions = [ 'block_townsquare_record_usersettings' => [ 'classname' => 'block_townsquare\external', From 58c5cc4176397b39fb8dff3943c7ee070d29dcff Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 23 May 2024 10:46:50 +0200 Subject: [PATCH 089/123] get subplugins events only when available --- classes/townsquareevents.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/classes/townsquareevents.php b/classes/townsquareevents.php index e833d79..b87d56e 100644 --- a/classes/townsquareevents.php +++ b/classes/townsquareevents.php @@ -33,7 +33,6 @@ global $CFG; require_once($CFG->dirroot . '/calendar/lib.php'); require_once($CFG->dirroot . '/blocks/townsquare/locallib.php'); -require_once($CFG->dirroot . '/local/townsquaresupport/lib.php'); /** * Class to get events and posts that will be shown in the townsquare block.. @@ -72,10 +71,17 @@ public function __construct() { * @return array */ public function get_all_events_sorted(): array { + global $CFG; $coreevents = $this->get_coreevents(); $postevents = $this->get_postevents(); - $subpluginevents = townsquaresupport_get_subplugin_events(); + // Check if the townsquaresupport plugin is installed. + $localplugins = \core_plugin_manager::instance()->get_plugins_of_type('local'); + $subpluginevents = []; + if (array_key_exists('townsquaresupport', $localplugins)) { + require_once($CFG->dirroot . '/local/townsquaresupport/lib.php'); + $subpluginevents = townsquaresupport_get_subplugin_events(); + } // Merge the events in a sorted order. $events = $coreevents + $postevents + $subpluginevents; return townsquare_mergesort($events); From 8528555cc0ae785bb91b8267b7085d15bcbcfdba Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 24 May 2024 15:07:44 +0200 Subject: [PATCH 090/123] change button activition effect --- amd/build/usersettings_save.min.js | 2 +- amd/build/usersettings_save.min.js.map | 2 +- amd/src/usersettings_save.js | 28 +++++++------------------- styles.css | 4 ++++ version.php | 2 +- 5 files changed, 14 insertions(+), 24 deletions(-) diff --git a/amd/build/usersettings_save.min.js b/amd/build/usersettings_save.min.js index ff6e923..d1ebe0e 100644 --- a/amd/build/usersettings_save.min.js +++ b/amd/build/usersettings_save.min.js @@ -8,6 +8,6 @@ define("block_townsquare/usersettings_save",["exports","core/ajax"],(function(_e * @module block_townsquare/usersettings_save * @copyright 2024 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,settingsfromdb){settingsfromdb&&function(settingsfromdb){let futurebuttonid=converttimetoid(settingsfromdb.timefilterfuture,!0),pastbuttonid=converttimetoid(settingsfromdb.timefilterpast,!1);"ts_time_all"!==futurebuttonid?(futureradiobuttons.forEach((function(button){button.id===futurebuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change")),alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))})),pastradiobuttons.forEach((function(button){button.id===pastbuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change")),alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))}))):alltimebutton.forEach((function(button){button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change"))}));checkboxes.forEach((function(checkbox){let basiclettercheck="basicletter"===checkbox.id&&""===settingsfromdb.basicletter,completionlettercheck="completionletter"===checkbox.id&&"0"===settingsfromdb.completionletter,postlettercheck="postletter"===checkbox.id&&"0"===settingsfromdb.postletter;(basiclettercheck||completionlettercheck||postlettercheck)&&checkbox.click()}))}(settingsfromdb);savebutton.addEventListener("click",(async function(){let timespans=function(){let settings={timepast:0,timefuture:0},settingsset=!1;if(alltimebutton.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id),settings.timefuture=convertidtotime(button.id),settingsset=!0)})),settingsset)return settings;return futureradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timefuture=convertidtotime(button.id))})),pastradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id))})),settings}(),letterfilter=function(){let settings={basicletter:0,completionletter:0,postletter:0};return checkboxes.forEach((function(checkbox){if(checkbox.checked)switch(checkbox.id){case"basicletter":settings.basicletter=1;break;case"completionletter":settings.completionletter=1;break;case"postletter":settings.postletter=1}})),settings}();!function(userid,timefilterpast,timefilterfuture,basicletter,completionletter,postletter){let result;const data={methodname:"block_townsquare_record_usersettings",args:{userid:userid,timefilterpast:timefilterpast,timefilterfuture:timefilterfuture,basicletter:basicletter,completionletter:completionletter,postletter:postletter}};result=_ajax.default.call([data]);let el=document.getElementById("ts_usersettings_successlabel");el.style.display="block",el.style.opacity=1,el.fadeOutTimer&&clearInterval(el.fadeOutTimer);setTimeout((function(){el.fadeOutTimer=setInterval((function(){el.style.opacity>.4?el.style.opacity-=.1:el.style.opacity>0?el.style.opacity-=.2:(clearInterval(el.fadeOutTimer),el.style.display="none")}),100)}),3e3)}(userid,timespans.timepast,timespans.timefuture,letterfilter.basicletter,letterfilter.completionletter,letterfilter.postletter)}))},_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};const savebutton=document.getElementById("ts_usersettings_savebutton"),alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button"),checkboxes=document.querySelectorAll(".ts_letter_checkbox");function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}function converttimetoid(time,future){switch(time){case"15778463":return"ts_time_all";case"172800":return future?"ts_time_next_twodays":"ts_time_past_twodays";case"432000":return future?"ts_time_next_fivedays":"ts_time_last_fivedays";case"604800":return future?"ts_time_next_week":"ts_time_last_week";case"2592000":return future?"ts_time_next_month":"ts_time_last_month"}}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,settingsfromdb){settingsfromdb&&function(settingsfromdb){let futurebuttonid=converttimetoid(settingsfromdb.timefilterfuture,!0),pastbuttonid=converttimetoid(settingsfromdb.timefilterpast,!1);"ts_time_all"!==futurebuttonid?(futureradiobuttons.forEach((function(button){button.id===futurebuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change")),alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))})),pastradiobuttons.forEach((function(button){button.id===pastbuttonid&&(button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change")),alltimebutton.forEach((function(alltimebutton){alltimebutton.checked=!1,alltimebutton.parentNode.classList.remove("active")})))}))):alltimebutton.forEach((function(button){button.parentNode.classList.add("active"),button.checked=!0,button.dispatchEvent(new Event("change"))}));checkboxes.forEach((function(checkbox){let basiclettercheck="basicletter"===checkbox.id&&""===settingsfromdb.basicletter,completionlettercheck="completionletter"===checkbox.id&&"0"===settingsfromdb.completionletter,postlettercheck="postletter"===checkbox.id&&"0"===settingsfromdb.postletter;(basiclettercheck||completionlettercheck||postlettercheck)&&checkbox.click()}))}(settingsfromdb);savebutton.addEventListener("click",(async function(){let timespans=function(){let settings={timepast:0,timefuture:0},settingsset=!1;if(alltimebutton.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id),settings.timefuture=convertidtotime(button.id),settingsset=!0)})),settingsset)return settings;return futureradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timefuture=convertidtotime(button.id))})),pastradiobuttons.forEach((function(button){button.parentNode.classList.contains("active")&&(settings.timepast=convertidtotime(button.id))})),settings}(),letterfilter=function(){let settings={basicletter:0,completionletter:0,postletter:0};return checkboxes.forEach((function(checkbox){if(checkbox.checked)switch(checkbox.id){case"basicletter":settings.basicletter=1;break;case"completionletter":settings.completionletter=1;break;case"postletter":settings.postletter=1}})),settings}();await function(userid,timefilterpast,timefilterfuture,basicletter,completionletter,postletter){let result;const data={methodname:"block_townsquare_record_usersettings",args:{userid:userid,timefilterpast:timefilterpast,timefilterfuture:timefilterfuture,basicletter:basicletter,completionletter:completionletter,postletter:postletter}};return result=_ajax.default.call([data]),savebutton.classList.add("bg-success","text-white","ts_button_transition"),setTimeout((function(){savebutton.classList.remove("bg-success"),savebutton.classList.remove("text-white")}),1500),result}(userid,timespans.timepast,timespans.timefuture,letterfilter.basicletter,letterfilter.completionletter,letterfilter.postletter)}))},_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};const savebutton=document.getElementById("ts_usersettings_savebutton"),alltimebutton=document.querySelectorAll(".ts_all_time_button"),futureradiobuttons=document.querySelectorAll(".ts_future_time_button"),pastradiobuttons=document.querySelectorAll(".ts_past_time_button"),checkboxes=document.querySelectorAll(".ts_letter_checkbox");function convertidtotime(id){switch(id){case"ts_time_all":return 15778463;case"ts_time_next_twodays":case"ts_time_last_twodays":return 172800;case"ts_time_next_fivedays":case"ts_time_last_fivedays":return 432e3;case"ts_time_next_week":case"ts_time_last_week":return 604800;case"ts_time_next_month":case"ts_time_last_month":return 2592e3}}function converttimetoid(time,future){switch(time){case"15778463":return"ts_time_all";case"172800":return future?"ts_time_next_twodays":"ts_time_past_twodays";case"432000":return future?"ts_time_next_fivedays":"ts_time_last_fivedays";case"604800":return future?"ts_time_next_week":"ts_time_last_week";case"2592000":return future?"ts_time_next_month":"ts_time_last_month"}}})); //# sourceMappingURL=usersettings_save.min.js.map \ No newline at end of file diff --git a/amd/build/usersettings_save.min.js.map b/amd/build/usersettings_save.min.js.map index f83e831..8cc2c92 100644 --- a/amd/build/usersettings_save.min.js.map +++ b/amd/build/usersettings_save.min.js.map @@ -1 +1 @@ -{"version":3,"file":"usersettings_save.min.js","sources":["../src/usersettings_save.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 * Javascript to save the user settings in the database.\n *\n * This file implements 1 functionality:\n * - If the \"save settings\" button is pressed, store the settings in the database.\n *\n * @module block_townsquare/usersettings_save\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n// Get the save button for the user settings.\nconst savebutton = document.getElementById('ts_usersettings_savebutton');\n\n// Get the buttons from the time filter.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Get the checkboxes from the letter filter.\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n *\n * @param {number} userid The id of the current user.\n * @param {object} settingsfromdb The settings from the database, if there are any.\n */\nexport function init(userid, settingsfromdb) {\n // When the page is loaded, set the settings from the database.\n if (settingsfromdb) {\n executeusersettings(settingsfromdb);\n }\n\n // Add event listener to the save button.\n\n savebutton.addEventListener('click', async function() {\n\n // First step: collect the current settings.\n // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes.\n let timespans = collecttimefiltersettings();\n let letterfilter = collectletterfiltersettings();\n\n // Second step: store the usersettings in the database.\n saveusersettings(userid, timespans['timepast'], timespans['timefuture'], letterfilter['basicletter'],\n letterfilter['completionletter'], letterfilter['postletter']);\n });\n}\n\n/**\n * Function to save the user settings in the database.\n * @param {number} userid\n * @param {number} timefilterpast\n * @param {number} timefilterfuture\n * @param {number} basicletter\n * @param {number} completionletter\n * @param {number} postletter\n * @returns {Promise<*>}\n */\nfunction saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) {\n let result;\n\n const data = {\n methodname: 'block_townsquare_record_usersettings',\n args: {\n userid: userid,\n timefilterpast: timefilterpast,\n timefilterfuture: timefilterfuture,\n basicletter: basicletter,\n completionletter: completionletter,\n postletter: postletter,\n },\n };\n //console.log(data);\n result = Ajax.call([data]);\n\n //console.log(\"The result [0] object \",result[0]);\n\n // Show a success message.\n let el = document.getElementById('ts_usersettings_successlabel');\n el.style.display = 'block';\n el.style.opacity = 1.0;\n\n // Start a new setInterval timer to gradually fade out the label.\n if (el.fadeOutTimer) {\n clearInterval(el.fadeOutTimer);\n }\n setTimeout(function () {\n el.fadeOutTimer = setInterval(function () {\n if (el.style.opacity > 0.4) {\n el.style.opacity -= 0.1;\n } else if (el.style.opacity > 0) {\n el.style.opacity -= 0.2;\n } else {\n // Once opacity reaches 0, clear the timer and hide the label.\n clearInterval(el.fadeOutTimer);\n el.style.display = 'none';\n }\n }, 100);\n }, 3000);\n return result;\n\n}\n\n/**\n * Function to execute existing user settings when loading the townsquare.\n * @param {Object} settingsfromdb\n */\nfunction executeusersettings(settingsfromdb) {\n\n // First step: set the time filter settings.\n // Change the time into the correct radio button id.\n let futurebuttonid = converttimetoid(settingsfromdb['timefilterfuture'], true);\n let pastbuttonid = converttimetoid(settingsfromdb['timefilterpast'], false);\n\n // If the time span is a combination of past and future, go through the two radio buttons and activate the filter.\n if (futurebuttonid !== \"ts_time_all\") {\n futureradiobuttons.forEach(function(button) {\n if (button.id === futurebuttonid) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n }\n });\n pastradiobuttons.forEach(function(button) {\n if (button.id === pastbuttonid) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n }\n });\n } else {\n // If the time span is set to all time, activate the all time button.\n alltimebutton.forEach(function(button) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n });\n }\n\n // Second step: set the letter filter settings.\n // Per default all checkboxes are checked. If the setting is 0, uncheck the checkbox.\n checkboxes.forEach(function(checkbox) {\n let basiclettercheck = checkbox.id === 'basicletter' && settingsfromdb['basicletter'] === \"\";\n let completionlettercheck = checkbox.id === 'completionletter' && settingsfromdb['completionletter'] === \"0\";\n let postlettercheck = checkbox.id === 'postletter' && settingsfromdb['postletter'] === \"0\";\n\n if (basiclettercheck || completionlettercheck || postlettercheck) {\n checkbox.click();\n }\n });\n}\n\n/**\n * Function to collect the letter filter settings.\n * @returns {{basicletter: number, completionletter: number, postletter: number}}\n */\nfunction collectletterfiltersettings() {\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\n\n checkboxes.forEach(function(checkbox) {\n if (checkbox.checked) {\n switch(checkbox.id) {\n case \"basicletter\":\n settings['basicletter'] = 1;\n break;\n case \"completionletter\":\n settings['completionletter'] = 1;\n break;\n case \"postletter\":\n settings['postletter'] = 1;\n break;\n\n }\n }\n });\n // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit.\n return settings;\n}\n\n/**\n * Function to collect the time filter settings.\n * @returns {{timepast: number, timefuture: number}}\n */\nfunction collecttimefiltersettings() {\n let settings = { timepast: 0, timefuture: 0};\n let settingsset = false;\n\n // Get the relevant time spans of the time filter.\n // Check if the alltimebutton is set.\n alltimebutton.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n settings['timefuture'] = convertidtotime(button.id);\n settingsset = true;\n }\n });\n\n if (settingsset) {\n return settings;\n }\n\n // If the alltimebutton is not set, check which of the future/past buttons is set.\n futureradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timefuture'] = convertidtotime(button.id);\n }\n });\n\n pastradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n }\n });\n return settings;\n}\n\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n // TODO: Please use global functions if possible.\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n\n/**\n * Function to convert the time span to a radio button id.\n * @param {string} time\n * @param {boolean} future\n * @returns {string}\n */\nfunction converttimetoid(time, future) {\n switch (time) {\n case \"15778463\":\n return \"ts_time_all\";\n case \"172800\":\n if (future) {\n return \"ts_time_next_twodays\";\n }\n return \"ts_time_past_twodays\";\n case \"432000\":\n if (future) {\n return \"ts_time_next_fivedays\";\n }\n return \"ts_time_last_fivedays\";\n case \"604800\":\n if (future) {\n return \"ts_time_next_week\";\n }\n return \"ts_time_last_week\";\n case \"2592000\":\n if (future) {\n return \"ts_time_next_month\";\n\n }\n return \"ts_time_last_month\";\n }\n}\n"],"names":["obj","userid","settingsfromdb","futurebuttonid","converttimetoid","pastbuttonid","futureradiobuttons","forEach","button","id","parentNode","classList","add","checked","dispatchEvent","Event","alltimebutton","remove","pastradiobuttons","checkboxes","checkbox","basiclettercheck","completionlettercheck","postlettercheck","click","executeusersettings","savebutton","addEventListener","async","timespans","settings","timepast","timefuture","settingsset","contains","convertidtotime","collecttimefiltersettings","letterfilter","basicletter","completionletter","postletter","collectletterfiltersettings","timefilterpast","timefilterfuture","result","data","methodname","args","Ajax","call","el","document","getElementById","style","display","opacity","fadeOutTimer","clearInterval","setTimeout","setInterval","saveusersettings","_ajax","__esModule","default","querySelectorAll","time","future"],"mappings":"8FA0B6B,IAAAA;;;;;;;;;;2EAmBtB,SAAcC,OAAQC,gBAErBA,gBA8ER,SAA6BA,gBAIzB,IAAIC,eAAiBC,gBAAgBF,eAAiC,kBAAG,GACrEG,aAAeD,gBAAgBF,eAA+B,gBAAG,GAG9C,gBAAnBC,gBACAG,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOC,KAAON,iBACdK,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,iBAItDC,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOC,KAAOJ,eACdG,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,kBAMtDD,cAAcT,SAAQ,SAASC,QAC3BA,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,cAMvCI,WAAWZ,SAAQ,SAASa,UACxB,IAAIC,iBAAmC,gBAAhBD,SAASX,IAA0D,KAAlCP,eAA4B,YAChFoB,sBAAwC,qBAAhBF,SAASX,IAAoE,MAAvCP,eAAiC,iBAC/FqB,gBAAkC,eAAhBH,SAASX,IAAwD,MAAjCP,eAA2B,YAE7EmB,kBAAoBC,uBAAyBC,kBAC7CH,SAASI,WA7HbC,CAAoBvB,gBAKxBwB,WAAWC,iBAAiB,SAASC,iBAIjC,IAAIC,UAwJZ,WACI,IAAIC,SAAW,CAAEC,SAAU,EAAGC,WAAY,GACtCC,aAAc,EAalB,GATAjB,cAAcT,SAAQ,SAASC,QACxBA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAmB,SAAIK,gBAAgB3B,OAAOC,IAC9CqB,SAAqB,WAAIK,gBAAgB3B,OAAOC,IAChDwB,aAAc,MAIjBA,YACA,OAAOH,SAiBX,OAbAxB,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAqB,WAAIK,gBAAgB3B,OAAOC,QAIxDS,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAmB,SAAIK,gBAAgB3B,OAAOC,QAG/CqB,SAzLaM,GACZC,aA4HZ,WACI,IAAIP,SAAW,CAACQ,YAAe,EAAGC,iBAAoB,EAAGC,WAAc,GAmBvE,OAjBArB,WAAWZ,SAAQ,SAASa,UACxB,GAAIA,SAASP,QACT,OAAOO,SAASX,IACZ,IAAK,cACDqB,SAAsB,YAAI,EAC1B,MACJ,IAAK,mBACDA,SAA2B,iBAAI,EAC/B,MACJ,IAAK,aACDA,SAAqB,WAAI,MAOlCA,SAhJgBW,IAkB3B,SAA0BxC,OAAQyC,eAAgBC,iBAAkBL,YAAaC,iBAAkBC,YAC/F,IAAII,OAEJ,MAAMC,KAAO,CACTC,WAAY,uCACZC,KAAM,CACF9C,OAAQA,OACRyC,eAAgBA,eAChBC,iBAAkBA,iBAClBL,YAAaA,YACbC,iBAAkBA,iBAClBC,WAAYA,aAIpBI,OAASI,cAAKC,KAAK,CAACJ,OAKpB,IAAIK,GAAKC,SAASC,eAAe,gCACjCF,GAAGG,MAAMC,QAAU,QACnBJ,GAAGG,MAAME,QAAU,EAGfL,GAAGM,cACHC,cAAcP,GAAGM,cAErBE,YAAW,WACPR,GAAGM,aAAeG,aAAY,WACtBT,GAAGG,MAAME,QAAU,GACnBL,GAAGG,MAAME,SAAW,GACbL,GAAGG,MAAME,QAAU,EAC1BL,GAAGG,MAAME,SAAW,IAGpBE,cAAcP,GAAGM,cACjBN,GAAGG,MAAMC,QAAU,UAExB,OACJ,KAvDCM,CAAiB3D,OAAQ4B,UAAoB,SAAGA,UAAsB,WAAGQ,aAA0B,YAC/FA,aAA+B,iBAAGA,aAAyB,gBApCvEwB,OAA6B7D,IAA7B6D,QAA6B7D,IAAA8D,WAAA9D,KAAA+D,QAAA/D,KAG7B,MAAM0B,WAAayB,SAASC,eAAe,8BAGrCpC,cAAgBmC,SAASa,iBAAiB,uBAC1C1D,mBAAqB6C,SAASa,iBAAiB,0BAC/C9C,iBAAmBiC,SAASa,iBAAiB,wBAG7C7C,WAAagC,SAASa,iBAAiB,uBAsN7C,SAAS7B,gBAAgB1B,IAErB,OAAOA,IACH,IAAK,cACD,OAAO,SACX,IAAK,uBACL,IAAK,uBACD,OAAO,OACX,IAAK,wBACL,IAAK,wBACD,OAAO,MACX,IAAK,oBACL,IAAK,oBACD,OAAO,OACX,IAAK,qBACL,IAAK,qBACD,OAAO,QAUnB,SAASL,gBAAgB6D,KAAMC,QAC3B,OAAQD,MACJ,IAAK,WACD,MAAO,cACX,IAAK,SACD,OAAIC,OACO,uBAEJ,uBACX,IAAK,SACD,OAAIA,OACO,wBAEJ,wBACX,IAAK,SACD,OAAIA,OACO,oBAEJ,oBACX,IAAK,UACD,OAAIA,OACO,qBAGJ,sBAElB"} \ No newline at end of file +{"version":3,"file":"usersettings_save.min.js","sources":["../src/usersettings_save.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 * Javascript to save the user settings in the database.\n *\n * This file implements 1 functionality:\n * - If the \"save settings\" button is pressed, store the settings in the database.\n *\n * @module block_townsquare/usersettings_save\n * @copyright 2024 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n// Get the save button for the user settings.\nconst savebutton = document.getElementById('ts_usersettings_savebutton');\n\n// Get the buttons from the time filter.\nconst alltimebutton = document.querySelectorAll('.ts_all_time_button');\nconst futureradiobuttons = document.querySelectorAll('.ts_future_time_button');\nconst pastradiobuttons = document.querySelectorAll('.ts_past_time_button');\n\n// Get the checkboxes from the letter filter.\nconst checkboxes = document.querySelectorAll('.ts_letter_checkbox');\n\n/**\n * Init function\n *\n * @param {number} userid The id of the current user.\n * @param {object} settingsfromdb The settings from the database, if there are any.\n */\nexport function init(userid, settingsfromdb) {\n // When the page is loaded, set the settings from the database.\n if (settingsfromdb) {\n executeusersettings(settingsfromdb);\n }\n\n // Add event listener to the save button.\n savebutton.addEventListener('click', async function() {\n\n // First step: collect the current settings.\n // Get the relevant time spans of the time filter and the setting of the letter filter checkboxes.\n let timespans = collecttimefiltersettings();\n let letterfilter = collectletterfiltersettings();\n\n // Second step: store the usersettings in the database.\n await saveusersettings(userid, timespans['timepast'], timespans['timefuture'], letterfilter['basicletter'],\n letterfilter['completionletter'], letterfilter['postletter']);\n });\n}\n\n/**\n * Function to save the user settings in the database.\n * @param {number} userid\n * @param {number} timefilterpast\n * @param {number} timefilterfuture\n * @param {number} basicletter\n * @param {number} completionletter\n * @param {number} postletter\n * @returns {Promise<*>}\n */\nfunction saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, completionletter, postletter) {\n let result;\n\n const data = {\n methodname: 'block_townsquare_record_usersettings',\n args: {\n userid: userid,\n timefilterpast: timefilterpast,\n timefilterfuture: timefilterfuture,\n basicletter: basicletter,\n completionletter: completionletter,\n postletter: postletter,\n },\n };\n result = Ajax.call([data]);\n\n // Make the clicked button green by adding a class.\n savebutton.classList.add('bg-success', 'text-white', 'ts_button_transition');\n\n // Remove the classes after one second.\n setTimeout(function() {\n savebutton.classList.remove('bg-success');\n savebutton.classList.remove('text-white');\n }, 1500);\n return result;\n\n}\n\n/**\n * Function to execute existing user settings when loading the townsquare.\n * @param {Object} settingsfromdb\n */\nfunction executeusersettings(settingsfromdb) {\n\n // First step: set the time filter settings.\n // Change the time into the correct radio button id.\n let futurebuttonid = converttimetoid(settingsfromdb['timefilterfuture'], true);\n let pastbuttonid = converttimetoid(settingsfromdb['timefilterpast'], false);\n\n // If the time span is a combination of past and future, go through the two radio buttons and activate the filter.\n if (futurebuttonid !== \"ts_time_all\") {\n futureradiobuttons.forEach(function(button) {\n if (button.id === futurebuttonid) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n }\n });\n pastradiobuttons.forEach(function(button) {\n if (button.id === pastbuttonid) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n alltimebutton.forEach(function(alltimebutton) {\n alltimebutton.checked = false;\n alltimebutton.parentNode.classList.remove('active');\n });\n }\n });\n } else {\n // If the time span is set to all time, activate the all time button.\n alltimebutton.forEach(function(button) {\n button.parentNode.classList.add('active');\n button.checked = true;\n button.dispatchEvent(new Event('change'));\n });\n }\n\n // Second step: set the letter filter settings.\n // Per default all checkboxes are checked. If the setting is 0, uncheck the checkbox.\n checkboxes.forEach(function(checkbox) {\n let basiclettercheck = checkbox.id === 'basicletter' && settingsfromdb['basicletter'] === \"\";\n let completionlettercheck = checkbox.id === 'completionletter' && settingsfromdb['completionletter'] === \"0\";\n let postlettercheck = checkbox.id === 'postletter' && settingsfromdb['postletter'] === \"0\";\n\n if (basiclettercheck || completionlettercheck || postlettercheck) {\n checkbox.click();\n }\n });\n}\n\n/**\n * Function to collect the letter filter settings.\n * @returns {{basicletter: number, completionletter: number, postletter: number}}\n */\nfunction collectletterfiltersettings() {\n let settings = {'basicletter': 0, 'completionletter': 0, 'postletter': 0 };\n\n checkboxes.forEach(function(checkbox) {\n if (checkbox.checked) {\n switch(checkbox.id) {\n case \"basicletter\":\n settings['basicletter'] = 1;\n break;\n case \"completionletter\":\n settings['completionletter'] = 1;\n break;\n case \"postletter\":\n settings['postletter'] = 1;\n break;\n\n }\n }\n });\n // Calculate the setting number. It is a number between 0 and 7, and each letter represents a bit.\n return settings;\n}\n\n/**\n * Function to collect the time filter settings.\n * @returns {{timepast: number, timefuture: number}}\n */\nfunction collecttimefiltersettings() {\n let settings = { timepast: 0, timefuture: 0};\n let settingsset = false;\n\n // Get the relevant time spans of the time filter.\n // Check if the alltimebutton is set.\n alltimebutton.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n settings['timefuture'] = convertidtotime(button.id);\n settingsset = true;\n }\n });\n\n if (settingsset) {\n return settings;\n }\n\n // If the alltimebutton is not set, check which of the future/past buttons is set.\n futureradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timefuture'] = convertidtotime(button.id);\n }\n });\n\n pastradiobuttons.forEach(function(button) {\n if (button.parentNode.classList.contains('active')) {\n // Get the timespan.\n settings['timepast'] = convertidtotime(button.id);\n }\n });\n return settings;\n}\n\n\n/**\n * Function to convert the radio button id to a useable time span.\n * @param {string} id The id of the radio button\n * @returns {number}\n */\nfunction convertidtotime(id) {\n // TODO: Please use global functions if possible.\n switch(id) {\n case \"ts_time_all\":\n return 15778463;\n case \"ts_time_next_twodays\":\n case \"ts_time_last_twodays\":\n return 172800;\n case \"ts_time_next_fivedays\":\n case \"ts_time_last_fivedays\":\n return 432000;\n case \"ts_time_next_week\":\n case \"ts_time_last_week\":\n return 604800;\n case \"ts_time_next_month\":\n case \"ts_time_last_month\":\n return 2592000;\n }\n}\n\n/**\n * Function to convert the time span to a radio button id.\n * @param {string} time\n * @param {boolean} future\n * @returns {string}\n */\nfunction converttimetoid(time, future) {\n switch (time) {\n case \"15778463\":\n return \"ts_time_all\";\n case \"172800\":\n if (future) {\n return \"ts_time_next_twodays\";\n }\n return \"ts_time_past_twodays\";\n case \"432000\":\n if (future) {\n return \"ts_time_next_fivedays\";\n }\n return \"ts_time_last_fivedays\";\n case \"604800\":\n if (future) {\n return \"ts_time_next_week\";\n }\n return \"ts_time_last_week\";\n case \"2592000\":\n if (future) {\n return \"ts_time_next_month\";\n\n }\n return \"ts_time_last_month\";\n }\n}\n"],"names":["obj","userid","settingsfromdb","futurebuttonid","converttimetoid","pastbuttonid","futureradiobuttons","forEach","button","id","parentNode","classList","add","checked","dispatchEvent","Event","alltimebutton","remove","pastradiobuttons","checkboxes","checkbox","basiclettercheck","completionlettercheck","postlettercheck","click","executeusersettings","savebutton","addEventListener","async","timespans","settings","timepast","timefuture","settingsset","contains","convertidtotime","collecttimefiltersettings","letterfilter","basicletter","completionletter","postletter","collectletterfiltersettings","timefilterpast","timefilterfuture","result","data","methodname","args","Ajax","call","setTimeout","saveusersettings","_ajax","__esModule","default","document","getElementById","querySelectorAll","time","future"],"mappings":"8FA0B6B,IAAAA;;;;;;;;;;2EAmBtB,SAAcC,OAAQC,gBAErBA,gBA4DR,SAA6BA,gBAIzB,IAAIC,eAAiBC,gBAAgBF,eAAiC,kBAAG,GACrEG,aAAeD,gBAAgBF,eAA+B,gBAAG,GAG9C,gBAAnBC,gBACAG,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOC,KAAON,iBACdK,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,iBAItDC,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOC,KAAOJ,eACdG,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,WAC/BC,cAAcT,SAAQ,SAASS,eAC3BA,cAAcH,SAAU,EACxBG,cAAcN,WAAWC,UAAUM,OAAO,kBAMtDD,cAAcT,SAAQ,SAASC,QAC3BA,OAAOE,WAAWC,UAAUC,IAAI,UAChCJ,OAAOK,SAAU,EACjBL,OAAOM,cAAc,IAAIC,MAAM,cAMvCI,WAAWZ,SAAQ,SAASa,UACxB,IAAIC,iBAAmC,gBAAhBD,SAASX,IAA0D,KAAlCP,eAA4B,YAChFoB,sBAAwC,qBAAhBF,SAASX,IAAoE,MAAvCP,eAAiC,iBAC/FqB,gBAAkC,eAAhBH,SAASX,IAAwD,MAAjCP,eAA2B,YAE7EmB,kBAAoBC,uBAAyBC,kBAC7CH,SAASI,WA3GbC,CAAoBvB,gBAIxBwB,WAAWC,iBAAiB,SAASC,iBAIjC,IAAIC,UAuIZ,WACI,IAAIC,SAAW,CAAEC,SAAU,EAAGC,WAAY,GACtCC,aAAc,EAalB,GATAjB,cAAcT,SAAQ,SAASC,QACxBA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAmB,SAAIK,gBAAgB3B,OAAOC,IAC9CqB,SAAqB,WAAIK,gBAAgB3B,OAAOC,IAChDwB,aAAc,MAIjBA,YACA,OAAOH,SAiBX,OAbAxB,mBAAmBC,SAAQ,SAASC,QAC5BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAqB,WAAIK,gBAAgB3B,OAAOC,QAIxDS,iBAAiBX,SAAQ,SAASC,QAC1BA,OAAOE,WAAWC,UAAUuB,SAAS,YAErCJ,SAAmB,SAAIK,gBAAgB3B,OAAOC,QAG/CqB,SAxKaM,GACZC,aA2GZ,WACI,IAAIP,SAAW,CAACQ,YAAe,EAAGC,iBAAoB,EAAGC,WAAc,GAmBvE,OAjBArB,WAAWZ,SAAQ,SAASa,UACxB,GAAIA,SAASP,QACT,OAAOO,SAASX,IACZ,IAAK,cACDqB,SAAsB,YAAI,EAC1B,MACJ,IAAK,mBACDA,SAA2B,iBAAI,EAC/B,MACJ,IAAK,aACDA,SAAqB,WAAI,MAOlCA,SA/HgBW,SAkB3B,SAA0BxC,OAAQyC,eAAgBC,iBAAkBL,YAAaC,iBAAkBC,YAC/F,IAAII,OAEJ,MAAMC,KAAO,CACTC,WAAY,uCACZC,KAAM,CACF9C,OAAQA,OACRyC,eAAgBA,eAChBC,iBAAkBA,iBAClBL,YAAaA,YACbC,iBAAkBA,iBAClBC,WAAYA,aAapB,OAVAI,OAASI,cAAKC,KAAK,CAACJ,OAGpBnB,WAAWf,UAAUC,IAAI,aAAc,aAAc,wBAGrDsC,YAAW,WACPxB,WAAWf,UAAUM,OAAO,cAC5BS,WAAWf,UAAUM,OAAO,gBAC7B,MACI2B,OAvCGO,CAAiBlD,OAAQ4B,UAAoB,SAAGA,UAAsB,WAAGQ,aAA0B,YACrGA,aAA+B,iBAAGA,aAAyB,gBAnCvEe,OAA6BpD,IAA7BoD,QAA6BpD,IAAAqD,WAAArD,KAAAsD,QAAAtD,KAG7B,MAAM0B,WAAa6B,SAASC,eAAe,8BAGrCxC,cAAgBuC,SAASE,iBAAiB,uBAC1CnD,mBAAqBiD,SAASE,iBAAiB,0BAC/CvC,iBAAmBqC,SAASE,iBAAiB,wBAG7CtC,WAAaoC,SAASE,iBAAiB,uBAoM7C,SAAStB,gBAAgB1B,IAErB,OAAOA,IACH,IAAK,cACD,OAAO,SACX,IAAK,uBACL,IAAK,uBACD,OAAO,OACX,IAAK,wBACL,IAAK,wBACD,OAAO,MACX,IAAK,oBACL,IAAK,oBACD,OAAO,OACX,IAAK,qBACL,IAAK,qBACD,OAAO,QAUnB,SAASL,gBAAgBsD,KAAMC,QAC3B,OAAQD,MACJ,IAAK,WACD,MAAO,cACX,IAAK,SACD,OAAIC,OACO,uBAEJ,uBACX,IAAK,SACD,OAAIA,OACO,wBAEJ,wBACX,IAAK,SACD,OAAIA,OACO,oBAEJ,oBACX,IAAK,UACD,OAAIA,OACO,qBAGJ,sBAElB"} \ No newline at end of file diff --git a/amd/src/usersettings_save.js b/amd/src/usersettings_save.js index 2136743..85f1d45 100644 --- a/amd/src/usersettings_save.js +++ b/amd/src/usersettings_save.js @@ -89,28 +89,14 @@ function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, }; result = Ajax.call([data]); - // Show a success message. - let el = document.getElementById('ts_usersettings_successlabel'); - el.style.display = 'block'; - el.style.opacity = 1.0; + // Make the clicked button green by adding a class. + savebutton.classList.add('bg-success', 'text-white', 'ts_button_transition'); - // Start a new setInterval timer to gradually fade out the label. - if (el.fadeOutTimer) { - clearInterval(el.fadeOutTimer); - } - setTimeout(function () { - el.fadeOutTimer = setInterval(function () { - if (el.style.opacity > 0.4) { - el.style.opacity -= 0.1; - } else if (el.style.opacity > 0) { - el.style.opacity -= 0.2; - } else { - // Once opacity reaches 0, clear the timer and hide the label. - clearInterval(el.fadeOutTimer); - el.style.display = 'none'; - } - }, 100); - }, 3000); + // Remove the classes after one second. + setTimeout(function() { + savebutton.classList.remove('bg-success'); + savebutton.classList.remove('text-white'); + }, 1500); return result; } diff --git a/styles.css b/styles.css index f139438..79070ac 100644 --- a/styles.css +++ b/styles.css @@ -28,6 +28,10 @@ display: none; } +.ts_button_transition { + transition: background-color 1.0s ease, color 1.0s ease; +} + /* Style for all letter or content templates */ .townsquareletter_header.card-header { diff --git a/version.php b/version.php index 1e19259..840bca2 100644 --- a/version.php +++ b/version.php @@ -25,6 +25,6 @@ defined('MOODLE_INTERNAL') || die(); $plugin->component = 'block_townsquare'; $plugin->release = '0.1.0'; -$plugin->version = 2024051701; +$plugin->version = 2024052400; $plugin->requires = 2022041900; $plugin->maturity = MATURITY_ALPHA; From 8d47e63c2761802fec01cf5090f39b24f0ceb223 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 24 May 2024 15:58:23 +0200 Subject: [PATCH 091/123] adapt workflow matrix to M4.4 --- .github/workflows/moodle-ci.yml | 24 +++++++++++++++++++++--- classes/external.php | 1 + 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index a2eae8d..9ad9b1e 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -113,9 +113,27 @@ jobs: strategy: fail-fast: false matrix: - php: ['8.0', '8.1'] - moodle-branch: ['MOODLE_401_STABLE', 'MOODLE_402_STABLE', 'MOODLE_403_STABLE'] - database: ['mariadb', 'pgsql'] + php: [ '8.0', '8.1', '8.2', '8.3' ] + moodle-branch: [ 'MOODLE_401_STABLE', 'MOODLE_402_STABLE', 'MOODLE_403_STABLE', 'MOODLE_404_STABLE' ] + database: [ 'mariadb', 'pgsql' ] + exclude: + - php: '8.0' + moodle-branch: 'MOODLE_404_STABLE' + - php: '8.2' + moodle-branch: 'MOODLE_401_STABLE' + - php: '8.3' + moodle-branch: 'MOODLE_401_STABLE' + - php: '8.3' + moodle-branch: 'MOODLE_402_STABLE' + - php: '8.3' + moodle-branch: 'MOODLE_403_STABLE' + include: + - php: '7.4' + moodle-branch: 'MOODLE_401_STABLE' + database: 'pgsql' + - php: '7.4' + moodle-branch: 'MOODLE_401_STABLE' + database: 'mariadb' steps: - name: Start MariaDB diff --git a/classes/external.php b/classes/external.php index f660634..9b3c07a 100644 --- a/classes/external.php +++ b/classes/external.php @@ -90,6 +90,7 @@ public static function record_usersettings($userid, $timefilterpast, $timefilter 'basicletter' => $basicletter, 'completionletter' => $completionletter, 'postletter' => $postletter, ]); } else { + // TODO: delete this branch when Moodle 4.1 is no longer supported. $params = [ 'userid' => $userid, 'timefilterpast' => $timefilterpast, 'timefilterfuture' => $timefilterfuture, 'basicletter' => $basicletter, 'completionletter' => $completionletter, 'postletter' => $postletter, ]; From 2ad11ef3e9a39da8d72e2b9947999e3df6b3f0a3 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 24 May 2024 16:00:15 +0200 Subject: [PATCH 092/123] use m4.4 as standard in github ci --- .github/workflows/moodle-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index 9ad9b1e..b5777a9 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -8,8 +8,8 @@ jobs: strategy: matrix: - php: ['8.2'] - moodle-branch: ['MOODLE_403_STABLE'] + php: ['8.3'] + moodle-branch: ['MOODLE_404_STABLE'] database: ['pgsql'] steps: From e3f91877a94d0977b4f54d274a06d844dc0d73d7 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 24 May 2024 16:18:00 +0200 Subject: [PATCH 093/123] WIP: fix for M4.1 --- classes/external.php | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/classes/external.php b/classes/external.php index 9b3c07a..a713182 100644 --- a/classes/external.php +++ b/classes/external.php @@ -84,6 +84,7 @@ public static function record_usersettings($userid, $timefilterpast, $timefilter global $DB, $CFG; // Parameter validation. + /* if ($CFG->branch >= 402) { $params = self::validate_parameters(self::record_usersettings_parameters(), [ 'userid' => $userid, 'timefilterpast' => $timefilterpast, 'timefilterfuture' => $timefilterfuture, @@ -94,7 +95,7 @@ public static function record_usersettings($userid, $timefilterpast, $timefilter $params = [ 'userid' => $userid, 'timefilterpast' => $timefilterpast, 'timefilterfuture' => $timefilterfuture, 'basicletter' => $basicletter, 'completionletter' => $completionletter, 'postletter' => $postletter, ]; - } + }*/ // Check if the user already has a record in the database. if ($records = $DB->get_records('block_townsquare_preferences', ['userid' => $userid])) { @@ -110,23 +111,36 @@ public static function record_usersettings($userid, $timefilterpast, $timefilter } } else { // Upgrade the existing record. - $record = reset($records); + $record = reset($records);/* $record->timefilterpast = $params['timefilterpast']; $record->timefilterfuture = $params['timefilterfuture']; $record->basicletter = $params['basicletter']; $record->completionletter = $params['completionletter']; - $record->postletter = $params['postletter']; + $record->postletter = $params['postletter'];*/ + $record->timefilterpast = $timefilterpast; + $record->timefilterfuture = $timefilterfuture; + $record->basicletter = $basicletter; + $record->completionletter = $completionletter; + $record->postletter = $postletter; + $DB->update_record('block_townsquare_preferences', $record); return true; } } $record = new stdClass(); + /* $record->userid = $params['userid']; $record->timefilterpast = $params['timefilterpast']; $record->timefilterfuture = $params['timefilterfuture']; $record->basicletter = $params['basicletter']; $record->completionletter = $params['completionletter']; - $record->postletter = $params['postletter']; + $record->postletter = $params['postletter'];*/ + $record->userid = $userid; + $record->timefilterpast = $timefilterpast; + $record->timefilterfuture = $timefilterfuture; + $record->basicletter = $basicletter; + $record->completionletter = $completionletter; + $record->postletter = $postletter; $DB->insert_record('block_townsquare_preferences', $record); return true; } From 98bed7b537582e4ea8ca492037d78b57ddb6f563 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 24 May 2024 16:41:14 +0200 Subject: [PATCH 094/123] WIP: fix for M4.1 --- .github/workflows/moodle-ci.yml | 14 ++------------ tests/behat/behat_block_townsquare.php | 11 +++++++++++ .../behat/block_townsquare_savepreferences.feature | 1 + 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index b5777a9..1ac8226 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -113,20 +113,10 @@ jobs: strategy: fail-fast: false matrix: - php: [ '8.0', '8.1', '8.2', '8.3' ] - moodle-branch: [ 'MOODLE_401_STABLE', 'MOODLE_402_STABLE', 'MOODLE_403_STABLE', 'MOODLE_404_STABLE' ] + php: [ '8.0', '8.1'] + moodle-branch: [ 'MOODLE_401_STABLE'] database: [ 'mariadb', 'pgsql' ] exclude: - - php: '8.0' - moodle-branch: 'MOODLE_404_STABLE' - - php: '8.2' - moodle-branch: 'MOODLE_401_STABLE' - - php: '8.3' - moodle-branch: 'MOODLE_401_STABLE' - - php: '8.3' - moodle-branch: 'MOODLE_402_STABLE' - - php: '8.3' - moodle-branch: 'MOODLE_403_STABLE' include: - php: '7.4' moodle-branch: 'MOODLE_401_STABLE' diff --git a/tests/behat/behat_block_townsquare.php b/tests/behat/behat_block_townsquare.php index 49cd84e..707daa0 100644 --- a/tests/behat/behat_block_townsquare.php +++ b/tests/behat/behat_block_townsquare.php @@ -61,4 +61,15 @@ public function i_add_an_townsquare_completion_event(string $coursename) { ]; $generator->create_module('assign', $assignrecord, $featurecompletionmanual); } + + /** + * Test for debugging + * @Given /^I townsquare debug$/ + */ + public function i_townsquare_debug() { + global $DB; + $record = $DB->get_records('block_townsquare_preferences'); + var_dump($record); + ob_flush(); + } } diff --git a/tests/behat/block_townsquare_savepreferences.feature b/tests/behat/block_townsquare_savepreferences.feature index b3c8c9c..ce3672c 100644 --- a/tests/behat/block_townsquare_savepreferences.feature +++ b/tests/behat/block_townsquare_savepreferences.feature @@ -31,5 +31,6 @@ Feature: In the townsquare block user can save their settings in a database. And I click on "Next two days" "text" When I click on "Save settings" "text" in the "Town Square" "block" Then I should not see "Test assign 2" in the "Town Square" "block" + And I townsquare debug And I reload the page Then I should not see "Test assign 2" in the "Town Square" "block" \ No newline at end of file From a983c301aab7df151bf0fcda3235953290559c15 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 24 May 2024 16:43:01 +0200 Subject: [PATCH 095/123] WIP: fix for M4.1 --- .github/workflows/moodle-ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index 1ac8226..f92161e 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -116,7 +116,6 @@ jobs: php: [ '8.0', '8.1'] moodle-branch: [ 'MOODLE_401_STABLE'] database: [ 'mariadb', 'pgsql' ] - exclude: include: - php: '7.4' moodle-branch: 'MOODLE_401_STABLE' From 926e61594cac531afca96213084b51fb607c4aec Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 24 May 2024 16:52:24 +0200 Subject: [PATCH 096/123] WIP: fix for M4.1 --- amd/src/usersettings_save.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/amd/src/usersettings_save.js b/amd/src/usersettings_save.js index 85f1d45..5662903 100644 --- a/amd/src/usersettings_save.js +++ b/amd/src/usersettings_save.js @@ -88,7 +88,7 @@ function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, }, }; result = Ajax.call([data]); - + console.log('HI I AM HERE') // Make the clicked button green by adding a class. savebutton.classList.add('bg-success', 'text-white', 'ts_button_transition'); From 15f0fab4a78572a742acc07cd2e850edf9b615f9 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 24 May 2024 17:25:25 +0200 Subject: [PATCH 097/123] WIP: fix for M4.1 --- amd/src/usersettings_save.js | 2 +- locallib.php | 32 +++++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/amd/src/usersettings_save.js b/amd/src/usersettings_save.js index 5662903..8a7b359 100644 --- a/amd/src/usersettings_save.js +++ b/amd/src/usersettings_save.js @@ -88,7 +88,7 @@ function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, }, }; result = Ajax.call([data]); - console.log('HI I AM HERE') + console.log('HI I AM HERE'); // Make the clicked button green by adding a class. savebutton.classList.add('bg-success', 'text-white', 'ts_button_transition'); diff --git a/locallib.php b/locallib.php index c7f9dfc..284b812 100644 --- a/locallib.php +++ b/locallib.php @@ -30,13 +30,31 @@ * @throws moodle_exception */ function townsquare_get_colorsetting($lettertype) { - return match ($lettertype) { - 'basicletter' => get_config('block_townsquare', 'basiclettercolor'), - 'postletter' => get_config('block_townsquare', 'postlettercolor'), - 'completionletter' => get_config('block_townsquare', 'completionlettercolor'), - 'orientationmarker' => get_config('block_townsquare', 'orientationmarkercolor'), - default => throw new \moodle_exception('invalidlettertype', 'block_townsquare'), - }; + global $CFG; + if ($CFG->branch >= 402) { + return match ($lettertype) { + 'basicletter' => get_config('block_townsquare', 'basiclettercolor'), + 'postletter' => get_config('block_townsquare', 'postlettercolor'), + 'completionletter' => get_config('block_townsquare', 'completionlettercolor'), + 'orientationmarker' => get_config('block_townsquare', 'orientationmarkercolor'), + default => throw new \moodle_exception('invalidlettertype', 'block_townsquare'), + }; + } else { + // The same but without the match expression as php 7.4 does not support it. + switch ($lettertype) { + case 'basicletter': + return get_config('block_townsquare', 'basiclettercolor'); + case 'postletter': + return get_config('block_townsquare', 'postlettercolor'); + case 'completionletter': + return get_config('block_townsquare', 'completionlettercolor'); + case 'orientationmarker': + return get_config('block_townsquare', 'orientationmarkercolor'); + default: + throw new \moodle_exception('invalidlettertype', 'block_townsquare'); + } + } + } /** From 5e30a0dec75d7bc94b8ffd7c60ecc1529af6b2a3 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 24 May 2024 17:34:11 +0200 Subject: [PATCH 098/123] WIP: fix for M4.1 --- locallib.php | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/locallib.php b/locallib.php index 284b812..d3f8883 100644 --- a/locallib.php +++ b/locallib.php @@ -30,31 +30,18 @@ * @throws moodle_exception */ function townsquare_get_colorsetting($lettertype) { - global $CFG; - if ($CFG->branch >= 402) { - return match ($lettertype) { - 'basicletter' => get_config('block_townsquare', 'basiclettercolor'), - 'postletter' => get_config('block_townsquare', 'postlettercolor'), - 'completionletter' => get_config('block_townsquare', 'completionlettercolor'), - 'orientationmarker' => get_config('block_townsquare', 'orientationmarkercolor'), - default => throw new \moodle_exception('invalidlettertype', 'block_townsquare'), - }; - } else { - // The same but without the match expression as php 7.4 does not support it. - switch ($lettertype) { - case 'basicletter': - return get_config('block_townsquare', 'basiclettercolor'); - case 'postletter': - return get_config('block_townsquare', 'postlettercolor'); - case 'completionletter': - return get_config('block_townsquare', 'completionlettercolor'); - case 'orientationmarker': - return get_config('block_townsquare', 'orientationmarkercolor'); - default: - throw new \moodle_exception('invalidlettertype', 'block_townsquare'); - } + switch ($lettertype) { + case 'basicletter': + return get_config('block_townsquare', 'basiclettercolor'); + case 'postletter': + return get_config('block_townsquare', 'postlettercolor'); + case 'completionletter': + return get_config('block_townsquare', 'completionlettercolor'); + case 'orientationmarker': + return get_config('block_townsquare', 'orientationmarkercolor'); + default: + throw new \moodle_exception('invalidlettertype', 'block_townsquare'); } - } /** From e665ab99f65666fab1e548257146b5b27a01db17 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 24 May 2024 18:17:02 +0200 Subject: [PATCH 099/123] WIP: fix for M4.1 --- classes/external.php | 11 ++--------- locallib.php | 4 ++-- tests/behat/behat_block_townsquare.php | 1 + tests/behat/block_townsquare_savepreferences.feature | 1 + 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/classes/external.php b/classes/external.php index a713182..691376e 100644 --- a/classes/external.php +++ b/classes/external.php @@ -22,7 +22,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace block_townsquare; -use core_external\external_function_parameters; +use external_function_parameters; use Exception; use external_api; use external_value; @@ -82,20 +82,13 @@ public static function record_usersettings_returns(): external_value { public static function record_usersettings($userid, $timefilterpast, $timefilterfuture, $basicletter, $completionletter, $postletter): bool { global $DB, $CFG; - // Parameter validation. - /* if ($CFG->branch >= 402) { $params = self::validate_parameters(self::record_usersettings_parameters(), [ 'userid' => $userid, 'timefilterpast' => $timefilterpast, 'timefilterfuture' => $timefilterfuture, 'basicletter' => $basicletter, 'completionletter' => $completionletter, 'postletter' => $postletter, ]); - } else { - // TODO: delete this branch when Moodle 4.1 is no longer supported. - $params = [ - 'userid' => $userid, 'timefilterpast' => $timefilterpast, 'timefilterfuture' => $timefilterfuture, - 'basicletter' => $basicletter, 'completionletter' => $completionletter, 'postletter' => $postletter, ]; - }*/ + } // Check if the user already has a record in the database. if ($records = $DB->get_records('block_townsquare_preferences', ['userid' => $userid])) { diff --git a/locallib.php b/locallib.php index d3f8883..29048bf 100644 --- a/locallib.php +++ b/locallib.php @@ -26,10 +26,10 @@ * Function to get the color of a letter. * * @param string $lettertype The type of the letter that wants to retrieve its color setting. - * @return false|mixed The color of the letter. + * @return false|string The color of the letter. * @throws moodle_exception */ -function townsquare_get_colorsetting($lettertype) { +function townsquare_get_colorsetting($lettertype): string { switch ($lettertype) { case 'basicletter': return get_config('block_townsquare', 'basiclettercolor'); diff --git a/tests/behat/behat_block_townsquare.php b/tests/behat/behat_block_townsquare.php index 707daa0..ef75c69 100644 --- a/tests/behat/behat_block_townsquare.php +++ b/tests/behat/behat_block_townsquare.php @@ -68,6 +68,7 @@ public function i_add_an_townsquare_completion_event(string $coursename) { */ public function i_townsquare_debug() { global $DB; + //\block_townsquare\external::record_usersettings(1, 1, 1, 1, 1, 1); $record = $DB->get_records('block_townsquare_preferences'); var_dump($record); ob_flush(); diff --git a/tests/behat/block_townsquare_savepreferences.feature b/tests/behat/block_townsquare_savepreferences.feature index ce3672c..64d7412 100644 --- a/tests/behat/block_townsquare_savepreferences.feature +++ b/tests/behat/block_townsquare_savepreferences.feature @@ -29,6 +29,7 @@ Feature: In the townsquare block user can save their settings in a database. Then I should see "Test assign 2" in the "Town Square" "block" And I click on "Time filter" "text" And I click on "Next two days" "text" + And I townsquare debug When I click on "Save settings" "text" in the "Town Square" "block" Then I should not see "Test assign 2" in the "Town Square" "block" And I townsquare debug From c43953f5c924095a0f4c36039b6c20bc954411c8 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 24 May 2024 18:21:45 +0200 Subject: [PATCH 100/123] WIP fix for M4.1 --- classes/external.php | 28 +++++++------------------- tests/behat/behat_block_townsquare.php | 2 +- 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/classes/external.php b/classes/external.php index 691376e..de9c4a9 100644 --- a/classes/external.php +++ b/classes/external.php @@ -83,12 +83,10 @@ public static function record_usersettings($userid, $timefilterpast, $timefilter $basicletter, $completionletter, $postletter): bool { global $DB, $CFG; // Parameter validation. - if ($CFG->branch >= 402) { - $params = self::validate_parameters(self::record_usersettings_parameters(), [ - 'userid' => $userid, 'timefilterpast' => $timefilterpast, 'timefilterfuture' => $timefilterfuture, - 'basicletter' => $basicletter, 'completionletter' => $completionletter, 'postletter' => $postletter, - ]); - } + $params = self::validate_parameters(self::record_usersettings_parameters(), [ + 'userid' => $userid, 'timefilterpast' => $timefilterpast, 'timefilterfuture' => $timefilterfuture, + 'basicletter' => $basicletter, 'completionletter' => $completionletter, 'postletter' => $postletter, + ]); // Check if the user already has a record in the database. if ($records = $DB->get_records('block_townsquare_preferences', ['userid' => $userid])) { @@ -104,36 +102,24 @@ public static function record_usersettings($userid, $timefilterpast, $timefilter } } else { // Upgrade the existing record. - $record = reset($records);/* + $record = reset($records); $record->timefilterpast = $params['timefilterpast']; $record->timefilterfuture = $params['timefilterfuture']; $record->basicletter = $params['basicletter']; $record->completionletter = $params['completionletter']; - $record->postletter = $params['postletter'];*/ - $record->timefilterpast = $timefilterpast; - $record->timefilterfuture = $timefilterfuture; - $record->basicletter = $basicletter; - $record->completionletter = $completionletter; - $record->postletter = $postletter; + $record->postletter = $params['postletter']; $DB->update_record('block_townsquare_preferences', $record); return true; } } $record = new stdClass(); - /* $record->userid = $params['userid']; $record->timefilterpast = $params['timefilterpast']; $record->timefilterfuture = $params['timefilterfuture']; $record->basicletter = $params['basicletter']; $record->completionletter = $params['completionletter']; - $record->postletter = $params['postletter'];*/ - $record->userid = $userid; - $record->timefilterpast = $timefilterpast; - $record->timefilterfuture = $timefilterfuture; - $record->basicletter = $basicletter; - $record->completionletter = $completionletter; - $record->postletter = $postletter; + $record->postletter = $params['postletter']; $DB->insert_record('block_townsquare_preferences', $record); return true; } diff --git a/tests/behat/behat_block_townsquare.php b/tests/behat/behat_block_townsquare.php index ef75c69..1e7aa09 100644 --- a/tests/behat/behat_block_townsquare.php +++ b/tests/behat/behat_block_townsquare.php @@ -68,7 +68,7 @@ public function i_add_an_townsquare_completion_event(string $coursename) { */ public function i_townsquare_debug() { global $DB; - //\block_townsquare\external::record_usersettings(1, 1, 1, 1, 1, 1); + // \block_townsquare\external::record_usersettings(1, 1, 1, 1, 1, 1); $record = $DB->get_records('block_townsquare_preferences'); var_dump($record); ob_flush(); From 178b7eb321500cc0bad8b59d4afe56626dabcaaf Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 24 May 2024 18:27:09 +0200 Subject: [PATCH 101/123] WIP: fix for M4.1 --- classes/letter/letter.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/classes/letter/letter.php b/classes/letter/letter.php index 48a71f0..f54cf16 100644 --- a/classes/letter/letter.php +++ b/classes/letter/letter.php @@ -78,8 +78,8 @@ class letter { /** @var bool variable for the mustache template */ public bool $isbasic = true; - /** @var mixed color of the letter. Only used by mustache */ - public mixed $lettercolor; + /** @var string color of the letter. Only used by mustache */ + public string $lettercolor; // Constructor. From dc49377a019b3116174834571235fa1f55c14c51 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 24 May 2024 18:35:44 +0200 Subject: [PATCH 102/123] WIP: fix for M4.1 --- .github/workflows/moodle-ci.yml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index f92161e..b5777a9 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -113,9 +113,20 @@ jobs: strategy: fail-fast: false matrix: - php: [ '8.0', '8.1'] - moodle-branch: [ 'MOODLE_401_STABLE'] + php: [ '8.0', '8.1', '8.2', '8.3' ] + moodle-branch: [ 'MOODLE_401_STABLE', 'MOODLE_402_STABLE', 'MOODLE_403_STABLE', 'MOODLE_404_STABLE' ] database: [ 'mariadb', 'pgsql' ] + exclude: + - php: '8.0' + moodle-branch: 'MOODLE_404_STABLE' + - php: '8.2' + moodle-branch: 'MOODLE_401_STABLE' + - php: '8.3' + moodle-branch: 'MOODLE_401_STABLE' + - php: '8.3' + moodle-branch: 'MOODLE_402_STABLE' + - php: '8.3' + moodle-branch: 'MOODLE_403_STABLE' include: - php: '7.4' moodle-branch: 'MOODLE_401_STABLE' From 0ec224ce309c453e021ce784207669f8bd9a96a1 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 24 May 2024 18:43:55 +0200 Subject: [PATCH 103/123] code cleaning --- classes/external.php | 2 +- tests/behat/behat_block_townsquare.php | 12 ------------ tests/behat/block_townsquare_savepreferences.feature | 2 -- 3 files changed, 1 insertion(+), 15 deletions(-) diff --git a/classes/external.php b/classes/external.php index de9c4a9..db19576 100644 --- a/classes/external.php +++ b/classes/external.php @@ -81,7 +81,7 @@ public static function record_usersettings_returns(): external_value { */ public static function record_usersettings($userid, $timefilterpast, $timefilterfuture, $basicletter, $completionletter, $postletter): bool { - global $DB, $CFG; + global $DB; // Parameter validation. $params = self::validate_parameters(self::record_usersettings_parameters(), [ 'userid' => $userid, 'timefilterpast' => $timefilterpast, 'timefilterfuture' => $timefilterfuture, diff --git a/tests/behat/behat_block_townsquare.php b/tests/behat/behat_block_townsquare.php index 1e7aa09..49cd84e 100644 --- a/tests/behat/behat_block_townsquare.php +++ b/tests/behat/behat_block_townsquare.php @@ -61,16 +61,4 @@ public function i_add_an_townsquare_completion_event(string $coursename) { ]; $generator->create_module('assign', $assignrecord, $featurecompletionmanual); } - - /** - * Test for debugging - * @Given /^I townsquare debug$/ - */ - public function i_townsquare_debug() { - global $DB; - // \block_townsquare\external::record_usersettings(1, 1, 1, 1, 1, 1); - $record = $DB->get_records('block_townsquare_preferences'); - var_dump($record); - ob_flush(); - } } diff --git a/tests/behat/block_townsquare_savepreferences.feature b/tests/behat/block_townsquare_savepreferences.feature index 64d7412..b3c8c9c 100644 --- a/tests/behat/block_townsquare_savepreferences.feature +++ b/tests/behat/block_townsquare_savepreferences.feature @@ -29,9 +29,7 @@ Feature: In the townsquare block user can save their settings in a database. Then I should see "Test assign 2" in the "Town Square" "block" And I click on "Time filter" "text" And I click on "Next two days" "text" - And I townsquare debug When I click on "Save settings" "text" in the "Town Square" "block" Then I should not see "Test assign 2" in the "Town Square" "block" - And I townsquare debug And I reload the page Then I should not see "Test assign 2" in the "Town Square" "block" \ No newline at end of file From 633d5632e187dc7007297c1951af4448d79c164f Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 24 May 2024 18:46:06 +0200 Subject: [PATCH 104/123] behat works on M4.1 --- .github/workflows/moodle-ci.yml | 4 ++-- amd/src/usersettings_save.js | 2 +- classes/external.php | 21 +++++++-------------- classes/letter/letter.php | 4 ++-- locallib.php | 23 ++++++++++++++--------- 5 files changed, 26 insertions(+), 28 deletions(-) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index 9ad9b1e..b5777a9 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -8,8 +8,8 @@ jobs: strategy: matrix: - php: ['8.2'] - moodle-branch: ['MOODLE_403_STABLE'] + php: ['8.3'] + moodle-branch: ['MOODLE_404_STABLE'] database: ['pgsql'] steps: diff --git a/amd/src/usersettings_save.js b/amd/src/usersettings_save.js index 85f1d45..8a7b359 100644 --- a/amd/src/usersettings_save.js +++ b/amd/src/usersettings_save.js @@ -88,7 +88,7 @@ function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, }, }; result = Ajax.call([data]); - + console.log('HI I AM HERE'); // Make the clicked button green by adding a class. savebutton.classList.add('bg-success', 'text-white', 'ts_button_transition'); diff --git a/classes/external.php b/classes/external.php index 9b3c07a..db19576 100644 --- a/classes/external.php +++ b/classes/external.php @@ -22,7 +22,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace block_townsquare; -use core_external\external_function_parameters; +use external_function_parameters; use Exception; use external_api; use external_value; @@ -81,20 +81,12 @@ public static function record_usersettings_returns(): external_value { */ public static function record_usersettings($userid, $timefilterpast, $timefilterfuture, $basicletter, $completionletter, $postletter): bool { - global $DB, $CFG; - + global $DB; // Parameter validation. - if ($CFG->branch >= 402) { - $params = self::validate_parameters(self::record_usersettings_parameters(), [ - 'userid' => $userid, 'timefilterpast' => $timefilterpast, 'timefilterfuture' => $timefilterfuture, - 'basicletter' => $basicletter, 'completionletter' => $completionletter, 'postletter' => $postletter, - ]); - } else { - // TODO: delete this branch when Moodle 4.1 is no longer supported. - $params = [ - 'userid' => $userid, 'timefilterpast' => $timefilterpast, 'timefilterfuture' => $timefilterfuture, - 'basicletter' => $basicletter, 'completionletter' => $completionletter, 'postletter' => $postletter, ]; - } + $params = self::validate_parameters(self::record_usersettings_parameters(), [ + 'userid' => $userid, 'timefilterpast' => $timefilterpast, 'timefilterfuture' => $timefilterfuture, + 'basicletter' => $basicletter, 'completionletter' => $completionletter, 'postletter' => $postletter, + ]); // Check if the user already has a record in the database. if ($records = $DB->get_records('block_townsquare_preferences', ['userid' => $userid])) { @@ -116,6 +108,7 @@ public static function record_usersettings($userid, $timefilterpast, $timefilter $record->basicletter = $params['basicletter']; $record->completionletter = $params['completionletter']; $record->postletter = $params['postletter']; + $DB->update_record('block_townsquare_preferences', $record); return true; } diff --git a/classes/letter/letter.php b/classes/letter/letter.php index 48a71f0..f54cf16 100644 --- a/classes/letter/letter.php +++ b/classes/letter/letter.php @@ -78,8 +78,8 @@ class letter { /** @var bool variable for the mustache template */ public bool $isbasic = true; - /** @var mixed color of the letter. Only used by mustache */ - public mixed $lettercolor; + /** @var string color of the letter. Only used by mustache */ + public string $lettercolor; // Constructor. diff --git a/locallib.php b/locallib.php index c7f9dfc..29048bf 100644 --- a/locallib.php +++ b/locallib.php @@ -26,17 +26,22 @@ * Function to get the color of a letter. * * @param string $lettertype The type of the letter that wants to retrieve its color setting. - * @return false|mixed The color of the letter. + * @return false|string The color of the letter. * @throws moodle_exception */ -function townsquare_get_colorsetting($lettertype) { - return match ($lettertype) { - 'basicletter' => get_config('block_townsquare', 'basiclettercolor'), - 'postletter' => get_config('block_townsquare', 'postlettercolor'), - 'completionletter' => get_config('block_townsquare', 'completionlettercolor'), - 'orientationmarker' => get_config('block_townsquare', 'orientationmarkercolor'), - default => throw new \moodle_exception('invalidlettertype', 'block_townsquare'), - }; +function townsquare_get_colorsetting($lettertype): string { + switch ($lettertype) { + case 'basicletter': + return get_config('block_townsquare', 'basiclettercolor'); + case 'postletter': + return get_config('block_townsquare', 'postlettercolor'); + case 'completionletter': + return get_config('block_townsquare', 'completionlettercolor'); + case 'orientationmarker': + return get_config('block_townsquare', 'orientationmarkercolor'); + default: + throw new \moodle_exception('invalidlettertype', 'block_townsquare'); + } } /** From 2b3a7345c7a70f257baadeab9eac9ef9c01d4198 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 7 Jun 2024 16:24:10 +0200 Subject: [PATCH 105/123] post pictures are shown correctly --- classes/letter/post_letter.php | 12 ++++++++++-- classes/townsquareevents.php | 3 ++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/classes/letter/post_letter.php b/classes/letter/post_letter.php index 2c1829b..630a030 100644 --- a/classes/letter/post_letter.php +++ b/classes/letter/post_letter.php @@ -26,6 +26,9 @@ use moodle_url; use stdClass; +global $CFG; +require_once($CFG->libdir . '/portfoliolib.php'); + /** * Class that represents a post from the forum or moodleoverflow module. * @@ -89,7 +92,8 @@ public function __construct($contentid, $postevent) { $this->post->instanceid = $postevent->instanceid; $this->post->discussionid = $postevent->postdiscussion; $this->post->id = $postevent->postid; - $this->post->message = $postevent->postmessage; + $this->post->message = $this->format_post($postevent->postmessage, $postevent->postmessageformat, + $postevent->coursemoduleid); $this->post->discussionsubject = $postevent->discussionsubject; $this->post->parentid = $postevent->postparentid; $this->author->id = $postevent->postuserid; @@ -120,7 +124,7 @@ public function export_letter():array { 'authorname' => $this->author->name, 'authorpicture' => $this->author->picture, 'postid' => $this->post->id, - 'message' => format_text($this->post->message), + 'message' => $this->post->message, 'created' => date('d.m.Y', $this->created), 'createdtimestamp' => $this->created, 'linktocourse' => $this->linktocourse->out(), @@ -192,7 +196,11 @@ private function add_anonymousattribute($postevent): void { } else { $this->post->anonymous = false; } + } + private function format_post($message, $messageformat, $cmid) { + $options = (array) portfolio_format_text_options() + ['context' => \context_module::instance($cmid)]; + return format_text($message, $messageformat, $options); } } diff --git a/classes/townsquareevents.php b/classes/townsquareevents.php index 2f275f6..dd5896c 100644 --- a/classes/townsquareevents.php +++ b/classes/townsquareevents.php @@ -233,7 +233,8 @@ private function get_posts_from_db($modulename, $courses, $timestart): array { posts.parent AS postparentid, posts.userid AS postuserid, posts.created AS postcreated, - posts.message AS postmessage "; + posts.message AS postmessage, + posts.messageformat AS postmessageformat "; // Extend the strings for the 2 module cases. if ($modulename == 'forum') { From 190912213822199d029faa7ccdea1940cecb7af9 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 7 Jun 2024 16:28:35 +0200 Subject: [PATCH 106/123] new testsuite and language fix --- lang/en/block_townsquare.php | 4 ++-- tests/phpunit.xml | 39 ++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 tests/phpunit.xml diff --git a/lang/en/block_townsquare.php b/lang/en/block_townsquare.php index f5822d9..8721fa2 100644 --- a/lang/en/block_townsquare.php +++ b/lang/en/block_townsquare.php @@ -26,8 +26,8 @@ defined('MOODLE_INTERNAL') || die(); // Core strings for the installation. -$string['pluginname'] = 'Townsquare block'; -$string['pluginname'] = 'Town Square'; +$string['pluginname'] = 'Townsquare'; +$string['plugintitle'] = 'Town Square Block'; $string['pluginname:addinstance'] = 'Add the Town Square block'; $string['pluginname:myaddinstance'] = 'Add the Town Square block to the dashboard'; diff --git a/tests/phpunit.xml b/tests/phpunit.xml new file mode 100644 index 0000000..92b65f6 --- /dev/null +++ b/tests/phpunit.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + blocks/townsquare/tests + + + + From c36f6a81902ca761b780f72573b0a3ab98aa4319 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 7 Jun 2024 16:36:20 +0200 Subject: [PATCH 107/123] add internal check --- classes/letter/post_letter.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/classes/letter/post_letter.php b/classes/letter/post_letter.php index 630a030..061b578 100644 --- a/classes/letter/post_letter.php +++ b/classes/letter/post_letter.php @@ -26,6 +26,8 @@ use moodle_url; use stdClass; +defined('MOODLE_INTERNAL') || die; + global $CFG; require_once($CFG->libdir . '/portfoliolib.php'); From 1d4825f2f401a95a54bdfd16c6d110f5edfa991e Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Tue, 11 Jun 2024 16:53:42 +0200 Subject: [PATCH 108/123] codecleaning --- block_townsquare.php | 6 +++--- classes/contentcontroller.php | 4 ++-- classes/letter/activitycompletion_letter.php | 2 +- classes/letter/post_letter.php | 9 ++++++++- classes/orientation_marker.php | 2 +- classes/output/renderer.php | 2 +- lang/en/block_townsquare.php | 8 ++++---- settings.php | 2 +- tests/calendarevents_test.php | 8 ++++---- tests/contentcontroller_test.php | 6 +++--- tests/external_test.php | 2 +- tests/postevents_test.php | 8 ++++---- tests/privacy/provider_test.php | 6 +++--- 13 files changed, 36 insertions(+), 29 deletions(-) diff --git a/block_townsquare.php b/block_townsquare.php index 70433ee..2cc0256 100644 --- a/block_townsquare.php +++ b/block_townsquare.php @@ -30,7 +30,7 @@ class block_townsquare extends block_base { * * @return void */ - public function init():void { + public function init(): void { $this->title = get_string('pluginname', 'block_townsquare'); } @@ -39,7 +39,7 @@ public function init():void { * * @return object|null The block HTML. */ - public function get_content():object { + public function get_content(): object { global $OUTPUT, $DB, $USER; if ($this->content !== null) { @@ -72,7 +72,7 @@ public function get_content():object { * * @return array of the pages where the block can be added. */ - public function applicable_formats():array { + public function applicable_formats(): array { return [ 'admin' => false, 'site-index' => false, diff --git a/classes/contentcontroller.php b/classes/contentcontroller.php index 878ce7e..8264085 100644 --- a/classes/contentcontroller.php +++ b/classes/contentcontroller.php @@ -108,7 +108,7 @@ public function build_content(): array { * Getter for the content * @return array */ - public function get_content():array { + public function get_content(): array { return $this->content; } @@ -116,7 +116,7 @@ public function get_content():array { * Getter for the events * @return array */ - public function get_events():array { + public function get_events(): array { return $this->events; } } diff --git a/classes/letter/activitycompletion_letter.php b/classes/letter/activitycompletion_letter.php index 4d84ffa..7ad5fb8 100644 --- a/classes/letter/activitycompletion_letter.php +++ b/classes/letter/activitycompletion_letter.php @@ -59,7 +59,7 @@ public function __construct($contentid, $calendarevent) { * Export function for the mustache template. * return array */ - public function export_letter():array { + public function export_letter(): array { return [ 'contentid' => $this->contentid, 'lettertype' => $this->lettertype, diff --git a/classes/letter/post_letter.php b/classes/letter/post_letter.php index 061b578..faa411b 100644 --- a/classes/letter/post_letter.php +++ b/classes/letter/post_letter.php @@ -112,7 +112,7 @@ public function __construct($contentid, $postevent) { * Export Function for the mustache template. * @return array */ - public function export_letter():array { + public function export_letter(): array { return [ 'contentid' => $this->contentid, 'lettertype' => $this->lettertype, @@ -200,6 +200,13 @@ private function add_anonymousattribute($postevent): void { } } + /** + * Function to format the post message before exporting it to the mustache template. + * @param $message + * @param $messageformat + * @param $cmid + * @return string + */ private function format_post($message, $messageformat, $cmid) { $options = (array) portfolio_format_text_options() + ['context' => \context_module::instance($cmid)]; return format_text($message, $messageformat, $options); diff --git a/classes/orientation_marker.php b/classes/orientation_marker.php index 741dadf..235aebe 100644 --- a/classes/orientation_marker.php +++ b/classes/orientation_marker.php @@ -68,7 +68,7 @@ public function __construct($contentid, $time) { * Export function for the mustache template. * @return array */ - public function export_data():array { + public function export_data(): array { // Change the timestamp to a date. $date = date('d.m.Y', $this->today); diff --git a/classes/output/renderer.php b/classes/output/renderer.php index f158b5e..a9db5c0 100644 --- a/classes/output/renderer.php +++ b/classes/output/renderer.php @@ -40,7 +40,7 @@ class renderer extends plugin_renderer_base { * @param array $data Data to render the townsquare templates * @return string HTML string */ - public function render_main($data):string { + public function render_main($data): string { return $this->render_from_template('block_townsquare/blockcontent', $data); } } diff --git a/lang/en/block_townsquare.php b/lang/en/block_townsquare.php index 8721fa2..09d857b 100644 --- a/lang/en/block_townsquare.php +++ b/lang/en/block_townsquare.php @@ -27,9 +27,9 @@ // Core strings for the installation. $string['pluginname'] = 'Townsquare'; -$string['plugintitle'] = 'Town Square Block'; $string['pluginname:addinstance'] = 'Add the Town Square block'; $string['pluginname:myaddinstance'] = 'Add the Town Square block to the dashboard'; +$string['plugintitle'] = 'Town Square Block'; // Privacy strings. $string['privacy:metadata:block_townsquare_preferences'] = 'Town Square stores the filters that a user wants to have activated.'; @@ -108,10 +108,10 @@ $string['forumduemessage'] = 'The forum is due until {$a->time}'; $string['lessonopenmessage'] = 'The lesson opens today at {$a->time}'; $string['lessonclosemessage'] = 'The lesson ends today at {$a->time}'; -$string['quizopenmessage'] = 'The Quiz is open from {$a->time} onwards'; $string['quizclosemessage'] = 'The Quiz closes today at {$a->time}'; -$string['quizopenmessage'] = 'Scorm Activity opens today'; -$string['quizclosemessage'] = 'Scorm Activity closes today'; +$string['quizopenmessage'] = 'The Quiz is open from {$a->time} onwards'; +$string['scormopenmessage'] = 'Scorm Activity opens today'; +$string['scormclosemessage'] = 'Scorm Activity closes today'; $string['workshopopensubmission'] = 'Submissions for the workshop are possible from {$a->time} onwards'; $string['workshopclosesubmission'] = 'Please submit your work until {$a->time}. The workshop closes afterwards'; $string['workshopopenassessment'] = 'The assessment phase starts today at {$a->time}'; diff --git a/settings.php b/settings.php index 232317f..43a254e 100644 --- a/settings.php +++ b/settings.php @@ -17,7 +17,7 @@ /** * File for the settings of moodleoverflow. * - * @package blocks_townsquare + * @package block_townsquare * @copyright 2024 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/tests/calendarevents_test.php b/tests/calendarevents_test.php index 103dd32..d9c32f0 100644 --- a/tests/calendarevents_test.php +++ b/tests/calendarevents_test.php @@ -41,7 +41,7 @@ * * @covers \block_townsquare\townsquareevents::get_calendarevents() */ -class calendarevents_test extends \advanced_testcase { +final class calendarevents_test extends \advanced_testcase { // Attributes. @@ -271,7 +271,7 @@ private function helper_course_set_up(): void { * @param bool $activitycompletion * @return object */ - private function create_assignment($courseid, $allowsubmissionsdate, $duedate, $gradingduedate, $activitycompletion):object { + private function create_assignment($courseid, $allowsubmissionsdate, $duedate, $gradingduedate, $activitycompletion): object { // Create an activity completion for the assignment if wanted. $featurecompletionmanual = []; if ($activitycompletion) { @@ -295,7 +295,7 @@ private function create_assignment($courseid, $allowsubmissionsdate, $duedate, $ * @param object $user The user for whom the events should be collected (townsquareevents.php uses $USER). * @return array */ - private function get_calendarevents_from_user($user):array { + private function get_calendarevents_from_user($user): array { $this->setUser($user); $townsquareevents = new townsquareevents(); return $townsquareevents->get_calendarevents(); @@ -308,7 +308,7 @@ private function get_calendarevents_from_user($user):array { * @param array $enrolledcourses * @return bool */ - private function check_eventcourses($events, $enrolledcourses):bool { + private function check_eventcourses($events, $enrolledcourses): bool { foreach ($events as $event) { $eventcourseid = $event->courseid; diff --git a/tests/contentcontroller_test.php b/tests/contentcontroller_test.php index 53b88ac..102c243 100644 --- a/tests/contentcontroller_test.php +++ b/tests/contentcontroller_test.php @@ -33,7 +33,7 @@ * * @covers \block_townsquare\contentcontroller */ -class contentcontroller_test extends \advanced_testcase { +final class contentcontroller_test extends \advanced_testcase { // Attributes. @@ -121,7 +121,7 @@ public function test_letters(): void { * Helper function that sets up the testdata. * @return void */ - private function helper_course_set_up():void { + private function helper_course_set_up(): void { global $DB; // Declare generators. $datagenerator = $this->getDataGenerator(); @@ -160,7 +160,7 @@ private function helper_course_set_up():void { * @param int $gradingduedate timestamp * @return object */ - private function create_assignment($allowsubmissionsdate, $duedate, $gradingduedate):object { + private function create_assignment($allowsubmissionsdate, $duedate, $gradingduedate): object { // Create an activity completion for the assignment if wanted. $featurecompletionmanual = [ 'completion' => COMPLETION_TRACKING_MANUAL, diff --git a/tests/external_test.php b/tests/external_test.php index d88e3e8..d10c623 100644 --- a/tests/external_test.php +++ b/tests/external_test.php @@ -39,7 +39,7 @@ * @covers \block_townsquare\external::record_usersettings * @runTestsInSeparateProcesses */ -class external_test extends \advanced_testcase { +final class external_test extends \advanced_testcase { public function setUp(): void { $this->resetAfterTest(); diff --git a/tests/postevents_test.php b/tests/postevents_test.php index a7a21dd..dee68a8 100644 --- a/tests/postevents_test.php +++ b/tests/postevents_test.php @@ -35,7 +35,7 @@ * * @covers \block_townsquare\townsquareevents::get_postevents() */ -class postevents_test extends \advanced_testcase { +final class postevents_test extends \advanced_testcase { // Attributes. @@ -378,7 +378,7 @@ private function helper_course_set_up(): void { * @param object $moodleoverflow The moodleoverflow that should be made anonymous. * @param int $anonymoussetting The type of anonymous moodleoverflow. */ - private function make_anonymous($moodleoverflow, $anonymoussetting):void { + private function make_anonymous($moodleoverflow, $anonymoussetting): void { global $DB; if ($anonymoussetting == 1 || $anonymoussetting == 2) { $moodleoverflow->anonymous = $anonymoussetting; @@ -393,7 +393,7 @@ private function make_anonymous($moodleoverflow, $anonymoussetting):void { * @param object $user The user for whom the events should be collected (townsquareevents.php uses $USER). * @return array */ - private function get_postevents_from_user($user):array { + private function get_postevents_from_user($user): array { $this->setUser($user); $townsquareevents = new townsquareevents(); return $townsquareevents->get_postevents(); @@ -405,7 +405,7 @@ private function get_postevents_from_user($user):array { * @param array $enrolledcourses * @return bool */ - private function check_postcourses($posts, $enrolledcourses):bool { + private function check_postcourses($posts, $enrolledcourses): bool { foreach ($posts as $post) { $postcourseid = $post->courseid; diff --git a/tests/privacy/provider_test.php b/tests/privacy/provider_test.php index c3355ac..af5afb5 100644 --- a/tests/privacy/provider_test.php +++ b/tests/privacy/provider_test.php @@ -40,7 +40,7 @@ * * @covers \block_townsquare\privacy\provider */ -class provider_test extends provider_testcase { +final class provider_test extends provider_testcase { /** @var object The data that will be used for testing. * This Class contains: @@ -86,7 +86,7 @@ public function test_get_contexts_for_userid(): void { * Test getting the users in the context related to this plugin. * @return void */ - public function test_get_users_in_context():void { + public function test_get_users_in_context(): void { // Check that no users are found in the context before the setting is set. $userlist = new userlist($this->testdata->studentcontext, 'block_townsquare'); provider::get_users_in_context($userlist); @@ -106,7 +106,7 @@ public function test_get_users_in_context():void { * Test if the metadata is correct. * @return void */ - public function test_get_metadata():void { + public function test_get_metadata(): void { // Get the metadata and check if a collection exists. $metadata = provider::get_metadata(new collection('block_townsquare')); $collection = $metadata->get_collection(); From 9306e04d6d7d23bb42b9ce50811ab54334258304 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 13 Jun 2024 11:07:32 +0200 Subject: [PATCH 109/123] adapt code to new codechecker version --- classes/townsquareevents.php | 1 - lang/en/block_townsquare.php | 124 ++++++++++++++++------------------- 2 files changed, 58 insertions(+), 67 deletions(-) diff --git a/classes/townsquareevents.php b/classes/townsquareevents.php index dd5896c..e005e87 100644 --- a/classes/townsquareevents.php +++ b/classes/townsquareevents.php @@ -293,7 +293,6 @@ private function get_events_from_db($timestart, $timeend, $courses): array { $coremodules = ['assign', 'book', 'chat', 'choice', 'data', 'feedback', 'folder', 'forum', 'glossary', 'h5pactivity', 'imscp', 'label', 'lesson', 'lti', 'page', 'quiz', 'resource', 'scorm', 'survey', 'url', 'wiki', 'workshop', ]; - // TODO: Additional modules should be implemented with subplugins. $additionalmodules = ['moodleoverflow', 'ratingallocate']; $modules = $coremodules + $additionalmodules; diff --git a/lang/en/block_townsquare.php b/lang/en/block_townsquare.php index 09d857b..8dac662 100644 --- a/lang/en/block_townsquare.php +++ b/lang/en/block_townsquare.php @@ -25,94 +25,86 @@ defined('MOODLE_INTERNAL') || die(); -// Core strings for the installation. +$string['allnotifications'] = 'All notifications'; +$string['assignduemessage'] = 'Assignment is due until {$a->time}'; +$string['assigngradingduemessage'] = 'Assignment is due to be graded until {$a->time}'; +$string['basiclettercolor'] = 'Color for basic letters'; +$string['basicletterorigin'] = 'A notification from {$a->modulename}:'; +$string['basicletters'] = 'Basic letters'; +$string['chattimemessage'] = 'The next chat time is today at {$a->time}'; +$string['choiceclosemessage'] = 'Please vote until {$a->time}. Afterwards the choice is closed'; +$string['choiceopenmessage'] = 'Voting is possible from {$a->time} onwards'; +$string['completionlettercolor'] = 'Color for activity completion letters'; +$string['completionletterorigin'] = '{$a->modulename} should be completed until {$a->date}'; +$string['completionletters'] = 'Activity completions'; +$string['configbasiclettercolor'] = 'Configuration for the color of the basic notification letters'; +$string['configcompletionlettercolor'] = 'Configuration for the color of the activity completion letters'; +$string['configorientationmarkercolor'] = 'Configuration for the color of the orientation marker'; +$string['configpostlettercolor'] = 'Configuration for the color of the post letters'; +$string['coursefilter'] = 'Course filter'; +$string['dataclosemessage'] = 'Please submit your entries until {$a->time}. The database closes afterwards'; +$string['dataopenmessage'] = 'The database opens today'; +$string['feedbackclosemessage'] = 'Writing feedback is possible until {$a->time}'; +$string['feedbackopenmessage'] = 'Writing feedback is possible from {$a->time} onwards'; +$string['forumduemessage'] = 'The forum is due until {$a->time}'; +$string['invalidlettertype'] = 'Invalid function parameter, please use a valid letter type'; +$string['invalidmodulename'] = 'Module name is unknown or not supported'; +$string['lastfivedaysnotifications'] = 'Last five days'; +$string['lastmonthnotifications'] = 'Last month'; +$string['lasttwodaysnotifications'] = 'Last two days'; +$string['lastweeknotifications'] = 'Last week'; +$string['lessonclosemessage'] = 'The lesson ends today at {$a->time}'; +$string['lessonopenmessage'] = 'The lesson opens today at {$a->time}'; +$string['letterfilter'] = 'Letter filter'; +$string['nextfivedaysnotifications'] = 'Next five days'; +$string['nextmonthnotifications'] = 'Next month'; +$string['nexttwodaysnotifications'] = 'Next two days'; +$string['nextweeknotifications'] = 'Next week'; +$string['orientationmarkercolor'] = 'Color for the orientation marker'; +$string['orientationmarkercontent'] = 'Hi {$a->username}, welcome to townsquare! Today is the {$a->date}'; $string['pluginname'] = 'Townsquare'; $string['pluginname:addinstance'] = 'Add the Town Square block'; $string['pluginname:myaddinstance'] = 'Add the Town Square block to the dashboard'; $string['plugintitle'] = 'Town Square Block'; -// Privacy strings. +$string['postlettercolor'] = 'Color for post letters'; +$string['postletternotification'] = 'New {$a->modulename} post!'; +$string['postletterorigin'] = '{$a->authorname} posted in {$a->instancename} -> {$a->discussionname}:'; +$string['postletters'] = 'Forum posts'; $string['privacy:metadata:block_townsquare_preferences'] = 'Town Square stores the filters that a user wants to have activated.'; -$string['privacy:metadata:block_townsquare_preferences:userid'] = 'The user id'; -$string['privacy:metadata:block_townsquare_preferences:timefilterpast'] = 'How far back the user wants to see notifications'; -$string['privacy:metadata:block_townsquare_preferences:timefilterfuture'] = 'How far into the future the user wants to see notifications'; $string['privacy:metadata:block_townsquare_preferences:basicletter'] = 'If the user wants to see basic letters'; $string['privacy:metadata:block_townsquare_preferences:completionletter'] = 'If the user wants to see completion letters'; $string['privacy:metadata:block_townsquare_preferences:postletter'] = 'If the user wants to see post letters'; +$string['privacy:metadata:block_townsquare_preferences:timefilterfuture'] = 'How far into the future the user wants to see notifications'; +$string['privacy:metadata:block_townsquare_preferences:timefilterpast'] = 'How far back the user wants to see notifications'; +$string['privacy:metadata:block_townsquare_preferences:userid'] = 'The user id'; -// Error strings. -$string['invalidlettertype'] = 'Invalid function parameter, please use a valid letter type'; -// Mustache templates strings. -$string['completionletterorigin'] = '{$a->modulename} should be completed until {$a->date}'; -$string['basicletterorigin'] = 'A notification from {$a->modulename}:'; -$string['postletternotification'] = 'New {$a->modulename} post!'; -$string['postletterorigin'] = '{$a->authorname} posted in {$a->instancename} -> {$a->discussionname}:'; -$string['orientationmarkercontent'] = 'Hi {$a->username}, welcome to townsquare! Today is the {$a->date}'; -// Side panel filter strings. -// Filter headers. -$string['coursefilter'] = 'Course filter'; -$string['timefilter'] = 'Time filter'; -$string['letterfilter'] = 'Letter filter'; -// Time filter options. -$string['allnotifications'] = 'All notifications'; -$string['nexttwodaysnotifications'] = 'Next two days'; -$string['nextfivedaysnotifications'] = 'Next five days'; -$string['nextweeknotifications'] = 'Next week'; -$string['nextmonthnotifications'] = 'Next month'; -$string['lasttwodaysnotifications'] = 'Last two days'; -$string['lastfivedaysnotifications'] = 'Last five days'; -$string['lastweeknotifications'] = 'Last week'; -$string['lastmonthnotifications'] = 'Last month'; - -// Letter filter options. -$string['basicletters'] = 'Basic letters'; -$string['completionletters'] = 'Activity completions'; -$string['postletters'] = 'Forum posts'; -$string['showmore'] = 'Show more'; -// Save button strings. +$string['quizclosemessage'] = 'The Quiz closes today at {$a->time}'; +$string['quizopenmessage'] = 'The Quiz is open from {$a->time} onwards'; $string['savebutton'] = 'Save settings'; $string['savehelpicontext'] = 'Save Settings for the future'; $string['savemessage'] = 'Settings successfully saved!'; +$string['scormclosemessage'] = 'Scorm Activity closes today'; +$string['scormopenmessage'] = 'Scorm Activity opens today'; +$string['showmore'] = 'Show more'; +$string['timefilter'] = 'Time filter'; -// End of the side panel filter strings. -// Letter strings. -$string['invalidmodulename'] = 'Module name is unknown or not supported'; -// Setting strings. -$string['basiclettercolor'] = 'Color for basic letters'; -$string['postlettercolor'] = 'Color for post letters'; -$string['completionlettercolor'] = 'Color for activity completion letters'; -$string['orientationmarkercolor'] = 'Color for the orientation marker'; -$string['configbasiclettercolor'] = 'Configuration for the color of the basic notification letters'; -$string['configpostlettercolor'] = 'Configuration for the color of the post letters'; -$string['configcompletionlettercolor'] = 'Configuration for the color of the activity completion letters'; -$string['configorientationmarkercolor'] = 'Configuration for the color of the orientation marker'; -// Event strings. -$string['assignduemessage'] = 'Assignment is due until {$a->time}'; -$string['assigngradingduemessage'] = 'Assignment is due to be graded until {$a->time}'; -$string['chattimemessage'] = 'The next chat time is today at {$a->time}'; -$string['choiceopenmessage'] = 'Voting is possible from {$a->time} onwards'; -$string['choiceclosemessage'] = 'Please vote until {$a->time}. Afterwards the choice is closed'; -$string['dataopenmessage'] = 'The database opens today'; -$string['dataclosemessage'] = 'Please submit your entries until {$a->time}. The database closes afterwards'; -$string['feedbackopenmessage'] = 'Writing feedback is possible from {$a->time} onwards'; -$string['feedbackclosemessage'] = 'Writing feedback is possible until {$a->time}'; -$string['forumduemessage'] = 'The forum is due until {$a->time}'; -$string['lessonopenmessage'] = 'The lesson opens today at {$a->time}'; -$string['lessonclosemessage'] = 'The lesson ends today at {$a->time}'; -$string['quizclosemessage'] = 'The Quiz closes today at {$a->time}'; -$string['quizopenmessage'] = 'The Quiz is open from {$a->time} onwards'; -$string['scormopenmessage'] = 'Scorm Activity opens today'; -$string['scormclosemessage'] = 'Scorm Activity closes today'; -$string['workshopopensubmission'] = 'Submissions for the workshop are possible from {$a->time} onwards'; + + + + + + +$string['workshopcloseassessment'] = 'Assessments for the workshop are due until {$a->time}'; $string['workshopclosesubmission'] = 'Please submit your work until {$a->time}. The workshop closes afterwards'; $string['workshopopenassessment'] = 'The assessment phase starts today at {$a->time}'; -$string['workshopcloseassessment'] = 'Assessments for the workshop are due until {$a->time}'; +$string['workshopopensubmission'] = 'Submissions for the workshop are possible from {$a->time} onwards'; From ebfc411be52ae45d7a430004ff7ad3e9105398eb Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 20 Jun 2024 08:35:40 +0200 Subject: [PATCH 110/123] rename locallib to lib --- classes/townsquareevents.php | 2 +- locallib.php => lib.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename locallib.php => lib.php (99%) diff --git a/classes/townsquareevents.php b/classes/townsquareevents.php index b87d56e..1b20e7b 100644 --- a/classes/townsquareevents.php +++ b/classes/townsquareevents.php @@ -32,7 +32,7 @@ global $CFG; require_once($CFG->dirroot . '/calendar/lib.php'); -require_once($CFG->dirroot . '/blocks/townsquare/locallib.php'); +require_once($CFG->dirroot . '/blocks/townsquare/lib.php'); /** * Class to get events and posts that will be shown in the townsquare block.. diff --git a/locallib.php b/lib.php similarity index 99% rename from locallib.php rename to lib.php index 6e9e42d..7a2fcfa 100644 --- a/locallib.php +++ b/lib.php @@ -15,7 +15,7 @@ // along with Moodle. If not, see . /** - * Internal library of functions for the townsquare block + * Library of functions of the townsquare block, that can be used moodle wide. * * @package block_townsquare * @copyright 2024 Tamaro Walter From d41ac75da4afa8d6faf09b189d4b49c28dca3c19 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Sun, 23 Jun 2024 15:35:17 +0200 Subject: [PATCH 111/123] WIP: code mess cleaning --- classes/contentcontroller.php | 8 +-- classes/letter/post_letter.php | 2 +- classes/townsquareevents.php | 10 +-- tests/behat/behat_block_townsquare.php | 4 +- tests/calendarevents_test.php | 6 +- tests/contentcontroller_test.php | 38 +++++++---- tests/postevents_test.php | 95 +++++++++++++++++--------- 7 files changed, 102 insertions(+), 61 deletions(-) diff --git a/classes/contentcontroller.php b/classes/contentcontroller.php index 8264085..c306d85 100644 --- a/classes/contentcontroller.php +++ b/classes/contentcontroller.php @@ -72,18 +72,16 @@ public function build_content(): array { // Build a letter for each event. foreach ($this->events as $event) { // Display a orientation marker on the current date between the other events. - if (!$orientationmarkerset && isset($event->eventtype) && ( - ($event->eventtype != 'post' && $event->timestart <= $time) || - ($event->eventtype == 'post' && $event->postcreated <= $time))) { + if (!$orientationmarkerset && (($event->timestart <= $time))) { $orientationmarkerset = true; $tempcontent = new orientation_marker($index, $time); $this->content[$index] = $tempcontent->export_data(); $index++; } - if (isset($event->eventtype) && $event->eventtype == 'post') { + if ($event->eventtype == 'post') { $templetter = new letter\post_letter($index, $event); - } else if (isset($event->eventtype) && $event->eventtype == 'expectcompletionon') { + } else if ($event->eventtype == 'expectcompletionon') { $templetter = new letter\activitycompletion_letter($index, $event); } else { $templetter = new letter\letter($index, $event->courseid, $event->modulename, $event->instancename, diff --git a/classes/letter/post_letter.php b/classes/letter/post_letter.php index faa411b..66b3f94 100644 --- a/classes/letter/post_letter.php +++ b/classes/letter/post_letter.php @@ -83,7 +83,7 @@ class post_letter extends letter { */ public function __construct($contentid, $postevent) { parent::__construct($contentid, $postevent->courseid, $postevent->modulename, $postevent->instancename, - $postevent->postmessage, $postevent->postcreated, $postevent->coursemoduleid); + $postevent->postmessage, $postevent->timestart, $postevent->coursemoduleid); $this->author = new stdClass(); $this->post = new stdClass(); diff --git a/classes/townsquareevents.php b/classes/townsquareevents.php index e005e87..1b8b8ee 100644 --- a/classes/townsquareevents.php +++ b/classes/townsquareevents.php @@ -77,7 +77,7 @@ public function get_all_events_sorted(): array { $numberofevents = count($calendarevents) + count($postevents); for ($i = 0; $i < $numberofevents; $i++) { if (current($calendarevents) && current($postevents)) { - if (current($calendarevents)->timestart > current($postevents)->postcreated) { + if (current($calendarevents)->timestart > current($postevents)->timestart) { $events[$i] = current($calendarevents); next($calendarevents); } else { @@ -176,7 +176,7 @@ public function get_postevents(): array { // Merge. if (current($forumposts) && current($moodleoverflowposts)) { - if (current($forumposts)->postcreated > current($moodleoverflowposts)->postcreated) { + if (current($forumposts)->timestart > current($moodleoverflowposts)->timestart) { $posts[$i] = current($forumposts); next($forumposts); } else { @@ -232,7 +232,7 @@ private function get_posts_from_db($modulename, $courses, $timestart): array { posts.discussion AS postdiscussion, posts.parent AS postparentid, posts.userid AS postuserid, - posts.created AS postcreated, + posts.created AS timestart, posts.message AS postmessage, posts.messageformat AS postmessageformat "; @@ -373,12 +373,12 @@ private function filter_assignment($calendarevent): bool { $overduecheck = $calendarevent->eventtype == "due" && $this->timenow >= ($calendarevent->timestart + 604800); // Check if the user is someone without grading capability. - $nogradecapabilitycheck = $calendarevent->eventtype == "gradingdue" && !has_capability('mod/assign:grade', + $cannotgradecheck = $calendarevent->eventtype == "gradingdue" && !has_capability('mod/assign:grade', context_module::instance($calendarevent->coursemoduleid)); // Check if the assignment is not open yet. $stillclosedcheck = $assignment->allowsubmissionsfromdate >= $this->timenow; - if ($overduecheck || $nogradecapabilitycheck || $stillclosedcheck) { + if ($overduecheck || $cannotgradecheck || $stillclosedcheck) { return true; } return false; diff --git a/tests/behat/behat_block_townsquare.php b/tests/behat/behat_block_townsquare.php index 49cd84e..3824594 100644 --- a/tests/behat/behat_block_townsquare.php +++ b/tests/behat/behat_block_townsquare.php @@ -47,7 +47,7 @@ public function i_add_an_townsquare_completion_event(string $coursename) { global $DB; $generator = new testing_data_generator(); $course = $DB->get_record('course', ['shortname' => $coursename]); - $featurecompletionmanual = [ + $options = [ 'completion' => COMPLETION_TRACKING_MANUAL, 'completionexpected' => time() + 604800, ]; @@ -59,6 +59,6 @@ public function i_add_an_townsquare_completion_event(string $coursename) { 'allowsubmissionsfromdate' => time() - 604800, 'gradingduedate' => time() + 604860, ]; - $generator->create_module('assign', $assignrecord, $featurecompletionmanual); + $generator->create_module('assign', $assignrecord, $options); } } diff --git a/tests/calendarevents_test.php b/tests/calendarevents_test.php index d9c32f0..2fd6216 100644 --- a/tests/calendarevents_test.php +++ b/tests/calendarevents_test.php @@ -273,9 +273,9 @@ private function helper_course_set_up(): void { */ private function create_assignment($courseid, $allowsubmissionsdate, $duedate, $gradingduedate, $activitycompletion): object { // Create an activity completion for the assignment if wanted. - $featurecompletionmanual = []; + $options = []; if ($activitycompletion) { - $featurecompletionmanual = [ + $options = [ 'completion' => COMPLETION_TRACKING_MANUAL, 'completionexpected' => $duedate, ]; @@ -287,7 +287,7 @@ private function create_assignment($courseid, $allowsubmissionsdate, $duedate, $ 'allowsubmissionsfromdate' => $allowsubmissionsdate, 'gradingduedate' => $gradingduedate, ]; - return $this->getDataGenerator()->create_module('assign', $assignrecord, $featurecompletionmanual); + return $this->getDataGenerator()->create_module('assign', $assignrecord, $options); } /** diff --git a/tests/contentcontroller_test.php b/tests/contentcontroller_test.php index 102c243..7cfcab3 100644 --- a/tests/contentcontroller_test.php +++ b/tests/contentcontroller_test.php @@ -49,7 +49,7 @@ final class contentcontroller_test extends \advanced_testcase { /** @var bool If the moodleoverflow module is available. * This Plugin can support moodleoverflow, but it is not necessary to have it installed. */ - private bool $moodleoverflowavailable; + private bool $modoverflowinstalled; // Construct functions. @@ -84,20 +84,20 @@ public function test_letters(): void { for ($i = 0; $i < $length; $i++) { // The content has an orientation marker. - if (isset(current($content)['isorientationmarker']) && current($content)['isorientationmarker']) { + if (isset(current($content)['isorientationmarker'])) { next($content); continue; } // Declare the three types of letter checks. - $postcheck = current($events)->eventtype == 'post' && current($content)['lettertype'] == 'post'; - $completioncheck = current($events)->eventtype == 'expectcompletionon' && - current($content)['lettertype'] == 'activitycompletion'; + $postcheck = $this->check_two_params(current($events)->eventtype, 'post', current($content)['lettertype'], 'post'); + $completioncheck = $this->check_two_params(current($events)->eventtype, 'expectcompletionon', + current($content)['lettertype'], 'activitycompletion'); $basiccheck = (current($events)->eventtype != 'post' && current($events)->eventtype != 'expectcompletionon') && current($content)['lettertype'] == 'basic'; - // If one of the checks fails there is a problem while creating the letters.. + // If one of the checks fails there is a problem while creating the letters. if (!$postcheck && !$completioncheck && !$basiccheck) { $result = false; break; @@ -107,7 +107,7 @@ public function test_letters(): void { next($events); } - if ($this->moodleoverflowavailable) { + if ($this->modoverflowinstalled) { $this->assertEquals(6, count($content)); } else { $this->assertEquals(5, count($content)); @@ -138,14 +138,14 @@ private function helper_course_set_up(): void { $this->testdata->fdiscussion = (object)$forumgenerator->create_discussion($record); if ($DB->get_record('modules', ['name' => 'moodleoverflow', 'visible' => 1])) { - $this->moodleoverflowavailable = true; - $moodleoverflowgenerator = $datagenerator->get_plugin_generator('mod_moodleoverflow'); + $this->modoverflowinstalled = true; + $modoverflowgenerator = $datagenerator->get_plugin_generator('mod_moodleoverflow'); $this->testdata->moodleoverflow = $datagenerator->create_module('moodleoverflow', ['course' => $this->testdata->course->id]); - $this->testdata->mdiscussion = $moodleoverflowgenerator->post_to_forum($this->testdata->moodleoverflow, + $this->testdata->mdiscussion = $modoverflowgenerator->post_to_forum($this->testdata->moodleoverflow, $this->testdata->teacher); } else { - $this->moodleoverflowavailable = false; + $this->modoverflowinstalled = false; } // Create an assign module with activity completion. @@ -162,7 +162,7 @@ private function helper_course_set_up(): void { */ private function create_assignment($allowsubmissionsdate, $duedate, $gradingduedate): object { // Create an activity completion for the assignment if wanted. - $featurecompletionmanual = [ + $options = [ 'completion' => COMPLETION_TRACKING_MANUAL, 'completionexpected' => $duedate, ]; @@ -174,6 +174,18 @@ private function create_assignment($allowsubmissionsdate, $duedate, $gradingdued 'allowsubmissionsfromdate' => $allowsubmissionsdate, 'gradingduedate' => $gradingduedate, ]; - return $this->getDataGenerator()->create_module('assign', $assignrecord, $featurecompletionmanual); + return $this->getDataGenerator()->create_module('assign', $assignrecord, $options); + } + + /** + * Little helper function to reduce cyclomatic complexity. Checks if two params equal values. + * @param mixed $param1 + * @param mixed $equal1 + * @param mixed $param2 + * @param mixed $equal2 + * @return bool + */ + private function check_two_params($param1, $equal1, $param2, $equal2) { + return $param1 == $equal1 && $param2 == $equal2; } } diff --git a/tests/postevents_test.php b/tests/postevents_test.php index dee68a8..6076c78 100644 --- a/tests/postevents_test.php +++ b/tests/postevents_test.php @@ -52,7 +52,7 @@ final class postevents_test extends \advanced_testcase { /** @var bool If the moodleoverflow module is available. * This Plugin can support moodleoverflow, but it is not necessary to have it installed. */ - private $moodleoverflowavailable; + private $modoverflowinstalled; // Construct functions. public function setUp(): void { @@ -73,6 +73,8 @@ public function tearDown(): void { * @return void */ public function test_sortorder(): void { + $this->create_moodleoverflow_posts(); + $this->create_forum_posts(); // Get the current post events from the teacher. $posts = $this->get_postevents_from_user($this->testdata->teacher); @@ -80,8 +82,8 @@ public function test_sortorder(): void { $timestamp = 9999999999; $result = true; foreach ($posts as $post) { - if ($timestamp >= $post->postcreated) { - $timestamp = $post->postcreated; + if ($timestamp >= $post->timestart) { + $timestamp = $post->timestart; } else { $result = false; } @@ -96,9 +98,11 @@ public function test_sortorder(): void { */ public function test_module_moodleoverflow(): void { global $DB; - if (!$this->moodleoverflowavailable) { + if (!$this->modoverflowinstalled) { return; } + $this->create_forum_posts(); + $this->create_moodleoverflow_posts(); // Test case: disable moodleoverflow. $DB->delete_records('modules', ['name' => 'moodleoverflow']); @@ -124,6 +128,8 @@ public function test_module_moodleoverflow(): void { */ public function test_module_forum(): void { global $DB; + $this->create_forum_posts(); + $this->create_moodleoverflow_posts(); // Test case: disable forum. $DB->delete_records('modules', ['name' => 'forum']); @@ -139,7 +145,7 @@ public function test_module_forum(): void { } // Two Checks: The number of posts (there are 4 moodleoverflow posts) and the result. - if ($this->moodleoverflowavailable) { + if ($this->modoverflowinstalled) { $this->assertEquals(4, count($posts)); } else { $this->assertEquals(0, count($posts)); @@ -153,6 +159,8 @@ public function test_module_forum(): void { */ public function test_course_deleted(): void { global $DB; + $this->create_forum_posts(); + $this->create_moodleoverflow_posts(); // Delete the course from the database. $DB->delete_records('course', ['id' => $this->testdata->course1->id]); @@ -174,6 +182,9 @@ public function test_course_deleted(): void { * @return void */ public function test_coursefilter(): void { + $this->create_forum_posts(); + $this->create_moodleoverflow_posts(); + // Test case 1: Post for the teacher. $posts = $this->get_postevents_from_user($this->testdata->teacher);; @@ -181,7 +192,7 @@ public function test_coursefilter(): void { $result = $this->check_postcourses($posts, enrol_get_all_users_courses($this->testdata->teacher->id, true)); // Two Checks: Is the number of posts correct (no post is missing) and is every post in the course of the teacher. - if ($this->moodleoverflowavailable) { + if ($this->modoverflowinstalled) { $this->assertEquals(6, count($posts)); } else { $this->assertEquals(2, count($posts)); @@ -193,7 +204,7 @@ public function test_coursefilter(): void { $result = $this->check_postcourses($posts, enrol_get_all_users_courses($this->testdata->student1->id, true)); - if ($this->moodleoverflowavailable) { + if ($this->modoverflowinstalled) { $this->assertEquals(3, count($posts)); } else { $this->assertEquals(1, count($posts)); @@ -205,7 +216,7 @@ public function test_coursefilter(): void { $result = $this->check_postcourses($posts, enrol_get_all_users_courses($this->testdata->student2->id, true)); - if ($this->moodleoverflowavailable) { + if ($this->modoverflowinstalled) { $this->assertEquals(3, count($posts)); } else { $this->assertEquals(1, count($posts)); @@ -218,9 +229,8 @@ public function test_coursefilter(): void { * @return void */ public function test_anonymous(): void { - if (!$this->moodleoverflowavailable) { - return; - } + // Only create moodleoverflowposts. + $this->create_moodleoverflow_posts(); // Set the first moodleoverflow to partially anonymous and the second to fully anonymous. $this->make_anonymous($this->testdata->moodleoverflow1, 1); @@ -239,13 +249,13 @@ public function test_anonymous(): void { // Iterate through all posts and save the posts from teacher and student. foreach ($posts as $post) { - if ($post->modulename == 'moodleoverflow' && $post->instanceid == $this->testdata->moodleoverflow1->id) { + if ($post->instanceid == $this->testdata->moodleoverflow1->id) { if ($post->postuserid == $this->testdata->teacher->id) { $firstteacherpost = $post; } else if ($post->postuserid == $this->testdata->student1->id) { $firststudentpost = $post; } - } else if ($post->modulename == 'moodleoverflow' && $post->instanceid == $this->testdata->moodleoverflow2->id) { + } else if ($post->instanceid == $this->testdata->moodleoverflow2->id) { if ($post->postuserid == $this->testdata->teacher->id) { $secondteacherpost = $post; } else if ($post->postuserid == $this->testdata->student2->id) { @@ -269,6 +279,8 @@ public function test_anonymous(): void { */ public function test_hidden(): void { global $DB; + $this->create_forum_posts(); + $this->create_moodleoverflow_posts(); // Test case 1: Hide the first forum. $cmid = get_coursemodule_from_instance('forum', $this->testdata->forum1->id)->id; $DB->update_record('course_modules', ['id' => $cmid, 'visible' => 0]); @@ -286,7 +298,7 @@ public function test_hidden(): void { $this->assertEquals(true, $result); // Test case 2: Hide the first moodleoverflow. - if ($this->moodleoverflowavailable) { + if ($this->modoverflowinstalled) { $cmid = get_coursemodule_from_instance('moodleoverflow', $this->testdata->moodleoverflow1->id)->id; $DB->update_record('course_modules', ['id' => $cmid, 'visible' => 0]); @@ -318,10 +330,7 @@ private function helper_course_set_up(): void { $datagenerator = $this->getDataGenerator(); // Create two new courses. $this->testdata->course1 = $datagenerator->create_course(); - $course1location = ['course' => $this->testdata->course1->id]; - $this->testdata->course2 = $datagenerator->create_course(); - $course2location = ['course' => $this->testdata->course2->id]; // Create a teacher and enroll the teacher in both courses. $this->testdata->teacher = $datagenerator->create_user(); @@ -334,41 +343,62 @@ private function helper_course_set_up(): void { $this->testdata->student2 = $datagenerator->create_user(); $this->getDataGenerator()->enrol_user($this->testdata->student2->id, $this->testdata->course2->id, 'student'); - // Create a moodleoverflow with 2 post in each course. (But only if it is available. + // Check if moodleoverflow is available. if ($DB->get_record('modules', ['name' => 'moodleoverflow', 'visible' => 1])) { - $this->moodleoverflowavailable = true; - $moodleoverflowgenerator = $datagenerator->get_plugin_generator('mod_moodleoverflow'); + $this->modoverflowinstalled = true; + } else { + $this->modoverflowinstalled = false; + } + } + + /** + * Helper function that creates a moodleoverflow and posts + * @return void + */ + private function create_moodleoverflow_posts() { + // Create a moodleoverflow with 2 post in each course. + if ($this->modoverflowinstalled) { + $course1location = ['course' => $this->testdata->course1->id]; + $course2location = ['course' => $this->testdata->course2->id]; + $datagenerator = $this->getDataGenerator(); + $modoverflowgenerator = $datagenerator->get_plugin_generator('mod_moodleoverflow'); $this->testdata->moodleoverflow1 = $datagenerator->create_module('moodleoverflow', $course1location); - $this->testdata->mdiscussion1 = $moodleoverflowgenerator->post_to_forum($this->testdata->moodleoverflow1, - $this->testdata->teacher); - $this->testdata->answer1 = $moodleoverflowgenerator->reply_to_post($this->testdata->mdiscussion1[1], - $this->testdata->student1, true); + $this->testdata->mdiscussion1 = $modoverflowgenerator->post_to_forum($this->testdata->moodleoverflow1, + $this->testdata->teacher); + $this->testdata->answer1 = $modoverflowgenerator->reply_to_post($this->testdata->mdiscussion1[1], + $this->testdata->student1, true); $this->testdata->moodleoverflow2 = $datagenerator->create_module('moodleoverflow', $course2location); - $this->testdata->mdiscussion2 = $moodleoverflowgenerator->post_to_forum($this->testdata->moodleoverflow2, - $this->testdata->teacher); - $this->testdata->answer2 = $moodleoverflowgenerator->reply_to_post($this->testdata->mdiscussion2[1], + $this->testdata->mdiscussion2 = $modoverflowgenerator->post_to_forum($this->testdata->moodleoverflow2, + $this->testdata->teacher); + $this->testdata->answer2 = $modoverflowgenerator->reply_to_post($this->testdata->mdiscussion2[1], $this->testdata->student2, true); - } else { - $this->moodleoverflowavailable = false; } + } + /** + * Helper function that creates a forum and posts. + * @return void + */ + private function create_forum_posts() { + $datagenerator = $this->getDataGenerator(); + $course1location = ['course' => $this->testdata->course1->id]; + $course2location = ['course' => $this->testdata->course2->id]; // Create a forum with 2 post in each course. $forumgenerator = $datagenerator->get_plugin_generator('mod_forum'); $this->testdata->forum1 = $datagenerator->create_module('forum', $course1location); $record = (array)$this->testdata->forum1 + ['forum' => $this->testdata->forum1->id, - 'userid' => $this->testdata->teacher->id, ]; + 'userid' => $this->testdata->teacher->id, ]; $this->testdata->fdiscussion1 = (object)$forumgenerator->create_discussion($record); $this->testdata->forum2 = $datagenerator->create_module('forum', $course2location); $record = (array)$this->testdata->forum2 + ['forum' => $this->testdata->forum2->id, - 'userid' => $this->testdata->teacher->id, ]; + 'userid' => $this->testdata->teacher->id, ]; $this->testdata->fdiscussion2 = (object)$forumgenerator->create_discussion($record); } - /** * Makes the existing moodleoverflow anonymous. * There are 2 types of anonymous moodleoverflows: @@ -391,6 +421,7 @@ private function make_anonymous($moodleoverflow, $anonymoussetting): void { /** * Helper function to get the post events from a certain user. * @param object $user The user for whom the events should be collected (townsquareevents.php uses $USER). + * * @return array */ private function get_postevents_from_user($user): array { From 2f3ac6a69eb50490d3b320fe16dd014d24f3b697 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Sun, 23 Jun 2024 23:08:11 +0200 Subject: [PATCH 112/123] php mess cleaning --- db/upgrade.php | 2 +- locallib.php | 87 +++++++++++++++++++++----------------------------- 2 files changed, 37 insertions(+), 52 deletions(-) diff --git a/db/upgrade.php b/db/upgrade.php index 619432e..58eb841 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -30,7 +30,7 @@ * @return bool */ function xmldb_block_townsquare_upgrade($oldversion) { - global $DB, $CFG; + global $DB; $dbman = $DB->get_manager(); diff --git a/locallib.php b/locallib.php index 29048bf..ac0d385 100644 --- a/locallib.php +++ b/locallib.php @@ -50,65 +50,50 @@ function townsquare_get_colorsetting($lettertype): string { * @param object $event The event, that is being checked. * @return void */ -function townsquare_check_coreevent($event): void { +function townsquare_check_coreevent(&$event): void { + // Activity completion event have a own message handling (as it always has the same structure). + if ($event->eventtype == 'expectcompletionon') { + return; + } + $time = date('H:i', $event->timestart); + + // Most modules only have open and closing events. + $opencloseevents = ['choice' , 'data', 'feedback', 'lesson', 'quiz', 'scorm']; + if (in_array($event->modulename, $opencloseevents)) { + $event->name = townsquare_get_open_close_message($event, $time); + } + + // Other core plugins have extra/other event types. if ($event->modulename == 'assign') { - if ($event->eventtype == 'due') { - $event->name = get_string('assignduemessage', 'block_townsquare', ['time' => $time]); - } else if ($event->eventtype == 'gradingdue') { - $event->name = get_string('assigngradingduemessage', 'block_townsquare', ['time' => $time]); - } + // Event type is either 'due' or 'gradingdue'. + $identifier = 'assign' . $event->eventtype . 'message'; + $event->name = get_string($identifier, 'block_townsquare', ['time' => $time]); } else if ($event->modulename == 'chat' && $event->eventtype == 'chattime') { $event->name = get_string('chattimemessage', 'block_townsquare', ['time' => $time]); - } else if ($event->modulename == 'choice') { - if ($event->eventtype == 'open') { - $event->name = get_string('choiceopenmessage', 'block_townsquare', ['time' => $time]); - } else if ($event->eventtype == 'close') { - $event->name = get_string('choiceclosemessage', 'block_townsquare', ['time' => $time]); - } - } else if ($event->modulename == 'data') { - if ($event->eventtype == 'open') { - $event->name = get_string('dataopenmessage', 'block_townsquare'); - } else if ($event->eventtype == 'close') { - $event->name = get_string('dataclosemessage', 'block_townsquare', ['time' => $time]); - } - } else if ($event->modulename == 'feedback') { - if ($event->eventtype == 'open') { - $event->name = get_string('feedbackopenmessage', 'block_townsquare', ['time' => $time]); - } else if ($event->eventtype == 'close') { - $event->name = get_string('feedbackclosemessage', 'block_townsquare', ['time' => $time]); - } } else if ($event->modulename == 'forum') { if ($event->eventtype == 'due') { $event->name = get_string('forumduemessage', 'block_townsquare', ['time' => $time]); } - } else if ($event->modulename == 'lesson') { - if ($event->eventtype == 'open') { - $event->name = get_string('lessonopenmessage', 'block_townsquare', ['time' => $time]); - } else if ($event->eventtype == 'close') { - $event->name = get_string('lessonclosemessage', 'block_townsquare', ['time' => $time]); - } - } else if ($event->modulename == 'quiz') { - if ($event->eventtype == 'open') { - $event->name = get_string('quizopenmessage', 'block_townsquare', ['time' => $time]); - } else if ($event->eventtype == 'close') { - $event->name = get_string('quizclosemessage', 'block_townsquare', ['time' => $time]); - } - } else if ($event->modulename == 'scorm') { - if ($event->eventtype == 'open') { - $event->name = get_string('scormopenmessage', 'block_townsquare'); - } else if ($event->eventtype == 'close') { - $event->name = get_string('scormclosemessage', 'block_townsquare'); - } } else if ($event->modulename == 'workshop') { - if ($event->eventtype == 'opensubmission') { - $event->name = get_string('workshopopensubmission', 'block_townsquare', ['time' => $time]); - } else if ($event->eventtype == 'closesubmission') { - $event->name = get_string('workshopclosesubmission', 'block_townsquare', ['time' => $time]); - } else if ($event->eventtype == 'openassessment') { - $event->name = get_string('workshopopenassessment', 'block_townsquare', ['time' => $time]); - } else if ($event->eventtype == 'closeassessment') { - $event->name = get_string('workshopcloseassessment', 'block_townsquare', ['time' => $time]); - } + // Event type is either 'opensubmission', 'closesubmission', 'openassessment' or 'closeassessment'. + $identifier = 'workshop' . $event->eventtype; + $event->name = get_string($identifier, 'block_townsquare', ['time' => $time]); + } +} + +/** + * Helper function for the check function. Helps to reduce repetitive checks + * @param $event + * @param $pluginname + * @param $time + * @return string + */ +function townsquare_get_open_close_message($event, $time) { + if ($event->eventtype == 'open') { + return get_string($event->modulename . 'openmessage', 'blok_townsquare', ['time' => $time]); + } else if ($event->eventtype == 'close') { + return get_string($event->modulename . 'closemessage', 'block_townsquare', ['time' => $time]); } + return ''; } From 23c4bb4bf48927bba57517dae7c333a15cb26574 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 27 Jun 2024 09:26:29 +0200 Subject: [PATCH 113/123] php mess cleaning completed --- tests/postevents_test.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/postevents_test.php b/tests/postevents_test.php index 6076c78..326aaaa 100644 --- a/tests/postevents_test.php +++ b/tests/postevents_test.php @@ -252,13 +252,13 @@ public function test_anonymous(): void { if ($post->instanceid == $this->testdata->moodleoverflow1->id) { if ($post->postuserid == $this->testdata->teacher->id) { $firstteacherpost = $post; - } else if ($post->postuserid == $this->testdata->student1->id) { + } else { $firststudentpost = $post; } } else if ($post->instanceid == $this->testdata->moodleoverflow2->id) { if ($post->postuserid == $this->testdata->teacher->id) { $secondteacherpost = $post; - } else if ($post->postuserid == $this->testdata->student2->id) { + } else { $secondstudentpost = $post; } } From bf4f8e46d38657c979f74641afab4f65d030152c Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 4 Jul 2024 09:56:35 +0200 Subject: [PATCH 114/123] behat problems solved --- lang/en/block_townsquare.php | 4 ++-- locallib.php | 2 +- tests/postevents_test.php | 9 +++++++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/lang/en/block_townsquare.php b/lang/en/block_townsquare.php index 8dac662..80f3a70 100644 --- a/lang/en/block_townsquare.php +++ b/lang/en/block_townsquare.php @@ -62,10 +62,10 @@ $string['nextweeknotifications'] = 'Next week'; $string['orientationmarkercolor'] = 'Color for the orientation marker'; $string['orientationmarkercontent'] = 'Hi {$a->username}, welcome to townsquare! Today is the {$a->date}'; -$string['pluginname'] = 'Townsquare'; +$string['pluginname'] = 'Town Square'; $string['pluginname:addinstance'] = 'Add the Town Square block'; $string['pluginname:myaddinstance'] = 'Add the Town Square block to the dashboard'; -$string['plugintitle'] = 'Town Square Block'; +$string['plugintitle'] = 'Town Square block'; $string['postlettercolor'] = 'Color for post letters'; $string['postletternotification'] = 'New {$a->modulename} post!'; diff --git a/locallib.php b/locallib.php index ac0d385..458ae32 100644 --- a/locallib.php +++ b/locallib.php @@ -91,7 +91,7 @@ function townsquare_check_coreevent(&$event): void { */ function townsquare_get_open_close_message($event, $time) { if ($event->eventtype == 'open') { - return get_string($event->modulename . 'openmessage', 'blok_townsquare', ['time' => $time]); + return get_string($event->modulename . 'openmessage', 'block_townsquare', ['time' => $time]); } else if ($event->eventtype == 'close') { return get_string($event->modulename . 'closemessage', 'block_townsquare', ['time' => $time]); } diff --git a/tests/postevents_test.php b/tests/postevents_test.php index 326aaaa..3356477 100644 --- a/tests/postevents_test.php +++ b/tests/postevents_test.php @@ -230,7 +230,9 @@ public function test_coursefilter(): void { */ public function test_anonymous(): void { // Only create moodleoverflowposts. - $this->create_moodleoverflow_posts(); + if (!$this->create_moodleoverflow_posts()) { + return; + } // Set the first moodleoverflow to partially anonymous and the second to fully anonymous. $this->make_anonymous($this->testdata->moodleoverflow1, 1); @@ -353,7 +355,7 @@ private function helper_course_set_up(): void { /** * Helper function that creates a moodleoverflow and posts - * @return void + * @return bool */ private function create_moodleoverflow_posts() { // Create a moodleoverflow with 2 post in each course. @@ -374,6 +376,9 @@ private function create_moodleoverflow_posts() { $this->testdata->teacher); $this->testdata->answer2 = $modoverflowgenerator->reply_to_post($this->testdata->mdiscussion2[1], $this->testdata->student2, true); + return true; + } else { + return false; } } From ebfeec282917b4a86cae6c342bc77aa4c40cd57a Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 4 Jul 2024 10:11:20 +0200 Subject: [PATCH 115/123] add subplugins to workflow --- .github/workflows/moodle-ci.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index 4e61abb..911b4e9 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -62,6 +62,15 @@ jobs: - name: Install local plugin run: moodle-plugin-ci add-plugin learnweb/moodle-local_townsquaresupport + - name: Install townsquareexpansion plugin + run: moodle-plugin-ci add-plugin learnweb/moodle-townsquareexpansion_moodleoverflow + + - name: Install townsquareexpansion plugin + run: moodle-plugin-ci add-plugin learnweb/moodle-townsquareexpansion_ratingallocate + + - name: Install townsquareexpansion plugin + run: moodle-plugin-ci add-plugin learnweb/moodle-townsquareexpansion_zoom + - name: Install moodle-plugin-ci run: | moodle-plugin-ci install --plugin ./plugin --db-host=127.0.0.1 --no-init From 2166e9b9f6b1fffc687d0d9f0411177ca84307c0 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 4 Jul 2024 10:12:05 +0200 Subject: [PATCH 116/123] code cleaning --- block_townsquare.php | 6 +-- classes/contentcontroller.php | 6 +-- classes/letter/activitycompletion_letter.php | 2 +- classes/letter/post_letter.php | 2 +- classes/orientation_marker.php | 2 +- classes/output/renderer.php | 2 +- lang/en/block_townsquare.php | 46 +++++++++----------- tests/contentcontroller_test.php | 6 +-- tests/coreevents_test.php | 8 ++-- tests/postevents_test.php | 8 ++-- 10 files changed, 42 insertions(+), 46 deletions(-) diff --git a/block_townsquare.php b/block_townsquare.php index cb03108..22cc853 100644 --- a/block_townsquare.php +++ b/block_townsquare.php @@ -31,7 +31,7 @@ class block_townsquare extends block_base { * * @return void */ - public function init():void { + public function init(): void { $this->title = get_string('pluginname', 'block_townsquare'); } @@ -40,7 +40,7 @@ public function init():void { * * @return object|null The block HTML. */ - public function get_content():object { + public function get_content(): object { global $OUTPUT; if ($this->content !== null) { @@ -62,7 +62,7 @@ public function get_content():object { * * @return array of the pages where the block can be added. */ - public function applicable_formats():array { + public function applicable_formats(): array { return [ 'admin' => false, 'site-index' => false, diff --git a/classes/contentcontroller.php b/classes/contentcontroller.php index 45e24c8..8607274 100644 --- a/classes/contentcontroller.php +++ b/classes/contentcontroller.php @@ -57,7 +57,7 @@ public function __construct() { * Builds the content from events. * @return array */ - public function build_content():array { + public function build_content(): array { $this->events = $this->townsquareevents->get_all_events_sorted(); $orientationmarkerset = false; @@ -95,7 +95,7 @@ public function build_content():array { * Getter for the content * @return array */ - public function get_content():array { + public function get_content(): array { return $this->content; } @@ -103,7 +103,7 @@ public function get_content():array { * Getter for the events * @return array */ - public function get_events():array { + public function get_events(): array { return $this->events; } } diff --git a/classes/letter/activitycompletion_letter.php b/classes/letter/activitycompletion_letter.php index 52819cc..3e05f60 100644 --- a/classes/letter/activitycompletion_letter.php +++ b/classes/letter/activitycompletion_letter.php @@ -61,7 +61,7 @@ public function __construct($contentid, $calendarevent) { * Export function for the mustache template. * return array */ - public function export_letter():array { + public function export_letter(): array { // Change the timestamp to a date. $date = date('d.m.Y', $this->created); diff --git a/classes/letter/post_letter.php b/classes/letter/post_letter.php index fd368f7..ed021ec 100644 --- a/classes/letter/post_letter.php +++ b/classes/letter/post_letter.php @@ -108,7 +108,7 @@ public function __construct($contentid, $postevent) { * Export Function for the mustache template. * @return array */ - public function export_letter():array { + public function export_letter(): array { return [ 'contentid' => $this->contentid, 'lettertype' => $this->lettertype, diff --git a/classes/orientation_marker.php b/classes/orientation_marker.php index 62ab900..9ca6024 100644 --- a/classes/orientation_marker.php +++ b/classes/orientation_marker.php @@ -64,7 +64,7 @@ public function __construct($contentid, $time) { * Export function for the mustache template. * @return array */ - public function export_data():array { + public function export_data(): array { // Change the timestamp to a date. $date = date('d.m.Y', $this->today); diff --git a/classes/output/renderer.php b/classes/output/renderer.php index f158b5e..a9db5c0 100644 --- a/classes/output/renderer.php +++ b/classes/output/renderer.php @@ -40,7 +40,7 @@ class renderer extends plugin_renderer_base { * @param array $data Data to render the townsquare templates * @return string HTML string */ - public function render_main($data):string { + public function render_main($data): string { return $this->render_from_template('block_townsquare/blockcontent', $data); } } diff --git a/lang/en/block_townsquare.php b/lang/en/block_townsquare.php index 57341d8..fffb6bd 100644 --- a/lang/en/block_townsquare.php +++ b/lang/en/block_townsquare.php @@ -25,39 +25,35 @@ defined('MOODLE_INTERNAL') || die(); -// Core strings for the installation. -$string['pluginname'] = 'Townsquare block'; -$string['pluginname'] = 'Town Square'; -$string['pluginname:addinstance'] = 'Add the Town Square block'; -$string['pluginname:myaddinstance'] = 'Add the Town Square block to the dashboard'; - -// Mustache templates strings. -$string['completionletterorigin'] = '{$a->modulename} should be completed until today'; -$string['basicletterorigin'] = 'A notification from {$a->instancename}:'; -$string['postletterorigin'] = '{$a->authorname} posted in {$a->instancename} -> {$a->discussionname}:'; -$string['orientationmarkercontent'] = 'Hi {$a->username}, welcome to townsquare! Today is the {$a->date}'; - -// Letter strings. -$string['invalidmodulename'] = 'Module name is unknown or not supported'; - -// Event strings. $string['assignduemessage'] = 'Assignment is due until {$a->time}'; $string['assigngradingduemessage'] = 'Assignment is due to be graded until {$a->time}'; +$string['basicletterorigin'] = 'A notification from {$a->instancename}:'; $string['chattimemessage'] = 'The next chat time is today at {$a->time}'; -$string['choiceopenmessage'] = 'Voting is possible from {$a->time} onwards'; $string['choiceclosemessage'] = 'Please vote until {$a->time}. Afterwards the choice is closed'; -$string['dataopenmessage'] = 'The database opens today'; +$string['choiceopenmessage'] = 'Voting is possible from {$a->time} onwards'; +$string['completionletterorigin'] = '{$a->modulename} should be completed until today'; $string['dataclosemessage'] = 'Please submit your entries until {$a->time}. The database closes afterwards'; -$string['feedbackopenmessage'] = 'Writing feedback is possible from {$a->time} onwards'; +$string['dataopenmessage'] = 'The database opens today'; $string['feedbackclosemessage'] = 'Writing feedback is possible until {$a->time}'; +$string['feedbackopenmessage'] = 'Writing feedback is possible from {$a->time} onwards'; $string['forumduemessage'] = 'The forum is due until {$a->time}'; -$string['lessonopenmessage'] = 'The lesson opens today at {$a->time}'; +$string['invalidmodulename'] = 'Module name is unknown or not supported'; $string['lessonclosemessage'] = 'The lesson ends today at {$a->time}'; -$string['quizopenmessage'] = 'The Quiz is open from {$a->time} onwards'; +$string['lessonopenmessage'] = 'The lesson opens today at {$a->time}'; +$string['orientationmarkercontent'] = 'Hi {$a->username}, welcome to townsquare! Today is the {$a->date}'; +$string['pluginname'] = 'Town Square'; +$string['pluginname:addinstance'] = 'Add the Town Square block'; +$string['pluginname:myaddinstance'] = 'Add the Town Square block to the dashboard'; +$string['plugintitle'] = 'Townsquare block'; + +$string['postletterorigin'] = '{$a->authorname} posted in {$a->instancename} -> {$a->discussionname}:'; + + + + $string['quizclosemessage'] = 'The Quiz closes today at {$a->time}'; -$string['quizopenmessage'] = 'Scorm Activity opens today'; -$string['quizclosemessage'] = 'Scorm Activity closes today'; -$string['workshopopensubmission'] = 'Submissions for the workshop are possible from {$a->time} onwards'; +$string['quizopenmessage'] = 'The Quiz is open from {$a->time} onwards'; +$string['workshopcloseassessment'] = 'Assessments for the workshop are due until {$a->time}'; $string['workshopclosesubmission'] = 'Please submit your work until {$a->time}. The workshop closes afterwards'; $string['workshopopenassessment'] = 'The assessment phase starts today at {$a->time}'; -$string['workshopcloseassessment'] = 'Assessments for the workshop are due until {$a->time}'; +$string['workshopopensubmission'] = 'Submissions for the workshop are possible from {$a->time} onwards'; diff --git a/tests/contentcontroller_test.php b/tests/contentcontroller_test.php index 53b88ac..102c243 100644 --- a/tests/contentcontroller_test.php +++ b/tests/contentcontroller_test.php @@ -33,7 +33,7 @@ * * @covers \block_townsquare\contentcontroller */ -class contentcontroller_test extends \advanced_testcase { +final class contentcontroller_test extends \advanced_testcase { // Attributes. @@ -121,7 +121,7 @@ public function test_letters(): void { * Helper function that sets up the testdata. * @return void */ - private function helper_course_set_up():void { + private function helper_course_set_up(): void { global $DB; // Declare generators. $datagenerator = $this->getDataGenerator(); @@ -160,7 +160,7 @@ private function helper_course_set_up():void { * @param int $gradingduedate timestamp * @return object */ - private function create_assignment($allowsubmissionsdate, $duedate, $gradingduedate):object { + private function create_assignment($allowsubmissionsdate, $duedate, $gradingduedate): object { // Create an activity completion for the assignment if wanted. $featurecompletionmanual = [ 'completion' => COMPLETION_TRACKING_MANUAL, diff --git a/tests/coreevents_test.php b/tests/coreevents_test.php index 05213a1..fd03d3e 100644 --- a/tests/coreevents_test.php +++ b/tests/coreevents_test.php @@ -41,7 +41,7 @@ * * @covers \block_townsquare\townsquareevents::get_coreevents() */ -class coreevents_test extends \advanced_testcase { +final class coreevents_test extends \advanced_testcase { // Attributes. @@ -271,7 +271,7 @@ private function helper_course_set_up(): void { * @param bool $activitycompletion * @return object */ - private function create_assignment($courseid, $allowsubmissionsdate, $duedate, $gradingduedate, $activitycompletion):object { + private function create_assignment($courseid, $allowsubmissionsdate, $duedate, $gradingduedate, $activitycompletion): object { // Create an activity completion for the assignment if wanted. $featurecompletionmanual = []; if ($activitycompletion) { @@ -295,7 +295,7 @@ private function create_assignment($courseid, $allowsubmissionsdate, $duedate, $ * @param object $user The user for whom the events should be collected (townsquareevents.php uses $USER). * @return array */ - private function get_calendarevents_from_user($user):array { + private function get_calendarevents_from_user($user): array { $this->setUser($user); $townsquareevents = new townsquareevents(); return $townsquareevents->get_coreevents(); @@ -308,7 +308,7 @@ private function get_calendarevents_from_user($user):array { * @param array $enrolledcourses * @return bool */ - private function check_eventcourses($events, $enrolledcourses):bool { + private function check_eventcourses($events, $enrolledcourses): bool { foreach ($events as $event) { $eventcourseid = $event->courseid; diff --git a/tests/postevents_test.php b/tests/postevents_test.php index 4a93b22..a08e337 100644 --- a/tests/postevents_test.php +++ b/tests/postevents_test.php @@ -35,7 +35,7 @@ * * @covers \block_townsquare\townsquareevents::get_postevents() */ -class postevents_test extends \advanced_testcase { +final class postevents_test extends \advanced_testcase { // Attributes. @@ -378,7 +378,7 @@ private function helper_course_set_up(): void { * @param object $moodleoverflow The moodleoverflow that should be made anonymous. * @param int $anonymoussetting The type of anonymous moodleoverflow. */ - private function make_anonymous($moodleoverflow, $anonymoussetting):void { + private function make_anonymous($moodleoverflow, $anonymoussetting): void { global $DB; if ($anonymoussetting == 1 || $anonymoussetting == 2) { $moodleoverflow->anonymous = $anonymoussetting; @@ -393,7 +393,7 @@ private function make_anonymous($moodleoverflow, $anonymoussetting):void { * @param object $user The user for whom the events should be collected (townsquareevents.php uses $USER). * @return array */ - private function get_postevents_from_user($user):array { + private function get_postevents_from_user($user): array { $this->setUser($user); $townsquareevents = new townsquareevents(); return $townsquareevents->get_postevents(); @@ -405,7 +405,7 @@ private function get_postevents_from_user($user):array { * @param array $enrolledcourses * @return bool */ - private function check_postcourses($posts, $enrolledcourses):bool { + private function check_postcourses($posts, $enrolledcourses): bool { foreach ($posts as $post) { $postcourseid = $post->courseid; From f531d025567f3a5abf64efc603ce0426139bcb99 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 11 Jul 2024 09:38:44 +0200 Subject: [PATCH 117/123] resolve merge conflict in ci file --- .github/workflows/moodle-ci.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index 690aa6d..5c7cba6 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -125,13 +125,8 @@ jobs: strategy: fail-fast: false matrix: -<<<<<<< HEAD - php: ['8.0', '8.1', '8.2', '8.3'] - moodle-branch: ['MOODLE_401_STABLE', 'MOODLE_402_STABLE', 'MOODLE_403_STABLE', 'MOODLE_404_STABLE'] -======= php: [ '8.0', '8.1', '8.2', '8.3' ] moodle-branch: [ 'MOODLE_401_STABLE', 'MOODLE_402_STABLE', 'MOODLE_403_STABLE', 'MOODLE_404_STABLE' ] ->>>>>>> bf4f8e46d38657c979f74641afab4f65d030152c database: [ 'mariadb', 'pgsql' ] exclude: - php: '8.0' From a85ccdbd9ef0f4d171af8aea051667222b73a60c Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 11 Jul 2024 09:45:07 +0200 Subject: [PATCH 118/123] codecleaning --- tests/postevents_test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/postevents_test.php b/tests/postevents_test.php index 10ca2a4..84a0abd 100644 --- a/tests/postevents_test.php +++ b/tests/postevents_test.php @@ -62,7 +62,7 @@ public function setUp(): void { } public function tearDown(): void { - // $this->testdata = null; + $this->testdata = null; } // Tests. From ba9f631f02d96b4f641fb500a10061dfe5e30ef9 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 11 Jul 2024 13:44:39 +0200 Subject: [PATCH 119/123] added functionality for private forum reply --- amd/src/usersettings_save.js | 1 - classes/letter/post_letter.php | 24 ++++++++++++++ classes/townsquareevents.php | 33 +++++++++++++++++-- lang/en/block_townsquare.php | 2 ++ lib.php | 2 ++ templates/postletter.mustache | 10 ++++++ .../block_townsquare_coursefilter.feature | 1 - .../block_townsquare_savepreferences.feature | 2 +- 8 files changed, 70 insertions(+), 5 deletions(-) diff --git a/amd/src/usersettings_save.js b/amd/src/usersettings_save.js index 8a7b359..bab24e9 100644 --- a/amd/src/usersettings_save.js +++ b/amd/src/usersettings_save.js @@ -88,7 +88,6 @@ function saveusersettings(userid, timefilterpast, timefilterfuture, basicletter, }, }; result = Ajax.call([data]); - console.log('HI I AM HERE'); // Make the clicked button green by adding a class. savebutton.classList.add('bg-success', 'text-white', 'ts_button_transition'); diff --git a/classes/letter/post_letter.php b/classes/letter/post_letter.php index f786ff7..c1abea3 100644 --- a/classes/letter/post_letter.php +++ b/classes/letter/post_letter.php @@ -105,6 +105,7 @@ public function __construct($contentid, $postevent) { $this->posturls->linktoauthor = $postevent->linktoauthor; $this->add_anonymousattribute($postevent); + $this->add_privatereplyattribute($postevent); $this->retrieve_profilepicture(); } @@ -125,6 +126,8 @@ public function export_letter(): array { 'instancename' => $this->instancename, 'discussionsubject' => $this->post->discussionsubject, 'anonymous' => $this->post->anonymous, + 'privatereplyfrom' => $this->post->privatereplyfrom, + 'privatereplyto' => $this->post->privatereplyto, 'authorname' => $this->author->name, 'authorpicture' => $this->author->picture, 'postid' => $this->post->id, @@ -174,6 +177,27 @@ private function add_anonymousattribute($postevent): void { } } + /** + * Method to add a boolean that indicates if the post is a private reply. + * @param $postevent + * @return void + */ + private function add_privatereplyattribute($postevent): void { + if ($postevent->modulename == 'forum') { + // Check if the private author is the same private recipient. + if ($postevent->privatereplyto && $postevent->privatereplyfrom) { + $this->post->privatereplyto = false; + $this->post->privatereplyfrom = true; + } else { + $this->post->privatereplyto = $postevent->privatereplyto; + $this->post->privatereplyfrom = $postevent->privatereplyfrom; + } + } else { + $this->post->privatereplyto = false; + $this->post->privatereplyfrom = false; + } + } + /** * Function to format the post message before exporting it to the mustache template. * @param $message diff --git a/classes/townsquareevents.php b/classes/townsquareevents.php index 037e132..149baca 100644 --- a/classes/townsquareevents.php +++ b/classes/townsquareevents.php @@ -139,7 +139,7 @@ public function get_postevents(): array { $forumposts = $this->get_forumposts_from_db($this->courses, $this->timestart); foreach ($forumposts as $post) { - if (townsquare_filter_availability($post)) { + if (townsquare_filter_availability($post) || $this->filter_forum_privatepost($post)) { unset($forumposts[$post->row_num]); } @@ -190,7 +190,8 @@ private function get_forumposts_from_db($courses, $timestart): array { posts.userid AS postuserid, posts.created AS timestart, posts.message AS postmessage, - posts.messageformat AS postmessageformat + posts.messageformat AS postmessageformat, + posts.privatereplyto AS postprivatereplyto FROM {forum_posts} posts JOIN {forum_discussions} discuss ON discuss.id = posts.discussion JOIN {forum} module ON module.id = discuss.forum @@ -280,4 +281,32 @@ private function filter_assignment($coreevent): bool { return false; } + /** + * Filter that checks if a forum posts is a private reply that only the author and the receiver can see. + * If the post is a private reply but is not filtered out, the functions adds to attributes to the post object. + * Applies to forum posts. + * @param object $forumpost The post that is checked. + * @return bool true if the posts needs to be filtered out, false if not. + */ + private function filter_forum_privatepost(&$forumpost): bool { + global $USER; + // Check if the postuserid or the userid from the private attribute is the current user. + $isprivatemessage = $forumpost->postprivatereplyto != 0; + $isauthor = $forumpost->postuserid == $USER->id; + $isreceiver = $forumpost->postprivatereplyto == $USER->id; + + // Filter out the post if the current user is not the author or the receiver. + if ($isprivatemessage && !$isauthor && !$isreceiver) { + return true; + } + + // Add attributes to know if the private reply is from or to the current user. + $forumpost->privatereplyfrom = $isprivatemessage && $isauthor; + $forumpost->privatereplyto = $isprivatemessage && $isreceiver; + + // Add attributes as the posts is further processed. + + return false; + } + } diff --git a/lang/en/block_townsquare.php b/lang/en/block_townsquare.php index f5bd5a6..e2cda7a 100644 --- a/lang/en/block_townsquare.php +++ b/lang/en/block_townsquare.php @@ -77,6 +77,8 @@ $string['privacy:metadata:block_townsquare_preferences:timefilterfuture'] = 'How far into the future the user wants to see notifications'; $string['privacy:metadata:block_townsquare_preferences:timefilterpast'] = 'How far back the user wants to see notifications'; $string['privacy:metadata:block_townsquare_preferences:userid'] = 'The user id'; +$string['privatereplyfrom'] = 'This is a private reply from you, that only you and the post author can see.'; +$string['privatereplyto'] = 'This is a private reply to your post, that only you and the reply author can see'; $string['quizclosemessage'] = 'The Quiz closes today at {$a->time}'; $string['quizopenmessage'] = 'The Quiz is open from {$a->time} onwards'; $string['savebutton'] = 'Save settings'; diff --git a/lib.php b/lib.php index be7bf2c..e68ae57 100644 --- a/lib.php +++ b/lib.php @@ -111,6 +111,8 @@ function townsquare_merge(array $left, array $right): array { /** * Filter that checks if the event needs to be filtered out for the current user because it is not available. + * @param object $event event that is checked + * @return bool true if the event needs to filtered out, false if not. */ function townsquare_filter_availability($event): bool { // If there is no restriction defined, the event is available. diff --git a/templates/postletter.mustache b/templates/postletter.mustache index 6f2d7e8..293a80c 100644 --- a/templates/postletter.mustache +++ b/templates/postletter.mustache @@ -99,6 +99,16 @@ data-action="block_townsquare/showmore_button"> {{#str}} showmore, block_townsquare {{/str}} + + {{#privatereplyto}} +


+ {{#str}} privatereplyto, block_townsquare {{/str}} + {{/privatereplyto}} + {{#privatereplyfrom}} +
+ {{#str}} privatereplyfrom, block_townsquare {{/str}} + {{/privatereplyfrom}} + diff --git a/tests/behat/block_townsquare_coursefilter.feature b/tests/behat/block_townsquare_coursefilter.feature index 61d728f..8fc4693 100644 --- a/tests/behat/block_townsquare_coursefilter.feature +++ b/tests/behat/block_townsquare_coursefilter.feature @@ -42,7 +42,6 @@ Feature: The townsquare block allows users to see notifications from different c When I click on "Course 3" "checkbox" Then I should not see "Test assign 3" in the "Town Square" "block" - Scenario: Test the time filter Given the following "activities" exist: | activity | course | idnumber | name | intro | timeopen | duedate | diff --git a/tests/behat/block_townsquare_savepreferences.feature b/tests/behat/block_townsquare_savepreferences.feature index b3c8c9c..da22af4 100644 --- a/tests/behat/block_townsquare_savepreferences.feature +++ b/tests/behat/block_townsquare_savepreferences.feature @@ -32,4 +32,4 @@ Feature: In the townsquare block user can save their settings in a database. When I click on "Save settings" "text" in the "Town Square" "block" Then I should not see "Test assign 2" in the "Town Square" "block" And I reload the page - Then I should not see "Test assign 2" in the "Town Square" "block" \ No newline at end of file + Then I should not see "Test assign 2" in the "Town Square" "block" From 05396ce90360b1b98ede2f3421007867333b42a1 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Fri, 12 Jul 2024 10:22:55 +0200 Subject: [PATCH 120/123] unit test for forum privatereply --- tests/postevents_test.php | 56 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/tests/postevents_test.php b/tests/postevents_test.php index 84a0abd..857e5bf 100644 --- a/tests/postevents_test.php +++ b/tests/postevents_test.php @@ -153,6 +153,44 @@ public function test_module_forum(): void { $this->assertEquals(true, $result); } + /** + * Test, if the post events are processed correctly if the forum post has a private reply. + * @return void + */ + public function test_forum_privatereply(): void { + $this->create_forum_posts(); + + // Test case: there is a private reply from the second student in the forum. + $this->create_forum_privatereply(); + + // The teacher (and second student) can see the post. The first student should not see the post. + // Get the post events from the first student. + $posts = $this->get_postevents_from_user($this->testdata->teacher); + + // There should be 3 forum posts and the private reply should among them. + $this->assertEquals(3, count($posts)); + $result = false; + foreach ($posts as $post) { + if ($post->postmessage == 'This is a private reply.') { + $result = true; + } + } + $this->assertEquals(true, $result); + + // Get the post events from the first student. + $posts = $this->get_postevents_from_user($this->testdata->student1); + + // There should be 1 forum posts and the private reply should not be among them. + $this->assertEquals(1, count($posts)); + $result = true; + foreach ($posts as $post) { + if ($post->postmessage == 'This is a private reply.') { + $result = false; + } + } + $this->assertEquals(true, $result); + } + /** * Test, if the post events are processed correctly if the course disappears. * @return void @@ -404,6 +442,24 @@ private function create_forum_posts() { $this->testdata->fdiscussion2 = (object)$forumgenerator->create_discussion($record); } + /** + * Helper function that adds a private reply post to the first forum. + * A private reply is a message, that only the discussion author and reply author can see + * @return void + */ + private function create_forum_privatereply() { + $forumgenerator = $this->getDataGenerator()->get_plugin_generator('mod_forum'); + + // Enrol the second student in the first course. + $this->getDataGenerator()->enrol_user($this->testdata->student2->id, $this->testdata->course1->id, 'student'); + + // The second student replies privately to the forum post of the teacher. + $record = (array)$this->testdata->forum1 + ['discussion' => $this->testdata->fdiscussion1->id, + 'userid' => $this->testdata->student2->id, 'parent' => $this->testdata->fdiscussion1->firstpost, + 'message' => 'This is a private reply.', 'privatereplyto' => $this->testdata->teacher->id, ]; + $this->testdata->fprivatereply = (object)$forumgenerator->create_post($record); + } + /** * Makes the existing moodleoverflow anonymous. * There are 2 types of anonymous moodleoverflows: From 6c644b7a95aee29a2237fdc22458f56436dc044d Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 18 Jul 2024 15:58:16 +0200 Subject: [PATCH 121/123] improve post content formatting --- amd/src/coursefilter.js | 2 +- amd/src/postletter.js | 6 +++--- classes/letter/post_letter.php | 18 ++++++++++-------- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/amd/src/coursefilter.js b/amd/src/coursefilter.js index 04baad9..2162ebe 100644 --- a/amd/src/coursefilter.js +++ b/amd/src/coursefilter.js @@ -33,7 +33,7 @@ const checkboxes = document.querySelectorAll('.ts_course_checkbox'); export function init() { checkboxes.forEach(function(checkbox) { checkbox.addEventListener('change', function() { - // Get the courseid associated with the checkbox + // Get the courseid associated with the checkbox. const courseid = checkbox.id; // Get all letters that are "activated". diff --git a/amd/src/postletter.js b/amd/src/postletter.js index 29fbd18..08e50f9 100644 --- a/amd/src/postletter.js +++ b/amd/src/postletter.js @@ -132,15 +132,15 @@ async function changeButtonString(index, toshowmore) { * @param {object} element */ async function replaceParagraghTags(element) { - // Identify and store the first

and

tags + // Identify and store the first

and

tags. let message = element.innerHTML; const firstPTag = message.indexOf('

'); const lastPTag = message.lastIndexOf('

'); - // Remove   and surrounding

tags excluding the first occurrence + // Remove   and surrounding

tags excluding the first occurrence. message = message.replace(/

 <\/p>/g, '').replace(/ /g, ''); - // Replace

tags with
excluding the first occurrence + // Replace

tags with
excluding the first occurrence. message = message.substring(0, firstPTag + 3) + message.substring(firstPTag + 3, lastPTag).replace(/

/g, '
').replace(/<\/p>/g, '') + message.substring(lastPTag); diff --git a/classes/letter/post_letter.php b/classes/letter/post_letter.php index c1abea3..16a545f 100644 --- a/classes/letter/post_letter.php +++ b/classes/letter/post_letter.php @@ -94,8 +94,7 @@ public function __construct($contentid, $postevent) { $this->post->instanceid = $postevent->instanceid; $this->post->discussionid = $postevent->postdiscussion; $this->post->id = $postevent->postid; - $this->post->message = $this->format_post($postevent->postmessage, $postevent->postmessageformat, - $postevent->coursemoduleid); + $this->post->message = $this->format_post($postevent); $this->post->discussionsubject = $postevent->discussionsubject; $this->post->parentid = $postevent->postparentid; $this->post->anonymous = $postevent->anonymous ?? false; @@ -200,14 +199,17 @@ private function add_privatereplyattribute($postevent): void { /** * Function to format the post message before exporting it to the mustache template. - * @param $message - * @param $messageformat - * @param $cmid + * @param $postevent * @return string */ - private function format_post($message, $messageformat, $cmid) { - $options = (array) portfolio_format_text_options() + ['context' => \context_module::instance($cmid)]; - return format_text($message, $messageformat, $options); + private function format_post($postevent) { + $context = \context_module::instance($postevent->coursemoduleid); + $message = file_rewrite_pluginfile_urls($postevent->postmessage, 'pluginfile.php', $context->id, + 'mod_'. $postevent->modulename, 'post', $postevent->postid, ['includetoken' => true]); + $options = new stdClass(); + $options->para = true; + $options->context = $context; + return format_text($message, $postevent->postmessageformat, $options); } } From 0a4ff3af077eb488d412b18bf44d88ab1fa072ad Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 18 Jul 2024 15:58:34 +0200 Subject: [PATCH 122/123] decrease event searching time --- lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib.php b/lib.php index e68ae57..3f3189e 100644 --- a/lib.php +++ b/lib.php @@ -49,7 +49,7 @@ function townsquare_get_courses(): array { * @return int */ function townsquare_get_timestart(): int { - return time() - 15768000; + return time() - 604800; } /** From eee934da441dbb12540459073f40fbebaf19f169 Mon Sep 17 00:00:00 2001 From: TamaroWalter Date: Thu, 1 Aug 2024 08:29:03 -0700 Subject: [PATCH 123/123] timestart time change --- classes/townsquareevents.php | 4 ++-- lib.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/classes/townsquareevents.php b/classes/townsquareevents.php index 149baca..ecc277e 100644 --- a/classes/townsquareevents.php +++ b/classes/townsquareevents.php @@ -69,7 +69,7 @@ public function __construct() { } /** - * Retrieves calendar and post events, merges and sorts them. + * Retrieves calendar, post events, merges and sorts them. * @return array */ public function get_all_events_sorted(): array { @@ -226,7 +226,7 @@ private function get_events_from_db($timestart, $timeend, $courses): array { return []; } - // Due to compatability reasons, only events from supported modules are shown. + // Due to compatability reasons, only events from core modules are shown. $modules = ['assign', 'book', 'chat', 'choice', 'data', 'feedback', 'file', 'folder', 'forum', 'glossary', 'h5pactivity', 'imscp', 'label', 'lesson', 'lti', 'page', 'quiz', 'resource', 'scorm', 'survey', 'url', 'wiki', 'workshop', ]; diff --git a/lib.php b/lib.php index 3f3189e..e68ae57 100644 --- a/lib.php +++ b/lib.php @@ -49,7 +49,7 @@ function townsquare_get_courses(): array { * @return int */ function townsquare_get_timestart(): int { - return time() - 604800; + return time() - 15768000; } /**