Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

Make VLink component that wraps around both external and internal links #879

Merged
merged 23 commits into from
Feb 21, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
6921e3b
Add VLink component for external links
obulat Feb 15, 2022
622acc0
Add VLink component for external links
obulat Feb 15, 2022
4379fb8
Use VLink for Download button
obulat Feb 15, 2022
8433e64
Apply code review suggestions and add localePath to NuxtLinks
obulat Feb 15, 2022
e8d70c6
Revert DownloadButton change
obulat Feb 15, 2022
7b069dd
Use VLink component as a wrapper for `a` and `NuxtLink`
obulat Feb 16, 2022
66a604e
Use VLink component as a wrapper for `a` and `NuxtLink`
obulat Feb 16, 2022
87416fc
Merge branch 'main' into add/bigger_vlink_component
obulat Feb 16, 2022
fb30b4c
Stop destructuring attrs in order to not lose reactivity
obulat Feb 16, 2022
5a68ae6
Merge branch 'main' into add/bigger_vlink_component
obulat Feb 16, 2022
673d8fb
Use VLink for Download Button
obulat Feb 16, 2022
7465072
Fix homepage image link URL
obulat Feb 16, 2022
4d7dfa0
Use href prop instead of href as an attr
obulat Feb 17, 2022
fcd3257
VLink unit test improvements
obulat Feb 17, 2022
e8ed2ea
Update src/components/VLink.vue
obulat Feb 17, 2022
231510c
Remove null check for app
obulat Feb 17, 2022
d52ed20
Merge branch 'add/bigger_vlink_component' of github.com:WordPress/ope…
obulat Feb 18, 2022
69345ad
Merge branch 'main' into add/bigger_vlink_component
obulat Feb 18, 2022
482d7e1
Use span for links without href
obulat Feb 18, 2022
d7ab14a
Merge branch 'main' into add/bigger_vlink_component
obulat Feb 18, 2022
ebed7be
Add some validation
obulat Feb 18, 2022
1d7e2a7
Merge branch 'main' into add/bigger_vlink_component
obulat Feb 20, 2022
7a4faff
Check for app not being undefined in tests
obulat Feb 20, 2022
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
7 changes: 4 additions & 3 deletions src/components/AudioDetails/VAudioDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
<div class="flex flex-col gap-4 lg:gap-6 flex-grow">
<p v-if="audio.description" class="mb-6">{{ audio.description }}</p>
<ul class="flex flex-wrap gap-2">
<MediaTag
<VMediaTag
v-for="(tag, index) in audio.tags.filter((i) => !!i)"
:key="index"
tag="li"
>
{{ tag.name }}
</MediaTag>
</VMediaTag>
</ul>
<dl v-if="audio">
<div v-if="audio.audio_set">
Expand Down Expand Up @@ -87,10 +87,11 @@ import { PROVIDER } from '~/constants/store-modules'
import { mapState } from 'vuex'
import VLink from '~/components/VLink.vue'
import VAudioThumbnail from '~/components/VAudioThumbnail/VAudioThumbnail.vue'
import VMediaTag from '~/components/VMediaTag/VMediaTag.vue'

