| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- <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
- 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 } from './mixin-post-types'
-
- import { convertTitleCase, typeFromRoute, sortTypes } from '@/utils/helpers'
-
- const TIMEOUT = 1
-
- export default {
- components: { sidebar, featuredImage, card },
- props: {
- sidebar: { type: Boolean },
- grid: { type: Boolean },
- sortBy: { type: String },
- },
- mixins: [postTypeGetters, scrollTop],
- data() {
- return {
- page: 1,
- perPage: 9
- }
- },
- computed: {
- type() {
- // Checks for type and fixes Episodes route edge case
- return typeFromRoute(this.$route)
- },
- dispatchName() {
- let type = convertTitleCase(this.type) + 's'
- return this.sortBy ? `getAll${type.split('/')[0]}` : `getAll${type}`
- },
- getMoreName() {
- let type = convertTitleCase(this.type) + 's'
- return this.sortBy ? `getMore${type.split('/')[0]}` : `getMore${type}`
- },
- loaded() {
- let type = convertTitleCase(this.type) + 's'
- if (!type) return
- return this[`all${type}Loaded`]
- },
- posts() {
- let type = convertTitleCase(this.type) + 's'
- if (!type) return
- return this[`all${type}`]
- },
- },
- methods: {
- loadMorePosts() {
- // console.log('loading...')
- this.page++
- this.getPosts(false)
- },
- getPosts(clear) {
- // Limit
- let params = {
- limit: this.perPage,
- page: this.page
- }
- // Sorting
- let sort = this.sortBy
- ? this.sortBy
- : this.$route.path
- .split('/')
- .filter(p => p)
- .pop()
-
- // console.log('Gettings posts:', this.type)
- // if (!Object.values(sortTypes).includes(sort)) {
- // console.log('Sort not found:', sort)
- // sort = null
- // }
-
- // Don't dispatch if there's no type
- if (this.type && this.dispatchName && clear) {
- this.$store.dispatch(
- this.dispatchName,
- { sortType: sort, params }
- )
-
- if (this.type == 'event') {
- this.$store.dispatch(
- 'getAllExhibitions',
- {
- sortType: sortTypes.currentAndUpcoming,
- params
- }
- )
- }
- if (this.type == 'exhibition') {
- this.$store.dispatch(
- 'getAllEvents',
- {
- sortType: sortTypes.currentAndUpcoming,
- params
- }
- )
- }
- // Add to existing
- } else if (!clear) {
- this.$store.dispatch(
- this.getMoreName,
- { sortType: sort, params }
- )
- }
- },
- async checkAndSetHero(type) {
- if (!this['allPagesLoaded']) {
- await this.$store.dispatch('getAllPages', { sortType: null, params: null })
- }
-
- // We always set a hero no matter what
- // Because the hero component will deal
- // with how to render based on hero.url
- const page = this.allPages.filter(
- page => page.slug == type + 's',
- )[0]
-
- let hero = { url: null, heroType: null }
-
- // Clear the hero and bail
- if(!page) return this.$store.commit('SET_HERO', hero)
-
- console.log('setting hero:', page)
- hero.url = page.featured
- hero.heroType = 'image'
- if (
- page.hero &&
- JSON.parse(page.hero) &&
- JSON.parse(page.hero).url
- ) {
- hero = JSON.parse(page.hero)
- hero.heroType = 'video'
- }
- // No featured or youTube
- if (!hero.url) {
- hero.heroType = null
- }
- // Set the hero text to the post title or excerpt
- hero.text = page && page.excerpt ? page.excerpt : page.title
- this.$store.commit('SET_HERO', hero)
- },
- scrollTo(hashtag) {
- setTimeout(() => {
- location.href = hashtag
- }, TIMEOUT)
- },
- setIntersectionLoader() {
- window.removeEventListener("load", e => {}, false)
- window.addEventListener("load", e => {
- const footerEl = document.querySelector(".footer-wrapper footer")
- const observer = new IntersectionObserver(this.loadMorePosts, {
- rootMargin: "0px 0px 20px 0px",
- })
- observer.observe(footerEl)
- }, false)
- }
- },
- watch: {
- $route(to, from) {
- this.checkAndSetHero(this.type)
-
- let sort = to.path
- .split('/')
- .filter(p => p)
- .pop()
-
- if (!Object.values(sortTypes).includes(sort)) {
- // console.warn('sort not found:', sort)
- sort = null
- }
-
- // TODO: Track last loaded page per post type
- // Less http calls
- this.page = 1
- this.setIntersectionLoader()
-
- this.getPosts(true)
- },
- },
- mounted() {
- if (this.$route.hash) {
- setTimeout(() => this.scrollTo(this.$route.hash), TIMEOUT)
- }
- this.setIntersectionLoader()
- },
- created() {
- let type = convertTitleCase(this.type) + 's'
- this.checkAndSetHero(this.type)
-
- // We also need to check if only ONE has been loaded because
- // coming from the homepage there will only be 1 item
- if (!this[`all${type}Loaded`] || this[`all${type}`].length < 2) this.getPosts(true)
- },
- }
- </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%
- /* posts not grid list */
- ul
- img
- max-width: 50%
-
- .is-grid
- display: flex
- flex-direction: row
- flex-wrap: wrap
- justify-content: space-between
- /* extra padding required? */
- /* padding: $ms-0 */
- /* background-color: white */
- section
- width: 32.5%
- /* 4 column grid see how dense this becomes */
- /* width: 24% */
- ul
- flex-wrap: wrap
- list-style: none
- img
- max-width: 100%
- @media (min-width: $medium)
- .page--list.f-col
- flex-direction: row
- </style>
|