Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: APPS-2955 remaining components #43

Merged
merged 13 commits into from
Oct 2, 2024
8 changes: 8 additions & 0 deletions cypress/e2e/blogArticlePage.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
describe('Blog Article Page', () => {
it('Visits a Blog Article Page', () => {
cy.visit('/blog/test-tom-reeds-for-members-only-black-perspectives-on-local-l-a-tv')
cy.getByData('breadcrumb').should('be.visible')
cy.getByData('recent-posts').should('be.visible')
cy.percySnapshot('blogarticlepage', { widths: [768, 992, 1200] })
})
})
3 changes: 2 additions & 1 deletion gql/queries/FTVAArticleDetail.gql
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ query FTVAArticleDetail($slug: [String!]) {
...AllFtvaFpb
}
# SectionTeaserCard (Recent posts)
ftvaRecentPosts: entries( section: "ftvaArticle", limit: 3, orderBy: "postDate ASC") {
# page only displays 3 but we query 4 in case the list includes the current article
ftvaRecentPosts: entries( section: "ftvaArticle", limit: 4, orderBy: "postDate ASC") {
id
title
to: slug
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@
"nuxt-graphql-request": "^7.0.5",
"sass": "^1.66.1",
"ucla-library-design-tokens": "^5.22.0",
"ucla-library-website-components": "3.22.1"
"ucla-library-website-components": "3.23.0"
}
}
}
272 changes: 137 additions & 135 deletions pages/blog/[slug].vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
// COMPONENT RE-IMPORTS
// TODO: remove when we have implemented component library as a module
// https://nuxt.com/docs/guide/directory-structure/components#library-authors
import { BlockTag, CardMeta, DividerWayFinder, FlexibleMediaGalleryNewLightbox, FlexibleBlocks, NavBreadcrumb, ResponsiveImage, RichText, SectionTeaserCard, SectionWrapper } from 'ucla-library-website-components'
import {
BlockTag, ButtonDropdown, CardMeta, DividerWayFinder, FlexibleMediaGalleryNewLightbox, FlexibleBlocks, NavBreadcrumb, ResponsiveImage, RichText, SectionTeaserCard, SectionWrapper, TwoColLayoutWStickySideBar
} from 'ucla-library-website-components'

// HELPERS
import _get from 'lodash/get'
Expand All @@ -14,6 +16,34 @@ const { $graphql } = useNuxtApp()

const route = useRoute()

// TODO should this data be changed to reflect current page URL? Moved somewhere else?
farosFreed marked this conversation as resolved.
Show resolved Hide resolved
const socialList = {
buttonTitle: 'Share',
hasIcon: true,
dropdownList: [
{
dropdownItemTitle: 'Copy Link',
dropdownItemUrl: '',
iconName: 'svg-icon-ftva-social-link',
},
{
dropdownItemTitle: 'Email',
dropdownItemUrl: '',
iconName: 'svg-icon-ftva-social-email',
},
{
dropdownItemTitle: 'Facebook',
dropdownItemUrl: 'https://www.facebook.com/sharer/sharer.php?u=',
iconName: 'svg-icon-ftva-social-facebook',
},
{
dropdownItemTitle: 'X',
dropdownItemUrl: 'https://twitter.com/share?url=',
iconName: 'svg-icon-ftva-social-x',
},
],
}

// DATA
const { data, error } = await useAsyncData(`blog-${route.params.slug}`, async () => {
const data = await $graphql.default.request(FTVAArticleDetail, { slug: route.params.slug })
Expand All @@ -37,7 +67,7 @@ const page = ref(_get(data.value, 'ftvaArticle', {}))
const ftvaRecentPosts = ref(_get(data.value, 'ftvaRecentPosts', {}))

watch(data, (newVal, oldVal) => {
console.log('In watch preview enabled, newVal, oldVal', newVal, oldVal)
// console.log('In watch preview enabled, newVal, oldVal', newVal, oldVal)
page.value = _get(newVal, 'ftvaArticle', {})
ftvaRecentPosts.value = _get(newVal, 'ftvaRecentPosts', {})
})
Expand All @@ -55,21 +85,42 @@ const parsedCarouselData = computed(() => {
return {
item: [{ ...rawItem.image[0], kind: 'image' }], // Carousels on this page are always images, no videos
credit: rawItem?.creditText,
captionTitle: 'dfdsfs', // TODO do we need these? test without
captionText: 'dfsdfsd',
// captionTitle: 'dfdsfs', // TODO do we need these? test without
farosFreed marked this conversation as resolved.
Show resolved Hide resolved
// captionText: 'dfsdfsd',
}
})
})

// Combine the categories into a String
const parsedArticleCategories = computed(() => {
const categoryList = page.value.articleCategories
const categories = []
if (page.value.articleCategories) {
return page.value.articleCategories.map(category => category.title).join(', ')
}
return ''
})

