Nuxt Season Finale (#531)

Co-authored-by: Emma Cypress Pointer-Null <emmaffle@modrinth.com>
This commit is contained in:
Prospector
2022-06-18 18:39:53 -07:00
committed by GitHub
parent 2bda7566b4
commit 405a3eda60
26 changed files with 1690 additions and 952 deletions

View File

@@ -139,8 +139,11 @@
</div>
<div
v-if="
currentMember &&
(project.status === 'processing' ||
(currentMember ||
($auth.user &&
($auth.user.role === 'moderator' ||
$auth.user.role === 'admin'))) &&
(project.status !== 'approved' ||
(project.moderator_message &&
(project.moderator_message.message ||
project.moderator_message.body)))
@@ -193,22 +196,44 @@
</div>
<div class="buttons">
<button
v-if="
project.status !== 'processing' && project.status !== 'approved'
"
class="iconified-button"
v-if="project.status === 'rejected'"
class="iconified-button brand-button-colors"
@click="submitForReview"
>
Resubmit for approval
<CheckIcon />
Resubmit for review
</button>
<button
v-if="project.status === 'draft'"
class="iconified-button brand-button-colors"
@click="submitForReview"
>
<CheckIcon />
Submit for review
</button>
<button
v-if="project.status === 'approved'"
class="iconified-button"
@click="clearMessage"
>
<ClearIcon />
Clear message
</button>
</div>
<div v-if="showKnownErrors" class="known-errors">
<ul>
<li v-if="project.body === ''">
Your project must have a body to submit for review.
</li>
<li v-if="project.versions.length < 1">
Your project must have at least one version to submit for review.
</li>
</ul>
</div>
<p v-if="project.status === 'rejected'">
Do not resubmit for review until you've addressed the moderator
message!
</p>
</div>
<div class="extra-info card">
<template
@@ -344,6 +369,12 @@
class="featured-version"
>
<a
v-tooltip="
findPrimary(version).filename +
' (' +
$formatBytes(findPrimary(version).size) +
')'
"
:href="findPrimary(version).url"
class="download"
:title="`Download ${version.name}`"
@@ -365,7 +396,11 @@
>
{{
version.loaders
.map((x) => x.charAt(0).toUpperCase() + x.slice(1))
.map((x) =>
x.toLowerCase() === 'modloader'
? 'ModLoader'
: x.charAt(0).toUpperCase() + x.slice(1)
)
.join(', ')
}}
{{ $formatVersion(version.game_versions) }}
@@ -485,7 +520,7 @@
<span>Changelog</span>
</nuxt-link>
<nuxt-link
v-if="project.versions.length > 0"
v-if="project.versions.length > 0 || currentMember"
:to="`/${project.project_type}/${
project.slug ? project.slug : project.id
}/versions`"
@@ -531,6 +566,8 @@
<script>
import CalendarIcon from '~/assets/images/utils/calendar.svg?inline'
import CheckIcon from '~/assets/images/utils/check.svg?inline'
import ClearIcon from '~/assets/images/utils/clear.svg?inline'
import DownloadIcon from '~/assets/images/utils/download.svg?inline'
import UpdateIcon from '~/assets/images/utils/updated.svg?inline'
import CodeIcon from '~/assets/images/sidebar/mod.svg?inline'
@@ -556,6 +593,8 @@ export default {
IssuesIcon,
DownloadIcon,
CalendarIcon,
CheckIcon,
ClearIcon,
UpdateIcon,
CodeIcon,
ReportIcon,
@@ -645,6 +684,11 @@ export default {
})
}
},
data() {
return {
showKnownErrors: false,
}
},
head() {
return {
title: `${this.project.title} - ${
@@ -737,28 +781,32 @@ export default {
this.$nuxt.$loading.finish()
},
async submitForReview() {
this.$nuxt.$loading.start()
if (this.project.body === '' || this.project.versions.length < 1) {
this.showKnownErrors = true
} else {
this.$nuxt.$loading.start()
try {
await this.$axios.patch(
`project/${this.project.id}`,
{
status: 'processing',
},
this.$auth.headers
)
try {
await this.$axios.patch(
`project/${this.project.id}`,
{
status: 'processing',
},
this.$auth.headers
)
this.project.status = 'processing'
} catch (err) {
this.$notify({
group: 'main',
title: 'An error occurred',
text: err.response.data.description,
type: 'error',
})
this.project.status = 'processing'
} catch (err) {
this.$notify({
group: 'main',
title: 'An error occurred',
text: err.response.data.description,
type: 'error',
})
}
this.$nuxt.$loading.finish()
}
this.$nuxt.$loading.finish()
},
},
}

View File

@@ -1,46 +1,77 @@
<template>
<div class="page-contents">
<header class="card columns">
<h3 class="column-grow-1">Edit project</h3>
<nuxt-link
:to="`/${project.project_type}/${
project.slug ? project.slug : project.id
}/settings`"
class="iconified-button column"
>
Back
</nuxt-link>
<button
v-if="
project.status === 'rejected' ||
project.status === 'draft' ||
project.status === 'unlisted'
"
title="Submit for approval"
class="iconified-button column"
:disabled="!$nuxt.$loading"
@click="saveProjectReview"
>
Submit for approval
</button>
<button
title="Save"
class="iconified-button brand-button-colors column"
:disabled="!$nuxt.$loading"
@click="saveProject"
>
<CheckIcon />
Save
</button>
<header class="card">
<div class="columns">
<h3 class="column-grow-1">Edit project</h3>
<nuxt-link
:to="`/${project.project_type}/${
project.slug ? project.slug : project.id
}/settings`"
class="iconified-button column"
>
<CrossIcon />
Cancel
</nuxt-link>
<button
v-if="
project.status === 'rejected' ||
project.status === 'draft' ||
project.status === 'unlisted'
"
title="Submit for review"
class="iconified-button column"
:disabled="!$nuxt.$loading"
@click="saveProjectReview"
>
<CheckIcon />
Submit for review
</button>
<button
title="Save"
class="iconified-button brand-button-colors column"
:disabled="!$nuxt.$loading"
@click="saveProjectNotForReview"
>
<SaveIcon />
Save changes
</button>
</div>
<div v-if="showKnownErrors" class="known-errors">
<ul>
<li v-if="newProject.title === ''">Your project must have a name.</li>
<li v-if="newProject.description === ''">
Your project must have a summary.
</li>
<li v-if="newProject.slug === ''">
Your project must have a vanity URL.
</li>
<li v-if="!savingAsDraft && newProject.body === ''">
Your project must have a body to submit for review.
</li>
<li v-if="!savingAsDraft && project.versions.length < 1">
Your project must have at least one version to submit for review.
</li>
<li
v-if="
license === null || license_url === null || license_url === ''
"
>
Your project must have a license.
</li>
</ul>
</div>
</header>
<section class="card essentials">
<h3>Name<span class="required">*</span></h3>
<label>
<span>
Be creative! Generic project names will be harder to search for.
<h3>Name<span class="required">*</span></h3>
<span>
Be creative! Generic project names will be harder to search for.
</span>
</span>
<input
v-model="newProject.title"
:class="{ 'known-error': newProject.title === '' && showKnownErrors }"
type="text"
placeholder="Enter the name"
:disabled="
@@ -48,14 +79,19 @@
"
/>
</label>
<h3>Summary<span class="required">*</span></h3>
<label>
<span>
Give a short description of your project that will appear on search
pages.
<h3>Summary<span class="required">*</span></h3>
<span>
Give a short description of your project that will appear on search
pages.
</span>
</span>
<input
v-model="newProject.description"
:class="{
'known-error': newProject.description === '' && showKnownErrors,
}"
type="text"
placeholder="Enter the summary"
:disabled="
@@ -63,11 +99,13 @@
"
/>
</label>
<h3>Categories</h3>
<label>
<span class="no-padding">
Select up to 3 categories that will help others <br />
find your project.
<span>
<h3>Categories</h3>
<span class="no-padding">
Select up to 3 categories that will help others <br />
find your project.
</span>
</span>
<Multiselect
id="categories"
@@ -77,6 +115,9 @@
.filter((x) => x.project_type === project.project_type)
.map((it) => it.name)
"
:custom-label="
(value) => value.charAt(0).toUpperCase() + value.slice(1)
"
:loading="$tag.categories.length === 0"
:multiple="true"
:searchable="false"
@@ -93,23 +134,28 @@
"
/>
</label>
<h3>Vanity URL (slug)<span class="required">*</span></h3>
<label>
<label class="vertical-input">
<span>
Set this to something that will looks nice in your project's URL.
<h3>Vanity URL (slug)<span class="required">*</span></h3>
<span class="slug-description"
>https://modrinth.com/{{ newProject.project_type.toLowerCase() }}/{{
newProject.slug ? newProject.slug : 'your-slug'
}}
</span>
</span>
<input
id="name"
v-model="newProject.slug"
:class="{ 'known-error': newProject.slug === '' && showKnownErrors }"
type="text"
placeholder="Enter the vanity URL slug"
placeholder="Enter the vanity URL"
:disabled="
(currentMember.permissions & EDIT_DETAILS) !== EDIT_DETAILS
"
/>
</label>
</section>
<section class="card project-icon rows">
<section class="card project-icon">
<h3>Icon</h3>
<img
:src="
@@ -121,7 +167,9 @@
"
alt="preview-image"
/>
<file-input
<SmartFileInput
:max-size="262144"
:show-icon="false"
accept="image/png,image/jpeg,image/gif,image/webp"
class="choose-image"
prompt="Choose image or drag it here"
@@ -142,15 +190,22 @@
</button>
</section>
<section class="card game-sides">
<h3>Supported environments</h3>
<div class="columns">
<span> Let others know what environments your project supports. </span>
<div>
<h3>Supported environments</h3>
<span>
Let others know what environments your project supports.
</span>
</div>
<div class="labeled-control">
<h3>Client<span class="required">*</span></h3>
<Multiselect
v-model="clientSideType"
placeholder="Select one"
:options="sideTypes"
:custom-label="
(value) => value.charAt(0).toUpperCase() + value.slice(1)
"
:searchable="false"
:close-on-select="true"
:show-labels="false"
@@ -166,6 +221,9 @@
v-model="serverSideType"
placeholder="Select one"
:options="sideTypes"
:custom-label="
(value) => value.charAt(0).toUpperCase() + value.slice(1)
"
:searchable="false"
:close-on-select="true"
:show-labels="false"
@@ -183,19 +241,20 @@
for="body"
title="You can type an extended description of your project here."
>
Description
Body<span class="required">*</span>
</label>
</h3>
<span>
You can type an extended description of your mod here. This editor
supports Markdown. Its syntax can be found
supports
<a
class="text-link"
href="https://guides.github.com/features/mastering-markdown/"
target="_blank"
rel="noopener noreferrer"
class="text-link"
>here</a
>.
>Markdown</a
>. HTML can also be used inside your description, not including styles,
scripts, and iframes (though YouTube iframes are allowed).
</span>
<ThisOrThat
v-model="bodyViewMode"
@@ -207,6 +266,9 @@
<textarea
id="body"
v-model="newProject.body"
:class="{
'known-error': newProject.body === '' && showKnownErrors,
}"
:disabled="(currentMember.permissions & EDIT_BODY) !== EDIT_BODY"
/>
</div>
@@ -297,10 +359,11 @@
<div class="input-group">
<Multiselect
v-model="license"
placeholder="Select one"
placeholder="Choose license..."
track-by="short"
label="short"
:options="$tag.licenses"
:custom-label="(value) => value.short.toUpperCase()"
:searchable="true"
:close-on-select="true"
:show-labels="false"
@@ -365,7 +428,7 @@
"
>
<TrashIcon />
Remove Link
Remove link
</button>
<hr
v-if="
@@ -381,21 +444,25 @@
<script>
import Multiselect from 'vue-multiselect'
import TrashIcon from '~/assets/images/utils/trash.svg?inline'
import CrossIcon from '~/assets/images/utils/x.svg?inline'
import CheckIcon from '~/assets/images/utils/check.svg?inline'
import PlusIcon from '~/assets/images/utils/plus.svg?inline'
import SaveIcon from '~/assets/images/utils/save.svg?inline'
import TrashIcon from '~/assets/images/utils/trash.svg?inline'
import FileInput from '~/components/ui/FileInput'
import ThisOrThat from '~/components/ui/ThisOrThat'
import SmartFileInput from '~/components/ui/SmartFileInput'
export default {
components: {
FileInput,
SmartFileInput,
ThisOrThat,
Multiselect,
TrashIcon,
CrossIcon,
CheckIcon,
PlusIcon,
SaveIcon,
TrashIcon,
},
beforeRouteLeave(to, from, next) {
if (
@@ -444,6 +511,9 @@ export default {
isEditing: true,
bodyViewMode: 'source',
showKnownErrors: false,
savingAsDraft: false,
}
},
fetch() {
@@ -514,9 +584,38 @@ export default {
this.DELETE_PROJECT = 1 << 7
},
methods: {
checkFields() {
const reviewConditions =
this.newProject.body !== '' && this.newProject.versions.length > 0
if (
this.newProject.name !== '' &&
this.newProject.description !== '' &&
this.newProject.slug !== '' &&
this.license.short !== null &&
this.license_url !== null &&
this.license_url !== ''
) {
if (this.savingAsDraft) {
return true
} else if (reviewConditions) {
return true
}
}
this.showKnownErrors = true
return false
},
async saveProjectReview() {
this.isProcessing = true
await this.saveProject()
this.savingAsDraft = false
if (this.checkFields()) {
this.isProcessing = true
await this.saveProject()
}
},
async saveProjectNotForReview() {
this.savingAsDraft = true
if (this.checkFields()) {
await this.saveProject()
}
},
async saveProject() {
this.$nuxt.$loading.start()
@@ -709,6 +808,15 @@ header {
section.essentials {
grid-area: essentials;
label {
margin-bottom: 0.5rem;
}
@media screen and (min-width: 1024px) {
input {
margin-left: 1.5rem;
}
}
}
section.project-icon {
@@ -716,12 +824,11 @@ section.project-icon {
img {
max-width: 100%;
margin-bottom: 1rem;
margin-bottom: 0.25rem;
border-radius: var(--size-rounded-lg);
}
.iconified-button {
width: 9rem;
margin-top: 0.5rem;
}
}
@@ -732,12 +839,11 @@ section.game-sides {
.columns {
flex-wrap: wrap;
span {
div {
flex: 2;
}
.labeled-control {
flex: 2;
margin-left: var(--spacing-card-lg);
h3 {
@@ -818,4 +924,15 @@ section.donations {
.required {
color: var(--color-badge-red-bg);
}
.vertical-input {
flex-direction: column;
justify-content: left;
align-items: unset;
gap: 0.5rem;
input {
margin-left: 0 !important;
}
}
</style>

View File

@@ -65,20 +65,18 @@
</div>
</div>
</div>
<div v-if="currentMember" class="card buttons">
<div v-if="currentMember" class="card buttons header-buttons">
<button
class="iconified-button"
@click="
newGalleryItems.push({
title: '',
description: '',
featured: false,
url: '',
})
v-if="
newGalleryItems.length > 0 ||
editGalleryIndexes.length > 0 ||
deleteGalleryUrls.length > 0
"
class="action iconified-button"
@click="resetGallery"
>
<UploadIcon />
Upload
<CrossIcon />
Cancel
</button>
<button
v-if="
@@ -90,19 +88,21 @@
@click="saveGallery"
>
<CheckIcon />
Save
Save changes
</button>
<button
v-if="
newGalleryItems.length > 0 ||
editGalleryIndexes.length > 0 ||
deleteGalleryUrls.length > 0
class="iconified-button"
@click="
newGalleryItems.push({
title: '',
description: '',
featured: false,
url: '',
})
"
class="action iconified-button"
@click="resetGallery"
>
<TrashIcon />
Discard Changes
<PlusIcon />
Add an image
</button>
</div>
<div class="items">
@@ -177,7 +177,7 @@
"
>
<TrashIcon />
Delete
Remove
</button>
</div>
</div>
@@ -214,6 +214,7 @@
</div>
<div class="gallery-bottom">
<SmartFileInput
:max-size="5242880"
accept="image/png,image/jpeg,image/gif,image/webp,.png,.jpeg,.gif,.webp"
prompt="Choose image or drag it here"
@change="(files) => showPreviewImage(files, index)"
@@ -225,7 +226,7 @@
@click="newGalleryItems.splice(index, 1)"
>
<TrashIcon />
Delete
Remove
</button>
</div>
</div>
@@ -236,7 +237,7 @@
</template>
<script>
import UploadIcon from '~/assets/images/utils/upload.svg?inline'
import PlusIcon from '~/assets/images/utils/plus.svg?inline'
import CalendarIcon from '~/assets/images/utils/calendar.svg?inline'
import TrashIcon from '~/assets/images/utils/trash.svg?inline'
import CrossIcon from '~/assets/images/utils/x.svg?inline'
@@ -254,7 +255,7 @@ import Checkbox from '~/components/ui/Checkbox'
export default {
components: {
CalendarIcon,
UploadIcon,
PlusIcon,
Checkbox,
EditIcon,
TrashIcon,
@@ -615,7 +616,7 @@ export default {
}
input {
width: calc(100% - 2rem - 4px);
width: 100%;
margin: 0 0 0.25rem;
}
@@ -663,6 +664,15 @@ export default {
.gallery-buttons {
display: flex;
}
.columns {
margin-bottom: 0.5rem;
}
}
}
.header-buttons {
display: flex;
justify-content: right;
}
</style>

View File

@@ -12,31 +12,46 @@
<div class="card">
<h3>General</h3>
</div>
<section class="card">
<h3>Edit project</h3>
<label>
<span> This leads you to a page where you can edit your project. </span>
<nuxt-link class="iconified-button" to="edit">Edit</nuxt-link>
</label>
<h3>Create version</h3>
<section class="card main-settings">
<label>
<span>
This leads to a page where you can create a version for your project.
<h3>Edit project</h3>
<span>
This leads you to a page where you can edit your project.
</span>
</span>
<nuxt-link
class="iconified-button"
to="version/create"
:disabled="
(currentMember.permissions & UPLOAD_VERSION) !== UPLOAD_VERSION
"
>Create version</nuxt-link
>
<div>
<nuxt-link class="iconified-button" to="edit"
><EditIcon />Edit</nuxt-link
>
</div>
</label>
<h3>Delete project</h3>
<label>
<span>
Removes your project from Modrinth's servers and search. Clicking on
this will delete your project, so be extra careful!
<h3>Create a version</h3>
<span>
This leads to a page where you can create a version for your
project.
</span>
</span>
<div>
<nuxt-link
class="iconified-button"
to="version/create"
:disabled="
(currentMember.permissions & UPLOAD_VERSION) !== UPLOAD_VERSION
"
><PlusIcon />Create a version</nuxt-link
>
</div>
</label>
<label>
<span>
<h3>Delete project</h3>
<span>
Removes your project from Modrinth's servers and search. Clicking on
this will delete your project, so be extra careful!
</span>
</span>
<div
class="iconified-button"
@@ -45,7 +60,7 @@
"
@click="showPopup"
>
Delete project
<TrashIcon />Delete project
</div>
</label>
</section>
@@ -81,14 +96,17 @@
<div class="info">
<img :src="member.avatar_url" :alt="member.name" />
<div class="text">
<h4>{{ member.name }}</h4>
<h3>{{ member.role }}</h3>
<nuxt-link :to="'/user/' + member.user.username" class="name">
<p class="title-link">{{ member.name }}</p>
</nuxt-link>
<p>{{ member.role }}</p>
</div>
</div>
<div class="side-buttons">
<Badge v-if="member.accepted" type="accepted" color="green" />
<Badge v-else type="pending" color="yellow" />
<button
v-if="member.role !== 'Owner'"
class="dropdown-icon"
@click="
openTeamMembers.indexOf(member.user.id) === -1
@@ -109,22 +127,21 @@
<input
v-model="allTeamMembers[index].role"
type="text"
:class="{ 'known-error': member.role === 'Owner' }"
:disabled="
member.role === 'Owner' ||
(currentMember.permissions & EDIT_MEMBER) !== EDIT_MEMBER
"
/>
</label>
<ul v-if="member.role === 'Owner'" class="known-errors">
<li>A project can only have one 'Owner'.</li>
</ul>
</div>
<h3>Permissions</h3>
<div class="permissions">
<Checkbox
:value="
(member.permissions & UPLOAD_VERSION) === UPLOAD_VERSION ||
member.role === 'Owner'
"
:value="(member.permissions & UPLOAD_VERSION) === UPLOAD_VERSION"
:disabled="
member.role === 'Owner' ||
(currentMember.permissions & EDIT_MEMBER) !== EDIT_MEMBER ||
(currentMember.permissions & UPLOAD_VERSION) !== UPLOAD_VERSION
"
@@ -132,12 +149,8 @@
@input="allTeamMembers[index].permissions ^= UPLOAD_VERSION"
/>
<Checkbox
:value="
(member.permissions & DELETE_VERSION) === DELETE_VERSION ||
member.role === 'Owner'
"
:value="(member.permissions & DELETE_VERSION) === DELETE_VERSION"
:disabled="
member.role === 'Owner' ||
(currentMember.permissions & EDIT_MEMBER) !== EDIT_MEMBER ||
(currentMember.permissions & DELETE_VERSION) !== DELETE_VERSION
"
@@ -145,12 +158,8 @@
@input="allTeamMembers[index].permissions ^= DELETE_VERSION"
/>
<Checkbox
:value="
(member.permissions & EDIT_DETAILS) === EDIT_DETAILS ||
member.role === 'Owner'
"
:value="(member.permissions & EDIT_DETAILS) === EDIT_DETAILS"
:disabled="
member.role === 'Owner' ||
(currentMember.permissions & EDIT_MEMBER) !== EDIT_MEMBER ||
(currentMember.permissions & EDIT_DETAILS) !== EDIT_DETAILS
"
@@ -158,12 +167,8 @@
@input="allTeamMembers[index].permissions ^= EDIT_DETAILS"
/>
<Checkbox
:value="
(member.permissions & EDIT_BODY) === EDIT_BODY ||
member.role === 'Owner'
"
:value="(member.permissions & EDIT_BODY) === EDIT_BODY"
:disabled="
member.role === 'Owner' ||
(currentMember.permissions & EDIT_MEMBER) !== EDIT_MEMBER ||
(currentMember.permissions & EDIT_BODY) !== EDIT_BODY
"
@@ -171,12 +176,8 @@
@input="allTeamMembers[index].permissions ^= EDIT_BODY"
/>
<Checkbox
:value="
(member.permissions & MANAGE_INVITES) === MANAGE_INVITES ||
member.role === 'Owner'
"
:value="(member.permissions & MANAGE_INVITES) === MANAGE_INVITES"
:disabled="
member.role === 'Owner' ||
(currentMember.permissions & EDIT_MEMBER) !== EDIT_MEMBER ||
(currentMember.permissions & MANAGE_INVITES) !== MANAGE_INVITES
"
@@ -184,12 +185,8 @@
@input="allTeamMembers[index].permissions ^= MANAGE_INVITES"
/>
<Checkbox
:value="
(member.permissions & REMOVE_MEMBER) === REMOVE_MEMBER ||
member.role === 'Owner'
"
:value="(member.permissions & REMOVE_MEMBER) === REMOVE_MEMBER"
:disabled="
member.role === 'Owner' ||
(currentMember.permissions & EDIT_MEMBER) !== EDIT_MEMBER ||
(currentMember.permissions & REMOVE_MEMBER) !== REMOVE_MEMBER
"
@@ -197,24 +194,16 @@
@input="allTeamMembers[index].permissions ^= REMOVE_MEMBER"
/>
<Checkbox
:value="
(member.permissions & EDIT_MEMBER) === EDIT_MEMBER ||
member.role === 'Owner'
"
:value="(member.permissions & EDIT_MEMBER) === EDIT_MEMBER"
:disabled="
member.role === 'Owner' ||
(currentMember.permissions & EDIT_MEMBER) !== EDIT_MEMBER
"
label="Edit member"
@input="allTeamMembers[index].permissions ^= EDIT_MEMBER"
/>
<Checkbox
:value="
(member.permissions & DELETE_PROJECT) === DELETE_PROJECT ||
member.role === 'Owner'
"
:value="(member.permissions & DELETE_PROJECT) === DELETE_PROJECT"
:disabled="
member.role === 'Owner' ||
(currentMember.permissions & EDIT_MEMBER) !== EDIT_MEMBER ||
(currentMember.permissions & DELETE_PROJECT) !== DELETE_PROJECT
"
@@ -226,7 +215,6 @@
<button
class="iconified-button"
:disabled="
member.role === 'Owner' ||
(currentMember.permissions & EDIT_MEMBER) !== EDIT_MEMBER
"
@click="removeTeamMember(index)"
@@ -249,7 +237,8 @@
<button
class="iconified-button brand-button-colors"
:disabled="
(currentMember.permissions & EDIT_MEMBER) !== EDIT_MEMBER
(currentMember.permissions & EDIT_MEMBER) !== EDIT_MEMBER ||
member.role === 'Owner'
"
@click="updateTeamMember(index)"
>
@@ -270,6 +259,7 @@ import Badge from '~/components/ui/Badge'
import DropdownIcon from '~/assets/images/utils/dropdown.svg?inline'
import PlusIcon from '~/assets/images/utils/plus.svg?inline'
import CheckIcon from '~/assets/images/utils/check.svg?inline'
import EditIcon from '~/assets/images/utils/edit.svg?inline'
import TrashIcon from '~/assets/images/utils/trash.svg?inline'
import UserIcon from '~/assets/images/utils/user.svg?inline'
@@ -281,6 +271,7 @@ export default {
Badge,
PlusIcon,
CheckIcon,
EditIcon,
TrashIcon,
UserIcon,
},
@@ -480,17 +471,12 @@ export default {
}
.text {
margin: auto 0 auto 0.5rem;
h4 {
font-weight: normal;
margin: 0;
font-size: var(--font-size-sm);
.name {
font-weight: bold;
}
h3 {
text-transform: uppercase;
margin-top: 0.1rem;
margin-bottom: 0;
font-size: var(--font-size-sm);
font-weight: var(--font-weight-extrabold);
letter-spacing: 0.02rem;
p {
margin: 0.2rem 0;
}
}
}
@@ -571,28 +557,19 @@ section {
padding-right: var(--spacing-card-lg);
}
div {
flex: none;
}
input {
flex: 3;
height: fit-content;
}
div,
a {
display: block;
text-align: center;
height: fit-content;
flex: 1;
@media screen and (max-width: 1024px) {
margin: 0.5rem 0 1rem 0;
}
}
div:hover {
cursor: pointer;
}
}
}
.team-invite {
gap: 0.5rem;
@media screen and (max-width: 1024px) {
flex-direction: column;
h3 {
@@ -638,4 +615,8 @@ section {
}
}
}
.main-settings span {
margin-bottom: 1rem;
}
</style>

View File

@@ -42,49 +42,52 @@
Auto-featured
</div>
</div>
<div v-if="mode === 'edit'" class="buttons">
<button
class="action iconified-button brand-button-colors"
@click="saveEditedVersion"
>
<CheckIcon aria-hidden="true" />
Save
</button>
<div v-if="mode === 'edit'" class="header-buttons buttons">
<nuxt-link
v-if="$auth.user"
:to="`/${project.project_type}/${
project.slug ? project.slug : project.id
}/version/${encodeURIComponent(version.version_number)}`"
class="action iconified-button"
class="iconified-button"
>
<TrashIcon aria-hidden="true" />
Discard changes
<CrossIcon aria-hidden="true" />
Cancel
</nuxt-link>
</div>
<div v-else-if="mode === 'create'" class="buttons">
<button
class="action iconified-button brand-button-colors"
@click="createVersion"
class="iconified-button brand-button-colors"
@click="saveEditedVersion"
>
<CheckIcon aria-hidden="true" />
<SaveIcon aria-hidden="true" />
Save
</button>
</div>
<div v-else-if="mode === 'create'" class="header-buttons buttons">
<nuxt-link
v-if="$auth.user"
:to="`/${project.project_type}/${
project.slug ? project.slug : project.id
}/versions`"
class="action iconified-button"
class="iconified-button"
>
<TrashIcon aria-hidden="true" />
Discard version
<CrossIcon aria-hidden="true" />
Cancel
</nuxt-link>
<button
class="iconified-button brand-button-colors"
@click="createVersion"
>
<CheckIcon aria-hidden="true" />
Create
</button>
</div>
<div v-else class="buttons">
<a
v-if="primaryFile"
v-tooltip="
primaryFile.filename + ' (' + $formatBytes(primaryFile.size) + ')'
"
:href="primaryFile.url"
class="action iconified-button brand-button-colors"
class="bold-button iconified-button brand-button-colors"
:title="`Download ${primaryFile.filename}`"
>
<DownloadIcon aria-hidden="true" />
@@ -124,6 +127,7 @@
>
<input
v-model="version.name"
class="full-width-input"
type="text"
placeholder="Enter the version name..."
/>
@@ -179,6 +183,9 @@
class="input"
placeholder="Select one"
:options="['release', 'beta', 'alpha']"
:custom-label="
(value) => value.charAt(0).toUpperCase() + value.slice(1)
"
:searchable="false"
:close-on-select="true"
:show-labels="false"
@@ -217,6 +224,12 @@
)
.map((it) => it.name)
"
:custom-label="
(value) =>
value === 'modloader'
? 'Risugami\'s ModLoader'
: value.charAt(0).toUpperCase() + value.slice(1)
"
:loading="$tag.loaders.length === 0"
:multiple="true"
:searchable="false"
@@ -231,7 +244,11 @@
<p v-else class="value">
{{
version.loaders
.map((x) => x.charAt(0).toUpperCase() + x.slice(1))
.map((x) =>
x.toLowerCase() === 'modloader'
? "Risugami's ModLoader"
: x.charAt(0).toUpperCase() + x.slice(1)
)
.join(', ')
}}
</p>
@@ -381,7 +398,7 @@
class="iconified-button"
@click="version.dependencies.splice(index, 1)"
>
<TrashIcon /> Delete
<TrashIcon /> Remove
</button>
</div>
</div>
@@ -401,13 +418,19 @@
v-model="newDependencyId"
type="text"
oninput="this.value = this.value.replace(' ', '')"
:placeholder="`Enter the ${dependencyAddMode} ID...`"
:placeholder="`Enter the ${dependencyAddMode} ID${
dependencyAddMode === 'project' ? '/slug' : ''
}`"
@keyup.enter="addDependency"
/>
<Multiselect
v-model="newDependencyType"
class="input"
placeholder="Select one"
:options="['required', 'optional', 'incompatible']"
:custom-label="
(value) => value.charAt(0).toUpperCase() + value.slice(1)
"
:searchable="false"
:close-on-select="true"
:show-labels="false"
@@ -415,7 +438,7 @@
/>
<button class="iconified-button" @click="addDependency">
<PlusIcon />
Add dependency
Add
</button>
</div>
</div>
@@ -456,7 +479,9 @@
:key="file.hashes.sha1"
class="file"
>
<p class="filename">{{ file.filename }}</p>
<p class="filename">
{{ file.filename }}
</p>
<div
v-if="primaryFile.hashes.sha1 === file.hashes.sha1"
class="featured"
@@ -473,6 +498,7 @@
<DownloadIcon aria-hidden="true" />
Download
</a>
<p v-if="mode === 'version'">({{ $formatBytes(file.size) }})</p>
<button
v-if="mode === 'edit'"
class="action iconified-button"
@@ -482,7 +508,7 @@
"
>
<TrashIcon aria-hidden="true" />
Delete
Remove
</button>
<button
v-if="
@@ -507,7 +533,7 @@
@click="newFiles.splice(index, 1)"
>
<TrashIcon aria-hidden="true" />
Delete
Remove
</button>
</div>
</div>
@@ -517,6 +543,7 @@
class="choose-files"
accept=".jar,application/java-archive,.zip,application/zip,.mrpack"
prompt="Choose files or drag them here"
:max-size="524288000"
@change="(x) => x.forEach((y) => newFiles.push(y))"
/>
</section>
@@ -531,7 +558,9 @@ import StatelessFileInput from '~/components/ui/StatelessFileInput'
import InfoIcon from '~/assets/images/utils/info.svg?inline'
import TrashIcon from '~/assets/images/utils/trash.svg?inline'
import SaveIcon from '~/assets/images/utils/save.svg?inline'
import PlusIcon from '~/assets/images/utils/plus.svg?inline'
import CrossIcon from '~/assets/images/utils/x.svg?inline'
import EditIcon from '~/assets/images/utils/edit.svg?inline'
import DownloadIcon from '~/assets/images/utils/download.svg?inline'
import ReportIcon from '~/assets/images/utils/report.svg?inline'
@@ -556,7 +585,9 @@ export default {
StarIcon,
CheckIcon,
Multiselect,
SaveIcon,
PlusIcon,
CrossIcon,
StatelessFileInput,
InfoIcon,
},
@@ -951,22 +982,22 @@ section {
}
}
.header-buttons {
justify-content: right;
}
.buttons {
display: flex;
flex-wrap: wrap;
row-gap: 0.5rem;
.brand-button-colors {
.bold-button {
font-weight: bold;
}
@media screen and (min-width: 1024px) {
margin-left: auto;
}
.action:not(:first-child) {
margin: 0 0 0 0.5rem;
}
}
.version-data-inputs {
@@ -1005,8 +1036,7 @@ section {
input {
margin: 0;
height: 1.25rem;
width: calc(100% - 2.25rem);
width: 100%;
}
}
}
@@ -1129,4 +1159,9 @@ section {
min-height: 10rem;
display: block;
}
.full-width-input {
width: 100%;
margin-bottom: 0.5rem;
}
</style>

View File

@@ -1,9 +1,12 @@
<template>
<div class="content">
<div class="card" v-if="currentMember">
<nuxt-link to="version/create" class="iconified-button new-version">
<UploadIcon />
Upload
<div v-if="currentMember" class="card header-buttons">
<nuxt-link
to="version/create"
class="brand-button-colors iconified-button"
>
<PlusIcon />
Create a version
</nuxt-link>
</div>
<VersionFilterControl
@@ -11,7 +14,7 @@
:versions="versions"
@updateVersions="updateVersions"
/>
<div class="card">
<div v-if="versions.length > 0" class="card">
<table>
<thead>
<tr>
@@ -25,6 +28,12 @@
<tr v-for="version in filteredVersions" :key="version.id">
<td>
<a
v-tooltip="
$parent.findPrimary(version).filename +
' (' +
$formatBytes($parent.findPrimary(version).size) +
')'
"
:href="$parent.findPrimary(version).url"
class="download-button"
:class="version.version_type"
@@ -69,7 +78,11 @@
<p>
{{
version.loaders
.map((x) => x.charAt(0).toUpperCase() + x.slice(1))
.map((x) =>
x.toLowerCase() === 'modloader'
? 'ModLoader'
: x.charAt(0).toUpperCase() + x.slice(1)
)
.join(', ') +
' ' +
$formatVersion(version.game_versions)
@@ -93,7 +106,11 @@
<p>
{{
version.loaders
.map((x) => x.charAt(0).toUpperCase() + x.slice(1))
.map((x) =>
x.toLowerCase() === 'modloader'
? 'ModLoader'
: x.charAt(0).toUpperCase() + x.slice(1)
)
.join(', ')
}}
</p>
@@ -118,14 +135,14 @@
</div>
</template>
<script>
import UploadIcon from '~/assets/images/utils/upload.svg?inline'
import PlusIcon from '~/assets/images/utils/plus.svg?inline'
import DownloadIcon from '~/assets/images/utils/download.svg?inline'
import VersionBadge from '~/components/ui/Badge'
import VersionFilterControl from '~/components/ui/VersionFilterControl'
export default {
components: {
UploadIcon,
PlusIcon,
DownloadIcon,
VersionBadge,
VersionFilterControl,
@@ -165,10 +182,6 @@ export default {
</script>
<style lang="scss" scoped>
.new-version {
max-width: 5.25rem;
}
table {
border-collapse: separate;
border-spacing: 0 0.75rem;
@@ -249,4 +262,9 @@ table {
display: none;
}
}
.header-buttons {
display: flex;
justify-content: right;
}
</style>