Add translation keys for collections (#1496)
* Begin Work * Add more common messages * Work on modal * Add more keys * Add keys for icon buttons * Add more keys * Handle error keys * Add more keys * Add more keys * Edit fields keys * Finish (almost) * Finish work for collection page * Dashboard Nav stack & Format * WIP * Move some messages to common * Finish work * Format * Reorganization * Fix some mistake * add common collections label * Add collections label key to default layout * Make title and description reactive (#8) --------- Co-authored-by: Sasha Sorokin <10401817+brawaru@users.noreply.github.com>
This commit is contained in:
parent
0195e94aa7
commit
52b299315d
@ -99,7 +99,7 @@
|
||||
<hr class="divider" />
|
||||
<NuxtLink class="item button-transparent" to="/dashboard/collections">
|
||||
<LibraryIcon class="icon" />
|
||||
<span class="title">Collections</span>
|
||||
<span class="title">{{ formatMessage(commonMessages.collectionsLabel) }}</span>
|
||||
</NuxtLink>
|
||||
<NuxtLink class="item button-transparent" to="/dashboard/notifications">
|
||||
<NotificationIcon class="icon" />
|
||||
@ -398,6 +398,8 @@ import NavRow from '~/components/ui/NavRow.vue'
|
||||
import ModalCreation from '~/components/ui/ModalCreation.vue'
|
||||
import Avatar from '~/components/ui/Avatar.vue'
|
||||
|
||||
const { formatMessage } = useVIntl()
|
||||
|
||||
const app = useNuxtApp()
|
||||
const auth = await useAuth()
|
||||
const cosmetics = useCosmetics()
|
||||
|
||||
@ -26,6 +26,78 @@
|
||||
"button.save": {
|
||||
"message": "Save"
|
||||
},
|
||||
"collection.button.delete-icon": {
|
||||
"message": "Delete icon"
|
||||
},
|
||||
"collection.button.edit-icon": {
|
||||
"message": "Edit icon"
|
||||
},
|
||||
"collection.button.remove-project": {
|
||||
"message": "Remove project"
|
||||
},
|
||||
"collection.button.unfollow-project": {
|
||||
"message": "Unfollow project"
|
||||
},
|
||||
"collection.button.upload-icon": {
|
||||
"message": "Upload icon"
|
||||
},
|
||||
"collection.delete-modal.description": {
|
||||
"message": "This will remove this collection forever. This action cannot be undone."
|
||||
},
|
||||
"collection.delete-modal.title": {
|
||||
"message": "Are you sure you want to delete this collection?"
|
||||
},
|
||||
"collection.description": {
|
||||
"message": "{description} - View the collection {name} by {username} on Modrinth"
|
||||
},
|
||||
"collection.description.following": {
|
||||
"message": "Auto-generated collection of all the projects you're following."
|
||||
},
|
||||
"collection.error.not-found": {
|
||||
"message": "Collection not found"
|
||||
},
|
||||
"collection.label.collection": {
|
||||
"message": "Collection"
|
||||
},
|
||||
"collection.label.created-at": {
|
||||
"message": "Created {ago}"
|
||||
},
|
||||
"collection.label.curated-by": {
|
||||
"message": "Curated by"
|
||||
},
|
||||
"collection.label.no-projects": {
|
||||
"message": "This collection has no projects!"
|
||||
},
|
||||
"collection.label.no-projects-auth": {
|
||||
"message": "You don't have any projects.\nWould you like to <create-link>add one</create-link>?"
|
||||
},
|
||||
"collection.label.owner": {
|
||||
"message": "Owner"
|
||||
},
|
||||
"collection.label.private": {
|
||||
"message": "Private"
|
||||
},
|
||||
"collection.label.projects-count": {
|
||||
"message": "{count, plural, one {<stat>{count}</stat> project} other {<stat>{count}</stat> projects}}"
|
||||
},
|
||||
"collection.label.updated-at": {
|
||||
"message": "Updated {ago}"
|
||||
},
|
||||
"collection.title": {
|
||||
"message": "{name} - Collection"
|
||||
},
|
||||
"dashboard.collections.button.create-new": {
|
||||
"message": "Create new"
|
||||
},
|
||||
"dashboard.collections.label.projects-count": {
|
||||
"message": "{count, plural, one {{count} project} other {{count} projects}}"
|
||||
},
|
||||
"dashboard.collections.label.search-input": {
|
||||
"message": "Search your collections"
|
||||
},
|
||||
"dashboard.collections.long-title": {
|
||||
"message": "Your collections"
|
||||
},
|
||||
"frog": {
|
||||
"message": "You've been frogged! 🐸"
|
||||
},
|
||||
@ -50,6 +122,33 @@
|
||||
"input.view.list": {
|
||||
"message": "List view"
|
||||
},
|
||||
"label.collections": {
|
||||
"message": "Collections"
|
||||
},
|
||||
"label.delete": {
|
||||
"message": "Delete"
|
||||
},
|
||||
"label.description": {
|
||||
"message": "Description"
|
||||
},
|
||||
"label.followed-projects": {
|
||||
"message": "Followed projects"
|
||||
},
|
||||
"label.public": {
|
||||
"message": "Public"
|
||||
},
|
||||
"label.rejected": {
|
||||
"message": "Rejected"
|
||||
},
|
||||
"label.title": {
|
||||
"message": "Title"
|
||||
},
|
||||
"label.unlisted": {
|
||||
"message": "Unlisted"
|
||||
},
|
||||
"label.visibility": {
|
||||
"message": "Visibility"
|
||||
},
|
||||
"notification.error.title": {
|
||||
"message": "An error occurred"
|
||||
},
|
||||
|
||||
@ -3,10 +3,10 @@
|
||||
<ModalConfirm
|
||||
v-if="auth.user && auth.user.id === creator.id"
|
||||
ref="deleteModal"
|
||||
title="Are you sure you want to delete this collection?"
|
||||
description="This will remove this collection forever. This action cannot be undone."
|
||||
:title="formatMessage(messages.deleteModalTitle)"
|
||||
:description="formatMessage(messages.deleteModalDescription)"
|
||||
:has-to-type="false"
|
||||
proceed-label="Delete"
|
||||
:proceed-label="formatMessage(commonMessages.deleteLabel)"
|
||||
@proceed="deleteCollection()"
|
||||
/>
|
||||
<div class="normal-page">
|
||||
@ -16,16 +16,16 @@
|
||||
<template v-if="canEdit && isEditing === false">
|
||||
<Button @click="isEditing = true">
|
||||
<EditIcon />
|
||||
Edit
|
||||
{{ formatMessage(commonMessages.editButton) }}
|
||||
</Button>
|
||||
<Button id="delete-collection" @click="() => $refs.deleteModal.show()">
|
||||
<TrashIcon />
|
||||
Delete
|
||||
{{ formatMessage(commonMessages.deleteLabel) }}
|
||||
</Button>
|
||||
</template>
|
||||
<template v-else-if="canEdit && isEditing === true">
|
||||
<PopoutMenu class="btn" position="bottom" direction="right">
|
||||
<EditIcon /> Edit icon
|
||||
<EditIcon /> {{ formatMessage(messages.editIconButton) }}
|
||||
<template #menu>
|
||||
<span class="icon-edit-menu">
|
||||
<FileInput
|
||||
@ -39,7 +39,7 @@
|
||||
@change="showPreviewImage"
|
||||
>
|
||||
<UploadIcon />
|
||||
Upload icon
|
||||
{{ formatMessage(messages.uploadIconButton) }}
|
||||
</FileInput>
|
||||
<Button
|
||||
v-if="!deletedIcon && (previewImage || collection.icon_url)"
|
||||
@ -53,7 +53,7 @@
|
||||
"
|
||||
>
|
||||
<TrashIcon />
|
||||
Delete icon
|
||||
{{ formatMessage(messages.deleteIconButton) }}
|
||||
</Button>
|
||||
</span>
|
||||
</template>
|
||||
@ -70,17 +70,21 @@
|
||||
/>
|
||||
</div>
|
||||
<label for="collection-title">
|
||||
<span class="label__title"> Title </span>
|
||||
<span class="label__title"> {{ formatMessage(commonMessages.titleLabel) }} </span>
|
||||
</label>
|
||||
<input id="collection-title" v-model="name" maxlength="255" type="text" />
|
||||
<label for="collection-description">
|
||||
<span class="label__title"> Description </span>
|
||||
<span class="label__title">
|
||||
{{ formatMessage(commonMessages.descriptionLabel) }}
|
||||
</span>
|
||||
</label>
|
||||
<div class="textarea-wrapper">
|
||||
<textarea id="collection-description" v-model="summary" maxlength="255" />
|
||||
</div>
|
||||
<label for="visibility">
|
||||
<span class="label__title"> Visibility </span>
|
||||
<span class="label__title">
|
||||
{{ formatMessage(commonMessages.visibilityLabel) }}
|
||||
</span>
|
||||
</label>
|
||||
<DropdownSelect
|
||||
id="visibility"
|
||||
@ -90,8 +94,8 @@
|
||||
:multiple="false"
|
||||
:display-name="
|
||||
(s) => {
|
||||
if (s === 'listed') return 'Public'
|
||||
return capitalizeString(s)
|
||||
if (s === 'listed') return formatMessage(commonMessages.publicLabel)
|
||||
return formatMessage(commonMessages[`${s}Label`])
|
||||
}
|
||||
"
|
||||
:searchable="false"
|
||||
@ -100,11 +104,11 @@
|
||||
<div class="push-right input-group">
|
||||
<Button @click="isEditing = false">
|
||||
<XIcon />
|
||||
Cancel
|
||||
{{ formatMessage(commonMessages.cancelButton) }}
|
||||
</Button>
|
||||
<Button color="primary" @click="saveChanges()">
|
||||
<SaveIcon />
|
||||
Save
|
||||
{{ formatMessage(commonMessages.saveButton) }}
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
@ -117,7 +121,9 @@
|
||||
<h1 class="title">{{ collection.name }}</h1>
|
||||
|
||||
<div>
|
||||
<span class="collection-label"><BoxIcon /> Collection</span>
|
||||
<span class="collection-label">
|
||||
<BoxIcon /> {{ formatMessage(messages.collectionLabel) }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="collection-info">
|
||||
@ -131,25 +137,25 @@
|
||||
<template v-if="collection.status === 'listed'">
|
||||
<WorldIcon class="primary-stat__icon" aria-hidden="true" />
|
||||
<div class="primary-stat__text">
|
||||
<strong> Public </strong>
|
||||
<strong> {{ formatMessage(commonMessages.publicLabel) }} </strong>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="collection.status === 'unlisted'">
|
||||
<LinkIcon class="primary-stat__icon" aria-hidden="true" />
|
||||
<div class="primary-stat__text">
|
||||
<strong> Unlisted </strong>
|
||||
<strong> {{ formatMessage(commonMessages.unlistedLabel) }} </strong>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="collection.status === 'private'">
|
||||
<LockIcon class="primary-stat__icon" aria-hidden="true" />
|
||||
<div class="primary-stat__text">
|
||||
<strong> Private </strong>
|
||||
<strong> {{ formatMessage(commonMessages.privateLabel) }} </strong>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="collection.status === 'rejected'">
|
||||
<XIcon class="primary-stat__icon" aria-hidden="true" />
|
||||
<div class="primary-stat__text">
|
||||
<strong> Rejected </strong>
|
||||
<strong> {{ formatMessage(commonMessages.rejectedLabel) }} </strong>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
@ -158,35 +164,57 @@
|
||||
<div class="primary-stat">
|
||||
<LibraryIcon class="primary-stat__icon" aria-hidden="true" />
|
||||
<div v-if="projects" class="primary-stat__text">
|
||||
<span class="primary-stat__counter">
|
||||
{{ $formatNumber(projects?.length || 0) }}
|
||||
</span>
|
||||
project<span v-if="projects?.length !== 1">s</span>
|
||||
<IntlFormatted
|
||||
:message-id="messages.projectsCountLabel"
|
||||
:values="{ count: formatCompactNumber(projects.length || 0) }"
|
||||
>
|
||||
<template #stat="{ children }">
|
||||
<span class="primary-stat__counter">
|
||||
<component :is="() => normalizeChildren(children)" />
|
||||
</span>
|
||||
</template>
|
||||
</IntlFormatted>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="metadata-item">
|
||||
<div
|
||||
v-tooltip="$dayjs(collection.created).format('MMMM D, YYYY [at] h:mm A')"
|
||||
v-tooltip="
|
||||
formatMessage(commonMessages.dateAtTimeTooltip, {
|
||||
date: new Date(collection.created),
|
||||
time: new Date(collection.created),
|
||||
})
|
||||
"
|
||||
class="date"
|
||||
>
|
||||
<CalendarIcon />
|
||||
<label>
|
||||
Created
|
||||
{{ fromNow(collection.created) }}
|
||||
{{
|
||||
formatMessage(messages.createdAtLabel, {
|
||||
ago: formatRelativeTime(collection.created),
|
||||
})
|
||||
}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="collection.id !== 'following'" class="metadata-item">
|
||||
<div
|
||||
v-tooltip="$dayjs(collection.updated).format('MMMM D, YYYY [at] h:mm A')"
|
||||
v-tooltip="
|
||||
formatMessage(commonMessages.dateAtTimeTooltip, {
|
||||
date: new Date(collection.updated),
|
||||
time: new Date(collection.updated),
|
||||
})
|
||||
"
|
||||
class="date"
|
||||
>
|
||||
<UpdatedIcon />
|
||||
<label>
|
||||
Updated
|
||||
{{ fromNow(collection.updated) }}
|
||||
{{
|
||||
formatMessage(messages.updatedAtLabel, {
|
||||
ago: formatRelativeTime(collection.updated),
|
||||
})
|
||||
}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@ -195,7 +223,7 @@
|
||||
<hr class="card-divider" />
|
||||
|
||||
<div class="collection-info">
|
||||
<h2 class="card-header">Curated by</h2>
|
||||
<h2 class="card-header">{{ formatMessage(messages.curatedByLabel) }}</h2>
|
||||
<div class="metadata-item">
|
||||
<nuxt-link
|
||||
class="team-member columns button-transparent"
|
||||
@ -205,7 +233,7 @@
|
||||
|
||||
<div class="member-info">
|
||||
<p class="name">{{ creator.username }}</p>
|
||||
<p class="role">Owner</p>
|
||||
<p class="role">{{ formatMessage(messages.ownerLabel) }}</p>
|
||||
</div>
|
||||
</nuxt-link>
|
||||
</div>
|
||||
@ -304,7 +332,7 @@
|
||||
"
|
||||
>
|
||||
<TrashIcon />
|
||||
Remove project
|
||||
{{ formatMessage(messages.removeProjectButton) }}
|
||||
</button>
|
||||
<button
|
||||
v-if="collection.id === 'following'"
|
||||
@ -312,18 +340,22 @@
|
||||
@click="unfollowProject(project)"
|
||||
>
|
||||
<TrashIcon />
|
||||
Unfollow project
|
||||
{{ formatMessage(messages.unfollowProjectButton) }}
|
||||
</button>
|
||||
</ProjectCard>
|
||||
</div>
|
||||
<div v-else class="error">
|
||||
<UpToDate class="icon" /><br />
|
||||
<span v-if="auth.user && auth.user.id === creator.id" class="text">
|
||||
You don't have any projects.<br />
|
||||
Would you like to
|
||||
<a class="link" @click.prevent="$router.push('/mods')"> add one</a>?
|
||||
<span v-if="auth.user && auth.user.id === creator.id" class="preserve-lines text">
|
||||
<IntlFormatted :message-id="messages.noProjectsAuthLabel">
|
||||
<template #create-link="{ children }">
|
||||
<a class="link" @click.prevent="$router.push('/mods')">
|
||||
<component :is="() => children" />
|
||||
</a>
|
||||
</template>
|
||||
</IntlFormatted>
|
||||
</span>
|
||||
<span v-else class="text">This collection has no projects!</span>
|
||||
<span v-else class="text">{{ formatMessage(messages.noProjectsLabel) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -332,7 +364,6 @@
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
capitalizeString,
|
||||
Avatar,
|
||||
Button,
|
||||
CalendarIcon,
|
||||
@ -364,6 +395,89 @@ import ProjectCard from '~/components/ui/ProjectCard.vue'
|
||||
|
||||
const vintl = useVIntl()
|
||||
const { formatMessage } = vintl
|
||||
const formatRelativeTime = useRelativeTime()
|
||||
const formatCompactNumber = useCompactNumber()
|
||||
|
||||
const messages = defineMessages({
|
||||
collectionDescription: {
|
||||
id: 'collection.description',
|
||||
defaultMessage: '{description} - View the collection {name} by {username} on Modrinth',
|
||||
},
|
||||
collectionLabel: {
|
||||
id: 'collection.label.collection',
|
||||
defaultMessage: 'Collection',
|
||||
},
|
||||
collectionTitle: {
|
||||
id: 'collection.title',
|
||||
defaultMessage: '{name} - Collection',
|
||||
},
|
||||
editIconButton: {
|
||||
id: 'collection.button.edit-icon',
|
||||
defaultMessage: 'Edit icon',
|
||||
},
|
||||
deleteIconButton: {
|
||||
id: 'collection.button.delete-icon',
|
||||
defaultMessage: 'Delete icon',
|
||||
},
|
||||
createdAtLabel: {
|
||||
id: 'collection.label.created-at',
|
||||
defaultMessage: 'Created {ago}',
|
||||
},
|
||||
collectionNotFoundError: {
|
||||
id: 'collection.error.not-found',
|
||||
defaultMessage: 'Collection not found',
|
||||
},
|
||||
curatedByLabel: {
|
||||
id: 'collection.label.curated-by',
|
||||
defaultMessage: 'Curated by',
|
||||
},
|
||||
deleteModalDescription: {
|
||||
id: 'collection.delete-modal.description',
|
||||
defaultMessage: 'This will remove this collection forever. This action cannot be undone.',
|
||||
},
|
||||
deleteModalTitle: {
|
||||
id: 'collection.delete-modal.title',
|
||||
defaultMessage: 'Are you sure you want to delete this collection?',
|
||||
},
|
||||
followingCollectionDescription: {
|
||||
id: 'collection.description.following',
|
||||
defaultMessage: "Auto-generated collection of all the projects you're following.",
|
||||
},
|
||||
noProjectsLabel: {
|
||||
id: 'collection.label.no-projects',
|
||||
defaultMessage: 'This collection has no projects!',
|
||||
},
|
||||
noProjectsAuthLabel: {
|
||||
id: 'collection.label.no-projects-auth',
|
||||
defaultMessage:
|
||||
"You don't have any projects.\nWould you like to <create-link>add one</create-link>?",
|
||||
},
|
||||
ownerLabel: {
|
||||
id: 'collection.label.owner',
|
||||
defaultMessage: 'Owner',
|
||||
},
|
||||
projectsCountLabel: {
|
||||
id: 'collection.label.projects-count',
|
||||
defaultMessage:
|
||||
'{count, plural, one {<stat>{count}</stat> project} other {<stat>{count}</stat> projects}}',
|
||||
},
|
||||
removeProjectButton: {
|
||||
id: 'collection.button.remove-project',
|
||||
defaultMessage: 'Remove project',
|
||||
},
|
||||
unfollowProjectButton: {
|
||||
id: 'collection.button.unfollow-project',
|
||||
defaultMessage: 'Unfollow project',
|
||||
},
|
||||
updatedAtLabel: {
|
||||
id: 'collection.label.updated-at',
|
||||
defaultMessage: 'Updated {ago}',
|
||||
},
|
||||
uploadIconButton: {
|
||||
id: 'collection.button.upload-icon',
|
||||
defaultMessage: 'Upload icon',
|
||||
},
|
||||
})
|
||||
|
||||
const data = useNuxtApp()
|
||||
const route = useRoute()
|
||||
@ -388,8 +502,8 @@ try {
|
||||
collection = ref({
|
||||
id: 'following',
|
||||
icon_url: 'https://cdn.modrinth.com/follow-collection.png',
|
||||
name: 'Followed projects',
|
||||
description: "Auto-generated collection of all the projects you're following.",
|
||||
name: formatMessage(commonMessages.followedProjectsLabel),
|
||||
description: formatMessage(messages.followingCollectionDescription),
|
||||
status: 'private',
|
||||
user: auth.value.user.id,
|
||||
created: auth.value.user.created,
|
||||
@ -426,7 +540,7 @@ try {
|
||||
throw createError({
|
||||
fatal: true,
|
||||
statusCode: 404,
|
||||
message: 'Collection not found',
|
||||
message: formatMessage(messages.collectionNotFoundError),
|
||||
})
|
||||
}
|
||||
|
||||
@ -434,16 +548,22 @@ if (!collection.value) {
|
||||
throw createError({
|
||||
fatal: true,
|
||||
statusCode: 404,
|
||||
message: 'Collection not found',
|
||||
message: formatMessage(messages.collectionNotFoundError),
|
||||
})
|
||||
}
|
||||
|
||||
const title = `${collection.value.name} - Collection`
|
||||
const description = `${collection.value.description} - View the collection ${collection.value.description} by ${creator.value.username} on Modrinth`
|
||||
const title = computed(() =>
|
||||
formatMessage(messages.collectionTitle, { name: collection.value.name })
|
||||
)
|
||||
|
||||
useSeoMeta({
|
||||
title,
|
||||
description,
|
||||
description: () =>
|
||||
formatMessage(messages.collectionDescription, {
|
||||
name: collection.value.name,
|
||||
description: collection.value.description,
|
||||
username: creator.value.username,
|
||||
}),
|
||||
ogTitle: title,
|
||||
ogDescription: collection.value.description,
|
||||
ogImage: collection.value.icon_url ?? 'https://cdn.modrinth.com/placeholder.png',
|
||||
@ -526,7 +646,7 @@ async function saveChanges() {
|
||||
} catch (err) {
|
||||
addNotification({
|
||||
group: 'main',
|
||||
title: 'An error occurred',
|
||||
title: formatMessage(commonMessages.errorNotificationTitle),
|
||||
text: err,
|
||||
type: 'error',
|
||||
})
|
||||
@ -546,7 +666,7 @@ async function deleteCollection() {
|
||||
} catch (err) {
|
||||
addNotification({
|
||||
group: 'main',
|
||||
title: 'An error occurred',
|
||||
title: formatMessage(commonMessages.errorNotificationTitle),
|
||||
text: err.data.description,
|
||||
type: 'error',
|
||||
})
|
||||
|
||||
@ -24,7 +24,10 @@
|
||||
<NavStackItem v-if="true" link="/dashboard/organizations" label="Organizations">
|
||||
<OrganizationIcon />
|
||||
</NavStackItem>
|
||||
<NavStackItem link="/dashboard/collections" label="Collections">
|
||||
<NavStackItem
|
||||
link="/dashboard/collections"
|
||||
:label="formatMessage(commonMessages.collectionsLabel)"
|
||||
>
|
||||
<LibraryIcon />
|
||||
</NavStackItem>
|
||||
<NavStackItem link="/dashboard/revenue" label="Revenue">
|
||||
@ -50,6 +53,8 @@ import ReportIcon from '~/assets/images/utils/report.svg'
|
||||
import NotificationsIcon from '~/assets/images/utils/bell.svg'
|
||||
import OrganizationIcon from '~/assets/images/utils/organization.svg'
|
||||
|
||||
const { formatMessage } = useVIntl()
|
||||
|
||||
definePageMeta({
|
||||
middleware: 'auth',
|
||||
})
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<div class="universal-card">
|
||||
<CollectionCreateModal ref="modal_creation" />
|
||||
<h2>Collections</h2>
|
||||
<h2>{{ formatMessage(commonMessages.collectionsLabel) }}</h2>
|
||||
<div class="search-row">
|
||||
<div class="iconified-input">
|
||||
<label for="search-input" hidden>Search your collections</label>
|
||||
<label for="search-input" hidden>{{ formatMessage(messages.searchInputLabel) }}</label>
|
||||
<SearchIcon />
|
||||
<input id="search-input" v-model="filterQuery" type="text" />
|
||||
<Button v-if="filterQuery" class="r-btn" @click="() => (filterQuery = '')">
|
||||
@ -12,7 +12,7 @@
|
||||
</Button>
|
||||
</div>
|
||||
<Button color="primary" @click="$refs.modal_creation.show()">
|
||||
<PlusIcon /> Create new
|
||||
<PlusIcon /> {{ formatMessage(messages.createNewButton) }}
|
||||
</Button>
|
||||
</div>
|
||||
<div class="collections-grid">
|
||||
@ -23,13 +23,22 @@
|
||||
>
|
||||
<Avatar src="https://cdn.modrinth.com/follow-collection.png" class="icon" />
|
||||
<div class="details">
|
||||
<span class="title">Followed projects</span>
|
||||
<span class="title">{{ formatMessage(commonMessages.followedProjectsLabel) }}</span>
|
||||
<span class="description">
|
||||
Auto-generated collection of all the projects you're following.
|
||||
{{ formatMessage(messages.followingCollectionDescription) }}
|
||||
</span>
|
||||
<div class="stat-bar">
|
||||
<div class="stats"><BoxIcon /> {{ user.follows.length }} projects</div>
|
||||
<div class="stats"><LockIcon /> <span> Private </span></div>
|
||||
<div class="stats">
|
||||
<BoxIcon />
|
||||
{{
|
||||
formatMessage(messages.projectsCountLabel, {
|
||||
count: formatCompactNumber(user.follows.length),
|
||||
})
|
||||
}}
|
||||
</div>
|
||||
<div class="stats">
|
||||
<LockIcon /> <span> {{ formatMessage(commonMessages.privateLabel) }} </span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nuxt-link>
|
||||
@ -46,23 +55,30 @@
|
||||
{{ collection.description }}
|
||||
</span>
|
||||
<div class="stat-bar">
|
||||
<div class="stats"><BoxIcon /> {{ collection.projects?.length || 0 }} projects</div>
|
||||
<div class="stats">
|
||||
<BoxIcon />
|
||||
{{
|
||||
formatMessage(messages.projectsCountLabel, {
|
||||
count: formatCompactNumber(collection.projects?.length || 0),
|
||||
})
|
||||
}}
|
||||
</div>
|
||||
<div class="stats">
|
||||
<template v-if="collection.status === 'listed'">
|
||||
<WorldIcon />
|
||||
<span> Public </span>
|
||||
<span> {{ formatMessage(commonMessages.publicLabel) }} </span>
|
||||
</template>
|
||||
<template v-else-if="collection.status === 'unlisted'">
|
||||
<LinkIcon />
|
||||
<span> Unlisted </span>
|
||||
<span> {{ formatMessage(commonMessages.unlistedLabel) }} </span>
|
||||
</template>
|
||||
<template v-else-if="collection.status === 'private'">
|
||||
<LockIcon />
|
||||
<span> Private </span>
|
||||
<span> {{ formatMessage(commonMessages.privateLabel) }} </span>
|
||||
</template>
|
||||
<template v-else-if="collection.status === 'rejected'">
|
||||
<XIcon />
|
||||
<span> Rejected </span>
|
||||
<span> {{ formatMessage(commonMessages.rejectedLabel) }} </span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
@ -76,12 +92,38 @@ import { Avatar, BoxIcon, SearchIcon, XIcon, Button, PlusIcon, LinkIcon, LockIco
|
||||
import WorldIcon from '~/assets/images/utils/world.svg'
|
||||
import CollectionCreateModal from '~/components/ui/CollectionCreateModal.vue'
|
||||
|
||||
const { formatMessage } = useVIntl()
|
||||
const formatCompactNumber = useCompactNumber()
|
||||
|
||||
const messages = defineMessages({
|
||||
createNewButton: {
|
||||
id: 'dashboard.collections.button.create-new',
|
||||
defaultMessage: 'Create new',
|
||||
},
|
||||
collectionsLongTitle: {
|
||||
id: 'dashboard.collections.long-title',
|
||||
defaultMessage: 'Your collections',
|
||||
},
|
||||
followingCollectionDescription: {
|
||||
id: 'collection.description.following',
|
||||
defaultMessage: "Auto-generated collection of all the projects you're following.",
|
||||
},
|
||||
projectsCountLabel: {
|
||||
id: 'dashboard.collections.label.projects-count',
|
||||
defaultMessage: '{count, plural, one {{count} project} other {{count} projects}}',
|
||||
},
|
||||
searchInputLabel: {
|
||||
id: 'dashboard.collections.label.search-input',
|
||||
defaultMessage: 'Search your collections',
|
||||
},
|
||||
})
|
||||
|
||||
definePageMeta({
|
||||
middleware: 'auth',
|
||||
})
|
||||
|
||||
useHead({
|
||||
title: 'Your collections - Modrinth',
|
||||
title: () => `${formatMessage(messages.collectionsLongTitle)} - Modrinth`,
|
||||
})
|
||||
|
||||
const user = await useUser()
|
||||
|
||||
@ -7,6 +7,10 @@ export const commonMessages = defineMessages({
|
||||
id: 'button.cancel',
|
||||
defaultMessage: 'Cancel',
|
||||
},
|
||||
collectionsLabel: {
|
||||
id: 'label.collections',
|
||||
defaultMessage: 'Collections',
|
||||
},
|
||||
continueButton: {
|
||||
id: 'button.continue',
|
||||
defaultMessage: 'Continue',
|
||||
@ -15,10 +19,26 @@ export const commonMessages = defineMessages({
|
||||
id: 'tooltip.date-at-time',
|
||||
defaultMessage: '{date, date, long} at {time, time, short}',
|
||||
},
|
||||
deleteLabel: {
|
||||
id: 'label.delete',
|
||||
defaultMessage: 'Delete',
|
||||
},
|
||||
descriptionLabel: {
|
||||
id: 'label.description',
|
||||
defaultMessage: 'Description',
|
||||
},
|
||||
editButton: {
|
||||
id: 'button.edit',
|
||||
defaultMessage: 'Edit',
|
||||
},
|
||||
errorNotificationTitle: {
|
||||
id: 'notification.error.title',
|
||||
defaultMessage: 'An error occurred',
|
||||
},
|
||||
followedProjectsLabel: {
|
||||
id: 'label.followed-projects',
|
||||
defaultMessage: 'Followed projects',
|
||||
},
|
||||
galleryInputView: {
|
||||
id: 'input.view.gallery',
|
||||
defaultMessage: 'Gallery view',
|
||||
@ -31,12 +51,32 @@ export const commonMessages = defineMessages({
|
||||
id: 'input.view.list',
|
||||
defaultMessage: 'List view',
|
||||
},
|
||||
errorNotificationTitle: {
|
||||
id: 'notification.error.title',
|
||||
defaultMessage: 'An error occurred',
|
||||
privateLabel: {
|
||||
id: 'collection.label.private',
|
||||
defaultMessage: 'Private',
|
||||
},
|
||||
publicLabel: {
|
||||
id: 'label.public',
|
||||
defaultMessage: 'Public',
|
||||
},
|
||||
rejectedLabel: {
|
||||
id: 'label.rejected',
|
||||
defaultMessage: 'Rejected',
|
||||
},
|
||||
saveButton: {
|
||||
id: 'button.save',
|
||||
defaultMessage: 'Save',
|
||||
},
|
||||
titleLabel: {
|
||||
id: 'label.title',
|
||||
defaultMessage: 'Title',
|
||||
},
|
||||
unlistedLabel: {
|
||||
id: 'label.unlisted',
|
||||
defaultMessage: 'Unlisted',
|
||||
},
|
||||
visibilityLabel: {
|
||||
id: 'label.visibility',
|
||||
defaultMessage: 'Visibility',
|
||||
},
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user