Skip to content

Instantly share code, notes, and snippets.

@mrkmiller
Last active May 11, 2023 00:41
Show Gist options
  • Select an option

  • Save mrkmiller/11193874120d26d9b3885addc27d03ad to your computer and use it in GitHub Desktop.

Select an option

Save mrkmiller/11193874120d26d9b3885addc27d03ad to your computer and use it in GitHub Desktop.
import {LitElement, html} from 'https://cdn.jsdelivr.net/gh/lit/dist@2/core/lit-core.min.js'
import jsonapiParse from 'https://cdn.jsdelivr.net/npm/jsonapi-parse@2.0.1/+esm'
import dayjs from 'https://cdn.jsdelivr.net/npm/dayjs@1.11.7/+esm'
class SFEventListing extends LitElement {
static properties = {
baseUrl: {type: String},
url: {type: String},
imageUrl: {type: String},
imageAlt: {type: String},
title: {type: String},
startDate: {type: String},
endDate: {type: String},
location: {type: String},
}
// Remove the Shadow Dom since we need the style to cascade from the main page.
createRenderRoot() {
return this;
}
render() {
const url = this.baseUrl + this.url
const getThumbnail = () => {
if (this.imageUrl) {
return html`
<div class="vm-teaser__figure">
<a href="${url}">
<img src="${this.baseUrl}${this.imageUrl}" alt="${this.imageAlt}" />
</a>
</div>
`;
}
}
return html`
<div class="vm-listing">
${getThumbnail()}
<div class="vm-listing__body">
<h3 class="vm-listing__title"><a href="${url}">${this.title}</a></h3>
<div class="vm-listing__submitted">
${dayjs(this.startDate).format('MMM-D')}-${dayjs(this.endDate).format('D')}, ${dayjs(this.startDate).format('YYYY')}
</div>
<div class="icon icon--location">${this.location}</div>
</div>
</div>
`;
}
}
customElements.define('sf-event-listing', SFEventListing)
class SFEventTeaser extends LitElement {
static properties = {
baseUrl: {type: String},
url: {type: String},
imageUrl: {type: String},
imageAlt: {type: String},
title: {type: String},
summary: {type: String},
startDate: {type: String},
endDate: {type: String},
mapUrl: {type: String},
mapTitle: {type: String},
location: {type: String},
}
// Remove the Shadow Dom since we need the style to cascade from the main page.
createRenderRoot() {
return this;
}
render() {
const url = this.baseUrl + this.url
const getThumbnail = () => {
if (this.imageUrl) {
return html`
<div class="vm-teaser__figure category">
<a href="${url}">
<img src="${this.baseUrl}${this.imageUrl}" alt="${this.imageAlt}" />
</a>
</div>
`;
}
}
return html`
<article class="vm-teaser">
${getThumbnail()}
<div class="vm-teaser__body">
<h3 class="vm-teaser__title"><a href="${url}">${this.title}</a></h3>
<div class="vm-teaser__summary">${this.summary}</div>
<ul class="vm-teaser__contact list--pipe text--smaller">
<li>
<a class="icon icon--link icon--calendar" href="${url}">
${dayjs(this.startDate).format('MMM-D')}-${dayjs(this.endDate).format('D')}, ${dayjs(this.startDate).format('YYYY')} <span class="date-separator">@</span> <span class="date-time">
${dayjs(this.startDate).format('h:mma')}-${dayjs(this.endDate).format('h:mma')}
</span>
</a>
</li>
<li>
<a class="icon icon--link icon--map" href="${this.mapUrl}">${this.mapTitle}</a>
</li>
<li>
<div class="icon icon--location">${this.location}</div>
</li>
<li>
<a class="icon icon--link icon--view-more" href="${url}">Event Details</a>
</li>
</ul>
</div>
</article>
`;
}
}
customElements.define('sf-event-teaser', SFEventTeaser)
class SFEvents extends LitElement {
static properties = {
events: {},
baseUrl: {type: String},
display: {type: String},
}
constructor() {
super()
this.events = []
this.baseUrl = window.location.origin
this.display = 'teaser'
}
connectedCallback() {
super.connectedCallback()
this.getEvents()
}
// Remove the Shadow Dom since we need the style to cascade from the main page.
createRenderRoot() {
return this;
}
async getEvents() {
const today = dayjs().add(-1, 'day').toISOString()
const response = await fetch(`${this.baseUrl}/jsonapi/node/sf_event?include=field_sf_m_primary_media,field_sf_m_primary_media.field_media_image&filter[status][value]=1&sort=field_sf_dates.value&filter[datefilter][condition][path]=field_sf_dates.value&filter[datefilter][condition][path]=field_sf_dates.value&filter[datefilter][condition][operator]=%3E&filter[datefilter][condition][value]=${today}`)
const jsonData = await response.json()
this.events = jsonapiParse.parse(jsonData).data
}
render() {
const eventsMarkup = []
this.events.forEach((event) => {
const url = this.baseUrl + event.path.alias
if (this.display === 'listing') {
eventsMarkup.push(html`
<sf-event-listing
baseurl="${this.baseUrl}"
url="${event.path?.alias}"
imageUrl="${event.field_sf_m_primary_media?.field_media_image.uri.url}"
imageAlt="${event.field_sf_m_primary_media?.field_media_image.meta?.alt}"
title="${event.title}"
startDate="${event.field_sf_dates?.value}"
endDate="${event.field_sf_dates?.end_value}"
location="${event.field_sf_event_location}"
></sf-event-listing>
`);
}
else {
eventsMarkup.push(html`
<sf-event-teaser
baseurl="${this.baseUrl}"
url="${event.path?.alias}"
imageUrl="${event.field_sf_m_primary_media?.field_media_image.uri.url}"
imageAlt="${event.field_sf_m_primary_media?.field_media_image.meta?.alt}"
title="${event.title}"
summary="${event.body?.value.replace(/(<([^>]+)>)/gi, "").substring(0, 200)}..."
startDate="${event.field_sf_dates?.value}"
endDate="${event.field_sf_dates?.end_value}"
mapUrl="${event.field_sf_event_map_link?.uri}"
mapTitle="${event.field_sf_event_map_link?.title}"
location="${event.field_sf_event_location}"
></sf-event-teaser>
`);
}
});
if (eventsMarkup.length === 0) {
eventsMarkup.push(html`Loading Events...`);
}
return html`
<style>
:is(sf-event-teaser, sf-event-listing) {
display: block;
}
sf-event-teaser + sf-event-teaser {
margin-top: 1.5rem;
}
:is(sf-event-teaser, sf-event-listing) .vm-teaser__figure img {
aspect-ratio: 1;
width: 135px;
object-fit: cover;
}
</style>
${eventsMarkup}
`;
}
}
customElements.define('sf-events', SFEvents)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment