This commit is contained in:
Jai A 2020-12-16 13:32:06 -07:00
commit 4e4f4e60b6
No known key found for this signature in database
GPG Key ID: E8B7DFB8C62797AC
13 changed files with 356 additions and 248 deletions

View File

Before

Width:  |  Height:  |  Size: 921 B

After

Width:  |  Height:  |  Size: 921 B

View File

@ -1,59 +1,59 @@
<template>
<div class="categories">
<p v-if="categories.includes('fabric')">
<FabricLoader />
<FabricLoader aria-hidden="true" />
Fabric
</p>
<p v-if="categories.includes('forge')">
<ForgeLoader />
<ForgeLoader aria-hidden="true" />
Forge
</p>
<p v-if="categories.includes('technology')">
<TechCategory />
<TechCategory aria-hidden="true" />
Technology
</p>
<p v-if="categories.includes('adventure')">
<AdventureCategory />
<AdventureCategory aria-hidden="true" />
Adventure
</p>
<p v-if="categories.includes('magic')">
<MagicCategory />
<MagicCategory aria-hidden="true" />
Magic
</p>
<p v-if="categories.includes('utility')">
<UtilityCategory />
<UtilityCategory aria-hidden="true" />
Utility
</p>
<p v-if="categories.includes('decoration')">
<DecorationCategory />
<DecorationCategory aria-hidden="true" />
Decoration
</p>
<p v-if="categories.includes('library')">
<LibraryCategory />
<LibraryCategory aria-hidden="true" />
Library
</p>
<p v-if="categories.includes('cursed')">
<CursedCategory />
<CursedCategory aria-hidden="true" />
Cursed
</p>
<p v-if="categories.includes('worldgen')">
<WorldGenCategory />
<WorldGenCategory aria-hidden="true" />
Worldgen
</p>
<p v-if="categories.includes('storage')">
<StorageCategory />
<StorageCategory aria-hidden="true" />
Storage
</p>
<p v-if="categories.includes('food')">
<FoodCategory />
<FoodCategory aria-hidden="true" />
Food
</p>
<p v-if="categories.includes('equipment')">
<EquipmentCategory />
<EquipmentCategory aria-hidden="true" />
Equipment
</p>
<p v-if="categories.includes('misc')">
<MiscCategory />
<MiscCategory aria-hidden="true" />
Misc
</p>
</div>

View File

@ -0,0 +1,62 @@
<template>
<div class="page-container">
<div class="page-contents">
<div class="sidebar-l">
<div class="card page-nav">
<nuxt-link :to="'/dashboard/projects'" class="tab last">
<ModIcon />
My mods
</nuxt-link>
<nuxt-link
v-if="
$auth.user.role === 'admin' || $auth.user.role === 'moderator'
"
:to="'/dashboard/moderation'"
class="tab last"
>
<ModerationIcon />
Moderation
</nuxt-link>
<nuxt-link :to="'/dashboard/settings'" class="tab last">
<SettingsIcon />
Settings
</nuxt-link>
</div>
<m-footer class="footer" />
<client-only>
<EthicalAd type="image" />
</client-only>
</div>
<div class="content">
<slot />
</div>
</div>
</div>
</template>
<script>
import ModIcon from '~/assets/images/sidebar/mod.svg?inline'
import ModerationIcon from '~/assets/images/sidebar/admin.svg?inline'
import SettingsIcon from '~/assets/images/sidebar/settings.svg?inline'
export default {
name: 'DashboardPage',
components: {
ModIcon,
ModerationIcon,
SettingsIcon,
},
}
</script>
<style lang="scss" scoped>
.section-header {
@extend %card;
padding: var(--spacing-card-md) var(--spacing-card-lg);
margin-bottom: var(--spacing-card-md);
h3 {
margin: auto 0;
color: var(--color-text-dark);
font-weight: var(--font-weight-extrabold);
}
}
</style>

View File

