You've already forked AstralRinth
forked from didirus/AstralRinth
@@ -1112,6 +1112,12 @@
|
|||||||
"moderation.technical.search.placeholder": {
|
"moderation.technical.search.placeholder": {
|
||||||
"message": "Search tech reviews..."
|
"message": "Search tech reviews..."
|
||||||
},
|
},
|
||||||
|
"profile.bio.fallback.creator": {
|
||||||
|
"message": "A Modrinth creator."
|
||||||
|
},
|
||||||
|
"profile.bio.fallback.user": {
|
||||||
|
"message": "A Modrinth user."
|
||||||
|
},
|
||||||
"profile.button.billing": {
|
"profile.button.billing": {
|
||||||
"message": "Manage user billing"
|
"message": "Manage user billing"
|
||||||
},
|
},
|
||||||
@@ -1124,18 +1130,48 @@
|
|||||||
"profile.button.manage-projects": {
|
"profile.button.manage-projects": {
|
||||||
"message": "Manage projects"
|
"message": "Manage projects"
|
||||||
},
|
},
|
||||||
|
"profile.details.label.auth-providers": {
|
||||||
|
"message": "Auth providers"
|
||||||
|
},
|
||||||
|
"profile.details.label.email": {
|
||||||
|
"message": "Email"
|
||||||
|
},
|
||||||
|
"profile.details.label.has-password": {
|
||||||
|
"message": "Has password"
|
||||||
|
},
|
||||||
|
"profile.details.label.has-totp": {
|
||||||
|
"message": "Has TOTP"
|
||||||
|
},
|
||||||
|
"profile.details.label.payment-methods": {
|
||||||
|
"message": "Payment methods"
|
||||||
|
},
|
||||||
|
"profile.details.tooltip.email-not-verified": {
|
||||||
|
"message": "Email not verified"
|
||||||
|
},
|
||||||
|
"profile.details.tooltip.email-verified": {
|
||||||
|
"message": "Email verified"
|
||||||
|
},
|
||||||
"profile.error.not-found": {
|
"profile.error.not-found": {
|
||||||
"message": "User not found"
|
"message": "User not found"
|
||||||
},
|
},
|
||||||
"profile.joined-at": {
|
|
||||||
"message": "Joined <date>{ago}</date>"
|
|
||||||
},
|
|
||||||
"profile.label.badges": {
|
"profile.label.badges": {
|
||||||
"message": "Badges"
|
"message": "Badges"
|
||||||
},
|
},
|
||||||
|
"profile.label.collection": {
|
||||||
|
"message": "Collection"
|
||||||
|
},
|
||||||
"profile.label.details": {
|
"profile.label.details": {
|
||||||
"message": "Details"
|
"message": "Details"
|
||||||
},
|
},
|
||||||
|
"profile.label.downloads": {
|
||||||
|
"message": "{count} {count, plural, one {download} other {downloads}}"
|
||||||
|
},
|
||||||
|
"profile.label.joined": {
|
||||||
|
"message": "Joined"
|
||||||
|
},
|
||||||
|
"profile.label.no": {
|
||||||
|
"message": "No"
|
||||||
|
},
|
||||||
"profile.label.no-collections": {
|
"profile.label.no-collections": {
|
||||||
"message": "This user has no collections!"
|
"message": "This user has no collections!"
|
||||||
},
|
},
|
||||||
@@ -1151,18 +1187,21 @@
|
|||||||
"profile.label.organizations": {
|
"profile.label.organizations": {
|
||||||
"message": "Organizations"
|
"message": "Organizations"
|
||||||
},
|
},
|
||||||
|
"profile.label.projects": {
|
||||||
|
"message": "{count} {count, plural, one {project} other {projects}}"
|
||||||
|
},
|
||||||
|
"profile.label.saving": {
|
||||||
|
"message": "Saving..."
|
||||||
|
},
|
||||||
|
"profile.label.yes": {
|
||||||
|
"message": "Yes"
|
||||||
|
},
|
||||||
"profile.meta.description": {
|
"profile.meta.description": {
|
||||||
"message": "Download {username}'s projects on Modrinth"
|
"message": "Download {username}'s projects on Modrinth"
|
||||||
},
|
},
|
||||||
"profile.meta.description-with-bio": {
|
"profile.meta.description-with-bio": {
|
||||||
"message": "{bio} - Download {username}'s projects on Modrinth"
|
"message": "{bio} - Download {username}'s projects on Modrinth"
|
||||||
},
|
},
|
||||||
"profile.stats.downloads": {
|
|
||||||
"message": "{count, plural, one {<stat>{count}</stat> project download} other {<stat>{count}</stat> project downloads}}"
|
|
||||||
},
|
|
||||||
"profile.stats.projects": {
|
|
||||||
"message": "{count, plural, one {<stat>{count}</stat> project} other {<stat>{count}</stat> projects}}"
|
|
||||||
},
|
|
||||||
"profile.stats.projects-followers": {
|
"profile.stats.projects-followers": {
|
||||||
"message": "{count, plural, one {<stat>{count}</stat> project follower} other {<stat>{count}</stat> project followers}}"
|
"message": "{count, plural, one {<stat>{count}</stat> project follower} other {<stat>{count}</stat> project followers}}"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
<ButtonStyled>
|
<ButtonStyled>
|
||||||
<button @click="cancelRoleEdit">
|
<button @click="cancelRoleEdit">
|
||||||
<XIcon />
|
<XIcon />
|
||||||
Cancel
|
{{ formatMessage(commonMessages.cancelButton) }}
|
||||||
</button>
|
</button>
|
||||||
</ButtonStyled>
|
</ButtonStyled>
|
||||||
<ButtonStyled color="brand">
|
<ButtonStyled color="brand">
|
||||||
@@ -25,9 +25,11 @@
|
|||||||
@click="saveRoleEdit"
|
@click="saveRoleEdit"
|
||||||
>
|
>
|
||||||
<template v-if="isSavingRole">
|
<template v-if="isSavingRole">
|
||||||
<SpinnerIcon class="animate-spin" /> Saving...
|
<SpinnerIcon class="animate-spin" /> {{ formatMessage(messages.savingLabel) }}
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<SaveIcon /> {{ formatMessage(commonMessages.saveChangesButton) }}
|
||||||
</template>
|
</template>
|
||||||
<template v-else> <SaveIcon /> Save changes </template>
|
|
||||||
</button>
|
</button>
|
||||||
</ButtonStyled>
|
</ButtonStyled>
|
||||||
</div>
|
</div>
|
||||||
@@ -36,10 +38,16 @@
|
|||||||
<NewModal v-if="auth.user && isStaff(auth.user)" ref="userDetailsModal" header="User details">
|
<NewModal v-if="auth.user && isStaff(auth.user)" ref="userDetailsModal" header="User details">
|
||||||
<div class="flex flex-col gap-3">
|
<div class="flex flex-col gap-3">
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<span class="text-lg font-bold text-primary">Email</span>
|
<span class="text-lg font-bold text-primary">{{
|
||||||
|
formatMessage(messages.emailLabel)
|
||||||
|
}}</span>
|
||||||
<div>
|
<div>
|
||||||
<span
|
<span
|
||||||
v-tooltip="user.email_verified ? 'Email verified' : 'Email not verified'"
|
v-tooltip="
|
||||||
|
user.email_verified
|
||||||
|
? formatMessage(messages.emailVerifiedTooltip)
|
||||||
|
: formatMessage(messages.emailNotVerifiedTooltip)
|
||||||
|
"
|
||||||
class="flex w-fit items-center gap-1"
|
class="flex w-fit items-center gap-1"
|
||||||
>
|
>
|
||||||
<span>{{ user.email }}</span>
|
<span>{{ user.email }}</span>
|
||||||
@@ -50,12 +58,16 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<span class="text-lg font-bold text-primary"> Auth providers </span>
|
<span class="text-lg font-bold text-primary">{{
|
||||||
|
formatMessage(messages.authProvidersLabel)
|
||||||
|
}}</span>
|
||||||
<span>{{ user.auth_providers.join(', ') }}</span>
|
<span>{{ user.auth_providers.join(', ') }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<span class="text-lg font-bold text-primary"> Payment methods</span>
|
<span class="text-lg font-bold text-primary">{{
|
||||||
|
formatMessage(messages.paymentMethodsLabel)
|
||||||
|
}}</span>
|
||||||
<span>
|
<span>
|
||||||
<template v-if="user.payout_data?.paypal_address">
|
<template v-if="user.payout_data?.paypal_address">
|
||||||
Paypal ({{ user.payout_data.paypal_address }} - {{ user.payout_data.paypal_country }})
|
Paypal ({{ user.payout_data.paypal_address }} - {{ user.payout_data.paypal_country }})
|
||||||
@@ -70,16 +82,22 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<span class="text-lg font-bold text-primary"> Has password </span>
|
<span class="text-lg font-bold text-primary">{{
|
||||||
|
formatMessage(messages.hasPasswordLabel)
|
||||||
|
}}</span>
|
||||||
<span>
|
<span>
|
||||||
{{ user.has_password ? 'Yes' : 'No' }}
|
{{
|
||||||
|
user.has_password ? formatMessage(messages.yesLabel) : formatMessage(messages.noLabel)
|
||||||
|
}}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<span class="text-lg font-bold text-primary"> Has TOTP </span>
|
<span class="text-lg font-bold text-primary">{{
|
||||||
|
formatMessage(messages.hasTotpLabel)
|
||||||
|
}}</span>
|
||||||
<span>
|
<span>
|
||||||
{{ user.has_totp ? 'Yes' : 'No' }}
|
{{ user.has_totp ? formatMessage(messages.yesLabel) : formatMessage(messages.noLabel) }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -98,8 +116,8 @@
|
|||||||
user.bio
|
user.bio
|
||||||
? user.bio
|
? user.bio
|
||||||
: projects.length === 0
|
: projects.length === 0
|
||||||
? 'A Modrinth user.'
|
? formatMessage(messages.bioFallbackUser)
|
||||||
: 'A Modrinth creator.'
|
: formatMessage(messages.bioFallbackCreator)
|
||||||
}}
|
}}
|
||||||
</template>
|
</template>
|
||||||
<template #stats>
|
<template #stats>
|
||||||
@@ -107,16 +125,22 @@
|
|||||||
class="flex items-center gap-2 border-0 border-r border-solid border-divider pr-4 font-semibold"
|
class="flex items-center gap-2 border-0 border-r border-solid border-divider pr-4 font-semibold"
|
||||||
>
|
>
|
||||||
<BoxIcon class="h-6 w-6 text-secondary" />
|
<BoxIcon class="h-6 w-6 text-secondary" />
|
||||||
{{ formatCompactNumber(projects?.length || 0) }}
|
{{
|
||||||
projects
|
formatMessage(messages.profileProjectsLabel, {
|
||||||
|
count: formatCompactNumber(projects?.length || 0),
|
||||||
|
})
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-tooltip="sumDownloads.toLocaleString()"
|
v-tooltip="sumDownloads.toLocaleString()"
|
||||||
class="flex items-center gap-2 border-0 border-r border-solid border-divider pr-4 font-semibold"
|
class="flex items-center gap-2 border-0 border-r border-solid border-divider pr-4 font-semibold"
|
||||||
>
|
>
|
||||||
<DownloadIcon class="h-6 w-6 text-secondary" />
|
<DownloadIcon class="h-6 w-6 text-secondary" />
|
||||||
{{ formatCompactNumber(sumDownloads) }}
|
{{
|
||||||
downloads
|
formatMessage(messages.profileDownloadsLabel, {
|
||||||
|
count: formatCompactNumber(sumDownloads),
|
||||||
|
})
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-tooltip="
|
v-tooltip="
|
||||||
@@ -128,7 +152,7 @@
|
|||||||
class="flex items-center gap-2 font-semibold"
|
class="flex items-center gap-2 font-semibold"
|
||||||
>
|
>
|
||||||
<CalendarIcon class="h-6 w-6 text-secondary" />
|
<CalendarIcon class="h-6 w-6 text-secondary" />
|
||||||
Joined
|
{{ formatMessage(messages.profileJoinedLabel) }}
|
||||||
{{ formatRelativeTime(user.created) }}
|
{{ formatRelativeTime(user.created) }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -287,7 +311,7 @@
|
|||||||
<h2 class="title">{{ collection.name }}</h2>
|
<h2 class="title">{{ collection.name }}</h2>
|
||||||
<div class="stats">
|
<div class="stats">
|
||||||
<LibraryIcon aria-hidden="true" />
|
<LibraryIcon aria-hidden="true" />
|
||||||
Collection
|
{{ formatMessage(messages.collectionLabel) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -298,25 +322,27 @@
|
|||||||
<div class="stats">
|
<div class="stats">
|
||||||
<BoxIcon />
|
<BoxIcon />
|
||||||
{{
|
{{
|
||||||
`${$formatNumber(collection.projects?.length || 0, false)} project${(collection.projects?.length || 0) !== 1 ? 's' : ''}`
|
`${$formatNumber(collection.projects?.length || 0, false)} project${
|
||||||
|
(collection.projects?.length || 0) !== 1 ? 's' : ''
|
||||||
|
}`
|
||||||
}}
|
}}
|
||||||
</div>
|
</div>
|
||||||
<div class="stats">
|
<div class="stats">
|
||||||
<template v-if="collection.status === 'listed'">
|
<template v-if="collection.status === 'listed'">
|
||||||
<GlobeIcon />
|
<GlobeIcon />
|
||||||
<span> Public </span>
|
<span> {{ formatMessage(commonMessages.publicLabel) }} </span>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="collection.status === 'unlisted'">
|
<template v-else-if="collection.status === 'unlisted'">
|
||||||
<LinkIcon />
|
<LinkIcon />
|
||||||
<span> Unlisted </span>
|
<span> {{ formatMessage(commonMessages.unlistedLabel) }} </span>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="collection.status === 'private'">
|
<template v-else-if="collection.status === 'private'">
|
||||||
<LockIcon />
|
<LockIcon />
|
||||||
<span> Private </span>
|
<span> {{ formatMessage(commonMessages.privateLabel) }} </span>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="collection.status === 'rejected'">
|
<template v-else-if="collection.status === 'rejected'">
|
||||||
<XIcon />
|
<XIcon />
|
||||||
<span> Rejected </span>
|
<span> {{ formatMessage(commonMessages.rejectedLabel) }} </span>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -450,25 +476,75 @@ const formatRelativeTime = useRelativeTime()
|
|||||||
const { addNotification } = injectNotificationManager()
|
const { addNotification } = injectNotificationManager()
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
profileProjectsStats: {
|
profileProjectsLabel: {
|
||||||
id: 'profile.stats.projects',
|
id: 'profile.label.projects',
|
||||||
defaultMessage:
|
defaultMessage: '{count} {count, plural, one {project} other {projects}}',
|
||||||
'{count, plural, one {<stat>{count}</stat> project} other {<stat>{count}</stat> projects}}',
|
|
||||||
},
|
},
|
||||||
profileDownloadsStats: {
|
profileDownloadsLabel: {
|
||||||
id: 'profile.stats.downloads',
|
id: 'profile.label.downloads',
|
||||||
defaultMessage:
|
defaultMessage: '{count} {count, plural, one {download} other {downloads}}',
|
||||||
'{count, plural, one {<stat>{count}</stat> project download} other {<stat>{count}</stat> project downloads}}',
|
},
|
||||||
|
profileJoinedLabel: {
|
||||||
|
id: 'profile.label.joined',
|
||||||
|
defaultMessage: 'Joined',
|
||||||
|
},
|
||||||
|
savingLabel: {
|
||||||
|
id: 'profile.label.saving',
|
||||||
|
defaultMessage: 'Saving...',
|
||||||
|
},
|
||||||
|
emailLabel: {
|
||||||
|
id: 'profile.details.label.email',
|
||||||
|
defaultMessage: 'Email',
|
||||||
|
},
|
||||||
|
emailVerifiedTooltip: {
|
||||||
|
id: 'profile.details.tooltip.email-verified',
|
||||||
|
defaultMessage: 'Email verified',
|
||||||
|
},
|
||||||
|
emailNotVerifiedTooltip: {
|
||||||
|
id: 'profile.details.tooltip.email-not-verified',
|
||||||
|
defaultMessage: 'Email not verified',
|
||||||
|
},
|
||||||
|
authProvidersLabel: {
|
||||||
|
id: 'profile.details.label.auth-providers',
|
||||||
|
defaultMessage: 'Auth providers',
|
||||||
|
},
|
||||||
|
paymentMethodsLabel: {
|
||||||
|
id: 'profile.details.label.payment-methods',
|
||||||
|
defaultMessage: 'Payment methods',
|
||||||
|
},
|
||||||
|
hasPasswordLabel: {
|
||||||
|
id: 'profile.details.label.has-password',
|
||||||
|
defaultMessage: 'Has password',
|
||||||
|
},
|
||||||
|
hasTotpLabel: {
|
||||||
|
id: 'profile.details.label.has-totp',
|
||||||
|
defaultMessage: 'Has TOTP',
|
||||||
|
},
|
||||||
|
yesLabel: {
|
||||||
|
id: 'profile.label.yes',
|
||||||
|
defaultMessage: 'Yes',
|
||||||
|
},
|
||||||
|
noLabel: {
|
||||||
|
id: 'profile.label.no',
|
||||||
|
defaultMessage: 'No',
|
||||||
|
},
|
||||||
|
bioFallbackUser: {
|
||||||
|
id: 'profile.bio.fallback.user',
|
||||||
|
defaultMessage: 'A Modrinth user.',
|
||||||
|
},
|
||||||
|
bioFallbackCreator: {
|
||||||
|
id: 'profile.bio.fallback.creator',
|
||||||
|
defaultMessage: 'A Modrinth creator.',
|
||||||
|
},
|
||||||
|
collectionLabel: {
|
||||||
|
id: 'profile.label.collection',
|
||||||
|
defaultMessage: 'Collection',
|
||||||
},
|
},
|
||||||
profileProjectsFollowersStats: {
|
profileProjectsFollowersStats: {
|
||||||
id: 'profile.stats.projects-followers',
|
id: 'profile.stats.projects-followers',
|
||||||
defaultMessage:
|
defaultMessage:
|
||||||
'{count, plural, one {<stat>{count}</stat> project follower} other {<stat>{count}</stat> project followers}}',
|
'{count, plural, one {<stat>{count}</stat> project follower} other {<stat>{count}</stat> project followers}}',
|
||||||
},
|
},
|
||||||
profileJoinedAt: {
|
|
||||||
id: 'profile.joined-at',
|
|
||||||
defaultMessage: 'Joined <date>{ago}</date>',
|
|
||||||
},
|
|
||||||
profileUserId: {
|
profileUserId: {
|
||||||
id: 'profile.user-id',
|
id: 'profile.user-id',
|
||||||
defaultMessage: 'User ID: {id}',
|
defaultMessage: 'User ID: {id}',
|
||||||
|
|||||||
Reference in New Issue
Block a user