chore: post + formatting
This commit is contained in:
parent
65e257e708
commit
8cd5071c65
2 changed files with 140 additions and 97 deletions
|
@ -39,31 +39,31 @@ Next, in a basic declaration for the edge function `(export default async (reque
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const ACCOUNT_ID_PLEX = Netlify.env.get('ACCOUNT_ID_PLEX');
|
const ACCOUNT_ID_PLEX = Netlify.env.get('ACCOUNT_ID_PLEX');
|
||||||
const MUSIC_KEY = Netlify.env.get('API_KEY_LASTFM');
|
const MUSIC_KEY = Netlify.env.get('API_KEY_LASTFM');
|
||||||
const params = new URL(request['url']).searchParams
|
const params = new URL(request['url']).searchParams
|
||||||
const id = params.get('id')
|
const id = params.get('id')
|
||||||
|
|
||||||
if (!id) return new Response(JSON.stringify({
|
if (!id) return new Response(JSON.stringify({
|
||||||
status: 'Bad request',
|
status: 'Bad request',
|
||||||
}),
|
}),
|
||||||
{ headers: { "Content-Type": "application/json" } }
|
{ headers: { "Content-Type": "application/json" } }
|
||||||
)
|
)
|
||||||
|
|
||||||
if (id !== ACCOUNT_ID_PLEX) return new Response(JSON.stringify({
|
if (id !== ACCOUNT_ID_PLEX) return new Response(JSON.stringify({
|
||||||
status: 'Forbidden',
|
status: 'Forbidden',
|
||||||
}),
|
}),
|
||||||
{ headers: { "Content-Type": "application/json" } }
|
{ headers: { "Content-Type": "application/json" } }
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
Moving on, we handle the webhook form data and set up our blob store variables:
|
Moving on, we handle the webhook form data and set up our blob store variables:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const data = await request.formData()
|
const data = await request.formData()
|
||||||
const payload = JSON.parse(data.get('payload'))
|
const payload = JSON.parse(data.get('payload'))
|
||||||
const artists = getStore('artists')
|
const artists = getStore('artists')
|
||||||
const albums = getStore('albums')
|
const albums = getStore('albums')
|
||||||
const scrobbles = getStore('scrobbles')
|
const scrobbles = getStore('scrobbles')
|
||||||
```
|
```
|
||||||
|
|
||||||
If the event sent from Plex is of the type `media.scrobble` we need to handle it:
|
If the event sent from Plex is of the type `media.scrobble` we need to handle it:
|
||||||
|
@ -89,7 +89,7 @@ If we don't yet have metadata cached for an artist or an album, we use the Last.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// if there is no artist blob, populate one
|
// if there is no artist blob, populate one
|
||||||
if (!artistsMap[artistSanitizedKey]) {
|
if (!artistsMap[artistSanitizedKey]) {
|
||||||
const artistRes = await fetch(
|
const artistRes = await fetch(
|
||||||
`https://ws.audioscrobbler.com/2.0/?method=artist.getInfo&api_key=${MUSIC_KEY}&artist=${sanitizeMediaString(artist).replace(/\s+/g, '+').toLowerCase()}&format=json`,
|
`https://ws.audioscrobbler.com/2.0/?method=artist.getInfo&api_key=${MUSIC_KEY}&artist=${sanitizeMediaString(artist).replace(/\s+/g, '+').toLowerCase()}&format=json`,
|
||||||
{
|
{
|
||||||
|
@ -137,33 +137,33 @@ If we don't yet have metadata cached for an artist or an album, we use the Last.
|
||||||
artistInfo = artistObj
|
artistInfo = artistObj
|
||||||
artistsMap[artistSanitizedKey] = artistObj
|
artistsMap[artistSanitizedKey] = artistObj
|
||||||
await artists.setJSON('artists-map', artistsMap)
|
await artists.setJSON('artists-map', artistsMap)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
This will be skipped on subsequent plays for the artist as we'll already have the information we need. Finally, we store our data:
|
This will be skipped on subsequent plays for the artist as we'll already have the information we need. Finally, we store our data:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// scrobble logic
|
// scrobble logic
|
||||||
const trackScrobbleData = {
|
const trackScrobbleData = {
|
||||||
track,
|
track,
|
||||||
album,
|
album,
|
||||||
artist,
|
artist,
|
||||||
trackNumber,
|
trackNumber,
|
||||||
timestamp,
|
timestamp,
|
||||||
genre: artistInfo?.['genre'] || ''
|
genre: artistInfo?.['genre'] || ''
|
||||||
}
|
}
|
||||||
const scrobbleData = await scrobbles.get(`${weekKey()}`, { type: 'json'})
|
const scrobbleData = await scrobbles.get(`${weekKey()}`, { type: 'json'})
|
||||||
const windowData = await scrobbles.get('window', { type: 'json'})
|
const windowData = await scrobbles.get('window', { type: 'json'})
|
||||||
await scrobbles.setJSON('now-playing', {...trackScrobbleData, ...{ url: `https://musicbrainz.org/artist/${artistInfo?.['mbid']}`}})
|
await scrobbles.setJSON('now-playing', {...trackScrobbleData, ...{ url: `https://musicbrainz.org/artist/${artistInfo?.['mbid']}`}})
|
||||||
let scrobbleUpdate = scrobbleData
|
let scrobbleUpdate = scrobbleData
|
||||||
let windowUpdate = windowData;
|
let windowUpdate = windowData;
|
||||||
if (scrobbleUpdate?.['data']) scrobbleUpdate['data'].push(trackScrobbleData)
|
if (scrobbleUpdate?.['data']) scrobbleUpdate['data'].push(trackScrobbleData)
|
||||||
if (!scrobbleUpdate?.['data']) scrobbleUpdate = { data: [trackScrobbleData] }
|
if (!scrobbleUpdate?.['data']) scrobbleUpdate = { data: [trackScrobbleData] }
|
||||||
if (windowData?.['data']) windowUpdate['data'].push(trackScrobbleData)
|
if (windowData?.['data']) windowUpdate['data'].push(trackScrobbleData)
|
||||||
if (!windowData?.['data']) windowUpdate = { data: [trackScrobbleData] }
|
if (!windowData?.['data']) windowUpdate = { data: [trackScrobbleData] }
|
||||||
windowUpdate = { data: filterOldScrobbles(windowUpdate.data) }
|
windowUpdate = { data: filterOldScrobbles(windowUpdate.data) }
|
||||||
await scrobbles.setJSON(`${weekKey()}`, scrobbleUpdate)
|
await scrobbles.setJSON(`${weekKey()}`, scrobbleUpdate)
|
||||||
await scrobbles.setJSON('window', windowUpdate)
|
await scrobbles.setJSON('window', windowUpdate)
|
||||||
```
|
```
|
||||||
|
|
||||||
We construct a `trackScrobbleData` object, merge our new scrobble with the data for the moving window of plays and current week and populate a `now-playing` blob that is now retrieved to populate [the dynamic check in component on my home page](https://coryd.dev/posts/2023/check-in-to-your-personal-site/).
|
We construct a `trackScrobbleData` object, merge our new scrobble with the data for the moving window of plays and current week and populate a `now-playing` blob that is now retrieved to populate [the dynamic check in component on my home page](https://coryd.dev/posts/2023/check-in-to-your-personal-site/).
|
||||||
|
|
43
src/posts/2024/enhancing-pagination-with-a-page-selector.md
Normal file
43
src/posts/2024/enhancing-pagination-with-a-page-selector.md
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
---
|
||||||
|
date: '2024-04-05T10:00-08:00'
|
||||||
|
title: 'Enhancing pagination with a page selector'
|
||||||
|
description: "I've made a change to my site's pagination wherein I've enhanced the page count displayed at the bottom of my home and links pages to display the page count in a select element. The select displays a list of all the pages and navigates to the selected page."
|
||||||
|
tags: ['Eleventy', 'development', 'javascript']
|
||||||
|
---
|
||||||
|
I've made a change to my site's pagination wherein I've enhanced the page count displayed at the bottom of my home and links pages to display the page count in a select element. The select displays a list of all the pages and navigates to the selected page.<!-- excerpt -->
|
||||||
|
|
||||||
|
If a user does not have JavaScript enabled, it simply renders the old static page count. The JavaScript logic looks like the following:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
window.onload = () => {
|
||||||
|
const pagination = document.getElementById('pagination')
|
||||||
|
const uri = window.location.pathname
|
||||||
|
const urlSegments = uri.split('/').filter(segment => segment !== '')
|
||||||
|
let pageNumber = parseInt(urlSegments[urlSegments.length - 1]) || 0
|
||||||
|
pagination.querySelector(`option[value="${pageNumber.toString()}"]`).setAttribute('selected', 'selected')
|
||||||
|
|
||||||
|
if (pagination) {
|
||||||
|
pagination.addEventListener('change', (event) => {
|
||||||
|
pageNumber = event.target.value
|
||||||
|
|
||||||
|
if (urlSegments.length === 0 || isNaN(urlSegments[urlSegments.length - 1])) {
|
||||||
|
urlSegments.push(pageNumber.toString())
|
||||||
|
} else {
|
||||||
|
urlSegments[urlSegments.length - 1] = pageNumber.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pageNumber === 0) {
|
||||||
|
window.location.href = `${window.location.protocol}//${window.location.host}/`
|
||||||
|
} else {
|
||||||
|
window.location = `${window.location.protocol}//${window.location.host}/${urlSegments.join('/')}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
We wait for the document to load, select the pagination DOM node, get the current `pathname`, split it at '/' delimited segments, filter empty values and look for a number representing the current page. We then set the `selected` attribute on the appropriate `<option>` node for the current page.
|
||||||
|
|
||||||
|
Within the `change` event listener I check whether we've extracted a url segment *and* that the last segment is a valid number — if not, we add a new numeric segment. If it is numeric, we replace it with the new page number. Finally, we have special handling for the root section — because my first page is at `/` and the second is at `/1/` we need to correctly navigate the user should the pageNumber be `0`.
|
||||||
|
|
||||||
|
With that, we have quicker and more convenient page navigation for users that have JavaScript enabled and a handy page count for users that have disabled JavaScript in their browser.
|
Reference in a new issue