Browse Source

pagination nav refactoring, only miss pages display in text

Bachir Soussi Chiadmi 3 years ago
parent
commit
def83059ed
4 changed files with 216 additions and 122 deletions
  1. 8 7
      assets/css/app.scss
  2. 130 0
      src/components/Content/EdPagination.vue
  3. 25 25
      src/components/Content/EdText.vue
  4. 53 90
      src/pages/Edition.vue

+ 8 - 7
assets/css/app.scss

@@ -472,7 +472,8 @@ section[role="main-content"]{
       $w:3em;
       width:$w; height:0;
       margin-left:calc(100% - (#{$w} * 0.5));
-      &:before, &:after{
+      // &:before
+      &:after{
         display: block;
         position: absolute;
         font-size: 0.630em;
@@ -483,13 +484,13 @@ section[role="main-content"]{
         color: $bleuroi;
         text-indent: $w + 0.5em;
       }
-      &:before{
-        content:attr(data-num-prev);
-        border-bottom: 1px solid $bleuroilight;
-        bottom: 0.1em;
-      }
+      // &:before{
+      //   content:attr(data-num-prev);
+      //   border-bottom: 1px solid $bleuroilight;
+      //   bottom: 0.1em;
+      // }
       &:after{
-        content:attr(data-num);
+        content:attr(title);
         border-top: 1px solid $bleuroilight;
         top:0.1em;
       }

+ 130 - 0
src/components/Content/EdPagination.vue

@@ -0,0 +1,130 @@
+<template>
+  <div v-if="options.length">
+    <!-- <select class="" name="page-nav" v-model="page_selected" placeholder="Pages">
+      <option value="" disabled selected>Pages</option>
+      <option v-for="(page, index) in pages" :key="index" :value="page">{{ page }}</option>
+    </select> -->
+    <v-select
+      id="page-nav-select"
+      type="select"
+      placeholder="Aller à la page ..."
+      append-to-body
+      :calculate-position="dropDownMenuPos"
+      :options="options"
+      :clearable="false"
+      :value="page_selected"
+      :selectable="option => ! option.disabled"
+      @input="onClickPaginationItem"
+    >
+      <template v-slot:option="option">
+        <span v-for="l in option.level" :key="l" class="op-tab"/>
+        {{ option.label }}
+      </template>
+    </v-select>
+  </div>
+</template>
+
+<script>
+
+import { createPopper } from '@popperjs/core'
+
+export default {
+  name: 'EdPagination',
+  props: {
+    pagination: Array
+  },
+  data: () => ({
+    options: [],
+    page_selected: ''
+  }),
+  created () {
+    this.parsePagesToOptions(this.pagination)
+  },
+  // watch: {
+  //   loadedtextsuuids (n, o) {
+  //     console.log('EdToc watch loadedtxtsuuids', o, n)
+  //   }
+  // },
+  methods: {
+    parsePagesToOptions (p, i = 0, l = 0) {
+      console.log('EdPagination parsePagesToOptions', p)
+      for (var j = 0; j < p.length; j++) {
+        // if it is just a section without page like a volume
+        if (p[j].text) {
+          this.options.push({
+            key: i,
+            code: p[j].text,
+            label: p[j].text,
+            disabled: true,
+            level: l
+          })
+        }
+        // if it's a real page break
+        if (p[j].pageBreak) {
+          this.options.push({
+            key: i,
+            code: p[j].pageBreak,
+            label: p[j].pageNum,
+            uuid: p[j].uuid,
+            level: l
+          })
+        }
+        if (p[j].pages && p[j].pages.length) {
+          this.parsePagesToOptions(p[j].pages, i++, l + 1)
+        } else {
+          i++
+        }
+      }
+    },
+    dropDownMenuPos (dropdownList, component, { width }) {
+      /**
+       * We need to explicitly define the dropdown width since
+       * it is usually inherited from the parent with CSS.
+       */
+      dropdownList.style.width = width
+
+      /**
+       * Here we position the dropdownList relative to the $refs.toggle Element.
+       *
+       * The 'offset' modifier aligns the dropdown so that the $refs.toggle and
+       * the dropdownList overlap by 1 pixel.
+       *
+       * The 'toggleClass' modifier adds a 'drop-up' class to the Vue Select
+       * wrapper so that we can set some styles for when the dropdown is placed
+       * above.
+       */
+      const popper = createPopper(component.$refs.toggle, dropdownList, {
+        placement: 'top',
+        modifiers: [
+          {
+            name: 'offset',
+            options: {
+              offset: [0, -1]
+            }
+          },
+          {
+            name: 'toggleClass',
+            enabled: true,
+            phase: 'write',
+            fn ({ state }) {
+              component.$el.classList.toggle('drop-up', state.placement === 'top')
+            }
+          }]
+      })
+
+      /**
+       * To prevent memory leaks Popper needs to be destroyed.
+       * If you return function, it will be called just before dropdown is removed from DOM.
+       */
+      return () => popper.destroy()
+    },
+    onClickPaginationItem (o) {
+      this.page_selected = o
+      this.$emit('onClickPaginationItem', o)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+</style>

+ 25 - 25
src/components/Content/EdText.vue

@@ -27,9 +27,9 @@ export default {
       this.buildTemplate()
     }
   },
-  mounted () {
-    this.$emit('onNewPageBreaks', this.pages)
-  },
+  // mounted () {
+  //   this.$emit('onNewPageBreaks', this.pages)
+  // },
   methods: {
     buildTemplate () {
       // console.log('EdText buildTemplate: tei', this.tei)
@@ -89,28 +89,28 @@ export default {
     },
     parsePageBreaks () {
       let pbs = this.html.match(/<span role="pageBreak"[^>]+><\/span>/g)
-      // console.log('pagebreaks', pbs)
-      if (pbs) {
-        let pbparts, newpb, num
-        for (var i = 0; i < pbs.length; i++) {
-          pbparts = RegExp(/<span role="pageBreak" data-num="(.+)"><\/span>/).exec(pbs[i], 'g')
-          if (!pbparts) {
-            console.warn(`pageBreak ${i} maformed`, pbs[i])
-          } else {
-            // console.log('pbparts', pbparts)
-            num = pbparts[1]
-            this.pages.push(num)
-            newpb = `<span` +
-              // ` id="page-break-${num}"` +
-              ` role="pageBreak"` +
-              ` data-num="${num}"` +
-              ` data-num-prev="${num - 1}"` +
-              ` />`
-            // console.log('newpb', newpb)
-            this.html = this.html.replace(pbs[i], newpb)
-          }
-        }
-      }
+      console.log('pagebreaks', pbs)
+      // if (pbs) {
+      //   let pbparts, newpb, num
+      //   for (var i = 0; i < pbs.length; i++) {
+      //     pbparts = RegExp(/<span role="pageBreak" data-num="(.+)"><\/span>/).exec(pbs[i], 'g')
+      //     if (!pbparts) {
+      //       console.warn(`pageBreak ${i} maformed`, pbs[i])
+      //     } else {
+      //       // console.log('pbparts', pbparts)
+      //       num = pbparts[1]
+      //       this.pages.push(num)
+      //       newpb = `<span` +
+      //         // ` id="page-break-${num}"` +
+      //         ` role="pageBreak"` +
+      //         ` data-num="${num}"` +
+      //         ` data-num-prev="${num - 1}"` +
+      //         ` />`
+      //       // console.log('newpb', newpb)
+      //       this.html = this.html.replace(pbs[i], newpb)
+      //     }
+      //   }
+      // }
     },
     onClickRef (e) {
       console.log('onClickRef(e)', e)

+ 53 - 90
src/pages/Edition.vue

@@ -51,7 +51,6 @@
           :textid="textid"
           @onHoverLink="onHoverLink"
           @onLeaveLink="onLeaveLink"
-          @onNewPageBreaks="onNewPageBreaks"
         />
         <infinite-loading
           :identifier="textid"
@@ -61,37 +60,30 @@
     </div>
 
     <template #nav>
-      <EdToc id="toc" :toc="toc" :loadedtextsuuids="textsuuids" @onClickTocItem="onClickTocItem" />
-      <div v-if="pages.length" id="page-nav">
-        <!-- <select class="" name="page-nav" v-model="page_selected" placeholder="Pages">
-          <option value="" disabled selected>Pages</option>
-          <option v-for="(page, index) in pages" :key="index" :value="page">{{ page }}</option>
-        </select> -->
-        <v-select
-          id="page-nav-select"
-          type="select"
-          placeholder="Aller à la page ..."
-          append-to-body
-          :calculate-position="dropDownMenuPos"
-          :options="pages"
-          :clearable="false"
-          :value="page_selected"
-          @input="onPageSelected"
-        />
-      </div>
+      <EdToc
+        id="toc"
+        :toc="toc"
+        :loadedtextsuuids="textsuuids"
+        @onClickTocItem="onClickTocItem"
+      />
+      <EdPagination
+        v-if="pagination"
+        id="page-nav"
+        :pagination="pagination"
+        @onClickPaginationItem="onClickPaginationItem"
+      />
     </template>
   </MainContentLayout>
 </template>
 
 <script>
 
-import { createPopper } from '@popperjs/core'
-
 import { REST } from 'api/rest-axios'
 import { mapState, mapActions } from 'vuex'
 import MainContentLayout from '../components/Layouts/MainContentLayout'
 import EdText from '../components/Content/EdText'
 import EdToc from '../components/Content/EdToc'
+import EdPagination from '../components/Content/EdPagination'
 
 export default {
   name: 'Edition',
@@ -104,7 +96,8 @@ export default {
   components: {
     MainContentLayout,
     EdText,
-    EdToc
+    EdToc,
+    EdPagination
   },
   data: () => ({
     toc: null,
@@ -126,9 +119,7 @@ export default {
     inifinite_load_distance: 10,
     reftoscrollto: null,
     //
-    pages: [],
-    pagesOptions: [],
-    page_selected: ''
+    pagination: null
   }),
   computed: {
     ...mapState({
@@ -193,10 +184,28 @@ export default {
           }
         } else {
           console.warn('Bad edition uuid', this.$route.params.id, this.$route)
-          this.$router.replace({
-            name: 'notfound',
-            query: { fullpath: this.$route.path }
-          })
+          // this.$router.replace({
+          //   name: 'notfound',
+          //   query: { fullpath: this.$route.path }
+          // })
+        }
+      })
+      .catch((error) => {
+        console.warn('Issue with text toc', error)
+        Promise.reject(error)
+      })
+    // get the edition's pagination
+    REST.get(`${window.apipath}/texts/` + this.$route.params.id + `/pagination`, {})
+      .then(({ data }) => {
+        console.log('texts/pagination REST: data', data)
+        if (data.content && data.content !== 'vide') {
+          this.pagination = data.content
+        } else {
+          console.warn('Bad edition uuid', this.$route.params.id, this.$route)
+          // this.$router.replace({
+          //   name: 'notfound',
+          //   query: { fullpath: this.$route.path }
+          // })
         }
       })
       .catch((error) => {
@@ -336,71 +345,25 @@ export default {
         })
       }
     },
-    onNewPageBreaks (p) {
-      // console.log('onNewPageBreaks', p)
-      for (var i = 0; i < p.length; i++) {
-        if (this.pages.indexOf(p[i]) === -1) {
-          this.pages.push(p[i])
-        }
+    onClickPaginationItem (o) {
+      console.log('onClickPaginationItem', o)
+      if (this.textsuuids.indexOf(o.uuid) !== -1) {
+        // if already loaded, scroll to uuid
+        this.scrollToPage(o)
+      } else {
+        // if not already loaded, change route
+        this.$router.push({
+          name: `editiontext`,
+          params: {
+            id: this.editionid,
+            textid: o.uuid
+          }
+        })
       }
-      // reorder array
-      this.pages.sort((a, b) => a - b)
-      // this.pagesOptions = []
-      // for (var j = 0; j < this.pages.length; j++) {
-      //   this.pagesOptions.push({ code: this.pages[j], label: `page ${this.pages[j]}` })
-      // }
-    },
-    dropDownMenuPos (dropdownList, component, { width }) {
-      /**
-       * We need to explicitly define the dropdown width since
-       * it is usually inherited from the parent with CSS.
-       */
-      dropdownList.style.width = width
-
-      /**
-       * Here we position the dropdownList relative to the $refs.toggle Element.
-       *
-       * The 'offset' modifier aligns the dropdown so that the $refs.toggle and
-       * the dropdownList overlap by 1 pixel.
-       *
-       * The 'toggleClass' modifier adds a 'drop-up' class to the Vue Select
-       * wrapper so that we can set some styles for when the dropdown is placed
-       * above.
-       */
-      const popper = createPopper(component.$refs.toggle, dropdownList, {
-        placement: 'top',
-        modifiers: [
-          {
-            name: 'offset',
-            options: {
-              offset: [0, -1]
-            }
-          },
-          {
-            name: 'toggleClass',
-            enabled: true,
-            phase: 'write',
-            fn ({ state }) {
-              component.$el.classList.toggle('drop-up', state.placement === 'top')
-            }
-          }]
-      })
-
-      /**
-       * To prevent memory leaks Popper needs to be destroyed.
-       * If you return function, it will be called just before dropdown is removed from DOM.
-       */
-      return () => popper.destroy()
-    },
-    onPageSelected (e) {
-      console.log('onPageSelected', e)
-      this.page_selected = e
-      this.scrollToPage(e)
-      // this.scrollToPage(e.code)
     },
     scrollToPage (p) {
       // console.log('scrollToPage', p)
-      this.reftoscrollto = `span[role="pageBreak"][data-num="${p}"]`
+      this.reftoscrollto = `span[role="pageBreak"][id="${p.code}"]`
     }
   }
 }