Rewrite Parity (#647)

* Rewrite Parity

* Update SEO, fix modals, add dashes to changelog

* Edit create version title

* Cache tags, SEO for search/partial noscript support, notifications fix

* Deploy?

* Fix vercel config

* Fix it again

* Finish user editing

* Remove broken docker build

* Switch reports to modals

* Update project card

* Navbar line animation in most places

* Add chips

* Move to navlink query params

* remove autogen file

* Add copy code

* Fix webkit text box outlines, port report modal

* Update error page

* Switch to avatar component

* Make keyboard nav work

* Fix team member spacing

* improve project ID display (#676)

* Bug fixes

* Update OG site title

* More fixes

* Design tweaks

* Fix card wrapping on mobile

* Darken light theme color a little

* Sidebar navigation for settings, notifications, and moderation

* Change follow icon from a heart to a bell

* Revert "Change follow icon from a heart to a bell"

This reverts commit e30b46ec5d93c57df847be88eba123c7419dd03b.

* Change follows icon in settings

* AaaaUUUUUUUGghghhhhhhhh

* Project sidebar transparent button animations

* Update file input button styling and change icon remove button text

* Fix environments filter condition being inverted

* Remove -> revert

* Improve readability of warning banners on light mode

* Fix mobile menu button colors

* Clean up notifications page more

* Creator dashboard and monetization work

* Add processing fees declarations and acknowledgement box

* Beta badges

* Downgrade Nuxt Vercel Builder

* Update the style of button groups to be more consistent

* More button consistency

* Remove desktop navbar on mobile

* Update home page progress indicators

* Fix page jumping (Thanks @stairman06)

* Make checkbox checked style consistent with other selection indicators

* More home page updates

* Properly reset NavRows

* Move filters menu on mobile

* Stylized checkbox updated to match active styling

* Filters icon

* Respect prefers-reduced-motion

* Add most backend payouts changes (untested)

* Finish tested payouts code

* Allow monetization unenrolling

* No longer use brand color for active highlights on standard nav elements

* More consistent button group on project page

* Rounded tables

* Fix some things (#716)

* Team member fixes + re-add changelog/versions stuff

* Remove dummy data

* The great CSS refactor

* Remove commented out css

* Give modals the legacy label styles and update profile edit labels

* Fix active chip size

* Remove shadow from selected chip

* Require email set for CMP

* Update styles of notifications to universal-card

* Equivalent exchange, trading some jank for some less bad jank

* Fix all gallery buttons being missing when there is only 1 image

* Update project creation modal

* Make beta badge less bright

* Beta badge heading styling

* Update withdraw processing fees info

* Remove redundant label

* be

* Fix inverted logic

* 2% is 0.02

* Add toggle to turn off alpha modpacks banner

* Why warning button?

* Add more footer links (#719)

* Add more footer links

* Move twitter

* Make items on user pages less comically large and move ad above navigation

* Bump text down a little on home page

* Update favicon colors

* Remove task list package and change default description to use bullet points

* I don't remember why I made this important but let's not

* Ah, yes

* this doesn't actually need to be important

* Align items in input groups

* Adjust some spacings and clear creation modal on opening

* Versions now clickable

* Add link to edit page to default description

* Improve monetization information text

* Make wrapped text inputs not shrink

* Make chips work better

* smol margin on clear mod message button

* Allow non-authenticated users to access settings

* Remove settings anchors

* Fix versions page button style on firefox

* Add advanced rendering toggle

* Update slug input and icon card in project edit page

* Legal sidebar

* h1 at beginning of description no longer has top margin

* Use universal card for legal pages

* Update email addresses on legal pages

* Update various page titles and descriptions for consistency

* Various fixes and consolidation to API URL retrieval

Prevents a bug where it's possible to generate the tags under one API, switch the API, and still have tags leftover from the old API

Also finally fixes staging URL being jank

* Make the theme button show regardless of login state

Also remove the change theme from the user dropdown because it's very redundant with the several other ways of changing theme

* Make mobile profile dropdown ordering consistent with desktop

* Change the base url back

* Revert "Change the base url back"

This reverts commit c1da89fddb83776b39f626eab33c8dc67f8a75e4.

* constantize

* Tiny fixes (#722)

* Box-shadow chip outlines

* Show settings when signed out

* mods -> projects

* space

* Beta badge border

* Slug input overflow fix, scrollable

* 🙈 it will all be okay 🙊 this is just temporary 🙉 😭😭 forgive me

* Fix minor bugs

* fix moderation  page

* More fixes

* Temp fix for download button

* BEGONE TABLES

* Fix download button

Co-authored-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
Co-authored-by: Prospector <prospectordev@gmail.com>
Co-authored-by: stairman06 <36215135+stairman06@users.noreply.github.com>
Co-authored-by: triphora <emmaffle@modrinth.com>
This commit is contained in:
Geometrically
2022-11-12 17:57:40 -07:00
committed by GitHub
parent 66d0ee8156
commit 20785926e2
100 changed files with 7572 additions and 7284 deletions

274
pages/settings/account.vue Normal file
View File

@@ -0,0 +1,274 @@
<template>
<div>
<ModalConfirm
ref="modal_confirm"
title="Are you sure you want to delete your account?"
description="This will **immediately delete all of your user data and follows**. This will not delete your projects. Deleting your account cannot be reversed.<br><br>If you need help with your account, get support on the [Modrinth Discord](https://discord.gg/EUHuJHt)."
proceed-label="Delete my account"
:confirmation-text="$auth.user.username"
:has-to-type="true"
@proceed="deleteAccount"
/>
<Modal ref="modal_revoke_token" header="Revoke your Modrinth token">
<div class="modal-revoke-token markdown-body">
<p>
Revoking your Modrinth token can have unintended consequences. Please
be aware that the following could break:
</p>
<ul>
<li>Any application that uses your token to access the API.</li>
<li>
Gradle - if Minotaur is given a incorrect token, your Gradle builds
could fail.
</li>
<li>
GitHub - if you use a GitHub action that uses the Modrinth API, it
will cause errors.
</li>
</ul>
<p>If you are willing to continue, complete the following steps:</p>
<ol>
<li>
<a
href="https://github.com/settings/connections/applications/3acffb2e808d16d4b226"
target="_blank"
>
Head to the Modrinth Application page on GitHub.
</a>
Make sure to be logged into the GitHub account you used for
Modrinth!
</li>
<li>
Press the big red "Revoke Access" button next to the "Permissions"
header.
</li>
</ol>
<p>
Once you have completed those steps, press the continue button below.
</p>
<p>
<strong>
This will log you out of Modrinth, however, when you log back in,
your token will be regenerated.
</strong>
</p>
<div class="button-group">
<button
class="iconified-button"
@click="$refs.modal_revoke_token.hide()"
>
<CrossIcon />
Cancel
</button>
<button class="iconified-button brand-button" @click="logout">
<RightArrowIcon />
Log out
</button>
</div>
</div>
</Modal>
<section class="universal-card">
<h2>User profile</h2>
<p>Visit your user profile to edit your profile information.</p>
<NuxtLink class="iconified-button" :to="`/user/${$auth.user.username}`">
<UserIcon /> Visit your profile
</NuxtLink>
</section>
<section class="universal-card">
<h2>Account information</h2>
<p>Your account information is not displayed publicly.</p>
<ul class="known-errors">
<li v-if="hasMonetizationEnabled() && !email">
You must have an email address set since you are enrolled in the
Creator Monetization Program.
</li>
</ul>
<label for="email-input"
><span class="label__title">Email address</span>
</label>
<input
id="email-input"
v-model="email"
maxlength="2048"
type="email"
:placeholder="`Enter your email address...`"
/>
<div class="button-group">
<button
type="button"
class="iconified-button brand-button"
:disabled="hasMonetizationEnabled() && !email"
@click="saveChanges()"
>
<SaveIcon />
Save changes
</button>
</div>
</section>
<section class="universal-card">
<h2>Authorization token</h2>
<p>
Your authorization token can be used with the Modrinth API, the Minotaur
Gradle plugin, and other applications that interact with Modrinth's API.
Be sure to keep this secret!
</p>
<div class="input-group">
<button
type="button"
class="iconified-button"
value="Copy to clipboard"
@click="copyToken"
>
<template v-if="copied">
<CheckIcon />
Copied token to clipboard
</template>
<template v-else><CopyIcon />Copy token to clipboard</template>
</button>
<button
type="button"
class="iconified-button"
@click="$refs.modal_revoke_token.show()"
>
<SlashIcon />
Revoke token
</button>
</div>
</section>
<section id="delete-account" class="universal-card">
<h2>Delete account</h2>
<p>
Once you delete your account, there is no going back. Deleting your
account will remove all attached data, excluding projects, from our
servers.
</p>
<button
type="button"
class="iconified-button danger-button"
@click="$refs.modal_confirm.show()"
>
<TrashIcon />
Delete account
</button>
</section>
</div>
</template>
<script>
import ModalConfirm from '~/components/ui/ModalConfirm'
import Modal from '~/components/ui/Modal'
import CrossIcon from '~/assets/images/utils/x.svg?inline'
import RightArrowIcon from '~/assets/images/utils/right-arrow.svg?inline'
import CheckIcon from '~/assets/images/utils/check.svg?inline'
import UserIcon from '~/assets/images/utils/user.svg?inline'
import SaveIcon from '~/assets/images/utils/save.svg?inline'
import CopyIcon from '~/assets/images/utils/clipboard-copy.svg?inline'
import TrashIcon from '~/assets/images/utils/trash.svg?inline'
import SlashIcon from '~/assets/images/utils/slash.svg?inline'
export default {
components: {
Modal,
ModalConfirm,
CrossIcon,
RightArrowIcon,
CheckIcon,
SaveIcon,
UserIcon,
CopyIcon,
TrashIcon,
SlashIcon,
},
data() {
return {
copied: false,
email: this.$auth.user.email,
showKnownErrors: false,
}
},
head: {
title: 'Account settings - Modrinth',
},
methods: {
async copyToken() {
this.copied = true
await navigator.clipboard.writeText(this.$auth.token)
},
async deleteAccount() {
this.$nuxt.$loading.start()
try {
await this.$axios.delete(
`user/${this.$auth.user.id}`,
this.$defaultHeaders()
)
} catch (err) {
this.$notify({
group: 'main',
title: 'An error occurred',
text: err.response.data.description,
type: 'error',
})
}
this.$nuxt.$loading.finish()
},
logout() {
this.$refs.modal_revoke_token.hide()
this.$cookies.set('auth-token-reset', true)
window.location.href = `${this.$axios.defaults.baseURL}auth/init?url=${process.env.domain}`
},
hasMonetizationEnabled() {
return (
this.$auth.user.payout_data.payout_wallet &&
this.$auth.user.payout_data.payout_wallet_type &&
this.$auth.user.payout_data.payout_address
)
},
async saveChanges() {
if (this.hasMonetizationEnabled() && !this.email) {
this.showKnownErrors = true
return
}
this.$nuxt.$loading.start()
try {
const data = {
email: this.email ? this.email : null,
}
await this.$axios.patch(
`user/${this.$auth.user.id}`,
data,
this.$defaultHeaders()
)
await this.$store.dispatch('auth/fetchUser', {
token: this.$auth.token,
})
} catch (err) {
this.$notify({
group: 'main',
title: 'An error occurred',
text: err.response.data.description,
type: 'error',
})
}
this.$nuxt.$loading.finish()
},
},
}
</script>
<style lang="scss" scoped>
.modal-revoke-token {
padding: var(--spacing-card-bg);
.button-group {
width: fit-content;
margin-left: auto;
}
}
</style>

View File

@@ -28,7 +28,7 @@
<FollowIllustration class="icon" />
<br />
<span class="text"
>You don't have any followed mods. <br />
>You don't have any followed projects. <br />
Why don't you <nuxt-link class="link" to="/mods">search</nuxt-link> for
new ones?</span
>
@@ -51,7 +51,7 @@ export default {
await this.$store.dispatch('user/fetchFollows')
},
head: {
title: 'Followed Projects - Modrinth',
title: 'Followed projects - Modrinth',
},
}
</script>

View File

@@ -1,84 +1,16 @@
<template>
<div class="edit-page">
<section class="card account-settings">
<div class="header">
<h2 class="title">Account settings</h2>
<div class="controls">
<button
class="brand-button-colors iconified-button"
title="Save account settings changes"
@click="saveChanges()"
<div>
<section class="universal-card">
<h2>Themes</h2>
<div class="adjacent-input">
<label for="theme-selector">
<span class="label__title">Color theme</span>
<span class="label__description"
>Change the global site color theme.</span
>
<SaveIcon />
Save changes
</button>
</div>
</div>
<div class="left-side">
<h3>Profile picture</h3>
<div class="profile-picture">
<img :src="previewImage ? previewImage : $auth.user.avatar_url" />
<div class="uploader">
<SmartFileInput
:show-icon="false"
:max-size="2097152"
accept="image/png,image/jpeg,image/gif,image/webp"
class="choose-image"
prompt="Choose image or drag it here"
@change="showPreviewImage"
/>
<button
class="iconified-button"
@click="
icon = null
previewImage = null
"
>
<TrashIcon />
Reset
</button>
</div>
</div>
</div>
<div class="right-side">
<label>
<span>
<h3>Username</h3>
<span>This must be unique.</span>
</span>
<input
v-model="username"
type="text"
placeholder="Enter your username"
/>
</label>
<label>
<span>
<h3>Email (optional)</h3>
<span>This is kept private.</span>
</span>
<input v-model="email" type="email" placeholder="Enter your email" />
</label>
<label>
<span>
<h3>Bio</h3>
<span>Describe yourself to other users!</span>
</span>
<input v-model="bio" type="text" placeholder="Enter your bio" />
</label>
</div>
</section>
<section class="card">
<div class="header">
<h2 class="title">Display settings</h2>
</div>
<label>
<span>
<h3>Theme</h3>
<span>Change the global site theme.</span>
</span>
<Multiselect
id="theme-selector"
v-model="$colorMode.preference"
:options="['system', 'light', 'dark', 'oled']"
:custom-label="
@@ -92,78 +24,118 @@
:show-labels="false"
:allow-empty="false"
/>
</label>
<label>
<span>
<h3>Search sidebar on the right</h3>
<span>
Enabling this will put the search page's filters sidebar on the
right side.
</span>
</span>
</div>
<div class="adjacent-input small">
<label for="search-layout-toggle">
<span class="label__title">Search sidebar on the right</span>
<span class="label__description"
>Enabling this will put the search page's filters sidebar on the
right side.</span
>
</label>
<input
id="search-layout-toggle"
v-model="searchLayout"
class="switch stylized-toggle"
type="checkbox"
@change="changeLayout"
@change="saveCosmeticSettings"
/>
</label>
<label>
<span>
<h3>Project sidebar on the right</h3>
<span>
Enabling this will put the project pages' info sidebars on the right
side.
</span>
</span>
</div>
<div class="adjacent-input small">
<label for="project-layout-toggle">
<span class="label__title">Project sidebar on the right</span>
<span class="label__description"
>Enabling this will put the project pages' info sidebars on the
right side.</span
>
</label>
<input
id="project-layout-toggle"
v-model="projectLayout"
class="switch stylized-toggle"
type="checkbox"
@change="changeLayout"
@change="saveCosmeticSettings"
/>
</label>
</div>
</section>
<section class="universal-card">
<h2>Feature flags</h2>
<div class="adjacent-input small">
<label for="advanced-rendering">
<span class="label__title">Advanced rendering</span>
<span class="label__description"
>Enables advanced rendering such as blur effects that may cause
performance issues without hardware-accelerated rendering.</span
>
</label>
<input
id="advanced-rendering"
v-model="advancedRendering"
class="switch stylized-toggle"
type="checkbox"
@change="saveCosmeticSettings"
/>
</div>
<div class="adjacent-input small">
<label for="modpacks-alpha-notice">
<span class="label__title">Modpacks alpha notice</span>
<span class="label__description"
>Shows a banner stating that modpacks are in alpha.</span
>
</label>
<input
id="modpacks-alpha-notice"
v-model="modpacksAlphaNotice"
class="switch stylized-toggle"
type="checkbox"
@change="saveCosmeticSettings"
/>
</div>
</section>
</div>
</template>
<script>
import Multiselect from 'vue-multiselect'
import SmartFileInput from '~/components/ui/SmartFileInput'
import TrashIcon from '~/assets/images/utils/trash.svg?inline'
import SaveIcon from '~/assets/images/utils/save.svg?inline'
export default {
components: {
TrashIcon,
SaveIcon,
SmartFileInput,
Multiselect,
},
asyncData(ctx) {
return {
username: ctx.$auth.user.username,
email: ctx.$auth.user.email,
bio: ctx.$auth.user.bio,
}
},
auth: false,
data() {
return {
icon: null,
previewImage: null,
searchLayout: false,
projectLayout: false,
modpacksAlphaNotice: true,
advancedRendering: true,
}
},
fetch() {
this.searchLayout = this.$store.state.cosmetics.searchLayout
this.projectLayout = this.$store.state.cosmetics.projectLayout
this.searchLayout =
this.$store.state.cosmetics.searchLayout ?? this.searchLayout
this.projectLayout =
this.$store.state.cosmetics.projectLayout ?? this.projectLayout
this.modpacksAlphaNotice =
this.$store.state.cosmetics.modpacksAlphaNotice ??
this.modpacksAlphaNotice
this.advancedRendering =
this.$store.state.cosmetics.advancedRendering ?? this.advancedRendering
},
head: {
title: 'Settings - Modrinth',
title: 'Display settings - Modrinth',
},
methods: {
async saveCosmeticSettings() {
await this.$store.dispatch('cosmetics/save', {
searchLayout: this.searchLayout,
projectLayout: this.projectLayout,
modpacksAlphaNotice: this.modpacksAlphaNotice,
advancedRendering: this.advancedRendering,
$cookies: this.$cookies,
})
},
changeTheme() {
const shift = event.shiftKey
switch (this.$colorMode.preference) {
@@ -177,141 +149,7 @@ export default {
this.$colorMode.preference = shift ? 'oled' : 'dark'
}
},
showPreviewImage(files) {
const reader = new FileReader()
this.icon = files[0]
reader.readAsDataURL(this.icon)
reader.onload = (event) => {
this.previewImage = event.target.result
}
},
sumDownloads() {
let sum = 0
for (const projects of this.$user.projects) {
sum += projects.downloads
}
return this.$formatNumber(sum)
},
async changeLayout() {
await this.$store.dispatch('cosmetics/save', {
searchLayout: this.searchLayout,
projectLayout: this.projectLayout,
$cookies: this.$cookies,
})
},
async saveChanges() {
this.$nuxt.$loading.start()
try {
if (this.icon) {
await this.$axios.patch(
`user/${this.$auth.user.id}/icon?ext=${
this.icon.type.split('/')[this.icon.type.split('/').length - 1]
}`,
this.icon,
this.$defaultHeaders()
)
}
const data = {
email: this.email,
bio: this.bio,
}
if (this.username !== this.$auth.user.username) {
data.username = this.username
}
await this.$axios.patch(
`user/${this.$auth.user.id}`,
data,
this.$defaultHeaders()
)
await this.$store.dispatch('auth/fetchUser', {
token: this.$auth.token,
})
} catch (err) {
this.$notify({
group: 'main',
title: 'An error occurred',
text: err.response.data.description,
type: 'error',
})
}
this.$nuxt.$loading.finish()
},
},
}
</script>
<style lang="scss" scoped>
.account-settings {
display: grid;
grid-template: 'header header' auto 'left-side left-side' auto 'right-side right-side' auto;
@media screen and (min-width: 1024px) {
grid-template:
'header header' auto
'left-side right-side' auto;
}
.left-side {
grid-area: left-side;
min-width: 20rem;
.profile-picture {
display: flex;
flex-direction: row;
gap: 0.5rem;
align-items: center;
img {
box-shadow: var(--shadow-card);
border-radius: var(--size-rounded-md);
width: 10rem;
height: 10rem;
object-fit: contain;
margin-bottom: 0.5rem;
}
.uploader {
text-align: center;
.iconified-button {
margin-top: 0.5rem;
}
}
}
}
.right-side {
grid-area: right-side;
margin-left: var(--spacing-card-lg);
}
}
.card span {
margin-bottom: 1rem;
}
label {
align-items: center;
}
.header {
display: flex;
align-items: center;
padding-bottom: 1rem;
grid-area: header;
.title {
flex-grow: 1;
margin: 0;
}
.controls {
display: flex;
flex-direction: row;
gap: 0.5rem;
}
}
</style>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,211 @@
<template>
<div>
<section v-if="enrolled" class="universal-card">
<h2>Revenue and metrics</h2>
<p>View your revenue and metrics in the creator dashboard:</p>
<NuxtLink class="iconified-button" to="/dashboard/revenue">
<ChartIcon /> Visit creator dashboard
</NuxtLink>
</section>
<section class="universal-card">
<h2 class="title">Enrollment</h2>
<template v-if="!enrolled && !$auth.user.email">
<p v-if="!enrolled">
You are not currently enrolled in Modrinth's Creator Monetization
Program. In order to enroll, you must first add a valid email address
to your account.
</p>
<NuxtLink class="iconified-button" to="/settings/account">
<SettingsIcon /> Visit account settings
</NuxtLink>
</template>
<template v-else-if="editing || !enrolled">
<p v-if="!enrolled">
You are not currently enrolled in Modrinth's Creator Monetization
Program. Setup a method of receiving payments below to enable
monetization.
</p>
<div class="enroll">
<Chips
v-model="selectedWallet"
:starting-value="selectedWallet"
:items="wallets"
:format-label="$formatWallet"
@input="onChangeWallet()"
/>
<p>
Enter the information for the
{{ $formatWallet(selectedWallet) }} account you would like to
receive your revenue from the Creator Monetization Program:
</p>
<div class="input-group">
<Multiselect
v-model="accountType"
:options="getAccountTypes()"
:custom-label="(value) => formatAccountType(value)"
:searchable="false"
:close-on-select="true"
:show-labels="false"
:allow-empty="false"
/>
<label class="hidden" for="account-input"
>{{ $formatWallet(selectedWallet) }}
{{ formatAccountType(accountType).toLowerCase() }} input
field</label
>
<input
id="account-input"
v-model="account"
:placeholder="`Enter your ${$formatWallet(
selectedWallet
)} ${formatAccountType(accountType).toLowerCase()}...`"
:type="accountType === 'email' ? 'email' : ''"
/>
<span v-if="accountType === 'phone'">
Format: +18888888888 or +1-888-888-8888
</span>
</div>
<div class="input-group">
<button
class="iconified-button brand-button"
@click="updatePayoutData(false)"
>
<SaveIcon /> Save information
</button>
<button
v-if="enrolled"
class="iconified-button danger-button"
@click="updatePayoutData(true)"
>
<TrashIcon /> Remove enrollment
</button>
</div>
</div>
</template>
<template v-else>
<p>
You are currently enrolled in the Creator Monetization Program with a
{{ $formatWallet(selectedWallet) }} account.
</p>
<button class="iconified-button brand-button" @click="editing = true">
<EditIcon /> Edit information
</button>
</template>
</section>
</div>
</template>
<script>
import Multiselect from 'vue-multiselect'
import Chips from '~/components/ui/Chips'
import SaveIcon from '~/assets/images/utils/save.svg?inline'
import TrashIcon from '~/assets/images/utils/trash.svg?inline'
import EditIcon from '~/assets/images/utils/edit.svg?inline'
import ChartIcon from '~/assets/images/utils/chart.svg?inline'
import SettingsIcon from '~/assets/images/utils/settings.svg?inline'
export default {
components: {
Multiselect,
Chips,
SaveIcon,
TrashIcon,
EditIcon,
ChartIcon,
SettingsIcon,
},
data() {
return {
editing: false,
enrolled:
this.$auth.user.payout_data.payout_wallet &&
this.$auth.user.payout_data.payout_wallet_type &&
this.$auth.user.payout_data.payout_address,
wallets: ['paypal', 'venmo'],
selectedWallet: this.$auth.user.payout_data.payout_wallet ?? 'paypal',
accountType:
this.$auth.user.payout_data.payout_wallet_type ??
this.getAccountTypes()[0],
account: this.$auth.user.payout_data.payout_address ?? '',
}
},
head: {
title: 'Monetization settings - Modrinth',
},
methods: {
getAccountTypes() {
const types = []
if (this.selectedWallet === 'venmo') {
types.push('user_handle')
}
types.push('email')
types.push('phone')
return types
},
formatAccountType(value) {
switch (value) {
case 'email':
return 'Email address'
case 'phone':
return 'Phone number'
case 'user_handle':
return 'Username'
default:
return value.charAt(0).toUpperCase() + value.slice(1)
}
},
onChangeWallet() {
this.account = ''
// Set default account type for each wallet
if (this.selectedWallet === 'paypal') {
this.accountType = 'email'
} else if (this.selectedWallet === 'venmo') {
this.accountType = 'user_handle'
}
},
async updatePayoutData(unenroll) {
this.$nuxt.$loading.start()
if (unenroll) {
this.selectedWallet = 'paypal'
this.accountType = this.getAccountTypes()[0]
this.account = ''
}
try {
const data = {
payout_data: unenroll
? null
: {
payout_wallet: this.selectedWallet,
payout_wallet_type: this.accountType,
payout_address: this.account,
},
}
await this.$axios.patch(
`user/${this.$auth.user.id}`,
data,
this.$defaultHeaders()
)
await this.$store.dispatch('auth/fetchUser', {
token: this.$auth.token,
})
this.editing = false
this.enrolled = !unenroll
} catch (err) {
this.$notify({
group: 'main',
title: 'An error occurred',
text: err.response.data.description,
type: 'error',
})
}
this.$nuxt.$loading.finish()
},
},
}
</script>
<style lang="scss" scoped></style>

View File

@@ -1,86 +0,0 @@
<template>
<div>
<section class="card essentials pad-maker">
<h3>Revoke your Modrinth token</h3>
<p>
Revoking your Modrinth token can have unintended consequences. Please be
aware that the following could break:
</p>
<ul>
<li>Any application that uses your token to access the API.</li>
<li>
Gradle - if Minotaur is given a incorrect token, your Gradle builds
could fail.
</li>
<li>
GitHub - if you use a GitHub action that uses the Modrinth API, it
will cause errors.
</li>
</ul>
<p>If you are willing to continue, complete the following steps:</p>
<ol>
<li>
<a
href="https://github.com/settings/connections/applications/3acffb2e808d16d4b226"
target="_blank"
>
Head to the Modrinth Application page on GitHub.
</a>
Make sure to be logged into the GitHub account you used for Modrinth!
</li>
<li>
Press the big red "Revoke Access" button next to the "Permissions"
header.
</li>
</ol>
<p>
Once you have completed those steps, press the continue button below.
</p>
<p>
<strong>
This will log you out of Modrinth, however, when you log back in, your
token will be regenerated.
</strong>
</p>
<button class="iconified-button brand-button-colors" @click="logout">
<CheckIcon />
Continue
</button>
</section>
</div>
</template>
<script>
import CheckIcon from '~/assets/images/utils/right-arrow.svg?inline'
export default {
components: {
CheckIcon,
},
head: {
title: 'Revoke Token - Modrinth',
},
methods: {
async logout() {
this.$cookies.set('auth-token-reset', true)
await this.$router.replace(
`auth/init?url=${process.env.domain}${this.$route.fullPath}`
)
},
},
}
</script>
<style lang="scss" scoped>
section {
a {
color: var(--color-link);
text-decoration: underline;
}
button {
padding: 0.5rem 0.75rem;
margin-left: auto;
}
}
</style>

View File

@@ -1,130 +0,0 @@
<template>
<div>
<ConfirmPopup
ref="delete_popup"
title="Are you sure you want to delete your account?"
description="If you proceed, your user and all attached data will be removed from our
servers. This cannot be reversed, so be careful!"
proceed-label="Delete account"
:confirmation-text="$auth.user.username"
:has-to-type="true"
@proceed="deleteAccount"
/>
<section class="card">
<div class="header">
<h2 class="title">Security settings</h2>
</div>
<label>
<span>
<h3>Authorization token</h3>
<span>
Your authorization token can be used with the Modrinth API, the
Minotaur Gradle plugin, and other applications that interact with
Modrinth's API. Be sure to keep this secret!
</span>
</span>
<input
type="button"
class="iconified-button"
value="Copy to clipboard"
@click="copyToken"
/>
</label>
<label>
<span>
<h3>Revoke your token</h3>
<span
>This will log you out of Modrinth, and you will have to log in
again to access Modrinth with a new token.</span
>
</span>
<input
type="button"
class="iconified-button"
value="Revoke token"
@click="$router.replace('/settings/revoke-token')"
/>
</label>
<label>
<span>
<h3>Delete your account</h3>
<span
>Clicking on this WILL delete your account. Do not click on this
unless you want your account deleted. If you delete your account,
all attached data, including projects, will be removed from our
servers. This cannot be reversed, so be careful!</span
>
</span>
<input
value="Delete account"
type="button"
class="iconified-button"
@click="$refs.delete_popup.show()"
/>
</label>
</section>
</div>
</template>
<script>
import ConfirmPopup from '~/components/ui/ConfirmPopup'
export default {
components: { ConfirmPopup },
head: {
title: 'Security - Modrinth',
},
methods: {
async copyToken() {
await navigator.clipboard.writeText(this.$auth.token)
this.$notify({
group: 'main',
title: 'Copied to clipboard.',
text: 'Copied your Modrinth token to the clipboard.',
type: 'success',
})
},
async deleteAccount() {
this.$nuxt.$loading.start()
try {
await this.$axios.delete(
`user/${this.$auth.user.id}`,
this.$defaultHeaders()
)
} catch (err) {
this.$notify({
group: 'main',
title: 'An error occurred',
text: err.response.data.description,
type: 'error',
})
}
this.$nuxt.$loading.finish()
},
},
}
</script>
<style lang="scss" scoped>
.card span {
margin-bottom: 1rem;
}
.header {
display: flex;
align-items: center;
padding-bottom: 1rem;
grid-area: header;
.title {
flex-grow: 1;
margin: 0;
}
.controls {
display: flex;
flex-direction: row;
gap: 0.5rem;
}
}
</style>