You've already forked AstralRinth
forked from didirus/AstralRinth
New features (#592)
* New features * Lots of bug fixes * Fix respack creation * Improve mobile nav with more project types * Fix resolution sorting and remove icons * Move cookie consent to top on small devices to get out of the way of navigation * Move cookie consent + fix hydration * Fix project editing + update search features * Centralize hardcoding of loader/category names, fix cookie consent shadow, fix mobile navbar rounding * Fix plugin platforms formatting * Kitchen sink! * Add support for display names * LiteLoader formatting * Fixed "show all loaders" toggle not resetting when changing pages * Allow multiple loaders in version filter controls * Fix clear filters button * Revert "Add support for display names" This reverts commit 370838763d86bcae51bf06c304248f7a1f8fc28f. * Let's see how this goes. Upstream filters, attempt 1 * github? hello? * No more "Server mod" on plugins * Fix formatting of project types in project creation * Move where project creation sets the resource pack loader * Allow setting pixelated image-rendering Allows to apply 'style' attribute to IMG tags with value 'image-rendering' set to 'pixelated', which can be useful for people who use pixel art in their READMEs (to demonstrate items, for example). * fix user page + hydration issue fix from Brawaru * Rename to proxies * Make categories use title case * Always show project type on moderation page, improve project type display on project pages * Remove invalid key * Missed a check * Fix browse menu animation * Fix disabled button condition and minimum width for 2 lines * Body -> Description in edit pages * More casing consistency issues * Fix duplicate version URLs * Fix version creation * Edit URLs, fix privacy page buttons * Fix notifications popup overlaying * Final merge fixes Co-authored-by: Prospector <prospectordev@gmail.com> Co-authored-by: Sasha Sorokin <10401817+Brawaru@users.noreply.github.com>
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
export default function (to, from, savedPosition) {
|
export default function (to, from, savedPosition) {
|
||||||
if (to.name.startsWith('type-id') && from.name.startsWith('type-id')) {
|
if (
|
||||||
|
from == null ||
|
||||||
|
(to.name.startsWith('type-id') && from.name.startsWith('type-id')) ||
|
||||||
|
to.name === from.name
|
||||||
|
) {
|
||||||
return savedPosition
|
return savedPosition
|
||||||
} else {
|
} else {
|
||||||
return { x: 0, y: 0 }
|
return { x: 0, y: 0 }
|
||||||
|
|||||||
@@ -263,6 +263,14 @@
|
|||||||
> :last-child {
|
> :last-child {
|
||||||
margin-bottom: 0 !important;
|
margin-bottom: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 850px) {
|
||||||
|
iframe {
|
||||||
|
aspect-ratio: 16 / 9;
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tooltip {
|
.tooltip {
|
||||||
@@ -826,12 +834,12 @@ label {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.vue-notification {
|
.vue-notification {
|
||||||
background: #44A4FC;
|
background: #44a4fc;
|
||||||
border-left: 5px solid #44A4FC;
|
border-left: 5px solid #44a4fc;
|
||||||
|
|
||||||
&.success {
|
&.success {
|
||||||
background: #68CD86;
|
background: #68cd86;
|
||||||
border-left-color: #68CD86;
|
border-left-color: #68cd86;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.warn {
|
&.warn {
|
||||||
@@ -840,25 +848,43 @@ label {
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.error {
|
&.error {
|
||||||
background: #E54D42;
|
background: #e54d42;
|
||||||
border-left-color: #E54D42;
|
border-left-color: #e54d42;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.vue-notification-group {
|
.vue-notification-group {
|
||||||
right: 25px !important;
|
right: 25px !important;
|
||||||
|
bottom: 25px !important;
|
||||||
|
|
||||||
.vue-notification-template {
|
.vue-notification-wrapper {
|
||||||
border-radius: var(--size-rounded-card);
|
margin-bottom: 10px;
|
||||||
margin: 0 0 25px 0;
|
|
||||||
|
|
||||||
.notification-title {
|
.vue-notification-template {
|
||||||
font-size: var(--font-size-lg);
|
border-radius: var(--size-rounded-card);
|
||||||
margin-right: auto;
|
margin: 0;
|
||||||
|
|
||||||
|
.notification-title {
|
||||||
|
font-size: var(--font-size-lg);
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notification-content {
|
||||||
|
font-size: var(--font-size-md);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.notification-content {
|
&:last-child {
|
||||||
font-size: var(--font-size-md);
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 750px) {
|
||||||
|
transition: bottom 0.25s ease-in-out;
|
||||||
|
bottom: calc(var(--size-mobile-navbar-height) + 10px) !important;
|
||||||
|
|
||||||
|
&.browse-menu-open {
|
||||||
|
bottom: calc(var(--size-mobile-navbar-height-expanded) + 10px) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,7 +208,9 @@ body {
|
|||||||
--size-rounded-tooltip: 0.25rem;
|
--size-rounded-tooltip: 0.25rem;
|
||||||
|
|
||||||
--size-navbar-height: 3.5rem;
|
--size-navbar-height: 3.5rem;
|
||||||
--size-mobile-navbar-height: 4rem;
|
--size-mobile-navbar-height: 3.5rem;
|
||||||
|
// --size-mobile-navbar-height-expanded: 10rem;
|
||||||
|
--size-mobile-navbar-height-expanded: 7.5rem;
|
||||||
|
|
||||||
--spacing-card-lg: 1.5rem;
|
--spacing-card-lg: 1.5rem;
|
||||||
--spacing-card-bg: 1rem;
|
--spacing-card-bg: 1rem;
|
||||||
@@ -235,6 +237,10 @@ body {
|
|||||||
--font-weight-text: var(--font-weight-medium);
|
--font-weight-text: var(--font-weight-medium);
|
||||||
--font-weight-heading: var(--font-weight-extrabold);
|
--font-weight-heading: var(--font-weight-extrabold);
|
||||||
--font-weight-title: var(--font-weight-extrabold);
|
--font-weight-title: var(--font-weight-extrabold);
|
||||||
|
|
||||||
|
@media screen and (min-width: 501px) {
|
||||||
|
--size-mobile-navbar-height-expanded: 7rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
|
|||||||
@@ -3,13 +3,15 @@
|
|||||||
<div
|
<div
|
||||||
ref="container"
|
ref="container"
|
||||||
class="container"
|
class="container"
|
||||||
:style="{ visibility: shown ? 'visible' : 'hidden' }"
|
:class="{ 'mobile-menu-open': mobileMenuOpen }"
|
||||||
|
:style="{
|
||||||
|
visibility: shown ? 'visible' : 'hidden',
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<div class="card banner">
|
<div class="card banner">
|
||||||
<span>
|
<span>
|
||||||
Modrinth uses cookies for various purposes, including advertising.<br />
|
Modrinth uses cookies for various purposes. We encourage you to review
|
||||||
We encourage you to review your privacy settings by clicking on the
|
your privacy settings by clicking on the button below:
|
||||||
button below:
|
|
||||||
</span>
|
</span>
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<button class="btn button" @click="review">Review</button>
|
<button class="btn button" @click="review">Review</button>
|
||||||
@@ -24,6 +26,12 @@
|
|||||||
import scopes from '~/privacy-toggles'
|
import scopes from '~/privacy-toggles'
|
||||||
export default {
|
export default {
|
||||||
name: 'CookieConsent',
|
name: 'CookieConsent',
|
||||||
|
props: {
|
||||||
|
mobileMenuOpen: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
shown: false,
|
shown: false,
|
||||||
@@ -68,15 +76,18 @@ export default {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
z-index: 20;
|
z-index: 2;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 4rem;
|
|
||||||
right: 0;
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
.banner {
|
.banner {
|
||||||
padding: 1rem;
|
|
||||||
font-size: 1.05rem;
|
font-size: 1.05rem;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
box-shadow: 0 0 20px 2px rgba(0, 0, 0, 0.3);
|
||||||
|
padding: 1rem 1rem calc(var(--size-mobile-navbar-height) + 1rem);
|
||||||
|
transition: padding-bottom 0.25s ease-in-out;
|
||||||
}
|
}
|
||||||
.actions {
|
.actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -89,11 +100,23 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (min-width: 750px) {
|
.banner {
|
||||||
bottom: 0;
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.mobile-menu-open {
|
||||||
.banner {
|
.banner {
|
||||||
margin-bottom: 0;
|
padding-bottom: calc(var(--size-mobile-navbar-height-expanded) + 1rem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 750px) {
|
||||||
|
.banner {
|
||||||
|
padding-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.mobile-menu-open {
|
||||||
|
bottom: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,7 +125,9 @@ export default {
|
|||||||
text-align: unset;
|
text-align: unset;
|
||||||
|
|
||||||
.banner {
|
.banner {
|
||||||
max-width: 18vw;
|
border-radius: var(--size-rounded-card);
|
||||||
|
width: 18vw;
|
||||||
|
min-width: 16rem;
|
||||||
border-left: solid 5px var(--color-brand);
|
border-left: solid 5px var(--color-brand);
|
||||||
margin: 0 2rem 2rem 0;
|
margin: 0 2rem 2rem 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,13 +28,16 @@
|
|||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="side-type">
|
<div
|
||||||
|
v-if="type !== 'resourcepack' && projectTypeDisplay !== 'plugin'"
|
||||||
|
class="side-type"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
v-if="clientSide === 'optional' && serverSide === 'optional'"
|
v-if="clientSide === 'optional' && serverSide === 'optional'"
|
||||||
class="side-descriptor"
|
class="side-descriptor"
|
||||||
>
|
>
|
||||||
<InfoIcon aria-hidden="true" />
|
<InfoIcon aria-hidden="true" />
|
||||||
Universal {{ type }}
|
Universal {{ projectTypeDisplay }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-else-if="
|
v-else-if="
|
||||||
@@ -44,7 +47,7 @@
|
|||||||
class="side-descriptor"
|
class="side-descriptor"
|
||||||
>
|
>
|
||||||
<InfoIcon aria-hidden="true" />
|
<InfoIcon aria-hidden="true" />
|
||||||
Client {{ type }}
|
Client {{ projectTypeDisplay }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-else-if="
|
v-else-if="
|
||||||
@@ -54,8 +57,16 @@
|
|||||||
class="side-descriptor"
|
class="side-descriptor"
|
||||||
>
|
>
|
||||||
<InfoIcon aria-hidden="true" />
|
<InfoIcon aria-hidden="true" />
|
||||||
Server {{ type }}
|
Server {{ projectTypeDisplay }}
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else-if="moderation" class="side-descriptor">
|
||||||
|
<InfoIcon aria-hidden="true" />
|
||||||
|
A {{ projectTypeDisplay }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="moderation" class="side-descriptor">
|
||||||
|
<InfoIcon aria-hidden="true" />
|
||||||
|
A {{ projectTypeDisplay }}
|
||||||
</div>
|
</div>
|
||||||
<p class="description">
|
<p class="description">
|
||||||
{{ description }}
|
{{ description }}
|
||||||
@@ -217,6 +228,16 @@ export default {
|
|||||||
required: false,
|
required: false,
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
|
moderation: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
projectTypeDisplay() {
|
||||||
|
return this.$getProjectTypeForDisplay(this.type, this.categories)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -43,11 +43,15 @@ export default {
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
button {
|
button {
|
||||||
|
text-transform: capitalize;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
text-transform: capitalize;
|
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button span::first-letter {
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -5,16 +5,16 @@
|
|||||||
>
|
>
|
||||||
<Multiselect
|
<Multiselect
|
||||||
v-if="getValidLoaders().length > 1"
|
v-if="getValidLoaders().length > 1"
|
||||||
v-model="selectedLoader"
|
v-model="selectedLoaders"
|
||||||
:options="getValidLoaders()"
|
:options="getValidLoaders()"
|
||||||
:custom-label="(value) => value.charAt(0).toUpperCase() + value.slice(1)"
|
:custom-label="(value) => value.charAt(0).toUpperCase() + value.slice(1)"
|
||||||
:multiple="false"
|
:multiple="true"
|
||||||
:searchable="false"
|
:searchable="false"
|
||||||
:show-no-results="false"
|
:show-no-results="false"
|
||||||
:close-on-select="true"
|
:close-on-select="true"
|
||||||
:clear-search-on-select="false"
|
:clear-search-on-select="false"
|
||||||
:show-labels="false"
|
:show-labels="false"
|
||||||
:allow-empty="false"
|
:allow-empty="true"
|
||||||
:disabled="getValidLoaders().length === 1"
|
:disabled="getValidLoaders().length === 1"
|
||||||
placeholder="Filter loader..."
|
placeholder="Filter loader..."
|
||||||
@input="updateVersionFilters()"
|
@input="updateVersionFilters()"
|
||||||
@@ -51,10 +51,12 @@
|
|||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
title="Clear filters"
|
title="Clear filters"
|
||||||
:disabled="selectedLoader === null && selectedGameVersions.length === 0"
|
:disabled="
|
||||||
|
selectedLoaders.length === 0 && selectedGameVersions.length === 0
|
||||||
|
"
|
||||||
class="iconified-button"
|
class="iconified-button"
|
||||||
@click="
|
@click="
|
||||||
selectedLoader = null
|
selectedLoaders = []
|
||||||
selectedGameVersions = []
|
selectedGameVersions = []
|
||||||
updateVersionFilters()
|
updateVersionFilters()
|
||||||
"
|
"
|
||||||
@@ -90,7 +92,7 @@ export default {
|
|||||||
cachedValidVersions: null,
|
cachedValidVersions: null,
|
||||||
cachedValidLoaders: null,
|
cachedValidLoaders: null,
|
||||||
selectedGameVersions: [],
|
selectedGameVersions: [],
|
||||||
selectedLoader: null,
|
selectedLoaders: [],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -124,8 +126,10 @@ export default {
|
|||||||
this.selectedGameVersions.some((gameVersion) =>
|
this.selectedGameVersions.some((gameVersion) =>
|
||||||
projectVersion.game_versions.includes(gameVersion)
|
projectVersion.game_versions.includes(gameVersion)
|
||||||
)) &&
|
)) &&
|
||||||
(this.selectedLoader === null ||
|
(this.selectedLoaders.length === 0 ||
|
||||||
projectVersion.loaders.includes(this.selectedLoader))
|
this.selectedLoaders.some((loader) =>
|
||||||
|
projectVersion.loaders.includes(loader)
|
||||||
|
))
|
||||||
)
|
)
|
||||||
this.$emit('updateVersions', temp)
|
this.$emit('updateVersions', temp)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,10 +3,7 @@
|
|||||||
<span
|
<span
|
||||||
v-for="category in categoriesFiltered"
|
v-for="category in categoriesFiltered"
|
||||||
:key="category.name"
|
:key="category.name"
|
||||||
v-html="
|
v-html="category.icon + $formatCategory(category.name)"
|
||||||
category.icon +
|
|
||||||
(category.name === 'modloader' ? 'ModLoader' : category.name)
|
|
||||||
"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -33,7 +30,8 @@ export default {
|
|||||||
.filter(
|
.filter(
|
||||||
(x) =>
|
(x) =>
|
||||||
this.categories.includes(x.name) &&
|
this.categories.includes(x.name) &&
|
||||||
(!x.project_type || x.project_type === this.type)
|
(!x.project_type || x.project_type === this.type) &&
|
||||||
|
x.name !== 'minecraft'
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -52,7 +50,6 @@ export default {
|
|||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
color: var(--color-icon);
|
color: var(--color-icon);
|
||||||
margin-right: 1em;
|
margin-right: 1em;
|
||||||
text-transform: capitalize;
|
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
width: 1rem;
|
width: 1rem;
|
||||||
|
|||||||
@@ -69,7 +69,6 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
text-transform: capitalize;
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="layout">
|
<div ref="layout" class="layout">
|
||||||
<header class="site-header" role="presentation">
|
<header class="site-header" role="presentation">
|
||||||
<section class="navbar columns" role="navigation">
|
<section class="navbar columns" role="navigation">
|
||||||
<section class="skip column" role="presentation">
|
<section class="skip column" role="presentation">
|
||||||
<a href="#main">Skip to Main Content</a>
|
<a href="#main">Skip to Main Content</a>
|
||||||
<a v-if="registeredSkipLink" :href="registeredSkipLink.id">{{
|
<a
|
||||||
registeredSkipLink.text
|
v-show="!!registeredSkipLink"
|
||||||
}}</a>
|
:href="(registeredSkipLink || {}).id"
|
||||||
|
>{{ (registeredSkipLink || {}).text }}</a
|
||||||
|
>
|
||||||
</section>
|
</section>
|
||||||
<section class="logo column" role="presentation">
|
<section class="logo column" role="presentation">
|
||||||
<NuxtLink to="/" aria-label="Modrinth home page">
|
<NuxtLink to="/" aria-label="Modrinth home page">
|
||||||
@@ -19,7 +21,13 @@
|
|||||||
<NuxtLink to="/mods" class="tab">
|
<NuxtLink to="/mods" class="tab">
|
||||||
<span>Mods</span>
|
<span>Mods</span>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<NuxtLink to="/modpacks" class="tab tab--alpha">
|
<!-- <NuxtLink to="/plugins" class="tab">-->
|
||||||
|
<!-- <span>Plugins</span>-->
|
||||||
|
<!-- </NuxtLink>-->
|
||||||
|
<!-- <NuxtLink to="/resourcepacks" class="tab">-->
|
||||||
|
<!-- <span>Resource Packs</span>-->
|
||||||
|
<!-- </NuxtLink>-->
|
||||||
|
<NuxtLink to="/modpacks" class="tab">
|
||||||
<span>Modpacks</span>
|
<span>Modpacks</span>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</div>
|
</div>
|
||||||
@@ -162,23 +170,62 @@
|
|||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
<section class="mobile-navbar">
|
<section ref="mobileNavBar" class="mobile-navbar">
|
||||||
<NuxtLink to="/" class="tab">
|
<div class="top-row">
|
||||||
<HomeIcon />
|
<NuxtLink to="/" class="tab" @click.native="closeBrowseMenu()">
|
||||||
<span>Home</span>
|
<HomeIcon />
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<NuxtLink to="/mods" class="tab">
|
<div class="spacer"></div>
|
||||||
<ModIcon />
|
<button class="tab browse" @click="toggleBrowseMenu()">
|
||||||
<span>Mods</span>
|
<DropdownIcon :class="{ closed: !isBrowseMenuOpen }" />
|
||||||
</NuxtLink>
|
<span>Browse</span>
|
||||||
<NuxtLink to="/modpacks" class="tab">
|
</button>
|
||||||
<ModpackIcon />
|
<div class="spacer"></div>
|
||||||
<span>Modpacks</span>
|
<button class="tab" @click="toggleMobileMenu()">
|
||||||
</NuxtLink>
|
<HamburgerIcon v-if="!isMobileMenuOpen" />
|
||||||
<button class="tab" @click="toggleMobileMenu()">
|
<CrossIcon v-else />
|
||||||
<HamburgerIcon />
|
</button>
|
||||||
<span>{{ isMobileMenuOpen ? 'Less' : 'More' }}</span>
|
</div>
|
||||||
</button>
|
<div
|
||||||
|
:class="{ 'disable-childern': !isBrowseMenuOpen }"
|
||||||
|
class="project-types"
|
||||||
|
>
|
||||||
|
<NuxtLink
|
||||||
|
:tabindex="isBrowseMenuOpen ? 0 : -1"
|
||||||
|
to="/mods"
|
||||||
|
class="tab"
|
||||||
|
@click.native="closeBrowseMenu()"
|
||||||
|
>
|
||||||
|
<span>Mods</span>
|
||||||
|
</NuxtLink>
|
||||||
|
|
||||||
|
<!-- <NuxtLink-->
|
||||||
|
<!-- :tabindex="isBrowseMenuOpen ? 0 : -1"-->
|
||||||
|
<!-- to="/plugins"-->
|
||||||
|
<!-- class="tab"-->
|
||||||
|
<!-- @click.native="closeBrowseMenu()"-->
|
||||||
|
<!-- >-->
|
||||||
|
<!-- <span>Plugins</span>-->
|
||||||
|
<!-- </NuxtLink>-->
|
||||||
|
|
||||||
|
<!-- <NuxtLink-->
|
||||||
|
<!-- :tabindex="isBrowseMenuOpen ? 0 : -1"-->
|
||||||
|
<!-- to="/resourcepacks"-->
|
||||||
|
<!-- class="tab"-->
|
||||||
|
<!-- @click.native="closeBrowseMenu()"-->
|
||||||
|
<!-- >-->
|
||||||
|
<!-- <span>Resource Packs</span>-->
|
||||||
|
<!-- </NuxtLink>-->
|
||||||
|
|
||||||
|
<NuxtLink
|
||||||
|
:tabindex="isBrowseMenuOpen ? 0 : -1"
|
||||||
|
to="/modpacks"
|
||||||
|
class="tab"
|
||||||
|
@click.native="closeBrowseMenu()"
|
||||||
|
>
|
||||||
|
<span>Modpacks</span>
|
||||||
|
</NuxtLink>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section ref="mobileMenu" class="mobile-menu">
|
<section ref="mobileMenu" class="mobile-menu">
|
||||||
<div class="mobile-menu-wrapper">
|
<div class="mobile-menu-wrapper">
|
||||||
@@ -239,11 +286,12 @@
|
|||||||
</section>
|
</section>
|
||||||
</header>
|
</header>
|
||||||
<main>
|
<main>
|
||||||
<CookieConsent />
|
<CookieConsent :mobile-menu-open="isBrowseMenuOpen" />
|
||||||
<notifications
|
<notifications
|
||||||
group="main"
|
group="main"
|
||||||
position="bottom right"
|
position="bottom right"
|
||||||
:max="5"
|
:max="5"
|
||||||
|
:class="{ 'browse-menu-open': isBrowseMenuOpen }"
|
||||||
:ignore-duplicates="true"
|
:ignore-duplicates="true"
|
||||||
:duration="10000"
|
:duration="10000"
|
||||||
/>
|
/>
|
||||||
@@ -312,16 +360,15 @@ import ClickOutside from 'vue-click-outside'
|
|||||||
import ModrinthLogo from '~/assets/images/text-logo.svg?inline'
|
import ModrinthLogo from '~/assets/images/text-logo.svg?inline'
|
||||||
|
|
||||||
import HamburgerIcon from '~/assets/images/utils/hamburger.svg?inline'
|
import HamburgerIcon from '~/assets/images/utils/hamburger.svg?inline'
|
||||||
|
import CrossIcon from '~/assets/images/utils/x.svg?inline'
|
||||||
|
|
||||||
import NotificationIcon from '~/assets/images/sidebar/notifications.svg?inline'
|
import NotificationIcon from '~/assets/images/sidebar/notifications.svg?inline'
|
||||||
import SettingsIcon from '~/assets/images/sidebar/settings.svg?inline'
|
import SettingsIcon from '~/assets/images/sidebar/settings.svg?inline'
|
||||||
import ShieldIcon from '~/assets/images/utils/shield.svg?inline'
|
import ShieldIcon from '~/assets/images/utils/shield.svg?inline'
|
||||||
import ModerationIcon from '~/assets/images/sidebar/admin.svg?inline'
|
import ModerationIcon from '~/assets/images/sidebar/admin.svg?inline'
|
||||||
import HomeIcon from '~/assets/images/sidebar/home.svg?inline'
|
import HomeIcon from '~/assets/images/sidebar/home.svg?inline'
|
||||||
import ModIcon from '~/assets/images/sidebar/mod.svg?inline'
|
|
||||||
import ModpackIcon from '~/assets/images/sidebar/modpack.svg?inline'
|
|
||||||
import MoonIcon from '~/assets/images/utils/moon.svg?inline'
|
|
||||||
|
|
||||||
|
import MoonIcon from '~/assets/images/utils/moon.svg?inline'
|
||||||
import SunIcon from '~/assets/images/utils/sun.svg?inline'
|
import SunIcon from '~/assets/images/utils/sun.svg?inline'
|
||||||
import PlusIcon from '~/assets/images/utils/plus.svg?inline'
|
import PlusIcon from '~/assets/images/utils/plus.svg?inline'
|
||||||
import DropdownIcon from '~/assets/images/utils/dropdown.svg?inline'
|
import DropdownIcon from '~/assets/images/utils/dropdown.svg?inline'
|
||||||
@@ -343,8 +390,7 @@ export default {
|
|||||||
GitHubIcon,
|
GitHubIcon,
|
||||||
NotificationIcon,
|
NotificationIcon,
|
||||||
HomeIcon,
|
HomeIcon,
|
||||||
ModIcon,
|
CrossIcon,
|
||||||
ModpackIcon,
|
|
||||||
HamburgerIcon,
|
HamburgerIcon,
|
||||||
CookieConsent,
|
CookieConsent,
|
||||||
SettingsIcon,
|
SettingsIcon,
|
||||||
@@ -365,6 +411,7 @@ export default {
|
|||||||
branch: process.env.branch || 'master',
|
branch: process.env.branch || 'master',
|
||||||
hash: process.env.hash || 'unknown',
|
hash: process.env.hash || 'unknown',
|
||||||
isMobileMenuOpen: false,
|
isMobileMenuOpen: false,
|
||||||
|
isBrowseMenuOpen: false,
|
||||||
registeredSkipLink: null,
|
registeredSkipLink: null,
|
||||||
moderationNotifications: 0,
|
moderationNotifications: 0,
|
||||||
}
|
}
|
||||||
@@ -429,6 +476,37 @@ export default {
|
|||||||
document.body.style.overflowY !== 'hidden' ? 'hidden' : overflowStyle
|
document.body.style.overflowY !== 'hidden' ? 'hidden' : overflowStyle
|
||||||
|
|
||||||
this.isMobileMenuOpen = !currentlyActive
|
this.isMobileMenuOpen = !currentlyActive
|
||||||
|
|
||||||
|
if (this.isMobileMenuOpen) {
|
||||||
|
this.$refs.mobileNavBar.className = `mobile-navbar`
|
||||||
|
this.$refs.layout.className = `layout`
|
||||||
|
|
||||||
|
this.isBrowseMenuOpen = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toggleBrowseMenu() {
|
||||||
|
const currentlyActive =
|
||||||
|
this.$refs.mobileNavBar.className === 'mobile-navbar expanded'
|
||||||
|
this.$refs.mobileNavBar.className = `mobile-navbar${
|
||||||
|
currentlyActive ? '' : ' expanded'
|
||||||
|
}`
|
||||||
|
this.$refs.layout.className = `layout${
|
||||||
|
currentlyActive ? '' : ' expanded-mobile-nav'
|
||||||
|
}`
|
||||||
|
|
||||||
|
this.isBrowseMenuOpen = !currentlyActive
|
||||||
|
|
||||||
|
if (this.isBrowseMenuOpen) {
|
||||||
|
this.$refs.mobileMenu.className = `mobile-menu`
|
||||||
|
|
||||||
|
this.isMobileMenuOpen = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
closeBrowseMenu() {
|
||||||
|
this.$refs.mobileNavBar.className = `mobile-navbar`
|
||||||
|
this.$refs.layout.className = `layout`
|
||||||
|
|
||||||
|
this.isBrowseMenuOpen = false
|
||||||
},
|
},
|
||||||
async logout() {
|
async logout() {
|
||||||
this.$cookies.set('auth-token-reset', true)
|
this.$cookies.set('auth-token-reset', true)
|
||||||
@@ -453,16 +531,6 @@ export default {
|
|||||||
removeFocus() {
|
removeFocus() {
|
||||||
document.activeElement.blur() // This doesn't work, sadly. Help
|
document.activeElement.blur() // This doesn't work, sadly. Help
|
||||||
},
|
},
|
||||||
async getModerationCount() {
|
|
||||||
const [projects, reports] = (
|
|
||||||
await Promise.all([
|
|
||||||
this.$axios.get(`moderation/projects`, this.$defaultHeaders()),
|
|
||||||
this.$axios.get(`report`, this.$defaultHeaders()),
|
|
||||||
])
|
|
||||||
).map((it) => it.data)
|
|
||||||
|
|
||||||
return projects.length + reports.length
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -819,34 +887,36 @@ export default {
|
|||||||
.mobile-navbar {
|
.mobile-navbar {
|
||||||
display: none;
|
display: none;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
transition: height 0.25s ease-in-out;
|
||||||
height: var(--size-mobile-navbar-height);
|
height: var(--size-mobile-navbar-height);
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: 0;
|
left: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
background-color: var(--color-raised-bg);
|
background-color: var(--color-raised-bg);
|
||||||
box-shadow: 0 0 20px 2px rgba(0, 0, 0, 0.3);
|
box-shadow: 0 0 20px 2px rgba(0, 0, 0, 0.3);
|
||||||
z-index: 6;
|
z-index: 6;
|
||||||
|
flex-direction: column;
|
||||||
|
border-radius: var(--size-rounded-card) var(--size-rounded-card) 0 0;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
.tab {
|
.tab {
|
||||||
background: none;
|
background: none;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-grow: 1;
|
|
||||||
flex-basis: 0;
|
flex-basis: 0;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-direction: column;
|
flex-direction: row;
|
||||||
|
gap: 0.25rem;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: auto;
|
|
||||||
transition: color ease-in-out 0.15s;
|
transition: color ease-in-out 0.15s;
|
||||||
color: var(--color-text-inactive);
|
color: var(--color-text-inactive);
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
height: 1.75rem;
|
height: 1.75rem;
|
||||||
width: 1.75rem;
|
width: 1.75rem;
|
||||||
margin-bottom: 0.25rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
@@ -863,9 +933,72 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.top-row {
|
||||||
|
min-height: var(--size-mobile-navbar-height);
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.browse {
|
||||||
|
flex-grow: 10;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
transition: transform 0.125s ease-in-out;
|
||||||
|
|
||||||
|
&.closed {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab {
|
||||||
|
&:first-child {
|
||||||
|
margin-left: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-right: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.spacer {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.disable-childern {
|
||||||
|
a {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-types {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
row-gap: 0.5rem;
|
||||||
|
|
||||||
|
.tab {
|
||||||
|
flex: 0 0 fit-content;
|
||||||
|
background-color: var(--color-button-bg);
|
||||||
|
padding: 0.5rem 1.25rem;
|
||||||
|
margin: 0 0.25rem;
|
||||||
|
border-radius: var(--size-rounded-max);
|
||||||
|
|
||||||
|
&.nuxt-link-exact-active {
|
||||||
|
background-color: var(--color-brand);
|
||||||
|
color: var(--color-brand-inverted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 750px) {
|
@media screen and (max-width: 750px) {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.expanded {
|
||||||
|
height: var(--size-mobile-navbar-height-expanded);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -874,12 +1007,13 @@ export default {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
background-color: var(--color-bg);
|
background-color: var(--color-bg);
|
||||||
height: calc(100% - var(--size-mobile-navbar-height));
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
|
|
||||||
.mobile-menu-wrapper {
|
.mobile-menu-wrapper {
|
||||||
max-height: calc(100vh - var(--size-mobile-navbar-height));
|
max-height: calc(100vh - var(--size-mobile-navbar-height));
|
||||||
|
margin-bottom: var(--size-mobile-navbar-height);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
margin-top: auto;
|
margin-top: auto;
|
||||||
|
|
||||||
@@ -903,6 +1037,7 @@ export default {
|
|||||||
|
|
||||||
&.nuxt-link-exact-active {
|
&.nuxt-link-exact-active {
|
||||||
color: var(--color-button-text-active);
|
color: var(--color-button-text-active);
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
color: var(--color-brand);
|
color: var(--color-brand);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -155,6 +155,16 @@ export default {
|
|||||||
component: resolve(__dirname, 'pages/search/modpacks.vue'),
|
component: resolve(__dirname, 'pages/search/modpacks.vue'),
|
||||||
name: 'modpacks',
|
name: 'modpacks',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/plugins',
|
||||||
|
component: resolve(__dirname, 'pages/search/plugins.vue'),
|
||||||
|
name: 'plugins',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/resourcepacks',
|
||||||
|
component: resolve(__dirname, 'pages/search/resourcepacks.vue'),
|
||||||
|
name: 'resourcepacks',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -222,7 +232,7 @@ export default {
|
|||||||
'/search/**',
|
'/search/**',
|
||||||
'/create/**',
|
'/create/**',
|
||||||
],
|
],
|
||||||
routes: ['mods', 'modpacks'],
|
routes: ['mods', 'modpacks', 'resourcepacks', 'plugins'],
|
||||||
},
|
},
|
||||||
/*
|
/*
|
||||||
** Axios module configuration
|
** Axios module configuration
|
||||||
@@ -309,7 +319,7 @@ export default {
|
|||||||
},
|
},
|
||||||
hooks: {
|
hooks: {
|
||||||
render: {
|
render: {
|
||||||
routeDone(url) {
|
routeDone(url, result, context) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
axios
|
axios
|
||||||
.post(
|
.post(
|
||||||
@@ -323,6 +333,12 @@ export default {
|
|||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
'Modrinth-Admin': process.env.ARIADNE_ADMIN_KEY || 'feedbeef',
|
'Modrinth-Admin': process.env.ARIADNE_ADMIN_KEY || 'feedbeef',
|
||||||
|
'User-Agent':
|
||||||
|
context.req.rawHeaders[
|
||||||
|
context.req.rawHeaders.findIndex(
|
||||||
|
(x) => x === 'User-Agent'
|
||||||
|
) + 1
|
||||||
|
],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -36,38 +36,46 @@
|
|||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
<div
|
<div
|
||||||
v-if="
|
v-if="
|
||||||
project.client_side === 'optional' &&
|
project.project_type !== 'resourcepack' &&
|
||||||
project.server_side === 'optional'
|
projectTypeDisplay !== 'plugin'
|
||||||
"
|
"
|
||||||
class="side-descriptor"
|
|
||||||
>
|
>
|
||||||
<InfoIcon aria-hidden="true" />
|
<div
|
||||||
Universal {{ project.project_type }}
|
v-if="
|
||||||
</div>
|
project.client_side === 'optional' &&
|
||||||
<div
|
project.server_side === 'optional'
|
||||||
v-else-if="
|
"
|
||||||
(project.client_side === 'optional' ||
|
class="side-descriptor"
|
||||||
project.client_side === 'required') &&
|
>
|
||||||
(project.server_side === 'optional' ||
|
<InfoIcon aria-hidden="true" />
|
||||||
project.server_side === 'unsupported')
|
Universal {{ projectTypeDisplay }}
|
||||||
"
|
</div>
|
||||||
class="side-descriptor"
|
<div
|
||||||
>
|
v-else-if="
|
||||||
<InfoIcon aria-hidden="true" />
|
(project.client_side === 'optional' ||
|
||||||
Client {{ project.project_type }}
|
project.client_side === 'required') &&
|
||||||
</div>
|
(project.server_side === 'optional' ||
|
||||||
<div
|
project.server_side === 'unsupported')
|
||||||
v-else-if="
|
"
|
||||||
(project.server_side === 'optional' ||
|
class="side-descriptor"
|
||||||
project.server_side === 'required') &&
|
>
|
||||||
(project.client_side === 'optional' ||
|
<InfoIcon aria-hidden="true" />
|
||||||
project.client_side === 'unsupported')
|
Client {{ projectTypeDisplay }}
|
||||||
"
|
</div>
|
||||||
class="side-descriptor"
|
<div
|
||||||
>
|
v-else-if="
|
||||||
<InfoIcon aria-hidden="true" />
|
(project.server_side === 'optional' ||
|
||||||
Server {{ project.project_type }}
|
project.server_side === 'required') &&
|
||||||
|
(project.client_side === 'optional' ||
|
||||||
|
project.client_side === 'unsupported')
|
||||||
|
"
|
||||||
|
class="side-descriptor"
|
||||||
|
>
|
||||||
|
<InfoIcon aria-hidden="true" />
|
||||||
|
Server {{ projectTypeDisplay }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="description">
|
<p class="description">
|
||||||
{{ project.description }}
|
{{ project.description }}
|
||||||
</p>
|
</p>
|
||||||
@@ -389,7 +397,7 @@
|
|||||||
<nuxt-link
|
<nuxt-link
|
||||||
:to="`/${project.project_type}/${
|
:to="`/${project.project_type}/${
|
||||||
project.slug ? project.slug : project.id
|
project.slug ? project.slug : project.id
|
||||||
}/version/${encodeURIComponent(version.version_number)}`"
|
}/version/${encodeURI(version.displayUrlEnding)}`"
|
||||||
class="top title-link"
|
class="top title-link"
|
||||||
>
|
>
|
||||||
{{ version.name }}
|
{{ version.name }}
|
||||||
@@ -398,15 +406,7 @@
|
|||||||
v-if="version.game_versions.length > 0"
|
v-if="version.game_versions.length > 0"
|
||||||
class="game-version item"
|
class="game-version item"
|
||||||
>
|
>
|
||||||
{{
|
{{ version.loaders.map((x) => $formatCategory(x)).join(', ') }}
|
||||||
version.loaders
|
|
||||||
.map((x) =>
|
|
||||||
x.toLowerCase() === 'modloader'
|
|
||||||
? 'ModLoader'
|
|
||||||
: x.charAt(0).toUpperCase() + x.slice(1)
|
|
||||||
)
|
|
||||||
.join(', ')
|
|
||||||
}}
|
|
||||||
{{ $formatVersion(version.game_versions) }}
|
{{ $formatVersion(version.game_versions) }}
|
||||||
</div>
|
</div>
|
||||||
<VersionBadge
|
<VersionBadge
|
||||||
@@ -455,13 +455,25 @@
|
|||||||
}}</a>
|
}}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="info">
|
<div
|
||||||
|
v-if="
|
||||||
|
project.project_type !== 'resourcepack' &&
|
||||||
|
projectTypeDisplay !== 'plugin'
|
||||||
|
"
|
||||||
|
class="info"
|
||||||
|
>
|
||||||
<div class="key">Client side</div>
|
<div class="key">Client side</div>
|
||||||
<div class="value">
|
<div class="value">
|
||||||
{{ project.client_side }}
|
{{ project.client_side }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="info">
|
<div
|
||||||
|
v-if="
|
||||||
|
project.project_type !== 'resourcepack' &&
|
||||||
|
projectTypeDisplay !== 'plugin'
|
||||||
|
"
|
||||||
|
class="info"
|
||||||
|
>
|
||||||
<div class="key">Server side</div>
|
<div class="key">Server side</div>
|
||||||
<div class="value">
|
<div class="value">
|
||||||
{{ project.server_side }}
|
{{ project.server_side }}
|
||||||
@@ -647,7 +659,7 @@ export default {
|
|||||||
Categories,
|
Categories,
|
||||||
},
|
},
|
||||||
async asyncData(data) {
|
async asyncData(data) {
|
||||||
const projectTypes = ['mod', 'modpack']
|
const projectTypes = ['mod', 'modpack', 'resourcepack']
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (
|
if (
|
||||||
@@ -706,6 +718,16 @@ export default {
|
|||||||
project.body = (await data.$axios.get(project.body_url)).data
|
project.body = (await data.$axios.get(project.body_url)).data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const loaders = []
|
||||||
|
|
||||||
|
versions.forEach((version) => {
|
||||||
|
version.loaders.forEach((loader) => {
|
||||||
|
if (!loaders.includes(loader)) {
|
||||||
|
loaders.push(loader)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
project,
|
project,
|
||||||
versions,
|
versions,
|
||||||
@@ -714,6 +736,7 @@ export default {
|
|||||||
allMembers: members,
|
allMembers: members,
|
||||||
currentMember,
|
currentMember,
|
||||||
dependencies,
|
dependencies,
|
||||||
|
loaders,
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
data.error({
|
data.error({
|
||||||
@@ -727,6 +750,10 @@ export default {
|
|||||||
showKnownErrors: false,
|
showKnownErrors: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
fetch() {
|
||||||
|
this.versions = this.$computeVersions(this.versions)
|
||||||
|
this.featuredVersions = this.$computeVersions(this.featuredVersions)
|
||||||
|
},
|
||||||
head() {
|
head() {
|
||||||
return {
|
return {
|
||||||
title: `${this.project.title} - ${
|
title: `${this.project.title} - ${
|
||||||
@@ -779,6 +806,14 @@ export default {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
projectTypeDisplay() {
|
||||||
|
return this.$getProjectTypeForDisplay(
|
||||||
|
this.project.project_type,
|
||||||
|
this.loaders
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
findPrimary(version) {
|
findPrimary(version) {
|
||||||
let file = version.files.find((x) => x.primary)
|
let file = version.files.find((x) => x.primary)
|
||||||
@@ -1119,7 +1154,10 @@ export default {
|
|||||||
|
|
||||||
.value {
|
.value {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
text-transform: capitalize;
|
|
||||||
|
&::first-letter {
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
&.lowercase {
|
&.lowercase {
|
||||||
text-transform: none;
|
text-transform: none;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<nuxt-link
|
<nuxt-link
|
||||||
:to="`/${project.project_type}/${
|
:to="`/${project.project_type}/${
|
||||||
project.slug ? project.slug : project.id
|
project.slug ? project.slug : project.id
|
||||||
}/version/${encodeURIComponent(version.version_number)}`"
|
}/version/${encodeURI(version.displayUrlEnding)}`"
|
||||||
>{{ version.name }}</nuxt-link
|
>{{ version.name }}</nuxt-link
|
||||||
>
|
>
|
||||||
</h2>
|
</h2>
|
||||||
@@ -69,12 +69,6 @@ export default {
|
|||||||
DownloadIcon,
|
DownloadIcon,
|
||||||
VersionFilterControl,
|
VersionFilterControl,
|
||||||
},
|
},
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
filteredVersions: this.versions,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
auth: false,
|
|
||||||
props: {
|
props: {
|
||||||
project: {
|
project: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@@ -95,6 +89,12 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
filteredVersions: this.versions,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
auth: false,
|
||||||
methods: {
|
methods: {
|
||||||
updateVersions(updatedVersions) {
|
updateVersions(updatedVersions) {
|
||||||
this.filteredVersions = updatedVersions
|
this.filteredVersions = updatedVersions
|
||||||
|
|||||||
@@ -110,17 +110,13 @@
|
|||||||
<Multiselect
|
<Multiselect
|
||||||
id="categories"
|
id="categories"
|
||||||
v-model="newProject.categories"
|
v-model="newProject.categories"
|
||||||
:options="
|
:options="selectableCategories"
|
||||||
$tag.categories
|
|
||||||
.filter((x) => x.project_type === project.project_type)
|
|
||||||
.map((it) => it.name)
|
|
||||||
"
|
|
||||||
:custom-label="
|
:custom-label="
|
||||||
(value) => value.charAt(0).toUpperCase() + value.slice(1)
|
(value) => value.charAt(0).toUpperCase() + value.slice(1)
|
||||||
"
|
"
|
||||||
:loading="$tag.categories.length === 0"
|
:loading="$tag.categories.length === 0"
|
||||||
:multiple="true"
|
:multiple="true"
|
||||||
:searchable="false"
|
:searchable="true"
|
||||||
:show-no-results="false"
|
:show-no-results="false"
|
||||||
:close-on-select="false"
|
:close-on-select="false"
|
||||||
:clear-on-select="false"
|
:clear-on-select="false"
|
||||||
@@ -132,13 +128,46 @@
|
|||||||
:disabled="
|
:disabled="
|
||||||
(currentMember.permissions & EDIT_DETAILS) !== EDIT_DETAILS
|
(currentMember.permissions & EDIT_DETAILS) !== EDIT_DETAILS
|
||||||
"
|
"
|
||||||
|
@input="setCategories"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<span>
|
||||||
|
<h3>Additional Categories</h3>
|
||||||
|
<span class="no-padding">
|
||||||
|
Select up to 3 categories that will help others <br />
|
||||||
|
find your project.
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<Multiselect
|
||||||
|
id="additional_categories"
|
||||||
|
v-model="newProject.additional_categories"
|
||||||
|
:options="selectableAdditionalCategories"
|
||||||
|
:custom-label="
|
||||||
|
(value) => value.charAt(0).toUpperCase() + value.slice(1)
|
||||||
|
"
|
||||||
|
:loading="$tag.categories.length === 0"
|
||||||
|
:multiple="true"
|
||||||
|
:searchable="true"
|
||||||
|
:show-no-results="false"
|
||||||
|
:close-on-select="false"
|
||||||
|
:clear-on-select="false"
|
||||||
|
:show-labels="false"
|
||||||
|
:max="255"
|
||||||
|
:limit="6"
|
||||||
|
:hide-selected="true"
|
||||||
|
placeholder="Choose additional categories"
|
||||||
|
:disabled="
|
||||||
|
(currentMember.permissions & EDIT_DETAILS) !== EDIT_DETAILS
|
||||||
|
"
|
||||||
|
@input="setCategories"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<label class="vertical-input">
|
<label class="vertical-input">
|
||||||
<span>
|
<span>
|
||||||
<h3>Vanity URL (slug)<span class="required">*</span></h3>
|
<h3>Vanity URL (slug)<span class="required">*</span></h3>
|
||||||
<span class="slug-description"
|
<span class="slug-description"
|
||||||
>https://modrinth.com/{{ newProject.project_type.toLowerCase() }}/{{
|
>https://modrinth.com/{{ project.project_type.toLowerCase() }}/{{
|
||||||
newProject.slug ? newProject.slug : 'your-slug'
|
newProject.slug ? newProject.slug : 'your-slug'
|
||||||
}}
|
}}
|
||||||
</span>
|
</span>
|
||||||
@@ -189,7 +218,10 @@
|
|||||||
Reset
|
Reset
|
||||||
</button>
|
</button>
|
||||||
</section>
|
</section>
|
||||||
<section class="card game-sides">
|
<section
|
||||||
|
v-if="project.project_type !== 'resourcepack'"
|
||||||
|
class="card game-sides"
|
||||||
|
>
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div>
|
<div>
|
||||||
<h3>Supported environments</h3>
|
<h3>Supported environments</h3>
|
||||||
@@ -241,7 +273,7 @@
|
|||||||
for="body"
|
for="body"
|
||||||
title="You can type an extended description of your project here."
|
title="You can type an extended description of your project here."
|
||||||
>
|
>
|
||||||
Body<span class="required">*</span>
|
Description<span class="required">*</span>
|
||||||
</label>
|
</label>
|
||||||
</h3>
|
</h3>
|
||||||
<span>
|
<span>
|
||||||
@@ -500,6 +532,9 @@ export default {
|
|||||||
donationPlatforms: [],
|
donationPlatforms: [],
|
||||||
donationLinks: [],
|
donationLinks: [],
|
||||||
|
|
||||||
|
selectableCategories: [],
|
||||||
|
selectableAdditionalCategories: [],
|
||||||
|
|
||||||
isProcessing: false,
|
isProcessing: false,
|
||||||
previewImage: null,
|
previewImage: null,
|
||||||
compiledBody: '',
|
compiledBody: '',
|
||||||
@@ -544,6 +579,8 @@ export default {
|
|||||||
this.serverSideType =
|
this.serverSideType =
|
||||||
this.newProject.server_side.charAt(0) +
|
this.newProject.server_side.charAt(0) +
|
||||||
this.newProject.server_side.slice(1)
|
this.newProject.server_side.slice(1)
|
||||||
|
|
||||||
|
this.setCategories()
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
license(newValue, oldValue) {
|
license(newValue, oldValue) {
|
||||||
@@ -584,6 +621,23 @@ export default {
|
|||||||
this.DELETE_PROJECT = 1 << 7
|
this.DELETE_PROJECT = 1 << 7
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
setCategories() {
|
||||||
|
this.selectableCategories = this.$tag.categories
|
||||||
|
.filter(
|
||||||
|
(x) =>
|
||||||
|
x.project_type === this.project.project_type &&
|
||||||
|
!this.newProject.additional_categories.includes(x.name)
|
||||||
|
)
|
||||||
|
.map((it) => it.name)
|
||||||
|
|
||||||
|
this.selectableAdditionalCategories = this.$tag.categories
|
||||||
|
.filter(
|
||||||
|
(x) =>
|
||||||
|
x.project_type === this.project.project_type &&
|
||||||
|
!this.newProject.categories.includes(x.name)
|
||||||
|
)
|
||||||
|
.map((it) => it.name)
|
||||||
|
},
|
||||||
checkFields() {
|
checkFields() {
|
||||||
const reviewConditions =
|
const reviewConditions =
|
||||||
this.newProject.body !== '' && this.newProject.versions.length > 0
|
this.newProject.body !== '' && this.newProject.versions.length > 0
|
||||||
@@ -626,6 +680,7 @@ export default {
|
|||||||
description: this.newProject.description,
|
description: this.newProject.description,
|
||||||
body: this.newProject.body,
|
body: this.newProject.body,
|
||||||
categories: this.newProject.categories,
|
categories: this.newProject.categories,
|
||||||
|
additional_categories: this.newProject.additional_categories,
|
||||||
issues_url: this.newProject.issues_url
|
issues_url: this.newProject.issues_url
|
||||||
? this.newProject.issues_url
|
? this.newProject.issues_url
|
||||||
: null,
|
: null,
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
Back to list
|
Back to list
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div v-if="version">
|
||||||
<div v-if="mode === 'version'" class="version-header">
|
<div v-if="mode === 'version'" class="version-header">
|
||||||
<h2>{{ version.name }}</h2>
|
<h2>{{ version.name }}</h2>
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
v-if="$auth.user"
|
v-if="$auth.user"
|
||||||
:to="`/${project.project_type}/${
|
:to="`/${project.project_type}/${
|
||||||
project.slug ? project.slug : project.id
|
project.slug ? project.slug : project.id
|
||||||
}/version/${encodeURIComponent(version.version_number)}`"
|
}/version/${encodeURI(version.displayUrlEnding)}`"
|
||||||
class="iconified-button"
|
class="iconified-button"
|
||||||
>
|
>
|
||||||
<CrossIcon aria-hidden="true" />
|
<CrossIcon aria-hidden="true" />
|
||||||
@@ -113,7 +113,7 @@
|
|||||||
class="action iconified-button"
|
class="action iconified-button"
|
||||||
:to="`/${project.project_type}/${
|
:to="`/${project.project_type}/${
|
||||||
project.slug ? project.slug : project.id
|
project.slug ? project.slug : project.id
|
||||||
}/version/${encodeURIComponent(version.version_number)}/edit`"
|
}/version/${encodeURI(version.displayUrlEnding)}/edit`"
|
||||||
@click.prevent="mode = 'edit'"
|
@click.prevent="mode = 'edit'"
|
||||||
>
|
>
|
||||||
<EditIcon aria-hidden="true" />
|
<EditIcon aria-hidden="true" />
|
||||||
@@ -209,8 +209,8 @@
|
|||||||
color="red"
|
color="red"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="data">
|
<div v-if="project.project_type !== 'resourcepack'" class="data">
|
||||||
<p class="title">Mod loaders</p>
|
<p class="title">Loaders</p>
|
||||||
<multiselect
|
<multiselect
|
||||||
v-if="mode === 'edit' || mode === 'create'"
|
v-if="mode === 'edit' || mode === 'create'"
|
||||||
v-model="version.loaders"
|
v-model="version.loaders"
|
||||||
@@ -223,12 +223,7 @@
|
|||||||
)
|
)
|
||||||
.map((it) => it.name)
|
.map((it) => it.name)
|
||||||
"
|
"
|
||||||
:custom-label="
|
:custom-label="(value) => $formatCategory(value)"
|
||||||
(value) =>
|
|
||||||
value === 'modloader'
|
|
||||||
? 'Risugami\'s ModLoader'
|
|
||||||
: value.charAt(0).toUpperCase() + value.slice(1)
|
|
||||||
"
|
|
||||||
:loading="$tag.loaders.length === 0"
|
:loading="$tag.loaders.length === 0"
|
||||||
:multiple="true"
|
:multiple="true"
|
||||||
:searchable="false"
|
:searchable="false"
|
||||||
@@ -238,18 +233,10 @@
|
|||||||
:show-labels="false"
|
:show-labels="false"
|
||||||
:limit="6"
|
:limit="6"
|
||||||
:hide-selected="true"
|
:hide-selected="true"
|
||||||
placeholder="Choose mod loaders..."
|
placeholder="Choose loaders..."
|
||||||
/>
|
/>
|
||||||
<p v-else class="value">
|
<p v-else class="value">
|
||||||
{{
|
{{ version.loaders.map((x) => $formatCategory(x)).join(', ') }}
|
||||||
version.loaders
|
|
||||||
.map((x) =>
|
|
||||||
x.toLowerCase() === 'modloader'
|
|
||||||
? "Risugami's ModLoader"
|
|
||||||
: x.charAt(0).toUpperCase() + x.slice(1)
|
|
||||||
)
|
|
||||||
.join(', ')
|
|
||||||
}}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="mode === 'version'" class="data">
|
<div v-if="mode === 'version'" class="data">
|
||||||
@@ -365,7 +352,7 @@
|
|||||||
dependency.project.slug
|
dependency.project.slug
|
||||||
? dependency.project.slug
|
? dependency.project.slug
|
||||||
: dependency.project.id
|
: dependency.project.id
|
||||||
}/version/${encodeURIComponent(
|
}/version/${encodeURI(
|
||||||
dependency.version.version_number
|
dependency.version.version_number
|
||||||
)}`
|
)}`
|
||||||
: `/${dependency.project.project_type}/${
|
: `/${dependency.project.project_type}/${
|
||||||
@@ -754,9 +741,18 @@ export default {
|
|||||||
|
|
||||||
if (!this.version)
|
if (!this.version)
|
||||||
this.version = this.versions.find(
|
this.version = this.versions.find(
|
||||||
(x) => x.version_number === this.$route.params.version
|
(x) => x.displayUrlEnding === this.$route.params.version
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (!this.version) {
|
||||||
|
this.$nuxt.context.error({
|
||||||
|
statusCode: 404,
|
||||||
|
message: 'The page could not be found',
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
this.version = JSON.parse(JSON.stringify(this.version))
|
this.version = JSON.parse(JSON.stringify(this.version))
|
||||||
this.primaryFile =
|
this.primaryFile =
|
||||||
this.version.files.find((file) => file.primary) ?? this.version.files[0]
|
this.version.files.find((file) => file.primary) ?? this.version.files[0]
|
||||||
@@ -891,8 +887,9 @@ export default {
|
|||||||
const index = this.versions.findIndex((x) => x.id === this.version.id)
|
const index = this.versions.findIndex((x) => x.id === this.version.id)
|
||||||
editedVersions.splice(index, 1, version)
|
editedVersions.splice(index, 1, version)
|
||||||
|
|
||||||
this.$emit('update:versions', editedVersions)
|
const newEditedVersions = this.$computeVersions(editedVersions)
|
||||||
|
|
||||||
|
this.$emit('update:versions', newEditedVersions)
|
||||||
this.$emit('update:featuredVersions', featuredVersions)
|
this.$emit('update:featuredVersions', featuredVersions)
|
||||||
|
|
||||||
this.newFiles = []
|
this.newFiles = []
|
||||||
@@ -901,7 +898,7 @@ export default {
|
|||||||
await this.$router.replace(
|
await this.$router.replace(
|
||||||
`/${this.project.project_type}/${
|
`/${this.project.project_type}/${
|
||||||
this.project.slug ? this.project.slug : this.project.id
|
this.project.slug ? this.project.slug : this.project.id
|
||||||
}/version/${encodeURIComponent(this.version.version_number)}`
|
}/version/${encodeURI(newEditedVersions[index].displayUrlEnding)}`
|
||||||
)
|
)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.$notify({
|
this.$notify({
|
||||||
@@ -921,6 +918,10 @@ export default {
|
|||||||
|
|
||||||
const fileParts = this.newFiles.map((f, idx) => `${f.name}-${idx}`)
|
const fileParts = this.newFiles.map((f, idx) => `${f.name}-${idx}`)
|
||||||
|
|
||||||
|
if (this.project.project_type === 'resourcepack') {
|
||||||
|
this.version.loaders = ['minecraft']
|
||||||
|
}
|
||||||
|
|
||||||
const newVersion = {
|
const newVersion = {
|
||||||
project_id: this.version.project_id,
|
project_id: this.version.project_id,
|
||||||
file_parts: fileParts,
|
file_parts: fileParts,
|
||||||
@@ -958,15 +959,19 @@ export default {
|
|||||||
).data
|
).data
|
||||||
|
|
||||||
const newProject = JSON.parse(JSON.stringify(this.project))
|
const newProject = JSON.parse(JSON.stringify(this.project))
|
||||||
newProject.versions = newProject.versions.concat([data])
|
newProject.versions = newProject.versions.concat([data.id])
|
||||||
|
|
||||||
|
const newVersions = this.$computeVersions(this.versions.concat([data]))
|
||||||
|
|
||||||
await this.$emit('update:project', newProject)
|
await this.$emit('update:project', newProject)
|
||||||
await this.$emit('update:versions', this.versions.concat([data]))
|
await this.$emit('update:versions', newVersions)
|
||||||
|
|
||||||
await this.$router.push(
|
await this.$router.push(
|
||||||
`/${this.project.project_type}/${
|
`/${this.project.project_type}/${
|
||||||
this.project.slug ? this.project.slug : this.project.project_id
|
this.project.slug ? this.project.slug : this.project.project_id
|
||||||
}/version/${encodeURIComponent(this.version.version_number)}`
|
}/version/${encodeURI(
|
||||||
|
newVersions[newVersions.length - 1].displayUrlEnding
|
||||||
|
)}`
|
||||||
)
|
)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.$notify({
|
this.$notify({
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
<nuxt-link
|
<nuxt-link
|
||||||
:to="`/${project.project_type}/${
|
:to="`/${project.project_type}/${
|
||||||
project.slug ? project.slug : project.id
|
project.slug ? project.slug : project.id
|
||||||
}/version/${encodeURIComponent(version.version_number)}`"
|
}/version/${encodeURI(version.displayUrlEnding)}`"
|
||||||
>
|
>
|
||||||
{{ version.name }}
|
{{ version.name }}
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
@@ -78,11 +78,7 @@
|
|||||||
<p>
|
<p>
|
||||||
{{
|
{{
|
||||||
version.loaders
|
version.loaders
|
||||||
.map((x) =>
|
.map((x) => $formatCategory(x))
|
||||||
x.toLowerCase() === 'modloader'
|
|
||||||
? 'ModLoader'
|
|
||||||
: x.charAt(0).toUpperCase() + x.slice(1)
|
|
||||||
)
|
|
||||||
.join(', ') +
|
.join(', ') +
|
||||||
' ' +
|
' ' +
|
||||||
$formatVersion(version.game_versions)
|
$formatVersion(version.game_versions)
|
||||||
@@ -104,15 +100,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<p>
|
<p>
|
||||||
{{
|
{{ version.loaders.map((x) => $formatCategory(x)).join(', ') }}
|
||||||
version.loaders
|
|
||||||
.map((x) =>
|
|
||||||
x.toLowerCase() === 'modloader'
|
|
||||||
? 'ModLoader'
|
|
||||||
: x.charAt(0).toUpperCase() + x.slice(1)
|
|
||||||
)
|
|
||||||
.join(', ')
|
|
||||||
}}
|
|
||||||
</p>
|
</p>
|
||||||
<p>{{ $formatVersion(version.game_versions) }}</p>
|
<p>{{ $formatVersion(version.game_versions) }}</p>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -54,16 +54,18 @@
|
|||||||
<label>
|
<label>
|
||||||
<span>
|
<span>
|
||||||
<h3>Type<span class="required">*</span></h3>
|
<h3>Type<span class="required">*</span></h3>
|
||||||
<span class="no-padding">The type of project of your project.</span>
|
<span class="no-padding">The type of project your project is.</span>
|
||||||
</span>
|
</span>
|
||||||
<Multiselect
|
<Multiselect
|
||||||
v-model="projectType"
|
v-model="projectType"
|
||||||
placeholder="Select one"
|
placeholder="Select one"
|
||||||
|
label="display"
|
||||||
:options="projectTypes"
|
:options="projectTypes"
|
||||||
:searchable="false"
|
:searchable="false"
|
||||||
:close-on-select="true"
|
:close-on-select="true"
|
||||||
:show-labels="false"
|
:show-labels="false"
|
||||||
:allow-empty="false"
|
:allow-empty="false"
|
||||||
|
@input="setCategories(true)"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
@@ -106,32 +108,59 @@
|
|||||||
<multiselect
|
<multiselect
|
||||||
id="categories"
|
id="categories"
|
||||||
v-model="categories"
|
v-model="categories"
|
||||||
:options="
|
:options="selectableCategories"
|
||||||
$tag.categories
|
|
||||||
.filter((x) => x.project_type === projectType.toLowerCase())
|
|
||||||
.map((it) => it.name)
|
|
||||||
"
|
|
||||||
:custom-label="
|
:custom-label="
|
||||||
(value) => value.charAt(0).toUpperCase() + value.slice(1)
|
(value) => value.charAt(0).toUpperCase() + value.slice(1)
|
||||||
"
|
"
|
||||||
:loading="$tag.categories.length === 0"
|
:loading="$tag.categories.length === 0"
|
||||||
:multiple="true"
|
:multiple="true"
|
||||||
:searchable="false"
|
:searchable="true"
|
||||||
:show-no-results="false"
|
:show-no-results="false"
|
||||||
:close-on-select="false"
|
:close-on-select="false"
|
||||||
:clear-on-select="false"
|
:clear-on-select="true"
|
||||||
:show-labels="false"
|
:show-labels="false"
|
||||||
:max="3"
|
:max="3"
|
||||||
:limit="6"
|
:limit="6"
|
||||||
:hide-selected="true"
|
:hide-selected="true"
|
||||||
placeholder="Choose categories"
|
placeholder="Choose categories"
|
||||||
|
@input="setCategories(false)"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<span>
|
||||||
|
<h3>Additional Categories</h3>
|
||||||
|
<span class="no-padding">
|
||||||
|
Select more categories that will help others <br />
|
||||||
|
find your project. These are searchable, but not <br />
|
||||||
|
displayed in search.
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<multiselect
|
||||||
|
id="additional_categories"
|
||||||
|
v-model="additional_categories"
|
||||||
|
:show-no-results="false"
|
||||||
|
:options="selectableAdditionalCategories"
|
||||||
|
:custom-label="
|
||||||
|
(value) => value.charAt(0).toUpperCase() + value.slice(1)
|
||||||
|
"
|
||||||
|
:loading="$tag.categories.length === 0"
|
||||||
|
:multiple="true"
|
||||||
|
:searchable="true"
|
||||||
|
:close-on-select="false"
|
||||||
|
:clear-on-select="true"
|
||||||
|
:show-labels="false"
|
||||||
|
:max="255"
|
||||||
|
:limit="6"
|
||||||
|
:hide-selected="true"
|
||||||
|
placeholder="Choose additional categories"
|
||||||
|
@input="setCategories(false)"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<span>
|
<span>
|
||||||
<h3>Vanity URL (slug)<span class="required">*</span></h3>
|
<h3>Vanity URL (slug)<span class="required">*</span></h3>
|
||||||
<span class="slug-description"
|
<span class="slug-description"
|
||||||
>https://modrinth.com/{{ projectType.toLowerCase() }}/{{
|
>https://modrinth.com/{{ projectType.id }}/{{
|
||||||
slug ? slug : 'your-slug'
|
slug ? slug : 'your-slug'
|
||||||
}}
|
}}
|
||||||
</span>
|
</span>
|
||||||
@@ -174,7 +203,13 @@
|
|||||||
Reset
|
Reset
|
||||||
</button>
|
</button>
|
||||||
</section>
|
</section>
|
||||||
<section class="card game-sides">
|
<section
|
||||||
|
v-if="
|
||||||
|
projectType.realId !== 'resourcepack' &&
|
||||||
|
projectType.realId !== 'plugin'
|
||||||
|
"
|
||||||
|
class="card game-sides"
|
||||||
|
>
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<h3>Supported environments</h3>
|
<h3>Supported environments</h3>
|
||||||
@@ -214,7 +249,7 @@
|
|||||||
for="body"
|
for="body"
|
||||||
title="You can type an extended description of your project here."
|
title="You can type an extended description of your project here."
|
||||||
>
|
>
|
||||||
Body<span class="required">*</span>
|
Description<span class="required">*</span>
|
||||||
</label>
|
</label>
|
||||||
</h3>
|
</h3>
|
||||||
<span>
|
<span>
|
||||||
@@ -318,7 +353,7 @@
|
|||||||
Your version must have a unique version number.
|
Your version must have a unique version number.
|
||||||
</li>
|
</li>
|
||||||
<li v-if="versions[currentVersionIndex].loaders.length < 1">
|
<li v-if="versions[currentVersionIndex].loaders.length < 1">
|
||||||
Your version must have the supported mod loaders selected.
|
Your version must have the supported loaders selected.
|
||||||
</li>
|
</li>
|
||||||
<li v-if="versions[currentVersionIndex].game_versions.length < 1">
|
<li v-if="versions[currentVersionIndex].game_versions.length < 1">
|
||||||
Your version must have the supported Minecraft versions
|
Your version must have the supported Minecraft versions
|
||||||
@@ -387,10 +422,10 @@
|
|||||||
:allow-empty="false"
|
:allow-empty="false"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label v-if="projectType.realId !== 'resourcepack'">
|
||||||
<span>
|
<span>
|
||||||
<h3>Mod loaders<span class="required">*</span></h3>
|
<h3>Loaders<span class="required">*</span></h3>
|
||||||
<span> Select all mod loaders this version supports. </span>
|
<span> Select all loaders this version supports. </span>
|
||||||
</span>
|
</span>
|
||||||
<multiselect
|
<multiselect
|
||||||
v-model="versions[currentVersionIndex].loaders"
|
v-model="versions[currentVersionIndex].loaders"
|
||||||
@@ -401,19 +436,18 @@
|
|||||||
}"
|
}"
|
||||||
:options="
|
:options="
|
||||||
$tag.loaders
|
$tag.loaders
|
||||||
.filter((x) =>
|
.filter((x) => {
|
||||||
x.supported_project_types.includes(
|
if (projectType.realId === 'plugin') {
|
||||||
projectType.toLowerCase()
|
return $tag.loaderData.allPluginLoaders.includes(x.name)
|
||||||
)
|
} else if (projectType.realId === 'mod') {
|
||||||
)
|
return $tag.loaderData.modLoaders.includes(x.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return x.supported_project_types.includes(projectType.id)
|
||||||
|
})
|
||||||
.map((it) => it.name)
|
.map((it) => it.name)
|
||||||
"
|
"
|
||||||
:custom-label="
|
:custom-label="(value) => $formatCategory(value)"
|
||||||
(value) =>
|
|
||||||
value === 'modloader'
|
|
||||||
? 'Risugami\'s ModLoader'
|
|
||||||
: value.charAt(0).toUpperCase() + value.slice(1)
|
|
||||||
"
|
|
||||||
:loading="$tag.loaders.length === 0"
|
:loading="$tag.loaders.length === 0"
|
||||||
:multiple="true"
|
:multiple="true"
|
||||||
:searchable="false"
|
:searchable="false"
|
||||||
@@ -423,7 +457,7 @@
|
|||||||
:show-labels="false"
|
:show-labels="false"
|
||||||
:limit="6"
|
:limit="6"
|
||||||
:hide-selected="true"
|
:hide-selected="true"
|
||||||
placeholder="Choose mod loaders..."
|
placeholder="Choose loaders..."
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
@@ -547,12 +581,9 @@
|
|||||||
<h3>Files<span class="required">*</span></h3>
|
<h3>Files<span class="required">*</span></h3>
|
||||||
<span>
|
<span>
|
||||||
You may upload multiple files, but this should only be used for
|
You may upload multiple files, but this should only be used for
|
||||||
cases like sources or Javadocs.
|
cases like sources or Javadocs for mods/plugins.
|
||||||
</span>
|
</span>
|
||||||
<p
|
<p v-if="projectType.id === 'modpack'" aria-label="Warning">
|
||||||
v-if="projectType.toLowerCase() === 'modpack'"
|
|
||||||
aria-label="Warning"
|
|
||||||
>
|
|
||||||
Modpack support is currently in alpha, and you may encounter
|
Modpack support is currently in alpha, and you may encounter
|
||||||
issues. Our documentation includes instructions on
|
issues. Our documentation includes instructions on
|
||||||
<a
|
<a
|
||||||
@@ -578,9 +609,9 @@
|
|||||||
class="file-input"
|
class="file-input"
|
||||||
multiple
|
multiple
|
||||||
:accept="
|
:accept="
|
||||||
projectType.toLowerCase() === 'modpack'
|
projectType.id === 'modpack'
|
||||||
? '.mrpack,application/x-modrinth-modpack+zip'
|
? '.mrpack,application/x-modrinth-modpack+zip'
|
||||||
: projectType.toLowerCase() === 'mod'
|
: projectType.id === 'mod'
|
||||||
? '.jar,application/java-archive'
|
? '.jar,application/java-archive'
|
||||||
: '*'
|
: '*'
|
||||||
"
|
"
|
||||||
@@ -661,7 +692,7 @@
|
|||||||
>
|
>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Version</th>
|
<th>Version</th>
|
||||||
<th>Mod loaders</th>
|
<th>Project loaders</th>
|
||||||
<th>Minecraft versions</th>
|
<th>Minecraft versions</th>
|
||||||
<th>Release channel</th>
|
<th>Release channel</th>
|
||||||
<th>Actions</th>
|
<th>Actions</th>
|
||||||
@@ -1137,6 +1168,7 @@ export default {
|
|||||||
body: '',
|
body: '',
|
||||||
versions: [],
|
versions: [],
|
||||||
categories: [],
|
categories: [],
|
||||||
|
additional_categories: [],
|
||||||
issues_url: null,
|
issues_url: null,
|
||||||
source_url: null,
|
source_url: null,
|
||||||
wiki_url: null,
|
wiki_url: null,
|
||||||
@@ -1145,8 +1177,41 @@ export default {
|
|||||||
license: null,
|
license: null,
|
||||||
license_url: null,
|
license_url: null,
|
||||||
|
|
||||||
projectTypes: ['Mod', 'Modpack'],
|
selectableCategories: [],
|
||||||
projectType: 'Mod',
|
selectableAdditionalCategories: [],
|
||||||
|
|
||||||
|
projectTypes: [
|
||||||
|
{
|
||||||
|
display: 'Mod',
|
||||||
|
id: 'mod',
|
||||||
|
realId: 'mod',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
display: 'Plugin',
|
||||||
|
id: 'mod',
|
||||||
|
realId: 'plugin',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
display: 'Mod and plugin',
|
||||||
|
id: 'mod',
|
||||||
|
realId: 'mod+plugin',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
display: 'Modpack',
|
||||||
|
id: 'modpack',
|
||||||
|
realId: 'modpack',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
display: 'Resource pack',
|
||||||
|
id: 'resourcepack',
|
||||||
|
realId: 'resourcepack',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
projectType: {
|
||||||
|
display: 'Mod',
|
||||||
|
id: 'mod',
|
||||||
|
realId: 'mod',
|
||||||
|
},
|
||||||
|
|
||||||
sideTypes: ['Required', 'Optional', 'Unsupported'],
|
sideTypes: ['Required', 'Optional', 'Unsupported'],
|
||||||
clientSideType: 'Required',
|
clientSideType: 'Required',
|
||||||
@@ -1171,6 +1236,9 @@ export default {
|
|||||||
savingAsDraft: false,
|
savingAsDraft: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
fetch() {
|
||||||
|
this.setCategories()
|
||||||
|
},
|
||||||
watch: {
|
watch: {
|
||||||
license(newValue, oldValue) {
|
license(newValue, oldValue) {
|
||||||
if (newValue == null) {
|
if (newValue == null) {
|
||||||
@@ -1199,6 +1267,28 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
setCategories(reset) {
|
||||||
|
this.selectableCategories = this.$tag.categories
|
||||||
|
.filter(
|
||||||
|
(x) =>
|
||||||
|
x.project_type === this.projectType.id &&
|
||||||
|
!this.additional_categories.includes(x.name)
|
||||||
|
)
|
||||||
|
.map((it) => it.name)
|
||||||
|
|
||||||
|
this.selectableAdditionalCategories = this.$tag.categories
|
||||||
|
.filter(
|
||||||
|
(x) =>
|
||||||
|
x.project_type === this.projectType.id &&
|
||||||
|
!this.categories.includes(x.name)
|
||||||
|
)
|
||||||
|
.map((it) => it.name)
|
||||||
|
|
||||||
|
if (reset) {
|
||||||
|
this.categories = []
|
||||||
|
this.additional_categories = []
|
||||||
|
}
|
||||||
|
},
|
||||||
checkFields() {
|
checkFields() {
|
||||||
const reviewConditions = this.body !== '' && this.versions.length > 0
|
const reviewConditions = this.body !== '' && this.versions.length > 0
|
||||||
if (
|
if (
|
||||||
@@ -1221,6 +1311,7 @@ export default {
|
|||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
async createDraft() {
|
async createDraft() {
|
||||||
|
this.setValues()
|
||||||
this.savingAsDraft = true
|
this.savingAsDraft = true
|
||||||
if (this.checkFields()) {
|
if (this.checkFields()) {
|
||||||
this.draft = true
|
this.draft = true
|
||||||
@@ -1228,11 +1319,21 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
async createProjectForReview() {
|
async createProjectForReview() {
|
||||||
|
this.setValues()
|
||||||
this.savingAsDraft = false
|
this.savingAsDraft = false
|
||||||
if (this.checkFields()) {
|
if (this.checkFields()) {
|
||||||
await this.createProject()
|
await this.createProject()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
setValues() {
|
||||||
|
if (this.projectType.realId === 'resourcepack') {
|
||||||
|
this.clientSideType = 'required'
|
||||||
|
this.serverSideType = 'optional'
|
||||||
|
} else if (this.projectType.realId === 'plugin') {
|
||||||
|
this.clientSideType = 'unsupported'
|
||||||
|
this.serverSideType = 'required'
|
||||||
|
}
|
||||||
|
},
|
||||||
async createProject() {
|
async createProject() {
|
||||||
this.$nuxt.$loading.start()
|
this.$nuxt.$loading.start()
|
||||||
|
|
||||||
@@ -1256,7 +1357,7 @@ export default {
|
|||||||
'data',
|
'data',
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
title: this.name,
|
title: this.name,
|
||||||
project_type: this.projectType.toLowerCase(),
|
project_type: this.projectType.id,
|
||||||
slug: this.slug,
|
slug: this.slug,
|
||||||
description: this.description,
|
description: this.description,
|
||||||
body: this.body,
|
body: this.body,
|
||||||
@@ -1269,6 +1370,7 @@ export default {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
categories: this.categories,
|
categories: this.categories,
|
||||||
|
additional_categories: this.additional_categories,
|
||||||
issues_url: this.issues_url ? this.issues_url : null,
|
issues_url: this.issues_url ? this.issues_url : null,
|
||||||
source_url: this.source_url ? this.source_url : null,
|
source_url: this.source_url ? this.source_url : null,
|
||||||
wiki_url: this.wiki_url ? this.wiki_url : null,
|
wiki_url: this.wiki_url ? this.wiki_url : null,
|
||||||
@@ -1405,6 +1507,9 @@ export default {
|
|||||||
|
|
||||||
saveVersion() {
|
saveVersion() {
|
||||||
const version = this.versions[this.currentVersionIndex]
|
const version = this.versions[this.currentVersionIndex]
|
||||||
|
if (this.projectType.realId === 'resourcepack') {
|
||||||
|
version.loaders = ['minecraft']
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
version.version_number !== '' &&
|
version.version_number !== '' &&
|
||||||
version.releaseChannels !== null &&
|
version.releaseChannels !== null &&
|
||||||
|
|||||||
@@ -89,6 +89,7 @@
|
|||||||
:client-side="project.client_side"
|
:client-side="project.client_side"
|
||||||
:server-side="project.server_side"
|
:server-side="project.server_side"
|
||||||
:type="project.project_type"
|
:type="project.project_type"
|
||||||
|
:moderation="true"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="iconified-button"
|
class="iconified-button"
|
||||||
|
|||||||
@@ -76,8 +76,8 @@ import UpToDate from '~/assets/images/illustrations/up_to_date.svg?inline'
|
|||||||
import ThisOrThat from '~/components/ui/ThisOrThat'
|
import ThisOrThat from '~/components/ui/ThisOrThat'
|
||||||
|
|
||||||
const NOTIFICATION_TYPES = {
|
const NOTIFICATION_TYPES = {
|
||||||
'Team Invites': 'team_invite',
|
'Team invites': 'team_invite',
|
||||||
'Project Updates': 'project_update',
|
'Project updates': 'project_update',
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|||||||
168
pages/search.vue
168
pages/search.vue
@@ -34,28 +34,41 @@
|
|||||||
Clear filters
|
Clear filters
|
||||||
</button>
|
</button>
|
||||||
<section aria-label="Category filters">
|
<section aria-label="Category filters">
|
||||||
<h3
|
<div v-for="(categories, header) in categoriesMap" :key="header">
|
||||||
v-if="
|
<h3
|
||||||
$tag.categories.filter((x) => x.project_type === projectType)
|
v-if="
|
||||||
.length > 0
|
categories.filter((x) => x.project_type === projectType)
|
||||||
"
|
.length > 0
|
||||||
class="sidebar-menu-heading"
|
"
|
||||||
>
|
class="sidebar-menu-heading"
|
||||||
Categories
|
>
|
||||||
</h3>
|
{{ $formatCategoryHeader(header) }}
|
||||||
<SearchFilter
|
</h3>
|
||||||
v-for="category in $tag.categories.filter(
|
|
||||||
(x) => x.project_type === projectType
|
<SearchFilter
|
||||||
)"
|
v-for="category in categories
|
||||||
:key="category.name"
|
.filter((x) => x.project_type === projectType)
|
||||||
:active-filters="facets"
|
.sort((a, b) => {
|
||||||
:display-name="category.name"
|
if (header === 'resolutions') {
|
||||||
:facet-name="`categories:${category.name}`"
|
return (
|
||||||
:icon="category.icon"
|
a.name.replace(/\D/g, '') - b.name.replace(/\D/g, '')
|
||||||
@toggle="toggleFacet"
|
)
|
||||||
/>
|
}
|
||||||
|
return 0
|
||||||
|
})"
|
||||||
|
:key="category.name"
|
||||||
|
:active-filters="facets"
|
||||||
|
:display-name="$formatCategory(category.name)"
|
||||||
|
:facet-name="`categories:${category.name}`"
|
||||||
|
:icon="header === 'resolutions' ? null : category.icon"
|
||||||
|
@toggle="toggleFacet"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section aria-label="Loader filters">
|
<section
|
||||||
|
v-if="projectType !== 'resourcepack'"
|
||||||
|
aria-label="Loader filters"
|
||||||
|
>
|
||||||
<h3
|
<h3
|
||||||
v-if="
|
v-if="
|
||||||
$tag.loaders.filter((x) =>
|
$tag.loaders.filter((x) =>
|
||||||
@@ -69,6 +82,8 @@
|
|||||||
<SearchFilter
|
<SearchFilter
|
||||||
v-for="loader in $tag.loaders.filter((x) => {
|
v-for="loader in $tag.loaders.filter((x) => {
|
||||||
if (
|
if (
|
||||||
|
projectType === 'mod' &&
|
||||||
|
!isPlugins &&
|
||||||
!showAllLoaders &&
|
!showAllLoaders &&
|
||||||
x.name !== 'forge' &&
|
x.name !== 'forge' &&
|
||||||
x.name !== 'fabric' &&
|
x.name !== 'fabric' &&
|
||||||
@@ -76,18 +91,25 @@
|
|||||||
) {
|
) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return x.supported_project_types.includes(projectType)
|
|
||||||
|
if (projectType === 'mod' && showAllLoaders) {
|
||||||
|
return $tag.loaderData.modLoaders.includes(x.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return isPlugins
|
||||||
|
? $tag.loaderData.pluginLoaders.includes(x.name)
|
||||||
|
: x.supported_project_types.includes(projectType)
|
||||||
})"
|
})"
|
||||||
:key="loader.name"
|
:key="loader.name"
|
||||||
|
ref="loaderFilters"
|
||||||
:active-filters="orFacets"
|
:active-filters="orFacets"
|
||||||
:display-name="
|
:display-name="$formatCategory(loader.name)"
|
||||||
loader.name === 'modloader' ? 'ModLoader' : loader.name
|
|
||||||
"
|
|
||||||
:facet-name="`categories:${loader.name}`"
|
:facet-name="`categories:${loader.name}`"
|
||||||
:icon="loader.icon"
|
:icon="loader.icon"
|
||||||
@toggle="toggleOrFacet"
|
@toggle="toggleOrFacet"
|
||||||
/>
|
/>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
|
v-if="projectType === 'mod' && !isPlugins"
|
||||||
v-model="showAllLoaders"
|
v-model="showAllLoaders"
|
||||||
:label="showAllLoaders ? 'Less' : 'More'"
|
:label="showAllLoaders ? 'Less' : 'More'"
|
||||||
description="Show all loaders"
|
description="Show all loaders"
|
||||||
@@ -96,7 +118,34 @@
|
|||||||
:collapsing-toggle-style="true"
|
:collapsing-toggle-style="true"
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
<section aria-label="Environment filters">
|
<section v-if="isPlugins" aria-label="Platform loader filters">
|
||||||
|
<h3
|
||||||
|
v-if="
|
||||||
|
$tag.loaders.filter((x) =>
|
||||||
|
x.supported_project_types.includes(projectType)
|
||||||
|
).length > 0
|
||||||
|
"
|
||||||
|
class="sidebar-menu-heading"
|
||||||
|
>
|
||||||
|
Proxies
|
||||||
|
</h3>
|
||||||
|
<SearchFilter
|
||||||
|
v-for="loader in $tag.loaders.filter((x) =>
|
||||||
|
$tag.loaderData.pluginPlatformLoaders.includes(x.name)
|
||||||
|
)"
|
||||||
|
:key="loader.name"
|
||||||
|
ref="platformFilters"
|
||||||
|
:active-filters="orFacets"
|
||||||
|
:display-name="$formatCategory(loader.name)"
|
||||||
|
:facet-name="`categories:${loader.name}`"
|
||||||
|
:icon="loader.icon"
|
||||||
|
@toggle="toggleOrFacet"
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
<section
|
||||||
|
v-if="projectType !== 'resourcepack' && !isPlugins"
|
||||||
|
aria-label="Environment filters"
|
||||||
|
>
|
||||||
<h3 class="sidebar-menu-heading">Environments</h3>
|
<h3 class="sidebar-menu-heading">Environments</h3>
|
||||||
<SearchFilter
|
<SearchFilter
|
||||||
:active-filters="selectedEnvironments"
|
:active-filters="selectedEnvironments"
|
||||||
@@ -267,7 +316,7 @@
|
|||||||
:icon-url="result.icon_url"
|
:icon-url="result.icon_url"
|
||||||
:client-side="result.client_side"
|
:client-side="result.client_side"
|
||||||
:server-side="result.server_side"
|
:server-side="result.server_side"
|
||||||
:categories="result.categories"
|
:categories="result.display_categories"
|
||||||
/>
|
/>
|
||||||
<div v-if="results && results.length === 0" class="no-results">
|
<div v-if="results && results.length === 0" class="no-results">
|
||||||
<p>No results found for your query!</p>
|
<p>No results found for your query!</p>
|
||||||
@@ -336,6 +385,7 @@ export default {
|
|||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
|
|
||||||
projectType: 'mod',
|
projectType: 'mod',
|
||||||
|
isPlugins: false,
|
||||||
|
|
||||||
sortTypes: [
|
sortTypes: [
|
||||||
{ display: 'Relevance', name: 'relevance' },
|
{ display: 'Relevance', name: 'relevance' },
|
||||||
@@ -405,8 +455,39 @@ export default {
|
|||||||
this.$route.name.length - 1
|
this.$route.name.length - 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (this.projectType === 'plugin') {
|
||||||
|
this.projectType = 'mod'
|
||||||
|
this.isPlugins = true
|
||||||
|
}
|
||||||
|
|
||||||
await this.onSearchChange(this.currentPage)
|
await this.onSearchChange(this.currentPage)
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
categoriesMap() {
|
||||||
|
const categories = {}
|
||||||
|
|
||||||
|
for (const category of this.$tag.categories) {
|
||||||
|
if (categories[category.header]) {
|
||||||
|
categories[category.header].push(category)
|
||||||
|
} else {
|
||||||
|
categories[category.header] = [category]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const newVals = Object.keys(categories)
|
||||||
|
.sort()
|
||||||
|
.reduce((obj, key) => {
|
||||||
|
obj[key] = categories[key]
|
||||||
|
return obj
|
||||||
|
}, {})
|
||||||
|
|
||||||
|
for (const header of Object.keys(categories)) {
|
||||||
|
newVals[header].sort((a, b) => a.name.localeCompare(b.name))
|
||||||
|
}
|
||||||
|
|
||||||
|
return newVals
|
||||||
|
},
|
||||||
|
},
|
||||||
watch: {
|
watch: {
|
||||||
'$route.path': {
|
'$route.path': {
|
||||||
async handler() {
|
async handler() {
|
||||||
@@ -415,12 +496,21 @@ export default {
|
|||||||
this.$route.name.length - 1
|
this.$route.name.length - 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (this.projectType === 'plugin') {
|
||||||
|
this.projectType = 'mod'
|
||||||
|
this.isPlugins = true
|
||||||
|
} else {
|
||||||
|
this.isPlugins = false
|
||||||
|
}
|
||||||
|
|
||||||
this.results = null
|
this.results = null
|
||||||
this.pages = []
|
this.pages = []
|
||||||
this.currentPage = 1
|
this.currentPage = 1
|
||||||
this.query = ''
|
this.query = ''
|
||||||
this.maxResults = 20
|
this.maxResults = 20
|
||||||
this.sortType = { display: 'Relevance', name: 'relevance' }
|
this.sortType = { display: 'Relevance', name: 'relevance' }
|
||||||
|
this.showAllLoaders = false
|
||||||
|
this.sidebarMenuOpen = false
|
||||||
|
|
||||||
await this.clearFilters()
|
await this.clearFilters()
|
||||||
},
|
},
|
||||||
@@ -463,6 +553,18 @@ export default {
|
|||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
this.orFacets.splice(index, 1)
|
this.orFacets.splice(index, 1)
|
||||||
} else {
|
} else {
|
||||||
|
if (elementName === 'categories:purpur') {
|
||||||
|
this.orFacets.push('categories:paper')
|
||||||
|
this.orFacets.push('categories:spigot')
|
||||||
|
this.orFacets.push('categories:bukkit')
|
||||||
|
} else if (elementName === 'categories:paper') {
|
||||||
|
this.orFacets.push('categories:spigot')
|
||||||
|
this.orFacets.push('categories:bukkit')
|
||||||
|
} else if (elementName === 'categories:spigot') {
|
||||||
|
this.orFacets.push('categories:bukkit')
|
||||||
|
} else if (elementName === 'categories:waterfall') {
|
||||||
|
this.orFacets.push('categories:bungeecord')
|
||||||
|
}
|
||||||
this.orFacets.push(elementName)
|
this.orFacets.push(elementName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,6 +600,7 @@ export default {
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
this.facets.length > 0 ||
|
this.facets.length > 0 ||
|
||||||
|
this.orFacets.length > 0 ||
|
||||||
this.selectedVersions.length > 0 ||
|
this.selectedVersions.length > 0 ||
|
||||||
this.selectedEnvironments.length > 0 ||
|
this.selectedEnvironments.length > 0 ||
|
||||||
this.projectType
|
this.projectType
|
||||||
@@ -507,8 +610,19 @@ export default {
|
|||||||
formattedFacets.push([facet])
|
formattedFacets.push([facet])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// loaders specifier
|
||||||
if (this.orFacets.length > 0) {
|
if (this.orFacets.length > 0) {
|
||||||
formattedFacets.push(this.orFacets)
|
formattedFacets.push(this.orFacets)
|
||||||
|
} else if (this.isPlugins) {
|
||||||
|
formattedFacets.push(
|
||||||
|
this.$tag.loaderData.allPluginLoaders.map(
|
||||||
|
(x) => `categories:${x}`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else if (this.projectType === 'mod') {
|
||||||
|
formattedFacets.push(
|
||||||
|
this.$tag.loaderData.modLoaders.map((x) => `categories:${x}`)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.selectedVersions.length > 0) {
|
if (this.selectedVersions.length > 0) {
|
||||||
|
|||||||
@@ -5,9 +5,6 @@
|
|||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'Modpacks',
|
name: 'Modpacks',
|
||||||
asyncData(ctx) {
|
|
||||||
ctx.params.projectType = 'modpack'
|
|
||||||
},
|
|
||||||
head: {
|
head: {
|
||||||
title: 'Modpacks - Modrinth',
|
title: 'Modpacks - Modrinth',
|
||||||
meta: [
|
meta: [
|
||||||
|
|||||||
@@ -5,9 +5,6 @@
|
|||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'Mods',
|
name: 'Mods',
|
||||||
asyncData(ctx) {
|
|
||||||
ctx.params.projectType = 'mod'
|
|
||||||
},
|
|
||||||
head: {
|
head: {
|
||||||
title: 'Mods - Modrinth',
|
title: 'Mods - Modrinth',
|
||||||
meta: [
|
meta: [
|
||||||
|
|||||||
31
pages/search/plugins.vue
Normal file
31
pages/search/plugins.vue
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<template>
|
||||||
|
<div></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Plugins',
|
||||||
|
head: {
|
||||||
|
title: 'Plugins - Modrinth',
|
||||||
|
meta: [
|
||||||
|
{
|
||||||
|
hid: 'apple-mobile-web-app-title',
|
||||||
|
name: 'apple-mobile-web-app-title',
|
||||||
|
content: 'Plugins - Modrinth',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
hid: 'og:title',
|
||||||
|
name: 'og:title',
|
||||||
|
content: 'Plugins - Modrinth',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
hid: 'og:url',
|
||||||
|
name: 'og:url',
|
||||||
|
content: `https://modrinth.com/plugins`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
31
pages/search/resourcepacks.vue
Normal file
31
pages/search/resourcepacks.vue
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<template>
|
||||||
|
<div></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'ResourcePacks',
|
||||||
|
head: {
|
||||||
|
title: 'Resource packs - Modrinth',
|
||||||
|
meta: [
|
||||||
|
{
|
||||||
|
hid: 'apple-mobile-web-app-title',
|
||||||
|
name: 'apple-mobile-web-app-title',
|
||||||
|
content: 'Resource packs - Modrinth',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
hid: 'og:title',
|
||||||
|
name: 'og:title',
|
||||||
|
content: 'Resource packs - Modrinth',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
hid: 'og:url',
|
||||||
|
name: 'og:url',
|
||||||
|
content: `https://modrinth.com/resourcepacks`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
@@ -204,6 +204,9 @@ export default {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
|
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -90,7 +90,8 @@
|
|||||||
<ProjectCard
|
<ProjectCard
|
||||||
v-for="project in selectedProjectType !== 'all'
|
v-for="project in selectedProjectType !== 'all'
|
||||||
? projects.filter(
|
? projects.filter(
|
||||||
(x) => x.project_type === selectedProjectType.slice(0, -1)
|
(x) =>
|
||||||
|
x.project_type === convertProjectType(selectedProjectType)
|
||||||
)
|
)
|
||||||
: projects"
|
: projects"
|
||||||
:id="project.slug || project.id"
|
:id="project.slug || project.id"
|
||||||
@@ -246,13 +247,24 @@ export default {
|
|||||||
const obj = { all: true }
|
const obj = { all: true }
|
||||||
|
|
||||||
for (const project of this.projects) {
|
for (const project of this.projects) {
|
||||||
obj[project.project_type + 's'] = true
|
if (project.project_type === 'resourcepack') {
|
||||||
|
obj['Resource Packs'] = true
|
||||||
|
} else {
|
||||||
|
obj[project.project_type + 's'] = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Object.keys(obj)
|
return Object.keys(obj)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
convertProjectType(name) {
|
||||||
|
if (name === 'Resource Packs') {
|
||||||
|
return 'resourcepack'
|
||||||
|
} else {
|
||||||
|
return name.slice(0, -1)
|
||||||
|
}
|
||||||
|
},
|
||||||
sumDownloads() {
|
sumDownloads() {
|
||||||
let sum = 0
|
let sum = 0
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export default ({ store }, inject) => {
|
export default (ctx, inject) => {
|
||||||
inject('user', store.state.user)
|
inject('user', ctx.store.state.user)
|
||||||
inject('tag', store.state.tag)
|
inject('tag', ctx.store.state.tag)
|
||||||
inject('auth', store.state.auth)
|
inject('auth', ctx.store.state.auth)
|
||||||
inject('defaultHeaders', () => {
|
inject('defaultHeaders', () => {
|
||||||
const obj = { headers: {} }
|
const obj = { headers: {} }
|
||||||
|
|
||||||
@@ -9,100 +9,143 @@ export default ({ store }, inject) => {
|
|||||||
obj.headers['x-ratelimit-key'] = process.env.RATE_LIMIT_IGNORE_KEY || ''
|
obj.headers['x-ratelimit-key'] = process.env.RATE_LIMIT_IGNORE_KEY || ''
|
||||||
}
|
}
|
||||||
|
|
||||||
if (store.state.auth.user) {
|
if (ctx.store.state.auth.user) {
|
||||||
obj.headers.Authorization = store.state.auth.token
|
obj.headers.Authorization = ctx.store.state.auth.token
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj
|
return obj
|
||||||
})
|
})
|
||||||
inject('formatNumber', formatNumber)
|
inject('formatNumber', formatNumber)
|
||||||
inject('formatVersion', (versionArray) => {
|
inject('formatVersion', (versionsArray) =>
|
||||||
const allVersions = store.state.tag.gameVersions.slice().reverse()
|
formatVersions(versionsArray, ctx.store)
|
||||||
const allReleases = allVersions.filter((x) => x.version_type === 'release')
|
)
|
||||||
|
inject('formatBytes', formatBytes)
|
||||||
|
inject('formatProjectType', formatProjectType)
|
||||||
|
inject('formatCategory', formatCategory)
|
||||||
|
inject('formatCategoryHeader', formatCategoryHeader)
|
||||||
|
inject('computeVersions', (versions) => {
|
||||||
|
const versionsMap = {}
|
||||||
|
|
||||||
const intervals = []
|
for (const version of versions.reverse()) {
|
||||||
let currentInterval = 0
|
if (versionsMap[version.version_number]) {
|
||||||
|
versionsMap[version.version_number].push(version)
|
||||||
for (let i = 0; i < versionArray.length; i++) {
|
|
||||||
const index = allVersions.findIndex((x) => x.version === versionArray[i])
|
|
||||||
const releaseIndex = allReleases.findIndex(
|
|
||||||
(x) => x.version === versionArray[i]
|
|
||||||
)
|
|
||||||
|
|
||||||
if (i === 0) {
|
|
||||||
intervals.push([[versionArray[i], index, releaseIndex]])
|
|
||||||
} else {
|
} else {
|
||||||
const intervalBase = intervals[currentInterval]
|
versionsMap[version.version_number] = [version]
|
||||||
|
|
||||||
if (
|
|
||||||
(index - intervalBase[intervalBase.length - 1][1] === 1 ||
|
|
||||||
releaseIndex - intervalBase[intervalBase.length - 1][2] === 1) &&
|
|
||||||
(allVersions[intervalBase[0][1]].version_type === 'release' ||
|
|
||||||
allVersions[index].version_type !== 'release')
|
|
||||||
) {
|
|
||||||
intervalBase[1] = [versionArray[i], index, releaseIndex]
|
|
||||||
} else {
|
|
||||||
currentInterval += 1
|
|
||||||
intervals[currentInterval] = [[versionArray[i], index, releaseIndex]]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const newIntervals = []
|
const returnVersions = []
|
||||||
for (let i = 0; i < intervals.length; i++) {
|
|
||||||
const interval = intervals[i]
|
|
||||||
|
|
||||||
if (
|
for (const id in versionsMap) {
|
||||||
interval.length === 2 &&
|
const versions = versionsMap[id]
|
||||||
interval[0][2] !== -1 &&
|
|
||||||
interval[1][2] === -1
|
|
||||||
) {
|
|
||||||
let lastSnapshot = null
|
|
||||||
for (let j = interval[1][1]; j > interval[0][1]; j--) {
|
|
||||||
if (allVersions[j].version_type === 'release') {
|
|
||||||
newIntervals.push([
|
|
||||||
interval[0],
|
|
||||||
[
|
|
||||||
allVersions[j].version,
|
|
||||||
j,
|
|
||||||
allReleases.findIndex(
|
|
||||||
(x) => x.version === allVersions[j].version
|
|
||||||
),
|
|
||||||
],
|
|
||||||
])
|
|
||||||
|
|
||||||
if (lastSnapshot !== null && lastSnapshot !== j + 1) {
|
if (versions.length === 1) {
|
||||||
newIntervals.push([
|
versions[0].displayUrlEnding = versions[0].version_number
|
||||||
[allVersions[lastSnapshot].version, lastSnapshot, -1],
|
|
||||||
interval[1],
|
returnVersions.push(versions[0])
|
||||||
])
|
} else {
|
||||||
|
const reservedNames = {}
|
||||||
|
|
||||||
|
const seenLoaders = {}
|
||||||
|
const duplicateLoaderIndexes = []
|
||||||
|
|
||||||
|
for (let i = 0; i < versions.length; i++) {
|
||||||
|
const version = versions[i]
|
||||||
|
const value = version.loaders.join('+')
|
||||||
|
|
||||||
|
if (seenLoaders[value]) {
|
||||||
|
duplicateLoaderIndexes.push(i)
|
||||||
|
} else {
|
||||||
|
if (i !== 0) {
|
||||||
|
version.displayUrlEnding = `${version.version_number}-${value}`
|
||||||
} else {
|
} else {
|
||||||
newIntervals.push([interval[1]])
|
version.displayUrlEnding = version.version_number
|
||||||
}
|
}
|
||||||
|
|
||||||
break
|
reservedNames[version.displayUrlEnding] = true
|
||||||
} else {
|
|
||||||
lastSnapshot = j
|
version.displayName = version.loaders
|
||||||
|
.map((x) => x.charAt(0).toUpperCase() + x.slice(1))
|
||||||
|
.join(', ')
|
||||||
|
|
||||||
|
returnVersions.push(version)
|
||||||
|
|
||||||
|
seenLoaders[value] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
newIntervals.push(interval)
|
const seenGameVersions = {}
|
||||||
|
const duplicateGameVersionIndexes = []
|
||||||
|
|
||||||
|
for (const i of duplicateLoaderIndexes) {
|
||||||
|
const version = versions[i]
|
||||||
|
const value = version.game_versions.join('+')
|
||||||
|
|
||||||
|
if (seenGameVersions[value]) {
|
||||||
|
duplicateGameVersionIndexes.push(i)
|
||||||
|
} else {
|
||||||
|
if (i !== 0) {
|
||||||
|
let setDisplayUrl = false
|
||||||
|
|
||||||
|
for (const gameVersion in version.game_versions) {
|
||||||
|
const displayUrlEnding = `${version.version_number}-${gameVersion}`
|
||||||
|
|
||||||
|
if (!reservedNames[version.version_number]) {
|
||||||
|
version.displayUrlEnding = displayUrlEnding
|
||||||
|
reservedNames[displayUrlEnding] = true
|
||||||
|
setDisplayUrl = true
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!setDisplayUrl) {
|
||||||
|
version.displayUrlEnding = `${version.version_number}-${value}`
|
||||||
|
}
|
||||||
|
} else if (!reservedNames[version.version_number]) {
|
||||||
|
version.displayUrlEnding = version.version_number
|
||||||
|
reservedNames[version.version_number] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
version.displayName = formatVersions(
|
||||||
|
version.game_versions,
|
||||||
|
ctx.store
|
||||||
|
)
|
||||||
|
|
||||||
|
returnVersions.push(version)
|
||||||
|
|
||||||
|
seenGameVersions[value] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const i in duplicateGameVersionIndexes) {
|
||||||
|
const version = versions[i]
|
||||||
|
|
||||||
|
version.displayUrlEnding = version.id
|
||||||
|
version.displayName = version.id
|
||||||
|
|
||||||
|
returnVersions.push(version)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const output = []
|
return returnVersions.reverse()
|
||||||
|
})
|
||||||
for (const interval of newIntervals) {
|
inject('getProjectTypeForDisplay', (type, categories) => {
|
||||||
if (interval.length === 2) {
|
if (type === 'mod') {
|
||||||
output.push(`${interval[0][0]}—${interval[1][0]}`)
|
const isPlugin = categories.some((category) => {
|
||||||
} else {
|
return ctx.store.state.tag.loaderData.allPluginLoaders.includes(
|
||||||
output.push(interval[0][0])
|
category
|
||||||
}
|
)
|
||||||
}
|
})
|
||||||
|
const isMod = categories.some((category) => {
|
||||||
return output.join(', ')
|
return ctx.store.state.tag.loaderData.modLoaders.includes(category)
|
||||||
|
})
|
||||||
|
return isPlugin && isMod ? 'mod and plugin' : isPlugin ? 'plugin' : 'mod'
|
||||||
|
} else {
|
||||||
|
return formatProjectType(type)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
inject('formatBytes', formatBytes)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const formatNumber = (number) => {
|
export const formatNumber = (number) => {
|
||||||
@@ -127,3 +170,126 @@ export const formatBytes = (bytes, decimals = 2) => {
|
|||||||
|
|
||||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const formatProjectType = (name) => {
|
||||||
|
if (name === 'resourcepack') {
|
||||||
|
return 'resource pack'
|
||||||
|
}
|
||||||
|
return name.charAt(0).toUpperCase() + name.slice(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const formatCategory = (name) => {
|
||||||
|
if (name === 'modloader') {
|
||||||
|
return "Risugami's ModLoader"
|
||||||
|
} else if (name === 'bungeecord') {
|
||||||
|
return 'BungeeCord'
|
||||||
|
} else if (name === 'liteloader') {
|
||||||
|
return 'LiteLoader'
|
||||||
|
} else if (name === 'game-mechanics') {
|
||||||
|
return 'Game Mechanics'
|
||||||
|
} else if (name === 'worldgen') {
|
||||||
|
return 'World Generation'
|
||||||
|
} else if (name === 'core-shaders') {
|
||||||
|
return 'Core Shaders'
|
||||||
|
} else if (name === 'gui') {
|
||||||
|
return 'GUI'
|
||||||
|
} else if (name === '8x-') {
|
||||||
|
return '8x or lower'
|
||||||
|
} else if (name === '512x+') {
|
||||||
|
return '512x or higher'
|
||||||
|
} else if (name === 'kitchen-sink') {
|
||||||
|
return 'Kitchen Sink'
|
||||||
|
}
|
||||||
|
return name.charAt(0).toUpperCase() + name.slice(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const formatCategoryHeader = (name) => {
|
||||||
|
return name.charAt(0).toUpperCase() + name.slice(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const formatVersions = (versionArray, store) => {
|
||||||
|
const allVersions = store.state.tag.gameVersions.slice().reverse()
|
||||||
|
const allReleases = allVersions.filter((x) => x.version_type === 'release')
|
||||||
|
|
||||||
|
const intervals = []
|
||||||
|
let currentInterval = 0
|
||||||
|
|
||||||
|
for (let i = 0; i < versionArray.length; i++) {
|
||||||
|
const index = allVersions.findIndex((x) => x.version === versionArray[i])
|
||||||
|
const releaseIndex = allReleases.findIndex(
|
||||||
|
(x) => x.version === versionArray[i]
|
||||||
|
)
|
||||||
|
|
||||||
|
if (i === 0) {
|
||||||
|
intervals.push([[versionArray[i], index, releaseIndex]])
|
||||||
|
} else {
|
||||||
|
const intervalBase = intervals[currentInterval]
|
||||||
|
|
||||||
|
if (
|
||||||
|
(index - intervalBase[intervalBase.length - 1][1] === 1 ||
|
||||||
|
releaseIndex - intervalBase[intervalBase.length - 1][2] === 1) &&
|
||||||
|
(allVersions[intervalBase[0][1]].version_type === 'release' ||
|
||||||
|
allVersions[index].version_type !== 'release')
|
||||||
|
) {
|
||||||
|
intervalBase[1] = [versionArray[i], index, releaseIndex]
|
||||||
|
} else {
|
||||||
|
currentInterval += 1
|
||||||
|
intervals[currentInterval] = [[versionArray[i], index, releaseIndex]]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const newIntervals = []
|
||||||
|
for (let i = 0; i < intervals.length; i++) {
|
||||||
|
const interval = intervals[i]
|
||||||
|
|
||||||
|
if (
|
||||||
|
interval.length === 2 &&
|
||||||
|
interval[0][2] !== -1 &&
|
||||||
|
interval[1][2] === -1
|
||||||
|
) {
|
||||||
|
let lastSnapshot = null
|
||||||
|
for (let j = interval[1][1]; j > interval[0][1]; j--) {
|
||||||
|
if (allVersions[j].version_type === 'release') {
|
||||||
|
newIntervals.push([
|
||||||
|
interval[0],
|
||||||
|
[
|
||||||
|
allVersions[j].version,
|
||||||
|
j,
|
||||||
|
allReleases.findIndex(
|
||||||
|
(x) => x.version === allVersions[j].version
|
||||||
|
),
|
||||||
|
],
|
||||||
|
])
|
||||||
|
|
||||||
|
if (lastSnapshot !== null && lastSnapshot !== j + 1) {
|
||||||
|
newIntervals.push([
|
||||||
|
[allVersions[lastSnapshot].version, lastSnapshot, -1],
|
||||||
|
interval[1],
|
||||||
|
])
|
||||||
|
} else {
|
||||||
|
newIntervals.push([interval[1]])
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
lastSnapshot = j
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newIntervals.push(interval)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const output = []
|
||||||
|
|
||||||
|
for (const interval of newIntervals) {
|
||||||
|
if (interval.length === 2) {
|
||||||
|
output.push(`${interval[0][0]}—${interval[1][0]}`)
|
||||||
|
} else {
|
||||||
|
output.push(interval[0][0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output.join(', ')
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import xss from 'xss'
|
import xss from 'xss'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {import('xss').IFilterXSSOptions}
|
||||||
|
*/
|
||||||
const options = {
|
const options = {
|
||||||
whiteList: {
|
whiteList: {
|
||||||
...xss.whiteList,
|
...xss.whiteList,
|
||||||
@@ -12,6 +15,12 @@ const options = {
|
|||||||
h6: ['id'],
|
h6: ['id'],
|
||||||
input: ['checked', 'disabled', 'type'],
|
input: ['checked', 'disabled', 'type'],
|
||||||
iframe: ['width', 'height', 'allowfullscreen', 'frameborder'],
|
iframe: ['width', 'height', 'allowfullscreen', 'frameborder'],
|
||||||
|
img: [...xss.whiteList.img, 'style'],
|
||||||
|
},
|
||||||
|
css: {
|
||||||
|
whiteList: {
|
||||||
|
'image-rendering': /^pixelated$/,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
onIgnoreTagAttr: (tag, name, value) => {
|
onIgnoreTagAttr: (tag, name, value) => {
|
||||||
// Allow iframes from acceptable sources
|
// Allow iframes from acceptable sources
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
15
store/tag.js
15
store/tag.js
@@ -4,6 +4,21 @@ export const state = () => ({
|
|||||||
gameVersions: [],
|
gameVersions: [],
|
||||||
licenses: [],
|
licenses: [],
|
||||||
donationPlatforms: [],
|
donationPlatforms: [],
|
||||||
|
loaderData: {
|
||||||
|
pluginLoaders: ['bukkit', 'spigot', 'paper', 'purpur', 'sponge'],
|
||||||
|
pluginPlatformLoaders: ['bungeecord', 'waterfall', 'velocity'],
|
||||||
|
allPluginLoaders: [
|
||||||
|
'bukkit',
|
||||||
|
'spigot',
|
||||||
|
'paper',
|
||||||
|
'purpur',
|
||||||
|
'sponge',
|
||||||
|
'bungeecord',
|
||||||
|
'waterfall',
|
||||||
|
'velocity',
|
||||||
|
],
|
||||||
|
modLoaders: ['forge', 'fabric', 'quilt', 'liteloader', 'modloader', 'rift'],
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
export const mutations = {
|
export const mutations = {
|
||||||
|
|||||||
Reference in New Issue
Block a user