unboundedpress/portfolio/pages/index.vue

152 lines
5.3 KiB
Vue
Raw Normal View History

2023-06-06 19:51:48 +02:00
<template>
2023-08-28 22:54:29 +02:00
<div class="bg-zinc-100 rounded-lg m-5 grid grid-cols-3 gap-10 divide-x divide-solid divide-black py-4 mb-10">
2023-06-08 00:30:48 +02:00
<div class="px-5">
<p class="text-lg">pieces</p>
2023-06-08 00:30:48 +02:00
<div class="py-2 ml-3" v-for="item in works">
<p class="font-thin">{{ item.year }}</p>
<div class="leading-tight py-1 ml-3" v-for="work in item.works">
<div class="grid grid-cols-[65%,30%] gap-1 font-thin items-start">
2023-06-19 19:11:27 +02:00
<div class="italic text-sm">{{ work.title }}</div>
<div class="inline-flex mt-[-4px]">
2023-06-08 00:30:48 +02:00
<div>
<IconButton :visible="work.score" type="score" :work="work" :link="work.score" class="inline-flex p-1"></IconButton>
</div>
2023-06-08 00:30:48 +02:00
<div>
<IconButton :visible="work.soundcloud_trackid" type="audio" :work="work" class="inline-flex p-1"></IconButton>
</div>
2023-06-08 05:29:29 +02:00
<div>
<IconButton :visible="work.vimeo_trackid" type="video" :work="work" class="inline-flex p-1"></IconButton>
</div>
2023-06-19 19:11:27 +02:00
<div>
<IconButton :visible="work.gallery" type="image" :work="work" class="inline-flex p-1"></IconButton>
</div>
2023-06-08 00:30:48 +02:00
</div>
</div>
</div>
</div>
</div>
<div class="px-5">
<p class="text-lg">writings</p>
2023-06-10 01:24:44 +02:00
2023-06-08 05:29:29 +02:00
<div class="leading-tight py-2 ml-3 text-sm" v-for="item in pubs">
<div class="grid grid-cols-[95%,5%] gap-1 items-start">
2023-06-12 18:00:37 +02:00
<div>
<span v-html="item.entryTags.title"></span>
2023-06-12 18:00:37 +02:00
<div class="ml-4 text-[#7F7F7F]">
{{ item.entryTags.author }}
<span v-if=item.entryTags.booktitle>{{ item.entryTags.booktitle}}.&nbsp;</span>
<span v-if=item.entryTags.journal>{{item.entryTags.journal}}.&nbsp;</span>
<span v-if=item.entryTags.editor>editors {{item.entryTags.editor}}&nbsp;</span>
<span v-if=item.entryTags.volume>volume {{item.entryTags.volume}}.</span>
<span v-if=item.entryTags.publisher>{{item.entryTags.publisher}}.</span>
{{ item.entryTags.year }}.
</div>
</div>
<div>
<IconButton :visible=item.entryTags.howpublished type="document" :link="item.entryTags.howpublished" class="inline-flex p-1 mt-[-6px]"></IconButton>
2023-06-12 18:00:37 +02:00
</div>
</div>
2023-06-08 05:29:29 +02:00
</div>
2023-06-08 00:30:48 +02:00
</div>
<div class="px-5">
2023-07-04 11:37:34 +02:00
<p class="text-lg">albums</p>
<div class="flex flex-col items-center leading-tight py-4 text-sm" v-for="item in releases">
<p class="leading-tight py-2">{{ item.title }}</p>
<button @click="modalStore.setModalProps('image', 'aspect-auto', true, 'album_art', [{image: item.album_art}], '')">
<nuxt-img :src="'/album_art/' + item.album_art"
2023-06-12 18:00:37 +02:00
quality="50"/>
</button>
<div class="flex place-content-center place-items-center">
<IconButton :visible="item.discogs_id" type="discogs" :link="'https://www.discogs.com/release/' + item.discogs_id" :newTab="true"></IconButton>
<IconButton :visible="item.buy_link" type="buy" :link="item.buy_link" :newTab="true"></IconButton>
</div>
2023-06-08 00:30:48 +02:00
</div>
</div>
2023-06-06 19:51:48 +02:00
</div>
2023-06-08 05:29:29 +02:00
</template>
2023-06-06 19:51:48 +02:00
<script setup>
2023-06-08 00:30:48 +02:00
2023-06-12 18:00:37 +02:00
import { useModalStore } from "@/stores/ModalStore"
2023-06-12 18:00:37 +02:00
const modalStore = useModalStore()
2023-06-08 00:30:48 +02:00
const groupBy = (x,f)=>x.reduce((a,b,i)=>((a[f(b,i,x)]||=[]).push(b),a),{});
const isValidUrl = urlString => {
2023-06-14 19:35:23 +02:00
var pattern = /^((http|https|ftp):\/\/)/;
return pattern.test(urlString)
}
const { data: images } = await useFetch('/api/images')
2023-06-11 23:53:56 +02:00
const { data: works } = await useFetch('/api/works', {
2023-06-08 00:30:48 +02:00
transform: (works) => {
2023-06-11 23:53:56 +02:00
for (const work of works) {
if(work.score){
work.score = "/scores/" + work.score
}
2023-06-14 19:35:23 +02:00
if(work.images){
let gallery = [];
for (const image of work.images){
gallery.push({
image: image.filename,
2023-06-14 19:35:23 +02:00
})
}
work.gallery = gallery
}
2023-06-11 23:53:56 +02:00
}
let priorityGroups = groupBy(works, work => work.priority)
let groups = groupBy(priorityGroups["1"], work => new Date(work.date).getFullYear())
groups = Object.keys(groups).map((year) => {
2023-06-08 00:30:48 +02:00
return {
year,
works: groups[year].sort((a,b) => new Date(b.date) - new Date(a.date))
2023-06-08 00:30:48 +02:00
};
});
groups.sort((a,b) => b.year - a.year)
if (priorityGroups["2"]) {
groups.push({year: "miscellany", works: priorityGroups["2"].sort((a,b) => new Date(b.date) - new Date(a.date))})
}
return groups
2023-06-08 00:30:48 +02:00
}
})
const { data: pubs } = await useFetch('/api/publications', {
2023-06-08 00:30:48 +02:00
transform: (pubs) => {
for (const pub of pubs) {
if(pub.entryTags && pub.entryTags.howpublished && !(isValidUrl(pub.entryTags.howpublished))){
pub.entryTags.howpublished = "/pubs/" + pub.entryTags.howpublished
}
}
2023-07-04 12:25:27 +02:00
return pubs.sort((a,b) => (a.citationKey > b.citationKey) ? -1 : ((b.citationKey > a.citationKey) ? 1 : 0))
2023-06-08 00:30:48 +02:00
}
})
const { data: releases } = await useFetch('/api/releases', {
2023-06-08 00:30:48 +02:00
transform: (releases) => {
return releases.sort((a,b) => {
const dateA = parseInt(a.date) || 0
const dateB = parseInt(b.date) || 0
return dateB - dateA
2023-06-08 00:30:48 +02:00
})
}
})
useHead({
titleTemplate: 'Michael Winter - Home / Works - Pieces, Publications, and Albums'
})
</script>