Fix #9, Fix #42, Fix #48, Fix #95, Fix #96, Fix #97, Fix #99, Fix #119. Fix 120

This commit is contained in:
Jai A
2021-03-26 22:07:15 -07:00
parent 98df1f5312
commit e6ece10716
13 changed files with 221 additions and 104 deletions

View File

@@ -1 +1 @@
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="15" y1="9" x2="9" y2="15"></line><line x1="9" y1="9" x2="15" y2="15"></line></svg> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>

Before

Width:  |  Height:  |  Size: 256 B

After

Width:  |  Height:  |  Size: 239 B

View File

@@ -362,6 +362,10 @@
&:active, &:active,
&:hover { &:hover {
background: var(--color-button-bg-hover); background: var(--color-button-bg-hover);
.multiselect__spinner {
background: var(--color-button-bg-hover);
}
} }
.multiselect__single { .multiselect__single {
background: transparent; background: transparent;
@@ -393,4 +397,13 @@
} }
} }
} }
.multiselect__spinner {
background: var(--color-dropdown-bg);
&:active,
&:hover {
background: var(--color-button-bg-hover);
}
}
} }

View File

@@ -39,8 +39,7 @@
color: var(--color-text); color: var(--color-text);
font-weight: var(--font-weight-extrabold); font-weight: var(--font-weight-extrabold);
letter-spacing: 0.02rem; letter-spacing: 0.02rem;
margin: 0; margin: 0 0 0.25em;
margin-bottom: 0.25em;
text-transform: uppercase; text-transform: uppercase;
} }

View File