@ -4,6 +4,7 @@
:class="{ disabled: currentPage === 1 }"
class="paginate has-icon"
@click="currentPage !== 1 ? switchPage(currentPage - 1) : null"
aria-label="Previous Page"
>
<LeftArrowIcon />
</button>
@ -34,6 +35,7 @@
? switchPage(currentPage + 1)
: null
"
aria-label="Next Page"
>
<RightArrowIcon />
</button>

View File

@ -1,5 +1,5 @@
<template>
<div class="project-card">
<article class="project-card">
<div class="icon">
<img
:src="iconUrl ? iconUrl : 'https://cdn.modrinth.com/placeholder.svg'"
@ -43,14 +43,14 @@
</div>
</div>
<div class="stat">
<DownloadIcon />
<DownloadIcon aria-hidden="true" />
<div class="info">
<h4>Downloads</h4>
<p class="value">{{ formatNumber(downloads) }}</p>
</div>
</div>
<div class="stat">
<CalendarIcon />
<CalendarIcon aria-hidden="true" />
<div class="info">
<h4>Created</h4>
<p
@ -66,7 +66,7 @@
</div>
</div>
<div class="stat">
<EditIcon />
<EditIcon aria-hidden="true" />
<div class="info">
<h4>Updated</h4>
<p
@ -82,7 +82,7 @@
</div>
</div>
<div v-if="latestVersion" class="stat">
<TagIcon />
<TagIcon aria-hidden="true" />
<div class="info">
<h4>Available For</h4>
<p class="value">
@ -97,7 +97,7 @@
<div v-if="editMode" class="buttons">
<slot />
</div>
</div>
</article>
</template>
<script>

View File

