Skip to content

Commit

Permalink
Update VCollectionHeader.vue (#3365)
Browse files Browse the repository at this point in the history
Signed-off-by: Olga Bulat <[email protected]>
  • Loading branch information
obulat authored Nov 18, 2023
1 parent 6fc9367 commit 7967abd
Show file tree
Hide file tree
Showing 18 changed files with 257 additions and 51 deletions.
102 changes: 75 additions & 27 deletions frontend/src/components/VCollectionHeader/VCollectionHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,18 @@
import { computed, defineComponent, PropType } from "vue"
import { useUiStore } from "~/stores/ui"
import type { Collection } from "~/types/search"
import type { CollectionParams } from "~/types/search"
import { useAnalytics } from "~/composables/use-analytics"
import VButton from "~/components/VButton.vue"
import { useProviderStore } from "~/stores/provider"
import { 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"
const icons = {
tag: "tag",
Expand All @@ -55,55 +62,96 @@ export default defineComponent({
name: "VCollectionHeader",
components: { VIcon, VButton },
props: {
collection: {
type: String as PropType<Collection>,
required: true,
},
/**
* The name of the tag/creator/source. The source name should be the display
* name, not the code.
*/
title: {
type: String,
collectionParams: {
type: Object as PropType<CollectionParams>,
required: true,
},
slug: {
creatorUrl: {
type: String,
},
url: {
type: String,
},
/**
* The label showing the result count, to display below the title.
* Should be built by the parent component.
*/
resultsLabel: {
type: String,
mediaType: {
type: String as PropType<SupportedMediaType>,
required: true,
},
},
setup(props) {
const providerStore = useProviderStore()
const uiStore = useUiStore()
const iconName = computed(() => icons[props.collection])
const iconName = computed(() => icons[props.collectionParams.collection])
const collection = computed(() => props.collectionParams.collection)
const sourceName = computed(() => {
if (props.collectionParams.collection === "tag") {
return ""
}
return providerStore.getProviderName(
props.collectionParams.source,
props.mediaType
)
})
const title = computed(() => {
if (props.collectionParams.collection === "tag") {
return props.collectionParams.tag
} else if (props.collectionParams.collection === "creator") {
return props.collectionParams.creator
}
return sourceName.value
})
const url = computed(() => {
if (props.collectionParams.collection === "tag") {
return undefined
} else if (props.collectionParams.collection === "creator") {
return props.creatorUrl
}
return providerStore.getSourceUrl(
props.collectionParams.source,
props.mediaType
)
})
const { getI18nCollectionResultCountLabel } = useI18nResultsCount()
const resultsLabel = computed(() => {
const resultsCount = useMediaStore().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 = () => {
if (!props.url || !props.slug) return
if (props.collectionParams.collection === "tag") return
const eventName =
props.collection === "creator"
props.collectionParams.collection === "creator"
? "VISIT_CREATOR_LINK"
: "VISIT_SOURCE_LINK"
sendCustomEvent(eventName, {
url: props.url,
source: props.slug,
url: url.value,
source: props.collectionParams.source,
})
}
return {
collection,
title,
resultsLabel,
url,
iconName,
isMd,
sendAnalyticsEvent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,50 +5,98 @@ import {
Meta,
Story,
} from "@storybook/addon-docs"
import { useProviderStore } from "~/stores/provider"

import VCollectionHeader from "~/components/VCollectionHeader/VCollectionHeader.vue"
import { useMediaStore } from "@/stores/media"

<Meta title="Components/VCollectionHeader" component={VCollectionHeader} />

export const imageProviders = [
{
source_name: "smithsonian_african_american_history_museum",
display_name:
"Smithsonian Institution: National Museum of African American History and Culture",
source_url: "https://nmaahc.si.edu",
logo_url: null,
media_count: 10895,
},
{
source_name: "flickr",
display_name: "Flickr",
source_url: "https://www.flickr.com",
logo_url: null,
media_count: 505849755,
},
{
source_name: "met",
display_name: "Metropolitan Museum of Art",
source_url: "https://www.metmuseum.org",
logo_url: null,
media_count: 396650,
},
]

export const imageProviderNames = [
"smithsonian_african_american_history_museum",
"flickr",
"met",
]

export const AllCollectionsTemplate = (args) => ({
template: `
<div class="wrapper w-full p-2 flex flex-col gap-2 bg-dark-charcoal-06">
<VCollectionHeader v-for="collection in args.collections" :key="collection.collectionName" v-bind="collection" class="bg-white"/>
</div>`,
components: { VCollectionHeader },
setup() {
const providerStore = useProviderStore()
providerStore.$patch({
providers: { image: imageProviders },
sourceNames: { image: imageProviderNames },
})
const mediaStore = useMediaStore()
mediaStore.$patch({
results: { image: { count: 10000 } },
})
return { args }
},
})

export const collections = [
{
collectionName: "tag",
collection: "tag",
title: "cat",
resultsLabel: "10000 audio files with the selected tag",
collectionParams: {
collection: "tag",
tag: "cat",
},
mediaType: "image",
},
{
collectionName: "source",
collection: "source",
title: "Metropolitan Museum of Art",
url: "https://www.metmuseum.org/",
resultsLabel: "10000 images provided by this source",
collectionParams: {
collection: "source",
source: "met",
},
mediaType: "image",
},
{
collectionName: "creator",
collection: "creator",
title: "iocyoungreporters",
url: "https://www.flickr.com/photos/126018610@N05",
resultsLabel: "10000 images. iocyoungreporters, Flickr",
collectionParams: {
collection: "creator",
source: "flickr",
creator: "iocyoungreporters",
},
mediaType: "image",
creatorUrl: "https://www.flickr.com/photos/126018610@N05",
},
{
collectionName: "source-with-long-name",
collection: "source",
title:
"Smithsonian Institution: National Museum of African American History and Culture",
url: "https://nmaahc.si.edu",
resultsLabel: "10000 images provided by this source",
collectionParams: {
collection: "source",
source: "smithsonian_african_american_history_museum",
},
mediaType: "image",
},
]

Expand Down
73 changes: 65 additions & 8 deletions frontend/src/composables/use-i18n-utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import { useGetLocaleFormattedNumber } from "~/composables/use-get-locale-format
import { useI18n } from "~/composables/use-i18n"
import type { SupportedMediaType, SupportedSearchType } from "~/constants/media"
import { ALL_MEDIA, AUDIO, IMAGE } from "~/constants/media"
import { Collection } from "~/types/search"

/**
* Not using dynamically-generated keys to ensure that
* correct line is shown in the 'po' locale files
*/
const i18nKeys = {
const searchResultKeys = {
[ALL_MEDIA]: {
noResult: "browsePage.allNoResults",
result: "browsePage.allResultCount",
Expand All @@ -24,6 +25,52 @@ const i18nKeys = {
more: "browsePage.contentLink.audio.countMore",
},
}
const collectionKeys = {
source: {
[IMAGE]: {
noResult: "collection.resultCountLabel.source.image.zero",
result: "collection.resultCountLabel.source.image.count",
more: "collection.resultCountLabel.source.image.countMore",
},
[AUDIO]: {
noResult: "collection.resultCountLabel.source.audio.zero",
result: "collection.resultCountLabel.source.audio.count",
more: "collection.resultCountLabel.source.audio.countMore",
},
},
creator: {
[IMAGE]: {
noResult: "collection.resultCountLabel.creator.image.zero",
result: "collection.resultCountLabel.creator.image.count",
more: "collection.resultCountLabel.creator.image.countMore",
},
[AUDIO]: {
noResult: "collection.resultCountLabel.creator.audio.zero",
result: "collection.resultCountLabel.creator.audio.count",
more: "collection.resultCountLabel.creator.audio.countMore",
},
},
tag: {
[IMAGE]: {
noResult: "collection.resultCountLabel.tag.image.zero",
result: "collection.resultCountLabel.tag.image.count",
more: "collection.resultCountLabel.tag.image.countMore",
},
[AUDIO]: {
noResult: "collection.resultCountLabel.tag.audio.zero",
result: "collection.resultCountLabel.tag.audio.count",
more: "collection.resultCountLabel.tag.audio.countMore",
},
},
}

function getCountKey(resultsCount: number) {
return resultsCount === 0
? "noResult"
: resultsCount >= 10000
? "more"
: "result"
}

/**
* Returns the localized text for the number of search results.
Expand All @@ -38,13 +85,8 @@ export function useI18nResultsCount() {
resultsCount: number,
searchType: SupportedSearchType
) => {
const countKey =
resultsCount === 0
? "noResult"
: resultsCount >= 10000
? "more"
: "result"
return i18nKeys[searchType][countKey]
const countKey = getCountKey(resultsCount)
return searchResultKeys[searchType][countKey]
}

/**
Expand All @@ -62,6 +104,20 @@ export function useI18nResultsCount() {
mediaType,
})
}
const getI18nCollectionResultCountLabel = (
resultCount: number,
mediaType: SupportedMediaType,
collectionType: Collection,
params: Record<string, string> | undefined = undefined
) => {
const key =
collectionKeys[collectionType][mediaType][getCountKey(resultCount)]
return i18n.tc(key, resultCount, {
localeCount: getLocaleFormattedNumber(resultCount),
...params,
})
}

/**
* Returns the localized text for the number of search results, using corresponding
* pluralization rules and decimal separators.
Expand All @@ -76,6 +132,7 @@ export function useI18nResultsCount() {
return {
getI18nCount,
getI18nContentLinkLabel,
getI18nCollectionResultCountLabel,
getLoading,
}
}
Loading

0 comments on commit 7967abd

Please sign in to comment.