Move mod pages to nuxt child (#201)

* Move mod pages to nuxt child

* Minor fixes

* Fix lockfile
This commit is contained in:
Geometrically
2021-05-10 21:35:03 -07:00
committed by GitHub
parent d914b38f9f
commit 0e338ef453
10 changed files with 1070 additions and 1415 deletions

899
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -22,7 +22,7 @@
"cookie-universal-nuxt": "^2.1.4", "cookie-universal-nuxt": "^2.1.4",
"highlight.js": "^10.3.2", "highlight.js": "^10.3.2",
"marked": "^2.0.0", "marked": "^2.0.0",
"nuxt": "^2.14.7", "nuxt": "^2.15.5",
"v-tooltip": "^2.0.3", "v-tooltip": "^2.0.3",
"vue-click-outside": "^1.1.0", "vue-click-outside": "^1.1.0",
"vue-highlightjs": "^1.3.3", "vue-highlightjs": "^1.3.3",
@@ -31,7 +31,7 @@
"xss": "^1.0.8" "xss": "^1.0.8"
}, },
"devDependencies": { "devDependencies": {
"@nuxt/types": "^2.14.12", "@nuxt/types": "^2.15.5",
"@nuxtjs/color-mode": "^1.1.1", "@nuxtjs/color-mode": "^1.1.1",
"@nuxtjs/eslint-config": "^3.1.0", "@nuxtjs/eslint-config": "^3.1.0",
"@nuxtjs/eslint-module": "^2.0.0", "@nuxtjs/eslint-module": "^2.0.0",
@@ -43,6 +43,6 @@
"eslint-plugin-prettier": "^3.1.4", "eslint-plugin-prettier": "^3.1.4",
"node-sass": "^4.14.1", "node-sass": "^4.14.1",
"prettier": "^2.1.2", "prettier": "^2.1.2",
"sass-loader": "^9.0.3" "sass-loader": "^10.1.1"
} }
} }

View File

@@ -84,7 +84,7 @@
</nuxt-link> </nuxt-link>
<nuxt-link <nuxt-link
v-if="currentMember" v-if="currentMember"
:to="'/mod/' + mod.id + '/settings'" :to="'/mod/' + (mod.slug ? mod.slug : mod.id) + '/settings'"
class="tab" class="tab"
> >
<span>Settings</span> <span>Settings</span>
@@ -129,7 +129,14 @@
</div> </div>
</div> </div>
<div class="mod-content"> <div class="mod-content">
<slot /> <NuxtChild
:mod="mod"
:versions="versions"
:featured-versions="featuredVersions"
:members="members"
:current-member="currentMember"
:link-bar.sync="linkBar"
/>
</div> </div>
</div> </div>
<section class="mod-info"> <section class="mod-info">
@@ -280,7 +287,14 @@
Alpha Alpha
</span> </span>
<h4 class="title"> <h4 class="title">
<nuxt-link :to="'/mod/' + mod.id + '/version/' + version.id"> <nuxt-link
:to="
'/mod/' +
(mod.slug ? mod.slug : mod.id) +
'/version/' +
version.id
"
>
{{ version.name }} {{ version.name }}
</nuxt-link> </nuxt-link>
</h4> </h4>
@@ -377,49 +391,65 @@ export default {
ReportIcon, ReportIcon,
FollowIcon, FollowIcon,
}, },
props: { async asyncData(data) {
mod: { try {
type: Object, const mod = (
default() { await axios.get(
return {} `https://api.modrinth.com/api/v1/mod/${data.params.id}`,
}, data.$auth.headers
}, )
featuredVersions: { ).data
type: Array,
default() { const [members, versions, featuredVersions, userFollows] = (
return [] await Promise.all([
}, axios.get(`https://api.modrinth.com/api/v1/team/${mod.team}/members`),
}, axios.get(`https://api.modrinth.com/api/v1/mod/${mod.id}/version`),
versions: { axios.get(
type: Array, `https://api.modrinth.com/api/v1/mod/${mod.id}/version?featured=true`
default() { ),
return [] axios.get(
}, data.$auth.user
}, ? `https://api.modrinth.com/api/v1/user/${data.$auth.user.id}/follows`
members: { : `https://api.modrinth.com`,
type: Array, data.$auth.headers
default() { ),
return [] ])
}, ).map((it) => it.data)
},
currentMember: { const users = (
type: Object, await axios.get(
default() { `https://api.modrinth.com/api/v1/users?ids=${JSON.stringify(
return null members.map((it) => it.user_id)
}, )}`,
}, data.$auth.headers
linkBar: { )
type: Array, ).data
default() {
return [] users.forEach((it) => {
}, const index = members.findIndex((x) => x.user_id === it.id)
}, members[index].avatar_url = it.avatar_url
userFollows: { members[index].name = it.username
type: Array, })
default() {
return null const currentMember = data.$auth.user
}, ? members.find((x) => x.user_id === data.$auth.user.id)
}, : null
return {
mod,
versions,
featuredVersions,
members,
currentMember,
userFollows: userFollows.name ? null : userFollows,
linkBar: [],
}
} catch {
data.error({
statusCode: 404,
message: 'Mod not found',
})
}
}, },
methods: { methods: {
formatNumber(x) { formatNumber(x) {
@@ -466,6 +496,52 @@ export default {
this.userFollows.splice(this.userFollows.indexOf(this.mod.id), 1) this.userFollows.splice(this.userFollows.indexOf(this.mod.id), 1)
}, },
}, },
head() {
return {
title: this.mod.title + ' - Modrinth',
meta: [
{
hid: 'og:type',
name: 'og:type',
content: 'website',
},
{
hid: 'og:title',
name: 'og:title',
content: this.mod.title,
},
{
hid: 'apple-mobile-web-app-title',
name: 'apple-mobile-web-app-title',
content: this.mod.title,
},
{
hid: 'og:description',
name: 'og:description',
content: this.mod.description,
},
{
hid: 'description',
name: 'description',
content:
this.mod.description +
' View other minecraft mods on Modrinth today! Modrinth is a new and modern Minecraft modding platform supporting both the Forge and Fabric mod loaders.',
},
{
hid: 'og:url',
name: 'og:url',
content: `https://modrinth.com/mod/${this.mod.id}`,
},
{
hid: 'og:image',
name: 'og:image',
content: this.mod.icon_url
? this.mod.icon_url
: 'https://cdn.modrinth.com/placeholder.png',
},
],
}
},
} }
</script> </script>