for (const category of categoryList) {
categories.push(category.title)
// Get the Contributor data if it exists, otherwise return nothing
const parsedByline = computed(() => {
if ((page.value.contributors && page.value.contributors[0]) && page.value.contributors[0].contributor) {
return page.value.contributors[0].contributor
}
return categories.join(', ')
return ''
})

// Recent Posts: Filter out the current post and then return the first 3 max
const parsedRecentPosts = computed(() => {
// fail gracefully if no recent posts
if (!ftvaRecentPosts.value || !route.params.slug)
return []

// Transform data
const recentPostsWImage = ftvaRecentPosts.value.map((item, index) => {
return {
...item,
image: item.imageCarousel && item.imageCarousel.length > 0 ? item.imageCarousel[0].image[0] : null,
}
})
return recentPostsWImage.filter(item => !item.to.includes(route.params.slug)).slice(0, 3)
})
</script>

Expand Down Expand Up @@ -117,66 +168,54 @@ const parsedArticleCategories = computed(() => {
</div>
</div>

<div
data-test="second-column"
class="two-column"
<TwoColLayoutWStickySideBar>
<template #primaryTop>
<CardMeta
data-test="text-block"
:category="parsedArticleCategories"
:title="page?.title"
:byline-one="parsedByline"
:date-created="page?.postDate"
:text="page?.aboutTheAuthor"
farosFreed marked this conversation as resolved.
Show resolved Hide resolved
section-handle="ftvaArticle"
>
<template #sharebutton>
<ButtonDropdown
button-title="Share"
:has-icon="true"
:dropdown-list="socialList.dropdownList"
/>
</template>
</CardMeta>
<DividerWayFinder class="remove-top-margin" />
<FlexibleBlocks
class="flexible-content"
:blocks="page.blocks"
/>
</template>
<template #sidebarTop />
</TwoColLayoutWStickySideBar>

<SectionWrapper
v-if="parsedRecentPosts && parsedRecentPosts.length > 0"
section-title="Read our most recent posts"
theme="paleblue"
>
<div class="primary-column top">
<SectionWrapper>
<CardMeta
data-test="text-block"
:title="page?.title"
:category="parsedArticleCategories"
/>

<!-- About the Author -->
<RichText
v-if="page?.aboutTheAuthor"
data-test="aboutTheAuthor"
class="acknowledgements"
:rich-text-content="page?.aboutTheAuthor"
/>
</SectionWrapper>
</div>
</div>

<SectionWrapper>
<DividerWayFinder />
</SectionWrapper>

<FlexibleBlocks
class="flexible-content"
:blocks="page.blocks"
/>

<SectionWrapper section-title="Read our most recent posts">
<h2>ftvaRecentPosts</h2>
<pre>{{ ftvaRecentPosts }}</pre>
<template #top-right>
<nuxt-link to="/series">
View All Series <span style="font-size:1.5em;"> &#8250;</span>
</nuxt-link>
</template>
<SectionTeaserCard
v-if="parsedRecentPosts && parsedRecentPosts.length > 0"
data-test="recent-posts"
:items="parsedRecentPosts"
/>
</SectionWrapper>
<!-- <SectionWrapper
v-if="parsedFtvaEventSeries && parsedFtvaEventSeries.length > 0"
section-title="Upcoming events in this series"
theme="paleblue"
>
<template #top-right>
<nuxt-link to="/series">
View All Series <span style="font-size:1.5em;"> &#8250;</span>
</nuxt-link>
</template>

<SectionTeaserCard
v-if="parsedFtvaEventSeries && parsedFtvaEventSeries.length > 0"
data-test="event-series"
:items="parsedFtvaEventSeries"
/>
</SectionWrapper> -->
</main>
</template>

<style
lang="scss"
scoped
>
<style lang="scss" scoped>
// PAGE STYLES
.page-article-detail {
position: relative;
Expand All @@ -202,62 +241,38 @@ const parsedArticleCategories = computed(() => {
}
}

.two-column {
position: relative;
width: 100%;
max-width: var(--max-width);
display: flex;
flex-direction: row;
flex-wrap: wrap;
// makes all EventSeries same height
:deep(.card) {
min-height: 350px;
}

:deep(.two-column) {

// specs say 832px for column @ 1440px screen
// 78% is close but not exact while being responsive
.primary-column {
margin-bottom: 0px;
width: 67%;
width: 78%; // override default 67% for article pages only

.section-wrapper {
.primary-section-wrapper {
padding-left: 0px;
margin-top: var(--space-2xl);
}

&.bottom {
margin-top: -30px;
.section-wrapper {
margin-top: var(--space-2xl);
}
}

.ftva.button-dropdown {
margin-top: 30px;
}

.ftva.block-info {
margin-top: 48px;
}

// SECTION SCREENING DETAILS
// TODO when component is patched, remove styles?
:deep(figure.responsive-video:not(:has(.video-embed))) {
display: none;
}

.sidebar-column {
min-width: 314px;
width: 30%;
position: absolute;
height: 100%;
top: 0;
right: 0;
padding-top: var(--space-2xl);
padding-bottom: 20px;

.sidebar-content-wrapper {
position: sticky;
top: 85px;
will-change: top;
.remove-top-margin {
margin-top: 0px;
padding-top: var(--space-l);
}

}
}

/* makes all EventSeries same height */
:deep(.card) {
min-height: 350px;
// if there is no author content, hide the 'about the author' heading
:deep(.heading-about-author:not(:has(+.rich-text))) {
display: none;
}

@media (max-width: 1200px) {
Expand All @@ -268,40 +283,27 @@ const parsedArticleCategories = computed(() => {
padding-right: var(--unit-gutter);
}

.sidebar-column {
padding-right: var(--unit-gutter);
}
:deep(.two-column) {
display: flex;

.two-column>.primary-column {
width: 62%;
// increase column percentage to 100 at 1200px
// only for article pages, since there is no sidebar content
.primary-column {
width: 100%;

.primary-section-wrapper {
padding-right: 0px;
}
}
}
}

@media #{$small} {
.two-column {
display: grid;
grid-template-columns: 1fr;

.primary-column {
width: auto;
grid-column: 1;

.section-wrapper {
padding-left: var(--unit-gutter);
}

&.bottom {
margin-top: auto;
}
}
display: flex;

.sidebar-column {
width: auto;
position: relative;
grid-column: 1;
margin: auto var(--unit-gutter);
padding-top: 0px;
height: auto; // let content determine height on mobile
.remove-top-margin {
margin-top: var(--space-2xl); //re add space as padding for mobile
}
}
}
Expand Down
Loading
Loading