Edition.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. <template>
  2. <MainContentLayout
  3. id="edition"
  4. :reftoscrollto="reftoscrollto"
  5. :navopened="navopened"
  6. @onCenterScrolled="onCenterScrolled"
  7. >
  8. <!-- <transition name="fade" mode="out-in"> -->
  9. <template v-if="!corpusLoaded" #header>
  10. <span class="loading">Loading ...</span>
  11. </template>
  12. <template v-else #header>
  13. <h1>
  14. <router-link :to="{ name:'edition', params: { id: editionid }}">{{ title }}</router-link>
  15. </h1>
  16. <div v-if="biblio" class="biblio">
  17. <p v-html="biblio.description" />
  18. <a
  19. :href="edition_manifestation_href"
  20. @click.prevent="onClickManifestation"
  21. @keyup.enter="onClickManifestation"
  22. >
  23. {{ biblio.uuid }}
  24. </a>
  25. </div>
  26. <!-- <p v-if="meta">{{ meta.author }}</p> -->
  27. <aside
  28. v-if="indexitem"
  29. class="index-tooltip"
  30. :style="{ top:tooltip_top + 'px' }"
  31. :data-index="indexitem.index"
  32. :data-uuid="indexitem.uuid"
  33. @click.prevent="onClickTooltip"
  34. @keyup.enter="onClickTooltip"
  35. >
  36. <span v-if="indexitem == 'loading'" class="loading">Loading ...</span>
  37. <template v-if="indexitem !== 'loading'">
  38. <h1 v-html="indexitem.title" />
  39. <p v-if="indexitem.birthDate" class="birthdeath">
  40. <time>{{ indexitem.birthDate }}</time>, <span class="place">{{ indexitem.birthPlace }}</span><br>
  41. <time>{{ indexitem.deathDate }}</time>, <span class="place">{{ indexitem.deathPlace }}</span>
  42. </p>
  43. <p v-if="indexitem.occupation" class="occupation">
  44. {{ indexitem.occupation }}
  45. </p>
  46. <p v-if="indexitem.type" class="type">
  47. {{ indexitem.type }}
  48. </p>
  49. </template>
  50. </aside>
  51. </template>
  52. <!-- </transition> -->
  53. <!-- default slot -->
  54. <div id="text">
  55. <template v-if="texts.length">
  56. <infinite-loading
  57. v-if="flattoc && center_scrolled"
  58. :identifier="inifinite_load_id"
  59. direction="top"
  60. :distance="inifinite_load_distance"
  61. @infinite="prevText"
  62. />
  63. <!-- <transition-group name="edition-texts" tag="div"> -->
  64. <EdText
  65. v-for="text in texts"
  66. :ref="text.content.uuid"
  67. :key="text.content.uuid"
  68. :tei="text.content.tei"
  69. :uuid="text.content.uuid"
  70. :url="text.content.url"
  71. :textid="textid"
  72. :extract="extract"
  73. @onHoverLink="onHoverLink"
  74. @onLeaveLink="onLeaveLink"
  75. />
  76. <!-- </transition-group> -->
  77. <infinite-loading
  78. v-if="flattoc"
  79. :identifier="inifinite_load_id"
  80. @infinite="nextText"
  81. />
  82. </template>
  83. </div>
  84. <template #nav>
  85. <span
  86. class="nav-title"
  87. @click.prevent="onOpenCloseNav"
  88. @keyup.enter="onOpenCloseNav"
  89. >
  90. <svg xmlns="http://www.w3.org/2000/svg" width="14" height="10" role="presentation" class="vs__open-indicator"><path d="M9.211364 7.59931l4.48338-4.867229c.407008-.441854.407008-1.158247 0-1.60046l-.73712-.80023c-.407008-.441854-1.066904-.441854-1.474243 0L7 5.198617 2.51662.33139c-.407008-.441853-1.066904-.441853-1.474243 0l-.737121.80023c-.407008.441854-.407008 1.158248 0 1.600461l4.48338 4.867228L7 10l2.211364-2.40069z" /></svg>
  91. Sommaire
  92. </span>
  93. <EdToc
  94. id="toc"
  95. :toc="toc"
  96. :loadedtextsuuids="textsuuids"
  97. @onClickTocItem="onClickTocItem"
  98. />
  99. <EdPagination
  100. v-if="pagination"
  101. id="page-nav"
  102. :pagination="pagination"
  103. @onClickPaginationItem="onClickPaginationItem"
  104. />
  105. </template>
  106. </MainContentLayout>
  107. </template>
  108. <script>
  109. import qs from 'querystring'
  110. import { REST } from 'api/rest-axios'
  111. import { mapState, mapActions } from 'vuex'
  112. import MainContentLayout from '../components/Layouts/MainContentLayout'
  113. import EdText from '../components/Content/EdText'
  114. import EdToc from '../components/Content/EdToc'
  115. import EdPagination from '../components/Content/EdPagination'
  116. export default {
  117. name: 'Edition',
  118. metaInfo () {
  119. // console.log('metainfo', this.meta)
  120. return {
  121. title: this.metainfotitle
  122. }
  123. },
  124. components: {
  125. MainContentLayout,
  126. EdText,
  127. EdToc,
  128. EdPagination
  129. },
  130. data: () => ({
  131. meta: null,
  132. editionid: null,
  133. textid: null,
  134. texts: [],
  135. textsuuids: [],
  136. metainfotitle: undefined,
  137. title: undefined,
  138. biblio: undefined,
  139. author: undefined,
  140. texttitle: undefined,
  141. //
  142. indexitem: null,
  143. tooltip_top: null,
  144. //
  145. next_loaded: false,
  146. center_scrolled: false,
  147. inifinite_load_distance: 10,
  148. inifinite_load_id: +new Date(),
  149. reftoscrollto: null,
  150. //
  151. toc: null,
  152. flattoc: null,
  153. //
  154. pagination: null,
  155. //
  156. navopened: false
  157. }),
  158. computed: {
  159. ...mapState({
  160. corpusLoaded: state => state.Corpus.corpusLoaded,
  161. editionslist: state => state.Corpus.editionslist,
  162. editionsbyuuid: state => state.Corpus.editionsbyuuid
  163. }),
  164. edition_manifestation_href () {
  165. return `${this.biblio.path}${this.biblio.uuid}`
  166. }
  167. },
  168. watch: {
  169. $route (to, from) {
  170. console.log('Edition Watcher $route', from, to)
  171. if (to.params.textid) {
  172. // change textid when route change
  173. this.textid = to.params.textid
  174. // change also extract if exists
  175. if (to.params.extract) {
  176. console.log('extract params from route', to.params.extract)
  177. this.extract = to.params.extract
  178. // scrolling is not working :(
  179. this.reftoscrollto = '#mark-1'
  180. }
  181. } else if (this.toc) {
  182. // if no textid in new route (e.g. edition front)
  183. // but we have toc
  184. // get the first item
  185. // will be replaced by front page of edition
  186. this.textid = this.toc[0].children[1].uuid
  187. } else {
  188. this.textid = null
  189. }
  190. },
  191. reftoscrollto (newref, oldref) {
  192. console.log('reftoscrollto changed', oldref, newref)
  193. },
  194. textid (newid, oldid) {
  195. console.log('textid watcher', this, oldid, newid)
  196. this.texts = []
  197. this.textsuuids = []
  198. this.pages = []
  199. this.pagesOtpions = []
  200. if (newid) {
  201. this.getTextContent(newid)
  202. this.inifinite_load_id += 1
  203. }
  204. },
  205. textdata (newtxtdata, oldtxtdata) {
  206. console.log('textdata watcher', oldtxtdata, newtxtdata)
  207. this.metainfotitle = `${this.title} ${newtxtdata.meta.title}`
  208. },
  209. page_selected (newp, oldp) {
  210. console.log('page_selected watcher', oldp, newp)
  211. this.scrollToPage(newp)
  212. },
  213. flattoc (n, o) {
  214. console.log('flattoc watcher', o, n)
  215. // this.scrollToPage(newp)
  216. }
  217. },
  218. created () {
  219. // console.log('Edition this.$route.params.id', this.$route.params.id)
  220. this.editionid = this.$route.params.id
  221. // get the text if textid available
  222. if (this.$route.params.textid) {
  223. this.textid = this.$route.params.textid
  224. }
  225. // get the searchkeys from route param (only comming from result item) for text highlighting
  226. if (this.$route.params.extract) {
  227. this.extract = this.$route.params.extract
  228. // scrolling is not working :(
  229. this.reftoscrollto = '#mark-1'
  230. }
  231. // wait for editions list from Corpus Store if not already loaded
  232. if (!this.corpusLoaded) {
  233. // this.getCorpuses()
  234. // subsribe to store to get the editionbyuuid list
  235. // https://dev.to/viniciuskneves/watch-for-vuex-state-changes-2mgj
  236. this.edUuuidsUnsubscribe = this.$store.subscribe((mutation, state) => {
  237. // console.log('Edition store subscribe', mutation.type)
  238. if (mutation.type === 'Corpus/setEditionsByUUID') {
  239. // console.log('Edition state.Coprus.editionsbyuuid', this.editionid, state.Corpus.editionsbyuuid)
  240. this.title = this.metainfotitle = state.Corpus.editionsbyuuid[this.editionid].title
  241. this.biblio = state.Corpus.editionsbyuuid[this.editionid].biblio
  242. }
  243. if (mutation.type === 'Corpus/setTocs') {
  244. console.log('Edition Corpus/setTocs', this.editionid, state.Corpus.editionsbyuuid)
  245. this.toc = state.Corpus.editionsbyuuid[this.editionid].toc
  246. }
  247. if (mutation.type === 'Corpus/buildFlatTocs') {
  248. console.log('Edition Corpus/buildFlatTocs', this.editionid, state.Corpus.editionsbyuuid)
  249. this.flattoc = state.Corpus.editionsbyuuid[this.editionid].flattoc
  250. // launch infinitloading
  251. this.inifinite_load_id += 1
  252. // if no textid in new route (e.g. edition front)
  253. // but we have toc
  254. // get the first item
  255. // will be replaced by front page of edition
  256. if (!this.textid) { this.textid = this.flattoc[1] }
  257. }
  258. if (mutation.type === 'Corpus/setPaginations') {
  259. // console.log('Edition state.Coprus.editionsbyuuid', this.editionid, state.Corpus.editionsbyuuid)
  260. this.pagination = state.Corpus.editionsbyuuid[this.editionid].pagination
  261. }
  262. })
  263. } else {
  264. // console.log('');
  265. this.title = this.metainfotitle = this.editionsbyuuid[this.editionid].title
  266. this.biblio = this.editionsbyuuid[this.editionid].biblio
  267. this.toc = this.editionsbyuuid[this.editionid].toc
  268. this.flattoc = this.editionsbyuuid[this.editionid].flattoc
  269. // if no textid in new route (e.g. edition front)
  270. // but we have toc
  271. // get the first item
  272. // will be replaced by front page of edition
  273. if (!this.textid) { this.textid = this.toc[0].children[0].uuid }
  274. this.pagination = this.editionsbyuuid[this.editionid].pagination
  275. }
  276. },
  277. methods: {
  278. ...mapActions({
  279. getCorpuses: 'Corpus/getCorpuses'
  280. }),
  281. getTextContent (textid, $state = null, direction = 'next') {
  282. console.log('getTextContent', textid)
  283. let params = {
  284. depth: 0
  285. }
  286. let q = qs.stringify(params)
  287. REST.get(`${window.apipath}/items/${textid}?${q}`, {})
  288. .then(({ data }) => {
  289. console.log('text REST: data', data)
  290. if (direction === 'next') {
  291. this.texts.push(data)
  292. this.textsuuids.push(data.content.uuid)
  293. } else {
  294. this.texts.unshift(data)
  295. this.textsuuids.unshift(data.content.uuid)
  296. }
  297. if ($state) {
  298. $state.loaded()
  299. this.next_loaded = true
  300. }
  301. })
  302. .catch((error) => {
  303. console.warn('Issue with getTextContent', error)
  304. Promise.reject(error)
  305. // if some item don't load and if we come from infinite loading
  306. // retry with next step
  307. if ($state) {
  308. switch (direction) {
  309. case 'next':
  310. this.nextText($state, 2)
  311. break
  312. case 'prev':
  313. this.prevText($state, 2)
  314. break
  315. }
  316. }
  317. // this.$router.replace({
  318. // name: 'notfound',
  319. // query: { fullpath: this.$route.path }
  320. // })
  321. })
  322. },
  323. onCenterScrolled (e) {
  324. // console.log('Edition centerScrolled(e)', e.target.scrollTop)
  325. if (!this.center_scrolled && e.target.scrollTop > this.inifinite_load_distance * 1.5) {
  326. this.center_scrolled = true
  327. }
  328. this.indexitem = null
  329. },
  330. nextText ($state, indent = 1) {
  331. console.log('infinite loading nextText()')
  332. let indexofnext = this.flattoc.indexOf(this.textsuuids[this.textsuuids.length - 1]) + indent
  333. if (indexofnext < this.flattoc.length) {
  334. this.getTextContent(this.flattoc[indexofnext], $state, 'next')
  335. } else {
  336. $state.complete()
  337. }
  338. },
  339. prevText ($state, indent = 1) {
  340. console.log('infinite loading prevText()')
  341. let indexofprev = this.flattoc.indexOf(this.textsuuids[0]) - indent
  342. if (indexofprev >= 0) {
  343. this.getTextContent(this.flattoc[indexofprev], $state, 'prev')
  344. } else {
  345. $state.complete()
  346. }
  347. },
  348. onHoverLink (elmt) {
  349. console.log('Edition onHoverLink(elmt)', elmt)
  350. this.tooltip_top = elmt.rect.top
  351. this.getIndexItem(elmt)
  352. },
  353. onLeaveLink () {
  354. console.log('Edition onLeaveLink()')
  355. this.indexitem = null
  356. },
  357. getIndexItem (item) {
  358. this.indexitem = 'loading'
  359. REST.get(`${window.apipath}/index${item.index.charAt(0).toUpperCase()}${item.index.slice(1)}/${item.uuid}`, {})
  360. .then(({ data }) => {
  361. console.log('index tooltip REST: data', data)
  362. if (this.indexitem === 'loading') {
  363. this.indexitem = data.content
  364. this.indexitem.index = item.index
  365. }
  366. })
  367. .catch((error) => {
  368. console.warn('Issue with index tooltip rest', error)
  369. Promise.reject(error)
  370. this.indexitem = null
  371. })
  372. },
  373. onClickTocItem (uuid) {
  374. console.log('Edition onClickTocItem', uuid, this.$refs)
  375. if (this.textsuuids.indexOf(uuid) !== -1) {
  376. // if already loaded, scroll to uuid
  377. this.reftoscrollto = `.tei[data-uuid="${uuid}"]`
  378. } else {
  379. // if not already loaded, change route
  380. this.$router.push({
  381. name: `editiontext`,
  382. params: {
  383. id: this.editionid,
  384. textid: uuid
  385. }
  386. })
  387. }
  388. },
  389. onClickPaginationItem (o) {
  390. console.log('onClickPaginationItem', o)
  391. if (this.textsuuids.indexOf(o.uuid) !== -1) {
  392. // if already loaded, scroll to uuid
  393. // this.scrollToPage(o)
  394. this.reftoscrollto = `span[role="pageBreak"][id="${o.code}"]`
  395. } else {
  396. // if not already loaded, change route
  397. this.$router.push({
  398. name: `editiontext`,
  399. params: {
  400. id: this.editionid,
  401. textid: o.uuid
  402. }
  403. })
  404. }
  405. },
  406. // scrollToPage (p) {
  407. // console.log('scrollToPage', p)
  408. //
  409. // },
  410. onOpenCloseNav (e) {
  411. console.log('onOpenCloseNav', e)
  412. this.navopened = !this.navopened
  413. },
  414. onClickTooltip (e) {
  415. console.log(`onClickTooltip index: ${e.target.dataset.index}, uuid: ${e.target.dataset.uuid}`)
  416. this.$router.push({
  417. name: e.target.dataset.index,
  418. params: { id: e.target.dataset.uuid }
  419. })
  420. },
  421. onClickManifestation (e) {
  422. console.log(`onClickManifestation`)
  423. this.$router.push({
  424. name: 'bibliographieItem',
  425. params: { type: 'manifestations', uuid: this.biblio.uuid }
  426. })
  427. }
  428. }
  429. }
  430. </script>
  431. <style lang="scss" scoped>
  432. </style>