You've already forked AstralRinth
forked from didirus/AstralRinth
Move everything to components, (WIP) Version creation
This commit is contained in:
1
assets/images/utils/upload.svg
Normal file
1
assets/images/utils/upload.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="17 8 12 3 7 8"></polyline><line x1="12" y1="3" x2="12" y2="15"></line></svg>
|
||||||
|
After Width: | Height: | Size: 277 B |
@@ -55,6 +55,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.required:after {
|
||||||
|
content: ' *';
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
.markdown-body {
|
.markdown-body {
|
||||||
p {
|
p {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|||||||
@@ -104,6 +104,8 @@ input {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@import "~assets/styles/layout.scss";
|
@import "~assets/styles/layout.scss";
|
||||||
@import "~assets/styles/utils.scss";
|
@import "~assets/styles/utils.scss";
|
||||||
@import "~assets/styles/components.scss";
|
@import "~assets/styles/components.scss";
|
||||||
|
|||||||
86
components/FileInput.vue
Normal file
86
components/FileInput.vue
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<slot></slot>
|
||||||
|
<input
|
||||||
|
:id="id"
|
||||||
|
class="file-input"
|
||||||
|
type="file"
|
||||||
|
:accept="accept"
|
||||||
|
:multiple="multiple"
|
||||||
|
@change="onChange"
|
||||||
|
/>
|
||||||
|
<label :for="id">{{ text }}</label>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'FileInput',
|
||||||
|
props: {
|
||||||
|
defaultText: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
inputId: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
inputAccept: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
inputMultiple: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
text: this.defaultText,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onChange(files) {
|
||||||
|
const length = files.target.length
|
||||||
|
|
||||||
|
if (length === 0) {
|
||||||
|
this.text = this.defaultText
|
||||||
|
} else if (length === 1) {
|
||||||
|
this.text = '1 file selected'
|
||||||
|
} else if (length > 1) {
|
||||||
|
this.text = length + ' files selected'
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$emit('change', files)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
[type='file'] {
|
||||||
|
border: 0;
|
||||||
|
clip: rect(0, 0, 0, 0);
|
||||||
|
height: 1px;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0;
|
||||||
|
position: absolute !important;
|
||||||
|
white-space: nowrap;
|
||||||
|
width: 1px;
|
||||||
|
|
||||||
|
+ label {
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 5px;
|
||||||
|
color: var(--color-grey-5);
|
||||||
|
background-color: var(--color-grey-1);
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus + label,
|
||||||
|
+ label:hover,
|
||||||
|
&:focus + label {
|
||||||
|
background-color: var(--color-grey-2);
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
:src="
|
:src="
|
||||||
mod.icon_url
|
mod.icon_url
|
||||||
? mod.icon_url
|
? mod.icon_url
|
||||||
: 'https://cdn.modrinth.com/placeholder.png'
|
: 'https://cdn.modrinth.com/placeholder.svg'
|
||||||
"
|
"
|
||||||
alt="mod-icon"
|
alt="mod-icon"
|
||||||
/>
|
/>
|
||||||
@@ -268,6 +268,7 @@ export default {
|
|||||||
|
|
||||||
.team-member {
|
.team-member {
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
|
margin-bottom: 10px;
|
||||||
border: 1px solid var(--color-grey-1);
|
border: 1px solid var(--color-grey-1);
|
||||||
border-radius: var(--size-rounded-sm);
|
border-radius: var(--size-rounded-sm);
|
||||||
|
|
||||||
@@ -297,6 +298,7 @@ export default {
|
|||||||
|
|
||||||
.featured-version {
|
.featured-version {
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
|
margin-bottom: 10px;
|
||||||
border: 1px solid var(--color-grey-1);
|
border: 1px solid var(--color-grey-1);
|
||||||
border-radius: var(--size-rounded-sm);
|
border-radius: var(--size-rounded-sm);
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div class="result rows">
|
<div class="result rows">
|
||||||
<img
|
<img
|
||||||
class="result-icon"
|
class="result-icon"
|
||||||
:src="iconUrl ? iconUrl : 'https://cdn.modrinth.com/placeholder.png'"
|
:src="iconUrl ? iconUrl : 'https://cdn.modrinth.com/placeholder.svg'"
|
||||||
:alt="name"
|
:alt="name"
|
||||||
/>
|
/>
|
||||||
<div class="rows result-name-author">
|
<div class="rows result-name-author">
|
||||||
|
|||||||
50
components/Popup.vue
Normal file
50
components/Popup.vue
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<template>
|
||||||
|
<div v-if="showPopup">
|
||||||
|
<div class="popup-overlay" />
|
||||||
|
<div class="popup-body">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Popup',
|
||||||
|
props: {
|
||||||
|
showPopup: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.popup-overlay {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 1;
|
||||||
|
position: fixed;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: var(--color-grey-3);
|
||||||
|
border: none;
|
||||||
|
opacity: 0.6;
|
||||||
|
overflow-x: hidden;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-body {
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: 2;
|
||||||
|
box-shadow: 0 2px 3px 1px var(--color-grey-2);
|
||||||
|
padding: 5px 60px 60px 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
max-height: 80%;
|
||||||
|
overflow-y: auto;
|
||||||
|
background-color: var(--color-bg);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -31,6 +31,7 @@ export default {
|
|||||||
content: 'Modrinth',
|
content: 'Modrinth',
|
||||||
},
|
},
|
||||||
{ hid: 'theme-color', name: 'theme-color', content: '#4d9227' },
|
{ hid: 'theme-color', name: 'theme-color', content: '#4d9227' },
|
||||||
|
{ hid: 'color-scheme', name: 'color-scheme', content: 'light dark' },
|
||||||
|
|
||||||
{ hid: 'og:site_name', name: 'og:site_name', content: 'Modrinth' },
|
{ hid: 'og:site_name', name: 'og:site_name', content: 'Modrinth' },
|
||||||
{
|
{
|
||||||
@@ -45,6 +46,8 @@ export default {
|
|||||||
name: 'og:image',
|
name: 'og:image',
|
||||||
content: 'https://cdn.modrinth.com/modrinth.png',
|
content: 'https://cdn.modrinth.com/modrinth.png',
|
||||||
},
|
},
|
||||||
|
{ hid: 'twitter:card', name: 'twitter:card', content: 'summary' },
|
||||||
|
{ hid: 'twitter:site', name: 'twitter:site', content: '@modrinth' },
|
||||||
],
|
],
|
||||||
link: [
|
link: [
|
||||||
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
|
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
|
||||||
|
|||||||
@@ -73,6 +73,11 @@ export default {
|
|||||||
name: 'og:site_name',
|
name: 'og:site_name',
|
||||||
content: this.mod.title,
|
content: this.mod.title,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
hid: 'og:url',
|
||||||
|
name: 'og:url',
|
||||||
|
content: `https://modrinth.com/mod/${this.mod.id}`,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
hid: 'og:description',
|
hid: 'og:description',
|
||||||
name: 'og:description',
|
name: 'og:description',
|
||||||
|
|||||||
50
pages/mod/_id/settings.vue
Normal file
50
pages/mod/_id/settings.vue
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<template>
|
||||||
|
<ModPage :mod="mod" :versions="versions" :members="members"></ModPage>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import ModPage from '@/components/ModPage'
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: { ModPage },
|
||||||
|
auth: false,
|
||||||
|
async asyncData(data) {
|
||||||
|
let res = await axios.get(
|
||||||
|
`https://api.modrinth.com/api/v1/mod/${data.params.id}`
|
||||||
|
)
|
||||||
|
const mod = res.data
|
||||||
|
|
||||||
|
res = await axios.get(
|
||||||
|
`https://api.modrinth.com/api/v1/team/${mod.team}/members`
|
||||||
|
)
|
||||||
|
const members = res.data
|
||||||
|
for (let i = 0; i < members.length; i++) {
|
||||||
|
res = await axios.get(
|
||||||
|
`https://api.modrinth.com/api/v1/user/${members[i].user_id}`
|
||||||
|
)
|
||||||
|
members[i].avatar_url = res.data.avatar_url
|
||||||
|
}
|
||||||
|
|
||||||
|
res = await axios.get(mod.body_url)
|
||||||
|
|
||||||
|
const versions = []
|
||||||
|
|
||||||
|
for (const version of mod.versions) {
|
||||||
|
res = await axios.get(
|
||||||
|
`https://api.modrinth.com/api/v1/version/${version}`
|
||||||
|
)
|
||||||
|
|
||||||
|
versions.push(res.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
mod,
|
||||||
|
versions,
|
||||||
|
members,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
@@ -1,7 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<ModPage :mod="mod" :versions="versions" :members="members">
|
<ModPage :mod="mod" :versions="versions" :members="members">
|
||||||
<div class="version">
|
<div class="version">
|
||||||
<h3>{{ version.name }}</h3>
|
<div class="header">
|
||||||
|
<h3>{{ version.name }}</h3>
|
||||||
|
<div class="user-actions">
|
||||||
|
<button class="trash red">
|
||||||
|
<TrashIcon />
|
||||||
|
</button>
|
||||||
|
<button class="upload">
|
||||||
|
<UploadIcon />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="markdown-body" v-html="changelog"></div>
|
<div class="markdown-body" v-html="changelog"></div>
|
||||||
<hr />
|
<hr />
|
||||||
<div class="columns metadata">
|
<div class="columns metadata">
|
||||||
@@ -46,6 +56,8 @@ import xss from 'xss'
|
|||||||
import marked from 'marked'
|
import marked from 'marked'
|
||||||
|
|
||||||
import DownloadIcon from '~/assets/images/utils/download.svg?inline'
|
import DownloadIcon from '~/assets/images/utils/download.svg?inline'
|
||||||
|
import UploadIcon from '~/assets/images/utils/upload.svg?inline'
|
||||||
|
import TrashIcon from '~/assets/images/utils/trash.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'
|
||||||
@@ -56,6 +68,8 @@ export default {
|
|||||||
ForgeIcon,
|
ForgeIcon,
|
||||||
FabricIcon,
|
FabricIcon,
|
||||||
DownloadIcon,
|
DownloadIcon,
|
||||||
|
UploadIcon,
|
||||||
|
TrashIcon,
|
||||||
},
|
},
|
||||||
auth: false,
|
auth: false,
|
||||||
async asyncData(data) {
|
async asyncData(data) {
|
||||||
@@ -121,12 +135,17 @@ export default {
|
|||||||
name: 'og:site_name',
|
name: 'og:site_name',
|
||||||
content: this.mod.title + ' - Modrinth',
|
content: this.mod.title + ' - Modrinth',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
hid: 'og:url',
|
||||||
|
name: 'og:url',
|
||||||
|
content: `https://modrinth.com/mod/${this.mod.id}`,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
hid: 'og:description',
|
hid: 'og:description',
|
||||||
name: 'og:description',
|
name: 'og:description',
|
||||||
content: this.mod.description,
|
content: this.mod.description,
|
||||||
},
|
},
|
||||||
{ hid: 'og:type', name: 'og:type', content: 'article' },
|
{ hid: 'og:type', name: 'og:type', content: 'website' },
|
||||||
{
|
{
|
||||||
hid: 'og:image',
|
hid: 'og:image',
|
||||||
name: 'og:image',
|
name: 'og:image',
|
||||||
@@ -147,6 +166,36 @@ export default {
|
|||||||
box-shadow: 0 2px 3px 1px var(--color-grey-2);
|
box-shadow: 0 2px 3px 1px var(--color-grey-2);
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
|
|
||||||
|
.header {
|
||||||
|
h3 {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.user-actions {
|
||||||
|
float: right;
|
||||||
|
|
||||||
|
button {
|
||||||
|
cursor: pointer;
|
||||||
|
margin-right: 10px;
|
||||||
|
padding: 5px;
|
||||||
|
border: none;
|
||||||
|
border-radius: var(--size-rounded-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.trash {
|
||||||
|
color: #9b2c2c;
|
||||||
|
background-color: var(--color-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload {
|
||||||
|
color: var(--color-text);
|
||||||
|
background-color: var(--color-grey-1);
|
||||||
|
* {
|
||||||
|
margin: auto 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
color: var(--color-grey-1);
|
color: var(--color-grey-1);
|
||||||
|
|||||||
@@ -53,23 +53,159 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<Popup
|
||||||
|
v-if="showPopup"
|
||||||
|
:show-popup="showPopup"
|
||||||
|
class="create-version-popup-body"
|
||||||
|
>
|
||||||
|
<h3>New Version</h3>
|
||||||
|
<div v-if="currentError" class="error">
|
||||||
|
<h4>Error</h4>
|
||||||
|
<p>{{ currentError }}</p>
|
||||||
|
</div>
|
||||||
|
<label
|
||||||
|
for="version-title"
|
||||||
|
class="required"
|
||||||
|
title="The title of your version"
|
||||||
|
>
|
||||||
|
Version Title
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="version-title"
|
||||||
|
v-model="createdVersion.version_title"
|
||||||
|
required
|
||||||
|
type="text"
|
||||||
|
placeholder="Combat Update"
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
for="version-number"
|
||||||
|
class="required"
|
||||||
|
title="The version number of this version. Preferably following semantic versioning"
|
||||||
|
>
|
||||||
|
Version Number
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="version-number"
|
||||||
|
v-model="createdVersion.version_number"
|
||||||
|
required
|
||||||
|
type="text"
|
||||||
|
placeholder="v1.9"
|
||||||
|
/>
|
||||||
|
<label class="required" title="The release channel of this version.">
|
||||||
|
Release Channel
|
||||||
|
</label>
|
||||||
|
<Multiselect
|
||||||
|
v-model="createdVersion.release_channel"
|
||||||
|
class="categories-input"
|
||||||
|
placeholder="Select one"
|
||||||
|
:options="['release', 'beta', 'alpha']"
|
||||||
|
:searchable="false"
|
||||||
|
:close-on-select="true"
|
||||||
|
:show-labels="false"
|
||||||
|
:allow-empty="false"
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
title="The version number of this version. Preferably following semantic versioning"
|
||||||
|
>
|
||||||
|
Loaders
|
||||||
|
</label>
|
||||||
|
<multiselect
|
||||||
|
v-model="createdVersion.loaders"
|
||||||
|
class="categories-input"
|
||||||
|
:options="selectableLoaders"
|
||||||
|
:loading="selectableLoaders.length === 0"
|
||||||
|
:multiple="true"
|
||||||
|
:searchable="false"
|
||||||
|
:show-no-results="false"
|
||||||
|
:close-on-select="true"
|
||||||
|
:clear-on-select="false"
|
||||||
|
:show-labels="false"
|
||||||
|
:limit="6"
|
||||||
|
:hide-selected="true"
|
||||||
|
placeholder="Choose loaders..."
|
||||||
|
/>
|
||||||
|
<label title="The versions of minecraft that this mod version supports">
|
||||||
|
Game Versions
|
||||||
|
</label>
|
||||||
|
<multiselect
|
||||||
|
v-model="createdVersion.game_versions"
|
||||||
|
class="categories-input"
|
||||||
|
:options="selectableVersions"
|
||||||
|
:loading="selectableVersions.length === 0"
|
||||||
|
:multiple="true"
|
||||||
|
:searchable="true"
|
||||||
|
:show-no-results="false"
|
||||||
|
:close-on-select="false"
|
||||||
|
:clear-on-select="false"
|
||||||
|
:show-labels="false"
|
||||||
|
:limit="6"
|
||||||
|
:hide-selected="true"
|
||||||
|
placeholder="Choose versions..."
|
||||||
|
/>
|
||||||
|
<label for="version-body" title="A list of changes for this version">
|
||||||
|
Changelog
|
||||||
|
</label>
|
||||||
|
<textarea
|
||||||
|
id="version-body"
|
||||||
|
v-model="createdVersion.version_body"
|
||||||
|
class="changelog-editor"
|
||||||
|
/>
|
||||||
|
<FileInput
|
||||||
|
input-id="version-files"
|
||||||
|
input-accept="application/java-archive,application/zip"
|
||||||
|
default-text="Upload Files"
|
||||||
|
:input-multiple="true"
|
||||||
|
@change="updateVersionFiles"
|
||||||
|
>
|
||||||
|
<label class="required" title="The files associated with the version">
|
||||||
|
Version Files
|
||||||
|
</label>
|
||||||
|
</FileInput>
|
||||||
|
|
||||||
|
<div class="popup-buttons">
|
||||||
|
<button
|
||||||
|
class="trash-button"
|
||||||
|
@click="
|
||||||
|
showPopup = false
|
||||||
|
createdVersion = {}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<TrashIcon />
|
||||||
|
</button>
|
||||||
|
<button class="default-button" @click="createVersion">
|
||||||
|
Create Version
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</Popup>
|
||||||
|
<button class="default-button" @click="showPopup = !showPopup">
|
||||||
|
New Version
|
||||||
|
</button>
|
||||||
</ModPage>
|
</ModPage>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
|
import Multiselect from 'vue-multiselect'
|
||||||
|
|
||||||
import ModPage from '@/components/ModPage'
|
import ModPage from '@/components/ModPage'
|
||||||
|
|
||||||
|
import Popup from '@/components/Popup'
|
||||||
|
import FileInput from '@/components/FileInput'
|
||||||
|
import TrashIcon from '~/assets/images/utils/trash.svg?inline'
|
||||||
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: {
|
||||||
|
Multiselect,
|
||||||
|
FileInput,
|
||||||
|
Popup,
|
||||||
ModPage,
|
ModPage,
|
||||||
ForgeIcon,
|
ForgeIcon,
|
||||||
FabricIcon,
|
FabricIcon,
|
||||||
DownloadIcon,
|
DownloadIcon,
|
||||||
|
TrashIcon,
|
||||||
},
|
},
|
||||||
auth: false,
|
auth: false,
|
||||||
async asyncData(data) {
|
async asyncData(data) {
|
||||||
@@ -98,12 +234,78 @@ export default {
|
|||||||
versions.push(res.data)
|
versions.push(res.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res = await axios.get(`https://api.modrinth.com/api/v1/tag/loader`)
|
||||||
|
const selectableLoaders = res.data
|
||||||
|
|
||||||
|
res = await axios.get(`https://api.modrinth.com/api/v1/tag/game_version`)
|
||||||
|
const selectableVersions = res.data
|
||||||
|
|
||||||
return {
|
return {
|
||||||
mod,
|
mod,
|
||||||
versions,
|
versions,
|
||||||
members,
|
members,
|
||||||
|
selectableLoaders,
|
||||||
|
selectableVersions,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showPopup: false,
|
||||||
|
currentError: null,
|
||||||
|
createdVersion: {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
updateVersionFiles(e) {
|
||||||
|
this.createdVersion.raw_files = e.target.files
|
||||||
|
|
||||||
|
const newFileParts = []
|
||||||
|
for (let i = 0; i < e.target.files.length; i++) {
|
||||||
|
newFileParts.push(e.target.files[i].name.concat('-' + i))
|
||||||
|
}
|
||||||
|
|
||||||
|
this.createdVersion.file_parts = newFileParts
|
||||||
|
},
|
||||||
|
async createVersion() {
|
||||||
|
this.$nuxt.$loading.start()
|
||||||
|
this.currentError = null
|
||||||
|
|
||||||
|
const formData = new FormData()
|
||||||
|
|
||||||
|
this.createdVersion.mod_id = this.$route.params.id
|
||||||
|
|
||||||
|
formData.append('data', JSON.stringify(this.createdVersion))
|
||||||
|
|
||||||
|
if (this.createdVersion.raw_files) {
|
||||||
|
for (let i = 0; i < this.createdVersion.raw_files.length; i++) {
|
||||||
|
formData.append(
|
||||||
|
this.createdVersion.file_parts[i],
|
||||||
|
new Blob([this.createdVersion.raw_files[i]]),
|
||||||
|
this.createdVersion.raw_files[i].name
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await axios({
|
||||||
|
url: 'https://api.modrinth.com/api/v1/version/version',
|
||||||
|
method: 'POST',
|
||||||
|
data: formData,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data',
|
||||||
|
Authorization: this.$auth.getToken('local'),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
await this.$router.go(null)
|
||||||
|
} catch (err) {
|
||||||
|
this.currentError = err.response.data.description
|
||||||
|
window.scrollTo({ top: 0, behavior: 'smooth' })
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$nuxt.$loading.finish()
|
||||||
|
},
|
||||||
|
},
|
||||||
head() {
|
head() {
|
||||||
return {
|
return {
|
||||||
title: this.mod.title + ' - Modrinth',
|
title: this.mod.title + ' - Modrinth',
|
||||||
@@ -126,6 +328,11 @@ export default {
|
|||||||
name: 'og:site_name',
|
name: 'og:site_name',
|
||||||
content: this.mod.title,
|
content: this.mod.title,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
hid: 'og:url',
|
||||||
|
name: 'og:url',
|
||||||
|
content: `https://modrinth.com/mod/${this.mod.id}`,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
hid: 'og:description',
|
hid: 'og:description',
|
||||||
name: 'og:description',
|
name: 'og:description',
|
||||||
@@ -209,4 +416,71 @@ table {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.multiselect {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: calc(100% - 15px);
|
||||||
|
padding: 0.5rem 5px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.changelog-editor {
|
||||||
|
padding: 20px;
|
||||||
|
width: calc(100% - 40px);
|
||||||
|
height: 200px;
|
||||||
|
resize: none;
|
||||||
|
outline: none;
|
||||||
|
border: none;
|
||||||
|
margin: 10px 0 30px;
|
||||||
|
background-color: var(--color-grey-1);
|
||||||
|
color: var(--color-text);
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-buttons {
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-left: auto;
|
||||||
|
display: flex;
|
||||||
|
justify-content: right;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.default-button {
|
||||||
|
float: none;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trash-button {
|
||||||
|
cursor: pointer;
|
||||||
|
margin-right: 10px;
|
||||||
|
padding: 5px;
|
||||||
|
border: none;
|
||||||
|
border-radius: var(--size-rounded-sm);
|
||||||
|
color: #9b2c2c;
|
||||||
|
background-color: var(--color-bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.default-button {
|
||||||
|
float: right;
|
||||||
|
margin-top: 20px;
|
||||||
|
border-radius: var(--size-rounded-sm);
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
padding: 10px;
|
||||||
|
background-color: var(--color-grey-1);
|
||||||
|
color: var(--color-grey-5);
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
color: var(--color-grey-4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
margin: 20px 0;
|
||||||
|
border-left: #e04e3e 7px solid;
|
||||||
|
padding: 5px 20px 20px 20px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -13,18 +13,17 @@
|
|||||||
:src="
|
:src="
|
||||||
previewImage
|
previewImage
|
||||||
? previewImage
|
? previewImage
|
||||||
: 'https://cdn.modrinth.com/placeholder.png'
|
: 'https://cdn.modrinth.com/placeholder.svg'
|
||||||
"
|
"
|
||||||
alt="preview-image"
|
alt="preview-image"
|
||||||
/>
|
/>
|
||||||
<input
|
<FileInput
|
||||||
id="icon-file"
|
id="icon-file"
|
||||||
class="file-input"
|
|
||||||
type="file"
|
|
||||||
accept="image/x-png,image/gif,image/jpeg"
|
accept="image/x-png,image/gif,image/jpeg"
|
||||||
|
default-text="Upload Icon"
|
||||||
|
:multiple="false"
|
||||||
@change="showPreviewImage"
|
@change="showPreviewImage"
|
||||||
/>
|
/>
|
||||||
<label for="icon-file">Upload Icon</label>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="mod-data">
|
<div class="mod-data">
|
||||||
<label for="name" class="required" title="The name of your mod">
|
<label for="name" class="required" title="The name of your mod">
|
||||||
@@ -100,12 +99,11 @@
|
|||||||
<div v-html="compiledBody"></div>
|
<div v-html="compiledBody"></div>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<button
|
<Popup
|
||||||
v-if="currentVersionIndex > -1"
|
v-if="currentVersionIndex > -1"
|
||||||
class="create-version-popup"
|
:show-popup="currentVersionIndex > -1"
|
||||||
@click="currentVersionIndex = -1"
|
class="create-version-popup-body"
|
||||||
/>
|
>
|
||||||
<div v-if="currentVersionIndex > -1" class="create-version-popup-body">
|
|
||||||
<div class="versions-header">
|
<div class="versions-header">
|
||||||
<h3>New Version</h3>
|
<h3>New Version</h3>
|
||||||
|
|
||||||
@@ -208,20 +206,14 @@
|
|||||||
<label class="required" title="The files associated with the version">
|
<label class="required" title="The files associated with the version">
|
||||||
Version Files
|
Version Files
|
||||||
</label>
|
</label>
|
||||||
<input
|
<FileInput
|
||||||
id="version-files"
|
input-id="version-files"
|
||||||
type="file"
|
input-accept="application/java-archive,application/zip"
|
||||||
accept="application/java-archive,application/zip"
|
:input-multiple="true"
|
||||||
multiple
|
default-text="Upload Files"
|
||||||
@change="updateVersionFiles"
|
@change="updateVersionFiles"
|
||||||
/>
|
/>
|
||||||
<label for="version-files">{{
|
</Popup>
|
||||||
getFilesSelectedText(
|
|
||||||
versions[currentVersionIndex].file_parts.length,
|
|
||||||
'Upload Files'
|
|
||||||
)
|
|
||||||
}}</label>
|
|
||||||
</div>
|
|
||||||
<div class="versions-header">
|
<div class="versions-header">
|
||||||
<h3>Versions</h3>
|
<h3>Versions</h3>
|
||||||
<button title="New Version" class="new-version" @click="createVersion">
|
<button title="New Version" class="new-version" @click="createVersion">
|
||||||
@@ -286,6 +278,8 @@ import Multiselect from 'vue-multiselect'
|
|||||||
import xss from 'xss'
|
import xss from 'xss'
|
||||||
import marked from 'marked'
|
import marked from 'marked'
|
||||||
|
|
||||||
|
import Popup from '@/components/Popup'
|
||||||
|
import FileInput from '@/components/FileInput'
|
||||||
import SaveIcon from '~/assets/images/utils/save.svg?inline'
|
import SaveIcon from '~/assets/images/utils/save.svg?inline'
|
||||||
import TrashIcon from '~/assets/images/utils/trash.svg?inline'
|
import TrashIcon from '~/assets/images/utils/trash.svg?inline'
|
||||||
import EditIcon from '~/assets/images/utils/edit.svg?inline'
|
import EditIcon from '~/assets/images/utils/edit.svg?inline'
|
||||||
@@ -293,6 +287,8 @@ import PlusIcon from '~/assets/images/utils/plus.svg?inline'
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
|
FileInput,
|
||||||
|
Popup,
|
||||||
Multiselect,
|
Multiselect,
|
||||||
TrashIcon,
|
TrashIcon,
|
||||||
EditIcon,
|
EditIcon,
|
||||||
@@ -436,22 +432,6 @@ export default {
|
|||||||
setMarkdownBody() {
|
setMarkdownBody() {
|
||||||
this.compiledBody = xss(marked(this.body))
|
this.compiledBody = xss(marked(this.body))
|
||||||
},
|
},
|
||||||
getFilesSelectedText(length, defaultText) {
|
|
||||||
if (length === 0) {
|
|
||||||
return defaultText
|
|
||||||
} else if (length === 1) {
|
|
||||||
return '1 file selected'
|
|
||||||
} else if (length > 1) {
|
|
||||||
return length + ' files selected'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
head() {
|
|
||||||
return {
|
|
||||||
bodyAttrs: {
|
|
||||||
class: this.currentVersionIndex > -1 ? 'no-scroll' : '',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -483,32 +463,6 @@ input {
|
|||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
[type='file'] {
|
|
||||||
border: 0;
|
|
||||||
clip: rect(0, 0, 0, 0);
|
|
||||||
height: 1px;
|
|
||||||
overflow: hidden;
|
|
||||||
padding: 0;
|
|
||||||
position: absolute !important;
|
|
||||||
white-space: nowrap;
|
|
||||||
width: 1px;
|
|
||||||
|
|
||||||
+ label {
|
|
||||||
cursor: pointer;
|
|
||||||
border-radius: 5px;
|
|
||||||
color: var(--color-grey-5);
|
|
||||||
background-color: var(--color-grey-1);
|
|
||||||
padding: 10px 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus + label,
|
|
||||||
+ label:hover,
|
|
||||||
&:focus + label {
|
|
||||||
background-color: var(--color-grey-2);
|
|
||||||
color: var(--color-text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.initial {
|
.initial {
|
||||||
display: flex;
|
display: flex;
|
||||||
.image-data {
|
.image-data {
|
||||||
@@ -587,38 +541,7 @@ input {
|
|||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.required:after {
|
|
||||||
content: ' *';
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
.create-version-popup {
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
z-index: 1;
|
|
||||||
position: fixed;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background-color: var(--color-grey-3);
|
|
||||||
border: none;
|
|
||||||
opacity: 0.6;
|
|
||||||
overflow-x: hidden;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.create-version-popup-body {
|
.create-version-popup-body {
|
||||||
position: fixed;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
z-index: 2;
|
|
||||||
box-shadow: 0 2px 3px 1px var(--color-grey-2);
|
|
||||||
padding: 5px 60px 60px 20px;
|
|
||||||
border-radius: 10px;
|
|
||||||
max-height: 80%;
|
|
||||||
overflow-y: auto;
|
|
||||||
background-color: var(--color-bg);
|
|
||||||
|
|
||||||
.popup-icons {
|
.popup-icons {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
margin-right: -20px;
|
margin-right: -20px;
|
||||||
@@ -627,7 +550,7 @@ input {
|
|||||||
|
|
||||||
.changelog-editor {
|
.changelog-editor {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
width: 100%;
|
width: calc(100% - 40px);
|
||||||
height: 200px;
|
height: 200px;
|
||||||
resize: none;
|
resize: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
@@ -689,8 +612,4 @@ button {
|
|||||||
.categories-input {
|
.categories-input {
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-scroll {
|
|
||||||
overflow: hidden !important;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user