2023-11-29 10:56:17 -08:00
< template >
< div class = "page" >
2025-02-02 14:09:10 -08:00
< div class = "experimental-styles-within flex flex-col gap-2" >
2025-04-28 18:14:04 -07:00
< RadialHeader class = "top-box mb-2 flex flex-col items-center justify-center" color = "orange" >
2025-02-02 14:09:10 -08:00
< ScaleIcon class = "h-12 w-12 text-brand-orange" / >
< h1 class = "m-3 gap-2 text-3xl font-extrabold" >
{ {
prefilled && itemName
? existingReport
? formatMessage ( messages . alreadyReportedItem , { title : itemName } )
: formatMessage ( messages . reportItem , { title : itemName } )
: formatMessage ( messages . reportContent )
} }
< / h1 >
< / RadialHeader >
< div
v - if = "prefilled && itemName && existingReport"
class = "mx-auto flex max-w-[35rem] flex-col items-center gap-4 text-center"
>
{ { formatMessage ( messages . alreadyReportedDescription , { item : reportItem || "content" } ) } }
< div class = "flex gap-2" >
< ButtonStyled v-if = "itemLink" >
< nuxt-link :to = "itemLink" >
< LeftArrowIcon / >
{ { formatMessage ( messages . backToItem , { item : reportItem || "content" } ) } }
< / nuxt-link >
< / ButtonStyled >
< ButtonStyled color = "brand" >
< nuxt-link :to = "`/dashboard/report/${existingReport.id}`" >
{ { formatMessage ( messages . goToReport ) } } < RightArrowIcon / >
< / nuxt-link >
< / ButtonStyled >
2023-11-29 10:56:17 -08:00
< / div >
2025-02-02 14:09:10 -08:00
< / div >
< template v-else >
< div class = "mb-3 grid grid-cols-1 gap-4 px-6 md:grid-cols-2" >
< div class = "flex flex-col gap-2" >
< h2 class = "m-0 text-lg font-extrabold" > { { formatMessage ( messages . pleaseReport ) } } < / h2 >
< div class = "text-md flex items-center gap-2 font-semibold text-contrast" >
< CheckCircleIcon class = "h-8 w-8 shrink-0 text-brand-green" / >
< div class = "flex flex-col" >
< span >
< IntlFormatted :message-id = "messages.violation" >
< template # rules -link = " { children } " >
< nuxt-link class = "text-link" :to = "`/legal/rules`" >
< component : is = "() => children" / >
< / nuxt-link >
< / template >
< template # terms -link = " { children } " >
< nuxt-link class = "text-link" :to = "`/legal/terms`" >
< component : is = "() => children" / >
< / nuxt-link >
< / template >
< / IntlFormatted >
< / span >
< span class = "text-sm font-medium text-secondary" >
{ { formatMessage ( messages . violationDescription ) } }
< / span >
< / div >
< / div >
2023-11-29 10:56:17 -08:00
< / div >
2025-02-02 14:09:10 -08:00
< div class = "flex flex-col gap-2" >
< h2 class = "m-0 text-lg font-extrabold" > { { formatMessage ( messages . formNotFor ) } } < / h2 >
< div class = "text-md flex items-center gap-2 font-semibold text-contrast" >
< XCircleIcon class = "h-8 w-8 shrink-0 text-brand-red" / >
2025-02-11 11:07:23 -08:00
< div class = "flex flex-col" >
< span > { { formatMessage ( messages . bugReports ) } } < / span >
< span v-if = "itemIssueTracker" class="text-sm font-medium text-secondary" >
< IntlFormatted :message-id = "messages.bugReportsDescription" >
< template # issues -link = " { children } " >
< a class = "text-link" :href = "itemIssueTracker" target = "_blank" >
< component : is = "() => children" / >
< ExternalIcon aria -hidden = " true " class = "mb-1 ml-1 h-2.5 w-2.5" / >
< / a >
< / template >
< / IntlFormatted >
< / span >
< / div >
2025-02-02 14:09:10 -08:00
< / div >
< div class = "text-md flex items-center gap-2 font-semibold text-contrast" >
< XCircleIcon class = "h-8 w-8 shrink-0 text-brand-red" / >
< div class = "flex flex-col" >
< span > { { formatMessage ( messages . dmcaTakedown ) } } < / span >
< span class = "text-sm font-medium text-secondary" >
< IntlFormatted :message-id = "messages.dmcaTakedownDescription" >
< template # policy -link = " { children } " >
< nuxt-link class = "text-link" :to = "`/legal/copyright`" >
< component : is = "() => children" / >
< / nuxt-link >
< / template >
< / IntlFormatted >
< / span >
< / div >
< / div >
2023-11-29 10:56:17 -08:00
< / div >
< / div >
2025-02-02 14:09:10 -08:00
< div class = "flex flex-col gap-4 rounded-xl bg-bg-raised p-6" >
< template v-if = "!prefilled || !currentItemValid" >
< div class = "flex flex-col gap-2" >
< span class = "text-lg font-bold text-contrast" >
{ { formatMessage ( messages . whatContentType ) } }
< / span >
< RadioButtons
v - slot = "{ item }"
v - model = "reportItem"
: items = "reportItems"
@ update : model - value = "
( ) => {
prefilled = false ;
fetchItem ( ) ;
}
"
>
{ { capitalizeString ( item ) } }
< / RadioButtons >
< / div >
< div class = "flex flex-col gap-2" : class = "{ hidden: !reportItem }" >
< span class = "text-lg font-bold text-contrast" >
{ { formatMessage ( messages . whatContentId , { item : reportItem || "content" } ) } }
< / span >
< div class = "flex gap-4" >
< input
id = "report-item-id"
v - model = "reportItemID"
type = "text"
placeholder = "ex: Dc7EYhxG"
autocomplete = "off"
: disabled = "reportItem === ''"
class = "w-40"
@ blur = "
( ) => {
prefilled = false ;
reportItemID = reportItemID . trim ( ) ;
fetchItem ( ) ;
}
"
/ >
< div v-if = "checkingId || checkedId" class="flex items-center gap-1" >
< template v-if = "checkingId" >
< SpinnerIcon class = "animate-spin" / >
{ { formatMessage ( messages . checking , { item : reportItem } ) } } ...
< / template >
< template v-else-if = "checkedId && itemName" >
< AutoLink
: to = "itemLink"
target = "_blank"
class = "flex items-center gap-1 font-bold text-contrast hover:underline"
>
< Avatar
v - if = "typeof itemIcon === 'string'"
: src = "itemIcon"
: alt = "itemName"
size = "24px"
: circle = "reportItem === 'user'"
/ >
< component :is = "itemIcon" v-else-if = "itemIcon" / >
< span > { { itemName } } < / span >
< / AutoLink >
< CheckIcon class = "text-brand-green" / >
< / template >
< span v-else-if = "checkedId" class="contents text-brand-red" >
< IssuesIcon / >
{ { formatMessage ( messages . couldNotFind , { item : reportItem } ) } }
< / span >
< / div >
< / div >
< / div >
< / template >
< template v-if = "existingReport" >
{ {
formatMessage ( messages . alreadyReportedDescription , { item : reportItem || "content" } )
} }
< ButtonStyled color = "brand" >
< nuxt-link :to = "`/dashboard/report/${existingReport.id}`" class = "w-fit" >
{ { formatMessage ( messages . goToReport ) } } < RightArrowIcon / >
< / nuxt-link >
< / ButtonStyled >
< / template >
< template v-else >
< div class = "flex flex-col gap-2" : class = "{ hidden: !reportItemID }" >
< span class = "text-lg font-bold text-contrast" >
{ { formatMessage ( messages . whatReportReason , { item : reportItem || "content" } ) } }
< / span >
< RadioButtons v-slot = "{ item }" v-model="reportType" :items="reportTypes" >
{ { item === "copyright" ? "Reuploaded work" : capitalizeString ( item ) } }
< / RadioButtons >
< / div >
< div
v - if = "warnings[reportType]"
class = "flex gap-2 rounded-xl border-2 border-solid border-brand-orange bg-highlight-orange p-4 text-contrast"
>
< IssuesIcon class = "h-5 w-5 shrink-0 text-orange" / >
< div class = "flex flex-col gap-2" >
< p
v - for = "(warning, index) in warnings[reportType]"
: key = "`warning-${reportType}-${index}`"
class = "m-0 leading-tight"
>
< IntlFormatted :message-id = "warning" >
< template # copyright -policy -link = " { children } " >
< nuxt-link class = "text-link" :to = "`/legal/copyright`" >
< component : is = "() => children" / >
< / nuxt-link >
< / template >
< / IntlFormatted >
< / p >
< / div >
< / div >
< div : class = "{ hidden: !reportType }" >
< span class = "text-lg font-bold text-contrast" >
{ { formatMessage ( messages . reportBodyTitle ) } }
< / span >
< p class = "m-0 leading-tight text-secondary" >
{ { formatMessage ( messages . reportBodyDescription ) } }
< / p >
< / div >
< div : class = "{ hidden: !reportType }" >
< MarkdownEditor
v - model = "reportBody"
placeholder = ""
: on - image - upload = "onImageUpload"
/ >
< / div >
< div : class = "{ hidden: !reportType }" >
< ButtonStyled color = "brand" >
< button
id = "submit-button"
: disabled = "submitLoading || !canSubmit"
@ click = "submitReport"
>
< SendIcon aria -hidden = " true " / >
{ { formatMessage ( messages . submitReport ) } }
< / button >
< / ButtonStyled >
< / div >
< / template >
2023-11-29 10:56:17 -08:00
< / div >
2025-02-02 14:09:10 -08:00
< / template >
< / div >
2023-11-29 10:56:17 -08:00
< / div >
< / template >
< script setup lang = "ts" >
2025-02-02 14:09:10 -08:00
import {
MarkdownEditor ,
RadialHeader ,
RadioButtons ,
ButtonStyled ,
Avatar ,
AutoLink ,
} from "@modrinth/ui" ;
import {
2025-02-11 11:07:23 -08:00
ExternalIcon ,
2025-02-02 14:09:10 -08:00
LeftArrowIcon ,
RightArrowIcon ,
CheckIcon ,
SpinnerIcon ,
SendIcon ,
IssuesIcon ,
CheckCircleIcon ,
XCircleIcon ,
ScaleIcon ,
VersionIcon ,
} from "@modrinth/assets" ;
import type { User , Version , Report } from "@modrinth/utils" ;
import { useVIntl , defineMessages , type MessageDescriptor } from "@vintl/vintl" ;
2024-07-06 20:57:32 -07:00
import { useImageUpload } from "~/composables/image-upload.ts" ;
2023-11-29 10:56:17 -08:00
2024-07-06 20:57:32 -07:00
const tags = useTags ( ) ;
const route = useNativeRoute ( ) ;
App redesign (#2946)
* Start of app redesign
* format
* continue progress
* Content page nearly done
* Fix recursion issues with content page
* Fix update all alignment
* Discover page progress
* Settings progress
* Removed unlocked-size hack that breaks web
* Revamp project page, refactor web project page to share code with app, fixed loading bar, misc UI/UX enhancements, update ko-fi logo, update arrow icons, fix web issues caused by floating-vue migration, fix tooltip issues, update web tooltips, clean up web hydration issues
* Ads + run prettier
* Begin auth refactor, move common messages to ui lib, add i18n extraction to all apps, begin Library refactor
* fix ads not hiding when plus log in
* rev lockfile changes/conflicts
* Fix sign in page
* Add generated
* (mostly) Data driven search
* Fix search mobile issue
* profile fixes
* Project versions page, fix typescript on UI lib and misc fixes
* Remove unused gallery component
* Fix linkfunction err
* Search filter controls at top, localization for locked filters
* Fix provided filter names
* Fix navigating from instance browse to main browse
* Friends frontend (#2995)
* Friends system frontend
* (almost) finish frontend
* finish friends, fix lint
* Fix lint
---------
Signed-off-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
* Refresh macOS app icon
* Update web search UI more
* Fix link opens
* Fix frontend build
---------
Signed-off-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
Co-authored-by: Jai A <jaiagr+gpg@pm.me>
Co-authored-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
2024-12-11 19:54:18 -08:00
const router = useRouter ( ) ;
const auth = await useAuth ( ) ;
2025-02-02 14:09:10 -08:00
const { formatMessage } = useVIntl ( ) ;
App redesign (#2946)
* Start of app redesign
* format
* continue progress
* Content page nearly done
* Fix recursion issues with content page
* Fix update all alignment
* Discover page progress
* Settings progress
* Removed unlocked-size hack that breaks web
* Revamp project page, refactor web project page to share code with app, fixed loading bar, misc UI/UX enhancements, update ko-fi logo, update arrow icons, fix web issues caused by floating-vue migration, fix tooltip issues, update web tooltips, clean up web hydration issues
* Ads + run prettier
* Begin auth refactor, move common messages to ui lib, add i18n extraction to all apps, begin Library refactor
* fix ads not hiding when plus log in
* rev lockfile changes/conflicts
* Fix sign in page
* Add generated
* (mostly) Data driven search
* Fix search mobile issue
* profile fixes
* Project versions page, fix typescript on UI lib and misc fixes
* Remove unused gallery component
* Fix linkfunction err
* Search filter controls at top, localization for locked filters
* Fix provided filter names
* Fix navigating from instance browse to main browse
* Friends frontend (#2995)
* Friends system frontend
* (almost) finish frontend
* finish friends, fix lint
* Fix lint
---------
Signed-off-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
* Refresh macOS app icon
* Update web search UI more
* Fix link opens
* Fix frontend build
---------
Signed-off-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
Co-authored-by: Jai A <jaiagr+gpg@pm.me>
Co-authored-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
2024-12-11 19:54:18 -08:00
if ( ! auth . value . user ) {
router . push ( "/auth/sign-in?redirect=" + encodeURIComponent ( route . fullPath ) ) ;
}
2023-11-29 10:56:17 -08:00
const accessQuery = ( id : string ) : string => {
2024-07-06 20:57:32 -07:00
return route . query ? . [ id ] ? . toString ( ) || "" ;
} ;
2023-11-29 10:56:17 -08:00
2024-07-06 20:57:32 -07:00
const submitLoading = ref < boolean > ( false ) ;
2023-11-29 10:56:17 -08:00
2024-07-06 20:57:32 -07:00
const uploadedImageIDs = ref < string [ ] > ( [ ] ) ;
2023-11-29 10:56:17 -08:00
2024-07-06 20:57:32 -07:00
const reportBody = ref < string > ( accessQuery ( "body" ) ) ;
const reportItem = ref < string > ( accessQuery ( "item" ) ) ;
const reportItemID = ref < string > ( accessQuery ( "itemID" ) ) ;
const reportType = ref < string > ( "" ) ;
2023-11-29 10:56:17 -08:00
2025-02-02 14:09:10 -08:00
const prefilled = ref < boolean > ( ! ! reportItem . value && ! ! reportItemID . value ) ;
const checkedId = ref < boolean > ( false ) ;
const checkingId = ref < boolean > ( false ) ;
const currentProject = ref < Project | null > ( null ) ;
const currentVersion = ref < Version | null > ( null ) ;
const currentUser = ref < User | null > ( null ) ;
const itemIcon = ref < string | Component | undefined > ( ) ;
const itemName = ref < string | undefined > ( ) ;
const itemLink = ref < string | undefined > ( ) ;
const itemId = ref < string | undefined > ( ) ;
2025-02-11 11:07:23 -08:00
const itemIssueTracker = ref < string | undefined > ( ) ;
2025-02-02 14:09:10 -08:00
const reports = ref < Report [ ] > ( [ ] ) ;
const existingReport = computed ( ( ) =>
reports . value . find (
( x ) =>
( x . item _id === reportItemID . value || x . item _id === itemId . value ) &&
x . item _type === reportItem . value ,
) ,
) ;
await fetchItem ( ) ;
await fetchExistingReports ( ) ;
const currentItemValid = computed (
( ) => ! ! currentProject . value || ! ! currentVersion . value || ! ! currentUser . value ,
) ;
async function fetchExistingReports ( ) {
reports . value = ( ( await useBaseFetch ( "report?count=1000" ) ) as Report [ ] ) . filter (
( x ) => x . reporter === auth . value . user ? . id ,
) ;
}
async function fetchItem ( ) {
if ( reportItem . value && reportItemID . value ) {
checkingId . value = true ;
itemIcon . value = undefined ;
itemName . value = undefined ;
itemLink . value = undefined ;
itemId . value = undefined ;
2025-02-11 11:07:23 -08:00
itemIssueTracker . value = undefined ;
2025-02-02 14:09:10 -08:00
try {
if ( reportItem . value === "project" ) {
const project = ( await useBaseFetch ( ` project/ ${ reportItemID . value } ` ) ) as Project ;
currentProject . value = project ;
itemIcon . value = project . icon _url ;
itemName . value = project . title ;
itemLink . value = ` /project/ ${ project . id } ` ;
itemId . value = project . id ;
2025-02-11 11:07:23 -08:00
itemIssueTracker . value = project . issues _url ;
2025-02-02 14:09:10 -08:00
} else if ( reportItem . value === "version" ) {
const version = ( await useBaseFetch ( ` version/ ${ reportItemID . value } ` ) ) as Version ;
currentVersion . value = version ;
itemIcon . value = VersionIcon ;
itemName . value = version . version _number ;
itemLink . value = ` project/ ${ version . project _id } /version/ ${ version . id } ` ;
itemId . value = version . id ;
} else if ( reportItem . value === "user" ) {
const user = ( await useBaseFetch ( ` user/ ${ reportItemID . value } ` ) ) as User ;
currentUser . value = user ;
itemIcon . value = user . avatar _url ;
itemName . value = user . username ;
itemLink . value = ` /user/ ${ user . username } ` ;
itemId . value = user . id ;
}
} catch { }
checkedId . value = true ;
checkingId . value = false ;
}
}
2024-07-06 20:57:32 -07:00
const reportItems = [ "project" , "version" , "user" ] ;
const reportTypes = computed ( ( ) => tags . value . reportTypes ) ;
2023-11-29 10:56:17 -08:00
const canSubmit = computed ( ( ) => {
return (
2024-07-06 20:57:32 -07:00
reportItem . value !== "" &&
reportItemID . value !== "" &&
reportType . value !== "" &&
reportBody . value !== ""
) ;
} ) ;
2023-11-29 10:56:17 -08:00
const submissionValidation = ( ) => {
if ( ! canSubmit . value ) {
2024-07-06 20:57:32 -07:00
throw new Error ( "Please fill out all required fields" ) ;
2023-11-29 10:56:17 -08:00
}
2024-07-06 20:57:32 -07:00
if ( reportItem . value === "" ) {
throw new Error ( "Please select a report item" ) ;
2023-11-29 10:56:17 -08:00
}
2024-07-06 20:57:32 -07:00
if ( reportItemID . value === "" ) {
throw new Error ( "Please enter a report item ID" ) ;
2023-11-29 10:56:17 -08:00
}
2024-07-06 20:57:32 -07:00
if ( reportType . value === "" ) {
throw new Error ( "Please select a report type" ) ;
2023-11-29 10:56:17 -08:00
}
2024-07-06 20:57:32 -07:00
if ( reportBody . value === "" ) {
throw new Error ( "Please enter a report body" ) ;
2023-11-29 10:56:17 -08:00
}
2024-07-06 20:57:32 -07:00
return true ;
} ;
2023-11-29 10:56:17 -08:00
const capitalizeString = ( value ? : string ) => {
2024-07-06 20:57:32 -07:00
if ( ! value ) return "" ;
return value ? . charAt ( 0 ) . toUpperCase ( ) + value ? . slice ( 1 ) ;
} ;
2023-11-29 10:56:17 -08:00
const submitReport = async ( ) => {
2024-07-06 20:57:32 -07:00
submitLoading . value = true ;
2023-11-29 10:56:17 -08:00
let data : {
2024-07-06 20:57:32 -07:00
[ key : string ] : unknown ;
2023-11-29 10:56:17 -08:00
} = {
report _type : reportType . value ,
item _type : reportItem . value ,
item _id : reportItemID . value ,
body : reportBody . value ,
2024-07-06 20:57:32 -07:00
} ;
2023-11-29 10:56:17 -08:00
function takeNLast < T > ( arr : T [ ] , n : number ) : T [ ] {
2024-07-06 20:57:32 -07:00
return arr . slice ( Math . max ( arr . length - n , 0 ) ) ;
2023-11-29 10:56:17 -08:00
}
if ( uploadedImageIDs . value . length > 0 ) {
data = {
... data ,
uploaded _images : takeNLast ( uploadedImageIDs . value , 10 ) ,
2024-07-06 20:57:32 -07:00
} ;
2023-11-29 10:56:17 -08:00
}
try {
2024-07-06 20:57:32 -07:00
submissionValidation ( ) ;
2023-11-29 10:56:17 -08:00
} catch ( error ) {
2024-07-06 20:57:32 -07:00
submitLoading . value = false ;
2023-11-29 10:56:17 -08:00
if ( error instanceof Error ) {
addNotification ( {
2024-07-06 20:57:32 -07:00
group : "main" ,
title : "An error occurred" ,
2023-11-29 10:56:17 -08:00
text : error . message ,
2024-07-06 20:57:32 -07:00
type : "error" ,
} ) ;
2023-11-29 10:56:17 -08:00
}
2024-07-06 20:57:32 -07:00
return ;
2023-11-29 10:56:17 -08:00
}
try {
2024-07-06 20:57:32 -07:00
const response = ( await useBaseFetch ( "report" , {
method : "POST" ,
2023-11-29 10:56:17 -08:00
body : data ,
2024-07-06 20:57:32 -07:00
} ) ) as { id : string } ;
2023-11-29 10:56:17 -08:00
2024-07-06 20:57:32 -07:00
submitLoading . value = false ;
2023-11-29 10:56:17 -08:00
if ( response ? . id ) {
2024-07-06 20:57:32 -07:00
navigateTo ( ` /dashboard/report/ ${ response . id } ` ) ;
2023-11-29 10:56:17 -08:00
}
} catch ( error ) {
2024-07-06 20:57:32 -07:00
submitLoading . value = false ;
2023-11-29 10:56:17 -08:00
if ( error instanceof Error ) {
addNotification ( {
2024-07-06 20:57:32 -07:00
group : "main" ,
title : "An error occurred" ,
2023-11-29 10:56:17 -08:00
text : error . message ,
2024-07-06 20:57:32 -07:00
type : "error" ,
} ) ;
2023-11-29 10:56:17 -08:00
}
2024-07-06 20:57:32 -07:00
throw error ;
2023-11-29 10:56:17 -08:00
}
2024-07-06 20:57:32 -07:00
} ;
2023-11-29 10:56:17 -08:00
const onImageUpload = async ( file : File ) => {
2024-07-06 20:57:32 -07:00
const item = await useImageUpload ( file , { context : "report" } ) ;
uploadedImageIDs . value . push ( item . id ) ;
return item . url ;
} ;
2023-11-29 10:56:17 -08:00
2025-02-02 14:09:10 -08:00
const warnings : Record < string , MessageDescriptor [ ] > = {
copyright : [
defineMessage ( {
id : "report.note.copyright.1" ,
defaultMessage :
"Please note that you are *not* submitting a DMCA takedown request, but rather a report of reuploaded content." ,
} ) ,
defineMessage ( {
id : "report.note.copyright.2" ,
defaultMessage :
"If you meant to file a DMCA takedown request (which is a legal action) instead, please see our <copyright-policy-link>Copyright Policy</copyright-policy-link>." ,
} ) ,
] ,
malicious : [
defineMessage ( {
id : "report.note.malicious.1" ,
defaultMessage :
"Reports for malicious or deceptive content must include substantial evidence of the behavior, such as code samples." ,
} ) ,
defineMessage ( {
id : "report.note.malicious.2" ,
defaultMessage :
"Summaries from Microsoft Defender, VirusTotal, or AI malware detection are not sufficient forms of evidence and will not be accepted." ,
} ) ,
] ,
} ;
2023-11-29 10:56:17 -08:00
2025-02-02 14:09:10 -08:00
const messages = defineMessages ( {
reportContent : {
id : "report.report-content" ,
defaultMessage : "Report content to moderators" ,
} ,
reportItem : {
id : "report.report-item" ,
defaultMessage : "Report {title} to moderators" ,
} ,
alreadyReportedItem : {
id : "report.already-reported" ,
defaultMessage : "You've already reported {title}" ,
} ,
alreadyReportedDescription : {
id : "report.already-reported-description" ,
defaultMessage :
"You have an open report for this {item} already. You can add more details to your report if you have more information to add." ,
} ,
backToItem : {
id : "report.back-to-item" ,
defaultMessage : "Back to {item}" ,
} ,
goToReport : {
id : "report.go-to-report" ,
defaultMessage : "Go to report" ,
} ,
pleaseReport : {
id : "report.please-report" ,
defaultMessage : "Please report:" ,
} ,
formNotFor : {
id : "report.form-not-for" ,
defaultMessage : "This form is not for:" ,
} ,
violation : {
id : "report.for.violation" ,
defaultMessage :
"Violation of Modrinth <rules-link>Rules</rules-link> or <terms-link>Terms of Use</terms-link>" ,
} ,
violationDescription : {
id : "report.for.violation.description" ,
defaultMessage :
"Examples include malicious, spam, offensive, deceptive, misleading, and illegal content." ,
} ,
bugReports : {
id : "report.not-for.bug-reports" ,
defaultMessage : "Bug reports" ,
} ,
2025-02-11 11:07:23 -08:00
bugReportsDescription : {
id : "report.not-for.bug-reports.description" ,
defaultMessage : "You can report bugs to their <issues-link>issue tracker</issues-link>." ,
} ,
2025-02-02 14:09:10 -08:00
dmcaTakedown : {
id : "report.not-for.dmca" ,
defaultMessage : "DMCA takedowns" ,
} ,
dmcaTakedownDescription : {
id : "report.not-for.dmca.description" ,
defaultMessage : "See our <policy-link>Copyright Policy</policy-link>." ,
} ,
whatContentType : {
id : "report.question.content-type" ,
defaultMessage : "What type of content are you reporting?" ,
} ,
whatContentId : {
id : "report.question.content-id" ,
defaultMessage : "What is the ID of the {item}?" ,
} ,
whatReportReason : {
id : "report.question.report-reason" ,
defaultMessage : "Which of Modrinth's rules is this {item} violating?" ,
} ,
checking : {
id : "report.checking" ,
defaultMessage : "Checking {item}..." ,
} ,
couldNotFind : {
id : "report.could-not-find" ,
defaultMessage : "Could not find {item}" ,
} ,
reportBodyTitle : {
id : "report.body.title" ,
defaultMessage : "Please provide additional context about your report" ,
} ,
reportBodyDescription : {
id : "report.body.description" ,
defaultMessage :
"Include links and images if possible and relevant. Empty or insufficient reports will be closed and ignored." ,
} ,
submitReport : {
id : "report.submit" ,
defaultMessage : "Submit report" ,
} ,
} ) ;
< / script >
2023-11-29 10:56:17 -08:00
2025-02-02 14:09:10 -08:00
< style scoped lang = "scss" >
2023-11-29 10:56:17 -08:00
. page {
2025-02-11 12:46:34 -08:00
padding : 1 rem ;
2023-11-29 10:56:17 -08:00
margin - left : auto ;
margin - right : auto ;
max - width : 56 rem ;
}
< / style >