@ -1,11 +1,14 @@
<template>
<div class="layout">
<aside>
<header>
<section class="navbar columns">
<section class="logo column">
<NuxtLink to="/">
<ModrinthLogo v-if="$colorMode.value === 'light'" />
<ModrinthLogoWhite v-else />
<ModrinthLogo
v-if="$colorMode.value === 'light'"
aria-label="modrinth"
/>
<ModrinthLogoWhite v-else aria-label="modrinth" />
</NuxtLink>
<span class="badge yellow">Beta</span>
</section>
@ -60,12 +63,6 @@
<span v-else>Light Mode</span>
</button>
</li>
<li v-tooltip="'Not implemented yet'" class="hidden">
<NuxtLink to="/settings" disabled>
<SettingsIcon />
<span>Settings</span>
</NuxtLink>
</li>
<hr />
<li>
<button @click="logout">
@ -81,7 +78,7 @@
<template v-else>
<section class="auth-prompt">
<a :href="authUrl" class="log-in-button"
><GitHubIcon />Sign In with GitHub</a
><GitHubIcon aria-hidden="true" />Sign In with GitHub</a
>
</section>
</template>
@ -97,13 +94,6 @@
<AnalyticsIcon />
<span>Analytics</span>
</NuxtLink>
<!-- <NuxtLink
v-if="this.$auth.user.role === 'admin'"
to="/dashboard/admin"
>
<AdminIcon />
<span>Admin</span>
</NuxtLink> -->
</section>
<div>
<button class="hamburger" @click="toggleNav">
@ -144,7 +134,7 @@
</section>
</nav>
</section>
</aside>
</header>
<main>
<notifications group="main" position="bottom right" />
<!--<notifications
@ -167,7 +157,6 @@ import ModrinthLogoWhite from '~/assets/images/text-logo-white.svg?inline'
import ModpackIcon from '~/assets/images/sidebar/modpack.svg?inline'
import ProjectsIcon from '~/assets/images/sidebar/projects.svg?inline'
import AnalyticsIcon from '~/assets/images/sidebar/analytics.svg?inline'
// import AdminIcon from '~/assets/images/sidebar/admin.svg?inline'
import DropdownIcon from '~/assets/images/utils/dropdown.svg?inline'
import HamburgerIcon from '~/assets/images/utils/hamburger.svg?inline'
@ -177,7 +166,6 @@ import SunIcon from '~/assets/images/utils/sun.svg?inline'
import UserIcon from '~/assets/images/utils/user.svg?inline'
import UsersIcon from '~/assets/images/utils/users.svg?inline'
import SettingsIcon from '~/assets/images/utils/settings.svg?inline'
import LogOutIcon from '~/assets/images/utils/log-out.svg?inline'
import GitHubIcon from '~/assets/images/utils/github.svg?inline'
@ -188,7 +176,6 @@ export default {
ModpackIcon,
ProjectsIcon,
AnalyticsIcon,
// AdminIcon,
DropdownIcon,
HamburgerIcon,
ExitIcon,
@ -196,7 +183,6 @@ export default {
SunIcon,
UserIcon,
UsersIcon,
SettingsIcon,
LogOutIcon,
GitHubIcon,
},
@ -264,7 +250,7 @@ export default {
display: block;
height: 100vh;
aside {
header {
height: var(--size-navbar-height);
background-color: var(--color-raised-bg);
max-width: 100vw;
@ -464,7 +450,7 @@ export default {
@media (min-width: 1024px) {
.layout {
aside {
header {
}
main {
@ -481,7 +467,7 @@ export default {
@media (min-width: 1280px) {
.layout {
aside {
header {
}
}
}

View File

@ -1,86 +1,56 @@
<template>
<div class="page-container">
<div class="page-contents">
<div class="sidebar-l">
<div class="card page-nav">
<nuxt-link :to="'/dashboard/projects'" class="tab last">
<ModIcon />
My mods
</nuxt-link>
<nuxt-link
v-if="
$auth.user.role === 'admin' || $auth.user.role === 'moderator'
"
:to="'/dashboard/moderation'"
class="tab last"
>
<ModerationIcon />
Moderation
</nuxt-link>
</div>
<m-footer class="footer" />
<client-only>
<EthicalAd type="image" />
</client-only>
</div>
<div class="content">
<div class="section-header">
<h3 class="column-grow-1">Mods</h3>
</div>
<ModCard
v-for="mod in mods"
:id="mod.id"
:key="mod.id"
:author="mod.author"
:name="mod.title"
:description="mod.description"
:latest-version="mod.latest_version"
:created-at="mod.published"
:updated-at="mod.updated"
:downloads="mod.downloads.toString()"
:icon-url="mod.icon_url"
:author-url="mod.author_url"
:page-url="mod.page_url"
:categories="mod.categories"
:edit-mode="true"
:status="mod.status"
:is-modrinth="true"
>
<button
class="button column approve"
@click="changeModStatus(mod.id, 'approved')"
>
Approve
</button>
<button
class="button column reject"
@click="changeModStatus(mod.id, 'rejected')"
>
Reject
</button>
</ModCard>
<div class="section-header">
<h3 class="column-grow-1">Versions</h3>
</div>
</div>
<DashboardPage>
<div class="section-header">
<h3 class="column-grow-1">Mods</h3>
</div>
</div>
<ModCard
v-for="mod in mods"
:id="mod.id"
:key="mod.id"
:author="mod.author"
:name="mod.title"
:description="mod.description"
:latest-version="mod.latest_version"
:created-at="mod.published"
:updated-at="mod.updated"
:downloads="mod.downloads.toString()"
:icon-url="mod.icon_url"
:author-url="mod.author_url"
:page-url="mod.page_url"
:categories="mod.categories"
:edit-mode="true"
:status="mod.status"
:is-modrinth="true"
>
<button
class="button column approve"
@click="changeModStatus(mod.id, 'approved')"
>
Approve
</button>
<button
class="button column reject"
@click="changeModStatus(mod.id, 'rejected')"
>
Reject
</button>
</ModCard>
<div class="section-header">
<h3 class="column-grow-1">Versions</h3>
</div>
</DashboardPage>
</template>
<script>
import axios from 'axios'
import EthicalAd from '@/components/EthicalAd'
import ModCard from '@/components/ProjectCard'
import ModIcon from '~/assets/images/sidebar/mod.svg?inline'
import ModerationIcon from '~/assets/images/sidebar/admin.svg?inline'
import ModCard from '@/components/ProjectCard'
import DashboardPage from '@/components/DashboardPage'
export default {
components: {
EthicalAd,
DashboardPage,
ModCard,
ModIcon,
ModerationIcon,
},
async asyncData(data) {
const config = {
@ -133,17 +103,6 @@ export default {
</script>
<style lang="scss" scoped>
.section-header {
@extend %card;
padding: var(--spacing-card-md) var(--spacing-card-lg);
margin-bottom: var(--spacing-card-md);
h3 {
margin: auto 0;
color: var(--color-text-dark);
font-weight: var(--font-weight-extrabold);
}
}
.button {
margin: 0.25rem 0;
}

View File

@ -1,79 +1,46 @@
<template>
<div class="page-container">
<div class="page-contents">
<div class="sidebar-l">
<div class="card page-nav">
<nuxt-link :to="'/dashboard/projects'" class="tab last">
<ModIcon />
My mods
</nuxt-link>
<nuxt-link
v-if="
$auth.user.role === 'admin' || $auth.user.role === 'moderator'
"
:to="'/dashboard/moderation'"
class="tab last"
>
<ModerationIcon />
Moderation
</nuxt-link>
</div>
<m-footer class="footer" />
<client-only>
<EthicalAd type="image" />
</client-only>
</div>
<div class="content">
<div class="section-header columns">
<h3 class="column-grow-1">My mods</h3>
<nuxt-link class="brand-button column" to="/mod/create">
Create a mod
</nuxt-link>
</div>
<ModCard
v-for="mod in mods"
:id="mod.slug ? mod.slug : mod.id"
:key="mod.id"
:author="mod.author"
:name="mod.title"
:description="mod.description"
:latest-version="mod.latest_version"
:created-at="mod.published"
:updated-at="mod.updated"
:downloads="mod.downloads.toString()"
:icon-url="mod.icon_url"
:author-url="mod.author_url"
:page-url="mod.page_url"
:categories="mod.categories"
:edit-mode="true"
:status="mod.status"
:is-modrinth="true"
>
<nuxt-link class="button column" :to="'/mod/' + mod.id + '/edit'">
Edit
</nuxt-link>
</ModCard>
</div>
<DashboardPage>
<div class="section-header columns">
<h3 class="column-grow-1">My mods</h3>
<nuxt-link class="brand-button column" to="/mod/create">
Create a mod
</nuxt-link>
</div>
</div>
<ModCard
v-for="mod in mods"
:id="mod.slug ? mod.slug : mod.id"
:key="mod.id"
:author="mod.author"
:name="mod.title"
:description="mod.description"
:latest-version="mod.latest_version"
:created-at="mod.published"
:updated-at="mod.updated"
:downloads="mod.downloads.toString()"
:icon-url="mod.icon_url"
:author-url="mod.author_url"
:page-url="mod.page_url"
:categories="mod.categories"
:edit-mode="true"
:status="mod.status"
:is-modrinth="true"
>
<nuxt-link class="button column" :to="'/mod/' + mod.id + '/edit'">
Edit
</nuxt-link>
</ModCard>
</DashboardPage>
</template>
<script>
import axios from 'axios'
import EthicalAd from '@/components/EthicalAd'
import ModCard from '@/components/ProjectCard'
import MFooter from '@/components/MFooter'
import ModIcon from '~/assets/images/sidebar/mod.svg?inline'
import ModerationIcon from '~/assets/images/sidebar/admin.svg?inline'
import DashboardPage from '@/components/DashboardPage'
export default {
components: {
EthicalAd,
DashboardPage,
ModCard,
ModIcon,
ModerationIcon,
MFooter,
},
async asyncData(data) {
const config = {
@ -102,17 +69,6 @@ export default {
</script>
<style lang="scss" scoped>
.section-header {
@extend %card;
padding: var(--spacing-card-md) var(--spacing-card-lg);
margin-bottom: var(--spacing-card-md);
h3 {
margin: auto 0;
color: var(--color-text-dark);
font-weight: var(--font-weight-extrabold);
}
}
.mod-name {
font-weight: bold;
}

View File

@ -0,0 +1,127 @@
<template>
<DashboardPage>
<div class="section-header columns">
<h3 class="column-grow-1">Settings</h3>
<button class="brand-button column" @click="editProfile">Save</button>
</div>
<section class="essentials">
<h3>Username</h3>
<label>
<span>
The username used on the modrinth site to identify yourself. This must
be unique.
</span>
<input
v-model="username"
type="text"
placeholder="Enter your username"
/>
</label>
<h3>Name</h3>
<label>
<span>
Your display name on your Modrinth profile. This does not have to be
unique, can be set to anything, and is optional.
</span>
<input v-model="name" type="text" placeholder="Enter your name" />
</label>
<h3>Email</h3>
<label>
<span>
The email for your account. This is private information which is not
displayed in any API routes or your profile. It is also optional.
</span>
<input v-model="email" type="email" placeholder="Enter your email" />
</label>
<h3>Bio</h3>
<label>
<span>
Give a quick description to your mod. It will appear in the search
</span>
<input v-model="bio" type="text" placeholder="Enter your bio" />
</label>
</section>
</DashboardPage>
</template>
<script>
import DashboardPage from '@/components/DashboardPage'
import axios from 'axios'
export default {
components: {
DashboardPage,
},
fetch() {
this.username = this.$auth.user.username
this.name = this.$auth.user.name
this.email = this.$auth.user.email
this.bio = this.$auth.user.bio
},
data() {
return {
username: '',
name: '',
email: '',
bio: '',
}
},
methods: {
async editProfile() {
const config = {
headers: {
Authorization: this.$auth.getToken('local'),
},
}
this.$nuxt.$loading.start()
try {
const data = {
username: this.username,
name: this.name,
email: this.email,
bio: this.bio,
}
await axios.patch(
`https://api.modrinth.com/api/v1/user/${this.$auth.user.id}`,
data,
config
)
} catch (err) {
this.$notify({
group: 'main',
title: 'An Error Occurred',
text: err.response.data.description,
type: 'error',
})
}
this.$nuxt.$loading.finish()
},
},
}
</script>
<style lang="scss" scoped>
section {
@extend %card;
padding: var(--spacing-card-md) var(--spacing-card-lg);
}
label {
display: flex;
span {
flex: 2;
padding-right: var(--spacing-card-lg);
}
input {
flex: 3;
height: fit-content;
}
}
</style>

View File

@ -145,7 +145,7 @@
a worldwide, non-exclusive, royalty-free, and unrestricted license to
use, reproduce, distribute copies, prepare derivative works of, or
display Content in connection with Modrinth in any medium and for any
purpose (including commercial purposes), which is irrevocable.
purpose (including commercial purposes).
</li>
</ul>
</div>

View File

@ -11,6 +11,9 @@ import ModPage from '@/components/ModPage'
export default {
components: { ModPage },
auth: false,
async fetch() {
this.body = (await axios.get(this.mod.body_url)).data
},
async asyncData(data) {
const config = {
headers: {
@ -27,38 +30,43 @@ export default {
)
).data
const [members, versions, body] = (
const [members, versions] = (
await Promise.all([
axios.get(
`https://api.modrinth.com/api/v1/team/${mod.team}/members`,
config
),
axios.get(`https://api.modrinth.com/api/v1/team/${mod.team}/members`),
axios.get(
`https://api.modrinth.com/api/v1/versions?ids=${JSON.stringify(
mod.versions
)}`,
config
),
axios.get(mod.body_url),
])
).map((it) => it.data)
const users = await Promise.all(
members.map((it) =>
axios.get(`https://api.modrinth.com/api/v1/user/${it.user_id}`, config)
const users = (
await axios.get(
`https://api.modrinth.com/api/v1/users?ids=${JSON.stringify(
members.map((it) => it.user_id)
)}`,
config
)
)
users.forEach(
(it, index) => (members[index].avatar_url = it.data.avatar_url)
)
).data
users.forEach((it, index) => {
members[index].avatar_url = it.avatar_url
members[index].name = it.username
})
return {
mod,
body,
versions: versions.reverse(),
members,
}
},
data() {
return {
body: '',
}
},
head() {
return {
title: this.mod.title + ' - Modrinth',

View File

@ -118,6 +118,11 @@ export default {
TagIcon,
},
auth: false,
async fetch() {
if (this.version.changelog_url) {
this.changelog = (await axios.get(this.version.changelog_url)).data
}
},
async asyncData(data) {
const config = {
headers: {
@ -136,10 +141,7 @@ export default {
const [members, versions] = (
await Promise.all([
axios.get(
`https://api.modrinth.com/api/v1/team/${mod.team}/members`,
config
),
axios.get(`https://api.modrinth.com/api/v1/team/${mod.team}/members`),
axios.get(
`https://api.modrinth.com/api/v1/versions?ids=${JSON.stringify(
mod.versions
@ -149,24 +151,24 @@ export default {
])
).map((it) => it.data)
const users = await Promise.all(
members.map((it) =>
axios.get(`https://api.modrinth.com/api/v1/user/${it.user_id}`, config)
const users = (
await axios.get(
`https://api.modrinth.com/api/v1/users?ids=${JSON.stringify(
members.map((it) => it.user_id)
)}`,
config
)
)
users.forEach(
(it, index) => (members[index].avatar_url = it.data.avatar_url)
)
).data
users.forEach((it, index) => {
members[index].avatar_url = it.avatar_url
members[index].name = it.username
})
const version = versions.find((x) => x.id === data.params.version)
version.author = members.find((x) => x.user_id === version.author_id)
let changelog = ''
if (version.changelog_url) {
changelog = (await axios.get(version.changelog_url)).data
}
let primaryFile = version.files.find((file) => file.primary)
if (!primaryFile) {
@ -178,12 +180,12 @@ export default {
versions,
members,
version,
changelog,
primaryFile,
}
},
data() {
return {
changelog: '',
filesToUpload: [],
}
},
@ -358,6 +360,10 @@ export default {
}
}
.markdown-body {
margin: 1rem 0;
}
.files {
display: flex;
@ -434,6 +440,6 @@ export default {
}
.file-input {
margin-top: 2rem;
margin-top: 1rem;
}
</style>

View File

@ -235,10 +235,7 @@ export default {
const [members, versions, selectableLoaders, selectableVersions] = (
await Promise.all([
axios.get(
`https://api.modrinth.com/api/v1/team/${mod.team}/members`,
config
),
axios.get(`https://api.modrinth.com/api/v1/team/${mod.team}/members`),
axios.get(
`https://api.modrinth.com/api/v1/versions?ids=${JSON.stringify(
mod.versions
@ -250,14 +247,19 @@ export default {
])
).map((it) => it.data)
const users = await Promise.all(
members.map((it) =>
axios.get(`https://api.modrinth.com/api/v1/user/${it.user_id}`, config)
const users = (
await axios.get(
`https://api.modrinth.com/api/v1/users?ids=${JSON.stringify(
members.map((it) => it.user_id)
)}`,
config
)
)
users.forEach(
(it, index) => (members[index].avatar_url = it.data.avatar_url)
)
).data
users.forEach((it, index) => {
members[index].avatar_url = it.avatar_url
members[index].name = it.username
})
return {
mod,