diff --git a/filter/filter_form.php b/classes/filter_form.php similarity index 84% rename from filter/filter_form.php rename to classes/filter_form.php index f67f698d..ff7b5984 100644 --- a/filter/filter_form.php +++ b/classes/filter_form.php @@ -24,11 +24,12 @@ defined('MOODLE_INTERNAL') || die(); require_once("$CFG->libdir/formslib.php"); +use core_form\dynamic_form; /** * */ -abstract class mod_datalynx_filter_base_form extends moodleform { +abstract class mod_datalynx_filter_base_form extends dynamic_form { protected $_filter = null; protected $_customfilter = null; @@ -39,16 +40,59 @@ abstract class mod_datalynx_filter_base_form extends moodleform { */ protected $_df = null; - /* - * - */ - public function __construct($df, $filter, $action = null, $customdata = null, $method = 'post', $target = '', - $attributes = null, $editable = true, $customfilter = false) { - $this->_filter = $filter; - $this->_customfilter = $customfilter; - $this->_df = $df; + public function get_context_for_dynamic_submission(): context { + //return context_module::instance($this->_df->cm->id); + return \context_system::instance(); + } - parent::__construct($action, $customdata, $method, $target, $attributes, $editable); + public function check_access_for_dynamic_submission(): void { + return; + //return has_capability('mod/datalynx:edit', $this->get_context_for_dynamic_submission()); + require_capability('moodle/site:config', \context_system::instance()); + } + + public function set_data_for_dynamic_submission(): void { + $datalynx_id = $this->_ajaxformdata["d"]; + $filter_id = $this->_ajaxformdata["fid"]; + + if ($datalynx_id == null || $filter_id == null) { + return; + } + + $this->_df = \mod_datalynx\datalynx::get_datalynx_by_instance($datalynx_id); + $fm = $this->_df->get_filter_manager(); + $this->_filter = $fm->get_filter_from_id($filter_id); + + // Update filter parameters based on the current form data (in order to dynamically render new form fields for filter details): + if ($this->_ajaxformdata["update"] && confirm_sesskey()) { + $procesedfilters = $fm->process_filters_for_ajax_refresh('update', $filter_id, $this, true); + $this->_filter = $procesedfilters[0]; + } + } + + public function process_dynamic_submission() { + + $datalynx_id = $this->_ajaxformdata["d"]; + $filter_id = $this->_ajaxformdata["fid"]; + + if ($datalynx_id == null || $filter_id == null) { + return; + } + + $this->_df = \mod_datalynx\datalynx::get_datalynx_by_instance($datalynx_id); + $fm = $this->_df->get_filter_manager(); + $this->_filter = $fm->get_filter_from_id($filter_id); + + if ($this->_ajaxformdata["update"] && confirm_sesskey()) { // Add/update a new filter. + $procesedfilters = $fm->process_filters_for_ajax_submission('update', $filter_id, $this, true); + $this->_filter = $procesedfilters[0]; + } + + return $this->_df->notifications; + } + + public function get_page_url_for_dynamic_submission(): moodle_url { + return new moodle_url('/mod/datalynx/view.php', array('id' => $this->_df->id)); } /* @@ -214,9 +258,6 @@ public function custom_search_definition($customsearch, $fields, $fieldoptions, $mform->disabledIf("searchoption$count", 'searchandor' . ($count - 1), 'eq', 0); } } - - $mform->registerNoSubmitButton('addsearchsettings'); - $mform->addElement('submit', 'addsearchsettings', get_string('reload')); } /* @@ -259,15 +300,18 @@ public function html() { class mod_datalynx_filter_form extends mod_datalynx_filter_base_form { + public function definition() {} + /* * */ - public function definition() { + public function definition_after_data() { $df = $this->_df; $filter = $this->_filter; $name = empty($filter->name) ? get_string('filternew', 'datalynx') : $filter->name; $description = empty($filter->description) ? '' : $filter->description; $visible = !isset($filter->visible) ? 1 : $filter->visible; + $fields = $df->get_fields(); $fieldoptions = array(0 => get_string('choose')) + $df->get_fields(array('entry'), true); @@ -334,10 +378,25 @@ public function definition() { $this->custom_search_definition($filter->customsearch, $fields, $fieldoptions, true); + // Hidden fields to track the Datalynx instance and the filter id. + if ($df !== null) { + $mform->addElement('hidden', 'd', $df->id()); + } + if ($filter !== null) { + $mform->addElement('hidden', 'fid', $filter->id); + } + $mform->addElement('hidden', 'refreshonly', '0'); + $mform->addElement('hidden', 'update', '1'); + // Buttons. $this->add_action_buttons(true); } + public function get_ajax_form_data() { + // Convert to stdClass: + return json_decode(json_encode($this->_ajaxformdata)); + } + /** * @param array $data * @param array $files @@ -346,16 +405,26 @@ public function definition() { */ public function validation($data, $files) { $errors = parent::validation($data, $files); + if (array_key_exists('refreshonly', $data)) { + if ($data['refreshonly'] == '0') { - $df = $this->_df; - $filter = $this->_filter; + $df = $this->_df; + $filter = $this->_filter; - // Validate unique name. - if (empty($data['name']) || $df->name_exists('filters', $data['name'], $filter->id)) { - $errors['name'] = get_string('invalidname', 'datalynx', - get_string('filter', 'datalynx')); + // Validate unique name. + if (empty($data['name']) || $df->name_exists('filters', $data['name'], $filter->id)) { + $errors['name'] = get_string('invalidname', 'datalynx', + get_string('filter', 'datalynx')); + } + } else { + // If we do not return any error after a submission, the form will + // be regarded as submitted and will render empty. + // We need to return a dummy error to prevent this. + // This also prevents process_dynamic_submission from being executed in this case, + // as the form gets no validated flag: + $errors['dummy_error_for_refreshing'] = 'dummy_error_for_refreshing'; + } } - return $errors; } } diff --git a/datalynx.js b/datalynx.js index 7048717c..1bb82245 100644 --- a/datalynx.js +++ b/datalynx.js @@ -474,3 +474,53 @@ function bulk_action(elem, url, action, defaultval) { M.mod_datalynx.field_gradeitem_form_init = function () { Y.one('#mform1').one('select[name="param1"]').set('value', Y.one('#mform1').one('input[type="hidden"][name="param1"]').get('value')); }; + +M.mod_datalynx.filter_form_init = function () { + require(['core_form/dynamicform', 'core/toast'], function (DynamicForm, Toast) { + const container = document.querySelector('#formcontainer'); + const dynamicForm = new DynamicForm(container, 'mod_datalynx_filter_form'); + + dynamicForm.addEventListener(dynamicForm.events.FORM_SUBMITTED, e => { + e.detail.good.forEach(successMessage => { + Toast.add(successMessage, { + type: 'success', + }); + }); + e.detail.bad.forEach(errorMessage => { + Toast.add(errorMessage, { + type: 'danger', + }); + }); + let searchParams = new URLSearchParams(window.location.search) + dynamicForm.load({ + d: searchParams.get("d"), + fid: searchParams.get("fid") + }); + }) + + container.addEventListener('change', e => { + if (e.target.matches('.custom-select') && (e.target.name.startsWith('searchfield') || e.target.name.startsWith('sortfield'))) { + e.preventDefault(); + document.getElementsByName("refreshonly")[0].value = "1"; + dynamicForm.submitFormAjax(); + } + }); + + container.addEventListener('click', e => { + if (e.target.matches('input[type="submit"]')) { + e.preventDefault(); + document.getElementsByName("refreshonly")[0].value = "0"; + dynamicForm.submitFormAjax(); + } + }); + + $(function() { + let searchParams = new URLSearchParams(window.location.search) + dynamicForm.load({ + d: searchParams.get("d"), + fid: searchParams.get("fid") + }); + }); + + }); +}; diff --git a/field/field_class.php b/field/field_class.php index f3af1cc3..02a14215 100644 --- a/field/field_class.php +++ b/field/field_class.php @@ -1027,14 +1027,6 @@ public function parse_search($formdata, $i) { public static function is_customfilterfield() { return true; } - - public function get_argument_count(string $operator) { - if ($operator === "") { // "Empty" operator - return 0; - } else { - return 1; - } - } } /** @@ -1267,14 +1259,6 @@ public function get_supported_search_operators() { 'ALL_OF' => get_string('allof', 'datalynx'), 'EXACTLY' => get_string('exactly', 'datalynx'), '' => get_string('empty', 'datalynx')); } - - public function get_argument_count(string $operator) { - if ($operator === "") { // "Empty" operator - return 0; - } else { - return 1; - } - } } /** diff --git a/field/select/field_class.php b/field/select/field_class.php index 2c617917..5c7a3b3a 100644 --- a/field/select/field_class.php +++ b/field/select/field_class.php @@ -59,12 +59,4 @@ public function get_search_value($value) { return ''; } } - - public function get_argument_count(string $operator) { - if ($operator === "") { // "Empty" operator - return 0; - } else { - return 1; - } - } } diff --git a/filter/filter_class.php b/filter/filter_class.php index d996867d..c3b17cb8 100644 --- a/filter/filter_class.php +++ b/filter/filter_class.php @@ -706,6 +706,127 @@ public function get_filters($exclude = null, $menu = false, $forceget = false) { } } + public function process_filters_for_ajax_refresh($action, $fids, $mform) { + global $DB, $OUTPUT; + + $df = $this->_df; + + $filters = array(); + // TODO may need new roles. + if (has_capability('mod/datalynx:managetemplates', $df->context)) { + // Don't need record from database for filter form submission. + if ($fids) { // Some filters are specified for action. + $filters = $DB->get_records_select('datalynx_filters', "id IN ($fids)"); + } else { + if ($action == 'update') { + $filters[] = $this->get_filter_from_id(self::BLANK_FILTER); + } + } + } + $processedfids = array(); + $processedfilters = array(); + $strnotify = ''; + + // TODO update should be roled. + if (empty($filters)) { + $df->notifications['bad'][] = get_string("filternoneforaction", 'datalynx'); + return false; + } else { + // Go ahead and perform the requested action. + if ($action == 'update') { + $filter = reset($filters); + + if (!$mform->is_cancelled()) { + // Regenerate form and filter to obtain custom search data. + $formdata = $mform->get_ajax_form_data(); + $filter = $this->get_filter_from_form($filter, $formdata); + $processedfids[] = $filter->id; + $processedfilters[] = $filter; + } + } + return $processedfilters; + } + } + + public function process_filters_for_ajax_submission($action, $fids, $mform) { + global $DB, $OUTPUT; + + $df = $this->_df; + + $filters = array(); + // TODO may need new roles. + if (has_capability('mod/datalynx:managetemplates', $df->context)) { + // Don't need record from database for filter form submission. + if ($fids) { // Some filters are specified for action. + $filters = $DB->get_records_select('datalynx_filters', "id IN ($fids)"); + } else { + if ($action == 'update') { + $filters[] = $this->get_filter_from_id(self::BLANK_FILTER); + } + } + } + $processedfids = array(); + $processedfilters = array(); + $strnotify = ''; + + // TODO update should be roled. + if (empty($filters)) { + $df->notifications['bad'][] = get_string("filternoneforaction", 'datalynx'); + return false; + } else { + // Go ahead and perform the requested action. + if ($action == 'update') { + $filter = reset($filters); + + if (!$mform->is_cancelled()) { + // Regenerate form and filter to obtain custom search data. + $formdata = $mform->get_ajax_form_data(); + $filter = $this->get_filter_from_form($filter, $formdata); + + if ($formdata = $mform->get_data()) { + + // Get clean filter from formdata. + $filter = $this->get_filter_from_form($filter, $formdata, true); + + if ($filter->id) { + $DB->update_record('datalynx_filters', $filter); + $processedfids[] = $filter->id; + $processedfilters[] = $filter; // VP Added this line. + $strnotify = 'filtersupdated'; + + $other = array('dataid' => $this->_df->id()); + $event = \mod_datalynx\event\field_updated::create( + array('context' => $this->_df->context, + 'objectid' => $filter->id, 'other' => $other)); + $event->trigger(); + } else { + $filter->id = $DB->insert_record('datalynx_filters', $filter, true); + $processedfids[] = $filter->id; + $processedfilters[] = $filter; // VP Added this line. + $strnotify = 'filtersadded'; + + $other = array('dataid' => $this->_df->id()); + $event = \mod_datalynx\event\field_created::create( + array('context' => $this->_df->context, + 'objectid' => $filter->id, 'other' => $other + )); + $event->trigger(); + } + // Update cached filters. + $this->_filters[$filter->id] = $filter; + } + } + } + + if (!empty($strnotify)) { + $filtersprocessed = $processedfids ? count($processedfids) : 'No'; + $df->notifications['good'][] = get_string($strnotify, 'datalynx', + $filtersprocessed); + } + return $processedfilters; + } + } + /** */ public function process_filters($action, $fids, $confirmed = false) { @@ -751,61 +872,6 @@ public function process_filters($action, $fids, $confirmed = false) { } else { // Go ahead and perform the requested action. switch ($action) { - case 'update': // Add new or update existing. - $filter = reset($filters); - $mform = $this->get_filter_form($filter); - - if ($mform->is_cancelled()) { - break; - } - - // Regenerate form and filter to obtain custom search data. - $formdata = $mform->get_submitted_data(); - $filter = $this->get_filter_from_form($filter, $formdata); - $filterform = $this->get_filter_form($filter); - - // Return to form (on reload button press). - if ($filterform->no_submit_button_pressed()) { - $this->display_filter_form($filterform, $filter); - - // Process validated. - } else { - if ($formdata = $filterform->get_data()) { - // Get clean filter from formdata. - $filter = $this->get_filter_from_form($filter, $formdata, true); - - if ($filter->id) { - $DB->update_record('datalynx_filters', $filter); - $processedfids[] = $filter->id; - $strnotify = 'filtersupdated'; - - $other = array('dataid' => $this->_df->id()); - $event = \mod_datalynx\event\field_updated::create( - array('context' => $this->_df->context, - 'objectid' => $filter->id, 'other' => $other)); - $event->trigger(); - } else { - $filter->id = $DB->insert_record('datalynx_filters', $filter, true); - $processedfids[] = $filter->id; - $strnotify = 'filtersadded'; - - $other = array('dataid' => $this->_df->id()); - $event = \mod_datalynx\event\field_created::create( - array('context' => $this->_df->context, - 'objectid' => $filter->id, 'other' => $other - )); - $event->trigger(); - } - // Update cached filters. - $this->_filters[$filter->id] = $filter; - } else { - // Form validation failed so return to form. - $this->display_filter_form($filterform, $filter); - } - } - - break; - case 'duplicate': if (!empty($filters)) { foreach ($filters as $filter) { @@ -890,17 +956,15 @@ public function process_filters($action, $fids, $confirmed = false) { */ public function get_filter_form($filter) { global $CFG; - - require_once("$CFG->dirroot/mod/datalynx/filter/filter_form.php"); $formurl = new moodle_url('/mod/datalynx/filter/index.php', array('d' => $this->_df->id(), 'fid' => $filter->id, 'update' => 1)); - $mform = new mod_datalynx_filter_form($this->_df, $filter, $formurl); + $mform = new mod_datalynx_filter_form($formurl); return $mform; } /** */ - public function display_filter_form($mform, $filter, $urlparams = null) { + public function display_filter_form($filter, $urlparams = null) { $streditinga = $filter->id ? get_string('filteredit', 'datalynx', $filter->name) : get_string( 'filternew', 'datalynx'); $heading = html_writer::tag('h2', format_string($streditinga), @@ -908,7 +972,7 @@ public function display_filter_form($mform, $filter, $urlparams = null) { $this->_df->print_header(array('tab' => 'filters', 'urlparams' => $urlparams)); echo $heading; - $mform->display(); + echo html_writer::div('', '', ['id' => 'formcontainer', 'data-region' => 'form']); $this->_df->print_footer(); exit(); diff --git a/filter/index.php b/filter/index.php index 1ec8bb69..35247b19 100644 --- a/filter/index.php +++ b/filter/index.php @@ -51,6 +51,13 @@ $df = new mod_datalynx\datalynx($urlparams->d, $urlparams->id); require_capability('mod/datalynx:managetemplates', $df->context); +$module = array( + 'name' => 'mod_datalynx', + 'fullpath' => '/mod/datalynx/datalynx.js', + 'requires' => array('moodle-core-notification-dialogue') +); +$PAGE->requires->js_init_call('M.mod_datalynx.filter_form_init', array(), true, $module); + $df->set_page('filter/index', array('modjs' => true, 'urlparams' => $urlparams)); require_login($df->data->course, false, $df->cm); @@ -62,24 +69,20 @@ $fm = $df->get_filter_manager(); // DATA PROCESSING. -if ($urlparams->update && confirm_sesskey()) { // Add/update a new filter. - $fm->process_filters('update', $urlparams->fid, true); +if ($urlparams->duplicate && confirm_sesskey()) { // Duplicate any requested filters. + $fm->process_filters('duplicate', $urlparams->duplicate, $urlparams->confirmed); } else { - if ($urlparams->duplicate && confirm_sesskey()) { // Duplicate any requested filters. - $fm->process_filters('duplicate', $urlparams->duplicate, $urlparams->confirmed); + if ($urlparams->delete && confirm_sesskey()) { // Delete any requested filters. + $fm->process_filters('delete', $urlparams->delete, $urlparams->confirmed); } else { - if ($urlparams->delete && confirm_sesskey()) { // Delete any requested filters. - $fm->process_filters('delete', $urlparams->delete, $urlparams->confirmed); + if ($urlparams->visible && confirm_sesskey()) { // Set filter's visibility. + $fm->process_filters('visible', $urlparams->visible, true); // Confirmed by default. } else { - if ($urlparams->visible && confirm_sesskey()) { // Set filter's visibility. - $fm->process_filters('visible', $urlparams->visible, true); // Confirmed by default. - } else { - if ($urlparams->default && confirm_sesskey()) { // Set filter to default. - if ($urlparams->default == -1) { - $df->set_default_filter(); // Reset. - } else { - $df->set_default_filter($urlparams->default); - } + if ($urlparams->default && confirm_sesskey()) { // Set filter to default. + if ($urlparams->default == -1) { + $df->set_default_filter(); // Reset. + } else { + $df->set_default_filter($urlparams->default); } } } @@ -89,15 +92,13 @@ // Edit a new filter. if ($urlparams->new && confirm_sesskey()) { $filter = $fm->get_filter_from_id($fm::BLANK_FILTER); - $filterform = $fm->get_filter_form($filter); - $fm->display_filter_form($filterform, $filter, $urlparams); + $fm->display_filter_form($filter, $urlparams); // Or edit existing filter. } else { if ($urlparams->fedit && confirm_sesskey()) { $filter = $fm->get_filter_from_id($urlparams->fedit); - $filterform = $fm->get_filter_form($filter); - $fm->display_filter_form($filterform, $filter, $urlparams); + $fm->display_filter_form($filter, $urlparams); // Or display the filters list. } else {