Skip to content

Commit

Permalink
Update VCollectionHeader.vue
Browse files Browse the repository at this point in the history
Signed-off-by: Olga Bulat <[email protected]>
  • Loading branch information
obulat committed Nov 16, 2023
1 parent 3986e71 commit 8f9d82b
Show file tree
Hide file tree
Showing 16 changed files with 212 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,93 @@ import {
Meta,
Story,
} from "@storybook/addon-docs"
import { useProviderStore } from "~/stores/provider"

import VCollectionHeader from "~/components/VCollectionHeader/VCollectionHeader.vue"

<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 },
})
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,
}
}
13 changes: 13 additions & 0 deletions frontend/src/types/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,16 @@ export type SearchQuery = SearchFilterQuery & SearchRequestQuery
export type PaginatedSearchQuery = SearchRequestQuery &
PaginatedParams &
SearchFilterQuery

export type TagCollection = { collection: "tag"; tag: string }
export type CreatorCollection = {
collection: "creator"
source: string
creator: string
}
export type SourceCollection = { collection: "source"; source: string }

export type CollectionParams =
| TagCollection
| CreatorCollection
| SourceCollection
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 8f9d82b

Please sign in to comment.