Browse Source

drafted ajax search call

Bachir Soussi Chiadmi 5 years ago
parent
commit
7f65fd79a4

+ 37 - 3
config/sync/search_api.index.database.yml

@@ -8,8 +8,8 @@ dependencies:
     - taxonomy
     - search_api
   config:
-    - field.storage.node.field_famille
     - field.storage.node.body
+    - field.storage.node.field_famille
     - field.storage.node.field_tags
     - field.storage.taxonomy_term.field_synonyms
     - field.storage.node.field_thesaurus
@@ -52,6 +52,14 @@ field_settings:
     dependencies:
       config:
         - field.storage.node.field_famille
+  nid:
+    label: ID
+    datasource_id: 'entity:node'
+    property_path: nid
+    type: integer
+    dependencies:
+      module:
+        - node
   node_grants:
     label: 'Node access information'
     property_path: search_api_node_grants
@@ -68,7 +76,7 @@ field_settings:
       config:
         - field.storage.node.body
   status:
-    label: null
+    label: status
     datasource_id: 'entity:node'
     property_path: status
     type: boolean
@@ -101,6 +109,18 @@ field_settings:
         - field.storage.taxonomy_term.field_synonyms
       module:
         - taxonomy
+  tag_tid:
+    label: 'Tags » Taxonomy term » Term ID'
+    datasource_id: 'entity:node'
+    property_path: 'field_tags:entity:tid'
+    type: text
+    boost: !!float 13
+    dependencies:
+      config:
+        - field.storage.node.field_tags
+      module:
+        - taxonomy
+        - taxonomy
   thesaurus_name:
     label: 'Thesaurus » Taxonomy term » Name'
     datasource_id: 'entity:node'
@@ -125,6 +145,18 @@ field_settings:
         - field.storage.taxonomy_term.field_synonyms
       module:
         - taxonomy
+  thesaurus_tid:
+    label: 'Thesaurus » Taxonomy term » Term ID'
+    datasource_id: 'entity:node'
+    property_path: 'field_thesaurus:entity:tid'
+    type: text
+    boost: !!float 21
+    dependencies:
+      config:
+        - field.storage.node.field_thesaurus
+      module:
+        - taxonomy
+        - taxonomy
   title:
     label: Title
     datasource_id: 'entity:node'
@@ -135,7 +167,7 @@ field_settings:
       module:
         - node
   uid:
-    label: null
+    label: uid
     datasource_id: 'entity:node'
     property_path: uid
     type: integer
@@ -185,8 +217,10 @@ processor_settings:
       - processed
       - tag_name
       - tag_synonyms
+      - tag_tid
       - thesaurus_name
       - thesaurus_synonyms
+      - thesaurus_tid
       - title
     title: true
     alt: true

+ 15 - 0
web/modules/custom/materio_sapi/materio_sapi.routing.yml

@@ -21,3 +21,18 @@ materio_sapi.search_form:
 #     _title: 'MaterioSapiSearchForm'
 #   requirements:
 #     _access: 'TRUE'
+
+materio_sapi.getresults:
+  path: '/materio_sapi/getresults'
+  defaults:
+    _controller: '\Drupal\materio_sapi\Controller\Base::getResults'
+    _format: json
+  requirements:
+    _permission: 'access materio search'
+
+# materio_sapi.base:
+#   path: '/base/{keys}/{autocomplete}'
+#   defaults:
+#     _controller: '\Drupal\materio_sapi\Controller\Base::base'
+#   requirements:
+#     _permission: 'access materio search'

+ 97 - 0
web/modules/custom/materio_sapi/src/Controller/Base.php

