Edition.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. <template>
  2. <MainContentLayout id="edition" :reftoscrollto="reftoscrollto" @onCenterScrolled="onCenterScrolled">
  3. <template v-if="!content" #header>
  4. <span>Loading ...</span>
  5. </template>
  6. <template #header>
  7. <h1>
  8. <router-link :to="{ name:'edition', params: { id: editionid }}">{{ title }}</router-link>
  9. </h1>
  10. <p v-if="meta">{{ meta.author }}</p>
  11. <aside
  12. v-if="indexitem"
  13. class="index-tooltip"
  14. :style="{ top:tooltip_top + 'px' }"
  15. >
  16. <span v-if="indexitem == 'loading'">Loading ...</span>
  17. <template v-if="indexitem !== 'loading'">
  18. <h1 v-html="indexitem.title" />
  19. <p v-if="indexitem.birthDate" class="birthdeath">
  20. <time>{{ indexitem.birthDate }}</time>, <span class="place">{{ indexitem.birthPlace }}</span><br>
  21. <time>{{ indexitem.deathDate }}</time>, <span class="place">{{ indexitem.deathPlace }}</span>
  22. </p>
  23. <p v-if="indexitem.occupation" class="occupation">
  24. {{ indexitem.occupation }}
  25. </p>
  26. <p v-if="indexitem.type" class="type">
  27. {{ indexitem.type }}
  28. </p>
  29. </template>
  30. </aside>
  31. </template>
  32. <!-- default slot -->
  33. <div id="text">
  34. <template v-if="texts.length">
  35. <infinite-loading
  36. v-if="center_scrolled"
  37. :identifier="textid"
  38. direction="top"
  39. :distance="inifinite_load_distance"
  40. @infinite="prevText"
  41. />
  42. <EdText
  43. v-for="text in texts"
  44. :ref="text.content.uuid"
  45. :key="text.content.uuid"
  46. :tei="text.content.tei"
  47. :uuid="text.content.uuid"
  48. :textid="textid"
  49. @onHoverLink="onHoverLink"
  50. @onLeaveLink="onLeaveLink"
  51. />
  52. <infinite-loading
  53. v-if="toc"
  54. :identifier="textid"
  55. @infinite="nextText"
  56. />
  57. </template>
  58. </div>
  59. <template #nav>
  60. <EdToc
  61. id="toc"
  62. :toc="toc"
  63. :loadedtextsuuids="textsuuids"
  64. @onClickTocItem="onClickTocItem"
  65. />
  66. <EdPagination
  67. v-if="pagination"
  68. id="page-nav"
  69. :pagination="pagination"
  70. @onClickPaginationItem="onClickPaginationItem"
  71. />
  72. </template>
  73. </MainContentLayout>
  74. </template>
  75. <script>
  76. import qs from 'querystring'
  77. import { REST } from 'api/rest-axios'
  78. import { mapState, mapActions } from 'vuex'
  79. import MainContentLayout from '../components/Layouts/MainContentLayout'
  80. import EdText from '../components/Content/EdText'
  81. import EdToc from '../components/Content/EdToc'
  82. import EdPagination from '../components/Content/EdPagination'
  83. export default {
  84. name: 'Edition',
  85. metaInfo () {
  86. // console.log('metainfo', this.meta)
  87. return {
  88. title: this.metainfotitle
  89. }
  90. },
  91. components: {
  92. MainContentLayout,
  93. EdText,
  94. EdToc,
  95. EdPagination
  96. },
  97. data: () => ({
  98. meta: null,
  99. editionid: null,
  100. textid: null,
  101. texts: [],
  102. textsuuids: [],
  103. metainfotitle: undefined,
  104. title: undefined,
  105. author: undefined,
  106. texttitle: undefined,
  107. //
  108. indexitem: null,
  109. tooltip_top: null,
  110. //
  111. next_loaded: false,
  112. center_scrolled: false,
  113. inifinite_load_distance: 10,
  114. reftoscrollto: null,
  115. //
  116. toc: null,
  117. //
  118. pagination: null
  119. }),
  120. computed: {
  121. ...mapState({
  122. editionslist: state => state.Corpus.editionslist,
  123. editionsbyuuid: state => state.Corpus.editionsbyuuid
  124. })
  125. },
  126. watch: {
  127. $route (to, from) {
  128. console.log('Edition Watcher $route', from, to)
  129. if (to.params.textid) {
  130. // change textid when route change
  131. this.textid = to.params.textid
  132. } else if (this.toc) {
  133. // if no textid in new route (e.g. edition front)
  134. // but we have toc
  135. // get the first item
  136. // will be replaced by front page of edition
  137. this.textid = this.toc[0].children[1].uuid
  138. } else {
  139. this.textid = null
  140. }
  141. },
  142. textid (newid, oldid) {
  143. console.log('textid watcher', this, oldid, newid)
  144. this.texts = []
  145. this.textsuuids = []
  146. this.pages = []
  147. this.pagesOtpions = []
  148. if (newid) {
  149. this.getTextContent(newid)
  150. }
  151. },
  152. textdata (newtxtdata, oldtxtdata) {
  153. console.log('textdata watcher', oldtxtdata, newtxtdata)
  154. this.metainfotitle = `${this.title} ${newtxtdata.meta.title}`
  155. },
  156. page_selected (newp, oldp) {
  157. console.log('page_selected watcher', oldp, newp)
  158. this.scrollToPage(newp)
  159. }
  160. },
  161. created () {
  162. // console.log('Edition this.$route.params.id', this.$route.params.id)
  163. this.editionid = this.$route.params.id
  164. // get the text if textid available
  165. if (this.$route.params.textid) {
  166. this.textid = this.$route.params.textid
  167. }
  168. // wait for editions list from Corpus Store if not already loaded
  169. if (!this.editionslist.length) {
  170. // this.getCorpuses()
  171. // subsribe to store to get the editionbyuuid list
  172. // https://dev.to/viniciuskneves/watch-for-vuex-state-changes-2mgj
  173. this.edUuuidsUnsubscribe = this.$store.subscribe((mutation, state) => {
  174. // console.log('Edition store subscribe', mutation.type)
  175. if (mutation.type === 'Corpus/setEditionsByUUID') {
  176. // console.log('Edition state.Coprus.editionsbyuuid', this.editionid, state.Corpus.editionsbyuuid)
  177. this.title = this.metainfotitle = state.Corpus.editionsbyuuid[this.editionid].title
  178. }
  179. if (mutation.type === 'Corpus/setTocs') {
  180. // console.log('Edition state.Coprus.editionsbyuuid', this.editionid, state.Corpus.editionsbyuuid)
  181. this.toc = state.Corpus.editionsbyuuid[this.editionid].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. if (!this.textid) { this.textid = this.toc[0].children[1].uuid }
  187. }
  188. if (mutation.type === 'Corpus/setPaginations') {
  189. // console.log('Edition state.Coprus.editionsbyuuid', this.editionid, state.Corpus.editionsbyuuid)
  190. this.pagination = state.Corpus.editionsbyuuid[this.editionid].pagination
  191. }
  192. })
  193. } else {
  194. this.title = this.metainfotitle = this.editionsbyuuid[this.editionid].title
  195. this.toc = this.editionsbyuuid[this.editionid].toc
  196. // if no textid in new route (e.g. edition front)
  197. // but we have toc
  198. // get the first item
  199. // will be replaced by front page of edition
  200. if (!this.textid) { this.textid = this.toc[0].children[1].uuid }
  201. this.pagination = this.editionsbyuuid[this.editionid].pagination
  202. }
  203. },
  204. methods: {
  205. ...mapActions({
  206. getCorpuses: 'Corpus/getCorpuses'
  207. }),
  208. getTextContent (textid, $state = null, direction = 'next') {
  209. console.log('getTextContent', textid)
  210. let params = {
  211. depth: 0
  212. }
  213. let q = qs.stringify(params)
  214. REST.get(`${window.apipath}/items/${textid}?${q}`, {})
  215. .then(({ data }) => {
  216. console.log('text REST: data', data)
  217. if (direction === 'next') {
  218. this.texts.push(data)
  219. this.textsuuids.push(data.content.uuid)
  220. } else {
  221. this.texts.unshift(data)
  222. this.textsuuids.unshift(data.content.uuid)
  223. }
  224. if ($state) {
  225. $state.loaded()
  226. this.next_loaded = true
  227. }
  228. })
  229. .catch((error) => {
  230. console.warn('Issue with getTextContent', error)
  231. Promise.reject(error)
  232. this.$router.replace({
  233. name: 'notfound',
  234. query: { fullpath: this.$route.path }
  235. })
  236. })
  237. },
  238. onCenterScrolled (e) {
  239. // console.log('Edition centerScrolled(e)', e.target.scrollTop)
  240. if (!this.center_scrolled && e.target.scrollTop > this.inifinite_load_distance * 1.5) {
  241. this.center_scrolled = true
  242. }
  243. this.indexitem = null
  244. },
  245. nextText ($state) {
  246. console.log('infinite loading nextText()', this.texts[this.texts.length - 1].content.itemAfterUuid, $state)
  247. if (this.texts[this.texts.length - 1].content.itemAfterUuid) {
  248. this.getTextContent(this.texts[this.texts.length - 1].content.itemAfterUuid, $state, 'next')
  249. } else {
  250. $state.complete()
  251. }
  252. },
  253. prevText ($state) {
  254. console.log('infinite loading prevText()', this.texts[0].content.itemBeforeUuid, $state)
  255. if (this.texts[0].content.itemBeforeUuid) {
  256. this.getTextContent(this.texts[0].content.itemBeforeUuid, $state, 'prev')
  257. } else {
  258. $state.complete()
  259. }
  260. },
  261. onHoverLink (elmt) {
  262. console.log('Edition onHoverLink(elmt)', elmt)
  263. this.tooltip_top = elmt.rect.top
  264. this.getIndexItem(elmt)
  265. },
  266. onLeaveLink () {
  267. console.log('Edition onLeaveLink()')
  268. this.indexitem = null
  269. },
  270. getIndexItem (item) {
  271. this.indexitem = 'loading'
  272. REST.get(`${window.apipath}/index${item.index.charAt(0).toUpperCase()}${item.index.slice(1)}/${item.uuid}`, {})
  273. .then(({ data }) => {
  274. console.log('index tooltip REST: data', data)
  275. if (this.indexitem === 'loading') {
  276. this.indexitem = data.content
  277. }
  278. })
  279. .catch((error) => {
  280. console.warn('Issue with index tooltip rest', error)
  281. Promise.reject(error)
  282. this.indexitem = null
  283. })
  284. },
  285. onClickTocItem (uuid) {
  286. console.log('Edition onClickTocItem', uuid, this.$refs)
  287. if (this.textsuuids.indexOf(uuid) !== -1) {
  288. // if already loaded, scroll to uuid
  289. this.reftoscrollto = `.tei[data-uuid="${uuid}"]`
  290. } else {
  291. // if not already loaded, change route
  292. this.$router.push({
  293. name: `editiontext`,
  294. params: {
  295. id: this.editionid,
  296. textid: uuid
  297. }
  298. })
  299. }
  300. },
  301. onClickPaginationItem (o) {
  302. console.log('onClickPaginationItem', o)
  303. if (this.textsuuids.indexOf(o.uuid) !== -1) {
  304. // if already loaded, scroll to uuid
  305. this.scrollToPage(o)
  306. } else {
  307. // if not already loaded, change route
  308. this.$router.push({
  309. name: `editiontext`,
  310. params: {
  311. id: this.editionid,
  312. textid: o.uuid
  313. }
  314. })
  315. }
  316. },
  317. scrollToPage (p) {
  318. // console.log('scrollToPage', p)
  319. this.reftoscrollto = `span[role="pageBreak"][id="${p.code}"]`
  320. }
  321. }
  322. }
  323. </script>
  324. <style lang="scss" scoped>
  325. </style>