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

Commit

Permalink
Image reporting view (#2090)
Browse files Browse the repository at this point in the history
Co-authored-by: Olga Bulat <obulat@gmail.com>
  • Loading branch information
zackkrida and obulat authored Jan 20, 2023
1 parent 93f5785 commit 5cc64a0
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 2 deletions.
9 changes: 7 additions & 2 deletions src/components/VContentReport/VContentReportForm.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div id="content-report-form" class="w-80 p-6">
<div id="content-report-form">
<div v-if="status === SENT">
<p class="heading-6 mb-4">
{{ $t("media-details.content-report.success.title") }}
Expand Down Expand Up @@ -76,7 +76,11 @@
</div>

<div class="flex flex-row items-center justify-end gap-4">
<VButton variant="secondary-bordered" @click="handleCancel">
<VButton
v-if="allowCancel"
variant="secondary-bordered"
@click="handleCancel"
>
{{ $t("media-details.content-report.form.cancel") }}
</VButton>

Expand Down Expand Up @@ -146,6 +150,7 @@ export default defineComponent({
providerName: { required: true },
reportService: { required: false },
closeFn: { required: true },
allowCancel: { type: Boolean, default: true },
},
setup(props) {
const service = props.reportService || ReportService
Expand Down
1 change: 1 addition & 0 deletions src/components/VContentReport/VContentReportPopover.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
@click="close"
/>
<VContentReportForm
class="w-80 p-6"
:close-fn="close"
:media="media"
:provider-name="media.providerName"
Expand Down
6 changes: 6 additions & 0 deletions src/composables/use-match-routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ export const useMatchSingleResultRoutes = () => {
.filter((name) => name !== ALL_MEDIA)
.map((name) => `${name}-id`),
]
// @TODO Switch to more generic implementation once
// an Audio reporting page is designed.
//
// routes = routes.concat(routes.map((name) => `${name}-report`))
routes.push("image-id-report")

return useMatchRoute(routes)
}

Expand Down
3 changes: 3 additions & 0 deletions src/locales/scripts/en.json5
Original file line number Diff line number Diff line change
Expand Up @@ -713,4 +713,7 @@
none: "No recent searches to show.",
disclaimer: "Openverse does not store your recent searches, this information is kept locally in your browser.",
},
report: {
"image-details": "See image details",
},
}
File renamed without changes.
File renamed without changes.
106 changes: 106 additions & 0 deletions src/pages/image/_id/report.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<template>
<div
class="mx-auto mt-8 mb-6 max-w-none gap-x-10 px-4 md:grid md:max-w-4xl md:grid-cols-2 md:px-6 lg:mb-30 lg:px-0 xl:max-w-4xl"
>
<figure class="mb-6 flex flex-col items-start gap-y-4">
<img
id="main-image"
:src="imageSrc"
:alt="image.title"
class="mx-auto h-auto w-full rounded-sm"
:width="imageWidth"
:height="imageHeight"
/>
<!-- Disable reason: We control the attribution HTML generation so this is safe and will not lead to XSS attacks -->
<!-- eslint-disable vue/no-v-html -->
<caption
class="block w-full text-left text-sr"
v-html="getAttributionMarkup({ includeIcons: false })"
/>
<!-- eslint-enable vue/no-v-html -->
<VButton
variant="secondary-bordered"
:href="`/image/${image.id}`"
as="VLink"
size="disabled"
class="p-2 text-sr text-dark-charcoal"
>
{{ $t("report.image-details") }}
</VButton>
</figure>

<VContentReportForm
:close-fn="() => {}"
:media="image"
:allow-cancel="false"
:provider-name="image.providerName"
/>
</div>
</template>

<script lang="ts">
import { defineComponent, ref, computed } from "@nuxtjs/composition-api"
import { useI18n } from "~/composables/use-i18n"
import { IMAGE } from "~/constants/media"
import { useSingleResultStore } from "~/stores/media/single-result"
import type { ImageDetail } from "~/types/media"
import { AttributionOptions, getAttribution } from "~/utils/attribution-html"
import VButton from "~/components/VButton.vue"
export default defineComponent({
name: "ReportImage",
components: {
VButton,
},
setup() {
const i18n = useI18n()
const singleResultStore = useSingleResultStore()
const image = computed(() =>
singleResultStore.mediaType === IMAGE
? (singleResultStore.mediaItem as ImageDetail)
: null
)
const imageWidth = ref(0)
const imageHeight = ref(0)
const imageType = ref("Unknown")
/**
* To make sure that image is loaded fast, we `src` to `image.thumbnail`,
* and then replace it with the provider image once it is loaded.
*/
const imageSrc = ref(image.value.thumbnail)
const getAttributionMarkup = (options?: AttributionOptions) =>
getAttribution(image.value, i18n, options)
return {
image,
imageWidth,
imageHeight,
imageType,
imageSrc,
getAttributionMarkup,
}
},
async asyncData({ app, error, route, $pinia }) {
const imageId = route.params.id
const singleResultStore = useSingleResultStore($pinia)
try {
await singleResultStore.fetch(IMAGE, imageId)
} catch (err) {
const errorMessage = app.i18n
.t("error.image-not-found", {
id: imageId,
})
.toString()
return error({
statusCode: 404,
message: errorMessage,
})
}
},
})
</script>

0 comments on commit 5cc64a0

Please sign in to comment.