View File

@@ -1,5 +1,4 @@
<template> <template>
<div class="page-container">
<div class="page-contents"> <div class="page-contents">
<header class="columns"> <header class="columns">
<h3 class="column-grow-1">Edit Mod</h3> <h3 class="column-grow-1">Edit Mod</h3>
@@ -31,8 +30,7 @@
<h3>Name</h3> <h3>Name</h3>
<label> <label>
<span> <span>
Be creative. TechCraft v7 won't be searchable and won't be clicked Be creative. TechCraft v7 won't be searchable and won't be clicked on
on
</span> </span>
<input v-model="mod.title" type="text" placeholder="Enter the name" /> <input v-model="mod.title" type="text" placeholder="Enter the name" />
</label> </label>
@@ -124,8 +122,8 @@
<h3>Supported environments</h3> <h3>Supported environments</h3>
<div class="columns"> <div class="columns">
<span> <span>
Let others know if your mod is for clients, servers or universal. Let others know if your mod is for clients, servers or universal. For
For example, IC2 will be required + required, while OptiFine will be example, IC2 will be required + required, while OptiFine will be
required + no functionality required + no functionality
</span> </span>
<div class="labeled-control"> <div class="labeled-control">
@@ -164,8 +162,8 @@
</label> </label>
</h3> </h3>
<span> <span>
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
editor supports markdown. You can find the syntax supports markdown. You can find the syntax
<a <a
href="https://guides.github.com/features/mastering-markdown/" href="https://guides.github.com/features/mastering-markdown/"
target="_blank" target="_blank"
@@ -228,8 +226,8 @@
<label> <label>
<span> <span>
It is really important to choose a proper license for your mod. You It is really important to choose a proper license for your mod. You
may choose one from our list or provide a URL to your own license. may choose one from our list or provide a URL to your own license. URL
URL field will be filled automatically for provided licenses field will be filled automatically for provided licenses
</span> </span>
<div class="input-group"> <div class="input-group">
<Multiselect <Multiselect
@@ -295,8 +293,6 @@
<hr /> <hr />
</div> </div>
</section> </section>
<m-footer class="footer" centered />
</div>
</div> </div>
</template> </template>
@@ -305,11 +301,9 @@ import axios from 'axios'
import Multiselect from 'vue-multiselect' import Multiselect from 'vue-multiselect'
import FileInput from '~/components/ui/FileInput' import FileInput from '~/components/ui/FileInput'
import MFooter from '~/components/layout/MFooter'
export default { export default {
components: { components: {
MFooter,
FileInput, FileInput,
Multiselect, Multiselect,
}, },
@@ -411,6 +405,9 @@ export default {
} }
}, },
}, },
created() {
this.$emit('update:link-bar', [['Edit', 'edit']])
},
methods: { methods: {
async saveModReview() { async saveModReview() {
this.isProcessing = true this.isProcessing = true
@@ -464,7 +461,9 @@ export default {
) )
} }
await this.$router.replace(`/mod/${this.mod.id}`) await this.$router.replace(
`/mod/${this.mod.slug ? this.mod.slug : this.mod.id}`
)
} catch (err) { } catch (err) {
this.$notify({ this.$notify({
group: 'main', group: 'main',
@@ -545,12 +544,14 @@ label {
grid-template: grid-template:
'header header header' auto 'header header header' auto
'advert advert advert' auto 'advert advert advert' auto
'essentials essentials mod-icon' auto 'essentials essentials essentials' auto
'mod-icon mod-icon mod-icon' auto
'game-sides game-sides game-sides' auto 'game-sides game-sides game-sides' auto
'description description description' auto 'description description description' auto
'versions versions versions' auto 'versions versions versions' auto
'extra-links license license' auto 'extra-links extra-links extra-links' auto
'donations donations .' auto 'license license license' auto
'donations donations donations' auto
'footer footer footer' auto 'footer footer footer' auto
/ 4fr 1fr 4fr; / 4fr 1fr 4fr;
column-gap: var(--spacing-card-md); column-gap: var(--spacing-card-md);

View File

@@ -1,136 +1,20 @@
<template> <template>
<ModPage <div v-compiled-markdown="mod.body" v-highlightjs class="markdown-body"></div>
:mod="mod"
:versions="versions"
:featured-versions="featuredVersions"
:members="members"
:current-member="currentMember"
:link-bar="[['Description', '']]"
:user-follows="userFollows"
>
<div
v-compiled-markdown="mod.body"
v-highlightjs
class="markdown-body"
></div>
</ModPage>
</template> </template>
<script> <script>
import axios from 'axios'
import ModPage from '~/components/layout/ModPage'
export default { export default {
components: { ModPage },
auth: false, auth: false,
async asyncData(data) { props: {
try { mod: {
const mod = ( type: Object,
await axios.get( default() {
`https://api.modrinth.com/api/v1/mod/${data.params.id}`, return {}
data.$auth.headers
)
).data
if (mod.body_url && !mod.body) {
mod.body = (await axios.get(mod.body_url)).data
}
const [members, versions, featuredVersions, userFollows] = (
await Promise.all([
axios.get(`https://api.modrinth.com/api/v1/team/${mod.team}/members`),
axios.get(`https://api.modrinth.com/api/v1/mod/${mod.id}/version`),
axios.get(
`https://api.modrinth.com/api/v1/mod/${mod.id}/version?featured=true`
),
axios.get(
data.$auth.user
? `https://api.modrinth.com/api/v1/user/${data.$auth.user.id}/follows`
: `https://api.modrinth.com`,
data.$auth.headers
),
])
).map((it) => it.data)
const users = (
await axios.get(
`https://api.modrinth.com/api/v1/users?ids=${JSON.stringify(
members.map((it) => it.user_id)
)}`,
data.$auth.headers
)
).data
users.forEach((it) => {
const index = members.findIndex((x) => x.user_id === it.id)
members[index].avatar_url = it.avatar_url
members[index].name = it.username
})
const currentMember = data.$auth.user
? members.find((x) => x.user_id === data.$auth.user.id)
: null
return {
mod,
versions,
featuredVersions,
members,
currentMember,
userFollows: userFollows.name ? null : userFollows,
}
} catch {
data.error({
statusCode: 404,
message: 'Mod not found',
})
}
}, },
head() {
return {
title: this.mod.title + ' - Modrinth',
meta: [
{
hid: 'og:type',
name: 'og:type',
content: 'website',
}, },
{
hid: 'og:title',
name: 'og:title',
content: this.mod.title,
}, },
{ created() {
hid: 'apple-mobile-web-app-title', this.$emit('update:link-bar', [['Description', '']])
name: 'apple-mobile-web-app-title',
content: this.mod.title,
},
{
hid: 'og:description',
name: 'og:description',
content: this.mod.description,
},
{
hid: 'description',
name: 'description',
content:
this.mod.description +
' View other 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/mod/${this.mod.id}`,
},
{
hid: 'og:image',
name: 'og:image',
content: this.mod.icon_url
? this.mod.icon_url
: 'https://cdn.modrinth.com/placeholder.png',
},
],
}
}, },
} }
</script> </script>

View File

@@ -1,13 +1,5 @@
<template> <template>
<ModPage <div>
:mod="mod"
:versions="versions"
:featured-versions="featuredVersions"
:members="members"
:current-member="currentMember"
:link-bar="[['New Version', 'newversion']]"
:user-follows="userFollows"
>
<div class="new-version"> <div class="new-version">
<div class="controls"> <div class="controls">
<button <button
@@ -124,88 +116,44 @@
</div> </div>
</div> </div>
</div> </div>
</ModPage> </div>
</template> </template>
<script> <script>
import axios from 'axios' import axios from 'axios'
import Multiselect from 'vue-multiselect' import Multiselect from 'vue-multiselect'
import ModPage from '~/components/layout/ModPage'
import FileInput from '~/components/ui/FileInput' import FileInput from '~/components/ui/FileInput'
export default { export default {
components: { components: {
ModPage,
Multiselect, Multiselect,
FileInput, FileInput,
}, },
props: {
mod: {
type: Object,
default() {
return {}
},
},
},
async asyncData(data) { async asyncData(data) {
try { try {
const mod = ( const [selectableLoaders, selectableVersions] = (
await axios.get(
`https://api.modrinth.com/api/v1/mod/${data.params.id}`,
data.$auth.headers
)
).data
const [
members,
versions,
featuredVersions,
selectableLoaders,
selectableVersions,
userFollows,
] = (
await Promise.all([ await Promise.all([
axios.get(`https://api.modrinth.com/api/v1/team/${mod.team}/members`),
axios.get(`https://api.modrinth.com/api/v1/mod/${mod.id}/version`),
axios.get(
`https://api.modrinth.com/api/v1/mod/${mod.id}/version?featured=true`
),
axios.get(`https://api.modrinth.com/api/v1/tag/loader`), axios.get(`https://api.modrinth.com/api/v1/tag/loader`),
axios.get(`https://api.modrinth.com/api/v1/tag/game_version`), axios.get(`https://api.modrinth.com/api/v1/tag/game_version`),
axios.get(
data.$auth.user
? `https://api.modrinth.com/api/v1/user/${data.$auth.user.id}/follows`
: `https://api.modrinth.com`,
data.$auth.headers
),
]) ])
).map((it) => it.data) ).map((it) => it.data)
const users = (
await axios.get(
`https://api.modrinth.com/api/v1/users?ids=${JSON.stringify(
members.map((it) => it.user_id)
)}`,
data.$auth.headers
)
).data
users.forEach((it) => {
const index = members.findIndex((x) => x.user_id === it.id)
members[index].avatar_url = it.avatar_url
members[index].name = it.username
})
const currentMember = data.$auth.user
? members.find((x) => x.user_id === data.$auth.user.id)
: null
return { return {
mod,
versions,
featuredVersions,
members,
selectableLoaders, selectableLoaders,
selectableVersions, selectableVersions,
currentMember,
userFollows: userFollows.name ? null : userFollows,
} }
} catch { } catch {
data.error({ data.error({
statusCode: 404, statusCode: 404,
message: 'Mod not found', message: 'Unable to fetch versions and loaders',
}) })
} }
}, },
@@ -214,6 +162,9 @@ export default {
createdVersion: {}, createdVersion: {},
} }
}, },
created() {
this.$emit('update:link-bar', [['New Version', 'newversion']])
},
methods: { methods: {
async createVersion() { async createVersion() {
this.$nuxt.$loading.start() this.$nuxt.$loading.start()
@@ -247,7 +198,11 @@ export default {
}, },
}) })
).data ).data
await this.$router.push(`/mod/${data.mod_id}/version/${data.id}`) await this.$router.push(
`/mod/${this.mod.slug ? this.mod.slug : data.mod_id}/version/${
data.id
}`
)
} catch (err) { } catch (err) {
this.$notify({ this.$notify({
group: 'main', group: 'main',

View File

@@ -1,13 +1,5 @@
<template> <template>
<ModPage <div>
:mod="mod"
:versions="versions"
:members="members.filter((it) => it.accepted)"
:current-member="currentMember"
:featured-versions="featuredVersions"
:link-bar="[['Settings', 'settings']]"
:user-follows="userFollows"
>
<ConfirmPopup <ConfirmPopup
ref="delete_popup" ref="delete_popup"
title="Are you sure you want to delete this mod?" title="Are you sure you want to delete this mod?"
@@ -244,82 +236,37 @@
</div> </div>
</div> </div>
</div> </div>
</ModPage> </div>
</template> </template>
<script> <script>
import axios from 'axios' import axios from 'axios'
import ModPage from '~/components/layout/ModPage'
import ConfirmPopup from '~/components/ui/ConfirmPopup' import ConfirmPopup from '~/components/ui/ConfirmPopup'
import DropdownIcon from '~/assets/images/utils/dropdown.svg?inline' import DropdownIcon from '~/assets/images/utils/dropdown.svg?inline'
export default { export default {
components: { ModPage, DropdownIcon, ConfirmPopup }, components: { DropdownIcon, ConfirmPopup },
async asyncData(data) { props: {
try { mod: {
const mod = ( type: Object,
await axios.get( default() {
`https://api.modrinth.com/api/v1/mod/${data.params.id}`, return {}
data.$auth.headers },
) },
).data members: {
type: Array,
const [members, versions, featuredVersions, userFollows] = ( default() {
await Promise.all([ return []
axios.get( },
`https://api.modrinth.com/api/v1/team/${mod.team}/members`, },
data.$auth.headers currentMember: {
), type: Object,
axios.get(`https://api.modrinth.com/api/v1/mod/${mod.id}/version`), default() {
axios.get( return null
`https://api.modrinth.com/api/v1/mod/${mod.id}/version?featured=true` },
), },
axios.get(
data.$auth.user
? `https://api.modrinth.com/api/v1/user/${data.$auth.user.id}/follows`
: `https://api.modrinth.com`,
data.$auth.headers
),
])
).map((it) => it.data)
const [users] = (
await Promise.all([
axios.get(
`https://api.modrinth.com/api/v1/users?ids=${JSON.stringify(
members.map((it) => it.user_id)
)}`,
data.$auth.headers
),
])
).map((it) => it.data)
users.forEach((it) => {
const index = members.findIndex((x) => x.user_id === it.id)
members[index].avatar_url = it.avatar_url
members[index].name = it.username
})
const currentMember = data.$auth.user
? members.find((x) => x.user_id === data.$auth.user.id)
: null
return {
mod,
versions,
featuredVersions,
members,
currentMember,
userFollows: userFollows.name ? null : userFollows,
}
} catch {
data.error({
statusCode: 404,
message: 'Mod not found',
})
}
}, },
data() { data() {
return { return {
@@ -328,6 +275,8 @@ export default {
} }
}, },
created() { created() {
this.$emit('update:link-bar', [['Settings', 'settings']])
this.UPLOAD_VERSION = 1 << 0 this.UPLOAD_VERSION = 1 << 0
this.DELETE_VERSION = 1 << 1 this.DELETE_VERSION = 1 << 1
this.EDIT_DETAILS = 1 << 2 this.EDIT_DETAILS = 1 << 2

View File

@@ -1,17 +1,5 @@
<template> <template>
<ModPage <div>
:mod="mod"
:versions="versions"
:featured-versions="featuredVersions"
:members="members"
:current-member="currentMember"
:link-bar="[
['Versions', 'versions'],
[version.name, 'versions/' + version.id],
['Edit Version', 'versions/' + version.id + '/edit'],
]"
:user-follows="userFollows"
>
<div class="new-version"> <div class="new-version">
<div class="controls"> <div class="controls">
<button class="brand-button" title="Save version" @click="saveVersion"> <button class="brand-button" title="Save version" @click="saveVersion">
@@ -111,106 +99,87 @@
</div> </div>
</div> </div>
</div> </div>
</ModPage> </div>
</template> </template>
<script> <script>
import axios from 'axios' import axios from 'axios'
import Multiselect from 'vue-multiselect' import Multiselect from 'vue-multiselect'
import ModPage from '~/components/layout/ModPage'
export default { export default {
components: { components: {
ModPage,
Multiselect, Multiselect,
}, },
auth: false, auth: false,
props: {
mod: {
type: Object,
default() {
return {}
},
},
versions: {
type: Array,
default() {
return []
},
},
members: {
type: Array,
default() {
return [{}]
},
},
currentMember: {
type: Object,
default() {
return null
},
},
},
async fetch() {
this.version = this.versions.find(
(x) => x.id === this.$route.params.version
)
if (!this.version.changelog && this.version.changelog_url) {
this.version.changelog = (
await axios.get(this.version.changelog_url)
).data
}
},
async asyncData(data) { async asyncData(data) {
try { try {
const mod = ( const [selectableLoaders, selectableVersions] = (
await axios.get(
`https://api.modrinth.com/api/v1/mod/${data.params.id}`,
data.$auth.headers
)
).data
const [
members,
versions,
featuredVersions,
selectableLoaders,
selectableVersions,
userFollows,
] = (
await Promise.all([ await Promise.all([
axios.get(`https://api.modrinth.com/api/v1/team/${mod.team}/members`),
axios.get(`https://api.modrinth.com/api/v1/mod/${mod.id}/version`),
axios.get(
`https://api.modrinth.com/api/v1/mod/${mod.id}/version?featured=true`
),
axios.get(`https://api.modrinth.com/api/v1/tag/loader`), axios.get(`https://api.modrinth.com/api/v1/tag/loader`),
axios.get(`https://api.modrinth.com/api/v1/tag/game_version`), axios.get(`https://api.modrinth.com/api/v1/tag/game_version`),
axios.get(
data.$auth.user
? `https://api.modrinth.com/api/v1/user/${data.$auth.user.id}/follows`
: `https://api.modrinth.com`,
data.$auth.headers
),
]) ])
).map((it) => it.data) ).map((it) => it.data)
const users = (
await axios.get(
`https://api.modrinth.com/api/v1/users?ids=${JSON.stringify(
members.map((it) => it.user_id)
)}`,
data.$auth.headers
)
).data
users.forEach((it) => {
const index = members.findIndex((x) => x.user_id === it.id)
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 primaryFile = version.files.find((file) => file.primary)
if (!primaryFile) {
primaryFile = version.files[0]
}
const currentMember = data.$auth.user
? members.find((x) => x.user_id === data.$auth.user.id)
: null
if (!version.changelog && version.changelog_url) {
version.changelog = (await axios.get(version.changelog_url)).data
}
return { return {
mod,
versions,
featuredVersions,
members,
version,
primaryFile,
currentMember,
selectableLoaders, selectableLoaders,
selectableVersions, selectableVersions,
userFollows: userFollows.name ? null : userFollows,
} }
} catch { } catch {
data.error({ data.error({
statusCode: 404, statusCode: 404,
message: 'Version not found', message: 'Unable to fetch versions or loaders',
}) })
} }
}, },
data() {
return {
version: {},
}
},
mounted() {
this.$emit('update:link-bar', [
['Versions', 'versions'],
[this.version.name, 'versions/' + this.version.id],
['Edit Version', 'versions/' + this.version.id + '/edit'],
])
},
methods: { methods: {
async saveVersion() { async saveVersion() {
this.$nuxt.$loading.start() this.$nuxt.$loading.start()
@@ -222,7 +191,9 @@ export default {
this.$auth.headers this.$auth.headers
) )
await this.$router.replace( await this.$router.replace(
`/mod/${this.mod.id}/version/${this.version.id}` `/mod/${this.mod.slug ? this.mod.slug : this.mod.id}/version/${
this.version.id
}`
) )
} catch (err) { } catch (err) {
this.$notify({ this.$notify({

View File

@@ -1,16 +1,5 @@
<template> <template>
<ModPage <div>
:mod="mod"
:versions="versions"
:members="members"
:current-member="currentMember"
:featured-versions="featuredVersions"
:link-bar="[
['Versions', 'versions'],
[version.name, 'versions/' + version.id],
]"
:user-follows="userFollows"
>
<ConfirmPopup <ConfirmPopup
ref="delete_file_popup" ref="delete_file_popup"
title="Are you sure you want to delete this file?" title="Are you sure you want to delete this file?"
@@ -73,7 +62,7 @@
:href="primaryFile.url" :href="primaryFile.url"
class="action iconified-button" class="action iconified-button"
@click.prevent=" @click.prevent="
downloadFile(primaryFile.hashes.sha1, primaryFile.url) $parent.downloadFile(primaryFile.hashes.sha1, primaryFile.url)
" "
> >
<DownloadIcon /> <DownloadIcon />
@@ -110,7 +99,9 @@
<div class="info"> <div class="info">
<h4>Available For</h4> <h4>Available For</h4>
<p class="value"> <p class="value">
{{ version.game_versions.join(', ') }} {{
version.game_versions ? version.game_versions.join(', ') : ''
}}
</p> </p>
</div> </div>
</div> </div>
@@ -142,12 +133,11 @@
</div> </div>
<FileInput v-if="currentMember" class="file-input" @change="addFiles" /> <FileInput v-if="currentMember" class="file-input" @change="addFiles" />
</div> </div>
</ModPage> </div>
</template> </template>
<script> <script>
import axios from 'axios' import axios from 'axios'
import ModPage from '~/components/layout/ModPage'
import ConfirmPopup from '~/components/ui/ConfirmPopup' import ConfirmPopup from '~/components/ui/ConfirmPopup'
import Categories from '~/components/ui/search/Categories' import Categories from '~/components/ui/search/Categories'
@@ -163,7 +153,6 @@ export default {
components: { components: {
FileInput, FileInput,
Categories, Categories,
ModPage,
DownloadIcon, DownloadIcon,
CalendarIcon, CalendarIcon,
TagIcon, TagIcon,
@@ -173,98 +162,66 @@ export default {
ConfirmPopup, ConfirmPopup,
}, },
auth: false, auth: false,
async asyncData(data) { props: {
try { mod: {
const mod = ( type: Object,
await axios.get( default() {
`https://api.modrinth.com/api/v1/mod/${data.params.id}`, return {}
data.$auth.headers },
},
versions: {
type: Array,
default() {
return []
},
},
members: {
type: Array,
default() {
return [{}]
},
},
currentMember: {
type: Object,
default() {
return null
},
},
},
async fetch() {
this.version = this.versions.find(
(x) => x.id === this.$route.params.version
) )
this.primaryFile = this.version.files.find((file) => file.primary)
if (!this.primaryFile) {
this.primaryFile = this.version.files[0]
}
if (!this.version.changelog && this.version.changelog_url) {
this.version.changelog = (
await axios.get(this.version.changelog_url)
).data ).data
const [members, versions, featuredVersions, userFollows] = (
await Promise.all([
axios.get(`https://api.modrinth.com/api/v1/team/${mod.team}/members`),
axios.get(`https://api.modrinth.com/api/v1/mod/${mod.id}/version`),
axios.get(
`https://api.modrinth.com/api/v1/mod/${mod.id}/version?featured=true`
),
axios.get(
data.$auth.user
? `https://api.modrinth.com/api/v1/user/${data.$auth.user.id}/follows`
: `https://api.modrinth.com`,
data.$auth.headers
),
])
).map((it) => it.data)
const users = (
await axios.get(
`https://api.modrinth.com/api/v1/users?ids=${JSON.stringify(
members.map((it) => it.user_id)
)}`,
data.$auth.headers
)
).data
users.forEach((it) => {
const index = members.findIndex((x) => x.user_id === it.id)
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 primaryFile = version.files.find((file) => file.primary)
if (!primaryFile) {
primaryFile = version.files[0]
} }
const currentMember = data.$auth.user console.log(this.version)
? members.find((x) => x.user_id === data.$auth.user.id)
: null
if (!version.changelog && version.changelog_url) {
version.changelog = (await axios.get(version.changelog_url)).data
}
return {
mod,
versions,
featuredVersions,
members,
version,
primaryFile,
currentMember,
userFollows: userFollows.name ? null : userFollows,
}
} catch {
data.error({
statusCode: 404,
message: 'Version not found',
})
}
}, },
data() { data() {
return { return {
primaryFile: {},
version: {},
filesToUpload: [], filesToUpload: [],
popup_data: null, popup_data: null,
} }
}, },
methods: { mounted() {
async downloadFile(hash, url) { this.$emit('update:link-bar', [
await axios.get( ['Versions', 'versions'],
`https://api.modrinth.com/api/v1/version_file/${hash}/download` [this.version.name, 'versions/' + this.version.id],
) ])
const elem = document.createElement('a')
elem.download = hash
elem.href = url
elem.click()
}, },
methods: {
deleteFilePopup(hash) { deleteFilePopup(hash) {
this.popup_data = hash this.popup_data = hash
this.$refs.delete_file_popup.show() this.$refs.delete_file_popup.show()
@@ -354,49 +311,6 @@ export default {
this.$nuxt.$loading.finish() this.$nuxt.$loading.finish()
}, },
}, },
head() {
return {
title: this.mod.title + ' - Modrinth - Files',
meta: [
{
hid: 'description',
name: 'description',
content:
this.mod.description +
' View other minecraft mods on Modrinth today! Modrinth is a new and modern Minecraft modding platform that is compatible with CurseForge too!',
},
{
hid: 'apple-mobile-web-app-title',
name: 'apple-mobile-web-app-title',
content: this.mod.title,
},
{
hid: 'og:title',
name: 'og:title',
content: this.mod.title,
},
{
hid: 'og:url',
name: 'og:url',
content: `https://modrinth.com/mod/${this.mod.id}`,
},
{
hid: 'og:description',
name: 'og:description',
content: this.mod.description,
},
{ hid: 'og:type', name: 'og:type', content: 'website' },
{
hid: 'og:image',
name: 'og:image',
content: this.mod.icon_url
? this.mod.icon_url
: 'https://cdn.modrinth.com/placeholder.png',
},
],
}
},
} }
</script> </script>

View File

@@ -1,13 +1,5 @@
<template> <template>
<ModPage <div>
:mod="mod"
:versions="versions"
:featured-versions="featuredVersions"
:members="members"
:current-member="currentMember"
:link-bar="[['Versions', 'versions']]"
:user-follows="userFollows"
>
<table> <table>
<thead> <thead>
<tr> <tr>
@@ -25,12 +17,12 @@
<tr v-for="version in versions" :key="version.id"> <tr v-for="version in versions" :key="version.id">
<td> <td>
<a <a
:href="findPrimary(version).url" :href="$parent.findPrimary(version).url"
class="download" class="download"
@click.prevent=" @click.prevent="
downloadFile( $parent.downloadFile(
findPrimary(version).hashes.sha1, $parent.findPrimary(version).hashes.sha1,
findPrimary(version).url $parent.findPrimary(version).url
) )
" "
> >
@@ -87,150 +79,42 @@
New Version New Version
</nuxt-link> </nuxt-link>
</div> </div>
</ModPage> </div>
</template> </template>
<script> <script>
import axios from 'axios'
import ModPage from '~/components/layout/ModPage'
import DownloadIcon from '~/assets/images/utils/download.svg?inline' import DownloadIcon from '~/assets/images/utils/download.svg?inline'
import ForgeIcon from '~/assets/images/categories/forge.svg?inline' import ForgeIcon from '~/assets/images/categories/forge.svg?inline'
import FabricIcon from '~/assets/images/categories/fabric.svg?inline' import FabricIcon from '~/assets/images/categories/fabric.svg?inline'
export default { export default {
components: { components: {
ModPage,
ForgeIcon, ForgeIcon,
FabricIcon, FabricIcon,
DownloadIcon, DownloadIcon,
}, },
auth: false, auth: false,
async asyncData(data) { props: {
try { mod: {
const mod = ( type: Object,
await axios.get( default() {
`https://api.modrinth.com/api/v1/mod/${data.params.id}`, return {}
data.$auth.headers
)
).data
const [members, versions, featuredVersions, userFollows] = (
await Promise.all([
axios.get(`https://api.modrinth.com/api/v1/team/${mod.team}/members`),
axios.get(`https://api.modrinth.com/api/v1/mod/${mod.id}/version`),
axios.get(
`https://api.modrinth.com/api/v1/mod/${mod.id}/version?featured=true`
),
axios.get(
data.$auth.user
? `https://api.modrinth.com/api/v1/user/${data.$auth.user.id}/follows`
: `https://api.modrinth.com`,
data.$auth.headers
),
])
).map((it) => it.data)
const users = (
await axios.get(
`https://api.modrinth.com/api/v1/users?ids=${JSON.stringify(
members.map((it) => it.user_id)
)}`,
data.$auth.headers
)
).data
users.forEach((it) => {
const index = members.findIndex((x) => x.user_id === it.id)
members[index].avatar_url = it.avatar_url
members[index].name = it.username
})
const currentMember = data.$auth.user
? members.find((x) => x.user_id === data.$auth.user.id)
: null
return {
mod,
versions,
featuredVersions,
members,
currentMember,
userFollows: userFollows.name ? null : userFollows,
}
} catch {
data.error({
statusCode: 404,
message: 'Mod not found',
})
}
},
methods: {
findPrimary(version) {
let file = version.files.find((x) => x.primary)
if (!file) {
file = version.files[0]
}
if (!file) {
file = { url: `/mod/${this.mod.id}/version/${version.id}` }
}
return file
},
async downloadFile(hash, url) {
await axios.get(
`https://api.modrinth.com/api/v1/version_file/${hash}/download`
)
const elem = document.createElement('a')
elem.download = hash
elem.href = url
elem.click()
}, },
}, },
head() { versions: {
return { type: Array,
title: this.mod.title + ' - Modrinth', default() {
meta: [ return []
{
hid: 'description',
name: 'description',
content:
this.mod.description +
' View other minecraft mods on Modrinth today! Modrinth is a new and modern Minecraft modding platform that is compatible with CurseForge too!',
}, },
{
hid: 'apple-mobile-web-app-title',
name: 'apple-mobile-web-app-title',
content: this.mod.title,
}, },
{ currentMember: {
hid: 'og:title', type: Object,
name: 'og:title', default() {
content: this.mod.title, return null
}, },
{
hid: 'og:url',
name: 'og:url',
content: `https://modrinth.com/mod/${this.mod.id}`,
}, },
{
hid: 'og:description',
name: 'og:description',
content: this.mod.description,
}, },
{ hid: 'og:type', name: 'og:type', content: 'website' }, created() {
{ this.$emit('update:link-bar', [['Versions', 'versions']])
hid: 'og:image',
name: 'og:image',
content: this.mod.icon_url
? this.mod.icon_url
: 'https://cdn.modrinth.com/placeholder.png',
},
],
}
}, },
} }
</script> </script>