export default {
name: 'VAudioDetails',
components: { VLink, VAudioThumbnail },
components: { VAudioThumbnail, VLink, VMediaTag },
props: ['audio'],
computed: {
...mapState(PROVIDER, ['audioProviders']),
Expand Down
9 changes: 5 additions & 4 deletions src/components/DownloadButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
:size="size"
>
<template #default="{ buttonProps }">
<a
<VLink
v-bind="buttonProps"
class="whitespace-nowrap"
:href="selectedFormat.download_url"
Expand All @@ -19,7 +19,7 @@
<span class="ms-1 font-normal">{{
getFormatSize(selectedFormat.extension_name)
}}</span>
</a>
</VLink>
</template>

<template
Expand Down Expand Up @@ -62,13 +62,14 @@
import filesize from 'filesize'
import axios from 'axios'
import local from '~/utils/local'
import DropdownButton from '~/components/DropdownButton'
import DropdownButton from '~/components/DropdownButton.vue'
import VLink from '~/components/VLink.vue'

const LS_DOWNLOAD_FORMAT_EXTENSION_KEY = 'openverse:download-format-extension'

export default {
name: 'DownloadButton',
components: { DropdownButton },
components: { DropdownButton, VLink },
props: {
formats: {
type: Array,
Expand Down
102 changes: 0 additions & 102 deletions src/components/FooterSection.vue

This file was deleted.

12 changes: 12 additions & 0 deletions src/components/VImageDetails/VImageDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
</h3>
<VContentReportPopover :media="image" />
</div>
<ul v-if="image && image.tags" class="flex flex-wrap gap-2 mb-6">
<VMediaTag
v-for="(tag, index) in image.tags.filter((i) => !!i)"
:key="index"
tag="li"
>{{ tag.name }}</VMediaTag
>
</ul>
<dl>
<div>
<dt>{{ $t('image-details.information.type') }}</dt>
Expand Down Expand Up @@ -38,8 +46,12 @@
<script>
import { computed, defineComponent, useContext } from '@nuxtjs/composition-api'

import VContentReportPopover from '~/components/VContentReport/VContentReportPopover.vue'
import VMediaTag from '~/components/VMediaTag/VMediaTag.vue'

const VImageDetails = defineComponent({
name: 'VImageDetails',
components: { VContentReportPopover, VMediaTag },
props: {
image: {
type: Object,
Expand Down
46 changes: 15 additions & 31 deletions src/components/VLink.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,50 +6,34 @@

<script>
/**
* This is a wrapper component for all links. All VLinks have to have a valid `href` attr.
* This is a wrapper component for all links. All VLinks have to have a valid `href` prop.
* Links with `href` starting with `/` are treated as internal links.
*
* Internal links use `NuxtLink` component with `to` attribute set to `localePath(href)`
* External links use `a` element set to open in a new tab and not raise an error with the current iframe setup.
*/
import {
computed,
defineComponent,
useContext,
watch,
} from '@nuxtjs/composition-api'
import { warn } from '@/utils/warn'
import { computed, defineComponent, useContext } from '@nuxtjs/composition-api'

const defaultProps = { target: '_blank', rel: 'noopener noreferrer' }

export default defineComponent({
name: 'VLink',
setup(_, { attrs }) {
props: {
href: {
type: String,
required: true,
validator: (v) => !['', '#'].includes(v),
krysal marked this conversation as resolved.
Show resolved Hide resolved
},
},
setup(props) {
const { app } = useContext()
const isInternal = computed(() => attrs.href?.startsWith('/'))
const isInternal = computed(() => props.href?.startsWith('/'))
obulat marked this conversation as resolved.
Show resolved Hide resolved
const linkComponent = computed(() => (isInternal.value ? 'NuxtLink' : 'a'))

let linkProperties = {}
watch(
[attrs],
([attrs]) => {
// No need to declare `href` as an explicit prop as Vue preserves
// the `attrs` object reference between renders and updates the properties
// meaning we'll always have the latest values for the properties on the
// attrs object
if (!attrs.href || attrs.href === '#') {
warn('VLink is missing a valid `href` attribute.')
}
const { href, ...otherProperties } = attrs
linkProperties = isInternal.value
? { ...otherProperties, to: app.localePath(href) }
: {
...otherProperties,
...defaultProps,
href,
}
},
{ immediate: true }
let linkProperties = computed(() =>
isInternal.value
? { to: app?.localePath(props.href) ?? props.href }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In what case is app null? 😱

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When testing 😆 That was probably a lazy hack to ensure tests pass without mocking the nuxt context :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh dear! I wish it was easier to set up a globally enabled mock of the nuxt stuff 🤔

: { ...defaultProps, href: props.href }
)

return { linkProperties, linkComponent }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<Component
:is="tag"
v-bind="$attrs"
class="text-dark-blue text-sr md:text-sm font-semibold px-2 md:px-3 py-1 md:py-2 bg-dark-charcoal-10 rounded-full leading-none inline-flex"
class="text-dark-blue text-sr md:text-base font-semibold px-3 md:px-4 py-1 md:py-2 bg-dark-charcoal-10 rounded-full leading-[130%] md:leading-[130%] inline-flex"
>
<!-- @slot Content goes here -->
<slot />
Expand All @@ -23,7 +23,7 @@ export default {
*/
tag: {
type: String,
default: 'div',
default: 'span',
},
},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,21 @@ import {
Story,
} from '@storybook/addon-docs'

import MediaTag from '~/components/MediaTag/MediaTag'
import VMediaTag from '~/components/VMediaTag/VMediaTag'

<Meta title="Components/Media tag" component={MediaTag} />
<Meta title="Components/VMediaTag" component={VMediaTag} />

export const Template = (args, { argTypes }) => ({
template: `<MediaTag v-bind="$props" v-on="$props">Hello</MediaTag>`,
components: { MediaTag },
template: `<VMediaTag v-bind="$props">Hello</VMediaTag>`,
components: { VMediaTag },
props: Object.keys(argTypes),
})

# Media tag

<Description of={MediaTag} />
<Description of={VMediaTag} />

<ArgsTable of={MediaTag} />
<ArgsTable of={VMediaTag} />

By default, the component is a transparent wrapper over `<span>`.

Expand All @@ -38,7 +38,6 @@ focus states on interactive elements, can be applied to add to the base styles.
args={{
tag: 'a',
href: 'https://wordpress.org/',
class: 'hover:bg-dark-charcoal-60 hover:text-white hover:no-underline',
}}
>
{Template.bind({})}
Expand Down
22 changes: 0 additions & 22 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,28 +64,6 @@
"with-count": "{count} Filter|{count} Filters"
}
},
"footer": {
"navigation": {
"contact": "Contact",
"privacy": "Privacy",
"policies": "Policies",
"terms": "Terms"
},
"caption": {
"label": "Except where otherwise {noted}, content on this site is licensed under a {attribution}. {icons}",
"noted": "noted",
"attribution": "Creative Commons Attribution 4.0 International license",
"icons": "Icons by Font Awesome."
},
"donate": {
"work": "Our work relies on you!",
"help": "Help us keep the internet free and open."
},
"aria": {
"contact": "contact info",
"donate": "donate section"
}
},
"about": {
"title": "About Openverse",
"description": {
Expand Down
Loading