@@ -0,0 +1,97 @@
+<?php
+// https://www.qed42.com/blog/autocomplete-drupal-8
+// https://www.drupal.org/docs/8/modules/search-api/developer-documentation/executing-a-search-in-code
+
+namespace Drupal\materio_sapi\Controller;
+
+use Drupal\Core\Controller\ControllerBase;
+use Symfony\Component\HttpFoundation\JsonResponse;
+use Symfony\Component\HttpFoundation\Request;
+use Drupal\Component\Utility\Tags;
+use Drupal\Component\Utility\Unicode;
+use Drupal\search_api\Entity\Index;
+
+// https://drupal.stackexchange.com/questions/225008/programatically-use-search-api
+
+/**
+ * Defines a route controller for entity autocomplete form elements.
+ */
+class Base extends ControllerBase {
+
+  /**
+   * Handler for autocomplete request.
+   */
+  public function getResults(Request $request) {
+    $resp = [
+      'tes' => 'ok',
+      'autocomplete' => $request->query->get('autocomplete'),
+      'keys' => $request->query->get('keys'),
+      'range' => array(
+        'offset' => $request->query->get('offset'),
+        'limit' => $request->query->get('limit'),
+      ),
+    ];
+
+    // Get the typed string from the URL, if it exists.
+    if ($keys = $resp['keys']) {
+      $typed_string = Tags::explode($keys);
+      $typed_string = Unicode::strtolower($keys);
+      \Drupal::logger('materio_sapi')->notice($typed_string);
+
+      $index = Index::load('database');
+      $query = $index->query();
+
+      // Change the parse mode for the search.
+      $parse_mode = \Drupal::service('plugin.manager.search_api.parse_mode')
+        ->createInstance('direct');
+      $parse_mode->setConjunction('OR');
+      $query->setParseMode($parse_mode);
+
+      // Set fulltext search keywords and fields.
+      $query->keys($typed_string);
+      // $query->setFulltextFields(['name']);
+
+      // Set additional conditions.
+      // $query->addCondition('status', 1)
+      //   ->addCondition('author', 1, '<>');
+
+      // Restrict the search to specific languages.
+      // $query->setLanguages(['de', 'it']);
+
+      // Do paging.
+      $query->range($resp['range']['offset'], $resp['range']['limit']);
+
+      // Add sorting.
+      $query->sort('search_api_relevance', 'DESC');
+
+      // Set one or more tags for the query.
+      // @see hook_search_api_query_TAG_alter()
+      // @see hook_search_api_results_TAG_alter()
+      $query->addTag('materio_sapi_search');
+
+      $results = $query->execute();
+
+      $resultitems = $results->getResultItems();
+      $resp['count'] = $results->getResultCount();
+      $resp['resultitems'] = array_keys($resultitems);
+      $resp['options'] = $query->getOptions();
+
+
+      $items = [];
+      foreach ($results as $result) {
+        // \Drupal::logger('materio_sapi')->notice(print_r($result->getField('tid')->getValues(),true));
+        // \Drupal::logger('materio_sapi')->notice(print_r($result->getField('name')->getValues(),true));
+        $nid = $result->getField('nid')->getValues()[0];
+        $title = $result->getField('title')->getValues()[0]->getText();
+        $items[] = [
+          'nid' => $nid,
+          'title' => $title,
+        ];
+      }
+      $resp['items'] = $items;
+    }
+
+    return new JsonResponse($resp);
+  }
+
+}

+ 10 - 3
web/modules/custom/materio_sapi/src/Form/MaterioSapiSearchForm.php

