浏览代码

Merge branch 'release/1.0.0'

Olivier Massot 4 年之前
父节点
当前提交
ce93041282

+ 19 - 7
components/Ui/Map/Structures.vue

@@ -63,6 +63,11 @@ export default Vue.extend({
       type: Array as () => Array<Structure>,
       required: false,
       default: () => []
+    },
+    zoomAtStart: {
+      type: Boolean,
+      required: false,
+      default: false
     }
   },
   data () {
@@ -77,7 +82,7 @@ export default Vue.extend({
         { src: '/images/la_reunion.png', alt: 'La Réunion', bounds: [[-20.65, 54.92], [-21.65, 56.15]] },
         { src: '/images/guyane.png', alt: 'Guyane', bounds: [[6.24, -54.62], [1.87, -50.59]] }
       ],
-      zoomRequired: false
+      zoomRequired: this.zoomAtStart
     }
   },
   watch: {
@@ -87,11 +92,7 @@ export default Vue.extend({
       }
 
       if (this.zoomRequired) {
-        const zoomed = this._fitBoundsToMarkers()
-        if (!zoomed) {
-          this.setMapBounds(this.defaultBounds)
-        }
-        this.zoomRequired = false
+        this._applyZoom()
       }
     }
   },
@@ -112,6 +113,10 @@ export default Vue.extend({
     this.map.on('zoomend moveend', () => {
       this.$emit('boundsUpdated', this.map.getBounds())
     })
+
+    if (this.zoomRequired) {
+      this._applyZoom()
+    }
   },
   beforeDestroy (): void {
     if (this.map) {
@@ -162,8 +167,15 @@ export default Vue.extend({
       if (!(coords.length > 0)) {
         return false
       }
-      this.setMapBounds(coords, [120, 120])
+      this.setMapBounds(coords, [80, 80])
       return true
+    },
+    _applyZoom (): void {
+      const zoomed = this._fitBoundsToMarkers()
+      if (!zoomed) {
+        this.setMapBounds(this.defaultBounds)
+      }
+      this.zoomRequired = false
     }
   }
 })

+ 25 - 15
components/Ui/Search/Address.vue

@@ -14,7 +14,9 @@
       :label="$t('where') + ' ?'"
       outlined
       append-icon="mdi-crosshairs-gps"
+      @click="onClick"
       @change="$emit('change', $event ? $event.value : '')"
+      @click:append="geolocalizeUser"
     />
     <v-snackbar :value="errorMsg !== ''">
       {{ errorMsg }}
@@ -92,23 +94,17 @@ export default Vue.extend({
       model: null as Address | null,
       search: null,
       features: [] as Array<Feature>,
+      items: [] as Array<Address>,
       loading: false,
-      errorMsg: ''
-    }
-  },
-  computed: {
-    items (): Array<Address> {
-      return this.features.map((f: Feature) => {
-        return {
-          text: f.properties.name + ' (' + f.properties.postcode + ')',
-          value: { longitude: f.geometry.coordinates[0] as number, latitude: f.geometry.coordinates[1] as number },
-          disabled: false
-        }
-      })
+      errorMsg: '',
+      geolocalized: false
     }
   },
   watch: {
     search (val: string) {
+      if (this.geolocalized) {
+        return
+      }
       if (!val) {
         this.features = []
         return
@@ -129,7 +125,13 @@ export default Vue.extend({
       fetch(encodeURI(apiUrl))
         .then(res => res.json())
         .then(({ features }) => {
-          this.features = features
+          this.items = features.map((f: Feature) => {
+            return {
+              text: f.properties.name + ' (' + f.properties.postcode + ')',
+              value: { longitude: f.geometry.coordinates[0] as number, latitude: f.geometry.coordinates[1] as number },
+              disabled: false
+            }
+          })
         })
         .catch((err) => {
           // eslint-disable-next-line no-console
@@ -144,20 +146,28 @@ export default Vue.extend({
     clear () {
       this.model = null
       this.search = null
-      this.features = []
+      this.items = []
       this.loading = false
       this.errorMsg = ''
+      this.geolocalized = false
+    },
+    onClick () {
+      this.clear()
     },
     geolocalizeUser () {
       if (navigator.geolocation) {
         navigator.geolocation.getCurrentPosition(
           (position: { coords: { longitude: number, latitude: number }}) => {
             this.clear()
-            this.model = {
+            const loc = {
               text: this.$t('my_position') as string,
               value: { longitude: position.coords.longitude, latitude: position.coords.latitude },
               disabled: false
             }
+            this.geolocalized = true
+            this.items = [loc]
+            this.model = loc
+            this.$emit('change', loc.value)
           },
           () => {
             this.errorMsg = this.$t('geolocation_error') as string

+ 14 - 13
pages/structures/_id.vue

@@ -3,6 +3,7 @@
     <header class="mb-4">
       <v-layout>
         <v-btn
+          v-if="parent"
           :to="{path: '/structures', query: { parent: parent, view: view, theme: theme }}"
           nuxt
           plain
@@ -52,11 +53,19 @@
 
       <v-row>
         <v-col cols="12">
-          <v-chip-group v-if="structure.practices" :max="0" active-class="primary--text" class="justify-center">
-            <v-chip v-for="practice in structure.practices" :key="practice">
+          <div
+            v-if="structure.practices"
+            class="d-flex justify-center flex-wrap"
+          >
+            <v-chip
+              v-for="practice in structure.practices"
+              :key="practice"
+              class="ma-1"
+              label
+            >
               {{ $t(practice) }}
             </v-chip>
-          </v-chip-group>
+          </div>
         </v-col>
       </v-row>
 
@@ -165,7 +174,7 @@
               </td>
               <td class="network">
                 <NuxtLink
-                  v-if="structure.n1Id !== parent"
+                  v-if="parent && (structure.n1Id !== parent)"
                   class="neutral"
                   :to="{path: '/structures/' + structure.n1Id, query: { parent: parent, view: view, theme: theme }}"
                   nuxt
@@ -221,14 +230,6 @@ import parsePhoneNumber from 'libphonenumber-js'
 import StructuresProvider from '~/services/data/StructuresProvider'
 
 export default Vue.extend({
-  validate ({ query }) {
-    if (!/^\d+$/.test(query.parent as string ?? '')) {
-      // eslint-disable-next-line no-console
-      console.error('Missing parameter: parent')
-      return false
-    }
-    return true
-  },
   async asyncData ({
     params, $axios
   }): Promise<{ structure: Structure }> {
@@ -238,7 +239,7 @@ export default Vue.extend({
   },
   data (): object {
     return {
-      parent: parseInt(this.$route.query.parent as string),
+      parent: this.$route.query.parent ? parseInt(this.$route.query.parent as string) : null,
       view: this.$route.query.view ?? 'map',
       theme: this.$route.query.theme ?? 'orange',
       showTel: false,

+ 30 - 15
pages/structures/index.vue

@@ -22,7 +22,7 @@
     <v-row>
       <!-- Map Column (hidden in 'list-view' mode)-->
       <v-col
-        v-show="mapview"
+        v-if="mapview"
         cols="12"
         sm="6"
       >
@@ -30,6 +30,7 @@
           <UiMapStructures
             ref="map"
             :structures="filteredStructures"
+            :zoom-at-start="mapZoomAtStart"
             @boundsUpdated="mapBoundsFilterChanged"
           />
         </no-ssr>
@@ -206,7 +207,14 @@
                         :contain="true"
                         style="margin: 12px;"
                       />
-                      <div v-else style="height: 104px; width: 264px"></div>
+                      <v-skeleton-loader
+                        v-else
+                        type="card-avatar"
+                        boilerplate
+                        width="164px"
+                        height="84px"
+                        style="margin: 10px 50px;"
+                      />
                     </div>
 
                     <div :class="'d-flex flex-column' + (listview ? ' flex-grow-1' : '')">
@@ -251,17 +259,21 @@
                       </v-card-text>
                     </div>
 
-                    <v-chip-group
+                    <div
                       v-if="structure.practices"
-                      column
-                      active-class="primary--text"
-                      class="d-flex flex-row align-start"
+                      class="d-grid flex-wrap"
                       :style="listview ? 'width: 25%;min-width: 25%;' : ''"
                     >
-                      <v-chip v-for="practice in structure.practices" :key="practice" outlined small pill>
+                      <v-chip
+                        v-for="practice in structure.practices"
+                        :key="practice"
+                        class="ma-1"
+                        label
+                        small
+                      >
                         {{ $t(practice) }}
                       </v-chip>
-                    </v-chip-group>
+                    </div>
 
                     <span v-if="mapview" class="flex-fill" />
 
@@ -339,7 +351,8 @@ export default Vue.extend({
       federationFilter: null as number | null,
       distanceFilter: null as number | null,
       mapBoundsFilter: null as LatLngBounds | null,
-      mapBoundsFilterStarted: false // map bounds filter is only activated when the map bounds are updated
+      mapBoundsFilterStarted: false, // map bounds filter is only activated when the map bounds are updated
+      mapZoomAtStart: false
     }
   },
   async fetch () {
@@ -361,7 +374,7 @@ export default Vue.extend({
 
         // zoom on map markers (except if the parent structure is the CMF)
         if (this.parent !== CMF_ID) {
-          this.fitMapToResults()
+          this.mapZoomAtStart = true
         }
       })
   },
@@ -399,7 +412,7 @@ export default Vue.extend({
     viewChanged (e: number) {
       this.view = (e === 0) ? 'map' : 'list'
       if (this.mapview) {
-        this.fitMapToResults()
+        this.mapZoomAtStart = true
       }
     },
     textFilterChanged (newVal: string) {
@@ -448,7 +461,7 @@ export default Vue.extend({
     matchTextFilter (structure: Structure): boolean {
       if (!this.textFilter) { return true }
 
-      return structure.name.toLowerCase().includes(this.textFilter.toLowerCase())
+      return this.searchTextNormalize(structure.name).includes(this.searchTextNormalize(this.textFilter))
     },
     /**
      * Does the structure match the current locationFilter
@@ -526,9 +539,11 @@ export default Vue.extend({
      */
     search (): void {
       this.filteredStructures = this.structures.filter((s) => { return this.matchFilters(s) })
-      this.fitMapToResults()
+      if (this.mapview) {
+        this.fitMapToResults()
+      }
     },
-    autocompleteSearchNormalize (s: string): string {
+    searchTextNormalize (s: string): string {
       return s
         .toLowerCase()
         .replace(/[éèẽëê]/g, 'e')
@@ -548,7 +563,7 @@ export default Vue.extend({
      * @param itemText
      */
     enhancedAutocompleteFilter (_: any, queryText: string, itemText: string): boolean {
-      return this.autocompleteSearchNormalize(itemText).includes(this.autocompleteSearchNormalize(queryText))
+      return this.searchTextNormalize(itemText).includes(this.searchTextNormalize(queryText))
     }
   }
 })

+ 3 - 4
test/cypress/integration/structures/index.spec.js

@@ -6,7 +6,7 @@ describe('Test the /structures page', () => {
 
     // wait for the page to be completely loaded
     cy.get('.structure-card', { timeout: 8000 })
-    cy.contains('Nos Structures adhérentes')
+    cy.contains('Nos structures adhérentes')
   })
 
   it('Map, filters, and all results shall display by default', () => {
@@ -46,9 +46,8 @@ describe('Test the /structures page', () => {
   it('If view is set on list mode, map shall be hidden', () => {
     cy.get('button').contains('Liste').click()
 
-    // map shall not be visible in list view
-    cy.get('#map', { timeout: 8000 })
-      .should('not.be.visible')
+    // map shall not exists in list view
+    cy.get('#map').should('not.exist')
 
     // results should still be visible
     cy.get('.structure-card')