Add shareable URLs for works with scores
- Score icon updates URL to /?work=[slug] without navigation - Modal closes to reset URL back to / - Direct /work/[slug] access redirects to /?work=[slug] - Index page opens modal when ?work= query param is present - Works with SSG/prerendering for /?work= routes
This commit is contained in:
parent
2fe7dad9fa
commit
9af20c1e5d
|
|
@ -2,7 +2,7 @@
|
|||
<div class="inline-flex p-1 min-w-[25px]">
|
||||
<div v-show="visible" class="bg-black rounded-full text-xs inline-flex" >
|
||||
|
||||
<button v-if="type === 'score'" @click="modalStore.setModalProps('pdf', 'aspect-[1/1.414]', true, '', '', '', link, work.soundcloud_trackid ? 'https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/' + work.soundcloud_trackid + '&auto_play=true&show_user=false' : '')" class="inline-flex p-1">
|
||||
<button v-if="type === 'score'" @click="openScoreModal()" class="inline-flex p-1">
|
||||
<Icon name="ion:book-sharp" style="color: white" />
|
||||
</button>
|
||||
|
||||
|
|
@ -41,13 +41,20 @@
|
|||
<script setup>
|
||||
import { useAudioPlayerStore } from "@/stores/AudioPlayerStore"
|
||||
import { useModalStore } from "@/stores/ModalStore"
|
||||
import { computed } from "vue"
|
||||
import { computed, watch } from "vue"
|
||||
|
||||
const props = defineProps(['type', 'work', 'visible', 'link', 'newTab'])
|
||||
|
||||
const audioPlayerStore = useAudioPlayerStore()
|
||||
const modalStore = useModalStore()
|
||||
|
||||
const slugify = (title) => {
|
||||
if (!title) return ''
|
||||
return title.toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '')
|
||||
}
|
||||
|
||||
const workSlug = computed(() => slugify(props.work?.title))
|
||||
|
||||
const isExternalLink = computed(() => {
|
||||
return props.link && !props.link.endsWith('.pdf') && !props.link.startsWith('/')
|
||||
})
|
||||
|
|
@ -63,4 +70,17 @@
|
|||
modalStore.setModalProps('document', 'aspect-[1/1.414]', true, '', '', '', '', '', props.link)
|
||||
}
|
||||
}
|
||||
|
||||
const openScoreModal = () => {
|
||||
modalStore.setModalProps('pdf', 'aspect-[1/1.414]', true, '', '', '', props.link, props.work?.soundcloud_trackid ? 'https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/' + props.work.soundcloud_trackid + '&auto_play=true&show_user=false' : '')
|
||||
if (workSlug.value && typeof window !== 'undefined') {
|
||||
window.history.replaceState({}, '', '/?work=' + workSlug.value)
|
||||
}
|
||||
}
|
||||
|
||||
watch(() => modalStore.isOpen, (isOpen) => {
|
||||
if (!isOpen && workSlug.value && typeof window !== 'undefined' && window.location.search.includes('work=')) {
|
||||
window.history.replaceState({}, '', '/')
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -78,8 +78,16 @@
|
|||
<script setup>
|
||||
|
||||
import { useModalStore } from "@/stores/ModalStore"
|
||||
import { watch, watchEffect } from "vue"
|
||||
|
||||
const modalStore = useModalStore()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const slugify = (title) => {
|
||||
if (!title) return ''
|
||||
return title.toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '')
|
||||
}
|
||||
|
||||
const groupBy = (x,f)=>x.reduce((a,b,i)=>((a[f(b,i,x)]||=[]).push(b),a),{});
|
||||
|
||||
|
|
@ -164,4 +172,37 @@
|
|||
titleTemplate: 'Michael Winter - Home / Works - Pieces, Publications, and Albums'
|
||||
})
|
||||
|
||||
const workFromSlug = computed(() => {
|
||||
const workSlug = route.query.work
|
||||
if (!workSlug || !works.value) return null
|
||||
for (const group of works.value) {
|
||||
const found = group.works.find(w => slugify(w.title) === workSlug)
|
||||
if (found) return found
|
||||
}
|
||||
return null
|
||||
})
|
||||
|
||||
watchEffect(() => {
|
||||
const workSlug = route.query.work
|
||||
const work = workFromSlug.value
|
||||
if (workSlug && work?.score) {
|
||||
modalStore.setModalProps(
|
||||
'pdf',
|
||||
'aspect-[1/1.414]',
|
||||
true,
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
work.score,
|
||||
work.soundcloud_trackid ? 'https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/' + work.soundcloud_trackid + '&auto_play=true&show_user=false' : ''
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
watch(() => modalStore.isOpen, (isOpen) => {
|
||||
if (!isOpen && route.query.work && typeof window !== 'undefined') {
|
||||
window.history.replaceState({}, '', '/')
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
|
|
|
|||
14
pages/work/[slug].vue
Normal file
14
pages/work/[slug].vue
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<script setup>
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const slug = route.params.slug
|
||||
|
||||
onMounted(() => {
|
||||
router.replace('/?work=' + slug)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
Loading…
Reference in a new issue