NEXT craftinamerica.org. Base setup for headless wordpress https://www.craftinamerica.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

single.vue 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. <template lang="pug">
  2. .page--single.f-row.between(v-if="$route.params.slug")
  3. gallery(:fullscreengallery="fullscreengallery" v-on:close="fullscreengallery = -1" :images="images")
  4. article.f-grow.shadow
  5. header
  6. h1 {{ type }}:{{ $route.params.slug }} single
  7. section(v-if="posts[$route.params.slug]")
  8. h4 {{ posts[$route.params.slug].title }}
  9. .block-wrapper(v-for="block in posts[$route.params.slug].blocks" v-html="block")
  10. sidebar(v-if="sidebar" :type="`${type}`")
  11. .shadow
  12. h1.t-up single slot
  13. div
  14. p body whatever
  15. </template>
  16. <script>
  17. import { mapGetters } from 'vuex'
  18. import sidebar from '@/components/sidebars/sidebar'
  19. import gallery from '@/components/gallery/'
  20. export default {
  21. props: {
  22. sidebar: {
  23. type: Boolean
  24. }
  25. },
  26. components: {
  27. sidebar: sidebar,
  28. gallery: gallery
  29. },
  30. data() {
  31. return {
  32. images: [],
  33. fullscreengallery: -1
  34. }
  35. },
  36. computed: {
  37. ...mapGetters({
  38. allPages: 'allPages',
  39. allPagesLoaded: 'allPagesLoaded',
  40. allPosts: 'allPosts',
  41. allPostsLoaded: 'allPostsLoaded',
  42. allArtists: 'allArtists',
  43. allArtistsLoaded: 'allArtistsLoaded',
  44. allEpisodes: 'allEpisodes',
  45. allEpisodesLoaded: 'allEpisodesLoaded',
  46. }),
  47. type() { // Checks for type and fixes Episodes route edge case
  48. return this.$route.params.type ? this.$route.params.type : this.$route.fullPath.slice(1)
  49. },
  50. posts() {
  51. let type = this.type.charAt(0).toUpperCase() + this.type.slice(1)
  52. // Return list keyed by slug
  53. return Object.values(this[`all${type}`]).reduce((postsMap, post) => {
  54. postsMap[post.slug] = post
  55. return postsMap
  56. }, {})
  57. }
  58. },
  59. methods: {
  60. pageBlocks(posts) {
  61. return posts[this.$route.params.slug].blocks.map(block => {
  62. if(block) return block
  63. })
  64. },
  65. checkForImages(posts) {
  66. this.pageBlocks(posts).forEach(block => {
  67. if(!block) return
  68. const doc = new DOMParser().parseFromString(block, 'text/html')
  69. const gallery = doc.querySelectorAll('.blocks-gallery-item img')
  70. // add captions
  71. if(gallery.length) {
  72. this.images = [].slice.call(gallery).map(
  73. item => { return item.src }
  74. )
  75. }
  76. })
  77. }
  78. },
  79. watch: {
  80. posts(newVal, oldVal) {
  81. // Loads images from the DOM
  82. this.checkForImages(newVal)
  83. // Gottas be on the next render tick
  84. this.$nextTick(() => {
  85. let gallery
  86. this.pageBlocks(newVal).forEach(block => {
  87. if(!block) return
  88. gallery = document.querySelectorAll('.blocks-gallery-item figure')
  89. })
  90. if(gallery.length < 1) return
  91. gallery.forEach((item, i) => {
  92. item.addEventListener('mouseup', event => { this.fullscreengallery = i })
  93. })
  94. })
  95. }
  96. },
  97. created() {
  98. // TODO: Only makes req if this hasn't been loaded yet
  99. let type = this.$route.params.type
  100. type = type.charAt(0).toUpperCase() + type.slice(1)
  101. this.$store.dispatch(`getAll${type}`)
  102. }
  103. }
  104. </script>