@@ -1,6 +1,6 @@
<template> <template>
<div class="layout"> <div class="layout">
<header> <header class="site-header">
<section class="navbar columns"> <section class="navbar columns">
<section class="logo column"> <section class="logo column">
<NuxtLink to="/"> <NuxtLink to="/">
@@ -160,9 +160,6 @@ export default {
return `${this.userUrl}/teams` return `${this.userUrl}/teams`
}, },
}, },
mounted() {
this.themeAds()
},
methods: { methods: {
toggleDropdown() { toggleDropdown() {
this.isDropdownOpen = !this.isDropdownOpen this.isDropdownOpen = !this.isDropdownOpen
@@ -177,14 +174,6 @@ export default {
changeTheme() { changeTheme() {
this.$colorMode.preference = this.$colorMode.preference =
this.$colorMode.value === 'dark' ? 'light' : 'dark' this.$colorMode.value === 'dark' ? 'light' : 'dark'
this.themeAds()
},
themeAds() {
const elements = document.getElementsByClassName('ethical-ad')
for (const elem of elements) {
elem.className = 'ethical-ad loaded ' + this.$colorMode.preference
}
}, },
}, },
} }
@@ -196,7 +185,7 @@ export default {
display: block; display: block;
height: 100vh; height: 100vh;
header { .site-header {
height: var(--size-navbar-height); height: var(--size-navbar-height);
background-color: var(--color-raised-bg); background-color: var(--color-raised-bg);
max-width: 100vw; max-width: 100vw;

View File

@@ -38,6 +38,11 @@ export default {
name: 'og:description', name: 'og:description',
content: 'An open source modding platform', content: 'An open source modding platform',
}, },
{
hid: 'og:title',
name: 'og:title',
content: 'Modrinth',
},
{ hid: 'og:type', name: 'og:type', content: 'website' }, { hid: 'og:type', name: 'og:type', content: 'website' },
{ hid: 'og:url', name: 'og:url', content: 'https://www.modrinth.com' }, { hid: 'og:url', name: 'og:url', content: 'https://www.modrinth.com' },
{ {

View File

@@ -101,7 +101,6 @@ export default {
`https://api.modrinth.com/api/v1/notification/${notification.id}`, `https://api.modrinth.com/api/v1/notification/${notification.id}`,
config config
) )
await this.$router.replace('/' + notification.link)
} catch (err) { } catch (err) {
this.$notify({ this.$notify({
group: 'main', group: 'main',

View File

@@ -129,14 +129,6 @@ export default {
changeTheme() { changeTheme() {
this.$colorMode.preference = this.$colorMode.preference =
this.$colorMode.value === 'dark' ? 'light' : 'dark' this.$colorMode.value === 'dark' ? 'light' : 'dark'
this.themeAds()
},
themeAds() {
const elements = document.getElementsByClassName('ethical-ad')
for (const elem of elements) {
elem.className = 'ethical-ad loaded ' + this.$colorMode.preference
}
}, },
gotoRevoke() { gotoRevoke() {
this.$router.replace('/dashboard/misc/revoke-token') this.$router.replace('/dashboard/misc/revoke-token')
@@ -172,6 +164,8 @@ export default {
data, data,
config config
) )
await this.$auth.fetchUser()
} catch (err) { } catch (err) {
this.$notify({ this.$notify({
group: 'main', group: 'main',

View File

@@ -2,7 +2,7 @@
<div class="page-container"> <div class="page-container">
<div class="page-contents"> <div class="page-contents">
<header class="columns"> <header class="columns">
<h2 class="column-grow-1">Edit Mod</h2> <h3 class="column-grow-1">Edit Mod</h3>
<nuxt-link <nuxt-link
:to="'/mod/' + (mod.slug ? mod.slug : mod.id)" :to="'/mod/' + (mod.slug ? mod.slug : mod.id)"
class="button column" class="button column"
@@ -133,8 +133,6 @@
<Multiselect <Multiselect
v-model="clientSideType" v-model="clientSideType"
placeholder="Select one" placeholder="Select one"
track-by="id"
label="label"
:options="sideTypes" :options="sideTypes"
:searchable="false" :searchable="false"
:close-on-select="true" :close-on-select="true"
@@ -147,8 +145,6 @@
<Multiselect <Multiselect
v-model="serverSideType" v-model="serverSideType"
placeholder="Select one" placeholder="Select one"
track-by="id"
label="label"
:options="sideTypes" :options="sideTypes"
:searchable="false" :searchable="false"
:close-on-select="true" :close-on-select="true"
@@ -373,14 +369,8 @@ export default {
return { return {
mod, mod,
clientSideType: { clientSideType: mod.client_side.charAt(0) + mod.client_side.slice(1),
label: mod.client_side, serverSideType: mod.server_side.charAt(0) + mod.server_side.slice(1),
id: mod.client_side,
},
serverSideType: {
label: mod.server_side,
id: mod.server_side,
},
availableCategories, availableCategories,
availableLoaders, availableLoaders,
availableGameVersions, availableGameVersions,
@@ -410,11 +400,7 @@ export default {
icon: null, icon: null,
iconChanged: false, iconChanged: false,
sideTypes: [ sideTypes: ['Required', 'Optional', 'Unsupported'],
{ label: 'Optional', id: 'optional' },
{ label: 'Required', id: 'required' },
{ label: 'Unsupported', id: 'unsupported' },
],
} }
}, },
watch: { watch: {
@@ -459,8 +445,8 @@ export default {
license_url: this.license_url, license_url: this.license_url,
discord_url: this.mod.discord_url, discord_url: this.mod.discord_url,
license_id: this.license.short, license_id: this.license.short,
client_side: this.clientSideType.id, client_side: this.clientSideType.toLowerCase(),
server_side: this.serverSideType.id, server_side: this.serverSideType.toLowerCase(),
slug: this.mod.slug, slug: this.mod.slug,
license: this.license.short, license: this.license.short,
donation_urls: this.donationPlatforms.map((it, index) => { donation_urls: this.donationPlatforms.map((it, index) => {
@@ -591,7 +577,7 @@ header {
grid-area: header; grid-area: header;
padding: var(--spacing-card-md) var(--spacing-card-lg); padding: var(--spacing-card-md) var(--spacing-card-lg);
h2 { h3 {
margin: auto 0; margin: auto 0;
color: var(--color-text-dark); color: var(--color-text-dark);
font-weight: var(--font-weight-extrabold); font-weight: var(--font-weight-extrabold);

View File

@@ -46,10 +46,21 @@
version.id version.id
" "
> >
{{ version.name }} {{ version.name ? version.name : version.version_number }}
</nuxt-link>
</td>
<td>
<nuxt-link
:to="
'/mod/' +
(mod.slug ? mod.slug : mod.id) +
'/version/' +
version.id
"
>
{{ version.version_number }}
</nuxt-link> </nuxt-link>
</td> </td>
<td>{{ version.version_number }}</td>
<td> <td>
<FabricIcon v-if="version.loaders.includes('fabric')" /> <FabricIcon v-if="version.loaders.includes('fabric')" />
<ForgeIcon v-if="version.loaders.includes('forge')" /> <ForgeIcon v-if="version.loaders.includes('forge')" />

View File

@@ -2,7 +2,7 @@
<div class="page-container"> <div class="page-container">
<div class="page-contents"> <div class="page-contents">
<header class="columns"> <header class="columns">
<h2 class="column-grow-1">Create a mod</h2> <h3 class="column-grow-1">Create a mod</h3>
<button <button
title="Save draft" title="Save draft"
class="button column" class="button column"
@@ -123,8 +123,6 @@
<Multiselect <Multiselect
v-model="clientSideType" v-model="clientSideType"
placeholder="Select one" placeholder="Select one"
track-by="id"
label="label"
:options="sideTypes" :options="sideTypes"
:searchable="false" :searchable="false"
:close-on-select="true" :close-on-select="true"
@@ -137,8 +135,6 @@
<Multiselect <Multiselect
v-model="serverSideType" v-model="serverSideType"
placeholder="Select one" placeholder="Select one"
track-by="id"
label="label"
:options="sideTypes" :options="sideTypes"
:searchable="false" :searchable="false"
:close-on-select="true" :close-on-select="true"
@@ -161,11 +157,13 @@
You can type the of the long form of your description here. This You can type the of the long form of your description here. This
editor supports markdown. You can find the syntax editor supports markdown. You can find the syntax
<a <a
class=""
href="https://guides.github.com/features/mastering-markdown/" href="https://guides.github.com/features/mastering-markdown/"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
>here</a >here</a
>. >. HTML can also be used inside your description, excluding scripts
and iframes.
</span> </span>
<div class="columns"> <div class="columns">
<div class="textarea-wrapper"> <div class="textarea-wrapper">
@@ -193,8 +191,8 @@
<th>Version</th> <th>Version</th>
<th>Mod Loader</th> <th>Mod Loader</th>
<th>Minecraft Version</th> <th>Minecraft Version</th>
<th>Status</th> <th>Version Type</th>
<th></th> <th>Actions</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -217,18 +215,21 @@
<td>{{ version.game_versions.join(', ') }}</td> <td>{{ version.game_versions.join(', ') }}</td>
<td> <td>
<span <span
v-if="version.version_type === 'release'" v-if="version.release_channel === 'release'"
class="badge green" class="badge green"
> >
Release Release
</span> </span>
<span <span
v-if="version.version_type === 'beta'" v-if="version.release_channel === 'beta'"
class="badge yellow" class="badge yellow"
> >
Beta Beta
</span> </span>
<span v-if="version.version_type === 'alpha'" class="badge red"> <span
v-if="version.release_channel === 'alpha'"
class="badge red"
>
Alpha Alpha
</span> </span>
</td> </td>
@@ -562,13 +563,9 @@ export default {
license: null, license: null,
license_url: null, license_url: null,
sideTypes: [ sideTypes: ['Required', 'Optional', 'Unsupported'],
{ label: 'Required', id: 'required' }, clientSideType: 'Required',
{ label: 'Optional', id: 'optional' }, serverSideType: 'Required',
{ label: 'Unsupported', id: 'unsupported' },
],
clientSideType: { label: 'Required', id: 'required' },
serverSideType: { label: 'Required', id: 'required' },
donationLinks: [], donationLinks: [],
donationPlatforms: [], donationPlatforms: [],
@@ -627,8 +624,8 @@ export default {
source_url: this.source_url, source_url: this.source_url,
wiki_url: this.wiki_url, wiki_url: this.wiki_url,
discord_url: this.discord_url, discord_url: this.discord_url,
client_side: this.clientSideType.id, client_side: this.clientSideType.toLowerCase(),
server_side: this.serverSideType.id, server_side: this.serverSideType.toLowerCase(),
license_id: this.license ? this.license.short : 'arr', license_id: this.license ? this.license.short : 'arr',
license_url: this.license_url, license_url: this.license_url,
is_draft: this.draft, is_draft: this.draft,
@@ -805,7 +802,7 @@ header {
grid-area: header; grid-area: header;
padding: var(--spacing-card-md) var(--spacing-card-lg); padding: var(--spacing-card-md) var(--spacing-card-lg);
h2 { h3 {
margin: auto 0; margin: auto 0;
color: var(--color-text-dark); color: var(--color-text-dark);
font-weight: var(--font-weight-extrabold); font-weight: var(--font-weight-extrabold);
@@ -860,6 +857,10 @@ section.game-sides {
section.description { section.description {
grid-area: description; grid-area: description;
span a {
text-decoration: underline;
}
& > .columns { & > .columns {
align-items: stretch; align-items: stretch;
min-height: 10rem; min-height: 10rem;

View File

@@ -64,26 +64,31 @@
</section> </section>
<div class="results column-grow-4"> <div class="results column-grow-4">
<Advertisement /> <Advertisement />
<SearchResult <div v-if="results === null" class="no-results">
v-for="(result, index) in results" <p>Loading...</p>
:id="result.slug ? result.slug : result.mod_id.split('-')[1]" </div>
:key="result.mod_id" <div v-else>
:author="result.author" <SearchResult
:name="result.title" v-for="(result, index) in results"
:description="result.description" :id="result.slug ? result.slug : result.mod_id.split('-')[1]"
:latest-version="result.latest_version" :key="result.mod_id"
:created-at="result.date_created" :author="result.author"
:updated-at="result.date_modified" :name="result.title"
:downloads="result.downloads.toString()" :description="result.description"
:icon-url="result.icon_url" :latest-version="result.latest_version"
:author-url="result.author_url" :created-at="result.date_created"
:page-url="result.page_url" :updated-at="result.date_modified"
:categories="result.categories" :downloads="result.downloads.toString()"
:is-ad="index === -1" :icon-url="result.icon_url"
:is-modrinth="result.host === 'modrinth'" :author-url="result.author_url"
/> :page-url="result.page_url"
<div v-if="results.length === 0" class="no-results"> :categories="result.categories"
<p>No results found for your query!</p> :is-ad="index === -1"
:is-modrinth="result.host === 'modrinth'"
/>
<div v-if="results.length === 0" class="no-results">
<p>No results found for your query!</p>
</div>
</div> </div>
</div> </div>
<section v-if="pages.length > 1" class="search-bottom"> <section v-if="pages.length > 1" class="search-bottom">
@@ -115,8 +120,13 @@
<button class="filter-button-done" @click="toggleFiltersMenu"> <button class="filter-button-done" @click="toggleFiltersMenu">
Done Done
</button> </button>
<button @click="clearFilters">Reset filters</button> <div class="filter-clear-button">
<h3>Categories</h3> <h3>Categories</h3>
<button class="iconified-button" @click="clearFilters">
<ExitIcon />
Clear filters
</button>
</div>
<SearchFilter <SearchFilter
:active-filters="facets" :active-filters="facets"
display-name="Technology" display-name="Technology"
@@ -230,7 +240,7 @@
> >
<ForgeLoader /> <ForgeLoader />
</SearchFilter> </SearchFilter>
<h3>Versions</h3> <h3>Minecraft Versions</h3>
<SearchFilter <SearchFilter
:active-filters="showVersions" :active-filters="showVersions"
display-name="Include snapshots" display-name="Include snapshots"
@@ -254,6 +264,20 @@
placeholder="Choose versions..." placeholder="Choose versions..."
@input="onSearchChange(1)" @input="onSearchChange(1)"
></multiselect> ></multiselect>
<h3>Licenses</h3>
<Multiselect
v-model="displayLicense"
placeholder="Choose licenses..."
:loading="licenses.length === 0"
:options="licenses"
track-by="name"
label="name"
:searchable="false"
:close-on-select="true"
:show-labels="false"
:allow-empty="true"
@input="toggleLicense"
/>
</div> </div>
<Advertisement format="rectangle" /> <Advertisement format="rectangle" />
<m-footer class="footer" /> <m-footer class="footer" />
@@ -287,6 +311,8 @@ import ForgeLoader from '~/assets/images/categories/forge.svg?inline'
import FabricLoader from '~/assets/images/categories/fabric.svg?inline' import FabricLoader from '~/assets/images/categories/fabric.svg?inline'
import SearchIcon from '~/assets/images/utils/search.svg?inline' import SearchIcon from '~/assets/images/utils/search.svg?inline'
import ExitIcon from '~/assets/images/utils/exit.svg?inline'
import Advertisement from '~/components/Advertisement' import Advertisement from '~/components/Advertisement'
export default { export default {
@@ -313,6 +339,7 @@ export default {
ForgeLoader, ForgeLoader,
FabricLoader, FabricLoader,
SearchIcon, SearchIcon,
ExitIcon,
}, },
async fetch() { async fetch() {
if (this.$route.query.q) this.query = this.$route.query.q if (this.$route.query.q) this.query = this.$route.query.q
@@ -325,8 +352,24 @@ export default {
this.selectedVersions = this.$route.query.v.split(',') this.selectedVersions = this.$route.query.v.split(',')
if (this.$route.query.s) { if (this.$route.query.s) {
this.sortType.name = this.$route.query.s this.sortType.name = this.$route.query.s
this.sortType.display =
this.sortType.name.charAt(0).toUpperCase() + this.sortType.name.slice(1) switch (this.sortType.name) {
case 'relevance':
this.sortType.display = 'Relevance'
break
case 'downloads':
this.sortType.display = 'Downloads'
break
case 'newest':
this.sortType.display = 'Recently created'
break
case 'updated':
this.sortType.display = 'Recently updated'
break
case 'follows':
this.sortType.display = 'Follow count'
break
}
} }
if (this.$route.query.m) { if (this.$route.query.m) {
this.maxResults = this.$route.query.m this.maxResults = this.$route.query.m
@@ -334,26 +377,38 @@ export default {
if (this.$route.query.o) if (this.$route.query.o)
this.currentPage = Math.ceil(this.$route.query.o / this.maxResults) + 1 this.currentPage = Math.ceil(this.$route.query.o / this.maxResults) + 1
await this.fillInitialVersions() await Promise.all([
await this.onSearchChange(this.currentPage) this.fillInitialVersions(),
this.fillInitialLicenses(),
this.onSearchChange(this.currentPage),
])
}, },
data() { data() {
return { return {
query: '', query: '',
displayLicense: '',
selectedLicense: '',
licenses: [],
showVersions: [], showVersions: [],
selectedVersions: [], selectedVersions: [],
versions: [], versions: [],
facets: [], facets: [],
results: [], results: null,
pages: [], pages: [],
currentPage: 1, currentPage: 1,
sortTypes: [ sortTypes: [
{ display: 'Relevance', name: 'relevance' }, { display: 'Relevance', name: 'relevance' },
{ display: 'Download count', name: 'downloads' }, { display: 'Download count', name: 'downloads' },
{ display: 'Follow count', name: 'follows' },
{ display: 'Recently created', name: 'newest' }, { display: 'Recently created', name: 'newest' },
{ display: 'Recently updated', name: 'updated' }, { display: 'Recently updated', name: 'updated' },
], ],
sortType: { display: 'Relevance', name: 'relevance' }, sortType: { display: 'Relevance', name: 'relevance' },
maxResults: 20, maxResults: 20,
firstRun: true, firstRun: true,
} }
@@ -383,9 +438,30 @@ export default {
console.error(err) console.error(err)
} }
}, },
async fillInitialLicenses() {
this.licenses = (
await axios.get('https://api.modrinth.com/api/v1/tag/license')
).data
},
async toggleLicense(license) {
if (this.selectedLicense) {
const index = this.facets.indexOf(this.selectedLicense)
this.facets.splice(index, 1)
}
if (license) {
this.selectedLicense = `license:${license.short}`
this.facets.push(this.selectedLicense)
}
await this.onSearchChange(1)
},
async clearFilters() { async clearFilters() {
for (const facet of [...this.facets]) await this.toggleFacet(facet, true) for (const facet of [...this.facets]) await this.toggleFacet(facet, true)
this.displayLicense = null
this.selectedLicense = null
this.selectedVersions = [] this.selectedVersions = []
await this.onSearchChange(1) await this.onSearchChange(1)
}, },
@@ -491,7 +567,7 @@ export default {
if (this.maxResults > 20) if (this.maxResults > 20)
url += `&m=${encodeURIComponent(this.maxResults)}` url += `&m=${encodeURIComponent(this.maxResults)}`
window.history.pushState(new Date(), 'Mods', url) window.history.replaceState(new Date(), 'Mods', url)
} }
} catch (err) { } catch (err) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
@@ -628,7 +704,7 @@ export default {
margin-bottom: var(--spacing-card-md); margin-bottom: var(--spacing-card-md);
} }
h3 { h3 {
@extend %large-label; @extend %small-label;
margin-top: 1.25em; margin-top: 1.25em;
} }
&.active { &.active {
@@ -658,15 +734,18 @@ export default {
} }
.filter-group { .filter-group {
margin-top: 1em;
button { button {
cursor: pointer; cursor: pointer;
width: 100%; }
.filter-clear-button {
display: flex;
justify-content: space-between;
} }
.filter-button-done { .filter-button-done {
display: block; display: block;
width: 100%;
} }
// Large screens that don't collapse // Large screens that don't collapse

View File

@@ -2,7 +2,7 @@
<div class="page-container"> <div class="page-container">
<div class="page-contents"> <div class="page-contents">
<header class="columns"> <header class="columns">
<h2 class="column-grow-1">File a report</h2> <h3 class="column-grow-1">File a report</h3>
<button <button
title="Create" title="Create"
class="brand-button column" class="brand-button column"
@@ -209,7 +209,7 @@ header {
grid-area: header; grid-area: header;
padding: var(--spacing-card-md) var(--spacing-card-lg); padding: var(--spacing-card-md) var(--spacing-card-lg);
h2 { h3 {
margin: auto 0; margin: auto 0;
color: var(--color-text-dark); color: var(--color-text-dark);
font-weight: var(--font-weight-extrabold); font-weight: var(--font-weight-extrabold);

View File

@@ -160,6 +160,47 @@ export default {
head() { head() {
return { return {
title: this.user.username + ' - Modrinth', title: this.user.username + ' - Modrinth',
meta: [
{
hid: 'og:type',
name: 'og:type',
content: 'website',
},
{
hid: 'og:title',
name: 'og:title',
content: this.user.username,
},
{
hid: 'apple-mobile-web-app-title',
name: 'apple-mobile-web-app-title',
content: this.user.username,
},
{
hid: 'og:description',
name: 'og:description',
content: this.user.bio,
},
{
hid: 'description',
name: 'description',
content:
this.user.bio +
' - View minecraft mods on Modrinth today! Modrinth is a new and modern Minecraft modding platform that is compatible with CurseForge too!',
},
{
hid: 'og:url',
name: 'og:url',
content: `https://modrinth.com/user/${this.user.id}`,
},
{
hid: 'og:image',
name: 'og:image',
content: this.user.avatar_url
? this.user.avatar_url
: 'https://cdn.modrinth.com/placeholder.png',
},
],
} }
}, },
} }