| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- <template lang="pug">
- .page--list.f-col.between
- article.f-grow
-
- header.center.t-up
- .title.f-row
- h3 {{ type }} list
- span(v-if="sortBy")
- h3 sorted {{ sortBy.replace('-', ' ') }}
-
- h3(v-if="!loaded") loading...
- .content(
- v-else-if="allPagesLoaded && type && allPages[type]"
- v-html="allPages[type].content"
- )
-
- .posts(v-if="posts && loaded" :class="{ 'is-grid': grid }")
- section(v-for="(post, i) in posts" :key="post.slug").shadow.post
- card(:content="post" :type="type" :wide="type == 'exhibition' && i > 1 || type == 'event' && i > 1 ")
-
- footer(v-if="loadingFetched || showMeta")
- p(v-if="loadingFetched") loading more {{ type }} ...
- p {{ `${type} count: ${Object.values(posts).length}` }}
- p {{ `show sidebar: ${sidebar}` }}
-
- sidebar(v-if="sidebar" :type="`${type}`" layout="list")
- </template>
-
- <script>
- import featuredImage from '@/components/featured-image'
- import card from '@/components/card'
- import sidebar from '@/components/sidebars/sidebar'
- import { postTypeGetters, scrollTop, heroUtils } from './mixin-post-types'
-
- import { postTypes, convertTitleCase, typeFromRoute } from '@/utils/helpers'
-
- const TIMEOUT = 1
- const INTERSECT_SELECTION = ".page--list > article footer"
- export default {
- components: { sidebar, featuredImage, card },
- props: {
- sidebar: { type: Boolean },
- grid: { type: Boolean },
- sortBy: { type: String },
- },
- mixins: [postTypeGetters, scrollTop, heroUtils],
- data() {
- return {
- showMeta: false,
- page: 0,
- perPage: 21,
- keepFetching: true,
- loadingFetched: false,
- observer: null
- }
- },
- computed: {
- type() {
- // Checks for type and fixes Episodes route edge case
- return typeFromRoute(this.$route)
- },
- pType() {
- if(!typeFromRoute(this.$route)) return
- return this.sortBy ? `${convertTitleCase(typeFromRoute(this.$route).split('/')[0])}s` : `${convertTitleCase(this.type)}s`
- },
- loaded() {
- if (!this.pType) return
- return this[`all${this.pType}Loaded`]
- },
- posts() {
- if (!this.pType) return
- return this[`all${this.pType}`]
- },
- },
- methods: {
- clearAllPosts() {
- const uppercaseType = this.type.toUpperCase() + 'S'
- this.$store.commit(`CLEAR_${uppercaseType}`)
- this.$store.commit(`${uppercaseType}_LOADED`)
- },
- async loadMorePosts() {
- // console.log('trying to load for: ', this.$route)
- const type = typeFromRoute(this.$route)
- if(!type) return console.error(`type: ${type} not found...`)
- if(!this.keepFetching) return console.warn('nothing left to fetch...')
-
- this.loadingFetched = true
- this.page++
- console.warn(`loading page ${this.page} of ${type} posts: ${this.page * this.perPage + 1} through ${this.page * this.perPage}`)
- await this.getPosts()
- },
- _getSortBy() {
- return this.sortBy
- ? this.sortBy
- : this.$route.path
- .split('/')
- .filter(p => p)
- .pop()
- },
- _getDispatchParams() {
- return {
- sortType: this._getSortBy(),
- params: {
- limit: this.perPage,
- page: this.page
- }
- }
- },
- async getPosts() {
- // Edge case for episodes
- await this._getAll('episode', this.$store)
-
- const dispatchAction = `getMore${this.pType}`
- let res = null
- if(this.pType && dispatchAction != `getMoreEpisodes`) {
- res = await this.$store.dispatch(
- dispatchAction,
- this._getDispatchParams()
- )
- }
-
- // Stop trying to load more posts
- if(res && !res.length) {
- console.warn('did not receive response...', res, this.type)
- this.keepFetching = false
- }
- this.loadingFetched = false
- },
- // _setHeroInfo(post) {} from mixin
- // _clearHero(store) {} from mixin
- async checkAndSetHero(type) {
- this._clearHero(this.$store)
-
- await this._getAll('page', this.$store)
-
- // We always set a hero no matter what
- // Because the hero component will deal
- // with how to render based on hero.url
- if(!this.allPages) return console.log('no pages in state', this)
- const page = this.allPages.filter(
- page => page.slug == type + 's',
- )[0]
- if(!page) return console.warn(`no page for ${type} found`)
-
- this.$store.commit('SET_HERO', this._setHeroInfo(page))
- },
- setIntersectionLoader() {
- if(!this.type) return console.error('cannot setup intersection handler for undefined type')
- if(this.type == 'episode') return console.warn('intersection handler not setup for episode')
-
- // console.warn('setting up intersection handler for:', this.type)
- const footerEl = document.querySelector(INTERSECT_SELECTION)
- if(!footerEl) return
-
- const onIntersect = entries => {
- // console.log('intersection handler fired...')
- entries.forEach(entry => {
- if (!entry.isIntersecting || this.loadingFetched) return
- setTimeout(() => {
- this.loadMorePosts()
- }, TIMEOUT)
- })
- }
- this.observer = new IntersectionObserver(onIntersect, {
- threshold: 0.80
- })
- this.observer['_for_type'] = this.type
- this.observer.observe(footerEl)
- },
- unsetIntersectionLoader() {
- const footerEl = document.querySelector(INTERSECT_SELECTION)
- if(!footerEl) return
-
- console.warn('unsetting intersection handler on:', footerEl)
- this.observer.unobserve(footerEl)
- this.observer.disconnect()
- },
- clearAndInitPostList() {
- this.page = 0
- this.keepFetching = true
-
- // Fires when loading from home
- // Clear any preloaded posts (from home, etc.)
- this.clearAllPosts()
- this.loadMorePosts()
- }
- },
- watch: {
- // This only fires navigating from
- // a list page, to another list page
- type(newType, oldType){
- if(!postTypes.includes(newType)) return console.warn('type not found...')
- this.clearAndInitPostList()
- this.setIntersectionLoader()
- },
- },
- mounted() {
- this.clearAndInitPostList()
- this.setIntersectionLoader()
- },
- beforeDestroy() {
- this.unsetIntersectionLoader()
- }
- }
- </script>
-
- <style lang="postcss">
- // prettier-ignore
- @import '../sss/variables.sss'
- @import '../sss/theme.sss'
- .page--list
- /* background-color: white */
- article
- > header
- /* padding: 1em 0 1em 0 */
- padding: 1em
- > h1
- margin: 0
- > .content
- padding: 0
- width: 100%
- > footer
- background-color: white
- padding: $ms-0
- /* posts not grid list */
- ul img
- max-width: 50%
-
- .is-grid
- display: flex
- flex-direction: row
- flex-wrap: wrap
- justify-content: space-between
- section
- width: 32.5%
- ul
- flex-wrap: wrap
- list-style: none
- img
- max-width: 100%
-
- @media (min-width: $medium)
- .page--list.f-col
- flex-direction: row
- </style>
|