@@ -30,12 +30,19 @@ class MaterioSapiSearchForm extends FormBase {
       '#weight' => '0',
       '#attributes' => [
         "placeholder" => $this->t('Search'),
-        "@keyup" => "keyup",
+        // "@keyup" => "keyup",
         "@keyup.enter" => "submit",
-        "v-model" => "typed"
-
+        "v-model" => "keys",
+        // "v-on:select" => "typed",
       ],
       '#autocomplete_route_name' => 'materio_sapi.search_autocomplete',
+
+    ];
+    $form['searchautocomplete'] = [
+      '#type' => 'hidden',
+      '#attributes' => [
+        "v-model" => "autocomplete"
+      ],
     ];
     $form['submit'] = [
       '#type' => 'submit',

File diff suppressed because it is too large
+ 0 - 0
web/themes/custom/materiotheme/assets/dist/main.js


+ 1 - 1
web/themes/custom/materiotheme/vuejs/components/Block/LoginBlock.vue

@@ -33,7 +33,7 @@ export default {
     }
   },
   beforeMount() {
-    console.log('LoginBlock beforeMount', this._props.block);
+    // console.log('LoginBlock beforeMount', this._props.block);
     if(this._props.block){
       // console.log('LoginBlock beforeMount if this._props.block ok');
       this.template = Vue.compile(this._props.block)

+ 47 - 6
web/themes/custom/materiotheme/vuejs/components/Form/SearchForm.vue

@@ -2,20 +2,54 @@
 
 import Vue from 'vue'
 
+import { mapState, mapActions } from 'vuex'
+
 export default {
   props: ['form'],
   data() {
     return {
-      template: null,
-      typed: ""
+      template: null
+      // keys: "",
+      // autocomplete: ""
     }
   },
-  methods: {
-    keyup() {
-      console.log("search typed", this.typed);
+  computed: {
+    // ...mapState(['Search'])
+    // ...mapState({
+    //   // keys: state => state.Search.keys,
+    //   autocomplete: state => state.Search.autocomplete
+    // }),
+    keys: {
+      get(){
+        return this.$store.state.Search.keys
+      },
+      set(value){
+        this.$store.commit('Search/setKeys', value)
+      }
     },
+    autocomplete: {
+      get(){
+        return this.$store.state.Search.autocomplete
+      },
+      set(value){
+        this.$store.commit('Search/setAutocomplete', value)
+      }
+    }
+
+  },
+  methods: {
+    ...mapActions({
+      getResults: 'Search/getResults'
+    }),
     submit() {
-      console.log("search clicked");
+      console.log("search clicked", this.keys, this.autocomplete);
+      this.getResults();
+    },
+    onAutoCompleteSelect(event, ui){
+      event.preventDefault();
+      // console.log('autoCompleteSelect', event, ui);
+      this.keys = ui.item.label
+      this.autocomplete = ui.item.value
     }
   },
   beforeMount() {
@@ -29,9 +63,16 @@ export default {
       this.template.staticRenderFns.map(fn => (this.$options.staticRenderFns.push(fn)));
     }
   },
+  watch: {
+    keys(){
+      console.log('keys changed', this.keys);
+    }
+  },
   mounted(){
     // console.log('SearchForm mounted');
     Drupal.attachBehaviors(this.$el);
+    // Catch the jquery ui events for autocmplete widget
+    jQuery(this.$el.querySelector('#edit-search')).on('autocompleteselect', this.onAutoCompleteSelect);
   },
   render(h) {
     // console.log('searchForm render');

+ 3 - 1
web/themes/custom/materiotheme/vuejs/store/index.js

@@ -1,12 +1,14 @@
 import Vue from 'vue'
 import Vuex from 'vuex'
 import User from './modules/user'
+import Search from './modules/search'
 
 // https://github.com/vuejs/vuex/tree/dev/examples/shopping-cart
 
 Vue.use(Vuex)
 export default new Vuex.Store({
   modules: {
-    User
+    User,
+    Search
   }
 })

+ 53 - 0
web/themes/custom/materiotheme/vuejs/store/modules/search.js

@@ -0,0 +1,53 @@
+import { JSONAPI } from 'vuejs/api/json-axios'
+import { MA } from 'vuejs/api/ma-axios'
+import qs from 'querystring'
+
+export default {
+  namespaced: true,
+
+  // initial state
+  state : {
+    keys: "",
+    autocomplete: "",
+    results: {}
+  },
+
+  // getters
+  getters : {},
+
+  // mutations
+  mutations : {
+    setResults (state, data) {
+      state.results = data.results
+    },
+    setKeys (state, keys) {
+      state.keys = keys
+    },
+    setAutocomplete (state, autocomplete) {
+      state.autocomplete = autocomplete
+    }
+  },
+
+  // actions
+  actions : {
+    getResults ({ dispatch, commit, state }) {
+      let params = {
+        keys: state.keys,
+        autocomplete: state.autocomplete,
+        offset:0,
+        limit: 25
+      }
+      console.log('Search getResults params', params);
+      let q = qs.stringify(params)
+      return MA.get(`/materio_sapi/getresults?`+q)
+        .then(({ data }) => {
+          console.log('search MA getresults data', data)
+          commit('setResults', data)
+        })
+        .catch(( error ) => {
+            console.warn('Issue with getResults', error)
+            Promise.reject(error)
+        })
+    }
+  }
+}

Some files were not shown because too many files changed in this diff