You've already forked AstralRinth
forked from didirus/AstralRinth
Add gallery view to search pages (#773)
This commit is contained in:
@@ -402,7 +402,7 @@
|
||||
')'
|
||||
"
|
||||
:href="findPrimary(version).url"
|
||||
class="download download-button"
|
||||
class="download square-button brand-button"
|
||||
:title="`Download ${version.name}`"
|
||||
@click.stop="(event) => event.stopPropagation()"
|
||||
>
|
||||
@@ -743,7 +743,7 @@
|
||||
')'
|
||||
"
|
||||
:href="findPrimary(version).url"
|
||||
class="download download-button"
|
||||
class="download square-button brand-button"
|
||||
:title="`Download ${version.name}`"
|
||||
@click.stop="(event) => event.stopPropagation()"
|
||||
>
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
')'
|
||||
"
|
||||
:href="$parent.findPrimary(version).url"
|
||||
class="download-button"
|
||||
class="download-button square-button brand-button"
|
||||
:class="version.version_type"
|
||||
:title="`Download ${version.name}`"
|
||||
@click.stop="(event) => event.stopPropagation()"
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
}}
|
||||
</div>
|
||||
<span
|
||||
>from {{ $user.projects.length }} project{{
|
||||
$user.projects.length === 1 ? '' : 's'
|
||||
}}</span
|
||||
>from
|
||||
{{ downloadsProjectCount }}
|
||||
project{{ downloadsProjectCount === 1 ? '' : 's' }}</span
|
||||
>
|
||||
<!-- <NuxtLink class="goto-link" to="/dashboard/analytics"-->
|
||||
<!-- >View breakdown-->
|
||||
@@ -35,8 +35,8 @@
|
||||
</div>
|
||||
<span>
|
||||
<span
|
||||
>from {{ $user.projects.length }} project{{
|
||||
$user.projects.length === 1 ? '' : 's'
|
||||
>from {{ followersProjectCount }} project{{
|
||||
followersProjectCount === 1 ? '' : 's'
|
||||
}}</span
|
||||
></span
|
||||
>
|
||||
@@ -117,6 +117,16 @@ export default {
|
||||
head: {
|
||||
title: 'Creator dashboard - Modrinth',
|
||||
},
|
||||
computed: {
|
||||
downloadsProjectCount() {
|
||||
return this.$user.projects.filter((project) => project.downloads > 0)
|
||||
.length
|
||||
},
|
||||
followersProjectCount() {
|
||||
return this.$user.projects.filter((project) => project.followers > 0)
|
||||
.length
|
||||
},
|
||||
},
|
||||
methods: {},
|
||||
}
|
||||
</script>
|
||||
|
||||
29
pages/frog.vue
Normal file
29
pages/frog.vue
Normal file
@@ -0,0 +1,29 @@
|
||||
<template>
|
||||
<div class="normal-page">
|
||||
<div class="card">
|
||||
<h1>Frog</h1>
|
||||
<p>You've been frogged! 🐸</p>
|
||||
<img
|
||||
src="https://cdn.modrinth.com/frog.png"
|
||||
alt="a photorealistic painting of a frog labyrinth"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
auth: false,
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.card {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
img {
|
||||
margin-block: 0 1.5rem;
|
||||
}
|
||||
</style>
|
||||
@@ -70,7 +70,7 @@
|
||||
</aside>
|
||||
</div>
|
||||
<div class="normal-page__content">
|
||||
<div class="projects">
|
||||
<div class="project-list display-mode--gallery">
|
||||
<ProjectCard
|
||||
v-for="project in $route.query.type !== undefined
|
||||
? projects.filter((x) => x.project_type === $route.query.type)
|
||||
|
||||
@@ -157,7 +157,7 @@
|
||||
facet-name="client"
|
||||
@toggle="toggleEnv"
|
||||
>
|
||||
<ClientSide aria-hidden="true" />
|
||||
<ClientIcon aria-hidden="true" />
|
||||
</SearchFilter>
|
||||
<SearchFilter
|
||||
:active-filters="selectedEnvironments"
|
||||
@@ -165,7 +165,7 @@
|
||||
facet-name="server"
|
||||
@toggle="toggleEnv"
|
||||
>
|
||||
<ServerSide aria-hidden="true" />
|
||||
<ServerIcon aria-hidden="true" />
|
||||
</SearchFilter>
|
||||
</section>
|
||||
<h3 class="sidebar-menu-heading">Minecraft versions</h3>
|
||||
@@ -303,6 +303,28 @@
|
||||
@input="onSearchChange(currentPage)"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
v-tooltip="
|
||||
$capitalizeString($cosmetics.searchDisplayMode[projectType.id]) +
|
||||
' view'
|
||||
"
|
||||
:aria-label="
|
||||
$capitalizeString($cosmetics.searchDisplayMode[projectType.id]) +
|
||||
' view'
|
||||
"
|
||||
class="square-button"
|
||||
@click="cycleSearchDisplayMode()"
|
||||
>
|
||||
<GridIcon
|
||||
v-if="$cosmetics.searchDisplayMode[projectType.id] === 'grid'"
|
||||
/>
|
||||
<ImageIcon
|
||||
v-else-if="
|
||||
$cosmetics.searchDisplayMode[projectType.id] === 'gallery'
|
||||
"
|
||||
/>
|
||||
<ListIcon v-else />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<pagination
|
||||
@@ -317,11 +339,22 @@
|
||||
<LogoAnimated aria-hidden="true" />
|
||||
<p>Loading...</p>
|
||||
</div>
|
||||
<div v-else id="search-results" role="list" aria-label="Search results">
|
||||
<SearchResult
|
||||
<div
|
||||
v-else-if="true"
|
||||
id="search-results"
|
||||
class="project-list"
|
||||
:class="
|
||||
'display-mode--' + $cosmetics.searchDisplayMode[projectType.id]
|
||||
"
|
||||
role="list"
|
||||
aria-label="Search results"
|
||||
>
|
||||
<ProjectCard
|
||||
v-for="result in results"
|
||||
:id="result.slug ? result.slug : result.project_id"
|
||||
:key="result.project_id"
|
||||
:display="$cosmetics.searchDisplayMode[projectType.id]"
|
||||
:gallery-images="result.gallery"
|
||||
:type="result.project_type"
|
||||
:author="result.author"
|
||||
:name="result.title"
|
||||
@@ -335,6 +368,7 @@
|
||||
:server-side="result.server_side"
|
||||
:categories="result.display_categories"
|
||||
:search="true"
|
||||
:show-updated-date="sortType.name !== 'newest'"
|
||||
/>
|
||||
<div v-if="results && results.length === 0" class="no-results">
|
||||
<p>No results found for your query!</p>
|
||||
@@ -354,18 +388,21 @@
|
||||
|
||||
<script>
|
||||
import Multiselect from 'vue-multiselect'
|
||||
import SearchResult from '~/components/ui/ProjectCard'
|
||||
import ProjectCard from '~/components/ui/ProjectCard'
|
||||
import Pagination from '~/components/ui/Pagination'
|
||||
import SearchFilter from '~/components/ui/search/SearchFilter'
|
||||
import LogoAnimated from '~/components/ui/search/LogoAnimated'
|
||||
import Checkbox from '~/components/ui/Checkbox'
|
||||
|
||||
import ClientSide from '~/assets/images/categories/client.svg?inline'
|
||||
import ServerSide from '~/assets/images/categories/server.svg?inline'
|
||||
import ClientIcon from '~/assets/images/categories/client.svg?inline'
|
||||
import ServerIcon from '~/assets/images/categories/server.svg?inline'
|
||||
|
||||
import SearchIcon from '~/assets/images/utils/search.svg?inline'
|
||||
import ClearIcon from '~/assets/images/utils/clear.svg?inline'
|
||||
import FilterIcon from '~/assets/images/utils/filter.svg?inline'
|
||||
import GridIcon from '~/assets/images/utils/grid.svg?inline'
|
||||
import ListIcon from '~/assets/images/utils/list.svg?inline'
|
||||
import ImageIcon from '~/assets/images/utils/image.svg?inline'
|
||||
|
||||
import Advertisement from '~/components/ads/Advertisement'
|
||||
|
||||
@@ -373,16 +410,19 @@ export default {
|
||||
auth: false,
|
||||
components: {
|
||||
Advertisement,
|
||||
SearchResult,
|
||||
ProjectCard,
|
||||
Pagination,
|
||||
Multiselect,
|
||||
SearchFilter,
|
||||
Checkbox,
|
||||
ClientSide,
|
||||
ServerSide,
|
||||
ClientIcon,
|
||||
ServerIcon,
|
||||
SearchIcon,
|
||||
ClearIcon,
|
||||
FilterIcon,
|
||||
GridIcon,
|
||||
ListIcon,
|
||||
ImageIcon,
|
||||
LogoAnimated,
|
||||
},
|
||||
data() {
|
||||
@@ -408,7 +448,7 @@ export default {
|
||||
{ display: 'Relevance', name: 'relevance' },
|
||||
{ display: 'Download count', name: 'downloads' },
|
||||
{ display: 'Follow count', name: 'follows' },
|
||||
{ display: 'Recently created', name: 'newest' },
|
||||
{ display: 'Recently published', name: 'newest' },
|
||||
{ display: 'Recently updated', name: 'updated' },
|
||||
],
|
||||
sortType: { display: 'Relevance', name: 'relevance' },
|
||||
@@ -782,6 +822,15 @@ export default {
|
||||
|
||||
return url
|
||||
},
|
||||
async cycleSearchDisplayMode() {
|
||||
const value = this.$cosmetics.searchDisplayMode[this.projectType.id]
|
||||
const newValue = this.$cycleValue(value, this.$tag.projectViewModes)
|
||||
await this.$store.dispatch('cosmetics/saveSearchDisplayMode', {
|
||||
projectType: this.projectType.id,
|
||||
mode: newValue,
|
||||
$cookies: this.$cookies,
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -892,6 +941,7 @@ export default {
|
||||
flex-direction: row;
|
||||
gap: var(--spacing-card-md);
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
|
||||
.labeled-control {
|
||||
flex: 1;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div v-if="$user.follows.length > 0">
|
||||
<div v-if="$user.follows.length > 0" class="project-list display-mode--list">
|
||||
<ProjectCard
|
||||
v-for="project in $user.follows"
|
||||
:id="project.id"
|
||||
|
||||
@@ -59,6 +59,32 @@
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
<section class="universal-card">
|
||||
<h2>Project list display mode</h2>
|
||||
<div
|
||||
v-for="projectType in listTypes"
|
||||
:key="projectType.id + '-display-mode-selector'"
|
||||
class="adjacent-input small"
|
||||
>
|
||||
<label :for="projectType.id + '-search-display-mode'">
|
||||
<span class="label__title">{{ projectType.name }} display mode</span>
|
||||
<span class="label__description"
|
||||
>Change the display view for {{ projectType.display }}.</span
|
||||
>
|
||||
</label>
|
||||
<Multiselect
|
||||
:id="projectType + '-search-display-mode'"
|
||||
:value="searchDisplayMode[projectType.id]"
|
||||
:options="$tag.projectViewModes"
|
||||
:custom-label="$capitalizeString"
|
||||
:searchable="false"
|
||||
:close-on-select="true"
|
||||
:show-labels="false"
|
||||
:allow-empty="false"
|
||||
@input="(value) => setSearchDisplayMode(projectType.id, value)"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
<section class="universal-card">
|
||||
<h2>Feature flags</h2>
|
||||
<div class="adjacent-input small">
|
||||
@@ -129,25 +155,46 @@ export default {
|
||||
modpacksAlphaNotice: true,
|
||||
advancedRendering: true,
|
||||
externalLinksNewTab: true,
|
||||
searchDisplayMode: {
|
||||
mod: 'list',
|
||||
plugin: 'list',
|
||||
resourcepack: 'gallery',
|
||||
modpack: 'list',
|
||||
user: 'list',
|
||||
},
|
||||
}
|
||||
},
|
||||
fetch() {
|
||||
this.searchLayout =
|
||||
this.$store.state.cosmetics.searchLayout ?? this.searchLayout
|
||||
this.projectLayout =
|
||||
this.$store.state.cosmetics.projectLayout ?? this.projectLayout
|
||||
this.modpacksAlphaNotice =
|
||||
this.$store.state.cosmetics.modpacksAlphaNotice ??
|
||||
this.modpacksAlphaNotice
|
||||
this.advancedRendering =
|
||||
this.$store.state.cosmetics.advancedRendering ?? this.advancedRendering
|
||||
this.externalLinksNewTab =
|
||||
this.$store.state.cosmetics.externalLinksNewTab ??
|
||||
this.externalLinksNewTab
|
||||
this.searchLayout = this.$store.state.cosmetics.searchLayout
|
||||
this.projectLayout = this.$store.state.cosmetics.projectLayout
|
||||
this.modpacksAlphaNotice = this.$store.state.cosmetics.modpacksAlphaNotice
|
||||
this.advancedRendering = this.$store.state.cosmetics.advancedRendering
|
||||
this.externalLinksNewTab = this.$store.state.cosmetics.externalLinksNewTab
|
||||
this.searchDisplayMode = this.$store.state.cosmetics.searchDisplayMode
|
||||
},
|
||||
head: {
|
||||
title: 'Display settings - Modrinth',
|
||||
},
|
||||
computed: {
|
||||
listTypes() {
|
||||
const types = this.$tag.projectTypes.map((type) => {
|
||||
return {
|
||||
id: type.id,
|
||||
name: this.$formatProjectType(type.id) + ' search',
|
||||
display:
|
||||
'the ' +
|
||||
this.$formatProjectType(type.id).toLowerCase() +
|
||||
's search page',
|
||||
}
|
||||
})
|
||||
types.push({
|
||||
id: 'user',
|
||||
name: 'User page',
|
||||
display: 'user pages',
|
||||
})
|
||||
return types
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async saveCosmeticSettings() {
|
||||
await this.$store.dispatch('cosmetics/save', {
|
||||
@@ -156,9 +203,18 @@ export default {
|
||||
modpacksAlphaNotice: this.modpacksAlphaNotice,
|
||||
advancedRendering: this.advancedRendering,
|
||||
externalLinksNewTab: this.externalLinksNewTab,
|
||||
searchDisplayMode: this.searchDisplayMode,
|
||||
$cookies: this.$cookies,
|
||||
})
|
||||
},
|
||||
async setSearchDisplayMode(projectType, value) {
|
||||
await this.$store.dispatch('cosmetics/saveSearchDisplayMode', {
|
||||
projectType,
|
||||
mode: value,
|
||||
$cookies: this.$cookies,
|
||||
})
|
||||
this.searchDisplayMode = this.$store.state.cosmetics.searchDisplayMode
|
||||
},
|
||||
changeTheme() {
|
||||
const shift = event.shiftKey
|
||||
switch (this.$colorMode.preference) {
|
||||
|
||||
@@ -164,23 +164,55 @@
|
||||
}),
|
||||
]"
|
||||
/>
|
||||
<button
|
||||
v-if="$auth.user && $auth.user.id === user.id"
|
||||
class="iconified-button brand-button"
|
||||
@click="$refs.modal_creation.show()"
|
||||
>
|
||||
<PlusIcon />
|
||||
Create a project
|
||||
</button>
|
||||
<div class="input-group">
|
||||
<NuxtLink
|
||||
v-if="$auth.user && $auth.user.id === user.id"
|
||||
class="iconified-button"
|
||||
to="/dashboard/projects"
|
||||
>
|
||||
<SettingsIcon />
|
||||
Manage projects
|
||||
</NuxtLink>
|
||||
<button
|
||||
v-tooltip="
|
||||
$capitalizeString($cosmetics.searchDisplayMode.user) + ' view'
|
||||
"
|
||||
:aria-label="
|
||||
$capitalizeString($cosmetics.searchDisplayMode.user) + ' view'
|
||||
"
|
||||
class="square-button"
|
||||
@click="cycleSearchDisplayMode()"
|
||||
>
|
||||
<GridIcon v-if="$cosmetics.searchDisplayMode.user === 'grid'" />
|
||||
<ImageIcon
|
||||
v-else-if="$cosmetics.searchDisplayMode.user === 'gallery'"
|
||||
/>
|
||||
<ListIcon v-else />
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
<div v-if="projects.length > 0">
|
||||
<div
|
||||
v-if="projects.length > 0"
|
||||
class="project-list"
|
||||
:class="'display-mode--' + $cosmetics.searchDisplayMode.user"
|
||||
>
|
||||
<ProjectCard
|
||||
v-for="project in $route.query.type !== undefined
|
||||
v-for="project in ($route.query.type !== undefined
|
||||
? projects.filter((x) => x.project_type === $route.query.type)
|
||||
: projects"
|
||||
: projects
|
||||
)
|
||||
.slice()
|
||||
.sort((a, b) => b.downloads - a.downloads)"
|
||||
:id="project.slug || project.id"
|
||||
:key="project.id"
|
||||
:name="project.title"
|
||||
:display="$cosmetics.searchDisplayMode.user"
|
||||
:gallery-images="
|
||||
project.gallery
|
||||
.slice()
|
||||
.sort((a, b) => b.featured - a.featured)
|
||||
.map((x) => x.url)
|
||||
"
|
||||
:description="project.description"
|
||||
:created-at="project.published"
|
||||
:updated-at="project.updated"
|
||||
@@ -200,18 +232,7 @@
|
||||
"
|
||||
:has-mod-message="project.moderator_message"
|
||||
:type="project.project_type"
|
||||
>
|
||||
<nuxt-link
|
||||
v-if="$auth.user && $auth.user.id === user.id"
|
||||
class="iconified-button"
|
||||
:to="`/${project.project_type}/${
|
||||
project.slug ? project.slug : project.id
|
||||
}/settings`"
|
||||
>
|
||||
<SettingsIcon />
|
||||
Settings
|
||||
</nuxt-link>
|
||||
</ProjectCard>
|
||||
/>
|
||||
</div>
|
||||
<div v-else class="error">
|
||||
<UpToDate class="icon" /><br />
|
||||
@@ -239,13 +260,15 @@ import ReportIcon from '~/assets/images/utils/report.svg?inline'
|
||||
import SunriseIcon from '~/assets/images/utils/sunrise.svg?inline'
|
||||
import DownloadIcon from '~/assets/images/utils/download.svg?inline'
|
||||
import SettingsIcon from '~/assets/images/utils/settings.svg?inline'
|
||||
import PlusIcon from '~/assets/images/utils/plus.svg?inline'
|
||||
import UpToDate from '~/assets/images/illustrations/up_to_date.svg?inline'
|
||||
import UserIcon from '~/assets/images/utils/user.svg?inline'
|
||||
import EditIcon from '~/assets/images/utils/edit.svg?inline'
|
||||
import HeartIcon from '~/assets/images/utils/heart.svg?inline'
|
||||
import CrossIcon from '~/assets/images/utils/x.svg?inline'
|
||||
import SaveIcon from '~/assets/images/utils/save.svg?inline'
|
||||
import GridIcon from '~/assets/images/utils/grid.svg?inline'
|
||||
import ListIcon from '~/assets/images/utils/list.svg?inline'
|
||||
import ImageIcon from '~/assets/images/utils/image.svg?inline'
|
||||
import FileInput from '~/components/ui/FileInput'
|
||||
import ModalReport from '~/components/ui/ModalReport'
|
||||
import ModalCreation from '~/components/ui/ModalCreation'
|
||||
@@ -269,7 +292,6 @@ export default {
|
||||
ReportIcon,
|
||||
Badge,
|
||||
SettingsIcon,
|
||||
PlusIcon,
|
||||
UpToDate,
|
||||
UserIcon,
|
||||
EditIcon,
|
||||
@@ -277,6 +299,9 @@ export default {
|
||||
HeartIcon,
|
||||
CrossIcon,
|
||||
SaveIcon,
|
||||
GridIcon,
|
||||
ListIcon,
|
||||
ImageIcon,
|
||||
},
|
||||
async asyncData(data) {
|
||||
try {
|
||||
@@ -486,6 +511,15 @@ export default {
|
||||
}
|
||||
this.$nuxt.$loading.finish()
|
||||
},
|
||||
async cycleSearchDisplayMode() {
|
||||
const value = this.$cosmetics.searchDisplayMode.user
|
||||
const newValue = this.$cycleValue(value, this.$tag.projectViewModes)
|
||||
await this.$store.dispatch('cosmetics/saveSearchDisplayMode', {
|
||||
projectType: 'user',
|
||||
mode: newValue,
|
||||
$cookies: this.$cookies,
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -533,6 +567,7 @@ export default {
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
row-gap: 0.5rem;
|
||||
padding-right: var(--spacing-card-bg);
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
|
||||
Reference in New Issue
Block a user