Edition.vue 15 KB

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