Edition.vue 10 KB

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