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

Add source links to creator pages #3780

Merged
merged 7 commits into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 106 additions & 60 deletions frontend/src/components/VCollectionHeader/VCollectionHeader.vue
Original file line number Diff line number Diff line change
@@ -1,53 +1,83 @@
<template>
<div
class="collection-header grid grid-cols-[1.5rem,1fr] gap-x-2 gap-y-4 md:grid-rows-[auto,auto] md:gap-y-8"
:class="
collection === 'tag'
? 'tags grid-rows-[auto,auto] md:grid-cols-[2.5rem,1fr]'
: 'grid-rows-[auto,auto,auto] md:grid-cols-[2.5rem,1fr,auto]'
"
class="collection-header grid gap-2 sm:grid-cols-[1fr,auto]"
:class="{ 'no-link': !showCollectionExternalLink }"
>
<VIcon :name="iconName" :size="isMd ? 10 : 6" class="icon" />
<h1 class="title text-3xl font-semibold leading-snug md:text-6xl">
{{ title }}
<h1 class="title flex flex-col gap-2 sm:flex-row">
<VIcon
:name="iconName"
:title="collection"
:size="10"
class="icon hidden sm:flex"
/>
<span class="label-regular flex text-dark-charcoal-70 sm:hidden">{{
$t(`collection.heading.${collection}`)
}}</span>
<span class="text-3xl font-semibold leading-snug sm:text-6xl">{{
title
}}</span>
</h1>
<VButton
v-if="collection !== 'tag' && url"
v-if="showCollectionExternalLink"
as="VLink"
variant="filled-dark"
size="medium"
class="button label-bold !flex-none md:ms-4 md:mt-1"
class="link label-bold mt-1 !w-full"
has-icon-end
show-external-icon
:external-icon-size="6"
:href="url"
@click="sendAnalyticsEvent"
>{{ $t(`collection.link.${collection}`) }}</VButton
>
<p
class="results caption-regular md:label-regular mt-2 text-dark-charcoal-70 md:mt-0"
<div
class="results mt-6 flex w-full min-w-0 flex-col items-start gap-1 sm:mt-0 sm:flex-row sm:items-center"
>
{{ resultsLabel }}
</p>
<p
class="label-regular w-max text-dark-charcoal-70 sm:whitespace-nowrap"
:class="{ 'pb-2 sm:pb-0': collection !== 'creator' }"
>
{{ resultsLabel }}
</p>
<VScrollableLine
v-if="collection === 'creator'"
class="-ms-2 -mt-1.5px h-8 w-[calc(100%+theme(space.4))] sm:ms-0"
>
<VButton
as="VLink"
size="disabled"
variant="transparent-gray"
class="label-bold m-1.5px h-8 w-max gap-x-1 whitespace-nowrap p-1"
:href="sourceCollectionLink"
has-icon-start
><VIcon
name="institution"
:title="$t('collection.link.source')"
/><span class="w-max whitespace-nowrap">{{
source.name
}}</span></VButton
>
</VScrollableLine>
</div>
</div>
</template>

<script lang="ts">
import { computed, defineComponent, PropType } from "vue"
import { computed, defineComponent, type PropType } from "vue"

import { useUiStore } from "~/stores/ui"
import type { CollectionParams } from "~/types/search"
import { useAnalytics } from "~/composables/use-analytics"

import { useMediaStore } from "~/stores/media"
import { useProviderStore } from "~/stores/provider"
import { SupportedMediaType } from "~/constants/media"
import { useSearchStore } from "~/stores/search"
import type { CollectionParams } from "~/types/search"
import type { SupportedMediaType } from "~/constants/media"

import { useI18nResultsCount } from "~/composables/use-i18n-utilities"

import { useMediaStore } from "~/stores/media"

import VIcon from "~/components/VIcon/VIcon.vue"
import VButton from "~/components/VButton.vue"
import VScrollableLine from "~/components/VScrollableLine.vue"

