From df2e030761e869791c01e4bdb5cbe14c822e68ba Mon Sep 17 00:00:00 2001 From: Diego Pino Navarro Date: Wed, 21 Jun 2023 17:19:28 -0400 Subject: [PATCH 01/13] JS for everything. Solves the "search" on Enter key. So much code for such a simple thing @alliomeria . Stuff is: Browsers will always pick the first submit found, so rendering order leads. If i put search first then other stuff like adding a + button by each one will still fail (future needs). Also Drupal will make all buttons input type=submit (if we want to pass stuff via form state) so i have to alter the form, intercept the Enter and trigger the only and only one (staring at the moon) button i care for (i care of other things, like plants and people) --- .../format_strawberryfield_views.libraries.yml | 7 +++++++ .../format_strawberryfield_views.module | 8 +++++++- .../js/sbf-advanced-search-default-submit.js | 18 ++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 modules/format_strawberryfield_views/js/sbf-advanced-search-default-submit.js diff --git a/modules/format_strawberryfield_views/format_strawberryfield_views.libraries.yml b/modules/format_strawberryfield_views/format_strawberryfield_views.libraries.yml index 1bae7086..546e0c31 100644 --- a/modules/format_strawberryfield_views/format_strawberryfield_views.libraries.yml +++ b/modules/format_strawberryfield_views/format_strawberryfield_views.libraries.yml @@ -42,3 +42,10 @@ view-ajax-interactions: - core/views - core/views.ajax - format_strawberryfield/iiif_formatstrawberryfield_utils + +advanced-search-default-submit: + js: + js/sbf-advanced-search-default-submit.js: {minified: false} + dependencies: + - core/drupal + - core/jquery diff --git a/modules/format_strawberryfield_views/format_strawberryfield_views.module b/modules/format_strawberryfield_views/format_strawberryfield_views.module index 4dd63405..3dcddf7a 100644 --- a/modules/format_strawberryfield_views/format_strawberryfield_views.module +++ b/modules/format_strawberryfield_views/format_strawberryfield_views.module @@ -141,8 +141,14 @@ function format_strawberryfield_views_block_view_views_exposed_filter_block_sbf_ */ function format_strawberryfield_views_form_alter(&$form, FormStateInterface $form_state, $form_id) { if ($form_id == 'views_exposed_form') { + if (isset($form['actions']['submit'])) { + $form['actions']['#attached']['library'][] = 'format_strawberryfield_views/advanced-search-default-submit'; + $form['actions']['submit']['#attributes']['autofocus'] = ''; + $form['actions']['submit']['#attributes']['tabindex'] = 1; + $form['actions']['submit']['#attributes']['data-default-submit'] = ''; + } foreach ($form as $key => $value) { - if (is_array($value) && isset ($value['#group']) && isset($value['#type']) && $value['#group'] == 'actions' && $value['#type'] == 'submit') { + if (is_array($value) && isset ($value['#group']) && isset($value['#type']) && $value['#group'] == 'actions' && ($value['#type'] == 'submit' || $value['#type'] == 'button')) { $form['actions'][$key] = $value; unset($form[$key]); } diff --git a/modules/format_strawberryfield_views/js/sbf-advanced-search-default-submit.js b/modules/format_strawberryfield_views/js/sbf-advanced-search-default-submit.js new file mode 100644 index 00000000..f15a56fc --- /dev/null +++ b/modules/format_strawberryfield_views/js/sbf-advanced-search-default-submit.js @@ -0,0 +1,18 @@ +(function ($, Drupal) { + Drupal.behaviors.sbfAdvancedSearchViewsForm = { + attach(context) { + var formInterception = function(defaultSubmitInput, ev) { + if (ev.keyCode == 13) { + ev.preventDefault(); + ev.stopPropagation(); + defaultSubmitInput.click(); + } + }; + for (const defaultSubmitInput of document.querySelectorAll('.views-exposed-form [data-default-submit]')) { + for (const formInput of defaultSubmitInput.form.querySelectorAll('input')) { + formInput.addEventListener('keypress', formInterception.bind(null, defaultSubmitInput)); + } + } + } + } +})(jQuery, Drupal); From 17ba815d32e30679adc5b17be04bf27d5c002d32 Mon Sep 17 00:00:00 2001 From: Diego Pino Navarro Date: Wed, 21 Jun 2023 18:53:16 -0400 Subject: [PATCH 02/13] Try with alternate #name. In the past this has cleared the form state But the past is past? --- .../Plugin/views/filter/AdvancedSearchApiFulltext.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php b/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php index 73452d4c..b4c9c9a9 100644 --- a/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php +++ b/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php @@ -690,23 +690,29 @@ public function buildExposedForm(&$form, FormStateInterface $form_state) { if (empty($this->view->live_preview)) { $form[$this->options['id'].'_addone'] = [ - '#type' => 'submit', + '#type' => 'button', '#op' => $this->options['id'] . '_addone', '#value' => $this->t('@label', [ '@label' => $this->options['exposed']['advanced_search_fields_add_one_label'] ?? 'add one' ]), + '#name' => 'addone', '#access' => $enable_more, + '#attributes' => ['data-disable-refocus' => "true", 'tabindex' => 2], + '#executes_submit_callback' => TRUE, '#weight' => '-100', '#group' => 'actions', ]; /* Note: #group does not work for buttons but we use this to bring them into 'actions' key in a form alter */ $form[$this->options['id'].'_delone'] = [ - '#type' => 'submit', + '#type' => 'button', + '#name' => 'delone', '#op' => $this->options['id'] . '_delone', '#value' => $this->t('@label', [ '@label' => $this->options['exposed']['advanced_search_fields_remove_one_label'] ?? 'remove one' ]), + '#executes_submit_callback' => TRUE, + '#attributes' => ['data-disable-refocus' => "true", 'tabindex' => 3], '#access' => $enable_less, '#weight' => '-101', '#group' => 'actions', From 09903324361783605cb2a3a92a247bba49a22568 Mon Sep 17 00:00:00 2001 From: Diego Pino Navarro Date: Wed, 21 Jun 2023 20:18:19 -0400 Subject: [PATCH 03/13] Ok, some advancements on detecting the silly buttons Still a debug statement here. Now the hard part. How to submit without querying? Or said differently, (bc i can) how to submit without querying new fields, if previously the user pressed "search", add one/delete one should not "delete the results" neither... i hate this --- .../format_strawberryfield_views.module | 3 +++ .../views/filter/AdvancedSearchApiFulltext.php | 17 +++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/modules/format_strawberryfield_views/format_strawberryfield_views.module b/modules/format_strawberryfield_views/format_strawberryfield_views.module index 3dcddf7a..5e342996 100644 --- a/modules/format_strawberryfield_views/format_strawberryfield_views.module +++ b/modules/format_strawberryfield_views/format_strawberryfield_views.module @@ -146,6 +146,9 @@ function format_strawberryfield_views_form_alter(&$form, FormStateInterface $for $form['actions']['submit']['#attributes']['autofocus'] = ''; $form['actions']['submit']['#attributes']['tabindex'] = 1; $form['actions']['submit']['#attributes']['data-default-submit'] = ''; + // Needed when multiple buttons are on the same form, by default the name is empty + // making \Drupal\Core\Form\FormBuilder::buttonWasClicked fail! + $form['actions']['submit']['#name'] = 'op'; } foreach ($form as $key => $value) { if (is_array($value) && isset ($value['#group']) && isset($value['#type']) && $value['#group'] == 'actions' && ($value['#type'] == 'submit' || $value['#type'] == 'button')) { diff --git a/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php b/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php index b4c9c9a9..0ba4c00e 100644 --- a/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php +++ b/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php @@ -544,10 +544,18 @@ public function query() { } public function submitExposed(&$form, FormStateInterface $form_state) { + /* if ($form_state->getTriggeringElement()['#op'] ?? NULL == $this->options['id'] . '_addone') { $current_count = &$form_state->getValue($this->options['id'].'_advanced_search_fields_count',1); $form_state->setRebuild(TRUE); } + */ + if (!$form_state->isValueEmpty('op') && + ((($form_state->getTriggeringElement()['#op'] ?? NULL) == $this->options['id'] . '_addone') || + (($form_state->getTriggeringElement()['#op'] ?? NULL) == $this->options['id'] . '_delone')) + ){ + $form_state->setRebuild(TRUE); + } // OR HOW THE RESET BUTTON DOES IT //if (!$form_state->isValueEmpty('op') && $form_state->getValue('op') == $this->options['reset_button_label']) parent::submitExposed( @@ -695,7 +703,7 @@ public function buildExposedForm(&$form, FormStateInterface $form_state) { '#value' => $this->t('@label', [ '@label' => $this->options['exposed']['advanced_search_fields_add_one_label'] ?? 'add one' ]), - '#name' => 'addone', + '#name' => 'op', '#access' => $enable_more, '#attributes' => ['data-disable-refocus' => "true", 'tabindex' => 2], '#executes_submit_callback' => TRUE, @@ -706,7 +714,7 @@ public function buildExposedForm(&$form, FormStateInterface $form_state) { 'actions' key in a form alter */ $form[$this->options['id'].'_delone'] = [ '#type' => 'button', - '#name' => 'delone', + '#name' => 'op', '#op' => $this->options['id'] . '_delone', '#value' => $this->t('@label', [ '@label' => $this->options['exposed']['advanced_search_fields_remove_one_label'] ?? 'remove one' @@ -780,9 +788,10 @@ public function validateExposed(&$form, FormStateInterface $form_state) { $current_count = &$form_state->getValue( $this->options['id'] . '_advanced_search_fields_count', 1 ); + error_log(var_export($form_state->getUserInput(),true)); if ((($triggering_element = $form_state->getTriggeringElement()['#op'] ?? NULL) == $this->options['id'] . '_addone') - && ($form_state->getUserInput()['op'] ?? NULL == $this->options['expose']['advanced_search_fields_add_one_label']) + && (isset($form_state->getUserInput()['op']) && $form_state->getUserInput()['op'] == $form_state->getTriggeringElement()['#value']) && $this->options['expose']['advanced_search_fields_multiple'] ) { $this->searchedFieldsCount = $this->searchedFieldsCount @@ -794,7 +803,7 @@ public function validateExposed(&$form, FormStateInterface $form_state) { } elseif ((($triggering_element = $form_state->getTriggeringElement()['#op'] ?? NULL) == $this->options['id'] . '_delone') - && ($form_state->getUserInput()['op'] ?? NULL == $this->options['expose']['advanced_search_fields_remove_one_label']) + && (isset($form_state->getUserInput()['op']) && $form_state->getUserInput()['op'] == $form_state->getTriggeringElement()['#value']) && $this->options['expose']['advanced_search_fields_multiple'] ) { $this->searchedFieldsCount = $this->searchedFieldsCount From 0b513a602a797d001efde5d43afc5e3aab7eba70 Mon Sep 17 00:00:00 2001 From: Diego Pino Navarro Date: Thu, 22 Jun 2023 10:57:29 -0400 Subject: [PATCH 04/13] Committing this, but it does not work I mean, almost. The issue is i can not not submit the value so what happens is basically the facet summary for queries gets offset (uses the submitted value)... gosh... I will try with a pure JS option now but want to keep this around in case i need to rollback --- .../filter/AdvancedSearchApiFulltext.php | 81 ++++++++++++++++--- 1 file changed, 71 insertions(+), 10 deletions(-) diff --git a/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php b/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php index 0ba4c00e..ec948860 100644 --- a/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php +++ b/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php @@ -407,7 +407,8 @@ public function query() { if ($negation) { $manual_keys[0]['#negation'] = $negation; } - + // @TODO: Check that manual_keys is an array;, that $query_able_datum_internal['real_solr_fields'] exists. + // if not abort the query. $flat_key = \Drupal\search_api_solr\Utility\Utility::flattenKeys( $manual_keys, $query_able_datum_internal['real_solr_fields'], $parse_mode->getPluginId() @@ -544,18 +545,20 @@ public function query() { } public function submitExposed(&$form, FormStateInterface $form_state) { - /* - if ($form_state->getTriggeringElement()['#op'] ?? NULL == $this->options['id'] . '_addone') { - $current_count = &$form_state->getValue($this->options['id'].'_advanced_search_fields_count',1); - $form_state->setRebuild(TRUE); - } - */ + if (!$form_state->isValueEmpty('op') && ((($form_state->getTriggeringElement()['#op'] ?? NULL) == $this->options['id'] . '_addone') || (($form_state->getTriggeringElement()['#op'] ?? NULL) == $this->options['id'] . '_delone')) ){ $form_state->setRebuild(TRUE); } + elseif (!$form_state->isValueEmpty('op') && !empty($this->options['exposed'])) { + if ($form_state->getTriggeringElement()['#parents'] ?? NULL && + isset($form_state->getTriggeringElement()['#parents'][0]) == 'reset') { + error_log('reset pressed'); + } + } + // OR HOW THE RESET BUTTON DOES IT //if (!$form_state->isValueEmpty('op') && $form_state->getValue('op') == $this->options['reset_button_label']) parent::submitExposed( @@ -591,6 +594,25 @@ public function acceptExposedInput($input) { // Value in our case needs to be multiple values (bc of the multiple options) if ($return && $realcount = $input[$this->options['expose']['identifier'].'_advanced_search_fields_count']) { $this->value = []; + // On add one/delete one (means not submit.. check if this will affect other exposed input? ) + if (isset($input['op']) && + isset($input['submit']) && + $input['op'] != $input['submit'] && + \Drupal::request()->hasSession() && + $this->getQuery() && + !$this->getQuery()->shouldAbort()) { + $session = \Drupal::request()->getSession(); + $display_id = ($this->view->display_handler->isDefaulted('filters')) + ? 'default' : $this->view->current_display; + $adv_search_session = $session->get('sbf_advanced_search_views', []); + if (isset($adv_search_session[$this->view->storage->id()][$display_id])) { + $input = $adv_search_session[$this->view->storage->id()][$display_id]; + // $realcount needs to be the last one submitted/stored in the session. + $realcount = $input[$this->options['expose']['identifier'] + . '_advanced_search_fields_count']; + } + } + $this->value[$this->options['expose']['identifier']] = $input[$this->options['expose']['identifier']]; for($i=1;$i < $realcount && $realcount > 1; $i++) { if (!empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator_id']) && isset($input[$this->options['expose']['operator_id'].'_'.$i])) { @@ -599,7 +621,6 @@ public function acceptExposedInput($input) { $this->value[$this->options['expose']['identifier'] . '_' . $i] = $input[$this->options['expose']['identifier'].'_'.$i] ?? ''; } } - if (!$return) { // Override for the "(not) empty" operators. $operators = $this->operators(); @@ -687,6 +708,7 @@ public function buildExposedForm(&$form, FormStateInterface $form_state) { $nextcount = (int) ($form_state->getUserInput()['sbf_advanced_search_api_fulltext_advanced_search_fields_count'] ?? 1); $prevcount = $this->view->exposed_raw_input[$this->options['id'].'_advanced_search_fields_count'] ?? NULL; $form_state_count = $form_state->getValue('sbf_advanced_search_api_fulltext_advanced_search_fields_count', NULL); + $realcount = $prevcount ?? ($form_state_count ?? $nextcount); // Cap it to the max limit $realcount = ($realcount <= $this->options['expose']['advanced_search_fields_count']) ? $realcount : $this->options['expose']['advanced_search_fields_count']; @@ -788,7 +810,6 @@ public function validateExposed(&$form, FormStateInterface $form_state) { $current_count = &$form_state->getValue( $this->options['id'] . '_advanced_search_fields_count', 1 ); - error_log(var_export($form_state->getUserInput(),true)); if ((($triggering_element = $form_state->getTriggeringElement()['#op'] ?? NULL) == $this->options['id'] . '_addone') && (isset($form_state->getUserInput()['op']) && $form_state->getUserInput()['op'] == $form_state->getTriggeringElement()['#value']) @@ -800,6 +821,9 @@ public function validateExposed(&$form, FormStateInterface $form_state) { : ($this->options['expose']['advanced_search_fields_count'] ?? 1); // Check if the state was set already $current_count++; + if (!empty($this->options['expose']['required']) && $this->getQuery()) { + + } } elseif ((($triggering_element = $form_state->getTriggeringElement()['#op'] ?? NULL) == $this->options['id'] . '_delone') @@ -812,6 +836,9 @@ public function validateExposed(&$form, FormStateInterface $form_state) { : ($this->options['expose']['advanced_search_fields_count'] ?? 1); // Check if the state was set already $current_count--; + if (!empty($this->options['expose']['required']) && $this->getQuery()) { + + } } if ($this->options['expose']['advanced_search_fields_multiple']) { @@ -829,7 +856,6 @@ public function validateExposed(&$form, FormStateInterface $form_state) { } } - $identifiers[] = $this->options['expose']['identifier']; for ($i = 1; $i < $current_count; $i++) { $identifiers[] = $this->options['expose']['identifier'] . '_' . $i; @@ -889,4 +915,39 @@ protected function canBuildGroup() { // Building groups here makes no sense. We disable it. return FALSE; } + + protected function prepareFilterSelectOptions(&$options) { + parent::prepareFilterSelectOptions( + $options + ); // TODO: Change the autogenerated stub + } + + public function storeExposedInput($input, $status) { + $return = parent::storeExposedInput( + $input, $status + ); + // In case of a proper submit (not addone/delone) we store all input in the session. + // This will be retrieved instead of the actual "form state/input submit on addone/delone + // So a previous search can be "replicated" and allowing added new fields to not be submited + // to the Views until the user decides so. + // @TODO make this an option, not the default (i like autosubmit). + if (!empty($this->options['exposed']) && isset($input['op']) && isset($input['submit']) && $input['op'] == $input['submit']) { + if (\Drupal::request()->hasSession() && $this->getQuery() && !$this->getQuery()->shouldAbort()) { + $session = \Drupal::request()->getSession(); + $display_id = ($this->view->display_handler->isDefaulted('filters')) + ? 'default' : $this->view->current_display; + $adv_search_session = $session->get('sbf_advanced_search_views', []); + $exclude = ['submit', 'form_build_id', 'form_id', 'form_token', 'exposed_form_plugin', 'reset']; + foreach( $exclude as $key) { + unset($input[$key]); + } + $adv_search_session[$this->view->storage->id()][$display_id] = $input; + $session->set('sbf_advanced_search_views', $adv_search_session); + } + } + + return $return; + } + + } From c3f9955c9b5124ed860cdc6252702ae91257074a Mon Sep 17 00:00:00 2001 From: Diego Pino Navarro Date: Thu, 22 Jun 2023 23:23:49 -0400 Subject: [PATCH 05/13] Fixes Stuck Keyword on removed Advanced Search (Facet Summary) --- .../processor/LastActiveFacetsProcessor.php | 40 +++++++++++++++---- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/modules/format_strawberryfield_facets/src/Plugin/facets_summary/processor/LastActiveFacetsProcessor.php b/modules/format_strawberryfield_facets/src/Plugin/facets_summary/processor/LastActiveFacetsProcessor.php index 19e6f2b4..692b6568 100644 --- a/modules/format_strawberryfield_facets/src/Plugin/facets_summary/processor/LastActiveFacetsProcessor.php +++ b/modules/format_strawberryfield_facets/src/Plugin/facets_summary/processor/LastActiveFacetsProcessor.php @@ -133,7 +133,7 @@ public function build(FacetsSummaryInterface $facets_summary, array $build, arra $exposed_input = $view->getExposedInput(); $view->getRequest()->getRequestUri(); $keys_to_filter = []; - $key_with_search_value = [] ; + $key_with_search_value = []; // Oh gosh, blocks... if (!$view->getDisplay()->isDefaultDisplay() && empty($view->getDisplay()->options['filters'] ?? [] )) { $filters = $view->getDisplay()->handlers['filter']; @@ -147,9 +147,17 @@ public function build(FacetsSummaryInterface $facets_summary, array $build, arra elseif ($filter->getPluginId() == 'sbf_advanced_search_api_fulltext' && $filter->isExposed() ) { + $current_count = 1; + if ($filter->options['expose']['identifier'] ?? NULL ) { + $field_count_field = $filter->options['expose']['identifier'] . '_advanced_search_fields_count'; + $current_count = $exposed_input[$field_count_field] ?? ($filter->options['expose']['advanced_search_fields_count'] ?? 1); + } $extra_keys_to_filter = []; - $keys_to_filter[] =$filter->options['expose']['operator_id'] ?? NULL; + $keys_to_filter[] = $filter->options['expose']['operator_id'] ?? NULL; $keys_to_filter[] = $filter->options['expose']['identifier'] ?? NULL; + if ($filter->options['expose']['identifier'] ?? NULL ) { + $keys_to_filter[] = $filter->options['expose']['identifier'] . '_advanced_search_fields_count'; + } $key_with_search_value[] = $filter->options['expose']['identifier'] ?? NULL; $keys_to_filter[] = $filter->options['expose']['searched_fields_id'] ?? NULL; $keys_to_filter[] = $filter->options['expose']['advanced_search_operator_id'] @@ -160,17 +168,20 @@ public function build(FacetsSummaryInterface $facets_summary, array $build, arra $i < $filter->options['expose']['advanced_search_fields_count'] ?? 1; $i++ ) { - $extra_keys_to_filter[] = $key_to_filter . '_' . $i; if (in_array($key_to_filter, $key_with_search_value)){ - $key_with_search_value[] = $key_to_filter . '_' . $i; + if ($i < $current_count) { + $key_with_search_value[] = $key_to_filter . '_' . $i; + } } } } - $keys_to_filter = array_filter($keys_to_filter); + $keys_to_filter = array_merge( $keys_to_filter, $extra_keys_to_filter ); + $keys_to_filter = array_unique($keys_to_filter); + $keys_to_filter = array_filter($keys_to_filter); } } } @@ -187,9 +198,20 @@ public function build(FacetsSummaryInterface $facets_summary, array $build, arra elseif ($filter['plugin_id'] == 'sbf_advanced_search_api_fulltext' && $filter['exposed'] ) { + $current_count = 1; + if ($filter['expose']['identifier'] ?? NULL ) { + $field_count_field = $filter['expose']['identifier'] . '_advanced_search_fields_count'; + $current_count = $exposed_input[$field_count_field] ?? ($filter['expose']['advanced_search_fields_count'] ?? 1); + } + $extra_keys_to_filter = []; $keys_to_filter[] = $filter['expose']['operator_id'] ?? NULL; $keys_to_filter[] = $filter['expose']['identifier'] ?? NULL; + // fields count = $filter['expose']['identifier'] + if ($filter['expose']['identifier'] ?? NULL ) { + $keys_to_filter[] + = $filter['expose']['identifier'] . '_advanced_search_fields_count'; + } $key_with_search_value[] = $filter['expose']['identifier'] ?? NULL; $keys_to_filter[] = $filter['expose']['searched_fields_id'] ?? @@ -203,17 +225,19 @@ public function build(FacetsSummaryInterface $facets_summary, array $build, arra $i < $filter['expose']['advanced_search_fields_count'] ?? 1; $i++ ) { - $extra_keys_to_filter[] = $key_to_filter . '_' . $i; if (in_array($key_to_filter, $key_with_search_value)) { - $key_with_search_value[] = $key_to_filter . '_' . $i; + if ($i < $current_count) { + $key_with_search_value[] = $key_to_filter . '_' . $i; + } } } } - $keys_to_filter = array_filter($keys_to_filter); $keys_to_filter = array_merge( $keys_to_filter, $extra_keys_to_filter ); + $keys_to_filter = array_unique($keys_to_filter); + $keys_to_filter = array_filter($keys_to_filter); } } } From 53a68d4c0318d8ab9daca20877daa06ab5d8e0b4 Mon Sep 17 00:00:00 2001 From: Diego Pino Navarro Date: Thu, 22 Jun 2023 23:24:10 -0400 Subject: [PATCH 06/13] We use Links now. Buttons are simply not the fit for this --- .../format_strawberryfield_views.module | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/format_strawberryfield_views/format_strawberryfield_views.module b/modules/format_strawberryfield_views/format_strawberryfield_views.module index 5e342996..7046d9ac 100644 --- a/modules/format_strawberryfield_views/format_strawberryfield_views.module +++ b/modules/format_strawberryfield_views/format_strawberryfield_views.module @@ -151,7 +151,7 @@ function format_strawberryfield_views_form_alter(&$form, FormStateInterface $for $form['actions']['submit']['#name'] = 'op'; } foreach ($form as $key => $value) { - if (is_array($value) && isset ($value['#group']) && isset($value['#type']) && $value['#group'] == 'actions' && ($value['#type'] == 'submit' || $value['#type'] == 'button')) { + if (is_array($value) && isset ($value['#group']) && isset($value['#type']) && $value['#group'] == 'actions' && ($value['#type'] == 'submit' || $value['#type'] == 'button' || $value['#type'] == 'link')) { $form['actions'][$key] = $value; unset($form[$key]); } From 31548a5f424cddd1380f1d5c924dd70d7bde47b9 Mon Sep 17 00:00:00 2001 From: Diego Pino Navarro Date: Thu, 22 Jun 2023 23:26:38 -0400 Subject: [PATCH 07/13] Pure JS deals with removal/adding of new fields This will eventually in the future allow what users want... 80's Advanced Searches. Gets around Drupal's Core bug that does not allow #ajax actions to work on exposed form filters bc the Filter logic removes the $form_id needed for the caching system to work (throwing an invisible error so weird... like max file upload reached? c'mon drupal) --- .../js/sbf-advanced-search-default-submit.js | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/modules/format_strawberryfield_views/js/sbf-advanced-search-default-submit.js b/modules/format_strawberryfield_views/js/sbf-advanced-search-default-submit.js index f15a56fc..055b4b35 100644 --- a/modules/format_strawberryfield_views/js/sbf-advanced-search-default-submit.js +++ b/modules/format_strawberryfield_views/js/sbf-advanced-search-default-submit.js @@ -8,10 +8,45 @@ defaultSubmitInput.click(); } }; + + var addMoreInterception = function(defaultSubmitInput, ev) { + ev.preventDefault(); + ev.stopPropagation(); + const $form = defaultSubmitInput.closest('.views-exposed-form'); + let $count = $form.querySelector('input[name="sbf_advanced_search_api_fulltext_advanced_search_fields_count"]'); + $count.value = Number($count.value) + 1; + defaultSubmitInput.click(); + }; + + var delOneInterception = function(defaultSubmitInput, ev) { + ev.preventDefault(); + ev.stopPropagation(); + if (typeof ev.target.dataset.advancedSearchPrefix !== 'undefined') { + const $name = ev.target.dataset.advancedSearchPrefix + '_advanced_search_fields_count'; + const $form = defaultSubmitInput.closest('.views-exposed-form'); + let $count = $form.querySelector('input[name="'+$name+'"]'); + if ($count) { + $count.value = Number($count.value) - 1; + const $tounsetSelector = ev.target.dataset.advancedSearchPrefix + '_' + $count.value; + let $tounset = $form.querySelector('input[name="' + $tounsetSelector + '"]'); + if ($tounset) { + $tounset.value = ''; + } + } + } + defaultSubmitInput.click(); + }; + for (const defaultSubmitInput of document.querySelectorAll('.views-exposed-form [data-default-submit]')) { for (const formInput of defaultSubmitInput.form.querySelectorAll('input')) { formInput.addEventListener('keypress', formInterception.bind(null, defaultSubmitInput)); } + for (const addMore of document.querySelectorAll('.views-exposed-form [data-advanced-search-addone]')) { + addMore.addEventListener('click', addMoreInterception.bind(null, defaultSubmitInput)); + } + for (const delOne of document.querySelectorAll('.views-exposed-form [data-advanced-search-delone]')) { + delOne.addEventListener('click', delOneInterception.bind(null, defaultSubmitInput)); + } } } } From 64bcb02effffe0f461e6c3c06965fec3995a6af9 Mon Sep 17 00:00:00 2001 From: Diego Pino Navarro Date: Thu, 22 Jun 2023 23:28:31 -0400 Subject: [PATCH 08/13] Still a few hours here? but this is now mostly working What is not YET working? The View is caching old Submit values. Means when i delete one and re-add one, the old "search" term reappears ... as a default. Who knows why? I will never know why. But i basically need to intervene either here or in the Ajax Controller to avoid non-accepted/not-parsed values to be take by the Filter as valid/kept around... --- .../filter/AdvancedSearchApiFulltext.php | 198 +++++++----------- 1 file changed, 72 insertions(+), 126 deletions(-) diff --git a/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php b/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php index ec948860..e4316479 100644 --- a/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php +++ b/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php @@ -5,6 +5,7 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Language\LanguageInterface; use Drupal\Core\StringTranslation\PluralTranslatableMarkup; +use Drupal\Core\Url; use Drupal\search_api\Entity\Index; use Drupal\search_api\ParseMode\ParseModePluginManager; use Drupal\search_api_solr\Utility\Utility; @@ -65,6 +66,8 @@ public function defineOptions() { $options['expose']['contains']['advanced_search_operator_id'] = ['default' => '']; $options['expose']['contains']['advanced_search_fields_add_one_label'] = ['default' => 'add one']; $options['expose']['contains']['advanced_search_fields_remove_one_label'] = ['default' => 'remove one']; + $options['advanced_search_fields_add_one_label'] = ['default' => ['add one']]; + $options['advanced_search_fields_remove_one_label'] = ['default' => ['remove one']]; return $options; } @@ -75,8 +78,8 @@ public function defaultExposeOptions() { $this->options['expose']['advanced_search_fields_count'] = 2; $this->options['expose']['advanced_search_use_operator'] = FALSE; $this->options['expose']['advanced_search_operator_id'] = $this->options['id'] . '_group_operator'; - $this->options['expose']['advanced_search_fields_add_one_label'] = 'add one'; - $this->options['expose']['advanced_search_fields_remove_one_label'] = 'remove one'; + $this->options['expose']['advanced_search_fields_add_one_label'] = $this->options['advanced_search_fields_add_one_label']; + $this->options['expose']['advanced_search_fields_remove_one_label'] = $this->options['advanced_search_fields_remove_one_label']; } /** @@ -426,12 +429,13 @@ public function query() { if ($j > 0) { if ($query_able_datum_internal['interfield_operator'] == 'and') { - $flat_key = ' && '.$flat_key; + $flat_key = ' && '. $flat_key; } } $flat_keys[] = $flat_key; $j++; } + if (count($flat_keys)) { /** @var \Drupal\search_api\ParseMode\ParseModeInterface $parse_mode */ $parse_mode_direct = $this->getParseModeManager() @@ -545,22 +549,9 @@ public function query() { } public function submitExposed(&$form, FormStateInterface $form_state) { - - if (!$form_state->isValueEmpty('op') && - ((($form_state->getTriggeringElement()['#op'] ?? NULL) == $this->options['id'] . '_addone') || - (($form_state->getTriggeringElement()['#op'] ?? NULL) == $this->options['id'] . '_delone')) - ){ - $form_state->setRebuild(TRUE); - } - elseif (!$form_state->isValueEmpty('op') && !empty($this->options['exposed'])) { - if ($form_state->getTriggeringElement()['#parents'] ?? NULL && - isset($form_state->getTriggeringElement()['#parents'][0]) == 'reset') { - error_log('reset pressed'); - } - } - // OR HOW THE RESET BUTTON DOES IT //if (!$form_state->isValueEmpty('op') && $form_state->getValue('op') == $this->options['reset_button_label']) + $form_state->setRebuild(); parent::submitExposed( $form, $form_state ); @@ -594,27 +585,8 @@ public function acceptExposedInput($input) { // Value in our case needs to be multiple values (bc of the multiple options) if ($return && $realcount = $input[$this->options['expose']['identifier'].'_advanced_search_fields_count']) { $this->value = []; - // On add one/delete one (means not submit.. check if this will affect other exposed input? ) - if (isset($input['op']) && - isset($input['submit']) && - $input['op'] != $input['submit'] && - \Drupal::request()->hasSession() && - $this->getQuery() && - !$this->getQuery()->shouldAbort()) { - $session = \Drupal::request()->getSession(); - $display_id = ($this->view->display_handler->isDefaulted('filters')) - ? 'default' : $this->view->current_display; - $adv_search_session = $session->get('sbf_advanced_search_views', []); - if (isset($adv_search_session[$this->view->storage->id()][$display_id])) { - $input = $adv_search_session[$this->view->storage->id()][$display_id]; - // $realcount needs to be the last one submitted/stored in the session. - $realcount = $input[$this->options['expose']['identifier'] - . '_advanced_search_fields_count']; - } - } - $this->value[$this->options['expose']['identifier']] = $input[$this->options['expose']['identifier']]; - for($i=1;$i < $realcount && $realcount > 1; $i++) { + for($i=1; $i < $realcount && $realcount > 1; $i++) { if (!empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator_id']) && isset($input[$this->options['expose']['operator_id'].'_'.$i])) { $this->operatorAdv[$this->options['expose']['identifier'] . '_' . $i] = $input[$this->options['expose']['operator_id'].'_'.$i]; } @@ -655,7 +627,6 @@ public function buildExposedForm(&$form, FormStateInterface $form_state) { = $this->options['expose']['searched_fields_id']; } - // Remove the group operator if found unset($form[$searched_fields_identifier]); $multiple_exposed_fields = $this->options['expose']['multiple'] ?? FALSE ? min(count($fields), 5) : 1; @@ -680,7 +651,6 @@ public function buildExposedForm(&$form, FormStateInterface $form_state) { $advanced_search_operator_id = $this->options['id'] . '_group_operator'; // And our own settings. if (!empty($this->options['expose']['advanced_search_use_operator']) && !empty($this->options['expose']['advanced_search_operator_id'])) { - if (!empty($this->options['expose']['advanced_search_operator_id'])) { $advanced_search_operator_id = $this->options['expose']['advanced_search_operator_id']; } @@ -705,44 +675,53 @@ public function buildExposedForm(&$form, FormStateInterface $form_state) { // Yes over complicated but so far the only way i found to keep the state // Of this value between calls/rebuilds and searches. // @TODO move this into Accept input. That is easier? - $nextcount = (int) ($form_state->getUserInput()['sbf_advanced_search_api_fulltext_advanced_search_fields_count'] ?? 1); - $prevcount = $this->view->exposed_raw_input[$this->options['id'].'_advanced_search_fields_count'] ?? NULL; - $form_state_count = $form_state->getValue('sbf_advanced_search_api_fulltext_advanced_search_fields_count', NULL); + $nextcount = (int) ($form_state->getUserInput()[$this->options['id'] . '_advanced_search_fields_count'] ?? 1); + //$prevcount = $this->view->exposed_raw_input[$this->options['id'].'_advanced_search_fields_count'] ?? NULL; + $form_state_count = $form_state->getValue($this->options['id'] . '_advanced_search_fields_count', NULL); - $realcount = $prevcount ?? ($form_state_count ?? $nextcount); + // $realcount = $prevcount ?? ($form_state_count ?? $nextcount); + $realcount = $form_state_count ?? $nextcount; // Cap it to the max limit $realcount = ($realcount <= $this->options['expose']['advanced_search_fields_count']) ? $realcount : $this->options['expose']['advanced_search_fields_count']; // Only enable if setup and the realcount is less than the max. $enable_more = $realcount < $this->options['expose']['advanced_search_fields_count'] && $this->options['expose']['advanced_search_fields_multiple']; $enable_less = $realcount > 1; - // This fails on Preview (because of competing Ajax and replace calls) - // @TODO Re-test without the IF bc of Sunday refactor that should have fixed it? if (empty($this->view->live_preview)) { $form[$this->options['id'].'_addone'] = [ - '#type' => 'button', - '#op' => $this->options['id'] . '_addone', - '#value' => $this->t('@label', [ - '@label' => $this->options['exposed']['advanced_search_fields_add_one_label'] ?? 'add one' - ]), - '#name' => 'op', + '#type' => 'link', + '#title' => t($this->options['expose']['advanced_search_fields_add_one_label'] ?? 'add one'), + '#url' => Url::fromRoute(''), + '#attributes' => [ + 'data-disable-refocus' => "true", + 'data-advanced-search-addone' => "true", + 'data-advanced-search-prefix' => $this->options['id'], + 'tabindex' => 2, + 'class' => [ + 'adv-search-addone', + 'button', + 'btn', + ], + ], '#access' => $enable_more, - '#attributes' => ['data-disable-refocus' => "true", 'tabindex' => 2], - '#executes_submit_callback' => TRUE, '#weight' => '-100', '#group' => 'actions', ]; - /* Note: #group does not work for buttons but we use this to bring them into - 'actions' key in a form alter */ $form[$this->options['id'].'_delone'] = [ - '#type' => 'button', - '#name' => 'op', - '#op' => $this->options['id'] . '_delone', - '#value' => $this->t('@label', [ - '@label' => $this->options['exposed']['advanced_search_fields_remove_one_label'] ?? 'remove one' - ]), - '#executes_submit_callback' => TRUE, - '#attributes' => ['data-disable-refocus' => "true", 'tabindex' => 3], + '#type' => 'link', + '#title' => t($this->options['expose']['advanced_search_fields_remove_one_label'] ?? 'delete one'), + '#url' => Url::fromRoute(''), + '#attributes' => [ + 'data-disable-refocus' => "true", + 'data-advanced-search-delone' => "true", + 'data-advanced-search-prefix' => $this->options['id'], + 'tabindex' => 3, + 'class' => [ + 'adv-search-delone', + 'button', + 'btn', + ], + ], '#access' => $enable_less, '#weight' => '-101', '#group' => 'actions', @@ -810,36 +789,7 @@ public function validateExposed(&$form, FormStateInterface $form_state) { $current_count = &$form_state->getValue( $this->options['id'] . '_advanced_search_fields_count', 1 ); - if ((($triggering_element = $form_state->getTriggeringElement()['#op'] ?? - NULL) == $this->options['id'] . '_addone') - && (isset($form_state->getUserInput()['op']) && $form_state->getUserInput()['op'] == $form_state->getTriggeringElement()['#value']) - && $this->options['expose']['advanced_search_fields_multiple'] - ) { - $this->searchedFieldsCount = $this->searchedFieldsCount - < ($this->options['expose']['advanced_search_fields_count'] ?? 1) - ? $this->searchedFieldsCount++ - : ($this->options['expose']['advanced_search_fields_count'] ?? 1); - // Check if the state was set already - $current_count++; - if (!empty($this->options['expose']['required']) && $this->getQuery()) { - - } - } - elseif ((($triggering_element = $form_state->getTriggeringElement()['#op'] ?? - NULL) == $this->options['id'] . '_delone') - && (isset($form_state->getUserInput()['op']) && $form_state->getUserInput()['op'] == $form_state->getTriggeringElement()['#value']) - && $this->options['expose']['advanced_search_fields_multiple'] - ) { - $this->searchedFieldsCount = $this->searchedFieldsCount - > ($this->options['expose']['advanced_search_fields_count'] ?? 1) - ? $this->searchedFieldsCount-- - : ($this->options['expose']['advanced_search_fields_count'] ?? 1); - // Check if the state was set already - $current_count--; - if (!empty($this->options['expose']['required']) && $this->getQuery()) { - - } - } + $this->searchedFieldsCount = $current_count; if ($this->options['expose']['advanced_search_fields_multiple']) { for ($i = 1; $i < $current_count; $i++) { @@ -856,11 +806,31 @@ public function validateExposed(&$form, FormStateInterface $form_state) { } } - $identifiers[] = $this->options['expose']['identifier']; - for ($i = 1; $i < $current_count; $i++) { - $identifiers[] = $this->options['expose']['identifier'] . '_' . $i; + $identifiers[] = $identifiers_to_keep[] = $this->options['expose']['identifier']; + + for ($i = 1; $i < $this->options['expose']['advanced_search_fields_count']; $i++) { + if ($i < $current_count) { + $identifiers_to_keep[] = $this->options['expose']['identifier'] . '_' + . $i; + } + $identifiers[] = $this->options['expose']['identifier'] . '_' + . $i; } - foreach ($identifiers as $identifier) { + + foreach ($identifiers as $index => $identifier) { + if (!in_array($identifier, $identifiers_to_keep)) { + $form_state->unsetValue($identifier); + $form_state->unsetValue($index > 0 ? $searched_fields_identifier . '_' . $index : $searched_fields_identifier); + $form_state->unsetValue($index > 0 ? $advanced_search_operator_id . '_' . $index : $advanced_search_operator_id); + $userInput = $form_state->getUserInput(); + unset($userInput[$identifier]); + unset($userInput[$index > 0 ? $searched_fields_identifier . '_' . $index : $searched_fields_identifier]); + unset($userInput[$index > 0 ? $advanced_search_operator_id . '_' . $index : $advanced_search_operator_id]); + $form_state->setUserInput($userInput); + } + } + + foreach ($identifiers_to_keep as $index => $identifier) { $input = &$form_state->getValue($identifier, ''); /// @TODO Add all inputs here... /// @@ -869,7 +839,8 @@ public function validateExposed(&$form, FormStateInterface $form_state) { ) { $this->operator = $this->options['group_info']['group_items'][$input]['operator']; - $input = &$this->options['group_info']['group_items'][$input]['value']; + $input + = &$this->options['group_info']['group_items'][$input]['value']; } // Under some circumstances, input will be an array containing the string @@ -881,7 +852,9 @@ public function validateExposed(&$form, FormStateInterface $form_state) { // No input was given by the user. If the filter was set to "required" and // there is a query (not the case when an exposed filter block is // displayed stand-alone), abort it. - if (!empty($this->options['expose']['required']) && $this->getQuery()) { + if (!empty($this->options['expose']['required']) + && $this->getQuery() + ) { $this->getQuery()->abort(); } // If the input is empty, there is nothing to validate: return early. @@ -922,32 +895,5 @@ protected function prepareFilterSelectOptions(&$options) { ); // TODO: Change the autogenerated stub } - public function storeExposedInput($input, $status) { - $return = parent::storeExposedInput( - $input, $status - ); - // In case of a proper submit (not addone/delone) we store all input in the session. - // This will be retrieved instead of the actual "form state/input submit on addone/delone - // So a previous search can be "replicated" and allowing added new fields to not be submited - // to the Views until the user decides so. - // @TODO make this an option, not the default (i like autosubmit). - if (!empty($this->options['exposed']) && isset($input['op']) && isset($input['submit']) && $input['op'] == $input['submit']) { - if (\Drupal::request()->hasSession() && $this->getQuery() && !$this->getQuery()->shouldAbort()) { - $session = \Drupal::request()->getSession(); - $display_id = ($this->view->display_handler->isDefaulted('filters')) - ? 'default' : $this->view->current_display; - $adv_search_session = $session->get('sbf_advanced_search_views', []); - $exclude = ['submit', 'form_build_id', 'form_id', 'form_token', 'exposed_form_plugin', 'reset']; - foreach( $exclude as $key) { - unset($input[$key]); - } - $adv_search_session[$this->view->storage->id()][$display_id] = $input; - $session->set('sbf_advanced_search_views', $adv_search_session); - } - } - - return $return; - } - } From ec218549be563b1bbdfc7bd540677518312ba069 Mon Sep 17 00:00:00 2001 From: Diego Pino Navarro Date: Thu, 22 Jun 2023 23:28:44 -0400 Subject: [PATCH 09/13] Remove Logs messages --- .../js/modal-exposed-form-ajax.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/modules/format_strawberryfield_views/js/modal-exposed-form-ajax.js b/modules/format_strawberryfield_views/js/modal-exposed-form-ajax.js index d704cf31..e30adee0 100644 --- a/modules/format_strawberryfield_views/js/modal-exposed-form-ajax.js +++ b/modules/format_strawberryfield_views/js/modal-exposed-form-ajax.js @@ -190,7 +190,6 @@ } }); if (reloadfacets) { - console.log('reloading!'); Drupal.AjaxFacetsView.updateFacetsBlocks(href, options.extraData.view_name, options.extraData.view_display_id); } } @@ -215,8 +214,6 @@ if (ajax_views_call && view_name && view_display_id) { var exposed_form_selector = '#views-exposed-form-' + view_name.replace(/_/g, '-') + '-' + view_display_id.replace(/_/g, '-'); var $exposed_form = $(exposed_form_selector).length; - console.log($exposed_form); - console.log(exposed_form_selector); if ($exposed_form > 0) { $exposed_form = 1; } @@ -258,10 +255,7 @@ }; Drupal.AjaxCommands.prototype.SbfSetBrowserUrl = function (ajax, response) { - console.log(response.url); window.history.replaceState(null, '', response.url); } - - })(jQuery, Drupal, once, drupalSettings); From a366cc00737dd0f81e6b108823c5e13dc06ed2c0 Mon Sep 17 00:00:00 2001 From: Diego Pino Navarro Date: Fri, 23 Jun 2023 01:48:19 -0400 Subject: [PATCH 10/13] I did it @alliomeria i did it. 2AM. Done for the day! --- ...ormatStrawberryfieldViewAjaxController.php | 39 +++++++++++- .../filter/AdvancedSearchApiFulltext.php | 60 +++++++++++++++++++ 2 files changed, 97 insertions(+), 2 deletions(-) diff --git a/modules/format_strawberryfield_views/src/Controller/FormatStrawberryfieldViewAjaxController.php b/modules/format_strawberryfield_views/src/Controller/FormatStrawberryfieldViewAjaxController.php index 8e4d8582..3b62369a 100644 --- a/modules/format_strawberryfield_views/src/Controller/FormatStrawberryfieldViewAjaxController.php +++ b/modules/format_strawberryfield_views/src/Controller/FormatStrawberryfieldViewAjaxController.php @@ -145,6 +145,8 @@ public function ajaxView(Request $request) { $response = new ViewAjaxResponse(); + + // Remove all of this stuff from the query of the request so it doesn't // end up in pagers and tablesort URLs. // @todo Remove this parsing once these are removed from the request in @@ -172,12 +174,44 @@ public function ajaxView(Request $request) { } $view = $this->executableFactory->get($entity); if ($view && $view->access($display_id) && $view->setDisplay($display_id) && $view->display_handler->ajaxEnabled()) { - $response->setView($view); + // Fix the current path for paging. if (!empty($path)) { $this->currentPath->setPath('/' . ltrim($path, '/'), $request); } + // Because Exposed filters use Get and our form is submitting via POST + // We end with stale old values. + + // Let's check if our view has our advanced search filter + + $filters = $view->getDisplay($display_id)->display['display_options']['filters'] ?? []; + foreach ($filters as $filter) { + /* @var \Drupal\views\Plugin\views\ViewsHandlerInterface $filter */ + if ($filter['plugin_id'] == 'sbf_advanced_search_api_fulltext' + && $filter['exposed'] == TRUE + ) { + if ($filter['expose']['identifier'] ?? NULL ) { + // At this stage the loaded View has already processed + // the whole GET bag as its own input based on the active request + // We need to alter that. Let's check if we have the id in both GET and POST + // If in POST, POST wins and replaces/needs to replace GET in the view + $views_post = $view->getRequest()->request->all(); + unset($views_post['ajax_page_state']); + $views_get = $view->getRequest()->query->all(); + if (isset($views_post[$filter['expose']['identifier']])) { + foreach ($views_get as $get_args_keys => $value) { + if (strpos($get_args_keys, $filter->options['expose']['identifier']) === 0) { + unset($views_get[$get_args_keys]); + } + } + } + } + $view->getRequest()->query->replace($views_post + $views_get); + } + } + + // Add all POST data, because AJAX is always a post and many things, // such as tablesorts, exposed filters and paging assume GET. $request_all = $request->request->all(); @@ -185,6 +219,7 @@ public function ajaxView(Request $request) { $query_all = $request->query->all(); $request->query->replace($request_all + $query_all); + $response->setView($view); // Overwrite the destination. // @see the redirect.destination service. $origin_destination = $path; @@ -236,7 +271,7 @@ public function ajaxView(Request $request) { ->merge($bubbleable_metadata) ->applyTo($exposed_form); } - $response->addCommand(new ReplaceCommand("#views-exposed-form-" . $view_id, $this->renderer->render($exposed_form))); + $response->addCommand(new ReplaceCommand("#views-exposed-form-" . $view_id, $this->renderer->render($exposed_form))); } return $response; diff --git a/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php b/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php index e4316479..fba44c54 100644 --- a/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php +++ b/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php @@ -62,12 +62,14 @@ public function defineOptions() { $options = parent::defineOptions(); $options['expose']['contains']['advanced_search_fields_multiple'] = ['default' => FALSE]; $options['expose']['contains']['advanced_search_fields_count'] = ['default' => 2]; + $options['expose']['contains']['advanced_search_fields_count_min'] = ['default' => 1]; $options['expose']['contains']['advanced_search_use_operator'] = ['default' => FALSE]; $options['expose']['contains']['advanced_search_operator_id'] = ['default' => '']; $options['expose']['contains']['advanced_search_fields_add_one_label'] = ['default' => 'add one']; $options['expose']['contains']['advanced_search_fields_remove_one_label'] = ['default' => 'remove one']; $options['advanced_search_fields_add_one_label'] = ['default' => ['add one']]; $options['advanced_search_fields_remove_one_label'] = ['default' => ['remove one']]; + $options['fields_label_replace'] = ['default' => NULL]; return $options; } @@ -76,6 +78,7 @@ public function defaultExposeOptions() { parent::defaultExposeOptions(); $this->options['expose']['advanced_search_fields_multiple'] = FALSE; $this->options['expose']['advanced_search_fields_count'] = 2; + $this->options['expose']['advanced_search_fields_count_min'] = 1; $this->options['expose']['advanced_search_use_operator'] = FALSE; $this->options['expose']['advanced_search_operator_id'] = $this->options['id'] . '_group_operator'; $this->options['expose']['advanced_search_fields_add_one_label'] = $this->options['advanced_search_fields_add_one_label']; @@ -113,6 +116,20 @@ public function buildExposeForm(&$form, FormStateInterface $form_state) { ], ], ]; + $form['expose']['advanced_search_fields_count_min'] = [ + '#type' => 'number', + '#default_value' => $this->options['expose']['advanced_search_fields_count_min'], + '#title' => $this->t('Min number of Multiple/add more Search Fields the user will see. Number must be less or equal to the max. If not it will cap automatically'), + '#size' => 5, + '#min' => 1, + '#max' => 10, + '#description' => $this->t('The number of search Fields with the same general exposed settings the user will see by default.'), + '#states' => [ + 'visible' => [ + ':input[name="options[expose][advanced_search_fields_multiple]"]' => ['checked' => TRUE], + ], + ], + ]; $form['expose']['advanced_search_fields_add_one_label'] = [ '#type' => 'textfield', @@ -164,6 +181,28 @@ public function buildExposeForm(&$form, FormStateInterface $form_state) { ]; } + + /** + * {@inheritdoc} + */ + public function buildOptionsForm(&$form, FormStateInterface $form_state) { + parent::buildOptionsForm($form, $form_state); + + if (isset($form['fields']['#options'])) { + foreach ($form['fields']['#options'] as $key => $value) { + $replacement[] = $key . '|' . $value; + } + $replacement = implode("\n", $replacement); + $form['fields_label_replace'] = [ + '#type' => 'textarea', + '#default_value' => $this->options['fields_label_replace'] ?? $replacement, + '#rows' => 8, + '#title' => $this->t('Replacement pattern for user facing Fields. '), + '#size' => 40, + '#description' => $this->t('Use a Pipe (|) to separate value from desired label. One per line'), + ]; + } + } /** * {@inheritdoc} */ @@ -615,11 +654,15 @@ public function buildExposedForm(&$form, FormStateInterface $form_state) { if ($this->options['expose']['expose_fields']) { $fields = $this->getFulltextFields(); $configured_fields = $this->options['fields']; + + // Only keep the configured fields. if (!empty($configured_fields)) { $configured_fields = array_flip($configured_fields); $fields = array_intersect_key($fields, $configured_fields); } + $fields = $this->rewriteFieldLabels($fields); + //Now the searched fields if exposed. $searched_fields_identifier = $this->options['id'] . '_searched_fields'; if (!empty($this->options['expose']['searched_fields_id'])) { @@ -695,6 +738,7 @@ public function buildExposedForm(&$form, FormStateInterface $form_state) { '#attributes' => [ 'data-disable-refocus' => "true", 'data-advanced-search-addone' => "true", + 'data-advanced-search-max' => $this->options['expose']['advanced_search_fields_count'], 'data-advanced-search-prefix' => $this->options['id'], 'tabindex' => 2, 'class' => [ @@ -714,6 +758,7 @@ public function buildExposedForm(&$form, FormStateInterface $form_state) { '#attributes' => [ 'data-disable-refocus' => "true", 'data-advanced-search-delone' => "true", + 'data-advanced-search-min' => $this->options['expose']['advanced_search_fields_count_min'], 'data-advanced-search-prefix' => $this->options['id'], 'tabindex' => 3, 'class' => [ @@ -895,5 +940,20 @@ protected function prepareFilterSelectOptions(&$options) { ); // TODO: Change the autogenerated stub } + private function rewriteFieldLabels($options) { + $lines = explode("\n", trim($this->options['fields_label_replace'])); + foreach ($lines as $line) { + if (strpos($line, '|') !== FALSE) { + [$search, $replace] = array_map('trim', explode('|', $line)); + if (!empty($search)) { + if (isset($options[$search])) { + $options[$search] = $replace; + } + } + } + } + return $options; + } + } From b4c57468ff081ceaa2bf388c9f18caa32f3c8a1a Mon Sep 17 00:00:00 2001 From: Diego Pino Navarro Date: Fri, 23 Jun 2023 01:48:35 -0400 Subject: [PATCH 11/13] Since i am release, let's remove this silly thing --- src/Plugin/Field/FieldFormatter/StrawberryPdfFormatter.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Plugin/Field/FieldFormatter/StrawberryPdfFormatter.php b/src/Plugin/Field/FieldFormatter/StrawberryPdfFormatter.php index fb9d9d82..b6a5968a 100644 --- a/src/Plugin/Field/FieldFormatter/StrawberryPdfFormatter.php +++ b/src/Plugin/Field/FieldFormatter/StrawberryPdfFormatter.php @@ -388,7 +388,6 @@ public static function changePdfCallBack( array $form, FormStateInterface $form_state ) { - error_log('changeSceneCallBack called'); $button = $form_state->getTriggeringElement(); $element = NestedArray::getValue( $form, From a79840537523618820b61f36926ea43db1a0b6fd Mon Sep 17 00:00:00 2001 From: Diego Pino Navarro Date: Fri, 23 Jun 2023 02:06:44 -0400 Subject: [PATCH 12/13] Little css here and there Just the minimal, each theme can override this --- .../format_strawberryfield_views/css/advanced_search.css | 7 +++++++ .../format_strawberryfield_views.libraries.yml | 3 +++ .../src/Plugin/views/filter/AdvancedSearchApiFulltext.php | 2 ++ 3 files changed, 12 insertions(+) create mode 100644 modules/format_strawberryfield_views/css/advanced_search.css diff --git a/modules/format_strawberryfield_views/css/advanced_search.css b/modules/format_strawberryfield_views/css/advanced_search.css new file mode 100644 index 00000000..22cd11c2 --- /dev/null +++ b/modules/format_strawberryfield_views/css/advanced_search.css @@ -0,0 +1,7 @@ +.adv-search-delone { + margin-right: 0.275rem; +} + +.adv-search-addone { + margin-right: 0.275rem; +} diff --git a/modules/format_strawberryfield_views/format_strawberryfield_views.libraries.yml b/modules/format_strawberryfield_views/format_strawberryfield_views.libraries.yml index 546e0c31..919b7bb5 100644 --- a/modules/format_strawberryfield_views/format_strawberryfield_views.libraries.yml +++ b/modules/format_strawberryfield_views/format_strawberryfield_views.libraries.yml @@ -46,6 +46,9 @@ view-ajax-interactions: advanced-search-default-submit: js: js/sbf-advanced-search-default-submit.js: {minified: false} + css: + component: + css/advanced_search.css: { } dependencies: - core/drupal - core/jquery diff --git a/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php b/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php index fba44c54..b9b7f043 100644 --- a/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php +++ b/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php @@ -745,6 +745,7 @@ public function buildExposedForm(&$form, FormStateInterface $form_state) { 'adv-search-addone', 'button', 'btn', + 'btn-secondary' ], ], '#access' => $enable_more, @@ -765,6 +766,7 @@ public function buildExposedForm(&$form, FormStateInterface $form_state) { 'adv-search-delone', 'button', 'btn', + 'btn-secondary' ], ], '#access' => $enable_less, From e887bd4bbdd62217d47719aa4b0de2bb52006ac0 Mon Sep 17 00:00:00 2001 From: Diego Pino Navarro Date: Fri, 23 Jun 2023 11:30:09 -0400 Subject: [PATCH 13/13] restore RESET functionality --- .../views/filter/AdvancedSearchApiFulltext.php | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php b/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php index b9b7f043..7f30789e 100644 --- a/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php +++ b/modules/format_strawberryfield_views/src/Plugin/views/filter/AdvancedSearchApiFulltext.php @@ -588,9 +588,16 @@ public function query() { } public function submitExposed(&$form, FormStateInterface $form_state) { - // OR HOW THE RESET BUTTON DOES IT - //if (!$form_state->isValueEmpty('op') && $form_state->getValue('op') == $this->options['reset_button_label']) - $form_state->setRebuild(); + if (!$form_state->isValueEmpty('op') && + !empty($this->options['exposed']) && + $form_state->getTriggeringElement()['#parents'] ?? NULL && + ($form_state->getTriggeringElement()['#parents'][0] ?? NULL) == 'reset') { + $form_state->setRebuild(FALSE); + } + elseif (!$form_state->isValueEmpty('op') && + !empty($this->options['exposed'])) { + $form_state->setRebuild(TRUE); + } parent::submitExposed( $form, $form_state ); @@ -954,7 +961,7 @@ private function rewriteFieldLabels($options) { } } } - return $options; + return $options; }