NEXT craftinamerica.org. Base setup for headless wordpress https://www.craftinamerica.org
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. <template lang="pug">
  2. .page--list.f-row.between
  3. article.f-grow
  4. header.f-col.center.t-up
  5. .title.f-row
  6. h1 {{ type }} list
  7. span(v-if="sortBy")
  8. h1 &nbsp;sorted by {{ sortBy.replace('-', ' ') }}
  9. h3(v-if="!loaded") loading...
  10. .content(v-else-if="allPagesLoaded && type && allPages[type]" v-html="allPages[type].content")
  11. .posts(v-if="posts && loaded" :class="{ 'is-grid': grid }")
  12. section(v-for="post in posts" :key="post.slug").shadow.post
  13. header
  14. router-link(:to="`/${type}/${post.slug}`")
  15. featured-image(:post="post")
  16. h2.t-up {{ post.title }}
  17. article
  18. h4 {{ post.date }}
  19. p Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras eu elit in ex pharetra volutpat ac at magna. Duis libero est, imperdiet non sollicitudin vel, eleifend at ante...
  20. footer
  21. p {{ `${type} count: ${Object.values(posts).length}` }}
  22. p {{ `show sidebar: ${sidebar}` }}
  23. sidebar(v-if="sidebar" :type="`${type}`")
  24. .shadow
  25. h1.t-up slots stuff
  26. div
  27. p more body whatever
  28. p another line of stuff
  29. </template>
  30. <script>
  31. import featuredImage from '@/components/featured-image'
  32. import sidebar from '@/components/sidebars/sidebar'
  33. import { postTypeGetters, scrollTop } from './mixin-post-types'
  34. import { convertTitleCase, typeFromRoute, sortTypes } from '@/utils/helpers'
  35. export default {
  36. components: { sidebar, featuredImage },
  37. props: {
  38. sidebar: { type: Boolean },
  39. grid: { type: Boolean },
  40. sortBy: { type: String }
  41. },
  42. mixins: [postTypeGetters, scrollTop],
  43. computed: {
  44. type() { // Checks for type and fixes Episodes route edge case
  45. return typeFromRoute(this.$route)
  46. },
  47. dispatchName() {
  48. let type = convertTitleCase(this.type)
  49. return this.sortBy ? `getAll${type.split('/')[0]}` : `getAll${type}`
  50. },
  51. loaded() {
  52. let type = convertTitleCase(this.type)
  53. if(!type) return
  54. return this[`all${type}Loaded`]
  55. },
  56. posts() {
  57. let type = convertTitleCase(this.type)
  58. if(!type) return
  59. /**
  60. * We override the API to sort by date
  61. * because items are returned by ID so
  62. * we need to resort it by date
  63. */
  64. let unsortedOfType = Object.values(this[`all${type}`])
  65. let sortedByRecent = unsortedOfType.sort((postA, postB) => new Date(postB.date) - new Date(postA.date))
  66. /**
  67. * Sorting of this[`all${type}`] is also controlled by API
  68. * so if a sortBy is specified we return it sorted or
  69. * we fail over to sorted by date
  70. */
  71. return this.sortBy ? this[`all${type}`] : sortedByRecent
  72. },
  73. },
  74. methods: {
  75. getPosts() {
  76. // Sorting
  77. let sort = this.sortBy ? this.sortBy : this.$route.path.split('/').pop()
  78. if(Object.values(sortTypes).includes(sort)) {
  79. console.log('trying to sort by:', sort)
  80. console.log(`sortTypes includes ${sort}:`, Object.values(sortTypes).includes(sort))
  81. }
  82. // Is this a sort type?
  83. // !: BUG
  84. // if(this.type !== sort || !Object.values(sortTypes).includes(sort)) sort = null
  85. // Don't dispatch if there's no type
  86. if(this.type && this.dispatchName) {
  87. this.$store.dispatch(this.dispatchName, sort)
  88. }
  89. },
  90. async checkAndSetHero(type) {
  91. if(!this['allPagesLoaded']) {
  92. await this.$store.dispatch('getAllPages')
  93. }
  94. const page = this.allPages[type]
  95. if(!page) return
  96. let json = { url: page.featured, heroType: 'image' }
  97. if(page.hero && JSON.parse(page.hero) && JSON.parse(page.hero).url) {
  98. json = JSON.parse(page.hero)
  99. json.heroType = 'video'
  100. }
  101. this.$store.commit('SET_HERO', json)
  102. },
  103. },
  104. watch: {
  105. async $route(to, from){
  106. // console.log(this.sidebar)
  107. let type = convertTitleCase(this.type)
  108. let sort = this.sortBy ? this.sortBy : to.path.split('/').pop()
  109. this.checkAndSetHero(this.type)
  110. if(!this[`all${type}Loaded`] || sort) this.getPosts()
  111. }
  112. },
  113. created() {
  114. let type = convertTitleCase(this.type)
  115. console.log(`${type} already loaded?:`, this[`all${type}Loaded`])
  116. this.checkAndSetHero(this.type)
  117. console.log(this.$store)
  118. if(!this[`all${type}Loaded`]) this.getPosts()
  119. }
  120. }
  121. </script>
  122. <style lang="postcss">
  123. .page--list
  124. article
  125. > header
  126. padding: 1em 0 1em 0
  127. > h1
  128. margin: 0
  129. > .content
  130. padding: 0
  131. width: 100%
  132. /* posts not grid list */
  133. ul
  134. img
  135. max-width: 50%
  136. li
  137. .is-grid
  138. display: flex
  139. flex-direction: row
  140. flex-wrap: wrap
  141. section
  142. width: 33%
  143. ul
  144. flex-wrap: wrap
  145. list-style: none
  146. img
  147. max-width: 100%
  148. </style>