const icons = {
tag: "tag",
Expand All @@ -60,7 +90,7 @@ const icons = {
*/
export default defineComponent({
name: "VCollectionHeader",
components: { VIcon, VButton },
components: { VScrollableLine, VIcon, VButton },
props: {
collectionParams: {
type: Object as PropType<CollectionParams>,
Expand All @@ -77,19 +107,28 @@ export default defineComponent({
setup(props) {
const mediaStore = useMediaStore()
const providerStore = useProviderStore()
const uiStore = useUiStore()
const searchStore = useSearchStore()

const iconName = computed(() => icons[props.collectionParams.collection])
const collection = computed(() => props.collectionParams.collection)

const sourceName = computed(() => {
const source = computed(() => {
if (props.collectionParams.collection === "tag") {
return ""
return {
name: "",
link: "",
}
}
return {
name: providerStore.getProviderName(
props.collectionParams.source,
props.mediaType
),
link: providerStore.getSourceUrl(
props.collectionParams.source,
props.mediaType
),
}
return providerStore.getProviderName(
props.collectionParams.source,
props.mediaType
)
})

const title = computed(() => {
Expand All @@ -98,7 +137,7 @@ export default defineComponent({
} else if (props.collectionParams.collection === "creator") {
return props.collectionParams.creator
}
return sourceName.value
return source.value.name
})

const url = computed(() => {
Expand All @@ -107,35 +146,41 @@ export default defineComponent({
} else if (props.collectionParams.collection === "creator") {
return props.creatorUrl
}
return providerStore.getSourceUrl(
props.collectionParams.source,
props.mediaType
)
return source.value.link
})

const sourceCollectionLink = computed(() => {
if (props.collectionParams.collection !== "creator") {
return ""
}
return searchStore.getCollectionPath({
type: props.mediaType,
collectionParams: {
collection: "source",
source: props.collectionParams.source,
},
})
})

const showCollectionExternalLink = computed(() => {
return Boolean(props.collectionParams.collection !== "tag" && url.value)
})

const { getI18nCollectionResultCountLabel } = useI18nResultsCount()

const resultsLabel = computed(() => {
if (mediaStore.resultCount === 0 && mediaStore.fetchState.isFetching) {
return ""
}
const resultsCount = mediaStore.results[props.mediaType].count
if (props.collectionParams.collection === "creator") {
return getI18nCollectionResultCountLabel(
resultsCount,
props.mediaType,
"creator",
{ source: sourceName.value }
)
}

return getI18nCollectionResultCountLabel(
resultsCount,
props.mediaType,
props.collectionParams.collection
)
})

const isMd = computed(() => uiStore.isBreakpoint("md"))

const { sendCustomEvent } = useAnalytics()

const sendAnalyticsEvent = () => {
Expand All @@ -157,9 +202,11 @@ export default defineComponent({
collection,
title,
resultsLabel,
source,
url,
sourceCollectionLink,
showCollectionExternalLink,
iconName,
isMd,
sendAnalyticsEvent,
}
},
Expand All @@ -168,29 +215,28 @@ export default defineComponent({

<style scoped>
.collection-header {
grid-template-areas: "icon title" "button button" "results results";
grid-template-areas: "title" "link" "results";
}
.no-link {
grid-template-areas: "title" "results";
}
@screen md {

@screen sm {
.collection-header {
grid-template-areas: "icon title button" "results results results";
grid-template-rows: minmax(3.75rem, auto) minmax(2rem, auto);
grid-template-areas: "title link" "results results";
}
}
.collection-header.tags {
grid-template-areas: "icon title" "results results";
}
@screen md {
.collection-header.tags {
grid-template-areas: "icon title" "results results";
.no-link {
grid-template-rows: minmax(3.625rem, auto) minmax(2rem, auto);
grid-template-columns: auto;
grid-template-areas: "title" "results";
}
}
.icon {
grid-area: icon;
}
.title {
grid-area: title;
}
.button {
grid-area: button;
.link {
grid-area: link;
}
.results {
grid-area: results;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export const imageProviderNames = [

export const AllCollectionsTemplate = (args) => ({
template: `
<div class="wrapper w-full p-2 flex flex-col gap-2 bg-dark-charcoal-06">
<div class="wrapper w-full p-3 flex flex-col gap-4 bg-dark-charcoal-06">
<VCollectionHeader v-for="collection in args.collections" :key="collection.collectionName" v-bind="collection" class="bg-white"/>
</div>`,
components: { VCollectionHeader },
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/VCollectionPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
:collection-params="collectionParams"
:creator-url="creatorUrl"
:media-type="mediaType"
:class="mediaType === 'image' ? 'mb-4' : 'mb-2'"
class="mb-2 md:mb-3"
/>
<VAudioList
v-if="results.type === 'audio'"
Expand Down
Loading
Loading